diff --git a/avrtft.c b/avrtft.c index bdc9a1f..18b92ac 100644 --- a/avrtft.c +++ b/avrtft.c @@ -113,6 +113,7 @@ _delay_ms(1000); + // may need to decrease SPI bus clock frequency for initialization sdcard = initSDCard(); initDisplay(); initTouchInt(); diff --git a/sdcard.c b/sdcard.c index 6d06983..5198603 100644 --- a/sdcard.c +++ b/sdcard.c @@ -214,9 +214,66 @@ return success; } +bool readMultiBlock(uint32_t address, consumer consume) { + select(); + + command(CMD18, address, CMD18_CRC); + uint8_t response = readR1(); + bool success = false; + bool cont = false; + uint8_t block[SD_BLOCK_SIZE]; + + if (response == SD_SUCCESS) { + // read command was successful + do { + // wait for start block token + uint8_t token = 0xff; + for (uint16_t attempt = 0; attempt < SD_MAX_READ && token == 0xff; attempt++) { + token = transmit(0xff); + } + + if (token == SD_START_BLOCK) { + // start block token received, 512 data bytes follow + for (uint16_t i = 0; i < SD_BLOCK_SIZE; i++) { + block[i] = transmit(0xff); + } + + // 16-bit CRC (ignore for now) + transmit(0xff); + transmit(0xff); + + cont = consume(block); + } else { + break; + } + } while (cont); + + deselect(); + select(); + + command(CMD12, CMD12_ARG, CMD12_CRC); + // stuff byte on CMD12? + transmit(0xff); + response = readR1(); + + if (response == SD_SUCCESS) { + // wait for not busy + uint8_t busy = 0x00; + for (uint16_t attempt = 0; attempt < SD_MAX_READ && busy == 0x00; attempt++) { + busy = transmit(0xff); + } + success = busy != 0x00; + } + } + + deselect(); + + return success; +} + bool writeSingleBlock(uint32_t address, uint8_t *block) { select(); - + command(CMD24, address, CMD24_CRC); uint8_t response = readR1(); uint8_t token = 0xff; diff --git a/sdcard.h b/sdcard.h index c64d95b..dfb74fb 100644 --- a/sdcard.h +++ b/sdcard.h @@ -13,6 +13,7 @@ #include "pins.h" #include "spi.h" #include "usart.h" +#include "types.h" #define CMD0 0 #define CMD0_ARG 0x00000000 @@ -22,9 +23,16 @@ #define CMD8_ARG 0x0000001aa #define CMD8_CRC 0x86 +#define CMD12 12 +#define CMD12_ARG 0x00000000 +#define CMD12_CRC 0x00 + #define CMD17 17 #define CMD17_CRC 0x00 +#define CMD18 18 +#define CMD18_CRC 0x00 + #define CMD24 24 #define CMD24_CRC 0x00 @@ -57,8 +65,8 @@ bool initSDCard(void); /** - * Reads a single block of 512 bytes starting at the given address - * into the given buffer and returns true on success, false otherwise. + * Reads a single block of 512 bytes at the given address into + * the given buffer and returns true on success, false otherwise. * * @param address address in 512 byte units * @param block 512 byte buffer @@ -67,6 +75,17 @@ bool readSingleBlock(uint32_t address, uint8_t *block); /** + * Reads multiple blocks of 512 bytes starting at the given address + * and, for each block, passes the buffer to the given function. + * By returning false, the function can request to stop reading blocks. + * + * @param address + * @param consume + * @return success + */ +bool readMultiBlock(uint32_t address, consumer consume); + +/** * Writes a single block of 512 bytes starting at the given address * from the given buffer and returns true on success, false otherwise. * diff --git a/types.h b/types.h index 99dfa2d..0a398b0 100644 --- a/types.h +++ b/types.h @@ -8,6 +8,8 @@ #ifndef TYPES_H #define TYPES_H +#include + /* Width, height and color space of bitmaps and glyphs */ typedef uint16_t width_t; typedef uint16_t height_t; @@ -34,5 +36,11 @@ int16_t y; } Point; +/** + * Pointer to a function that takes an array of bytes + * and returns a boolean. + */ +typedef bool (*consumer)(uint8_t*); + #endif /* TYPES_H */