CHGame 0.3.0
Libraries for the CHGame handheld
Loading...
Searching...
No Matches
SdSpi.h
Go to the documentation of this file.
1// SdSpi - a read-only SPI-mode microSD block driver (CHSd, MIT: see NOTICE).
2
3/// @file
4/// @brief The SD card's blocks: identify the card, read one 512-byte block
5/// or stream a run of them.
6
7/// @defgroup chsd_sd SD card blocks
8/// @ingroup lib_chsd
9/// @brief A read-only SPI-mode microSD block driver: `sd::init()`,
10/// `sd::read()` and `sd::stream()`.
11///
12/// HypeRunner's clean-room driver cut down to what reading a game's data
13/// file needs: identify the card, read one 512-byte block. No writing, no
14/// CRC (the games' files check their own blocks or records), and DMA only
15/// in `stream()`, for a sketch that reads whole files every frame. Most
16/// sketches never call these directly: @ref chsd_fat "fat::open()" and
17/// `fat::read()` do it for them.
18///
19/// The card is a block device addressed by LBA (512-byte block number)
20/// whatever its size: SDSC, SDHC and SDXC cards all work.
21///
22/// @warning **Bus rule.** SPI1 is shared with the LCD. Call these only after
23/// `gfx_wait()`, before the next flush. SPI1 is handed back exactly as
24/// CHGfx left it.
25///
26/// @note After a read fails, call `sd::init()` before reading again: a
27/// block whose token came late may still be on its way, and `init()`'s CMD0
28/// is what clears it.
29/// @{
30#pragma once
31#include <stdint.h>
32
33/// @brief The SD card's SPI-mode block driver (CHSd).
34namespace sd {
35
36/// @brief Wakes the card and identifies it (SD v1, SDSC v2, SDHC/SDXC).
37///
38/// Runs at 187.5 kHz with the card's CS (PB11) low, then sets 12 MHz for
39/// `read()`. Takes up to about a second with a card that is slow to come
40/// ready; with no card it fails in about 15 ms (MISO is pulled up, so an
41/// empty slot reads 0xFF). Call it again after any failed read, or after
42/// the card may have been swapped.
43/// @return `true` if a card answered and is ready; `false`: no card, or not
44/// one this can read.
45bool init(); // false: no card, or not one this can read
46
47/// @brief Reads one 512-byte block (CMD17), polled at 12 MHz.
48///
49/// About 0.5 ms of bytes plus the card's own access time (0.1-1 ms, up to
50/// ~0.8 s for a block's first read after power-up); ~1.5 ms in all is
51/// typical. The block's CRC is not checked.
52/// @param lba the block number on the card (0 = the card's first block,
53/// whatever the card type).
54/// @param dst where the 512 bytes go.
55/// @return `true` if the block arrived; `false`: the card did not deliver
56/// (call `init()` before the next read).
57bool read(uint32_t lba, uint8_t *dst); // one block; false: the card did not deliver
58
59/// @brief What `stream()` calls with each block, in order.
60///
61/// It runs while the next block arrives by DMA, so it must keep off SPI1
62/// and off the other of `stream()`'s two buffers, and must not read the
63/// card.
64/// @param block the block's 512 bytes (in `buf0` or `buf1`), valid until
65/// the callback returns.
66/// @param ctx the `ctx` given to `stream()`.
67typedef void (*BlockFn)(const uint8_t *block, void *ctx);
68
69/// @brief Reads `n` consecutive blocks with one multi-block read (CMD18),
70/// handing each to `fn` while the next one arrives.
71///
72/// For a sketch that reads a file over and over (CHStlView reads a whole
73/// model every frame). The blocks come at 24 MHz by DMA into `buf0` and
74/// `buf1` in turn while `fn(block, ctx)` works on the one before; `fn`
75/// gets each block once, in order. Costs about 0.6 ms of card latency per
76/// call plus 0.17 ms per block, against ~1.5 ms per block for `read()`.
77/// No CRC is checked (a block garbled on the wire reaches `fn` as it
78/// came). DMA1 channels 2 and 3 are borrowed and left off: CHGfx sets
79/// channel 3 up afresh for every flush. The games never call it, so it is
80/// not in their images.
81/// @param lba the first block's number on the card.
82/// @param n how many blocks to read; 0 does nothing and returns `true`.
83/// @param buf0 a 512-byte buffer for the even blocks (0, 2, 4 ...).
84/// @param buf1 a 512-byte buffer for the odd blocks; not the same as
85/// `buf0`.
86/// @param fn called once per block, in order (see @ref BlockFn).
87/// @param ctx passed to `fn` unchanged; may be `nullptr`.
88/// @return `true` if every block was delivered; `false`: the card stopped
89/// delivering (call `init()` before the next read). Some of the
90/// blocks may have reached `fn` before the failure.
91bool stream(uint32_t lba, uint32_t n, uint8_t *buf0, uint8_t *buf1, BlockFn fn, void *ctx);
92
93} // namespace sd
94
95/// @}
The SD card's SPI-mode block driver (CHSd).
Definition SdSpi.h:34
bool init()
Wakes the card and identifies it (SD v1, SDSC v2, SDHC/SDXC).
bool read(uint32_t lba, uint8_t *dst)
Reads one 512-byte block (CMD17), polled at 12 MHz.
bool stream(uint32_t lba, uint32_t n, uint8_t *buf0, uint8_t *buf1, BlockFn fn, void *ctx)
Reads n consecutive blocks with one multi-block read (CMD18), handing each to fn while the next one a...
void(* BlockFn)(const uint8_t *block, void *ctx)
What stream() calls with each block, in order.
Definition SdSpi.h:67