Skip to content

Commit 1deb0bd

Browse files
committed
Simple Arduino Analog Read for the STM32
1 parent 658d3ea commit 1deb0bd

File tree

5 files changed

+72
-43
lines changed

5 files changed

+72
-43
lines changed

examples/tests/timer/test-timer/test-timer.ino

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
#include "AudioTools.h"
22

3-
4-
53
uint32_t sampling_rate = 44100;
64
uint32_t delay_us = AudioUtils::toTimeUs(sampling_rate);
75
uint32_t count;

src/AudioAnalog/AnalogAudioArduino.h

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class AnalogConfig : public AudioBaseInfo {
2424
}
2525
int start_pin = PIN_ADC_START;
2626
uint16_t buffer_size = ADC_BUFFER_SIZE;
27-
uint8_t buffers = ADC_BUFFERS;
27+
uint16_t buffers = ADC_BUFFERS;
2828
};
2929

3030
/**
@@ -37,7 +37,7 @@ class AnalogAudioStream : public AudioStreamX {
3737
public:
3838
AnalogAudioStream() = default;
3939

40-
AnalogConfig defaultConfig() {
40+
AnalogConfig defaultConfig(RxTxMode mode=RX_MODE) {
4141
AnalogConfig cfg;
4242
return cfg;
4343
}
@@ -51,18 +51,15 @@ class AnalogAudioStream : public AudioStreamX {
5151
}
5252

5353
bool begin(AnalogConfig cfg) {
54-
LOGD("%s", __func__);
54+
TRACED();
5555
config = cfg;
5656
if (buffer == nullptr) {
5757
// allocate buffers
5858
buffer = new NBuffer<int16_t>(cfg.buffer_size, cfg.buffers);
5959
if (buffer==nullptr){
6060
LOGE("Not enough memory for buffer");
6161
return false;
62-
} else {
63-
LOGI("buffer: %d", (int) buffer);
64-
LOGI("self: %d", (int) this);
65-
}
62+
}
6663
// setup pins
6764
setupPins();
6865
} else {
@@ -77,7 +74,7 @@ class AnalogAudioStream : public AudioStreamX {
7774
return timer.begin(callback, time, TimeUnit::US);
7875
}
7976

80-
virtual int available() { return buffer==nullptr ? 0 : buffer->available(); };
77+
virtual int available() { return buffer==nullptr ? 0 : buffer->available()*2; };
8178

8279
/// Provides the sampled audio data
8380
size_t readBytes(uint8_t *values, size_t len) {
@@ -90,6 +87,7 @@ class AnalogAudioStream : public AudioStreamX {
9087
AnalogConfig config;
9188
TimerAlarmRepeating timer;
9289
BaseBuffer<int16_t> *buffer = nullptr;
90+
int16_t avg_value=0;
9391

9492
/// Sample data and write to buffer
9593
static void callback(void *arg) {
@@ -98,26 +96,32 @@ class AnalogAudioStream : public AudioStreamX {
9896
if (self->buffer != nullptr) {
9997
int channels = self->config.channels;
10098
for (int j = 0; j < channels; j++) {
101-
//Serial.print("+");
10299
// provides value in range 0…4095
103100
value = analogRead(self->config.start_pin + j);
104-
//Serial.print("-");
105-
value = (value-2048)*15;
101+
value = (value - self->avg_value) * 16;
106102
self->buffer->write(value);
107103
}
108104
}
109105
}
110106

111107
/// pinmode input for defined analog pins
112108
void setupPins() {
113-
LOGD("%s", __func__);
109+
TRACED();
114110
LOGI("start_pin: %d", config.start_pin);
115111
// setup pins for read
116112
for (int j = 0; j < config.channels; j++) {
117113
int pin = config.start_pin + j;
118114
pinMode(pin, INPUT);
119115
LOGD("pinMode(%d, INPUT)",pin);
120116
}
117+
// calculate the avarage value to center the signal
118+
float total=0;
119+
for (int j=0;j<200;j++){
120+
total += analogRead(config.start_pin);
121+
}
122+
avg_value = total / 200.0;
123+
LOGI("Avg Signal was %d", avg_value);
124+
121125
}
122126
};
123127

src/AudioConfig.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,11 @@ typedef uint32_t eps32_i2s_sample_rate_type;
405405
#define USE_I2S
406406
#define USE_PWM
407407
#define USE_TIMER
408+
#define USE_ADC_ARDUINO
409+
#define ADC_BUFFER_SIZE 1024
410+
#define ADC_BUFFERS 20
408411

412+
#define PIN_ADC_START PA0
409413
#define PIN_PWM_START 6
410414
#define PIN_I2S_BCK 1
411415
#define PIN_I2S_WS PIN_I2S_BCK+1

src/AudioI2S/I2SSTM32.h

Lines changed: 49 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace audio_tools {
88

99
/**
1010
* @brief Basic I2S API - for the STM32
11-
* Depends on https://github.com/pschatzmann/STM32F411-i2s-prototype
11+
* Depends on https://github.com/pschatzmann/stm32f411-i2s
1212
* We just add a write and read buffer and pass some parameters to the STM32 API!
1313
* @author Phil Schatzmann
1414
* @copyright GPLv3
@@ -27,11 +27,14 @@ class I2SBase {
2727

2828
/// starts the DAC with the default config in TX Mode
2929
bool begin(RxTxMode mode = TX_MODE) {
30+
TRACED();
3031
return begin(defaultConfig(mode));
3132
}
3233

3334
/// starts the DAC
3435
bool begin(I2SConfig cfg) {
36+
TRACED();
37+
bool result = false;
3538
deleteBuffers();
3639

3740
if (cfg.bits_per_sample!=16){
@@ -48,27 +51,28 @@ class I2SBase {
4851
switch(cfg.rx_tx_mode){
4952
case RX_MODE:
5053
p_rx_buffer = new NBuffer<uint8_t>(cfg.buffer_size, cfg.buffer_count);
51-
startI2SReceive(&i2s_stm32, writeFromReceive, cfg.buffer_size);
54+
result = startI2SReceive(&i2s_stm32, writeFromReceive, cfg.buffer_size);
5255
break;
5356
case TX_MODE:
5457
p_tx_buffer = new NBuffer<uint8_t>(cfg.buffer_size, cfg.buffer_count);
55-
startI2STransmit(&i2s_stm32, readToTransmit, cfg.buffer_size);
58+
result = startI2STransmit(&i2s_stm32, readToTransmit, cfg.buffer_size);
5659
break;
5760
case RXTX_MODE:
5861
p_tx_buffer = new NBuffer<uint8_t>(cfg.buffer_size, cfg.buffer_count);
59-
startI2STransmitReceive(&i2s_stm32, readToTransmit, writeFromReceive, cfg.buffer_size);
62+
result = startI2STransmitReceive(&i2s_stm32, readToTransmit, writeFromReceive, cfg.buffer_size);
6063
break;
6164
default:
6265
LOGE("Unsupported mode");
6366
return false;
6467

6568
}
6669

67-
return true;
70+
return result;
6871
}
6972

7073
/// stops the I2C and unistalls the driver
7174
void end(){
75+
TRACED();
7276
stopI2S();
7377
deleteBuffers();
7478
}
@@ -80,42 +84,33 @@ class I2SBase {
8084

8185
/// We limit the write size to the buffer size
8286
int availableForWrite() {
83-
return I2S_BUFFER_COUNT*I2S_BUFFER_SIZE;
87+
return I2S_BUFFER_SIZE;
8488
}
8589

8690
/// provides the actual configuration
8791
I2SConfig config() {
8892
return cfg;
8993
}
9094

91-
/// writes the data to the I2S interface
95+
/// blocking writes for the data to the I2S interface
9296
size_t writeBytes(const void *src, size_t size_bytes){
97+
TRACED();
9398
size_t result = 0;
94-
if (cfg.channels == 2){
95-
result = p_tx_buffer->writeArray((uint8_t*)src, size_bytes);
96-
} else {
97-
// write each sample 2 times
98-
int samples = size_bytes / 2;
99-
int16_t *src_16 = (int16_t *)src;
100-
int16_t tmp[2];
101-
int result = 0;
102-
for (int j=0;j<samples;j++){
103-
tmp[0]=src_16[j];
104-
tmp[1]=src_16[j];
105-
if (p_tx_buffer->availableForWrite()>=4){
106-
p_tx_buffer->writeArray((uint8_t*)tmp, 4);
107-
result = j*2;
108-
} else {
109-
// abort if the buffer is full
110-
break;
111-
}
112-
}
99+
int open = size_bytes;
100+
while(open>0){
101+
int actual_written = writeBytesExt(src, size_bytes);
102+
result+= actual_written;
103+
open -= actual_written;
104+
if (open>0){
105+
delay(10);
106+
}
113107
}
114108
return result;
115109
}
116110

117111
size_t readBytes(void *dest, size_t size_bytes){
118-
if (cfg.channels == 2){
112+
TRACED();
113+
if (cfg.channels == 2){
119114
return p_rx_buffer->readArray((uint8_t*)dest, size_bytes);
120115
} else {
121116
// combine two channels to 1: so request double the amout
@@ -134,10 +129,12 @@ class I2SBase {
134129
}
135130
}
136131

132+
/// @brief Callback function used by https://github.com/pschatzmann/stm32f411-i2s
137133
static void writeFromReceive(uint8_t *buffer, uint16_t byteCount){
138134
p_rx_buffer->writeArray(buffer, byteCount);
139135
}
140136

137+
/// @brief Callback function used by https://github.com/pschatzmann/stm32f411-i2s
141138
static void readToTransmit(uint8_t *buffer, uint16_t byteCount) {
142139
memset(buffer,0,byteCount);
143140
p_tx_buffer->readArray(buffer, byteCount);
@@ -227,7 +224,31 @@ class I2SBase {
227224
}
228225
}
229226

230-
227+
size_t writeBytesExt(const void *src, size_t size_bytes){
228+
size_t result = 0;
229+
if (cfg.channels == 2){
230+
result = p_tx_buffer->writeArray((uint8_t*)src, size_bytes);
231+
} else {
232+
// write each sample 2 times
233+
int samples = size_bytes / 2;
234+
int16_t *src_16 = (int16_t *)src;
235+
int16_t tmp[2];
236+
int result = 0;
237+
for (int j=0;j<samples;j++){
238+
tmp[0]=src_16[j];
239+
tmp[1]=src_16[j];
240+
if (p_tx_buffer->availableForWrite()>=4){
241+
p_tx_buffer->writeArray((uint8_t*)tmp, 4);
242+
result = j*2;
243+
} else {
244+
// abort if the buffer is full
245+
break;
246+
}
247+
}
248+
}
249+
LOGD("writeBytesExt: %u", result)
250+
return result;
251+
}
231252
};
232253

233254
}

src/AudioTimer/AudioTimerSTM32.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ class TimerAlarmRepeatingSTM32 : public TimerAlarmRepeatingDef {
3333
* Starts the alarm timer
3434
*/
3535
bool begin(repeating_timer_callback_t callback_f, uint32_t time, TimeUnit unit = MS) override {
36-
timer->attachInterrupt(std::bind(callback_f, this));
36+
TRACEI();
37+
timer->attachInterrupt(std::bind(callback_f, object));
3738

3839
// we determine the time in microseconds
3940
switch(unit){
@@ -50,6 +51,7 @@ class TimerAlarmRepeatingSTM32 : public TimerAlarmRepeatingDef {
5051

5152
// ends the timer and if necessary the task
5253
bool end() override {
54+
TRACEI();
5355
timer->pause();
5456
return true;
5557
}

0 commit comments

Comments
 (0)