diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 4b9641ee..766ac296 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -164,6 +164,7 @@ CPPSRC = main.cpp \ ui_rds.cpp \ ui_lcr.cpp \ ui_whistle.cpp \ + ui_jammer.cpp \ ui_afsksetup.cpp \ ui_console.cpp \ ui_receiver.cpp \ diff --git a/firmware/application/ui_jammer.cpp b/firmware/application/ui_jammer.cpp new file mode 100644 index 00000000..68a6137a --- /dev/null +++ b/firmware/application/ui_jammer.cpp @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * 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_jammer.hpp" +#include "ui_receiver.hpp" + +#include "ch.h" +#include "evtimer.h" + +#include "ff.h" +#include "hackrf_gpio.hpp" +#include "portapack.hpp" +#include "radio.hpp" + +#include "hackrf_hal.hpp" +#include "portapack_shared_memory.hpp" +#include "portapack_persistent_memory.hpp" + +#include +#include + +using namespace hackrf::one; + +namespace ui { + +void JammerView::focus() { + options_preset.focus(); +} + +JammerView::~JammerView() { + transmitter_model.disable(); +} + +void JammerView::paint(Painter& painter) { + +} + +void JammerView::updfreq(uint8_t id, rf::Frequency f) { + char finalstr[25] = {0}; + uint8_t c; + + auto mhz = to_string_dec_int(f / 1000000, 3); + auto hz100 = to_string_dec_int((f / 100) % 10000, 4, '0'); + + strcat(finalstr, mhz.c_str()); + strcat(finalstr, "."); + strcat(finalstr, hz100.c_str()); + strcat(finalstr, "M"); + + while (strlen(finalstr) < 10) { + strcat(finalstr, " "); + } + + if (id == 0) { + range1_min = f; + this->button_setfreq1_min.set_text(finalstr); + } + if (id == 1) { + range1_max = f; + this->button_setfreq1_max.set_text(finalstr); + } + if (id == 2) { + range2_min = f; + this->button_setfreq2_min.set_text(finalstr); + } + if (id == 3) { + range2_max = f; + this->button_setfreq2_max.set_text(finalstr); + } + if (id == 4) { + range3_min = f; + this->button_setfreq3_min.set_text(finalstr); + } + if (id == 5) { + range3_max = f; + this->button_setfreq3_max.set_text(finalstr); + } + + rf::Frequency center; + std::string bw; + + for (c = 0; c < 3; c++) { + if (c == 0) center = (range1_min + range1_max) / 2; + if (c == 1) center = (range2_min + range2_max) / 2; + if (c == 2) center = (range3_min + range3_max) / 2; + + if (c == 0) bw = to_string_dec_int(abs(range1_max - range1_min) / 1000, 5); + if (c == 1) bw = to_string_dec_int(abs(range2_max - range2_min) / 1000, 5); + if (c == 2) bw = to_string_dec_int(abs(range3_max - range3_min) / 1000, 5); + + auto center_mhz = to_string_dec_int(center / 1000000, 4); + auto center_hz100 = to_string_dec_int((center / 100) % 10000, 4, '0'); + + strcpy(finalstr, "C:"); + strcat(finalstr, center_mhz.c_str()); + strcat(finalstr, "."); + strcat(finalstr, center_hz100.c_str()); + strcat(finalstr, "M W:"); + strcat(finalstr, bw.c_str()); + strcat(finalstr, "kHz"); + + while (strlen(finalstr) < 23) { + strcat(finalstr, " "); + } + + if (c == 0) this->text_info1.set(finalstr); + if (c == 1) this->text_info2.set(finalstr); + if (c == 2) this->text_info3.set(finalstr); + } +} + +JammerView::JammerView( + NavigationView& nav, + TransmitterModel& transmitter_model +) : transmitter_model(transmitter_model) +{ + static constexpr Style style_val { + .font = font::fixed_8x16, + .background = Color::green(), + .foreground = Color::black(), + }; + + static constexpr Style style_cancel { + .font = font::fixed_8x16, + .background = Color::red(), + .foreground = Color::black(), + }; + + static constexpr Style style_info { + .font = font::fixed_8x16, + .background = Color::black(), + .foreground = Color::grey(), + }; + + transmitter_model.set_modulation(18); + transmitter_model.set_tuning_frequency(persistent_memory::tuned_frequency()); + + add_children({ { + &text_type, + &options_modulation, + &text_sweep, + &options_sweep, + &text_preset, + &options_preset, + &text_hop, + &options_hop, + &checkbox_range1, + &checkbox_range2, + &checkbox_range3, + &button_setfreq1_min, + &button_setfreq1_max, + &text_info1, + &button_setfreq2_min, + &button_setfreq2_max, + &text_info2, + &button_setfreq3_min, + &button_setfreq3_max, + &text_info3, + &button_transmit, + &button_exit + } }); + + 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_preset.on_change = [this](size_t n, OptionsField::value_t v) { + (void)n; + uint8_t c; + + for (c = 0; c < 3; c++) { + updfreq(c*2, range_presets[v][c].min); + updfreq((c*2)+1, range_presets[v][c].max); + if (c == 0) checkbox_range1.set_value(range_presets[v][c].active); + if (c == 1) checkbox_range2.set_value(range_presets[v][c].active); + if (c == 2) checkbox_range3.set_value(range_presets[v][c].active); + } + }; + + button_setfreq1_min.on_select = [this,&nav](Button&){ + auto new_view = new FrequencyKeypadView { nav, 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 }; + new_view->on_changed = [this](rf::Frequency f) { + updfreq(1, f); + }; + nav.push(new_view); + }; + + button_transmit.on_select = [this,&transmitter_model](Button&){ + /*uint16_t c; + ui::Context context; + + make_frame(); + + shared_memory.afsk_samples_per_bit = 228000/persistent_memory::afsk_bitrate(); + shared_memory.afsk_phase_inc_mark = persistent_memory::afsk_mark_freq()*(65536*1024)/2280; + shared_memory.afsk_phase_inc_space = persistent_memory::afsk_space_freq()*(65536*1024)/2280; + + for (c = 0; c < 256; c++) { + shared_memory.lcrdata[c] = this->lcrframe[c]; + } + + shared_memory.afsk_transmit_done = false; + shared_memory.afsk_repeat = 5; // DEFAULT + + text_status.set("Send...");*/ + + if (jamming == true) { + jamming = false; + button_transmit.set_style(&style_val); + button_transmit.set_text("START"); + transmitter_model.disable(); + } else { + jamming = true; + button_transmit.set_style(&style_cancel); + button_transmit.set_text("STOP"); + transmitter_model.enable(); + } + }; + + button_exit.on_select = [&nav](Button&){ + nav.pop(); + }; + +} + +} /* namespace ui */ diff --git a/firmware/application/ui_jammer.hpp b/firmware/application/ui_jammer.hpp new file mode 100644 index 00000000..d74ffc86 --- /dev/null +++ b/firmware/application/ui_jammer.hpp @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * 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" +#include "ui_font_fixed_8x16.hpp" +#include "clock_manager.hpp" +#include "message.hpp" +#include "rf_path.hpp" +#include "max2837.hpp" +#include "volume.hpp" +#include "transmitter_model.hpp" + +namespace ui { + +class JammerView : public View { +public: + JammerView(NavigationView& nav, TransmitterModel& transmitter_model); + ~JammerView(); + + void updfreq(uint8_t id, rf::Frequency f); + void focus() override; + void paint(Painter& painter) override; + +private: + rf::Frequency range1_min; + rf::Frequency range1_max; + rf::Frequency range2_min; + rf::Frequency range2_max; + rf::Frequency range3_min; + rf::Frequency range3_max; + + typedef struct rangepreset { + bool active; + rf::Frequency min; + rf::Frequency max; + } rangepreset; + + const rangepreset range_presets[8][3] = { + // Orange + {{ true, 935000000, 945000000 }, // GSM 900 + { true, 1808000000, 1832000000 }, // GSM 1800 + { true, 2154900000, 2169700000 }}, // UMTS + + // SFR + {{ true, 950000000, 960000000 }, // GSM 900 + { true, 1832000000, 1853000000 }, // GSM 1800 + { true, 2110500000, 2125300000 }}, // UMTS + + // Bouygues + {{ true, 925000000, 935000000 }, // GSM 900 + { true, 1858000000, 1880000000 }, // GSM 1800 + { true, 2125300000, 2140100000 }}, // UMTS + + // Free + {{ true, 945000000, 950000000 }, // GSM 900 + { false, 0, 0 }, // GSM 1800 + { true, 2144900000, 2149900000 }}, // UMTS + + // GSM-R + {{ true, 921000000, 925000000 }, // GSM 900 + { false, 0, 0 }, // GSM 1800 + { false, 0, 0 }}, // UMTS + + // TODO: TDD UMTS, voir doc Arcep + // TODO: Wi-FI, BT: 2 400 et 2 483,5 MHz + + // DECT + {{ true, 1880000000, 1900000000 }, // BW: 20MHz + { false, 0, 0 }, + { false, 0, 0 }}, + + // Optifib, lol + {{ true, 162930000, 162970000 }, // BW: 40kHz + { false, 0, 0 }, + { false, 0, 0 }}, + + // ISM 433 + {{ true, 433050000, 434790000 }, // BW: 0.2% + { false, 0, 0 }, + { false, 0, 0 }} + + }; + + bool jamming = false; + rf::Frequency f; + TransmitterModel& transmitter_model; + + Text text_type { + { 1 * 8, 1 * 16, 40, 16 }, + "Type:" + }; + OptionsField options_modulation { + { 7 * 8, 1 * 16 }, + 4, + { + { "Ramp ", 0 }, + { "FM ", 1 }, + { "PSK ", 2 }, + { "Tones", 3 } + } + }; + + Text text_sweep { + { 1 * 8, 2 * 16, 6 * 8, 16 }, + "Sweep:" + }; + OptionsField options_sweep { + { 8 * 8, 2 * 16 }, + 8, + { + { " 1Hz", 0 }, + { " 10Hz", 1 }, + { "100Hz", 2 }, + { " 1kHz", 3 }, + { " 5kHz", 4 }, + { "10kHz", 5 }, + { "20kHz", 6 }, + { "50kHz", 7 } + } + }; + + Text text_hop { + { 1 * 8, 4 * 16, 10 * 8, 16 }, + "Range hop:" + }; + OptionsField options_hop { + { 12 * 8, 4 * 16 }, + 6, + { + { " 10s", 0 }, + { " 5s", 1 }, + { " 1s", 2 }, + { " 0.1s", 3 }, + { " 10ms", 4 }, + { " 1ms", 5 } + } + }; + + Text text_preset { + { 1 * 8, 3 * 16, 8 * 8, 16 }, + "Presets:" + }; + OptionsField options_preset { + { 10 * 8, 3 * 16 }, + 8, + { + { "Orange ", 0 }, + { "SFR ", 1 }, + { "Bouygues", 2 }, + { "Free ", 3 }, + { "GSM-R ", 4 }, + { "DECT ", 5 }, + { "Optifib ", 6 }, + { "ISM 433 ", 7 }, + } + }; + + Checkbox checkbox_range1 { + { 1 * 8, 6 * 16}, + "Range 1" + }; + Checkbox checkbox_range2 { + { 1 * 8, 9 * 16 + 4}, + "Range 2" + }; + Checkbox checkbox_range3 { + { 1 * 8, 12 * 16 + 8 }, + "Range 3" + }; + + Button button_setfreq1_min { + { 13 * 8, 6 * 16 - 4 - 1, 11 * 8, 18 }, + "----.----M" + }; + Button button_setfreq1_max { + { 13 * 8, 7 * 16 - 4, 11 * 8, 18 }, + "----.----M" + }; + Text text_info1 { + { 3 * 8, 8 * 16 - 4 + 2, 25 * 8, 16 }, + "C:----.----M W:-----kHz" + }; + + Button button_setfreq2_min { + { 13 * 8, 9 * 16 - 1, 11 * 8, 18 }, + "----.----M" + }; + Button button_setfreq2_max { + { 13 * 8, 10 * 16, 11 * 8, 18 }, + "----.----M" + }; + Text text_info2 { + { 3 * 8, 11 * 16 + 2, 25 * 8, 16 }, + "C:----.----M W:-----kHz" + }; + + Button button_setfreq3_min { + { 13 * 8, 12 * 16 + 4 - 1, 11 * 8, 18 }, + "----.----M" + }; + Button button_setfreq3_max { + { 13 * 8, 13 * 16 + 4, 11 * 8, 18 }, + "----.----M" + }; + Text text_info3 { + { 3 * 8, 14 * 16 + 4 + 2, 25 * 8, 16 }, + "C:----.----M W:-----kHz" + }; + + Button button_transmit { + { 2 * 8, 16 * 16, 64, 32 }, + "START" + }; + + Button button_exit { + { 21 * 8, 16 * 16, 64, 32 }, + "Exit" + }; +}; + +} /* namespace ui */ diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 651bf4a0..5b2e65d4 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -33,6 +33,7 @@ #include "ui_rds.hpp" #include "ui_lcr.hpp" #include "ui_whistle.hpp" +#include "ui_jammer.hpp" #include "portapack.hpp" #include "m4_startup.hpp" @@ -105,7 +106,7 @@ SystemMenuView::SystemMenuView(NavigationView& nav) { add_items<10>({ { { "Play dead", ui::Color::red(), [&nav](){ nav.push(new PlayDeadView { nav, false }); } }, { "Receiver", ui::Color::white(), [&nav](){ nav.push(new ReceiverView { nav, receiver_model }); } }, - { "Capture", ui::Color::white(), [&nav](){ nav.push(new NotImplementedView { nav }); } }, + { "Jammer", ui::Color::white(), [&nav](){ nav.push(new JammerView { nav, transmitter_model }); } }, { "Whistle", ui::Color::white(), [&nav](){ nav.push(new WhistleView { nav, transmitter_model }); } }, { "RDS TX", ui::Color::yellow(), [&nav](){ nav.push(new RDSView { nav, transmitter_model }); } }, { "LCR TX", ui::Color::orange(), [&nav](){ nav.push(new LCRView { nav, transmitter_model }); } }, diff --git a/firmware/application/ui_whistle.cpp b/firmware/application/ui_whistle.cpp index 76ee53a6..9cc180bc 100644 --- a/firmware/application/ui_whistle.cpp +++ b/firmware/application/ui_whistle.cpp @@ -76,7 +76,6 @@ WhistleView::WhistleView( transmitter_model.set_tuning_frequency(persistent_memory::tuned_frequency()); add_children({ { - &button_scan, &button_transmit, &button_exit } }); @@ -98,17 +97,17 @@ WhistleView::WhistleView( shared_memory.afsk_transmit_done = false; shared_memory.afsk_repeat = 5; // DEFAULT - text_status.set("Send..."); + text_status.set("Send...");*/ - transmitter_model.enable();*/ + transmitter_model.enable(); }; button_exit.on_select = [&nav](Button&){ nav.pop(); }; - static VirtualTimer vt1; - msg_t msg, result; + //static VirtualTimer vt1; + //msg_t msg, result; /*static EvTimer evt; static EventListener el0; @@ -119,14 +118,14 @@ WhistleView::WhistleView( //chVTSet(&vt1, MS2ST(2000), whistle_th, (void *)&mbox); - while(1) { + //while(1) { /*result = chMBFetch(&mbox, &msg, TIME_INFINITE); if(result == RDY_OK) { if(msg & 1) button_scan.set_text("POUET"); }*/ - chThdSleepMilliseconds(500); - } + //chThdSleepMilliseconds(500); + //} } diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index 660bd935..73257bcf 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -889,6 +889,71 @@ private: int32_t sample, sig, frq; }; +#define POLY_MASK_32 0xB4BCD35C + +class JammerProcessor : public BasebandProcessor { +public: + void execute(buffer_c8_t buffer) override { + + for (size_t i = 0; i 3000000) { + s = 0; + feedback = lfsr & 1; + lfsr >>= 1; + if (feedback == 1) + lfsr ^= POLY_MASK_32; + } else { + s++; + } + + aphase += lfsr;*/ + + /*if (s >= 10) { + s = 0; + aphase += 353205; // DEBUG + } else { + s++; + } + + sample = sintab[(aphase & 0x03FF0000)>>16];*/ + + if (s >= 10) { + if (sample < 128) + sample++; + else + sample = -127; + s = 0; + } else { + s++; + } + + //FM + frq = sample << 17; // Bandwidth + + //65536 -> 0.6M + //131072 -> 1.2M + + phase = (phase + frq); + sphase = phase + (256<<16); + + re = sintab[(sphase & 0x03FF0000)>>16]; + im = sintab[(phase & 0x03FF0000)>>16]; + + buffer.p[i] = {(int8_t)re,(int8_t)im}; + } + } + +private: + int32_t s, lfsr32 = 0xABCDE; + int8_t re, im; + int feedback; + int32_t lfsr; + uint32_t sample_count; + uint32_t aphase, phase, sphase; + int32_t sample, frq; +}; + static BasebandProcessor* baseband_processor { nullptr }; static BasebandConfiguration baseband_configuration; @@ -1163,6 +1228,11 @@ int main(void) { direction = baseband::Direction::Transmit; baseband_processor = new ToneProcessor(); break; + + case 18: + direction = baseband::Direction::Transmit; + baseband_processor = new JammerProcessor(); + break; default: break; diff --git a/firmware/common/ui.hpp b/firmware/common/ui.hpp index 862d3495..a61e3d08 100644 --- a/firmware/common/ui.hpp +++ b/firmware/common/ui.hpp @@ -83,6 +83,10 @@ struct Color { static constexpr Color white() { return { 255, 255, 255 }; } + + static constexpr Color grey() { + return { 127, 127, 127 }; + } }; #if 0 enum class CardinalDirection : uint8_t { diff --git a/firmware/portapack-h1-firmware.bin b/firmware/portapack-h1-firmware.bin index 9d94eb64..a61a5540 100644 Binary files a/firmware/portapack-h1-firmware.bin and b/firmware/portapack-h1-firmware.bin differ