mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-14 16:03:41 +00:00
machine/attiny85: add LSB-first bit order support
Add software-based LSB-first support for USI SPI. The USI hardware only supports MSB-first, so bit reversal is done in software before sending and after receiving. Uses an efficient parallel bit swap algorithm (3 operations) to reverse the byte. Co-authored-by: Ona <no-reply@ona.com>
This commit is contained in:
@@ -405,6 +405,9 @@ type SPI struct {
|
|||||||
|
|
||||||
// USICR value configured for the selected SPI mode
|
// USICR value configured for the selected SPI mode
|
||||||
usicrValue uint8
|
usicrValue uint8
|
||||||
|
|
||||||
|
// LSB-first mode (requires software bit reversal)
|
||||||
|
lsbFirst bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// SPI0 is the USI-based SPI interface on the ATTiny85
|
// SPI0 is the USI-based SPI interface on the ATTiny85
|
||||||
@@ -500,15 +503,30 @@ func (s *SPI) Configure(config SPIConfig) error {
|
|||||||
s.delayCycles = 0
|
s.delayCycles = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: LSBFirst is not directly supported by USI hardware
|
// Store LSBFirst setting for use in Transfer
|
||||||
// It would need to be implemented in software if required
|
s.lsbFirst = config.LSBFirst
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reverseByte reverses the bit order of a byte (MSB <-> LSB)
|
||||||
|
// Used for LSB-first SPI mode since USI hardware only supports MSB-first
|
||||||
|
func reverseByte(b byte) byte {
|
||||||
|
b = (b&0xF0)>>4 | (b&0x0F)<<4
|
||||||
|
b = (b&0xCC)>>2 | (b&0x33)<<2
|
||||||
|
b = (b&0xAA)>>1 | (b&0x55)<<1
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
// Transfer performs a single byte SPI transfer (send and receive simultaneously)
|
// Transfer performs a single byte SPI transfer (send and receive simultaneously)
|
||||||
// This implements the USI-based SPI transfer using the "clock strobing" technique
|
// This implements the USI-based SPI transfer using the "clock strobing" technique
|
||||||
func (s *SPI) Transfer(b byte) (byte, error) {
|
func (s *SPI) Transfer(b byte) (byte, error) {
|
||||||
|
// For LSB-first mode, reverse the bits before sending
|
||||||
|
// USI hardware only supports MSB-first, so we do it in software
|
||||||
|
if s.lsbFirst {
|
||||||
|
b = reverseByte(b)
|
||||||
|
}
|
||||||
|
|
||||||
// Load the byte to transmit into the USI Data Register
|
// Load the byte to transmit into the USI Data Register
|
||||||
s.usidr.Set(b)
|
s.usidr.Set(b)
|
||||||
|
|
||||||
@@ -542,6 +560,13 @@ func (s *SPI) Transfer(b byte) (byte, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// After 8 bits are transferred, return the received byte
|
// Get the received byte
|
||||||
return s.usidr.Get(), nil
|
result := s.usidr.Get()
|
||||||
|
|
||||||
|
// For LSB-first mode, reverse the received bits
|
||||||
|
if s.lsbFirst {
|
||||||
|
result = reverseByte(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user