Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/machine/i2c.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//go:build atmega || nrf || sam || stm32 || fe310 || k210 || rp2040
// +build atmega nrf sam stm32 fe310 k210 rp2040
//go:build atmega || nrf || sam || (stm32 && !stm32wle5) || fe310 || k210 || rp2040 || arduino
// +build atmega nrf sam stm32,!stm32wle5 fe310 k210 rp2040 arduino


package machine

Expand Down
17 changes: 17 additions & 0 deletions src/machine/interface_i2c.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//go:build !gameboyadvance && !mimxrt1062 && !mk66f18 && !attiny85 && !stm32 && !esp32c3 && !k210
// +build !gameboyadvance,!mimxrt1062,!mk66f18,!attiny85,!stm32,!esp32c3,!k210

package machine

func init() {
type i2cer interface {
SetBaudRate(br uint32) error
Configure(config I2CConfig) error
ReadRegister(address uint8, register uint8, data []byte) error
WriteRegister(address uint8, register uint8, data []byte) error

Tx(addr uint16, w, r []byte) error
}

var _ i2cer = &I2C{}
}
17 changes: 17 additions & 0 deletions src/machine/interface_spi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//go:build !gameboyadvance && !mimxrt1062 && !mk66f18 && !stm32 && !attiny85 && !esp32c3 && !k210
// +build !gameboyadvance,!mimxrt1062,!mk66f18,!stm32,!attiny85,!esp32c3,!k210

package machine

func init() {
type spier interface {
SetBaudRate(br uint32) error
Configure(config SPIConfig) error
Transfer(b byte) (byte, error)
Tx(w, r []byte) error
}
_ = SPIConfig{
Frequency: 0,
}
var _ spier = &SPI{}
}
17 changes: 17 additions & 0 deletions src/machine/interface_uart.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//go:build !gameboyadvance && !attiny85
// +build !gameboyadvance,!attiny85

package machine

import "io"

func init() {
type uarter interface {
io.Writer
io.Reader

Buffered() int
}

var _ uarter = &UART{}
}
65 changes: 39 additions & 26 deletions src/machine/machine_atmega.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build avr && atmega
// +build avr,atmega

package machine
Expand Down Expand Up @@ -34,15 +35,18 @@ func (i2c *I2C) Configure(config I2CConfig) error {
// Initialize twi prescaler and bit rate.
avr.TWSR.SetBits((avr.TWSR_TWPS0 | avr.TWSR_TWPS1))

// twi bit rate formula from atmega128 manual pg. 204:
// SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR))
// NOTE: TWBR should be 10 or higher for controller mode.
// It is 72 for a 16mhz board with 100kHz TWI
avr.TWBR.Set(uint8(((CPUFrequency() / config.Frequency) - 16) / 2))

// Enable twi module.
avr.TWCR.Set(avr.TWCR_TWEN)
return nil
}

func (i2c *I2C) SetBaudRate(baud uint32) error {
// twi bit rate formula from atmega128 manual pg. 204:
// SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR))
// NOTE: TWBR should be 10 or higher for controller mode.
// It is 72 for a 16mhz board with 100kHz TWI
avr.TWBR.Set(uint8(((CPUFrequency() / baud) - 16) / 2))
return nil
}

Expand Down Expand Up @@ -231,26 +235,7 @@ func (s SPI) Configure(config SPIConfig) error {
// slave mode.
s.cs.Configure(PinConfig{Mode: PinOutput})

frequencyDivider := CPUFrequency() / config.Frequency

switch {
case frequencyDivider >= 128:
s.spcr.SetBits(avr.SPCR_SPR0 | avr.SPCR_SPR1)
case frequencyDivider >= 64:
s.spcr.SetBits(avr.SPCR_SPR1)
case frequencyDivider >= 32:
s.spcr.SetBits(avr.SPCR_SPR1)
s.spsr.SetBits(avr.SPSR_SPI2X)
case frequencyDivider >= 16:
s.spcr.SetBits(avr.SPCR_SPR0)
case frequencyDivider >= 8:
s.spcr.SetBits(avr.SPCR_SPR0)
s.spsr.SetBits(avr.SPSR_SPI2X)
case frequencyDivider >= 4:
// The clock is already set to all 0's.
default: // defaults to fastest which is /2
s.spsr.SetBits(avr.SPSR_SPI2X)
}
s.SetBaudRate(config.Frequency)

switch config.Mode {
case Mode1:
Expand All @@ -267,11 +252,16 @@ func (s SPI) Configure(config SPIConfig) error {
}

// enable SPI, set controller, set clock rate
s.spcr.SetBits(avr.SPCR_SPE | avr.SPCR_MSTR)
s.enable()

return nil
}

func (s SPI) enable() {
// enable SPI, set controller, set clock rate
s.spcr.SetBits(avr.SPCR_SPE | avr.SPCR_MSTR)
}

// Transfer writes the byte into the register and returns the read content
func (s SPI) Transfer(b byte) (byte, error) {
s.spdr.Set(uint8(b))
Expand All @@ -281,3 +271,26 @@ func (s SPI) Transfer(b byte) (byte, error) {

return byte(s.spdr.Get()), nil
}

func (s SPI) SetBaudRate(baud uint32) error {
frequencyDivider := CPUFrequency() / baud
switch {
case frequencyDivider >= 128:
s.spcr.SetBits(avr.SPCR_SPR0 | avr.SPCR_SPR1)
case frequencyDivider >= 64:
s.spcr.SetBits(avr.SPCR_SPR1)
case frequencyDivider >= 32:
s.spcr.SetBits(avr.SPCR_SPR1)
s.spsr.SetBits(avr.SPSR_SPI2X)
case frequencyDivider >= 16:
s.spcr.SetBits(avr.SPCR_SPR0)
case frequencyDivider >= 8:
s.spcr.SetBits(avr.SPCR_SPR0)
s.spsr.SetBits(avr.SPSR_SPI2X)
case frequencyDivider >= 4:
// The clock is already set to all 0's.
default: // defaults to fastest which is /2
s.spsr.SetBits(avr.SPSR_SPI2X)
}
return nil
}
20 changes: 13 additions & 7 deletions src/machine/machine_atsamd21.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build sam && atsamd21
// +build sam,atsamd21

// Peripheral abstraction layer for the atsamd21.
Expand Down Expand Up @@ -730,11 +731,12 @@ func (i2c *I2C) Configure(config I2CConfig) error {
}

// SetBaudRate sets the communication speed for the I2C.
func (i2c *I2C) SetBaudRate(br uint32) {
func (i2c *I2C) SetBaudRate(br uint32) error {
// Synchronous arithmetic baudrate, via Arduino SAMD implementation:
// SystemCoreClock / ( 2 * baudrate) - 5 - (((SystemCoreClock / 1000000) * WIRE_RISE_TIME_NANOSECONDS) / (2 * 1000));
baud := CPUFrequency()/(2*br) - 5 - (((CPUFrequency() / 1000000) * riseTimeNanoseconds) / (2 * 1000))
i2c.Bus.BAUD.Set(baud)
return nil
}

// Tx does a single I2C transaction at the specified address.
Expand Down Expand Up @@ -1247,12 +1249,7 @@ func (spi SPI) Configure(config SPIConfig) error {
}

// Set synch speed for SPI
baudRate := CPUFrequency() / (2 * config.Frequency)
if baudRate > 0 {
baudRate--
}
spi.Bus.BAUD.Set(uint8(baudRate))

spi.SetBaudRate(config.Frequency)
// Enable SPI port.
spi.Bus.CTRLA.SetBits(sam.SERCOM_SPI_CTRLA_ENABLE)
for spi.Bus.SYNCBUSY.HasBits(sam.SERCOM_SPI_SYNCBUSY_ENABLE) {
Expand All @@ -1261,6 +1258,15 @@ func (spi SPI) Configure(config SPIConfig) error {
return nil
}

func (spi SPI) SetBaudRate(baud uint32) error {
baudRate := CPUFrequency() / (2 * baud)
if baudRate > 0 {
baudRate--
}
spi.Bus.BAUD.Set(uint8(baudRate))
return nil
}

// Transfer writes/reads a single byte using the SPI interface.
func (spi SPI) Transfer(w byte) (byte, error) {
// write data
Expand Down
39 changes: 28 additions & 11 deletions src/machine/machine_atsamd51.go
Original file line number Diff line number Diff line change
Expand Up @@ -1204,11 +1204,12 @@ func (i2c *I2C) Configure(config I2CConfig) error {
}

// SetBaudRate sets the communication speed for the I2C.
func (i2c *I2C) SetBaudRate(br uint32) {
func (i2c *I2C) SetBaudRate(br uint32) error {
// Synchronous arithmetic baudrate, via Adafruit SAMD51 implementation:
// sercom->I2CM.BAUD.bit.BAUD = SERCOM_FREQ_REF / ( 2 * baudrate) - 1 ;
baud := SERCOM_FREQ_REF/(2*br) - 1
i2c.Bus.BAUD.Set(baud)
return nil
}

// Tx does a single I2C transaction at the specified address.
Expand Down Expand Up @@ -1429,9 +1430,7 @@ func (spi SPI) Configure(config SPIConfig) error {
}

// Disable SPI port.
spi.Bus.CTRLA.ClearBits(sam.SERCOM_SPIM_CTRLA_ENABLE)
for spi.Bus.SYNCBUSY.HasBits(sam.SERCOM_SPIM_SYNCBUSY_ENABLE) {
}
spi.disable()

// enable pins
config.SCK.Configure(PinConfig{Mode: sckPinMode})
Expand Down Expand Up @@ -1483,18 +1482,22 @@ func (spi SPI) Configure(config SPIConfig) error {
spi.Bus.CTRLA.ClearBits(sam.SERCOM_SPIM_CTRLA_CPOL)
}

// Enable SPI port.
spi.enable()
spi.SetBaudRate(config.Frequency)
return nil
}

// SetBaudRate sets SPI bus frequency.
func (spi SPI) SetBaudRate(baud uint32) error {
spi.disable()
// Set synch speed for SPI
baudRate := SERCOM_FREQ_REF / (2 * config.Frequency)
baudRate := SERCOM_FREQ_REF / (2 * baud)
if baudRate > 0 {
baudRate--
}
spi.Bus.BAUD.Set(uint8(baudRate))

// Enable SPI port.
spi.Bus.CTRLA.SetBits(sam.SERCOM_SPIM_CTRLA_ENABLE)
for spi.Bus.SYNCBUSY.HasBits(sam.SERCOM_SPIM_SYNCBUSY_ENABLE) {
}

spi.enable()
return nil
}

Expand All @@ -1511,6 +1514,20 @@ func (spi SPI) Transfer(w byte) (byte, error) {
return byte(spi.Bus.DATA.Get()), nil
}

// Enable SPI port.
func (spi SPI) enable() {
spi.Bus.CTRLA.SetBits(sam.SERCOM_SPIM_CTRLA_ENABLE)
for spi.Bus.SYNCBUSY.HasBits(sam.SERCOM_SPIM_SYNCBUSY_ENABLE) {
}
}

// Disable SPI port.
func (spi SPI) disable() {
spi.Bus.CTRLA.ClearBits(sam.SERCOM_SPIM_CTRLA_ENABLE)
for spi.Bus.SYNCBUSY.HasBits(sam.SERCOM_SPIM_SYNCBUSY_ENABLE) {
}
}

var (
ErrTxInvalidSliceSize = errors.New("SPI write and read slices must be same size")
)
Expand Down
52 changes: 30 additions & 22 deletions src/machine/machine_fe310.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build fe310
// +build fe310

package machine
Expand Down Expand Up @@ -148,14 +149,7 @@ func (spi SPI) Configure(config SPIConfig) error {
config.SDO.Configure(PinConfig{Mode: PinSPI})
config.SDI.Configure(PinConfig{Mode: PinSPI})

// set default frequency
if config.Frequency == 0 {
config.Frequency = 4000000 // 4MHz
}

// div = (SPI_CFG(dev)->f_sys / (2 * frequency)) - 1;
div := CPUFrequency()/(2*config.Frequency) - 1
spi.Bus.DIV.Set(div)
spi.SetBaudRate(config.Frequency)

// set mode
switch config.Mode {
Expand All @@ -174,7 +168,6 @@ func (spi SPI) Configure(config SPIConfig) error {
spi.Bus.MODE.ClearBits(sifive.QSPI_MODE_PHASE)
spi.Bus.MODE.ClearBits(sifive.QSPI_MODE_POLARITY)
}

// frame length
spi.Bus.FMT.SetBits(8 << sifive.QSPI_FMT_LENGTH_Pos)

Expand All @@ -191,6 +184,18 @@ func (spi SPI) Configure(config SPIConfig) error {
return nil
}

func (spi SPI) SetBaudRate(baud uint32) error {
// set default frequency
if baud == 0 {
baud = 4000000 // 4MHz
}

// div = (SPI_CFG(dev)->f_sys / (2 * frequency)) - 1;
div := CPUFrequency()/(2*baud) - 1
spi.Bus.DIV.Set(div)
return nil
}

// Transfer writes/reads a single byte using the SPI interface.
func (spi SPI) Transfer(w byte) (byte, error) {
// wait for tx ready
Expand Down Expand Up @@ -228,31 +233,34 @@ type I2CConfig struct {

// Configure is intended to setup the I2C interface.
func (i2c *I2C) Configure(config I2CConfig) error {
var i2cClockFrequency uint32 = 32000000
if config.Frequency == 0 {
config.Frequency = TWI_FREQ_100KHZ
}

if config.SDA == 0 && config.SCL == 0 {
config.SDA = I2C0_SDA_PIN
config.SCL = I2C0_SCL_PIN
}

var prescaler = i2cClockFrequency/(5*config.Frequency) - 1
i2c.SetBaudRate(config.Frequency)
// enable controller
i2c.Bus.CTR.SetBits(sifive.I2C_CTR_EN)

config.SDA.Configure(PinConfig{Mode: PinI2C})
config.SCL.Configure(PinConfig{Mode: PinI2C})

return nil
}

func (i2c *I2C) SetBaudRate(baud uint32) error {
var i2cClockFrequency uint32 = 32000000
if baud == 0 {
baud = TWI_FREQ_100KHZ
}
var prescaler = i2cClockFrequency/(5*baud) - 1

// disable controller before setting the prescale registers
i2c.Bus.CTR.ClearBits(sifive.I2C_CTR_EN)

// set prescaler registers
i2c.Bus.PRER_LO.Set(uint32(prescaler & 0xff))
i2c.Bus.PRER_HI.Set(uint32((prescaler >> 8) & 0xff))

// enable controller
i2c.Bus.CTR.SetBits(sifive.I2C_CTR_EN)

config.SDA.Configure(PinConfig{Mode: PinI2C})
config.SCL.Configure(PinConfig{Mode: PinI2C})

return nil
}

Expand Down
Loading