diff --git a/src/machine/machine_nrf.go b/src/machine/machine_nrf.go index f6641999..e8859c41 100644 --- a/src/machine/machine_nrf.go +++ b/src/machine/machine_nrf.go @@ -5,6 +5,12 @@ package machine import ( "device/arm" "device/nrf" + "errors" +) + +var ( + ErrTxSlicesRequired = errors.New("SPI Tx requires a write or read slice, or both") + ErrTxInvalidSliceSize = errors.New("SPI write and read slices must be same size") ) type PinMode uint8 @@ -322,3 +328,70 @@ func (spi SPI) Transfer(w byte) (byte, error) { // TODO: handle SPI errors return byte(r), nil } + +// Tx handles read/write operation for SPI interface. Since SPI is a syncronous write/read +// interface, there must always be the same number of bytes written as bytes read. +// The Tx method knows about this, and offers a few different ways of calling it. +// +// This form sends the bytes in tx buffer, putting the resulting bytes read into the rx buffer. +// Note that the tx and rx buffers must be the same size: +// +// spi.Tx(tx, rx) +// +// This form sends the tx buffer, ignoring the result. Useful for sending "commands" that return zeros +// until all the bytes in the command packet have been received: +// +// spi.Tx(tx, nil) +// +// This form sends zeros, putting the result into the rx buffer. Good for reading a "result packet": +// +// spi.Tx(nil, rx) +// +func (spi SPI) Tx(w, r []byte) error { + if w == nil && r == nil { + return ErrTxSlicesRequired + } + + var err error + + switch { + case len(w) == 0: + // read only, so write zero and read a result. + for i := range r { + r[i], err = spi.Transfer(0) + if err != nil { + return err + } + } + case len(r) == 0: + // write only + spi.Bus.TXD.Set(uint32(w[0])) + w = w[1:] + for _, b := range w { + spi.Bus.TXD.Set(uint32(b)) + for spi.Bus.EVENTS_READY.Get() == 0 { + } + _ = spi.Bus.RXD.Get() + spi.Bus.EVENTS_READY.Set(0) + } + for spi.Bus.EVENTS_READY.Get() == 0 { + } + _ = spi.Bus.RXD.Get() + spi.Bus.EVENTS_READY.Set(0) + + default: + // write/read + if len(w) != len(r) { + return ErrTxInvalidSliceSize + } + + for i, b := range w { + r[i], err = spi.Transfer(b) + if err != nil { + return err + } + } + } + + return nil +} diff --git a/src/machine/spi.go b/src/machine/spi.go index b913f200..340b4486 100644 --- a/src/machine/spi.go +++ b/src/machine/spi.go @@ -1,4 +1,4 @@ -// +build nrf sam stm32,!stm32f407 +// +build sam stm32,!stm32f407 package machine