| 39 | |
| 40 | |
| 41 | class SDCard: |
| 42 | def __init__(self, spi, cs, baudrate=1320000): |
| 43 | self.spi = spi |
| 44 | self.cs = cs |
| 45 | |
| 46 | self.cmdbuf = bytearray(6) |
| 47 | self.dummybuf = bytearray(512) |
| 48 | self.tokenbuf = bytearray(1) |
| 49 | for i in range(512): |
| 50 | self.dummybuf[i] = 0xFF |
| 51 | self.dummybuf_memoryview = memoryview(self.dummybuf) |
| 52 | |
| 53 | # initialise the card |
| 54 | self.init_card(baudrate) |
| 55 | |
| 56 | def init_spi(self, baudrate): |
| 57 | try: |
| 58 | master = self.spi.MASTER |
| 59 | except AttributeError: |
| 60 | # on ESP8266 |
| 61 | self.spi.init(baudrate=baudrate, phase=0, polarity=0) |
| 62 | else: |
| 63 | # on pyboard |
| 64 | self.spi.init(master, baudrate=baudrate, phase=0, polarity=0) |
| 65 | |
| 66 | def init_card(self, baudrate): |
| 67 | |
| 68 | # init CS pin |
| 69 | self.cs.init(self.cs.OUT, value=1) |
| 70 | |
| 71 | # init SPI bus; use low data rate for initialisation |
| 72 | self.init_spi(100000) |
| 73 | |
| 74 | # clock card at least 100 cycles with cs high |
| 75 | for i in range(16): |
| 76 | self.spi.write(b"\xff") |
| 77 | |
| 78 | # CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts) |
| 79 | for _ in range(5): |
| 80 | if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE: |
| 81 | break |
| 82 | else: |
| 83 | raise OSError("no SD card") |
| 84 | |
| 85 | # CMD8: determine card version |
| 86 | r = self.cmd(8, 0x01AA, 0x87, 4) |
| 87 | if r == _R1_IDLE_STATE: |
| 88 | self.init_card_v2() |
| 89 | elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND): |
| 90 | self.init_card_v1() |
| 91 | else: |
| 92 | raise OSError("couldn't determine SD card version") |
| 93 | |
| 94 | # get the number of sectors |
| 95 | # CMD9: response R2 (R1 byte + 16-byte block read) |
| 96 | if self.cmd(9, 0, 0, 0, False) != 0: |
| 97 | raise OSError("no response from SD card") |
| 98 | csd = bytearray(16) |