mirror of
https://github.com/stianeikeland/go-rpio.git
synced 2025-01-23 02:31:05 +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
|
||||
|
||||
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{}
|
||||
}
|
||||
|
|
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