@ -76,6 +76,9 @@ func (s *SPI) Connect(f physic.Frequency, mode spi.Mode, bits int) (spi.Conn, er
if mode & spi . LSBFirst == spi . LSBFirst {
if mode & spi . LSBFirst == spi . LSBFirst {
return nil , errors . New ( "bitbang-spi: LSBFirst mode not supported" )
return nil , errors . New ( "bitbang-spi: LSBFirst mode not supported" )
}
}
if mode >= 0x20 {
return nil , fmt . Errorf ( "bitbang-spi: unhandled mode %d(%s)" , mode , mode . String ( ) )
}
s . spiConn . mu . Lock ( )
s . spiConn . mu . Lock ( )
defer s . spiConn . mu . Unlock ( )
defer s . spiConn . mu . Unlock ( )
s . spiConn . freqDev = f
s . spiConn . freqDev = f
@ -84,6 +87,14 @@ func (s *SPI) Connect(f physic.Frequency, mode spi.Mode, bits int) (spi.Conn, er
}
}
s . spiConn . mode = mode
s . spiConn . mode = mode
s . spiConn . bits = bits
s . spiConn . bits = bits
s . spiConn . readAfterClockPulse = mode & spi . Mode1 == spi . Mode1
// Set clock idle polarity, ensuring an idle clock to start
s . spiConn . clockIdle = gpio . Level ( mode & spi . Mode2 == spi . Mode2 )
if err := s . spiConn . sck . Out ( s . spiConn . clockIdle ) ; err != nil {
return nil , fmt . Errorf ( "bitbang-spi: failed to idle clock: %v" , err )
}
return & s . spiConn , nil
return & s . spiConn , nil
}
}
@ -135,6 +146,8 @@ type spiConn struct {
mu sync . Mutex
mu sync . Mutex
freqPort physic . Frequency
freqPort physic . Frequency
freqDev physic . Frequency
freqDev physic . Frequency
clockIdle gpio . Level
readAfterClockPulse bool
mode spi . Mode
mode spi . Mode
bits int
bits int
halfCycle time . Duration
halfCycle time . Duration
@ -150,46 +163,6 @@ func (s *spiConn) Duplex() conn.Duplex {
return conn . Full
return conn . Full
}
}
func ( s * spiConn ) clockOn ( ) error {
if s . mode & spi . Mode2 == spi . Mode2 {
return s . sck . Out ( gpio . Low )
}
return s . sck . Out ( gpio . High )
}
func ( s * spiConn ) clockOff ( ) error {
if s . mode & spi . Mode2 == spi . Mode2 {
return s . sck . Out ( gpio . High )
}
return s . sck . Out ( gpio . Low )
}
func ( s * spiConn ) readAfterClockPulse ( ) bool {
return s . mode & spi . Mode1 == spi . Mode1
}
func ( s * spiConn ) assertCS ( ) error {
if s . csn == nil || s . mode & spi . NoCS == spi . NoCS {
return nil
}
if err := s . csn . Out ( gpio . Low ) ; err != nil {
return err
}
s . sleepHalfCycle ( )
return nil
}
func ( s * spiConn ) unassertCS ( ) error {
if s . csn == nil || s . mode & spi . NoCS == spi . NoCS {
return nil
}
if err := s . csn . Out ( gpio . High ) ; err != nil {
return err
}
s . sleepHalfCycle ( )
return nil
}
// Tx implements spi.Conn.
// Tx implements spi.Conn.
//
//
// BUG(maruel): Implement mode (HalfDuplex and LSBFirst remain to be done).
// BUG(maruel): Implement mode (HalfDuplex and LSBFirst remain to be done).
@ -213,14 +186,14 @@ func (s *spiConn) Tx(w, r []byte) (err error) {
}
}
s . sleepHalfCycle ( )
s . sleepHalfCycle ( )
if err = s . clockOn ( ) ; err != nil {
if err = s . sck . Out ( ! s . clockIdle ) ; err != nil {
return fmt . Errorf ( "bitbang-spi: failed to assert clock: %v" , err )
return fmt . Errorf ( "bitbang-spi: failed to assert clock: %v" , err )
}
}
s . sleepHalfCycle ( )
s . sleepHalfCycle ( )
if s . readAfterClockPulse ( ) {
if s . readAfterClockPulse {
if err = s . clockOff ( ) ; err != nil {
if err = s . sck . Out ( s . clockIdle ) ; err != nil {
return fmt . Errorf ( "bitbang-spi: failed to unassert clock: %v", err )
return fmt . Errorf ( "bitbang-spi: failed to idle clock: %v", err )
}
}
s . sleepHalfCycle ( )
s . sleepHalfCycle ( )
}
}
@ -231,9 +204,9 @@ func (s *spiConn) Tx(w, r []byte) (err error) {
}
}
}
}
if ! s . readAfterClockPulse ( ) {
if ! s . readAfterClockPulse {
if err = s . clockOff ( ) ; err != nil {
if err = s . sck . Out ( s . clockIdle ) ; err != nil {
return fmt . Errorf ( "bitbang-spi: failed to unassert clock: %v", err )
return fmt . Errorf ( "bitbang-spi: failed to idle clock: %v", err )
}
}
}
}
}
}
@ -284,5 +257,27 @@ func (s *spiConn) sleepHalfCycle() {
cpu . Nanospin ( s . halfCycle )
cpu . Nanospin ( s . halfCycle )
}
}
func ( s * spiConn ) assertCS ( ) error {
if s . csn == nil || s . mode & spi . NoCS == spi . NoCS {
return nil
}
if err := s . csn . Out ( gpio . Low ) ; err != nil {
return err
}
s . sleepHalfCycle ( )
return nil
}
func ( s * spiConn ) unassertCS ( ) error {
if s . csn == nil || s . mode & spi . NoCS == spi . NoCS {
return nil
}
if err := s . csn . Out ( gpio . High ) ; err != nil {
return err
}
s . sleepHalfCycle ( )
return nil
}
var _ spi . PortCloser = & SPI { }
var _ spi . PortCloser = & SPI { }
var _ fmt . Stringer = & SPI { }
var _ fmt . Stringer = & SPI { }