/* * 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_jammer.hpp" #include "ui_receiver.hpp" #include "baseband_api.hpp" #include "string_format.hpp" #include "portapack_shared_memory.hpp" #include "portapack_persistent_memory.hpp" #include #include using namespace portapack; namespace ui { void JammerView::focus() { options_preset.focus(); } JammerView::~JammerView() { transmitter_model.disable(); baseband::shutdown(); } void JammerView::update_text(uint8_t id, rf::Frequency f) { char finalstr[25] = {0}; rf::Frequency center; std::string bw; 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, " "); buttons_freq[id].set_text(finalstr); */ for (c = 0; c < 3; c++) { center = (frequency_range[c].min + frequency_range[c].max) / 2; bw = to_string_dec_int(abs(frequency_range[c].max - frequency_range[c].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) text_info1.set(finalstr); if (c == 1) text_info2.set(finalstr); if (c == 2) text_info3.set(finalstr); } } void JammerView::on_retune(const int64_t freq) { if (freq > 0) transmitter_model.set_tuning_frequency(freq); } JammerView::JammerView(NavigationView& nav) { size_t n; baseband::run_image(portapack::spi_flash::image_tag_jammer); 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(), }; JammerRange * jammer_ranges = (JammerRange*)shared_memory.bb_data.data; add_children({ &text_type, &options_modulation, &text_sweep, &options_sweep, &text_preset, &options_preset, &text_hop, &options_hop, &checkbox_range1, &checkbox_range2, &checkbox_range3, &text_info1, &text_info2, &text_info3, &button_transmit, &button_exit }); const auto button_freq_fn = [this, &nav](Button& button) { uint16_t id = button.id; rf::Frequency * value_ptr; if (id & 1) value_ptr = &frequency_range[id].max; else value_ptr = &frequency_range[id].min; auto new_view = nav.push(*value_ptr); new_view->on_changed = [this, value_ptr](rf::Frequency f) { *value_ptr = f; }; }; n = 0; for (auto& button : buttons_freq) { button.on_select = button_freq_fn; button.set_parent_rect({ static_cast(13 * 8), static_cast(((n >> 1) * 52) + 90 + (18 * (n & 1))), 88, 18 }); button.id = n; button.set_text("----.----M"); add_child(&button); 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_preset.on_change = [this](size_t n, OptionsField::value_t v) { (void)n; for (uint8_t c = 0; c < 3; c++) { frequency_range[c].min = range_presets[v][c].min; frequency_range[c].max = range_presets[v][c].max; } 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); // Sigfox, because they deserve it button_transmit.on_select = [this, &nav, jammer_ranges](Button&) { uint8_t c, i = 0; size_t num_ranges; rf::Frequency start_freq, range_bw, ch_width; bool out_of_ranges = false; // Disable all ranges by default for (i = 0; i < 9; i++) jammer_ranges[i].enabled = false; // Generate jamming "channels", maximum: 9 // Convert ranges min/max to center/bw for (c = 0; c < 3; c++) { range_bw = abs(frequency_range[c].max - frequency_range[c].min); // Total bw for range if (frequency_range[c].min < frequency_range[c].max) start_freq = frequency_range[c].min; else start_freq = frequency_range[c].max; if (range_bw > 500000) { // Example: 600kHz // int(600000 / 500000) = 2 // CH-BW = 600000 / 2 = 300000 // Center-A = min + CH-BW / 2 = 150000 // BW-A = CH-BW = 300000 // Center-B = min + CH-BW + Center-A = 450000 // BW-B = CH-BW = 300000 num_ranges = 0; while (range_bw > 500000) { range_bw -= 500000; num_ranges++; } ch_width = range_bw / num_ranges; for (c = 0; c < num_ranges; 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 = 2280000 / 10; // ? 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 = 2280000 / 10; // ? i++; } } if (!out_of_ranges) { if (jamming == true) { jamming = false; button_transmit.set_style(&style_val); button_transmit.set_text("START"); radio::disable(); } else { jamming = true; button_transmit.set_style(&style_cancel); button_transmit.set_text("STOP"); //transmitter_model.set_tuning_frequency(433920000); // TODO transmitter_model.set_sampling_rate(1536000U); transmitter_model.set_rf_amp(true); transmitter_model.set_baseband_bandwidth(1750000); transmitter_model.enable(); } } else { nav.display_modal("Error", "Jamming bandwidth too high."); } } }; button_exit.on_select = [&nav](Button&){ nav.pop(); }; } } /* namespace ui */