diff --git a/src/machine/board_arduino_nano33.go b/src/machine/board_arduino_nano33.go index 00cc387c2..fba4e200f 100644 --- a/src/machine/board_arduino_nano33.go +++ b/src/machine/board_arduino_nano33.go @@ -110,10 +110,10 @@ const ( // I2C on the Arduino Nano 33. var ( - I2C0 = I2C{Bus: sam.SERCOM4_I2CM, - SDA: SDA_PIN, - SCL: SCL_PIN, - PinMode: PinSERCOMAlt} + I2C0 = I2C{ + Bus: sam.SERCOM4_I2CM, + SERCOM: 4, + } ) // SPI pins diff --git a/src/machine/board_circuitplay_express.go b/src/machine/board_circuitplay_express.go index ae1bca9d5..6f7e34a1a 100644 --- a/src/machine/board_circuitplay_express.go +++ b/src/machine/board_circuitplay_express.go @@ -94,15 +94,15 @@ const ( // I2C on the Circuit Playground Express. var ( // external device - I2C0 = I2C{Bus: sam.SERCOM5_I2CM, - SDA: SDA_PIN, - SCL: SCL_PIN, - PinMode: PinSERCOM} + I2C0 = I2C{ + Bus: sam.SERCOM5_I2CM, + SERCOM: 5, + } // internal device - I2C1 = I2C{Bus: sam.SERCOM1_I2CM, - SDA: SDA1_PIN, - SCL: SCL1_PIN, - PinMode: PinSERCOMAlt} + I2C1 = I2C{ + Bus: sam.SERCOM1_I2CM, + SERCOM: 1, + } ) // SPI pins (internal flash) diff --git a/src/machine/board_feather-m0.go b/src/machine/board_feather-m0.go index 8c4dc7595..57704cc58 100644 --- a/src/machine/board_feather-m0.go +++ b/src/machine/board_feather-m0.go @@ -73,10 +73,10 @@ const ( // I2C on the Feather M0. var ( - I2C0 = I2C{Bus: sam.SERCOM3_I2CM, - SDA: SDA_PIN, - SCL: SCL_PIN, - PinMode: PinSERCOM} + I2C0 = I2C{ + Bus: sam.SERCOM3_I2CM, + SERCOM: 3, + } ) // SPI pins diff --git a/src/machine/board_itsybitsy-m0.go b/src/machine/board_itsybitsy-m0.go index 48a7a0954..0d7248c62 100644 --- a/src/machine/board_itsybitsy-m0.go +++ b/src/machine/board_itsybitsy-m0.go @@ -75,10 +75,10 @@ const ( // I2C on the ItsyBitsy M0. var ( - I2C0 = I2C{Bus: sam.SERCOM3_I2CM, - SDA: SDA_PIN, - SCL: SCL_PIN, - PinMode: PinSERCOM} + I2C0 = I2C{ + Bus: sam.SERCOM3_I2CM, + SERCOM: 3, + } ) // SPI pins diff --git a/src/machine/board_trinket.go b/src/machine/board_trinket.go index 7eec1f6f1..d5acf8ee6 100644 --- a/src/machine/board_trinket.go +++ b/src/machine/board_trinket.go @@ -79,10 +79,10 @@ const ( // I2C on the Trinket M0. var ( - I2C0 = I2C{Bus: sam.SERCOM2_I2CM, - SDA: SDA_PIN, - SCL: SCL_PIN, - PinMode: PinSERCOMAlt} + I2C0 = I2C{ + Bus: sam.SERCOM2_I2CM, + SERCOM: 2, + } ) // I2S pins diff --git a/src/machine/machine.go b/src/machine/machine.go index e55b522d5..a7863d8ff 100644 --- a/src/machine/machine.go +++ b/src/machine/machine.go @@ -5,6 +5,8 @@ import "errors" var ( ErrInvalidInputPin = errors.New("machine: invalid input pin") ErrInvalidOutputPin = errors.New("machine: invalid output pin") + ErrInvalidClockPin = errors.New("machine: invalid clock pin") + ErrInvalidDataPin = errors.New("machine: invalid data pin") ) type PinConfig struct { diff --git a/src/machine/machine_atsamd21.go b/src/machine/machine_atsamd21.go index 32febd020..1c5b676b1 100644 --- a/src/machine/machine_atsamd21.go +++ b/src/machine/machine_atsamd21.go @@ -519,10 +519,8 @@ func defaultUART1Handler() { // I2C on the SAMD21. type I2C struct { - Bus *sam.SERCOM_I2CM_Type - SCL Pin - SDA Pin - PinMode PinMode + Bus *sam.SERCOM_I2CM_Type + SERCOM uint8 } // I2CConfig is used to store config info for I2C. @@ -552,11 +550,30 @@ const ( const i2cTimeout = 1000 // Configure is intended to setup the I2C interface. -func (i2c I2C) Configure(config I2CConfig) { +func (i2c I2C) Configure(config I2CConfig) error { // Default I2C bus speed is 100 kHz. if config.Frequency == 0 { config.Frequency = TWI_FREQ_100KHZ } + if config.SDA == 0 && config.SCL == 0 { + config.SDA = SDA_PIN + config.SCL = SCL_PIN + } + + sclPinMode, sclPad, ok := findPinPadMapping(i2c.SERCOM, config.SCL) + if !ok || sclPad != 1 { + // SCL must be on pad 1, according to section 27.5 of the datasheet. + // Note: this is not an exhaustive test for I2C support on the pin: not + // all pins support I2C. + return ErrInvalidClockPin + } + sdaPinMode, sdaPad, ok := findPinPadMapping(i2c.SERCOM, config.SDA) + if !ok || sdaPad != 0 { + // SDA must be on pad 0, according to section 27.5 of the datasheet. + // Note: this is not an exhaustive test for I2C support on the pin: not + // all pins support I2C. + return ErrInvalidDataPin + } // reset SERCOM i2c.Bus.CTRLA.SetBits(sam.SERCOM_I2CM_CTRLA_SWRST) @@ -582,8 +599,10 @@ func (i2c I2C) Configure(config I2CConfig) { } // enable pins - i2c.SDA.Configure(PinConfig{Mode: i2c.PinMode}) - i2c.SCL.Configure(PinConfig{Mode: i2c.PinMode}) + config.SDA.Configure(PinConfig{Mode: sdaPinMode}) + config.SCL.Configure(PinConfig{Mode: sclPinMode}) + + return nil } // SetBaudRate sets the communication speed for the I2C.