Skip to content

Commit e015fc5

Browse files
authored
Merge pull request #75 from arduino-libraries/dac_loop_mode
AdvancedDAC: Add support for loop mode.
2 parents 70a630e + f530b02 commit e015fc5

File tree

4 files changed

+61
-13
lines changed

4 files changed

+61
-13
lines changed

docs/api.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -189,12 +189,12 @@ AdvancedDAC dac1(A13);
189189

190190
### `AdvancedDAC.begin()`
191191

192-
Initializes the DAC with the specified parameters. To reconfigure the DAC, `stop()` must be called first.
192+
Initializes the DAC with the specified parameters. To reconfigure the DAC, `stop()` must be called first. The DAC has a special mode called _loop mode_ enabled by setting `loop` parameter to `true`. In loop mode, the DAC will start automatically after all buffers are filled, and continuously cycle through over all buffers.
193193

194194
#### Syntax
195195

196196
```
197-
dac.begin(resolution, frequency, n_samples, n_buffers)
197+
dac.begin(resolution, frequency, n_samples, n_buffers, loop=false)
198198
```
199199

200200
#### Parameters
@@ -206,6 +206,7 @@ dac.begin(resolution, frequency, n_samples, n_buffers)
206206
- `int` - **frequency** - the output frequency in Hertz, e.g. `8000`.
207207
- `int` - **n_samples** - the number of samples per sample buffer. See [SampleBuffer](#samplebuffer) for more details.
208208
- `int` - **n_buffers** - the number of sample buffers in the queue. See [SampleBuffer](#samplebuffer) for more details.
209+
- `bool`- **loop** - enables loop mode.
209210

210211
#### Returns
211212

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// This examples shows how to use the DAC in loop mode. In loop mode the
2+
// DAC starts automatically after all buffers are filled, and continuously
3+
// cycle through over all buffers.
4+
#include <Arduino_AdvancedAnalog.h>
5+
6+
AdvancedDAC dac1(A12);
7+
8+
void setup() {
9+
Serial.begin(9600);
10+
11+
while (!Serial) {
12+
13+
}
14+
15+
// Start DAC in loop mode.
16+
if (!dac1.begin(AN_RESOLUTION_12, 16000, 32, 16, true)) {
17+
Serial.println("Failed to start DAC1 !");
18+
while (1);
19+
}
20+
21+
// Write all buffers.
22+
uint16_t sample = 0;
23+
while (dac1.available()) {
24+
// Get a free buffer for writing.
25+
SampleBuffer buf = dac1.dequeue();
26+
27+
// Write data to buffer.
28+
for (int i=0; i<buf.size(); i++) {
29+
buf.data()[i] = sample;
30+
}
31+
32+
// Write the buffer to DAC.
33+
dac1.write(buf);
34+
sample += 256;
35+
}
36+
}
37+
38+
39+
void loop() {
40+
// In loop mode, no other DAC functions need to be called.
41+
}

src/AdvancedDAC.cpp

+16-10
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[] = {
@@ -130,7 +131,9 @@ 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

@@ -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,8 @@ 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;
175180
descr->resolution = DAC_RES_LUT[resolution];
176181

177182
// Init and config DMA.
@@ -192,26 +197,23 @@ int AdvancedDAC::begin(uint32_t resolution, uint32_t frequency, size_t n_samples
192197
return 1;
193198
}
194199

195-
int AdvancedDAC::stop()
196-
{
200+
int AdvancedDAC::stop() {
197201
if (descr != nullptr) {
198202
dac_descr_deinit(descr, true);
199203
descr = nullptr;
200204
}
201205
return 1;
202206
}
203207

204-
int AdvancedDAC::frequency(uint32_t const frequency)
205-
{
208+
int AdvancedDAC::frequency(uint32_t const frequency) {
206209
if (descr != nullptr) {
207210
// Reconfigure the trigger timer.
208211
dac_descr_deinit(descr, false);
209212
hal_tim_config(&descr->tim, frequency);
210213
}
211214
}
212215

213-
AdvancedDAC::~AdvancedDAC()
214-
{
216+
AdvancedDAC::~AdvancedDAC() {
215217
dac_descr_deinit(descr, true);
216218
}
217219

@@ -227,6 +229,10 @@ void DAC_DMAConvCplt(DMA_HandleTypeDef *dma, uint32_t channel) {
227229
size_t ct = ! hal_dma_get_ct(dma);
228230
descr->dmabuf[ct]->release();
229231
descr->dmabuf[ct] = descr->pool->alloc(DMA_BUFFER_READ);
232+
if (descr->loop_mode) {
233+
// Move a buffer from the write queue to the read queue.
234+
descr->pool->alloc(DMA_BUFFER_WRITE)->release();
235+
}
230236
hal_dma_update_memory(dma, descr->dmabuf[ct]->data());
231237
} else {
232238
dac_descr_deinit(descr, false);

src/AdvancedDAC.h

+1-1
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)