Skip to content

Commit 4d7f4eb

Browse files
committed
stmhal: Add ADC function to read data at a given frequency.
Reads ADC values into a bytearray (or similar) at a fixed rate. Needs a better name and improved API. Also fix up DAC dma function (which also needs a better name and API).
1 parent e95da5b commit 4d7f4eb

5 files changed

Lines changed: 82 additions & 22 deletions

File tree

stmhal/adc.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "adc.h"
1212
#include "pin.h"
1313
#include "build/pins.h"
14+
#include "timer.h"
1415

1516
// Usage Model:
1617
//
@@ -162,8 +163,39 @@ STATIC mp_obj_t adc_read(mp_obj_t self_in) {
162163

163164
STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_read_obj, adc_read);
164165

166+
STATIC mp_obj_t adc_read_timed(mp_obj_t self_in, mp_obj_t buf_in, mp_obj_t freq_in) {
167+
pyb_obj_adc_t *self = self_in;
168+
169+
buffer_info_t bufinfo;
170+
mp_get_buffer_raise(buf_in, &bufinfo);
171+
172+
// Init TIM6 at the required frequency (in Hz)
173+
timer_tim6_init(mp_obj_get_int(freq_in));
174+
175+
// Start timer
176+
HAL_TIM_Base_Start(&TIM6_Handle);
177+
178+
// This uses the timer in polling mode to do the sampling
179+
// TODO use DMA
180+
for (uint i = 0; i < bufinfo.len; i++) {
181+
// Wait for the timer to trigger
182+
while (__HAL_TIM_GET_FLAG(&TIM6_Handle, TIM_FLAG_UPDATE) == RESET) {
183+
}
184+
__HAL_TIM_CLEAR_FLAG(&TIM6_Handle, TIM_FLAG_UPDATE);
185+
((byte*)bufinfo.buf)[i] = adc_read_channel(&self->handle) >> 4;
186+
}
187+
188+
// Stop timer
189+
HAL_TIM_Base_Stop(&TIM6_Handle);
190+
191+
return mp_obj_new_int(bufinfo.len);
192+
}
193+
194+
STATIC MP_DEFINE_CONST_FUN_OBJ_3(adc_read_timed_obj, adc_read_timed);
195+
165196
STATIC const mp_map_elem_t adc_locals_dict_table[] = {
166197
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&adc_read_obj},
198+
{ MP_OBJ_NEW_QSTR(MP_QSTR_read_timed), (mp_obj_t)&adc_read_timed_obj},
167199
};
168200

169201
STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table);

stmhal/dac.c

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
#include "parse.h"
1111
#include "obj.h"
1212
#include "runtime.h"
13+
#include "timer.h"
1314
#include "dac.h"
1415

15-
TIM_HandleTypeDef TIM6_Handle;
1616
STATIC DAC_HandleTypeDef DAC_Handle;
1717

1818
void dac_init(void) {
@@ -22,19 +22,8 @@ void dac_init(void) {
2222
}
2323

2424
STATIC void TIM6_Config(uint freq) {
25-
// TIM6 clock enable
26-
__TIM6_CLK_ENABLE();
27-
28-
// Compute the prescaler value so TIM6 triggers at freq-Hz
29-
uint16_t period = (uint16_t) ((SystemCoreClock / 2) / freq) - 1;
30-
31-
// time base clock configuration
32-
TIM6_Handle.Instance = TIM6;
33-
TIM6_Handle.Init.Period = period;
34-
TIM6_Handle.Init.Prescaler = 0; // timer runs at SystemCoreClock / 2
35-
TIM6_Handle.Init.ClockDivision = 0; // unused for TIM6
36-
TIM6_Handle.Init.CounterMode = TIM_COUNTERMODE_UP; // unused for TIM6
37-
HAL_TIM_Base_Init(&TIM6_Handle);
25+
// Init TIM6 at the required frequency (in Hz)
26+
timer_tim6_init(freq);
3827

3928
// TIM6 TRGO selection
4029
TIM_MasterConfigTypeDef config;
@@ -203,17 +192,14 @@ mp_obj_t pyb_dac_dma(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
203192
DAC_Init(self->dac_channel, &DAC_InitStructure);
204193
*/
205194

206-
if (self->state != 3) {
207-
DAC_ChannelConfTypeDef config;
208-
config.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
209-
config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
210-
HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel);
211-
self->state = 3;
212-
}
213-
214195
// DMA1_Stream[67] channel7 configuration
215196
DMA_HandleTypeDef DMA_Handle;
216197
DMA_Handle.Instance = self->dma_stream;
198+
199+
// Need to deinit DMA first
200+
DMA_Handle.State = HAL_DMA_STATE_READY;
201+
HAL_DMA_DeInit(&DMA_Handle);
202+
217203
DMA_Handle.Init.Channel = DMA_CHANNEL_7;
218204
DMA_Handle.Init.Direction = DMA_MEMORY_TO_PERIPH;
219205
DMA_Handle.Init.PeriphInc = DMA_PINC_DISABLE;
@@ -231,6 +217,18 @@ mp_obj_t pyb_dac_dma(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
231217

232218
__HAL_LINKDMA(&DAC_Handle, DMA_Handle1, DMA_Handle);
233219

220+
DAC_Handle.Instance = DAC;
221+
DAC_Handle.State = HAL_DAC_STATE_RESET;
222+
HAL_DAC_Init(&DAC_Handle);
223+
224+
if (self->state != 3) {
225+
DAC_ChannelConfTypeDef config;
226+
config.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
227+
config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
228+
HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel);
229+
self->state = 3;
230+
}
231+
234232
HAL_DAC_Start_DMA(&DAC_Handle, self->dac_channel, (uint32_t*)bufinfo.buf, bufinfo.len, DAC_ALIGN_8B_R);
235233

236234
/*

stmhal/qstrdefsport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ Q(filtered_xyz)
9797
// for ADC object
9898
Q(ADC)
9999
Q(ADC_all)
100+
Q(read_timed)
100101
Q(read_channel)
101102
Q(read_core_temp)
102103
Q(read_core_vbat)

stmhal/timer.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
TIM_HandleTypeDef TIM3_Handle;
2929
TIM_HandleTypeDef TIM5_Handle;
30+
TIM_HandleTypeDef TIM6_Handle;
3031

3132
// TIM3 is set-up for the USB CDC interface
3233
void timer_tim3_init(void) {
@@ -57,6 +58,7 @@ void timer_tim3_deinit(void) {
5758
*/
5859

5960
// TIM5 is set-up for the servo controller
61+
// This function inits but does not start the timer
6062
void timer_tim5_init(void) {
6163
// TIM5 clock enable
6264
__TIM5_CLK_ENABLE();
@@ -74,6 +76,31 @@ void timer_tim5_init(void) {
7476
HAL_TIM_PWM_Init(&TIM5_Handle);
7577
}
7678

79+
// Init TIM6 with a counter-overflow at the given frequency (given in Hz)
80+
// TIM6 is used by the DAC and ADC for auto sampling at a given frequency
81+
// This function inits but does not start the timer
82+
void timer_tim6_init(uint freq) {
83+
// TIM6 clock enable
84+
__TIM6_CLK_ENABLE();
85+
86+
// Timer runs at SystemCoreClock / 2
87+
// Compute the prescaler value so TIM6 triggers at freq-Hz
88+
uint32_t period = (SystemCoreClock / 2) / freq;
89+
uint32_t prescaler = 1;
90+
while (period > 0xffff) {
91+
period >>= 1;
92+
prescaler <<= 1;
93+
}
94+
95+
// Time base clock configuration
96+
TIM6_Handle.Instance = TIM6;
97+
TIM6_Handle.Init.Period = period - 1;
98+
TIM6_Handle.Init.Prescaler = prescaler - 1;
99+
TIM6_Handle.Init.ClockDivision = 0; // unused for TIM6
100+
TIM6_Handle.Init.CounterMode = TIM_COUNTERMODE_UP; // unused for TIM6
101+
HAL_TIM_Base_Init(&TIM6_Handle);
102+
}
103+
77104
// Interrupt dispatch
78105
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
79106
if (htim == &TIM3_Handle) {

stmhal/timer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
extern TIM_HandleTypeDef TIM3_Handle;
77
extern TIM_HandleTypeDef TIM5_Handle;
8+
extern TIM_HandleTypeDef TIM6_Handle;
89

910
void timer_tim3_init(void);
1011
void timer_tim5_init(void);
12+
void timer_tim6_init(uint freq);

0 commit comments

Comments
 (0)