From 19bf2b0766eb24be890e17c073c74086053e1222 Mon Sep 17 00:00:00 2001 From: unicod Date: Wed, 11 Mar 2026 23:26:45 +0100 Subject: [PATCH] ADC >> AudioBuf >> DAC forwarding works (mic signal to headphone) - Sound select: 7=mic (ADC right) - producer-consumer clock skew correction via sample doubling/dropping - keeping audio buffer between 25-75% fill level --- Core/Src/main.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/Core/Src/main.c b/Core/Src/main.c index 05f7487..ba8feed 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -68,6 +68,16 @@ LL_DMA_LinkNodeTypeDef Node_GPDMA1_Channel1; uint32_t I2S2RxDmaBuf[I2S2_RXDMA_BUF_SAMPLE_CNT][2] = {0}; uint32_t I2S2TxDmaBuf[I2S2_TXDMA_BUF_SAMPLE_CNT][2] = {0}; + +#define AUDIO_TX_CHAN_CNT 2 // Audio channel count for sending on RS485 bus +#define AUDIO_BUF_SAMPLE_CNT 1024 // Audio buffer size in samples (per channel) +int16_t AudioChanBuf[AUDIO_BUF_SAMPLE_CNT]; // Audio sample buffer for each channel, filled by audio ADC task and consumed by RS485 bus task. Each sample is 16-bit signed integer. + +uint16_t AudioWrPos = 0; // Write position in audio buffer (in samples) +uint16_t AudioRdPos = 0; // Read position in audio buffer (in samples) +uint16_t AudioDatCnt = 0; // Number of valid audio samples in buffer (per channel), updated by producer (audio ADC) and consumer (RS485 bus) tasks + + uint8_t ChSel = 0; uint8_t Vol = 0; @@ -214,8 +224,13 @@ void TLV320_AIC3204_Init() { void Fill_I2S_Buffer(uint32_t *buf, uint32_t start_sample, uint32_t sample_count) { + static uint8_t playing = 0; + uint_fast8_t doubling = 0; + uint_fast8_t dropping = 0; + for (uint32_t i = 0; i < sample_count; i++) { int16_t pcmsample = 0; + switch (ChSel) { case 0: case 1: @@ -239,11 +254,59 @@ void Fill_I2S_Buffer(uint32_t *buf, uint32_t start_sample, uint32_t sample_count if (SoundIdx >= ARRAY_COUNT(Sound_DE)) SoundIdx = 0; pcmsample = s << 8; // 8-bit PCM in MSB }break; + case 7: { + if (AudioDatCnt < (AUDIO_BUF_SAMPLE_CNT * 1 / 4)) { // too few samples in input buffer + if (doubling == 0) doubling = 10; + } + if (playing) { + if (AudioDatCnt == 0) { + pcmsample = 0; + playing = 0; + printf("x"); + } else { + int16_t d = AudioChanBuf[AudioRdPos]; // read audio sample + pcmsample = d; + AudioDatCnt--; + AudioRdPos++; + if (AudioRdPos >= AUDIO_BUF_SAMPLE_CNT) AudioRdPos = 0; + } + } else { // Buffering (wait..) + pcmsample = 0; + if (AudioDatCnt > (AUDIO_BUF_SAMPLE_CNT / 2)) { + playing = 1; + printf("w"); + } + } + if (AudioDatCnt > (AUDIO_BUF_SAMPLE_CNT * 3 / 4)) { // too many samples in input buffer + if (dropping == 0) dropping = 10; + } + }break; } int32_t frame = pcmsample << 16; // convert to 32-bit sample with 16-bit left justified uint32_t pos = (start_sample + i) * 2; // Stereo: L,R buf[pos + 0] = frame/4; // Left buf[pos + 1] = frame/4; // Right + + if (doubling == 10) { + if (i= AUDIO_BUF_SAMPLE_CNT) AudioRdPos = 0; + if (playing) printf("-"); + } + if (dropping) dropping--; + } } @@ -278,6 +341,13 @@ void Proc_I2S_Buffer(uint32_t *buf, uint32_t start_sample, uint32_t sample_count uint32_t pos = (start_sample + i) * 2; // Stereo: L,R int16_t left = buf[pos + 0] >> 16; // convert back to 16-bit sample from 32-bit left justified int16_t right = buf[pos + 1] >> 16; // convert back to 16-bit sample from 32-bit left justified + int16_t sample = right; + if (AudioDatCnt < AUDIO_BUF_SAMPLE_CNT-1) { + AudioDatCnt++; + AudioWrPos++; // increment position + if (AudioWrPos >= AUDIO_BUF_SAMPLE_CNT) AudioWrPos = 0; + AudioChanBuf[AudioWrPos] = sample; // store audio sample + } if (DumpI2SBufCnt) { printf("%d;%d\n", left, right); DumpI2SBufCnt--;