Recovered lost ctcss/roger beep/correct mic gain in mic app from 1.5.1 without ALC (Auto mic Limit Control-AK) (#633)

* Update spectrum_collector.cpp

lower case correction

* Update spectrum_collector.cpp

Description changed , better explanation.

* Revert "Update spectrum_collector.cpp"

This reverts commit 4a6fc35384.

* Revert "Update spectrum_collector.cpp"

This reverts commit 35cece1cb0.

* Revert "Solving Compile error on gcc10 . Keeping same safety protection about the size of the array ,but with slightly different sintax."

This reverts commit f4db4e2b53.

* Recovered CTCSS-Roger_beep-MIC-GAIN from 1.5.1

* Temporary removing ALC-( for AK4951 platorm)
This commit is contained in:
Brumi-2021
2022-05-07 01:43:14 +02:00
committed by GitHub
parent c9db1aab30
commit 1027e80d53
13 changed files with 334 additions and 433 deletions

View File

@@ -21,6 +21,8 @@
#include "dsp_modulate.hpp"
#include "sine_table_int8.hpp"
#include "portapack_shared_memory.hpp"
#include "tonesets.hpp"
namespace dsp {
namespace modulate {
@@ -40,13 +42,42 @@ void Modulator::set_over(uint32_t new_over) {
over = new_over;
}
void Modulator::set_gain_vumeter_beep(float new_audio_gain , bool new_play_beep ) {
audio_gain = new_audio_gain ;
play_beep = new_play_beep;
}
int32_t Modulator::apply_beep(int32_t sample_in, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message ) {
if (play_beep) { // We need to add audio beep sample.
if (new_beep_timer) {
new_beep_timer--;
} else {
new_beep_timer = baseband_fs * 0.05; // 50ms
if (new_beep_index == BEEP_TONES_NB) {
configured_in = false;
shared_memory.application_queue.push(new_txprogress_message);
} else {
beep_gen.configure(beep_deltas[new_beep_index], 1.0); // config sequentially the audio beep tone.
new_beep_index++;
}
}
sample_in = beep_gen.process(0); // Get sample of the selected sequence of 6 beep tones , and overwrite audio sample. Mix 0%.
}
return sample_in; // Return audio mic scaled with gain , 8 bit sample or audio beep sample.
}
///
SSB::SSB() : hilbert() {
mode = Mode::LSB;
}
void SSB::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) {
void SSB::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer,TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ) {
// No way to activate correctly the roger beep in this option, Maybe not enough M4 CPU power , Let's block roger beep in SSB selection by now .
int32_t sample = 0;
int8_t re = 0, im = 0;
@@ -55,7 +86,9 @@ void SSB::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) {
float i = 0.0, q = 0.0;
sample = audio.p[counter / over] >> 2;
//switch (mode) {
sample *= audio_gain; // Apply GAIN Scale factor to the audio TX modulation.
//switch (mode) {
//case Mode::LSB:
hilbert.execute(sample / 32768.0f, i, q);
//case Mode::USB: hilbert.execute(sample / 32768.0f, q, i);
@@ -72,9 +105,23 @@ void SSB::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) {
//re = q;
//im = i;
//break;
}
buffer.p[counter] = { re, im };
// Update vu-meter bar in the LCD screen.
power_acc += (sample < 0) ? -sample : sample; // Power average for UI vu-meter
if (new_power_acc_count) {
new_power_acc_count--;
} else { // power_acc_count = 0
new_power_acc_count = new_divider;
new_level_message.value = power_acc / (new_divider *8); // Why ? . This division is to adj vu-meter sentitivity, to match saturation point to red-muter .
shared_memory.application_queue.push(new_level_message);
power_acc = 0;
}
}
}
@@ -88,15 +135,39 @@ void FM::set_fm_delta(uint32_t new_delta) {
fm_delta = new_delta;
}
void FM::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) {
void FM::set_tone_gen_configure(const uint32_t set_delta, const float set_tone_mix_weight) {
tone_gen.configure(set_delta, set_tone_mix_weight);
}
void FM::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ) {
int32_t sample = 0;
int8_t re, im;
for (size_t counter = 0; counter < buffer.count; counter++) {
if (counter % over == 0) {
sample = audio.p[counter / over] >> 8;
delta = sample * fm_delta;
}
sample = audio.p[counter>>6] >> 8; // sample = audio.p[counter / over] >> 8; (not enough efficient running code, over = 1536000/240000= 64 )
sample *= audio_gain; // Apply GAIN Scale factor to the audio TX modulation.
if (play_beep) {
sample = apply_beep(sample, configured_in, new_beep_index, new_beep_timer, new_txprogress_message ); // Apply beep -if selected - atom ,sample by sample.
} else {
// Update vu-meter bar in the LCD screen.
power_acc += (sample < 0) ? -sample : sample; // Power average for UI vu-meter
if (new_power_acc_count) {
new_power_acc_count--;
} else { // power_acc_count = 0
new_power_acc_count = new_divider;
new_level_message.value = power_acc / (new_divider / 4); // Why ? . This division is to adj vu-meter sentitivity, to match saturation point to red-muter .
shared_memory.application_queue.push(new_level_message);
power_acc = 0;
}
// TODO: pending to optimize CPU running code.
// So far , we can not handle all 3 issues at the same time (vu-meter , CTCSS, beep).
sample = tone_gen.process(sample); // Add selected Key_Tone or CTCSS subtone , atom function() , sample by sample.
}
delta = sample * fm_delta; // Modulate FM
phase += delta;
sphase = phase >> 24;
@@ -112,16 +183,33 @@ AM::AM() {
mode = Mode::AM;
}
void AM::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) {
void AM::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ) {
int32_t sample = 0;
int8_t re = 0, im = 0;
float q = 0.0;
float q = 0.0;
for (size_t counter = 0; counter < buffer.count; counter++) {
if (counter % 128 == 0) {
sample = audio.p[counter / over] >> 2;
sample *= audio_gain; // Apply GAIN Scale factor to the audio TX modulation.
}
if (play_beep) {
sample = apply_beep(sample, configured_in, new_beep_index, new_beep_timer, new_txprogress_message )<<5; // Apply beep -if selected - atom sample by sample.
} else {
// Update vu-meter bar in the LCD screen.
power_acc += (sample < 0) ? -sample : sample; // Power average for UI vu-meter
if (new_power_acc_count) {
new_power_acc_count--;
} else { // power_acc_count = 0
new_power_acc_count = new_divider;
new_level_message.value = power_acc / (new_divider *8); // Why ?orig / (new_divider / 4); // Why ?
shared_memory.application_queue.push(new_level_message);
power_acc = 0;
}
}
q = sample / 32768.0f;
q *= 256.0f; // Original 64.0f,now x4 (+12 dB's BB_modulation in AM & DSB)
switch (mode) {

View File

@@ -24,6 +24,8 @@
#include "dsp_types.hpp"
#include "dsp_hilbert.hpp"
#include "tone_gen.hpp"
#include "baseband_processor.hpp"
namespace dsp {
namespace modulate {
@@ -41,13 +43,28 @@ enum class Mode {
class Modulator {
public:
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) = 0;
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer,bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ) = 0;
virtual ~Modulator();
Mode get_mode();
void set_mode(Mode new_mode);
void set_over(uint32_t new_over);
void set_gain_vumeter_beep(float new_audio_gain , bool new_play_beep );
int32_t apply_beep(int32_t sample_in, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message );
float audio_gain { };
bool play_beep { false };
uint32_t power_acc_count { 0 }; // this var it is initialized from Proc_mictx.cpp
uint32_t divider { }; // this var it is initialized from Proc_mictx.cpp
uint64_t power_acc { 0 }; // it is aux Accumulated sum (Absolute sample signal) , initialitzed to zero.
AudioLevelReportMessage level_message { };
private:
static constexpr size_t baseband_fs = 1536000U;
TXProgressMessage txprogress_message { };
ToneGen beep_gen { };
uint32_t beep_index { }, beep_timer { };
protected:
uint32_t over = 1;
@@ -60,7 +77,7 @@ class SSB : public Modulator {
public:
SSB();
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer);
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider );
private:
dsp::HilbertTransform hilbert;
@@ -72,8 +89,9 @@ class FM : public Modulator {
public:
FM();
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer);
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ) ;
void set_fm_delta(uint32_t new_delta);
void set_tone_gen_configure(const uint32_t delta, const float tone_mix_weight);
///
@@ -81,13 +99,16 @@ private:
uint32_t fm_delta { 0 };
uint32_t phase { 0 }, sphase { 0 };
int32_t sample { 0 }, delta { };
ToneGen tone_gen { };
};
class AM : public Modulator {
public:
AM();
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer);
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider );
};
} /* namespace modulate */

View File

@@ -35,8 +35,10 @@ void MicTXProcessor::execute(const buffer_c8_t& buffer){
if (!configured) return;
audio_input.read_audio_buffer(audio_buffer);
modulator->execute(audio_buffer, buffer);
modulator->set_gain_vumeter_beep(audio_gain, play_beep ) ;
modulator->execute(audio_buffer, buffer, configured, beep_index, beep_timer, txprogress_message, level_message, power_acc_count, divider ); // Now "Key Tones & CTCSS" baseband additon inside FM mod. dsp_modulate.cpp"
/* Original fw 1.3.1 good reference, beep and vu-meter
for (size_t i = 0; i < buffer.count; i++) {
if (!play_beep) {
@@ -67,13 +69,13 @@ void MicTXProcessor::execute(const buffer_c8_t& buffer){
beep_index++;
}
}
sample = beep_gen.process(0);
}
/*
sample = beep_gen.process(0); // TODO : Pending how to move inside modulate.cpp
}
*/
/* Original fw 1.3.1 good reference FM moulation version, including "key tones CTCSS" fw 1.3.1
sample = tone_gen.process(sample);
// FM
if (configured) {
delta = sample * fm_delta;
@@ -89,8 +91,8 @@ void MicTXProcessor::execute(const buffer_c8_t& buffer){
}
buffer.p[i] = { re, im };
*/
}
} */
}
void MicTXProcessor::on_message(const Message* const msg) {
@@ -100,12 +102,16 @@ void MicTXProcessor::on_message(const Message* const msg) {
switch(msg->id) {
case Message::ID::AudioTXConfig:
if (fm_enabled) {
dsp::modulate::FM *fm = new dsp::modulate::FM();
fm->set_fm_delta(config_message.deviation_hz * (0xFFFFFFUL / baseband_fs));
dsp::modulate::FM *fm = new dsp::modulate::FM();
// Config fm_delta private var inside DSP modulate.cpp
fm->set_fm_delta(config_message.deviation_hz * (0xFFFFFFUL / baseband_fs));
// Config properly the private tone_gen function parameters inside DSP modulate.cpp
fm->set_tone_gen_configure(config_message.tone_key_delta, config_message.tone_key_mix_weight);
modulator = fm;
}
if (usb_enabled) {
modulator = new dsp::modulate::SSB();
modulator->set_mode(dsp::modulate::Mode::USB);
@@ -124,7 +130,7 @@ void MicTXProcessor::on_message(const Message* const msg) {
modulator->set_mode(dsp::modulate::Mode::DSB);
}
modulator->set_over(baseband_fs / 24000);
modulator->set_over(baseband_fs / 24000); // Keep no change.
am_enabled = config_message.am_enabled;
usb_enabled = config_message.usb_enabled;
@@ -137,8 +143,9 @@ void MicTXProcessor::on_message(const Message* const msg) {
audio_gain = config_message.audio_gain;
divider = config_message.divider;
power_acc_count = 0;
tone_gen.configure(config_message.tone_key_delta, config_message.tone_key_mix_weight);
// now this config moved, in the case Message::ID::AudioTXConfig , only FM case.
// tone_gen.configure(config_message.tone_key_delta, config_message.tone_key_mix_weight);
txprogress_message.done = true;

View File

@@ -49,8 +49,8 @@ private:
};
AudioInput audio_input { };
ToneGen tone_gen { };
ToneGen beep_gen { };
// ToneGen tone_gen { }; moved to dsp_modulate.cpp
// ToneGen beep_gen { }; moved to dsp_modulate.cpp
dsp::modulate::Modulator *modulator = NULL ;
bool am_enabled { false };

View File

@@ -103,27 +103,13 @@ void SpectrumCollector::post_message(const buffer_c16_t& data) {
}
}
/* 3 types of Windowing time domain shapes declaration , but only used Hamming , shapes for FFT
GCC10 compile sintax error c/m (1/2),
The primary diff. between const and constexpr variables is that
the initialization of a const var can be deferred until run time.
A constexpr var. must be initialized at compile time. ...
A var. can be declared with constexpr , when it has a literal type and is initialized.
GCC compile sintax error c/m (2/2)
Static assert --> Tests a software assertion at compile time for debugging.
we keep the same safety compile protection , just changing slightly the sintax checking that the size of the called array is power of 2.
if the bool "constant expression" is TRUE (normal case) , the declaration has no effect.
if the bool "constant expression" is FALSE (abnormal array size) , it is aborted the compile with a msg error.
*/
template<typename T> // Although currently we are not using that Windowing shape, we apply the same GCC10 compile error c/m
template<typename T>
static typename T::value_type spectrum_window_none(const T& s, const size_t i) {
static_assert(power_of_two(ARRAY_ELEMENTS(s)), "Array number of elements must be power of 2"); // c/m compile error GCC10 , OK for all GCC versions.
return s[i];
};
template<typename T> // Currently we are calling and using that Window shape.
template<typename T>
static typename T::value_type spectrum_window_hamming_3(const T& s, const size_t i) {
static_assert(power_of_two(ARRAY_ELEMENTS(s)), "Array number of elements must be power of 2"); // c/m compile error GCC10 , OK for all GCC versions.
const size_t mask = s.size() - 1; // c/m compile error GCC10 , constexpr->const
@@ -131,7 +117,7 @@ static typename T::value_type spectrum_window_hamming_3(const T& s, const size_t
return s[i] * 0.54f + (s[(i-1) & mask] + s[(i+1) & mask]) * -0.23f;
};
template<typename T> // Although currently we are not using that Windowing shape, we apply the same GCC10 compile error c/m
template<typename T>
static typename T::value_type spectrum_window_blackman_3(const T& s, const size_t i) {
static_assert(power_of_two(ARRAY_ELEMENTS(s)), "Array number of elements must be power of 2"); // c/m compile error GCC10 , OK for all GCC versions.
const size_t mask = s.size() - 1; // c/m compile error GCC10 , constexpr->const

View File

@@ -24,14 +24,20 @@
#include "sine_table_int8.hpp"
/*
int32_t ToneGen::tone_sine() {
// TODO : Added for Sonde App. We keep it by now , but it needs to be reviewed in Sonde
// Hoepfully we can manage without it , same as previous fw 1.3.1
int32_t tone_sample = sine_table_i8[tone_phase_] * 0x1000000;
tone_phase_ += delta_;
return tone_sample;
}
*/
int32_t ToneGen::tone_square() {
// TODO : Added for Sonde App. We keep it by now , but it needs to be reviewed in Sonde
int32_t tone_sample = 0;
if(tone_phase_ < (UINT32_MAX / 2)) {
@@ -46,33 +52,66 @@ int32_t ToneGen::tone_square() {
return tone_sample;
}
/*
void ToneGen::configure(const uint32_t delta, const float tone_mix_weight) {
// Confirmed ! It is not working well in the fw 1.4.4 Mic App , CTCSS generation, (but added for Sonde App)
// I Think it should be deleted or modified but not use it as it is in Mic App .
delta_ = (uint8_t) ((delta & 0xFF000000U) >> 24);
delta_ = delta;
tone_mix_weight_ = tone_mix_weight;
input_mix_weight_ = 1.0 - tone_mix_weight;
current_tone_type_ = sine;
}
*/
void ToneGen::configure(const uint32_t freq, const float tone_mix_weight, const tone_type tone_type, const uint32_t sample_rate) {
// TODO : Added for Sonde App. We keep it by now to avoid compile errors, but it needs to be reviewed in Sonde
delta_ = (uint8_t) ((freq * sizeof(sine_table_i8)) / sample_rate);
tone_mix_weight_ = tone_mix_weight;
input_mix_weight_ = 1.0 - tone_mix_weight;
current_tone_type_ = tone_type;
}
// ----Original available core SW code from fw 1.3.1 , Working also well in Mic App CTCSS Gen from fw 1.4.0 onwards
// Original direct-look-up synthesis algorithm with Fractional delta phase. It is OK
// Delta and Accumulator fase are stored in 32 bits (4 bytes), 1st top byte used as Modulo-256 Sine look-up table [index]
// the lower 3 bytes (24 bits) are used as a Fractional Detla and Accumulator phase, to have very finer Fstep control.
void ToneGen::configure(const uint32_t delta, const float tone_mix_weight) {
delta_ = delta;
tone_mix_weight_ = tone_mix_weight;
input_mix_weight_ = 1.0 - tone_mix_weight;
}
int32_t ToneGen::process(const int32_t sample_in) {
if (!delta_)
return sample_in;
int32_t tone_sample = 0;
if(current_tone_type_ == sine) {
tone_sample = tone_sine();
}
else if(current_tone_type_ == square) {
tone_sample = tone_square();
}
int32_t tone_sample = sine_table_i8[(tone_phase_ & 0xFF000000U) >> 24];
tone_phase_ += delta_;
return (sample_in * input_mix_weight_) + (tone_sample * tone_mix_weight_);
}
// -------------------------------------------------------------
int32_t ToneGen::process_square(const int32_t sample_in) {
// TODO : Added for Sonde App. We keep it by now , but it needs to be reviewed in Sonde
if (!delta_)
return sample_in;
int32_t tone_sample = 0;
tone_sample = tone_square();
return (sample_in * input_mix_weight_) + (tone_sample * tone_mix_weight_);
}

View File

@@ -28,7 +28,7 @@
class ToneGen {
public:
enum tone_type { sine, square };
enum tone_type { sine, square }; // TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not.
/*ToneGen(const size_t sample_rate
) : sample_rate_ { sample_rate }
@@ -38,6 +38,7 @@ public:
void configure(const uint32_t freq, const float tone_mix_weight, const tone_type tone_type, const uint32_t sample_rate);
int32_t process(const int32_t sample_in);
int32_t process_square(const int32_t sample_in);
private:
tone_type current_tone_type_ { sine };
@@ -45,19 +46,23 @@ private:
float input_mix_weight_ { 1 };
float tone_mix_weight_ { 0 };
uint8_t delta_ { 0 };
uint8_t tone_phase_ { 0 };
uint32_t delta_ { 0 };
uint32_t tone_phase_ { 0 };
// uint8_t delta_ { 0 }; // TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not.
// uint8_t tone_phase_ { 0 }; // TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not.
/**
* Generator function which selects every other sample from the reference sine waveform to the output sample:
*/
int32_t tone_sine();
int32_t tone_sine();// TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not.
/**
* Generator function for square waves:
*/
int32_t tone_square();
int32_t tone_square(); // TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not.
};
#endif /* __TONE_GEN_H__ */