Define 3 SPI transfering functions, and other minor changes

This commit is contained in:
Drahoslav 2018-10-05 15:23:51 +02:00
parent 094a866c10
commit 7d2387e2cc
2 changed files with 64 additions and 34 deletions

82
spi.go
View File

@ -1,15 +1,12 @@
// SPI functionality is implemented here
package rpio package rpio
import ( import (
"errors" "errors"
) )
var (
SpiMapError = errors.New("SPI registers not mapped correctly - are you root?")
)
const ( const (
SPI0 = iota // only spi0 supported for now SPI0 = iota // only SPI0 supported for now
SPI1 // aux SPI1 // aux
SPI2 // aux SPI2 // aux
) )
@ -20,9 +17,13 @@ const (
clkDivReg = 2 clkDivReg = 2
) )
// Sets SPI pins of given device to SIP mode var (
// (CE0, CE1, [CE2], SCLK, MOSI, MISO) SpiMapError = errors.New("SPI registers not mapped correctly - are you root?")
// also reset SPI control register )
// 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 { func SpiBegin(dev int) error {
spiMem[csReg] = 0 // reset spi settings to default spiMem[csReg] = 0 // reset spi settings to default
if spiMem[csReg] == 0 { if spiMem[csReg] == 0 {
@ -39,7 +40,7 @@ func SpiBegin(dev int) error {
return nil 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) { func SpiEnd(dev int) {
var pins = getSpiPins(dev) var pins = getSpiPins(dev)
for _, pin := range pins { 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 // Param speed may be as big as 125MHz in theory, but
// only values up to 31.25MHz are considered relayable. // only values up to 31.25MHz are considered relayable.
func SpiSpeed(speed int) { func SpiSpeed(speed int) {
@ -57,8 +58,8 @@ func SpiSpeed(speed int) {
} }
// Select chip, one of 0, 1, 2 // Select chip, one of 0, 1, 2
// for selecting slave on CE0, CE1, or CE2 // for selecting slave on CE0, CE1, or CE2 pin
func SpiChipSelect(chip int) { // control & status func SpiChipSelect(chip int) {
const csMask = 3 // chip select has 2 bits const csMask = 3 // chip select has 2 bits
cs := uint32(chip & csMask) cs := uint32(chip & csMask)
@ -66,32 +67,50 @@ func SpiChipSelect(chip int) { // control & status
spiMem[csReg] = spiMem[csReg]&^csMask | cs 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 // Transmit all bytes in data to slave
// and simultaneously receives bytes from slave to data // and simultaneously receives bytes from slave to data.
func SpiTransfer(data []byte) { // control & status //
// If you want to only send or only receive, use SpiTransmit/SpiReceive
func SpiExchange(data []byte) {
const ta = 1 << 7 // transfer active const ta = 1 << 7 // transfer active
const txd = 1 << 18 // tx fifo can accept data const txd = 1 << 18 // tx fifo can accept data
const rxd = 1 << 17 // rx fifo contains data const rxd = 1 << 17 // rx fifo contains data
const done = 1 << 16 const done = 1 << 16
length := len(data)
i := 0 // data index
clearSpiTxRxFifo() clearSpiTxRxFifo()
// set TA = 1 // set TA = 1
spiMem[csReg] |= ta spiMem[csReg] |= ta
for i < length { for i := range data {
// Poll TXD writing bytes to SPI_FIFO // wait for TXD
for spiMem[csReg]&txd == 0 { for spiMem[csReg]&txd == 0 {
} }
// write bytes to SPI_FIFO
spiMem[fifoReg] = uint32(data[i]) spiMem[fifoReg] = uint32(data[i])
// Poll RXD reading bytes from SPI_FIFO
// wait for RXD
for spiMem[csReg]&rxd == 0 { for spiMem[csReg]&rxd == 0 {
} }
// read bytes from SPI_FIFO
data[i] = byte(spiMem[fifoReg]) data[i] = byte(spiMem[fifoReg])
i++
} }
// wait for DONE // wait for DONE
@ -102,32 +121,27 @@ func SpiTransfer(data []byte) { // control & status
spiMem[csReg] &^= ta spiMem[csReg] &^= ta
} }
func setSpiDiv(div uint32) { // set spi clock divider value
const divMask = 1<<16 - 1 - 1 // cdiv have 16 bits and must be odd (for some reason) 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 spiMem[clkDivReg] = div & divMask
} }
// clear both FIFOs
func clearSpiTxRxFifo() { func clearSpiTxRxFifo() {
const clearTxRx = 1<<5 | 1<<4 const clearTxRx = 1<<5 | 1<<4
spiMem[csReg] |= clearTxRx spiMem[csReg] |= clearTxRx
} }
func getSpiPins(dev int) []Pin { func getSpiPins(dev int) []Pin {
switch dev { switch dev {
case SPI0: case SPI0:
return []Pin{ return []Pin{7, 8, 9, 10, 11}
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
// 35, 36, 37, 38, 39, // only one set of SPI0 can be set in Spi mode at a time
}
case SPI1: case SPI1:
return []Pin{ return []Pin{16, 17, 18, 19, 20, 21}
16, 17, 18, 19, 20, 21,
}
case SPI2: case SPI2:
return []Pin{ return []Pin{40, 41, 42, 43, 44, 45}
40, 41, 42, 43, 44, 45,
}
default: default:
return []Pin{} return []Pin{}
} }

16
spi_test.go Normal file
View File

@ -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)
}