Просмотр исходного кода

firmware: adjustments for Mk.II Rev.C; enable timesetting from SNES menu

ikari 13 лет назад
Родитель
Сommit
bfe9a91d07
34 измененных файлов с 2806 добавлено и 2559 удалено
  1. 3 4
      src/Makefile
  2. 2 2
      src/bootldr/Makefile
  3. 35 37
      src/bootldr/config.h
  4. 0 16
      src/bootldr/crc.S
  5. 1 1
      src/bootldr/faulthandler.c
  6. 1 1
      src/bootldr/ff.c
  7. 5 5
      src/bootldr/iap.c
  8. 28 12
      src/bootldr/led.c
  9. 1 1
      src/bootldr/lpc1754boot.ld
  10. 1 1
      src/bootldr/main.c
  11. 77 10
      src/bootldr/sdnative.c
  12. 2 0
      src/bootldr/sdnative.h
  13. 2281 2338
      src/cfgware.h
  14. 7 2
      src/cli.c
  15. 2 1
      src/clock.c
  16. 30 33
      src/config.h
  17. 4 7
      src/crc16.c
  18. 1 8
      src/crc16.h
  19. 10 3
      src/filetypes.c
  20. 5 4
      src/filetypes.h
  21. 1 1
      src/flash.script
  22. 11 2
      src/fpga_spi.c
  23. 1 0
      src/fpga_spi.h
  24. 43 31
      src/led.c
  25. 1 1
      src/lpc1754.ld
  26. 38 10
      src/main.c
  27. 31 1
      src/memory.c
  28. 3 1
      src/memory.h
  29. 64 5
      src/rtc.c
  30. 18 5
      src/rtc.h
  31. 85 14
      src/sdnative.c
  32. 2 0
      src/sdnative.h
  33. 5 2
      src/snes.c
  34. 7 0
      src/timer.c

+ 3 - 4
src/Makefile

@@ -55,7 +55,7 @@ TARGET = $(OBJDIR)/sd2snes
 
 
 # List C source files here. (C dependencies are automatically generated.)
-SRC = main.c ff.c ccsbcs.c clock.c uart.c power.c led.c timer.c printf.c spi.c fileops.c rtc.c fpga.c fpga_spi.c snes.c smc.c memory.c filetypes.c faulthandler.c sort.c crc32.c cic.c cli.c xmodem.c irq.c rle.c sdnative.c msu1.c
+SRC = main.c ff.c ccsbcs.c clock.c uart.c power.c led.c timer.c printf.c spi.c fileops.c rtc.c fpga.c fpga_spi.c snes.c smc.c memory.c filetypes.c faulthandler.c sort.c crc32.c cic.c cli.c xmodem.c irq.c rle.c sdnative.c msu1.c crc16.c
 
 # usbcontrol.c usb_hid.c usbhw_lpc.c usbinit.c usbstdreq.c
 
@@ -215,12 +215,11 @@ sym: $(TARGET).sym
 #	cp $(TARGET).bin /mbed/hw_LPC1768.bin
 
 
-program: bin
+program: build
 	utils/lpcchksum $(TARGET).bin
 	openocd -f openocd-usb.cfg -f lpc1754.cfg -f flash.cfg
-	make -C bootldr program
 
-debug: bin
+debug: build
 	openocd -f openocd-usb.cfg -f lpc1754.cfg
 
 reset:

+ 2 - 2
src/bootldr/Makefile

@@ -55,7 +55,7 @@ TARGET = $(OBJDIR)/sd2snes_bootldr
 
 
 # List C source files here. (C dependencies are automatically generated.)
-SRC = timer.c main.c ff.c clock.c uart.c power.c led.c faulthandler.c crc32.c sdnative.c fileops.c iap.c printf.c crc.c
+SRC = timer.c main.c ff.c clock.c uart.c power.c led.c faulthandler.c crc16.c crc32.c sdnative.c fileops.c iap.c printf.c 
 
 # usbcontrol.c usb_hid.c usbhw_lpc.c usbinit.c usbstdreq.c
 
@@ -67,7 +67,7 @@ SRC = timer.c main.c ff.c clock.c uart.c power.c led.c faulthandler.c crc32.c sd
 #     Even though the DOS/Win* filesystem matches both .s and .S the same,
 #     it will preserve the spelling of the filenames, and gcc itself does
 #     care about how the name is spelled on its command-line.
-ASRC = startup.S
+ASRC = startup.S crc.S
 
 
 # Optimization level, can be [0, 1, 2, 3, s].

+ 35 - 37
src/bootldr/config.h

@@ -5,17 +5,18 @@
 // #define DEBUG_IRQ
 // #define DEBUG_MSU1
 
-//#define DEBUG_BL
-#ifdef DEBUG_BL
-#define DBG_BL
+#ifdef DEBUG_UART
+#define DBG_UART
 #else
-#define DBG_BL while(0)
+#define DBG_UART while(0)
 #endif
 
+#define DBG_BL while(0)
 
 #define FW_START                  (0x00002000L)
 #define FLASH_SECTORS             (17)
 
+
 #define VER                       "0.0.1(NSFW)"
 #define IN_AHBRAM                 __attribute__ ((section(".ahbram")))
 
@@ -29,10 +30,10 @@
 
 #define SD_CHANGE_CLR()           do {LPC_GPIOINT->IO2IntClr = BV(SD_DT_BIT);} while(0)
 
-#define SD_DT_REG                 LPC_GPIO2
-#define SD_DT_BIT                 3
-#define SD_WP_REG                 LPC_GPIO2
-#define SD_WP_BIT                 4
+#define SD_DT_REG                 LPC_GPIO0
+#define SD_DT_BIT                 8
+#define SD_WP_REG                 LPC_GPIO0
+#define SD_WP_BIT                 6
 
 #define SDCARD_DETECT             (!(BITBAND(SD_DT_REG->FIOPIN, SD_DT_BIT)))
 #define SDCARD_WP                 (BITBAND(SD_WP_REG->FIOPIN, SD_WP_BIT))
@@ -40,16 +41,16 @@
 #define CONFIG_SD_BLOCKTRANSFER   1
 #define CONFIG_SD_AUTO_RETRIES    10
 // #define SD_CHANGE_VECT
-// #define CONFIG_SD_DATACRC 1
+#define CONFIG_SD_DATACRC 1
 
 #define CONFIG_UART_NUM	          3
 // #define CONFIG_CPU_FREQUENCY      90315789
 #define CONFIG_CPU_FREQUENCY      (92000000L)
 //#define CONFIG_CPU_FREQUENCY      46000000
 #define CONFIG_UART_PCLKDIV       1
-#define CONFIG_UART_TX_BUF_SHIFT  1
+#define CONFIG_UART_TX_BUF_SHIFT  8
 #define CONFIG_UART_BAUDRATE      921600
-#define CONFIG_UART_DEADLOCKABLE
+//#define CONFIG_UART_DEADLOCKABLE
 
 #define SSP_CLK_DIVISOR_FAST 2
 #define SSP_CLK_DIVISOR_SLOW 250
@@ -58,20 +59,19 @@
 #define SSP_CLK_DIVISOR_FPGA_SLOW 20
 
 #define SNES_RESET_REG            LPC_GPIO1
-#define SNES_RESET_BIT            29
-/* XXX Rev.B: 1.26 */
-#define SNES_CIC_D0_REG           LPC_GPIO1
-#define SNES_CIC_D0_BIT           26
-/* XXX Rev.B: 0.1 */
-#define SNES_CIC_D1_REG           LPC_GPIO1
-#define SNES_CIC_D1_BIT           25
-/* XXX Rev.B: 0.0 */
-#define SNES_CIC_STATUS_REG       LPC_GPIO0
-#define SNES_CIC_STATUS_BIT       1
-/* XXX Rev.B: 1.29 */
-#define SNES_CIC_PAIR_REG         LPC_GPIO0
-#define SNES_CIC_PAIR_BIT         0
-/* XXX Rev.B: 1.25 */
+#define SNES_RESET_BIT            26
+
+#define SNES_CIC_D0_REG           LPC_GPIO0
+#define SNES_CIC_D0_BIT           1
+
+#define SNES_CIC_D1_REG           LPC_GPIO0
+#define SNES_CIC_D1_BIT           0
+
+#define SNES_CIC_STATUS_REG       LPC_GPIO1
+#define SNES_CIC_STATUS_BIT       29
+
+#define SNES_CIC_PAIR_REG         LPC_GPIO1
+#define SNES_CIC_PAIR_BIT         25
 
 #define QSORT_MAXELEM             1024
 
@@ -88,20 +88,18 @@
 
 #define SD_CLKREG LPC_GPIO0
 #define SD_CMDREG LPC_GPIO0
-#define SD_DAT0REG LPC_GPIO0
-#define SD_DAT1REG LPC_GPIO1
-#define SD_DAT2REG LPC_GPIO1
-#define SD_DAT3REG LPC_GPIO0
+#define SD_DAT0REG LPC_GPIO2
+#define SD_DAT1REG LPC_GPIO2
+#define SD_DAT2REG LPC_GPIO2
+#define SD_DAT3REG LPC_GPIO2
 
 #define SD_CLKPIN (7)
 #define SD_CMDPIN (9)
-#define SD_DAT0PIN (8)
-#define SD_DAT1PIN (14)
-#define SD_DAT2PIN (15)
-#define SD_DAT3PIN (6)
-
-#define SD_DAT ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))\
-                |((SD_DAT1REG->FIOPIN1 >> 5) & 0x6)\
-                |((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3))
+#define SD_DAT0PIN (0)
+#define SD_DAT1PIN (1)
+#define SD_DAT2PIN (2)
+#define SD_DAT3PIN (3)
+
+#define SD_DAT (LPC_GPIO2->FIOPIN & 0xf)
 
 #endif

+ 0 - 16
src/bootldr/crc.S

@@ -26,22 +26,6 @@ loop:
         uxtb    r0, r0          // clear top bits of result
         bx      lr              // return
 
-        
-        /* uint16_t crc_xmodem_block(uint16_t crc, uint8_t *data, uint32_t len) */
-        .global crc_xmodem_block
-        .thumb_func
-crc_xmodem_block:
-        adr     r12, crc_table        // load address of crc table
-blockloop:
-        ldrb.w  r3, [r1], #1          // read data byte
-        eor     r3,  r3, r0, lsr #8   // EOR data byte
-        ldrh    r3, [r12, r3, lsl #1] // load value from CRC table
-        eor     r0,  r3, r0, lsl #8   // update CRC
-        uxth    r0, r0                // clear top bits of result
-        subs    r2, r2, #1            // decrement length
-        bne     blockloop             // loop while length > 0
-        bx      lr                    // return
-
         /* uint16_t crc_xmodem_block(uint16_t crc, uint8_t *data, uint32_t len) */
         .global crc_xmodem_update
         .thumb_func

+ 1 - 1
src/bootldr/faulthandler.c

@@ -4,7 +4,7 @@
 
 void HardFault_Handler(void) {
   DBG_BL printf("HFSR: %lx\n", SCB->HFSR);
-  uart_putc('H');
+  DBG_UART uart_putc('H');
   while (1) ;
 }
 

+ 1 - 1
src/bootldr/ff.c

@@ -2183,7 +2183,7 @@ FRESULT f_read (
 					mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs));
 #else
 				if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc){
-					mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs)); uart_putc('Y');}
+					mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs)); }
 #endif
 #endif
 				rcnt = SS(fp->fs) * cc;				/* Number of bytes transferred */

+ 5 - 5
src/bootldr/iap.c

@@ -127,9 +127,9 @@ FLASH_RES flash_file(uint8_t *filename) {
   DBG_BL printf("firmware image found. file size: %ld\n", file_handle.fsize);
   DBG_BL printf("reading header...\n");
   f_read(&file_handle, &file_header, 32, &bytes_read);
-  print_header(&file_header);
+  DBG_BL print_header(&file_header);
   if(check_flash() || file_header.version != fw_header->version || file_header.version == FW_MAGIC || fw_header->version == FW_MAGIC) {
-    uart_putc('F');
+    DBG_UART uart_putc('F');
     f_read(&file_handle, file_buf, 0xe0, &bytes_read);
     for(;;) {
       bytes_read = file_read();
@@ -171,7 +171,7 @@ FLASH_RES flash_file(uint8_t *filename) {
       current_sec = flash_addr & 0x10000 ? (16 + ((flash_addr >> 15) & 1))
                                          : (flash_addr >> 12);
       DBG_BL printf("current_sec=%d flash_addr=%08lx\n", current_sec, flash_addr);
-      uart_putc('.');
+      DBG_UART uart_putc('.');
       toggle_rdy_led();
       if(current_sec < (FW_START / 0x1000)) return ERR_FLASH;
       if((res = iap_prepare_for_write(current_sec, current_sec)) != CMD_SUCCESS) {
@@ -185,11 +185,11 @@ FLASH_RES flash_file(uint8_t *filename) {
     }
     if(total_read != file_header.size) {
       DBG_BL printf("wrote less data than expected! (%08lx vs. %08lx)\n", total_read, file_header.size);
-      uart_putc('X');
+      DBG_UART uart_putc('X');
       return ERR_FILECHK;
     }
   } else {
-    uart_putc('n');
+    DBG_UART uart_putc('n');
     DBG_BL printf("flash content is ok, no version mismatch, no forced upgrade. No need to flash\n");
   }
   return ERR_OK;

+ 28 - 12
src/bootldr/led.c

@@ -9,18 +9,27 @@ int led_rdyledstate = 0;
 int led_readledstate = 0;
 int led_writeledstate = 0;
 
+/* LED connections (Rev.C)
+
+   LED    color  IO    PWM
+   ---------------------------
+   ready  green  P2.4  PWM1[5]
+   read   yellow P2.5  PWM1[6]
+   write  red    P1.23 PWM1[4]
+*/
+
 void rdyled(unsigned int state) {
-  BITBAND(LPC_GPIO2->FIODIR, 0) = state;
+  BITBAND(LPC_GPIO2->FIODIR, 4) = state;
   led_rdyledstate = state;
 }
 
 void readled(unsigned int state) {
-  BITBAND(LPC_GPIO2->FIODIR, 1) = state;
+  BITBAND(LPC_GPIO2->FIODIR, 5) = state;
   led_readledstate = state;
 }
 
 void writeled(unsigned int state) {
-  BITBAND(LPC_GPIO2->FIODIR, 2) = state;
+  BITBAND(LPC_GPIO1->FIODIR, 23) = state;
   led_writeledstate = state;
 }
 
@@ -36,7 +45,7 @@ void led_clkout32(uint32_t val) {
 }
 
 void toggle_rdy_led() {
-  rdyled(!led_rdyledstate);
+  rdyled(~led_rdyledstate);
 }
 
 void toggle_read_led() {
@@ -49,21 +58,28 @@ void toggle_write_led() {
 
 void led_panic() {
   while(1) {
-    LPC_GPIO2->FIODIR |= BV(0) | BV(1) | BV(2);
+    LPC_GPIO2->FIODIR |= BV(4) | BV(5);
+    LPC_GPIO1->FIODIR |= BV(23);
     delay_ms(350);
-    LPC_GPIO2->FIODIR &= ~(BV(0) | BV(1) | BV(2));
+    LPC_GPIO2->FIODIR &= ~(BV(4) | BV(5));
+    LPC_GPIO1->FIODIR &= ~BV(23);
     delay_ms(350);
   }
 }
 
 void led_std() {
-  BITBAND(LPC_PINCON->PINSEL4, 1) = 0;
-  BITBAND(LPC_PINCON->PINSEL4, 3) = 0;
-  BITBAND(LPC_PINCON->PINSEL4, 5) = 0;
+  BITBAND(LPC_PINCON->PINSEL4, 9) = 0;
+  BITBAND(LPC_PINCON->PINSEL4, 8) = 0;
+
+  BITBAND(LPC_PINCON->PINSEL4, 11) = 0;
+  BITBAND(LPC_PINCON->PINSEL4, 10) = 0;
+
+  BITBAND(LPC_PINCON->PINSEL3, 15) = 0;
+  BITBAND(LPC_PINCON->PINSEL3, 14) = 0;
 
-  BITBAND(LPC_PINCON->PINSEL4, 0) = 0;
-  BITBAND(LPC_PINCON->PINSEL4, 2) = 0;
-  BITBAND(LPC_PINCON->PINSEL4, 4) = 0;
+  BITBAND(LPC_PWM1->PCR, 12) = 0;
+  BITBAND(LPC_PWM1->PCR, 13) = 0;
+  BITBAND(LPC_PWM1->PCR, 14) = 0;
 }
 
 void led_init() {

+ 1 - 1
src/bootldr/lpc1754boot.ld

@@ -10,7 +10,7 @@ ENTRY(_start)
 
 MEMORY
 {
-  flash  (rx)  : ORIGIN = 0x00000000, LENGTH = 0x03000
+  flash  (rx)  : ORIGIN = 0x00000000, LENGTH = 0x02000
   ram    (rwx) : ORIGIN = 0x10000000, LENGTH = 0x03fe0 /* leave room for IAP */
   ahbram (rwx) : ORIGIN = 0x2007C000, LENGTH = 0x04000
 }

+ 1 - 1
src/bootldr/main.c

@@ -42,7 +42,7 @@ int main(void) {
   clock_disconnect();
   power_init();
   timer_init();
-  uart_init();
+  DBG_UART uart_init();
   led_init();
   readled(0);
   rdyled(0);

+ 77 - 10
src/bootldr/sdnative.c

@@ -66,12 +66,13 @@
 #define CARD_SDHC (1<<1)
 
 /*
-    1 DAT3/SS   P0.6
-    2 CMD/DI    P0.9
-    5 Clock     P0.7
-    7 DAT0/DO   P0.8
-    8 DAT1/IRQ  P1.14
-    9 DAT2/NC   P1.15
+                Rev.A    Rev.C
+    1 DAT3/SS   P0.6     P2.3
+    2 CMD/DI    P0.9     P0.9
+    5 Clock     P0.7     P0.7
+    7 DAT0/DO   P0.8     P2.0
+    8 DAT1/IRQ  P1.14    P2.1
+    9 DAT2/NC   P1.15    P2.2
 */
 
 /* SD init procedure
@@ -195,6 +196,42 @@ static inline void wiggle_fast_pos1(void) {
   BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
 }
 
+int get_and_check_datacrc(uint8_t *buf) {
+  uint16_t crc0=0, crc1=0, crc2=0, crc3=0;
+  uint16_t sdcrc0=0, sdcrc1=0, sdcrc2=0, sdcrc3=0;
+  uint8_t d0=0, d1=0, d2=0, d3=0;
+  uint8_t datdata;
+  uint16_t datcnt;
+  /* get crcs from card */
+  for (datcnt=0; datcnt < 16; datcnt++) {
+    datdata = SD_DAT;
+    wiggle_fast_neg1();
+    sdcrc0 = ((sdcrc0 << 1) & 0xfffe) | ((datdata >> 3) & 0x0001);
+    sdcrc1 = ((sdcrc1 << 1) & 0xfffe) | ((datdata >> 2) & 0x0001);
+    sdcrc2 = ((sdcrc2 << 1) & 0xfffe) | ((datdata >> 1) & 0x0001);
+    sdcrc3 = ((sdcrc3 << 1) & 0xfffe) | ((datdata >> 0) & 0x0001);
+  }
+  wiggle_fast_neg1();
+  /* calc crcs from data */
+  for (datcnt=0; datcnt < 512; datcnt++) {
+    d0 = ((d0 << 2) & 0xfc) | ((buf[datcnt] >> 6) & 0x02) | ((buf[datcnt] >> 3) & 0x01) ;
+    d1 = ((d1 << 2) & 0xfc) | ((buf[datcnt] >> 5) & 0x02) | ((buf[datcnt] >> 2) & 0x01) ;
+    d2 = ((d2 << 2) & 0xfc) | ((buf[datcnt] >> 4) & 0x02) | ((buf[datcnt] >> 1) & 0x01) ;
+    d3 = ((d3 << 2) & 0xfc) | ((buf[datcnt] >> 3) & 0x02) | ((buf[datcnt] >> 0) & 0x01) ;
+    if((datcnt % 4) == 3) {
+      crc0 = crc_xmodem_update(crc0, d0);
+      crc1 = crc_xmodem_update(crc1, d1);
+      crc2 = crc_xmodem_update(crc2, d2);
+      crc3 = crc_xmodem_update(crc3, d3);
+    }
+  }
+  if((crc0 != sdcrc0) || (crc1 != sdcrc1) || (crc2 != sdcrc2) || (crc3 != sdcrc3)) {
+    DBG_SD printf("CRC mismatch\nSDCRC   CRC\n %04x    %04x\n %04x    %04x\n %04x    %04x\n %04x    %04x\n", sdcrc0, crc0, sdcrc1, crc1, sdcrc2, crc2, sdcrc3, crc3);
+    return 1;
+  }
+  return 0;
+}
+
 static inline void wait_busy(void) {
   while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
     wiggle_fast_neg1();
@@ -446,8 +483,16 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
         }
       }
     }
-    /* just eat the crcs for now */
-    if(dat) wiggle_fast_neg(17);
+    if(dat) {
+#ifdef CONFIG_SD_DATACRC
+      if(get_and_check_datacrc(buf-512)) {
+        return CRC_ERROR;
+      }
+#else
+      /* eat the crcs */
+      wiggle_fast_neg(17);
+#endif
+    }
 
     if(waitbusy) {
       DBG_SD printf("waitbusy after send_cmd\n");
@@ -515,7 +560,7 @@ int acmd_fast(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* r
   return cmd_fast(cmd, param, crc, dat, rsp);
 }
 
-void stream_datablock(uint8_t *buf) {
+int stream_datablock(uint8_t *buf) {
 //  uint8_t datshift=8;
   int j=512;
   uint8_t datdata=0;
@@ -537,8 +582,13 @@ void stream_datablock(uint8_t *buf) {
     j--;
     if(!j) break;
   }
-  /* eat the crc for now */
+#ifdef CONFIG_SD_DATACRC
+  return get_and_check_datacrc(buf-512);
+#else
+  /* eat the crcs */
   wiggle_fast_neg(17);
+#endif
+  return 0;
 }
 
 void send_datablock(uint8_t *buf) {
@@ -667,7 +717,17 @@ void send_datablock(uint8_t *buf) {
 void read_block(uint32_t address, uint8_t *buf) {
   if(during_blocktrans == TRANS_READ && (last_block == address-1)) {
 //uart_putc('r');
+#ifdef CONFIG_SD_DATACRC
+    int cmd_res;
+    if((cmd_res = stream_datablock(buf)) == CRC_ERROR) {
+      while(cmd_res == CRC_ERROR) {
+        cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp);
+        cmd_res = cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp);
+      }
+    }
+#else
     stream_datablock(buf);
+#endif
     last_block=address;
   } else {
     if(during_blocktrans) {
@@ -680,7 +740,14 @@ void read_block(uint32_t address, uint8_t *buf) {
     if(!ccs) {
       address <<= 9;
     }
+#ifdef CONFIG_SD_DATACRC
+    while(1) {
+      if(cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp) != CRC_ERROR) break;
+      cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp);
+    };
+#else
     cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp);
+#endif
     during_blocktrans = TRANS_READ;
   }
 }

+ 2 - 0
src/bootldr/sdnative.h

@@ -11,6 +11,8 @@
 
 #include "diskio.h"
 
+#define CRC_ERROR        (0xf000)
+
 /* These functions are weak-aliased to disk_... */
 void    sdn_init(void);
 DSTATUS sdn_status(BYTE drv);

Разница между файлами не показана из-за своего большого размера
+ 2281 - 2338
src/cfgware.h


+ 7 - 2
src/cli.c

@@ -388,7 +388,7 @@ void cmd_settime(void) {
     curchar[4+2] = 0;
     time.tm_mon = atoi(curchar+4);
     curchar[4] = 0;
-    time.tm_year = atoi(curchar) - 1900;
+    time.tm_year = atoi(curchar);
     set_rtc(&time);
   }
 }
@@ -396,7 +396,7 @@ void cmd_settime(void) {
 void cmd_time(void) {
   struct tm time;
   read_rtc(&time);
-  printf("%04d-%02d-%02d %02d:%02d:%02d\n", time.tm_year+1900, time.tm_mon,
+  printf("%04d-%02d-%02d %02d:%02d:%02d\n", time.tm_year, time.tm_mon,
     time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec);
 }
 
@@ -513,6 +513,11 @@ void cli_loop(void) {
     case CMD_TIME:
       cmd_time();
       break;
+
+    case CMD_TEST:
+      testbattery();
+      break;
     }
+    
   }
 }

+ 2 - 1
src/clock.c

@@ -49,7 +49,8 @@ void clock_init() {
   enableMainOsc();
   setClkSrc(CLKSRC_MAINOSC);
 // XXX  setPLL0MultPrediv(429, 19);
-  setPLL0MultPrediv(23, 2);
+// XXX  setPLL0MultPrediv(23, 2);
+  setPLL0MultPrediv(12, 1);
   enablePLL0();
   setCCLKDiv(3);
   connectPLL0();

+ 30 - 33
src/config.h

@@ -18,10 +18,10 @@
 
 #define SD_CHANGE_CLR()           do {LPC_GPIOINT->IO2IntClr = BV(SD_DT_BIT);} while(0)
 
-#define SD_DT_REG                 LPC_GPIO2
-#define SD_DT_BIT                 3
-#define SD_WP_REG                 LPC_GPIO2
-#define SD_WP_BIT                 4
+#define SD_DT_REG                 LPC_GPIO0
+#define SD_DT_BIT                 8
+#define SD_WP_REG                 LPC_GPIO0
+#define SD_WP_BIT                 6
 
 #define SDCARD_DETECT             (!(BITBAND(SD_DT_REG->FIOPIN, SD_DT_BIT)))
 #define SDCARD_WP                 (BITBAND(SD_WP_REG->FIOPIN, SD_WP_BIT))
@@ -33,12 +33,12 @@
 
 #define CONFIG_UART_NUM	          3
 // #define CONFIG_CPU_FREQUENCY      90315789
-#define CONFIG_CPU_FREQUENCY      92000000
+#define CONFIG_CPU_FREQUENCY      96000000
 //#define CONFIG_CPU_FREQUENCY      46000000
 #define CONFIG_UART_PCLKDIV       1
-#define CONFIG_UART_TX_BUF_SHIFT  10
+#define CONFIG_UART_TX_BUF_SHIFT  8
 #define CONFIG_UART_BAUDRATE      921600
-//#define CONFIG_UART_DEADLOCKABLE
+#define CONFIG_UART_DEADLOCKABLE
 
 #define SSP_CLK_DIVISOR_FAST 2
 #define SSP_CLK_DIVISOR_SLOW 250
@@ -47,20 +47,19 @@
 #define SSP_CLK_DIVISOR_FPGA_SLOW 20
 
 #define SNES_RESET_REG            LPC_GPIO1
-#define SNES_RESET_BIT            29
-/* XXX Rev.B: 1.26 */
-#define SNES_CIC_D0_REG           LPC_GPIO1
-#define SNES_CIC_D0_BIT           26
-/* XXX Rev.B: 0.1 */
-#define SNES_CIC_D1_REG           LPC_GPIO1
-#define SNES_CIC_D1_BIT           25
-/* XXX Rev.B: 0.0 */
-#define SNES_CIC_STATUS_REG       LPC_GPIO0
-#define SNES_CIC_STATUS_BIT       1
-/* XXX Rev.B: 1.29 */
-#define SNES_CIC_PAIR_REG         LPC_GPIO0
-#define SNES_CIC_PAIR_BIT         0
-/* XXX Rev.B: 1.25 */
+#define SNES_RESET_BIT            26
+
+#define SNES_CIC_D0_REG           LPC_GPIO0
+#define SNES_CIC_D0_BIT           1
+
+#define SNES_CIC_D1_REG           LPC_GPIO0
+#define SNES_CIC_D1_BIT           0
+
+#define SNES_CIC_STATUS_REG       LPC_GPIO1
+#define SNES_CIC_STATUS_BIT       29
+
+#define SNES_CIC_PAIR_REG         LPC_GPIO1
+#define SNES_CIC_PAIR_BIT         25
 
 #define QSORT_MAXELEM             1024
 
@@ -77,20 +76,18 @@
 
 #define SD_CLKREG LPC_GPIO0
 #define SD_CMDREG LPC_GPIO0
-#define SD_DAT0REG LPC_GPIO0
-#define SD_DAT1REG LPC_GPIO1
-#define SD_DAT2REG LPC_GPIO1
-#define SD_DAT3REG LPC_GPIO0
+#define SD_DAT0REG LPC_GPIO2
+#define SD_DAT1REG LPC_GPIO2
+#define SD_DAT2REG LPC_GPIO2
+#define SD_DAT3REG LPC_GPIO2
 
 #define SD_CLKPIN (7)
 #define SD_CMDPIN (9)
-#define SD_DAT0PIN (8)
-#define SD_DAT1PIN (14)
-#define SD_DAT2PIN (15)
-#define SD_DAT3PIN (6)
-
-#define SD_DAT ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))\
-                |((SD_DAT1REG->FIOPIN1 >> 5) & 0x6)\
-                |((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3))
+#define SD_DAT0PIN (0)
+#define SD_DAT1PIN (1)
+#define SD_DAT2PIN (2)
+#define SD_DAT3PIN (3)
+
+#define SD_DAT (LPC_GPIO2->FIOPIN0)
 
 #endif

+ 4 - 7
src/crc16.c

@@ -20,7 +20,7 @@
 /**
  * Static table used for the table_driven implementation.
  *****************************************************************************/
-static const crc_t crc_table[256] = {
+static const uint16_t crc_table[256] = {
     0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
     0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
     0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
@@ -63,14 +63,11 @@ static const crc_t crc_table[256] = {
  * \param data_len Number of bytes in the \a data buffer.
  * \return         The updated crc value.
  *****************************************************************************/
-crc_t crc16_update(crc_t crc, const unsigned char *data, size_t data_len)
+uint16_t crc16_update(uint16_t crc, const unsigned char data)
 {
   unsigned int tbl_idx;
-  while (data_len--) {
-    tbl_idx = (crc ^ *data) & 0xff;
-    crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffff;
-    data++;
-  }
+  tbl_idx = (crc ^ data) & 0xff;
+  crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffff;
   return crc & 0xffff;
 }
 

+ 1 - 8
src/crc16.h

@@ -29,13 +29,6 @@ extern "C" {
  *****************************************************************************/
 #define CRC_ALGO_BIT_BY_BIT_FAST 1
 
-/**
- * The type of the CRC values.
- *
- * This type must be big enough to contain at least 16 bits.
- *****************************************************************************/
-typedef uint16_t crc_t;
-
 /**
  * Update the crc value with new data.
  *
@@ -44,7 +37,7 @@ typedef uint16_t crc_t;
  * \param data_len Number of bytes in the \a data buffer.
  * \return         The updated crc value.
  *****************************************************************************/
-crc_t crc16_update(crc_t crc, const unsigned char *data, size_t data_len);
+uint16_t crc16_update(uint16_t crc, const unsigned char data);
 
 #ifdef __cplusplus
 }           /* closing brace for extern "C" */

+ 10 - 3
src/filetypes.c

@@ -84,7 +84,7 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
     this_dir_tgt = SRAM_DIR_ADDR;
     parent_tgt = 0;
     printf("root dir @%lx\n", dir_tgt);
-  }	
+  }
 
   fno.lfsize = 255;
   fno.lfname = (TCHAR*)file_lfn;
@@ -178,6 +178,7 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
                 strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len);
                 uint16_t pathlen = strlen(path);
                 switch(type) {
+                  case TYPE_IPS:
                   case TYPE_SMC:
 /*                    file_open_by_filinfo(&fno);
                     if(file_res){
@@ -194,7 +195,7 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
                       db_tgt += 0x00010000;
                       printf("new=%lx\n", db_tgt);
                     }
-                    sram_writelong((db_tgt-SRAM_MENU_ADDR), dir_tgt);
+                    sram_writelong((db_tgt-SRAM_MENU_ADDR) | ((uint32_t)type << 24), dir_tgt);
                     dir_tgt += 4;
                     /* save element:
                         - index of last slash character
@@ -252,7 +253,13 @@ SNES_FTYPE determine_filetype(char* filename) {
      ||(!strcasecmp(ext+1, "FIG"))
     ) {
     return TYPE_SMC;
-  }/* later
+  }
+  if(  (!strcasecmp(ext+1, "IPS"))
+     ||(!strcasecmp(ext+1, "UPS"))
+    ) {
+    return TYPE_IPS;
+  }
+  /* later
   if(!strcasecmp_P(ext+1, PSTR("SRM"))) {
     return TYPE_SRM;
   }

+ 5 - 4
src/filetypes.h

@@ -29,10 +29,11 @@
 
 #include "ff.h"
 typedef enum {
-  TYPE_UNKNOWN = 0,	/* 0 */
-  TYPE_SMC,		/* 1 */
-  TYPE_SRM,		/* 2 */
-  TYPE_SPC		/* 3 */
+  TYPE_UNKNOWN = 0, /* 0 */
+  TYPE_SMC,         /* 1 */
+  TYPE_SRM,         /* 2 */
+  TYPE_SPC,         /* 3 */
+  TYPE_IPS          /* 4 */
 } SNES_FTYPE;
 
 

+ 1 - 1
src/flash.script

@@ -6,7 +6,7 @@
 #flash info 0
 
 reset init
-flash write_image erase unlock obj/sd2snes.elf
+flash write_image erase unlock obj/firmware.img 8192
 reset run
 shutdown
 

+ 11 - 2
src/fpga_spi.c

@@ -53,10 +53,10 @@
 
 	8p	-		read (RAM only)
 				p: 0 = no increment after read
-				   1 = increment after read
+				   8 = increment after read
 
 	9p	{xx}*		write xx
-				p: tt-i
+				p: i-tt
 				tt = target (see above)
 				i = increment (see above)
 
@@ -73,6 +73,7 @@
 				         nibbles packed)
                                 eg 0x20111210094816 is 2011-12-10, 9:48:16
 	E6	ssrr		set/reset BS-X status register [7:0]
+	E7	-		reset SRTC state
 	F0	-		receive test token (to see if FPGA is alive)
 	F1	-		receive status (16bit, MSB first), see below
 
@@ -336,3 +337,11 @@ void set_fpga_time(uint64_t time) {
   FPGA_TX_BYTE(0x00);
   FPGA_DESELECT();
 }
+
+void fpga_reset_srtc_state() {
+  FPGA_SELECT();
+  FPGA_TX_BYTE(0xe7);
+  FPGA_TX_BYTE(0x00);
+  FPGA_TX_BYTE(0x00);
+  FPGA_DESELECT();
+}

+ 1 - 0
src/fpga_spi.h

@@ -74,5 +74,6 @@ uint32_t get_msu_offset(void);
 uint32_t get_snes_sysclk(void);
 void set_bsx_regs(uint8_t set, uint8_t reset);
 void set_fpga_time(uint64_t time);
+void fpga_reset_srtc_state(void);
 
 #endif

+ 43 - 31
src/led.c

@@ -12,11 +12,20 @@ int led_readledstate = 0;
 int led_writeledstate = 0;
 int led_pwmstate = 0;
 
+/* LED connections (Rev.C)
+
+   LED    color  IO    PWM
+   ---------------------------
+   ready  green  P2.4  PWM1[5]
+   read   yellow P2.5  PWM1[6]
+   write  red    P1.23 PWM1[4]
+*/
+
 void rdyled(unsigned int state) {
   if(led_pwmstate) {
     rdybright(state?15:0);
   } else {
-    BITBAND(LPC_GPIO2->FIODIR, 0) = state;
+    BITBAND(LPC_GPIO2->FIODIR, 4) = state;
   }
   led_rdyledstate = state;
 }
@@ -25,7 +34,7 @@ void readled(unsigned int state) {
   if(led_pwmstate) {
     readbright(state?15:0);
   } else {
-    BITBAND(LPC_GPIO2->FIODIR, 1) = state;
+    BITBAND(LPC_GPIO2->FIODIR, 5) = state;
   }
   led_readledstate = state;
 }
@@ -34,22 +43,22 @@ void writeled(unsigned int state) {
   if(led_pwmstate) {
     writebright(state?15:0);
   } else {
-    BITBAND(LPC_GPIO2->FIODIR, 2) = state;
+    BITBAND(LPC_GPIO1->FIODIR, 23) = state;
   }
   led_writeledstate = state;
 }
 
 void rdybright(uint8_t bright) {
-  LPC_PWM1->MR1 = led_bright[(bright & 15)];
-  BITBAND(LPC_PWM1->LER, 1) = 1;
+  LPC_PWM1->MR5 = led_bright[(bright & 15)];
+  BITBAND(LPC_PWM1->LER, 5) = 1;
 }
 void readbright(uint8_t bright) {
-  LPC_PWM1->MR2 = led_bright[(bright & 15)];
-  BITBAND(LPC_PWM1->LER, 2) = 1;
+  LPC_PWM1->MR6 = led_bright[(bright & 15)];
+  BITBAND(LPC_PWM1->LER, 6) = 1;
 }
 void writebright(uint8_t bright) {
-  LPC_PWM1->MR3 = led_bright[(bright & 15)];
-  BITBAND(LPC_PWM1->LER, 3) = 1;
+  LPC_PWM1->MR4 = led_bright[(bright & 15)];
+  BITBAND(LPC_PWM1->LER, 4) = 1;
 }
 
 void led_clkout32(uint32_t val) {
@@ -77,43 +86,46 @@ void toggle_write_led() {
 
 void led_panic() {
   while(1) {
-    LPC_GPIO2->FIODIR |= BV(0) | BV(1) | BV(2);
+    LPC_GPIO2->FIODIR |= BV(4) | BV(5);
+    LPC_GPIO1->FIODIR |= BV(23);
     delay_ms(350);
-    LPC_GPIO2->FIODIR &= ~(BV(0) | BV(1) | BV(2));
+    LPC_GPIO2->FIODIR &= ~(BV(4) | BV(5));
+    LPC_GPIO1->FIODIR &= ~BV(23);
     delay_ms(350);
   }
 }
 
 void led_pwm() {
-/* connect PWM to P2.0 - P2.2 */
-/* XXX Rev.B P2.???? */
-  BITBAND(LPC_PINCON->PINSEL4, 1) = 0;
-  BITBAND(LPC_PINCON->PINSEL4, 3) = 0;
-  BITBAND(LPC_PINCON->PINSEL4, 5) = 0;
+/* Rev.C P2.4, P2.5, P1.23 */
+  BITBAND(LPC_PINCON->PINSEL4, 9) = 0;
+  BITBAND(LPC_PINCON->PINSEL4, 8) = 1;
 
-  BITBAND(LPC_PINCON->PINSEL4, 0) = 1;
-  BITBAND(LPC_PINCON->PINSEL4, 2) = 1;
-  BITBAND(LPC_PINCON->PINSEL4, 4) = 1;
+  BITBAND(LPC_PINCON->PINSEL4, 11) = 0;
+  BITBAND(LPC_PINCON->PINSEL4, 10) = 1;
 
-  BITBAND(LPC_PWM1->PCR, 9) = 1;
-  BITBAND(LPC_PWM1->PCR, 10) = 1;
-  BITBAND(LPC_PWM1->PCR, 11) = 1;
+  BITBAND(LPC_PINCON->PINSEL3, 15) = 1;
+  BITBAND(LPC_PINCON->PINSEL3, 14) = 0;
+
+  BITBAND(LPC_PWM1->PCR, 12) = 1;
+  BITBAND(LPC_PWM1->PCR, 13) = 1;
+  BITBAND(LPC_PWM1->PCR, 14) = 1;
 
   led_pwmstate = 1;
 }
 
 void led_std() {
-  BITBAND(LPC_PINCON->PINSEL4, 1) = 0;
-  BITBAND(LPC_PINCON->PINSEL4, 3) = 0;
-  BITBAND(LPC_PINCON->PINSEL4, 5) = 0;
+  BITBAND(LPC_PINCON->PINSEL4, 9) = 0;
+  BITBAND(LPC_PINCON->PINSEL4, 8) = 0;
+
+  BITBAND(LPC_PINCON->PINSEL4, 11) = 0;
+  BITBAND(LPC_PINCON->PINSEL4, 10) = 0;
 
-  BITBAND(LPC_PINCON->PINSEL4, 0) = 0;
-  BITBAND(LPC_PINCON->PINSEL4, 2) = 0;
-  BITBAND(LPC_PINCON->PINSEL4, 4) = 0;
+  BITBAND(LPC_PINCON->PINSEL3, 15) = 0;
+  BITBAND(LPC_PINCON->PINSEL3, 14) = 0;
 
-  BITBAND(LPC_PWM1->PCR, 9) = 0;
-  BITBAND(LPC_PWM1->PCR, 10) = 0;
-  BITBAND(LPC_PWM1->PCR, 11) = 0;
+  BITBAND(LPC_PWM1->PCR, 12) = 0;
+  BITBAND(LPC_PWM1->PCR, 13) = 0;
+  BITBAND(LPC_PWM1->PCR, 14) = 0;
 
   led_pwmstate = 0;
 }

+ 1 - 1
src/lpc1754.ld

@@ -10,7 +10,7 @@ ENTRY(_start)
 
 MEMORY
 {
-  flash  (rx)  : ORIGIN = 0x00004100, LENGTH = 0x1bf00 /* leave room for bootldr + metadata */
+  flash  (rx)  : ORIGIN = 0x00002100, LENGTH = 0x1df00 /* leave room for bootldr + metadata */
   ram    (rwx) : ORIGIN = 0x10000000, LENGTH = 0x04000
   ahbram (rwx) : ORIGIN = 0x2007C000, LENGTH = 0x04000
 }

+ 38 - 10
src/main.c

@@ -25,8 +25,8 @@
 #include "crc.h"
 #include "smc.h"
 #include "msu1.h"
+#include "rtc.h"
 
-#include "usb_hid.h"
 #define EMC0TOGGLE	(3<<4)
 #define MR0R		(1<<1)
 
@@ -37,14 +37,18 @@ int sd_offload_partial = 0;
 uint16_t sd_offload_partial_start = 0;
 uint16_t sd_offload_partial_end = 0;
 
-/* FIXME HACK */
 volatile enum diskstates disk_state;
 extern volatile tick_t ticks;
 extern snes_romprops_t romprops;
+extern volatile int reset_changed;
+
+enum system_states {
+  SYS_RTC_STATUS = 0
+};
 
 int main(void) {
-  LPC_GPIO2->FIODIR = BV(0) | BV(1) | BV(2);
-  LPC_GPIO1->FIODIR = 0;
+  LPC_GPIO2->FIODIR = BV(4) | BV(5);
+  LPC_GPIO1->FIODIR = BV(23);
   LPC_GPIO0->FIODIR = BV(16);
 
  /* connect UART3 on P0[25:26] + SSP0 on P0[15:18] + MAT3.0 on P0[10] */
@@ -54,7 +58,7 @@ int main(void) {
 /*                      | BV(13) | BV(15) | BV(17) | BV(19)  SSP1 (SD) */
 
  /* pull-down CIC data lines */
-  LPC_PINCON->PINMODE3 = BV(18) | BV(19) | BV(20) | BV(21);
+  LPC_PINCON->PINMODE0 = BV(0) | BV(1) | BV(2) | BV(3);
 
   clock_disconnect();
   snes_init();
@@ -72,6 +76,7 @@ led_pwm();
   sdn_init();
   printf("\n\nsd2snes mk.2\n============\nfw ver.: " VER "\ncpu clock: %d Hz\n", CONFIG_CPU_FREQUENCY);
 printf("PCONP=%lx\n", LPC_SC->PCONP);
+
   file_init();
   cic_init(0);
 /* setup timer (fpga clk) */
@@ -197,22 +202,35 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
     /* shared mode */
     set_mcu_ovr(0);
 
+    if((rtc_state = rtc_isvalid()) != RTC_OK) {
+      printf("RTC invalid!\n");
+      sram_writebyte(0xff, SRAM_STATUS_ADDR+SYS_RTC_STATUS);
+      set_bcdtime(0x20110401000000LL);
+      set_fpga_time(0x20110401000000LL);
+      invalidate_rtc();
+    } else {
+      printf("RTC valid!\n");
+      sram_writebyte(0x00, SRAM_STATUS_ADDR+SYS_RTC_STATUS);
+      set_fpga_time(get_bcdtime());
+    }
+
     printf("SNES GO!\n");
     snes_reset(1);
     delay_ms(1);
     snes_reset(0);
 
     uint8_t cmd = 0;
+    uint64_t btime = 0;
     uint32_t filesize=0;
     sram_writebyte(32, SRAM_CMD_ADDR);
     printf("test sram\n");
     while(!sram_reliable());
     printf("ok\n");
-
-  //while(1) {
-  //  delay_ms(1000);
-  //  printf("Estimated SNES master clock: %ld Hz\n", get_snes_sysclk());
-  //}
+sram_hexdump(SRAM_DIR_ADDR, 0x300);
+//while(1) {
+//  delay_ms(1000);
+//  printf("Estimated SNES master clock: %ld Hz\n", get_snes_sysclk());
+//}
   //sram_hexdump(SRAM_DB_ADDR, 0x200);
   //sram_hexdump(SRAM_MENU_ADDR, 0x400);
     while(!cmd) {
@@ -241,6 +259,11 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
 	  snes_reset(0);
 	  break;
 	case SNES_CMD_SETRTC:
+          /* get time from RAM */
+          btime = sram_gettime(SRAM_PARAM_ADDR);
+          /* set RTC */
+          set_bcdtime(btime);
+          set_fpga_time(btime);
 	  cmd=0; /* stay in loop */
 	  break;
 	default:
@@ -265,6 +288,11 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
       sleep_ms(250);
       sram_reliable();
       printf("%s ", get_cic_statename(get_cic_state()));
+      if(reset_changed) {
+        printf("reset\n");
+        reset_changed = 0;
+        fpga_reset_srtc_state();
+      }
       snes_reset_now=get_snes_reset();
       if(snes_reset_now) {
 	if(!snes_reset_prev) {

+ 31 - 1
src/memory.c

@@ -227,7 +227,7 @@ ticks_total=getticks()-ticksstart;
     sram_writebyte(0x33, rombase+0xda);
     sram_writebyte(0x00, rombase+0xd4);
     sram_writebyte(0xfc, rombase+0xd5);
-    set_fpga_time(0x0020110212180500LL);
+    set_fpga_time(0x0220110301180530LL);
   }
   uint32_t rammask;
   uint32_t rommask;
@@ -418,3 +418,33 @@ void sram_memset(uint32_t base_addr, uint32_t len, uint8_t val) {
   FPGA_TX_BYTE(0x00);
   FPGA_DESELECT();
 }
+
+uint64_t sram_gettime(uint32_t base_addr) {
+  set_mcu_addr(base_addr);
+  FPGA_SELECT();
+  FPGA_TX_BYTE(0x88);
+  FPGA_TX_BYTE(0x00);
+  uint8_t data;
+  uint64_t result = 0LL;
+  /* 1st nibble is the century - 10 (binary)
+     4th nibble is the month (binary)
+     all other fields are BCD */
+  for(int i=0; i<12; i++) {
+    data = FPGA_TXRX_BYTE(0x00);
+    data &= 0xf;
+    switch(i) {
+      case 0:
+        result = (result << 4) | ((data / 10) + 1);
+        result = (result << 4) | (data % 10);
+        break;
+      case 3:
+        result = (result << 4) | ((data / 10));
+        result = (result << 4) | (data % 10);
+        break;
+      default:
+        result = (result << 4) | data;
+    }
+  }
+  FPGA_DESELECT();
+  return result & 0x00ffffffffffffffLL;
+}

+ 3 - 1
src/memory.h

@@ -38,6 +38,7 @@
 #define SRAM_DIR_ADDR (0xE10000L)
 #define SRAM_CMD_ADDR (0xFF1000L)
 #define SRAM_PARAM_ADDR (0xFF1004L)
+#define SRAM_STATUS_ADDR (0xFF1100L)
 #define SRAM_MENU_SAVE_ADDR (0xFF0000L)
 #define SRAM_SCRATCHPAD (0xFFFF00L)
 #define SRAM_DIRID (0xFFFFF0L)
@@ -61,6 +62,7 @@ void sram_writeblock(void* buf, uint32_t addr, uint16_t size);
 void save_sram(uint8_t* filename, uint32_t sram_size, uint32_t base_addr);
 uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size);
 uint8_t sram_reliable(void);
-void sram_memset(uint32_t base_adde, uint32_t len, uint8_t val);
+void sram_memset(uint32_t base_addr, uint32_t len, uint8_t val);
+uint64_t sram_gettime(uint32_t base_addr);
 
 #endif

+ 64 - 5
src/rtc.c

@@ -2,12 +2,22 @@
 #include <arm/bits.h>
 #include "config.h"
 #include "rtc.h"
+#include "uart.h"
+#include "timer.h"
+#include "power.h"
 
 rtcstate_t rtc_state;
 
 #define CLKEN  0
 #define CTCRST 1
 
+uint8_t rtc_isvalid(void) {
+  if(LPC_RTC->GPREG0 == RTC_MAGIC) {
+    return RTC_OK;
+  }
+  return RTC_INVALID;
+}
+
 void rtc_init(void) {
   if (LPC_RTC->CCR & BV(CLKEN)) {
     rtc_state = RTC_OK;
@@ -23,11 +33,25 @@ void read_rtc(struct tm *time) {
     time->tm_hour = LPC_RTC->HOUR;
     time->tm_mday = LPC_RTC->DOM;
     time->tm_mon  = LPC_RTC->MONTH;
-    time->tm_year = LPC_RTC->YEAR - 1900;
+    time->tm_year = LPC_RTC->YEAR;
     time->tm_wday = LPC_RTC->DOW;
   } while (time->tm_sec != LPC_RTC->SEC);
 }
 
+uint8_t calc_weekday(struct tm *time) {
+  int month = time->tm_mon;
+  int year = time->tm_year;
+  int day = time->tm_mday;
+
+  /* Variation of Sillke for the Gregorian calendar.
+   * http://www.mathematik.uni-bielefeld.de/~sillke/ALGORITHMS/calendar/weekday.c */
+  if (month <= 2) {
+     month += 10;
+     year--;
+  } else month -= 2;
+  return (83*month/32 + day + year + year/4 - year/100 + year/400) % 7;
+}
+
 void set_rtc(struct tm *time) {
   LPC_RTC->CCR   = BV(CTCRST);
   LPC_RTC->SEC   = time->tm_sec;
@@ -35,17 +59,21 @@ void set_rtc(struct tm *time) {
   LPC_RTC->HOUR  = time->tm_hour;
   LPC_RTC->DOM   = time->tm_mday;
   LPC_RTC->MONTH = time->tm_mon;
-  LPC_RTC->YEAR  = time->tm_year + 1900;
-  LPC_RTC->DOW   = time->tm_wday;
+  LPC_RTC->YEAR  = time->tm_year;
+  LPC_RTC->DOW   = calc_weekday(time);
   LPC_RTC->CCR   = BV(CLKEN);
+  LPC_RTC->GPREG0 = RTC_MAGIC;
 }
 
+void invalidate_rtc() {
+  LPC_RTC->GPREG0 = 0;
+}
 
 uint32_t get_fattime(void) {
   struct tm time;
 
   read_rtc(&time);
-  return ((uint32_t)time.tm_year-80) << 25 |
+  return ((uint32_t)time.tm_year-1980) << 25 |
     ((uint32_t)time.tm_mon) << 21 |
     ((uint32_t)time.tm_mday)  << 16 |
     ((uint32_t)time.tm_hour)  << 11 |
@@ -56,7 +84,7 @@ uint32_t get_fattime(void) {
 uint64_t get_bcdtime(void) {
   struct tm time;
   read_rtc(&time);
-  uint16_t year = time.tm_year + 1900;
+  uint16_t year = time.tm_year;
 
   return ((uint64_t)(time.tm_wday % 7) << 56)
          |((uint64_t)((year / 1000) % 10) << 52)
@@ -74,3 +102,34 @@ uint64_t get_bcdtime(void) {
          |((time.tm_sec / 10) << 4)
          |(time.tm_sec % 10);
 }
+
+void set_bcdtime(uint64_t btime) {
+  struct tm time;
+  time.tm_sec = (btime & 0xf) + ((btime >> 4) & 0xf) * 10;
+  time.tm_min = ((btime >> 8) & 0xf) + ((btime >> 12) & 0xf) * 10;
+  time.tm_hour = ((btime >> 16) & 0xf) + ((btime >> 20) & 0xf) * 10;
+  time.tm_mday = ((btime >> 24) & 0xf) + ((btime >> 28) & 0xf) * 10;
+  time.tm_mon = ((btime >> 32) & 0xf) + ((btime >> 36) & 0xf) * 10;
+  time.tm_year = ((btime >> 40) & 0xf) + ((btime >> 44) & 0xf) * 10
+               + ((btime >> 48) & 0xf) * 100 + ((btime >> 52) & 0xf) * 1000;
+  printtime(&time);
+  set_rtc(&time);
+}
+
+void printtime(struct tm *time) {
+  printf("%04d-%02d-%02d %02d:%02d:%02d\n", time->tm_year, time->tm_mon,
+    time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec);
+}
+
+void testbattery() {
+  printf("%lx\n", LPC_RTC->GPREG0);
+  LPC_RTC->GPREG0 = RTC_MAGIC;
+  printf("%lx\n", LPC_RTC->GPREG0);
+  LPC_RTC->CCR = 0;
+  BITBAND(LPC_SC->PCONP, PCRTC) = 0;
+  delay_ms(20000);
+  BITBAND(LPC_SC->PCONP, PCRTC) = 1;
+  printf("%lx\n", LPC_RTC->GPREG0);
+  delay_ms(20);
+  LPC_RTC->CCR = BV(CLKEN);
+}

+ 18 - 5
src/rtc.h

@@ -22,9 +22,6 @@
 
    rtc.h: Definitions for RTC support
 
-   There is no rtc.c, the functions defined here are implemented by a
-   device-specific .c file, e.g. pcf8583.c.
-
 */
 
 #ifndef RTC_H
@@ -44,22 +41,38 @@ struct tm {
   uint8_t tm_hour; // 0..23
   uint8_t tm_mday; // 1..[28..31]
   uint8_t tm_mon;  // 0..11
-  uint8_t tm_year; // since 1900, i.e. 2000 is 100
+  uint16_t tm_year; // since 0 A.D.
   uint8_t tm_wday; // 0 to 6, sunday is 6
   // A Unix struct tm has a few more fields we don't need in this application
 };
 
+#define RTC_MAGIC        (0x43545253L)
+
 extern rtcstate_t rtc_state;
 
 void rtc_init(void);
 
+/* return RTC valid state based on magic token in backup register */
+uint8_t rtc_isvalid(void);
+
 /* Return current time in struct tm */
 void read_rtc(struct tm *time);
 
-/* Set time from struct tm */
+/* Set time from struct tm, also sets RTC valid */
 void set_rtc(struct tm *time);
 
+/* Set RTC invalid */
+void invalidate_rtc(void);
+
 /* get current time in 60-bit BCD format (WYYYYMMDDHHMMSS) (W=DOW) */
 uint64_t get_bcdtime(void);
 
+/* set current time from 56-bit BCD format (YYYYMMDDHHMMSS)
+   DOW is calculated */
+void set_bcdtime(uint64_t btime);
+
+/* print the time to the console */
+void printtime(struct tm *time);
+
+void testbattery(void);
 #endif

+ 85 - 14
src/sdnative.c

@@ -2,6 +2,7 @@
 #include <stdio.h>
 #include "config.h"
 #include "crc.h"
+#include "crc16.h"
 #include "diskio.h"
 #include "spi.h"
 #include "timer.h"
@@ -68,12 +69,13 @@
 #define CARD_SDHC (1<<1)
 
 /*
-    1 DAT3/SS   P0.6
-    2 CMD/DI    P0.9
-    5 Clock     P0.7
-    7 DAT0/DO   P0.8
-    8 DAT1/IRQ  P1.14
-    9 DAT2/NC   P1.15
+                Rev.A    Rev.C
+    1 DAT3/SS   P0.6     P2.3
+    2 CMD/DI    P0.9     P0.9
+    5 Clock     P0.7     P0.7
+    7 DAT0/DO   P0.8     P2.0
+    8 DAT1/IRQ  P1.14    P2.1
+    9 DAT2/NC   P1.15    P2.2
 */
 
 /* SD init procedure
@@ -197,6 +199,42 @@ static inline void wiggle_fast_pos1(void) {
   BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
 }
 
+int get_and_check_datacrc(uint8_t *buf) {
+  uint16_t crc0=0, crc1=0, crc2=0, crc3=0;
+  uint16_t sdcrc0=0, sdcrc1=0, sdcrc2=0, sdcrc3=0;
+  uint8_t d0=0, d1=0, d2=0, d3=0;
+  uint8_t datdata;
+  uint16_t datcnt;
+  /* get crcs from card */
+  for (datcnt=0; datcnt < 16; datcnt++) {
+    datdata = SD_DAT;
+    wiggle_fast_neg1();
+    sdcrc0 = ((sdcrc0 << 1) & 0xfffe) | ((datdata >> 3) & 0x0001);
+    sdcrc1 = ((sdcrc1 << 1) & 0xfffe) | ((datdata >> 2) & 0x0001);
+    sdcrc2 = ((sdcrc2 << 1) & 0xfffe) | ((datdata >> 1) & 0x0001);
+    sdcrc3 = ((sdcrc3 << 1) & 0xfffe) | ((datdata >> 0) & 0x0001);
+  }
+  wiggle_fast_neg1();
+  /* calc crcs from data */
+  for (datcnt=0; datcnt < 512; datcnt++) {
+    d0 = ((d0 << 2) & 0xfc) | ((buf[datcnt] >> 6) & 0x02) | ((buf[datcnt] >> 3) & 0x01) ;
+    d1 = ((d1 << 2) & 0xfc) | ((buf[datcnt] >> 5) & 0x02) | ((buf[datcnt] >> 2) & 0x01) ;
+    d2 = ((d2 << 2) & 0xfc) | ((buf[datcnt] >> 4) & 0x02) | ((buf[datcnt] >> 1) & 0x01) ;
+    d3 = ((d3 << 2) & 0xfc) | ((buf[datcnt] >> 3) & 0x02) | ((buf[datcnt] >> 0) & 0x01) ;
+    if((datcnt % 4) == 3) {
+      crc0 = crc_xmodem_update(crc0, d0);
+      crc1 = crc_xmodem_update(crc1, d1);
+      crc2 = crc_xmodem_update(crc2, d2);
+      crc3 = crc_xmodem_update(crc3, d3);
+    }
+  }
+  if((crc0 != sdcrc0) || (crc1 != sdcrc1) || (crc2 != sdcrc2) || (crc3 != sdcrc3)) {
+    printf("CRC mismatch\nSDCRC   CRC\n %04x    %04x\n %04x    %04x\n %04x    %04x\n %04x    %04x\n", sdcrc0, crc0, sdcrc1, crc1, sdcrc2, crc2, sdcrc3, crc3);
+    return 1;
+  }
+  return 0;
+}
+
 static inline void wait_busy(void) {
   while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
     wiggle_fast_neg1();
@@ -459,8 +497,16 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
         }
       }
     }
-    /* just eat the crcs for now */
-    if(dat) wiggle_fast_neg(17);
+    if(dat) {
+#ifdef CONFIG_SD_DATACRC
+      if(get_and_check_datacrc(buf-512)) {
+        return CRC_ERROR;
+      }
+#else
+      /* eat the crcs */
+      wiggle_fast_neg(17);
+#endif
+    }
 
     if(waitbusy) {
       DBG_SD printf("waitbusy after send_cmd\n");
@@ -528,7 +574,7 @@ int acmd_fast(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* r
   return cmd_fast(cmd, param, crc, dat, rsp);
 }
 
-void stream_datablock(uint8_t *buf) {
+int stream_datablock(uint8_t *buf) {
 //  uint8_t datshift=8;
   int j=512;
   uint8_t datdata=0;
@@ -559,9 +605,14 @@ void stream_datablock(uint8_t *buf) {
       j--;
       if(!j) break;
     }
-  /* eat the crc for now */
-  wiggle_fast_neg(17);
-  }
+#ifdef CONFIG_SD_DATACRC
+    return get_and_check_datacrc(buf-512);
+#else
+    /* eat the crcs */
+    wiggle_fast_neg(17);
+#endif
+  }
+  return 0;
 }
 
 void send_datablock(uint8_t *buf) {
@@ -585,7 +636,7 @@ void send_datablock(uint8_t *buf) {
     datshift=8;
     do {
       datshift-=4;
-      if(((*buf)>>datshift) & 0x8) {
+/*      if(((*buf)>>datshift) & 0x8) {
         BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1;
       } else {
         BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1;
@@ -604,7 +655,8 @@ void send_datablock(uint8_t *buf) {
         BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1;
       } else {
         BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1;
-      }
+      }*/
+      SD_DAT0REG->FIOPIN0 = (*buf) >> datshift;
       wiggle_fast_pos1();
     } while (datshift);
 
@@ -690,7 +742,17 @@ void send_datablock(uint8_t *buf) {
 void read_block(uint32_t address, uint8_t *buf) {
   if(during_blocktrans == TRANS_READ && (last_block == address-1)) {
 //uart_putc('r');
+#ifdef CONFIG_SD_DATACRC
+    int cmd_res;
+    if((cmd_res = stream_datablock(buf)) == CRC_ERROR) {
+      while(cmd_res == CRC_ERROR) {
+        cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp);
+        cmd_res = cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp);
+      }
+    }
+#else
     stream_datablock(buf);
+#endif
     last_block=address;
   } else {
     if(during_blocktrans) {
@@ -703,7 +765,14 @@ void read_block(uint32_t address, uint8_t *buf) {
     if(!ccs) {
       address <<= 9;
     }
+#ifdef CONFIG_SD_DATACRC
+    while(1) {
+      if(cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp) != CRC_ERROR) break;
+      cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp);
+    };
+#else
     cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp);
+#endif
     during_blocktrans = TRANS_READ;
   }
 }
@@ -840,6 +909,8 @@ void sdn_init(void) {
   BITBAND(SD_CLKREG->FIODIR, SD_CLKPIN) = 1;
   BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1;
   BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN) = 1;
+  LPC_GPIO2->FIOPIN0 = 0x00;
+  LPC_GPIO2->FIOMASK0 = ~0xf;
 }
 void disk_init(void) __attribute__ ((weak, alias("sdn_init")));
 

+ 2 - 0
src/sdnative.h

@@ -11,6 +11,8 @@
 
 #include "diskio.h"
 
+#define CRC_ERROR        (0xf000)
+
 extern int sd_offload;
 
 /* These functions are weak-aliased to disk_... */

+ 5 - 2
src/snes.c

@@ -43,6 +43,8 @@ uint8_t initloop=1;
 uint32_t saveram_crc, saveram_crc_old;
 extern snes_romprops_t romprops;
 
+volatile int reset_changed;
+
 void prepare_reset() {
   set_mcu_ovr(1);
   snes_reset(1);
@@ -142,7 +144,7 @@ uint8_t menu_main_loop() {
   sram_writebyte(0, SRAM_CMD_ADDR);
   while(!cmd) {
     if(!get_snes_reset()) {
-      while(!sram_reliable())printf("hurr\n");;
+      while(!sram_reliable())printf("hurr\n");
       cmd = sram_readbyte(SRAM_CMD_ADDR);
     }
     if(get_snes_reset()) {
@@ -155,7 +157,8 @@ uint8_t menu_main_loop() {
 }
 
 void get_selected_name(uint8_t* fn) {
-  uint32_t addr = sram_readlong(SRAM_PARAM_ADDR);
+  uint32_t addr;
+  addr = sram_readlong(SRAM_PARAM_ADDR);
   printf("fd addr=%lx\n", addr);
   sram_readblock(fn, addr + 7 + SRAM_MENU_ADDR, 256);
 }

+ 7 - 0
src/timer.c

@@ -7,6 +7,7 @@
 #include "clock.h"
 #include "uart.h"
 #include "sdnative.h"
+#include "snes.h"
 
 /* bit definitions */
 #define RITINT 0
@@ -15,6 +16,7 @@
 #define PCRIT 16
 
 extern volatile int sd_changed;
+extern volatile int reset_changed;
 volatile tick_t ticks;
 volatile int wokefromrit;
 
@@ -26,10 +28,15 @@ void __attribute__((weak,noinline)) SysTick_Hook(void) {
 void SysTick_Handler(void) {
   ticks++;
   static uint16_t sdch_state = 0;
+  static uint16_t reset_state = 0;
   sdch_state = (sdch_state << 1) | SDCARD_DETECT | 0xe000;
   if((sdch_state == 0xf000) || (sdch_state == 0xefff)) {
     sd_changed = 1;
   }
+  reset_state = (reset_state << 1) | get_snes_reset() | 0xe000;
+  if((reset_state == 0xf000) || (reset_state == 0xefff)) {
+    reset_changed = 1;
+  }
   sdn_changed();
   SysTick_Hook();
 }

Некоторые файлы не были показаны из-за большого количества измененных файлов