From 114dfd624a977449de9be7b32cf79004d2613f79 Mon Sep 17 00:00:00 2001
From: Erik Strand <erik.strand@cba.mit.edu>
Date: Sun, 12 May 2019 16:08:47 -0400
Subject: [PATCH] Read an SD card, if somewhat unreliably

Bit banging is not the way to go.
---
 sd_tests/neil/read_sd.c | 123 +++++++++++++++++++++++++---------------
 1 file changed, 76 insertions(+), 47 deletions(-)

diff --git a/sd_tests/neil/read_sd.c b/sd_tests/neil/read_sd.c
index 65e67f6..936a263 100644
--- a/sd_tests/neil/read_sd.c
+++ b/sd_tests/neil/read_sd.c
@@ -221,7 +221,7 @@ unsigned char SPI_write(uint8_t chr) {
 // SD_command
 //    write an SD command and return the response
 //
-void SD_command(uint8_t command,uint32_t argument,uint8_t CRC,uint8_t *result) {
+void SD_command(uint8_t command, uint32_t argument, uint8_t CRC, uint8_t *result) {
    clear(CS_port,CS_pin);
    SPI_write(command);
    SPI_write((argument >> 24) & 0xFF);
@@ -300,49 +300,22 @@ void SD_read(uint32_t sector,uint16_t offset,uint8_t *buffer,uint16_t size) {
    set(CS_port,CS_pin);
 }
 
-//
-// main
-//
-int main(void) {
-   //
-   // main
-   //
+void sd_loop() {
+   static uint8_t count, sectors_per_cluster, FATs, attribute, result[8], buffer[50];
+   static uint16_t bytes_per_sector, reserved_sectors, offset, file_cluster_low, file_cluster_hi,
+      buffer_length, sector_count;
+   static uint32_t partition, FAT_sectors, fat_sector, root_cluster, root_sector, file_length,
+      file_cluster, file_sector, chars_read;
 
-   // Debug loop to verify we can detect when the card is inserted
-   // Configure DETECT_pin as an input and led_pin as an output
-   DETECT_direction &= ~DETECT_pin;
-   led_direction |= led_pin;
-   while (1) {
-       if (PINA & DETECT_pin) {
-           led_port &= ~led_pin;
-       } else {
-           led_port |= led_pin;
-       }
+   // Wait for card to be inserted
+   while (PINA & DETECT_pin) {
+       led_port |= led_pin;
+       _delay_ms(200);
+       led_port &= ~led_pin;
+       _delay_ms(200);
    }
+   led_port |= led_pin;
 
-   static uint8_t count,sectors_per_cluster,FATs,attribute,result[8],buffer[50];
-   static uint16_t bytes_per_sector,reserved_sectors,offset,
-      file_cluster_low,file_cluster_hi,buffer_length,sector_count;
-   static uint32_t partition,FAT_sectors,fat_sector,root_cluster,
-      root_sector,file_length,file_cluster,file_sector,chars_read;
-   //
-   // set clock divider to /1
-   //
-   CLKPR = (1 << CLKPCE);
-   CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
-   //
-   // initialize output pins
-   //
-   set(serial_port,serial_pin_out);
-   output(serial_direction,serial_pin_out);
-   set(CS_port,CS_pin);
-   output(CS_direction,CS_pin);
-   clear(MOSI_port,MOSI_pin);
-   output(MOSI_direction,MOSI_pin);
-   set(SCK_port,SCK_pin);
-   output(SCK_direction,SCK_pin);
-   set(MISO_port,MISO_pin); //turn on pull-up
-   input(MISO_direction,MISO_pin);
    //
    // put card in SPI mode
    //
@@ -354,20 +327,23 @@ int main(void) {
       clear(SCK_port,SCK_pin);
       SPI_delay();
       }
+
    //
    // CMD0: reset and enter idle state
    //    should return 0x01
    //
    put_flash_string(PSTR("\r\nreset: 0x"));
-   SD_command(0x40,0,0x95,result);
+   SD_command(0x40, 0, 0x95, result);
    put_hex_string(result,8);
+
    //
    // CMD8: send interface condition, set SDHC
    //    should return 0x01000001AA
    //
    put_flash_string(PSTR("\r\nset interface: 0x"));
-   SD_command(0x48,0x000001AA,0x87,result);
+   SD_command(0x48, 0x000001AA, 0x87, result);
    put_hex_string(result,8);
+
    //
    // initialization loop
    //
@@ -378,21 +354,31 @@ int main(void) {
       //    should return 0x01
       //
       put_flash_string(PSTR("\r\n   application command: "));
-      SD_command(0x77,0,0,result);
-      put_hex_string(result,8);
+      SD_command(0x77, 0, 0, result);
+      put_hex_string(result, 8);
+
       //
       // ACMD41: initialize the card
       //    should return 0x00 when ready
       //
       put_flash_string(PSTR("\r\n   initialize card: 0x"));
-      SD_command(0x69,0x40000000,0,result);
+      SD_command(0x69, 0x40000000, 0, result);
       put_hex_string(result,8);
+
       //
       // check if done
       //
-      if (result[1] == 0)
+      if (result[1] == 0) {
+         put_string("\ncard initialized");
          break;
       }
+
+       if (PINA & DETECT_pin) {
+           put_string("\ncard removed");
+           return;
+       }
+   }
+
    //
    // read the first partition table
    //
@@ -403,6 +389,7 @@ int main(void) {
    put_flash_string(PSTR("\r\n   first sector: 0x"));
    put_hex_string(buffer+8,4);
    memcpy(&partition,buffer+8,4);
+
    //
    // read the first partition block
    //
@@ -442,6 +429,7 @@ int main(void) {
    put_hex_char((root_cluster >> 16) & 0xFF);
    put_hex_char((root_cluster >> 8) & 0xFF);
    put_hex_char(root_cluster & 0xFF);
+
    //
    // read the root directory
    //
@@ -498,6 +486,7 @@ int main(void) {
          }
       offset += 32;
       }
+
    //
    // read the file
    //
@@ -520,6 +509,7 @@ int main(void) {
       put_char_string(buffer,buffer_length);
       chars_read += buffer_length;
       offset += buffer_length;
+
       //
       // check sector length
       //
@@ -549,9 +539,48 @@ int main(void) {
             offset = 0;
             }
          }
+
       //
       // sector length not reached, continue
       //
       }
    put_flash_string(PSTR("\r\n\r\nend of file\r\n"));
+   led_port &= ~led_pin;
+}
+
+//
+// main
+//
+int main(void) {
+   //
+   // main
+   //
+
+   //
+   // set clock divider to /1
+   //
+   CLKPR = (1 << CLKPCE);
+   CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
+
+   // Configure DETECT_pin as an input and led_pin as an output
+   DETECT_direction &= ~DETECT_pin;
+   led_direction |= led_pin;
+
+   //
+   // initialize output pins
+   //
+   set(serial_port,serial_pin_out);
+   output(serial_direction,serial_pin_out);
+   set(CS_port,CS_pin);
+   output(CS_direction,CS_pin);
+   clear(MOSI_port,MOSI_pin);
+   output(MOSI_direction,MOSI_pin);
+   set(SCK_port,SCK_pin);
+   output(SCK_direction,SCK_pin);
+   set(MISO_port,MISO_pin); //turn on pull-up
+   input(MISO_direction,MISO_pin);
+
+   while (1) {
+       sd_loop();
+   }
 }
-- 
GitLab