mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-08-19 14:14:04 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e33e697cca | |||
| d7d27d99e7 | |||
| 78d3480b68 | |||
| 70b42f4a56 |
+17
-1
@@ -1 +1,17 @@
|
||||
Please check [Intended-Use-and-Legality](https://github.com/portapack-mayhem/mayhem-firmware/wiki/)
|
||||
# Security Policy
|
||||
|
||||
## Scope and Threat Model
|
||||
This repository hosts the codebase for an embedded system designed for security research. Because the system operates primarily offline, traditional network-based vulnerabilities are generally not applicable. However, we still welcome and review security reports concerning the code within this repository.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
If you discover a vulnerability within this tool itself, please submit a report. Please be aware that the maintainers do not promise assistance with obtaining CVE IDs or managing formal security advisories.
|
||||
|
||||
## Out of Scope
|
||||
* **Vulnerabilities found *using* this tool:** Please do not submit reports here for vulnerabilities you have discovered in other systems or targets using this tool. This channel is strictly for reporting vulnerabilities found *in* the tool itself.
|
||||
* **Other Repositories:** For security issues concerning related tools, such as MayhemHub, please submit your reports directly to their respective repositories.
|
||||
|
||||
## Research Attribution
|
||||
If you utilize this tool to successfully discover vulnerabilities in external systems, we would greatly appreciate it if you credit or mention our project in your published research or write-ups.
|
||||
|
||||
## Legal and Security Disclaimer
|
||||
For comprehensive guidelines regarding the legal and secure usage of this tool, as well as our full liability disclaimer, please refer to: [Intended-Use-and-Legality](https://github.com/portapack-mayhem/mayhem-firmware/wiki/). Users are expected to comply with all applicable laws and regulations when using this software and/or hardware.
|
||||
|
||||
@@ -419,10 +419,10 @@ void AnalogAudioView::on_baseband_bandwidth_changed(uint32_t bandwidth_hz) {
|
||||
}
|
||||
|
||||
void AnalogAudioView::on_modulation_changed(ReceiverModel::Mode modulation) {
|
||||
baseband::spectrum_streaming_stop();
|
||||
waterfall.stop();
|
||||
update_modulation(modulation);
|
||||
on_show_options_modulation();
|
||||
baseband::spectrum_streaming_start();
|
||||
waterfall.start();
|
||||
}
|
||||
|
||||
void AnalogAudioView::remove_options_widget() {
|
||||
|
||||
+12
-14
@@ -3,13 +3,11 @@
|
||||
/*
|
||||
* FPV RX — how frequency search and lock work
|
||||
*
|
||||
* 1. Power metric: We use channelized power (baseband IQ magnitude² in the
|
||||
* capture bandwidth), not raw RF RSSI. Stats come from ChannelStatsCollector
|
||||
* over filtered IQ, so we see power in the tuned channel, not wideband.
|
||||
* 1. Power metric: We use channelized power that portapack RSSI algo included.
|
||||
*
|
||||
* 2. Scanning: We step through FPV bands/channels (A/B/E/F/R, 8 ch each). When
|
||||
* power on the current channel exceeds the detect threshold, we enter
|
||||
* "Candidate" and run verification — we do not lock on a single peak.
|
||||
* "Candidate" and run verification - with some edge detecting algo.
|
||||
*
|
||||
* 3. Verification (making sure the drone is on that freq):
|
||||
* - Multiple samples: verify_hits / verify_misses over several updates.
|
||||
@@ -177,7 +175,7 @@ void FpvDetectView::reset_detector(bool retune_current) {
|
||||
}
|
||||
}
|
||||
|
||||
bool FpvDetectView::is_possible_analog_carrier(const ChannelStatistics& statistics) const {
|
||||
bool FpvDetectView::is_possible_freq_spike(const ChannelStatistics& statistics) const {
|
||||
return statistics.max_db >= detect_threshold_db();
|
||||
}
|
||||
|
||||
@@ -392,17 +390,17 @@ void FpvDetectView::update_state_badge() {
|
||||
text_state.set("SCANNING");
|
||||
break;
|
||||
case DetectState::Candidate:
|
||||
text_state.set("VERIFY FPV");
|
||||
text_state.set("CHECKING");
|
||||
break;
|
||||
case DetectState::Locked:
|
||||
text_state.set("DRONE FOUND");
|
||||
text_state.set("FREQ FOUND");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FpvDetectView::update_confidence_text() {
|
||||
char buf[16];
|
||||
std::snprintf(buf, sizeof(buf), "Conf %u%%", static_cast<unsigned>(candidate_confidence_));
|
||||
std::snprintf(buf, sizeof(buf), "Posi %u%%", static_cast<unsigned>(candidate_confidence_));
|
||||
text_confidence.set(buf);
|
||||
}
|
||||
|
||||
@@ -412,21 +410,21 @@ void FpvDetectView::update_status_text() {
|
||||
switch (detect_state_) {
|
||||
case DetectState::Scanning:
|
||||
if (band_mode < FPV_NUM_BANDS) {
|
||||
std::snprintf(buf, sizeof(buf), "Scanning band %c for analog FPV", band_labels[band_mode]);
|
||||
std::snprintf(buf, sizeof(buf), "Scanning band %c", band_labels[band_mode]);
|
||||
} else {
|
||||
std::snprintf(buf, sizeof(buf), "Scanning all FPV bands");
|
||||
std::snprintf(buf, sizeof(buf), "Scanning all from list");
|
||||
}
|
||||
break;
|
||||
|
||||
case DetectState::Candidate:
|
||||
std::snprintf(buf, sizeof(buf), "VERIFYING %c%d %ld MHz",
|
||||
std::snprintf(buf, sizeof(buf), "CHKING %c%d %ld MHz",
|
||||
band_labels[candidate_band_],
|
||||
static_cast<int>(candidate_ch_ + 1),
|
||||
static_cast<long>(fpv_frequencies[candidate_band_][candidate_ch_] / 1000000LL));
|
||||
break;
|
||||
|
||||
case DetectState::Locked:
|
||||
std::snprintf(buf, sizeof(buf), "!!! DRONE FOUND !!! %c%d %ld",
|
||||
std::snprintf(buf, sizeof(buf), "FREQ FOUND %c%d %ld",
|
||||
band_labels[candidate_band_],
|
||||
static_cast<int>(candidate_ch_ + 1),
|
||||
static_cast<long>(fpv_frequencies[candidate_band_][candidate_ch_] / 1000000LL));
|
||||
@@ -453,7 +451,7 @@ void FpvDetectView::update_detail_text() {
|
||||
break;
|
||||
|
||||
case DetectState::Locked:
|
||||
std::snprintf(buf, sizeof(buf), "LOCKED %c%d conf %u%% hold %u",
|
||||
std::snprintf(buf, sizeof(buf), "LOCKED %c%d posi %u%% hold %u",
|
||||
band_labels[candidate_band_],
|
||||
static_cast<int>(candidate_ch_ + 1),
|
||||
static_cast<unsigned>(candidate_confidence_),
|
||||
@@ -605,7 +603,7 @@ void FpvDetectView::on_statistics_update(const ChannelStatistics& statistics) {
|
||||
|
||||
switch (detect_state_) {
|
||||
case DetectState::Scanning:
|
||||
if (is_possible_analog_carrier(statistics)) {
|
||||
if (is_possible_freq_spike(statistics)) {
|
||||
enter_candidate(statistics);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -72,7 +72,7 @@ class FpvDetectView : public View {
|
||||
void step_scan();
|
||||
void reset_detector(bool retune_current);
|
||||
|
||||
bool is_possible_analog_carrier(const ChannelStatistics& statistics) const;
|
||||
bool is_possible_freq_spike(const ChannelStatistics& statistics) const;
|
||||
void enter_candidate(const ChannelStatistics& statistics);
|
||||
void evaluate_candidate_sample(const ChannelStatistics& statistics);
|
||||
void enter_lock();
|
||||
@@ -162,7 +162,7 @@ class FpvDetectView : public View {
|
||||
Text text_freq{{UI_POS_X_RIGHT(20), UI_POS_Y(1), UI_POS_WIDTH(20), UI_POS_DEFAULT_HEIGHT}, ""};
|
||||
|
||||
Text text_state{{UI_POS_X(0), UI_POS_Y(2), UI_POS_WIDTH(12), UI_POS_DEFAULT_HEIGHT}, "SCANNING"};
|
||||
Text text_confidence{{UI_POS_X(12), UI_POS_Y(2), UI_POS_WIDTH(8), UI_POS_DEFAULT_HEIGHT}, "Conf 0%"};
|
||||
Text text_confidence{{UI_POS_X(12), UI_POS_Y(2), UI_POS_WIDTH(8), UI_POS_DEFAULT_HEIGHT}, "Posi 0%"};
|
||||
Text text_detect_label{{UI_POS_X_RIGHT(10), UI_POS_Y(2), UI_POS_WIDTH(5), UI_POS_DEFAULT_HEIGHT}, "Thr>"};
|
||||
|
||||
NumberField field_detect_threshold{
|
||||
@@ -176,8 +176,8 @@ class FpvDetectView : public View {
|
||||
Text freq_stats_rssi{{UI_POS_X(0), UI_POS_Y(3), UI_POS_WIDTH(15), UI_POS_DEFAULT_HEIGHT}, "RSSI 0/0/0"};
|
||||
Text freq_stats_db{{UI_POS_X_RIGHT(14), UI_POS_Y(3), UI_POS_WIDTH(14), UI_POS_DEFAULT_HEIGHT}, "PWR -120 dB"};
|
||||
|
||||
Text text_status{{UI_POS_X(0), UI_POS_Y(4), UI_POS_WIDTH(30), UI_POS_DEFAULT_HEIGHT}, "SCANNING FOR ANALOG FPV"};
|
||||
Text text_detail{{UI_POS_X(0), UI_POS_Y(5), UI_POS_WIDTH(30), UI_POS_DEFAULT_HEIGHT}, "Waiting for FPV-like carrier"};
|
||||
Text text_status{{UI_POS_X(0), UI_POS_Y(4), UI_POS_WIDTH(30), UI_POS_DEFAULT_HEIGHT}, "SCANNING FOR FREQS"};
|
||||
Text text_detail{{UI_POS_X(0), UI_POS_Y(5), UI_POS_WIDTH(30), UI_POS_DEFAULT_HEIGHT}, "Waiting for FPV FREQ"};
|
||||
|
||||
RSSIGraph rssi_graph{{UI_POS_X(0), UI_POS_Y(6), UI_POS_WIDTH_REMAINING(5), UI_POS_HEIGHT_REMAINING(7)}};
|
||||
RSSI rssi{{UI_POS_X_RIGHT(5), UI_POS_Y(6), UI_POS_WIDTH(5), UI_POS_HEIGHT_REMAINING(7)}};
|
||||
|
||||
+75
-42
@@ -27,6 +27,9 @@ MorseRadiotxView::MorseRadiotxView(ui::NavigationView& nav)
|
||||
&chk_trans,
|
||||
&bandwidth,
|
||||
&chk_callsgn,
|
||||
&chk_loop,
|
||||
&wait_time,
|
||||
&progressbar,
|
||||
&txt_last,
|
||||
&console_text,
|
||||
&btn_clear,
|
||||
@@ -69,6 +72,7 @@ MorseRadiotxView::MorseRadiotxView(ui::NavigationView& nav)
|
||||
options_mode.set_selected_index(current_mode, true);
|
||||
tone_.set_value(tone, true);
|
||||
wpm_.set_value(wpm, true);
|
||||
wait_time.set_value(1, true);
|
||||
bandwidth.set_value(band, true);
|
||||
|
||||
btn_ptt.on_select = [this](Button&) {
|
||||
@@ -156,6 +160,14 @@ MorseRadiotxView::MorseRadiotxView(ui::NavigationView& nav)
|
||||
transmitter_model.set_target_frequency(f);
|
||||
};
|
||||
};
|
||||
|
||||
chk_trans.on_select = [this](Checkbox&, bool v) {
|
||||
if (v) chk_loop.set_value(false);
|
||||
};
|
||||
|
||||
chk_loop.on_select = [this](Checkbox&, bool v) {
|
||||
if (v) chk_trans.set_value(false);
|
||||
};
|
||||
}
|
||||
|
||||
MorseRadiotxView::~MorseRadiotxView() {
|
||||
@@ -197,19 +209,15 @@ MorseRadiotxView::MorseTimings MorseRadiotxView::calculate_morse_timings(uint32_
|
||||
|
||||
void MorseRadiotxView::transmit_morse_message() {
|
||||
std::string full_message = "";
|
||||
// cal sign
|
||||
if (chk_callsgn.value() && !call_sign.empty()) {
|
||||
full_message = call_sign;
|
||||
if (!chk_trans.value() && !msg_buffer.empty()) {
|
||||
full_message += " " + msg_buffer;
|
||||
}
|
||||
} else {
|
||||
if (!chk_trans.value()) full_message = msg_buffer;
|
||||
}
|
||||
|
||||
if (full_message.empty() && !chk_trans.value()) {
|
||||
if (chk_trans.value()) {
|
||||
ptt_button_visibility(false);
|
||||
return;
|
||||
} else {
|
||||
full_message = msg_buffer;
|
||||
if (chk_callsgn.value() && !call_sign.empty()) { // call sign
|
||||
full_message += " " + call_sign;
|
||||
}
|
||||
}
|
||||
|
||||
// enable transmit
|
||||
@@ -219,46 +227,63 @@ void MorseRadiotxView::transmit_morse_message() {
|
||||
ui_toggle();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < full_message.length(); i++) {
|
||||
if (chThdShouldTerminate()) break;
|
||||
uint8_t loop_seconds = static_cast<uint8_t>(wait_time.value());
|
||||
progressbar.set_max(loop_seconds * 2);
|
||||
|
||||
char c = full_message[i];
|
||||
do {
|
||||
for (size_t i = 0; i < full_message.length(); i++) {
|
||||
if (chThdShouldTerminate()) break;
|
||||
|
||||
std::string s_char(1, c);
|
||||
// space
|
||||
if (c == ' ') {
|
||||
console_text.write(" ");
|
||||
chThdSleepMilliseconds(current_timings.word_gap);
|
||||
continue;
|
||||
}
|
||||
char c = full_message[i];
|
||||
|
||||
const char* pattern = morse_decoder_.get_morse_pattern(c);
|
||||
std::string s_char(1, c);
|
||||
// space
|
||||
if (c == ' ') {
|
||||
console_text.write(" ");
|
||||
chThdSleepMilliseconds(current_timings.word_gap);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pattern != nullptr) {
|
||||
txt_last.set(pattern);
|
||||
const char* pattern = morse_decoder_.get_morse_pattern(c);
|
||||
|
||||
// write blue char to console
|
||||
console_text.write(STR_COLOR_BLUE + s_char);
|
||||
if (pattern != nullptr) {
|
||||
txt_last.set(pattern);
|
||||
|
||||
// Morze (dih/dah) send
|
||||
for (int j = 0; pattern[j] != '\0'; j++) {
|
||||
baseband::set_morsetx_key(true);
|
||||
if (pattern[j] == '.') {
|
||||
chThdSleepMilliseconds(current_timings.dot_ms);
|
||||
} else if (pattern[j] == '-') {
|
||||
chThdSleepMilliseconds(current_timings.dash_ms);
|
||||
// write blue char to console
|
||||
console_text.write(STR_COLOR_BLUE + s_char);
|
||||
|
||||
// Morze (dih/dah) send
|
||||
for (int j = 0; pattern[j] != '\0'; j++) {
|
||||
baseband::set_morsetx_key(true);
|
||||
if (pattern[j] == '.') {
|
||||
chThdSleepMilliseconds(current_timings.dot_ms);
|
||||
} else if (pattern[j] == '-') {
|
||||
chThdSleepMilliseconds(current_timings.dash_ms);
|
||||
}
|
||||
if (chThdShouldTerminate()) break;
|
||||
// pause between signs
|
||||
baseband::set_morsetx_key(false);
|
||||
chThdSleepMilliseconds(current_timings.symbol_gap);
|
||||
}
|
||||
if (chThdShouldTerminate()) break;
|
||||
// pause between signs
|
||||
baseband::set_morsetx_key(false);
|
||||
chThdSleepMilliseconds(current_timings.symbol_gap);
|
||||
}
|
||||
if (chThdShouldTerminate()) break;
|
||||
if (current_timings.char_gap > current_timings.symbol_gap) {
|
||||
chThdSleepMilliseconds(current_timings.char_gap - current_timings.symbol_gap);
|
||||
if (current_timings.char_gap > current_timings.symbol_gap) {
|
||||
chThdSleepMilliseconds(current_timings.char_gap - current_timings.symbol_gap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (chThdShouldTerminate()) break;
|
||||
if (chk_loop.value()) {
|
||||
console_text.write(" ");
|
||||
for (uint8_t s = 0; s < (loop_seconds * 2); s++) {
|
||||
if (chThdShouldTerminate()) break;
|
||||
progressbar.set_value(s + 1);
|
||||
if (!chk_loop.value()) break;
|
||||
chThdSleepMilliseconds(500);
|
||||
}
|
||||
progressbar.set_value(0);
|
||||
}
|
||||
if (!chk_loop.value()) break;
|
||||
} while (chk_loop.value() && !chThdShouldTerminate());
|
||||
|
||||
if (chk_trans.value()) ptt_button_visibility(false);
|
||||
baseband::set_morsetx_key(false);
|
||||
@@ -356,13 +381,17 @@ void MorseRadiotxView::ui_toggle() {
|
||||
wpm_.set_style(Theme::getInstance()->fg_dark);
|
||||
wpm_.set_focusable(false);
|
||||
btn_message.set_style(Theme::getInstance()->fg_dark);
|
||||
btn_message.set_focusable(false);
|
||||
btn_calls.set_style(Theme::getInstance()->fg_dark);
|
||||
btn_calls.set_focusable(false);
|
||||
chk_trans.set_style(Theme::getInstance()->fg_dark);
|
||||
chk_trans.set_focusable(false);
|
||||
bandwidth.set_style(Theme::getInstance()->fg_dark);
|
||||
bandwidth.set_focusable(false);
|
||||
chk_callsgn.set_style(Theme::getInstance()->fg_dark);
|
||||
chk_callsgn.set_focusable(false);
|
||||
wait_time.set_style(Theme::getInstance()->fg_dark);
|
||||
wait_time.set_focusable(false);
|
||||
bandwidth.set_style(Theme::getInstance()->fg_dark);
|
||||
bandwidth.set_focusable(false);
|
||||
|
||||
} else {
|
||||
options_mode.set_style(Theme::getInstance()->bg_darker);
|
||||
@@ -370,11 +399,15 @@ void MorseRadiotxView::ui_toggle() {
|
||||
wpm_.set_style(Theme::getInstance()->bg_darker);
|
||||
wpm_.set_focusable(true);
|
||||
btn_message.set_style(Theme::getInstance()->bg_darker);
|
||||
btn_message.set_focusable(true);
|
||||
btn_calls.set_style(Theme::getInstance()->bg_darker);
|
||||
btn_calls.set_focusable(true);
|
||||
chk_trans.set_style(Theme::getInstance()->bg_darker);
|
||||
chk_trans.set_focusable(true);
|
||||
chk_callsgn.set_style(Theme::getInstance()->bg_darker);
|
||||
chk_callsgn.set_focusable(true);
|
||||
wait_time.set_style(Theme::getInstance()->bg_darker);
|
||||
wait_time.set_focusable(true);
|
||||
ptt_button_visibility(true);
|
||||
tone_.set_style(Theme::getInstance()->bg_darker);
|
||||
tone_.set_focusable(true);
|
||||
|
||||
@@ -118,15 +118,20 @@ class MorseRadiotxView : public ui::View {
|
||||
{{"AM", 0}, {"FM", 1}, {"DSB", 2}, {"USB", 3}, {"LSB", 4}}};
|
||||
NumberField tone_{{UI_POS_X(14), UI_POS_Y(0)}, 4, {400, 1400}, 10, ' ', true};
|
||||
NumberField wpm_{{UI_POS_X(25), UI_POS_Y(0)}, 2, {10, 45}, 1, ' ', true};
|
||||
FloatField bandwidth{{UI_POS_X(20), UI_POS_Y(3)}, 4, {1.0, 16.0}, 0.1, ' ', true, 1};
|
||||
NumberField wait_time{{UI_POS_X(10), UI_POS_Y(4)}, 3, {1, 99}, 1, ' ', true}; // wait between tx-es in loop mode (sec)
|
||||
FloatField bandwidth{{UI_POS_X(6), UI_POS_Y(5)}, 4, {1.0, 16.0}, 0.1, ' ', true, 1};
|
||||
|
||||
ProgressBar progressbar{
|
||||
{UI_POS_X(0), UI_POS_Y(6), screen_width, 16}};
|
||||
|
||||
ui::Text txt_msg{{UI_POS_X(0), UI_POS_Y(1), UI_POS_MAXWIDTH, UI_POS_HEIGHT(1)}, "[" + msg_buffer + "] "};
|
||||
ui::Button btn_message{{UI_POS_X(0), UI_POS_Y(2), UI_POS_WIDTH(11), UI_POS_HEIGHT(1)}, "Message"};
|
||||
ui::Button btn_calls{{UI_POS_X(0), UI_POS_Y(4), UI_POS_WIDTH(11), UI_POS_HEIGHT(1)}, (call_sign.empty()) ? "call sign?" : call_sign};
|
||||
ui::Button btn_calls{{UI_POS_X(0), UI_POS_Y(3), UI_POS_WIDTH(11), UI_POS_HEIGHT(1)}, (call_sign.empty()) ? "call sign?" : call_sign};
|
||||
Checkbox chk_trans{{UI_POS_X(14), UI_POS_Y(2)}, 13, "Manual trans.", true};
|
||||
Checkbox chk_callsgn{{UI_POS_X(14), UI_POS_Y(4)}, 13, "Call sign", true};
|
||||
ui::Text txt_last{{UI_POS_X(10), UI_POS_Y(5), UI_POS_WIDTH_REMAINING(10), UI_POS_HEIGHT(1)}, ""};
|
||||
ui::Console console_text{{UI_POS_X(0), UI_POS_Y(7), UI_POS_MAXWIDTH, UI_POS_HEIGHT_REMAINING(14)}};
|
||||
Checkbox chk_callsgn{{UI_POS_X(14), UI_POS_Y(3)}, 9, "Call sign", true};
|
||||
Checkbox chk_loop{{UI_POS_X(14), UI_POS_Y(4)}, 4, "loop", true};
|
||||
ui::Text txt_last{{UI_POS_X(10), UI_POS_Y(7), UI_POS_WIDTH_REMAINING(10), UI_POS_HEIGHT(1)}, ""};
|
||||
ui::Console console_text{{UI_POS_X(0), UI_POS_Y(9), UI_POS_MAXWIDTH, UI_POS_HEIGHT_REMAINING(14)}};
|
||||
ui::Button btn_clear{{UI_POS_X(0), UI_POS_Y_BOTTOM(5), UI_POS_WIDTH(5), UI_POS_HEIGHT(1)}, "CLR"};
|
||||
ui::Button btn_ptt{{UI_POS_X_CENTER(12), UI_POS_Y_BOTTOM(7), UI_POS_WIDTH(12), UI_POS_HEIGHT(3)}, "PTT"};
|
||||
|
||||
@@ -135,10 +140,11 @@ class MorseRadiotxView : public ui::View {
|
||||
{{UI_POS_X(9), UI_POS_Y(0)}, "Tone:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(18), UI_POS_Y(0)}, "Hz", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(21), UI_POS_Y(0)}, "WPM:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(14), UI_POS_Y(3)}, "BandW:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(24), UI_POS_Y(3)}, "kHz", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), UI_POS_Y(5)}, "Last seq:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), UI_POS_Y(6)}, "Sent Message:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), UI_POS_Y(5)}, "BandW:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(10), UI_POS_Y(5)}, "kHz", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), UI_POS_Y(4)}, "Wait time: ", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), UI_POS_Y(7)}, "Last seq:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), UI_POS_Y(8)}, "Sent Message:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X_RIGHT(7), UI_POS_Y_BOTTOM(5)}, "Vol.:", Theme::getInstance()->fg_light->foreground},
|
||||
};
|
||||
|
||||
|
||||
@@ -361,6 +361,8 @@ void WaterfallView::stop() {
|
||||
baseband::spectrum_streaming_stop();
|
||||
running_ = false;
|
||||
}
|
||||
this->channel_fifo = nullptr;
|
||||
this->audio_spectrum_data = nullptr;
|
||||
}
|
||||
|
||||
void WaterfallView::show_audio_spectrum_view(const bool show) {
|
||||
|
||||
@@ -173,12 +173,16 @@ class WaterfallView : public View {
|
||||
MessageHandlerRegistration message_handler_channel_spectrum_config{
|
||||
Message::ID::ChannelSpectrumConfig,
|
||||
[this](const Message* const p) {
|
||||
if (!running_)
|
||||
return;
|
||||
const auto message = *reinterpret_cast<const ChannelSpectrumConfigMessage*>(p);
|
||||
this->channel_fifo = message.fifo;
|
||||
}};
|
||||
MessageHandlerRegistration message_handler_audio_spectrum{
|
||||
Message::ID::AudioSpectrum,
|
||||
[this](const Message* const p) {
|
||||
if (!running_)
|
||||
return;
|
||||
const auto message = *reinterpret_cast<const AudioSpectrumMessage*>(p);
|
||||
this->audio_spectrum_data = message.data;
|
||||
this->audio_spectrum_update = true;
|
||||
@@ -186,6 +190,8 @@ class WaterfallView : public View {
|
||||
MessageHandlerRegistration message_handler_frame_sync{
|
||||
Message::ID::DisplayFrameSync,
|
||||
[this](const Message* const) {
|
||||
if (!running_)
|
||||
return;
|
||||
if (this->channel_fifo) {
|
||||
ChannelSpectrum channel_spectrum;
|
||||
while (channel_fifo->out(channel_spectrum)) {
|
||||
|
||||
Reference in New Issue
Block a user