Skip to content

Commit 8f7b7e6

Browse files
deadprogramaykevl
authored andcommitted
nrf52: implement ADC and PWM interfaces
Signed-off-by: Ron Evans <[email protected]>
1 parent 3e98fbc commit 8f7b7e6

File tree

2 files changed

+164
-0
lines changed

2 files changed

+164
-0
lines changed

src/machine/board_pca10040.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,13 @@ const (
2525
UART_TX_PIN = 6
2626
UART_RX_PIN = 8
2727
)
28+
29+
// ADC pins
30+
const (
31+
ADC0 = 3
32+
ADC1 = 4
33+
ADC2 = 28
34+
ADC3 = 29
35+
ADC4 = 30
36+
ADC5 = 31
37+
)

src/machine/machine_nrf52.go

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
// +build nrf52
2+
3+
package machine
4+
5+
import (
6+
"device/nrf"
7+
"unsafe"
8+
)
9+
10+
// InitADC initializes the registers needed for ADC.
11+
func InitADC() {
12+
return // no specific setup on nrf52 machine.
13+
}
14+
15+
// Configure configures an ADC pin to be able to read analog data.
16+
func (a ADC) Configure() {
17+
return // no pin specific setup on nrf52 machine.
18+
}
19+
20+
// Get returns the current value of a ADC pin in the range 0..0xffff.
21+
func (a ADC) Get() uint16 {
22+
var pwmPin uint32
23+
var value int16
24+
25+
switch a.Pin {
26+
case 2:
27+
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput0
28+
29+
case 3:
30+
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput1
31+
32+
case 4:
33+
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput2
34+
35+
case 5:
36+
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput3
37+
38+
case 28:
39+
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput4
40+
41+
case 29:
42+
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput5
43+
44+
case 30:
45+
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput6
46+
47+
case 31:
48+
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput7
49+
50+
default:
51+
return 0
52+
}
53+
54+
nrf.SAADC.RESOLUTION = nrf.SAADC_RESOLUTION_VAL_12bit
55+
56+
// Enable ADC.
57+
nrf.SAADC.ENABLE = (nrf.SAADC_ENABLE_ENABLE_Enabled << nrf.SAADC_ENABLE_ENABLE_Pos)
58+
for i := 0; i < 8; i++ {
59+
nrf.SAADC.CH[i].PSELN = nrf.SAADC_CH_PSELP_PSELP_NC
60+
nrf.SAADC.CH[i].PSELP = nrf.SAADC_CH_PSELP_PSELP_NC
61+
}
62+
63+
// Configure ADC.
64+
nrf.SAADC.CH[0].CONFIG = ((nrf.SAADC_CH_CONFIG_RESP_Bypass << nrf.SAADC_CH_CONFIG_RESP_Pos) & nrf.SAADC_CH_CONFIG_RESP_Msk) |
65+
((nrf.SAADC_CH_CONFIG_RESP_Bypass << nrf.SAADC_CH_CONFIG_RESN_Pos) & nrf.SAADC_CH_CONFIG_RESN_Msk) |
66+
((nrf.SAADC_CH_CONFIG_GAIN_Gain1_5 << nrf.SAADC_CH_CONFIG_GAIN_Pos) & nrf.SAADC_CH_CONFIG_GAIN_Msk) |
67+
((nrf.SAADC_CH_CONFIG_REFSEL_Internal << nrf.SAADC_CH_CONFIG_REFSEL_Pos) & nrf.SAADC_CH_CONFIG_REFSEL_Msk) |
68+
((nrf.SAADC_CH_CONFIG_TACQ_3us << nrf.SAADC_CH_CONFIG_TACQ_Pos) & nrf.SAADC_CH_CONFIG_TACQ_Msk) |
69+
((nrf.SAADC_CH_CONFIG_MODE_SE << nrf.SAADC_CH_CONFIG_MODE_Pos) & nrf.SAADC_CH_CONFIG_MODE_Msk)
70+
71+
// Set pin to read.
72+
nrf.SAADC.CH[0].PSELN = nrf.RegValue(pwmPin)
73+
nrf.SAADC.CH[0].PSELP = nrf.RegValue(pwmPin)
74+
75+
// Destination for sample result.
76+
nrf.SAADC.RESULT.PTR = nrf.RegValue(uintptr(unsafe.Pointer(&value)))
77+
nrf.SAADC.RESULT.MAXCNT = 1 // One sample
78+
79+
// Start tasks.
80+
nrf.SAADC.TASKS_START = 1
81+
for nrf.SAADC.EVENTS_STARTED == 0 {
82+
}
83+
nrf.SAADC.EVENTS_STARTED = 0x00
84+
85+
// Start the sample task.
86+
nrf.SAADC.TASKS_SAMPLE = 1
87+
88+
// Wait until the sample task is done.
89+
for nrf.SAADC.EVENTS_END == 0 {
90+
}
91+
nrf.SAADC.EVENTS_END = 0x00
92+
93+
// Stop the ADC
94+
nrf.SAADC.TASKS_STOP = 1
95+
for nrf.SAADC.EVENTS_STOPPED == 0 {
96+
}
97+
nrf.SAADC.EVENTS_STOPPED = 0
98+
99+
// Disable the ADC.
100+
nrf.SAADC.ENABLE = (nrf.SAADC_ENABLE_ENABLE_Disabled << nrf.SAADC_ENABLE_ENABLE_Pos)
101+
102+
if value < 0 {
103+
value = 0
104+
}
105+
106+
// Return 16-bit result from 12-bit value.
107+
return uint16(value << 4)
108+
}
109+
110+
// PWM
111+
var (
112+
pwmChannelPins = [3]uint32{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
113+
pwms = [3]*nrf.PWM_Type{nrf.PWM0, nrf.PWM1, nrf.PWM2}
114+
pwmChannelSequence [3]uint16
115+
)
116+
117+
// InitPWM initializes the registers needed for PWM.
118+
func InitPWM() {
119+
return
120+
}
121+
122+
// Configure configures a PWM pin for output.
123+
func (pwm PWM) Configure() {
124+
}
125+
126+
// Set turns on the duty cycle for a PWM pin using the provided value.
127+
func (pwm PWM) Set(value uint16) {
128+
for i := 0; i < 3; i++ {
129+
if pwmChannelPins[i] == 0xFFFFFFFF || pwmChannelPins[i] == uint32(pwm.Pin) {
130+
pwmChannelPins[i] = uint32(pwm.Pin)
131+
pwmChannelSequence[i] = (value >> 2) | 0x8000 // set bit 15 to invert polarity
132+
133+
p := pwms[i]
134+
135+
p.PSEL.OUT[0] = nrf.RegValue(pwm.Pin)
136+
p.PSEL.OUT[1] = nrf.RegValue(pwm.Pin)
137+
p.PSEL.OUT[2] = nrf.RegValue(pwm.Pin)
138+
p.PSEL.OUT[3] = nrf.RegValue(pwm.Pin)
139+
p.ENABLE = (nrf.PWM_ENABLE_ENABLE_Enabled << nrf.PWM_ENABLE_ENABLE_Pos)
140+
p.PRESCALER = nrf.PWM_PRESCALER_PRESCALER_DIV_2
141+
p.MODE = nrf.PWM_MODE_UPDOWN_Up
142+
p.COUNTERTOP = 16384 // frequency
143+
p.LOOP = 0
144+
p.DECODER = (nrf.PWM_DECODER_LOAD_Common << nrf.PWM_DECODER_LOAD_Pos) | (nrf.PWM_DECODER_MODE_RefreshCount << nrf.PWM_DECODER_MODE_Pos)
145+
p.SEQ[0].PTR = nrf.RegValue(uintptr(unsafe.Pointer(&pwmChannelSequence[i])))
146+
p.SEQ[0].CNT = 1
147+
p.SEQ[0].REFRESH = 1
148+
p.SEQ[0].ENDDELAY = 0
149+
p.TASKS_SEQSTART[0] = 1
150+
151+
break
152+
}
153+
}
154+
}

0 commit comments

Comments
 (0)