Skip to content

Commit 591dc8b

Browse files
committed
AdvancedDAC: Add support for loop mode.
Loop mode starts the DAC automatically when all buffers in the queue are written. Once started, the DAC will continuously loop over all buffers. Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
1 parent 70a630e commit 591dc8b

File tree

2 files changed

+20
-13
lines changed

2 files changed

+20
-13
lines changed

src/AdvancedDAC.cpp

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,17 @@ struct dac_descr_t {
3232
uint32_t dmaudr_flag;
3333
DMAPool<Sample> *pool;
3434
DMABuffer<Sample> *dmabuf[2];
35+
bool loop_mode;
3536
};
3637

3738
// NOTE: Both DAC channel descriptors share the same DAC handle.
3839
static DAC_HandleTypeDef dac = {0};
3940

4041
static dac_descr_t dac_descr_all[] = {
4142
{&dac, DAC_CHANNEL_1, {DMA1_Stream4, {DMA_REQUEST_DAC1_CH1}}, DMA1_Stream4_IRQn, {TIM4},
42-
DAC_TRIGGER_T4_TRGO, DAC_ALIGN_12B_R, DAC_FLAG_DMAUDR1, nullptr, {nullptr, nullptr}},
43+
DAC_TRIGGER_T4_TRGO, DAC_ALIGN_12B_R, DAC_FLAG_DMAUDR1, nullptr, {nullptr, nullptr}, false},
4344
{&dac, DAC_CHANNEL_2, {DMA1_Stream5, {DMA_REQUEST_DAC1_CH2}}, DMA1_Stream5_IRQn, {TIM5},
44-
DAC_TRIGGER_T5_TRGO, DAC_ALIGN_12B_R, DAC_FLAG_DMAUDR2, nullptr, {nullptr, nullptr}},
45+
DAC_TRIGGER_T5_TRGO, DAC_ALIGN_12B_R, DAC_FLAG_DMAUDR2, nullptr, {nullptr, nullptr}, false},
4546
};
4647

4748
static uint32_t DAC_RES_LUT[] = {
@@ -110,7 +111,7 @@ bool AdvancedDAC::available() {
110111

111112
DMABuffer<Sample> &AdvancedDAC::dequeue() {
112113
static DMABuffer<Sample> NULLBUF;
113-
if (descr != nullptr) {
114+
if (descr != nullptr && !descr->loop_mode) {
114115
while (!available()) {
115116
__WFI();
116117
}
@@ -130,13 +131,15 @@ void AdvancedDAC::write(DMABuffer<Sample> &dmabuf) {
130131
dmabuf.flush();
131132
dmabuf.release();
132133

133-
if (descr->dmabuf[0] == nullptr && (++buf_count % 3) == 0) {
134+
if (!descr->dmabuf[0] &&
135+
((descr->loop_mode && !descr->pool->writable()) ||
136+
(!descr->loop_mode && (++buf_count % 3 == 0)))) {
134137
descr->dmabuf[0] = descr->pool->alloc(DMA_BUFFER_READ);
135138
descr->dmabuf[1] = descr->pool->alloc(DMA_BUFFER_READ);
136139

137140
// Start DAC DMA.
138141
HAL_DAC_Start_DMA(descr->dac, descr->channel,
139-
(uint32_t *) descr->dmabuf[0]->data(), descr->dmabuf[0]->size(), descr->resolution);
142+
(uint32_t *) descr->dmabuf[0]->data(), descr->dmabuf[0]->size(), descr->resolution);
140143

141144
// Re/enable DMA double buffer mode.
142145
HAL_NVIC_DisableIRQ(descr->dma_irqn);
@@ -148,7 +151,7 @@ void AdvancedDAC::write(DMABuffer<Sample> &dmabuf) {
148151
}
149152
}
150153

151-
int AdvancedDAC::begin(uint32_t resolution, uint32_t frequency, size_t n_samples, size_t n_buffers) {
154+
int AdvancedDAC::begin(uint32_t resolution, uint32_t frequency, size_t n_samples, size_t n_buffers, bool loop) {
152155
// Sanity checks.
153156
if (resolution >= AN_ARRAY_SIZE(DAC_RES_LUT) || descr != nullptr) {
154157
return 0;
@@ -172,6 +175,9 @@ int AdvancedDAC::begin(uint32_t resolution, uint32_t frequency, size_t n_samples
172175
descr = nullptr;
173176
return 0;
174177
}
178+
179+
descr->loop_mode = loop;
180+
n_buffers = n_buffers;
175181
descr->resolution = DAC_RES_LUT[resolution];
176182

177183
// Init and config DMA.
@@ -192,26 +198,23 @@ int AdvancedDAC::begin(uint32_t resolution, uint32_t frequency, size_t n_samples
192198
return 1;
193199
}
194200

195-
int AdvancedDAC::stop()
196-
{
201+
int AdvancedDAC::stop() {
197202
if (descr != nullptr) {
198203
dac_descr_deinit(descr, true);
199204
descr = nullptr;
200205
}
201206
return 1;
202207
}
203208

204-
int AdvancedDAC::frequency(uint32_t const frequency)
205-
{
209+
int AdvancedDAC::frequency(uint32_t const frequency) {
206210
if (descr != nullptr) {
207211
// Reconfigure the trigger timer.
208212
dac_descr_deinit(descr, false);
209213
hal_tim_config(&descr->tim, frequency);
210214
}
211215
}
212216

213-
AdvancedDAC::~AdvancedDAC()
214-
{
217+
AdvancedDAC::~AdvancedDAC() {
215218
dac_descr_deinit(descr, true);
216219
}
217220

@@ -227,6 +230,10 @@ void DAC_DMAConvCplt(DMA_HandleTypeDef *dma, uint32_t channel) {
227230
size_t ct = ! hal_dma_get_ct(dma);
228231
descr->dmabuf[ct]->release();
229232
descr->dmabuf[ct] = descr->pool->alloc(DMA_BUFFER_READ);
233+
if (descr->loop_mode) {
234+
// Move a buffer from the write queue to the read queue.
235+
descr->pool->alloc(DMA_BUFFER_WRITE)->release();
236+
}
230237
hal_dma_update_memory(dma, descr->dmabuf[ct]->data());
231238
} else {
232239
dac_descr_deinit(descr, false);

src/AdvancedDAC.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class AdvancedDAC {
4545
bool available();
4646
SampleBuffer dequeue();
4747
void write(SampleBuffer dmabuf);
48-
int begin(uint32_t resolution, uint32_t frequency, size_t n_samples=0, size_t n_buffers=0);
48+
int begin(uint32_t resolution, uint32_t frequency, size_t n_samples=0, size_t n_buffers=0, bool loop=false);
4949
int stop();
5050
int frequency(uint32_t const frequency);
5151
};

0 commit comments

Comments
 (0)