From 4a2faeb2c5680a54a6653c9c22c0f76c90e38849 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Sat, 4 Dec 2021 20:27:07 +0100 Subject: [PATCH] machine/stm32f103: initial implementation on ADC interface Signed-off-by: deadprogram --- src/machine/machine_stm32_adc_f1.go | 108 ++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 src/machine/machine_stm32_adc_f1.go diff --git a/src/machine/machine_stm32_adc_f1.go b/src/machine/machine_stm32_adc_f1.go new file mode 100644 index 00000000..fb0cee66 --- /dev/null +++ b/src/machine/machine_stm32_adc_f1.go @@ -0,0 +1,108 @@ +//go:build stm32f103 +// +build stm32f103 + +package machine + +import ( + "device/stm32" + "unsafe" +) + +const ( + Cycles_1_5 = 0x0 + Cycles_7_5 = 0x1 + Cycles_13_5 = 0x2 + Cycles_28_5 = 0x3 + Cycles_41_5 = 0x4 + Cycles_55_5 = 0x5 + Cycles_71_5 = 0x6 + Cycles_239_5 = 0x7 +) + +// InitADC initializes the registers needed for ADC1. +func InitADC() { + // Enable ADC clock + enableAltFuncClock(unsafe.Pointer(stm32.ADC1)) + + // set scan mode + stm32.ADC1.CR1.SetBits(stm32.ADC_CR1_SCAN) + + // clear CONT, ALIGN, EXTRIG and EXTSEL bits from CR2 + stm32.ADC1.CR2.ClearBits(stm32.ADC_CR2_CONT | stm32.ADC_CR2_ALIGN | stm32.ADC_CR2_EXTTRIG_Msk | stm32.ADC_CR2_EXTSEL_Msk) + + stm32.ADC1.SQR1.ClearBits(stm32.ADC_SQR1_L_Msk) + stm32.ADC1.SQR1.SetBits(2 << stm32.ADC_SQR1_L_Pos) // 2 means 3 conversions + + // enable + stm32.ADC1.CR2.SetBits(stm32.ADC_CR2_ADON) + + return +} + +// Configure configures an ADC pin to be able to read analog data. +func (a ADC) Configure(ADCConfig) { + a.Pin.Configure(PinConfig{Mode: PinInputModeAnalog}) + + // set sample time + ch := a.getChannel() + if ch > 9 { + stm32.ADC1.SMPR1.SetBits(Cycles_28_5 << (ch - 10) * stm32.ADC_SMPR1_SMP11_Pos) + } else { + stm32.ADC1.SMPR2.SetBits(Cycles_28_5 << (ch * stm32.ADC_SMPR2_SMP1_Pos)) + } + + return +} + +// Get returns the current value of a ADC pin in the range 0..0xffff. +// TODO: DMA based implementation. +func (a ADC) Get() uint16 { + // set rank + ch := uint32(a.getChannel()) + stm32.ADC1.SQR3.SetBits(ch) + + // start conversion + stm32.ADC1.CR2.SetBits(stm32.ADC_CR2_SWSTART) + + // wait for conversion to complete + for !stm32.ADC1.SR.HasBits(stm32.ADC_SR_EOC) { + } + + // read result as 16 bit value + result := uint16(stm32.ADC1.DR.Get()) << 4 + + // clear flag + stm32.ADC1.SR.ClearBits(stm32.ADC_SR_EOC) + + // clear rank + stm32.ADC1.SMPR1.ClearBits(ch) + + return result +} + +func (a ADC) getChannel() uint8 { + switch a.Pin { + case PA0: + return 0 + case PA1: + return 1 + case PA2: + return 2 + case PA3: + return 3 + case PA4: + return 4 + case PA5: + return 5 + case PA6: + return 6 + case PA7: + return 7 + case PB0: + return 8 + case PB1: + return 9 + } + + return 0 +}