Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

machine/i2c: add interface check and implementation where missing for SetBaudRate() #3406

Merged
merged 8 commits into from
Oct 14, 2023
11 changes: 11 additions & 0 deletions src/machine/i2c.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ import (
"errors"
)

// If you are getting a compile error on this line please check to see you've
// correctly implemented the methods on the I2C type. They must match
// the i2cController interface method signatures type to type perfectly.
// If not implementing the I2C type please remove your target from the build tags
// at the top of this file.
var _ interface { // 2
Configure(config I2CConfig) error
Tx(addr uint16, w, r []byte) error
SetBaudRate(br uint32) error
} = (*I2C)(nil)

// TWI_FREQ is the I2C bus speed. Normally either 100 kHz, or 400 kHz for high-speed bus.
//
// Deprecated: use 100 * machine.KHz or 400 * machine.KHz instead.
Expand Down
7 changes: 6 additions & 1 deletion src/machine/machine_atmega.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,19 @@ func (i2c *I2C) Configure(config I2CConfig) error {
// Activate internal pullups for twi.
avr.PORTC.SetBits((avr.DIDR0_ADC4D | avr.DIDR0_ADC5D))

return i2c.SetBaudRate(config.Frequency)
}

// SetBaudRate sets the communication speed for I2C.
func (i2c *I2C) SetBaudRate(br uint32) 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))
avr.TWBR.Set(uint8(((CPUFrequency() / br) - 16) / 2))

// Enable twi module.
avr.TWCR.Set(avr.TWCR_TWEN)
Expand Down
5 changes: 3 additions & 2 deletions src/machine/machine_atsamd21.go
Original file line number Diff line number Diff line change
Expand Up @@ -732,12 +732,13 @@ func (i2c *I2C) Configure(config I2CConfig) error {
return nil
}

// SetBaudRate sets the communication speed for the I2C.
func (i2c *I2C) SetBaudRate(br uint32) {
// SetBaudRate sets the communication speed for I2C.
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
5 changes: 3 additions & 2 deletions src/machine/machine_atsamd51.go
Original file line number Diff line number Diff line change
Expand Up @@ -1228,12 +1228,13 @@ func (i2c *I2C) Configure(config I2CConfig) error {
return nil
}

// SetBaudRate sets the communication speed for the I2C.
func (i2c *I2C) SetBaudRate(br uint32) {
// SetBaudRate sets the communication speed for I2C.
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
18 changes: 13 additions & 5 deletions src/machine/machine_fe310.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,10 @@ type I2CConfig struct {
SDA Pin
}

var i2cClockFrequency uint32 = 32000000

// 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 = 100 * KHz
}
Expand All @@ -241,7 +242,17 @@ func (i2c *I2C) Configure(config I2CConfig) error {
config.SCL = I2C0_SCL_PIN
}

var prescaler = i2cClockFrequency/(5*config.Frequency) - 1
i2c.SetBaudRate(config.Frequency)

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

return nil
}

// SetBaudRate sets the communication speed for I2C.
func (i2c *I2C) SetBaudRate(br uint32) error {
var prescaler = i2cClockFrequency/(5*br) - 1

// disable controller before setting the prescale registers
i2c.Bus.CTR.ClearBits(sifive.I2C_CTR_EN)
Expand All @@ -253,9 +264,6 @@ func (i2c *I2C) Configure(config I2CConfig) error {
// 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
9 changes: 9 additions & 0 deletions src/machine/machine_generic.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ func (i2c *I2C) Configure(config I2CConfig) error {
return nil
}

// SetBaudRate sets the I2C frequency.
func (i2c *I2C) SetBaudRate(br uint32) error {
i2cSetBaudRate(i2c.Bus, br)
return nil
}

// Tx does a single I2C transaction at the specified address.
func (i2c *I2C) Tx(addr uint16, w, r []byte) error {
i2cTransfer(i2c.Bus, &w[0], len(w), &r[0], len(r))
Expand All @@ -117,6 +123,9 @@ func (i2c *I2C) Tx(addr uint16, w, r []byte) error {
//export __tinygo_i2c_configure
func i2cConfigure(bus uint8, scl Pin, sda Pin)

//export __tinygo_i2c_set_baud_rate
func i2cSetBaudRate(bus uint8, br uint32)

//export __tinygo_i2c_transfer
func i2cTransfer(bus uint8, w *byte, wlen int, r *byte, rlen int) int

Expand Down
19 changes: 13 additions & 6 deletions src/machine/machine_k210.go
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,19 @@ func (i2c *I2C) Configure(config I2CConfig) error {
config.SCL.SetFPIOAFunction(FUNC_I2C2_SCLK)
}

div := CPUFrequency() / config.Frequency / 16
i2c.SetBaudRate(config.Frequency)

i2c.Bus.INTR_MASK.Set(0)
i2c.Bus.DMA_CR.Set(0x03)
i2c.Bus.DMA_RDLR.Set(0)
i2c.Bus.DMA_TDLR.Set(0x4)

return nil
}

// SetBaudRate sets the communication speed for I2C.
func (i2c *I2C) SetBaudRate(br uint32) error {
div := CPUFrequency() / br / 16

// Disable controller before setting the prescale register.
i2c.Bus.ENABLE.Set(0)
Expand All @@ -574,11 +586,6 @@ func (i2c *I2C) Configure(config I2CConfig) error {
i2c.Bus.SS_SCL_HCNT.Set(uint32(div))
i2c.Bus.SS_SCL_LCNT.Set(uint32(div))

i2c.Bus.INTR_MASK.Set(0)
i2c.Bus.DMA_CR.Set(0x03)
i2c.Bus.DMA_RDLR.Set(0)
i2c.Bus.DMA_TDLR.Set(0x4)

return nil
}

Expand Down
6 changes: 6 additions & 0 deletions src/machine/machine_mimxrt1062_i2c.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,12 @@ func (i2c *I2C) Configure(config I2CConfig) {
i2c.reset(freq)
}

// SetBaudRate sets the communication speed for I2C.
func (i2c I2C) SetBaudRate(br uint32) error {
// TODO: implement
return nil
deadprogram marked this conversation as resolved.
Show resolved Hide resolved
}

func (i2c I2C) Tx(addr uint16, w, r []byte) error {
// perform transmit transfer
if nil != w {
Expand Down
24 changes: 18 additions & 6 deletions src/machine/machine_nrf.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,13 +246,8 @@ func (i2c *I2C) Configure(config I2CConfig) error {
i2c.setPins(config.SCL, config.SDA)

i2c.mode = config.Mode

if i2c.mode == I2CModeController {
if config.Frequency >= 400*KHz {
i2c.Bus.FREQUENCY.Set(nrf.TWI_FREQUENCY_FREQUENCY_K400)
} else {
i2c.Bus.FREQUENCY.Set(nrf.TWI_FREQUENCY_FREQUENCY_K100)
}
i2c.SetBaudRate(config.Frequency)

i2c.enableAsController()
} else {
Expand All @@ -262,6 +257,23 @@ func (i2c *I2C) Configure(config I2CConfig) error {
return nil
}

// SetBaudRate sets the I2C frequency. It has the side effect of also
// enabling the I2C hardware if disabled beforehand.
//
//go:inline
func (i2c *I2C) SetBaudRate(br uint32) error {
switch {
case br >= 400*KHz:
i2c.Bus.SetFREQUENCY(nrf.TWI_FREQUENCY_FREQUENCY_K400)
case br >= 250*KHz:
i2c.Bus.SetFREQUENCY(nrf.TWI_FREQUENCY_FREQUENCY_K250)
default:
i2c.Bus.SetFREQUENCY(nrf.TWI_FREQUENCY_FREQUENCY_K100)
}

return nil
}

// signalStop sends a stop signal to the I2C peripheral and waits for confirmation.
func (i2c *I2C) signalStop() error {
tries := 0
Expand Down
6 changes: 6 additions & 0 deletions src/machine/machine_stm32_i2c_reva.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,12 @@ func (i2c *I2C) Configure(config I2CConfig) error {
return nil
}

// SetBaudRate sets the communication speed for I2C.
func (i2c *I2C) SetBaudRate(br uint32) error {
// TODO: implement
return nil
}

func (i2c *I2C) Tx(addr uint16, w, r []byte) error {

if err := i2c.controllerTransmit(addr, w); nil != err {
Expand Down
6 changes: 6 additions & 0 deletions src/machine/machine_stm32_i2c_revb.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ func (i2c *I2C) Configure(config I2CConfig) error {
return nil
}

// SetBaudRate sets the communication speed for I2C.
func (i2c *I2C) SetBaudRate(br uint32) error {
// TODO: implement
return nil
}

func (i2c *I2C) Tx(addr uint16, w, r []byte) error {
if len(w) > 0 {
if err := i2c.controllerTransmit(addr, w); nil != err {
Expand Down