mirror of
https://github.com/stianeikeland/go-rpio.git
synced 2025-01-23 10:41:03 +01:00
Define 3 SPI transfering functions, and other minor changes
This commit is contained in:
parent
094a866c10
commit
7d2387e2cc
82
spi.go
82
spi.go
|
@ -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
16
spi_test.go
Normal 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)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user