@@ -188,6 +188,18 @@ func (p GPIO) Configure(config GPIOConfig) {
188
188
}
189
189
// enable port config
190
190
p .setPinCfg (sam .PORT_PINCFG0_PMUXEN )
191
+ case GPIO_ANALOG :
192
+ if p .Pin & 1 > 0 {
193
+ // odd pin, so save the even pins
194
+ val := p .getPMux () & sam .PORT_PMUX0_PMUXE_Msk
195
+ p .setPMux (val | (GPIO_ANALOG << sam .PORT_PMUX0_PMUXO_Pos ))
196
+ } else {
197
+ // even pin, so save the odd pins
198
+ val := p .getPMux () & sam .PORT_PMUX0_PMUXO_Msk
199
+ p .setPMux (val | (GPIO_COM << sam .PORT_PMUX0_PMUXE_Pos ))
200
+ }
201
+ // enable port config
202
+ p .setPinCfg (sam .PORT_PINCFG0_PMUXEN | sam .PORT_PINCFG0_DRVSTR )
191
203
}
192
204
}
193
205
@@ -258,6 +270,141 @@ func (p GPIO) setPinCfg(val sam.RegValue8) {
258
270
setPinCfg (p .Pin , val )
259
271
}
260
272
273
+ // InitADC initializes the ADC.
274
+ func InitADC () {
275
+ // ADC Bias Calibration
276
+ // #define ADC_FUSES_BIASCAL_ADDR (NVMCTRL_OTP4 + 4)
277
+ // #define ADC_FUSES_BIASCAL_Pos 3 /**< \brief (NVMCTRL_OTP4) ADC Bias Calibration */
278
+ // #define ADC_FUSES_BIASCAL_Msk (0x7u << ADC_FUSES_BIASCAL_Pos)
279
+ // #define ADC_FUSES_BIASCAL(value) ((ADC_FUSES_BIASCAL_Msk & ((value) << ADC_FUSES_BIASCAL_Pos)))
280
+ // #define ADC_FUSES_LINEARITY_0_ADDR NVMCTRL_OTP4
281
+ // #define ADC_FUSES_LINEARITY_0_Pos 27 /**< \brief (NVMCTRL_OTP4) ADC Linearity bits 4:0 */
282
+ // #define ADC_FUSES_LINEARITY_0_Msk (0x1Fu << ADC_FUSES_LINEARITY_0_Pos)
283
+ // #define ADC_FUSES_LINEARITY_0(value) ((ADC_FUSES_LINEARITY_0_Msk & ((value) << ADC_FUSES_LINEARITY_0_Pos)))
284
+ // #define ADC_FUSES_LINEARITY_1_ADDR (NVMCTRL_OTP4 + 4)
285
+ // #define ADC_FUSES_LINEARITY_1_Pos 0 /**< \brief (NVMCTRL_OTP4) ADC Linearity bits 7:5 */
286
+ // #define ADC_FUSES_LINEARITY_1_Msk (0x7u << ADC_FUSES_LINEARITY_1_Pos)
287
+ // #define ADC_FUSES_LINEARITY_1(value) ((ADC_FUSES_LINEARITY_1_Msk & ((value) << ADC_FUSES_LINEARITY_1_Pos)))
288
+
289
+ biasFuse := * (* uint32 )(unsafe .Pointer (uintptr (0x00806020 ) + 4 ))
290
+ bias := sam .RegValue16 (uint16 (biasFuse >> 3 ) & uint16 (0x7 ))
291
+
292
+ // ADC Linearity bits 4:0
293
+ linearity0Fuse := * (* uint32 )(unsafe .Pointer (uintptr (0x00806020 )))
294
+ linearity := sam .RegValue16 (uint16 (linearity0Fuse >> 27 ) & uint16 (0x1f ))
295
+
296
+ // ADC Linearity bits 7:5
297
+ linearity1Fuse := * (* uint32 )(unsafe .Pointer (uintptr (0x00806020 ) + 4 ))
298
+ linearity |= sam .RegValue16 (uint16 (linearity1Fuse )& uint16 (0x7 )) << 5
299
+
300
+ // set calibration
301
+ sam .ADC .CALIB = (bias << 8 ) | linearity
302
+
303
+ // Wait for synchronization
304
+ waitADCSync ()
305
+
306
+ // Divide Clock by 32 with 12 bits resolution as default
307
+ sam .ADC .CTRLB = (sam .ADC_CTRLB_PRESCALER_DIV32 << sam .ADC_CTRLB_PRESCALER_Pos ) |
308
+ (sam .ADC_CTRLB_RESSEL_12BIT << sam .ADC_CTRLB_RESSEL_Pos )
309
+
310
+ // Sampling Time Length
311
+ sam .ADC .SAMPCTRL = 5
312
+
313
+ // Wait for synchronization
314
+ waitADCSync ()
315
+
316
+ // Use internal ground
317
+ sam .ADC .INPUTCTRL = (sam .ADC_INPUTCTRL_MUXNEG_GND << sam .ADC_INPUTCTRL_MUXNEG_Pos )
318
+
319
+ // Averaging (see datasheet table in AVGCTRL register description)
320
+ sam .ADC .AVGCTRL = (sam .ADC_AVGCTRL_SAMPLENUM_1 << sam .ADC_AVGCTRL_SAMPLENUM_Pos ) |
321
+ (0x0 << sam .ADC_AVGCTRL_ADJRES_Pos )
322
+
323
+ // Analog Reference is AREF pin (3.3v)
324
+ sam .ADC .INPUTCTRL |= (sam .ADC_INPUTCTRL_GAIN_DIV2 << sam .ADC_INPUTCTRL_GAIN_Pos )
325
+
326
+ // 1/2 VDDANA = 0.5 * 3V3 = 1.65V
327
+ sam .ADC .REFCTRL |= (sam .ADC_REFCTRL_REFSEL_INTVCC1 << sam .ADC_REFCTRL_REFSEL_Pos )
328
+ }
329
+
330
+ // Configure configures a ADCPin to be able to be used to read data.
331
+ func (a ADC ) Configure () {
332
+ GPIO {a .Pin }.Configure (GPIOConfig {Mode : GPIO_ANALOG })
333
+ return
334
+ }
335
+
336
+ // Get returns the current value of a ADC pin, in the range 0..0xffff.
337
+ func (a ADC ) Get () uint16 {
338
+ ch := a .getADCChannel ()
339
+
340
+ // Selection for the positive ADC input
341
+ sam .ADC .INPUTCTRL &^= sam .ADC_INPUTCTRL_MUXPOS_Msk
342
+ waitADCSync ()
343
+ sam .ADC .INPUTCTRL |= sam .RegValue (ch << sam .ADC_INPUTCTRL_MUXPOS_Pos )
344
+ waitADCSync ()
345
+
346
+ // Enable ADC
347
+ sam .ADC .CTRLA |= sam .ADC_CTRLA_ENABLE
348
+ waitADCSync ()
349
+
350
+ // Start conversion
351
+ sam .ADC .SWTRIG |= sam .ADC_SWTRIG_START
352
+ waitADCSync ()
353
+
354
+ // Clear the Data Ready flag
355
+ sam .ADC .INTFLAG = sam .ADC_INTFLAG_RESRDY
356
+ waitADCSync ()
357
+
358
+ // Start conversion again, since first conversion after reference voltage changed is invalid.
359
+ sam .ADC .SWTRIG |= sam .ADC_SWTRIG_START
360
+ waitADCSync ()
361
+
362
+ // Waiting for conversion to complete
363
+ for (sam .ADC .INTFLAG & sam .ADC_INTFLAG_RESRDY ) == 0 {
364
+ }
365
+ val := sam .ADC .RESULT
366
+
367
+ // Disable ADC
368
+ sam .ADC .CTRLA &^= sam .ADC_CTRLA_ENABLE
369
+ waitADCSync ()
370
+
371
+ return uint16 (val )
372
+ }
373
+
374
+ func (a ADC ) getADCChannel () uint8 {
375
+ switch a .Pin {
376
+ case PA02 :
377
+ return 0
378
+ case PB08 :
379
+ return 2
380
+ case PB09 :
381
+ return 3
382
+ case PA04 :
383
+ return 4
384
+ case PA05 :
385
+ return 5
386
+ case PA06 :
387
+ return 6
388
+ case PA07 :
389
+ return 7
390
+ case PB02 :
391
+ return 10
392
+ case PB03 :
393
+ return 11
394
+ case PA09 :
395
+ return 17
396
+ case PA11 :
397
+ return 19
398
+ default :
399
+ return 0
400
+ }
401
+ }
402
+
403
+ func waitADCSync () {
404
+ for (sam .ADC .STATUS & sam .ADC_STATUS_SYNCBUSY ) > 0 {
405
+ }
406
+ }
407
+
261
408
// UART on the SAMD21.
262
409
type UART struct {
263
410
Buffer * RingBuffer
0 commit comments