#define ROM_SIZE  (0xffff)
#define SER_BUF   (1024)

#define SIG_RESET ('r')
#define SIG_WRITE ('w')

enum states {
  IDLE,
  WRITE // write rom to memory
};

void do_reset() {
  SCB->AIRCR = 0x05fa0004;
}

enum states state = IDLE;
volatile static uint8_t rom[ROM_SIZE];
uint8_t buf[SER_BUF];
uint16_t rom_idx = 0;
uint32_t start = 0;

void setup() {
  bzero(&buf, SER_BUF);
  bzero((void*)&rom, ROM_SIZE);

  Serial.begin(115200);

  start = millis();
  state = IDLE;

  Serial.println("READY");
}

void flush_serial() {
  while(Serial.available() > 0) Serial.read();
}

void loop() {
  if(state == IDLE) {
    char c = Serial.read();

    if(c == SIG_RESET) {
      Serial.println("resetting");
      delay(1000);
      do_reset();
    } else if(c == SIG_WRITE) {
      state = WRITE;
      rom_idx = 0;

      bzero((void*)&rom, ROM_SIZE);

      start = millis();

      Serial.println("Ready for ROM");
    }
  } else if(state == WRITE) {
    while(true && rom_idx < 0x7ffe && millis() - start < 3000) {
      while(Serial.available()) rom[rom_idx++] = Serial.read();
    }

    state = IDLE;
    Serial.printf("Read 0x%04X bytes into memory\r\n", rom_idx);
  }
}
