AnalogAudio corrections

This commit is contained in:
Phil Schatzmann 2021-10-10 11:06:08 +02:00
parent 33493201c8
commit 0e6b930877
8 changed files with 220 additions and 95 deletions

View File

@ -0,0 +1,44 @@
# Stream Analog Input to I2S
## General Description:
In this sketch we get the data from via the ESP32 I2S ADC and send it to I2S
Since the ADC via I2S is using the i2s port 0, we use port 1 for the output.
### Analog Input:
| ADC | ESP32
| --------| ---------------
| GND | GND
| Left | GPIO34
| Right | GPIO35
### External DAC:
![DAC](https://pschatzmann.github.io/arduino-audio-tools/resources/dac.jpeg)
For my tests I am using the 24-bit PCM5102 PCM5102A Stereo DAC Digital-to-analog Converter PLL Voice Module pHAT
I am just using the default pins defined by the framework. However I could change them with the help of the config object. The mute pin can be defined in the constructor of the I2SStream - by not defining anything we use the default which is GPIO23
| DAC | ESP32
| --------| ---------------
| VDD | 5V
| GND | GND
| SD | OUT (GPIO22)
| L/R | GND
| WS | WS (GPIO15)
| SCK | BCK (GPIO14)
| FMT | GND
| XSMT | GPIO23
- DEMP - De-emphasis control for 44.1kHz sampling rate(1): Off (Low) / On (High)
- FLT - Filter select : Normal latency (Low) / Low latency (High)
- SCK - System clock input (probably SCL on your board).
- FMT - Audio format selection : I2S (Low) / Left justified (High)
- XSMT - Soft mute control(1): Soft mute (Low) / soft un-mute (High)

View File

@ -0,0 +1,43 @@
/**
* @file streams-analog-i2s.ino
* @author Phil Schatzmann
* @brief see https://github.com/pschatzmann/arduino-audio-tools/blob/main/examples/streams-analog-i2s/README.md
*
* @author Phil Schatzmann
* @copyright GPLv3
*/
#include "Arduino.h"
#include "AudioTools.h"
using namespace audio_tools;
const uint16_t sample_rate = 44100;
AnalogAudioStream in;
I2SStream out;
StreamCopy copier(out, in); // copy i2sStream to a2dpStream
ConverterAutoCenter<int16_t> converter;
// Arduino Setup
void setup(void) {
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Info);
// RX automatically uses port 0 with pins GPIO34,GPIO35
auto cfgRx = in.defaultConfig(RX_MODE);
cfgRx.sample_rate = sample_rate;
in.begin(cfgRx);
// TX on I2S_NUM_1
auto cfgTx = out.defaultConfig(TX_MODE);
cfgTx.port_no = 1;
cfgTx.sample_rate = sample_rate;
out.begin(cfgTx);
}
// Arduino loop - copy data
void loop() {
copier.copy(converter);
}

View File

@ -0,0 +1,19 @@
# Stream Analog Input to Serial Output
## General Description:
In this sketch we get the data from via the ESP32 I2S ADC and send it to the Plotter
Since the ADC via I2S is using the i2s port 0 with the pins GPIO34 and GPIO35.
The ACD provides values centered around 24576 but we want to make sure that the average of the singal is around 0, so we use the ConverterAutoCenter.
### Analog Input:
| ADC | ESP32
| --------| ---------------
| GND | GND
| Left | GPIO34
| Right | GPIO35

View File

@ -0,0 +1,41 @@
/**
* @file streams-analog-serial.ino
* @author Phil Schatzmann
* @brief see https://github.com/pschatzmann/arduino-audio-tools/blob/main/examples/streams-analog-serial/README.md
*
* @author Phil Schatzmann
* @copyright GPLv3
*/
#include "Arduino.h"
#include "AudioTools.h"
using namespace audio_tools;
const uint16_t sample_rate = 44100;
const uint8_t channels = 2;
AnalogAudioStream in;
CsvStream<int16_t> out(Serial, channels); // ASCII output stream
StreamCopy copier(out, in); // copy i2sStream to a2dpStream
ConverterAutoCenter<int16_t> center; // set avg to 0
// Arduino Setup
void setup(void) {
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Info);
// RX automatically uses port 0 with pins GPIO34,GPIO35
auto cfgRx = in.defaultConfig(RX_MODE);
cfgRx.sample_rate = sample_rate;
in.begin(cfgRx);
// open output
out.begin();
}
// Arduino loop - copy data
void loop() {
copier.copy(center);
}

View File

@ -8,3 +8,21 @@ Currently we provide multiple mp3 decoders
Unfortunatly non of those are currently stable in all environments....
### Output Device: Piezo Electric Element
To test the output I am using piezo electric elements
![DAC](https://pschatzmann.github.io/arduino-audio-tools/resources/piezo.jpeg)
It should also be possible to connect a headphone to the output pins.
| PIEZO Left | ESP32
| ------------| --------------
| + | GPIO25
| - | GND
| PIEZO2 Rigt | ESP32
| ------------| --------------
| + | GPIO26
| - | GND

View File

@ -1,6 +1,6 @@
# Decoding a MP3 file
In this example we decode a MP3 file into RAW output and send it the analog output pins.
In this example we decode a MP3 file into RAW output and write the output with the help of a PWM signal to the pins.
Currently we provide multiple mp3 decoders
- libhelix
@ -8,3 +8,22 @@ Currently we provide multiple mp3 decoders
Unfortunatly non of those are currently stable in all environments....
### Output Device: Earphone
To test the output I am using an earphone from a mobile phone.
We get 2 signals one for the left and the other for the right channel.
![DAC](https://pschatzmann.github.io/arduino-audio-tools/resources/earphones.jpg)
The pins depend on the Processor:
| EarPhone | ESP32 | RPI Pico | MBED |
| -----------| -------------|---------------|--------------|
| Left | GPI2 | GPI2 | GPI2 |
| Right | GPI3 | GPIO3 | GPI3 |
| GND | GND | GND | GND |
To verify check the PWM_START_PIN in AudioConfig.h or you can set the pins by calling setPins() method on the PWMConfig object.

View File

@ -1,6 +1,6 @@
#pragma once
#include "AudioAnalog/ESP32AnalogAudio.h"
#include "AudioAnalog/AnalogAudioESP32.h"

View File

@ -41,9 +41,9 @@ class AnalogConfig : public AudioBaseInfo {
RxTxMode mode;
int dma_buf_count = I2S_BUFFER_COUNT;
int dma_buf_len = I2S_BUFFER_SIZE;
bool use_apll = false;
int mode_internal;
i2s_port_t i2s_port = I2S_NUM_0; // Analog input only supports 0!
int port_no = I2S_NUM_0; // Analog input and output only supports 0!
bool use_apll = false;
AnalogConfig() {
sample_rate = 44100;
@ -85,13 +85,13 @@ class AnalogConfig : public AudioBaseInfo {
void logInfo() {
AudioBaseInfo::logInfo();
if (mode == TX_MODE){
//int pin1, pin2;
//dac_pad_get_io_num(DAC_CHANNEL_1, pin1);
//dac_pad_get_io_num(DAC_CHANNEL_2, pin2);
LOGI("analog left output pin: %d", 25);
LOGI("analog right output pin: %d", 26);
} else {
LOGI("input pin: %d", adc_pin);
LOGI("input pin1: %d", adc_pin[0]);
if (channels==2){
LOGI("input pin2: %d", adc_pin[1]);
}
}
}
@ -106,35 +106,35 @@ class AnalogConfig : public AudioBaseInfo {
this->adc_pin[channelIdx] = gpio;
switch(gpio){
case 32:
adc_unit[0] = ADC_UNIT_1;
adc_unit[channelIdx] = ADC_UNIT_1;
adc_channel[channelIdx] = ADC1_GPIO32_CHANNEL;
break;
case 33:
adc_unit[0] = ADC_UNIT_1;
adc_unit[channelIdx] = ADC_UNIT_1;
adc_channel[channelIdx] = ADC1_GPIO33_CHANNEL;
break;
case 34:
adc_unit[0] = ADC_UNIT_1;
adc_unit[channelIdx] = ADC_UNIT_1;
adc_channel[channelIdx] = ADC1_GPIO34_CHANNEL;
break;
case 35:
adc_unit[0] = ADC_UNIT_1;
adc_unit[channelIdx] = ADC_UNIT_1;
adc_channel[channelIdx] = ADC1_GPIO35_CHANNEL;
break;
case 36:
adc_unit[0] = ADC_UNIT_1;
adc_unit[channelIdx] = ADC_UNIT_1;
adc_channel[channelIdx] = ADC1_GPIO36_CHANNEL;
break;
case 37:
adc_unit[0] = ADC_UNIT_1;
adc_unit[channelIdx] = ADC_UNIT_1;
adc_channel[channelIdx] = ADC1_GPIO37_CHANNEL;
break;
case 38:
adc_unit[0] = ADC_UNIT_1;
adc_unit[channelIdx] = ADC_UNIT_1;
adc_channel[channelIdx] = ADC1_GPIO38_CHANNEL;
break;
case 39:
adc_unit[0] = ADC_UNIT_1;
adc_unit[channelIdx] = ADC_UNIT_1;
adc_channel[channelIdx] = ADC1_GPIO39_CHANNEL;
break;
@ -142,8 +142,6 @@ class AnalogConfig : public AudioBaseInfo {
LOGE( "%s - pin GPIO%d is not supported", __func__,gpio);
}
}
};
@ -190,6 +188,7 @@ class AnalogAudio : public Stream, public AudioBaseInfoDependent {
void begin(AnalogConfig cfg) {
LOGI(LOG_METHOD);
cfg.logInfo();
port_no = (i2s_port_t) cfg.port_no;
adc_config = cfg;
i2s_config_t i2s_config = {
@ -207,13 +206,13 @@ class AnalogAudio : public Stream, public AudioBaseInfoDependent {
// setup config
if (i2s_driver_install(cfg.i2s_port, &i2s_config, 0, nullptr)!=ESP_OK){
if (i2s_driver_install(port_no, &i2s_config, 0, nullptr)!=ESP_OK){
LOGE( "%s - %s", __func__, "i2s_driver_install");
return;
}
// clear i2s buffer
if (i2s_zero_dma_buffer(cfg.i2s_port)!=ESP_OK) {
if (i2s_zero_dma_buffer(port_no)!=ESP_OK) {
LOGE( "%s - %s", __func__, "i2s_zero_dma_buffer");
return;
}
@ -221,10 +220,12 @@ class AnalogAudio : public Stream, public AudioBaseInfoDependent {
switch (cfg.mode) {
case RX_MODE:
//init ADC pad
if (i2s_set_adc_mode(cfg.adc_unit[0], cfg.adc_channel[0])!=ESP_OK) {
LOGE( "%s - %s", __func__, "i2s_driver_install");
return;
}
if (cfg.channels>1){
if (i2s_set_adc_mode(cfg.adc_unit[1], cfg.adc_channel[1])!=ESP_OK) {
LOGE( "%s - %s", __func__, "i2s_driver_install");
@ -233,14 +234,21 @@ class AnalogAudio : public Stream, public AudioBaseInfoDependent {
}
// enable the ADC
if (i2s_adc_enable(cfg.i2s_port)!=ESP_OK) {
if (i2s_adc_enable(port_no)!=ESP_OK) {
LOGE( "%s - %s", __func__, "i2s_adc_enable");
return;
}
// if (adc1_config_channel_atten(ADC1_CHANNEL_6,ADC_ATTEN_DB_11)!=ESP_OK){
// LOGE( "%s - %s", __func__, "adc1_config_channel_atten");
// }
// if (adc1_config_channel_atten(ADC1_CHANNEL_7,ADC_ATTEN_DB_11)!=ESP_OK){
// LOGE( "%s - %s", __func__, "adc1_config_channel_atten");
// }
break;
case TX_MODE:
i2s_set_pin(cfg.i2s_port, nullptr);
i2s_set_pin(port_no, nullptr);
break;
}
active = true;
@ -251,7 +259,8 @@ class AnalogAudio : public Stream, public AudioBaseInfoDependent {
/// stops the I2C and unistalls the driver
void end(){
LOGD( "%s", __func__);
i2s_driver_uninstall(adc_config.i2s_port);
i2s_adc_disable(port_no);
i2s_driver_uninstall(port_no);
active = false;
}
@ -273,19 +282,19 @@ class AnalogAudio : public Stream, public AudioBaseInfoDependent {
size_t result = 0;
if (adc_config.channels==2){
if (i2s_write(adc_config.i2s_port, src, size_bytes, &result, portMAX_DELAY)!=ESP_OK){
if (i2s_write(port_no, src, size_bytes, &result, portMAX_DELAY)!=ESP_OK){
LOGE(LOG_METHOD);
}
LOGD("i2s_write %d -> %d bytes", size_bytes, result);
} else {
result = I2SBase::writeExpandChannel(adc_config.i2s_port, adc_config.bits_per_sample, src, size_bytes);
result = I2SBase::writeExpandChannel(port_no, adc_config.bits_per_sample, src, size_bytes);
}
return result;
}
size_t readBytes(void *dest, size_t size_bytes){
size_t result = 0;
if (i2s_read(adc_config.i2s_port, dest, size_bytes, &result, portMAX_DELAY)!=ESP_OK){
if (i2s_read(port_no, dest, size_bytes, &result, portMAX_DELAY)!=ESP_OK){
LOGE(LOG_METHOD);
}
LOGD( "%s - len: %d -> %d", __func__, size_bytes, result);
@ -314,77 +323,9 @@ class AnalogAudio : public Stream, public AudioBaseInfoDependent {
protected:
AnalogConfig adc_config;
i2s_port_t port_no;
bool active = false;
// /// writes the data by making shure that we send 2 channels 16 data scaled to 8 bits
// static size_t writeExpandChannel(i2s_port_t i2s_port, int channels, const int bits_per_sample, const void *src, size_t size_bytes){
// size_t result = 0;
// int j;
// switch(bits_per_sample){
// case 8:
// for (j=0;j<size_bytes;j+=channels) {
// int16_t frame[2];
// int8_t *data = (int8_t *)src;
// frame[0]=convert8DAC(data[j],bits_per_sample);
// frame[1]=convert8DAC(data[j+channels-1],bits_per_sample);
// size_t result_call = 0;
// if (i2s_write(i2s_port, frame, sizeof(int16_t)*2, &result_call, portMAX_DELAY)!=ESP_OK){
// LOGE(LOG_METHOD);
// } else {
// result += result_call;
// }
// }
// break;
// case 16:
// for (j=0;j<size_bytes/2;j+=channels) {
// int16_t frame[2];
// int16_t *data = (int16_t*)src;
// frame[0]=convert8DAC(data[j],bits_per_sample);
// frame[1]=convert8DAC(data[j+channels-1],bits_per_sample);
// size_t result_call = 0;
// if (i2s_write(i2s_port, frame, sizeof(int16_t)*2, &result_call, portMAX_DELAY)!=ESP_OK){
// LOGE(LOG_METHOD);
// } else {
// result += result_call;
// }
// }
// break;
// case 24:
// for (j=0;j<size_bytes/4;j+=channels){
// int16_t frame[2];
// int24_t *data = (int24_t*) src;
// frame[0]=convert8DAC(data[j],bits_per_sample);
// frame[1]=convert8DAC(data[j+channels-1],bits_per_sample);
// size_t result_call = 0;
// if (i2s_write(i2s_port, frame, sizeof(int16_t)*2, &result_call, portMAX_DELAY)!=ESP_OK){
// LOGE(LOG_METHOD);
// } else {
// result += result_call;
// }
// }
// break;
// case 32:
// for (j=0;j<size_bytes/4;j+=channels){
// int16_t frame[2];
// int32_t *data = (int32_t*) src;
// frame[0]=convert8DAC(data[j],bits_per_sample);
// frame[1]=convert8DAC(data[j+channels-1],bits_per_sample);
// size_t result_call = 0;
// if (i2s_write(i2s_port, frame, sizeof(int16_t)*2, &result_call, portMAX_DELAY)!=ESP_OK){
// LOGE(LOG_METHOD);
// } else {
// result += result_call;
// }
// }
// break;
// }
// return result;
// }
};
/**