diff --git a/firmware/application/bitmap.hpp b/firmware/application/bitmap.hpp index b61e3d55..7219c7e9 100644 --- a/firmware/application/bitmap.hpp +++ b/firmware/application/bitmap.hpp @@ -117,6 +117,20 @@ static constexpr Bitmap bitmap_icon_unistroke { { 16, 16 }, bitmap_icon_unistroke_data }; +static constexpr uint8_t bitmap_stripes_data[] = { + 0xFF, 0x03, 0xC0, + 0xFF, 0x01, 0xE0, + 0xFF, 0x00, 0xF0, + 0x7F, 0x00, 0xF8, + 0x3F, 0x00, 0xFC, + 0x1F, 0x00, 0xFE, + 0x0F, 0x00, 0xFF, + 0x07, 0x80, 0xFF, +}; +static constexpr Bitmap bitmap_stripes { + { 24, 8 }, bitmap_stripes_data +}; + static constexpr uint8_t bitmap_icon_adsb_data[] = { 0x80, 0x01, 0xC0, 0x03, diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index c29a619c..736689d1 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -23,7 +23,8 @@ // Color bitmaps generated with: // Gimp image > indexed colors (16), then "xxd -i *.bmp" -//BUG: POCSAG TX: Chops off the few last chars on long messages ? +//BUG: RDS Radiotext is not recognized in Redsea (and car radio) +//BUG: POCSAG TX: Chops off the last few chars on long messages ? //BUG: (fixed ?) POCSAG: Bad console scroll init //BUG: (fixed ?) POCSAG misses alphanum messages, cuts them off sometimes //BUG: Check AFSK transmit end, skips last bits ? @@ -32,7 +33,7 @@ //TEST: Imperial in whipcalc //TEST: Numbers -//TODO: Use TransmitterView everywhere possible +//TODO: Use TransmitterView in ADSB, Morse, TEDI/LCR, Numbers, whistle, jammer... //TODO: FreqMan: Add and rename categories //TODO: FreqMan: Sort by category in edit screen //TODO: FreqMan: Cap entry count per category (only done for total entries right now) diff --git a/firmware/application/pocsag_app.hpp b/firmware/application/pocsag_app.hpp index 80d1665d..3038b512 100644 --- a/firmware/application/pocsag_app.hpp +++ b/firmware/application/pocsag_app.hpp @@ -57,9 +57,6 @@ public: ~POCSAGAppView(); void set_parent_rect(const Rect new_parent_rect) override; - - void paint(Painter&) override { }; - void focus() override; std::string title() const override { return "POCSAG RX"; }; diff --git a/firmware/application/ui_alphanum.cpp b/firmware/application/ui_alphanum.cpp index 1031ebe7..2de5c0ca 100644 --- a/firmware/application/ui_alphanum.cpp +++ b/firmware/application/ui_alphanum.cpp @@ -31,9 +31,8 @@ using namespace hackrf::one; namespace ui { - -void AlphanumView::paint(Painter& painter) { - (void)painter; + +void AlphanumView::paint(Painter&) { move_cursor(); } @@ -43,21 +42,8 @@ AlphanumView::AlphanumView( size_t max_length ) : _max_length(max_length) { - _lowercase = false; size_t n; - static constexpr Style style_alpha { - .font = font::fixed_8x16, - .background = Color::black(), - .foreground = Color(255, 63, 63) - }; - - static constexpr Style style_num { - .font = font::fixed_8x16, - .background = Color::black(), - .foreground = Color(191, 191, 31) - }; - txtidx = strlen(txt); memcpy(txtinput, txt, _max_length + 1); n = txtidx; @@ -68,8 +54,9 @@ AlphanumView::AlphanumView( add_children({ &text_input, - &button_lowercase, - &raw_char, + &button_mode, + &text_raw, + &field_raw, &button_ok }); @@ -82,33 +69,21 @@ AlphanumView::AlphanumView( button.on_select = button_fn; button.set_parent_rect({ static_cast((n % 5) * (240 / 5)), - static_cast((n / 5) * 28 + 24), - 240 / 5, 28 + static_cast((n / 5) * 38 + 24), + 240 / 5, 38 }); - if ((n < 10) || (n == 39)) - button.set_style(&style_num); - else - button.set_style(&style_alpha); add_child(&button); n++; } - set_keys(keys_upper); + set_mode(mode); - button_lowercase.on_select = [this, &nav](Button&) { - if (_lowercase == true) { - _lowercase = false; - button_lowercase.set_text("UC"); - set_keys(keys_upper); - } else { - _lowercase = true; - button_lowercase.set_text("LC"); - set_keys(keys_lower); - } + button_mode.on_select = [this, &nav](Button&) { + set_mode(mode + 1); }; - raw_char.set_value('0'); - raw_char.on_select = [this, &nav](NumberField&) { - char_add(raw_char.value()); + field_raw.set_value('0'); + field_raw.on_select = [this, &nav](NumberField&) { + char_add(field_raw.value()); update_text(); }; @@ -124,7 +99,7 @@ AlphanumView::AlphanumView( void AlphanumView::move_cursor() { Point cursor_pos; - cursor_pos = {text_input.screen_rect().location().x() + (txtidx * 8), + cursor_pos = {text_input.screen_rect().location().x() + (Coord)(txtidx * 8), text_input.screen_rect().location().y() + 16}; portapack::display.fill_rectangle( @@ -137,9 +112,16 @@ void AlphanumView::move_cursor() { ); } -void AlphanumView::set_keys(const char * const key_list) { +void AlphanumView::set_mode(const uint32_t new_mode) { size_t n = 0; + if (new_mode < 3) + mode = new_mode; + else + mode = 0; + + const char * key_list = pages[mode].second; + for (auto& button : buttons) { const std::string label { key_list[n] @@ -147,6 +129,11 @@ void AlphanumView::set_keys(const char * const key_list) { button.set_text(label); n++; } + + if (mode < 2) + button_mode.set_text(pages[mode + 1].first); + else + button_mode.set_text(pages[0].first); } void AlphanumView::focus() { diff --git a/firmware/application/ui_alphanum.hpp b/firmware/application/ui_alphanum.hpp index 92f73d93..da898362 100644 --- a/firmware/application/ui_alphanum.hpp +++ b/firmware/application/ui_alphanum.hpp @@ -52,17 +52,24 @@ public: std::string title() const override { return "Text entry"; }; private: - const char * const keys_upper = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ. !<"; - const char * const keys_lower = "0123456789abcdefghijklmnopqrstuvwxyz:=?<"; + const char * const keys_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ' .<"; + const char * const keys_lower = "abcdefghijklmnopqrstuvwxyz' .<"; + const char * const keys_digit = "0123456789!\"#'()*+-/:;=>?@[\\]<"; + + const std::pair pages[3] = { + { "Upper", keys_upper }, + { "Lower", keys_lower }, + { "Digit", keys_digit } + }; size_t _max_length { }; - uint8_t txtidx { 0 }; - bool _lowercase = false; + uint32_t txtidx { 0 }; + uint32_t mode = 0; // Upper char txtinput[29] = { 0 }; // 28 chars max void char_add(const char c); void char_delete(); - void set_keys(const char * const key_list); + void set_mode(const uint32_t new_mode); void move_cursor(); void on_button(Button& button); void update_text(); @@ -71,15 +78,19 @@ private: { 8, 0, 232, 16 } }; - std::array buttons { }; + std::array buttons { }; - Button button_lowercase { - { 21 * 8, 270, 32, 24 }, - "UC" + Button button_mode { + { 21 * 8, 33 * 8, 8 * 8, 32 }, + "" }; - NumberField raw_char { - { 16, 270 }, + Text text_raw { + { 1 * 8, 33 * 8, 4 * 8, 16 }, + "Raw:" + }; + NumberField field_raw { + { 5 * 8, 33 * 8 }, 3, { 1, 255 }, 1, @@ -87,7 +98,7 @@ private: }; Button button_ok { - { 88, 270, 64, 24 }, + { 10 * 8, 33 * 8, 9 * 8, 32 }, "OK" }; }; diff --git a/firmware/application/ui_encoders.cpp b/firmware/application/ui_encoders.cpp index 85c0e044..2785b5bf 100644 --- a/firmware/application/ui_encoders.cpp +++ b/firmware/application/ui_encoders.cpp @@ -143,6 +143,7 @@ void EncodersView::on_txdone(int n, const bool txdone) { tx_mode = IDLE; text_status.set("Done"); progress.set_value(0); + tx_view.set_transmitting(false); //} } } @@ -154,6 +155,7 @@ void EncodersView::on_tuning_frequency_changed(rf::Frequency f) { void EncodersView::start_tx(const bool scan) { char ook_bitstream[256]; uint32_t ook_bitstream_length; + (void)scan; /*if (scan) { if (tx_mode != SCAN) { @@ -263,7 +265,6 @@ EncodersView::EncodersView(NavigationView& nav) { encoder_def = &encoder_defs[0]; add_children({ - &field_frequency, &text_enctype, &options_enctype, &text_clk, @@ -284,23 +285,9 @@ EncodersView::EncodersView(NavigationView& nav) { &waveform, &text_status, &progress, - &button_transmit + &tx_view }); - field_frequency.set_value(transmitter_model.tuning_frequency()); - field_frequency.set_step(50000); - field_frequency.on_change = [this](rf::Frequency f) { - this->on_tuning_frequency_changed(f); - }; - field_frequency.on_edit = [this, &nav]() { - // TODO: Provide separate modal method/scheme? - auto new_view = nav.push(transmitter_model.tuning_frequency()); - new_view->on_changed = [this](rf::Frequency f) { - this->on_tuning_frequency_changed(f); - this->field_frequency.set_value(f); - }; - }; - // Load encoder types for (i = 0; i < ENC_TYPES_COUNT; i++) enc_options.emplace_back(std::make_pair(encoder_defs[i].name, i)); @@ -317,8 +304,6 @@ EncodersView::EncodersView(NavigationView& nav) { this->generate_frame(); }; - button_transmit.set_style(&style_val); - // Selecting input clock changes symbol and word duration numberfield_clk.on_change = [this](int32_t value) { //int32_t new_value = 1000000 / (((float)value * 1000) / encoder_def->clk_per_symbol); @@ -347,9 +332,21 @@ EncodersView::EncodersView(NavigationView& nav) { numberfield_clk.set_value(1000000 / (((float)new_value * 1000) / encoder_def->clk_per_symbol), false); } }; - - button_transmit.on_select = [this, &nav](Button&) { - if (tx_mode == IDLE) start_tx(false); + + tx_view.on_edit_frequency = [this, &nav]() { + auto new_view = nav.push(receiver_model.tuning_frequency()); + new_view->on_changed = [this](rf::Frequency f) { + receiver_model.set_tuning_frequency(f); + }; + }; + + tx_view.on_start = [this]() { + tx_view.set_transmitting(true); + start_tx(false); + }; + + tx_view.on_stop = [this]() { + tx_view.set_transmitting(false); }; } diff --git a/firmware/application/ui_encoders.hpp b/firmware/application/ui_encoders.hpp index f91ac704..82354a58 100644 --- a/firmware/application/ui_encoders.hpp +++ b/firmware/application/ui_encoders.hpp @@ -25,6 +25,7 @@ #include "ui_navigation.hpp" #include "ui_font_fixed_8x16.hpp" #include "ui_receiver.hpp" +#include "ui_transmitter.hpp" #include "encoders.hpp" #include "message.hpp" #include "transmitter_model.hpp" @@ -58,14 +59,14 @@ private: }; uint8_t enc_type = 0; - const encoder_def_t * encoder_def; + const encoder_def_t * encoder_def { }; tx_modes tx_mode = IDLE; //bool abort_scan = false; //uint8_t scan_count; //double scan_progress; //unsigned int scan_index; std::string debug_text = "0"; - uint8_t repeat_index; + uint8_t repeat_index { 0 }; int8_t waveform_buffer[512]; void draw_waveform(); @@ -98,10 +99,6 @@ private: .foreground = Color::blue(), }; - FrequencyField field_frequency { - { 1 * 8, 4 }, - }; - Text text_enctype { { 1 * 8, 32, 5 * 8, 16 }, "Type:" @@ -193,16 +190,17 @@ private: }; Text text_status { - { 2 * 8, 224, 128, 16 }, + { 2 * 8, 13 * 16, 128, 16 }, "Ready" }; ProgressBar progress { - { 16, 224 + 20, 208, 16 } + { 2 * 8, 13 * 16 + 20, 208, 16 } }; - Button button_transmit { - { 16, 270, 80, 32 }, - "TX" + TransmitterView tx_view { + 16 * 16, + 50000, + 9 }; MessageHandlerRegistration message_handler_tx_done { diff --git a/firmware/application/ui_lcr.hpp b/firmware/application/ui_lcr.hpp index e68ead94..7a05311a 100644 --- a/firmware/application/ui_lcr.hpp +++ b/firmware/application/ui_lcr.hpp @@ -80,15 +80,15 @@ private: tx_modes tx_mode = IDLE; bool abort_scan = false; - uint8_t scan_count, scan_index; - double scan_progress; + uint8_t scan_count { 0 }, scan_index { 0 }; + double scan_progress { 0 }; char litteral[5][8] = { { 0 }, { 0 }, { 0 }, { 0 }, { 0 } }; char rgsb[5] = { 0 }; char lcr_message[512]; char lcr_message_data[512]; char checksum = 0; - rf::Frequency f; - uint8_t repeat_index; + rf::Frequency f { 0 }; + uint8_t repeat_index { 0 }; void generate_message(); void update_progress(); @@ -107,9 +107,9 @@ private: .foreground = Color::red(), }; - std::array buttons; - std::array checkboxes; - std::array rectangles; + std::array buttons { }; + std::array checkboxes { }; + std::array rectangles { }; Text text_recap { { 8, 6, 18 * 8, 16 }, diff --git a/firmware/application/ui_nuoptix.cpp b/firmware/application/ui_nuoptix.cpp index eecaa6a4..7b952c47 100644 --- a/firmware/application/ui_nuoptix.cpp +++ b/firmware/application/ui_nuoptix.cpp @@ -60,7 +60,7 @@ void NuoptixView::transmit(bool setup) { timecode = lfsr_iterate(timecode) % 1999; // Could be 9999 but that would be one long audio track ! if (setup) { - pbar.set_max(6 * 2); + progressbar.set_max(6 * 2); if (tx_mode == IMPROVISE) { // Seed from RTC @@ -86,7 +86,7 @@ void NuoptixView::transmit(bool setup) { number_timecode.set_value(timecode); } - pbar.set_value(0); + progressbar.set_value(0); dtmf_message[2] = (timecode / 100) % 10; dtmf_message[3] = (timecode / 10) % 10; @@ -145,12 +145,11 @@ NuoptixView::NuoptixView( baseband::run_image(portapack::spi_flash::image_tag_tones); add_children({ - &tx_view, &number_timecode, &text_timecode, &text_mod, - &pbar, - &button_exit + &progressbar, + &tx_view }); number_timecode.set_value(1); @@ -183,10 +182,6 @@ NuoptixView::NuoptixView( transmit(true); } };*/ - - button_exit.on_select = [&nav](Button&){ - nav.pop(); - }; } } diff --git a/firmware/application/ui_nuoptix.hpp b/firmware/application/ui_nuoptix.hpp index 61865948..a305d75b 100644 --- a/firmware/application/ui_nuoptix.hpp +++ b/firmware/application/ui_nuoptix.hpp @@ -62,19 +62,13 @@ private: uint32_t timecode { 0 }; - TransmitterView tx_view { - 11 * 16, - 10000, - 15 - }; - Text text_timecode { - { 10 * 8, 32, 9 * 8, 16 }, + { 10 * 8, 2 * 16, 9 * 8, 16 }, "Timecode:" }; NumberField number_timecode { - { 13 * 8, 48 }, + { 13 * 8, 3 * 16 }, 4, { 1, 9999 }, 1, @@ -82,12 +76,12 @@ private: }; Text text_mod { - { 10 * 8, 80, 6 * 8, 16 }, + { 10 * 8, 5 * 16, 6 * 8, 16 }, "Mod: " }; - ProgressBar pbar { - { 16, 236, 208, 16 } + ProgressBar progressbar { + { 16, 14 * 16, 208, 16 } }; /*Button button_impro { @@ -95,9 +89,10 @@ private: "IMPROVISE" };*/ - Button button_exit { - { 88, 270, 64, 32 }, - "Exit" + TransmitterView tx_view { + 16 * 16, + 10000, + 15 }; MessageHandlerRegistration message_handler_tx_done { @@ -107,7 +102,7 @@ private: if (message.done) transmit(false); else - pbar.set_value(message.progress); + progressbar.set_value(message.progress); } }; }; diff --git a/firmware/application/ui_rds.cpp b/firmware/application/ui_rds.cpp index 9e38d6aa..b33e8bd9 100644 --- a/firmware/application/ui_rds.cpp +++ b/firmware/application/ui_rds.cpp @@ -57,8 +57,7 @@ void RDSView::start_tx() { baseband::set_rds_data(message_length); } -void RDSView::paint(Painter& painter) { - (void)painter; +void RDSView::paint(Painter&) { char RadioTextA[17]; text_psn.set(PSN); @@ -78,7 +77,6 @@ RDSView::RDSView(NavigationView& nav) { strcpy(RadioText, "Radiotext test ABCD1234"); add_children({ - &field_frequency, &text_pty, &options_pty, &text_countrycode, @@ -99,23 +97,43 @@ RDSView::RDSView(NavigationView& nav) { &text_radiotext, &text_radiotexta, &text_radiotextb, - &button_tx, - &button_exit + &tx_view, }); - field_frequency.set_value(transmitter_model.tuning_frequency()); - field_frequency.set_step(50000); // 50kHz steps - field_frequency.on_change = [this](rf::Frequency f) { - this->on_tuning_frequency_changed(f); - }; - field_frequency.on_edit = [this, &nav]() { - auto new_view = nav.push(field_frequency.value()); + tx_view.on_edit_frequency = [this, &nav]() { + auto new_view = nav.push(receiver_model.tuning_frequency()); new_view->on_changed = [this](rf::Frequency f) { - this->field_frequency.set_value(f); + receiver_model.set_tuning_frequency(f); this->on_tuning_frequency_changed(f); }; }; + tx_view.on_start = [this]() { + tx_view.set_transmitting(true); + rds_flags.PI_code = sym_pi_code.value_hex_u64(); + rds_flags.PTY = options_pty.selected_index_value(); + rds_flags.DI = check_mono_stereo.value() ? 1 : 0; + rds_flags.TP = check_TP.value(); + rds_flags.TA = check_TA.value(); + rds_flags.MS = check_MS.value(); + + if (options_tx.selected_index() == 0) + message_length = gen_PSN(PSN, &rds_flags); + else if (options_tx.selected_index() == 1) + message_length = gen_RadioText(RadioText, 0, &rds_flags); + else + message_length = gen_ClockTime(&rds_flags, 2016, 12, 1, 9, 23, 2); + + txing = true; + start_tx(); + }; + + tx_view.on_stop = [this]() { + tx_view.set_transmitting(false); + transmitter_model.disable(); + txing = false; + }; + check_TA.set_value(true); check_TP.set_value(true); @@ -145,40 +163,10 @@ RDSView::RDSView(NavigationView& nav) { button_editpsn.on_select = [this, &nav](Button&) { textentry(nav, PSN, 8); }; - button_tx.on_select = [this](Button&) { - if (txing) { - transmitter_model.disable(); - button_tx.set_text("START"); - txing = false; - } else { - rds_flags.PI_code = sym_pi_code.value_hex_u64(); - rds_flags.PTY = options_pty.selected_index_value(); - rds_flags.DI = check_mono_stereo.value() ? 1 : 0; - rds_flags.TP = check_TP.value(); - rds_flags.TA = check_TA.value(); - rds_flags.MS = check_MS.value(); - - if (options_tx.selected_index() == 0) - message_length = gen_PSN(PSN, &rds_flags); - else if (options_tx.selected_index() == 1) - message_length = gen_RadioText(RadioText, 0, &rds_flags); - else - message_length = gen_ClockTime(&rds_flags, 2016, 12, 1, 9, 23, 2); - - button_tx.set_text("STOP"); - - txing = true; - start_tx(); - } - }; button_editradiotext.on_select = [this, &nav](Button&){ textentry(nav, RadioText, 24); }; - - button_exit.on_select = [&nav](Button&){ - nav.pop(); - }; } } /* namespace ui */ diff --git a/firmware/application/ui_rds.hpp b/firmware/application/ui_rds.hpp index 320c726b..1b9cc430 100644 --- a/firmware/application/ui_rds.hpp +++ b/firmware/application/ui_rds.hpp @@ -25,6 +25,7 @@ #include "ui_navigation.hpp" #include "ui_font_fixed_8x16.hpp" #include "ui_receiver.hpp" +#include "ui_transmitter.hpp" #include "ui_textentry.hpp" #include "message.hpp" #include "rds.hpp" @@ -44,20 +45,16 @@ public: std::string title() const override { return "RDS transmit"; }; private: - char PSN[9]; - char RadioText[25]; + char PSN[9] { 0 }; + char RadioText[25] { 0 }; bool txing = false; - RDS_flags rds_flags; + RDS_flags rds_flags { }; - uint16_t message_length; + uint16_t message_length { 0 }; void start_tx(); void on_tuning_frequency_changed(rf::Frequency f); - FrequencyField field_frequency { - { 1 * 8, 4 }, - }; - Text text_pty { { 1 * 8, 16 + 8, 4 * 8, 16 }, "PTY:" @@ -272,13 +269,10 @@ private: } }; - Button button_tx { - { 3 * 8, 16 * 16, 80, 32 }, - "START" - }; - Button button_exit { - { 19 * 8, 16 * 16, 64, 32 }, - "Exit" + TransmitterView tx_view { + 16 * 16, + 50000, + 9 }; }; diff --git a/firmware/application/ui_transmitter.cpp b/firmware/application/ui_transmitter.cpp index eebacc6d..b0bb33e0 100644 --- a/firmware/application/ui_transmitter.cpp +++ b/firmware/application/ui_transmitter.cpp @@ -51,6 +51,24 @@ TXGainField::TXGainField( /* TransmitterView *******************************************************/ +void TransmitterView::paint(Painter& painter) { + size_t c; + Point pos = { 0, screen_pos().y() }; + + for (c = 0; c < 20; c++) { + painter.draw_bitmap( + pos, + bitmap_stripes, + ui::Color(191, 191, 0), + ui::Color::black() + ); + if (c != 9) + pos += { 24, 0 }; + else + pos = { 0, screen_pos().y() + 32 + 8 }; + } +} + void TransmitterView::on_tuning_frequency_changed(rf::Frequency f) { receiver_model.set_tuning_frequency(f); } @@ -82,7 +100,7 @@ void TransmitterView::focus() { TransmitterView::TransmitterView( const Coord y, const uint32_t frequency_step, const uint32_t bandwidth ) { - set_parent_rect({ 0 * 8, y, 30 * 8, 2 * 16 }); + set_parent_rect({ 0 * 8, y, 30 * 8, 6 * 8 }); add_children({ &field_frequency, diff --git a/firmware/application/ui_transmitter.hpp b/firmware/application/ui_transmitter.hpp index 156d8a9f..d743d2de 100644 --- a/firmware/application/ui_transmitter.hpp +++ b/firmware/application/ui_transmitter.hpp @@ -56,6 +56,7 @@ public: ~TransmitterView(); void on_show() override; + void paint(Painter& painter) override; void focus() override; void set_transmitting(const bool transmitting); @@ -75,27 +76,27 @@ private: bool transmitting_ { false }; FrequencyField field_frequency { - { 0 * 8, 0 * 16 } + { 0 * 8, 1 * 8 } }; TXGainField field_gain { - { 10 * 8, 0 * 16 } + { 10 * 8, 1 * 8 } }; NumberField field_bw { - { 13 * 8, 0 * 16 }, + { 13 * 8, 1 * 8 }, 3, { 1, 150 }, 1, ' ' }; Text text_kHz { - { 16 * 8, 0 * 16, 3 * 8, 1 * 16 }, + { 16 * 8, 1 * 8, 3 * 8, 1 * 16 }, "kHz" }; Button button_start { - { 20 * 8, 0 * 16, 9 * 8, 32 }, + { 20 * 8, 1 * 8, 9 * 8, 32 }, "START" }; diff --git a/firmware/graphics/stripes.png b/firmware/graphics/stripes.png new file mode 100644 index 00000000..2253faf1 Binary files /dev/null and b/firmware/graphics/stripes.png differ diff --git a/firmware/portapack-h1-havoc.bin b/firmware/portapack-h1-havoc.bin index fae23b9e..7561258b 100644 Binary files a/firmware/portapack-h1-havoc.bin and b/firmware/portapack-h1-havoc.bin differ