diff --git a/src/machine/machine_nrf52.go b/src/machine/machine_nrf52.go index 880126a1..189f0a32 100644 --- a/src/machine/machine_nrf52.go +++ b/src/machine/machine_nrf52.go @@ -4,17 +4,48 @@ package machine import ( "device/nrf" - "unsafe" +) + +// Hardware pins +const ( + P0_00 Pin = 0 + P0_01 Pin = 1 + P0_02 Pin = 2 + P0_03 Pin = 3 + P0_04 Pin = 4 + P0_05 Pin = 5 + P0_06 Pin = 6 + P0_07 Pin = 7 + P0_08 Pin = 8 + P0_09 Pin = 9 + P0_10 Pin = 10 + P0_11 Pin = 11 + P0_12 Pin = 12 + P0_13 Pin = 13 + P0_14 Pin = 14 + P0_15 Pin = 15 + P0_16 Pin = 16 + P0_17 Pin = 17 + P0_18 Pin = 18 + P0_19 Pin = 19 + P0_20 Pin = 20 + P0_21 Pin = 21 + P0_22 Pin = 22 + P0_23 Pin = 23 + P0_24 Pin = 24 + P0_25 Pin = 25 + P0_26 Pin = 26 + P0_27 Pin = 27 + P0_28 Pin = 28 + P0_29 Pin = 29 + P0_30 Pin = 30 + P0_31 Pin = 31 ) var ( UART0 = NRF_UART0 ) -func CPUFrequency() uint32 { - return 64000000 -} - // Get peripheral and pin number for this GPIO pin. func (p Pin) getPortPin() (*nrf.GPIO_Type, uint32) { return nrf.P0, uint32(p) @@ -30,165 +61,9 @@ func (i2c I2C) setPins(scl, sda Pin) { i2c.Bus.PSELSDA.Set(uint32(sda)) } -// SPI -func (spi SPI) setPins(sck, sdo, sdi Pin) { - if sck == 0 { - sck = SPI0_SCK_PIN - } - if sdo == 0 { - sdo = SPI0_SDO_PIN - } - if sdi == 0 { - sdi = SPI0_SDI_PIN - } - spi.Bus.PSEL.SCK.Set(uint32(sck)) - spi.Bus.PSEL.MOSI.Set(uint32(sdo)) - spi.Bus.PSEL.MISO.Set(uint32(sdi)) -} - -// InitADC initializes the registers needed for ADC. -func InitADC() { - return // no specific setup on nrf52 machine. -} - -// Configure configures an ADC pin to be able to read analog data. -func (a ADC) Configure() { - return // no pin specific setup on nrf52 machine. -} - -// Get returns the current value of a ADC pin in the range 0..0xffff. -func (a ADC) Get() uint16 { - var pwmPin uint32 - var value int16 - - switch a.Pin { - case 2: - pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput0 - - case 3: - pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput1 - - case 4: - pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput2 - - case 5: - pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput3 - - case 28: - pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput4 - - case 29: - pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput5 - - case 30: - pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput6 - - case 31: - pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput7 - - default: - return 0 - } - - nrf.SAADC.RESOLUTION.Set(nrf.SAADC_RESOLUTION_VAL_12bit) - - // Enable ADC. - nrf.SAADC.ENABLE.Set(nrf.SAADC_ENABLE_ENABLE_Enabled << nrf.SAADC_ENABLE_ENABLE_Pos) - for i := 0; i < 8; i++ { - nrf.SAADC.CH[i].PSELN.Set(nrf.SAADC_CH_PSELP_PSELP_NC) - nrf.SAADC.CH[i].PSELP.Set(nrf.SAADC_CH_PSELP_PSELP_NC) - } - - // Configure ADC. - nrf.SAADC.CH[0].CONFIG.Set(((nrf.SAADC_CH_CONFIG_RESP_Bypass << nrf.SAADC_CH_CONFIG_RESP_Pos) & nrf.SAADC_CH_CONFIG_RESP_Msk) | - ((nrf.SAADC_CH_CONFIG_RESP_Bypass << nrf.SAADC_CH_CONFIG_RESN_Pos) & nrf.SAADC_CH_CONFIG_RESN_Msk) | - ((nrf.SAADC_CH_CONFIG_GAIN_Gain1_5 << nrf.SAADC_CH_CONFIG_GAIN_Pos) & nrf.SAADC_CH_CONFIG_GAIN_Msk) | - ((nrf.SAADC_CH_CONFIG_REFSEL_Internal << nrf.SAADC_CH_CONFIG_REFSEL_Pos) & nrf.SAADC_CH_CONFIG_REFSEL_Msk) | - ((nrf.SAADC_CH_CONFIG_TACQ_3us << nrf.SAADC_CH_CONFIG_TACQ_Pos) & nrf.SAADC_CH_CONFIG_TACQ_Msk) | - ((nrf.SAADC_CH_CONFIG_MODE_SE << nrf.SAADC_CH_CONFIG_MODE_Pos) & nrf.SAADC_CH_CONFIG_MODE_Msk)) - - // Set pin to read. - nrf.SAADC.CH[0].PSELN.Set(pwmPin) - nrf.SAADC.CH[0].PSELP.Set(pwmPin) - - // Destination for sample result. - nrf.SAADC.RESULT.PTR.Set(uint32(uintptr(unsafe.Pointer(&value)))) - nrf.SAADC.RESULT.MAXCNT.Set(1) // One sample - - // Start tasks. - nrf.SAADC.TASKS_START.Set(1) - for nrf.SAADC.EVENTS_STARTED.Get() == 0 { - } - nrf.SAADC.EVENTS_STARTED.Set(0x00) - - // Start the sample task. - nrf.SAADC.TASKS_SAMPLE.Set(1) - - // Wait until the sample task is done. - for nrf.SAADC.EVENTS_END.Get() == 0 { - } - nrf.SAADC.EVENTS_END.Set(0x00) - - // Stop the ADC - nrf.SAADC.TASKS_STOP.Set(1) - for nrf.SAADC.EVENTS_STOPPED.Get() == 0 { - } - nrf.SAADC.EVENTS_STOPPED.Set(0) - - // Disable the ADC. - nrf.SAADC.ENABLE.Set(nrf.SAADC_ENABLE_ENABLE_Disabled << nrf.SAADC_ENABLE_ENABLE_Pos) - - if value < 0 { - value = 0 - } - - // Return 16-bit result from 12-bit value. - return uint16(value << 4) -} - // PWM var ( pwmChannelPins = [3]uint32{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF} pwms = [3]*nrf.PWM_Type{nrf.PWM0, nrf.PWM1, nrf.PWM2} pwmChannelSequence [3]uint16 ) - -// InitPWM initializes the registers needed for PWM. -func InitPWM() { - return -} - -// Configure configures a PWM pin for output. -func (pwm PWM) Configure() error { - return nil -} - -// Set turns on the duty cycle for a PWM pin using the provided value. -func (pwm PWM) Set(value uint16) { - for i := 0; i < 3; i++ { - if pwmChannelPins[i] == 0xFFFFFFFF || pwmChannelPins[i] == uint32(pwm.Pin) { - pwmChannelPins[i] = uint32(pwm.Pin) - pwmChannelSequence[i] = (value >> 2) | 0x8000 // set bit 15 to invert polarity - - p := pwms[i] - - p.PSEL.OUT[0].Set(uint32(pwm.Pin)) - p.PSEL.OUT[1].Set(uint32(pwm.Pin)) - p.PSEL.OUT[2].Set(uint32(pwm.Pin)) - p.PSEL.OUT[3].Set(uint32(pwm.Pin)) - p.ENABLE.Set(nrf.PWM_ENABLE_ENABLE_Enabled << nrf.PWM_ENABLE_ENABLE_Pos) - p.PRESCALER.Set(nrf.PWM_PRESCALER_PRESCALER_DIV_2) - p.MODE.Set(nrf.PWM_MODE_UPDOWN_Up) - p.COUNTERTOP.Set(16384) // frequency - p.LOOP.Set(0) - p.DECODER.Set((nrf.PWM_DECODER_LOAD_Common << nrf.PWM_DECODER_LOAD_Pos) | (nrf.PWM_DECODER_MODE_RefreshCount << nrf.PWM_DECODER_MODE_Pos)) - p.SEQ[0].PTR.Set(uint32(uintptr(unsafe.Pointer(&pwmChannelSequence[i])))) - p.SEQ[0].CNT.Set(1) - p.SEQ[0].REFRESH.Set(1) - p.SEQ[0].ENDDELAY.Set(0) - p.TASKS_SEQSTART[0].Set(1) - - break - } - } -} diff --git a/src/machine/machine_nrf52840.go b/src/machine/machine_nrf52840.go index 7afb9286..157495dc 100644 --- a/src/machine/machine_nrf52840.go +++ b/src/machine/machine_nrf52840.go @@ -4,13 +4,8 @@ package machine import ( "device/nrf" - "unsafe" ) -func CPUFrequency() uint32 { - return 64000000 -} - // Hardware pins const ( P0_00 Pin = 0 @@ -82,164 +77,9 @@ func (i2c I2C) setPins(scl, sda Pin) { i2c.Bus.PSEL.SDA.Set(uint32(sda)) } -// SPI -func (spi SPI) setPins(sck, sdo, sdi Pin) { - if sck == 0 { - sck = SPI0_SCK_PIN - } - if sdo == 0 { - sdo = SPI0_SDO_PIN - } - if sdi == 0 { - sdi = SPI0_SDI_PIN - } - spi.Bus.PSEL.SCK.Set(uint32(sck)) - spi.Bus.PSEL.MOSI.Set(uint32(sdo)) - spi.Bus.PSEL.MISO.Set(uint32(sdi)) -} - -// InitADC initializes the registers needed for ADC. -func InitADC() { - return // no specific setup on nrf52840 machine. -} - -// Configure configures an ADC pin to be able to read analog data. -func (a ADC) Configure() error { - return nil // no pin specific setup on nrf52840 machine. -} - -// Get returns the current value of a ADC pin in the range 0..0xffff. -func (a ADC) Get() uint16 { - var pwmPin uint32 - var value int16 - - switch a.Pin { - case 2: - pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput0 - - case 3: - pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput1 - - case 4: - pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput2 - - case 5: - pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput3 - - case 28: - pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput4 - - case 29: - pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput5 - - case 30: - pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput6 - - case 31: - pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput7 - - default: - return 0 - } - - nrf.SAADC.RESOLUTION.Set(nrf.SAADC_RESOLUTION_VAL_12bit) - - // Enable ADC. - nrf.SAADC.ENABLE.Set(nrf.SAADC_ENABLE_ENABLE_Enabled << nrf.SAADC_ENABLE_ENABLE_Pos) - for i := 0; i < 8; i++ { - nrf.SAADC.CH[i].PSELN.Set(nrf.SAADC_CH_PSELP_PSELP_NC) - nrf.SAADC.CH[i].PSELP.Set(nrf.SAADC_CH_PSELP_PSELP_NC) - } - - // Configure ADC. - nrf.SAADC.CH[0].CONFIG.Set(((nrf.SAADC_CH_CONFIG_RESP_Bypass << nrf.SAADC_CH_CONFIG_RESP_Pos) & nrf.SAADC_CH_CONFIG_RESP_Msk) | - ((nrf.SAADC_CH_CONFIG_RESP_Bypass << nrf.SAADC_CH_CONFIG_RESN_Pos) & nrf.SAADC_CH_CONFIG_RESN_Msk) | - ((nrf.SAADC_CH_CONFIG_GAIN_Gain1_5 << nrf.SAADC_CH_CONFIG_GAIN_Pos) & nrf.SAADC_CH_CONFIG_GAIN_Msk) | - ((nrf.SAADC_CH_CONFIG_REFSEL_Internal << nrf.SAADC_CH_CONFIG_REFSEL_Pos) & nrf.SAADC_CH_CONFIG_REFSEL_Msk) | - ((nrf.SAADC_CH_CONFIG_TACQ_3us << nrf.SAADC_CH_CONFIG_TACQ_Pos) & nrf.SAADC_CH_CONFIG_TACQ_Msk) | - ((nrf.SAADC_CH_CONFIG_MODE_SE << nrf.SAADC_CH_CONFIG_MODE_Pos) & nrf.SAADC_CH_CONFIG_MODE_Msk)) - - // Set pin to read. - nrf.SAADC.CH[0].PSELN.Set(pwmPin) - nrf.SAADC.CH[0].PSELP.Set(pwmPin) - - // Destination for sample result. - nrf.SAADC.RESULT.PTR.Set(uint32(uintptr(unsafe.Pointer(&value)))) - nrf.SAADC.RESULT.MAXCNT.Set(1) // One sample - - // Start tasks. - nrf.SAADC.TASKS_START.Set(1) - for nrf.SAADC.EVENTS_STARTED.Get() == 0 { - } - nrf.SAADC.EVENTS_STARTED.Set(0x00) - - // Start the sample task. - nrf.SAADC.TASKS_SAMPLE.Set(1) - - // Wait until the sample task is done. - for nrf.SAADC.EVENTS_END.Get() == 0 { - } - nrf.SAADC.EVENTS_END.Set(0x00) - - // Stop the ADC - nrf.SAADC.TASKS_STOP.Set(1) - for nrf.SAADC.EVENTS_STOPPED.Get() == 0 { - } - nrf.SAADC.EVENTS_STOPPED.Set(0) - - // Disable the ADC. - nrf.SAADC.ENABLE.Set(nrf.SAADC_ENABLE_ENABLE_Disabled << nrf.SAADC_ENABLE_ENABLE_Pos) - - if value < 0 { - value = 0 - } - - // Return 16-bit result from 12-bit value. - return uint16(value << 4) -} - // PWM var ( pwmChannelPins = [4]uint32{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF} pwms = [4]*nrf.PWM_Type{nrf.PWM0, nrf.PWM1, nrf.PWM2, nrf.PWM3} pwmChannelSequence [4]uint16 ) - -// InitPWM initializes the registers needed for PWM. -func InitPWM() { - return -} - -// Configure configures a PWM pin for output. -func (pwm PWM) Configure() { -} - -// Set turns on the duty cycle for a PWM pin using the provided value. -func (pwm PWM) Set(value uint16) { - for i := 0; i < 4; i++ { - if pwmChannelPins[i] == 0xFFFFFFFF || pwmChannelPins[i] == uint32(pwm.Pin) { - pwmChannelPins[i] = uint32(pwm.Pin) - pwmChannelSequence[i] = (value >> 2) | 0x8000 // set bit 15 to invert polarity - - p := pwms[i] - - p.PSEL.OUT[0].Set(uint32(pwm.Pin)) - p.PSEL.OUT[1].Set(uint32(pwm.Pin)) - p.PSEL.OUT[2].Set(uint32(pwm.Pin)) - p.PSEL.OUT[3].Set(uint32(pwm.Pin)) - p.ENABLE.Set(nrf.PWM_ENABLE_ENABLE_Enabled << nrf.PWM_ENABLE_ENABLE_Pos) - p.PRESCALER.Set(nrf.PWM_PRESCALER_PRESCALER_DIV_2) - p.MODE.Set(nrf.PWM_MODE_UPDOWN_Up) - p.COUNTERTOP.Set(16384) // frequency - p.LOOP.Set(0) - p.DECODER.Set((nrf.PWM_DECODER_LOAD_Common << nrf.PWM_DECODER_LOAD_Pos) | (nrf.PWM_DECODER_MODE_RefreshCount << nrf.PWM_DECODER_MODE_Pos)) - p.SEQ[0].PTR.Set(uint32(uintptr(unsafe.Pointer(&pwmChannelSequence[i])))) - p.SEQ[0].CNT.Set(1) - p.SEQ[0].REFRESH.Set(1) - p.SEQ[0].ENDDELAY.Set(0) - p.TASKS_SEQSTART[0].Set(1) - - break - } - } -} diff --git a/src/machine/machine_nrf528xx.go b/src/machine/machine_nrf528xx.go new file mode 100644 index 00000000..2a207580 --- /dev/null +++ b/src/machine/machine_nrf528xx.go @@ -0,0 +1,167 @@ +// +build nrf52 nrf52840 + +package machine + +import ( + "device/nrf" + "unsafe" +) + +func CPUFrequency() uint32 { + return 64000000 +} + +// InitADC initializes the registers needed for ADC. +func InitADC() { + return // no specific setup on nrf52 machine. +} + +// Configure configures an ADC pin to be able to read analog data. +func (a ADC) Configure() { + return // no pin specific setup on nrf52 machine. +} + +// Get returns the current value of a ADC pin in the range 0..0xffff. +func (a ADC) Get() uint16 { + var pwmPin uint32 + var value int16 + + switch a.Pin { + case 2: + pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput0 + + case 3: + pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput1 + + case 4: + pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput2 + + case 5: + pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput3 + + case 28: + pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput4 + + case 29: + pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput5 + + case 30: + pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput6 + + case 31: + pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput7 + + default: + return 0 + } + + nrf.SAADC.RESOLUTION.Set(nrf.SAADC_RESOLUTION_VAL_12bit) + + // Enable ADC. + nrf.SAADC.ENABLE.Set(nrf.SAADC_ENABLE_ENABLE_Enabled << nrf.SAADC_ENABLE_ENABLE_Pos) + for i := 0; i < 8; i++ { + nrf.SAADC.CH[i].PSELN.Set(nrf.SAADC_CH_PSELP_PSELP_NC) + nrf.SAADC.CH[i].PSELP.Set(nrf.SAADC_CH_PSELP_PSELP_NC) + } + + // Configure ADC. + nrf.SAADC.CH[0].CONFIG.Set(((nrf.SAADC_CH_CONFIG_RESP_Bypass << nrf.SAADC_CH_CONFIG_RESP_Pos) & nrf.SAADC_CH_CONFIG_RESP_Msk) | + ((nrf.SAADC_CH_CONFIG_RESP_Bypass << nrf.SAADC_CH_CONFIG_RESN_Pos) & nrf.SAADC_CH_CONFIG_RESN_Msk) | + ((nrf.SAADC_CH_CONFIG_GAIN_Gain1_5 << nrf.SAADC_CH_CONFIG_GAIN_Pos) & nrf.SAADC_CH_CONFIG_GAIN_Msk) | + ((nrf.SAADC_CH_CONFIG_REFSEL_Internal << nrf.SAADC_CH_CONFIG_REFSEL_Pos) & nrf.SAADC_CH_CONFIG_REFSEL_Msk) | + ((nrf.SAADC_CH_CONFIG_TACQ_3us << nrf.SAADC_CH_CONFIG_TACQ_Pos) & nrf.SAADC_CH_CONFIG_TACQ_Msk) | + ((nrf.SAADC_CH_CONFIG_MODE_SE << nrf.SAADC_CH_CONFIG_MODE_Pos) & nrf.SAADC_CH_CONFIG_MODE_Msk)) + + // Set pin to read. + nrf.SAADC.CH[0].PSELN.Set(pwmPin) + nrf.SAADC.CH[0].PSELP.Set(pwmPin) + + // Destination for sample result. + nrf.SAADC.RESULT.PTR.Set(uint32(uintptr(unsafe.Pointer(&value)))) + nrf.SAADC.RESULT.MAXCNT.Set(1) // One sample + + // Start tasks. + nrf.SAADC.TASKS_START.Set(1) + for nrf.SAADC.EVENTS_STARTED.Get() == 0 { + } + nrf.SAADC.EVENTS_STARTED.Set(0x00) + + // Start the sample task. + nrf.SAADC.TASKS_SAMPLE.Set(1) + + // Wait until the sample task is done. + for nrf.SAADC.EVENTS_END.Get() == 0 { + } + nrf.SAADC.EVENTS_END.Set(0x00) + + // Stop the ADC + nrf.SAADC.TASKS_STOP.Set(1) + for nrf.SAADC.EVENTS_STOPPED.Get() == 0 { + } + nrf.SAADC.EVENTS_STOPPED.Set(0) + + // Disable the ADC. + nrf.SAADC.ENABLE.Set(nrf.SAADC_ENABLE_ENABLE_Disabled << nrf.SAADC_ENABLE_ENABLE_Pos) + + if value < 0 { + value = 0 + } + + // Return 16-bit result from 12-bit value. + return uint16(value << 4) +} + +// SPI +func (spi SPI) setPins(sck, sdo, sdi Pin) { + if sck == 0 { + sck = SPI0_SCK_PIN + } + if sdo == 0 { + sdo = SPI0_SDO_PIN + } + if sdi == 0 { + sdi = SPI0_SDI_PIN + } + spi.Bus.PSEL.SCK.Set(uint32(sck)) + spi.Bus.PSEL.MOSI.Set(uint32(sdo)) + spi.Bus.PSEL.MISO.Set(uint32(sdi)) +} + +// InitPWM initializes the registers needed for PWM. +func InitPWM() { + return +} + +// Configure configures a PWM pin for output. +func (pwm PWM) Configure() { +} + +// Set turns on the duty cycle for a PWM pin using the provided value. +func (pwm PWM) Set(value uint16) { + for i := 0; i < len(pwmChannelPins); i++ { + if pwmChannelPins[i] == 0xFFFFFFFF || pwmChannelPins[i] == uint32(pwm.Pin) { + pwmChannelPins[i] = uint32(pwm.Pin) + pwmChannelSequence[i] = (value >> 2) | 0x8000 // set bit 15 to invert polarity + + p := pwms[i] + + p.PSEL.OUT[0].Set(uint32(pwm.Pin)) + p.PSEL.OUT[1].Set(uint32(pwm.Pin)) + p.PSEL.OUT[2].Set(uint32(pwm.Pin)) + p.PSEL.OUT[3].Set(uint32(pwm.Pin)) + p.ENABLE.Set(nrf.PWM_ENABLE_ENABLE_Enabled << nrf.PWM_ENABLE_ENABLE_Pos) + p.PRESCALER.Set(nrf.PWM_PRESCALER_PRESCALER_DIV_2) + p.MODE.Set(nrf.PWM_MODE_UPDOWN_Up) + p.COUNTERTOP.Set(16384) // frequency + p.LOOP.Set(0) + p.DECODER.Set((nrf.PWM_DECODER_LOAD_Common << nrf.PWM_DECODER_LOAD_Pos) | (nrf.PWM_DECODER_MODE_RefreshCount << nrf.PWM_DECODER_MODE_Pos)) + p.SEQ[0].PTR.Set(uint32(uintptr(unsafe.Pointer(&pwmChannelSequence[i])))) + p.SEQ[0].CNT.Set(1) + p.SEQ[0].REFRESH.Set(1) + p.SEQ[0].ENDDELAY.Set(0) + p.TASKS_SEQSTART[0].Set(1) + + break + } + } +}