# sdcard3.cpp

This fairly complicated sketch demonstrates streaming disk I/O via a simple packet protocol. It supports initializing an SD card on any face, setting the current block number, and performing buffered reads and writes to sequential addresses on the card.

Here, first I initialized to the east with 'ie', then set the block number to 20000, then wrote some data with 'w' packets, and finally read it back with 'r' packets.

      ie
      Ln 241.416 Card has 7563000 blocks
      b20000
      wNow we can blast data into the disk just about
      w as fast as we can send packets.  Let's
      w do a sync now, to make sure everything's stashed safely..
      s
      b20000
      r
      L:Now we can blast data into the d
      r
      L:isk just about as fast as we can
      r
      L: send packets.  Let's do a sync
      r
      L:now, to make sure everything's s
      r
      L:tashed safely..[00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00]

In that example, I did a 'sync' between the writing and reading, but that wasn't strictly necessary -- the ensuing reads would have worked without it -- but if I'd done, say, another 'ie' instead without syncing, some or all (in this case, all) of my writes would have been lost.

Note also that when I read beyond what I'd written, I got 'null bytes', which this sketch printed as '[00]' because of the handy '#' flag provided in the '%#c' printf format. If your disk has already been used for data storage, you might see any values there instead.

    // SD Card 3: Streaming buffered SD card I/O via packet commands
    #include "SFBSDRaw.h"           // Load the SDRaw library

    SDRaw mySD;                     // Allocate space for a raw sdcard controller
    u8 buffer[512];                 // And a disk-block-sized buffer
    bool initted = false;           // So we can blink different if initted
    u64 lastAddress;                // Remember where we where

    void doInit(u8 * packet) {      // E.g., 'iw' tries to init west
      u8 face;
      if (packetScanf(packet,"i%F\n",&face) != 3) return; // Ignore bad formats
      mySD.begin(face);             // Set up for 'IXM SD Cell' connectivity
      if ((initted = mySD.init())) {     // Try to init, remember if it worked
        mySD.setBlockBuffer(buffer,512); // Success!  Provide a block buffer
        logNormal("Card has %d blocks\n", mySD.getBlockCount());
      }
      lastAddress = 0;              // Reset position
    }
    void doBlock(u8 * packet) {     // Sets lastAddress to some block number
      if (!initted) return;         // Not ready
      u32 block;
      if (packetScanf(packet,"b%d\n",&block) != 3) return; // Ignore bad formats
      lastAddress = ((u64) block)*512;  // Convert to byte address
    }
    void doWrite(u8 * packet) {     // Writes contents of packet starting at lastAddress
      if (!initted) return;         // Not ready
      u32 len = packetLength(packet)-1; // All but the leading 'w'
      if (mySD.write(lastAddress,&packet[1],len)) lastAddress += len;
      else logNormal("Write failed\n");
    }
    void doRead(u8 *) {             // Read 32 bytes starting at lastAddress
      if (!initted) return;         // Not ready
      pprintf("L:");                // Start the response
      for (u32 i = 0; i < 32; ++i) {
        u8 ch;
        if (!mySD.read(lastAddress++,&ch,1)) break; // Read a byte if possible
        pprintf("%#c",ch);          // Send it out, escaping 'non-printable' bytes
      }
      pprintf("\n");                // End the response
    }
    void doSync(u8 *) {
      if (!initted) return;         // Not ready
      mySD.sync();                  // Do it
    }
    void setup() {
      Body.reflex('i',doInit);      // Try to init the card
      Body.reflex('b',doBlock);     // Specify block number to start at
      Body.reflex('r',doRead);      // Read some bytes from the card
      Body.reflex('w',doWrite);     // Write some bytes to the card
      Body.reflex('s',doSync);      // Ensure everything's been written
    }

    void loop() {
      u8 pin = initted?BODY_RGB_GREEN_PIN:BODY_RGB_RED_PIN;
      ledOn(pin);
      delay(1000);
      ledOff(pin);
      delay(1000);
    }