diff --git a/firmware/application/Makefile b/firmware/application/Makefile index d4192e14..b50dacdc 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -165,6 +165,7 @@ CPPSRC = main.cpp \ ui_epar.cpp \ ui_focus.cpp \ ui_font_fixed_8x16.cpp \ + ui_freqman.cpp \ ui_handwrite.cpp \ ui_jammer.cpp \ ui_lcr.cpp \ diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index 1d71aa8f..80423118 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -24,24 +24,24 @@ //BUG: No audio in about when shown second time //BUG: Description doesn't show up first time going to system>module info (UI drawn on top) -//TODO: Two players tic-tac-toe -//TODO: Breakout game +//BUG: Crash after TX stop (unregister message !) + +//TODO: Show MD5 mismatches for modules not found, etc... +//TODO: Frequency manager ! +//TODO: Weird LCR AFSK scrambling ? //TODO: SD card wiper //TODO: Draw on touchscreen and transmit as spectrum paint //TODO: Use progressbars -//TODO: Setting: Prefered input method //TODO: LCR receiver //TODO: Xylos receiver //TODO: Morse coder //TODO: Playdead amnesia and login //TODO: Touch screen calibration -//TODO: Show MD5 mismatches for modules not found, etc... //TODO: Check jammer bandwidths //TODO: GSM channel detector //TODO: AFSK receiver //TODO: SIGFOX RX/TX //TODO: Module name/filename in modules.hpp to indicate requirement in case it's not found ui_loadmodule -//BUG: Crash after TX stop (unregister message !) //TODO: Check bw setting in LCR TX //TODO: Bodet :) //TODO: Whistler @@ -51,7 +51,8 @@ //TODO: LCR EC=A,J,N //TODO: LCR full message former (see norm) //TODO: AFSK NRZI -//TODO: TX power +//TODO: TX power setting +//TODO: Two players tic-tac-toe #include "ch.h" diff --git a/firmware/application/ui_afsksetup.cpp b/firmware/application/ui_afsksetup.cpp index a835b20d..4b80b51b 100644 --- a/firmware/application/ui_afsksetup.cpp +++ b/firmware/application/ui_afsksetup.cpp @@ -82,17 +82,19 @@ AFSKSetupView::AFSKSetupView( &field_space, &text_bw, &field_bw, - &text_repeat, - &field_repeat, - &checkbox_lsb, - &checkbox_parity, - &checkbox_datasize, + //&text_repeat, + //&field_repeat, + //&checkbox_lsb, + //&checkbox_parity, + //&checkbox_datasize, + &checkbox_altformat, &button_done } }); - if (portapack::persistent_memory::afsk_config() & 1) checkbox_lsb.set_value(true); - if (portapack::persistent_memory::afsk_config() & 2) checkbox_parity.set_value(true); - if (portapack::persistent_memory::afsk_config() & 4) checkbox_datasize.set_value(true); + //if (portapack::persistent_memory::afsk_config() & 1) checkbox_lsb.set_value(true); + //if (portapack::persistent_memory::afsk_config() & 2) checkbox_parity.set_value(true); + //if (portapack::persistent_memory::afsk_config() & 4) checkbox_datasize.set_value(true); + if (portapack::persistent_memory::afsk_config() & 8) checkbox_altformat.set_value(true); updfreq(portapack::persistent_memory::tuned_frequency()); @@ -133,9 +135,10 @@ AFSKSetupView::AFSKSetupView( portapack::persistent_memory::set_afsk_space(field_space.value()/100); portapack::persistent_memory::set_afsk_bw(field_bw.value()); - if (checkbox_lsb.value() == true) afsk_config |= 1; - if (checkbox_parity.value() == true) afsk_config |= 2; - if (checkbox_datasize.value() == true) afsk_config |= 4; + //if (checkbox_lsb.value() == true) afsk_config |= 1; + //if (checkbox_parity.value() == true) afsk_config |= 2; + //if (checkbox_datasize.value() == true) afsk_config |= 4; + if (checkbox_altformat.value() == true) afsk_config |= 8; afsk_config |= (field_repeat.value() << 8); portapack::persistent_memory::set_afsk_config(afsk_config); diff --git a/firmware/application/ui_afsksetup.hpp b/firmware/application/ui_afsksetup.hpp index ed8a3ab5..5fcf8a25 100644 --- a/firmware/application/ui_afsksetup.hpp +++ b/firmware/application/ui_afsksetup.hpp @@ -105,6 +105,12 @@ private: ' ' }; + Checkbox checkbox_altformat { + { 8, 150 }, + 11, + "Alt. format" + }; + Checkbox checkbox_lsb { { 8, 150 }, 9, diff --git a/firmware/application/ui_alphanum.cpp b/firmware/application/ui_alphanum.cpp index eaf8f1ba..ca93e970 100644 --- a/firmware/application/ui_alphanum.cpp +++ b/firmware/application/ui_alphanum.cpp @@ -51,13 +51,13 @@ AlphanumView::AlphanumView( static constexpr Style style_alpha { .font = font::fixed_8x16, - .background = Color::red(), + .background = Color(191,31,31), .foreground = Color::black() }; static constexpr Style style_num { .font = font::fixed_8x16, - .background = Color::yellow(), + .background = Color(191,191,31), .foreground = Color::black() }; @@ -99,6 +99,13 @@ AlphanumView::AlphanumView( set_lowercase(); } }; + + /*add_child(&raw_char); + raw_char.set_value(0x30); + raw_char.on_select = [this, &nav, txt, max_len](Button&) { + char_add(raw_char.value()); + update_text(); + };*/ add_child(&button_done); button_done.on_select = [this, &nav, txt, max_len](Button&) { diff --git a/firmware/application/ui_alphanum.hpp b/firmware/application/ui_alphanum.hpp index 150303f1..10892750 100644 --- a/firmware/application/ui_alphanum.hpp +++ b/firmware/application/ui_alphanum.hpp @@ -72,6 +72,14 @@ private: { 88+64+16, 270, 32, 24 }, "UC" }; + + /*NumberField raw_char { + { 16, 270, 16, 16 }, + 3, + { 1, 255 }, + 1, + '0' + };*/ Button button_done { { 88, 270, 64, 24 }, diff --git a/firmware/application/ui_freqman.cpp b/firmware/application/ui_freqman.cpp new file mode 100644 index 00000000..cb8b6218 --- /dev/null +++ b/firmware/application/ui_freqman.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "ui_freqman.hpp" + +#include "ch.h" + +#include "ff.h" +#include "portapack.hpp" +#include "event_m0.hpp" +#include "hackrf_hal.hpp" +#include "portapack_shared_memory.hpp" + +#include + +using namespace portapack; + +namespace ui { + +void FreqManView::paint(Painter& painter) { + (void)painter; +} + +FreqManView::FreqManView( + NavigationView& nav +) { + + add_children({ { + &button_ok + } }); + + size_t n = 0; + for(auto& text : text_list) { + add_child(&text); + text.set_parent_rect({ + static_cast(0), + static_cast(16 + (n * 16)), + 240, 16 + }); + const std::string label { + (char)(n + 0x30) + }; + text.set(label); + n++; + } + + button_ok.on_select = [this, &nav](Button&) { + nav.pop(); + }; + +} + +void FreqManView::on_show() { + +} + +void FreqManView::on_hide() { + +} + +} diff --git a/firmware/application/ui_freqman.hpp b/firmware/application/ui_freqman.hpp new file mode 100644 index 00000000..f18b385a --- /dev/null +++ b/firmware/application/ui_freqman.hpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "ui.hpp" +#include "ui_widget.hpp" +#include "ui_painter.hpp" +#include "ui_menu.hpp" +#include "ui_navigation.hpp" + +namespace ui { + +class FreqManView : public View { +public: + FreqManView(NavigationView& nav); + //~FreqManView(); + std::string title() const override { return "Frequency list"; }; + + void paint(Painter& painter) override; + void on_show() override; + void on_hide() override; + +private: + std::array text_list; + + Button button_ok { + { 72, 264, 96, 32 }, + "OK" + }; +}; + +} /* namespace ui */ diff --git a/firmware/application/ui_jammer.cpp b/firmware/application/ui_jammer.cpp index 4f29b010..0d9257bb 100644 --- a/firmware/application/ui_jammer.cpp +++ b/firmware/application/ui_jammer.cpp @@ -171,7 +171,7 @@ JammerView::JammerView( }; transmitter_model.set_baseband_configuration({ - .mode = 3, + .mode = 6, .sampling_rate = 1536000, // ? .decimation_factor = 1, }); @@ -205,6 +205,8 @@ JammerView::JammerView( text_info1.set_style(&style_info); text_info2.set_style(&style_info); text_info3.set_style(&style_info); + + options_preset.set_selected_index(8); options_preset.on_change = [this](size_t n, OptionsField::value_t v) { (void)n; @@ -220,27 +222,25 @@ JammerView::JammerView( }; button_setfreq1_min.on_select = [this,&nav](Button&){ - auto new_view = new FrequencyKeypadView { nav, range1_min }; + auto new_view = nav.push(range1_min); new_view->on_changed = [this](rf::Frequency f) { updfreq(0, f); }; - nav.push(new_view); }; button_setfreq1_max.on_select = [this,&nav](Button&){ - auto new_view = new FrequencyKeypadView { nav, range1_max }; + auto new_view = nav.push(range1_max); new_view->on_changed = [this](rf::Frequency f) { - updfreq(1, f); + updfreq(0, f); }; - nav.push(new_view); }; - button_transmit.on_select = [this,&transmitter_model](Button&) { + button_transmit.on_select = [this](Button&) { uint8_t i = 0; rf::Frequency t, range_lower; EventDispatcher::message_map().unregister_handler(Message::ID::Retune); EventDispatcher::message_map().register_handler(Message::ID::Retune, - [this,&transmitter_model](Message* const p) { + [this](Message* const p) { const auto message = static_cast(p); if (message->freq > 0) { transmitter_model.set_tuning_frequency(message->freq); @@ -252,28 +252,80 @@ JammerView::JammerView( shared_memory.jammer_ranges[i].active = false; } + // Swap if (range1_min > range1_max) { t = range1_min; range1_min = range1_max; range1_max = t; } + i = 0; range_lower = range1_min; - for (i = 0;;) { +// for (i = 0; i < 3; i++) { + if (range1_max - range_lower > 1000000) { shared_memory.jammer_ranges[i].center = range_lower + (1000000/2); shared_memory.jammer_ranges[i].width = 1000000 / 10; shared_memory.jammer_ranges[i].active = true; - shared_memory.jammer_ranges[i].duration = 2280000/10; + shared_memory.jammer_ranges[i].duration = 2280000 / 10; range_lower += 1000000; } else { shared_memory.jammer_ranges[i].center = (range1_max + range_lower) / 2; - shared_memory.jammer_ranges[i].width = (range1_max - range_lower) / 10; + shared_memory.jammer_ranges[i].width = (range1_max - range_lower) / 10; // ? shared_memory.jammer_ranges[i].active = true; - shared_memory.jammer_ranges[i].duration = 2280000/10; - break; + shared_memory.jammer_ranges[i].duration = 2280000 / 10; + //break; } - i++; +// } + + // Swap + if (range2_min > range2_max) { + t = range2_min; + range2_min = range2_max; + range2_max = t; } + i = 1; + range_lower = range2_min; +// for (i = 0; i < 3; i++) { + + if (range1_max - range_lower > 1000000) { + shared_memory.jammer_ranges[i].center = range_lower + (1000000/2); + shared_memory.jammer_ranges[i].width = 1000000 / 10; + shared_memory.jammer_ranges[i].active = true; + shared_memory.jammer_ranges[i].duration = 2280000 / 10; + range_lower += 1000000; + } else { + shared_memory.jammer_ranges[i].center = (range1_max + range_lower) / 2; + shared_memory.jammer_ranges[i].width = (range1_max - range_lower) / 10; // ? + shared_memory.jammer_ranges[i].active = true; + shared_memory.jammer_ranges[i].duration = 2280000 / 10; + //break; + } +// } + + // Swap + if (range3_min > range3_max) { + t = range3_min; + range3_min = range3_max; + range3_max = t; + } + i = 2; + range_lower = range3_min; +// for (i = 0; i < 3; i++) { + + if (range1_max - range_lower > 1000000) { + shared_memory.jammer_ranges[i].center = range_lower + (1000000/2); + shared_memory.jammer_ranges[i].width = 1000000 / 10; + shared_memory.jammer_ranges[i].active = true; + shared_memory.jammer_ranges[i].duration = 2280000 / 10; + range_lower += 1000000; + } else { + shared_memory.jammer_ranges[i].center = (range1_max + range_lower) / 2; + shared_memory.jammer_ranges[i].width = (range1_max - range_lower) / 10; // ? + shared_memory.jammer_ranges[i].active = true; + shared_memory.jammer_ranges[i].duration = 2280000 / 10; + //break; + } +// } transmitter_model.set_tuning_frequency(shared_memory.jammer_ranges[0].center); diff --git a/firmware/application/ui_jammer.hpp b/firmware/application/ui_jammer.hpp index 9edbf155..af1fe2b1 100644 --- a/firmware/application/ui_jammer.hpp +++ b/firmware/application/ui_jammer.hpp @@ -108,11 +108,11 @@ private: { false, 0, 0 }, { false, 0, 0 }}, - // Reims 164 - {{ true, 164000000 - 200000, 164000000 + 200000}, // BW: 400kHz - { false, 0, 0 }, + // GPS L1 & L2 + {{ true, 1575420000 - 50000, 1575420000 + 50000}, // BW: 100kHz + { true, 1227600000 - 50000, 1227600000 + 50000 }, // BW: 100kHz { false, 0, 0 }} - + }; bool jamming = false; @@ -185,7 +185,7 @@ private: { "DECT ", 5 }, { "Optifib ", 6 }, { "ISM 433 ", 7 }, - { "Reims ", 8 }, + { "GPS ", 8 }, } }; diff --git a/firmware/application/ui_lcr.cpp b/firmware/application/ui_lcr.cpp index d259b172..95d4e795 100644 --- a/firmware/application/ui_lcr.cpp +++ b/firmware/application/ui_lcr.cpp @@ -55,12 +55,18 @@ LCRView::~LCRView() { } void LCRView::make_frame() { + const char ec_lut[3][2] = { { 'A', 0x00 }, + { 'J', 0x00 }, + { 'N', 0x00 } + }; char eom[3] = { 3, 0, 0 }; // EOM and space for checksum uint8_t i, pm; uint16_t dp; uint8_t cp, pp, cur_byte, new_byte; - // Pad litterals right to 7 chars (not required ?) + button_setrgsb.set_text(rgsb); + + // Pad litterals to 7 chars (not required ?) for (i = 0; i < 5; i++) { while (strlen(litteral[i]) < 7) { strcat(litteral[i], " "); @@ -77,11 +83,10 @@ void LCRView::make_frame() { lcrframe[5] = 127; lcrframe[6] = 127; lcrframe[7] = 15; // SOM - - button_setrgsb.set_text(rgsb); strcat(lcrframe, rgsb); strcat(lcrframe, "PA "); + if (checkbox_am_a.value() == true) { strcat(lcrframe, "AM=1 AF=\""); strcat(lcrframe, litteral[0]); @@ -107,18 +112,20 @@ void LCRView::make_frame() { strcat(lcrframe, litteral[4]); strcat(lcrframe, "\" CL=0 "); } - strcat(lcrframe, "EC=A SAB=0"); + strcat(lcrframe, "EC="); + strcat(lcrframe, ec_lut[options_ec.selected_index()]); + strcat(lcrframe, " SAB=0"); memcpy(lcrstring, lcrframe, 256); - //Checksum + // Checksum checksum = 0; - i = 7; + i = 7; // Skip modem sync while (lcrframe[i]) { checksum ^= lcrframe[i]; i++; } - checksum ^= eom[0]; // EOM + checksum ^= eom[0]; // EOM char checksum &= 0x7F; eom[1] = checksum; @@ -129,8 +136,8 @@ void LCRView::make_frame() { //else // pm = 1; // Odd parity - //if (persistent_memory::afsk_config() & 1) { - // LSB first + if (!(persistent_memory::afsk_config() & 8)) { + // Clear format for (dp = 0; dp < strlen(lcrframe); dp++) { pp = pm; new_byte = 0; @@ -141,6 +148,24 @@ void LCRView::make_frame() { } lcrframe_f[dp] = new_byte | (pp & 1); } + lcrframe_f[dp] = 0; + } else { + // Alt format + for (dp = 0; dp < strlen(lcrframe); dp++) { + pp = pm; + cur_byte = alt_lookup[lcrframe[dp]]; + for (cp = 0; cp < 8; cp++) { + if ((cur_byte >> cp) & 1) pp++; + } + lcrframe_f[dp * 2] = cur_byte; + lcrframe_f[(dp * 2) + 1] = pp & 1; + } + lcrframe_f[dp * 2] = 0; + } + + //if (persistent_memory::afsk_config() & 1) { + // LSB first + // See above /*} else { // MSB first for (dp=0;dp> 8) & 0xFF).c_str()); text_status.set(str); progress.set_value(0); transmitter_model.disable(); @@ -237,7 +275,6 @@ void LCRView::start_tx() { text_status.set(" "); strcpy(str, to_string_dec_int(6 - message->n).c_str()); strcat(str, "/5"); - //strcat(str, to_string_dec_int((portapack::persistent_memory::afsk_config() >> 8) & 0xFF).c_str()); text_status.set(str); progress.set_value((6 - message->n) * 20); } @@ -297,11 +334,9 @@ LCRView::LCRView( NavigationView& nav ) { - char finalstr[24] = {0}; - transmitter_model.set_baseband_configuration({ .mode = 3, - .sampling_rate = 2280000, // Is this right ? + .sampling_rate = 2280000, .decimation_factor = 1, }); @@ -313,6 +348,7 @@ LCRView::LCRView( add_children({ { &text_recap, + &options_ec, &button_setrgsb, &button_txsetup, &checkbox_am_a, @@ -333,21 +369,14 @@ LCRView::LCRView( &button_clear } }); + options_ec.set_selected_index(0); + checkbox_am_a.set_value(true); checkbox_am_b.set_value(false); checkbox_am_c.set_value(false); checkbox_am_d.set_value(false); checkbox_am_e.set_value(false); - // Recap: tx freq @ bps - auto fstr = to_string_dec_int(portapack::persistent_memory::tuned_frequency() / 1000, 6); - auto bstr = to_string_dec_int(portapack::persistent_memory::afsk_bitrate(), 4); - strcat(finalstr, fstr.c_str()); - strcat(finalstr, " @ "); - strcat(finalstr, bstr.c_str()); - strcat(finalstr, "bps"); - text_recap.set(finalstr); - button_transmit.set_style(&style_val); button_scan.set_style(&style_val); @@ -397,14 +426,18 @@ LCRView::LCRView( }; button_clear.on_select = [this, &nav](Button&) { - memset(litteral, 0, 5 * 8); - checkbox_am_a.set_value(true); - checkbox_am_b.set_value(true); - checkbox_am_c.set_value(true); - checkbox_am_d.set_value(true); - checkbox_am_e.set_value(true); - set_dirty(); - start_tx(); + if (txing == false) { + scanning = false; + memset(litteral, 0, 5 * 8); + options_ec.set_selected_index(0); + checkbox_am_a.set_value(true); + checkbox_am_b.set_value(true); + checkbox_am_c.set_value(true); + checkbox_am_d.set_value(true); + checkbox_am_e.set_value(true); + set_dirty(); + start_tx(); + } }; } diff --git a/firmware/application/ui_lcr.hpp b/firmware/application/ui_lcr.hpp index c042ba20..2a7ef479 100644 --- a/firmware/application/ui_lcr.hpp +++ b/firmware/application/ui_lcr.hpp @@ -74,6 +74,28 @@ private: void make_frame(); void start_tx(); + // 2: 94 ? + // 9: 85 ? + + const char alt_lookup[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0F, // 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10 + 0xF8, 0, 0x99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 !"#$%&'()*+,-./ + 0xF5, 0, 0x94, 0x55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1C, 0, 0, // 30 0123456789:;<=>? + 0, 0x3C, 0x9C, 0x5D, 0, 0, 0, 0, 0, 0x44, 0x85, 0, 0xD5, 0x14, 0, 0, // 40 @ABCDEFGHIJKLMNO + 0xF0, 0, 0, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 50 PQRSTUVWXYZ[\]^_ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60 `abcdefghijklmno + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x7F, // 70 pqrstuvwxyz{|}~ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 90 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F0 + }; + const Style style_val { .font = font::fixed_8x16, .background = Color::green(), @@ -90,12 +112,14 @@ private: "-" }; - NumberField adr_code { - { 220, 6 }, - 2, - { 0, 36 }, - 1, - '0' + OptionsField options_ec { + { 20 * 8, 1 * 16 }, + 4, + { + { "Auto", 0 }, + { "Jour", 1 }, + { "Nuit", 2 } + } }; Button button_setrgsb { diff --git a/firmware/application/ui_loadmodule.cpp b/firmware/application/ui_loadmodule.cpp index 63eed8ef..60f80f7c 100644 --- a/firmware/application/ui_loadmodule.cpp +++ b/firmware/application/ui_loadmodule.cpp @@ -41,6 +41,7 @@ #include "ui_debug.hpp" #include "ui_closecall.hpp" #include "ui_audiotx.hpp" +#include "ui_jammer.hpp" #include #include @@ -174,6 +175,7 @@ LoadModuleView::LoadModuleView( if (viewid == RDS) nav.push(); if (viewid == CloseCall) nav.push(); if (viewid == Receiver) nav.push(); + if (viewid == Jammer) nav.push(); } }; } diff --git a/firmware/application/ui_loadmodule.hpp b/firmware/application/ui_loadmodule.hpp index e142d070..275ec4ab 100644 --- a/firmware/application/ui_loadmodule.hpp +++ b/firmware/application/ui_loadmodule.hpp @@ -40,6 +40,7 @@ enum ViewID { SoundBoard, AnalogAudio, RDS, + Jammer }; class LoadModuleView : public View { diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index fde5a135..d47956bc 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -36,6 +36,7 @@ #include "ui_handwrite.hpp" // DEBUG #include "ui_soundboard.hpp" // DEBUG #include "ui_closecall.hpp" // DEBUG +#include "ui_freqman.hpp" // DEBUG #include "analog_audio_app.hpp" #include "ais_app.hpp" @@ -209,13 +210,14 @@ ReceiverMenuView::ReceiverMenuView(NavigationView& nav) { /* SystemMenuView ********************************************************/ SystemMenuView::SystemMenuView(NavigationView& nav) { - add_items<11>({ { + add_items<12>({ { { "Play dead", ui::Color::red(), [&nav](){ nav.push(false); } }, { "Receiver RX", ui::Color::cyan(), [&nav](){ nav.push(md5_baseband, Receiver); } }, { "Close Call RX", ui::Color::cyan(), [&nav](){ nav.push(md5_baseband, CloseCall); } }, - { "Soundboard TX", ui::Color::yellow(), [&nav](){ nav.push(md5_baseband_tx, SoundBoard); } }, + { "Pokemon GO Away TX", ui::Color::blue(), [&nav](){ nav.push(md5_baseband_tx, Jammer); } }, + //{ "Soundboard TX", ui::Color::yellow(), [&nav](){ nav.push(md5_baseband_tx, SoundBoard); } }, //{ "Audio TX", ui::Color::yellow(), [&nav](){ nav.push(md5_baseband_tx, AudioTX); } }, - + { "Frequency manager", ui::Color::white(), [&nav](){ nav.push(); } }, //{ "EPAR TX", ui::Color::green(), [&nav](){ nav.push(md5_baseband_tx, EPAR); } }, { "Xylos TX", ui::Color::green(), [&nav](){ nav.push(md5_baseband_tx, Xylos); } }, { "TEDI/LCR TX", ui::Color::orange(), [&nav](){ nav.push(md5_baseband_tx, LCR); } }, @@ -293,6 +295,7 @@ SystemView::SystemView( //navigation_view.push(); //navigation_view.push(); //navigation_view.push(debugtxt, 20); + navigation_view.push(); } diff --git a/firmware/application/ui_xylos.cpp b/firmware/application/ui_xylos.cpp index 1ef6ac32..53e03888 100644 --- a/firmware/application/ui_xylos.cpp +++ b/firmware/application/ui_xylos.cpp @@ -197,6 +197,8 @@ XylosView::XylosView( NavigationView& nav ) { + int c; + transmitter_model.set_baseband_configuration({ .mode = 2, .sampling_rate = 1536000, @@ -325,7 +327,7 @@ XylosView::XylosView( XylosView::upd_message(); - button_txtest.on_select = [this](Button&) { + /*button_txtest.on_select = [this](Button&) { const uint8_t ccirtest[21] = { 11, 13, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 14, 12, 10, 12, 14, 0, 9, 0xFF }; if (txing == false) { EventDispatcher::message_map().unregister_handler(Message::ID::TXDone); @@ -351,6 +353,68 @@ XylosView::XylosView( audio::headphone::set_volume(volume_t::decibel(90 - 99) + audio::headphone::volume_range().max); + txing = true; + button_txtest.set_style(&style_cancel); + button_txtest.set_text("Wait"); + transmitter_model.enable(); + } + };*/ + + // Sequence testing: + button_txtest.on_select = [this](Button&) { + int c; + + if (txing == false) { + sequence_idx = 0; + EventDispatcher::message_map().unregister_handler(Message::ID::TXDone); + + EventDispatcher::message_map().register_handler(Message::ID::TXDone, + [this](Message* const p) { + int c; + const auto message = static_cast(p); + if (message->n == 25) { + transmitter_model.disable(); + + if (sequence_idx != 9) { + chThdSleepMilliseconds(15000); + memcpy(ccirmessage, &xylos_sequence[sequence_idx][0], 21); + // ASCII to frequency LUT index + for (c=0; c<20; c++) { + if (ccirmessage[c] > '9') + ccirmessage[c] -= 0x37; + else + ccirmessage[c] -= 0x30; + } + ccirmessage[20] = 0xFF; + shared_memory.transmit_done = false; + memcpy(shared_memory.xylosdata, ccirmessage, 21); + sequence_idx++; + txing = true; + transmitter_model.enable(); + } else { + button_txtest.set_style(&style()); + button_txtest.set_text("TEST"); + } + } + } + ); + + memcpy(ccirmessage, &xylos_sequence[sequence_idx][0], 21); + // ASCII to frequency LUT index + for (c=0; c<20; c++) { + if (ccirmessage[c] > '9') + ccirmessage[c] -= 0x37; + else + ccirmessage[c] -= 0x30; + } + ccirmessage[20] = 0xFF; + shared_memory.transmit_done = false; + memcpy(shared_memory.xylosdata, ccirmessage, 21); + + sequence_idx++; + + transmitter_model.set_tuning_frequency(xylos_freqs[options_freq.selected_index()]); + txing = true; button_txtest.set_style(&style_cancel); button_txtest.set_text("Wait"); diff --git a/firmware/application/ui_xylos.hpp b/firmware/application/ui_xylos.hpp index 132b204b..ce819f85 100644 --- a/firmware/application/ui_xylos.hpp +++ b/firmware/application/ui_xylos.hpp @@ -157,6 +157,20 @@ private: const rf::Frequency xylos_freqs[7] = { 31325000, 31387500, 31437500, 31475000, 31687500, 31975000, 88000000 }; char ccirmessage[21]; + const char xylos_sequence[9][21] = { + "0E0E18920EB1E10B0E0E", + "0E0E1890E0B0E12B0E0E", + "0E0E18920EB1E20B0E0E", + "0E0E18920EB1210B0E0E", + "0E0E18920EB1E10B0E0E", + "0E0E18920EB1E10B0E0E", + "0E0E181AEAB10E0B0E0E", + "0E01E81AEAB10E0B0E0E", // 2016-05-22 05:22:29 0E01E81AEA/10E0/0E0E + "0E03181AEAB10E0B0E0E" + }; + + int sequence_idx; + void start_tx(); void upd_message(); diff --git a/firmware/baseband-tx.bin b/firmware/baseband-tx.bin index f37fb9ee..d7f2a1b1 100644 Binary files a/firmware/baseband-tx.bin and b/firmware/baseband-tx.bin differ diff --git a/firmware/baseband-tx/Makefile b/firmware/baseband-tx/Makefile index 2079d1b6..b1eb38e8 100755 --- a/firmware/baseband-tx/Makefile +++ b/firmware/baseband-tx/Makefile @@ -138,6 +138,7 @@ CPPSRC = main.cpp \ dsp_decimate.cpp \ dsp_demodulate.cpp \ matched_filter.cpp \ + proc_jammer.cpp \ proc_audiotx.cpp \ proc_fsk_lcr.cpp \ proc_epar.cpp \ diff --git a/firmware/baseband-tx/baseband_thread.cpp b/firmware/baseband-tx/baseband_thread.cpp index 83118ff6..6256afb8 100644 --- a/firmware/baseband-tx/baseband_thread.cpp +++ b/firmware/baseband-tx/baseband_thread.cpp @@ -34,6 +34,7 @@ #include "proc_epar.hpp" #include "proc_fsk_lcr.hpp" #include "proc_rds.hpp" +#include "proc_jammer.hpp" #include "rssi.hpp" #include "i2s.hpp" @@ -128,6 +129,7 @@ BasebandProcessor* BasebandThread::create_processor(const int32_t mode) { case 3: return new LCRFSKProcessor(); case 4: return new EPARProcessor(); case 5: return new RDSProcessor(); + case 6: return new JammerProcessor(); default: return nullptr; } } diff --git a/firmware/baseband-tx/proc_fsk_lcr.cpp b/firmware/baseband-tx/proc_fsk_lcr.cpp index a76b002c..4e01a924 100644 --- a/firmware/baseband-tx/proc_fsk_lcr.cpp +++ b/firmware/baseband-tx/proc_fsk_lcr.cpp @@ -34,14 +34,17 @@ void LCRFSKProcessor::execute(const buffer_c8_t& buffer) { s = 0; if (sample_count >= shared_memory.afsk_samples_per_bit) { - if (shared_memory.afsk_transmit_done == false) + if (shared_memory.afsk_transmit_done == false) { cur_byte = shared_memory.radio_data[byte_pos]; + ext_byte = shared_memory.radio_data[byte_pos + 1]; + } if (!cur_byte) { if (shared_memory.afsk_repeat) { shared_memory.afsk_repeat--; bit_pos = 0; byte_pos = 0; cur_byte = shared_memory.radio_data[0]; + ext_byte = shared_memory.radio_data[1]; message.n = shared_memory.afsk_repeat; shared_memory.application_queue.push(message); } else { @@ -49,18 +52,32 @@ void LCRFSKProcessor::execute(const buffer_c8_t& buffer) { shared_memory.afsk_transmit_done = true; shared_memory.application_queue.push(message); cur_byte = 0; + ext_byte = 0; } } - gbyte = 0; - gbyte = cur_byte << 1; - gbyte |= 1; + if (shared_memory.afsk_alt_format) { + // 0bbbbbbbbp + // Start, 8-bit data, parity + gbyte = 0; + gbyte = cur_byte << 1; + gbyte |= (ext_byte & 1); + } else { + // 0bbbbbbbp1 + // Start, 7-bit data, parity, stop + gbyte = 0; + gbyte = cur_byte << 1; + gbyte |= 1; + } - cur_bit = (gbyte >> (9-bit_pos)) & 1; + cur_bit = (gbyte >> (9 - bit_pos)) & 1; if (bit_pos == 9) { bit_pos = 0; - byte_pos++; + if (!shared_memory.afsk_alt_format) + byte_pos++; + else + byte_pos += 2; } else { bit_pos++; } diff --git a/firmware/baseband-tx/proc_fsk_lcr.hpp b/firmware/baseband-tx/proc_fsk_lcr.hpp index 06ad0361..70de97c3 100644 --- a/firmware/baseband-tx/proc_fsk_lcr.hpp +++ b/firmware/baseband-tx/proc_fsk_lcr.hpp @@ -31,8 +31,9 @@ public: private: int8_t re, im; uint8_t s; - uint8_t bit_pos, byte_pos = 0; + uint8_t bit_pos = 0, byte_pos = 0; char cur_byte = 0; + char ext_byte = 0; uint16_t gbyte; uint8_t cur_bit = 0; uint32_t sample_count; diff --git a/firmware/baseband-tx/proc_jammer.cpp b/firmware/baseband-tx/proc_jammer.cpp index c2dd47ad..001b503d 100644 --- a/firmware/baseband-tx/proc_jammer.cpp +++ b/firmware/baseband-tx/proc_jammer.cpp @@ -30,7 +30,7 @@ void JammerProcessor::execute(const buffer_c8_t& buffer) { for (size_t i = 0; i= 10000) { //shared_memory.jammer_ranges[ir].duration + if (s >= 10000) { //shared_memory.jammer_ranges[ir].duration s = 0; for (;;) { ir++; diff --git a/firmware/baseband-tx/proc_xylos.cpp b/firmware/baseband-tx/proc_xylos.cpp index 5c4e2069..57bcbf90 100644 --- a/firmware/baseband-tx/proc_xylos.cpp +++ b/firmware/baseband-tx/proc_xylos.cpp @@ -39,7 +39,7 @@ void XylosProcessor::execute(const buffer_c8_t& buffer) { for (size_t i = 0; i= 9) { + if (s >= (5-1)) { s = 0; if (silence) { @@ -78,7 +78,7 @@ void XylosProcessor::execute(const buffer_c8_t& buffer) { re = 0; im = 0; } else { - sample = (sine_table_f32[(aphase & 0x03FF0000)>>18]*255); + sample = (sine_table_f32[(aphase & 0x03FF0000)>>18]*127); // 255 here before :D // Audio preview sample generation: 1536000/48000 = 32 /*if (as >= 31) { @@ -87,15 +87,15 @@ void XylosProcessor::execute(const buffer_c8_t& buffer) { } else { as++; }*/ - + //FM - frq = sample * 500; // To check ! + frq = sample * 1000; // 500 was here phase = (phase + frq); sphase = phase + (256<<16); - re = (sine_table_f32[(sphase & 0x03FF0000)>>18]*127); - im = (sine_table_f32[(phase & 0x03FF0000)>>18]*127); + re = (sine_table_f32[(sphase & 0x03FF0000)>>18]*15); + im = (sine_table_f32[(phase & 0x03FF0000)>>18]*15); } buffer.p[i] = {(int8_t)re,(int8_t)im}; diff --git a/firmware/baseband-tx/proc_xylos.hpp b/firmware/baseband-tx/proc_xylos.hpp index 1a7b2cf3..db5baab0 100644 --- a/firmware/baseband-tx/proc_xylos.hpp +++ b/firmware/baseband-tx/proc_xylos.hpp @@ -31,23 +31,15 @@ #include "audio_output.hpp" #include "baseband_processor.hpp" -#define CCIR_TONELENGTH 15360-1 // 1536000/10/10 -#define PHASEV 436.91 // (65536*1024)/1536000*10 -#define SILENCE 61440-1 // 400ms +#define CCIR_TONELENGTH (15360*2)-1 // 1536000/10/10 +#define PHASEV (436.91/2) // (65536*1024)/1536000*10 +#define SILENCE (46080*2)-1 // 400ms class XylosProcessor : public BasebandProcessor { public: void execute(const buffer_c8_t& buffer) override; private: - /*int16_t audio_data[64]; - - std::array audio; - const buffer_s16_t audio_buffer { - audio.data(), - audio.size() - };*/ - uint32_t ccir_phases[16] = { (uint32_t)(1981*PHASEV), (uint32_t)(1124*PHASEV), diff --git a/firmware/common/modules.h b/firmware/common/modules.h index dfaf5445..33a0f7e4 100644 --- a/firmware/common/modules.h +++ b/firmware/common/modules.h @@ -1,2 +1,2 @@ const char md5_baseband[16] = {0xb8,0x9e,0x9b,0x08,0x44,0x34,0x04,0x20,0x0b,0xbc,0x60,0x7e,0x67,0x88,0x53,0xf7,}; -const char md5_baseband_tx[16] = {0x76,0x21,0x56,0xb0,0x12,0x45,0xdd,0x66,0x87,0xee,0x8a,0x97,0xda,0xee,0xc5,0xac,}; +const char md5_baseband_tx[16] = {0xd5,0xaf,0x76,0xd5,0xa3,0x32,0x5d,0x9a,0x9d,0x83,0x46,0x37,0x02,0x2d,0xd0,0x57,}; diff --git a/firmware/common/portapack_shared_memory.hpp b/firmware/common/portapack_shared_memory.hpp index 1995aadd..7ab097f7 100644 --- a/firmware/common/portapack_shared_memory.hpp +++ b/firmware/common/portapack_shared_memory.hpp @@ -63,6 +63,7 @@ struct SharedMemory { uint8_t afsk_repeat; uint32_t afsk_fmmod; bool afsk_transmit_done; + bool afsk_alt_format; JammerRange jammer_ranges[16]; diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index 2484b3d7..ef161f34 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -916,6 +916,17 @@ void NumberField::paint(Painter& painter) { ); } +bool NumberField::on_key(const KeyEvent key) { + /*if( key == KeyEvent::Select ) { + if( on_select ) { + on_select(*this); + return true; + } + }*/ + + return false; +} + bool NumberField::on_encoder(const EncoderEvent delta) { set_value(value() + (delta * step)); return true; diff --git a/firmware/common/ui_widget.hpp b/firmware/common/ui_widget.hpp index eda09257..11e931f2 100644 --- a/firmware/common/ui_widget.hpp +++ b/firmware/common/ui_widget.hpp @@ -384,6 +384,7 @@ public: void paint(Painter& painter) override; + bool on_key(const KeyEvent key) override; bool on_encoder(const EncoderEvent delta) override; bool on_touch(const TouchEvent event) override; diff --git a/firmware/portapack-h1-firmware.bin b/firmware/portapack-h1-firmware.bin index 74ab82e9..7717ea9c 100644 Binary files a/firmware/portapack-h1-firmware.bin and b/firmware/portapack-h1-firmware.bin differ diff --git a/sdcard/baseband-tx.bin b/sdcard/baseband-tx.bin index f37fb9ee..d7f2a1b1 100644 Binary files a/sdcard/baseband-tx.bin and b/sdcard/baseband-tx.bin differ