3030import time
3131import uctypes
3232from errno import ETIMEDOUT , EIO , ENODEV , EINVAL
33- from crc7 import crc7
33+
34+ crc7_be_syndrome_table = (
35+ b"\x00 \x12 $6HZl~\x90 \x82 \xb4 \xa6 \xd8 \xca \xfc \xee 2 \x16 \x04 zh^L\xa2 \xb0 \x86 \x94 \xea \xf8 "
36+ b"\xce \xdc dv@R,>\x08 \x1a \xf4 \xe6 \xd0 \xc2 \xbc \xae \x98 \x8a VDr`\x1e \x0c :(\xc6 \xd4 \xe2 \xf0 "
37+ b"\x8e \x9c \xaa \xb8 \xc8 \xda \xec \xfe \x80 \x92 \xa4 \xb6 XJ|n\x10 \x02 4&\xfa \xe8 \xde \xcc \xb2 \xa0 "
38+ b'\x96 \x84 jxN\\ "0\x06 \x14 \xac \xbe \x88 \x9a \xe4 \xf6 \xc0 \xd2 <.\x18 \n tfPB\x9e \x8c \xba \xa8 '
39+ b"\xd6 \xc4 \xf2 \xe0 \x0e \x1c *8FTbp\x82 \x90 \xa6 \xb4 \xca \xd8 \xee \xfc \x12 \x00 6$ZH~l\xb0 \xa2 "
40+ b"\x94 \x86 \xf8 \xea \xdc \xce 2\x04 \x16 hzL^\xe6 \xf4 \xc2 \xd0 \xae \xbc \x8a \x98 vdR@>,\x1a \x08 "
41+ b"\xd4 \xc6 \xf0 \xe2 \x9c \x8e \xb8 \xaa DV`r\x0c \x1e (:JXn|\x02 \x10 &4\xda \xc8 \xfe \xec \x92 \x80 "
42+ b'\xb6 \xa4 xj\\ N0"\x14 \x06 \xe8 \xfa \xcc \xde \xa0 \xb2 \x84 \x96 .<\n \x18 ftBP\xbe \xac \x9a \x88 \xf6 '
43+ b"\xe4 \xd2 \xc0 \x1c \x0e 8*TFpb\x8c \x9e \xa8 \xba \xc4 \xd6 \xe0 \xf2 "
44+ )
45+
46+ # ruff: noqa: F821 - @asm_thumb and @viper decorator adds names to function scope
47+ try :
48+ from uctypes import addressof
49+
50+ @micropython .viper
51+ def crc7 (buf ) -> int :
52+ n = int (len (buf ))
53+ table = ptr8 (addressof (crc7_be_syndrome_table ))
54+ bp = ptr8 (addressof (buf ))
55+ idx = 0
56+ crc = 0
57+ while idx < n :
58+ crc = table [crc ^ bp [idx ]]
59+ idx = idx + 1
60+ return crc
61+
62+ # test to make sure this works!
63+ # print(f"{crc7('abcde'):02x}")
64+ assert crc7 (b"abcde" ) == 0x34
65+ except :
66+ # non-viper version if viper can'r be built
67+ def crc7 (buf ) -> int :
68+ crc = 0
69+ for b in buf :
70+ crc = crc7_be_syndrome_table [crc ^ b ]
71+ return crc
72+
73+
74+ def gb (bigval , b0 , bn ):
75+ # get numbered bits from a buf_to_int from, for example, the CSD
76+ return (bigval >> b0 ) & ((1 << (1 + bn - b0 )) - 1 )
77+
3478
3579_CMD_TIMEOUT = const (50 )
3680
@@ -64,8 +108,9 @@ def __init__(self, spi, cs, baudrate=1320000, crc16_function=None):
64108 def check_crcs (self , crc16_function ):
65109 self .crc16 = crc16_function
66110 result = self .cmd (
67- 59 , 1 if crc16_function else 0 , None , release = True
111+ 59 , 1 if crc16_function else 0 , release = True
68112 ) # send CRC enable/disable command
113+ return result
69114
70115 def init_spi (self , baudrate ):
71116 try :
@@ -77,12 +122,7 @@ def init_spi(self, baudrate):
77122 # on pyboard
78123 self .spi .init (master , baudrate = baudrate , phase = 0 , polarity = 0 )
79124
80- @staticmethod
81- def gb (bigval , b0 , bn ):
82- # get numbered bits from a buf_to_int from, for example, the CSD
83- return (bigval >> b0 ) & ((1 << (1 + bn - b0 )) - 1 )
84-
85- def spiff (self ):
125+ def _spiff (self ):
86126 self .spi .write (b"\xff " )
87127
88128 def init_card (self , baudrate ):
@@ -104,40 +144,40 @@ def init_card(self, baudrate):
104144 raise OSError (ENODEV , "no SD card" )
105145
106146 # CMD8: determine card version
107- r = self .cmd (8 , 0x01AA , 0x87 , 4 ) # probe version
147+ r = self .cmd (8 , 0x01AA , 4 ) # probe version
108148 v2 = r == _R1_IDLE_STATE
109149 v1 = r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND )
110150
111151 if not (v1 or v2 ):
112152 raise OSError (EIO , "couldn't determine SD card version" )
113153 arg41 = _HCS_BIT if v2 else 0 # we support high capacity, on v2 cards
114154 for i in range (_CMD_TIMEOUT ): # loop on acmd41 to get
115- self .cmd (55 , 0 , None )
116- if (r := self .cmd (41 , arg41 , None )) == 0 :
155+ self .cmd (55 , 0 )
156+ if (r := self .cmd (41 , arg41 )) == 0 :
117157 break
118158 time .sleep_ms (5 )
119159 if r != 0 :
120160 raise OSError (ETIMEDOUT , "card type" , "v2" if v2 else "v1" )
121161
122162 # get the number of sectors
123163 # CMD9: response R2 (R1 byte + 16-byte block read)
124- if self .cmd (9 , 0 , None , 0 , False ) != 0 :
164+ if self .cmd (9 , 0 , 0 , False ) != 0 :
125165 raise OSError (EIO , "no CSD response" )
126166 csd = bytearray (16 )
127167 self .readinto (csd )
128168 self .CSD = csd_int = int .from_bytes (
129169 csd , "big"
130170 ) # convert 16-byte CSD to a giant integer for bit extraction
131- gb = self . gb # just for shorter code
171+ _gb = gb # just for local binding
132172 # use bit numbers from SD card spec v9.0.0, table 5.3.2
133- vers = gb (csd_int , 126 , 127 )
173+ vers = _gb (csd_int , 126 , 127 )
134174 if vers == 1 : # CSD version 2.0
135- self .sectors = (gb (csd_int , 48 , 69 ) + 1 ) * 1024
175+ self .sectors = (_gb (csd_int , 48 , 69 ) + 1 ) * 1024
136176 self .cdv = 1
137177 elif vers == 0x00 : # CSD version 1.0 (old, <=2GB)
138- c_size = gb (csd_int , 62 , 73 )
139- c_size_mult = gb (csd_int , 47 , 49 )
140- read_bl_len = gb (csd_int , 80 , 83 )
178+ c_size = _gb (csd_int , 62 , 73 )
179+ c_size_mult = _gb (csd_int , 47 , 49 )
180+ read_bl_len = _gb (csd_int , 80 , 83 )
141181 capacity = (c_size + 1 ) * (2 ** (c_size_mult + 2 )) * (2 ** read_bl_len )
142182 self .sectors = capacity // 512
143183 self .cdv = 512 # converts bytes to sectors
@@ -146,18 +186,18 @@ def init_card(self, baudrate):
146186 # print('sectors', self.sectors)
147187
148188 # CMD16: set block length to 512 bytes
149- if self .cmd (16 , 512 , None ) != 0 :
189+ if self .cmd (16 , 512 ) != 0 :
150190 raise OSError (EIO , "can't set 512 block size" )
151191
152192 # set to high data rate now that it's initialised
153193 self .init_spi (baudrate )
154194
155- def cmd (self , cmd , arg , crc , final = 0 , release = True , skip1 = False ):
195+ def cmd (self , cmd , arg , final = 0 , release = True , skip1 = False ):
156196 cs = self .cs # prebind
157197 w = self .spi .write
158198 r = self .spi .readinto
159199 tb = self .tokenbuf
160- spiff = self .spiff
200+ spiff = self ._spiff
161201
162202 cs (0 ) # select chip
163203
@@ -168,7 +208,7 @@ def cmd(self, cmd, arg, crc, final=0, release=True, skip1=False):
168208 buf [2 ] = arg >> 16
169209 buf [3 ] = arg >> 8
170210 buf [4 ] = arg
171- buf [5 ] = ( crc if crc is not None else crc7 (self .cmdbuf5 ) ) | 1
211+ buf [5 ] = crc7 (self .cmdbuf5 ) | 1
172212 w (buf )
173213
174214 if skip1 :
@@ -207,7 +247,7 @@ def cmd(self, cmd, arg, crc, final=0, release=True, skip1=False):
207247
208248 def readinto (self , buf ):
209249 cs = self .cs
210- spiff = self .spiff
250+ spiff = self ._spiff
211251
212252 cs (0 )
213253
@@ -237,7 +277,7 @@ def readinto(self, buf):
237277
238278 def write (self , token , buf ):
239279 cs = self .cs
240- spiff = self .spiff
280+ spiff = self ._spiff
241281 r = self .spi .read
242282 w = self .spi .write
243283
@@ -269,13 +309,13 @@ def write(self, token, buf):
269309 def write_token (self , token ):
270310 self .cs (0 )
271311 self .spi .read (1 , token )
272- self .spiff ()
312+ self ._spiff ()
273313 # wait for write to finish
274314 while self .spi .read (1 , 0xFF )[0 ] == 0x00 :
275315 pass
276316
277317 self .cs (1 )
278- self .spiff ()
318+ self ._spiff ()
279319
280320 @staticmethod
281321 def blocks (buf ):
@@ -287,29 +327,29 @@ def blocks(buf):
287327 def readblocks (self , block_num , buf ):
288328 # workaround for shared bus, required for (at least) some Kingston
289329 # devices, ensure MOSI is high before starting transaction
290- self .spiff ()
330+ self ._spiff ()
291331 nblocks = self .blocks (buf )
292332
293333 # CMD18: set read address for multiple blocks
294- if self .cmd (18 , block_num * self .cdv , None , release = False ) != 0 :
334+ if self .cmd (18 , block_num * self .cdv , release = False ) != 0 :
295335 # release the card
296336 self .cs (1 )
297337 raise OSError (EIO ) # EIO
298338 mv = memoryview (buf )
299339 for offset in range (0 , nblocks * 512 , 512 ):
300340 self .readinto (mv [offset : offset + 512 ])
301341
302- if self .cmd (12 , 0 , None , skip1 = True ):
342+ if self .cmd (12 , 0 , skip1 = True ):
303343 raise OSError (EIO ) # EIO
304344
305345 def writeblocks (self , block_num , buf ):
306346 # workaround for shared bus, required for (at least) some Kingston
307347 # devices, ensure MOSI is high before starting transaction
308- self .spiff ()
348+ self ._spiff ()
309349 nblocks = self .blocks (buf )
310350
311351 # CMD25: set write address for first block
312- if ( r := self .cmd (25 , block_num * self .cdv , None ) ) != 0 :
352+ if self .cmd (25 , block_num * self .cdv ) != 0 :
313353 raise OSError (EIO ) # EIO`
314354 # send the data
315355 mv = memoryview (buf )
0 commit comments