EPIRB TX application update (#3120)

This commit is contained in:
Frederic BORRY
2026-04-03 11:35:46 +02:00
committed by GitHub
parent 605c9efa0c
commit 03131c8a0c
4 changed files with 273 additions and 45 deletions
+175 -22
View File
@@ -98,6 +98,39 @@ void EPIRBTXAppView::on_timer() {
}
}
void EPIRBTXAppView::update_bpsk_frequency() {
bool was_transmitting = false;
if (transmitting && (am_enabled || transmitting_bpsk)) {
// We need to stop transmission before changing frequency
transmitter_model.disable();
was_transmitting = true;
}
transmitter_model.set_target_frequency(bpsk_frequency);
// Update displayed frequency
tx_view.on_show();
if (was_transmitting) {
// Start over
start_tx();
}
}
void EPIRBTXAppView::update_am_transmission() {
if (am_enabled && transmitting && !transmitting_bpsk) {
// Start am transmission
// Restore am frequency
epirb_tx_message.mode_bpsk = false;
transmitter_model.set_target_frequency(am_frequency);
// Send config to baseband
baseband::set_epirb_tx_config(epirb_tx_message);
// Start transmitting
transmitter_model.enable();
} else if (transmitting && !transmitting_bpsk) {
// Stop am transmission
transmitter_model.disable();
tx_view.set_transmitting(false);
}
}
void EPIRBTXAppView::update_frame(bool updateConfig) {
if (mode_file) {
// In file mode, currently selected beacon has changed => load the new one
@@ -136,17 +169,17 @@ void EPIRBTXAppView::update_frame(bool updateConfig) {
}
void EPIRBTXAppView::update_config() {
if (epirb_tx_message.mode_bpsk) {
// Already in BPSK mode => backup bpsk frequency
bpsk_frequency = transmitter_model.target_frequency();
} else {
if (!epirb_tx_message.mode_bpsk) {
// Previously in AM mode => restore bpsk frequency
transmitter_model.set_target_frequency(bpsk_frequency);
// Update displayed frequency
tx_view.on_show();
}
// Set mode to bpsk
epirb_tx_message.mode_bpsk = true;
transmitting_bpsk = true;
// Set pre/post count
epirb_tx_message.pre_count = (150 * TONES_SAMPLERATE) / 1000; // 150 ms
epirb_tx_message.pre_count = (160 * TONES_SAMPLERATE) / 1000; // 160 ms carrier (COSPAS spec.)
epirb_tx_message.post_count = (100 * TONES_SAMPLERATE) / 1000; // 100 ms
// Send config to baseband
baseband::set_epirb_tx_config(epirb_tx_message);
@@ -178,15 +211,12 @@ void EPIRBTXAppView::stop_tx() {
void EPIRBTXAppView::on_tx_progress(const uint32_t progress, const bool done) {
(void)progress;
if (done) {
transmitting_bpsk = false;
if (am_enabled) {
// BPSK frame sent, switch back to 121.5 AM signal
epirb_tx_message.mode_bpsk = false;
// Backup bpsk frequency for next run
bpsk_frequency = transmitter_model.target_frequency();
// Restore am frequency
transmitter_model.set_target_frequency(am_frequency);
// Send config to baseband
baseband::set_epirb_tx_config(epirb_tx_message);
// Start am transmission
update_am_transmission();
} else {
// End of BPSK frame
transmitter_model.disable();
@@ -262,6 +292,8 @@ EPIRBTXAppView::EPIRBTXAppView(
&checkbox_am,
&field_am_frequency,
&checkbox_send_on_change,
&options_am_channel,
&options_bpsk_channel,
&tx_view});
text_beacon.set_style(Theme::getInstance()->fg_light);
@@ -279,6 +311,11 @@ EPIRBTXAppView::EPIRBTXAppView(
options_mode.set_by_value(!mode_file);
transmitter_model.set_target_frequency(bpsk_frequency);
field_am_frequency.set_value(am_frequency);
options_am_channel.set_by_value(am_channel);
options_am_channel.set_style((am_channel == (uint8_t)AmChannel::REAL) ? Theme::getInstance()->fg_red : Theme::getInstance()->bg_darkest);
manual_am_frequency = am_frequency;
options_bpsk_channel.set_by_value(bpsk_channel);
manual_bpsk_frequency = bpsk_frequency;
field_delay.set_value(delay);
options_beacon_type.set_by_value(beacon_type);
options_beacon_protocol.set_by_value(beacon_protocol);
@@ -292,23 +329,23 @@ EPIRBTXAppView::EPIRBTXAppView(
update_mode();
update_location();
options_mode.on_change = [this](size_t index, OptionsField::value_t) {
mode_file = (index == 0);
options_mode.on_change = [this](size_t, OptionsField::value_t value) {
mode_file = (((BeaconMode)value) == BeaconMode::FILE);
update_mode();
update_frame();
set_dirty();
};
options_beacon_type.on_change = [this](size_t index, OptionsField::value_t) {
beacon_params.type = (BeaconType)index;
beacon_type = index;
options_beacon_type.on_change = [this](size_t, OptionsField::value_t value) {
beacon_params.type = (BeaconType)value;
beacon_type = value;
update_frame();
set_dirty();
};
options_beacon_protocol.on_change = [this](size_t index, OptionsField::value_t) {
beacon_params.protocol = (BeaconProtocol)index;
beacon_protocol = index;
options_beacon_protocol.on_change = [this](size_t, OptionsField::value_t value) {
beacon_params.protocol = (BeaconProtocol)value;
beacon_protocol = value;
update_frame();
set_dirty();
};
@@ -320,6 +357,71 @@ EPIRBTXAppView::EPIRBTXAppView(
set_dirty();
};
options_am_channel.on_change = [this](size_t, OptionsField::value_t v) {
bool is_real = false;
switch ((AmChannel)v) {
case AmChannel::REAL:
is_real = true;
am_frequency = AM_REAL_FREQUENCY;
break;
case AmChannel::MANUAL:
am_frequency = manual_am_frequency;
break;
default:
v = (uint8_t)AmChannel::TEST;
// fallthrough
case AmChannel::TEST:
am_frequency = AM_TEST_FREQUENCY;
break;
}
// Actual frequency change will be done by field_am_frequency.on_change()
field_am_frequency.set_value(am_frequency);
am_channel = v;
options_am_channel.set_style(is_real ? Theme::getInstance()->fg_red : Theme::getInstance()->bg_darkest);
set_dirty();
};
options_bpsk_channel.on_change = [this](size_t, OptionsField::value_t v) {
switch ((BpskChannel)v) {
case BpskChannel::MANUAL:
bpsk_frequency = manual_bpsk_frequency;
break;
case BpskChannel::B:
bpsk_frequency = BPSK_FREQUENCY_B;
break;
case BpskChannel::C:
bpsk_frequency = BPSK_FREQUENCY_C;
break;
case BpskChannel::F:
bpsk_frequency = BPSK_FREQUENCY_F;
break;
case BpskChannel::G:
bpsk_frequency = BPSK_FREQUENCY_G;
break;
case BpskChannel::J:
bpsk_frequency = BPSK_FREQUENCY_J;
break;
case BpskChannel::K:
bpsk_frequency = BPSK_FREQUENCY_K;
break;
case BpskChannel::N:
bpsk_frequency = BPSK_FREQUENCY_N;
break;
case BpskChannel::O:
bpsk_frequency = BPSK_FREQUENCY_O;
break;
default:
v = (uint8_t)BpskChannel::HAM;
// fallthrough
case BpskChannel::HAM:
bpsk_frequency = BPSK_FREQUENCY_HAM;
break;
}
bpsk_channel = v;
update_bpsk_frequency();
set_dirty();
};
checkbox_beacon_internal.on_select = [this](Checkbox&, bool v) {
beacon_internal = v;
beacon_params.is_internal = v;
@@ -358,7 +460,7 @@ EPIRBTXAppView::EPIRBTXAppView(
field_am_frequency.on_change = [this](rf::Frequency freq) {
am_frequency = freq;
if (transmitting && !epirb_tx_message.mode_bpsk && am_enabled)
if (transmitting && !transmitting_bpsk && am_enabled)
// Update transmitter frequency
transmitter_model.set_target_frequency(am_frequency);
};
@@ -397,6 +499,8 @@ EPIRBTXAppView::EPIRBTXAppView(
checkbox_am.on_select = [this](Checkbox&, bool v) {
beacon_params.has_121_5 = v;
am_enabled = v;
update_am_transmission();
// We update the additional location device data in the frame based on this
if (!mode_file) update_frame(false);
};
@@ -404,7 +508,21 @@ EPIRBTXAppView::EPIRBTXAppView(
field_am_frequency.on_edit = [this, &nav]() {
auto new_view = nav.push<FrequencyKeypadView>(field_am_frequency.value());
new_view->on_changed = [this](rf::Frequency f) {
field_am_frequency.set_value(f);
switch (f) {
case AM_REAL_FREQUENCY:
am_channel = (uint8_t)AmChannel::REAL;
break;
case AM_TEST_FREQUENCY:
am_channel = (uint8_t)AmChannel::TEST;
break;
default:
manual_am_frequency = f;
am_channel = (uint8_t)AmChannel::MANUAL;
break;
}
// Actual frequency change will be done by options_am_channel.on_change()
options_am_channel.set_by_value(am_channel);
set_dirty();
};
};
@@ -415,8 +533,43 @@ EPIRBTXAppView::EPIRBTXAppView(
tx_view.on_edit_frequency = [this, &nav]() {
auto new_view = nav.push<FrequencyKeypadView>(transmitter_model.target_frequency());
new_view->on_changed = [this](rf::Frequency f) {
transmitter_model.set_target_frequency(f);
bpsk_frequency = f;
switch (f) {
case BPSK_FREQUENCY_HAM:
bpsk_channel = (uint8_t)BpskChannel::HAM;
break;
case BPSK_FREQUENCY_B:
bpsk_channel = (uint8_t)BpskChannel::B;
break;
case BPSK_FREQUENCY_C:
bpsk_channel = (uint8_t)BpskChannel::C;
break;
case BPSK_FREQUENCY_F:
bpsk_channel = (uint8_t)BpskChannel::F;
break;
case BPSK_FREQUENCY_G:
bpsk_channel = (uint8_t)BpskChannel::G;
break;
case BPSK_FREQUENCY_J:
bpsk_channel = (uint8_t)BpskChannel::J;
break;
case BPSK_FREQUENCY_K:
bpsk_channel = (uint8_t)BpskChannel::K;
break;
case BPSK_FREQUENCY_N:
bpsk_channel = (uint8_t)BpskChannel::N;
break;
case BPSK_FREQUENCY_O:
bpsk_channel = (uint8_t)BpskChannel::O;
break;
default:
bpsk_channel = (uint8_t)BpskChannel::MANUAL;
manual_bpsk_frequency = bpsk_frequency;
break;
}
// Actual frequency change will be done by options_bpsk_channel.on_change()
options_bpsk_channel.set_by_value(bpsk_channel);
set_dirty();
};
};