From e4fa1a8288f7f0d539cbf0df26d554cac89ab8a6 Mon Sep 17 00:00:00 2001 From: Ron Evans Date: Wed, 3 Oct 2018 20:34:22 +0200 Subject: [PATCH] nrf: I2C interface Signed-off-by: Ron Evans --- src/examples/blinkm/blinkm.go | 8 ++-- src/machine/board_pca10040.go | 6 +++ src/machine/i2c.go | 9 ++++ src/machine/machine_avr.go | 10 +--- src/machine/machine_nrf.go | 90 +++++++++++++++++++++++++++++++++++ 5 files changed, 110 insertions(+), 13 deletions(-) create mode 100644 src/machine/i2c.go diff --git a/src/examples/blinkm/blinkm.go b/src/examples/blinkm/blinkm.go index 1cab2592..a175ab99 100644 --- a/src/examples/blinkm/blinkm.go +++ b/src/examples/blinkm/blinkm.go @@ -20,20 +20,18 @@ func main() { count := 0 for { - machine.I2C0.WriteTo(0x09, []byte("n")) - switch count { case 0: // Crimson - machine.I2C0.WriteTo(0x09, []byte{0xdc, 0x14, 0x3c}) + machine.I2C0.WriteTo(0x09, []byte{'n', 0xdc, 0x14, 0x3c}) count = 1 case 1: // MediumPurple - machine.I2C0.WriteTo(0x09, []byte{0x93, 0x70, 0xdb}) + machine.I2C0.WriteTo(0x09, []byte{'n', 0x93, 0x70, 0xdb}) count = 2 case 2: // MediumSeaGreen - machine.I2C0.WriteTo(0x09, []byte{0x3c, 0xb3, 0x71}) + machine.I2C0.WriteTo(0x09, []byte{'n', 0x3c, 0xb3, 0x71}) count = 0 } diff --git a/src/machine/board_pca10040.go b/src/machine/board_pca10040.go index c1e3d695..3ba0c5f7 100644 --- a/src/machine/board_pca10040.go +++ b/src/machine/board_pca10040.go @@ -35,3 +35,9 @@ const ( ADC4 = 30 ADC5 = 31 ) + +// I2C pins +const ( + SDA_PIN = 26 + SCL_PIN = 27 +) diff --git a/src/machine/i2c.go b/src/machine/i2c.go new file mode 100644 index 00000000..9daa6ce0 --- /dev/null +++ b/src/machine/i2c.go @@ -0,0 +1,9 @@ +// +build avr nrf + +package machine + +// TWI_FREQ is the I2C bus speed. Normally either 100 kHz, or 400 kHz for high-speed bus. +const ( + TWI_FREQ_100KHZ = 100000 + TWI_FREQ_400KHZ = 400000 +) diff --git a/src/machine/machine_avr.go b/src/machine/machine_avr.go index 993276d3..7e18511c 100644 --- a/src/machine/machine_avr.go +++ b/src/machine/machine_avr.go @@ -158,20 +158,14 @@ func (a ADC) Get() uint16 { return uint16(low) | uint16(high<<8) } -// I2C on the Arduino +// I2C on the Arduino. type I2C struct { } // I2C0 is the only I2C interface on the Arduino. var I2C0 = I2C{} -// TWI_FREQ is the bus speed. Normally either 100 kHz, or 400 kHz for high-speed bus. -const ( - TWI_FREQ_100KHZ = 100000 - TWI_FREQ_400KHZ = 400000 -) - -// I2CConfig does not do much of anything on Arduino. +// I2CConfig is used to store config info for I2C. type I2CConfig struct { Frequency uint32 } diff --git a/src/machine/machine_nrf.go b/src/machine/machine_nrf.go index 6f58d366..9308b9e7 100644 --- a/src/machine/machine_nrf.go +++ b/src/machine/machine_nrf.go @@ -96,3 +96,93 @@ func handleUART0() { nrf.UART0.EVENTS_RXDRDY = 0x0 } } + +// I2C on the NRF. +type I2C struct { + Bus *nrf.TWI_Type +} + +// There are 2 I2C interfaces on the NRF. +var ( + I2C0 = I2C{Bus: nrf.TWI0} + I2C1 = I2C{Bus: nrf.TWI1} +) + +// I2CConfig is used to store config info for I2C. +type I2CConfig struct { + Frequency uint32 + SCL uint8 + SDA uint8 +} + +// Configure is intended to setup the I2C interface. +func (i2c I2C) Configure(config I2CConfig) { + // Default I2C bus speed is 100 kHz. + if config.Frequency == 0 { + config.Frequency = TWI_FREQ_100KHZ + } + // Default I2C pins if not set. + if config.SDA == 0 && config.SCL == 0 { + config.SDA = SDA_PIN + config.SCL = SCL_PIN + } + + // do config + nrf.P0.PIN_CNF[config.SCL] = (nrf.GPIO_PIN_CNF_DIR_Input << nrf.GPIO_PIN_CNF_DIR_Pos) | + (nrf.GPIO_PIN_CNF_INPUT_Connect << nrf.GPIO_PIN_CNF_INPUT_Pos) | + (nrf.GPIO_PIN_CNF_PULL_Pullup << nrf.GPIO_PIN_CNF_PULL_Pos) | + (nrf.GPIO_PIN_CNF_DRIVE_S0D1 << nrf.GPIO_PIN_CNF_DRIVE_Pos) | + (nrf.GPIO_PIN_CNF_SENSE_Disabled << nrf.GPIO_PIN_CNF_SENSE_Pos) + + nrf.P0.PIN_CNF[config.SDA] = (nrf.GPIO_PIN_CNF_DIR_Input << nrf.GPIO_PIN_CNF_DIR_Pos) | + (nrf.GPIO_PIN_CNF_INPUT_Connect << nrf.GPIO_PIN_CNF_INPUT_Pos) | + (nrf.GPIO_PIN_CNF_PULL_Pullup << nrf.GPIO_PIN_CNF_PULL_Pos) | + (nrf.GPIO_PIN_CNF_DRIVE_S0D1 << nrf.GPIO_PIN_CNF_DRIVE_Pos) | + (nrf.GPIO_PIN_CNF_SENSE_Disabled << nrf.GPIO_PIN_CNF_SENSE_Pos) + + if config.Frequency == TWI_FREQ_400KHZ { + i2c.Bus.FREQUENCY = nrf.TWI_FREQUENCY_FREQUENCY_K400 + } else { + i2c.Bus.FREQUENCY = nrf.TWI_FREQUENCY_FREQUENCY_K100 + } + + i2c.Bus.ENABLE = nrf.TWI_ENABLE_ENABLE_Enabled + i2c.Bus.PSELSCL = nrf.RegValue(config.SCL) + i2c.Bus.PSELSDA = nrf.RegValue(config.SDA) +} + +// WriteTo writes a slice of data bytes to a peripheral with a specific address. +func (i2c I2C) WriteTo(address uint8, data []byte) { + i2c.Bus.ADDRESS = nrf.RegValue(address) + i2c.Bus.TASKS_STARTTX = 1 + for _, v := range data { + i2c.Bus.TXD = nrf.RegValue(v) + for i2c.Bus.EVENTS_TXDSENT == 0 { + } + i2c.Bus.EVENTS_TXDSENT = 0 + } + + // Assume stop after write. + i2c.Bus.TASKS_STOP = 1 + for i2c.Bus.EVENTS_STOPPED == 0 { + } + i2c.Bus.EVENTS_STOPPED = 0 +} + +// ReadFrom reads a slice of data bytes from an I2C peripheral with a specific address. +func (i2c I2C) ReadFrom(address uint8, data []byte) { + i2c.Bus.ADDRESS = nrf.RegValue(address) + i2c.Bus.TASKS_STARTRX = 1 + for i, _ := range data { + for i2c.Bus.EVENTS_RXDREADY == 0 { + } + i2c.Bus.EVENTS_RXDREADY = 0 + data[i] = byte(i2c.Bus.RXD) + } + + // Assume stop after read. + i2c.Bus.TASKS_STOP = 1 + for i2c.Bus.EVENTS_STOPPED == 0 { + } + i2c.Bus.EVENTS_STOPPED = 0 +}