From cc533594204c9959bcff5f629d0f48bbee51d390 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:44:51 +0100 Subject: [PATCH 01/14] JMS1 First Attempt IQ data displayed but didn't crash! --- T41EEE/AudioSignal.h | 68 ++++++++++++++++++++++++++++++++++++++---- T41EEE/ReceiveDSP.cpp | 10 +++++++ T41EEE/RxCalibrate.cpp | 10 ++++++- T41EEE/SDT.h | 10 ++++++- T41EEE/TxCalibrate.cpp | 10 ++++++- 5 files changed, 99 insertions(+), 9 deletions(-) diff --git a/T41EEE/AudioSignal.h b/T41EEE/AudioSignal.h index ef35e5d..cc9aea8 100644 --- a/T41EEE/AudioSignal.h +++ b/T41EEE/AudioSignal.h @@ -4,19 +4,31 @@ const float sample_rate_Hz = 48000.0; // The transmitter operates at 48ksps. const int audio_block_samples = 128; // Always 128 AudioSettings_F32 audio_settings(sample_rate_Hz, audio_block_samples); +#define JMS_QUAD 1 +#ifdef JMS_QUAD +AudioInputI2SQuad_F32 i2s_quadIn_f32; // 4 inputs available in experimental Open Audio library. Ussing Terrane's code +#else AudioInputI2SQuad i2s_quadIn; // 4 inputs available only in Teensy audio and not Open Audio library. +#endif AudioOutputI2SQuad_F32 i2s_quadOut_f32(audio_settings); // Transmitter -AudioControlSGTL5000 sgtl5000_1; // Controller for the Teensy Audio Adapter. +AudioControlSGTL5000 sgtl5000_1; +#ifdef JMS_QUAD +#warning //not neeeded +#else // Controller for the Teensy Audio Adapter. AudioConvert_I16toF32 int2Float1_tx; // Converts Int16 to Float. +#endif AudioEffectGain_F32 micGain(audio_settings), compGainCompensate(audio_settings); // Microphone gain control. AudioFilterEqualizer_F32 txEqualizer(audio_settings); AudioEffectCompressor2_F32 compressor1; // Open Audio Compressor radioCESSB_Z_transmit_F32 cessb1; +#ifdef JMS_QUAD +#warning //not neeeded +#else // Controller for the Teensy Audio Adapter. AudioConvert_F32toI16 float2Int1_tx, float2Int2_tx; // Converts Float to Int16. See class in AudioStream_F32.h - +#endif AudioSwitch4_OA_F32 switch3_tx, switch4_tx; AudioMixer4_F32 mixer1_tx, mixer2_tx, mixer3_tx; // Used to switch in tone during calibration. AudioSynthWaveformSine_F32 toneSSBCal1, toneSSBCal2; // Tones for SSB calibration and IMD testing. @@ -29,10 +41,15 @@ AudioPlayQueue_F32 Q_out_R_Ex; // AudioPlayQueue for driving the Q channel (CW/ AudioPlayQueue_F32 cwToneData; // The tone from the CW Exciter. // Begin transmit signal chain. +#ifdef JMS_QUAD +#warning //don't need the int2float object so just connect input straight to mixer +AudioConnection_F32 connect3(i2s_quadIn_f32, 0, mixer1_tx, 0); // Connect microphone mixer1 output 0 via gain control. +#else AudioConnection connect0(i2s_quadIn, 0, int2Float1_tx, 0); // Microphone audio channel. Must use int2Float because Open Audio does not have quad input. // Need a mixer to switch between microphone audio and tones used for calibration, testing, and CW. AudioConnection_F32 connect3(int2Float1_tx, 0, mixer1_tx, 0); // Connect microphone mixer1 output 0 via gain control. +#endif AudioConnection_F32 connect4(toneSSBCal1, 0, mixer1_tx, 1); // Connect tone for SSB calibration and IM3 testing. AudioConnection_F32 connect22(toneSSBCal2, 0, mixer1_tx, 2); // Connect tone for IM3 testing. @@ -75,15 +92,26 @@ AudioMixer4_F32 mixer4, mixer5; AudioSwitch4_OA_F32 switch1_rx, switch2_rx; AudioConvert_F32toI16 float2Int3, float2Int4, float2Int5, float2Int6; - +#ifdef JMS_QUAD +#warning //don't need the 16Bit to 32 conversion??? +AudioRecordQueue_F32 ADC_RX_I; // Receiver I channel from ADC PCM1808, 32 bit. +AudioRecordQueue_F32 ADC_RX_Q; // Receiver Q channel from ADC PCM1808, 32 bit. +#else AudioRecordQueue ADC_RX_I; // Receiver I channel from ADC PCM1808, 16 bit. AudioRecordQueue ADC_RX_Q; // Receiver Q channel from ADC PCM1808, 16 bit. +#endif AudioPlayQueue_F32 audioOutQueue; // Receiver audio out and CW sidetone. AudioPlayQueue_F32 sidetoneOutQueue; // Receiver audio out and CW sidetone. - +#ifdef JMS_QUAD +#warning //don't need the int2float object??? +AudioConnection patchCord1(i2s_quadIn_f32, 3, ADC_RX_I, 0); // Receiver I and Q channel data stream. +AudioConnection patchCord2(i2s_quadIn_f32, 2, ADC_RX_Q, 0); // This data stream goes to sketch code for processing. +#else AudioConnection patchCord1(i2s_quadIn, 3, ADC_RX_I, 0); // Receiver I and Q channel data stream. AudioConnection patchCord2(i2s_quadIn, 2, ADC_RX_Q, 0); // This data stream goes to sketch code for processing. +#endif + AudioConnection_F32 patchCord3(audioOutQueue, 0, mixer5, 0); // mixer5 selects receiver or CW sidetone audio. AudioConnection_F32 patchCord35(sidetoneOutQueue, 0, mixer5, 1); @@ -224,7 +252,12 @@ void SetAudioOperatingState(RadioState operatingState) { patchCord2.connect(); mixer5.gain(0, 1.0); // Connect receiver audio from DSP. mixer5.gain(1, 0); // Disconnect CW sidetone. +#ifdef JMS_QUAD +#warning //don't need the int2float object so just connect input straight to mixer + //connect3.disconnect(); // Disconnect microphone input data stream. +#else connect0.disconnect(); // Disconnect microphone input data stream. +#endif // Configure audio compressor (AGC) if (ConfigData.AGCMode == true) { // Activate compressor2_1 path. @@ -268,8 +301,12 @@ void SetAudioOperatingState(RadioState operatingState) { patchCord2.disconnect(); // Receiver Q channel mixer5.gain(0, 0); // Stop receiver audio. mixer5.gain(1, 0); // Stop sidetone audio. +#ifdef JMS_QUAD +#warning do we need to do something with connect3???? + //connect3.connect(); // Connect microphone input data stream. +#else connect0.connect(); // Connect microphone input data stream. - +#endif ADC_RX_I.end(); ADC_RX_I.clear(); ADC_RX_Q.end(); @@ -340,7 +377,12 @@ void SetAudioOperatingState(RadioState operatingState) { mixer1_tx.gain(1, 1); // testTone on. mixer1_tx.gain(2, 0); // testTone 2 off. +#ifdef JMS_QUAD +#warning do we need to do something with connect3???? + //connect3.disconnect(); // Disconnect microphone input data stream. +#else connect0.disconnect(); // Disconnect microphone input data stream. +#endif mixer_rxtx_I.gain(0, 1.0); // Connect transmitter back-end to Audio Adapter. mixer_rxtx_Q.gain(0, 1.0); mixer_rxtx_I.gain(1, 0); // Disconnect headphone path to Audio Adapter. @@ -392,8 +434,12 @@ void SetAudioOperatingState(RadioState operatingState) { patchCord2.disconnect(); // Receiver Q channel mixer5.gain(0, 0); // Stop receiver audio. mixer5.gain(1, 0); // Stop sidetone audio. +#ifdef JMS_QUAD +#warning do we need to do something with connect3???? + //connect3.disconnect(); // Disconnect microphone input data stream. +#else connect0.disconnect(); // Disconnect microphone input data stream. - +#endif ADC_RX_I.end(); ADC_RX_I.clear(); ADC_RX_Q.end(); @@ -462,7 +508,12 @@ void SetAudioOperatingState(RadioState operatingState) { patchCord2.disconnect(); // Receiver Q channel mixer5.gain(0, 0); // Disconnect receiver audio from DSP. mixer5.gain(1, 1.0); // Connect CW sidetone. +#ifdef JMS_QUAD +#warning do we need to do something with connect3???? + //connect3.disconnect(); // Disconnect microphone input data stream. +#else connect0.disconnect(); // Disconnect microphone input data stream. +#endif // Speaker and headphones should be unmuted according to current audio out state for sidetone. controlAudioOut(ConfigData.audioOut, false); @@ -522,7 +573,12 @@ void SetAudioOperatingState(RadioState operatingState) { InitializeDataArrays(); // I2S sample rate set in this function. controlAudioOut(AudioState::MUTE_BOTH, true); // Mute all audio. sgtl5000_1.unmuteLineout(); +#ifdef JMS_QUAD +#warning do we need to do something with connect3???? + //connect3.disconnect(); // Disconnect microphone input data stream. +#else connect0.disconnect(); // Disconnect microphone input data stream. +#endif mixer5.gain(0, 0); // Stop receiver audio. mixer5.gain(1, 0); // Stop sidetone audio. diff --git a/T41EEE/ReceiveDSP.cpp b/T41EEE/ReceiveDSP.cpp index 2742532..9f93918 100644 --- a/T41EEE/ReceiveDSP.cpp +++ b/T41EEE/ReceiveDSP.cpp @@ -39,8 +39,18 @@ bool ReceiveDSP::ProcessIQData() { Using arm_Math library, convert to float one buffer_size. Float_buffer samples are now standardized from > -1.0 to < 1.0 **********************************************************************************/ +#define JMS_QUAD 1 +#warning // need to find a place for this define +#ifdef JMS_QUAD +#warning // 32Bit copying with conversion do we need to chnage bloack sixe etc? + arm_copy_f32(ADC_RX_Q.readBuffer(), &float_buffer_L[BUFFER_SIZE * i], BUFFER_SIZE); // move input buffer as float 32bit. BUFFER_SIZE = 128. + arm_copy_f32(ADC_RX_I.readBuffer(), &float_buffer_R[BUFFER_SIZE * i], BUFFER_SIZE); // move input buffer as float 32bit. BUFFER_SIZE = 128. +#else arm_q15_to_float(ADC_RX_Q.readBuffer(), &float_buffer_L[BUFFER_SIZE * i], BUFFER_SIZE); // convert int_buffer to float 32bit. BUFFER_SIZE = 128. arm_q15_to_float(ADC_RX_I.readBuffer(), &float_buffer_R[BUFFER_SIZE * i], BUFFER_SIZE); // convert int_buffer to float 32bit +#endif + + ADC_RX_I.freeBuffer(); ADC_RX_Q.freeBuffer(); } // end for loop diff --git a/T41EEE/RxCalibrate.cpp b/T41EEE/RxCalibrate.cpp index 429dc9f..692e48a 100644 --- a/T41EEE/RxCalibrate.cpp +++ b/T41EEE/RxCalibrate.cpp @@ -776,8 +776,16 @@ void RxCalibrate::MakeFFTData() { Using arm_Math library, convert to float one buffer_size. Float_buffer samples are now standardized from > -1.0 to < 1.0 **********************************************************************************/ - arm_q15_to_float(ADC_RX_Q.readBuffer(), &float_buffer_L[BUFFER_SIZE * i], BUFFER_SIZE); // convert int_buffer to float 32bit +#define JMS_QUAD 1 +#warning // need to find a place for this define +#ifdef JMS_QUAD +#warning // 32Bit copying with conversion do we need to chnage bloack sixe etc? + arm_copy_f32(ADC_RX_Q.readBuffer(), &float_buffer_L[BUFFER_SIZE * i], BUFFER_SIZE); // move input buffer as float 32bit. BUFFER_SIZE = 128. + arm_copy_f32(ADC_RX_I.readBuffer(), &float_buffer_R[BUFFER_SIZE * i], BUFFER_SIZE); // move input buffer as float 32bit. BUFFER_SIZE = 128. +#else + arm_q15_to_float(ADC_RX_Q.readBuffer(), &float_buffer_L[BUFFER_SIZE * i], BUFFER_SIZE); // convert int_buffer to float 32bit. BUFFER_SIZE = 128. arm_q15_to_float(ADC_RX_I.readBuffer(), &float_buffer_R[BUFFER_SIZE * i], BUFFER_SIZE); // convert int_buffer to float 32bit +#endif ADC_RX_I.freeBuffer(); ADC_RX_Q.freeBuffer(); } diff --git a/T41EEE/SDT.h b/T41EEE/SDT.h index 65257b8..acc295c 100644 --- a/T41EEE/SDT.h +++ b/T41EEE/SDT.h @@ -306,7 +306,7 @@ extern Bands bands; // Configuration data structure. struct config_t { - char versionSettings[10] = "T41EEE.93"; // This is required to be the first! + char versionSettings[10] = "E93_JMS1"; // This is required to be the first! bool AGCMode = true; float32_t AGCThreshold = -40.0; @@ -549,8 +549,16 @@ extern int32_t NCOFreq; // AFP 04-16-22 // Teensy and OpenAudio objects which need to be global. Revised by KF5N July 24, 2024 extern AudioAmplifier volumeAdjust; +#define JMS_QUAD 1 +#warning // need to find a place for this define +#ifdef JMS_QUAD +#warning // 32Bit conversion ADC_RX_I/ADC_RX_Q +extern AudioRecordQueue_F32 ADC_RX_I; // Receiver I channel from ADC PCM1808, 32 bit. +extern AudioRecordQueue_F32 ADC_RX_Q; // Receiver Q channel from ADC PCM1808, 32 bit. +#else extern AudioRecordQueue ADC_RX_I; extern AudioRecordQueue ADC_RX_Q; +#endif extern AudioRecordQueue_F32 Q_in_L_Ex; extern AudioRecordQueue_F32 Q_in_R_Ex; diff --git a/T41EEE/TxCalibrate.cpp b/T41EEE/TxCalibrate.cpp index b8db1fb..0187621 100644 --- a/T41EEE/TxCalibrate.cpp +++ b/T41EEE/TxCalibrate.cpp @@ -1220,8 +1220,16 @@ void TxCalibrate::MakeFFTData() { Using arm_Math library, convert to float one buffer_size. Float_buffer samples are now standardized from > -1.0 to < 1.0 **********************************************************************************/ - arm_q15_to_float(ADC_RX_Q.readBuffer(), &float_buffer_L[BUFFER_SIZE * i], BUFFER_SIZE); // convert int_buffer to float 32bit +#define JMS_QUAD 1 +#warning // need to find a place for this define +#ifdef JMS_QUAD +#warning // 32Bit copying with conversion do we need to chnage bloack sixe etc? + arm_copy_f32(ADC_RX_Q.readBuffer(), &float_buffer_L[BUFFER_SIZE * i], BUFFER_SIZE); // move input buffer as float 32bit. BUFFER_SIZE = 128. + arm_copy_f32(ADC_RX_I.readBuffer(), &float_buffer_R[BUFFER_SIZE * i], BUFFER_SIZE); // move input buffer as float 32bit. BUFFER_SIZE = 128. +#else + arm_q15_to_float(ADC_RX_Q.readBuffer(), &float_buffer_L[BUFFER_SIZE * i], BUFFER_SIZE); // convert int_buffer to float 32bit. BUFFER_SIZE = 128. arm_q15_to_float(ADC_RX_I.readBuffer(), &float_buffer_R[BUFFER_SIZE * i], BUFFER_SIZE); // convert int_buffer to float 32bit +#endif ADC_RX_I.freeBuffer(); ADC_RX_Q.freeBuffer(); } From e3fc1debd8da1e7f43a401a20f3b00a710687dac 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:06:00 +0100 Subject: [PATCH 02/14] Update AudioSignal.h The Floating point libraries need audio settings to work properly. --- T41EEE/AudioSignal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/T41EEE/AudioSignal.h b/T41EEE/AudioSignal.h index cc9aea8..47c3f43 100644 --- a/T41EEE/AudioSignal.h +++ b/T41EEE/AudioSignal.h @@ -6,7 +6,7 @@ const int audio_block_samples = 128; // Always 128 AudioSettings_F32 audio_settings(sample_rate_Hz, audio_block_samples); #define JMS_QUAD 1 #ifdef JMS_QUAD -AudioInputI2SQuad_F32 i2s_quadIn_f32; // 4 inputs available in experimental Open Audio library. Ussing Terrane's code +AudioInputI2SQuad_F32 i2s_quadIn_f32(audio_settings); // 4 inputs available in experimental Open Audio library. Ussing Terrane's code #else AudioInputI2SQuad i2s_quadIn; // 4 inputs available only in Teensy audio and not Open Audio library. #endif From c719b8dd794deaa2fcc331bdc3a735fe93d1142d Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Sun, 12 Jul 2026 09:09:27 +0100 Subject: [PATCH 03/14] Working on RX Works on RX, had to disconnect Microphone connection3 as there was a Null pointer crash in line 144 of AudioStream_F32.cpp --- T41EEE/AudioSignal.h | 55 +++++++++++++++++++++++++++++++++---------- T41EEE/ReceiveDSP.cpp | 5 +++- T41EEE/T41EEE.ino | 13 ++++++++-- 3 files changed, 57 insertions(+), 16 deletions(-) diff --git a/T41EEE/AudioSignal.h b/T41EEE/AudioSignal.h index 47c3f43..3b3cfb8 100644 --- a/T41EEE/AudioSignal.h +++ b/T41EEE/AudioSignal.h @@ -13,10 +13,11 @@ AudioInputI2SQuad i2s_quadIn; // 4 inputs available only in Teensy audio and no AudioOutputI2SQuad_F32 i2s_quadOut_f32(audio_settings); // Transmitter + AudioControlSGTL5000 sgtl5000_1; -#ifdef JMS_QUAD +#ifdef JMS_QUAD // Controller for the Teensy Audio Adapter. #warning //not neeeded -#else // Controller for the Teensy Audio Adapter. +#else AudioConvert_I16toF32 int2Float1_tx; // Converts Int16 to Float. #endif AudioEffectGain_F32 micGain(audio_settings), compGainCompensate(audio_settings); // Microphone gain control. @@ -26,7 +27,7 @@ radioCESSB_Z_transmit_F32 cessb1; #ifdef JMS_QUAD #warning //not neeeded -#else // Controller for the Teensy Audio Adapter. +#else AudioConvert_F32toI16 float2Int1_tx, float2Int2_tx; // Converts Float to Int16. See class in AudioStream_F32.h #endif AudioSwitch4_OA_F32 switch3_tx, switch4_tx; @@ -42,8 +43,9 @@ AudioPlayQueue_F32 cwToneData; // The tone from the CW Exciter. // Begin transmit signal chain. #ifdef JMS_QUAD -#warning //don't need the int2float object so just connect input straight to mixer -AudioConnection_F32 connect3(i2s_quadIn_f32, 0, mixer1_tx, 0); // Connect microphone mixer1 output 0 via gain control. +#warning //don't need the int2float object so ust connect input straight to mixer + +//AudioConnection_F32 connect3(i2s_quadIn_f32, 0, mixer1_tx, 0); // Connect microphone mixer1 output 0 via gain control. #else AudioConnection connect0(i2s_quadIn, 0, int2Float1_tx, 0); // Microphone audio channel. Must use int2Float because Open Audio does not have quad input. @@ -94,8 +96,8 @@ AudioSwitch4_OA_F32 switch1_rx, switch2_rx; AudioConvert_F32toI16 float2Int3, float2Int4, float2Int5, float2Int6; #ifdef JMS_QUAD #warning //don't need the 16Bit to 32 conversion??? -AudioRecordQueue_F32 ADC_RX_I; // Receiver I channel from ADC PCM1808, 32 bit. -AudioRecordQueue_F32 ADC_RX_Q; // Receiver Q channel from ADC PCM1808, 32 bit. +AudioRecordQueue_F32 ADC_RX_I(audio_settings); // Receiver I channel from ADC PCM1808, 32 bit. +AudioRecordQueue_F32 ADC_RX_Q(audio_settings); // Receiver Q channel from ADC PCM1808, 32 bit. #else AudioRecordQueue ADC_RX_I; // Receiver I channel from ADC PCM1808, 16 bit. AudioRecordQueue ADC_RX_Q; // Receiver Q channel from ADC PCM1808, 16 bit. @@ -105,8 +107,8 @@ AudioPlayQueue_F32 audioOutQueue; // Receiver audio out and CW sidetone. AudioPlayQueue_F32 sidetoneOutQueue; // Receiver audio out and CW sidetone. #ifdef JMS_QUAD #warning //don't need the int2float object??? -AudioConnection patchCord1(i2s_quadIn_f32, 3, ADC_RX_I, 0); // Receiver I and Q channel data stream. -AudioConnection patchCord2(i2s_quadIn_f32, 2, ADC_RX_Q, 0); // This data stream goes to sketch code for processing. +AudioConnection_F32 patchCord1(i2s_quadIn_f32, 3, ADC_RX_I, 0); // Receiver I and Q channel data stream. +AudioConnection_F32 patchCord2(i2s_quadIn_f32, 2, ADC_RX_Q, 0); // This data stream goes to sketch code for processing. #else AudioConnection patchCord1(i2s_quadIn, 3, ADC_RX_I, 0); // Receiver I and Q channel data stream. AudioConnection patchCord2(i2s_quadIn, 2, ADC_RX_Q, 0); // This data stream goes to sketch code for processing. @@ -248,8 +250,12 @@ void SetAudioOperatingState(RadioState operatingState) { mixer3_tx.gain(1, 0.0); // Connect audio paths +#ifdef JMS_QUAD +#warning // Auconnection_F32 doesn't support connect/disconnect WTF??? +#else patchCord1.connect(); patchCord2.connect(); +#endif mixer5.gain(0, 1.0); // Connect receiver audio from DSP. mixer5.gain(1, 0); // Disconnect CW sidetone. #ifdef JMS_QUAD @@ -297,8 +303,12 @@ void SetAudioOperatingState(RadioState operatingState) { // QSD disabled and disconnected controlAudioOut(ConfigData.audioOut, true); // Mute all receiver audio. sgtl5000_1.unmuteLineout(); +#ifdef JMS_QUAD +#warning // Auconnection_F32 doesn't support connect/disconnect WTF??? +#else patchCord1.disconnect(); // Receiver I channel patchCord2.disconnect(); // Receiver Q channel +#endif mixer5.gain(0, 0); // Stop receiver audio. mixer5.gain(1, 0); // Stop sidetone audio. #ifdef JMS_QUAD @@ -356,9 +366,12 @@ void SetAudioOperatingState(RadioState operatingState) { InitializeDataArrays(); // I2S sample rate set in this function. controlAudioOut(AudioState::MUTE_BOTH, true); // Mute all audio. sgtl5000_1.unmuteLineout(); - patchCord1.connect(); // Receiver I channel - patchCord2.connect(); // Receiver Q channel - mixer5.gain(0, 0); // Stop receiver audio. +#ifdef JMS_QUAD +#warning // Auconnection_F32 doesn't support connect/disconnect WTF??? +#else + patchCord1.connect(); + patchCord2.connect(); +#endif mixer5.gain(0, 0); // Stop receiver audio. mixer5.gain(1, 0); // Stop sidetone audio. ADC_RX_I.end(); ADC_RX_I.clear(); @@ -430,8 +443,12 @@ void SetAudioOperatingState(RadioState operatingState) { // QSD disabled and disconnected controlAudioOut(AudioState::MUTE_BOTH, true); // Mute all audio. sgtl5000_1.unmuteLineout(); +#ifdef JMS_QUAD +#warning // Auconnection_F32 doesn't support connect/disconnect WTF??? +#else patchCord1.disconnect(); // Receiver I channel patchCord2.disconnect(); // Receiver Q channel +#endif mixer5.gain(0, 0); // Stop receiver audio. mixer5.gain(1, 0); // Stop sidetone audio. #ifdef JMS_QUAD @@ -504,8 +521,12 @@ void SetAudioOperatingState(RadioState operatingState) { controlAudioOut(ConfigData.audioOut, true); // Mute all audio. Unmuted at end of configuration. sgtl5000_1.unmuteLineout(); // QSD disabled and disconnected +#ifdef JMS_QUAD +#warning // Auconnection_F32 doesn't support connect/disconnect WTF??? +#else patchCord1.disconnect(); // Receiver I channel patchCord2.disconnect(); // Receiver Q channel +#endif mixer5.gain(0, 0); // Disconnect receiver audio from DSP. mixer5.gain(1, 1.0); // Connect CW sidetone. #ifdef JMS_QUAD @@ -619,8 +640,12 @@ void SetAudioOperatingState(RadioState operatingState) { cessb1.setIQCorrections(true, CalData.IQCWAmpCorrectionFactorUSB[ConfigData.currentBand], CalData.IQCWPhaseCorrectionFactorUSB[ConfigData.currentBand], 0.0); } - patchCord1.connect(); // Connect I and Q receiver data converters. +#ifdef JMS_QUAD +#warning // AudioConnection_F32 doesn't support connect/disconnect WTF??? +#else + patchCord1.connect(); patchCord2.connect(); +#endif ADC_RX_I.begin(); // Calibration is full duplex! ADC_RX_Q.begin(); @@ -659,8 +684,12 @@ void SetAudioOperatingState(RadioState operatingState) { mixer_rxtx_Q.gain(0, 1.0); mixer_rxtx_I.gain(1, 0.0); // Disconnect headphone path to Audio Adapter. mixer_rxtx_Q.gain(1, 0.0); +#ifdef JMS_QUAD +#warning // Auconnection_F32 doesn't support connect/disconnect WTF??? +#else patchCord1.connect(); patchCord2.connect(); +#endif ADC_RX_I.begin(); // Calibration is full duplex! ADC_RX_Q.begin(); diff --git a/T41EEE/ReceiveDSP.cpp b/T41EEE/ReceiveDSP.cpp index 9f93918..a97b3b0 100644 --- a/T41EEE/ReceiveDSP.cpp +++ b/T41EEE/ReceiveDSP.cpp @@ -28,10 +28,13 @@ bool ReceiveDSP::ProcessIQData() { uint32_t AudioMaxIndex; float rfGainValue; int rfGain; - + /*Serial.printf("ADC_RX_I.available=%d ADC_RX_Q.available=%d \n", + ADC_RX_I.available(), + ADC_RX_Q.available() );*/ // Are there at least N_BLOCKS buffers in each channel available ? N_BLOCKS should be 16. Fill float_buffer_L/R[2048]. if (static_cast(ADC_RX_I.available()) > 15 && static_cast(ADC_RX_Q.available()) > 15) { usec = 0; + // Get audio samples from the audio buffers and convert them to float. // Read in 16 blocks and 128 samples in I and Q. 16 * 128 = 2048 (N_BLOCKS = 16) for (unsigned i = 0; i < N_BLOCKS; i++) { diff --git a/T41EEE/T41EEE.ino b/T41EEE/T41EEE.ino index e2bab15..ca6829b 100644 --- a/T41EEE/T41EEE.ino +++ b/T41EEE/T41EEE.ino @@ -874,8 +874,9 @@ FLASHMEM void setup() { Serial.begin(115200); // Check for CrashReport stored from previous run. + if (CrashReport) { - /* print info (hope Serial Monitor windows is open) */ + // print info (hope Serial Monitor windows is open) Serial.print(CrashReport); } @@ -1086,7 +1087,15 @@ void loop() { long ditTimerOff; //AFP 09-22-22 bool cwKeyDown; unsigned long cwBlockIndex; - + /* + Serial.printf("lastState=%d radioState=%d memory_used=%d memory_used_max=%d f32_memory_used=%d f32_memory_used_max=%d\n", + lastState, + radioState, + (int)AudioStream::memory_used, + (int)AudioStream::memory_used_max, + (int)AudioStream_F32::f32_memory_used, + (int)AudioStream_F32::f32_memory_used_max); +*/ // Radio state detection before entering the primary radio loop. if (bands.bands[ConfigData.currentBand].mode == RadioMode::SSB_MODE and digitalRead(PTT) == HIGH) radioState = RadioState::SSB_RECEIVE_STATE; if (bands.bands[ConfigData.currentBand].mode == RadioMode::SSB_MODE and digitalRead(PTT) == LOW) radioState = RadioState::SSB_TRANSMIT_STATE; From 48dcdc7cc0e24cd38802569edfe3cb99a0153d87 Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Sun, 12 Jul 2026 10:01:03 +0100 Subject: [PATCH 04/14] Seems to be working on TX and RX now Did change anything just a rebuild --- T41EEE/AudioSignal.h | 2 +- T41EEE/T41EEE.ino | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/T41EEE/AudioSignal.h b/T41EEE/AudioSignal.h index 3b3cfb8..3c9e6ac 100644 --- a/T41EEE/AudioSignal.h +++ b/T41EEE/AudioSignal.h @@ -45,7 +45,7 @@ AudioPlayQueue_F32 cwToneData; // The tone from the CW Exciter. #ifdef JMS_QUAD #warning //don't need the int2float object so ust connect input straight to mixer -//AudioConnection_F32 connect3(i2s_quadIn_f32, 0, mixer1_tx, 0); // Connect microphone mixer1 output 0 via gain control. +AudioConnection_F32 connect3(i2s_quadIn_f32, 0, mixer1_tx, 0); // Connect microphone mixer1 output 0 via gain control. #else AudioConnection connect0(i2s_quadIn, 0, int2Float1_tx, 0); // Microphone audio channel. Must use int2Float because Open Audio does not have quad input. diff --git a/T41EEE/T41EEE.ino b/T41EEE/T41EEE.ino index ca6829b..447c922 100644 --- a/T41EEE/T41EEE.ino +++ b/T41EEE/T41EEE.ino @@ -1087,7 +1087,7 @@ void loop() { long ditTimerOff; //AFP 09-22-22 bool cwKeyDown; unsigned long cwBlockIndex; - /* + Serial.printf("lastState=%d radioState=%d memory_used=%d memory_used_max=%d f32_memory_used=%d f32_memory_used_max=%d\n", lastState, radioState, @@ -1095,7 +1095,7 @@ void loop() { (int)AudioStream::memory_used_max, (int)AudioStream_F32::f32_memory_used, (int)AudioStream_F32::f32_memory_used_max); -*/ + // Radio state detection before entering the primary radio loop. if (bands.bands[ConfigData.currentBand].mode == RadioMode::SSB_MODE and digitalRead(PTT) == HIGH) radioState = RadioState::SSB_RECEIVE_STATE; if (bands.bands[ConfigData.currentBand].mode == RadioMode::SSB_MODE and digitalRead(PTT) == LOW) radioState = RadioState::SSB_TRANSMIT_STATE; From 77d6d95f30b17e8b9e54a6181dde2ac3a87d1ff2 Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Wed, 15 Jul 2026 08:10:47 +0100 Subject: [PATCH 05/14] Remove most of the warnings I have done an investigation into the connect/disconnect and discovered it is handled in the RecordQueue object which discards data if it is disabled. --- T41EEE/AudioSignal.h | 57 +++++++++++++++++++++++------------------- T41EEE/ReceiveDSP.cpp | 1 - T41EEE/RxCalibrate.cpp | 1 - T41EEE/SDT.h | 1 - T41EEE/TxCalibrate.cpp | 1 - 5 files changed, 31 insertions(+), 30 deletions(-) diff --git a/T41EEE/AudioSignal.h b/T41EEE/AudioSignal.h index 3c9e6ac..1602a59 100644 --- a/T41EEE/AudioSignal.h +++ b/T41EEE/AudioSignal.h @@ -16,7 +16,7 @@ AudioOutputI2SQuad_F32 i2s_quadOut_f32(audio_settings); AudioControlSGTL5000 sgtl5000_1; #ifdef JMS_QUAD // Controller for the Teensy Audio Adapter. -#warning //not neeeded +//not neeeded float conversion done in AudioInputI2SQuad_F32 #else AudioConvert_I16toF32 int2Float1_tx; // Converts Int16 to Float. #endif @@ -26,7 +26,7 @@ AudioEffectCompressor2_F32 compressor1; // Open Audio Compressor radioCESSB_Z_transmit_F32 cessb1; #ifdef JMS_QUAD -#warning //not neeeded +//not neeeded float conversion done in AudioInputI2SQuad_F32 #else AudioConvert_F32toI16 float2Int1_tx, float2Int2_tx; // Converts Float to Int16. See class in AudioStream_F32.h #endif @@ -43,8 +43,7 @@ AudioPlayQueue_F32 cwToneData; // The tone from the CW Exciter. // Begin transmit signal chain. #ifdef JMS_QUAD -#warning //don't need the int2float object so ust connect input straight to mixer - +//don't need the int2float object so just connect input straight to mixer AudioConnection_F32 connect3(i2s_quadIn_f32, 0, mixer1_tx, 0); // Connect microphone mixer1 output 0 via gain control. #else AudioConnection connect0(i2s_quadIn, 0, int2Float1_tx, 0); // Microphone audio channel. Must use int2Float because Open Audio does not have quad input. @@ -95,7 +94,6 @@ AudioMixer4_F32 mixer4, mixer5; AudioSwitch4_OA_F32 switch1_rx, switch2_rx; AudioConvert_F32toI16 float2Int3, float2Int4, float2Int5, float2Int6; #ifdef JMS_QUAD -#warning //don't need the 16Bit to 32 conversion??? AudioRecordQueue_F32 ADC_RX_I(audio_settings); // Receiver I channel from ADC PCM1808, 32 bit. AudioRecordQueue_F32 ADC_RX_Q(audio_settings); // Receiver Q channel from ADC PCM1808, 32 bit. #else @@ -106,7 +104,6 @@ AudioRecordQueue ADC_RX_Q; // Receiver Q channel from ADC PCM1808, 16 bit. AudioPlayQueue_F32 audioOutQueue; // Receiver audio out and CW sidetone. AudioPlayQueue_F32 sidetoneOutQueue; // Receiver audio out and CW sidetone. #ifdef JMS_QUAD -#warning //don't need the int2float object??? AudioConnection_F32 patchCord1(i2s_quadIn_f32, 3, ADC_RX_I, 0); // Receiver I and Q channel data stream. AudioConnection_F32 patchCord2(i2s_quadIn_f32, 2, ADC_RX_Q, 0); // This data stream goes to sketch code for processing. #else @@ -251,7 +248,8 @@ void SetAudioOperatingState(RadioState operatingState) { // Connect audio paths #ifdef JMS_QUAD -#warning // Auconnection_F32 doesn't support connect/disconnect WTF??? + // AudioConnection_F32 doesn't support connect/disconnect + // Instead the AudioRecordQueue_F32 discards any received data #else patchCord1.connect(); patchCord2.connect(); @@ -259,8 +257,8 @@ void SetAudioOperatingState(RadioState operatingState) { mixer5.gain(0, 1.0); // Connect receiver audio from DSP. mixer5.gain(1, 0); // Disconnect CW sidetone. #ifdef JMS_QUAD -#warning //don't need the int2float object so just connect input straight to mixer - //connect3.disconnect(); // Disconnect microphone input data stream. + // AudioConnection_F32 doesn't support connect/disconnect + // Instead the AudioRecordQueue_F32 discards any received data #else connect0.disconnect(); // Disconnect microphone input data stream. #endif @@ -304,7 +302,8 @@ void SetAudioOperatingState(RadioState operatingState) { controlAudioOut(ConfigData.audioOut, true); // Mute all receiver audio. sgtl5000_1.unmuteLineout(); #ifdef JMS_QUAD -#warning // Auconnection_F32 doesn't support connect/disconnect WTF??? + // AudioConnection_F32 doesn't support connect/disconnect + // Instead the AudioRecordQueue_F32 discards any received data #else patchCord1.disconnect(); // Receiver I channel patchCord2.disconnect(); // Receiver Q channel @@ -312,8 +311,8 @@ void SetAudioOperatingState(RadioState operatingState) { mixer5.gain(0, 0); // Stop receiver audio. mixer5.gain(1, 0); // Stop sidetone audio. #ifdef JMS_QUAD -#warning do we need to do something with connect3???? - //connect3.connect(); // Connect microphone input data stream. + // AudioConnection_F32 doesn't support connect/disconnect + // Instead the AudioRecordQueue_F32 discards any received data #else connect0.connect(); // Connect microphone input data stream. #endif @@ -367,11 +366,13 @@ void SetAudioOperatingState(RadioState operatingState) { controlAudioOut(AudioState::MUTE_BOTH, true); // Mute all audio. sgtl5000_1.unmuteLineout(); #ifdef JMS_QUAD -#warning // Auconnection_F32 doesn't support connect/disconnect WTF??? + // AudioConnection_F32 doesn't support connect/disconnect + // Instead the AudioRecordQueue_F32 discards any received data #else patchCord1.connect(); patchCord2.connect(); -#endif mixer5.gain(0, 0); // Stop receiver audio. +#endif + mixer5.gain(0, 0); // Stop receiver audio. mixer5.gain(1, 0); // Stop sidetone audio. ADC_RX_I.end(); ADC_RX_I.clear(); @@ -391,8 +392,8 @@ void SetAudioOperatingState(RadioState operatingState) { mixer1_tx.gain(2, 0); // testTone 2 off. #ifdef JMS_QUAD -#warning do we need to do something with connect3???? - //connect3.disconnect(); // Disconnect microphone input data stream. + // AudioConnection_F32 doesn't support connect/disconnect + // Instead the AudioRecordQueue_F32 discards any received data #else connect0.disconnect(); // Disconnect microphone input data stream. #endif @@ -444,7 +445,8 @@ void SetAudioOperatingState(RadioState operatingState) { controlAudioOut(AudioState::MUTE_BOTH, true); // Mute all audio. sgtl5000_1.unmuteLineout(); #ifdef JMS_QUAD -#warning // Auconnection_F32 doesn't support connect/disconnect WTF??? + // AudioConnection_F32 doesn't support connect/disconnect + // Instead the AudioRecordQueue_F32 discards any received data #else patchCord1.disconnect(); // Receiver I channel patchCord2.disconnect(); // Receiver Q channel @@ -452,8 +454,8 @@ void SetAudioOperatingState(RadioState operatingState) { mixer5.gain(0, 0); // Stop receiver audio. mixer5.gain(1, 0); // Stop sidetone audio. #ifdef JMS_QUAD -#warning do we need to do something with connect3???? - //connect3.disconnect(); // Disconnect microphone input data stream. + // AudioConnection_F32 doesn't support connect/disconnect + // Instead the AudioRecordQueue_F32 discards any received data #else connect0.disconnect(); // Disconnect microphone input data stream. #endif @@ -522,7 +524,8 @@ void SetAudioOperatingState(RadioState operatingState) { sgtl5000_1.unmuteLineout(); // QSD disabled and disconnected #ifdef JMS_QUAD -#warning // Auconnection_F32 doesn't support connect/disconnect WTF??? + // AudioConnection_F32 doesn't support connect/disconnect + // Instead the AudioRecordQueue_F32 discards any received data #else patchCord1.disconnect(); // Receiver I channel patchCord2.disconnect(); // Receiver Q channel @@ -530,8 +533,8 @@ void SetAudioOperatingState(RadioState operatingState) { mixer5.gain(0, 0); // Disconnect receiver audio from DSP. mixer5.gain(1, 1.0); // Connect CW sidetone. #ifdef JMS_QUAD -#warning do we need to do something with connect3???? - //connect3.disconnect(); // Disconnect microphone input data stream. + // AudioConnection_F32 doesn't support connect/disconnect + // Instead the AudioRecordQueue_F32 discards any received data #else connect0.disconnect(); // Disconnect microphone input data stream. #endif @@ -595,8 +598,8 @@ void SetAudioOperatingState(RadioState operatingState) { controlAudioOut(AudioState::MUTE_BOTH, true); // Mute all audio. sgtl5000_1.unmuteLineout(); #ifdef JMS_QUAD -#warning do we need to do something with connect3???? - //connect3.disconnect(); // Disconnect microphone input data stream. + // AudioConnection_F32 doesn't support connect/disconnect + // Instead the AudioRecordQueue_F32 discards any received data #else connect0.disconnect(); // Disconnect microphone input data stream. #endif @@ -641,7 +644,8 @@ void SetAudioOperatingState(RadioState operatingState) { } #ifdef JMS_QUAD -#warning // AudioConnection_F32 doesn't support connect/disconnect WTF??? + // AudioConnection_F32 doesn't support connect/disconnect + // Instead the AudioRecordQueue_F32 discards any received data #else patchCord1.connect(); patchCord2.connect(); @@ -685,7 +689,8 @@ void SetAudioOperatingState(RadioState operatingState) { mixer_rxtx_I.gain(1, 0.0); // Disconnect headphone path to Audio Adapter. mixer_rxtx_Q.gain(1, 0.0); #ifdef JMS_QUAD -#warning // Auconnection_F32 doesn't support connect/disconnect WTF??? + // AudioConnection_F32 doesn't support connect/disconnect + // Instead the AudioRecordQueue_F32 discards any received data #else patchCord1.connect(); patchCord2.connect(); diff --git a/T41EEE/ReceiveDSP.cpp b/T41EEE/ReceiveDSP.cpp index a97b3b0..109f01f 100644 --- a/T41EEE/ReceiveDSP.cpp +++ b/T41EEE/ReceiveDSP.cpp @@ -45,7 +45,6 @@ bool ReceiveDSP::ProcessIQData() { #define JMS_QUAD 1 #warning // need to find a place for this define #ifdef JMS_QUAD -#warning // 32Bit copying with conversion do we need to chnage bloack sixe etc? arm_copy_f32(ADC_RX_Q.readBuffer(), &float_buffer_L[BUFFER_SIZE * i], BUFFER_SIZE); // move input buffer as float 32bit. BUFFER_SIZE = 128. arm_copy_f32(ADC_RX_I.readBuffer(), &float_buffer_R[BUFFER_SIZE * i], BUFFER_SIZE); // move input buffer as float 32bit. BUFFER_SIZE = 128. #else diff --git a/T41EEE/RxCalibrate.cpp b/T41EEE/RxCalibrate.cpp index 692e48a..27edfd7 100644 --- a/T41EEE/RxCalibrate.cpp +++ b/T41EEE/RxCalibrate.cpp @@ -779,7 +779,6 @@ void RxCalibrate::MakeFFTData() { #define JMS_QUAD 1 #warning // need to find a place for this define #ifdef JMS_QUAD -#warning // 32Bit copying with conversion do we need to chnage bloack sixe etc? arm_copy_f32(ADC_RX_Q.readBuffer(), &float_buffer_L[BUFFER_SIZE * i], BUFFER_SIZE); // move input buffer as float 32bit. BUFFER_SIZE = 128. arm_copy_f32(ADC_RX_I.readBuffer(), &float_buffer_R[BUFFER_SIZE * i], BUFFER_SIZE); // move input buffer as float 32bit. BUFFER_SIZE = 128. #else diff --git a/T41EEE/SDT.h b/T41EEE/SDT.h index acc295c..82241c7 100644 --- a/T41EEE/SDT.h +++ b/T41EEE/SDT.h @@ -552,7 +552,6 @@ extern AudioAmplifier volumeAdjust; #define JMS_QUAD 1 #warning // need to find a place for this define #ifdef JMS_QUAD -#warning // 32Bit conversion ADC_RX_I/ADC_RX_Q extern AudioRecordQueue_F32 ADC_RX_I; // Receiver I channel from ADC PCM1808, 32 bit. extern AudioRecordQueue_F32 ADC_RX_Q; // Receiver Q channel from ADC PCM1808, 32 bit. #else diff --git a/T41EEE/TxCalibrate.cpp b/T41EEE/TxCalibrate.cpp index 0187621..bea7a51 100644 --- a/T41EEE/TxCalibrate.cpp +++ b/T41EEE/TxCalibrate.cpp @@ -1223,7 +1223,6 @@ void TxCalibrate::MakeFFTData() { #define JMS_QUAD 1 #warning // need to find a place for this define #ifdef JMS_QUAD -#warning // 32Bit copying with conversion do we need to chnage bloack sixe etc? arm_copy_f32(ADC_RX_Q.readBuffer(), &float_buffer_L[BUFFER_SIZE * i], BUFFER_SIZE); // move input buffer as float 32bit. BUFFER_SIZE = 128. arm_copy_f32(ADC_RX_I.readBuffer(), &float_buffer_R[BUFFER_SIZE * i], BUFFER_SIZE); // move input buffer as float 32bit. BUFFER_SIZE = 128. #else From 1fcf39da85072803152b866d0fa1c0a68fd74a4d Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Sun, 19 Jul 2026 15:29:58 +0100 Subject: [PATCH 06/14] Bug fix and remove magic numbers Also removed debug --- T41EEE/RxCalibrate.cpp | 8 ++------ T41EEE/T41EEE.ino | 4 ++-- T41EEE/TxCalibrate.cpp | 12 +++++------- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/T41EEE/RxCalibrate.cpp b/T41EEE/RxCalibrate.cpp index 27edfd7..719870f 100644 --- a/T41EEE/RxCalibrate.cpp +++ b/T41EEE/RxCalibrate.cpp @@ -695,7 +695,6 @@ void RxCalibrate::DoReceiveCalibrate(int calMode, bool radio, bool refine, bool void RxCalibrate::MakeFFTData() { float rfGainValue, powerScale; // AFP 2-11-23. Greg KF5N February 13, 2023 // float recBandFactor[7] = { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; // AFP 2-11-23 KF5N uniform values - /********************************************************************************** AFP 12-31-20 Get samples from queue buffers Teensy Audio Library stores ADC data in two buffers size=128, Q_in_L and Q_in_R as initiated from the audio lib. @@ -770,14 +769,12 @@ void RxCalibrate::MakeFFTData() { // Get I16 audio blocks from the record queues and convert them to float. // Read in 16 blocks of 128 samples in I and Q if available. - if (static_cast(ADC_RX_I.available()) > 16 and static_cast(ADC_RX_Q.available()) > 16) { - for (unsigned i = 0; i < 16; i++) { + if (static_cast(ADC_RX_I.available()) > 15 && static_cast(ADC_RX_Q.available()) > 15) { + for (unsigned i = 0; i < N_BLOCKS; i++) { /********************************************************************************** AFP 12-31-20 Using arm_Math library, convert to float one buffer_size. Float_buffer samples are now standardized from > -1.0 to < 1.0 **********************************************************************************/ -#define JMS_QUAD 1 -#warning // need to find a place for this define #ifdef JMS_QUAD arm_copy_f32(ADC_RX_Q.readBuffer(), &float_buffer_L[BUFFER_SIZE * i], BUFFER_SIZE); // move input buffer as float 32bit. BUFFER_SIZE = 128. arm_copy_f32(ADC_RX_I.readBuffer(), &float_buffer_R[BUFFER_SIZE * i], BUFFER_SIZE); // move input buffer as float 32bit. BUFFER_SIZE = 128. @@ -788,7 +785,6 @@ void RxCalibrate::MakeFFTData() { ADC_RX_I.freeBuffer(); ADC_RX_Q.freeBuffer(); } - rfGainValue = pow(10, (float)ConfigData.rfGain[ConfigData.currentBand] / 20); //AFP 2-11-23 arm_scale_f32(float_buffer_L, rfGainValue, float_buffer_L, BUFFER_SIZE * N_BLOCKS); //AFP 2-11-23 arm_scale_f32(float_buffer_R, rfGainValue, float_buffer_R, BUFFER_SIZE * N_BLOCKS); //AFP 2-11-23 diff --git a/T41EEE/T41EEE.ino b/T41EEE/T41EEE.ino index 447c922..fd50836 100644 --- a/T41EEE/T41EEE.ino +++ b/T41EEE/T41EEE.ino @@ -1087,7 +1087,7 @@ void loop() { long ditTimerOff; //AFP 09-22-22 bool cwKeyDown; unsigned long cwBlockIndex; - +/* Serial.printf("lastState=%d radioState=%d memory_used=%d memory_used_max=%d f32_memory_used=%d f32_memory_used_max=%d\n", lastState, radioState, @@ -1095,7 +1095,7 @@ void loop() { (int)AudioStream::memory_used_max, (int)AudioStream_F32::f32_memory_used, (int)AudioStream_F32::f32_memory_used_max); - +*/ // Radio state detection before entering the primary radio loop. if (bands.bands[ConfigData.currentBand].mode == RadioMode::SSB_MODE and digitalRead(PTT) == HIGH) radioState = RadioState::SSB_RECEIVE_STATE; if (bands.bands[ConfigData.currentBand].mode == RadioMode::SSB_MODE and digitalRead(PTT) == LOW) radioState = RadioState::SSB_TRANSMIT_STATE; diff --git a/T41EEE/TxCalibrate.cpp b/T41EEE/TxCalibrate.cpp index bea7a51..ae3417e 100644 --- a/T41EEE/TxCalibrate.cpp +++ b/T41EEE/TxCalibrate.cpp @@ -1214,14 +1214,12 @@ void TxCalibrate::MakeFFTData() { // Get audio samples from the audio buffers and convert them to float. // Read in 16 blocks of 128 samples in I and Q if available. - if (static_cast(ADC_RX_I.available()) > 15 and static_cast(ADC_RX_Q.available()) > 15) { + if (static_cast(ADC_RX_I.available()) > 15 && static_cast(ADC_RX_Q.available()) > 15) { for (unsigned i = 0; i < N_BLOCKS; i++) { /********************************************************************************** AFP 12-31-20 Using arm_Math library, convert to float one buffer_size. Float_buffer samples are now standardized from > -1.0 to < 1.0 **********************************************************************************/ -#define JMS_QUAD 1 -#warning // need to find a place for this define #ifdef JMS_QUAD arm_copy_f32(ADC_RX_Q.readBuffer(), &float_buffer_L[BUFFER_SIZE * i], BUFFER_SIZE); // move input buffer as float 32bit. BUFFER_SIZE = 128. arm_copy_f32(ADC_RX_I.readBuffer(), &float_buffer_R[BUFFER_SIZE * i], BUFFER_SIZE); // move input buffer as float 32bit. BUFFER_SIZE = 128. @@ -1232,10 +1230,10 @@ void TxCalibrate::MakeFFTData() { ADC_RX_I.freeBuffer(); ADC_RX_Q.freeBuffer(); } - rfGainValue = pow(10, static_cast(ConfigData.rfGain[ConfigData.currentBand]) / 20); //AFP 2-11-23 - arm_scale_f32(float_buffer_L, rfGainValue, float_buffer_L, 2048); //AFP 2-11-23 - arm_scale_f32(float_buffer_R, rfGainValue, float_buffer_R, 2048); //AFP 2-11-23 + + arm_scale_f32(float_buffer_L, rfGainValue, float_buffer_L, BUFFER_SIZE * N_BLOCKS); //AFP 2-11-23 + arm_scale_f32(float_buffer_R, rfGainValue, float_buffer_R, BUFFER_SIZE * N_BLOCKS); //AFP 2-11-23 // Manual IQ amplitude and phase correction (receive only). if (mode == 0) { @@ -1266,7 +1264,7 @@ void TxCalibrate::MakeFFTData() { // This process started because there are 2048 samples available. Perform FFT. updateDisplayFlag = true; - if (fftActive) ZoomFFTExe(2048); + if (fftActive) ZoomFFTExe(BUFFER_SIZE * N_BLOCKS); fftSuccess = true; } // End of receive code else { From 7ad1df4560910aa962aa677b5cc9430896abe44a Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Mon, 20 Jul 2026 08:07:46 +0100 Subject: [PATCH 07/14] TX/RX switching works Needs Tidying up --- T41EEE/AudioSignal.h | 56 ++++++++++++++++++++++++++++-------- T41EEE/MyConfigurationFile.h | 2 +- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/T41EEE/AudioSignal.h b/T41EEE/AudioSignal.h index 1602a59..6c62339 100644 --- a/T41EEE/AudioSignal.h +++ b/T41EEE/AudioSignal.h @@ -7,6 +7,11 @@ AudioSettings_F32 audio_settings(sample_rate_Hz, audio_block_samples); #define JMS_QUAD 1 #ifdef JMS_QUAD AudioInputI2SQuad_F32 i2s_quadIn_f32(audio_settings); // 4 inputs available in experimental Open Audio library. Ussing Terrane's code +#warning new stuff +#if 1 +AudioSwitch4_OA_F32 switchMicMute(audio_settings); //Switch Mic between bitBucket and Normal +AudioRecordQueue_F32 micBitBucketL(audio_settings); //DataSink when Mic not in use +#endif #else AudioInputI2SQuad i2s_quadIn; // 4 inputs available only in Teensy audio and not Open Audio library. #endif @@ -44,7 +49,14 @@ AudioPlayQueue_F32 cwToneData; // The tone from the CW Exciter. // Begin transmit signal chain. #ifdef JMS_QUAD //don't need the int2float object so just connect input straight to mixer +#warning new stuff +#if 1 +AudioConnection_F32 connect31(i2s_quadIn_f32, 0, switchMicMute, 0); +AudioConnection_F32 connect3(switchMicMute, 0, mixer1_tx, 0); +AudioConnection_F32 connect32(switchMicMute, 1, micBitBucketL, 0); +#else AudioConnection_F32 connect3(i2s_quadIn_f32, 0, mixer1_tx, 0); // Connect microphone mixer1 output 0 via gain control. +#endif #else AudioConnection connect0(i2s_quadIn, 0, int2Float1_tx, 0); // Microphone audio channel. Must use int2Float because Open Audio does not have quad input. @@ -249,7 +261,6 @@ void SetAudioOperatingState(RadioState operatingState) { // Connect audio paths #ifdef JMS_QUAD // AudioConnection_F32 doesn't support connect/disconnect - // Instead the AudioRecordQueue_F32 discards any received data #else patchCord1.connect(); patchCord2.connect(); @@ -257,8 +268,10 @@ void SetAudioOperatingState(RadioState operatingState) { mixer5.gain(0, 1.0); // Connect receiver audio from DSP. mixer5.gain(1, 0); // Disconnect CW sidetone. #ifdef JMS_QUAD - // AudioConnection_F32 doesn't support connect/disconnect - // Instead the AudioRecordQueue_F32 discards any received data +#warning new stuff + //micBitBucketL.begin(); + //switchMicMute.setChannel(1); // Bypass tx audio chain straight to micBitBucket + switchMicMute.setChannel(1); #else connect0.disconnect(); // Disconnect microphone input data stream. #endif @@ -302,6 +315,7 @@ void SetAudioOperatingState(RadioState operatingState) { controlAudioOut(ConfigData.audioOut, true); // Mute all receiver audio. sgtl5000_1.unmuteLineout(); #ifdef JMS_QUAD +#warning new stuff // AudioConnection_F32 doesn't support connect/disconnect // Instead the AudioRecordQueue_F32 discards any received data #else @@ -312,7 +326,6 @@ void SetAudioOperatingState(RadioState operatingState) { mixer5.gain(1, 0); // Stop sidetone audio. #ifdef JMS_QUAD // AudioConnection_F32 doesn't support connect/disconnect - // Instead the AudioRecordQueue_F32 discards any received data #else connect0.connect(); // Connect microphone input data stream. #endif @@ -320,7 +333,12 @@ void SetAudioOperatingState(RadioState operatingState) { ADC_RX_I.clear(); ADC_RX_Q.end(); ADC_RX_Q.clear(); - +#ifdef JMS_QUAD +#warning new stuff + switchMicMute.setChannel(0); // Connect Mic to tx audio chain + //micBitBucketL.end();// Don't need micBitBucket +#endif + mixer1_tx.gain(0, 1); // microphone audio on. mixer1_tx.gain(1, 0); // testTone off. mixer_rxtx_I.gain(0, 1.0); // Connect transmitter back-end to Audio Adapter. @@ -351,8 +369,7 @@ void SetAudioOperatingState(RadioState operatingState) { Q_in_L_Ex.begin(); // I channel Microphone audio Q_in_R_Ex.begin(); // Q channel Microphone audio - - // Update equalizer. Update first 14 only. Last two are constant. + // Update equalizer. Update first 14 only. Last two are constant. for (int i = 0; i < 14; i = i + 1) dbBand1[i] = static_cast(ConfigData.equalizerXmt[i]); txEqualizer.equalizerNew(16, &fBand1[0], &dbBand1[0], 249, &equalizeCoeffs[0], 65.0f); @@ -367,7 +384,6 @@ void SetAudioOperatingState(RadioState operatingState) { sgtl5000_1.unmuteLineout(); #ifdef JMS_QUAD // AudioConnection_F32 doesn't support connect/disconnect - // Instead the AudioRecordQueue_F32 discards any received data #else patchCord1.connect(); patchCord2.connect(); @@ -392,8 +408,10 @@ void SetAudioOperatingState(RadioState operatingState) { mixer1_tx.gain(2, 0); // testTone 2 off. #ifdef JMS_QUAD +#warning new stuff // AudioConnection_F32 doesn't support connect/disconnect - // Instead the AudioRecordQueue_F32 discards any received data + //micBitBucketL.begin(); + switchMicMute.setChannel(1); // Bypass tx audio chain straight to micBitBucket #else connect0.disconnect(); // Disconnect microphone input data stream. #endif @@ -454,8 +472,10 @@ void SetAudioOperatingState(RadioState operatingState) { mixer5.gain(0, 0); // Stop receiver audio. mixer5.gain(1, 0); // Stop sidetone audio. #ifdef JMS_QUAD +#warning new stuff // AudioConnection_F32 doesn't support connect/disconnect - // Instead the AudioRecordQueue_F32 discards any received data + //micBitBucketL.begin(); + switchMicMute.setChannel(1); // Bypass tx audio chain straight to micBitBucket #else connect0.disconnect(); // Disconnect microphone input data stream. #endif @@ -505,6 +525,7 @@ void SetAudioOperatingState(RadioState operatingState) { Q_in_L_Ex.begin(); // I channel Microphone audio Q_in_R_Ex.begin(); // Q channel Microphone audio + // Update equalizer. Update first 14 only. Last two are constant. for (int i = 0; i < 14; i = i + 1) dbBand1[i] = ConfigData.equalizerXmt[i]; @@ -533,8 +554,10 @@ void SetAudioOperatingState(RadioState operatingState) { mixer5.gain(0, 0); // Disconnect receiver audio from DSP. mixer5.gain(1, 1.0); // Connect CW sidetone. #ifdef JMS_QUAD +#warning new stuff // AudioConnection_F32 doesn't support connect/disconnect - // Instead the AudioRecordQueue_F32 discards any received data + //micBitBucketL.begin(); + switchMicMute.setChannel(1); // Bypass tx audio chain straight to micBitBucket #else connect0.disconnect(); // Disconnect microphone input data stream. #endif @@ -583,6 +606,7 @@ void SetAudioOperatingState(RadioState operatingState) { Q_in_L_Ex.begin(); // I channel Microphone audio Q_in_R_Ex.begin(); // Q channel Microphone audio + // Speaker and headphones should be unmuted according to current audio out state for sidetone. controlAudioOut(ConfigData.audioOut, false); sgtl5000_1.unmuteLineout(); @@ -598,8 +622,10 @@ void SetAudioOperatingState(RadioState operatingState) { controlAudioOut(AudioState::MUTE_BOTH, true); // Mute all audio. sgtl5000_1.unmuteLineout(); #ifdef JMS_QUAD +#warning new stuff // AudioConnection_F32 doesn't support connect/disconnect - // Instead the AudioRecordQueue_F32 discards any received data + //micBitBucketL.begin(); + switchMicMute.setChannel(1); // Bypass tx audio chain straight to micBitBucket #else connect0.disconnect(); // Disconnect microphone input data stream. #endif @@ -644,8 +670,11 @@ void SetAudioOperatingState(RadioState operatingState) { } #ifdef JMS_QUAD +#warning new stuff // AudioConnection_F32 doesn't support connect/disconnect // Instead the AudioRecordQueue_F32 discards any received data + //micBitBucketL.begin(); + switchMicMute.setChannel(1); // Bypass tx audio chain straight to micBitBucket #else patchCord1.connect(); patchCord2.connect(); @@ -689,8 +718,11 @@ void SetAudioOperatingState(RadioState operatingState) { mixer_rxtx_I.gain(1, 0.0); // Disconnect headphone path to Audio Adapter. mixer_rxtx_Q.gain(1, 0.0); #ifdef JMS_QUAD +#warning new stuff // AudioConnection_F32 doesn't support connect/disconnect // Instead the AudioRecordQueue_F32 discards any received data + //micBitBucketL.begin(); + switchMicMute.setChannel(1); // Bypass tx audio chain straight to micBitBucket #else patchCord1.connect(); patchCord2.connect(); diff --git a/T41EEE/MyConfigurationFile.h b/T41EEE/MyConfigurationFile.h index d9b00bc..355feaf 100644 --- a/T41EEE/MyConfigurationFile.h +++ b/T41EEE/MyConfigurationFile.h @@ -10,7 +10,7 @@ const int RIGNAME_X_OFFSET = 570; // Pixel count to rig name field. //#define DEBUG_SWITCH_CAL // Uncomment to run switch cal by pushing and holding a button at power-up. // Debug switch cal must be disabled for normal radio operation! //#define DEBUG_CESSB // Uncomment to get CESSB operating parameters printed to the serial monitor. -//#define LOOP_TIMER +#define LOOP_TIMER #define FAST_TUNE // Uncomment to activate variable speed fast tune by Harry GM3RVL. #define DEFAULT_KEYER_WPM 15 // Startup value for keyer wpm #define FREQ_SEP_CHARACTER '.' // Some may prefer period, space, or combo From 13b4acaa1a9102730d151f406fb8c9eadad0a9be Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Mon, 20 Jul 2026 08:18:21 +0100 Subject: [PATCH 08/14] Tidyup comments bitBucket can run all the time it will just discard anything it receives. --- T41EEE/AudioSignal.h | 44 +++++++------------------------------------- 1 file changed, 7 insertions(+), 37 deletions(-) diff --git a/T41EEE/AudioSignal.h b/T41EEE/AudioSignal.h index 6c62339..f0b6036 100644 --- a/T41EEE/AudioSignal.h +++ b/T41EEE/AudioSignal.h @@ -6,12 +6,10 @@ const int audio_block_samples = 128; // Always 128 AudioSettings_F32 audio_settings(sample_rate_Hz, audio_block_samples); #define JMS_QUAD 1 #ifdef JMS_QUAD -AudioInputI2SQuad_F32 i2s_quadIn_f32(audio_settings); // 4 inputs available in experimental Open Audio library. Ussing Terrane's code -#warning new stuff -#if 1 -AudioSwitch4_OA_F32 switchMicMute(audio_settings); //Switch Mic between bitBucket and Normal -AudioRecordQueue_F32 micBitBucketL(audio_settings); //DataSink when Mic not in use -#endif +AudioInputI2SQuad_F32 i2s_quadIn_f32(audio_settings); // 4 inputs available in experimental Open Audio library. Ussing Terrane's code +AudioSwitch4_OA_F32 switchMicMute(audio_settings); //Switch Mic between bitBucket and Normal +AudioRecordQueue_F32 micBitBucketL(audio_settings); //DataSink when Mic not in use + #else AudioInputI2SQuad i2s_quadIn; // 4 inputs available only in Teensy audio and not Open Audio library. #endif @@ -48,15 +46,11 @@ AudioPlayQueue_F32 cwToneData; // The tone from the CW Exciter. // Begin transmit signal chain. #ifdef JMS_QUAD -//don't need the int2float object so just connect input straight to mixer -#warning new stuff -#if 1 +//don't need the int2float object so just connect input via mute mixer AudioConnection_F32 connect31(i2s_quadIn_f32, 0, switchMicMute, 0); AudioConnection_F32 connect3(switchMicMute, 0, mixer1_tx, 0); AudioConnection_F32 connect32(switchMicMute, 1, micBitBucketL, 0); -#else -AudioConnection_F32 connect3(i2s_quadIn_f32, 0, mixer1_tx, 0); // Connect microphone mixer1 output 0 via gain control. -#endif + #else AudioConnection connect0(i2s_quadIn, 0, int2Float1_tx, 0); // Microphone audio channel. Must use int2Float because Open Audio does not have quad input. @@ -269,9 +263,7 @@ void SetAudioOperatingState(RadioState operatingState) { mixer5.gain(1, 0); // Disconnect CW sidetone. #ifdef JMS_QUAD #warning new stuff - //micBitBucketL.begin(); - //switchMicMute.setChannel(1); // Bypass tx audio chain straight to micBitBucket - switchMicMute.setChannel(1); + switchMicMute.setChannel(1);// Bypass tx audio chain, mic straight to micBitBucket #else connect0.disconnect(); // Disconnect microphone input data stream. #endif @@ -315,9 +307,7 @@ void SetAudioOperatingState(RadioState operatingState) { controlAudioOut(ConfigData.audioOut, true); // Mute all receiver audio. sgtl5000_1.unmuteLineout(); #ifdef JMS_QUAD -#warning new stuff // AudioConnection_F32 doesn't support connect/disconnect - // Instead the AudioRecordQueue_F32 discards any received data #else patchCord1.disconnect(); // Receiver I channel patchCord2.disconnect(); // Receiver Q channel @@ -336,7 +326,6 @@ void SetAudioOperatingState(RadioState operatingState) { #ifdef JMS_QUAD #warning new stuff switchMicMute.setChannel(0); // Connect Mic to tx audio chain - //micBitBucketL.end();// Don't need micBitBucket #endif mixer1_tx.gain(0, 1); // microphone audio on. @@ -408,9 +397,7 @@ void SetAudioOperatingState(RadioState operatingState) { mixer1_tx.gain(2, 0); // testTone 2 off. #ifdef JMS_QUAD -#warning new stuff // AudioConnection_F32 doesn't support connect/disconnect - //micBitBucketL.begin(); switchMicMute.setChannel(1); // Bypass tx audio chain straight to micBitBucket #else connect0.disconnect(); // Disconnect microphone input data stream. @@ -464,7 +451,6 @@ void SetAudioOperatingState(RadioState operatingState) { sgtl5000_1.unmuteLineout(); #ifdef JMS_QUAD // AudioConnection_F32 doesn't support connect/disconnect - // Instead the AudioRecordQueue_F32 discards any received data #else patchCord1.disconnect(); // Receiver I channel patchCord2.disconnect(); // Receiver Q channel @@ -472,9 +458,7 @@ void SetAudioOperatingState(RadioState operatingState) { mixer5.gain(0, 0); // Stop receiver audio. mixer5.gain(1, 0); // Stop sidetone audio. #ifdef JMS_QUAD -#warning new stuff // AudioConnection_F32 doesn't support connect/disconnect - //micBitBucketL.begin(); switchMicMute.setChannel(1); // Bypass tx audio chain straight to micBitBucket #else connect0.disconnect(); // Disconnect microphone input data stream. @@ -546,7 +530,6 @@ void SetAudioOperatingState(RadioState operatingState) { // QSD disabled and disconnected #ifdef JMS_QUAD // AudioConnection_F32 doesn't support connect/disconnect - // Instead the AudioRecordQueue_F32 discards any received data #else patchCord1.disconnect(); // Receiver I channel patchCord2.disconnect(); // Receiver Q channel @@ -554,9 +537,6 @@ void SetAudioOperatingState(RadioState operatingState) { mixer5.gain(0, 0); // Disconnect receiver audio from DSP. mixer5.gain(1, 1.0); // Connect CW sidetone. #ifdef JMS_QUAD -#warning new stuff - // AudioConnection_F32 doesn't support connect/disconnect - //micBitBucketL.begin(); switchMicMute.setChannel(1); // Bypass tx audio chain straight to micBitBucket #else connect0.disconnect(); // Disconnect microphone input data stream. @@ -623,8 +603,6 @@ void SetAudioOperatingState(RadioState operatingState) { sgtl5000_1.unmuteLineout(); #ifdef JMS_QUAD #warning new stuff - // AudioConnection_F32 doesn't support connect/disconnect - //micBitBucketL.begin(); switchMicMute.setChannel(1); // Bypass tx audio chain straight to micBitBucket #else connect0.disconnect(); // Disconnect microphone input data stream. @@ -670,10 +648,6 @@ void SetAudioOperatingState(RadioState operatingState) { } #ifdef JMS_QUAD -#warning new stuff - // AudioConnection_F32 doesn't support connect/disconnect - // Instead the AudioRecordQueue_F32 discards any received data - //micBitBucketL.begin(); switchMicMute.setChannel(1); // Bypass tx audio chain straight to micBitBucket #else patchCord1.connect(); @@ -718,10 +692,6 @@ void SetAudioOperatingState(RadioState operatingState) { mixer_rxtx_I.gain(1, 0.0); // Disconnect headphone path to Audio Adapter. mixer_rxtx_Q.gain(1, 0.0); #ifdef JMS_QUAD -#warning new stuff - // AudioConnection_F32 doesn't support connect/disconnect - // Instead the AudioRecordQueue_F32 discards any received data - //micBitBucketL.begin(); switchMicMute.setChannel(1); // Bypass tx audio chain straight to micBitBucket #else patchCord1.connect(); From e7a8406409ff8529800532e989c918bf4988cb43 Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Mon, 20 Jul 2026 16:11:28 +0100 Subject: [PATCH 09/14] Try to get TX Calibrate to work I think the audio pipeline stalls if this is not running so give it a try. Untested --- T41EEE/AudioSignal.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/T41EEE/AudioSignal.h b/T41EEE/AudioSignal.h index f0b6036..742e5e5 100644 --- a/T41EEE/AudioSignal.h +++ b/T41EEE/AudioSignal.h @@ -262,7 +262,6 @@ void SetAudioOperatingState(RadioState operatingState) { mixer5.gain(0, 1.0); // Connect receiver audio from DSP. mixer5.gain(1, 0); // Disconnect CW sidetone. #ifdef JMS_QUAD -#warning new stuff switchMicMute.setChannel(1);// Bypass tx audio chain, mic straight to micBitBucket #else connect0.disconnect(); // Disconnect microphone input data stream. @@ -324,7 +323,6 @@ void SetAudioOperatingState(RadioState operatingState) { ADC_RX_Q.end(); ADC_RX_Q.clear(); #ifdef JMS_QUAD -#warning new stuff switchMicMute.setChannel(0); // Connect Mic to tx audio chain #endif @@ -398,7 +396,9 @@ void SetAudioOperatingState(RadioState operatingState) { #ifdef JMS_QUAD // AudioConnection_F32 doesn't support connect/disconnect - switchMicMute.setChannel(1); // Bypass tx audio chain straight to micBitBucket + //switchMicMute.setChannel(1); // Bypass tx audio chain straight to micBitBucket + switchMicMute.setChannel(0); // May need tx audio chain to be running so tones are generated??? + #else connect0.disconnect(); // Disconnect microphone input data stream. #endif @@ -602,7 +602,6 @@ void SetAudioOperatingState(RadioState operatingState) { controlAudioOut(AudioState::MUTE_BOTH, true); // Mute all audio. sgtl5000_1.unmuteLineout(); #ifdef JMS_QUAD -#warning new stuff switchMicMute.setChannel(1); // Bypass tx audio chain straight to micBitBucket #else connect0.disconnect(); // Disconnect microphone input data stream. From 01d3d9b24772e0c051a0f555caf440c170bfc466 Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Mon, 3 Aug 2026 13:05:39 +0100 Subject: [PATCH 10/14] Move warning so its more useful --- T41EEE/SDT.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/T41EEE/SDT.h b/T41EEE/SDT.h index 82241c7..9dd3310 100644 --- a/T41EEE/SDT.h +++ b/T41EEE/SDT.h @@ -550,8 +550,8 @@ extern int32_t NCOFreq; // AFP 04-16-22 // Teensy and OpenAudio objects which need to be global. Revised by KF5N July 24, 2024 extern AudioAmplifier volumeAdjust; #define JMS_QUAD 1 -#warning // need to find a place for this define #ifdef JMS_QUAD +#warning JMS_QUAD enabled extern AudioRecordQueue_F32 ADC_RX_I; // Receiver I channel from ADC PCM1808, 32 bit. extern AudioRecordQueue_F32 ADC_RX_Q; // Receiver Q channel from ADC PCM1808, 32 bit. #else From 0444a036de62963ab2981e7e521f5687ecb68545 Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Tue, 4 Aug 2026 10:31:17 +0100 Subject: [PATCH 11/14] Reordering many things makes it work This seems to do a TX Calibrate now. I re-ordered the startup and made sure that MakeFFTData doesn't return until it has a full RX buffer. I notice that during the first few frames we get two Rx frames and One Tx frame and then it is Tx/RX alternating so this may have been the problem originally - just takes a while to get into lockstep? The calls seem to happen to fast to this function before and it would send several error messages before the buffers were full. This maybe because its running at 48kHz so will take longer to fill the buffers c/w RxCalibrate which runs at 192kHz TODO: Remove Bit Bucket and isolate change that actually does makes it work. Also add #defines around changes. Also remove T/R printfs? --- T41EEE/AudioSignal.h | 16 ++++++++++------ T41EEE/TxCalibrate.cpp | 32 +++++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/T41EEE/AudioSignal.h b/T41EEE/AudioSignal.h index 742e5e5..eee095b 100644 --- a/T41EEE/AudioSignal.h +++ b/T41EEE/AudioSignal.h @@ -364,7 +364,7 @@ void SetAudioOperatingState(RadioState operatingState) { break; - case RadioState::SSB_CALIBRATE_STATE: + case RadioState::SSB_CALIBRATE_STATE:// TRANSMIT SampleRate = SAMPLE_RATE_48K; InitializeDataArrays(); // I2S sample rate set in this function. controlAudioOut(AudioState::MUTE_BOTH, true); // Mute all audio. @@ -381,6 +381,11 @@ void SetAudioOperatingState(RadioState operatingState) { ADC_RX_I.clear(); ADC_RX_Q.end(); ADC_RX_Q.clear(); + // Just stop everything This changes behaviour + Q_in_L_Ex.end(); // Transmit I channel path. + Q_in_R_Ex.end(); // Transmit Q channel path. + Q_in_L_Ex.clear(); + Q_in_R_Ex.clear(); cessb1.setSampleRate_Hz(48000); //// @@ -428,18 +433,17 @@ void SetAudioOperatingState(RadioState operatingState) { mixer2_tx.gain(1, 1.0); } - Q_out_L_Ex.setBehaviour(AudioPlayQueue_F32::ORIGINAL); // Need this as CW will put into wrong mode. Greg KF5N August 4, 2024. - Q_out_R_Ex.setBehaviour(AudioPlayQueue_F32::ORIGINAL); Q_in_L_Ex.begin(); // I channel Microphone audio Q_in_R_Ex.begin(); // Q channel Microphone audio - ADC_RX_I.begin(); // Calibration is full duplex! Activate receiver data. No demodulation during calibrate, spectrum only. - ADC_RX_Q.begin(); - + Q_out_L_Ex.setBehaviour(AudioPlayQueue_F32::ORIGINAL); // Need this as CW will put into wrong mode. Greg KF5N August 4, 2024. + Q_out_R_Ex.setBehaviour(AudioPlayQueue_F32::ORIGINAL); // Update equalizer. Update first 14 only. Last two are constant. for (int i = 0; i < 14; i = i + 1) dbBand1[i] = ConfigData.equalizerXmt[i]; txEqualizer.equalizerNew(16, &fBand1[0], &dbBand1[0], 249, &equalizeCoeffs[0], 65.0f); updateMic(); + ADC_RX_I.begin(); // Calibration is full duplex! Activate receiver data. No demodulation during calibrate, spectrum only. + ADC_RX_Q.begin(); break; diff --git a/T41EEE/TxCalibrate.cpp b/T41EEE/TxCalibrate.cpp index ae3417e..b7593a5 100644 --- a/T41EEE/TxCalibrate.cpp +++ b/T41EEE/TxCalibrate.cpp @@ -1148,10 +1148,17 @@ void TxCalibrate::MakeFFTData() { float32_t* iBuffer = nullptr; // I and Q pointers needed for one-time read of record queues. float32_t* qBuffer = nullptr; - + int32_t lAvailable ; + int32_t rAvailable; + int32_t iAvailable; + int32_t qAvailable; + int exit=0; + do {// Loop until we have a full RX buffer Send TX if available + lAvailable = Q_in_L_Ex.available(); + rAvailable = Q_in_R_Ex.available(); // Read incoming I and Q audio blocks from the SSB exciter. // Are there at least N_BLOCKS buffers in each channel available ? - if (static_cast(Q_in_L_Ex.available()) > 15 and static_cast(Q_in_R_Ex.available()) > 15) { + if ((lAvailable > 15) and (rAvailable > 15)) { for (unsigned i = 0; i < 16; i++) { iBuffer = Q_in_L_Ex.readBuffer(); @@ -1206,15 +1213,21 @@ void TxCalibrate::MakeFFTData() { Q_out_L_Ex.play(float_buffer_L_EX, dataWidth); // play it! This is the I channel from the Audio Adapter line out to QSE I input. Q_out_R_Ex.play(float_buffer_R_EX, dataWidth); // play it! This is the Q channel from the Audio Adapter line out to QSE Q input. + Serial.printf("T"); } else { - fftSuccess = false; // Not enough transmit data. - Serial.printf("Failed to get enough I and Q transmitter data!\n"); +// fftSuccess = false; // Not enough transmit data. +// Serial.printf("Failed to get enough I and Q transmitter data!\n"); +// TxCalibrate::flushTxBuffers(); +// Serial.printf("TX:%d\n",lAvailable); } // End of transmit code. Begin receive code. // Get audio samples from the audio buffers and convert them to float. // Read in 16 blocks of 128 samples in I and Q if available. - if (static_cast(ADC_RX_I.available()) > 15 && static_cast(ADC_RX_Q.available()) > 15) { + iAvailable = ADC_RX_I.available(); + qAvailable = ADC_RX_Q.available(); + + if ((iAvailable> 15) and (qAvailable > 15)) { for (unsigned i = 0; i < N_BLOCKS; i++) { /********************************************************************************** AFP 12-31-20 Using arm_Math library, convert to float one buffer_size. @@ -1266,11 +1279,16 @@ void TxCalibrate::MakeFFTData() { updateDisplayFlag = true; if (fftActive) ZoomFFTExe(BUFFER_SIZE * N_BLOCKS); fftSuccess = true; + exit=1; + Serial.printf("R"); } // End of receive code else { - fftSuccess = false; // Insufficient receive buffers to make FFT. Do not plot FFT data! - Serial.printf("FFT failed due to insufficient I and Q receive data!\n"); +// fftSuccess = false; // Insufficient receive buffers to make FFT. Do not plot FFT data! +// Serial.printf("FFT failed due to insufficient I and Q receive data!\n"); +// TxCalibrate::flushRxBuffers(); +// Serial.printf("RX:%d\n",iAvailable); } + } while(exit==0); } From 6845096d74d0a51bafcc3ed061999641d75bc2e3 Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Fri, 7 Aug 2026 09:44:17 +0100 Subject: [PATCH 12/14] Tidy up some of the debug Removed some hackery which wasn't needed and tidied up debug --- T41EEE/AudioSignal.h | 42 ++++++++++++++++++++++++++++++++++-------- T41EEE/TxCalibrate.cpp | 12 ++++++++---- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/T41EEE/AudioSignal.h b/T41EEE/AudioSignal.h index eee095b..454d561 100644 --- a/T41EEE/AudioSignal.h +++ b/T41EEE/AudioSignal.h @@ -1,3 +1,28 @@ +/* +T41EVE Copyright 2026 Gregory Raven + +This file is part of T41EVE. + +T41EVE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +T41EVE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with T41EVE. If not, see . + + This comment block must appear in the load page (e.g., main() or setup()) in any source code + that uses code presented as whole or part of the T41-EP source code. + + (c) Frank Dziock, DD4WH, 2020_05_8 + "TEENSY CONVOLUTION SDR" substantially modified by Jack Purdum, W8TEE, and Al Peter, AC8GY + + This software is made available under the GNU GPLv3 license agreement. If commercial use of this + software is planned, we would appreciate it if the interested parties contact Jack Purdum, W8TEE, + and Al Peter, AC8GY. + + Any and all other uses, written or implied, by the GPLv3 license are forbidden without written + permission from from Jack Purdum, W8TEE, and Al Peter, AC8GY. +*/ + // Teensy and Open Audio Signal Chains include file. // Common to Transmitter and Receiver. @@ -16,11 +41,10 @@ AudioInputI2SQuad i2s_quadIn; // 4 inputs available only in Teensy audio and no AudioOutputI2SQuad_F32 i2s_quadOut_f32(audio_settings); // Transmitter - AudioControlSGTL5000 sgtl5000_1; #ifdef JMS_QUAD // Controller for the Teensy Audio Adapter. //not neeeded float conversion done in AudioInputI2SQuad_F32 -#else +#else AudioConvert_I16toF32 int2Float1_tx; // Converts Int16 to Float. #endif AudioEffectGain_F32 micGain(audio_settings), compGainCompensate(audio_settings); // Microphone gain control. @@ -30,7 +54,7 @@ radioCESSB_Z_transmit_F32 cessb1; #ifdef JMS_QUAD //not neeeded float conversion done in AudioInputI2SQuad_F32 -#else +#else AudioConvert_F32toI16 float2Int1_tx, float2Int2_tx; // Converts Float to Int16. See class in AudioStream_F32.h #endif AudioSwitch4_OA_F32 switch3_tx, switch4_tx; @@ -381,12 +405,13 @@ void SetAudioOperatingState(RadioState operatingState) { ADC_RX_I.clear(); ADC_RX_Q.end(); ADC_RX_Q.clear(); +#ifdef JMS_QUAD // Just stop everything This changes behaviour Q_in_L_Ex.end(); // Transmit I channel path. Q_in_R_Ex.end(); // Transmit Q channel path. Q_in_L_Ex.clear(); Q_in_R_Ex.clear(); - +#endif cessb1.setSampleRate_Hz(48000); //// // Test tone enabled and connected @@ -433,17 +458,18 @@ void SetAudioOperatingState(RadioState operatingState) { mixer2_tx.gain(1, 1.0); } - Q_in_L_Ex.begin(); // I channel Microphone audio - Q_in_R_Ex.begin(); // Q channel Microphone audio Q_out_L_Ex.setBehaviour(AudioPlayQueue_F32::ORIGINAL); // Need this as CW will put into wrong mode. Greg KF5N August 4, 2024. Q_out_R_Ex.setBehaviour(AudioPlayQueue_F32::ORIGINAL); + Q_in_L_Ex.begin(); // I channel Microphone audio + Q_in_R_Ex.begin(); // Q channel Microphone audio + ADC_RX_I.begin(); // Calibration is full duplex! Activate receiver data. No demodulation during calibrate, spectrum only. + ADC_RX_Q.begin(); + // Update equalizer. Update first 14 only. Last two are constant. for (int i = 0; i < 14; i = i + 1) dbBand1[i] = ConfigData.equalizerXmt[i]; txEqualizer.equalizerNew(16, &fBand1[0], &dbBand1[0], 249, &equalizeCoeffs[0], 65.0f); updateMic(); - ADC_RX_I.begin(); // Calibration is full duplex! Activate receiver data. No demodulation during calibrate, spectrum only. - ADC_RX_Q.begin(); break; diff --git a/T41EEE/TxCalibrate.cpp b/T41EEE/TxCalibrate.cpp index b7593a5..773c10a 100644 --- a/T41EEE/TxCalibrate.cpp +++ b/T41EEE/TxCalibrate.cpp @@ -76,7 +76,11 @@ void TxCalibrate::warmUpCal() { arm_max_q15(pixelnew, 512, &rawSpectrumPeak, &index_of_max); if (index_of_max > 251 and index_of_max < 260) { // The peak is in the correct bin? count = count + 1; - } else count = 0; // Reset count in case of failure. + } //else count = 0; // Reset count in case of failure. + else { + count = 0; // Reset count in case of failure. +// Serial.printf("index_of_max:%d\n",index_of_max); + } if (count == 5) break; // If five in a row, exit the loop. Warm-up is complete. } updateDisplayFlag = true; @@ -85,9 +89,9 @@ void TxCalibrate::warmUpCal() { updateDisplayFlag = false; // Find peak of spectrum, which is 512 wide. Use this to adjust spectrum peak to top of spectrum display. arm_max_q15(pixelnew, 512, &rawSpectrumPeak, &index_of_max); - // Serial.printf("TX rawSpectrumPeak = %d count = %d i = %d\n", rawSpectrumPeak, count, i); - // Serial.printf("TX index_of_max = %d\n", index_of_max); - if (index_of_max < 251 or index_of_max > 260) Serial.printf("Problem with TX warmUpCal\n"); +// Serial.printf("TX rawSpectrumPeak = %d count = %d i = %d\n", rawSpectrumPeak, count, i); +// Serial.printf("TX index_of_max = %d\n", index_of_max); + if (index_of_max < 251 or index_of_max > 260) Serial.printf("Problem with TX warmUpCal index_of_max=%d\n",index_of_max); } From 96270e83f2932bae76e405e9fdd6e3ffbfde9b53 Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Fri, 7 Aug 2026 10:40:55 +0100 Subject: [PATCH 13/14] More Tidying up Pulled in some headers from main branch Made sure all my changes (not) bug fixes are in #defines --- T41EEE/AudioSignal.h | 12 ++------ T41EEE/Button.cpp | 30 ++++++++++++++++-- T41EEE/MyConfigurationFile.h | 25 +++++++++++++++ T41EEE/ReceiveDSP.cpp | 32 ++++++++++++++++--- T41EEE/RxCalibrate.cpp | 26 ++++++++++++++++ T41EEE/SDT.h | 46 +++++++++++++++++++++++++-- T41EEE/T41EEE.ino | 43 ++++++++++++++++++++++++-- T41EEE/TxCalibrate.cpp | 60 +++++++++++++++++++++++++++++++----- T41EEE/TxCalibrate.h | 25 +++++++++++++++ 9 files changed, 270 insertions(+), 29 deletions(-) diff --git a/T41EEE/AudioSignal.h b/T41EEE/AudioSignal.h index 454d561..a5d51f4 100644 --- a/T41EEE/AudioSignal.h +++ b/T41EEE/AudioSignal.h @@ -29,12 +29,10 @@ You should have received a copy of the GNU General Public License along with T41 const float sample_rate_Hz = 48000.0; // The transmitter operates at 48ksps. const int audio_block_samples = 128; // Always 128 AudioSettings_F32 audio_settings(sample_rate_Hz, audio_block_samples); -#define JMS_QUAD 1 #ifdef JMS_QUAD AudioInputI2SQuad_F32 i2s_quadIn_f32(audio_settings); // 4 inputs available in experimental Open Audio library. Ussing Terrane's code AudioSwitch4_OA_F32 switchMicMute(audio_settings); //Switch Mic between bitBucket and Normal AudioRecordQueue_F32 micBitBucketL(audio_settings); //DataSink when Mic not in use - #else AudioInputI2SQuad i2s_quadIn; // 4 inputs available only in Teensy audio and not Open Audio library. #endif @@ -74,7 +72,6 @@ AudioPlayQueue_F32 cwToneData; // The tone from the CW Exciter. AudioConnection_F32 connect31(i2s_quadIn_f32, 0, switchMicMute, 0); AudioConnection_F32 connect3(switchMicMute, 0, mixer1_tx, 0); AudioConnection_F32 connect32(switchMicMute, 1, micBitBucketL, 0); - #else AudioConnection connect0(i2s_quadIn, 0, int2Float1_tx, 0); // Microphone audio channel. Must use int2Float because Open Audio does not have quad input. @@ -141,7 +138,6 @@ AudioConnection patchCord1(i2s_quadIn, 3, ADC_RX_I, 0); // Receiver I and Q cha AudioConnection patchCord2(i2s_quadIn, 2, ADC_RX_Q, 0); // This data stream goes to sketch code for processing. #endif - AudioConnection_F32 patchCord3(audioOutQueue, 0, mixer5, 0); // mixer5 selects receiver or CW sidetone audio. AudioConnection_F32 patchCord35(sidetoneOutQueue, 0, mixer5, 1); @@ -396,8 +392,8 @@ void SetAudioOperatingState(RadioState operatingState) { #ifdef JMS_QUAD // AudioConnection_F32 doesn't support connect/disconnect #else - patchCord1.connect(); - patchCord2.connect(); + patchCord1.connect(); // Receiver I channel + patchCord2.connect(); // Receiver Q channel #endif mixer5.gain(0, 0); // Stop receiver audio. mixer5.gain(1, 0); // Stop sidetone audio. @@ -539,7 +535,6 @@ void SetAudioOperatingState(RadioState operatingState) { Q_in_L_Ex.begin(); // I channel Microphone audio Q_in_R_Ex.begin(); // Q channel Microphone audio - // Update equalizer. Update first 14 only. Last two are constant. for (int i = 0; i < 14; i = i + 1) dbBand1[i] = ConfigData.equalizerXmt[i]; @@ -616,7 +611,6 @@ void SetAudioOperatingState(RadioState operatingState) { Q_in_L_Ex.begin(); // I channel Microphone audio Q_in_R_Ex.begin(); // Q channel Microphone audio - // Speaker and headphones should be unmuted according to current audio out state for sidetone. controlAudioOut(ConfigData.audioOut, false); sgtl5000_1.unmuteLineout(); @@ -679,7 +673,7 @@ void SetAudioOperatingState(RadioState operatingState) { #ifdef JMS_QUAD switchMicMute.setChannel(1); // Bypass tx audio chain straight to micBitBucket #else - patchCord1.connect(); + patchCord1.connect(); // Connect I and Q receiver data converters. patchCord2.connect(); #endif ADC_RX_I.begin(); // Calibration is full duplex! diff --git a/T41EEE/Button.cpp b/T41EEE/Button.cpp index 1b45cf4..416be08 100644 --- a/T41EEE/Button.cpp +++ b/T41EEE/Button.cpp @@ -1,3 +1,28 @@ +/* +T41EVE Copyright 2026 Gregory Raven + +This file is part of T41EVE. + +T41EVE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +T41EVE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with T41EVE. If not, see . + + This comment block must appear in the load page (e.g., main() or setup()) in any source code + that uses code presented as whole or part of the T41-EP source code. + + (c) Frank Dziock, DD4WH, 2020_05_8 + "TEENSY CONVOLUTION SDR" substantially modified by Jack Purdum, W8TEE, and Al Peter, AC8GY + + This software is made available under the GNU GPLv3 license agreement. If commercial use of this + software is planned, we would appreciate it if the interested parties contact Jack Purdum, W8TEE, + and Al Peter, AC8GY. + + Any and all other uses, written or implied, by the GPLv3 license are forbidden without written + permission from from Jack Purdum, W8TEE, and Al Peter, AC8GY. +*/ + // Button class #include "SDT.h" @@ -191,7 +216,7 @@ void Button::ExecuteButtonPress(MenuSelect val) { switch (val) { case MenuSelect::MENU_OPTION_SELECT: // 1 - + menucontrol.top = false; ShowMenu(&topMenus[mainMenuIndex], PRIMARY_MENU); functionPtr[mainMenuIndex](); // These are processed in MenuProcessing.cpp break; @@ -199,7 +224,7 @@ void Button::ExecuteButtonPress(MenuSelect val) { case MenuSelect::MAIN_MENU_UP: // 2 ButtonMenuIncrease(); ShowMenu(&topMenus[mainMenuIndex], PRIMARY_MENU); - + menucontrol.top = true; break; case MenuSelect::BAND_UP: // 3 @@ -213,6 +238,7 @@ void Button::ExecuteButtonPress(MenuSelect val) { case MenuSelect::MAIN_MENU_DN: // 5 ButtonMenuDecrease(); ShowMenu(&topMenus[mainMenuIndex], PRIMARY_MENU); + menucontrol.top = true; break; case MenuSelect::BAND_DN: // 6 diff --git a/T41EEE/MyConfigurationFile.h b/T41EEE/MyConfigurationFile.h index 355feaf..d543b3e 100644 --- a/T41EEE/MyConfigurationFile.h +++ b/T41EEE/MyConfigurationFile.h @@ -1,3 +1,28 @@ +/* +T41EVE Copyright 2026 Gregory Raven + +This file is part of T41EVE. + +T41EVE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +T41EVE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with T41EVE. If not, see . + + This comment block must appear in the load page (e.g., main() or setup()) in any source code + that uses code presented as whole or part of the T41-EP source code. + + (c) Frank Dziock, DD4WH, 2020_05_8 + "TEENSY CONVOLUTION SDR" substantially modified by Jack Purdum, W8TEE, and Al Peter, AC8GY + + This software is made available under the GNU GPLv3 license agreement. If commercial use of this + software is planned, we would appreciate it if the interested parties contact Jack Purdum, W8TEE, + and Al Peter, AC8GY. + + Any and all other uses, written or implied, by the GPLv3 license are forbidden without written + permission from from Jack Purdum, W8TEE, and Al Peter, AC8GY. +*/ + // User configuration file. #pragma once diff --git a/T41EEE/ReceiveDSP.cpp b/T41EEE/ReceiveDSP.cpp index 109f01f..6f27967 100644 --- a/T41EEE/ReceiveDSP.cpp +++ b/T41EEE/ReceiveDSP.cpp @@ -1,3 +1,28 @@ +/* +T41EVE Copyright 2026 Gregory Raven + +This file is part of T41EVE. + +T41EVE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +T41EVE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with T41EVE. If not, see . + + This comment block must appear in the load page (e.g., main() or setup()) in any source code + that uses code presented as whole or part of the T41-EP source code. + + (c) Frank Dziock, DD4WH, 2020_05_8 + "TEENSY CONVOLUTION SDR" substantially modified by Jack Purdum, W8TEE, and Al Peter, AC8GY + + This software is made available under the GNU GPLv3 license agreement. If commercial use of this + software is planned, we would appreciate it if the interested parties contact Jack Purdum, W8TEE, + and Al Peter, AC8GY. + + Any and all other uses, written or implied, by the GPLv3 license are forbidden without written + permission from from Jack Purdum, W8TEE, and Al Peter, AC8GY. +*/ + // Receive DSP. ProcessIQData is the primary DSP function of the receiver. #include "SDT.h" @@ -28,13 +53,14 @@ bool ReceiveDSP::ProcessIQData() { uint32_t AudioMaxIndex; float rfGainValue; int rfGain; +#ifdef JMS_QUAD /*Serial.printf("ADC_RX_I.available=%d ADC_RX_Q.available=%d \n", ADC_RX_I.available(), ADC_RX_Q.available() );*/ +#endif // Are there at least N_BLOCKS buffers in each channel available ? N_BLOCKS should be 16. Fill float_buffer_L/R[2048]. if (static_cast(ADC_RX_I.available()) > 15 && static_cast(ADC_RX_Q.available()) > 15) { usec = 0; - // Get audio samples from the audio buffers and convert them to float. // Read in 16 blocks and 128 samples in I and Q. 16 * 128 = 2048 (N_BLOCKS = 16) for (unsigned i = 0; i < N_BLOCKS; i++) { @@ -42,8 +68,6 @@ bool ReceiveDSP::ProcessIQData() { Using arm_Math library, convert to float one buffer_size. Float_buffer samples are now standardized from > -1.0 to < 1.0 **********************************************************************************/ -#define JMS_QUAD 1 -#warning // need to find a place for this define #ifdef JMS_QUAD arm_copy_f32(ADC_RX_Q.readBuffer(), &float_buffer_L[BUFFER_SIZE * i], BUFFER_SIZE); // move input buffer as float 32bit. BUFFER_SIZE = 128. arm_copy_f32(ADC_RX_I.readBuffer(), &float_buffer_R[BUFFER_SIZE * i], BUFFER_SIZE); // move input buffer as float 32bit. BUFFER_SIZE = 128. @@ -51,8 +75,6 @@ bool ReceiveDSP::ProcessIQData() { arm_q15_to_float(ADC_RX_Q.readBuffer(), &float_buffer_L[BUFFER_SIZE * i], BUFFER_SIZE); // convert int_buffer to float 32bit. BUFFER_SIZE = 128. arm_q15_to_float(ADC_RX_I.readBuffer(), &float_buffer_R[BUFFER_SIZE * i], BUFFER_SIZE); // convert int_buffer to float 32bit #endif - - ADC_RX_I.freeBuffer(); ADC_RX_Q.freeBuffer(); } // end for loop diff --git a/T41EEE/RxCalibrate.cpp b/T41EEE/RxCalibrate.cpp index 719870f..6d38133 100644 --- a/T41EEE/RxCalibrate.cpp +++ b/T41EEE/RxCalibrate.cpp @@ -1,3 +1,28 @@ +/* +T41EVE Copyright 2026 Gregory Raven + +This file is part of T41EVE. + +T41EVE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +T41EVE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with T41EVE. If not, see . + + This comment block must appear in the load page (e.g., main() or setup()) in any source code + that uses code presented as whole or part of the T41-EP source code. + + (c) Frank Dziock, DD4WH, 2020_05_8 + "TEENSY CONVOLUTION SDR" substantially modified by Jack Purdum, W8TEE, and Al Peter, AC8GY + + This software is made available under the GNU GPLv3 license agreement. If commercial use of this + software is planned, we would appreciate it if the interested parties contact Jack Purdum, W8TEE, + and Al Peter, AC8GY. + + Any and all other uses, written or implied, by the GPLv3 license are forbidden without written + permission from from Jack Purdum, W8TEE, and Al Peter, AC8GY. +*/ + // RxCalibrate class // Class extensively modified to perform receive calibration only. Greg KF5N August 2025 @@ -785,6 +810,7 @@ void RxCalibrate::MakeFFTData() { ADC_RX_I.freeBuffer(); ADC_RX_Q.freeBuffer(); } + rfGainValue = pow(10, (float)ConfigData.rfGain[ConfigData.currentBand] / 20); //AFP 2-11-23 arm_scale_f32(float_buffer_L, rfGainValue, float_buffer_L, BUFFER_SIZE * N_BLOCKS); //AFP 2-11-23 arm_scale_f32(float_buffer_R, rfGainValue, float_buffer_R, BUFFER_SIZE * N_BLOCKS); //AFP 2-11-23 diff --git a/T41EEE/SDT.h b/T41EEE/SDT.h index 9dd3310..8d36264 100644 --- a/T41EEE/SDT.h +++ b/T41EEE/SDT.h @@ -1,3 +1,28 @@ +/* +T41EVE Copyright 2026 Gregory Raven + +This file is part of T41EVE. + +T41EVE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +T41EVE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with T41EVE. If not, see . + + This comment block must appear in the load page (e.g., main() or setup()) in any source code + that uses code presented as whole or part of the T41-EP source code. + + (c) Frank Dziock, DD4WH, 2020_05_8 + "TEENSY CONVOLUTION SDR" substantially modified by Jack Purdum, W8TEE, and Al Peter, AC8GY + + This software is made available under the GNU GPLv3 license agreement. If commercial use of this + software is planned, we would appreciate it if the interested parties contact Jack Purdum, W8TEE, + and Al Peter, AC8GY. + + Any and all other uses, written or implied, by the GPLv3 license are forbidden without written + permission from from Jack Purdum, W8TEE, and Al Peter, AC8GY. +*/ + // Includes and global variables. #pragma once @@ -32,6 +57,7 @@ constexpr int NUMBER_OF_SWITCHES = 18; // Number of push button switches. constexpr int TEMPMON_ROOMTEMP = 25.0; #define SD_CS BUILTIN_SDCARD // Works on T_3.6 and T_4.1 ... +#define JMS_QUAD 1 // Enables Float32 Input Object Needs latest version of OpenAudio_ArduinoLibrary //======================================== Symbolic constants ========================================================== @@ -271,6 +297,18 @@ enum class MenuSelect { MENU_OPTION_SELECT, BEARING, BOGUS_PIN_READ, DEFAULT }; + +// Menu functions struct. This sets the current menu level. +// This was adapted from T41EVE. +struct menuControl +{ + bool top{false}; + bool CWOptions{false}; + bool subMenuSelect{false}; + bool runOptionFunction{false}; + bool runButtonFunction{false}; +}; +extern menuControl menucontrol; /* struct maps { char mapNames[50]; @@ -306,8 +344,11 @@ extern Bands bands; // Configuration data structure. struct config_t { - char versionSettings[10] = "E93_JMS1"; // This is required to be the first! - +#ifdef JMS_QUAD + char versionSettings[10] = "T41EQE.93"; // This is required to be the first! +#else + char versionSettings[10] = "T41EEE.93"; // This is required to be the first! +#endif bool AGCMode = true; float32_t AGCThreshold = -40.0; int speakerVolume = 30; @@ -549,7 +590,6 @@ extern int32_t NCOFreq; // AFP 04-16-22 // Teensy and OpenAudio objects which need to be global. Revised by KF5N July 24, 2024 extern AudioAmplifier volumeAdjust; -#define JMS_QUAD 1 #ifdef JMS_QUAD #warning JMS_QUAD enabled extern AudioRecordQueue_F32 ADC_RX_I; // Receiver I channel from ADC PCM1808, 32 bit. diff --git a/T41EEE/T41EEE.ino b/T41EEE/T41EEE.ino index fd50836..2ee963e 100644 --- a/T41EEE/T41EEE.ino +++ b/T41EEE/T41EEE.ino @@ -1,3 +1,28 @@ +/* +T41EVE Copyright 2026 Gregory Raven + +This file is part of T41EVE. + +T41EVE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +T41EVE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with T41EVE. If not, see . + + This comment block must appear in the load page (e.g., main() or setup()) in any source code + that uses code presented as whole or part of the T41-EP source code. + + (c) Frank Dziock, DD4WH, 2020_05_8 + "TEENSY CONVOLUTION SDR" substantially modified by Jack Purdum, W8TEE, and Al Peter, AC8GY + + This software is made available under the GNU GPLv3 license agreement. If commercial use of this + software is planned, we would appreciate it if the interested parties contact Jack Purdum, W8TEE, + and Al Peter, AC8GY. + + Any and all other uses, written or implied, by the GPLv3 license are forbidden without written + permission from from Jack Purdum, W8TEE, and Al Peter, AC8GY. +*/ + // T41 Transceiver Arduino Sketch: T41EEE // "T41 Extreme Experimenters Edition" // @@ -131,6 +156,7 @@ float32_t DMAMEM float_buffer_RTemp[2048]; //======================================== Global structure declarations =============================================== config_t ConfigData; calibration_t CalData; +menuControl menucontrol; Bands bands = { { // Revised band struct with mode and sideband. Greg KF5N February 14, 2025 // band low band hi name mode sideband FHiCut FLoCut FAMCut Gain type gain AGC @@ -874,9 +900,8 @@ FLASHMEM void setup() { Serial.begin(115200); // Check for CrashReport stored from previous run. - if (CrashReport) { - // print info (hope Serial Monitor windows is open) + /* print info (hope Serial Monitor windows is open) */ Serial.print(CrashReport); } @@ -1087,6 +1112,7 @@ void loop() { long ditTimerOff; //AFP 09-22-22 bool cwKeyDown; unsigned long cwBlockIndex; +#ifdef JMS_QUAD /* Serial.printf("lastState=%d radioState=%d memory_used=%d memory_used_max=%d f32_memory_used=%d f32_memory_used_max=%d\n", lastState, @@ -1096,6 +1122,7 @@ void loop() { (int)AudioStream_F32::f32_memory_used, (int)AudioStream_F32::f32_memory_used_max); */ +#endif // Radio state detection before entering the primary radio loop. if (bands.bands[ConfigData.currentBand].mode == RadioMode::SSB_MODE and digitalRead(PTT) == HIGH) radioState = RadioState::SSB_RECEIVE_STATE; if (bands.bands[ConfigData.currentBand].mode == RadioMode::SSB_MODE and digitalRead(PTT) == LOW) radioState = RadioState::SSB_TRANSMIT_STATE; @@ -1117,7 +1144,17 @@ void loop() { // SSB and FT8 transmit operate via the main loop(). CW modes operate within independent while loops. Don't stop in SSB and FT8 modes to read the buttons. if ((radioState != RadioState::SSB_TRANSMIT_STATE) and (radioState != RadioState::FT8_TRANSMIT_STATE) and (calibrateFlag == false) and (morseDecodeAdjustFlag == false)) { menu = readButton(); - if (menu != MenuSelect::BOGUS_PIN_READ) button.ExecuteButtonPress(menu); + // Restrict allowed button selections if in top menu. + if (menucontrol.top == true) + { + if ((menu != MenuSelect::BOGUS_PIN_READ) and (menu == MenuSelect::MAIN_MENU_UP or menu == MenuSelect::MAIN_MENU_DN or menu == MenuSelect::MENU_OPTION_SELECT)) + button.ExecuteButtonPress(menu); + } + else + { + if (menu != MenuSelect::BOGUS_PIN_READ) + button.ExecuteButtonPress(menu); + } } // Transition to new state if required and only if the radio state has changed. diff --git a/T41EEE/TxCalibrate.cpp b/T41EEE/TxCalibrate.cpp index 773c10a..e8a200e 100644 --- a/T41EEE/TxCalibrate.cpp +++ b/T41EEE/TxCalibrate.cpp @@ -1,3 +1,28 @@ +/* +T41EVE Copyright 2026 Gregory Raven + +This file is part of T41EVE. + +T41EVE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +T41EVE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with T41EVE. If not, see . + + This comment block must appear in the load page (e.g., main() or setup()) in any source code + that uses code presented as whole or part of the T41-EP source code. + + (c) Frank Dziock, DD4WH, 2020_05_8 + "TEENSY CONVOLUTION SDR" substantially modified by Jack Purdum, W8TEE, and Al Peter, AC8GY + + This software is made available under the GNU GPLv3 license agreement. If commercial use of this + software is planned, we would appreciate it if the interested parties contact Jack Purdum, W8TEE, + and Al Peter, AC8GY. + + Any and all other uses, written or implied, by the GPLv3 license are forbidden without written + permission from from Jack Purdum, W8TEE, and Al Peter, AC8GY. +*/ + // Class TxCalibrate. Greg KF5N July 10, 2024 // Re-factored August 2025. @@ -89,8 +114,8 @@ void TxCalibrate::warmUpCal() { updateDisplayFlag = false; // Find peak of spectrum, which is 512 wide. Use this to adjust spectrum peak to top of spectrum display. arm_max_q15(pixelnew, 512, &rawSpectrumPeak, &index_of_max); -// Serial.printf("TX rawSpectrumPeak = %d count = %d i = %d\n", rawSpectrumPeak, count, i); -// Serial.printf("TX index_of_max = %d\n", index_of_max); + // Serial.printf("TX rawSpectrumPeak = %d count = %d i = %d\n", rawSpectrumPeak, count, i); + // Serial.printf("TX index_of_max = %d\n", index_of_max); if (index_of_max < 251 or index_of_max > 260) Serial.printf("Problem with TX warmUpCal index_of_max=%d\n",index_of_max); } @@ -1152,6 +1177,8 @@ void TxCalibrate::MakeFFTData() { float32_t* iBuffer = nullptr; // I and Q pointers needed for one-time read of record queues. float32_t* qBuffer = nullptr; +#ifdef JMS_QUAD + // Make code a bit more readable and allow debug int32_t lAvailable ; int32_t rAvailable; int32_t iAvailable; @@ -1163,6 +1190,9 @@ void TxCalibrate::MakeFFTData() { // Read incoming I and Q audio blocks from the SSB exciter. // Are there at least N_BLOCKS buffers in each channel available ? if ((lAvailable > 15) and (rAvailable > 15)) { +#else + if (static_cast(Q_in_L_Ex.available()) > 15 and static_cast(Q_in_R_Ex.available()) > 15) { +#endif for (unsigned i = 0; i < 16; i++) { iBuffer = Q_in_L_Ex.readBuffer(); @@ -1219,19 +1249,27 @@ void TxCalibrate::MakeFFTData() { Q_out_R_Ex.play(float_buffer_R_EX, dataWidth); // play it! This is the Q channel from the Audio Adapter line out to QSE Q input. Serial.printf("T"); } else { +#ifdef JMS_QUAD // fftSuccess = false; // Not enough transmit data. // Serial.printf("Failed to get enough I and Q transmitter data!\n"); -// TxCalibrate::flushTxBuffers(); // Serial.printf("TX:%d\n",lAvailable); +#else + fftSuccess = false; // Not enough transmit data. + Serial.printf("Failed to get enough I and Q transmitter data!\n"); +#endif } // End of transmit code. Begin receive code. // Get audio samples from the audio buffers and convert them to float. // Read in 16 blocks of 128 samples in I and Q if available. +#ifdef JMS_QUAD iAvailable = ADC_RX_I.available(); qAvailable = ADC_RX_Q.available(); if ((iAvailable> 15) and (qAvailable > 15)) { +#else + if (static_cast(ADC_RX_I.available()) > 15 and static_cast(ADC_RX_Q.available()) > 15) { +#endif for (unsigned i = 0; i < N_BLOCKS; i++) { /********************************************************************************** AFP 12-31-20 Using arm_Math library, convert to float one buffer_size. @@ -1247,8 +1285,8 @@ void TxCalibrate::MakeFFTData() { ADC_RX_I.freeBuffer(); ADC_RX_Q.freeBuffer(); } - rfGainValue = pow(10, static_cast(ConfigData.rfGain[ConfigData.currentBand]) / 20); //AFP 2-11-23 + rfGainValue = pow(10, static_cast(ConfigData.rfGain[ConfigData.currentBand]) / 20); //AFP 2-11-23 arm_scale_f32(float_buffer_L, rfGainValue, float_buffer_L, BUFFER_SIZE * N_BLOCKS); //AFP 2-11-23 arm_scale_f32(float_buffer_R, rfGainValue, float_buffer_R, BUFFER_SIZE * N_BLOCKS); //AFP 2-11-23 @@ -1283,16 +1321,24 @@ void TxCalibrate::MakeFFTData() { updateDisplayFlag = true; if (fftActive) ZoomFFTExe(BUFFER_SIZE * N_BLOCKS); fftSuccess = true; - exit=1; +#ifdef JMS_QUAD + exit=1; // we have ebough RX data escape from do..while loop Serial.printf("R"); +#endif } // End of receive code else { +#ifdef JMS_QUAD // fftSuccess = false; // Insufficient receive buffers to make FFT. Do not plot FFT data! // Serial.printf("FFT failed due to insufficient I and Q receive data!\n"); -// TxCalibrate::flushRxBuffers(); // Serial.printf("RX:%d\n",iAvailable); +#else + fftSuccess = false; // Insufficient receive buffers to make FFT. Do not plot FFT data! + Serial.printf("FFT failed due to insufficient I and Q receive data!\n"); +#endif } - } while(exit==0); +#ifdef JMS_QUAD + } while(exit==0);// keep looping (FOREVER!!!!) until enough RX data received +#endif } diff --git a/T41EEE/TxCalibrate.h b/T41EEE/TxCalibrate.h index 6c7f258..a4540fd 100644 --- a/T41EEE/TxCalibrate.h +++ b/T41EEE/TxCalibrate.h @@ -1,3 +1,28 @@ +/* +T41EVE Copyright 2026 Gregory Raven + +This file is part of T41EVE. + +T41EVE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +T41EVE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with T41EVE. If not, see . + + This comment block must appear in the load page (e.g., main() or setup()) in any source code + that uses code presented as whole or part of the T41-EP source code. + + (c) Frank Dziock, DD4WH, 2020_05_8 + "TEENSY CONVOLUTION SDR" substantially modified by Jack Purdum, W8TEE, and Al Peter, AC8GY + + This software is made available under the GNU GPLv3 license agreement. If commercial use of this + software is planned, we would appreciate it if the interested parties contact Jack Purdum, W8TEE, + and Al Peter, AC8GY. + + Any and all other uses, written or implied, by the GPLv3 license are forbidden without written + permission from from Jack Purdum, W8TEE, and Al Peter, AC8GY. +*/ + // Transmit calibrate class. This calibrates both CW and SSB exciters. From d095d4be2549b333425f11d46645d7c39b2d4b4a Mon Sep 17 00:00:00 2001 From: Julia M Stephenson <52968628+julia-m-stephenson@users.noreply.github.com> Date: Fri, 7 Aug 2026 10:57:58 +0100 Subject: [PATCH 14/14] Removed BitBucket Removed BitBucket and TX/RX printf --- T41EEE/AudioSignal.h | 4 ++-- T41EEE/TxCalibrate.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/T41EEE/AudioSignal.h b/T41EEE/AudioSignal.h index a5d51f4..560018b 100644 --- a/T41EEE/AudioSignal.h +++ b/T41EEE/AudioSignal.h @@ -32,7 +32,7 @@ AudioSettings_F32 audio_settings(sample_rate_Hz, audio_block_samples); #ifdef JMS_QUAD AudioInputI2SQuad_F32 i2s_quadIn_f32(audio_settings); // 4 inputs available in experimental Open Audio library. Ussing Terrane's code AudioSwitch4_OA_F32 switchMicMute(audio_settings); //Switch Mic between bitBucket and Normal -AudioRecordQueue_F32 micBitBucketL(audio_settings); //DataSink when Mic not in use +//AudioRecordQueue_F32 micBitBucketL(audio_settings); //DataSink when Mic not in use #else AudioInputI2SQuad i2s_quadIn; // 4 inputs available only in Teensy audio and not Open Audio library. #endif @@ -71,7 +71,7 @@ AudioPlayQueue_F32 cwToneData; // The tone from the CW Exciter. //don't need the int2float object so just connect input via mute mixer AudioConnection_F32 connect31(i2s_quadIn_f32, 0, switchMicMute, 0); AudioConnection_F32 connect3(switchMicMute, 0, mixer1_tx, 0); -AudioConnection_F32 connect32(switchMicMute, 1, micBitBucketL, 0); +//AudioConnection_F32 connect32(switchMicMute, 1, micBitBucketL, 0); #else AudioConnection connect0(i2s_quadIn, 0, int2Float1_tx, 0); // Microphone audio channel. Must use int2Float because Open Audio does not have quad input. diff --git a/T41EEE/TxCalibrate.cpp b/T41EEE/TxCalibrate.cpp index e8a200e..e60c745 100644 --- a/T41EEE/TxCalibrate.cpp +++ b/T41EEE/TxCalibrate.cpp @@ -1247,7 +1247,7 @@ void TxCalibrate::MakeFFTData() { Q_out_L_Ex.play(float_buffer_L_EX, dataWidth); // play it! This is the I channel from the Audio Adapter line out to QSE I input. Q_out_R_Ex.play(float_buffer_R_EX, dataWidth); // play it! This is the Q channel from the Audio Adapter line out to QSE Q input. - Serial.printf("T"); +// Serial.printf("T"); } else { #ifdef JMS_QUAD // fftSuccess = false; // Not enough transmit data. @@ -1323,7 +1323,7 @@ void TxCalibrate::MakeFFTData() { fftSuccess = true; #ifdef JMS_QUAD exit=1; // we have ebough RX data escape from do..while loop - Serial.printf("R"); +// Serial.printf("R"); #endif } // End of receive code else {