Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit af1ea92

Browse files
jmdodd95682iabdalkader
authored andcommittedMar 20, 2024
AdvancedADC: Add support for dual ADC mode.
1 parent 2309705 commit af1ea92

File tree

4 files changed

+141
-39
lines changed

4 files changed

+141
-39
lines changed
 

‎src/AdvancedADC.cpp

Lines changed: 103 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,20 @@ static void dac_descr_deinit(adc_descr_t *descr, bool dealloc_pool) {
9797
}
9898
}
9999

100+
int AdvancedADC::id() {
101+
if (descr) {
102+
ADC_TypeDef *adc = descr->adc.Instance;
103+
if (adc == ADC1) {
104+
return 1;
105+
} else if (adc == ADC2) {
106+
return 2;
107+
} else if (adc == ADC3) {
108+
return 3;
109+
}
110+
}
111+
return -1;
112+
}
113+
100114
bool AdvancedADC::available() {
101115
if (descr != nullptr) {
102116
return descr->pool->readable();
@@ -115,9 +129,9 @@ DMABuffer<Sample> &AdvancedADC::read() {
115129
return NULLBUF;
116130
}
117131

118-
int AdvancedADC::begin(uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers) {
132+
int AdvancedADC::begin(uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers, bool start) {
133+
119134
ADCName instance = ADC_NP;
120-
121135
// Sanity checks.
122136
if (resolution >= AN_ARRAY_SIZE(ADC_RES_LUT) || (descr && descr->pool)) {
123137
return 0;
@@ -159,6 +173,8 @@ int AdvancedADC::begin(uint32_t resolution, uint32_t sample_rate, size_t n_sampl
159173

160174
// Configure ADC pins.
161175
pinmap_pinout(adc_pins[0], PinMap_ADC);
176+
177+
//If ADC was not specified ensure the remaining channels are mappable to same ADC
162178
uint8_t ch_init = 1;
163179
for (size_t i=1; i<n_channels; i++) {
164180
for (size_t j=0; j<AN_ARRAY_SIZE(adc_pin_alt); j++) {
@@ -177,7 +193,6 @@ int AdvancedADC::begin(uint32_t resolution, uint32_t sample_rate, size_t n_sampl
177193
}
178194
}
179195
}
180-
181196
// All channels must share the same instance; if not, bail out.
182197
if (ch_init < n_channels) {
183198
return 0;
@@ -188,6 +203,8 @@ int AdvancedADC::begin(uint32_t resolution, uint32_t sample_rate, size_t n_sampl
188203
if (descr->pool == nullptr) {
189204
return 0;
190205
}
206+
207+
// Allocate the two DMA buffers used for double buffering.
191208
descr->dmabuf[0] = descr->pool->allocate();
192209
descr->dmabuf[1] = descr->pool->allocate();
193210

@@ -212,56 +229,110 @@ int AdvancedADC::begin(uint32_t resolution, uint32_t sample_rate, size_t n_sampl
212229
hal_dma_enable_dbm(&descr->dma, descr->dmabuf[0]->data(), descr->dmabuf[1]->data());
213230
HAL_NVIC_EnableIRQ(descr->dma_irqn);
214231

215-
// Init, config and start the ADC timer.
232+
if (start) {
233+
return this->start(sample_rate);
234+
}
235+
236+
return id();
237+
}
238+
239+
int AdvancedADC::start(uint32_t sample_rate){
240+
// Initialize and configure the ADC timer.
216241
hal_tim_config(&descr->tim, sample_rate);
242+
243+
// Start the ADC timer. Note, if dual ADC mode is enabled,
244+
// this will also start ADC2.
217245
if (HAL_TIM_Base_Start(&descr->tim) != HAL_OK) {
218246
return 0;
219247
}
220-
248+
221249
return 1;
222250
}
223251

224-
int AdvancedADC::stop()
225-
{
252+
int AdvancedADC::stop() {
226253
dac_descr_deinit(descr, true);
227254
return 1;
228255
}
229256

230-
AdvancedADC::~AdvancedADC()
231-
{
257+
void AdvancedADC::clear() {
258+
if (descr && descr->pool) {
259+
descr->pool->flush();
260+
}
261+
}
262+
263+
size_t AdvancedADC::channels() {
264+
return n_channels;
265+
}
266+
267+
AdvancedADC::~AdvancedADC() {
232268
dac_descr_deinit(descr, true);
233269
}
234270

271+
int AdvancedADCDual::begin(uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers) {
272+
// The two ADCs must have the same number of channels.
273+
if (adc1.channels() != adc2.channels()) {
274+
return 0;
275+
}
276+
277+
// Configure the ADCs.
278+
// Note only ADC1 (master) and ADC2 can be used in dual mode.
279+
if (adc1.begin(resolution, sample_rate, n_samples, n_buffers, false) != 1) {
280+
return 0;
281+
}
282+
283+
if (adc2.begin(resolution, sample_rate, n_samples, n_buffers, false) != 2) {
284+
return -3;
285+
}
286+
287+
// Enable dual ADC mode.
288+
hal_adc_enable_dual_mode(true);
289+
290+
// Start ADC1, note ADC2 is also automatically started.
291+
return adc1.start(sample_rate);
292+
}
293+
294+
int AdvancedADCDual:: stop(){
295+
adc1.stop();
296+
adc2.stop();
297+
// Disable dual mode.
298+
hal_adc_enable_dual_mode(false);
299+
return 1;
300+
}
301+
302+
AdvancedADCDual::~AdvancedADCDual(){
303+
stop();
304+
}
305+
235306
extern "C" {
236-
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *adc) {
237-
adc_descr_t *descr = adc_descr_get(adc->Instance);
238-
// NOTE: CT bit is inverted, to get the DMA buffer that's Not currently in use.
239-
size_t ct = ! hal_dma_get_ct(&descr->dma);
307+
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *adc) {
308+
adc_descr_t *descr = adc_descr_get(adc->Instance);
309+
// NOTE: CT bit is inverted, to get the DMA buffer that's Not currently in use.
310+
size_t ct = ! hal_dma_get_ct(&descr->dma);
240311

241-
// Timestamp the buffer.
242-
descr->dmabuf[ct]->timestamp(us_ticker_read());
312+
// Timestamp the buffer.
313+
descr->dmabuf[ct]->timestamp(us_ticker_read());
243314

244-
if (descr->pool->writable()) {
245-
// Make sure any cached data is discarded.
246-
descr->dmabuf[ct]->invalidate();
315+
if (descr->pool->writable()) {
316+
// Make sure any cached data is discarded.
317+
descr->dmabuf[ct]->invalidate();
247318

248-
// Move current DMA buffer to ready queue.
249-
descr->pool->enqueue(descr->dmabuf[ct]);
319+
// Move current DMA buffer to ready queue.
320+
descr->pool->enqueue(descr->dmabuf[ct]);
250321

251-
// Allocate a new free buffer.
252-
descr->dmabuf[ct] = descr->pool->allocate();
322+
// Allocate a new free buffer.
323+
descr->dmabuf[ct] = descr->pool->allocate();
253324

254-
// Currently, all multi-channel buffers are interleaved.
255-
if (descr->dmabuf[ct]->channels() > 1) {
256-
descr->dmabuf[ct]->setflags(DMA_BUFFER_INTRLVD);
325+
// Currently, all multi-channel buffers are interleaved.
326+
if (descr->dmabuf[ct]->channels() > 1) {
327+
descr->dmabuf[ct]->setflags(DMA_BUFFER_INTRLVD);
328+
}
329+
} else {
330+
descr->dmabuf[ct]->setflags(DMA_BUFFER_DISCONT);
257331
}
258-
} else {
259-
descr->dmabuf[ct]->setflags(DMA_BUFFER_DISCONT);
260-
}
261332

262-
// Update the next DMA target pointer.
263-
// NOTE: If the pool was empty, the same buffer is reused.
264-
hal_dma_update_memory(&descr->dma, descr->dmabuf[ct]->data());
265-
}
333+
// Update the next DMA target pointer.
334+
// NOTE: If the pool was empty, the same buffer is reused.
335+
hal_dma_update_memory(&descr->dma, descr->dmabuf[ct]->data());
336+
}
266337

267338
} // extern C

‎src/AdvancedADC.h

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,24 +41,44 @@ class AdvancedADC {
4141
for (auto p : {p0, args...}) {
4242
adc_pins[n_channels++] = analogPinToPinName(p);
4343
}
44-
}
4544
AdvancedADC(): n_channels(0), descr(nullptr) {
4645
}
4746
~AdvancedADC();
47+
int id();
4848
bool available();
4949
SampleBuffer read();
50-
int begin(uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers);
51-
int begin(uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers,
52-
size_t n_pins, pin_size_t *pins) {
50+
int begin(uint32_t resolution, uint32_t sample_rate, size_t n_samples,
51+
size_t n_buffers, bool start=true);
52+
int begin(uint32_t resolution, uint32_t sample_rate, size_t n_samples,
53+
size_t n_buffers, size_t n_pins, pin_size_t *pins, bool start=true) {
5354
if (n_pins > AN_MAX_ADC_CHANNELS) {
5455
n_pins = AN_MAX_ADC_CHANNELS;
5556
}
5657
for (size_t i = 0; i < n_pins; ++i) {
5758
adc_pins[i] = analogPinToPinName(pins[i]);
5859
}
60+
5961
n_channels = n_pins;
60-
return begin(resolution, sample_rate, n_samples, n_buffers);
62+
return begin(resolution, sample_rate, n_samples, n_buffers, start);
63+
}
64+
int start(uint32_t sample_rate);
65+
int stop();
66+
void clear();
67+
size_t channels();
68+
};
69+
70+
class AdvancedADCDual {
71+
private:
72+
AdvancedADC &adc1;
73+
AdvancedADC &adc2;
74+
size_t n_channels;
75+
76+
public:
77+
AdvancedADCDual(AdvancedADC &adc1_in, AdvancedADC &adc2_in):
78+
n_channels(0), adc1(adc1_in), adc2(adc2_in) {
6179
}
80+
~AdvancedADCDual();
81+
int begin(uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers);
6282
int stop();
6383
};
6484

‎src/HALConfig.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ static uint32_t ADC_RANK_LUT[] = {
173173
int hal_adc_config(ADC_HandleTypeDef *adc, uint32_t resolution, uint32_t trigger, PinName *adc_pins, uint32_t n_channels) {
174174
// Set ADC clock source.
175175
__HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP);
176-
176+
177177
// Enable ADC clock
178178
if (adc->Instance == ADC1) {
179179
__HAL_RCC_ADC12_CLK_ENABLE();
@@ -209,7 +209,7 @@ int hal_adc_config(ADC_HandleTypeDef *adc, uint32_t resolution, uint32_t trigger
209209
sConfig.OffsetNumber = ADC_OFFSET_NONE;
210210
sConfig.SingleDiff = ADC_SINGLE_ENDED;
211211
sConfig.SamplingTime = ADC_SAMPLETIME_8CYCLES_5;
212-
212+
213213
for (size_t rank=0; rank<n_channels; rank++) {
214214
uint32_t function = pinmap_function(adc_pins[rank], PinMap_ADC);
215215
uint32_t channel = STM_PIN_CHANNEL(function);
@@ -223,6 +223,16 @@ int hal_adc_config(ADC_HandleTypeDef *adc, uint32_t resolution, uint32_t trigger
223223
return 0;
224224
}
225225

226+
int hal_adc_enable_dual_mode(bool enable) {
227+
if (enable) {
228+
LL_ADC_SetMultimode(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_MULTI_DUAL_REG_SIMULT);
229+
} else {
230+
LL_ADC_SetMultimode(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_MULTI_INDEPENDENT);
231+
}
232+
return 0;
233+
}
234+
235+
226236
int hal_i2s_config(I2S_HandleTypeDef *i2s, uint32_t sample_rate, uint32_t mode, bool mck_enable) {
227237
// Set I2S clock source.
228238
RCC_PeriphCLKInitTypeDef pclk_init = {0};

‎src/HALConfig.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ void hal_dma_enable_dbm(DMA_HandleTypeDef *dma, void *m0 = nullptr, void *m1 = n
3030
void hal_dma_update_memory(DMA_HandleTypeDef *dma, void *addr);
3131
int hal_dac_config(DAC_HandleTypeDef *dac, uint32_t channel, uint32_t trigger);
3232
int hal_adc_config(ADC_HandleTypeDef *adc, uint32_t resolution, uint32_t trigger, PinName *adc_pins, uint32_t n_channels);
33+
int hal_adc_enable_dual_mode(bool enable);
3334
int hal_i2s_config(I2S_HandleTypeDef *i2s, uint32_t sample_rate, uint32_t mode, bool mck_enable);
3435

3536
#endif // __HAL_CONFIG_H__

0 commit comments

Comments
 (0)
Please sign in to comment.