mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-09-12 09:39:30 +00:00
EPIRB TX application update (#3120)
This commit is contained in:
+175
-22
@@ -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) {
|
void EPIRBTXAppView::update_frame(bool updateConfig) {
|
||||||
if (mode_file) {
|
if (mode_file) {
|
||||||
// In file mode, currently selected beacon has changed => load the new one
|
// 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() {
|
void EPIRBTXAppView::update_config() {
|
||||||
if (epirb_tx_message.mode_bpsk) {
|
if (!epirb_tx_message.mode_bpsk) {
|
||||||
// Already in BPSK mode => backup bpsk frequency
|
|
||||||
bpsk_frequency = transmitter_model.target_frequency();
|
|
||||||
} else {
|
|
||||||
// Previously in AM mode => restore bpsk frequency
|
// Previously in AM mode => restore bpsk frequency
|
||||||
transmitter_model.set_target_frequency(bpsk_frequency);
|
transmitter_model.set_target_frequency(bpsk_frequency);
|
||||||
|
// Update displayed frequency
|
||||||
|
tx_view.on_show();
|
||||||
}
|
}
|
||||||
// Set mode to bpsk
|
// Set mode to bpsk
|
||||||
epirb_tx_message.mode_bpsk = true;
|
epirb_tx_message.mode_bpsk = true;
|
||||||
|
transmitting_bpsk = true;
|
||||||
// Set pre/post count
|
// 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
|
epirb_tx_message.post_count = (100 * TONES_SAMPLERATE) / 1000; // 100 ms
|
||||||
// Send config to baseband
|
// Send config to baseband
|
||||||
baseband::set_epirb_tx_config(epirb_tx_message);
|
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 EPIRBTXAppView::on_tx_progress(const uint32_t progress, const bool done) {
|
||||||
(void)progress;
|
(void)progress;
|
||||||
if (done) {
|
if (done) {
|
||||||
|
transmitting_bpsk = false;
|
||||||
if (am_enabled) {
|
if (am_enabled) {
|
||||||
// BPSK frame sent, switch back to 121.5 AM signal
|
// BPSK frame sent, switch back to 121.5 AM signal
|
||||||
epirb_tx_message.mode_bpsk = false;
|
epirb_tx_message.mode_bpsk = false;
|
||||||
// Backup bpsk frequency for next run
|
// Start am transmission
|
||||||
bpsk_frequency = transmitter_model.target_frequency();
|
update_am_transmission();
|
||||||
// Restore am frequency
|
|
||||||
transmitter_model.set_target_frequency(am_frequency);
|
|
||||||
// Send config to baseband
|
|
||||||
baseband::set_epirb_tx_config(epirb_tx_message);
|
|
||||||
} else {
|
} else {
|
||||||
// End of BPSK frame
|
// End of BPSK frame
|
||||||
transmitter_model.disable();
|
transmitter_model.disable();
|
||||||
@@ -262,6 +292,8 @@ EPIRBTXAppView::EPIRBTXAppView(
|
|||||||
&checkbox_am,
|
&checkbox_am,
|
||||||
&field_am_frequency,
|
&field_am_frequency,
|
||||||
&checkbox_send_on_change,
|
&checkbox_send_on_change,
|
||||||
|
&options_am_channel,
|
||||||
|
&options_bpsk_channel,
|
||||||
&tx_view});
|
&tx_view});
|
||||||
|
|
||||||
text_beacon.set_style(Theme::getInstance()->fg_light);
|
text_beacon.set_style(Theme::getInstance()->fg_light);
|
||||||
@@ -279,6 +311,11 @@ EPIRBTXAppView::EPIRBTXAppView(
|
|||||||
options_mode.set_by_value(!mode_file);
|
options_mode.set_by_value(!mode_file);
|
||||||
transmitter_model.set_target_frequency(bpsk_frequency);
|
transmitter_model.set_target_frequency(bpsk_frequency);
|
||||||
field_am_frequency.set_value(am_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);
|
field_delay.set_value(delay);
|
||||||
options_beacon_type.set_by_value(beacon_type);
|
options_beacon_type.set_by_value(beacon_type);
|
||||||
options_beacon_protocol.set_by_value(beacon_protocol);
|
options_beacon_protocol.set_by_value(beacon_protocol);
|
||||||
@@ -292,23 +329,23 @@ EPIRBTXAppView::EPIRBTXAppView(
|
|||||||
update_mode();
|
update_mode();
|
||||||
update_location();
|
update_location();
|
||||||
|
|
||||||
options_mode.on_change = [this](size_t index, OptionsField::value_t) {
|
options_mode.on_change = [this](size_t, OptionsField::value_t value) {
|
||||||
mode_file = (index == 0);
|
mode_file = (((BeaconMode)value) == BeaconMode::FILE);
|
||||||
update_mode();
|
update_mode();
|
||||||
update_frame();
|
update_frame();
|
||||||
set_dirty();
|
set_dirty();
|
||||||
};
|
};
|
||||||
|
|
||||||
options_beacon_type.on_change = [this](size_t index, OptionsField::value_t) {
|
options_beacon_type.on_change = [this](size_t, OptionsField::value_t value) {
|
||||||
beacon_params.type = (BeaconType)index;
|
beacon_params.type = (BeaconType)value;
|
||||||
beacon_type = index;
|
beacon_type = value;
|
||||||
update_frame();
|
update_frame();
|
||||||
set_dirty();
|
set_dirty();
|
||||||
};
|
};
|
||||||
|
|
||||||
options_beacon_protocol.on_change = [this](size_t index, OptionsField::value_t) {
|
options_beacon_protocol.on_change = [this](size_t, OptionsField::value_t value) {
|
||||||
beacon_params.protocol = (BeaconProtocol)index;
|
beacon_params.protocol = (BeaconProtocol)value;
|
||||||
beacon_protocol = index;
|
beacon_protocol = value;
|
||||||
update_frame();
|
update_frame();
|
||||||
set_dirty();
|
set_dirty();
|
||||||
};
|
};
|
||||||
@@ -320,6 +357,71 @@ EPIRBTXAppView::EPIRBTXAppView(
|
|||||||
set_dirty();
|
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) {
|
checkbox_beacon_internal.on_select = [this](Checkbox&, bool v) {
|
||||||
beacon_internal = v;
|
beacon_internal = v;
|
||||||
beacon_params.is_internal = v;
|
beacon_params.is_internal = v;
|
||||||
@@ -358,7 +460,7 @@ EPIRBTXAppView::EPIRBTXAppView(
|
|||||||
|
|
||||||
field_am_frequency.on_change = [this](rf::Frequency freq) {
|
field_am_frequency.on_change = [this](rf::Frequency freq) {
|
||||||
am_frequency = freq;
|
am_frequency = freq;
|
||||||
if (transmitting && !epirb_tx_message.mode_bpsk && am_enabled)
|
if (transmitting && !transmitting_bpsk && am_enabled)
|
||||||
// Update transmitter frequency
|
// Update transmitter frequency
|
||||||
transmitter_model.set_target_frequency(am_frequency);
|
transmitter_model.set_target_frequency(am_frequency);
|
||||||
};
|
};
|
||||||
@@ -397,6 +499,8 @@ EPIRBTXAppView::EPIRBTXAppView(
|
|||||||
checkbox_am.on_select = [this](Checkbox&, bool v) {
|
checkbox_am.on_select = [this](Checkbox&, bool v) {
|
||||||
beacon_params.has_121_5 = v;
|
beacon_params.has_121_5 = v;
|
||||||
am_enabled = 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);
|
if (!mode_file) update_frame(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -404,7 +508,21 @@ EPIRBTXAppView::EPIRBTXAppView(
|
|||||||
field_am_frequency.on_edit = [this, &nav]() {
|
field_am_frequency.on_edit = [this, &nav]() {
|
||||||
auto new_view = nav.push<FrequencyKeypadView>(field_am_frequency.value());
|
auto new_view = nav.push<FrequencyKeypadView>(field_am_frequency.value());
|
||||||
new_view->on_changed = [this](rf::Frequency f) {
|
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]() {
|
tx_view.on_edit_frequency = [this, &nav]() {
|
||||||
auto new_view = nav.push<FrequencyKeypadView>(transmitter_model.target_frequency());
|
auto new_view = nav.push<FrequencyKeypadView>(transmitter_model.target_frequency());
|
||||||
new_view->on_changed = [this](rf::Frequency f) {
|
new_view->on_changed = [this](rf::Frequency f) {
|
||||||
transmitter_model.set_target_frequency(f);
|
|
||||||
bpsk_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();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+87
-15
@@ -37,8 +37,26 @@
|
|||||||
#define BEACON_HEXA_HALF_SIZE 18
|
#define BEACON_HEXA_HALF_SIZE 18
|
||||||
#define BEACON_SIZE 18
|
#define BEACON_SIZE 18
|
||||||
|
|
||||||
|
#define AM_TEST_FREQUENCY 121375000
|
||||||
|
#define AM_REAL_FREQUENCY 121500000
|
||||||
|
|
||||||
|
#define BPSK_FREQUENCY_HAM 433025000
|
||||||
|
#define BPSK_FREQUENCY_B 406025000
|
||||||
|
#define BPSK_FREQUENCY_C 406028000
|
||||||
|
#define BPSK_FREQUENCY_F 406037000
|
||||||
|
#define BPSK_FREQUENCY_G 406040000
|
||||||
|
#define BPSK_FREQUENCY_J 406049000
|
||||||
|
#define BPSK_FREQUENCY_K 406052000
|
||||||
|
#define BPSK_FREQUENCY_N 406061000
|
||||||
|
#define BPSK_FREQUENCY_O 406064000
|
||||||
|
|
||||||
namespace ui::external_app::epirb_tx {
|
namespace ui::external_app::epirb_tx {
|
||||||
|
|
||||||
|
enum class BeaconMode {
|
||||||
|
FILE = 0,
|
||||||
|
MODE_MANUAL = 1
|
||||||
|
};
|
||||||
|
|
||||||
enum class BeaconType {
|
enum class BeaconType {
|
||||||
EPIRB = 0,
|
EPIRB = 0,
|
||||||
ELT = 1,
|
ELT = 1,
|
||||||
@@ -51,6 +69,25 @@ enum class BeaconProtocol {
|
|||||||
NATIONAL = 2
|
NATIONAL = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class AmChannel {
|
||||||
|
TEST = 0,
|
||||||
|
REAL = 1,
|
||||||
|
MANUAL = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BpskChannel {
|
||||||
|
HAM = 0,
|
||||||
|
B = 1,
|
||||||
|
C = 2,
|
||||||
|
F = 3,
|
||||||
|
G = 4,
|
||||||
|
J = 5,
|
||||||
|
K = 6,
|
||||||
|
N = 7,
|
||||||
|
O = 8,
|
||||||
|
MANUAL = 10
|
||||||
|
};
|
||||||
|
|
||||||
struct Location {
|
struct Location {
|
||||||
std::string locator;
|
std::string locator;
|
||||||
bool south;
|
bool south;
|
||||||
@@ -95,6 +132,8 @@ class EPIRBTXAppView : public View {
|
|||||||
std::string frame_to_hex_string(bool start);
|
std::string frame_to_hex_string(bool start);
|
||||||
void generate_frame(BeaconParams params);
|
void generate_frame(BeaconParams params);
|
||||||
void update_frame(bool updateConfig = true);
|
void update_frame(bool updateConfig = true);
|
||||||
|
void update_bpsk_frequency();
|
||||||
|
void update_am_transmission();
|
||||||
void update_mode();
|
void update_mode();
|
||||||
void update_location(bool updateLocatorField = true);
|
void update_location(bool updateLocatorField = true);
|
||||||
|
|
||||||
@@ -114,25 +153,33 @@ class EPIRBTXAppView : public View {
|
|||||||
// Frequency of the transmitter before starting the app (used to restore frequency when leaving)
|
// Frequency of the transmitter before starting the app (used to restore frequency when leaving)
|
||||||
rf::Frequency original_frequency{0};
|
rf::Frequency original_frequency{0};
|
||||||
// Frequency of the AM emergency signal
|
// Frequency of the AM emergency signal
|
||||||
rf::Frequency am_frequency{121500000};
|
rf::Frequency am_frequency{AM_TEST_FREQUENCY};
|
||||||
// Frequency of the 406 MHz BPSK signal
|
// Frequency of the 406 MHz BPSK signal
|
||||||
rf::Frequency bpsk_frequency{406025000};
|
rf::Frequency bpsk_frequency{BPSK_FREQUENCY_HAM};
|
||||||
|
// Selected am channel
|
||||||
|
uint8_t am_channel{(uint8_t)AmChannel::TEST};
|
||||||
|
// Selected bpsk channel
|
||||||
|
uint8_t bpsk_channel{(uint8_t)BpskChannel::HAM};
|
||||||
|
// Manual AM frequency value
|
||||||
|
rf::Frequency manual_am_frequency{AM_TEST_FREQUENCY};
|
||||||
|
// Manual BPSK frequency value
|
||||||
|
rf::Frequency manual_bpsk_frequency{BPSK_FREQUENCY_HAM};
|
||||||
|
|
||||||
// True when using a beacon from the BEACONS.TXT file
|
// True when using a beacon from the BEACONS.TXT file
|
||||||
bool mode_file{true};
|
bool mode_file{false};
|
||||||
// True when looping on sending beacons is enabled
|
// True when looping on sending beacons is enabled
|
||||||
bool loop_enabled{true};
|
bool loop_enabled{true};
|
||||||
// True if AM emergency signal transmission is enabled
|
// True if AM emergency signal transmission is enabled
|
||||||
bool am_enabled{true};
|
bool am_enabled{true};
|
||||||
// True if we want to send a new frame each time the user changes the current beacon
|
// True if we want to send a new frame each time the user changes the current beacon
|
||||||
bool send_on_change{false};
|
bool send_on_change{true};
|
||||||
// The current locator string
|
// The current locator string
|
||||||
std::string locator{"JN03RO"};
|
std::string locator{"JN03RO"};
|
||||||
// The delay between each frame when on loop mode
|
// The delay between each frame when on loop mode
|
||||||
uint32_t delay{50};
|
uint32_t delay{50};
|
||||||
uint8_t beacon_type{0};
|
uint8_t beacon_type{(uint8_t)BeaconType::EPIRB};
|
||||||
// Currently selected beacon protocol
|
// Currently selected beacon protocol
|
||||||
uint8_t beacon_protocol{0};
|
uint8_t beacon_protocol{(uint8_t)BeaconProtocol::USER};
|
||||||
// Currently selected beacon country
|
// Currently selected beacon country
|
||||||
uint32_t beacon_country{227};
|
uint32_t beacon_country{227};
|
||||||
// Current beacon's internal state (true for internal location system)
|
// Current beacon's internal state (true for internal location system)
|
||||||
@@ -150,6 +197,8 @@ class EPIRBTXAppView : public View {
|
|||||||
{"sbeacon"sv, &selected_beacon},
|
{"sbeacon"sv, &selected_beacon},
|
||||||
{"amfreq"sv, &am_frequency},
|
{"amfreq"sv, &am_frequency},
|
||||||
{"bpskfreq"sv, &bpsk_frequency},
|
{"bpskfreq"sv, &bpsk_frequency},
|
||||||
|
{"amchan"sv, &am_channel},
|
||||||
|
{"bpskchan"sv, &bpsk_channel},
|
||||||
{"loop"sv, &loop_enabled},
|
{"loop"sv, &loop_enabled},
|
||||||
{"delay"sv, &delay},
|
{"delay"sv, &delay},
|
||||||
{"file"sv, &mode_file},
|
{"file"sv, &mode_file},
|
||||||
@@ -166,6 +215,8 @@ class EPIRBTXAppView : public View {
|
|||||||
uint32_t last_frame_time{0};
|
uint32_t last_frame_time{0};
|
||||||
// True when transmission is enabled
|
// True when transmission is enabled
|
||||||
bool transmitting{false};
|
bool transmitting{false};
|
||||||
|
// True when transmitting a BPSK frame
|
||||||
|
bool transmitting_bpsk{false};
|
||||||
// True when currently looping on sending beacons
|
// True when currently looping on sending beacons
|
||||||
bool loop{false};
|
bool loop{false};
|
||||||
|
|
||||||
@@ -179,7 +230,9 @@ class EPIRBTXAppView : public View {
|
|||||||
{{UI_POS_X(0), UI_POS_Y(0)}, "Source:", Theme::getInstance()->fg_light->foreground},
|
{{UI_POS_X(0), UI_POS_Y(0)}, "Source:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{UI_POS_X(0), UI_POS_Y(6)}, "Frame:", Theme::getInstance()->fg_light->foreground},
|
{{UI_POS_X(0), UI_POS_Y(6)}, "Frame:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{UI_POS_X(0), UI_POS_Y(10)}, "Next frame in s.", Theme::getInstance()->fg_light->foreground},
|
{{UI_POS_X(0), UI_POS_Y(10)}, "Next frame in s.", Theme::getInstance()->fg_light->foreground},
|
||||||
{{UI_POS_X(0), UI_POS_Y(12)}, "AM frequency MHz", Theme::getInstance()->fg_light->foreground},
|
{{UI_POS_X(0), UI_POS_Y(12)}, "AM frequency: MHz", Theme::getInstance()->fg_light->foreground},
|
||||||
|
{{UI_POS_X(0), UI_POS_Y(14)}, "AM chan.:", Theme::getInstance()->fg_light->foreground},
|
||||||
|
{{UI_POS_X(0), UI_POS_Y(15)}, "BPSK chan.:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{UI_POS_X(17), UI_POS_Y(9)}, "s.", Theme::getInstance()->fg_light->foreground}};
|
{{UI_POS_X(17), UI_POS_Y(9)}, "s.", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
// For file mode
|
// For file mode
|
||||||
@@ -231,15 +284,15 @@ class EPIRBTXAppView : public View {
|
|||||||
OptionsField options_beacon_type{
|
OptionsField options_beacon_type{
|
||||||
{UI_POS_X(9), UI_POS_Y(1)},
|
{UI_POS_X(9), UI_POS_Y(1)},
|
||||||
7,
|
7,
|
||||||
{{"EPIRB", 0},
|
{{"EPIRB", (uint8_t)BeaconType::EPIRB},
|
||||||
{"ELT", 1},
|
{"ELT", (uint8_t)BeaconType::ELT},
|
||||||
{"PLB", 2}}};
|
{"PLB", (uint8_t)BeaconType::PLB}}};
|
||||||
OptionsField options_beacon_protocol{
|
OptionsField options_beacon_protocol{
|
||||||
{UI_POS_X(9 + 7), UI_POS_Y(1)},
|
{UI_POS_X(9 + 7), UI_POS_Y(1)},
|
||||||
30,
|
30,
|
||||||
{{"User", 0},
|
{{"User", (uint8_t)BeaconProtocol::USER},
|
||||||
{"Standard", 1},
|
{"Standard", (uint8_t)BeaconProtocol::STANDARD},
|
||||||
{"National", 2}}};
|
{"National", (uint8_t)BeaconProtocol::NATIONAL}}};
|
||||||
OptionsField options_beacon_country{
|
OptionsField options_beacon_country{
|
||||||
{UI_POS_X(9), UI_POS_Y(2)},
|
{UI_POS_X(9), UI_POS_Y(2)},
|
||||||
7,
|
7,
|
||||||
@@ -261,8 +314,8 @@ class EPIRBTXAppView : public View {
|
|||||||
OptionsField options_mode{
|
OptionsField options_mode{
|
||||||
{UI_POS_X(7), UI_POS_Y(0)},
|
{UI_POS_X(7), UI_POS_Y(0)},
|
||||||
30,
|
30,
|
||||||
{{"File (BEACONS.TXT)", 0},
|
{{"File (BEACONS.TXT)", (uint8_t)BeaconMode::FILE},
|
||||||
{"Manual (Editor)", 1}}};
|
{"Manual (Editor)", (uint8_t)BeaconMode::MODE_MANUAL}}};
|
||||||
|
|
||||||
// Frame content
|
// Frame content
|
||||||
Text text_frame{
|
Text text_frame{
|
||||||
@@ -305,6 +358,25 @@ class EPIRBTXAppView : public View {
|
|||||||
"START"};
|
"START"};
|
||||||
const Style& style_tx_start = *Theme::getInstance()->fg_green;
|
const Style& style_tx_start = *Theme::getInstance()->fg_green;
|
||||||
const Style& style_tx_stop = *Theme::getInstance()->fg_red;
|
const Style& style_tx_stop = *Theme::getInstance()->fg_red;
|
||||||
|
OptionsField options_am_channel{
|
||||||
|
{UI_POS_X(11), UI_POS_Y(14)},
|
||||||
|
20,
|
||||||
|
{{"121.375 MHz (Test)", 0},
|
||||||
|
{"121.500 MHz /!\\Real", 1},
|
||||||
|
{"Manual", 2}}};
|
||||||
|
OptionsField options_bpsk_channel{
|
||||||
|
{UI_POS_X(11), UI_POS_Y(15)},
|
||||||
|
20,
|
||||||
|
{{"433.025 MHz (Ham)", (uint8_t)BpskChannel::HAM},
|
||||||
|
{"406.025 MHz (B)", (uint8_t)BpskChannel::B},
|
||||||
|
{"406.028 MHz (C)", (uint8_t)BpskChannel::C},
|
||||||
|
{"406.037 MHz (F)", (uint8_t)BpskChannel::F},
|
||||||
|
{"406.040 MHz (G)", (uint8_t)BpskChannel::G},
|
||||||
|
{"406.049 MHz (J)", (uint8_t)BpskChannel::J},
|
||||||
|
{"406.052 MHz (K)", (uint8_t)BpskChannel::K},
|
||||||
|
{"406.061 MHz (N)", (uint8_t)BpskChannel::N},
|
||||||
|
{"406.064 MHz (O)", (uint8_t)BpskChannel::O},
|
||||||
|
{"Manual", (uint8_t)BpskChannel::MANUAL}}};
|
||||||
|
|
||||||
// Transmitter view
|
// Transmitter view
|
||||||
TransmitterView tx_view{
|
TransmitterView tx_view{
|
||||||
|
|||||||
@@ -46,15 +46,15 @@ void EPIRBTXProcessor::execute(const buffer_c8_t& buffer) {
|
|||||||
if (mode_bpsk) {
|
if (mode_bpsk) {
|
||||||
// BPSK Manchester beacon signal
|
// BPSK Manchester beacon signal
|
||||||
if (bpsk_pre_count < config_pre_count) {
|
if (bpsk_pre_count < config_pre_count) {
|
||||||
// Pre-count state: send a negative phase carrier during pre-count
|
// Pre-count state: send carrier only during pre-count
|
||||||
bpsk_pre_count++;
|
bpsk_pre_count++;
|
||||||
re = i_neg;
|
re = i_carrier;
|
||||||
im = q_neg;
|
im = q_carrier;
|
||||||
} else if (bpsk_post_count > 0) {
|
} else if (bpsk_post_count > 0) {
|
||||||
// Post-count: send a negative phase carrier during post-count
|
// Post-count: send carrier only during post-count
|
||||||
bpsk_post_count++;
|
bpsk_post_count++;
|
||||||
re = i_neg;
|
re = i_carrier;
|
||||||
im = q_neg;
|
im = q_carrier;
|
||||||
if (bpsk_post_count >= config_post_count) {
|
if (bpsk_post_count >= config_post_count) {
|
||||||
// End transmission here
|
// End transmission here
|
||||||
byte_index = 0;
|
byte_index = 0;
|
||||||
|
|||||||
@@ -60,14 +60,17 @@ class EPIRBTXProcessor : public BasebandProcessor {
|
|||||||
// Size of the frame to send in BPSK mode
|
// Size of the frame to send in BPSK mode
|
||||||
uint8_t frame_data_len = 0;
|
uint8_t frame_data_len = 0;
|
||||||
|
|
||||||
// BPSK parameters: Target phase +/-63° as per COSPAS/SARSAT specifications
|
// BPSK parameters: Target phase +/-1.1 RAD as per COSPAS/SARSAT specifications
|
||||||
static constexpr float phase_rad = 63.0f * M_PI / 180.0f;
|
static constexpr float phase_rad = 1.1f;
|
||||||
|
|
||||||
// I/Q values for BPSK (positive phase and negative phase)
|
// I/Q values for BPSK (positive phase and negative phase)
|
||||||
int8_t i_pos = (int8_t)(cos(phase_rad) * 127);
|
int8_t i_pos = (int8_t)(cos(phase_rad) * 127);
|
||||||
int8_t q_pos = (int8_t)(sin(phase_rad) * 127);
|
int8_t q_pos = (int8_t)(sin(phase_rad) * 127);
|
||||||
int8_t i_neg = i_pos;
|
int8_t i_neg = i_pos;
|
||||||
int8_t q_neg = -q_pos;
|
int8_t q_neg = -q_pos;
|
||||||
|
// I/Q values for carrier only
|
||||||
|
static constexpr int8_t i_carrier = 127;
|
||||||
|
static constexpr int8_t q_carrier = 0;
|
||||||
|
|
||||||
// COSPAS/SARSAT signal is manchester (2 states per bit) encoded 400 bit/sec
|
// COSPAS/SARSAT signal is manchester (2 states per bit) encoded 400 bit/sec
|
||||||
static const uint32_t samples_per_halfbit = TONES_SAMPLERATE / 400 / 2;
|
static const uint32_t samples_per_halfbit = TONES_SAMPLERATE / 400 / 2;
|
||||||
|
|||||||
Reference in New Issue
Block a user