This is a code which generates the various zoomed versions of an image stored in an SD card and displays it on a Nokia LCD based on the keys pressed on a capacitive touch pad.

Dependencies:   FatFileSystem mbed

Fork of Lab3 by Martin Sturm

Committer:
abarve9
Date:
Thu Oct 11 06:10:31 2012 +0000
Revision:
1:6048138606a0
Parent:
0:c546b51ecf0b
This is an image zooming program which reads an image stored in an SD card and displays the various zoomed versions of the image based on the key pressed in the capacitive touch sensor.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
XkLi 0:c546b51ecf0b 1 /* mbed SDFileSystem Library, for providing file access to SD cards
XkLi 0:c546b51ecf0b 2 * Copyright (c) 2008-2010, sford
XkLi 0:c546b51ecf0b 3 *
XkLi 0:c546b51ecf0b 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
XkLi 0:c546b51ecf0b 5 * of this software and associated documentation files (the "Software"), to deal
XkLi 0:c546b51ecf0b 6 * in the Software without restriction, including without limitation the rights
XkLi 0:c546b51ecf0b 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
XkLi 0:c546b51ecf0b 8 * copies of the Software, and to permit persons to whom the Software is
XkLi 0:c546b51ecf0b 9 * furnished to do so, subject to the following conditions:
XkLi 0:c546b51ecf0b 10 *
XkLi 0:c546b51ecf0b 11 * The above copyright notice and this permission notice shall be included in
XkLi 0:c546b51ecf0b 12 * all copies or substantial portions of the Software.
XkLi 0:c546b51ecf0b 13 *
XkLi 0:c546b51ecf0b 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
XkLi 0:c546b51ecf0b 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
XkLi 0:c546b51ecf0b 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
XkLi 0:c546b51ecf0b 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
XkLi 0:c546b51ecf0b 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
XkLi 0:c546b51ecf0b 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
XkLi 0:c546b51ecf0b 20 * THE SOFTWARE.
XkLi 0:c546b51ecf0b 21 */
XkLi 0:c546b51ecf0b 22
XkLi 0:c546b51ecf0b 23 /* Introduction
XkLi 0:c546b51ecf0b 24 * ------------
XkLi 0:c546b51ecf0b 25 * SD and MMC cards support a number of interfaces, but common to them all
XkLi 0:c546b51ecf0b 26 * is one based on SPI. This is the one I'm implmenting because it means
XkLi 0:c546b51ecf0b 27 * it is much more portable even though not so performant, and we already
XkLi 0:c546b51ecf0b 28 * have the mbed SPI Interface!
XkLi 0:c546b51ecf0b 29 *
XkLi 0:c546b51ecf0b 30 * The main reference I'm using is Chapter 7, "SPI Mode" of:
XkLi 0:c546b51ecf0b 31 * http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf
XkLi 0:c546b51ecf0b 32 *
XkLi 0:c546b51ecf0b 33 * SPI Startup
XkLi 0:c546b51ecf0b 34 * -----------
XkLi 0:c546b51ecf0b 35 * The SD card powers up in SD mode. The SPI interface mode is selected by
XkLi 0:c546b51ecf0b 36 * asserting CS low and sending the reset command (CMD0). The card will
XkLi 0:c546b51ecf0b 37 * respond with a (R1) response.
XkLi 0:c546b51ecf0b 38 *
XkLi 0:c546b51ecf0b 39 * CMD8 is optionally sent to determine the voltage range supported, and
XkLi 0:c546b51ecf0b 40 * indirectly determine whether it is a version 1.x SD/non-SD card or
XkLi 0:c546b51ecf0b 41 * version 2.x. I'll just ignore this for now.
XkLi 0:c546b51ecf0b 42 *
XkLi 0:c546b51ecf0b 43 * ACMD41 is repeatedly issued to initialise the card, until "in idle"
XkLi 0:c546b51ecf0b 44 * (bit 0) of the R1 response goes to '0', indicating it is initialised.
XkLi 0:c546b51ecf0b 45 *
XkLi 0:c546b51ecf0b 46 * You should also indicate whether the host supports High Capicity cards,
XkLi 0:c546b51ecf0b 47 * and check whether the card is high capacity - i'll also ignore this
XkLi 0:c546b51ecf0b 48 *
XkLi 0:c546b51ecf0b 49 * SPI Protocol
XkLi 0:c546b51ecf0b 50 * ------------
XkLi 0:c546b51ecf0b 51 * The SD SPI protocol is based on transactions made up of 8-bit words, with
XkLi 0:c546b51ecf0b 52 * the host starting every bus transaction by asserting the CS signal low. The
XkLi 0:c546b51ecf0b 53 * card always responds to commands, data blocks and errors.
XkLi 0:c546b51ecf0b 54 *
XkLi 0:c546b51ecf0b 55 * The protocol supports a CRC, but by default it is off (except for the
XkLi 0:c546b51ecf0b 56 * first reset CMD0, where the CRC can just be pre-calculated, and CMD8)
XkLi 0:c546b51ecf0b 57 * I'll leave the CRC off I think!
XkLi 0:c546b51ecf0b 58 *
XkLi 0:c546b51ecf0b 59 * Standard capacity cards have variable data block sizes, whereas High
XkLi 0:c546b51ecf0b 60 * Capacity cards fix the size of data block to 512 bytes. I'll therefore
XkLi 0:c546b51ecf0b 61 * just always use the Standard Capacity cards with a block size of 512 bytes.
XkLi 0:c546b51ecf0b 62 * This is set with CMD16.
XkLi 0:c546b51ecf0b 63 *
XkLi 0:c546b51ecf0b 64 * You can read and write single blocks (CMD17, CMD25) or multiple blocks
XkLi 0:c546b51ecf0b 65 * (CMD18, CMD25). For simplicity, I'll just use single block accesses. When
XkLi 0:c546b51ecf0b 66 * the card gets a read command, it responds with a response token, and then
XkLi 0:c546b51ecf0b 67 * a data token or an error.
XkLi 0:c546b51ecf0b 68 *
XkLi 0:c546b51ecf0b 69 * SPI Command Format
XkLi 0:c546b51ecf0b 70 * ------------------
XkLi 0:c546b51ecf0b 71 * Commands are 6-bytes long, containing the command, 32-bit argument, and CRC.
XkLi 0:c546b51ecf0b 72 *
XkLi 0:c546b51ecf0b 73 * +---------------+------------+------------+-----------+----------+--------------+
XkLi 0:c546b51ecf0b 74 * | 01 | cmd[5:0] | arg[31:24] | arg[23:16] | arg[15:8] | arg[7:0] | crc[6:0] | 1 |
XkLi 0:c546b51ecf0b 75 * +---------------+------------+------------+-----------+----------+--------------+
XkLi 0:c546b51ecf0b 76 *
XkLi 0:c546b51ecf0b 77 * As I'm not using CRC, I can fix that byte to what is needed for CMD0 (0x95)
XkLi 0:c546b51ecf0b 78 *
XkLi 0:c546b51ecf0b 79 * All Application Specific commands shall be preceded with APP_CMD (CMD55).
XkLi 0:c546b51ecf0b 80 *
XkLi 0:c546b51ecf0b 81 * SPI Response Format
XkLi 0:c546b51ecf0b 82 * -------------------
XkLi 0:c546b51ecf0b 83 * The main response format (R1) is a status byte (normally zero). Key flags:
XkLi 0:c546b51ecf0b 84 * idle - 1 if the card is in an idle state/initialising
XkLi 0:c546b51ecf0b 85 * cmd - 1 if an illegal command code was detected
XkLi 0:c546b51ecf0b 86 *
XkLi 0:c546b51ecf0b 87 * +-------------------------------------------------+
XkLi 0:c546b51ecf0b 88 * R1 | 0 | arg | addr | seq | crc | cmd | erase | idle |
XkLi 0:c546b51ecf0b 89 * +-------------------------------------------------+
XkLi 0:c546b51ecf0b 90 *
XkLi 0:c546b51ecf0b 91 * R1b is the same, except it is followed by a busy signal (zeros) until
XkLi 0:c546b51ecf0b 92 * the first non-zero byte when it is ready again.
XkLi 0:c546b51ecf0b 93 *
XkLi 0:c546b51ecf0b 94 * Data Response Token
XkLi 0:c546b51ecf0b 95 * -------------------
XkLi 0:c546b51ecf0b 96 * Every data block written to the card is acknowledged by a byte
XkLi 0:c546b51ecf0b 97 * response token
XkLi 0:c546b51ecf0b 98 *
XkLi 0:c546b51ecf0b 99 * +----------------------+
XkLi 0:c546b51ecf0b 100 * | xxx | 0 | status | 1 |
XkLi 0:c546b51ecf0b 101 * +----------------------+
XkLi 0:c546b51ecf0b 102 * 010 - OK!
XkLi 0:c546b51ecf0b 103 * 101 - CRC Error
XkLi 0:c546b51ecf0b 104 * 110 - Write Error
XkLi 0:c546b51ecf0b 105 *
XkLi 0:c546b51ecf0b 106 * Single Block Read and Write
XkLi 0:c546b51ecf0b 107 * ---------------------------
XkLi 0:c546b51ecf0b 108 *
XkLi 0:c546b51ecf0b 109 * Block transfers have a byte header, followed by the data, followed
XkLi 0:c546b51ecf0b 110 * by a 16-bit CRC. In our case, the data will always be 512 bytes.
XkLi 0:c546b51ecf0b 111 *
XkLi 0:c546b51ecf0b 112 * +------+---------+---------+- - - -+---------+-----------+----------+
XkLi 0:c546b51ecf0b 113 * | 0xFE | data[0] | data[1] | | data[n] | crc[15:8] | crc[7:0] |
XkLi 0:c546b51ecf0b 114 * +------+---------+---------+- - - -+---------+-----------+----------+
XkLi 0:c546b51ecf0b 115 */
XkLi 0:c546b51ecf0b 116
XkLi 0:c546b51ecf0b 117 #include "SDFileSystem.h"
XkLi 0:c546b51ecf0b 118
XkLi 0:c546b51ecf0b 119 #define SD_COMMAND_TIMEOUT 5000
XkLi 0:c546b51ecf0b 120
XkLi 0:c546b51ecf0b 121 SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name) :
XkLi 0:c546b51ecf0b 122 FATFileSystem(name), _spi(mosi, miso, sclk), _cs(cs) {
XkLi 0:c546b51ecf0b 123 _cs = 1;
XkLi 0:c546b51ecf0b 124 }
XkLi 0:c546b51ecf0b 125
XkLi 0:c546b51ecf0b 126 #define R1_IDLE_STATE (1 << 0)
XkLi 0:c546b51ecf0b 127 #define R1_ERASE_RESET (1 << 1)
XkLi 0:c546b51ecf0b 128 #define R1_ILLEGAL_COMMAND (1 << 2)
XkLi 0:c546b51ecf0b 129 #define R1_COM_CRC_ERROR (1 << 3)
XkLi 0:c546b51ecf0b 130 #define R1_ERASE_SEQUENCE_ERROR (1 << 4)
XkLi 0:c546b51ecf0b 131 #define R1_ADDRESS_ERROR (1 << 5)
XkLi 0:c546b51ecf0b 132 #define R1_PARAMETER_ERROR (1 << 6)
XkLi 0:c546b51ecf0b 133
XkLi 0:c546b51ecf0b 134 // Types
XkLi 0:c546b51ecf0b 135 // - v1.x Standard Capacity
XkLi 0:c546b51ecf0b 136 // - v2.x Standard Capacity
XkLi 0:c546b51ecf0b 137 // - v2.x High Capacity
XkLi 0:c546b51ecf0b 138 // - Not recognised as an SD Card
XkLi 0:c546b51ecf0b 139
XkLi 0:c546b51ecf0b 140 #define SDCARD_FAIL 0
XkLi 0:c546b51ecf0b 141 #define SDCARD_V1 1
XkLi 0:c546b51ecf0b 142 #define SDCARD_V2 2
XkLi 0:c546b51ecf0b 143 #define SDCARD_V2HC 3
XkLi 0:c546b51ecf0b 144
XkLi 0:c546b51ecf0b 145 int SDFileSystem::initialise_card() {
XkLi 0:c546b51ecf0b 146 // Set to 100kHz for initialisation, and clock card with cs = 1
XkLi 0:c546b51ecf0b 147 _spi.frequency(100000);
XkLi 0:c546b51ecf0b 148 _cs = 1;
XkLi 0:c546b51ecf0b 149 for(int i=0; i<16; i++) {
XkLi 0:c546b51ecf0b 150 _spi.write(0xFF);
XkLi 0:c546b51ecf0b 151 }
XkLi 0:c546b51ecf0b 152
XkLi 0:c546b51ecf0b 153 // send CMD0, should return with all zeros except IDLE STATE set (bit 0)
XkLi 0:c546b51ecf0b 154 if(_cmd(0, 0) != R1_IDLE_STATE) {
XkLi 0:c546b51ecf0b 155 fprintf(stderr, "No disk, or could not put SD card in to SPI idle state\n");
XkLi 0:c546b51ecf0b 156 return SDCARD_FAIL;
XkLi 0:c546b51ecf0b 157 }
XkLi 0:c546b51ecf0b 158
XkLi 0:c546b51ecf0b 159 // send CMD8 to determine whther it is ver 2.x
XkLi 0:c546b51ecf0b 160 int r = _cmd8();
XkLi 0:c546b51ecf0b 161 if(r == R1_IDLE_STATE) {
XkLi 0:c546b51ecf0b 162 return initialise_card_v2();
XkLi 0:c546b51ecf0b 163 } else if(r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) {
XkLi 0:c546b51ecf0b 164 return initialise_card_v1();
XkLi 0:c546b51ecf0b 165 } else {
XkLi 0:c546b51ecf0b 166 fprintf(stderr, "Not in idle state after sending CMD8 (not an SD card?)\n");
XkLi 0:c546b51ecf0b 167 return SDCARD_FAIL;
XkLi 0:c546b51ecf0b 168 }
XkLi 0:c546b51ecf0b 169 }
XkLi 0:c546b51ecf0b 170
XkLi 0:c546b51ecf0b 171 int SDFileSystem::initialise_card_v1() {
XkLi 0:c546b51ecf0b 172 for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
XkLi 0:c546b51ecf0b 173 _cmd(55, 0);
XkLi 0:c546b51ecf0b 174 if(_cmd(41, 0) == 0) {
XkLi 0:c546b51ecf0b 175 return SDCARD_V1;
XkLi 0:c546b51ecf0b 176 }
XkLi 0:c546b51ecf0b 177 }
XkLi 0:c546b51ecf0b 178
XkLi 0:c546b51ecf0b 179 fprintf(stderr, "Timeout waiting for v1.x card\n");
XkLi 0:c546b51ecf0b 180 return SDCARD_FAIL;
XkLi 0:c546b51ecf0b 181 }
XkLi 0:c546b51ecf0b 182
XkLi 0:c546b51ecf0b 183 int SDFileSystem::initialise_card_v2() {
XkLi 0:c546b51ecf0b 184
XkLi 0:c546b51ecf0b 185 for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
XkLi 0:c546b51ecf0b 186 _cmd(55, 0);
XkLi 0:c546b51ecf0b 187 if(_cmd(41, 0) == 0) {
XkLi 0:c546b51ecf0b 188 _cmd58();
XkLi 0:c546b51ecf0b 189 return SDCARD_V2;
XkLi 0:c546b51ecf0b 190 }
XkLi 0:c546b51ecf0b 191 }
XkLi 0:c546b51ecf0b 192
XkLi 0:c546b51ecf0b 193 fprintf(stderr, "Timeout waiting for v2.x card\n");
XkLi 0:c546b51ecf0b 194 return SDCARD_FAIL;
XkLi 0:c546b51ecf0b 195 }
XkLi 0:c546b51ecf0b 196
XkLi 0:c546b51ecf0b 197 int SDFileSystem::disk_initialize() {
XkLi 0:c546b51ecf0b 198
XkLi 0:c546b51ecf0b 199 int i = initialise_card();
XkLi 0:c546b51ecf0b 200 // printf("init card = %d\n", i);
XkLi 0:c546b51ecf0b 201 // printf("OK\n");
XkLi 0:c546b51ecf0b 202
XkLi 0:c546b51ecf0b 203 _sectors = _sd_sectors();
XkLi 0:c546b51ecf0b 204
XkLi 0:c546b51ecf0b 205 // Set block length to 512 (CMD16)
XkLi 0:c546b51ecf0b 206 if(_cmd(16, 512) != 0) {
XkLi 0:c546b51ecf0b 207 fprintf(stderr, "Set 512-byte block timed out\n");
XkLi 0:c546b51ecf0b 208 return 1;
XkLi 0:c546b51ecf0b 209 }
XkLi 0:c546b51ecf0b 210
XkLi 0:c546b51ecf0b 211 _spi.frequency(1000000); // Set to 1MHz for data transfer
XkLi 0:c546b51ecf0b 212 return 0;
XkLi 0:c546b51ecf0b 213 }
XkLi 0:c546b51ecf0b 214
XkLi 0:c546b51ecf0b 215 int SDFileSystem::disk_write(const char *buffer, int block_number) {
XkLi 0:c546b51ecf0b 216 // set write address for single block (CMD24)
XkLi 0:c546b51ecf0b 217 if(_cmd(24, block_number * 512) != 0) {
XkLi 0:c546b51ecf0b 218 return 1;
XkLi 0:c546b51ecf0b 219 }
XkLi 0:c546b51ecf0b 220
XkLi 0:c546b51ecf0b 221 // send the data block
XkLi 0:c546b51ecf0b 222 _write(buffer, 512);
XkLi 0:c546b51ecf0b 223 return 0;
XkLi 0:c546b51ecf0b 224 }
XkLi 0:c546b51ecf0b 225
XkLi 0:c546b51ecf0b 226 int SDFileSystem::disk_read(char *buffer, int block_number) {
XkLi 0:c546b51ecf0b 227 // set read address for single block (CMD17)
XkLi 0:c546b51ecf0b 228 if(_cmd(17, block_number * 512) != 0) {
XkLi 0:c546b51ecf0b 229 return 1;
XkLi 0:c546b51ecf0b 230 }
XkLi 0:c546b51ecf0b 231
XkLi 0:c546b51ecf0b 232 // receive the data
XkLi 0:c546b51ecf0b 233 _read(buffer, 512);
XkLi 0:c546b51ecf0b 234 return 0;
XkLi 0:c546b51ecf0b 235 }
XkLi 0:c546b51ecf0b 236
XkLi 0:c546b51ecf0b 237 int SDFileSystem::disk_status() { return 0; }
XkLi 0:c546b51ecf0b 238 int SDFileSystem::disk_sync() { return 0; }
XkLi 0:c546b51ecf0b 239 int SDFileSystem::disk_sectors() { return _sectors; }
XkLi 0:c546b51ecf0b 240
XkLi 0:c546b51ecf0b 241 // PRIVATE FUNCTIONS
XkLi 0:c546b51ecf0b 242
XkLi 0:c546b51ecf0b 243 int SDFileSystem::_cmd(int cmd, int arg) {
XkLi 0:c546b51ecf0b 244 _cs = 0;
XkLi 0:c546b51ecf0b 245
XkLi 0:c546b51ecf0b 246 // send a command
XkLi 0:c546b51ecf0b 247 _spi.write(0x40 | cmd);
XkLi 0:c546b51ecf0b 248 _spi.write(arg >> 24);
XkLi 0:c546b51ecf0b 249 _spi.write(arg >> 16);
XkLi 0:c546b51ecf0b 250 _spi.write(arg >> 8);
XkLi 0:c546b51ecf0b 251 _spi.write(arg >> 0);
XkLi 0:c546b51ecf0b 252 _spi.write(0x95);
XkLi 0:c546b51ecf0b 253
XkLi 0:c546b51ecf0b 254 // wait for the repsonse (response[7] == 0)
XkLi 0:c546b51ecf0b 255 for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
XkLi 0:c546b51ecf0b 256 int response = _spi.write(0xFF);
XkLi 0:c546b51ecf0b 257 if(!(response & 0x80)) {
XkLi 0:c546b51ecf0b 258 _cs = 1;
XkLi 0:c546b51ecf0b 259 _spi.write(0xFF);
XkLi 0:c546b51ecf0b 260 return response;
XkLi 0:c546b51ecf0b 261 }
XkLi 0:c546b51ecf0b 262 }
XkLi 0:c546b51ecf0b 263 _cs = 1;
XkLi 0:c546b51ecf0b 264 _spi.write(0xFF);
XkLi 0:c546b51ecf0b 265 return -1; // timeout
XkLi 0:c546b51ecf0b 266 }
XkLi 0:c546b51ecf0b 267 int SDFileSystem::_cmdx(int cmd, int arg) {
XkLi 0:c546b51ecf0b 268 _cs = 0;
XkLi 0:c546b51ecf0b 269
XkLi 0:c546b51ecf0b 270 // send a command
XkLi 0:c546b51ecf0b 271 _spi.write(0x40 | cmd);
XkLi 0:c546b51ecf0b 272 _spi.write(arg >> 24);
XkLi 0:c546b51ecf0b 273 _spi.write(arg >> 16);
XkLi 0:c546b51ecf0b 274 _spi.write(arg >> 8);
XkLi 0:c546b51ecf0b 275 _spi.write(arg >> 0);
XkLi 0:c546b51ecf0b 276 _spi.write(0x95);
XkLi 0:c546b51ecf0b 277
XkLi 0:c546b51ecf0b 278 // wait for the repsonse (response[7] == 0)
XkLi 0:c546b51ecf0b 279 for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
XkLi 0:c546b51ecf0b 280 int response = _spi.write(0xFF);
XkLi 0:c546b51ecf0b 281 if(!(response & 0x80)) {
XkLi 0:c546b51ecf0b 282 return response;
XkLi 0:c546b51ecf0b 283 }
XkLi 0:c546b51ecf0b 284 }
XkLi 0:c546b51ecf0b 285 _cs = 1;
XkLi 0:c546b51ecf0b 286 _spi.write(0xFF);
XkLi 0:c546b51ecf0b 287 return -1; // timeout
XkLi 0:c546b51ecf0b 288 }
XkLi 0:c546b51ecf0b 289
XkLi 0:c546b51ecf0b 290
XkLi 0:c546b51ecf0b 291 int SDFileSystem::_cmd58() {
XkLi 0:c546b51ecf0b 292 _cs = 0;
XkLi 0:c546b51ecf0b 293 int arg = 0;
XkLi 0:c546b51ecf0b 294
XkLi 0:c546b51ecf0b 295 // send a command
XkLi 0:c546b51ecf0b 296 _spi.write(0x40 | 58);
XkLi 0:c546b51ecf0b 297 _spi.write(arg >> 24);
XkLi 0:c546b51ecf0b 298 _spi.write(arg >> 16);
XkLi 0:c546b51ecf0b 299 _spi.write(arg >> 8);
XkLi 0:c546b51ecf0b 300 _spi.write(arg >> 0);
XkLi 0:c546b51ecf0b 301 _spi.write(0x95);
XkLi 0:c546b51ecf0b 302
XkLi 0:c546b51ecf0b 303 // wait for the repsonse (response[7] == 0)
XkLi 0:c546b51ecf0b 304 for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
XkLi 0:c546b51ecf0b 305 int response = _spi.write(0xFF);
XkLi 0:c546b51ecf0b 306 if(!(response & 0x80)) {
XkLi 0:c546b51ecf0b 307 int ocr = _spi.write(0xFF) << 24;
XkLi 0:c546b51ecf0b 308 ocr |= _spi.write(0xFF) << 16;
XkLi 0:c546b51ecf0b 309 ocr |= _spi.write(0xFF) << 8;
XkLi 0:c546b51ecf0b 310 ocr |= _spi.write(0xFF) << 0;
XkLi 0:c546b51ecf0b 311 // printf("OCR = 0x%08X\n", ocr);
XkLi 0:c546b51ecf0b 312 _cs = 1;
XkLi 0:c546b51ecf0b 313 _spi.write(0xFF);
XkLi 0:c546b51ecf0b 314 return response;
XkLi 0:c546b51ecf0b 315 }
XkLi 0:c546b51ecf0b 316 }
XkLi 0:c546b51ecf0b 317 _cs = 1;
XkLi 0:c546b51ecf0b 318 _spi.write(0xFF);
XkLi 0:c546b51ecf0b 319 return -1; // timeout
XkLi 0:c546b51ecf0b 320 }
XkLi 0:c546b51ecf0b 321
XkLi 0:c546b51ecf0b 322 int SDFileSystem::_cmd8() {
XkLi 0:c546b51ecf0b 323 _cs = 0;
XkLi 0:c546b51ecf0b 324
XkLi 0:c546b51ecf0b 325 // send a command
XkLi 0:c546b51ecf0b 326 _spi.write(0x40 | 8); // CMD8
XkLi 0:c546b51ecf0b 327 _spi.write(0x00); // reserved
XkLi 0:c546b51ecf0b 328 _spi.write(0x00); // reserved
XkLi 0:c546b51ecf0b 329 _spi.write(0x01); // 3.3v
XkLi 0:c546b51ecf0b 330 _spi.write(0xAA); // check pattern
XkLi 0:c546b51ecf0b 331 _spi.write(0x87); // crc
XkLi 0:c546b51ecf0b 332
XkLi 0:c546b51ecf0b 333 // wait for the repsonse (response[7] == 0)
XkLi 0:c546b51ecf0b 334 for(int i=0; i<SD_COMMAND_TIMEOUT * 1000; i++) {
XkLi 0:c546b51ecf0b 335 char response[5];
XkLi 0:c546b51ecf0b 336 response[0] = _spi.write(0xFF);
XkLi 0:c546b51ecf0b 337 if(!(response[0] & 0x80)) {
XkLi 0:c546b51ecf0b 338 for(int j=1; j<5; j++) {
XkLi 0:c546b51ecf0b 339 response[i] = _spi.write(0xFF);
XkLi 0:c546b51ecf0b 340 }
XkLi 0:c546b51ecf0b 341 _cs = 1;
XkLi 0:c546b51ecf0b 342 _spi.write(0xFF);
XkLi 0:c546b51ecf0b 343 return response[0];
XkLi 0:c546b51ecf0b 344 }
XkLi 0:c546b51ecf0b 345 }
XkLi 0:c546b51ecf0b 346 _cs = 1;
XkLi 0:c546b51ecf0b 347 _spi.write(0xFF);
XkLi 0:c546b51ecf0b 348 return -1; // timeout
XkLi 0:c546b51ecf0b 349 }
XkLi 0:c546b51ecf0b 350
XkLi 0:c546b51ecf0b 351 int SDFileSystem::_read(char *buffer, int length) {
XkLi 0:c546b51ecf0b 352 _cs = 0;
XkLi 0:c546b51ecf0b 353
XkLi 0:c546b51ecf0b 354 // read until start byte (0xFF)
XkLi 0:c546b51ecf0b 355 while(_spi.write(0xFF) != 0xFE);
XkLi 0:c546b51ecf0b 356
XkLi 0:c546b51ecf0b 357 // read data
XkLi 0:c546b51ecf0b 358 for(int i=0; i<length; i++) {
XkLi 0:c546b51ecf0b 359 buffer[i] = _spi.write(0xFF);
XkLi 0:c546b51ecf0b 360 }
XkLi 0:c546b51ecf0b 361 _spi.write(0xFF); // checksum
XkLi 0:c546b51ecf0b 362 _spi.write(0xFF);
XkLi 0:c546b51ecf0b 363
XkLi 0:c546b51ecf0b 364 _cs = 1;
XkLi 0:c546b51ecf0b 365 _spi.write(0xFF);
XkLi 0:c546b51ecf0b 366 return 0;
XkLi 0:c546b51ecf0b 367 }
XkLi 0:c546b51ecf0b 368
XkLi 0:c546b51ecf0b 369 int SDFileSystem::_write(const char *buffer, int length) {
XkLi 0:c546b51ecf0b 370 _cs = 0;
XkLi 0:c546b51ecf0b 371
XkLi 0:c546b51ecf0b 372 // indicate start of block
XkLi 0:c546b51ecf0b 373 _spi.write(0xFE);
XkLi 0:c546b51ecf0b 374
XkLi 0:c546b51ecf0b 375 // write the data
XkLi 0:c546b51ecf0b 376 for(int i=0; i<length; i++) {
XkLi 0:c546b51ecf0b 377 _spi.write(buffer[i]);
XkLi 0:c546b51ecf0b 378 }
XkLi 0:c546b51ecf0b 379
XkLi 0:c546b51ecf0b 380 // write the checksum
XkLi 0:c546b51ecf0b 381 _spi.write(0xFF);
XkLi 0:c546b51ecf0b 382 _spi.write(0xFF);
XkLi 0:c546b51ecf0b 383
XkLi 0:c546b51ecf0b 384 // check the repsonse token
XkLi 0:c546b51ecf0b 385 if((_spi.write(0xFF) & 0x1F) != 0x05) {
XkLi 0:c546b51ecf0b 386 _cs = 1;
XkLi 0:c546b51ecf0b 387 _spi.write(0xFF);
XkLi 0:c546b51ecf0b 388 return 1;
XkLi 0:c546b51ecf0b 389 }
XkLi 0:c546b51ecf0b 390
XkLi 0:c546b51ecf0b 391 // wait for write to finish
XkLi 0:c546b51ecf0b 392 while(_spi.write(0xFF) == 0);
XkLi 0:c546b51ecf0b 393
XkLi 0:c546b51ecf0b 394 _cs = 1;
XkLi 0:c546b51ecf0b 395 _spi.write(0xFF);
XkLi 0:c546b51ecf0b 396 return 0;
XkLi 0:c546b51ecf0b 397 }
XkLi 0:c546b51ecf0b 398
XkLi 0:c546b51ecf0b 399 static int ext_bits(char *data, int msb, int lsb) {
XkLi 0:c546b51ecf0b 400 int bits = 0;
XkLi 0:c546b51ecf0b 401 int size = 1 + msb - lsb;
XkLi 0:c546b51ecf0b 402 for(int i=0; i<size; i++) {
XkLi 0:c546b51ecf0b 403 int position = lsb + i;
XkLi 0:c546b51ecf0b 404 int byte = 15 - (position >> 3);
XkLi 0:c546b51ecf0b 405 int bit = position & 0x7;
XkLi 0:c546b51ecf0b 406 int value = (data[byte] >> bit) & 1;
XkLi 0:c546b51ecf0b 407 bits |= value << i;
XkLi 0:c546b51ecf0b 408 }
XkLi 0:c546b51ecf0b 409 return bits;
XkLi 0:c546b51ecf0b 410 }
XkLi 0:c546b51ecf0b 411
XkLi 0:c546b51ecf0b 412 int SDFileSystem::_sd_sectors() {
XkLi 0:c546b51ecf0b 413
XkLi 0:c546b51ecf0b 414 // CMD9, Response R2 (R1 byte + 16-byte block read)
XkLi 0:c546b51ecf0b 415 if(_cmdx(9, 0) != 0) {
XkLi 0:c546b51ecf0b 416 fprintf(stderr, "Didn't get a response from the disk\n");
XkLi 0:c546b51ecf0b 417 return 0;
XkLi 0:c546b51ecf0b 418 }
XkLi 0:c546b51ecf0b 419
XkLi 0:c546b51ecf0b 420 char csd[16];
XkLi 0:c546b51ecf0b 421 if(_read(csd, 16) != 0) {
XkLi 0:c546b51ecf0b 422 fprintf(stderr, "Couldn't read csd response from disk\n");
XkLi 0:c546b51ecf0b 423 return 0;
XkLi 0:c546b51ecf0b 424 }
XkLi 0:c546b51ecf0b 425
XkLi 0:c546b51ecf0b 426 // csd_structure : csd[127:126]
XkLi 0:c546b51ecf0b 427 // c_size : csd[73:62]
XkLi 0:c546b51ecf0b 428 // c_size_mult : csd[49:47]
XkLi 0:c546b51ecf0b 429 // read_bl_len : csd[83:80] - the *maximum* read block length
XkLi 0:c546b51ecf0b 430
XkLi 0:c546b51ecf0b 431 int csd_structure = ext_bits(csd, 127, 126);
XkLi 0:c546b51ecf0b 432 int c_size = ext_bits(csd, 73, 62);
XkLi 0:c546b51ecf0b 433 int c_size_mult = ext_bits(csd, 49, 47);
XkLi 0:c546b51ecf0b 434 int read_bl_len = ext_bits(csd, 83, 80);
XkLi 0:c546b51ecf0b 435
XkLi 0:c546b51ecf0b 436 // printf("CSD_STRUCT = %d\n", csd_structure);
XkLi 0:c546b51ecf0b 437
XkLi 0:c546b51ecf0b 438 if(csd_structure != 0) {
XkLi 0:c546b51ecf0b 439 fprintf(stderr, "This disk tastes funny! I only know about type 0 CSD structures\n");
XkLi 0:c546b51ecf0b 440 return 0;
XkLi 0:c546b51ecf0b 441 }
XkLi 0:c546b51ecf0b 442
XkLi 0:c546b51ecf0b 443 // memory capacity = BLOCKNR * BLOCK_LEN
XkLi 0:c546b51ecf0b 444 // where
XkLi 0:c546b51ecf0b 445 // BLOCKNR = (C_SIZE+1) * MULT
XkLi 0:c546b51ecf0b 446 // MULT = 2^(C_SIZE_MULT+2) (C_SIZE_MULT < 8)
XkLi 0:c546b51ecf0b 447 // BLOCK_LEN = 2^READ_BL_LEN, (READ_BL_LEN < 12)
XkLi 0:c546b51ecf0b 448
XkLi 0:c546b51ecf0b 449 int block_len = 1 << read_bl_len;
XkLi 0:c546b51ecf0b 450 int mult = 1 << (c_size_mult + 2);
XkLi 0:c546b51ecf0b 451 int blocknr = (c_size + 1) * mult;
XkLi 0:c546b51ecf0b 452 int capacity = blocknr * block_len;
XkLi 0:c546b51ecf0b 453
XkLi 0:c546b51ecf0b 454 int blocks = capacity / 512;
XkLi 0:c546b51ecf0b 455
XkLi 0:c546b51ecf0b 456 return blocks;
XkLi 0:c546b51ecf0b 457 }