Files
drivers/sd/card.go
T
2024-01-15 21:25:22 -03:00

103 lines
2.6 KiB
Go

package sd
import (
"errors"
"time"
"tinygo.org/x/drivers"
)
// See rustref.go for the new implementation.
var (
errBadCSDCID = errors.New("sd:bad CSD/CID in CRC or always1")
errNoSDCard = errors.New("sd:no card")
errCardNotSupported = errors.New("sd:card not supported")
errWaitStartBlock = errors.New("sd:did not find start block token")
errNeedBlockLenMultiple = errors.New("sd:need blocksize multiple for I/O")
errWrite = errors.New("sd:write")
errWriteTimeout = errors.New("sd:write timeout")
errReadTimeout = errors.New("sd:read timeout")
errBusyTimeout = errors.New("sd:busy card timeout")
errOOB = errors.New("sd:oob block access")
errNoblocks = errors.New("sd:no readable blocks")
)
type digitalPinout = func(b bool)
type SPICard struct {
bus drivers.SPI
cs digitalPinout
timers [2]timer
numblocks int64
timeout time.Duration
wait time.Duration
// Card Identification Register.
cid CID
// Card Specific Register.
csd CSD
bufcmd [6]byte
kind CardKind
// shift to calculate blocksize, taken from CSD.
blockshift uint8
lastCRC uint16
}
func NewSPICard(spi drivers.SPI, cs digitalPinout) *SPICard {
const defaultTimeout = 300 * time.Millisecond
s := &SPICard{
bus: spi,
cs: cs,
}
s.setTimeout(defaultTimeout)
return s
}
// setTimeout sets the timeout for all operations and the wait time between each yield during busy spins.
func (c *SPICard) setTimeout(timeout time.Duration) {
if timeout <= 0 {
panic("timeout must be positive")
}
c.timeout = timeout
c.wait = timeout / 512
}
func (c *SPICard) csEnable(b bool) {
c.cs(!b)
}
// LastReadCRC returns the CRC for the last ReadBlock operation.
func (c *SPICard) LastReadCRC() uint16 { return c.lastCRC }
// Init initializes the SD card. This routine should be performed with a SPI clock
// speed of around 100..400kHz. One may increase the clock speed after initialization.
func (d *SPICard) Init() error {
return d.initRs()
}
func (d *SPICard) NumberOfBlocks() int64 {
return d.numblocks
}
// CID returns a copy of the Card Identification Register value last read.
func (d *SPICard) CID() CID { return d.cid }
// CSD returns a copy of the Card Specific Data Register value last read.
func (d *SPICard) CSD() CSD { return d.csd }
func (d *SPICard) yield() { time.Sleep(d.wait) }
type timer struct {
deadline time.Time
}
func (t *timer) setTimeout(timeout time.Duration) *timer {
t.deadline = time.Now().Add(timeout)
return t
}
func (t timer) expired() bool {
return time.Since(t.deadline) >= 0
}