|
| 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