mirror of
https://github.com/meshtastic/firmware.git
synced 2025-02-03 03:09:59 +00:00
Audio Module is finished for regression tests.
This commit is contained in:
parent
eb4f682ad1
commit
470e711383
@ -1 +1 @@
|
||||
Subproject commit 2bb457de42cd6d5c2a6e7d8a4992fc6c90e37de5
|
||||
Subproject commit 0a59599589bc77763e76302e533a4c4bfa5ec80e
|
@ -151,7 +151,7 @@ extern const pb_msgdesc_t LocalModuleConfig_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define LocalConfig_size 387
|
||||
#define LocalModuleConfig_size 364
|
||||
#define LocalModuleConfig_size 358
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
@ -63,8 +63,6 @@ typedef enum _ModuleConfig_CannedMessageConfig_InputEventChar {
|
||||
/* Struct definitions */
|
||||
typedef struct _ModuleConfig_AudioConfig {
|
||||
bool codec2_enabled;
|
||||
uint8_t mic_chan;
|
||||
uint8_t amp_pin;
|
||||
uint8_t ptt_pin;
|
||||
ModuleConfig_AudioConfig_Audio_Baud bitrate;
|
||||
uint8_t i2s_ws;
|
||||
@ -187,7 +185,7 @@ extern "C" {
|
||||
/* Initializer values for message structs */
|
||||
#define ModuleConfig_init_default {0, {ModuleConfig_MQTTConfig_init_default}}
|
||||
#define ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0}
|
||||
#define ModuleConfig_AudioConfig_init_default {0, 0, 0, 0, _ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0}
|
||||
#define ModuleConfig_AudioConfig_init_default {0, 0, _ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0}
|
||||
#define ModuleConfig_SerialConfig_init_default {0, 0, 0, 0, _ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _ModuleConfig_SerialConfig_Serial_Mode_MIN}
|
||||
#define ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0, 0}
|
||||
#define ModuleConfig_StoreForwardConfig_init_default {0, 0, 0, 0, 0}
|
||||
@ -196,7 +194,7 @@ extern "C" {
|
||||
#define ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
|
||||
#define ModuleConfig_init_zero {0, {ModuleConfig_MQTTConfig_init_zero}}
|
||||
#define ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0}
|
||||
#define ModuleConfig_AudioConfig_init_zero {0, 0, 0, 0, _ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0}
|
||||
#define ModuleConfig_AudioConfig_init_zero {0, 0, _ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0}
|
||||
#define ModuleConfig_SerialConfig_init_zero {0, 0, 0, 0, _ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _ModuleConfig_SerialConfig_Serial_Mode_MIN}
|
||||
#define ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0, 0}
|
||||
#define ModuleConfig_StoreForwardConfig_init_zero {0, 0, 0, 0, 0}
|
||||
@ -206,14 +204,12 @@ extern "C" {
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define ModuleConfig_AudioConfig_codec2_enabled_tag 1
|
||||
#define ModuleConfig_AudioConfig_mic_chan_tag 2
|
||||
#define ModuleConfig_AudioConfig_amp_pin_tag 3
|
||||
#define ModuleConfig_AudioConfig_ptt_pin_tag 4
|
||||
#define ModuleConfig_AudioConfig_bitrate_tag 5
|
||||
#define ModuleConfig_AudioConfig_i2s_ws_tag 6
|
||||
#define ModuleConfig_AudioConfig_i2s_sd_tag 7
|
||||
#define ModuleConfig_AudioConfig_i2s_din_tag 8
|
||||
#define ModuleConfig_AudioConfig_i2s_sck_tag 9
|
||||
#define ModuleConfig_AudioConfig_ptt_pin_tag 2
|
||||
#define ModuleConfig_AudioConfig_bitrate_tag 3
|
||||
#define ModuleConfig_AudioConfig_i2s_ws_tag 4
|
||||
#define ModuleConfig_AudioConfig_i2s_sd_tag 5
|
||||
#define ModuleConfig_AudioConfig_i2s_din_tag 6
|
||||
#define ModuleConfig_AudioConfig_i2s_sck_tag 7
|
||||
#define ModuleConfig_CannedMessageConfig_rotary1_enabled_tag 1
|
||||
#define ModuleConfig_CannedMessageConfig_inputbroker_pin_a_tag 2
|
||||
#define ModuleConfig_CannedMessageConfig_inputbroker_pin_b_tag 3
|
||||
@ -300,14 +296,12 @@ X(a, STATIC, SINGULAR, BOOL, json_enabled, 6)
|
||||
|
||||
#define ModuleConfig_AudioConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, BOOL, codec2_enabled, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, mic_chan, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, amp_pin, 3) \
|
||||
X(a, STATIC, SINGULAR, UINT32, ptt_pin, 4) \
|
||||
X(a, STATIC, SINGULAR, UENUM, bitrate, 5) \
|
||||
X(a, STATIC, SINGULAR, UINT32, i2s_ws, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, i2s_sd, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, i2s_din, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, i2s_sck, 9)
|
||||
X(a, STATIC, SINGULAR, UINT32, ptt_pin, 2) \
|
||||
X(a, STATIC, SINGULAR, UENUM, bitrate, 3) \
|
||||
X(a, STATIC, SINGULAR, UINT32, i2s_ws, 4) \
|
||||
X(a, STATIC, SINGULAR, UINT32, i2s_sd, 5) \
|
||||
X(a, STATIC, SINGULAR, UINT32, i2s_din, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, i2s_sck, 7)
|
||||
#define ModuleConfig_AudioConfig_CALLBACK NULL
|
||||
#define ModuleConfig_AudioConfig_DEFAULT NULL
|
||||
|
||||
@ -395,7 +389,7 @@ extern const pb_msgdesc_t ModuleConfig_CannedMessageConfig_msg;
|
||||
#define ModuleConfig_CannedMessageConfig_fields &ModuleConfig_CannedMessageConfig_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define ModuleConfig_AudioConfig_size 25
|
||||
#define ModuleConfig_AudioConfig_size 19
|
||||
#define ModuleConfig_CannedMessageConfig_size 49
|
||||
#define ModuleConfig_ExternalNotificationConfig_size 22
|
||||
#define ModuleConfig_MQTTConfig_size 169
|
||||
|
@ -8,8 +8,6 @@
|
||||
#include "Router.h"
|
||||
#include "FSCommon.h"
|
||||
|
||||
#include <soc/sens_reg.h>
|
||||
#include <soc/sens_struct.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
@ -23,23 +21,14 @@
|
||||
|
||||
Basic Usage:
|
||||
1) Enable the module by setting audio.codec2_enabled to 1.
|
||||
2a) Set the pins for the I2S interface if you want to use digital audio. Recommended on TLora is I2S_WS 13/I2S_SD 15/I2S_SIN 2/I2S_SCK 14
|
||||
2b) Set the pins (audio.mic_pin / audio.amp_pin) for your preferred microphone and amplifier GPIO pins if you want to use analog audio.
|
||||
This is rather heavy on the CPU and not recommended.
|
||||
On tbeam, best use:
|
||||
audio.mic_chan 6 (GPIO 34)
|
||||
audio.amp_pin 14
|
||||
audio.ptt_pin 39
|
||||
2) Set the pins for the I2S interface. Recommended on TLora is I2S_WS 13/I2S_SD 15/I2S_SIN 2/I2S_SCK 14
|
||||
3) Set audio.bitrate to the desired codec2 rate (CODEC2_3200, CODEC2_2400, CODEC2_1600, CODEC2_1400, CODEC2_1300, CODEC2_1200, CODEC2_700, CODEC2_700B)
|
||||
|
||||
KNOWN PROBLEMS
|
||||
* Until the module is initilized by the startup sequence, the amp_pin is in a floating
|
||||
state. This may produce a bit of "noise".
|
||||
* Half Duplex
|
||||
* Will not work on NRF and the Linux device targets (yet?).
|
||||
*/
|
||||
|
||||
#define AMIC 6
|
||||
#define AAMP 14
|
||||
#define PTT_PIN 39
|
||||
|
||||
ButterworthFilter hp_filter(240, 8000, ButterworthFilter::ButterworthFilter::Highpass, 1);
|
||||
@ -60,67 +49,10 @@ AudioModule *audioModule;
|
||||
#define YIELD_FROM_ISR(x) portYIELD_FROM_ISR(x)
|
||||
#endif
|
||||
|
||||
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
|
||||
hw_timer_t* adcTimer = NULL;
|
||||
|
||||
//int16_t 1KHz sine test tone
|
||||
int16_t Sine1KHz[8] = { -21210 , -30000, -21210, 0 , 21210 , 30000 , 21210, 0 };
|
||||
int Sine1KHz_index = 0;
|
||||
|
||||
int IRAM_ATTR local_adc1_read(int channel) {
|
||||
uint16_t adc_value;
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
SENS.sar_meas1_ctrl2.sar1_en_pad = (1 << channel); // only one channel is selected
|
||||
while (SENS.sar_slave_addr1.meas_status != 0);
|
||||
SENS.sar_meas1_ctrl2.meas1_start_sar = 0;
|
||||
SENS.sar_meas1_ctrl2.meas1_start_sar = 1;
|
||||
while (SENS.sar_meas1_ctrl2.meas1_done_sar == 0);
|
||||
adc_value = SENS.sar_meas1_ctrl2.meas1_data_sar;
|
||||
#else
|
||||
SENS.sar_meas_start1.sar1_en_pad = (1 << channel); // only one channel is selected
|
||||
while (SENS.sar_slave_addr1.meas_status != 0);
|
||||
SENS.sar_meas_start1.meas1_start_sar = 0;
|
||||
SENS.sar_meas_start1.meas1_start_sar = 1;
|
||||
while (SENS.sar_meas_start1.meas1_done_sar == 0);
|
||||
adc_value = SENS.sar_meas_start1.meas1_data_sar;
|
||||
#endif
|
||||
return adc_value;
|
||||
}
|
||||
|
||||
IRAM_ATTR void am_onTimer()
|
||||
{
|
||||
portENTER_CRITICAL_ISR(&timerMux); //Enter crital code without interruptions
|
||||
if ((audioModule->radio_state == RadioState::tx) && (!moduleConfig.audio.i2s_sd)) {
|
||||
audioModule->adc_buffer[audioModule->adc_buffer_index++] = (16 * local_adc1_read(audioModule->mic_chan)) - 32768;
|
||||
|
||||
//If you want to test with a 1KHz tone, comment the line above and descomment the three lines below
|
||||
|
||||
// adc_buffer[adc_buffer_index++] = Sine1KHz[Sine1KHz_index++];
|
||||
// if (Sine1KHz_index >= 8)
|
||||
// Sine1KHz_index = 0;
|
||||
|
||||
if (audioModule->adc_buffer_index == audioModule->adc_buffer_size) {
|
||||
audioModule->adc_buffer_index = 0;
|
||||
memcpy((void*)audioModule->speech, (void*)audioModule->adc_buffer, 2 * audioModule->adc_buffer_size);
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
vTaskNotifyGiveFromISR(codec2HandlerTask, &xHigherPriorityTaskWoken);
|
||||
if (xHigherPriorityTaskWoken == pdTRUE)
|
||||
YIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
} else if ((audioModule->radio_state == RadioState::rx) && (!moduleConfig.audio.i2s_din)) {
|
||||
// ESP32-S3 does not have DAC support
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
//Get a value from audio_fifo and convert it to 0 - 255 to play it in the ADC
|
||||
if (audioModule->fifo.get(&audioModule->sample))
|
||||
audioModule->rx_raw_audio_value = (uint8_t)((audioModule->sample + 32768) / 256);
|
||||
|
||||
dacWrite(moduleConfig.audio.amp_pin ? moduleConfig.audio.amp_pin : AAMP, audioModule->rx_raw_audio_value);
|
||||
#endif
|
||||
}
|
||||
portEXIT_CRITICAL_ISR(&timerMux); // exit critical code
|
||||
}
|
||||
|
||||
void run_codec2(void* parameter)
|
||||
{
|
||||
while (true) {
|
||||
@ -128,10 +60,12 @@ void run_codec2(void* parameter)
|
||||
|
||||
if (tcount != 0) {
|
||||
if (audioModule->radio_state == RadioState::tx) {
|
||||
|
||||
|
||||
// Apply the TX filter
|
||||
for (int i = 0; i < audioModule->adc_buffer_size; i++)
|
||||
audioModule->speech[i] = (int16_t)hp_filter.Update((float)audioModule->speech[i]);
|
||||
|
||||
// Encode the audio
|
||||
codec2_encode(audioModule->codec2, audioModule->tx_encode_frame + audioModule->tx_encode_frame_index, audioModule->speech);
|
||||
|
||||
//increment the pointer where the encoded frame must be saved
|
||||
@ -141,7 +75,7 @@ void run_codec2(void* parameter)
|
||||
if (audioModule->tx_encode_frame_index == audioModule->encode_frame_size)
|
||||
{
|
||||
//Transmit it
|
||||
DEBUG_MSG("♪♫♪ Sending %d bytes\n", audioModule->encode_frame_size);
|
||||
DEBUG_MSG("♪♫♪ Sending %d codec2 bytes\n", audioModule->encode_frame_size);
|
||||
audioModule->sendPayload();
|
||||
audioModule->tx_encode_frame_index = 0;
|
||||
}
|
||||
@ -152,16 +86,8 @@ void run_codec2(void* parameter)
|
||||
{
|
||||
//Decode the codec2 frame
|
||||
codec2_decode(audioModule->codec2, audioModule->output_buffer, audioModule->rx_encode_frame + i);
|
||||
|
||||
if (moduleConfig.audio.i2s_din) {
|
||||
size_t bytesOut = 0;
|
||||
|
||||
i2s_write(I2S_PORT, &audioModule->output_buffer, audioModule->adc_buffer_size, &bytesOut, pdMS_TO_TICKS(40));
|
||||
} else {
|
||||
//Put the decoded audio in the fifo
|
||||
for (int j = 0; j < audioModule->adc_buffer_size; j++)
|
||||
audioModule->fifo.put(audioModule->output_buffer[j]);
|
||||
}
|
||||
size_t bytesOut = 0;
|
||||
i2s_write(I2S_PORT, &audioModule->output_buffer, audioModule->adc_buffer_size, &bytesOut, pdMS_TO_TICKS(500));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -171,7 +97,6 @@ void run_codec2(void* parameter)
|
||||
AudioModule::AudioModule() : SinglePortModule("AudioModule", PortNum_AUDIO_APP), concurrency::OSThread("AudioModule")
|
||||
{
|
||||
if ((moduleConfig.audio.codec2_enabled) && (myRegion->audioPermitted)) {
|
||||
fifo.init();
|
||||
DEBUG_MSG("♪♫♪ Setting up codec2 in mode %u", (moduleConfig.audio.bitrate ? moduleConfig.audio.bitrate : AUDIO_MODULE_MODE) - 1);
|
||||
codec2 = codec2_create((moduleConfig.audio.bitrate ? moduleConfig.audio.bitrate : AUDIO_MODULE_MODE) - 1);
|
||||
codec2_set_lpc_post_filter(codec2, 1, 0, 0.8, 0.2);
|
||||
@ -191,86 +116,39 @@ int32_t AudioModule::runOnce()
|
||||
if ((moduleConfig.audio.codec2_enabled) && (myRegion->audioPermitted)) {
|
||||
esp_err_t res;
|
||||
if (firstTime) {
|
||||
// if we have I2S_SD defined, take samples from digital mic. I2S_DIN means digital output to amp.
|
||||
if (moduleConfig.audio.i2s_sd || moduleConfig.audio.i2s_din) {
|
||||
// Set up I2S Processor configuration. This will produce 16bit samples at 8 kHz instead of 12 from the ADC
|
||||
DEBUG_MSG("♪♫♪ Initializing I2S SD: %d DIN: %d WS: %d SCK:%d\n", moduleConfig.audio.i2s_sd, moduleConfig.audio.i2s_din, moduleConfig.audio.i2s_ws, moduleConfig.audio.i2s_sck);
|
||||
i2s_config_t i2s_config = {
|
||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | (moduleConfig.audio.i2s_sd ? I2S_MODE_RX : 0) | (moduleConfig.audio.i2s_din ? I2S_MODE_TX : 0)),
|
||||
.sample_rate = 8000,
|
||||
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
|
||||
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
|
||||
.communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_STAND_I2S),
|
||||
.intr_alloc_flags = 0,
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = adc_buffer_size, // 320 * 2 bytes
|
||||
.use_apll = false,
|
||||
.tx_desc_auto_clear = true,
|
||||
.fixed_mclk = 0
|
||||
};
|
||||
res = i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
|
||||
if(res != ESP_OK)
|
||||
DEBUG_MSG("♪♫♪ Failed to install I2S driver: %d\n", res);
|
||||
// Set up I2S Processor configuration. This will produce 16bit samples at 8 kHz instead of 12 from the ADC
|
||||
DEBUG_MSG("♪♫♪ Initializing I2S SD: %d DIN: %d WS: %d SCK:%d\n", moduleConfig.audio.i2s_sd, moduleConfig.audio.i2s_din, moduleConfig.audio.i2s_ws, moduleConfig.audio.i2s_sck);
|
||||
i2s_config_t i2s_config = {
|
||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | (moduleConfig.audio.i2s_sd ? I2S_MODE_RX : 0) | (moduleConfig.audio.i2s_din ? I2S_MODE_TX : 0)),
|
||||
.sample_rate = 8000,
|
||||
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
|
||||
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
|
||||
.communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_STAND_I2S),
|
||||
.intr_alloc_flags = 0,
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = adc_buffer_size, // 320 * 2 bytes
|
||||
.use_apll = false,
|
||||
.tx_desc_auto_clear = true,
|
||||
.fixed_mclk = 0
|
||||
};
|
||||
res = i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
|
||||
if(res != ESP_OK)
|
||||
DEBUG_MSG("♪♫♪ Failed to install I2S driver: %d\n", res);
|
||||
|
||||
const i2s_pin_config_t pin_config = {
|
||||
.bck_io_num = moduleConfig.audio.i2s_sck,
|
||||
.ws_io_num = moduleConfig.audio.i2s_ws,
|
||||
.data_out_num = moduleConfig.audio.i2s_din ? moduleConfig.audio.i2s_din : I2S_PIN_NO_CHANGE,
|
||||
.data_in_num = moduleConfig.audio.i2s_sd ? moduleConfig.audio.i2s_sd : I2S_PIN_NO_CHANGE
|
||||
};
|
||||
res = i2s_set_pin(I2S_PORT, &pin_config);
|
||||
if(res != ESP_OK)
|
||||
DEBUG_MSG("♪♫♪ Failed to set I2S pin config: %d\n", res);
|
||||
const i2s_pin_config_t pin_config = {
|
||||
.bck_io_num = moduleConfig.audio.i2s_sck,
|
||||
.ws_io_num = moduleConfig.audio.i2s_ws,
|
||||
.data_out_num = moduleConfig.audio.i2s_din ? moduleConfig.audio.i2s_din : I2S_PIN_NO_CHANGE,
|
||||
.data_in_num = moduleConfig.audio.i2s_sd ? moduleConfig.audio.i2s_sd : I2S_PIN_NO_CHANGE
|
||||
};
|
||||
res = i2s_set_pin(I2S_PORT, &pin_config);
|
||||
if(res != ESP_OK)
|
||||
DEBUG_MSG("♪♫♪ Failed to set I2S pin config: %d\n", res);
|
||||
|
||||
res = i2s_start(I2S_PORT);
|
||||
if(res != ESP_OK)
|
||||
DEBUG_MSG("♪♫♪ Failed to start I2S: %d\n", res);
|
||||
}
|
||||
|
||||
// setup analogue DAC only if we don't use I2S for output. This is not available on ESP32-S3
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
if (!moduleConfig.audio.i2s_din)
|
||||
DEBUG_MSG("♪♫♪ Initializing DAC on Pin %u\n", moduleConfig.audio.amp_pin ? moduleConfig.audio.amp_pin : AAMP);
|
||||
#else
|
||||
if (!moduleConfig.audio.i2s_din) {
|
||||
DEBUG_MSG("♪♫♪ ESP32-S3 does not support DAC. Audio Module Disabled.\n");
|
||||
return INT32_MAX;
|
||||
}
|
||||
#endif
|
||||
res = i2s_start(I2S_PORT);
|
||||
if(res != ESP_OK)
|
||||
DEBUG_MSG("♪♫♪ Failed to start I2S: %d\n", res);
|
||||
|
||||
if (!moduleConfig.audio.i2s_sd) {
|
||||
// Set up ADC if we don't have a digital microphone.
|
||||
DEBUG_MSG("♪♫♪ Initializing ADC on Channel %u\n", moduleConfig.audio.mic_chan ? moduleConfig.audio.mic_chan : AMIC);
|
||||
mic_chan = moduleConfig.audio.mic_chan ? (adc1_channel_t)(int)moduleConfig.audio.mic_chan : (adc1_channel_t)AMIC;
|
||||
adc1_config_width(ADC_WIDTH_12Bit);
|
||||
adc1_config_channel_atten(mic_chan, ADC_ATTEN_DB_6);
|
||||
adc1_get_raw(mic_chan);
|
||||
}
|
||||
|
||||
if ((!moduleConfig.audio.i2s_sd) || (!moduleConfig.audio.i2s_din)) {
|
||||
// Start a timer at 8kHz to sample the ADC and play the audio on the DAC, but only if we have analogue audio to process
|
||||
uint32_t cpufreq = getCpuFrequencyMhz();
|
||||
switch (cpufreq){
|
||||
case 160:
|
||||
adcTimer = timerBegin(3, 1000, true); // 160 MHz / 1000 = 160KHz
|
||||
break;
|
||||
case 240:
|
||||
adcTimer = timerBegin(3, 1500, true); // 240 MHz / 1500 = 160KHz
|
||||
break;
|
||||
case 320:
|
||||
adcTimer = timerBegin(3, 2000, true); // 320 MHz / 2000 = 160KHz
|
||||
break;
|
||||
case 80:
|
||||
default:
|
||||
adcTimer = timerBegin(3, 500, true); // 80 MHz / 500 = 160KHz
|
||||
break;
|
||||
}
|
||||
DEBUG_MSG("♪♫♪ Timer CPU Frequency: %u MHz\n", cpufreq);
|
||||
timerAttachInterrupt(adcTimer, &am_onTimer, false);
|
||||
timerAlarmWrite(adcTimer, 20, true); // Interrupts when counter == 20, 8.000 times a second
|
||||
timerAlarmEnable(adcTimer);
|
||||
}
|
||||
|
||||
radio_state = RadioState::rx;
|
||||
|
||||
// Configure PTT input
|
||||
@ -289,7 +167,7 @@ int32_t AudioModule::runOnce()
|
||||
if (radio_state == RadioState::tx) {
|
||||
if (tx_encode_frame_index > 0) {
|
||||
// Send the incomplete frame
|
||||
DEBUG_MSG("♪♫♪ Sending %d bytes (incomplete)\n", tx_encode_frame_index);
|
||||
DEBUG_MSG("♪♫♪ Sending %d codec2 bytes (incomplete)\n", tx_encode_frame_index);
|
||||
sendPayload();
|
||||
}
|
||||
DEBUG_MSG("♪♫♪ PTT released, switching to RX\n");
|
||||
@ -297,7 +175,7 @@ int32_t AudioModule::runOnce()
|
||||
radio_state = RadioState::rx;
|
||||
}
|
||||
}
|
||||
if ((radio_state == RadioState::tx) && moduleConfig.audio.i2s_sd) {
|
||||
if (radio_state == RadioState::tx) {
|
||||
// Get I2S data from the microphone and place in data buffer
|
||||
size_t bytesIn = 0;
|
||||
res = i2s_read(I2S_PORT, adc_buffer + adc_buffer_index, adc_buffer_size - adc_buffer_index, &bytesIn, pdMS_TO_TICKS(40)); // wait 40ms for audio to arrive.
|
||||
|
@ -7,11 +7,9 @@
|
||||
#include "NodeDB.h"
|
||||
#include <Arduino.h>
|
||||
#include <driver/i2s.h>
|
||||
// #include <driver/adc.h>
|
||||
#include <functional>
|
||||
#include <codec2.h>
|
||||
#include <ButterworthFilter.h>
|
||||
#include <FastAudioFIFO.h>
|
||||
|
||||
#define ADC_BUFFER_SIZE_MAX 320
|
||||
|
||||
@ -32,11 +30,9 @@ class AudioModule : public SinglePortModule, private concurrency::OSThread
|
||||
int encode_codec_size = 0;
|
||||
int encode_frame_size = 0;
|
||||
volatile RadioState radio_state = RadioState::rx;
|
||||
FastAudioFIFO fifo;
|
||||
|
||||
struct CODEC2* codec2 = NULL;
|
||||
int16_t sample;
|
||||
adc1_channel_t mic_chan = (adc1_channel_t)0;
|
||||
uint8_t rx_raw_audio_value = 127;
|
||||
// int16_t sample;
|
||||
|
||||
AudioModule();
|
||||
|
||||
@ -49,7 +45,6 @@ class AudioModule : public SinglePortModule, private concurrency::OSThread
|
||||
int encode_frame_num = 0;
|
||||
bool firstTime = true;
|
||||
|
||||
|
||||
virtual int32_t runOnce() override;
|
||||
|
||||
virtual MeshPacket *allocReply() override;
|
||||
|
Loading…
Reference in New Issue
Block a user