Browse Source

SD native write support (still needs error handling), DB creation update (display file sizes)

ikari 13 years ago
parent
commit
561477ec53
14 changed files with 414 additions and 196 deletions
  1. 1 1
      src/Makefile
  2. 14 5
      src/config.h
  3. 1 0
      src/ff.c
  4. 8 6
      src/filetypes.c
  5. 1 1
      src/fpga_spi.c
  6. 9 9
      src/fpga_spi.h
  7. 18 6
      src/main.c
  8. 285 50
      src/sdnative.c
  9. 1 1
      src/snes.c
  10. 2 2
      src/sort.c
  11. 62 105
      src/spi.c
  12. 9 9
      src/spi.h
  13. 2 0
      src/uart.h
  14. 1 1
      src/xmodem.c

+ 1 - 1
src/Makefile

@@ -73,7 +73,7 @@ ASRC = startup.S crc.S
 #     (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
 # Use s -mcall-prologues when you really need size...
 #OPT = 2
-OPT = s
+OPT = 2
 
 # Debugging format.
 DEBUG = dwarf-2

+ 14 - 5
src/config.h

@@ -36,13 +36,11 @@
 #define CONFIG_UART_BAUDRATE      921600
 #define CONFIG_UART_DEADLOCKABLE
 
-#define SPI_SD                    1
-#define SPI_FPGA                  0
+#define SSP_CLK_DIVISOR_FAST 4
+#define SSP_CLK_DIVISOR_SLOW 250
 
-#define SSP_CLK_DIVISOR_FAST      4
-#define SSP_CLK_DIVISOR_SLOW      250
 #define SSP_CLK_DIVISOR_FPGA_FAST 6
-#define SSP_CLK_DIVISOR_FPGA_SLOW 16
+#define SSP_CLK_DIVISOR_FPGA_SLOW 20
 
 #define SNES_RESET_REG            LPC_GPIO1
 #define SNES_RESET_BIT            29
@@ -62,4 +60,15 @@
 
 #define QSORT_MAXELEM             1024
 
+#define SSP_REGS LPC_SSP0
+#define SSP_PCLKREG PCLKSEL1
+// 1: PCLKSEL0
+#define SSP_PCLKBIT 10
+// 1: 20
+#define SSP_DMAID_TX 0
+// 1: 2
+#define SSP_DMAID_RX 1
+// 1: 3
+#define SSP_DMACH LPC_GPDMACH0
+
 #endif

+ 1 - 0
src/ff.c

@@ -2174,6 +2174,7 @@ FRESULT f_read (
 			if (cc) {								/* Read maximum contiguous sectors directly */
 				if (csect + cc > fp->fs->csize)		/* Clip at cluster boundary */
 					cc = fp->fs->csize - csect;
+/* XXX OFFLOAD GOES HERE */
 				if (disk_read(fp->fs->drv, rbuff, sect, (BYTE)cc) != RES_OK)
 					ABORT(fp->fs, FR_DISK_ERR);
 #if !_FS_READONLY && _FS_MINIMIZE <= 2				/* Replace one of the read sectors with cached data if it contains a dirty sector */

+ 8 - 6
src/filetypes.c

@@ -24,7 +24,6 @@
    filetypes.c: directory scanning and file type detection
 */
 
-#include <stdio.h>
 #include <string.h>
 #include "config.h"
 #include "uart.h"
@@ -71,6 +70,7 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
   uint16_t numentries;
   uint32_t dirsize;
   uint8_t pass = 0;
+  char buf[10];
 
   dir_tgt = this_dir_tgt;
   if(depth==0) {
@@ -198,10 +198,12 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
                         - file name
                         - file size */
 /*                  sram_writeblock((uint8_t*)&romprops, db_tgt, sizeof(romprops)); */
-                    sram_writebyte(len+1, db_tgt);
-                    sram_writeblock(path, db_tgt + sizeof(len), pathlen + 1);
-                    sram_writelong(fno.fsize, db_tgt + sizeof(len) + pathlen + 1);
-                    db_tgt += sizeof(len) + pathlen + sizeof(fno.fsize) + 1;
+                    snprintf(buf, sizeof(buf), " % 7ldk", fno.fsize/1024);
+                    sram_writeblock(buf, db_tgt, sizeof(buf)-1);
+                    sram_writebyte(len+1, db_tgt + sizeof(buf)-1);
+                    sram_writeblock(path, db_tgt + sizeof(len) + sizeof(buf)-1, pathlen + 1);
+//                    sram_writelong(fno.fsize, db_tgt + sizeof(len) + pathlen + 1);
+                    db_tgt += sizeof(len) + pathlen + sizeof(buf)-1 + 1;
                     break;
                   case TYPE_UNKNOWN:
                   default:
@@ -224,7 +226,7 @@ uint32_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
       }
     } else uart_putc(0x30+res);
   }
-  printf("db_tgt=%lx dir_end=%lx\n", db_tgt, dir_end);
+//  printf("db_tgt=%lx dir_end=%lx\n", db_tgt, dir_end);
   sram_writelong(db_tgt, SRAM_DB_ADDR+4);
   sram_writelong(dir_end, SRAM_DB_ADDR+8);
   return crc;

+ 1 - 1
src/fpga_spi.c

@@ -52,7 +52,7 @@
 #include "timer.h"
 
 void fpga_spi_init(void) {
-  spi_init(SPI_SPEED_FPGA_FAST, SPI_FPGA);
+  spi_init(SPI_SPEED_FPGA_FAST);
 }
 
 void set_mcu_addr(uint32_t address) {

+ 9 - 9
src/fpga_spi.h

@@ -36,15 +36,15 @@
 #define FPGA_SELECT()	do {FPGA_TX_SYNC(); BITBAND(FPGA_SS_REG->FIOCLR, FPGA_SS_BIT) = 1;} while (0)
 #define FPGA_DESELECT()	do {FPGA_TX_SYNC(); BITBAND(FPGA_SS_REG->FIOSET, FPGA_SS_BIT) = 1;} while (0)
 
-#define FPGA_TX_SYNC()     spi_tx_sync(SPI_FPGA)
-#define FPGA_TX_BYTE(x)    spi_tx_byte(x, SPI_FPGA)
-#define FPGA_RX_BYTE()     spi_rx_byte(SPI_FPGA)
-#define FPGA_TXRX_BYTE(x)  spi_txrx_byte(x, SPI_FPGA)
-#define FPGA_TX_BLOCK(x,y) spi_tx_block(x,y,SPI_FPGA)
-#define FPGA_RX_BLOCK(x,y) spi_rx_block(x,y,SPI_FPGA)
-
-#define FPGA_SPI_FAST()    spi_set_speed(SPI_SPEED_FPGA_FAST, SPI_FPGA)
-#define FPGA_SPI_SLOW()    spi_set_speed(SPI_SPEED_FPGA_SLOW, SPI_FPGA)
+#define FPGA_TX_SYNC()     spi_tx_sync()
+#define FPGA_TX_BYTE(x)    spi_tx_byte(x)
+#define FPGA_RX_BYTE()     spi_rx_byte()
+#define FPGA_TXRX_BYTE(x)  spi_txrx_byte(x)
+#define FPGA_TX_BLOCK(x,y) spi_tx_block(x,y)
+#define FPGA_RX_BLOCK(x,y) spi_rx_block(x,y)
+
+#define FPGA_SPI_FAST()    spi_set_speed(SPI_SPEED_FPGA_FAST)
+#define FPGA_SPI_SLOW()    spi_set_speed(SPI_SPEED_FPGA_SLOW)
 
 void fpga_spi_init(void);
 void fpga_spi_test(void);

+ 18 - 6
src/main.c

@@ -10,7 +10,6 @@
 #include "ff.h"
 #include "diskio.h"
 #include "spi.h"
-#include "sdcard.h"
 #include "fileops.h"
 #include "fpga.h"
 #include "fpga_spi.h"
@@ -23,6 +22,7 @@
 #include "tests.h"
 #include "cli.h"
 #include "sdnative.h"
+#include "crc.h"
 
 #define EMC0TOGGLE	(3<<4)
 #define MR0R		(1<<1)
@@ -54,15 +54,13 @@ int main(void) {
   timer_init();
   uart_init();
   fpga_spi_init();
-  spi_preinit(SPI_FPGA);
-  spi_preinit(SPI_SD);
+  spi_preinit();
  /* do this last because the peripheral init()s change PCLK dividers */
   clock_init();
 
 //  sd_init();
   sdn_init();
 //  while(1);
-
   fpga_spi_init();
   delay_ms(10);
   printf("\n\nsd2snes mk.2\n============\nfw ver.: " VER "\ncpu clock: %d Hz\n", CONFIG_CPU_FREQUENCY);
@@ -105,6 +103,16 @@ restart:
   uint32_t mem_dir_id = sram_readlong(SRAM_DIRID);
   uint32_t mem_magic = sram_readlong(SRAM_SCRATCHPAD);
 
+/*  printf("savetest...");
+  int i;
+  uint16_t testcrc = 0;
+  for(i=0; i<128; i++) {
+    testcrc = crc_xmodem_update(testcrc, 0xff);
+  }
+  printf("testcrc = %04x\n", testcrc);
+  save_sram((uint8_t*)"/pretty long filename here you know.bin", 0x400000, SRAM_DB_ADDR);
+  printf("it's over!\n");
+  while(1)cli_entrycheck(); */
   printf("mem_magic=%lx mem_dir_id=%lx saved_dir_id=%lx\n", mem_magic, mem_dir_id, saved_dir_id);
   mem_magic=0x12938712; /* always rescan card for now */
   if((mem_magic != 0x12345678) || (mem_dir_id != saved_dir_id)) {
@@ -142,7 +150,6 @@ restart:
     load_sram((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR);
     load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR);
   }
-
   /* load menu */
   uart_putc('(');
   load_rom((uint8_t*)"/sd2snes/menu.bin", SRAM_MENU_ADDR);
@@ -161,19 +168,23 @@ restart:
   snes_reset(0);
 
   uint8_t cmd = 0;
+  uint32_t filesize=0;
   printf("test sram\n");
   while(!sram_reliable());
   printf("ok\n");
 sram_hexdump(SRAM_DB_ADDR, 0x200);
+
   while(!cmd) {
     cmd=menu_main_loop();
+    printf("derp %d\n", cmd);
     sleep_ms(50);
+    uart_putc('-');
     switch(cmd) {
       case SNES_CMD_LOADROM:
         get_selected_name(file_lfn);
         set_mcu_ovr(1);
         printf("Selected name: %s\n", file_lfn);
-        load_rom(file_lfn, SRAM_ROM_ADDR);
+        filesize = load_rom(file_lfn, SRAM_ROM_ADDR);
         if(romprops.ramsize_bytes) {
           strcpy(strrchr((char*)file_lfn, (int)'.'), ".srm");
           printf("SRM file: %s\n", file_lfn);
@@ -181,6 +192,7 @@ sram_hexdump(SRAM_DB_ADDR, 0x200);
         } else {
           printf("No SRAM\n");
         }
+save_sram((uint8_t*)"/debug.smc", filesize, SRAM_ROM_ADDR);
         set_mcu_ovr(0);
         snes_reset(1);
         delay_ms(100);

+ 285 - 50
src/sdnative.c

@@ -120,7 +120,10 @@ uint8_t csd[17];
 uint8_t ccs=0;
 uint8_t rca1, rca2;
 
-int during_blocktrans = 0;
+enum trans_state { TRANS_NONE = 0, TRANS_READ, TRANS_WRITE };
+enum cmd_state { CMD_RSP = 0, CMD_RSPDAT, CMD_DAT };
+
+int during_blocktrans = TRANS_NONE;
 uint32_t last_block = 0;
 
 /**
@@ -161,18 +164,18 @@ static uint32_t getbits(void *buffer, uint16_t start, int8_t bits) {
 
 static inline void wiggle_slow_pos(uint16_t times) {
   while(times--) {
-    delay_us(5);
+    delay_us(2);
     BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
-    delay_us(5);
+    delay_us(2);
     BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
   }
 }
 
 static inline void wiggle_slow_neg(uint16_t times) {
   while(times--) {
-    delay_us(5);
+    delay_us(2);
     BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
-    delay_us(5);
+    delay_us(2);
     BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
   }
 }
@@ -191,6 +194,18 @@ static inline void wiggle_fast_neg(uint16_t times) {
   }
 }
 
+static inline void wiggle_fast_neg1(void) {
+  BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
+  BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
+}
+
+static inline void wiggle_fast_pos1(void) {
+  BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
+  BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
+}
+
+
+
 
 /* 
    send_command_slow
@@ -272,10 +287,10 @@ int send_command_slow(uint8_t* cmd, uint8_t* rsp){
 */
 int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
   uint8_t datshift=8, cmdshift, i=6;
-  int rsplen, dat=0, datcnt=512, j=0;
-  static int state=0;
+  int rsplen, dat=0, waitbusy=0, datcnt=512, j=0;
+  static int state=CMD_RSP;
 //  printf("send_command_fast: sending CMD:\n");
-  wiggle_fast_pos(5);
+  wiggle_fast_pos(9);
 //  uart_trace(cmd, 0, 6);
   switch(*cmd & 0x3f) {
     case 0:
@@ -286,15 +301,18 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
     case 10:
       rsplen = 17;
       break;
+    case 12:
+      rsplen = 6;
+      waitbusy = 1;
+      break;
     case 17:
     case 18:
       dat = 1;
     default:
       rsplen = 6;
   }
-
   if(dat && (buf==NULL)) {
-    printf("error: buf is null but data transfer expected.\n");
+    printf("send_command_fast error: buf is null but data transfer expected.\n");
     return 0;
   }
   /* send command */
@@ -311,7 +329,7 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
       } else {
         BITBAND(SD_CMDREG->FIOCLR, SD_CMDPIN) = 1;
       }
-      wiggle_fast_pos(1);
+      wiggle_fast_pos1();
     } while (cmdshift);
     cmd++;
   }
@@ -323,7 +341,7 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
     uint16_t timeout=65535;
     /* wait for responsebob */
     while((BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) && --timeout) {
-      wiggle_fast_neg(1);
+      wiggle_fast_neg1();
     }
   //  printf("timeout=%d\n", timeout);  
     if(!timeout) {
@@ -339,13 +357,13 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
           if(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
 //            printf("data start\n");
             j=datcnt;
-            state=1;
+            state=CMD_RSPDAT;
             break;
           }
         }
         cmdshift--;
         cmddata |= (BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) << cmdshift;
-        wiggle_fast_neg(1);
+        wiggle_fast_neg1();
       } while (cmdshift);
       if(state==1)break;
       *rsp=cmddata;
@@ -353,7 +371,7 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
       rsp++;
     }
 
-    if(state==1) { /* process response+data */
+    if(state==CMD_RSPDAT) { /* process response+data */
       int startbit=1;
       printf("processing rsp+data cmdshift=%d i=%d j=%d\n", cmdshift, i, j);
       datshift=8;
@@ -368,14 +386,15 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
           i--;
           if(!i) {
             printf("response end\n");
-            if(j) state=2; /* response over, remaining data */
+            if(j) state=CMD_DAT; /* response over, remaining data */
             break;
           }
         }
         if(!startbit) {
-          datshift--;
-          datdata |= (BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) << datshift;
-      
+          datshift-=4;
+          datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))
+                      |((SD_DAT1REG->FIOPIN >> 13) & 0x6)
+                      |((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << datshift;      
           if(!datshift) {
             datshift=8;
             *buf=datdata;
@@ -386,42 +405,69 @@ int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
           }
         }
         startbit=0;
-        wiggle_fast_neg(1);
+        wiggle_fast_neg1();
       }
     }
 
-    if(dat && state!=2) { /* response ended before data */
-      state=2;
+    if(dat && state != CMD_DAT) { /* response ended before data */
+      state=CMD_DAT;
       j=datcnt;
       datshift=8;
 //      printf("response over, waiting for data...\n");
       while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) {
-        wiggle_fast_neg(1);
+        wiggle_fast_neg1();
       }
-      wiggle_fast_neg(1); /* eat the start bit */
+      wiggle_fast_neg1(); /* eat the start bit */
     }
     
-    if(state==2) { /* transfer rest of data */
+    if(state==CMD_DAT) { /* transfer rest of data */
 //      printf("remaining data: %d\n", j);
-      while(1) {
-        datshift-=4;
-        datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))
-                    |((SD_DAT1REG->FIOPIN >> 13) & 0x6)
-                    |((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << datshift;
-        if(!datshift) {
-          datshift=8;
+      if(datshift==8) {
+        while(1) {
+          datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))
+                      |((SD_DAT1REG->FIOPIN >> 13) & 0x6)
+                      |((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << 4;
+          wiggle_fast_neg1();
+
+          datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))
+                      |((SD_DAT1REG->FIOPIN >> 13) & 0x6)
+                      |((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3));
+          wiggle_fast_neg1();
+
           *buf=datdata;
           datdata=0;
           buf++;
           j--;
           if(!j) break;
         }
-        wiggle_fast_neg(1);
+      } else {
+
+        while(1) {
+          datshift-=4;
+          datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))
+                      |((SD_DAT1REG->FIOPIN >> 13) & 0x6)
+                      |((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << datshift;
+          if(!datshift) {
+            datshift=8;
+            *buf=datdata;
+            datdata=0;
+            buf++;
+            j--;
+            if(!j) break;
+          }
+          wiggle_fast_neg1();
+        }
       }
     }
     /* just eat the crcs for now */
-    wiggle_fast_neg(17);
-    state=3;
+    if(dat) wiggle_fast_neg(17);
+
+    if(waitbusy) {
+      while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
+        wiggle_fast_neg1();
+      }
+    }
+    state=CMD_RSP;
   }
   return rsplen;
 }
@@ -436,18 +482,19 @@ void make_crc7(uint8_t* cmd) {
   cmd[5]=(cmd[5] << 1) | 1;
 }
 
-void stream_datablock(uint8_t* buf) {
-  uint8_t datshift=8;
+void stream_datablock(uint8_t *buf) {
+//  uint8_t datshift=8;
   int j=512;
   uint8_t datdata=0;
   uint16_t timeout=65535;
 
   while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) {
-    wiggle_fast_neg(1);
+    wiggle_fast_neg1();
   }
-  wiggle_fast_neg(1); /* eat the start bit */
+  wiggle_fast_neg1(); /* eat the start bit */
 
   while(1) {
+/*
     datshift-=4;
     datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))
                 |((SD_DAT1REG->FIOPIN >> 13) & 0x6)
@@ -460,20 +507,164 @@ void stream_datablock(uint8_t* buf) {
       j--;
       if(!j) break;
     }
-    wiggle_fast_neg(1);
+*/
+    datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))
+                |((SD_DAT1REG->FIOPIN >> 13) & 0x6)
+                |((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3)) << 4;
+    wiggle_fast_neg1();
+
+    datdata |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))
+                |((SD_DAT1REG->FIOPIN >> 13) & 0x6)
+                |((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3));
+ 
+    wiggle_fast_neg1();
+
+    *buf=datdata;
+    datdata=0;
+    buf++;
+    j--;
+    if(!j) break;
   }
 
   /* eat the crc for now */ 
   wiggle_fast_neg(17);
 }
 
-void read_block(uint32_t address, uint8_t* buf) {
-  if(during_blocktrans && (last_block == address-1)) {
+void send_datablock(uint8_t *buf) {
+  uint16_t crc0=0, crc1=0, crc2=0, crc3=0, cnt=512;
+  uint8_t dat0=0, dat1=0, dat2=0, dat3=0, crcshift, datshift;
+//uart_trace(buf, 0, 512);
+  wiggle_fast_pos(1);
+//  printf("send_datablock: wait for card\n");
+  /* wait - card might be busy */
+  while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
+    wiggle_fast_neg(1);
+    printf(".");
+  }
+  BITBAND(SD_DAT0REG->FIODIR, SD_DAT0PIN) = 1;
+  BITBAND(SD_DAT1REG->FIODIR, SD_DAT1PIN) = 1;
+  BITBAND(SD_DAT2REG->FIODIR, SD_DAT2PIN) = 1;
+  BITBAND(SD_DAT3REG->FIODIR, SD_DAT3PIN) = 1;
+
+  BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1;
+  BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1;
+  BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1;
+  BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1;
+  
+  wiggle_fast_pos(1); /* send start bit to card */
+  crcshift=8;
+  while(cnt--) {
+    datshift=8;
+    do {
+      datshift-=4;
+      if(((*buf)>>datshift) & 0x8) {
+        BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1;
+      } else {
+        BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1;
+      }
+      if(((*buf)>>datshift) & 0x4) {
+        BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1;
+      } else {
+        BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1;
+      }
+      if(((*buf)>>datshift) & 0x2){
+        BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1;
+      } else {
+        BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1;
+      }
+      if(((*buf)>>datshift) & 0x1){
+        BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1;
+      } else {
+        BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1;
+      }
+      wiggle_fast_pos(1);
+    } while (datshift);
+
+    crcshift-=2;
+    dat0 |= (((*buf)&0x01) | (((*buf)&0x10) >> 3)) << crcshift;
+    dat1 |= ((((*buf)&0x02) >> 1) | (((*buf)&0x20) >> 4)) << crcshift;
+    dat2 |= ((((*buf)&0x04) >> 2) | (((*buf)&0x40) >> 5)) << crcshift;
+    dat3 |= ((((*buf)&0x08) >> 3) | (((*buf)&0x80) >> 6)) << crcshift;
+    if(!crcshift) {
+      crc0 = crc_xmodem_update(crc0, dat0);
+      crc1 = crc_xmodem_update(crc1, dat1);
+      crc2 = crc_xmodem_update(crc2, dat2);
+      crc3 = crc_xmodem_update(crc3, dat3);
+      crcshift=8;
+      dat0=0;
+      dat1=0;
+      dat2=0;
+      dat3=0;
+    }
+    buf++;
+  }
+//  printf("crc0=%04x crc1=%04x crc2=%04x crc3=%04x ", crc0, crc1, crc2, crc3);
+  /* send crcs */
+  datshift=16;
+  do {
+    datshift--;
+    if((crc0 >> datshift)&1) {
+      BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1;
+    } else {
+      BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1;
+    }
+    if((crc1 >> datshift)&1) {
+      BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1;
+    } else {
+      BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1;
+    }
+    if((crc2 >> datshift)&1) {
+      BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1;
+    } else {
+      BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1;
+    }
+    if((crc3 >> datshift)&1) {
+      BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1;
+    } else {
+      BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1;
+    }
+    wiggle_fast_pos(1);
+  } while(datshift);
+  /* send end bit */
+  BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1;
+  BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1;
+  BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1;
+  BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1;
+
+  wiggle_fast_pos(1);
+  
+  BITBAND(SD_DAT0REG->FIODIR, SD_DAT0PIN) = 0;
+  BITBAND(SD_DAT1REG->FIODIR, SD_DAT1PIN) = 0;
+  BITBAND(SD_DAT2REG->FIODIR, SD_DAT2PIN) = 0;
+  BITBAND(SD_DAT3REG->FIODIR, SD_DAT3PIN) = 0;
+
+  wiggle_fast_neg(4);
+  dat0=0;
+
+  datshift=3;
+  do {
+    datshift--;
+    dat0 |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) << datshift);
+    wiggle_fast_neg(1);
+  } while (datshift);
+
+  if(dat0!=2) {
+    printf("crc error! %02x\n", dat0);
+    while(1);
+  }
+  wiggle_fast_neg(1);
+  while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
+    wiggle_fast_neg(1);
+  } 
+}
+
+void read_block(uint32_t address, uint8_t *buf) {
+  if(during_blocktrans == TRANS_READ && (last_block == address-1)) {
     stream_datablock(buf);
     last_block=address;
   } else {
     if(during_blocktrans) {
-      /* send STOP_TRANSMISSION */ 
+      /* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */ 
       cmd[0]=0x40+STOP_TRANSMISSION;
       cmd[1]=0;
       cmd[2]=0;
@@ -493,11 +684,40 @@ void read_block(uint32_t address, uint8_t* buf) {
     send_command_fast(cmd, rsp, buf);
 //    uart_trace(cmd, 0, 6);
 //    uart_trace(rsp, 0, rsplen);
-    during_blocktrans = 1;
+    during_blocktrans = TRANS_READ;
   }
 //  uart_trace(buf, 0, 512);
 }
 
+void write_block(uint32_t address, uint8_t* buf) {
+  if(during_blocktrans == TRANS_WRITE && (last_block == address-1)) {
+    send_datablock(buf);
+    last_block=address;
+  } else {
+    if(during_blocktrans) {
+      /* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */
+      cmd[0]=0x40+STOP_TRANSMISSION;
+      cmd[1]=0;
+      cmd[2]=0;
+      cmd[3]=0;
+      cmd[4]=0;
+      cmd[5]=0x61;
+      send_command_fast(cmd, rsp, NULL);
+    }
+    last_block=address;
+    if(!ccs) address <<= 9;
+    cmd[0]=0x40+WRITE_MULTIPLE_BLOCK;
+    cmd[1]=address>>24;
+    cmd[2]=address>>16;
+    cmd[3]=address>>8;
+    cmd[4]=address;
+    make_crc7(cmd);
+    send_command_fast(cmd, rsp, NULL); /* only send cmd & get response */
+    send_datablock(buf);
+    during_blocktrans = TRANS_WRITE;
+  }
+}
+
 //
 // Public functions
 //
@@ -520,15 +740,14 @@ DRESULT sdn_initialize(BYTE drv) {
   uint8_t cmd[6]={0,0,0,0,0,0}; /* command */
   uint8_t rsp[17]; /* space for response */
   int rsplen;
-  uint8_t hcs=0, data;
+  uint8_t hcs=0;
   if(drv>=MAX_CARDS)
     return STA_NOINIT|STA_NODISK;
 
-  data=BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN);
   /* if the card is sending data from before a reset we try to deselect it
      prior to initialization */
-  for(rsplen=0; rsplen<1042; rsplen++) {
-    if((data != BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
+  for(rsplen=0; rsplen<2042; rsplen++) {
+    if(!(BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN))) {
       printf("card seems to be sending data, attempting deselect\n");
       cmd[0]=0x40+7;
       cmd[1]=0;
@@ -542,7 +761,6 @@ DRESULT sdn_initialize(BYTE drv) {
         printf("CMD7 deselect no response! D:\n");
       }
     }
-    data=BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN);
     wiggle_slow_neg(1);
   }
   cmd[0]=0x40+GO_IDLE_STATE;
@@ -638,6 +856,7 @@ DRESULT sdn_initialize(BYTE drv) {
   cmd[4]=0;
   make_crc7(cmd);
 
+  /* record CSD for getinfo */
   if((rsplen=send_command_slow(cmd, csd))) {
 //    printf("CMD9 response:\n");
 //    uart_trace(rsp, 0, rsplen);
@@ -652,6 +871,7 @@ DRESULT sdn_initialize(BYTE drv) {
   cmd[4]=0;
   make_crc7(cmd);
 
+  /* select the card */
   if((rsplen=send_command_slow(cmd, rsp))) {
 //    printf("CMD7 response:\n");
 //    uart_trace(rsp, 0, rsplen);
@@ -667,6 +887,7 @@ DRESULT sdn_initialize(BYTE drv) {
   cmd[4]=0;
   make_crc7(cmd);
 
+  /* get card status */
   if((rsplen=send_command_fast(cmd, rsp, NULL))) {
 //    printf("CMD13 response:\n");
 //    uart_trace(rsp, 0, rsplen);
@@ -674,6 +895,7 @@ DRESULT sdn_initialize(BYTE drv) {
     printf("CMD13 no response!\n");
   }
 
+  /* set bus width */
   cmd[0]=0x40+55;
   cmd[1]=rca1;
   cmd[2]=rca2;
@@ -776,8 +998,21 @@ DRESULT sdn_getinfo(BYTE drv, BYTE page, void *buffer) {
 DRESULT disk_getinfo(BYTE drv, BYTE page, void *buffer) __attribute__ ((weak, alias("sdn_getinfo")));
 
 DRESULT sdn_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) {
-  return RES_OK;
+  uint8_t sec;
+  uint8_t *buf = (uint8_t*)buffer;
+  if(drv >= MAX_CARDS) {
+    return RES_NOTRDY;
+  }
+  if (sdn_status(drv) & STA_NODISK)
+    return RES_NOTRDY;
+
+  for(sec=0; sec<count; sec++) {
+    write_block(sector+sec, buf);
+    buf+=512;
+  }
+  return RES_OK; 
 }
+
 DRESULT disk_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) __attribute__ ((weak, alias("sdn_write")));
 
 /* Detect changes of SD card 0 */

+ 1 - 1
src/snes.c

@@ -135,5 +135,5 @@ uint8_t menu_main_loop() {
 void get_selected_name(uint8_t* fn) {
   uint32_t addr = sram_readlong(SRAM_PARAM_ADDR);
   printf("fd addr=%lx\n", addr);
-  sram_readblock(fn, addr+1+SRAM_MENU_ADDR, 256);
+  sram_readblock(fn, addr+10+SRAM_MENU_ADDR, 256);
 }

+ 2 - 2
src/sort.c

@@ -67,8 +67,8 @@ stat_getstring++;
     /* is directory link, name offset 6 */
     sram_readblock(ptr, addr+0x6+SRAM_MENU_ADDR, 20);
   } else {
-    /* is file link, name offset 65 */
-    sram_readblock(ptr, addr+1+SRAM_MENU_ADDR, 20);
+    /* is file link, name offset 10 */
+    sram_readblock(ptr, addr+10+SRAM_MENU_ADDR, 20);
   }
   ptr[20]=0;
 }

+ 62 - 105
src/spi.c

@@ -36,174 +36,134 @@
 #define SSP_RFF 3   // Receive FIFO full
 #define SSP_BSY 4   // Busy
 
-typedef struct {
-  LPC_SSP_TypeDef     *SSP_REGS;
-  LPC_GPDMACH_TypeDef *SSP_DMACH;
-  uint32_t            *SSP_PCLKREG;
-  int                  SSP_PCLKBIT;
-  int                  SSP_DMAID_TX;
-  int                  SSP_DMAID_RX;
-} ssp_props;
-
-
-static ssp_props SSP_SEL[2] = {
-  { LPC_SSP0, LPC_GPDMACH0, (uint32_t*)&(LPC_SC->PCLKSEL1), 10, 0, 1 }, /* SSP0 */
-  { LPC_SSP1, LPC_GPDMACH1, (uint32_t*)&(LPC_SC->PCLKSEL0), 20, 2, 3 }  /* SSP1 */
-};
-
-void spi_preinit(int device) {
-  /* select interface */
-  ssp_props *ssp = &(SSP_SEL[device]);
+void spi_preinit() {
 
   /* Set clock prescaler to 1:1 */
-  BITBAND(*(ssp->SSP_PCLKREG), ssp->SSP_PCLKBIT) = 1;
+  BITBAND(LPC_SC->SSP_PCLKREG, SSP_PCLKBIT) = 1;
 }
 
-void spi_init(spi_speed_t speed, int device) {
-
-  /* select interface */
-  ssp_props *ssp = &(SSP_SEL[device]);
+void spi_init(spi_speed_t speed) {
 
   /* configure data format - 8 bits, SPI, CPOL=0, CPHA=0, 1 clock per bit */
-  ssp->SSP_REGS->CR0 = (8-1);
+  SSP_REGS->CR0 = (8-1);
 
   /* set clock prescaler */
   if (speed == SPI_SPEED_FAST) {
-    ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_FAST;
+    SSP_REGS->CPSR = SSP_CLK_DIVISOR_FAST;
   } else if (speed == SPI_SPEED_SLOW) {
-    ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_SLOW;
+    SSP_REGS->CPSR = SSP_CLK_DIVISOR_SLOW;
   } else if (speed == SPI_SPEED_FPGA_FAST) {
-    ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_FAST;
+    SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_FAST;
   } else {
-    ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_SLOW;
+    SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_SLOW;
   }
 
   /* Enable SSP */
-  ssp->SSP_REGS->CR1 = BV(1);
+  SSP_REGS->CR1 = BV(1);
 
   /* Enable DMA controller, little-endian mode */
   BITBAND(LPC_SC->PCONP, 29) = 1;
   LPC_GPDMA->DMACConfig = 1;
 }
 
-void spi_tx_sync(int device) {
-  /* select interface */
-  ssp_props *ssp = &(SSP_SEL[device]);
-  
+void spi_tx_sync() {
   /* Wait until TX fifo is flushed */
-  while (BITBAND(ssp->SSP_REGS->SR, SSP_BSY)) ;
+  while (BITBAND(SSP_REGS->SR, SSP_BSY)) ;
 }
 
-void spi_tx_byte(uint8_t data, int device) {
-
-  /* select interface */
-  ssp_props *ssp = &(SSP_SEL[device]);
-
+void spi_tx_byte(uint8_t data) {
   /* Wait until TX fifo can accept data */
-  while (!BITBAND(ssp->SSP_REGS->SR, SSP_TNF)) ;
+  while (!BITBAND(SSP_REGS->SR, SSP_TNF)) ;
 
   /* Send byte */
-  ssp->SSP_REGS->DR = data;
+  SSP_REGS->DR = data;
 }
 
-uint8_t spi_txrx_byte(uint8_t data, int device) {
-  /* select interface */
-  ssp_props *ssp = &(SSP_SEL[device]);
-
+uint8_t spi_txrx_byte(uint8_t data) {
   /* Wait until SSP is not busy */
-  while (BITBAND(ssp->SSP_REGS->SR, SSP_BSY)) ;
+  while (BITBAND(SSP_REGS->SR, SSP_BSY)) ;
 
   /* Clear RX fifo */
-  while (BITBAND(ssp->SSP_REGS->SR, SSP_RNE))
-    (void) ssp->SSP_REGS->DR;
+  while (BITBAND(SSP_REGS->SR, SSP_RNE))
+    (void) SSP_REGS->DR;
 
   /* Transmit a single dummy byte */
-  ssp->SSP_REGS->DR = data;
+  SSP_REGS->DR = data;
 
   /* Wait until answer has been received */
-  while (!BITBAND(ssp->SSP_REGS->SR, SSP_RNE)) ;
+  while (!BITBAND(SSP_REGS->SR, SSP_RNE)) ;
 
-  return ssp->SSP_REGS->DR;
+  return SSP_REGS->DR;
 }
 
-uint8_t spi_rx_byte(int device) {
-
-  /* select interface */
-  ssp_props *ssp = &(SSP_SEL[device]);
-
+uint8_t spi_rx_byte() {
   /* Wait until SSP is not busy */
-  while (BITBAND(ssp->SSP_REGS->SR, SSP_BSY)) ;
+  while (BITBAND(SSP_REGS->SR, SSP_BSY)) ;
 
   /* Clear RX fifo */
-  while (BITBAND(ssp->SSP_REGS->SR, SSP_RNE))
-    (void) ssp->SSP_REGS->DR;
+  while (BITBAND(SSP_REGS->SR, SSP_RNE))
+    (void) SSP_REGS->DR;
 
   /* Transmit a single dummy byte */
-  ssp->SSP_REGS->DR = 0xff;
+  SSP_REGS->DR = 0xff;
 
   /* Wait until answer has been received */
-  while (!BITBAND(ssp->SSP_REGS->SR, SSP_RNE)) ;
+  while (!BITBAND(SSP_REGS->SR, SSP_RNE)) ;
 
-  return ssp->SSP_REGS->DR;
+  return SSP_REGS->DR;
 }
 
-void spi_tx_block(const void *ptr, unsigned int length, int device) {
+void spi_tx_block(const void *ptr, unsigned int length) {
   const uint8_t *data = (const uint8_t *)ptr;
 
-  /* select interface */
-  ssp_props *ssp = &(SSP_SEL[device]);
-
   while (length--) {
   /* Wait until TX fifo can accept data */
-    while (!BITBAND(ssp->SSP_REGS->SR, SSP_TNF)) ;
+    while (!BITBAND(SSP_REGS->SR, SSP_TNF)) ;
 
-    ssp->SSP_REGS->DR = *data++;
+    SSP_REGS->DR = *data++;
   }
 }
 
-void spi_rx_block(void *ptr, unsigned int length, int device) {
+void spi_rx_block(void *ptr, unsigned int length) {
   uint8_t *data = (uint8_t *)ptr;
   unsigned int txlen = length;
 
-  /* select interface */
-  ssp_props *ssp = &(SSP_SEL[device]);
-
   /* Wait until SSP is not busy */
-  while (BITBAND(ssp->SSP_REGS->SR, SSP_BSY)) ;
+  while (BITBAND(SSP_REGS->SR, SSP_BSY)) ;
 
   /* Clear RX fifo */
-  while (BITBAND(ssp->SSP_REGS->SR, SSP_RNE))
-    (void) ssp->SSP_REGS->DR;
+  while (BITBAND(SSP_REGS->SR, SSP_RNE))
+    (void) SSP_REGS->DR;
 
   if ((length & 3) != 0 || ((uint32_t)ptr & 3) != 0) {
     /* Odd length or unaligned buffer */
     while (length > 0) {
       /* Wait until TX or RX FIFO are ready */
-      while (txlen > 0 && !BITBAND(ssp->SSP_REGS->SR, SSP_TNF) &&
-             !BITBAND(ssp->SSP_REGS->SR, SSP_RNE)) ;
+      while (txlen > 0 && !BITBAND(SSP_REGS->SR, SSP_TNF) &&
+             !BITBAND(SSP_REGS->SR, SSP_RNE)) ;
 
       /* Try to receive data */
-      while (length > 0 && BITBAND(ssp->SSP_REGS->SR, SSP_RNE)) {
-        *data++ = ssp->SSP_REGS->DR;
+      while (length > 0 && BITBAND(SSP_REGS->SR, SSP_RNE)) {
+        *data++ = SSP_REGS->DR;
         length--;
       }
 
       /* Send dummy data until TX full or RX ready */
-      while (txlen > 0 && BITBAND(ssp->SSP_REGS->SR, SSP_TNF) && !BITBAND(ssp->SSP_REGS->SR, SSP_RNE)) {
+      while (txlen > 0 && BITBAND(SSP_REGS->SR, SSP_TNF) && !BITBAND(SSP_REGS->SR, SSP_RNE)) {
         txlen--;
-        ssp->SSP_REGS->DR = 0xff;
+        SSP_REGS->DR = 0xff;
       }
     }
   } else {
     /* Clear interrupt flags of DMA channels 0 */
-    LPC_GPDMA->DMACIntTCClear = BV(device);
-    LPC_GPDMA->DMACIntErrClr  = BV(device);
+    LPC_GPDMA->DMACIntTCClear = BV(0);
+    LPC_GPDMA->DMACIntErrClr  = BV(0);
 
     /* Set up RX DMA channel */
-    ssp->SSP_DMACH->DMACCSrcAddr  = (uint32_t)&ssp->SSP_REGS->DR;
-    ssp->SSP_DMACH->DMACCDestAddr = (uint32_t)ptr;
-    ssp->SSP_DMACH->DMACCLLI      = 0; // no linked list
-    ssp->SSP_DMACH->DMACCControl  = length
+    SSP_DMACH->DMACCSrcAddr  = (uint32_t)&SSP_REGS->DR;
+    SSP_DMACH->DMACCDestAddr = (uint32_t)ptr;
+    SSP_DMACH->DMACCLLI      = 0; // no linked list
+    SSP_DMACH->DMACCControl  = length
       | (0 << 12) // source burst size 1 (FIXME: Check if larger possible/useful)
       | (0 << 15) // destination burst size 1
       | (0 << 18) // source transfer width 1 byte
@@ -211,52 +171,49 @@ void spi_rx_block(void *ptr, unsigned int length, int device) {
       | (0 << 26) // source address not incremented
       | (1 << 27) // destination address incremented
       ;
-    ssp->SSP_DMACH->DMACCConfig = 1 // enable channel
-      | (ssp->SSP_DMAID_RX << 1) // data source SSP RX
+    SSP_DMACH->DMACCConfig = 1 // enable channel
+      | (SSP_DMAID_RX << 1) // data source SSP RX
       | (2 << 11) // transfer from peripheral to memory
       ;
 
     /* Enable RX FIFO DMA */
-    ssp->SSP_REGS->DMACR = 1;
+    SSP_REGS->DMACR = 1;
 
     /* Write <length> bytes into TX FIFO */
     // FIXME: Any value in doing this using DMA too?
     while (txlen > 0) {
-      while (txlen > 0 && BITBAND(ssp->SSP_REGS->SR, SSP_TNF)) {
+      while (txlen > 0 && BITBAND(SSP_REGS->SR, SSP_TNF)) {
         txlen--;
-        ssp->SSP_REGS->DR = 0xff;
+        SSP_REGS->DR = 0xff;
       }
     }
 
     /* Wait until DMA channel disables itself */
-    while (ssp->SSP_DMACH->DMACCConfig & 1) ;
+    while (SSP_DMACH->DMACCConfig & 1) ;
 
     /* Disable RX FIFO DMA */
-    ssp->SSP_REGS->DMACR = 0;
+    SSP_REGS->DMACR = 0;
   }
 }
 
-void spi_set_speed(spi_speed_t speed, int device) {
-  /* select interface */
-  ssp_props *ssp = &(SSP_SEL[device]);
-
+void spi_set_speed(spi_speed_t speed) {
   /* Wait until TX fifo is empty */
-  while (!BITBAND(ssp->SSP_REGS->SR, 0)) ;
+  while (!BITBAND(SSP_REGS->SR, 0)) ;
 
   /* Disable SSP (FIXME: Is this required?) */
-  ssp->SSP_REGS->CR1 = 0;
+  SSP_REGS->CR1 = 0;
 
   /* Change clock divisor */
   if (speed == SPI_SPEED_FAST) {
-    ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_FAST;
+    SSP_REGS->CPSR = SSP_CLK_DIVISOR_FAST;
   } else if (speed == SPI_SPEED_SLOW) {
-    ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_SLOW;
+    SSP_REGS->CPSR = SSP_CLK_DIVISOR_SLOW;
   } else if (speed == SPI_SPEED_FPGA_FAST) {
-    ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_FAST;
+    SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_FAST;
   } else {
-    ssp->SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_SLOW;
+    SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_SLOW;
   }
 
   /* Enable SSP */
-  ssp->SSP_REGS->CR1 = BV(1);
+  SSP_REGS->CR1 = BV(1);
 }

+ 9 - 9
src/spi.h

@@ -33,30 +33,30 @@
 typedef enum { SPI_SPEED_FAST, SPI_SPEED_SLOW, SPI_SPEED_FPGA_FAST, SPI_SPEED_FPGA_SLOW } spi_speed_t;
 
 /* Pre-Initialize SPI interface (PCLK divider before PLL setup) */
-void spi_preinit(int device);
+void spi_preinit(void);
 
 /* Initialize SPI interface */
-void spi_init(spi_speed_t speed, int device);
+void spi_init(spi_speed_t speed);
 
 /* Transmit a single byte */
-void spi_tx_byte(uint8_t data, int device);
+void spi_tx_byte(uint8_t data);
 
 /* Transmit a single byte and return received data */
-uint8_t spi_txrx_byte(uint8_t data, int device);
+uint8_t spi_txrx_byte(uint8_t data);
 
 /* Transmit a data block */
-void spi_tx_block(const void *data, unsigned int length, int device);
+void spi_tx_block(const void *data, unsigned int length);
 
 /* Receive a single byte */
-uint8_t spi_rx_byte(int device);
+uint8_t spi_rx_byte(void);
 
 /* Receive a data block */
-void spi_rx_block(void *data, unsigned int length, int device);
+void spi_rx_block(void *data, unsigned int length);
 
 /* Switch speed of SPI interface */
-void spi_set_speed(spi_speed_t speed, int device);
+void spi_set_speed(spi_speed_t speed);
 
 /* wait for SPI TX FIFO to become empty */
-void spi_tx_sync(int device);
+void spi_tx_sync(void);
 
 #endif

+ 2 - 0
src/uart.h

@@ -7,6 +7,7 @@
 #ifndef UART_H
 #define UART_H
 
+#include <stdio.h>
 #include <stdint.h>
 
 //#ifdef CONFIG_UART_DEBUG
@@ -28,6 +29,7 @@ void uart_puthex(uint8_t num);
 void uart_trace(void *ptr, uint16_t start, uint16_t len);
 void uart_flush(void);
 int  printf(const char *fmt, ...);
+int  snprintf(char *str, size_t size, const char *format, ...);
 #define uart_putcrlf() uart_putc('\n')
 
 #else

+ 1 - 1
src/xmodem.c

@@ -20,7 +20,7 @@ void xmodem_rxfile(FIL* fil) {
   FRESULT res;
   uart_flush();
   do {
-    sleep_ms(10000);
+    delay_ms(10000);
     uart_putc(ASC_NAK);
   } while (uart_getc() != ASC_SOH);
   do {