Переглянути джерело

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

ikari 13 роки тому
батько
коміт
561477ec53
14 змінених файлів з 414 додано та 196 видалено
  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 {