From 1eb9d6c3d00a1008def6e2296e73abe39820e177 Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Fri, 10 Jul 2026 15:45:42 +0100 Subject: [PATCH 01/10] JMS1 First Attempt no IQ displayed but didn't crash --- OpenAudio_ArduinoLibrary.h | 1 + input_i2s_quad_f32.cpp | 216 +++++++++++++++++++++++++++++++++++++ input_i2s_quad_f32.h | 75 +++++++++++++ 3 files changed, 292 insertions(+) create mode 100644 input_i2s_quad_f32.cpp create mode 100644 input_i2s_quad_f32.h diff --git a/OpenAudio_ArduinoLibrary.h b/OpenAudio_ArduinoLibrary.h index 6006e91..6809e81 100644 --- a/OpenAudio_ArduinoLibrary.h +++ b/OpenAudio_ArduinoLibrary.h @@ -29,6 +29,7 @@ #include "AudioSettings_F32.h" #include "AudioSpectralDenoise_F32.h" #include "input_i2s_f32.h" +#include "input_i2s_quad_f32.h" #include "input_spdif3_f32.h" #include "async_input_spdif3_F32.h" #include "output_i2s_f32.h" diff --git a/input_i2s_quad_f32.cpp b/input_i2s_quad_f32.cpp new file mode 100644 index 0000000..8898a2d --- /dev/null +++ b/input_i2s_quad_f32.cpp @@ -0,0 +1,216 @@ +/* + * input_i2s_quad_f32.cpp + * + * Audio Library for Teensy 3.X + * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com + * + * Development of this audio library was funded by PJRC.COM, LLC by sales of + * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop + * open source software by purchasing Teensy or other PJRC products. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice, development funding notice, and this permission + * notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + /* + * Extended by Terrance Robertson, May 2025 + * Converted to F32 + */ + +#include +#include "input_i2s_quad_f32.h" +#include "output_i2s_quad_f32.h" +#include "output_i2s_f32.h" + +DMAMEM __attribute__((aligned(32))) static uint32_t i2s_rx_buffer[AUDIO_BLOCK_SAMPLES*2]; +audio_block_f32_t * AudioInputI2SQuad_F32::block_ch1 = NULL; +audio_block_f32_t * AudioInputI2SQuad_F32::block_ch2 = NULL; +audio_block_f32_t * AudioInputI2SQuad_F32::block_ch3 = NULL; +audio_block_f32_t * AudioInputI2SQuad_F32::block_ch4 = NULL; +uint16_t AudioInputI2SQuad_F32::block_offset = 0; +bool AudioInputI2SQuad_F32::update_responsibility = false; +DMAChannel AudioInputI2SQuad_F32::dma(false); + +float AudioInputI2SQuad_F32::sample_rate_Hz = AUDIO_SAMPLE_RATE; +int AudioInputI2SQuad_F32::audio_block_samples = AUDIO_BLOCK_SAMPLES; + +void AudioInputI2SQuad_F32::begin(void) { + dma.begin(true); // Allocate the DMA channel first + + AudioOutputI2S_F32::config_i2s(); + CORE_PIN8_CONFIG = 3; + CORE_PIN6_CONFIG = 3; + IOMUXC_SAI1_RX_DATA0_SELECT_INPUT = 2; // GPIO_B1_00_ALT3, pg 873 + IOMUXC_SAI1_RX_DATA1_SELECT_INPUT = 1; // GPIO_B0_10_ALT3, pg 873 + dma.TCD->SADDR = (void *)((uint32_t)&I2S1_RDR0 + 2); + dma.TCD->SOFF = 4; + dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1); + dma.TCD->NBYTES_MLOFFYES = DMA_TCD_NBYTES_SMLOE | + DMA_TCD_NBYTES_MLOFFYES_MLOFF(-8) | + DMA_TCD_NBYTES_MLOFFYES_NBYTES(4); + dma.TCD->SLAST = -8; + dma.TCD->DADDR = i2s_rx_buffer; + dma.TCD->DOFF = 2; + dma.TCD->CITER_ELINKNO = AUDIO_BLOCK_SAMPLES * 2; + dma.TCD->DLASTSGA = -sizeof(i2s_rx_buffer); + dma.TCD->BITER_ELINKNO = AUDIO_BLOCK_SAMPLES * 2; + dma.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR; + dma.triggerAtHardwareEvent(DMAMUX_SOURCE_SAI1_RX); + + I2S1_RCSR = 0; + I2S1_RCR3 = I2S_RCR3_RCE_2CH; + + I2S1_RCSR = I2S_RCSR_RE | I2S_RCSR_BCE | I2S_RCSR_FRDE | I2S_RCSR_FR; + update_responsibility = update_setup(); + dma.enable(); + dma.attachInterrupt(isr); +} + +void AudioInputI2SQuad_F32::isr(void) { + uint32_t daddr, offset; + const int16_t *src; + float32_t *dest1, *dest2, *dest3, *dest4; + + daddr = (uint32_t)(dma.TCD->DADDR); + dma.clearInterrupt(); + + if(daddr < (uint32_t)i2s_rx_buffer + sizeof(i2s_rx_buffer) / 2) { + // DMA is receiving to the first half of the buffer + // need to remove data from the second half + src = (int16_t *)&i2s_rx_buffer[AUDIO_BLOCK_SAMPLES]; + if(update_responsibility) update_all(); + } else { + // DMA is receiving to the second half of the buffer + // need to remove data from the first half + src = (int16_t *)&i2s_rx_buffer[0]; + } + if(block_ch1) { + offset = block_offset; + if(offset <= AUDIO_BLOCK_SAMPLES/2) { + arm_dcache_delete((void*)src, sizeof(i2s_rx_buffer) / 2); + block_offset = offset + AUDIO_BLOCK_SAMPLES/2; + dest1 = &(block_ch1->data[offset]); + dest2 = &(block_ch2->data[offset]); + dest3 = &(block_ch3->data[offset]); + dest4 = &(block_ch4->data[offset]); + for (int i=0; i < AUDIO_BLOCK_SAMPLES/2; i++) { + *dest1++ = (float32_t)*src++; + *dest3++ = (float32_t)*src++; + *dest2++ = (float32_t)*src++; + *dest4++ = (float32_t)*src++; + } + } + } +} + +#define I16_TO_F32_NORM_FACTOR (3.051850947599719e-05) //which is 1/32767 +void AudioInputI2SQuad_F32::scale_i16_to_f32( float32_t *p_i16, float32_t *p_f32, int len) { + for (int i=0; i= AUDIO_BLOCK_SAMPLES) { + // the DMA filled 4 blocks, so grab them and get the + // 4 new blocks to the DMA, as quickly as possible + out1 = block_ch1; + block_ch1 = new1; + out2 = block_ch2; + block_ch2 = new2; + out3 = block_ch3; + block_ch3 = new3; + out4 = block_ch4; + block_ch4 = new4; + block_offset = 0; + __enable_irq(); + + //scale the float values so that the maximum possible audio values span -1.0 to + 1.0 + scale_i16_to_f32(out1->data, out1->data, AUDIO_BLOCK_SAMPLES); + scale_i16_to_f32(out2->data, out2->data, AUDIO_BLOCK_SAMPLES); + scale_i16_to_f32(out3->data, out3->data, AUDIO_BLOCK_SAMPLES); + scale_i16_to_f32(out4->data, out4->data, AUDIO_BLOCK_SAMPLES); + + // then transmit the DMA's former blocks + AudioStream_F32::transmit(out1, 0); + AudioStream_F32::release(out1); + AudioStream_F32::transmit(out2, 1); + AudioStream_F32::release(out2); + AudioStream_F32::transmit(out3, 2); + AudioStream_F32::release(out3); + AudioStream_F32::transmit(out4, 3); + AudioStream_F32::release(out4); + } else if(new1 != NULL) { + // the DMA didn't fill blocks, but we allocated blocks + if(block_ch1 == NULL) { + // the DMA doesn't have any blocks to fill, so + // give it the ones we just allocated + block_ch1 = new1; + block_ch2 = new2; + block_ch3 = new3; + block_ch4 = new4; + block_offset = 0; + __enable_irq(); + } else { + // the DMA already has blocks, doesn't need these + __enable_irq(); + AudioStream_F32::release(new1); + AudioStream_F32::release(new2); + AudioStream_F32::release(new3); + AudioStream_F32::release(new4); + } + } else { + // The DMA didn't fill blocks, and we could not allocate + // memory... the system is likely starving for memory! + // Sadly, there's nothing we can do. + __enable_irq(); + } +} diff --git a/input_i2s_quad_f32.h b/input_i2s_quad_f32.h new file mode 100644 index 0000000..ccad473 --- /dev/null +++ b/input_i2s_quad_f32.h @@ -0,0 +1,75 @@ +/* + * input_i2s_quad_f32.h + * + * Audio Library for Teensy 3.X + * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com + * + * Development of this audio library was funded by PJRC.COM, LLC by sales of + * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop + * open source software by purchasing Teensy or other PJRC products. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice, development funding notice, and this permission + * notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + /* + * Extended by Terrance Robertson, May 2025 + * Converted to F32 + */ + +#ifndef _input_i2s_quad_f32_h_ +#define _input_i2s_quad_f32_h_ + +//#define __IMXRT1062__ + +#include +#include +#include +#include + +class AudioInputI2SQuad_F32 : public AudioStream_F32 +{ +public: + AudioInputI2SQuad_F32(void) : AudioStream_F32(0, NULL) { begin(); } + AudioInputI2SQuad_F32(const AudioSettings_F32 &settings) : AudioStream_F32(0, NULL) { + sample_rate_Hz = settings.sample_rate_Hz; + audio_block_samples = settings.audio_block_samples; + begin(); + } + + virtual void update(void); + static void scale_i16_to_f32( float32_t *p_i16, float32_t *p_f32, int len) ; + static void scale_i24_to_f32( float32_t *p_i24, float32_t *p_f32, int len) ; + static void scale_i32_to_f32( float32_t *p_i32, float32_t *p_f32, int len); + void begin(void); +protected: + static void isr_32(void); +private: + static bool update_responsibility; + static DMAChannel dma; + static void isr(void); + static audio_block_f32_t *block_ch1; + static audio_block_f32_t *block_ch2; + static audio_block_f32_t *block_ch3; + static audio_block_f32_t *block_ch4; + static uint16_t block_offset; + static float sample_rate_Hz; + static int audio_block_samples; +}; + + +#endif From e36818ff0bf3f5f8e6a6d0ceee508ab6eba33f9c Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Fri, 10 Jul 2026 17:27:49 +0100 Subject: [PATCH 02/10] Create PassThroughQuadF32.ino Initial placeholder for Passthrough test, this is currently the output test with some tweaks for T41-EP --- .../PassThroughQuadF32/PassThroughQuadF32.ino | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 examples/PassThroughQuadF32/PassThroughQuadF32.ino diff --git a/examples/PassThroughQuadF32/PassThroughQuadF32.ino b/examples/PassThroughQuadF32/PassThroughQuadF32.ino new file mode 100644 index 0000000..b22228f --- /dev/null +++ b/examples/PassThroughQuadF32/PassThroughQuadF32.ino @@ -0,0 +1,100 @@ +// Demonstration of AudioOutputI2SQuad_F32 four channel I2S output object. +// Greg Raven KF5N November 2025. +// The first left and right channels are output on pin 7, which drives the +// Teensy Audio Adapter (Teensy 4.1). The second left and right channels are output on pin 32 (Teensy 4.1). + +#include +#include +#include +#include + +const int sample_rate_Hz = 48000; +const int audio_block_samples = 128; // Always 128 + +AudioControlSGTL5000 sgtl5000_1; +AudioSettings_F32 audio_settings(sample_rate_Hz, audio_block_samples); +AudioSynthWaveformSine_F32 tone0(audio_settings), tone1(audio_settings), tone2(audio_settings), tone3(audio_settings); +AudioOutputI2SQuad_F32 i2s_out(audio_settings); + +AudioConnection_F32 connect0(tone0, 0, i2s_out, 0); +AudioConnection_F32 connect1(tone1, 0, i2s_out, 1); +AudioConnection_F32 connect2(tone2, 0, i2s_out, 2); +AudioConnection_F32 connect3(tone3, 0, i2s_out, 3); + +void setup() { + + Serial.begin(115200); + + /* check for CrashReport stored from previous run */ + if (CrashReport) { + Serial.print(CrashReport); + } + +/* DMA debug code. + uint32_t* dmaErrors; + dmaErrors = (uint32_t*)(0x400E8000 + 0x4); + Serial.printf("DMA errors = %u\n", *dmaErrors); + */ +#define UNMUTEAUDIO LOW +#define MUTEAUDIO HIGH +const int MUTE = 38; // Mute Audio, HIGH = "On" Audio PA, LOW = Mute Audio PA off. This may be reversed depending on PA. + + pinMode(MUTE, OUTPUT); + digitalWrite(MUTE, MUTEAUDIO); // Keep audio junk out of the speakers/headphones until configuration is complete. + Serial.printf("MUTE\n"); + + sgtl5000_1.enable(); + sgtl5000_1.setAddress(LOW); + AudioMemory_F32(10); + sgtl5000_1.volume(0.8); // Set headphone volume. + sgtl5000_1.unmuteHeadphone(); + Serial.printf("Please listen for tones!\n"); + tone0.amplitude(0.1); + tone0.frequency(261.63); + tone1.amplitude(0.1); + tone1.frequency(329.63); + tone2.amplitude(0.5);// 2.8Vpkpk 1.0 = 5V pkpk out + tone2.frequency(392.0); + tone3.amplitude(0.5);// 2.8Vpkpk 1.0 = 5V pkpk out + tone3.frequency(440.0); + tone0.begin(); + tone1.begin(); + tone2.begin(); + tone3.begin(); + Serial.printf("UNMUTE\n"); + + digitalWrite(MUTE, UNMUTEAUDIO); // Keep audio junk out of the speakers/headphones until configuration is complete. + +} + +void loop() { + + delay(5000); + Serial.printf("All Off\n"); + + // After 5 seconds, turn off all tones. + tone0.end(); + tone1.end(); + tone2.end(); + tone3.end(); + + delay(2000); + // After 2 seconds, turn on tone0. + Serial.printf("Tone 0 - Headphone Left - On\n"); + tone0.begin(); + + delay(2000); + // After 2 seconds, turn on tone1. + Serial.printf("Tone 1 - Headphone Right - On\n"); + tone1.begin(); + + delay(2000); + // After 2 seconds, turn on tone2. + Serial.printf("Tone 2- PCM5102 Left On\n"); + tone2.begin(); + + delay(2000); + // After 2 seconds, turn on tone3. + Serial.printf("Tone 3 - PCM5102 Right - On\n"); + tone3.begin(); +} From fc11197338208491f6da916e06a64a7c6bdd44b3 Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Fri, 10 Jul 2026 17:49:02 +0100 Subject: [PATCH 03/10] Update PassThroughQuadF32.ino Moving to be closer to the Teensy PassThrough example --- .../PassThroughQuadF32/PassThroughQuadF32.ino | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/examples/PassThroughQuadF32/PassThroughQuadF32.ino b/examples/PassThroughQuadF32/PassThroughQuadF32.ino index b22228f..0c7845c 100644 --- a/examples/PassThroughQuadF32/PassThroughQuadF32.ino +++ b/examples/PassThroughQuadF32/PassThroughQuadF32.ino @@ -12,14 +12,35 @@ const int sample_rate_Hz = 48000; const int audio_block_samples = 128; // Always 128 AudioControlSGTL5000 sgtl5000_1; +#if 1 AudioSettings_F32 audio_settings(sample_rate_Hz, audio_block_samples); AudioSynthWaveformSine_F32 tone0(audio_settings), tone1(audio_settings), tone2(audio_settings), tone3(audio_settings); + AudioOutputI2SQuad_F32 i2s_out(audio_settings); AudioConnection_F32 connect0(tone0, 0, i2s_out, 0); AudioConnection_F32 connect1(tone1, 0, i2s_out, 1); AudioConnection_F32 connect2(tone2, 0, i2s_out, 2); AudioConnection_F32 connect3(tone3, 0, i2s_out, 3); +#else +AudioInputI2SQuad_F32 i2s_in(); +AudioOutputI2SQuad_F32 i2s_out(audio_settings); + +#ifdef MIXUP +AudioConnection patchCord1(i2s_in, 0, i2s_out, 2); +AudioConnection patchCord2(i2s_in, 1, i2s_out, 3); +AudioConnection patchCord3(i2s_in, 2, i2s_out, 0); +AudioConnection patchCord4(i2s_in, 3, i2s_out, 1); +#else // loopback +AudioConnection patchCord1(i2s_in, 0, i2s_out, 0); +AudioConnection patchCord2(i2s_in, 1, i2s_out, 1); +AudioConnection patchCord3(i2s_in, 2, i2s_out, 2); +AudioConnection patchCord4(i2s_in, 3, i2s_out, 3); + +#endif +#endif +const int myInput = AUDIO_INPUT_LINEIN; +//const int myInput = AUDIO_INPUT_MIC; void setup() { @@ -42,11 +63,22 @@ const int MUTE = 38; // Mute Audio, HIGH = "On" Audio PA, LOW = Mute Au pinMode(MUTE, OUTPUT); digitalWrite(MUTE, MUTEAUDIO); // Keep audio junk out of the speakers/headphones until configuration is complete. Serial.printf("MUTE\n"); + // Audio connections require memory to work. For more + // detailed information, see the MemoryAndCpuUsage example + AudioMemory_F32(20); - sgtl5000_1.enable(); + // Enable the first audio shield, select input, and enable output sgtl5000_1.setAddress(LOW); - AudioMemory_F32(10); + sgtl5000_1.enable(); + sgtl5000_1.inputSelect(myInput); sgtl5000_1.volume(0.8); // Set headphone volume. +#if 0 + // Enable the second audio shield, select input, and enable output + sgtl5000_2.setAddress(HIGH); + sgtl5000_2.enable(); + sgtl5000_2.inputSelect(myInput); + sgtl5000_2.volume(0.5); + #endif sgtl5000_1.unmuteHeadphone(); Serial.printf("Please listen for tones!\n"); tone0.amplitude(0.1); From ebb68001812518ce576479f1bc9a91ccdbfbe5ea Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Fri, 10 Jul 2026 19:15:43 +0100 Subject: [PATCH 04/10] Update PassThroughQuadF32.ino Can receive data from MIC and RX IQ inputs simultaneously and peak readings change. --- .../PassThroughQuadF32/PassThroughQuadF32.ino | 56 +++++++++++++------ 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/examples/PassThroughQuadF32/PassThroughQuadF32.ino b/examples/PassThroughQuadF32/PassThroughQuadF32.ino index 0c7845c..ab7cf33 100644 --- a/examples/PassThroughQuadF32/PassThroughQuadF32.ino +++ b/examples/PassThroughQuadF32/PassThroughQuadF32.ino @@ -12,8 +12,8 @@ const int sample_rate_Hz = 48000; const int audio_block_samples = 128; // Always 128 AudioControlSGTL5000 sgtl5000_1; -#if 1 AudioSettings_F32 audio_settings(sample_rate_Hz, audio_block_samples); +#if 0 AudioSynthWaveformSine_F32 tone0(audio_settings), tone1(audio_settings), tone2(audio_settings), tone3(audio_settings); AudioOutputI2SQuad_F32 i2s_out(audio_settings); @@ -23,24 +23,33 @@ AudioConnection_F32 connect1(tone1, 0, i2s_out, 1); AudioConnection_F32 connect2(tone2, 0, i2s_out, 2); AudioConnection_F32 connect3(tone3, 0, i2s_out, 3); #else -AudioInputI2SQuad_F32 i2s_in(); +AudioAnalyzePeak_F32 peak0L(audio_settings); +AudioAnalyzePeak_F32 peak1R(audio_settings); +AudioAnalyzePeak_F32 peak2L(audio_settings); +AudioAnalyzePeak_F32 peak3R(audio_settings); +AudioInputI2SQuad_F32 i2s_in(audio_settings); AudioOutputI2SQuad_F32 i2s_out(audio_settings); #ifdef MIXUP -AudioConnection patchCord1(i2s_in, 0, i2s_out, 2); -AudioConnection patchCord2(i2s_in, 1, i2s_out, 3); -AudioConnection patchCord3(i2s_in, 2, i2s_out, 0); -AudioConnection patchCord4(i2s_in, 3, i2s_out, 1); +AudioConnection_F32 patchCord1(i2s_in, 0, i2s_out, 2); +AudioConnection_F32 patchCord2(i2s_in, 1, i2s_out, 3); +AudioConnection_F32 patchCord3(i2s_in, 2, i2s_out, 0); +AudioConnection_F32 patchCord4(i2s_in, 3, i2s_out, 1); #else // loopback -AudioConnection patchCord1(i2s_in, 0, i2s_out, 0); -AudioConnection patchCord2(i2s_in, 1, i2s_out, 1); -AudioConnection patchCord3(i2s_in, 2, i2s_out, 2); -AudioConnection patchCord4(i2s_in, 3, i2s_out, 3); +AudioConnection_F32 connect0(i2s_in, 0, peak0L, 0); +AudioConnection_F32 connect1(i2s_in, 1, peak1R, 0); +AudioConnection_F32 connect2(i2s_in, 2, peak2L, 0); +AudioConnection_F32 connect3(i2s_in, 3, peak3R, 0); + +//AudioConnection_F32 patchCord1(i2s_in, 0, i2s_out, 0); +//AudioConnection_F32 patchCord2(i2s_in, 1, i2s_out, 1); +//AudioConnection_F32 patchCord3(i2s_in, 2, i2s_out, 2); +//AudioConnection_F32 patchCord4(i2s_in, 3, i2s_out, 3); #endif #endif -const int myInput = AUDIO_INPUT_LINEIN; -//const int myInput = AUDIO_INPUT_MIC; +//const int myInput = AUDIO_INPUT_LINEIN; +const int myInput = AUDIO_INPUT_MIC; void setup() { @@ -78,8 +87,9 @@ const int MUTE = 38; // Mute Audio, HIGH = "On" Audio PA, LOW = Mute Au sgtl5000_2.enable(); sgtl5000_2.inputSelect(myInput); sgtl5000_2.volume(0.5); - #endif + #endif sgtl5000_1.unmuteHeadphone(); +#if 0 Serial.printf("Please listen for tones!\n"); tone0.amplitude(0.1); tone0.frequency(261.63); @@ -93,16 +103,17 @@ const int MUTE = 38; // Mute Audio, HIGH = "On" Audio PA, LOW = Mute Au tone1.begin(); tone2.begin(); tone3.begin(); - Serial.printf("UNMUTE\n"); - +#endif + Serial.printf("UNMUTE\n"); digitalWrite(MUTE, UNMUTEAUDIO); // Keep audio junk out of the speakers/headphones until configuration is complete. } void loop() { - delay(5000); +#if 0 Serial.printf("All Off\n"); + delay(5000); // After 5 seconds, turn off all tones. tone0.end(); @@ -129,4 +140,17 @@ void loop() { // After 2 seconds, turn on tone3. Serial.printf("Tone 3 - PCM5102 Right - On\n"); tone3.begin(); +#else + Serial.printf("PassThrough Running Now using mic not line in!\n"); + Serial.print("Max float memory = "); + Serial.println(AudioStream_F32::f32_memory_used_max); + if(peak0L.available()) Serial.print(peak0L.read(), 6); + Serial.print(" <-0L 1R-> "); + if(peak1R.available()) Serial.println(peak1R.read(), 6); + if(peak2L.available()) Serial.print(peak2L.read(), 6); + Serial.print(" <-2L 3R-> "); + if(peak3R.available()) Serial.println(peak3R.read(), 6); + delay(1000); + +#endif } From 5d1f68f8d80b311e1cb8b8193fa7c9eead8e1ea7 Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Sat, 11 Jul 2026 10:09:06 +0100 Subject: [PATCH 05/10] Update PassThroughQuadF32.ino This now works. With TAA MIC -> TAA Headphones PCM1808 Input -> PCM5102 output --- examples/PassThroughQuadF32/PassThroughQuadF32.ino | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/examples/PassThroughQuadF32/PassThroughQuadF32.ino b/examples/PassThroughQuadF32/PassThroughQuadF32.ino index ab7cf33..b220474 100644 --- a/examples/PassThroughQuadF32/PassThroughQuadF32.ino +++ b/examples/PassThroughQuadF32/PassThroughQuadF32.ino @@ -29,7 +29,6 @@ AudioAnalyzePeak_F32 peak2L(audio_settings); AudioAnalyzePeak_F32 peak3R(audio_settings); AudioInputI2SQuad_F32 i2s_in(audio_settings); AudioOutputI2SQuad_F32 i2s_out(audio_settings); - #ifdef MIXUP AudioConnection_F32 patchCord1(i2s_in, 0, i2s_out, 2); AudioConnection_F32 patchCord2(i2s_in, 1, i2s_out, 3); @@ -41,10 +40,10 @@ AudioConnection_F32 connect1(i2s_in, 1, peak1R, 0); AudioConnection_F32 connect2(i2s_in, 2, peak2L, 0); AudioConnection_F32 connect3(i2s_in, 3, peak3R, 0); -//AudioConnection_F32 patchCord1(i2s_in, 0, i2s_out, 0); -//AudioConnection_F32 patchCord2(i2s_in, 1, i2s_out, 1); -//AudioConnection_F32 patchCord3(i2s_in, 2, i2s_out, 2); -//AudioConnection_F32 patchCord4(i2s_in, 3, i2s_out, 3); +AudioConnection_F32 patchCord1(i2s_in, 0, i2s_out, 0); +AudioConnection_F32 patchCord2(i2s_in, 1, i2s_out, 1); +AudioConnection_F32 patchCord3(i2s_in, 2, i2s_out, 2); +AudioConnection_F32 patchCord4(i2s_in, 3, i2s_out, 3); #endif #endif @@ -141,7 +140,9 @@ void loop() { Serial.printf("Tone 3 - PCM5102 Right - On\n"); tone3.begin(); #else - Serial.printf("PassThrough Running Now using mic not line in!\n"); + Serial.printf("Now using mic not line in!\n"); + Serial.printf("PassThrough Running Now with audiosettings!\n"); + Serial.print("Max float memory = "); Serial.println(AudioStream_F32::f32_memory_used_max); if(peak0L.available()) Serial.print(peak0L.read(), 6); From 4f9cc0cee069d7f0c7fd7ab151a93d1940cf51dd Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Sat, 11 Jul 2026 12:50:52 +0100 Subject: [PATCH 06/10] 32Bit DMA Changes Original library just input 16Bit values in the DMA engine now changed to 32bits. Need to remove the scaling as not needed I2S automatically puts 16bit and 24bit numbers in the MSBits. --- .../PassThroughQuadF32/PassThroughQuadF32.ino | 12 ++++-- input_i2s_quad_f32.cpp | 42 +++++++++++++------ input_i2s_quad_f32.h | 2 +- 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/examples/PassThroughQuadF32/PassThroughQuadF32.ino b/examples/PassThroughQuadF32/PassThroughQuadF32.ino index b220474..7f736f2 100644 --- a/examples/PassThroughQuadF32/PassThroughQuadF32.ino +++ b/examples/PassThroughQuadF32/PassThroughQuadF32.ino @@ -59,11 +59,11 @@ void setup() { Serial.print(CrashReport); } -/* DMA debug code. +// DMA debug code. uint32_t* dmaErrors; dmaErrors = (uint32_t*)(0x400E8000 + 0x4); Serial.printf("DMA errors = %u\n", *dmaErrors); - */ +// #define UNMUTEAUDIO LOW #define MUTEAUDIO HIGH const int MUTE = 38; // Mute Audio, HIGH = "On" Audio PA, LOW = Mute Audio PA off. This may be reversed depending on PA. @@ -73,7 +73,7 @@ const int MUTE = 38; // Mute Audio, HIGH = "On" Audio PA, LOW = Mute Au Serial.printf("MUTE\n"); // Audio connections require memory to work. For more // detailed information, see the MemoryAndCpuUsage example - AudioMemory_F32(20); + AudioMemory_F32(100); // Enable the first audio shield, select input, and enable output sgtl5000_1.setAddress(LOW); @@ -142,6 +142,7 @@ void loop() { #else Serial.printf("Now using mic not line in!\n"); Serial.printf("PassThrough Running Now with audiosettings!\n"); + Serial.printf("Mic settings will need scakubg as now 24 Bit\n"); Serial.print("Max float memory = "); Serial.println(AudioStream_F32::f32_memory_used_max); @@ -152,6 +153,11 @@ void loop() { Serial.print(" <-2L 3R-> "); if(peak3R.available()) Serial.println(peak3R.read(), 6); delay(1000); +// DMA debug code. + uint32_t* dmaErrors; + dmaErrors = (uint32_t*)(0x400E8000 + 0x4); + Serial.printf("DMA errors = %x\n", *dmaErrors); +// #endif } diff --git a/input_i2s_quad_f32.cpp b/input_i2s_quad_f32.cpp index 8898a2d..3556a01 100644 --- a/input_i2s_quad_f32.cpp +++ b/input_i2s_quad_f32.cpp @@ -36,12 +36,12 @@ #include "output_i2s_quad_f32.h" #include "output_i2s_f32.h" -DMAMEM __attribute__((aligned(32))) static uint32_t i2s_rx_buffer[AUDIO_BLOCK_SAMPLES*2]; +DMAMEM __attribute__((aligned(32))) static uint32_t i2s_rx_buffer[AUDIO_BLOCK_SAMPLES*4];// 4 channels 128 samples each, total = 512. audio_block_f32_t * AudioInputI2SQuad_F32::block_ch1 = NULL; audio_block_f32_t * AudioInputI2SQuad_F32::block_ch2 = NULL; audio_block_f32_t * AudioInputI2SQuad_F32::block_ch3 = NULL; audio_block_f32_t * AudioInputI2SQuad_F32::block_ch4 = NULL; -uint16_t AudioInputI2SQuad_F32::block_offset = 0; +uint32_t AudioInputI2SQuad_F32::block_offset = 0; bool AudioInputI2SQuad_F32::update_responsibility = false; DMAChannel AudioInputI2SQuad_F32::dma(false); @@ -54,17 +54,17 @@ void AudioInputI2SQuad_F32::begin(void) { AudioOutputI2S_F32::config_i2s(); CORE_PIN8_CONFIG = 3; CORE_PIN6_CONFIG = 3; - IOMUXC_SAI1_RX_DATA0_SELECT_INPUT = 2; // GPIO_B1_00_ALT3, pg 873 - IOMUXC_SAI1_RX_DATA1_SELECT_INPUT = 1; // GPIO_B0_10_ALT3, pg 873 - dma.TCD->SADDR = (void *)((uint32_t)&I2S1_RDR0 + 2); + IOMUXC_SAI1_RX_DATA0_SELECT_INPUT = 2; // GPIO_B1_00_ALT3, pg 873 // Teensy Pin 8 + IOMUXC_SAI1_RX_DATA1_SELECT_INPUT = 1; // GPIO_B0_10_ALT3, pg 873 // Teensy Pin 6 + dma.TCD->SADDR = (void *)((uint32_t)&I2S1_RDR0); dma.TCD->SOFF = 4; - dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1); + dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(2) | DMA_TCD_ATTR_DSIZE(2); dma.TCD->NBYTES_MLOFFYES = DMA_TCD_NBYTES_SMLOE | DMA_TCD_NBYTES_MLOFFYES_MLOFF(-8) | - DMA_TCD_NBYTES_MLOFFYES_NBYTES(4); + DMA_TCD_NBYTES_MLOFFYES_NBYTES(8); dma.TCD->SLAST = -8; dma.TCD->DADDR = i2s_rx_buffer; - dma.TCD->DOFF = 2; + dma.TCD->DOFF = 4; dma.TCD->CITER_ELINKNO = AUDIO_BLOCK_SAMPLES * 2; dma.TCD->DLASTSGA = -sizeof(i2s_rx_buffer); dma.TCD->BITER_ELINKNO = AUDIO_BLOCK_SAMPLES * 2; @@ -82,7 +82,7 @@ void AudioInputI2SQuad_F32::begin(void) { void AudioInputI2SQuad_F32::isr(void) { uint32_t daddr, offset; - const int16_t *src; + const int32_t *src; float32_t *dest1, *dest2, *dest3, *dest4; daddr = (uint32_t)(dma.TCD->DADDR); @@ -91,12 +91,12 @@ void AudioInputI2SQuad_F32::isr(void) { if(daddr < (uint32_t)i2s_rx_buffer + sizeof(i2s_rx_buffer) / 2) { // DMA is receiving to the first half of the buffer // need to remove data from the second half - src = (int16_t *)&i2s_rx_buffer[AUDIO_BLOCK_SAMPLES]; + src = (int32_t *)&i2s_rx_buffer[AUDIO_BLOCK_SAMPLES * 2]; if(update_responsibility) update_all(); } else { // DMA is receiving to the second half of the buffer // need to remove data from the first half - src = (int16_t *)&i2s_rx_buffer[0]; + src = (int32_t *)&i2s_rx_buffer[0]; } if(block_ch1) { offset = block_offset; @@ -172,13 +172,29 @@ void AudioInputI2SQuad_F32::update(void) { block_ch4 = new4; block_offset = 0; __enable_irq(); - + // Application will have to scale 16bit inputs? As we don't know here what is coming in. +#if 0 // JMS Change pass 24bit value through as that is a sensible maximum + // the mantissa is 24 bits including sign so we will only lose 1 bit??? //scale the float values so that the maximum possible audio values span -1.0 to + 1.0 scale_i16_to_f32(out1->data, out1->data, AUDIO_BLOCK_SAMPLES); scale_i16_to_f32(out2->data, out2->data, AUDIO_BLOCK_SAMPLES); scale_i16_to_f32(out3->data, out3->data, AUDIO_BLOCK_SAMPLES); scale_i16_to_f32(out4->data, out4->data, AUDIO_BLOCK_SAMPLES); - +#else +#if 1 + //scale the float values so that the maximum possible audio values span -1.0 to + 1.0 + scale_i32_to_f32(out1->data, out1->data, AUDIO_BLOCK_SAMPLES); + scale_i32_to_f32(out2->data, out2->data, AUDIO_BLOCK_SAMPLES); + scale_i32_to_f32(out3->data, out3->data, AUDIO_BLOCK_SAMPLES); + scale_i32_to_f32(out4->data, out4->data, AUDIO_BLOCK_SAMPLES); +#else + //scale the float values so that the maximum possible audio values span -1.0 to + 1.0 + scale_i24_to_f32(out1->data, out1->data, AUDIO_BLOCK_SAMPLES); + scale_i24_to_f32(out2->data, out2->data, AUDIO_BLOCK_SAMPLES); + scale_i24_to_f32(out3->data, out3->data, AUDIO_BLOCK_SAMPLES); + scale_i24_to_f32(out4->data, out4->data, AUDIO_BLOCK_SAMPLES); +#endif +#endif // then transmit the DMA's former blocks AudioStream_F32::transmit(out1, 0); AudioStream_F32::release(out1); diff --git a/input_i2s_quad_f32.h b/input_i2s_quad_f32.h index ccad473..f9a6c2c 100644 --- a/input_i2s_quad_f32.h +++ b/input_i2s_quad_f32.h @@ -66,7 +66,7 @@ class AudioInputI2SQuad_F32 : public AudioStream_F32 static audio_block_f32_t *block_ch2; static audio_block_f32_t *block_ch3; static audio_block_f32_t *block_ch4; - static uint16_t block_offset; + static uint32_t block_offset; static float sample_rate_Hz; static int audio_block_samples; }; From ac91d11ff7dc8401b8dce1a1f09db7d46336ba7a Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Sat, 11 Jul 2026 13:10:00 +0100 Subject: [PATCH 07/10] Tidied up Example and removed scale code Example now should support two TAA devices or 1 TAA and 1x PCM1808 + PCM5102 as used on the T41-EP --- .../PassThroughQuadF32/PassThroughQuadF32.ino | 106 ++++-------------- input_i2s_quad_f32.cpp | 30 +---- input_i2s_quad_f32.h | 4 +- 3 files changed, 28 insertions(+), 112 deletions(-) diff --git a/examples/PassThroughQuadF32/PassThroughQuadF32.ino b/examples/PassThroughQuadF32/PassThroughQuadF32.ino index 7f736f2..cc280fa 100644 --- a/examples/PassThroughQuadF32/PassThroughQuadF32.ino +++ b/examples/PassThroughQuadF32/PassThroughQuadF32.ino @@ -13,28 +13,14 @@ const int audio_block_samples = 128; // Always 128 AudioControlSGTL5000 sgtl5000_1; AudioSettings_F32 audio_settings(sample_rate_Hz, audio_block_samples); -#if 0 -AudioSynthWaveformSine_F32 tone0(audio_settings), tone1(audio_settings), tone2(audio_settings), tone3(audio_settings); - -AudioOutputI2SQuad_F32 i2s_out(audio_settings); -AudioConnection_F32 connect0(tone0, 0, i2s_out, 0); -AudioConnection_F32 connect1(tone1, 0, i2s_out, 1); -AudioConnection_F32 connect2(tone2, 0, i2s_out, 2); -AudioConnection_F32 connect3(tone3, 0, i2s_out, 3); -#else AudioAnalyzePeak_F32 peak0L(audio_settings); AudioAnalyzePeak_F32 peak1R(audio_settings); AudioAnalyzePeak_F32 peak2L(audio_settings); AudioAnalyzePeak_F32 peak3R(audio_settings); AudioInputI2SQuad_F32 i2s_in(audio_settings); AudioOutputI2SQuad_F32 i2s_out(audio_settings); -#ifdef MIXUP -AudioConnection_F32 patchCord1(i2s_in, 0, i2s_out, 2); -AudioConnection_F32 patchCord2(i2s_in, 1, i2s_out, 3); -AudioConnection_F32 patchCord3(i2s_in, 2, i2s_out, 0); -AudioConnection_F32 patchCord4(i2s_in, 3, i2s_out, 1); -#else // loopback + AudioConnection_F32 connect0(i2s_in, 0, peak0L, 0); AudioConnection_F32 connect1(i2s_in, 1, peak1R, 0); AudioConnection_F32 connect2(i2s_in, 2, peak2L, 0); @@ -44,9 +30,7 @@ AudioConnection_F32 patchCord1(i2s_in, 0, i2s_out, 0); AudioConnection_F32 patchCord2(i2s_in, 1, i2s_out, 1); AudioConnection_F32 patchCord3(i2s_in, 2, i2s_out, 2); AudioConnection_F32 patchCord4(i2s_in, 3, i2s_out, 3); - -#endif -#endif +// Select Which Input from Teensy Audio Adaptor //const int myInput = AUDIO_INPUT_LINEIN; const int myInput = AUDIO_INPUT_MIC; @@ -59,91 +43,46 @@ void setup() { Serial.print(CrashReport); } -// DMA debug code. - uint32_t* dmaErrors; - dmaErrors = (uint32_t*)(0x400E8000 + 0x4); - Serial.printf("DMA errors = %u\n", *dmaErrors); -// -#define UNMUTEAUDIO LOW -#define MUTEAUDIO HIGH -const int MUTE = 38; // Mute Audio, HIGH = "On" Audio PA, LOW = Mute Audio PA off. This may be reversed depending on PA. - - pinMode(MUTE, OUTPUT); - digitalWrite(MUTE, MUTEAUDIO); // Keep audio junk out of the speakers/headphones until configuration is complete. - Serial.printf("MUTE\n"); // Audio connections require memory to work. For more // detailed information, see the MemoryAndCpuUsage example - AudioMemory_F32(100); + AudioMemory_F32(20,audio_settings); // Enable the first audio shield, select input, and enable output sgtl5000_1.setAddress(LOW); sgtl5000_1.enable(); sgtl5000_1.inputSelect(myInput); sgtl5000_1.volume(0.8); // Set headphone volume. + sgtl5000_1.unmuteHeadphone(); #if 0 // Enable the second audio shield, select input, and enable output sgtl5000_2.setAddress(HIGH); sgtl5000_2.enable(); sgtl5000_2.inputSelect(myInput); - sgtl5000_2.volume(0.5); - #endif - sgtl5000_1.unmuteHeadphone(); -#if 0 - Serial.printf("Please listen for tones!\n"); - tone0.amplitude(0.1); - tone0.frequency(261.63); - tone1.amplitude(0.1); - tone1.frequency(329.63); - tone2.amplitude(0.5);// 2.8Vpkpk 1.0 = 5V pkpk out - tone2.frequency(392.0); - tone3.amplitude(0.5);// 2.8Vpkpk 1.0 = 5V pkpk out - tone3.frequency(440.0); - tone0.begin(); - tone1.begin(); - tone2.begin(); - tone3.begin(); -#endif + sgtl5000_2.volume(0.8); + sgtl5000_2.unmuteHeadphone(); + #else + // Specific code for T41-EP ADC PCM1808/ DAC PCM5102 +#define UNMUTEAUDIO LOW +#define MUTEAUDIO HIGH + const int MUTE = 38; // Mute Audio, HIGH = "On" Audio PA, LOW = Mute Audio PA off. This may be reversed depending on PA. + + pinMode(MUTE, OUTPUT); Serial.printf("UNMUTE\n"); digitalWrite(MUTE, UNMUTEAUDIO); // Keep audio junk out of the speakers/headphones until configuration is complete. + #endif + } void loop() { - -#if 0 - Serial.printf("All Off\n"); - delay(5000); - - // After 5 seconds, turn off all tones. - tone0.end(); - tone1.end(); - tone2.end(); - tone3.end(); - - delay(2000); - // After 2 seconds, turn on tone0. - Serial.printf("Tone 0 - Headphone Left - On\n"); - tone0.begin(); - - delay(2000); - // After 2 seconds, turn on tone1. - Serial.printf("Tone 1 - Headphone Right - On\n"); - tone1.begin(); - - delay(2000); - // After 2 seconds, turn on tone2. - Serial.printf("Tone 2- PCM5102 Left On\n"); - tone2.begin(); - - delay(2000); - // After 2 seconds, turn on tone3. - Serial.printf("Tone 3 - PCM5102 Right - On\n"); - tone3.begin(); -#else - Serial.printf("Now using mic not line in!\n"); - Serial.printf("PassThrough Running Now with audiosettings!\n"); - Serial.printf("Mic settings will need scakubg as now 24 Bit\n"); + Serial.printf("PassThrough Running Now\n"); + + if (myInput == AUDIO_INPUT_MIC){ + Serial.printf("Now using mic!\n"); + } else { + Serial.printf("Now using line in!\n"); + } Serial.print("Max float memory = "); Serial.println(AudioStream_F32::f32_memory_used_max); if(peak0L.available()) Serial.print(peak0L.read(), 6); @@ -159,5 +98,4 @@ void loop() { Serial.printf("DMA errors = %x\n", *dmaErrors); // -#endif } diff --git a/input_i2s_quad_f32.cpp b/input_i2s_quad_f32.cpp index 3556a01..9c427c5 100644 --- a/input_i2s_quad_f32.cpp +++ b/input_i2s_quad_f32.cpp @@ -29,6 +29,8 @@ /* * Extended by Terrance Robertson, May 2025 * Converted to F32 + * Changed By Julia Stephenson, July 2026 + * from 16Bit to 32Bit Transfers from I2S */ #include @@ -117,14 +119,6 @@ void AudioInputI2SQuad_F32::isr(void) { } } -#define I16_TO_F32_NORM_FACTOR (3.051850947599719e-05) //which is 1/32767 -void AudioInputI2SQuad_F32::scale_i16_to_f32( float32_t *p_i16, float32_t *p_f32, int len) { - for (int i=0; idata, out1->data, AUDIO_BLOCK_SAMPLES); - scale_i16_to_f32(out2->data, out2->data, AUDIO_BLOCK_SAMPLES); - scale_i16_to_f32(out3->data, out3->data, AUDIO_BLOCK_SAMPLES); - scale_i16_to_f32(out4->data, out4->data, AUDIO_BLOCK_SAMPLES); -#else -#if 1 + //scale the float values so that the maximum possible audio values span -1.0 to + 1.0 scale_i32_to_f32(out1->data, out1->data, AUDIO_BLOCK_SAMPLES); scale_i32_to_f32(out2->data, out2->data, AUDIO_BLOCK_SAMPLES); scale_i32_to_f32(out3->data, out3->data, AUDIO_BLOCK_SAMPLES); scale_i32_to_f32(out4->data, out4->data, AUDIO_BLOCK_SAMPLES); -#else - //scale the float values so that the maximum possible audio values span -1.0 to + 1.0 - scale_i24_to_f32(out1->data, out1->data, AUDIO_BLOCK_SAMPLES); - scale_i24_to_f32(out2->data, out2->data, AUDIO_BLOCK_SAMPLES); - scale_i24_to_f32(out3->data, out3->data, AUDIO_BLOCK_SAMPLES); - scale_i24_to_f32(out4->data, out4->data, AUDIO_BLOCK_SAMPLES); -#endif -#endif + // then transmit the DMA's former blocks AudioStream_F32::transmit(out1, 0); AudioStream_F32::release(out1); diff --git a/input_i2s_quad_f32.h b/input_i2s_quad_f32.h index f9a6c2c..6d4c20d 100644 --- a/input_i2s_quad_f32.h +++ b/input_i2s_quad_f32.h @@ -29,6 +29,8 @@ /* * Extended by Terrance Robertson, May 2025 * Converted to F32 + * Changed By Julia Stephenson, July 2026 + * from 16Bit to 32Bit Transfers from I2S */ #ifndef _input_i2s_quad_f32_h_ @@ -52,8 +54,6 @@ class AudioInputI2SQuad_F32 : public AudioStream_F32 } virtual void update(void); - static void scale_i16_to_f32( float32_t *p_i16, float32_t *p_f32, int len) ; - static void scale_i24_to_f32( float32_t *p_i24, float32_t *p_f32, int len) ; static void scale_i32_to_f32( float32_t *p_i32, float32_t *p_f32, int len); void begin(void); protected: From 6997a2bb220728dc97b9fd7b3a92657e35cee52e Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Sat, 11 Jul 2026 15:06:56 +0100 Subject: [PATCH 08/10] Can now change sample frequency TAA and PCM1808/PCM5102 all seem to work at 192000 on Teensy 4.1 --- .../PassThroughQuadF32/PassThroughQuadF32.ino | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/examples/PassThroughQuadF32/PassThroughQuadF32.ino b/examples/PassThroughQuadF32/PassThroughQuadF32.ino index cc280fa..3968840 100644 --- a/examples/PassThroughQuadF32/PassThroughQuadF32.ino +++ b/examples/PassThroughQuadF32/PassThroughQuadF32.ino @@ -7,8 +7,13 @@ #include #include #include +#include -const int sample_rate_Hz = 48000; +// T3.x supported sample rates: 2000, 8000, 11025, 16000, 22050, 24000, 32000, 44100, 44117, 48000, +// 88200, 88235 (44117*2), 95680, 96000, 176400, 176470, 192000 +// T4.x supports any sample rate the codec will handle. + +const int sample_rate_Hz = 192000; const int audio_block_samples = 128; // Always 128 AudioControlSGTL5000 sgtl5000_1; @@ -71,12 +76,14 @@ void setup() { digitalWrite(MUTE, UNMUTEAUDIO); // Keep audio junk out of the speakers/headphones until configuration is complete. #endif + setI2SFreq(sample_rate_Hz); } void loop() { Serial.printf("PassThrough Running Now\n"); + Serial.printf("Sample Rate = %d\n",sample_rate_Hz); if (myInput == AUDIO_INPUT_MIC){ Serial.printf("Now using mic!\n"); @@ -99,3 +106,18 @@ void loop() { // } +// Frank B's routine for setting I2S clocks. *** FOR T4.x ONLY *** +void setI2SFreq(int freq1) // Thank ypu, Frank B. + { + // PLL between 27*24 = 648MHz und 54*24=1296MHz + int n1 = 4; //SAI prescaler 4 => (n1*n2) = multiple of 4 + int n2 = 1 + (24000000 * 27) / (freq1 * 256 * n1); + double C = ((double)freq1 * 256 * n1 * n2) / 24000000; + int c0 = C; + int c2 = 10000; + int c1 = C * c2 - (c0 * c2); + set_audioClock(c0, c1, c2, true); + CCM_CS1CDR = (CCM_CS1CDR & ~(CCM_CS1CDR_SAI1_CLK_PRED_MASK | CCM_CS1CDR_SAI1_CLK_PODF_MASK)) + | CCM_CS1CDR_SAI1_CLK_PRED(n1-1) // &0x07 + | CCM_CS1CDR_SAI1_CLK_PODF(n2-1); // &0x3f + } From 2245fa0074b88874d834750b4bb11b6b25f80955 Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Sun, 12 Jul 2026 07:56:01 +0100 Subject: [PATCH 09/10] Update PassThroughQuadF32.ino Just some formatting --- examples/PassThroughQuadF32/PassThroughQuadF32.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/PassThroughQuadF32/PassThroughQuadF32.ino b/examples/PassThroughQuadF32/PassThroughQuadF32.ino index 3968840..b71ab85 100644 --- a/examples/PassThroughQuadF32/PassThroughQuadF32.ino +++ b/examples/PassThroughQuadF32/PassThroughQuadF32.ino @@ -23,8 +23,8 @@ AudioAnalyzePeak_F32 peak0L(audio_settings); AudioAnalyzePeak_F32 peak1R(audio_settings); AudioAnalyzePeak_F32 peak2L(audio_settings); AudioAnalyzePeak_F32 peak3R(audio_settings); -AudioInputI2SQuad_F32 i2s_in(audio_settings); -AudioOutputI2SQuad_F32 i2s_out(audio_settings); +AudioInputI2SQuad_F32 i2s_in(audio_settings); +AudioOutputI2SQuad_F32 i2s_out(audio_settings); AudioConnection_F32 connect0(i2s_in, 0, peak0L, 0); AudioConnection_F32 connect1(i2s_in, 1, peak1R, 0); From d093d4a24ad15b97e20ea1419b8e84eaba7ccaa2 Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Mon, 13 Jul 2026 13:03:42 +0100 Subject: [PATCH 10/10] Minor tweaks Mic gain set to 0dB to prevent feedback to headphones! Added first guess for GUI don't know what else is required. --- examples/PassThroughQuadF32/PassThroughQuadF32.ino | 2 ++ input_i2s_quad_f32.h | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/PassThroughQuadF32/PassThroughQuadF32.ino b/examples/PassThroughQuadF32/PassThroughQuadF32.ino index b71ab85..6d63f25 100644 --- a/examples/PassThroughQuadF32/PassThroughQuadF32.ino +++ b/examples/PassThroughQuadF32/PassThroughQuadF32.ino @@ -56,6 +56,7 @@ void setup() { sgtl5000_1.setAddress(LOW); sgtl5000_1.enable(); sgtl5000_1.inputSelect(myInput); + sgtl5000_1.micGain(0); sgtl5000_1.volume(0.8); // Set headphone volume. sgtl5000_1.unmuteHeadphone(); #if 0 @@ -63,6 +64,7 @@ void setup() { sgtl5000_2.setAddress(HIGH); sgtl5000_2.enable(); sgtl5000_2.inputSelect(myInput); + sgtl5000_2.micGain(0); sgtl5000_2.volume(0.8); sgtl5000_2.unmuteHeadphone(); #else diff --git a/input_i2s_quad_f32.h b/input_i2s_quad_f32.h index 6d4c20d..a190750 100644 --- a/input_i2s_quad_f32.h +++ b/input_i2s_quad_f32.h @@ -36,8 +36,6 @@ #ifndef _input_i2s_quad_f32_h_ #define _input_i2s_quad_f32_h_ -//#define __IMXRT1062__ - #include #include #include @@ -45,8 +43,11 @@ class AudioInputI2SQuad_F32 : public AudioStream_F32 { +//GUI: inputs:0, outputs:4 //this line used for automatic generation of GUI node public: + //uses default AUDIO_SAMPLE_RATE and BLOCK_SIZE_SAMPLES from AudioStream.h: AudioInputI2SQuad_F32(void) : AudioStream_F32(0, NULL) { begin(); } + // Allow variable sample rate and block size: AudioInputI2SQuad_F32(const AudioSettings_F32 &settings) : AudioStream_F32(0, NULL) { sample_rate_Hz = settings.sample_rate_Hz; audio_block_samples = settings.audio_block_samples;