diff --git a/spi.go b/spi.go index 41015cc..1e40d01 100644 --- a/spi.go +++ b/spi.go @@ -1,15 +1,12 @@ +// SPI functionality is implemented here package rpio import ( "errors" ) -var ( - SpiMapError = errors.New("SPI registers not mapped correctly - are you root?") -) - const ( - SPI0 = iota // only spi0 supported for now + SPI0 = iota // only SPI0 supported for now SPI1 // aux SPI2 // aux ) @@ -20,9 +17,13 @@ const ( clkDivReg = 2 ) -// Sets SPI pins of given device to SIP mode -// (CE0, CE1, [CE2], SCLK, MOSI, MISO) -// also reset SPI control register +var ( + SpiMapError = errors.New("SPI registers not mapped correctly - are you root?") +) + +// Sets SPI pins of given device to SPI mode +// (CE0, CE1, [CE2], SCLK, MOSI, MISO). +// It also resets SPI control register. func SpiBegin(dev int) error { spiMem[csReg] = 0 // reset spi settings to default if spiMem[csReg] == 0 { @@ -39,7 +40,7 @@ func SpiBegin(dev int) error { return nil } -// Sets SPI pins of given device to default (Input) mode +// Sets SPI pins of given device to default (Input) mode. func SpiEnd(dev int) { var pins = getSpiPins(dev) for _, pin := range pins { @@ -47,7 +48,7 @@ func SpiEnd(dev int) { } } -// Set (maximal) speed [Hz] of SPI clock +// Set (maximal) speed [Hz] of SPI clock. // Param speed may be as big as 125MHz in theory, but // only values up to 31.25MHz are considered relayable. func SpiSpeed(speed int) { @@ -57,8 +58,8 @@ func SpiSpeed(speed int) { } // Select chip, one of 0, 1, 2 -// for selecting slave on CE0, CE1, or CE2 -func SpiChipSelect(chip int) { // control & status +// for selecting slave on CE0, CE1, or CE2 pin +func SpiChipSelect(chip int) { const csMask = 3 // chip select has 2 bits cs := uint32(chip & csMask) @@ -66,32 +67,50 @@ func SpiChipSelect(chip int) { // control & status spiMem[csReg] = spiMem[csReg]&^csMask | cs } +// SpiTransmit takes one or more bytes and send them to slave. +// +// Data received from slave are ignored. +// Use spread operator to send slice of bytes. +func SpiTransmit(data ...byte) { + SpiExchange(append(data[:0:0], data...)) // clone data because it will be rewriten by received bytes +} + +// SpiReceive receives n bytes from slave. +// +// Note that n zeroed bytes are send to slave as side effect. +func SpiReceive(n int) []byte { + data := make([]byte, n, n) + SpiExchange(data) + return data +} + // Transmit all bytes in data to slave -// and simultaneously receives bytes from slave to data -func SpiTransfer(data []byte) { // control & status +// and simultaneously receives bytes from slave to data. +// +// If you want to only send or only receive, use SpiTransmit/SpiReceive +func SpiExchange(data []byte) { const ta = 1 << 7 // transfer active const txd = 1 << 18 // tx fifo can accept data const rxd = 1 << 17 // rx fifo contains data const done = 1 << 16 - length := len(data) - i := 0 // data index - clearSpiTxRxFifo() // set TA = 1 spiMem[csReg] |= ta - for i < length { - // Poll TXD writing bytes to SPI_FIFO + for i := range data { + // wait for TXD for spiMem[csReg]&txd == 0 { } + // write bytes to SPI_FIFO spiMem[fifoReg] = uint32(data[i]) - // Poll RXD reading bytes from SPI_FIFO + + // wait for RXD for spiMem[csReg]&rxd == 0 { } + // read bytes from SPI_FIFO data[i] = byte(spiMem[fifoReg]) - i++ } // wait for DONE @@ -102,32 +121,27 @@ func SpiTransfer(data []byte) { // control & status spiMem[csReg] &^= ta } -func setSpiDiv(div uint32) { - const divMask = 1<<16 - 1 - 1 // cdiv have 16 bits and must be odd (for some reason) +// set spi clock divider value +func setSpiDiv(cdiv uint32) { + const cdivMask = 1<<16 - 1 - 1 // cdiv have 16 bits and must be odd (for some reason) spiMem[clkDivReg] = div & divMask } +// clear both FIFOs func clearSpiTxRxFifo() { const clearTxRx = 1<<5 | 1<<4 - spiMem[csReg] |= clearTxRx } func getSpiPins(dev int) []Pin { switch dev { case SPI0: - return []Pin{ - 7, 8, 9, 10, 11, - // 35, 36, 37, 38, 39, // only one set of SPI0 can be set in Spi mode at a time - } + return []Pin{7, 8, 9, 10, 11} + // ommit 35, 36, 37, 38, 39 - only one set of SPI0 can be set in Spi mode at a time case SPI1: - return []Pin{ - 16, 17, 18, 19, 20, 21, - } + return []Pin{16, 17, 18, 19, 20, 21} case SPI2: - return []Pin{ - 40, 41, 42, 43, 44, 45, - } + return []Pin{40, 41, 42, 43, 44, 45} default: return []Pin{} } diff --git a/spi_test.go b/spi_test.go new file mode 100644 index 0000000..8348011 --- /dev/null +++ b/spi_test.go @@ -0,0 +1,16 @@ +package rpio + +import () + +func Example_SPI() { + SpiBegin(SPI0) // BCM pins 7 to 11 + + SpiSpeed(144000) // 144kHz + SpiChipSelect(1) // CE1 + + SpiTransmit(0xFF) + SpiTransmit(0xDE, 0xAD) + SpiTransmit(data...) + + SpiEnd(SPI0) +}