Joe Body 201215898

Dependencies:   mbed

Navigation

  • From the Main Menu the A button will take you into one of the play, highscore or instructions options.
  • The B button will return you to the Main Menu from either the highscore or instruction screens, though this is prompted on screen.
  • When in the Main Menu Pot1 can be used to adjust the contrast and the volume control by the speaker is active.
  • When the game is over the B button can be used to return to the Main Menu, again this is prompted.
  • To return to the Main Menu while the game is being played the reset button must be pressed, this will not save your score or anything about the game.

In Game

  • While in the game the A button is used to shoot while you aim with the Joystick.
  • You have control over the cross while the objective of the game is to rack up as many points shooting the moving head.
  • There is a slight reload time on each shot so you are unable to spam A if you miss.
  • Once you miss 6 times the game will end and your score will be saved.
  • When hit by a falling spike the game will transition and the head will vanish.
  • 4 new spikes will spawn which you need to avoid, being hit by 1 of these will decrease your remaining miss chances by 5.
  • When the game is in this state you must avoid these spikes by tilting the device, the Joystick will have no effect.
  • The head will move progressively faster as the game goes on, make use of the clock power up by shooting it when it appears, this will slow the head down to a more manageable level hopefully helping you to reach a higher score.

Highscore

  • If you have a SD card inserted into the device the game can save your highest score.
  • A decent score is somewhere around 25.
Committer:
el18jgb
Date:
Sun May 24 11:24:57 2020 +0000
Revision:
23:0e8155320571
Parent:
18:c600a6545e81
Final Submission. I have read and agreed with Statement of Academic Integrity.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
el18jgb 18:c600a6545e81 1 /* SD/MMC File System Library
el18jgb 18:c600a6545e81 2 * Copyright (c) 2016 Neil Thiessen
el18jgb 18:c600a6545e81 3 *
el18jgb 18:c600a6545e81 4 * Licensed under the Apache License, Version 2.0 (the "License");
el18jgb 18:c600a6545e81 5 * you may not use this file except in compliance with the License.
el18jgb 18:c600a6545e81 6 * You may obtain a copy of the License at
el18jgb 18:c600a6545e81 7 *
el18jgb 18:c600a6545e81 8 * http://www.apache.org/licenses/LICENSE-2.0
el18jgb 18:c600a6545e81 9 *
el18jgb 18:c600a6545e81 10 * Unless required by applicable law or agreed to in writing, software
el18jgb 18:c600a6545e81 11 * distributed under the License is distributed on an "AS IS" BASIS,
el18jgb 18:c600a6545e81 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
el18jgb 18:c600a6545e81 13 * See the License for the specific language governing permissions and
el18jgb 18:c600a6545e81 14 * limitations under the License.
el18jgb 18:c600a6545e81 15 */
el18jgb 18:c600a6545e81 16
el18jgb 18:c600a6545e81 17 #include "SDFileSystem.h"
el18jgb 18:c600a6545e81 18 #include "diskio.h"
el18jgb 18:c600a6545e81 19 #include "pinmap.h"
el18jgb 18:c600a6545e81 20 #include "SDCRC.h"
el18jgb 18:c600a6545e81 21
el18jgb 18:c600a6545e81 22 SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name, PinName cd, SwitchType cdtype, int hz)
el18jgb 18:c600a6545e81 23 : FATFileSystem(name),
el18jgb 18:c600a6545e81 24 m_Spi(mosi, miso, sclk),
el18jgb 18:c600a6545e81 25 m_Cs(cs, 1),
el18jgb 18:c600a6545e81 26 m_Cd(cd),
el18jgb 18:c600a6545e81 27 m_FREQ(hz)
el18jgb 18:c600a6545e81 28 {
el18jgb 18:c600a6545e81 29 //Initialize the member variables
el18jgb 18:c600a6545e81 30 m_CardType = CARD_NONE;
el18jgb 18:c600a6545e81 31 m_Crc = true;
el18jgb 18:c600a6545e81 32 m_LargeFrames = false;
el18jgb 18:c600a6545e81 33 m_WriteValidation = true;
el18jgb 18:c600a6545e81 34 m_Status = STA_NOINIT;
el18jgb 18:c600a6545e81 35
el18jgb 18:c600a6545e81 36 //Enable the internal pull-up resistor on MISO
el18jgb 18:c600a6545e81 37 pin_mode(miso, PullUp);
el18jgb 18:c600a6545e81 38
el18jgb 18:c600a6545e81 39 //Configure the SPI bus
el18jgb 18:c600a6545e81 40 m_Spi.format(8, 0);
el18jgb 18:c600a6545e81 41
el18jgb 18:c600a6545e81 42 //Configure the card detect pin
el18jgb 18:c600a6545e81 43 if (cdtype == SWITCH_POS_NO) {
el18jgb 18:c600a6545e81 44 m_Cd.mode(PullDown);
el18jgb 18:c600a6545e81 45 m_CdAssert = 1;
el18jgb 18:c600a6545e81 46 m_Cd.fall(this, &SDFileSystem::onCardRemoval);
el18jgb 18:c600a6545e81 47 } else if (cdtype == SWITCH_POS_NC) {
el18jgb 18:c600a6545e81 48 m_Cd.mode(PullDown);
el18jgb 18:c600a6545e81 49 m_CdAssert = 0;
el18jgb 18:c600a6545e81 50 m_Cd.rise(this, &SDFileSystem::onCardRemoval);
el18jgb 18:c600a6545e81 51 } else if (cdtype == SWITCH_NEG_NO) {
el18jgb 18:c600a6545e81 52 m_Cd.mode(PullUp);
el18jgb 18:c600a6545e81 53 m_CdAssert = 0;
el18jgb 18:c600a6545e81 54 m_Cd.rise(this, &SDFileSystem::onCardRemoval);
el18jgb 18:c600a6545e81 55 } else if (cdtype == SWITCH_NEG_NC) {
el18jgb 18:c600a6545e81 56 m_Cd.mode(PullUp);
el18jgb 18:c600a6545e81 57 m_CdAssert = 1;
el18jgb 18:c600a6545e81 58 m_Cd.fall(this, &SDFileSystem::onCardRemoval);
el18jgb 18:c600a6545e81 59 } else {
el18jgb 18:c600a6545e81 60 m_CdAssert = -1;
el18jgb 18:c600a6545e81 61 }
el18jgb 18:c600a6545e81 62 }
el18jgb 18:c600a6545e81 63
el18jgb 18:c600a6545e81 64 bool SDFileSystem::card_present()
el18jgb 18:c600a6545e81 65 {
el18jgb 18:c600a6545e81 66 //Check the card socket
el18jgb 18:c600a6545e81 67 checkSocket();
el18jgb 18:c600a6545e81 68
el18jgb 18:c600a6545e81 69 //Return whether or not a card is present
el18jgb 18:c600a6545e81 70 return !(m_Status & STA_NODISK);
el18jgb 18:c600a6545e81 71 }
el18jgb 18:c600a6545e81 72
el18jgb 18:c600a6545e81 73 SDFileSystem::CardType SDFileSystem::card_type()
el18jgb 18:c600a6545e81 74 {
el18jgb 18:c600a6545e81 75 //Check the card socket
el18jgb 18:c600a6545e81 76 checkSocket();
el18jgb 18:c600a6545e81 77
el18jgb 18:c600a6545e81 78 //Return the card type
el18jgb 18:c600a6545e81 79 return m_CardType;
el18jgb 18:c600a6545e81 80 }
el18jgb 18:c600a6545e81 81
el18jgb 18:c600a6545e81 82 bool SDFileSystem::crc()
el18jgb 18:c600a6545e81 83 {
el18jgb 18:c600a6545e81 84 //Return whether or not CRC is enabled
el18jgb 18:c600a6545e81 85 return m_Crc;
el18jgb 18:c600a6545e81 86 }
el18jgb 18:c600a6545e81 87
el18jgb 18:c600a6545e81 88 void SDFileSystem::crc(bool enabled)
el18jgb 18:c600a6545e81 89 {
el18jgb 18:c600a6545e81 90 //Check the card socket
el18jgb 18:c600a6545e81 91 checkSocket();
el18jgb 18:c600a6545e81 92
el18jgb 18:c600a6545e81 93 //Just update the member variable if the card isn't initialized
el18jgb 18:c600a6545e81 94 if (m_Status & STA_NOINIT) {
el18jgb 18:c600a6545e81 95 m_Crc = enabled;
el18jgb 18:c600a6545e81 96 return;
el18jgb 18:c600a6545e81 97 }
el18jgb 18:c600a6545e81 98
el18jgb 18:c600a6545e81 99 //Enable or disable CRC
el18jgb 18:c600a6545e81 100 if (enabled && !m_Crc) {
el18jgb 18:c600a6545e81 101 //Send CMD59(0x00000001) to enable CRC
el18jgb 18:c600a6545e81 102 m_Crc = true;
el18jgb 18:c600a6545e81 103 commandTransaction(CMD59, 0x00000001);
el18jgb 18:c600a6545e81 104 } else if (!enabled && m_Crc) {
el18jgb 18:c600a6545e81 105 //Send CMD59(0x00000000) to disable CRC
el18jgb 18:c600a6545e81 106 commandTransaction(CMD59, 0x00000000);
el18jgb 18:c600a6545e81 107 m_Crc = false;
el18jgb 18:c600a6545e81 108 }
el18jgb 18:c600a6545e81 109 }
el18jgb 18:c600a6545e81 110
el18jgb 18:c600a6545e81 111 bool SDFileSystem::large_frames()
el18jgb 18:c600a6545e81 112 {
el18jgb 18:c600a6545e81 113 //Return whether or not 16-bit frames are enabled
el18jgb 18:c600a6545e81 114 return m_LargeFrames;
el18jgb 18:c600a6545e81 115 }
el18jgb 18:c600a6545e81 116
el18jgb 18:c600a6545e81 117 void SDFileSystem::large_frames(bool enabled)
el18jgb 18:c600a6545e81 118 {
el18jgb 18:c600a6545e81 119 //Set whether or not 16-bit frames are enabled
el18jgb 18:c600a6545e81 120 m_LargeFrames = enabled;
el18jgb 18:c600a6545e81 121 }
el18jgb 18:c600a6545e81 122
el18jgb 18:c600a6545e81 123 bool SDFileSystem::write_validation()
el18jgb 18:c600a6545e81 124 {
el18jgb 18:c600a6545e81 125 //Return whether or not write validation is enabled
el18jgb 18:c600a6545e81 126 return m_WriteValidation;
el18jgb 18:c600a6545e81 127 }
el18jgb 18:c600a6545e81 128
el18jgb 18:c600a6545e81 129 void SDFileSystem::write_validation(bool enabled)
el18jgb 18:c600a6545e81 130 {
el18jgb 18:c600a6545e81 131 //Set whether or not write validation is enabled
el18jgb 18:c600a6545e81 132 m_WriteValidation = enabled;
el18jgb 18:c600a6545e81 133 }
el18jgb 18:c600a6545e81 134
el18jgb 18:c600a6545e81 135 int SDFileSystem::unmount()
el18jgb 18:c600a6545e81 136 {
el18jgb 18:c600a6545e81 137 //Unmount the filesystem
el18jgb 18:c600a6545e81 138 FATFileSystem::unmount();
el18jgb 18:c600a6545e81 139
el18jgb 18:c600a6545e81 140 //Change the status to not initialized, and the card type to unknown
el18jgb 18:c600a6545e81 141 m_Status |= STA_NOINIT;
el18jgb 18:c600a6545e81 142 m_CardType = CARD_UNKNOWN;
el18jgb 18:c600a6545e81 143
el18jgb 18:c600a6545e81 144 //Always succeeds
el18jgb 18:c600a6545e81 145 return 0;
el18jgb 18:c600a6545e81 146 }
el18jgb 18:c600a6545e81 147
el18jgb 18:c600a6545e81 148 int SDFileSystem::disk_initialize()
el18jgb 18:c600a6545e81 149 {
el18jgb 18:c600a6545e81 150 char token;
el18jgb 18:c600a6545e81 151 unsigned int resp;
el18jgb 18:c600a6545e81 152 Timer timer;
el18jgb 18:c600a6545e81 153
el18jgb 18:c600a6545e81 154 //Make sure there's a card in the socket before proceeding
el18jgb 18:c600a6545e81 155 checkSocket();
el18jgb 18:c600a6545e81 156 if (m_Status & STA_NODISK)
el18jgb 18:c600a6545e81 157 return m_Status;
el18jgb 18:c600a6545e81 158
el18jgb 18:c600a6545e81 159 //Make sure we're not already initialized before proceeding
el18jgb 18:c600a6545e81 160 if (!(m_Status & STA_NOINIT))
el18jgb 18:c600a6545e81 161 return m_Status;
el18jgb 18:c600a6545e81 162
el18jgb 18:c600a6545e81 163 //Set the SPI frequency to 400kHz for initialization
el18jgb 18:c600a6545e81 164 m_Spi.frequency(400000);
el18jgb 18:c600a6545e81 165
el18jgb 18:c600a6545e81 166 //Try to reset the card up to 3 times
el18jgb 18:c600a6545e81 167 for (int f = 0; f < 3; f++) {
el18jgb 18:c600a6545e81 168 //Send 80 dummy clocks with /CS deasserted and DI held high
el18jgb 18:c600a6545e81 169 m_Cs = 1;
el18jgb 18:c600a6545e81 170 for (int i = 0; i < 10; i++) {
el18jgb 18:c600a6545e81 171 m_Spi.write(0xFF);
el18jgb 18:c600a6545e81 172 }
el18jgb 18:c600a6545e81 173
el18jgb 18:c600a6545e81 174 //Send CMD0(0x00000000) to reset the card
el18jgb 18:c600a6545e81 175 token = commandTransaction(CMD0, 0x00000000);
el18jgb 18:c600a6545e81 176 if (token == 0x01) {
el18jgb 18:c600a6545e81 177 break;
el18jgb 18:c600a6545e81 178 }
el18jgb 18:c600a6545e81 179 }
el18jgb 18:c600a6545e81 180
el18jgb 18:c600a6545e81 181 //Check if the card reset
el18jgb 18:c600a6545e81 182 if (token != 0x01) {
el18jgb 18:c600a6545e81 183 //Initialization failed
el18jgb 18:c600a6545e81 184 m_CardType = CARD_UNKNOWN;
el18jgb 18:c600a6545e81 185 return m_Status;
el18jgb 18:c600a6545e81 186 }
el18jgb 18:c600a6545e81 187
el18jgb 18:c600a6545e81 188 //Send CMD59(0x00000001) to enable CRC if necessary
el18jgb 18:c600a6545e81 189 if (m_Crc) {
el18jgb 18:c600a6545e81 190 if (commandTransaction(CMD59, 0x00000001) != 0x01) {
el18jgb 18:c600a6545e81 191 //Initialization failed
el18jgb 18:c600a6545e81 192 m_CardType = CARD_UNKNOWN;
el18jgb 18:c600a6545e81 193 return m_Status;
el18jgb 18:c600a6545e81 194 }
el18jgb 18:c600a6545e81 195 }
el18jgb 18:c600a6545e81 196
el18jgb 18:c600a6545e81 197 //Send CMD8(0x000001AA) to see if this is an SDCv2 card
el18jgb 18:c600a6545e81 198 if (commandTransaction(CMD8, 0x000001AA, &resp) == 0x01) {
el18jgb 18:c600a6545e81 199 //This is an SDCv2 card, get the 32-bit return value and verify the voltage range/check pattern
el18jgb 18:c600a6545e81 200 if ((resp & 0xFFF) != 0x1AA) {
el18jgb 18:c600a6545e81 201 //Initialization failed
el18jgb 18:c600a6545e81 202 m_CardType = CARD_UNKNOWN;
el18jgb 18:c600a6545e81 203 return m_Status;
el18jgb 18:c600a6545e81 204 }
el18jgb 18:c600a6545e81 205
el18jgb 18:c600a6545e81 206 //Send CMD58(0x00000000) to read the OCR, and verify that the card supports 3.2-3.3V
el18jgb 18:c600a6545e81 207 if (commandTransaction(CMD58, 0x00000000, &resp) != 0x01 || !(resp & (1 << 20))) {
el18jgb 18:c600a6545e81 208 //Initialization failed
el18jgb 18:c600a6545e81 209 m_CardType = CARD_UNKNOWN;
el18jgb 18:c600a6545e81 210 return m_Status;
el18jgb 18:c600a6545e81 211 }
el18jgb 18:c600a6545e81 212
el18jgb 18:c600a6545e81 213 //Try to initialize the card using ACMD41(0x40100000) for up to 2 seconds
el18jgb 18:c600a6545e81 214 timer.start();
el18jgb 18:c600a6545e81 215 do {
el18jgb 18:c600a6545e81 216 token = commandTransaction(ACMD41, 0x40100000);
el18jgb 18:c600a6545e81 217 } while (token == 0x01 && timer.read_ms() < 2000);
el18jgb 18:c600a6545e81 218 timer.stop();
el18jgb 18:c600a6545e81 219 timer.reset();
el18jgb 18:c600a6545e81 220
el18jgb 18:c600a6545e81 221 //Check if the card initialized
el18jgb 18:c600a6545e81 222 if (token != 0x00) {
el18jgb 18:c600a6545e81 223 //Initialization failed
el18jgb 18:c600a6545e81 224 m_CardType = CARD_UNKNOWN;
el18jgb 18:c600a6545e81 225 return m_Status;
el18jgb 18:c600a6545e81 226 }
el18jgb 18:c600a6545e81 227
el18jgb 18:c600a6545e81 228 //Send CMD58(0x00000000) to read the OCR
el18jgb 18:c600a6545e81 229 if (commandTransaction(CMD58, 0x00000000, &resp) == 0x00) {
el18jgb 18:c600a6545e81 230 //Check the CCS bit to determine if this is a high capacity card
el18jgb 18:c600a6545e81 231 if (resp & (1 << 30))
el18jgb 18:c600a6545e81 232 m_CardType = CARD_SDHC;
el18jgb 18:c600a6545e81 233 else
el18jgb 18:c600a6545e81 234 m_CardType = CARD_SD;
el18jgb 18:c600a6545e81 235
el18jgb 18:c600a6545e81 236 //Increase the SPI frequency to full speed (up to 50MHz for SDCv2)
el18jgb 18:c600a6545e81 237 if (m_FREQ > 25000000) {
el18jgb 18:c600a6545e81 238 if (enableHighSpeedMode()) {
el18jgb 18:c600a6545e81 239 if (m_FREQ > 50000000) {
el18jgb 18:c600a6545e81 240 m_Spi.frequency(50000000);
el18jgb 18:c600a6545e81 241 } else {
el18jgb 18:c600a6545e81 242 m_Spi.frequency(m_FREQ);
el18jgb 18:c600a6545e81 243 }
el18jgb 18:c600a6545e81 244 } else {
el18jgb 18:c600a6545e81 245 m_Spi.frequency(25000000);
el18jgb 18:c600a6545e81 246 }
el18jgb 18:c600a6545e81 247 } else {
el18jgb 18:c600a6545e81 248 m_Spi.frequency(m_FREQ);
el18jgb 18:c600a6545e81 249 }
el18jgb 18:c600a6545e81 250 } else {
el18jgb 18:c600a6545e81 251 //Initialization failed
el18jgb 18:c600a6545e81 252 m_CardType = CARD_UNKNOWN;
el18jgb 18:c600a6545e81 253 return m_Status;
el18jgb 18:c600a6545e81 254 }
el18jgb 18:c600a6545e81 255 } else {
el18jgb 18:c600a6545e81 256 //Didn't respond or illegal command, this is either an SDCv1 or MMC card
el18jgb 18:c600a6545e81 257 //Send CMD58(0x00000000) to read the OCR, and verify that the card supports 3.2-3.3V
el18jgb 18:c600a6545e81 258 if (commandTransaction(CMD58, 0x00000000, &resp) != 0x01 || !(resp & (1 << 20))) {
el18jgb 18:c600a6545e81 259 //Initialization failed
el18jgb 18:c600a6545e81 260 m_CardType = CARD_UNKNOWN;
el18jgb 18:c600a6545e81 261 return m_Status;
el18jgb 18:c600a6545e81 262 }
el18jgb 18:c600a6545e81 263
el18jgb 18:c600a6545e81 264 //Try to initialize the card using ACMD41(0x40100000) for up to 2 seconds
el18jgb 18:c600a6545e81 265 timer.start();
el18jgb 18:c600a6545e81 266 do {
el18jgb 18:c600a6545e81 267 token = commandTransaction(ACMD41, 0x40100000);
el18jgb 18:c600a6545e81 268 } while (token == 0x01 && timer.read_ms() < 2000);
el18jgb 18:c600a6545e81 269 timer.stop();
el18jgb 18:c600a6545e81 270 timer.reset();
el18jgb 18:c600a6545e81 271
el18jgb 18:c600a6545e81 272 //Check if the card initialized
el18jgb 18:c600a6545e81 273 if (token == 0x00) {
el18jgb 18:c600a6545e81 274 //This is an SDCv1 standard capacity card
el18jgb 18:c600a6545e81 275 m_CardType = CARD_SD;
el18jgb 18:c600a6545e81 276
el18jgb 18:c600a6545e81 277 //Increase the SPI frequency to full speed (up to 25MHz for SDCv1)
el18jgb 18:c600a6545e81 278 if (m_FREQ > 25000000)
el18jgb 18:c600a6545e81 279 m_Spi.frequency(25000000);
el18jgb 18:c600a6545e81 280 else
el18jgb 18:c600a6545e81 281 m_Spi.frequency(m_FREQ);
el18jgb 18:c600a6545e81 282 } else {
el18jgb 18:c600a6545e81 283 //Try to initialize the card using CMD1(0x00100000) for up to 2 seconds
el18jgb 18:c600a6545e81 284 timer.start();
el18jgb 18:c600a6545e81 285 do {
el18jgb 18:c600a6545e81 286 token = commandTransaction(CMD1, 0x00100000);
el18jgb 18:c600a6545e81 287 } while (token == 0x01 && timer.read_ms() < 2000);
el18jgb 18:c600a6545e81 288 timer.stop();
el18jgb 18:c600a6545e81 289 timer.reset();
el18jgb 18:c600a6545e81 290
el18jgb 18:c600a6545e81 291 //Check if the card initialized
el18jgb 18:c600a6545e81 292 if (token == 0x00) {
el18jgb 18:c600a6545e81 293 //This is an MMCv3 card
el18jgb 18:c600a6545e81 294 m_CardType = CARD_MMC;
el18jgb 18:c600a6545e81 295
el18jgb 18:c600a6545e81 296 //Increase the SPI frequency to full speed (up to 20MHz for MMCv3)
el18jgb 18:c600a6545e81 297 if (m_FREQ > 20000000)
el18jgb 18:c600a6545e81 298 m_Spi.frequency(20000000);
el18jgb 18:c600a6545e81 299 else
el18jgb 18:c600a6545e81 300 m_Spi.frequency(m_FREQ);
el18jgb 18:c600a6545e81 301 } else {
el18jgb 18:c600a6545e81 302 //Initialization failed
el18jgb 18:c600a6545e81 303 m_CardType = CARD_UNKNOWN;
el18jgb 18:c600a6545e81 304 return m_Status;
el18jgb 18:c600a6545e81 305 }
el18jgb 18:c600a6545e81 306 }
el18jgb 18:c600a6545e81 307 }
el18jgb 18:c600a6545e81 308
el18jgb 18:c600a6545e81 309 //Send ACMD42(0x00000000) to disconnect the internal pull-up resistor on pin 1 if necessary
el18jgb 18:c600a6545e81 310 if (m_CardType != CARD_MMC) {
el18jgb 18:c600a6545e81 311 if (commandTransaction(ACMD42, 0x00000000) != 0x00) {
el18jgb 18:c600a6545e81 312 //Initialization failed
el18jgb 18:c600a6545e81 313 m_CardType = CARD_UNKNOWN;
el18jgb 18:c600a6545e81 314 return m_Status;
el18jgb 18:c600a6545e81 315 }
el18jgb 18:c600a6545e81 316 }
el18jgb 18:c600a6545e81 317
el18jgb 18:c600a6545e81 318 //Send CMD16(0x00000200) to force the block size to 512B if necessary
el18jgb 18:c600a6545e81 319 if (m_CardType != CARD_SDHC) {
el18jgb 18:c600a6545e81 320 if (commandTransaction(CMD16, 0x00000200) != 0x00) {
el18jgb 18:c600a6545e81 321 //Initialization failed
el18jgb 18:c600a6545e81 322 m_CardType = CARD_UNKNOWN;
el18jgb 18:c600a6545e81 323 return m_Status;
el18jgb 18:c600a6545e81 324 }
el18jgb 18:c600a6545e81 325 }
el18jgb 18:c600a6545e81 326
el18jgb 18:c600a6545e81 327 //The card is now initialized
el18jgb 18:c600a6545e81 328 m_Status &= ~STA_NOINIT;
el18jgb 18:c600a6545e81 329
el18jgb 18:c600a6545e81 330 //Return the disk status
el18jgb 18:c600a6545e81 331 return m_Status;
el18jgb 18:c600a6545e81 332 }
el18jgb 18:c600a6545e81 333
el18jgb 18:c600a6545e81 334 int SDFileSystem::disk_status()
el18jgb 18:c600a6545e81 335 {
el18jgb 18:c600a6545e81 336 //Check the card socket
el18jgb 18:c600a6545e81 337 checkSocket();
el18jgb 18:c600a6545e81 338
el18jgb 18:c600a6545e81 339 //Return the disk status
el18jgb 18:c600a6545e81 340 return m_Status;
el18jgb 18:c600a6545e81 341 }
el18jgb 18:c600a6545e81 342
el18jgb 18:c600a6545e81 343 int SDFileSystem::disk_read(uint8_t* buffer, uint32_t sector, uint32_t count)
el18jgb 18:c600a6545e81 344 {
el18jgb 18:c600a6545e81 345 //Make sure the card is initialized before proceeding
el18jgb 18:c600a6545e81 346 if (m_Status & STA_NOINIT)
el18jgb 18:c600a6545e81 347 return RES_NOTRDY;
el18jgb 18:c600a6545e81 348
el18jgb 18:c600a6545e81 349 //Read a single block, or multiple blocks
el18jgb 18:c600a6545e81 350 if (count > 1) {
el18jgb 18:c600a6545e81 351 return readBlocks((char*)buffer, sector, count) ? RES_OK : RES_ERROR;
el18jgb 18:c600a6545e81 352 } else {
el18jgb 18:c600a6545e81 353 return readBlock((char*)buffer, sector) ? RES_OK : RES_ERROR;
el18jgb 18:c600a6545e81 354 }
el18jgb 18:c600a6545e81 355 }
el18jgb 18:c600a6545e81 356
el18jgb 18:c600a6545e81 357 int SDFileSystem::disk_write(const uint8_t* buffer, uint32_t sector, uint32_t count)
el18jgb 18:c600a6545e81 358 {
el18jgb 18:c600a6545e81 359 //Make sure the card is initialized before proceeding
el18jgb 18:c600a6545e81 360 if (m_Status & STA_NOINIT)
el18jgb 18:c600a6545e81 361 return RES_NOTRDY;
el18jgb 18:c600a6545e81 362
el18jgb 18:c600a6545e81 363 //Make sure the card isn't write protected before proceeding
el18jgb 18:c600a6545e81 364 if (m_Status & STA_PROTECT)
el18jgb 18:c600a6545e81 365 return RES_WRPRT;
el18jgb 18:c600a6545e81 366
el18jgb 18:c600a6545e81 367 //Write a single block, or multiple blocks
el18jgb 18:c600a6545e81 368 if (count > 1) {
el18jgb 18:c600a6545e81 369 return writeBlocks((const char*)buffer, sector, count) ? RES_OK : RES_ERROR;
el18jgb 18:c600a6545e81 370 } else {
el18jgb 18:c600a6545e81 371 return writeBlock((const char*)buffer, sector) ? RES_OK : RES_ERROR;
el18jgb 18:c600a6545e81 372 }
el18jgb 18:c600a6545e81 373 }
el18jgb 18:c600a6545e81 374
el18jgb 18:c600a6545e81 375 int SDFileSystem::disk_sync()
el18jgb 18:c600a6545e81 376 {
el18jgb 18:c600a6545e81 377 //Select the card so we're forced to wait for the end of any internal write processes
el18jgb 18:c600a6545e81 378 if (select()) {
el18jgb 18:c600a6545e81 379 deselect();
el18jgb 18:c600a6545e81 380 return RES_OK;
el18jgb 18:c600a6545e81 381 } else {
el18jgb 18:c600a6545e81 382 return RES_ERROR;
el18jgb 18:c600a6545e81 383 }
el18jgb 18:c600a6545e81 384 }
el18jgb 18:c600a6545e81 385
el18jgb 18:c600a6545e81 386 uint32_t SDFileSystem::disk_sectors()
el18jgb 18:c600a6545e81 387 {
el18jgb 18:c600a6545e81 388 //Make sure the card is initialized before proceeding
el18jgb 18:c600a6545e81 389 if (m_Status & STA_NOINIT)
el18jgb 18:c600a6545e81 390 return 0;
el18jgb 18:c600a6545e81 391
el18jgb 18:c600a6545e81 392 //Try to read the CSD register up to 3 times
el18jgb 18:c600a6545e81 393 for (int f = 0; f < 3; f++) {
el18jgb 18:c600a6545e81 394 //Select the card, and wait for ready
el18jgb 18:c600a6545e81 395 if(!select())
el18jgb 18:c600a6545e81 396 break;
el18jgb 18:c600a6545e81 397
el18jgb 18:c600a6545e81 398 //Send CMD9(0x00000000) to read the CSD register
el18jgb 18:c600a6545e81 399 if (writeCommand(CMD9, 0x00000000) == 0x00) {
el18jgb 18:c600a6545e81 400 //Read the 16B CSD data block
el18jgb 18:c600a6545e81 401 char csd[16];
el18jgb 18:c600a6545e81 402 bool success = readData(csd, 16);
el18jgb 18:c600a6545e81 403 deselect();
el18jgb 18:c600a6545e81 404 if (success) {
el18jgb 18:c600a6545e81 405 //Calculate the sector count based on the card type
el18jgb 18:c600a6545e81 406 if ((csd[0] >> 6) == 0x01) {
el18jgb 18:c600a6545e81 407 //Calculate the sector count for a high capacity card
el18jgb 18:c600a6545e81 408 unsigned int size = (((csd[7] & 0x3F) << 16) | (csd[8] << 8) | csd[9]) + 1;
el18jgb 18:c600a6545e81 409 return size << 10;
el18jgb 18:c600a6545e81 410 } else {
el18jgb 18:c600a6545e81 411 //Calculate the sector count for a standard capacity card
el18jgb 18:c600a6545e81 412 unsigned int size = (((csd[6] & 0x03) << 10) | (csd[7] << 2) | ((csd[8] & 0xC0) >> 6)) + 1;
el18jgb 18:c600a6545e81 413 size <<= ((((csd[9] & 0x03) << 1) | ((csd[10] & 0x80) >> 7)) + 2);
el18jgb 18:c600a6545e81 414 size <<= (csd[5] & 0x0F);
el18jgb 18:c600a6545e81 415 return size >> 9;
el18jgb 18:c600a6545e81 416 }
el18jgb 18:c600a6545e81 417 }
el18jgb 18:c600a6545e81 418 } else {
el18jgb 18:c600a6545e81 419 //The command failed, get out
el18jgb 18:c600a6545e81 420 break;
el18jgb 18:c600a6545e81 421 }
el18jgb 18:c600a6545e81 422 }
el18jgb 18:c600a6545e81 423
el18jgb 18:c600a6545e81 424 //The read operation failed 3 times
el18jgb 18:c600a6545e81 425 deselect();
el18jgb 18:c600a6545e81 426 return 0;
el18jgb 18:c600a6545e81 427 }
el18jgb 18:c600a6545e81 428
el18jgb 18:c600a6545e81 429 void SDFileSystem::onCardRemoval()
el18jgb 18:c600a6545e81 430 {
el18jgb 18:c600a6545e81 431 //Check the card socket
el18jgb 18:c600a6545e81 432 checkSocket();
el18jgb 18:c600a6545e81 433 }
el18jgb 18:c600a6545e81 434
el18jgb 18:c600a6545e81 435 inline void SDFileSystem::checkSocket()
el18jgb 18:c600a6545e81 436 {
el18jgb 18:c600a6545e81 437 //Use the card detect switch (if available) to determine if the socket is occupied
el18jgb 18:c600a6545e81 438 if (m_CdAssert != -1) {
el18jgb 18:c600a6545e81 439 if (m_Status & STA_NODISK) {
el18jgb 18:c600a6545e81 440 if (m_Cd == m_CdAssert) {
el18jgb 18:c600a6545e81 441 //The socket is now occupied
el18jgb 18:c600a6545e81 442 m_Status &= ~STA_NODISK;
el18jgb 18:c600a6545e81 443 m_CardType = CARD_UNKNOWN;
el18jgb 18:c600a6545e81 444 }
el18jgb 18:c600a6545e81 445 } else {
el18jgb 18:c600a6545e81 446 if (m_Cd != m_CdAssert) {
el18jgb 18:c600a6545e81 447 //The socket is now empty
el18jgb 18:c600a6545e81 448 m_Status |= (STA_NODISK | STA_NOINIT);
el18jgb 18:c600a6545e81 449 m_CardType = CARD_NONE;
el18jgb 18:c600a6545e81 450 }
el18jgb 18:c600a6545e81 451 }
el18jgb 18:c600a6545e81 452 }
el18jgb 18:c600a6545e81 453 }
el18jgb 18:c600a6545e81 454
el18jgb 18:c600a6545e81 455 inline bool SDFileSystem::waitReady(int timeout)
el18jgb 18:c600a6545e81 456 {
el18jgb 18:c600a6545e81 457 char resp;
el18jgb 18:c600a6545e81 458
el18jgb 18:c600a6545e81 459 //Keep sending dummy clocks with DI held high until the card releases the DO line
el18jgb 18:c600a6545e81 460 m_Timer.start();
el18jgb 18:c600a6545e81 461 do {
el18jgb 18:c600a6545e81 462 resp = m_Spi.write(0xFF);
el18jgb 18:c600a6545e81 463 } while (resp == 0x00 && m_Timer.read_ms() < timeout);
el18jgb 18:c600a6545e81 464 m_Timer.stop();
el18jgb 18:c600a6545e81 465 m_Timer.reset();
el18jgb 18:c600a6545e81 466
el18jgb 18:c600a6545e81 467 //Return success/failure
el18jgb 18:c600a6545e81 468 return (resp > 0x00);
el18jgb 18:c600a6545e81 469 }
el18jgb 18:c600a6545e81 470
el18jgb 18:c600a6545e81 471 inline bool SDFileSystem::select()
el18jgb 18:c600a6545e81 472 {
el18jgb 18:c600a6545e81 473 //Assert /CS
el18jgb 18:c600a6545e81 474 m_Cs = 0;
el18jgb 18:c600a6545e81 475
el18jgb 18:c600a6545e81 476 //Send 8 dummy clocks with DI held high to enable DO
el18jgb 18:c600a6545e81 477 m_Spi.write(0xFF);
el18jgb 18:c600a6545e81 478
el18jgb 18:c600a6545e81 479 //Wait for up to 500ms for the card to become ready
el18jgb 18:c600a6545e81 480 if (waitReady(500)) {
el18jgb 18:c600a6545e81 481 return true;
el18jgb 18:c600a6545e81 482 } else {
el18jgb 18:c600a6545e81 483 //We timed out, deselect and return false
el18jgb 18:c600a6545e81 484 deselect();
el18jgb 18:c600a6545e81 485 return false;
el18jgb 18:c600a6545e81 486 }
el18jgb 18:c600a6545e81 487 }
el18jgb 18:c600a6545e81 488
el18jgb 18:c600a6545e81 489 inline void SDFileSystem::deselect()
el18jgb 18:c600a6545e81 490 {
el18jgb 18:c600a6545e81 491 //Deassert /CS
el18jgb 18:c600a6545e81 492 m_Cs = 1;
el18jgb 18:c600a6545e81 493
el18jgb 18:c600a6545e81 494 //Send 8 dummy clocks with DI held high to disable DO
el18jgb 18:c600a6545e81 495 m_Spi.write(0xFF);
el18jgb 18:c600a6545e81 496 }
el18jgb 18:c600a6545e81 497
el18jgb 18:c600a6545e81 498 inline char SDFileSystem::commandTransaction(char cmd, unsigned int arg, unsigned int* resp)
el18jgb 18:c600a6545e81 499 {
el18jgb 18:c600a6545e81 500 //Select the card, and wait for ready
el18jgb 18:c600a6545e81 501 if(!select())
el18jgb 18:c600a6545e81 502 return 0xFF;
el18jgb 18:c600a6545e81 503
el18jgb 18:c600a6545e81 504 //Perform the command transaction
el18jgb 18:c600a6545e81 505 char token = writeCommand(cmd, arg, resp);
el18jgb 18:c600a6545e81 506
el18jgb 18:c600a6545e81 507 //Deselect the card, and return the R1 response token
el18jgb 18:c600a6545e81 508 deselect();
el18jgb 18:c600a6545e81 509 return token;
el18jgb 18:c600a6545e81 510 }
el18jgb 18:c600a6545e81 511
el18jgb 18:c600a6545e81 512 char SDFileSystem::writeCommand(char cmd, unsigned int arg, unsigned int* resp)
el18jgb 18:c600a6545e81 513 {
el18jgb 18:c600a6545e81 514 char token;
el18jgb 18:c600a6545e81 515
el18jgb 18:c600a6545e81 516 //Try to send the command up to 3 times
el18jgb 18:c600a6545e81 517 for (int f = 0; f < 3; f++) {
el18jgb 18:c600a6545e81 518 //Send CMD55(0x00000000) prior to an application specific command
el18jgb 18:c600a6545e81 519 if (cmd == ACMD22 || cmd == ACMD23 || cmd == ACMD41 || cmd == ACMD42) {
el18jgb 18:c600a6545e81 520 token = writeCommand(CMD55, 0x00000000);
el18jgb 18:c600a6545e81 521 if (token > 0x01)
el18jgb 18:c600a6545e81 522 return token;
el18jgb 18:c600a6545e81 523
el18jgb 18:c600a6545e81 524 //Deselect and reselect the card between CMD55 and an ACMD
el18jgb 18:c600a6545e81 525 deselect();
el18jgb 18:c600a6545e81 526 if(!select())
el18jgb 18:c600a6545e81 527 return 0xFF;
el18jgb 18:c600a6545e81 528 }
el18jgb 18:c600a6545e81 529
el18jgb 18:c600a6545e81 530 //Prepare the command packet
el18jgb 18:c600a6545e81 531 char cmdPacket[6];
el18jgb 18:c600a6545e81 532 cmdPacket[0] = cmd;
el18jgb 18:c600a6545e81 533 cmdPacket[1] = arg >> 24;
el18jgb 18:c600a6545e81 534 cmdPacket[2] = arg >> 16;
el18jgb 18:c600a6545e81 535 cmdPacket[3] = arg >> 8;
el18jgb 18:c600a6545e81 536 cmdPacket[4] = arg;
el18jgb 18:c600a6545e81 537 if (m_Crc || cmd == CMD0 || cmd == CMD8)
el18jgb 18:c600a6545e81 538 cmdPacket[5] = (SDCRC::crc7(cmdPacket, 5) << 1) | 0x01;
el18jgb 18:c600a6545e81 539 else
el18jgb 18:c600a6545e81 540 cmdPacket[5] = 0x01;
el18jgb 18:c600a6545e81 541
el18jgb 18:c600a6545e81 542 //Send the command packet
el18jgb 18:c600a6545e81 543 for (int i = 0; i < 6; i++)
el18jgb 18:c600a6545e81 544 m_Spi.write(cmdPacket[i]);
el18jgb 18:c600a6545e81 545
el18jgb 18:c600a6545e81 546 //Discard the stuff byte immediately following CMD12
el18jgb 18:c600a6545e81 547 if (cmd == CMD12)
el18jgb 18:c600a6545e81 548 m_Spi.write(0xFF);
el18jgb 18:c600a6545e81 549
el18jgb 18:c600a6545e81 550 //Allow up to 8 bytes of delay for the R1 response token
el18jgb 18:c600a6545e81 551 for (int i = 0; i < 9; i++) {
el18jgb 18:c600a6545e81 552 token = m_Spi.write(0xFF);
el18jgb 18:c600a6545e81 553 if (!(token & 0x80))
el18jgb 18:c600a6545e81 554 break;
el18jgb 18:c600a6545e81 555 }
el18jgb 18:c600a6545e81 556
el18jgb 18:c600a6545e81 557 //Verify the R1 response token
el18jgb 18:c600a6545e81 558 if (token == 0xFF) {
el18jgb 18:c600a6545e81 559 //No data was received, get out early
el18jgb 18:c600a6545e81 560 break;
el18jgb 18:c600a6545e81 561 } else if (token & (1 << 3)) {
el18jgb 18:c600a6545e81 562 //There was a CRC error, try again
el18jgb 18:c600a6545e81 563 continue;
el18jgb 18:c600a6545e81 564 } else if (token > 0x01) {
el18jgb 18:c600a6545e81 565 //An error occured, get out early
el18jgb 18:c600a6545e81 566 break;
el18jgb 18:c600a6545e81 567 }
el18jgb 18:c600a6545e81 568
el18jgb 18:c600a6545e81 569 //Handle R2 and R3/R7 response tokens
el18jgb 18:c600a6545e81 570 if (cmd == CMD13 && resp != NULL) {
el18jgb 18:c600a6545e81 571 //Read the R2 response value
el18jgb 18:c600a6545e81 572 *resp = m_Spi.write(0xFF);
el18jgb 18:c600a6545e81 573 } else if ((cmd == CMD8 || cmd == CMD58) && resp != NULL) {
el18jgb 18:c600a6545e81 574 //Read the R3/R7 response value
el18jgb 18:c600a6545e81 575 *resp = (m_Spi.write(0xFF) << 24);
el18jgb 18:c600a6545e81 576 *resp |= (m_Spi.write(0xFF) << 16);
el18jgb 18:c600a6545e81 577 *resp |= (m_Spi.write(0xFF) << 8);
el18jgb 18:c600a6545e81 578 *resp |= m_Spi.write(0xFF);
el18jgb 18:c600a6545e81 579 }
el18jgb 18:c600a6545e81 580
el18jgb 18:c600a6545e81 581 //The command was successful
el18jgb 18:c600a6545e81 582 break;
el18jgb 18:c600a6545e81 583 }
el18jgb 18:c600a6545e81 584
el18jgb 18:c600a6545e81 585 //Return the R1 response token
el18jgb 18:c600a6545e81 586 return token;
el18jgb 18:c600a6545e81 587 }
el18jgb 18:c600a6545e81 588
el18jgb 18:c600a6545e81 589 bool SDFileSystem::readData(char* buffer, int length)
el18jgb 18:c600a6545e81 590 {
el18jgb 18:c600a6545e81 591 char token;
el18jgb 18:c600a6545e81 592 unsigned short crc;
el18jgb 18:c600a6545e81 593
el18jgb 18:c600a6545e81 594 //Wait for up to 500ms for a token to arrive
el18jgb 18:c600a6545e81 595 m_Timer.start();
el18jgb 18:c600a6545e81 596 do {
el18jgb 18:c600a6545e81 597 token = m_Spi.write(0xFF);
el18jgb 18:c600a6545e81 598 } while (token == 0xFF && m_Timer.read_ms() < 500);
el18jgb 18:c600a6545e81 599 m_Timer.stop();
el18jgb 18:c600a6545e81 600 m_Timer.reset();
el18jgb 18:c600a6545e81 601
el18jgb 18:c600a6545e81 602 //Check if a valid start block token was received
el18jgb 18:c600a6545e81 603 if (token != 0xFE)
el18jgb 18:c600a6545e81 604 return false;
el18jgb 18:c600a6545e81 605
el18jgb 18:c600a6545e81 606 //Check if large frames are enabled or not
el18jgb 18:c600a6545e81 607 if (m_LargeFrames) {
el18jgb 18:c600a6545e81 608 //Switch to 16-bit frames for better performance
el18jgb 18:c600a6545e81 609 m_Spi.format(16, 0);
el18jgb 18:c600a6545e81 610
el18jgb 18:c600a6545e81 611 //Read the data block into the buffer
el18jgb 18:c600a6545e81 612 unsigned short dataWord;
el18jgb 18:c600a6545e81 613 for (int i = 0; i < length; i += 2) {
el18jgb 18:c600a6545e81 614 dataWord = m_Spi.write(0xFFFF);
el18jgb 18:c600a6545e81 615 buffer[i] = dataWord >> 8;
el18jgb 18:c600a6545e81 616 buffer[i + 1] = dataWord;
el18jgb 18:c600a6545e81 617 }
el18jgb 18:c600a6545e81 618
el18jgb 18:c600a6545e81 619 //Read the CRC16 checksum for the data block
el18jgb 18:c600a6545e81 620 crc = m_Spi.write(0xFFFF);
el18jgb 18:c600a6545e81 621
el18jgb 18:c600a6545e81 622 //Switch back to 8-bit frames
el18jgb 18:c600a6545e81 623 m_Spi.format(8, 0);
el18jgb 18:c600a6545e81 624 } else {
el18jgb 18:c600a6545e81 625 //Read the data into the buffer
el18jgb 18:c600a6545e81 626 for (int i = 0; i < length; i++)
el18jgb 18:c600a6545e81 627 buffer[i] = m_Spi.write(0xFF);
el18jgb 18:c600a6545e81 628
el18jgb 18:c600a6545e81 629 //Read the CRC16 checksum for the data block
el18jgb 18:c600a6545e81 630 crc = (m_Spi.write(0xFF) << 8);
el18jgb 18:c600a6545e81 631 crc |= m_Spi.write(0xFF);
el18jgb 18:c600a6545e81 632 }
el18jgb 18:c600a6545e81 633
el18jgb 18:c600a6545e81 634 //Return the validity of the CRC16 checksum (if enabled)
el18jgb 18:c600a6545e81 635 return (!m_Crc || crc == SDCRC::crc16(buffer, length));
el18jgb 18:c600a6545e81 636 }
el18jgb 18:c600a6545e81 637
el18jgb 18:c600a6545e81 638 char SDFileSystem::writeData(const char* buffer, char token)
el18jgb 18:c600a6545e81 639 {
el18jgb 18:c600a6545e81 640 //Calculate the CRC16 checksum for the data block (if enabled)
el18jgb 18:c600a6545e81 641 unsigned short crc = (m_Crc) ? SDCRC::crc16(buffer, 512) : 0xFFFF;
el18jgb 18:c600a6545e81 642
el18jgb 18:c600a6545e81 643 //Wait for up to 500ms for the card to become ready
el18jgb 18:c600a6545e81 644 if (!waitReady(500))
el18jgb 18:c600a6545e81 645 return false;
el18jgb 18:c600a6545e81 646
el18jgb 18:c600a6545e81 647 //Send the start block token
el18jgb 18:c600a6545e81 648 m_Spi.write(token);
el18jgb 18:c600a6545e81 649
el18jgb 18:c600a6545e81 650 //Check if large frames are enabled or not
el18jgb 18:c600a6545e81 651 if (m_LargeFrames) {
el18jgb 18:c600a6545e81 652 //Switch to 16-bit frames for better performance
el18jgb 18:c600a6545e81 653 m_Spi.format(16, 0);
el18jgb 18:c600a6545e81 654
el18jgb 18:c600a6545e81 655 //Write the data block from the buffer
el18jgb 18:c600a6545e81 656 for (int i = 0; i < 512; i += 2)
el18jgb 18:c600a6545e81 657 m_Spi.write((buffer[i] << 8) | buffer[i + 1]);
el18jgb 18:c600a6545e81 658
el18jgb 18:c600a6545e81 659 //Send the CRC16 checksum for the data block
el18jgb 18:c600a6545e81 660 m_Spi.write(crc);
el18jgb 18:c600a6545e81 661
el18jgb 18:c600a6545e81 662 //Switch back to 8-bit frames
el18jgb 18:c600a6545e81 663 m_Spi.format(8, 0);
el18jgb 18:c600a6545e81 664 } else {
el18jgb 18:c600a6545e81 665 //Write the data block from the buffer
el18jgb 18:c600a6545e81 666 for (int i = 0; i < 512; i++)
el18jgb 18:c600a6545e81 667 m_Spi.write(buffer[i]);
el18jgb 18:c600a6545e81 668
el18jgb 18:c600a6545e81 669 //Send the CRC16 checksum for the data block
el18jgb 18:c600a6545e81 670 m_Spi.write(crc >> 8);
el18jgb 18:c600a6545e81 671 m_Spi.write(crc);
el18jgb 18:c600a6545e81 672 }
el18jgb 18:c600a6545e81 673
el18jgb 18:c600a6545e81 674 //Return the data response token
el18jgb 18:c600a6545e81 675 return (m_Spi.write(0xFF) & 0x1F);
el18jgb 18:c600a6545e81 676 }
el18jgb 18:c600a6545e81 677
el18jgb 18:c600a6545e81 678 inline bool SDFileSystem::readBlock(char* buffer, unsigned int lba)
el18jgb 18:c600a6545e81 679 {
el18jgb 18:c600a6545e81 680 //Try to read the block up to 3 times
el18jgb 18:c600a6545e81 681 for (int f = 0; f < 3; f++) {
el18jgb 18:c600a6545e81 682 //Select the card, and wait for ready
el18jgb 18:c600a6545e81 683 if(!select())
el18jgb 18:c600a6545e81 684 break;
el18jgb 18:c600a6545e81 685
el18jgb 18:c600a6545e81 686 //Send CMD17(block) to read a single block
el18jgb 18:c600a6545e81 687 if (writeCommand(CMD17, (m_CardType == CARD_SDHC) ? lba : lba << 9) == 0x00) {
el18jgb 18:c600a6545e81 688 //Try to read the block, and deselect the card
el18jgb 18:c600a6545e81 689 bool success = readData(buffer, 512);
el18jgb 18:c600a6545e81 690 deselect();
el18jgb 18:c600a6545e81 691
el18jgb 18:c600a6545e81 692 //Return if successful
el18jgb 18:c600a6545e81 693 if (success)
el18jgb 18:c600a6545e81 694 return true;
el18jgb 18:c600a6545e81 695 } else {
el18jgb 18:c600a6545e81 696 //The command failed, get out
el18jgb 18:c600a6545e81 697 break;
el18jgb 18:c600a6545e81 698 }
el18jgb 18:c600a6545e81 699 }
el18jgb 18:c600a6545e81 700
el18jgb 18:c600a6545e81 701 //The single block read failed
el18jgb 18:c600a6545e81 702 deselect();
el18jgb 18:c600a6545e81 703 return false;
el18jgb 18:c600a6545e81 704 }
el18jgb 18:c600a6545e81 705
el18jgb 18:c600a6545e81 706 inline bool SDFileSystem::readBlocks(char* buffer, unsigned int lba, unsigned int count)
el18jgb 18:c600a6545e81 707 {
el18jgb 18:c600a6545e81 708 //Try to read each block up to 3 times
el18jgb 18:c600a6545e81 709 for (int f = 0; f < 3;) {
el18jgb 18:c600a6545e81 710 //Select the card, and wait for ready
el18jgb 18:c600a6545e81 711 if(!select())
el18jgb 18:c600a6545e81 712 break;
el18jgb 18:c600a6545e81 713
el18jgb 18:c600a6545e81 714 //Send CMD18(block) to read multiple blocks
el18jgb 18:c600a6545e81 715 if (writeCommand(CMD18, (m_CardType == CARD_SDHC) ? lba : lba << 9) == 0x00) {
el18jgb 18:c600a6545e81 716 //Try to read all of the data blocks
el18jgb 18:c600a6545e81 717 do {
el18jgb 18:c600a6545e81 718 //Read the next block, and break on errors
el18jgb 18:c600a6545e81 719 if (!readData(buffer, 512)) {
el18jgb 18:c600a6545e81 720 f++;
el18jgb 18:c600a6545e81 721 break;
el18jgb 18:c600a6545e81 722 }
el18jgb 18:c600a6545e81 723
el18jgb 18:c600a6545e81 724 //Update the variables
el18jgb 18:c600a6545e81 725 lba++;
el18jgb 18:c600a6545e81 726 buffer += 512;
el18jgb 18:c600a6545e81 727 f = 0;
el18jgb 18:c600a6545e81 728 } while (--count);
el18jgb 18:c600a6545e81 729
el18jgb 18:c600a6545e81 730 //Send CMD12(0x00000000) to stop the transmission
el18jgb 18:c600a6545e81 731 if (writeCommand(CMD12, 0x00000000) != 0x00) {
el18jgb 18:c600a6545e81 732 //The command failed, get out
el18jgb 18:c600a6545e81 733 break;
el18jgb 18:c600a6545e81 734 }
el18jgb 18:c600a6545e81 735
el18jgb 18:c600a6545e81 736 //Deselect the card, and return if successful
el18jgb 18:c600a6545e81 737 deselect();
el18jgb 18:c600a6545e81 738 if (count == 0)
el18jgb 18:c600a6545e81 739 return true;
el18jgb 18:c600a6545e81 740 } else {
el18jgb 18:c600a6545e81 741 //The command failed, get out
el18jgb 18:c600a6545e81 742 break;
el18jgb 18:c600a6545e81 743 }
el18jgb 18:c600a6545e81 744 }
el18jgb 18:c600a6545e81 745
el18jgb 18:c600a6545e81 746 //The multiple block read failed
el18jgb 18:c600a6545e81 747 deselect();
el18jgb 18:c600a6545e81 748 return false;
el18jgb 18:c600a6545e81 749 }
el18jgb 18:c600a6545e81 750
el18jgb 18:c600a6545e81 751 inline bool SDFileSystem::writeBlock(const char* buffer, unsigned int lba)
el18jgb 18:c600a6545e81 752 {
el18jgb 18:c600a6545e81 753 //Try to write the block up to 3 times
el18jgb 18:c600a6545e81 754 for (int f = 0; f < 3; f++) {
el18jgb 18:c600a6545e81 755 //Select the card, and wait for ready
el18jgb 18:c600a6545e81 756 if(!select())
el18jgb 18:c600a6545e81 757 break;
el18jgb 18:c600a6545e81 758
el18jgb 18:c600a6545e81 759 //Send CMD24(block) to write a single block
el18jgb 18:c600a6545e81 760 if (writeCommand(CMD24, (m_CardType == CARD_SDHC) ? lba : lba << 9) == 0x00) {
el18jgb 18:c600a6545e81 761 //Try to write the block, and deselect the card
el18jgb 18:c600a6545e81 762 char token = writeData(buffer, 0xFE);
el18jgb 18:c600a6545e81 763 deselect();
el18jgb 18:c600a6545e81 764
el18jgb 18:c600a6545e81 765 //Check the data response token
el18jgb 18:c600a6545e81 766 if (token == 0x0A) {
el18jgb 18:c600a6545e81 767 //A CRC error occured, try again
el18jgb 18:c600a6545e81 768 continue;
el18jgb 18:c600a6545e81 769 } else if (token == 0x0C) {
el18jgb 18:c600a6545e81 770 //A write error occured, get out
el18jgb 18:c600a6545e81 771 break;
el18jgb 18:c600a6545e81 772 }
el18jgb 18:c600a6545e81 773
el18jgb 18:c600a6545e81 774 //Send CMD13(0x00000000) to verify that the programming was successful if enabled
el18jgb 18:c600a6545e81 775 if (m_WriteValidation) {
el18jgb 18:c600a6545e81 776 unsigned int resp;
el18jgb 18:c600a6545e81 777 if (commandTransaction(CMD13, 0x00000000, &resp) != 0x00 || resp != 0x00) {
el18jgb 18:c600a6545e81 778 //Some manner of unrecoverable write error occured during programming, get out
el18jgb 18:c600a6545e81 779 break;
el18jgb 18:c600a6545e81 780 }
el18jgb 18:c600a6545e81 781 }
el18jgb 18:c600a6545e81 782
el18jgb 18:c600a6545e81 783 //The data was written successfully
el18jgb 18:c600a6545e81 784 return true;
el18jgb 18:c600a6545e81 785 } else {
el18jgb 18:c600a6545e81 786 //The command failed, get out
el18jgb 18:c600a6545e81 787 break;
el18jgb 18:c600a6545e81 788 }
el18jgb 18:c600a6545e81 789 }
el18jgb 18:c600a6545e81 790
el18jgb 18:c600a6545e81 791 //The single block write failed
el18jgb 18:c600a6545e81 792 deselect();
el18jgb 18:c600a6545e81 793 return false;
el18jgb 18:c600a6545e81 794 }
el18jgb 18:c600a6545e81 795
el18jgb 18:c600a6545e81 796 inline bool SDFileSystem::writeBlocks(const char* buffer, unsigned int lba, unsigned int count)
el18jgb 18:c600a6545e81 797 {
el18jgb 18:c600a6545e81 798 char token;
el18jgb 18:c600a6545e81 799 const char* currentBuffer = buffer;
el18jgb 18:c600a6545e81 800 unsigned int currentLba = lba;
el18jgb 18:c600a6545e81 801 int currentCount = count;
el18jgb 18:c600a6545e81 802
el18jgb 18:c600a6545e81 803 //Try to write each block up to 3 times
el18jgb 18:c600a6545e81 804 for (int f = 0; f < 3;) {
el18jgb 18:c600a6545e81 805 //If this is an SD card, send ACMD23(count) to set the number of blocks to pre-erase
el18jgb 18:c600a6545e81 806 if (m_CardType != CARD_MMC) {
el18jgb 18:c600a6545e81 807 if (commandTransaction(ACMD23, currentCount) != 0x00) {
el18jgb 18:c600a6545e81 808 //The command failed, get out
el18jgb 18:c600a6545e81 809 break;
el18jgb 18:c600a6545e81 810 }
el18jgb 18:c600a6545e81 811 }
el18jgb 18:c600a6545e81 812
el18jgb 18:c600a6545e81 813 //Select the card, and wait for ready
el18jgb 18:c600a6545e81 814 if(!select())
el18jgb 18:c600a6545e81 815 break;
el18jgb 18:c600a6545e81 816
el18jgb 18:c600a6545e81 817 //Send CMD25(block) to write multiple blocks
el18jgb 18:c600a6545e81 818 if (writeCommand(CMD25, (m_CardType == CARD_SDHC) ? currentLba : currentLba << 9) == 0x00) {
el18jgb 18:c600a6545e81 819 //Try to write all of the data blocks
el18jgb 18:c600a6545e81 820 do {
el18jgb 18:c600a6545e81 821 //Write the next block and break on errors
el18jgb 18:c600a6545e81 822 token = writeData(currentBuffer, 0xFC);
el18jgb 18:c600a6545e81 823 if (token != 0x05) {
el18jgb 18:c600a6545e81 824 f++;
el18jgb 18:c600a6545e81 825 break;
el18jgb 18:c600a6545e81 826 }
el18jgb 18:c600a6545e81 827
el18jgb 18:c600a6545e81 828 //Update the variables
el18jgb 18:c600a6545e81 829 currentBuffer += 512;
el18jgb 18:c600a6545e81 830 f = 0;
el18jgb 18:c600a6545e81 831 } while (--currentCount);
el18jgb 18:c600a6545e81 832
el18jgb 18:c600a6545e81 833 //Wait for up to 500ms for the card to finish processing the last block
el18jgb 18:c600a6545e81 834 if (!waitReady(500))
el18jgb 18:c600a6545e81 835 break;
el18jgb 18:c600a6545e81 836
el18jgb 18:c600a6545e81 837 //Finalize the transmission
el18jgb 18:c600a6545e81 838 if (currentCount == 0) {
el18jgb 18:c600a6545e81 839 //Send the stop tran token, and deselect the card
el18jgb 18:c600a6545e81 840 m_Spi.write(0xFD);
el18jgb 18:c600a6545e81 841 deselect();
el18jgb 18:c600a6545e81 842
el18jgb 18:c600a6545e81 843 //Send CMD13(0x00000000) to verify that the programming was successful if enabled
el18jgb 18:c600a6545e81 844 if (m_WriteValidation) {
el18jgb 18:c600a6545e81 845 unsigned int resp;
el18jgb 18:c600a6545e81 846 if (commandTransaction(CMD13, 0x00000000, &resp) != 0x00 || resp != 0x00) {
el18jgb 18:c600a6545e81 847 //Some manner of unrecoverable write error occured during programming, get out
el18jgb 18:c600a6545e81 848 break;
el18jgb 18:c600a6545e81 849 }
el18jgb 18:c600a6545e81 850 }
el18jgb 18:c600a6545e81 851
el18jgb 18:c600a6545e81 852 //The data was written successfully
el18jgb 18:c600a6545e81 853 return true;
el18jgb 18:c600a6545e81 854 } else {
el18jgb 18:c600a6545e81 855 //Send CMD12(0x00000000) to abort the transmission
el18jgb 18:c600a6545e81 856 if (writeCommand(CMD12, 0x00000000) != 0x00) {
el18jgb 18:c600a6545e81 857 //The command failed, get out
el18jgb 18:c600a6545e81 858 break;
el18jgb 18:c600a6545e81 859 }
el18jgb 18:c600a6545e81 860
el18jgb 18:c600a6545e81 861 //Deselect the card
el18jgb 18:c600a6545e81 862 deselect();
el18jgb 18:c600a6545e81 863
el18jgb 18:c600a6545e81 864 //Check the error token
el18jgb 18:c600a6545e81 865 if (token == 0x0A) {
el18jgb 18:c600a6545e81 866 //Determine the number of well written blocks if possible
el18jgb 18:c600a6545e81 867 unsigned int writtenBlocks = 0;
el18jgb 18:c600a6545e81 868 if (m_CardType != CARD_MMC && select()) {
el18jgb 18:c600a6545e81 869 //Send ACMD22(0x00000000) to get the number of well written blocks
el18jgb 18:c600a6545e81 870 if (writeCommand(ACMD22, 0x00000000) == 0x00) {
el18jgb 18:c600a6545e81 871 //Read the data
el18jgb 18:c600a6545e81 872 char acmdData[4];
el18jgb 18:c600a6545e81 873 if (readData(acmdData, 4)) {
el18jgb 18:c600a6545e81 874 //Extract the number of well written blocks
el18jgb 18:c600a6545e81 875 writtenBlocks = acmdData[0] << 24;
el18jgb 18:c600a6545e81 876 writtenBlocks |= acmdData[1] << 16;
el18jgb 18:c600a6545e81 877 writtenBlocks |= acmdData[2] << 8;
el18jgb 18:c600a6545e81 878 writtenBlocks |= acmdData[3];
el18jgb 18:c600a6545e81 879 }
el18jgb 18:c600a6545e81 880 }
el18jgb 18:c600a6545e81 881 deselect();
el18jgb 18:c600a6545e81 882 }
el18jgb 18:c600a6545e81 883
el18jgb 18:c600a6545e81 884 //Roll back the variables based on the number of well written blocks
el18jgb 18:c600a6545e81 885 currentBuffer = buffer + (writtenBlocks << 9);
el18jgb 18:c600a6545e81 886 currentLba = lba + writtenBlocks;
el18jgb 18:c600a6545e81 887 currentCount = count - writtenBlocks;
el18jgb 18:c600a6545e81 888
el18jgb 18:c600a6545e81 889 //Try again
el18jgb 18:c600a6545e81 890 continue;
el18jgb 18:c600a6545e81 891 } else {
el18jgb 18:c600a6545e81 892 //A write error occured, get out
el18jgb 18:c600a6545e81 893 break;
el18jgb 18:c600a6545e81 894 }
el18jgb 18:c600a6545e81 895 }
el18jgb 18:c600a6545e81 896 } else {
el18jgb 18:c600a6545e81 897 //The command failed, get out
el18jgb 18:c600a6545e81 898 break;
el18jgb 18:c600a6545e81 899 }
el18jgb 18:c600a6545e81 900 }
el18jgb 18:c600a6545e81 901
el18jgb 18:c600a6545e81 902 //The multiple block write failed
el18jgb 18:c600a6545e81 903 deselect();
el18jgb 18:c600a6545e81 904 return false;
el18jgb 18:c600a6545e81 905 }
el18jgb 18:c600a6545e81 906
el18jgb 18:c600a6545e81 907 bool SDFileSystem::enableHighSpeedMode()
el18jgb 18:c600a6545e81 908 {
el18jgb 18:c600a6545e81 909 //Try to issue CMD6 up to 3 times
el18jgb 18:c600a6545e81 910 for (int f = 0; f < 3; f++) {
el18jgb 18:c600a6545e81 911 //Select the card, and wait for ready
el18jgb 18:c600a6545e81 912 if(!select())
el18jgb 18:c600a6545e81 913 break;
el18jgb 18:c600a6545e81 914
el18jgb 18:c600a6545e81 915 //Send CMD6(0x80FFFFF1) to change the access mode to high speed
el18jgb 18:c600a6545e81 916 if (writeCommand(CMD6, 0x80FFFFF1) == 0x00) {
el18jgb 18:c600a6545e81 917 //Read the 64B status data block
el18jgb 18:c600a6545e81 918 char status[64];
el18jgb 18:c600a6545e81 919 bool success = readData(status, 64);
el18jgb 18:c600a6545e81 920 deselect();
el18jgb 18:c600a6545e81 921 if (success) {
el18jgb 18:c600a6545e81 922 //Return whether or not the operation was successful
el18jgb 18:c600a6545e81 923 return ((status[16] & 0x0F) == 0x1);
el18jgb 18:c600a6545e81 924 }
el18jgb 18:c600a6545e81 925 } else {
el18jgb 18:c600a6545e81 926 //The command failed, get out
el18jgb 18:c600a6545e81 927 break;
el18jgb 18:c600a6545e81 928 }
el18jgb 18:c600a6545e81 929 }
el18jgb 18:c600a6545e81 930
el18jgb 18:c600a6545e81 931 //The operation failed 3 times
el18jgb 18:c600a6545e81 932 deselect();
el18jgb 18:c600a6545e81 933 return false;
el18jgb 18:c600a6545e81 934 }