43 ArduinoSpiIO(
int cs = -1, SPIClass &spi = SPI) { setSPI(cs, spi); }
46 void setSPI(SPIClass &spi = SPI) {
51 void setSPI(
int cs = -1, SPIClass &spi = SPI) {
59 DSTATUS disk_initialize(BYTE drv
61 BYTE n, cmd, ty, ocr[4];
63 if (drv != 0)
return STA_NOINIT;
66 if (stat & STA_NODISK)
return stat;
69 for (n = 10; n; n--) xchg_spi(0xFF);
72 if (send_cmd(CMD0, 0) == 1) {
74 if (send_cmd(CMD8, 0x1AA) == 1) {
75 for (n = 0; n < 4; n++)
76 ocr[n] = xchg_spi(0xFF);
79 while (spi_timer_status() &&
80 send_cmd(ACMD41, 1UL << 30));
82 if (spi_timer_status() &&
83 send_cmd(CMD58, 0) == 0) {
84 for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF);
86 (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;
90 if (send_cmd(ACMD41, 0) <= 1) {
97 while (spi_timer_status() &&
99 if (!spi_timer_status() ||
100 send_cmd(CMD16, 512) != 0)
121 DSTATUS disk_status(BYTE drv
123 if (drv)
return STA_NOINIT;
137 if (drv || !count)
return RES_PARERR;
138 if (stat & STA_NOINIT)
return RES_NOTRDY;
140 if (!(CardType & CT_BLOCK))
144 if ((send_cmd(CMD17, sector) == 0)
145 && rcvr_datablock(buff, 512)) {
149 if (send_cmd(CMD18, sector) == 0) {
151 if (!rcvr_datablock(buff, 512))
break;
160 return count ? RES_ERROR : RES_OK;
169 DRESULT disk_write(BYTE drv,
174 if (drv || !count)
return RES_PARERR;
175 if (stat & STA_NOINIT)
return RES_NOTRDY;
176 if (stat & STA_PROTECT)
return RES_WRPRT;
178 if (!(CardType & CT_BLOCK))
182 if ((send_cmd(CMD24, sector) == 0)
183 && xmit_datablock((BYTE*)buff, 0xFE)) {
187 if (CardType & CT_SDC)
188 send_cmd(ACMD23, count);
189 if (send_cmd(CMD25, sector) == 0) {
191 if (!xmit_datablock((BYTE*)buff, 0xFC))
break;
194 if (!xmit_datablock(0, 0xFD)) count = 1;
199 return count ? RES_ERROR : RES_OK;
208 DRESULT disk_ioctl(BYTE drv,
214 DWORD *dp, st, ed, csize;
216 if (drv)
return RES_PARERR;
217 if (stat & STA_NOINIT)
return RES_NOTRDY;
223 if (spiselect()) res = RES_OK;
226 case GET_SECTOR_COUNT:
227 if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
228 if ((csd[0] >> 6) == 1) {
230 csd[9] + ((WORD)csd[8] << 8) + ((DWORD)(csd[7] & 63) << 16) + 1;
231 *(DWORD *)buff = csize << 10;
233 n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) +
235 csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) +
236 ((WORD)(csd[6] & 3) << 10) + 1;
237 *(DWORD *)buff = csize << (n - 9);
244 if (CardType & CT_SD2) {
245 if (send_cmd(ACMD13, 0) == 0) {
247 if (rcvr_datablock(csd, 16)) {
248 for (n = 64 - 16; n; n--)
250 *(DWORD *)buff = 16UL << (csd[10] >> 4);
255 if ((send_cmd(CMD9, 0) == 0) &&
256 rcvr_datablock(csd, 16)) {
257 if (CardType & CT_SD1) {
259 (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1)
260 << ((csd[13] >> 6) - 1);
263 ((WORD)((csd[10] & 124) >> 2) + 1) *
264 (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1);
273 if (!(CardType & CT_SDC))
break;
274 if (disk_ioctl(drv, MMC_GET_CSD, csd))
break;
275 if (!(csd[0] >> 6) && !(csd[10] & 0x40))
280 if (!(CardType & CT_BLOCK)) {
284 if (send_cmd(CMD32, st) == 0 && send_cmd(CMD33, ed) == 0 &&
285 send_cmd(CMD38, 0) == 0 &&
303 volatile DSTATUS stat = STA_NOINIT;
305 SPIClass *p_spi = &SPI;
306 SPISettings spi_slow{280000, MSBFIRST, SPI_MODE0};
307 SPISettings spi_fast{FF_SPI_SPEED_FAST, MSBFIRST, SPI_MODE0};
308 SPISettings spi_settings;
309 uint32_t spi_timeout;
312 void spi_timer_on(uint32_t waitTicks) { spi_timeout = millis() + waitTicks; }
314 bool spi_timer_status() {
return (millis() < spi_timeout); }
317 void set_spi_fast(
bool fast) { spi_settings = fast ? spi_fast : spi_slow; }
321 if (cs != -1) digitalWrite(cs, high);
325 inline BYTE xchg_spi(BYTE dat) {
return p_spi->transfer(dat); }
328 void rcvr_spi_multi(BYTE *buff, UINT btr) {
330 for (UINT i = 0; i < btr; i++) {
331 buff[i] = xchg_spi(0xFF);
336 void xmit_spi_multi(BYTE *buff, UINT btr) {
337 p_spi->transfer(buff, btr);
347 uint32_t timeout = millis() + wt;
353 }
while (d != 0xFF && ((millis() < timeout)));
355 return (d == 0xFF) ? 1 : 0;
360 void despiselect(
void) {
361 p_spi->endTransaction();
370 p_spi->beginTransaction(spi_settings);
373 if (wait_ready(500))
return 1;
387 uint64_t end = millis() + 200;
389 token = xchg_spi(0xFF);
392 }
while ((token == 0xFF) && millis() < end);
396 rcvr_spi_multi(buff, btr);
412 if (!wait_ready(500))
return 0;
416 xmit_spi_multi(buff, 512);
420 resp = xchg_spi(0xFF);
421 if ((resp & 0x1F) != 0x05)
437 res = send_cmd(CMD55, 0);
438 if (res > 1)
return res;
444 if (!spiselect())
return 0xFF;
448 xchg_spi(0x40 | cmd);
449 xchg_spi((BYTE)(arg >> 24));
450 xchg_spi((BYTE)(arg >> 16));
451 xchg_spi((BYTE)(arg >> 8));
454 if (cmd == CMD0) n = 0x95;
455 if (cmd == CMD8) n = 0x87;
463 res = xchg_spi(0xFF);
464 }
while ((res & 0x80) && --n);