29
29
Requires an SPI bus and a CS pin. Provides readblocks and writeblocks
30
30
methods so the device can be mounted as a filesystem.
31
31
32
- Example usage:
32
+ * Author(s): Scott Shawcroft
33
33
34
- .. code-block:: python
34
+ Implementation Notes
35
+ --------------------
35
36
36
- import busio
37
- import storage
38
- import adafruit_sdcard
39
- import os
40
- import board
37
+ **Hardware:**
41
38
42
- spi = busio.SPI(SCK, MOSI, MISO)
43
- sd = adafruit_sdcard.SDCard(spi, board.SD_CS)
44
- vfs = storage.VfsFat(sdcard)
45
- storage.mount(vfs, '/sd')
46
- os.listdir('/')
39
+ * Adafruit `MicroSD card breakout board+
40
+ <https://www.adafruit.com/product/254>`_ (Product ID: 254)
47
41
48
- * Author(s): Scott Shawcroft
42
+ * Adafruit `Assembled Data Logging shield for Arduino
43
+ <https://www.adafruit.com/product/1141>`_ (Product ID: 1141)
44
+
45
+ * Adafruit `Feather M0 Adalogger
46
+ <https://www.adafruit.com/product/2796>`_ (Product ID: 2796)
47
+
48
+ * Adalogger `FeatherWing - RTC + SD Add-on For All Feather Boards
49
+ <https://www.adafruit.com/product/2922>`_ (Product ID: 2922)
50
+
51
+ **Software and Dependencies:**
52
+
53
+ * Adafruit CircuitPython firmware for the ESP8622 and M0-based boards:
54
+ https://github.com/adafruit/circuitpython/releases
55
+ * Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
49
56
"""
50
57
51
58
import time
@@ -73,7 +80,25 @@ class SDCard:
73
80
"""Controls an SD card over SPI.
74
81
75
82
:param ~busio.SPI spi: The SPI bus
76
- :param ~digitalio.DigitalInOut cs: The chip select connected to the card"""
83
+ :param ~digitalio.DigitalInOut cs: The chip select connected to the card
84
+
85
+ Example usage:
86
+
87
+ .. code-block:: python
88
+
89
+ import busio
90
+ import storage
91
+ import adafruit_sdcard
92
+ import os
93
+ import board
94
+
95
+ spi = busio.SPI(SCK, MOSI, MISO)
96
+ sd = adafruit_sdcard.SDCard(spi, board.SD_CS)
97
+ vfs = storage.VfsFat(sdcard)
98
+ storage.mount(vfs, '/sd')
99
+ os.listdir('/')
100
+
101
+ """
77
102
def __init__ (self , spi , cs ):
78
103
# This is the init baudrate. We create a second device for high speed.
79
104
self ._spi = spi_device .SPIDevice (spi , cs , baudrate = 250000 , extra_clocks = 8 )
@@ -88,9 +113,10 @@ def __init__(self, spi, cs):
88
113
self ._init_card ()
89
114
90
115
def _clock_card (self , cycles = 8 ):
91
- """Clock the bus a minimum of `cycles` with the chip select high.
116
+ """
117
+ Clock the bus a minimum of `cycles` with the chip select high.
92
118
93
- :param int cycles: The minimum number of clock cycles to cycle the bus.
119
+ :param int cycles: The minimum number of clock cycles to cycle the bus.
94
120
"""
95
121
while not self ._spi .spi .try_lock ():
96
122
pass
@@ -177,24 +203,28 @@ def _init_card_v2(self):
177
203
raise OSError ("timeout waiting for v2 card" )
178
204
179
205
def _wait_for_ready (self , spi , timeout = 0.3 ):
180
- """Wait for the card to clock out 0xff to indicate its ready.
206
+ """
207
+ Wait for the card to clock out 0xff to indicate its ready.
181
208
182
- :param busio.SPI spi: The locked SPI bus.
183
- :param float timeout: Maximum time to wait in seconds."""
209
+ :param busio.SPI spi: The locked SPI bus.
210
+ :param float timeout: Maximum time to wait in seconds.
211
+ """
184
212
start_time = time .monotonic ()
185
213
self ._single_byte [0 ] = 0x00
186
214
while time .monotonic () - start_time < timeout and self ._single_byte [0 ] != 0xff :
187
215
spi .readinto (self ._single_byte , write_value = 0xff )
188
216
189
217
#pylint: disable-msg=too-many-arguments
190
218
def _cmd (self , cmd , arg = 0 , crc = 0 , response_buf = None , data_block = True , wait = True ):
191
- """Issue a command to the card and read an optional data response.
219
+ """
220
+ Issue a command to the card and read an optional data response.
192
221
193
- :param int cmd: The command number.
194
- :param int arg: The command argument.
195
- :param int crc: The crc to allow the card to verify the command and argument.
196
- :param bytearray response_buf: Buffer to read a data block response into.
197
- :param bool data_block: True if the response data is in a data block."""
222
+ :param int cmd: The command number.
223
+ :param int arg: The command argument.
224
+ :param int crc: The crc to allow the card to verify the command and argument.
225
+ :param bytearray response_buf: Buffer to read a data block response into.
226
+ :param bool data_block: True if the response data is in a data block.
227
+ """
198
228
# create and send the command
199
229
buf = self ._cmdbuf
200
230
buf [0 ] = 0x40 | cmd
@@ -229,11 +259,13 @@ def _cmd(self, cmd, arg=0, crc=0, response_buf=None, data_block=True, wait=True)
229
259
#pylint: enable-msg=too-many-arguments
230
260
231
261
def _block_cmd (self , cmd , block , crc , response_buf = None ):
232
- """Issue a command to the card with a block argument.
262
+ """
263
+ Issue a command to the card with a block argument.
233
264
234
- :param int cmd: The command number.
235
- :param int block: The relevant block.
236
- :param int crc: The crc to allow the card to verify the command and argument."""
265
+ :param int cmd: The command number.
266
+ :param int block: The relevant block.
267
+ :param int crc: The crc to allow the card to verify the command and argument.
268
+ """
237
269
if self ._cdv == 1 :
238
270
return self ._cmd (cmd , block , crc , response_buf = response_buf )
239
271
@@ -268,9 +300,11 @@ def _block_cmd(self, cmd, block, crc, response_buf=None):
268
300
return result
269
301
270
302
def _cmd_nodata (self , cmd , response = 0xff ):
271
- """Issue a command to the card with no argument.
303
+ """
304
+ Issue a command to the card with no argument.
272
305
273
- :param int cmd: The command number."""
306
+ :param int cmd: The command number.
307
+ """
274
308
buf = self ._cmdbuf
275
309
buf [0 ] = cmd
276
310
buf [1 ] = 0xff
@@ -284,11 +318,13 @@ def _cmd_nodata(self, cmd, response=0xff):
284
318
return 1 # timeout
285
319
286
320
def _readinto (self , buf , start = 0 , end = None ):
287
- """Read a data block into buf.
321
+ """
322
+ Read a data block into buf.
288
323
289
- :param bytearray buf: The buffer to write into
290
- :param int start: The first index to write data at
291
- :param int end: The index after the last byte to write to"""
324
+ :param bytearray buf: The buffer to write into
325
+ :param int start: The first index to write data at
326
+ :param int end: The index after the last byte to write to.
327
+ """
292
328
if end is None :
293
329
end = len (buf )
294
330
with self ._spi as spi :
@@ -303,12 +339,14 @@ def _readinto(self, buf, start=0, end=None):
303
339
spi .readinto (self ._cmdbuf , end = 2 , write_value = 0xff )
304
340
305
341
def _write (self , token , buf , start = 0 , end = None ):
306
- """Write a data block to the card.
342
+ """
343
+ Write a data block to the card.
307
344
308
- :param int token: The start token
309
- :param bytearray buf: The buffer to write from
310
- :param int start: The first index to read data from
311
- :param int end: The index after the last byte to read from"""
345
+ :param int token: The start token
346
+ :param bytearray buf: The buffer to write from
347
+ :param int start: The first index to read data from
348
+ :param int end: The index after the last byte to read from.
349
+ """
312
350
cmd = self ._cmdbuf
313
351
if end is None :
314
352
end = len (buf )
@@ -340,17 +378,21 @@ def _write(self, token, buf, start=0, end=None):
340
378
return 0 # worked
341
379
342
380
def count (self ):
343
- """Returns the total number of sectors.
381
+ """
382
+ Returns the total number of sectors.
344
383
345
- :return: The number of 512-byte blocks
346
- :rtype: int"""
384
+ :return: The number of 512-byte blocks
385
+ :rtype: int
386
+ """
347
387
return self ._sectors
348
388
349
389
def readblocks (self , start_block , buf ):
350
- """Read one or more blocks from the card
390
+ """
391
+ Read one or more blocks from the card
351
392
352
- :param int start_block: The block to start reading from
353
- :param bytearray buf: The buffer to write into. Length must be multiple of 512."""
393
+ :param int start_block: The block to start reading from
394
+ :param bytearray buf: The buffer to write into. Length must be multiple of 512.
395
+ """
354
396
nblocks , err = divmod (len (buf ), 512 )
355
397
assert nblocks and not err , 'Buffer length is invalid'
356
398
if nblocks == 1 :
@@ -372,10 +414,12 @@ def readblocks(self, start_block, buf):
372
414
return 0
373
415
374
416
def writeblocks (self , start_block , buf ):
375
- """Write one or more blocks to the card
417
+ """
418
+ Write one or more blocks to the card
376
419
377
- :param int start_block: The block to start writing to
378
- :param bytearray buf: The buffer to write into. Length must be multiple of 512."""
420
+ :param int start_block: The block to start writing to
421
+ :param bytearray buf: The buffer to write into. Length must be multiple of 512.
422
+ """
379
423
nblocks , err = divmod (len (buf ), 512 )
380
424
assert nblocks and not err , 'Buffer length is invalid'
381
425
if nblocks == 1 :
0 commit comments