1// +build nrf52840 2 3package machine 4 5import ( 6 "device/nrf" 7 "unsafe" 8) 9 10func CPUFrequency() uint32 { 11 return 64000000 12} 13 14// Hardware pins 15const ( 16 P0_00 Pin = 0 17 P0_01 Pin = 1 18 P0_02 Pin = 2 19 P0_03 Pin = 3 20 P0_04 Pin = 4 21 P0_05 Pin = 5 22 P0_06 Pin = 6 23 P0_07 Pin = 7 24 P0_08 Pin = 8 25 P0_09 Pin = 9 26 P0_10 Pin = 10 27 P0_11 Pin = 11 28 P0_12 Pin = 12 29 P0_13 Pin = 13 30 P0_14 Pin = 14 31 P0_15 Pin = 15 32 P0_16 Pin = 16 33 P0_17 Pin = 17 34 P0_18 Pin = 18 35 P0_19 Pin = 19 36 P0_20 Pin = 20 37 P0_21 Pin = 21 38 P0_22 Pin = 22 39 P0_23 Pin = 23 40 P0_24 Pin = 24 41 P0_25 Pin = 25 42 P0_26 Pin = 26 43 P0_27 Pin = 27 44 P0_28 Pin = 28 45 P0_29 Pin = 29 46 P0_30 Pin = 30 47 P0_31 Pin = 31 48 P1_00 Pin = 32 49 P1_01 Pin = 33 50 P1_02 Pin = 34 51 P1_03 Pin = 35 52 P1_04 Pin = 36 53 P1_05 Pin = 37 54 P1_06 Pin = 38 55 P1_07 Pin = 39 56 P1_08 Pin = 40 57 P1_09 Pin = 41 58 P1_10 Pin = 42 59 P1_11 Pin = 43 60 P1_12 Pin = 44 61 P1_13 Pin = 45 62 P1_14 Pin = 46 63 P1_15 Pin = 47 64) 65 66// Get peripheral and pin number for this GPIO pin. 67func (p Pin) getPortPin() (*nrf.GPIO_Type, uint32) { 68 if p >= 32 { 69 return nrf.P1, uint32(p - 32) 70 } else { 71 return nrf.P0, uint32(p) 72 } 73} 74 75func (uart UART) setPins(tx, rx Pin) { 76 nrf.UART0.PSEL.TXD.Set(uint32(tx)) 77 nrf.UART0.PSEL.RXD.Set(uint32(rx)) 78} 79 80func (i2c I2C) setPins(scl, sda Pin) { 81 i2c.Bus.PSEL.SCL.Set(uint32(scl)) 82 i2c.Bus.PSEL.SDA.Set(uint32(sda)) 83} 84 85// SPI 86func (spi SPI) setPins(sck, sdo, sdi Pin) { 87 if sck == 0 { 88 sck = SPI0_SCK_PIN 89 } 90 if sdo == 0 { 91 sdo = SPI0_SDO_PIN 92 } 93 if sdi == 0 { 94 sdi = SPI0_SDI_PIN 95 } 96 spi.Bus.PSEL.SCK.Set(uint32(sck)) 97 spi.Bus.PSEL.MOSI.Set(uint32(sdo)) 98 spi.Bus.PSEL.MISO.Set(uint32(sdi)) 99} 100 101// InitADC initializes the registers needed for ADC. 102func InitADC() { 103 return // no specific setup on nrf52840 machine. 104} 105 106// Configure configures an ADC pin to be able to read analog data. 107func (a ADC) Configure() error { 108 return nil // no pin specific setup on nrf52840 machine. 109} 110 111// Get returns the current value of a ADC pin in the range 0..0xffff. 112func (a ADC) Get() uint16 { 113 var pwmPin uint32 114 var value int16 115 116 switch a.Pin { 117 case 2: 118 pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput0 119 120 case 3: 121 pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput1 122 123 case 4: 124 pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput2 125 126 case 5: 127 pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput3 128 129 case 28: 130 pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput4 131 132 case 29: 133 pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput5 134 135 case 30: 136 pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput6 137 138 case 31: 139 pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput7 140 141 default: 142 return 0 143 } 144 145 nrf.SAADC.RESOLUTION.Set(nrf.SAADC_RESOLUTION_VAL_12bit) 146 147 // Enable ADC. 148 nrf.SAADC.ENABLE.Set(nrf.SAADC_ENABLE_ENABLE_Enabled << nrf.SAADC_ENABLE_ENABLE_Pos) 149 for i := 0; i < 8; i++ { 150 nrf.SAADC.CH[i].PSELN.Set(nrf.SAADC_CH_PSELP_PSELP_NC) 151 nrf.SAADC.CH[i].PSELP.Set(nrf.SAADC_CH_PSELP_PSELP_NC) 152 } 153 154 // Configure ADC. 155 nrf.SAADC.CH[0].CONFIG.Set(((nrf.SAADC_CH_CONFIG_RESP_Bypass << nrf.SAADC_CH_CONFIG_RESP_Pos) & nrf.SAADC_CH_CONFIG_RESP_Msk) | 156 ((nrf.SAADC_CH_CONFIG_RESP_Bypass << nrf.SAADC_CH_CONFIG_RESN_Pos) & nrf.SAADC_CH_CONFIG_RESN_Msk) | 157 ((nrf.SAADC_CH_CONFIG_GAIN_Gain1_5 << nrf.SAADC_CH_CONFIG_GAIN_Pos) & nrf.SAADC_CH_CONFIG_GAIN_Msk) | 158 ((nrf.SAADC_CH_CONFIG_REFSEL_Internal << nrf.SAADC_CH_CONFIG_REFSEL_Pos) & nrf.SAADC_CH_CONFIG_REFSEL_Msk) | 159 ((nrf.SAADC_CH_CONFIG_TACQ_3us << nrf.SAADC_CH_CONFIG_TACQ_Pos) & nrf.SAADC_CH_CONFIG_TACQ_Msk) | 160 ((nrf.SAADC_CH_CONFIG_MODE_SE << nrf.SAADC_CH_CONFIG_MODE_Pos) & nrf.SAADC_CH_CONFIG_MODE_Msk)) 161 162 // Set pin to read. 163 nrf.SAADC.CH[0].PSELN.Set(pwmPin) 164 nrf.SAADC.CH[0].PSELP.Set(pwmPin) 165 166 // Destination for sample result. 167 nrf.SAADC.RESULT.PTR.Set(uint32(uintptr(unsafe.Pointer(&value)))) 168 nrf.SAADC.RESULT.MAXCNT.Set(1) // One sample 169 170 // Start tasks. 171 nrf.SAADC.TASKS_START.Set(1) 172 for nrf.SAADC.EVENTS_STARTED.Get() == 0 { 173 } 174 nrf.SAADC.EVENTS_STARTED.Set(0x00) 175 176 // Start the sample task. 177 nrf.SAADC.TASKS_SAMPLE.Set(1) 178 179 // Wait until the sample task is done. 180 for nrf.SAADC.EVENTS_END.Get() == 0 { 181 } 182 nrf.SAADC.EVENTS_END.Set(0x00) 183 184 // Stop the ADC 185 nrf.SAADC.TASKS_STOP.Set(1) 186 for nrf.SAADC.EVENTS_STOPPED.Get() == 0 { 187 } 188 nrf.SAADC.EVENTS_STOPPED.Set(0) 189 190 // Disable the ADC. 191 nrf.SAADC.ENABLE.Set(nrf.SAADC_ENABLE_ENABLE_Disabled << nrf.SAADC_ENABLE_ENABLE_Pos) 192 193 if value < 0 { 194 value = 0 195 } 196 197 // Return 16-bit result from 12-bit value. 198 return uint16(value << 4) 199} 200 201// PWM 202var ( 203 pwmChannelPins = [4]uint32{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF} 204 pwms = [4]*nrf.PWM_Type{nrf.PWM0, nrf.PWM1, nrf.PWM2, nrf.PWM3} 205 pwmChannelSequence [4]uint16 206) 207 208// InitPWM initializes the registers needed for PWM. 209func InitPWM() { 210 return 211} 212 213// Configure configures a PWM pin for output. 214func (pwm PWM) Configure() { 215} 216 217// Set turns on the duty cycle for a PWM pin using the provided value. 218func (pwm PWM) Set(value uint16) { 219 for i := 0; i < 4; i++ { 220 if pwmChannelPins[i] == 0xFFFFFFFF || pwmChannelPins[i] == uint32(pwm.Pin) { 221 pwmChannelPins[i] = uint32(pwm.Pin) 222 pwmChannelSequence[i] = (value >> 2) | 0x8000 // set bit 15 to invert polarity 223 224 p := pwms[i] 225 226 p.PSEL.OUT[0].Set(uint32(pwm.Pin)) 227 p.PSEL.OUT[1].Set(uint32(pwm.Pin)) 228 p.PSEL.OUT[2].Set(uint32(pwm.Pin)) 229 p.PSEL.OUT[3].Set(uint32(pwm.Pin)) 230 p.ENABLE.Set(nrf.PWM_ENABLE_ENABLE_Enabled << nrf.PWM_ENABLE_ENABLE_Pos) 231 p.PRESCALER.Set(nrf.PWM_PRESCALER_PRESCALER_DIV_2) 232 p.MODE.Set(nrf.PWM_MODE_UPDOWN_Up) 233 p.COUNTERTOP.Set(16384) // frequency 234 p.LOOP.Set(0) 235 p.DECODER.Set((nrf.PWM_DECODER_LOAD_Common << nrf.PWM_DECODER_LOAD_Pos) | (nrf.PWM_DECODER_MODE_RefreshCount << nrf.PWM_DECODER_MODE_Pos)) 236 p.SEQ[0].PTR.Set(uint32(uintptr(unsafe.Pointer(&pwmChannelSequence[i])))) 237 p.SEQ[0].CNT.Set(1) 238 p.SEQ[0].REFRESH.Set(1) 239 p.SEQ[0].ENDDELAY.Set(0) 240 p.TASKS_SEQSTART[0].Set(1) 241 242 break 243 } 244 } 245} 246