diff --git a/firmware/application/external/jammer/ui_jammer.hpp b/firmware/application/external/jammer/ui_jammer.hpp index 3a34dbf2c..73b2d9dcd 100644 --- a/firmware/application/external/jammer/ui_jammer.hpp +++ b/firmware/application/external/jammer/ui_jammer.hpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. * Copyright (C) 2016 Furrtek + * Copyright (C) 2025 RocketGod - Added modes from my Flipper Zero RF Jammer App - https://betaskynet.com * * This file is part of PortaPack. * @@ -150,12 +151,17 @@ class JammerView : public View { OptionsField options_type{ {7 * 8, 23 * 8}, 8, - { - {"Rand FSK", 0}, - {"FM tone", 1}, - {"CW sweep", 2}, - {"Rand CW", 3}, - }}; + {{"Rand FSK", 0}, + {"FM tone", 1}, + {"CW sweep", 2}, + {"Noise", 3}, + {"Sine", 4}, + {"Square", 5}, + {"Sawtooth", 6}, + {"Triangle", 7}, + {"Chirp", 8}, + {"Gauss", 9}, + {"Brute", 10}}}; Text text_range_number{ {16 * 8, 23 * 8, 2 * 8, 16}, diff --git a/firmware/baseband/proc_jammer.cpp b/firmware/baseband/proc_jammer.cpp index 893e49035..cce46029a 100644 --- a/firmware/baseband/proc_jammer.cpp +++ b/firmware/baseband/proc_jammer.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. * Copyright (C) 2016 Furrtek + * Copyright (C) 2025 RocketGod - Added modes from my Flipper Zero RF Jammer App - https://betaskynet.com * * This file is part of PortaPack. * @@ -26,22 +27,26 @@ #include "event_m4.hpp" #include +#include +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846f +#endif void JammerProcessor::execute(const buffer_c8_t& buffer) { if (!configured) return; for (size_t i = 0; i < buffer.count; i++) { if (!jammer_duration) { - // Find next enabled range do { current_range++; if (current_range == JAMMER_MAX_CH) current_range = 0; } while (!jammer_channels[current_range].enabled); jammer_duration = jammer_channels[current_range].duration; - jammer_bw = jammer_channels[current_range].width / 2; // TODO: Exact value + jammer_bw = jammer_channels[current_range].width / 2; - // Ask for retune message.freq = jammer_channels[current_range].center; message.range = current_range; shared_memory.application_queue.push(message); @@ -49,26 +54,51 @@ void JammerProcessor::execute(const buffer_c8_t& buffer) { jammer_duration--; } - // Phase noise if (!period_counter) { period_counter = noise_period; - if (noise_type == JammerType::TYPE_FSK) { + if (noise_type == jammer::JammerType::TYPE_FSK) { sample = (sample + lfsr) >> 1; - } else if (noise_type == JammerType::TYPE_TONE) { - tone_delta = 150000 + (lfsr >> 9); // Approx 100Hz to 6kHz - } else if (noise_type == JammerType::TYPE_SWEEP) { - sample++; // This is like saw wave FM + } else if (noise_type == jammer::JammerType::TYPE_TONE) { + tone_delta = 150000 + (lfsr >> 9); + } else if (noise_type == jammer::JammerType::TYPE_SWEEP) { + sample++; + } else if (noise_type == jammer::JammerType::TYPE_RANDOM) { + sample = lfsr & 0xFF; + } else if (noise_type == jammer::JammerType::TYPE_SINE) { + wave_phase += 0x01000000; + sample = sine_table_i8[(wave_phase >> 24) & 0xFF]; + } else if (noise_type == jammer::JammerType::TYPE_SQUARE) { + wave_index = (wave_index + 1) % 2; + sample = wave_index ? 127 : -128; + } else if (noise_type == jammer::JammerType::TYPE_SAWTOOTH) { + wave_index = (wave_index + 1) % 256; + sample = (wave_index * 127) / 255 - 128; + } else if (noise_type == jammer::JammerType::TYPE_TRIANGLE) { + wave_index = (wave_index + 1) % 256; + sample = (wave_index < 128 ? wave_index : (255 - wave_index)) * 127 / 127 - 128; + } else if (noise_type == jammer::JammerType::TYPE_CHIRP) { + chirp_freq += 0.01f; + if (chirp_freq > 1.0f) chirp_freq = 0.0f; + wave_phase += static_cast(0x01000000 * (1.0f + chirp_freq)); + sample = sine_table_i8[(wave_phase >> 24) & 0xFF]; + } else if (noise_type == jammer::JammerType::TYPE_GAUSSIAN) { + float u1 = static_cast(lfsr & 0xFFFF) / 0x10000; + float u2 = static_cast((lfsr >> 16) & 0xFFFF) / 0x10000; + float gaussian = std::sqrt(-2.0f * std::log(u1)) * std::cos(2 * M_PI * u2); + sample = static_cast(gaussian * 32); + } else if (noise_type == jammer::JammerType::TYPE_BRUTEFORCE) { + sample = 127; } feedback = ((lfsr >> 31) ^ (lfsr >> 29) ^ (lfsr >> 15) ^ (lfsr >> 11)) & 1; lfsr = (lfsr << 1) | feedback; - if (!lfsr) lfsr = 0x1337; // Shouldn't do this :( + if (!lfsr) lfsr = 0x1337; } else { period_counter--; } - if (noise_type == JammerType::TYPE_TONE) { + if (noise_type == jammer::JammerType::TYPE_TONE) { aphase += tone_delta; sample = sine_table_i8[(aphase & 0xFF000000) >> 24]; } @@ -78,12 +108,12 @@ void JammerProcessor::execute(const buffer_c8_t& buffer) { phase += delta; sphase = phase + (64 << 24); - re = (sine_table_i8[(sphase & 0xFF000000) >> 24]); - im = (sine_table_i8[(phase & 0xFF000000) >> 24]); + re = sine_table_i8[(sphase & 0xFF000000) >> 24]; + im = sine_table_i8[(phase & 0xFF000000) >> 24]; buffer.p[i] = {re, im}; } -}; +} void JammerProcessor::on_message(const Message* const msg) { if (msg->id == Message::ID::JammerConfigure) { @@ -93,12 +123,18 @@ void JammerProcessor::on_message(const Message* const msg) { jammer_channels = (JammerChannel*)shared_memory.bb_data.data; noise_type = message.type; noise_period = 3072000 / message.speed; - if (noise_type == JammerType::TYPE_SWEEP) + if (noise_type == jammer::JammerType::TYPE_SWEEP || noise_type == jammer::JammerType::TYPE_SINE || + noise_type == jammer::JammerType::TYPE_SQUARE || noise_type == jammer::JammerType::TYPE_SAWTOOTH || + noise_type == jammer::JammerType::TYPE_TRIANGLE || noise_type == jammer::JammerType::TYPE_CHIRP || + noise_type == jammer::JammerType::TYPE_GAUSSIAN || noise_type == jammer::JammerType::TYPE_BRUTEFORCE) noise_period >>= 8; period_counter = 0; jammer_duration = 0; current_range = 0; lfsr = 0xDEAD0012; + wave_phase = 0; + wave_index = 0; + chirp_freq = 0.0f; configured = true; } else { diff --git a/firmware/baseband/proc_jammer.hpp b/firmware/baseband/proc_jammer.hpp index e9fa45c5d..2919bae21 100644 --- a/firmware/baseband/proc_jammer.hpp +++ b/firmware/baseband/proc_jammer.hpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. * Copyright (C) 2016 Furrtek + * Copyright (C) 2025 RocketGod - Added modes from my Flipper Zero RF Jammer App - https://betaskynet.com * * This file is part of PortaPack. * @@ -27,6 +28,8 @@ #include "baseband_thread.hpp" #include "portapack_shared_memory.hpp" #include "jammer.hpp" +#include +#include using namespace jammer; @@ -50,9 +53,11 @@ class JammerProcessor : public BasebandProcessor { uint32_t aphase{0}, phase{0}, delta{0}, sphase{0}; int8_t sample{0}; int8_t re{0}, im{0}; + uint32_t wave_phase{0}; + uint32_t wave_index{0}; + float chirp_freq{0.0f}; RetuneMessage message{}; - /* NB: Threads should be the last members in the class definition. */ BasebandThread baseband_thread{3072000, this, baseband::Direction::Transmit}; }; diff --git a/firmware/common/jammer.hpp b/firmware/common/jammer.hpp index 29fadde8d..3c3072b66 100644 --- a/firmware/common/jammer.hpp +++ b/firmware/common/jammer.hpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. * Copyright (C) 2016 Furrtek + * Copyright (C) 2025 RocketGod - Added modes from my Flipper Zero RF Jammer App - https://betaskynet.com * * This file is part of PortaPack. * @@ -20,12 +21,12 @@ * Boston, MA 02110-1301, USA. */ -#define JAMMER_CH_WIDTH 1000000 -#define JAMMER_MAX_CH 24 - #ifndef __JAMMER_H__ #define __JAMMER_H__ +#define JAMMER_CH_WIDTH 1000000 +#define JAMMER_MAX_CH 24 + namespace jammer { typedef struct jammer_range { @@ -37,7 +38,15 @@ typedef struct jammer_range { enum JammerType : uint32_t { TYPE_FSK = 0, TYPE_TONE = 1, - TYPE_SWEEP = 2 + TYPE_SWEEP = 2, + TYPE_RANDOM = 3, + TYPE_SINE = 4, + TYPE_SQUARE = 5, + TYPE_SAWTOOTH = 6, + TYPE_TRIANGLE = 7, + TYPE_CHIRP = 8, + TYPE_GAUSSIAN = 9, + TYPE_BRUTEFORCE = 10 }; } /* namespace jammer */