nrf: refactor code a bit to reduce duplication
The nrf52 series is all very similar and copying the code only makes it harder to maintain the code or to add more chips in the nrf52 series (for example, the nrf52833 as used in the micro:bit v2). This commit also has a small improvement regarding pins: it now includes chip-level pin names (P0.00, P0.01, etc) to the machine package.
Этот коммит содержится в:
родитель
43a31467d3
коммит
ce539ce583
3 изменённых файлов: 203 добавлений и 321 удалений
|
@ -4,17 +4,48 @@ package machine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"device/nrf"
|
"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 (
|
var (
|
||||||
UART0 = NRF_UART0
|
UART0 = NRF_UART0
|
||||||
)
|
)
|
||||||
|
|
||||||
func CPUFrequency() uint32 {
|
|
||||||
return 64000000
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get peripheral and pin number for this GPIO pin.
|
// Get peripheral and pin number for this GPIO pin.
|
||||||
func (p Pin) getPortPin() (*nrf.GPIO_Type, uint32) {
|
func (p Pin) getPortPin() (*nrf.GPIO_Type, uint32) {
|
||||||
return nrf.P0, uint32(p)
|
return nrf.P0, uint32(p)
|
||||||
|
@ -30,165 +61,9 @@ func (i2c I2C) setPins(scl, sda Pin) {
|
||||||
i2c.Bus.PSELSDA.Set(uint32(sda))
|
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
|
// PWM
|
||||||
var (
|
var (
|
||||||
pwmChannelPins = [3]uint32{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
|
pwmChannelPins = [3]uint32{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
|
||||||
pwms = [3]*nrf.PWM_Type{nrf.PWM0, nrf.PWM1, nrf.PWM2}
|
pwms = [3]*nrf.PWM_Type{nrf.PWM0, nrf.PWM1, nrf.PWM2}
|
||||||
pwmChannelSequence [3]uint16
|
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,13 +4,8 @@ package machine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"device/nrf"
|
"device/nrf"
|
||||||
"unsafe"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func CPUFrequency() uint32 {
|
|
||||||
return 64000000
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hardware pins
|
// Hardware pins
|
||||||
const (
|
const (
|
||||||
P0_00 Pin = 0
|
P0_00 Pin = 0
|
||||||
|
@ -82,164 +77,9 @@ func (i2c I2C) setPins(scl, sda Pin) {
|
||||||
i2c.Bus.PSEL.SDA.Set(uint32(sda))
|
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
|
// PWM
|
||||||
var (
|
var (
|
||||||
pwmChannelPins = [4]uint32{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
|
pwmChannelPins = [4]uint32{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
|
||||||
pwms = [4]*nrf.PWM_Type{nrf.PWM0, nrf.PWM1, nrf.PWM2, nrf.PWM3}
|
pwms = [4]*nrf.PWM_Type{nrf.PWM0, nrf.PWM1, nrf.PWM2, nrf.PWM3}
|
||||||
pwmChannelSequence [4]uint16
|
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
167
src/machine/machine_nrf528xx.go
Обычный файл
167
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Загрузка…
Создание таблицы
Сослаться в новой задаче