Final opt. AM-9K, applied to Audio_RX and Mic App.

This commit is contained in:
Brumi-2021 2022-11-19 18:17:54 +01:00
parent 25dfa96257
commit 1e4c93b979
6 changed files with 63 additions and 55 deletions

View File

@ -53,12 +53,13 @@ private:
OptionsField options_config { OptionsField options_config {
{ 3 * 8, 0 * 16 }, { 3 * 8, 0 * 16 },
4, 5,
{ {
{ "DSB ", 0 }, { "DSB 9k ", 0 },
{ "USB ", 0 }, { "DSB 6k ", 0 },
{ "LSB ", 0 }, { "USB+3k ", 0 },
{ "CW ", 0 }, { "LSB-3k ", 0 },
{ "CW ", 0 },
} }
}; };
}; };

View File

@ -163,7 +163,7 @@ void MicTXView::rxaudio(bool is_on) {
baseband::run_image(portapack::spi_flash::image_tag_am_audio); baseband::run_image(portapack::spi_flash::image_tag_am_audio);
receiver_model.set_modulation(ReceiverModel::Mode::AMAudio); // that AM demodulation engine is common to all Amplitude mod : AM/USB/LSB/DSB (2,3,4,5) receiver_model.set_modulation(ReceiverModel::Mode::AMAudio); // that AM demodulation engine is common to all Amplitude mod : AM/USB/LSB/DSB (2,3,4,5)
if (options_mode.selected_index() < 5) // We will be called here with 2,3,4,5 . We treat here demod. filter 2,3,4; (excluding DSB-C case (5) it is treated more down). if (options_mode.selected_index() < 5) // We will be called here with 2,3,4,5 . We treat here demod. filter 2,3,4; (excluding DSB-C case (5) it is treated more down).
receiver_model.set_am_configuration(options_mode.selected_index() - 2); // selecting proper filter(2,3,4). 2-2=0=>6k-AM(0) , 3-2=1=>+3k-USB(1), 4-2=2=>-3K-LSB(2), receiver_model.set_am_configuration(options_mode.selected_index() - 1); // selecting proper filter(2,3,4). 2-1=1=>6k-AM(1) , 3-1=2=>+3k-USB(2), 4-1=3=>-3K-LSB(3),
} }
else { // We are in NFM/FM or WFM (NFM BW:8k5 or 11k / FM BW 16k / WFM BW:200k) else { // We are in NFM/FM or WFM (NFM BW:8k5 or 11k / FM BW 16k / WFM BW:200k)
@ -423,7 +423,8 @@ MicTXView::MicTXView(
set_dirty(); // Refresh display set_dirty(); // Refresh display
options_tone_key.hidden(1); // we hide that Key-tones & CTCSS input selecction, (no meaning in AM/DSB/SSB). options_tone_key.hidden(1); // we hide that Key-tones & CTCSS input selecction, (no meaning in AM/DSB/SSB).
rxbw.emplace_back(" 6k-AM ", 0); // locked a fixed option , to display it . rxbw.emplace_back(" DSB1-9k ", 0); // we offer in AM DSB two audio BW 9k / 6k .
rxbw.emplace_back(" DSB2-6k ", 1);
field_rxbw.set_options(rxbw); // store that aux GUI option to the field_rxbw. field_rxbw.set_options(rxbw); // store that aux GUI option to the field_rxbw.
field_rxbw.hidden(0); // we show fixed RX AM BW 6Khz field_rxbw.hidden(0); // we show fixed RX AM BW 6Khz
@ -436,7 +437,7 @@ MicTXView::MicTXView(
check_rogerbeep.set_value(false); // reset the possible activation of roger beep, because it is not compatible with SSB , by now. check_rogerbeep.set_value(false); // reset the possible activation of roger beep, because it is not compatible with SSB , by now.
check_rogerbeep.hidden(1); // hide that roger beep selection. check_rogerbeep.hidden(1); // hide that roger beep selection.
rxbw.emplace_back(" 3k-USB ", 0); // locked a fixed option , to display it . rxbw.emplace_back(" USB+3k ", 0); // locked a fixed option , to display it .
field_rxbw.set_options(rxbw); // store that aux GUI option to the field_rxbw. field_rxbw.set_options(rxbw); // store that aux GUI option to the field_rxbw.
set_dirty(); // Refresh display set_dirty(); // Refresh display
@ -447,7 +448,7 @@ MicTXView::MicTXView(
check_rogerbeep.set_value(false); // reset the possible activation of roger beep, because it is not compatible with SSB , by now. check_rogerbeep.set_value(false); // reset the possible activation of roger beep, because it is not compatible with SSB , by now.
check_rogerbeep.hidden(1); // hide that roger beep selection. check_rogerbeep.hidden(1); // hide that roger beep selection.
rxbw.emplace_back(" 3k-LSB ", 0); // locked a fixed option , to display it . rxbw.emplace_back(" LSB-3k ", 0); // locked a fixed option , to display it .
field_rxbw.set_options(rxbw); // store that aux GUI option to the field_rxbw. field_rxbw.set_options(rxbw); // store that aux GUI option to the field_rxbw.
set_dirty(); // Refresh display set_dirty(); // Refresh display
@ -457,8 +458,8 @@ MicTXView::MicTXView(
rxaudio(rx_enabled); //Update now if we have RX audio on rxaudio(rx_enabled); //Update now if we have RX audio on
check_rogerbeep.hidden(0); // make visible again the "rogerbeep" selection. check_rogerbeep.hidden(0); // make visible again the "rogerbeep" selection.
rxbw.emplace_back("SSB1:3k-USB", 0); // added dynamically two options (index 0,1) to that DSB-C case to the field_rxbw value. rxbw.emplace_back("SSB1:USB+3k", 0); // added dynamically two options (index 0,1) to that DSB-C case to the field_rxbw value.
rxbw.emplace_back("SSB2:3k-LSB", 1); rxbw.emplace_back("SSB2:LSB-3k", 1);
field_rxbw.set_options(rxbw); // store that aux GUI option to the field_rxbw. field_rxbw.set_options(rxbw); // store that aux GUI option to the field_rxbw.
@ -542,9 +543,13 @@ MicTXView::MicTXView(
// In Previous fw versions, that nbfm_configuration(n) was done in any mode (FM/AM/SSB/DSB)...strictly speaking only need it in (NFM/FM) // In Previous fw versions, that nbfm_configuration(n) was done in any mode (FM/AM/SSB/DSB)...strictly speaking only need it in (NFM/FM)
receiver_model.set_nbfm_configuration(v ); // we are in NFM/FM case, we need to select proper NFM/FM RX channel filter , NFM BW 8K5(0), NFM BW 11K(1) , FM BW 16K (2) receiver_model.set_nbfm_configuration(v ); // we are in NFM/FM case, we need to select proper NFM/FM RX channel filter , NFM BW 8K5(0), NFM BW 11K(1) , FM BW 16K (2)
} }
else { // we are not in NFM/FM mode .(we could be in any of the rest : AM /USB/LSB/DSB-C) else { // we are not in NFM/FM mode .(we could be in any of the rest : AM /USB/LSB/DSB-SC)
if (enable_dsb) { // we are in DSB-SC in TX mode , we will allow both independent RX SSB demodulation (USB / LSB side band) if (enable_am) { // we are in AM TX mode , we will allow both independent RX audio BW : AM 9K (9K00AE3 / AM 6K (6K00AE3). (In AM option v can be 0 (9k) , 1 (6k)
receiver_model.set_am_configuration(v +1 ); // we are in DSB-C TX mode , we need to select proper SSB filter. 0+1 =>usb(1), 1+1=2 =>lsb(2), receiver_model.set_am_configuration(v ); // we are in AM TX mode , we need to select proper AM full path config AM-9K filter. 0+0 =>AM-9K(0), 0+1=1 =>AM-6K(1),
}
if (enable_dsb) { // we are in DSB-SC in TX mode , we will allow both independent RX SSB demodulation (USB / LSB side band). in that submenu, v is 0 (SSB1 USB) or 1 (SSB2 LSB)
receiver_model.set_am_configuration(v +2 ); // we are in DSB-SC TX mode , we need to select proper SSB filter. 0+2 =>usb(2), 1+2=3 =>lsb(3),
} }
} }
}; };

View File

@ -45,11 +45,11 @@ static void send_message(const Message* const message) {
void AMConfig::apply() const { void AMConfig::apply() const {
const AMConfigureMessage message { const AMConfigureMessage message {
taps_6k0_decim_0, taps_6k0_decim_0, // common FIR filter taps pre-decim_0 to all 5 x AM mod types.(AM-9K, AM-6K, USB, LSB, CW)
taps_6k0_decim_1, taps_6k0_decim_1, // common FIR filter taps pre-decim_1 to all 5 x AM mod. types.
taps_6k0_decim_2, decim_2, // var decim_2 FIR taps filter , variable values, depending selected AM mod(AM 9k / 6k all rest AM modes)
channel, channel, // var channel FIR taps filter , variable values, depending selected AM mode, each one different (DSB-9K, DSB-6K, USB-3K, LSB-3K,CW)
modulation, modulation, // var parameter .
audio_12k_hpf_300hz_config audio_12k_hpf_300hz_config
}; };
send_message(&message); send_message(&message);

View File

@ -36,6 +36,7 @@
namespace baseband { namespace baseband {
struct AMConfig { struct AMConfig {
const fir_taps_real<32> decim_2; // added to handle two types decim_2 9k, 6k
const fir_taps_complex<64> channel; const fir_taps_complex<64> channel;
const AMConfigureMessage::Modulation modulation; const AMConfigureMessage::Modulation modulation;

View File

@ -38,11 +38,12 @@ using namespace portapack;
namespace { namespace {
static constexpr std::array<baseband::AMConfig, 4> am_configs { { static constexpr std::array<baseband::AMConfig, 5> am_configs { { // we config here all the non COMMON parameters to each AM modulation type in RX.
{ taps_6k0_dsb_channel, AMConfigureMessage::Modulation::DSB }, { taps_9k0_decim_2, taps_9k0_dsb_channel, AMConfigureMessage::Modulation::DSB }, // AM DSB-C BW 9khz (+-4k5) commercial EU bandwidth .
{ taps_2k8_usb_channel, AMConfigureMessage::Modulation::SSB }, { taps_6k0_decim_2, taps_6k0_dsb_channel, AMConfigureMessage::Modulation::DSB }, // AM DSB-C BW 6khz (+-3k0) narrow AM , ham equipments.
{ taps_2k8_lsb_channel, AMConfigureMessage::Modulation::SSB }, { taps_6k0_decim_2, taps_2k8_usb_channel, AMConfigureMessage::Modulation::SSB }, // SSB USB BW 2K8 (+ 2K8)
{ taps_0k7_usb_channel, AMConfigureMessage::Modulation::SSB }, { taps_6k0_decim_2, taps_2k8_lsb_channel, AMConfigureMessage::Modulation::SSB }, // SSB LSB BW 2K8 (- 2K8)
{ taps_6k0_decim_2, taps_0k7_usb_channel, AMConfigureMessage::Modulation::SSB }, // SSB USB BW 0K7 (+ 0K7) used to get audio tone from CW Morse, assuming tx shifted +700hz aprox
} }; } };
static constexpr std::array<baseband::NBFMConfig, 3> nbfm_configs { { static constexpr std::array<baseband::NBFMConfig, 3> nbfm_configs { {

View File

@ -247,20 +247,20 @@ constexpr fir_taps_real<32> taps_6k0_decim_2 {
} }, } },
}; };
// IFIR prototype filter fs=48000 ; pass=4500 , stop=7800, decim=4, fout=12000 // IFIR prototype filter fs=48000 ; pass=4500 (cutt off -3dBs) , stop=8000 (<-60dBs), decim=4, fout=12000
// For Europe AM commercial broadcasting stations in LF/MF/HF, Emissions Designator 9K00A3E Bandwidth: 9.00 kHz (derivated from taps_6k0_decim_2 ): // For Europe AM commercial broadcasting stations in LF/MF/HF, Emissions Designator 9K00A3E Bandwidth: 9.00 kHz (derivated from taps_6k0_decim_2 )
// Pre-decimate LPF FIR filter design Created by SciPy Python with the "window method", num_taps = 32, cut_off = 4950. sample_rate = 48000 # Hz, // Pre-decimate LPF FIR filter design Created with SciPy Python with the "window method", num_taps = 32, cut_off = 5150. sample_rate = 48000 # Hz,
// Created with h = signal.firwin(num_taps, cut_off, nyq=sample_rate/2, window=('chebwin',49)) , achieving good STOP band plot < -60 dB's with some ripple. // Created with h = signal.firwin(num_taps, cut_off, nyq=sample_rate/2, window=('chebwin',50)) , achieving good STOP band plot < -60 dB's with some ripple.
// post-escaled h taps to avoid decimals , targetting <= similar int values as previous taps_6k0_dsb_channel peak < 32.767 (2 exp 15) and similar H(f)gain // post-scaled h taps to avoid decimals , targeting <= similar int values as previous taps_6k0_dsb_channel peak < 32.767 (2 exp 15) and similar H(f)gain
constexpr fir_taps_real<32> taps_9k0_decim_2 { constexpr fir_taps_real<32> taps_9k0_decim_2 {
.low_frequency_normalized = -4500.0f / 48000.0f, // Negative -cutt off freq -3dB (real achieved data ,in the plot and measurements) .low_frequency_normalized = -4500.0f / 48000.0f, // Negative -cutt off freq -3dB (real achieved data ,in the plot and measurements)
.high_frequency_normalized = 4500.0f / 48000.0f, // Positive +cutt off freq -3dB (idem) .high_frequency_normalized = 4500.0f / 48000.0f, // Positive +cutt off freq -3dB (idem)
.transition_normalized = 3300.0f / 48000.0f, // 3300 Hz = (7800 Hz - 4500 Hz) (both from plot H(f) curve plot) .transition_normalized = 3500.0f / 48000.0f, // 3500 Hz = (8000 Hz - 4500 Hz) (both from plot H(f) curve plot)
.taps = { { .taps = { {
-40, 3, 98, 239, 340, 266, -96, -726, -53, -30, 47, 198, 355, 372, 89, -535,
-1391, -1659, -1041, 772, 3691, 7156, 10271, 12118, -1307, -1771, -1353, 370, 3384, 7109, 10535, 12591,
12118, 10271, 7156, 3691, 772, -1041, -1659, -1391, 12591, 10535, 7109, 3384, 370, -1353, -1771, -1307,
-726, -96, 266, 340, 239, 98, 3, -40 -535, 89, 372, 355, 198, 47, -30, -53
} }, } },
}; };
@ -292,32 +292,32 @@ constexpr fir_taps_complex<64> taps_6k0_dsb_channel {
} }, } },
}; };
// Channel filter: fs=12000, pass=4450, stop=4800, decim=1, fout=12000 (4k45 selected = aprox 4k5, after several iterative plot H(f) test, best trade off curve) // Channel filter: fs=12000, pass=4500 (cutt off -3dBs), stop=4940 (<-60dBs), decim=1, fout=12000 (*1) real frec pass / stop , based on plotted H(f) curve)
// For Europe AM commercial broadcasting stations in LF/MF/HF, Emissions Designator 9K00A3E Bandwidth: 9.00 kHz (derivative from taps_6k0_dsb_channel) // For Europe AM commercial broadcasting stations in LF/MF/HF, Emissions Designator 9K00A3E Bandwidth: 9.00 kHz (derivative from taps_6k0_dsb_channel)
// FIR filter design created by SciPy Python with the "window method"; num_taps = 64, cut_off = 4450. sample_rate = 12000 # Hz, // FIR filter design created with SciPy Python using "window method"; selected design parameters: num_taps = 64, cut_off = 4575. sample_rate = 12000 # Hz,
// Created with : h=signal.firwin(num_taps, cut_off, nyq=sample_rate/2, window=('chebwin',50)), achieving good STOP band plot < -60 dB's with some ripple. // Created with : h = signal.firwin(num_taps, cut_off, nyq=sample_rate/2, window=('chebwin',50)) , achieving real plot curve (*1) with peak stop band ripple -60dBs.
// post-escaled h taps to avoid decimals , targetting <= similar int values as previous taps_6k0_dsb_channel peak < 32.767 (2 exp 15), (29253) and similar H(f)gain // post-scaled h taps to avoid decimals , targeting <= similar int values as previous taps_6k0_dsb_channel peak < 32.767 (2 exp 15), (29625) and similar H(f)gain
constexpr fir_taps_complex<64> taps_9k0_dsb_channel { constexpr fir_taps_complex<64> taps_9k0_dsb_channel {
.low_frequency_normalized = -4500.0f / 12000.0f, // Negative -cutt off freq -3dB (in the H(f) curve plot) .low_frequency_normalized = -4500.0f / 12000.0f, // Negative -cutt off freq -3dB (in the H(f) curve plot)
.high_frequency_normalized = 4500.0f / 12000.0f, // Positive +cutt off freq -3dB (in the H(f) curve plot) .high_frequency_normalized = 4500.0f / 12000.0f, // Positive +cutt off freq -3dB (in the H(f) curve plot)
.transition_normalized = 350.0f / 12000.0f, // 350Hz = (4800 Hz -4450 Hz) cut-3dB's (both data comes from H(f) curve plot and confirmed by measurements ) .transition_normalized = 440.0f / 12000.0f, // 440Hz = (4940 Hz -4500 Hz) cut-3dB's (both data comes from H(f) curve plot and confirmed by measurements )
.taps = { { .taps = { {
{ -34, 0 }, { 23, 0 }, { -13, 0 }, { -19, 0 }, { 2, 0 }, { -18, 0 }, { 34, 0 }, { -33, 0 },
{ 55, 0 }, { -65, 0 }, { 25, 0 }, { 59, 0 }, { 6, 0 }, { 44, 0 }, { -91, 0 }, { 96, 0 },
{ -137, 0 }, { 141, 0 }, { -35, 0 }, { -146, 0 }, { -35, 0 }, { -80, 0 }, { 193, 0 }, { -223, 0 },
{ 287, 0 }, { -262, 0 }, { 26, 0 }, { 317, 0 }, { 116, 0 }, { 112, 0 }, { -353, 0 }, { 452, 0 },
{ -544, 0 }, { 441, 0 }, { 29, 0 }, { -638, 0 }, { -293, 0 }, { -111, 0 }, { 584, 0 }, { -844, 0 },
{ 980, 0 }, { -707, 0 }, { -191, 0 }, { 1272, 0 }, { 653, 0 }, { 22, 0 }, { -921, 0 }, { 1554, 0 },
{ -1805, 0 }, { 1175, 0 }, { 660, 0 }, { -2934, 0 }, { -1422, 0 }, { 301, 0 }, { 1533, 0 }, { -3282, 0 },
{ 4214, 0 }, { -2774, 0 }, { -3655, 0 }, { 29253, 0 }, { 3804, 0 }, { -1819, 0 }, { -4605, 0 }, { 29625, 0 },
{ 29253, 0 }, { -3655, 0 }, { -2774, 0 }, { 4214, 0 }, { 29625, 0 }, { -4605, 0 }, { -1819, 0 }, { 3804, 0 },
{ -2934, 0 }, { 660, 0 }, { 1175, 0 }, { -1805, 0 }, { -3282, 0 }, { 1533, 0 }, { 301, 0 }, { -1422, 0 },
{ 1272, 0 }, { -191, 0 }, { -707, 0 }, { 980, 0 }, { 1554, 0 }, { -921, 0 }, { 22, 0 }, { 653, 0 },
{ -638, 0 }, { 29, 0 }, { 441, 0 }, { -544, 0 }, { -844, 0 }, { 584, 0 }, { -111, 0 }, { -293, 0 },
{ 317, 0 }, { 26, 0 }, { -262, 0 }, { 287, 0 }, { 452, 0 }, { -353, 0 }, { 112, 0 }, { 116, 0 },
{ -146, 0 }, { -35, 0 }, { 141, 0 }, { -137, 0 }, { -223, 0 }, { 193, 0 }, { -80, 0 }, { -35, 0 },
{ 59, 0 }, { 25, 0 }, { -65, 0 }, { 55, 0 }, { 96, 0 }, { -91, 0 }, { 44, 0 }, { 6, 0 },
{ -19, 0 }, { -13, 0 }, { 23, 0 }, { -34, 0 }, { -33, 0 }, { 34, 0 }, { -18, 0 }, { 2, 0 },
} }, } },
}; };