#include <avr/io.h>
#include <stdio.h>
#include <string.h>
#include <util/delay.h>
#include "i2c.h"
#include "br24t_eeprom_driver.h"
#include "uart.h"
#include "pins.h"
#include "debug.h"

#define EEPROM_ADDR       0x57
#define EEPROM_PAGE_SIZE  64

//for burning eeprom
#define MAGIC_SYN         0xdeadbeef
#define MAGIC_ACK         0xf00dd00d

#define PAGE_WRITE_OK                 0x00
#define PAGE_WRITE_CORRUPTED          0x01
#define PAGE_WRITE_UNKNOWN_ERROR      0xff


#ifdef FLASH_EEPROM
int main() {
  LED_DEBUG_DDR |= _BV(LED_DEBUG); //TODO move to debug file or somethin
  LED_DEBUG_PORT &= ~(_BV(LED_DEBUG));
  i2c_init();

  uart_debug_init();
  FILE stdout_replacement = FDEV_SETUP_STREAM((void *)uart_debug_sendbyte, NULL, _FDEV_SETUP_WRITE);
  FILE stdin_replacement = FDEV_SETUP_STREAM(NULL, (void *)uart_debug_recvbyte, _FDEV_SETUP_READ);
  stdout = &stdout_replacement;
  stdin = &stdin_replacement;
  printf("booted\r\n\r\n");

  uart_flash_init();
  flash_eeprom();
  return 0;

}

void flash_eeprom() {
  unsigned int page_len;
  unsigned int on_byte;
  uint8_t eeprom_buffer_out[EEPROM_PAGE_SIZE]; 
  uint8_t eeprom_buffer_in[EEPROM_PAGE_SIZE];
 
  /**
  FILE master_f = FDEV_SETUP_STREAM((void *)uart_flash_sendbyte, NULL, _FDEV_SETUP_WRITE);
  **/
  FILE master_fin = FDEV_SETUP_STREAM(NULL, (void *)uart_flash_recvbyte, _FDEV_SETUP_READ);
  FILE master_fout = FDEV_SETUP_STREAM((void *)uart_flash_sendbyte, NULL, _FDEV_SETUP_WRITE);

  FILE master_f;
  char temp_buffer[15];
  int blah = 0;
  int debug = 0;
  unsigned int tots_blah = 0;
  for(;;) {
    if(blah > 9) blah = 0;
    blah++;
    tots_blah++;
    debug = fread(temp_buffer, 12, 1, &master_fin);
    printf("PACKET %i : fread status: %i, error: %i, eof: %i\r\n", tots_blah, debug, ferror(&master_fin), feof(&master_fin));
    printf("recv: %s\r\n\r\n\r\n", temp_buffer);
    snprintf(temp_buffer, 12, "debugstr %i\r\n", blah);
    printf("sending \"%s\"...\r\n", temp_buffer);
    fwrite(temp_buffer, 12, 1, &master_fout);
    memset(temp_buffer, 0, 12);
  }

  printf("waiting for master\r\n");

  fread(&page_len, 1, 1, &master_f);
  printf("%i pages total\r\n", page_len);
  
  for(int page = 0; page < page_len; page++) {
    printf("writing page %i...\r\n", page);


    fread(eeprom_buffer_out, EEPROM_PAGE_SIZE, 1, &master_f);
    fputc(PAGE_WRITE_CORRUPTED, &master_f);


    i2c_start(EEPROM_I2C_ADDR, I2C_READ);
    i2c_send((uint8_t)(page * EEPROM_PAGE_SIZE) & 0xff);
    i2c_send((uint8_t)(page * EEPROM_PAGE_SIZE) >> 8);
    for(on_byte = 0; on_byte < EEPROM_PAGE_SIZE; on_byte++) 
      i2c_send(eeprom_buffer_out[on_byte]); 
    i2c_stop();

    //verify
    eeprom_buffer_in[0] = EEPROM_READBYTE(page * EEPROM_PAGE_SIZE);
    //eeprom_buffer_in[0] = i2c_read_reg_addr16(EEPROM_I2C_ADDR, page * EEPROM_PAGE_SIZE);
    i2c_start(EEPROM_I2C_ADDR, I2C_READ);
    for(on_byte = 1; on_byte < EEPROM_PAGE_SIZE; on_byte++)
      eeprom_buffer_in[on_byte] = i2c_recv();
    i2c_stop();

    if(memcmp(eeprom_buffer_in, eeprom_buffer_out, EEPROM_PAGE_SIZE)) {
      fputc(PAGE_WRITE_CORRUPTED, &master_f);
      printf("invalid checksum on page %i!", page);
    }
    fputc(PAGE_WRITE_OK, &master_f);
  }
  printf("If you ever read this, you should be happy\r\n");
}
#endif
