diff --git a/firmware/application/baseband_api.cpp b/firmware/application/baseband_api.cpp index 32c439203..5db5014a8 100644 --- a/firmware/application/baseband_api.cpp +++ b/firmware/application/baseband_api.cpp @@ -155,9 +155,9 @@ void set_adsb() { send_message(&message); } -void set_jammer() { +void set_jammer(const bool run) { const JammerConfigureMessage message { - 1 + run }; send_message(&message); } diff --git a/firmware/application/baseband_api.hpp b/firmware/application/baseband_api.hpp index 5bc3c82d8..61db43fc0 100644 --- a/firmware/application/baseband_api.hpp +++ b/firmware/application/baseband_api.hpp @@ -65,7 +65,7 @@ void set_ook_data(const uint32_t stream_length, const uint32_t samples_per_bit, const uint32_t pause_symbols); void set_pocsag(const pocsag::BitRate bitrate); void set_adsb(); -void set_jammer(); +void set_jammer(const bool run); void set_rds_data(const uint16_t message_length); //void set_dtmf_data(const uint32_t bw, const uint32_t tone_length, const uint32_t pause_length); diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index cfa0aef3e..582875fe7 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -25,10 +25,6 @@ //BUG: (fixed ?) Bad console scroll init //BUG: POCSAG misses alphanum messages, cuts them off sometimes -//BUG: Jammer channels are wrong (not enough) when using multiple ranges - -//TODO: Array for checkboxes and texts, options_preset "CUSTOM" on manual freq. entry, in jammer -//TODO: Digital mode for Waveform widget //TEST: Imperial in whipcalc //TEST: Numbers diff --git a/firmware/application/pocsag_app.cpp b/firmware/application/pocsag_app.cpp index e2e14aa97..f942879bb 100644 --- a/firmware/application/pocsag_app.cpp +++ b/firmware/application/pocsag_app.cpp @@ -129,8 +129,8 @@ POCSAGAppView::POCSAGAppView(NavigationView& nav) { }); check_log.set_value(logging); - check_log.on_select = [this](Checkbox&) { - logging = check_log.value(); + check_log.on_select = [this](Checkbox&, bool v) { + logging = v; }; options_bitrate.set_selected_index(1); // 1200bps diff --git a/firmware/application/transmitter_model.cpp b/firmware/application/transmitter_model.cpp index fc00d011f..f78c9d46d 100644 --- a/firmware/application/transmitter_model.cpp +++ b/firmware/application/transmitter_model.cpp @@ -88,6 +88,11 @@ void TransmitterModel::set_sampling_rate(uint32_t v) { update_sampling_rate(); } +void TransmitterModel::set_tx_gain(int32_t v_db) { + tx_gain_db_ = v_db; + update_tx_gain(); +} + void TransmitterModel::on_tick_second() { if (portapack::persistent_memory::stealth_mode()) led_tx.toggle(); diff --git a/firmware/application/ui_bht_tx.cpp b/firmware/application/ui_bht_tx.cpp index aea1c4864..c1f04ec34 100644 --- a/firmware/application/ui_bht_tx.cpp +++ b/firmware/application/ui_bht_tx.cpp @@ -221,8 +221,8 @@ BHTView::BHTView(NavigationView& nav) { generate_message(); }; - checkbox_speaker.on_select = [this](Checkbox&) { - speaker_enabled = checkbox_speaker.value(); + checkbox_speaker.on_select = [this](Checkbox&, bool v) { + speaker_enabled = v; }; header_code_a.on_change = [this](int32_t) { @@ -244,8 +244,8 @@ BHTView::BHTView(NavigationView& nav) { generate_message(); }; - checkbox_wcsubfamily.on_select = [this](Checkbox&) { - if (checkbox_wcsubfamily.value()) { + checkbox_wcsubfamily.on_select = [this](Checkbox&, bool v) { + if (v) { subfamily_code.set_focusable(false); subfamily_code.set_style(&style_grey); text_subfamily.set_style(&style_grey); @@ -257,8 +257,8 @@ BHTView::BHTView(NavigationView& nav) { generate_message(); }; - checkbox_wcid.on_select = [this](Checkbox&) { - if (checkbox_wcid.value()) { + checkbox_wcid.on_select = [this](Checkbox&, bool v) { + if (v) { receiver_code.set_focusable(false); receiver_code.set_style(&style_grey); text_receiver.set_style(&style_grey); diff --git a/firmware/application/ui_jammer.cpp b/firmware/application/ui_jammer.cpp index 184452cd6..68267ad3a 100644 --- a/firmware/application/ui_jammer.cpp +++ b/firmware/application/ui_jammer.cpp @@ -32,6 +32,8 @@ #include #include +#define JAMMER_CH_WIDTH 500000 + using namespace portapack; namespace ui { @@ -84,9 +86,7 @@ void JammerView::update_text(uint8_t id, rf::Frequency f) { while (strlen(finalstr) < 23) strcat(finalstr, " "); - if (c == 0) text_info1.set(finalstr); - if (c == 1) text_info2.set(finalstr); - if (c == 2) text_info3.set(finalstr); + texts_info[c].set(finalstr); } } @@ -120,7 +120,7 @@ JammerView::JammerView(NavigationView& nav) { .foreground = Color::grey(), }; - JammerRange * jammer_ranges = (JammerRange*)shared_memory.bb_data.data; + JammerChannel * jammer_channels = (JammerChannel*)shared_memory.bb_data.data; add_children({ &text_type, @@ -132,12 +132,6 @@ JammerView::JammerView(NavigationView& nav) { &options_preset, &text_hop, &options_hop, - &checkbox_range1, - &checkbox_range2, - &checkbox_range3, - &text_info1, - &text_info2, - &text_info3, &button_transmit, &button_exit }); @@ -156,6 +150,10 @@ JammerView::JammerView(NavigationView& nav) { }; }; + const auto checkbox_fn = [this](Checkbox& checkbox, bool v) { + frequency_range[checkbox.id].enabled = v; + }; + n = 0; for (auto& button : buttons_freq) { button.on_select = button_freq_fn; @@ -170,49 +168,72 @@ JammerView::JammerView(NavigationView& nav) { n++; } + n = 0; + for (auto& checkbox : checkboxes) { + checkbox.on_select = checkbox_fn; + checkbox.set_parent_rect({ + static_cast(8), + static_cast(96 + (n * 52)), + 24, 24 + }); + checkbox.id = n; + checkbox.set_text("Range " + to_string_dec_uint(n + 1)); + add_child(&checkbox); + n++; + } + + n = 0; + for (auto& text : texts_info) { + text.set_parent_rect({ + static_cast(3 * 8), + static_cast(126 + (n * 52)), + 25 * 8, 16 + }); + text.set("C:----.----M W:-----kHz"); + text.set_style(&style_info); + add_child(&text); + n++; + } + button_transmit.set_style(&style_val); - text_info1.set_style(&style_info); - text_info2.set_style(&style_info); - text_info3.set_style(&style_info); + options_hop.set_selected_index(1); options_preset.on_change = [this](size_t, OptionsField::value_t v) { for (uint32_t c = 0; c < 3; c++) { frequency_range[c].min = range_presets[v][c].min; frequency_range[c].max = range_presets[v][c].max; + checkboxes[c].set_value(range_presets[v][c].enabled); } - checkbox_range1.set_value(range_presets[v][0].enabled); - checkbox_range2.set_value(range_presets[v][1].enabled); - checkbox_range3.set_value(range_presets[v][2].enabled); update_text(0, 0); }; - options_preset.set_selected_index(8); + options_preset.set_selected_index(9); // GPS - button_transmit.on_select = [this, &nav, jammer_ranges](Button&) { + button_transmit.on_select = [this, &nav, jammer_channels](Button&) { uint8_t c, i = 0; - size_t num_ranges; + size_t num_channels; rf::Frequency start_freq, range_bw, range_bw_sub, ch_width; bool out_of_ranges = false; // Disable all ranges by default for (c = 0; c < 9; c++) - jammer_ranges[c].enabled = false; + jammer_channels[c].enabled = false; // Generate jamming "channels", maximum: 9 // Convert ranges min/max to center/bw - for (c = 0; c < 3; c++) { + for (size_t r = 0; r < 3; r++) { - range_bw = abs(frequency_range[c].max - frequency_range[c].min); // Total bw for range - - if (range_bw) { - // Sort - if (frequency_range[c].min < frequency_range[c].max) - start_freq = frequency_range[c].min; - else - start_freq = frequency_range[c].max; + if (frequency_range[r].enabled) { + range_bw = abs(frequency_range[r].max - frequency_range[r].min); - if (range_bw > 500000) { + // Sort + if (frequency_range[r].min < frequency_range[r].max) + start_freq = frequency_range[r].min; + else + start_freq = frequency_range[r].max; + + if (range_bw >= JAMMER_CH_WIDTH) { // Example: 600kHz // int(600000 / 500000) = 2 // CH-BW = 600000 / 2 = 300000 @@ -220,32 +241,32 @@ JammerView::JammerView(NavigationView& nav) { // BW-A = CH-BW = 300000 // Center-B = min + CH-BW + Center-A = 450000 // BW-B = CH-BW = 300000 - num_ranges = 0; + num_channels = 0; range_bw_sub = range_bw; do { - range_bw_sub -= 500000; - num_ranges++; - } while (range_bw_sub > 500000); - ch_width = range_bw / num_ranges; - for (c = 0; c < num_ranges; c++) { + range_bw_sub -= JAMMER_CH_WIDTH; + num_channels++; + } while (range_bw_sub >= JAMMER_CH_WIDTH); + ch_width = range_bw / num_channels; + for (c = 0; c < num_channels; c++) { if (i >= 9) { out_of_ranges = true; break; } - jammer_ranges[i].enabled = true; - jammer_ranges[i].width = ch_width; - jammer_ranges[i].center = start_freq + (ch_width / 2) + (ch_width * c); - jammer_ranges[i].duration = 15360 * options_hop.selected_index_value(); + jammer_channels[i].enabled = true; + jammer_channels[i].width = ch_width; + jammer_channels[i].center = start_freq + (ch_width / 2) + (ch_width * c); + jammer_channels[i].duration = 15360 * options_hop.selected_index_value(); i++; } } else { if (i >= 9) { out_of_ranges = true; } else { - jammer_ranges[i].enabled = true; - jammer_ranges[i].width = range_bw; - jammer_ranges[i].center = start_freq + (range_bw / 2); - jammer_ranges[i].duration = 15360 * options_hop.selected_index_value(); + jammer_channels[i].enabled = true; + jammer_channels[i].width = range_bw; + jammer_channels[i].center = start_freq + (range_bw / 2); + jammer_channels[i].duration = 15360 * options_hop.selected_index_value(); i++; } } @@ -257,7 +278,9 @@ JammerView::JammerView(NavigationView& nav) { jamming = false; button_transmit.set_style(&style_val); button_transmit.set_text("START"); + transmitter_model.disable(); radio::disable(); + baseband::set_jammer(false); } else { jamming = true; button_transmit.set_style(&style_cancel); @@ -266,9 +289,10 @@ JammerView::JammerView(NavigationView& nav) { transmitter_model.set_sampling_rate(1536000U); transmitter_model.set_rf_amp(true); transmitter_model.set_baseband_bandwidth(1750000); + transmitter_model.set_tx_gain(47); transmitter_model.enable(); - - baseband::set_jammer(); + + baseband::set_jammer(true); } } else { nav.display_modal("Error", "Jamming bandwidth too large."); diff --git a/firmware/application/ui_jammer.hpp b/firmware/application/ui_jammer.hpp index 3fba8d3e6..3697d378d 100644 --- a/firmware/application/ui_jammer.hpp +++ b/firmware/application/ui_jammer.hpp @@ -100,8 +100,8 @@ private: { false, 0, 0 }}, // GPS L1 & L2 - {{ true, 1575420000 - 1000000, 1575420000 + 1000000}, // BW: 2MHz - { true, 1227600000 - 1000000, 1227600000 + 1000000 }, // BW: 2MHz + {{ true, 1575420000 - 500000, 1575420000 + 500000 }, // BW: 1MHz + { false, 1227600000 - 1000000, 1227600000 + 1000000 }, // BW: 2MHz { false, 0, 0 }}, // WLAN 2.4G CH1 @@ -210,8 +210,10 @@ private: 5, { { " 10ms", 1 }, + { " 50ms", 5 }, { "100ms", 10 }, { " 1s", 100 }, + { " 2s", 200 }, { " 5s", 500 }, { " 10s", 1000 } } @@ -250,39 +252,10 @@ private: { "WLAN 2.4G CH13 ", 22 } } }; - - Checkbox checkbox_range1 { - { 1 * 8, 6 * 16}, - 7, - "Range 1" - }; - Checkbox checkbox_range2 { - { 1 * 8, 9 * 16 + 4}, - 7, - "Range 2" - }; - Checkbox checkbox_range3 { - { 1 * 8, 12 * 16 + 8 }, - 7, - "Range 3" - }; - + + std::array checkboxes { }; std::array buttons_freq { }; - - Text text_info1 { - { 3 * 8, 8 * 16 - 4 + 2, 25 * 8, 16 }, - "C:----.----M W:-----kHz" - }; - - Text text_info2 { - { 3 * 8, 11 * 16 + 2, 25 * 8, 16 }, - "C:----.----M W:-----kHz" - }; - - Text text_info3 { - { 3 * 8, 14 * 16 + 4 + 2, 25 * 8, 16 }, - "C:----.----M W:-----kHz" - }; + std::array texts_info { }; Button button_transmit { { 2 * 8, 16 * 16, 64, 32 }, diff --git a/firmware/application/ui_numbers.cpp b/firmware/application/ui_numbers.cpp index 340f46538..a92f5d676 100644 --- a/firmware/application/ui_numbers.cpp +++ b/firmware/application/ui_numbers.cpp @@ -200,8 +200,8 @@ NumbersStationView::NumbersStationView( }; }; - check_armed.on_select = [this](Checkbox&) { - if (check_armed.value()) { + check_armed.on_select = [this](Checkbox&, bool v) { + if (v) { armed_blink = false; signal_token_tick_second = rtc_time::signal_tick_second += [this]() { this->on_tick_second(); diff --git a/firmware/baseband/proc_jammer.cpp b/firmware/baseband/proc_jammer.cpp index 1e0e4930a..af0246c16 100644 --- a/firmware/baseband/proc_jammer.cpp +++ b/firmware/baseband/proc_jammer.cpp @@ -34,18 +34,16 @@ void JammerProcessor::execute(const buffer_c8_t& buffer) { if (!jammer_duration) { // Find next enabled range - for (ir = 0; ir < 9; ir++) { + do { current_range++; if (current_range == 9) current_range = 0; - if (jammer_ranges[current_range].enabled) - break; - } + } while (!jammer_channels[current_range].enabled); - jammer_duration = jammer_ranges[current_range].duration; - jammer_bw = jammer_ranges[current_range].width / 6; // TODO: Exact value + jammer_duration = jammer_channels[current_range].duration; + jammer_bw = jammer_channels[current_range].width / 5; // TODO: Exact value // Ask for retune - message.freq = jammer_ranges[current_range].center; + message.freq = jammer_channels[current_range].center; message.range = current_range; shared_memory.application_queue.push(message); } else { @@ -64,7 +62,7 @@ void JammerProcessor::execute(const buffer_c8_t& buffer) { }*/ // Phase noise - if (r >= 70) { + if (r >= 10) { aphase += ((aphase>>4) ^ 0x4573) << 14; r = 0; } else { @@ -84,7 +82,6 @@ void JammerProcessor::execute(const buffer_c8_t& buffer) { im = (sine_table_i8[(phase & 0x03FC0000) >> 18]); buffer.p[i] = {(int8_t)re, (int8_t)im}; - //buffer.p[i] = {re, im}; } }; @@ -92,11 +89,15 @@ void JammerProcessor::on_message(const Message* const msg) { const auto message = *reinterpret_cast(msg); if (message.id == Message::ID::JammerConfigure) { - jammer_ranges = (JammerRange*)shared_memory.bb_data.data; - jammer_duration = 0; - current_range = -1; - - configured = true; + if (message.run) { + jammer_channels = (JammerChannel*)shared_memory.bb_data.data; + jammer_duration = 0; + current_range = 0; + + configured = true; + } else { + configured = false; + } } } diff --git a/firmware/baseband/proc_jammer.hpp b/firmware/baseband/proc_jammer.hpp index c599427ef..33e9032ae 100644 --- a/firmware/baseband/proc_jammer.hpp +++ b/firmware/baseband/proc_jammer.hpp @@ -38,11 +38,11 @@ private: BasebandThread baseband_thread { 1536000, this, NORMALPRIO + 20, baseband::Direction::Transmit }; - JammerRange * jammer_ranges { }; + JammerChannel * jammer_channels { }; uint32_t jammer_duration { 0 }; int8_t r { 0 }, ir { 0 }; - int32_t current_range { 0 }; + uint32_t current_range { 0 }; int64_t jammer_center { 0 }; uint32_t sample_count { 0 }; uint32_t aphase { 0 }, phase { 0 }, delta { 0 }, sphase { 0 }; diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index fc1e65151..6cd473179 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -706,13 +706,13 @@ public: class JammerConfigureMessage : public Message { public: constexpr JammerConfigureMessage( - const uint32_t test + const bool run ) : Message { ID::JammerConfigure }, - test(test) + run(run) { } - const uint32_t test; + const bool run; }; class DTMFTXConfigMessage : public Message { diff --git a/firmware/common/portapack_shared_memory.hpp b/firmware/common/portapack_shared_memory.hpp index a67ca1097..a1966275d 100644 --- a/firmware/common/portapack_shared_memory.hpp +++ b/firmware/common/portapack_shared_memory.hpp @@ -29,7 +29,7 @@ #include "portapack_shared_memory.hpp" #include "message_queue.hpp" -struct JammerRange { +struct JammerChannel { bool enabled; uint64_t center; uint32_t width; @@ -62,7 +62,7 @@ struct SharedMemory { union { ToneData tones_data; - JammerRange jammer_ranges[9]; + JammerChannel jammer_channels[9]; uint8_t data[512]; } bb_data { { { { 0, 0 } }, 0, { 0 } } }; }; diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index fef1c5c2a..b2464c06f 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -585,7 +585,7 @@ bool Checkbox::set_value(const bool value) { set_dirty(); if( on_select ) { - on_select(*this); + on_select(*this, value_); return true; } @@ -680,7 +680,7 @@ bool Checkbox::on_touch(const TouchEvent event) { value_ = not value_; set_dirty(); if( on_select ) { - on_select(*this); + on_select(*this, value_); } return true; diff --git a/firmware/common/ui_widget.hpp b/firmware/common/ui_widget.hpp index eed09a303..dc6758a0a 100644 --- a/firmware/common/ui_widget.hpp +++ b/firmware/common/ui_widget.hpp @@ -260,7 +260,7 @@ private: class Checkbox : public Widget { public: - std::function on_select { }; + std::function on_select { }; Checkbox(Point parent_pos, size_t length, std::string text, bool small); Checkbox( diff --git a/firmware/portapack-h1-havoc.bin b/firmware/portapack-h1-havoc.bin index 633ab61da..bbd084594 100644 Binary files a/firmware/portapack-h1-havoc.bin and b/firmware/portapack-h1-havoc.bin differ