Skip to content

Commit c506380

Browse files
authored
Merge pull request #36 from arduino-libraries/fix_queues
Fixes and updates.
2 parents 80eeb61 + e21c57b commit c506380

File tree

5 files changed

+183
-94
lines changed

5 files changed

+183
-94
lines changed

examples/Beginner/Waveform_Generator/Waveform_Generator.ino

+69-36
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,51 @@
11
// This example generates different waveforms based on user input on A12/DAC1.
22

33
#include <Arduino_AdvancedAnalog.h>
4+
#include <mbed_stats.h>
45

5-
#define N_SAMPLES (256)
6-
#define DEFAULT_FREQUENCY (16000)
6+
#define N_SAMPLES (64)
7+
#define DEFAULT_FREQUENCY (32000)
78

89
AdvancedDAC dac1(A12);
910
uint8_t SAMPLES_BUFFER[N_SAMPLES];
10-
size_t dac_frequency = DEFAULT_FREQUENCY;
1111

12-
void generate_waveform(int cmd)
13-
{
12+
uint32_t get_current_heap() {
13+
mbed_stats_heap_t heap_stats;
14+
mbed_stats_heap_get(&heap_stats);
15+
return heap_stats.current_size;
16+
}
17+
18+
void print_menu() {
19+
Serial.println();
20+
Serial.println("Enter a command:");
21+
Serial.println("t: Triangle wave");
22+
Serial.println("q: Square wave");
23+
Serial.println("s: Sine wave");
24+
Serial.println("r: Sawtooth wave");
25+
Serial.println("k: stop DAC");
26+
Serial.println("+: Increase frequency");
27+
Serial.println("-: Decrease frequency");
28+
}
29+
30+
void generate_waveform(int cmd) {
31+
static bool dac_started = false;
32+
static size_t dac_frequency = DEFAULT_FREQUENCY;
33+
static size_t starting_heap = get_current_heap();
34+
1435
switch (cmd) {
1536
case 't':
1637
// Triangle wave
1738
Serial.print("Waveform: Triangle ");
18-
for (int i=0; i<N_SAMPLES; i++){
19-
SAMPLES_BUFFER[i] = abs((i % 255) - 127);
39+
for (int i=0, j=N_SAMPLES-1; i<N_SAMPLES; i++, j--){
40+
SAMPLES_BUFFER[i] = abs((i - j) * 256 / N_SAMPLES);
2041
}
2142
break;
2243

2344
case 'q':
2445
// Square wave
2546
Serial.print("Waveform: Square ");
2647
for (int i=0; i<N_SAMPLES; i++){
27-
SAMPLES_BUFFER[i] = (i % 255) < 127 ? 127 : 0;
48+
SAMPLES_BUFFER[i] = i < (N_SAMPLES / 2) ? 0 : 255;
2849
}
2950
break;
3051

@@ -38,36 +59,59 @@ void generate_waveform(int cmd)
3859

3960
case 'r':
4061
// Sawtooth
41-
Serial.print("Waveform: Sawtooth");
62+
Serial.print("Waveform: Sawtooth ");
4263
for (int i=0; i<N_SAMPLES; i++){
43-
SAMPLES_BUFFER[i] = i;
64+
SAMPLES_BUFFER[i] = i * (256 / N_SAMPLES);
4465
}
4566
break;
4667

4768
case '+':
4869
case '-':
4970
Serial.print("Current frequency: ");
50-
51-
if (cmd == '+' && dac_frequency < 64000) {
52-
dac_frequency *= 2;
71+
72+
if (cmd == '+' && dac_frequency < 128000) {
73+
dac_frequency *= 2;
5374
} else if (cmd == '-' && dac_frequency > 1000) {
54-
dac_frequency /= 2;
75+
dac_frequency /= 2;
5576
} else {
56-
break;
77+
break;
5778
}
5879

5980
// Change frequency.
6081
dac1.frequency(dac_frequency * N_SAMPLES);
6182
break;
62-
83+
84+
case 'k':
85+
dac1.stop();
86+
dac_started = false;
87+
break;
88+
6389
default:
6490
Serial.print("Unknown command ");
6591
Serial.println((char) cmd);
6692
return;
6793
}
68-
69-
Serial.print(dac_frequency/1000);
70-
Serial.println("KHz");
94+
95+
if (cmd == 'k') {
96+
Serial.println("DAC stopped!");
97+
print_menu();
98+
} else {
99+
Serial.print(dac_frequency/1000);
100+
Serial.println("KHz");
101+
102+
if (dac_started == false) {
103+
// Initialize and start the DAC.
104+
if (!dac1.begin(AN_RESOLUTION_8, dac_frequency * N_SAMPLES, N_SAMPLES, 32)) {
105+
Serial.println("Failed to start DAC1 !");
106+
while (1);
107+
}
108+
dac_started = true;
109+
}
110+
}
111+
112+
Serial.print("Used memory: ");
113+
Serial.print(get_current_heap() - starting_heap);
114+
Serial.println(" bytes");
71115
}
72116

73117
void setup() {
@@ -77,32 +121,21 @@ void setup() {
77121

78122
}
79123

80-
81-
Serial.println("Enter a command:");
82-
Serial.println("t: Triangle wave");
83-
Serial.println("q: Square wave");
84-
Serial.println("s: Sine wave");
85-
Serial.println("r: Sawtooth wave");
86-
Serial.println("+: Increase frequency");
87-
Serial.println("-: Decrease frequency");
88-
124+
// Print list of commands.
125+
print_menu();
126+
127+
// Start generating a sine wave.
89128
generate_waveform('s');
90-
91-
// DAC initialization
92-
if (!dac1.begin(AN_RESOLUTION_8, DEFAULT_FREQUENCY * N_SAMPLES, N_SAMPLES, 32)) {
93-
Serial.println("Failed to start DAC1 !");
94-
while (1);
95-
}
96129
}
97130

98131
void loop() {
99132
if (Serial.available() > 0) {
100133
int cmd = Serial.read();
101134
if (cmd != '\n') {
102-
generate_waveform(cmd);
135+
generate_waveform(cmd);
103136
}
104137
}
105-
138+
106139
if (dac1.available()) {
107140
// Get a free buffer for writing.
108141
SampleBuffer buf = dac1.dequeue();

src/AdvancedDAC.cpp

+32-12
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ struct dac_descr_t {
2929
TIM_HandleTypeDef tim;
3030
uint32_t tim_trig;
3131
uint32_t resolution;
32+
uint32_t dmaudr_flag;
3233
DMABufferPool<Sample> *pool;
3334
DMABuffer<Sample> *dmabuf[2];
3435
};
@@ -37,10 +38,10 @@ struct dac_descr_t {
3738
static DAC_HandleTypeDef dac = {0};
3839

3940
static dac_descr_t dac_descr_all[] = {
40-
{&dac, DAC_CHANNEL_1, {DMA1_Stream4, {DMA_REQUEST_DAC1_CH1}}, DMA1_Stream4_IRQn,
41-
{TIM4}, DAC_TRIGGER_T4_TRGO, DAC_ALIGN_12B_R, nullptr, {nullptr, nullptr}},
42-
{&dac, DAC_CHANNEL_2, {DMA1_Stream5, {DMA_REQUEST_DAC1_CH2}}, DMA1_Stream5_IRQn,
43-
{TIM5}, DAC_TRIGGER_T5_TRGO, DAC_ALIGN_12B_R, nullptr, {nullptr, nullptr}},
41+
{&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, 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}},
4445
};
4546

4647
static uint32_t DAC_RES_LUT[] = {
@@ -73,10 +74,12 @@ static dac_descr_t *dac_descr_get(uint32_t channel) {
7374
}
7475

7576
static void dac_descr_deinit(dac_descr_t *descr, bool dealloc_pool) {
76-
if (descr) {
77+
if (descr != nullptr) {
7778
HAL_TIM_Base_Stop(&descr->tim);
7879
HAL_DAC_Stop_DMA(descr->dac, descr->channel);
7980

81+
__HAL_DAC_CLEAR_FLAG(descr->dac, descr->dmaudr_flag);
82+
8083
for (size_t i=0; i<AN_ARRAY_SIZE(descr->dmabuf); i++) {
8184
if (descr->dmabuf[i]) {
8285
descr->dmabuf[i]->release();
@@ -89,13 +92,17 @@ static void dac_descr_deinit(dac_descr_t *descr, bool dealloc_pool) {
8992
delete descr->pool;
9093
}
9194
descr->pool = nullptr;
95+
} else {
96+
descr->pool->flush();
9297
}
93-
9498
}
9599
}
96100

97101
bool AdvancedDAC::available() {
98102
if (descr != nullptr) {
103+
if (__HAL_DAC_GET_FLAG(descr->dac, descr->dmaudr_flag)) {
104+
dac_descr_deinit(descr, false);
105+
}
99106
return descr->pool->writable();
100107
}
101108
return false;
@@ -113,11 +120,17 @@ DMABuffer<Sample> &AdvancedDAC::dequeue() {
113120
}
114121

115122
void AdvancedDAC::write(DMABuffer<Sample> &dmabuf) {
123+
static uint32_t buf_count = 0;
124+
125+
if (descr == nullptr) {
126+
return;
127+
}
128+
116129
// Make sure any cached data is flushed.
117130
dmabuf.flush();
118131
descr->pool->enqueue(&dmabuf);
119132

120-
if (descr->dmabuf[0] == nullptr && descr->pool->readable() > 2) {
133+
if (descr->dmabuf[0] == nullptr && (++buf_count % 3) == 0) {
121134
descr->dmabuf[0] = descr->pool->dequeue();
122135
descr->dmabuf[1] = descr->pool->dequeue();
123136

@@ -126,7 +139,9 @@ void AdvancedDAC::write(DMABuffer<Sample> &dmabuf) {
126139
(uint32_t *) descr->dmabuf[0]->data(), descr->dmabuf[0]->size(), descr->resolution);
127140

128141
// Re/enable DMA double buffer mode.
142+
HAL_NVIC_DisableIRQ(descr->dma_irqn);
129143
hal_dma_enable_dbm(&descr->dma, descr->dmabuf[0]->data(), descr->dmabuf[1]->data());
144+
HAL_NVIC_EnableIRQ(descr->dma_irqn);
130145

131146
// Start trigger timer.
132147
HAL_TIM_Base_Start(&descr->tim);
@@ -135,7 +150,7 @@ void AdvancedDAC::write(DMABuffer<Sample> &dmabuf) {
135150

136151
int AdvancedDAC::begin(uint32_t resolution, uint32_t frequency, size_t n_samples, size_t n_buffers) {
137152
// Sanity checks.
138-
if (resolution >= AN_ARRAY_SIZE(DAC_RES_LUT) || (descr && descr->pool)) {
153+
if (resolution >= AN_ARRAY_SIZE(DAC_RES_LUT) || descr != nullptr) {
139154
return 0;
140155
}
141156

@@ -147,13 +162,14 @@ int AdvancedDAC::begin(uint32_t resolution, uint32_t frequency, size_t n_samples
147162

148163
uint32_t function = pinmap_function(dac_pins[0], PinMap_DAC);
149164
descr = dac_descr_get(DAC_CHAN_LUT[STM_PIN_CHANNEL(function) - 1]);
150-
if (descr == nullptr || descr->pool) {
165+
if (descr == nullptr) {
151166
return 0;
152167
}
153168

154169
// Allocate DMA buffer pool.
155170
descr->pool = new DMABufferPool<Sample>(n_samples, n_channels, n_buffers);
156171
if (descr->pool == nullptr) {
172+
descr = nullptr;
157173
return 0;
158174
}
159175
descr->resolution = DAC_RES_LUT[resolution];
@@ -178,13 +194,16 @@ int AdvancedDAC::begin(uint32_t resolution, uint32_t frequency, size_t n_samples
178194

179195
int AdvancedDAC::stop()
180196
{
181-
dac_descr_deinit(descr, true);
197+
if (descr != nullptr) {
198+
dac_descr_deinit(descr, true);
199+
descr = nullptr;
200+
}
182201
return 1;
183202
}
184203

185204
int AdvancedDAC::frequency(uint32_t const frequency)
186205
{
187-
if (descr && descr->pool) {
206+
if (descr != nullptr) {
188207
// Reconfigure the trigger timer.
189208
dac_descr_deinit(descr, false);
190209
hal_tim_config(&descr->tim, frequency);
@@ -200,9 +219,10 @@ extern "C" {
200219

201220
void DAC_DMAConvCplt(DMA_HandleTypeDef *dma, uint32_t channel) {
202221
dac_descr_t *descr = dac_descr_get(channel);
222+
203223
// Release the DMA buffer that was just done, allocate a new one,
204224
// and update the next DMA memory address target.
205-
if (descr->pool->readable()) {
225+
if (descr && descr->pool->readable()) {
206226
// NOTE: CT bit is inverted, to get the DMA buffer that's Not currently in use.
207227
size_t ct = ! hal_dma_get_ct(dma);
208228
descr->dmabuf[ct]->release();

0 commit comments

Comments
 (0)