@@ -81,6 +81,7 @@ class SDCard:
81
81
82
82
:param ~busio.SPI spi: The SPI bus
83
83
:param ~digitalio.DigitalInOut cs: The chip select connected to the card
84
+ :param int baudrate: The SPI data rate to use after card setup
84
85
85
86
Example usage:
86
87
@@ -99,8 +100,9 @@ class SDCard:
99
100
os.listdir('/')
100
101
101
102
"""
102
- def __init__ (self , spi , cs ):
103
- # This is the init baudrate. We create a second device for high speed.
103
+ def __init__ (self , spi , cs , baudrate = 1320000 ):
104
+ # This is the init baudrate.
105
+ # We create a second device with the target baudrate after card initialization.
104
106
self ._spi = spi_device .SPIDevice (spi , cs , baudrate = 250000 , extra_clocks = 8 )
105
107
106
108
self ._cmdbuf = bytearray (6 )
@@ -109,8 +111,8 @@ def __init__(self, spi, cs):
109
111
# Card is byte addressing, set to 1 if addresses are per block
110
112
self ._cdv = 512
111
113
112
- # initialise the card
113
- self ._init_card ()
114
+ # initialise the card and switch to high speed
115
+ self ._init_card (baudrate )
114
116
115
117
def _clock_card (self , cycles = 8 ):
116
118
"""
@@ -128,7 +130,7 @@ def _clock_card(self, cycles=8):
128
130
self ._spi .spi .write (self ._single_byte )
129
131
self ._spi .spi .unlock ()
130
132
131
- def _init_card (self ):
133
+ def _init_card (self , baudrate ):
132
134
"""Initialize the card in SPI mode."""
133
135
# clock card at least cycles with cs high
134
136
self ._clock_card (80 )
@@ -174,7 +176,7 @@ def _init_card(self):
174
176
175
177
# set to high data rate now that it's initialised
176
178
self ._spi = spi_device .SPIDevice (self ._spi .spi , self ._spi .chip_select ,
177
- baudrate = 1320000 , extra_clocks = 8 )
179
+ baudrate = baudrate , extra_clocks = 8 )
178
180
179
181
def _init_card_v1 (self ):
180
182
"""Initialize v1 SDCards which use byte addressing."""
@@ -253,6 +255,7 @@ def _cmd(self, cmd, arg=0, crc=0, response_buf=None, data_block=True, wait=True)
253
255
if response_buf :
254
256
if data_block :
255
257
# Wait for the start block byte
258
+ buf [1 ] = 0xff
256
259
while buf [1 ] != 0xfe :
257
260
spi .readinto (buf , start = 1 , end = 2 , write_value = 0xff )
258
261
spi .readinto (response_buf , write_value = 0xff )
@@ -456,17 +459,13 @@ def writeblocks(self, start_block, buf):
456
459
self ._cmd_nodata (_TOKEN_STOP_TRAN , 0x0 )
457
460
return 0
458
461
459
- def calculate_crc (message ):
460
- """
461
- Calculate the CRC of a message.
462
- :param bytearray message: Where each index is a byte
463
- """
462
+ def _calculate_crc_table ():
463
+ """Precompute the table used in calculate_crc."""
464
464
# Code converted from https://github.com/hazelnusse/crc7/blob/master/crc7.cc by devoh747
465
465
# With permission from Dale Lukas Peterson <[email protected] >
466
466
# 8/6/2019
467
467
468
468
crc_table = bytearray (256 )
469
-
470
469
crc_poly = const (0x89 ) # the value of our CRC-7 polynomial
471
470
472
471
# generate a table value for all 256 possible byte values
@@ -479,10 +478,19 @@ def calculate_crc(message):
479
478
crc_table [i ] = crc_table [i ] << 1
480
479
if (crc_table [i ] & 0x80 ):
481
480
crc_table [i ] = crc_table [i ] ^ crc_poly
481
+ return crc_table
482
+
483
+ CRC_TABLE = _calculate_crc_table ()
484
+
485
+ def calculate_crc (message ):
486
+ """
487
+ Calculate the CRC of message[0:5], using a precomputed table in CRC_TABLE.
488
+ :param bytearray message: Where each index is a byte
489
+ """
482
490
483
491
crc = 0
484
492
# All messages in _cmd are 5 bytes including the cmd.. The 6th byte is the crc value.
485
493
for i in range (0 , 5 ):
486
- crc = crc_table [(crc << 1 ) ^ message [i ]]
494
+ crc = CRC_TABLE [(crc << 1 ) ^ message [i ]]
487
495
488
496
return ((crc << 1 ) | 1 )
0 commit comments