diff --git a/firmware/application/external/ook_editor/ui_ook_editor.cpp b/firmware/application/external/ook_editor/ui_ook_editor.cpp index a4e53ccc..eabee43e 100644 --- a/firmware/application/external/ook_editor/ui_ook_editor.cpp +++ b/firmware/application/external/ook_editor/ui_ook_editor.cpp @@ -1,5 +1,7 @@ /* * Copyright (C) 2024 Samir Sánchez Garnica @sasaga92 + * copyleft Elliot Alderson from F society + * copyleft Darlene Alderson from F society * * This file is part of PortaPack. * @@ -178,7 +180,8 @@ OOKEditorAppView::OOKEditorAppView(NavigationView& nav) &label_waveform, &waveform, &button_open, - &button_save}); + &button_save, + &button_bug_key}); // Initialize default values for controls field_symbol_rate.set_value(100); @@ -267,6 +270,16 @@ OOKEditorAppView::OOKEditorAppView(NavigationView& nav) }); }; + button_bug_key.on_select = [&](Button&) { + auto bug_key_input_view = nav_.push(ook_data.payload); + + bug_key_input_view->on_save = [this](std::string p) { + ook_data.payload = p; + text_payload.set(ook_data.payload); + draw_waveform(); + }; + }; + // Configure button to start or stop the transmission button_send_stop.on_select = [this](Button&) { if (!is_transmitting) { @@ -280,4 +293,145 @@ OOKEditorAppView::OOKEditorAppView(NavigationView& nav) // initial waveform drawing (should be a single line) draw_waveform(); } + +/*************** bug key view ****************/ + +OOKEditorBugKeyView::OOKEditorBugKeyView(NavigationView& nav, std::string payload) + : nav_{nav}, + payload_{payload} { + add_children({&labels, + &field_primary_step, + &field_secondary_step, + &console, + &button_insert_high_level_long, + &button_insert_high_level_short, + &button_insert_low_level_long, + &button_insert_low_level_short, + &button_delete, + &button_save}); + + button_insert_low_level_short.on_select = [this](Button&) { + on_insert(InsertType::LOW_LEVEL_SHORT); + }; + + button_insert_low_level_long.on_select = [this](Button&) { + on_insert(InsertType::LOW_LEVEL_LONG); + }; + + button_insert_high_level_short.on_select = [this](Button&) { + on_insert(InsertType::HIGH_LEVEL_SHORT); + }; + + button_insert_high_level_long.on_select = [this](Button&) { + on_insert(InsertType::HIGH_LEVEL_LONG); + }; + + button_delete.on_select = [this](Button&) { + on_delete(); + }; + + button_save.on_select = [this](Button&) { + if (on_save) on_save(build_payload()); + nav_.pop(); + }; + + auto update_step_buttons = [this](int32_t value, Button& btnLow, Button& btnHigh) { + std::string low_level_btn_str; + std::string high_level_btn_str; + if (value <= 14) { // the button width allow max 14 chars + for (int i = 0; i < value; i++) { + low_level_btn_str.push_back('0'); + high_level_btn_str.push_back('1'); + } + } else { + low_level_btn_str = to_string_dec_int(value) + " * \"0\""; + high_level_btn_str = to_string_dec_int(value) + " * \"1\""; + } + btnLow.set_text(" "); // set_dirty broken console. this is work around + btnHigh.set_text(" "); + btnLow.set_text(low_level_btn_str); + btnHigh.set_text(high_level_btn_str); + }; + + field_primary_step.on_change = [&](int32_t) { + update_step_buttons(field_primary_step.value(), + button_insert_low_level_short, + button_insert_high_level_short); + update_console(); + }; + + field_secondary_step.on_change = [&](int32_t) { + update_step_buttons(field_secondary_step.value(), + button_insert_low_level_long, + button_insert_high_level_long); + update_console(); + }; + + field_primary_step.set_value(1); + field_secondary_step.set_value(2); + update_step_buttons(field_primary_step.value(), + button_insert_low_level_short, + button_insert_high_level_short); + update_console(); +} + +void OOKEditorBugKeyView::on_insert(InsertType type) { + auto promise_length = 0; + std::string promose_level = "0"; + switch (type) { + case InsertType::LOW_LEVEL_SHORT: + promise_length = field_primary_step.value(); + promose_level = "0"; + break; + case InsertType::LOW_LEVEL_LONG: + promise_length = field_secondary_step.value(); + promose_level = "0"; + break; + case InsertType::HIGH_LEVEL_SHORT: + promise_length = field_primary_step.value(); + promose_level = "1"; + break; + case InsertType::HIGH_LEVEL_LONG: + promise_length = field_secondary_step.value(); + promose_level = "1"; + break; + } + + for (auto i = 0; i < promise_length; i++) { + payload_ += promose_level; + } + + update_console(); +} + +void OOKEditorBugKeyView::on_delete() { + // I'm aware that if user inputted like: [long high][long high][short high], this will delete a pile of them + // but this doesnt matter because: + // 1. they should not do it, high or low shoudl cross each other, don't repeat + // 2. don't have too much RAM to trach the input trace + if (payload_.length() > 0) { + size_t len = payload_.length(); + char last_char = payload_[len - 1]; + size_t pos = len - 1; + while (pos > 0 && payload_[pos - 1] == last_char) { + pos--; + } + payload_.erase(pos); + update_console(); + } +} + +void OOKEditorBugKeyView::update_console() { + console.clear(true); + console.write(payload_); +} + +std::string OOKEditorBugKeyView::build_payload() { + return payload_; +} + +void OOKEditorBugKeyView::focus() { + button_save.focus(); +} + } // namespace ui::external_app::ook_editor diff --git a/firmware/application/external/ook_editor/ui_ook_editor.hpp b/firmware/application/external/ook_editor/ui_ook_editor.hpp index 34376334..e972ca5c 100644 --- a/firmware/application/external/ook_editor/ui_ook_editor.hpp +++ b/firmware/application/external/ook_editor/ui_ook_editor.hpp @@ -1,5 +1,7 @@ /* * Copyright (C) 2024 Samir Sánchez Garnica @sasaga92 + * copyleft Elliot Alderson from F society + * copyleft Darlene Alderson from F society * * This file is part of PortaPack. * @@ -29,6 +31,8 @@ namespace ui::external_app::ook_editor { #define TRANSMISSION_FREQUENCY_DEFAULT 433920000U // Sets the default transmission frequency (27 MHz). #define WAVEFORM_BUFFER_SIZE 550 +/*****************Editor View ******************/ + class OOKEditorAppView : public View { public: void focus() override; @@ -123,6 +127,7 @@ class OOKEditorAppView : public View { Button button_set{{0, 125, 60, 28}, LanguageHelper::currentMessages[LANG_SET]}; Button button_open{{68, 125, 80, 28}, LanguageHelper::currentMessages[LANG_OPEN_FILE]}; Button button_save{{154, 125, 80, 28}, LanguageHelper::currentMessages[LANG_SAVE_FILE]}; + Button button_bug_key{{0, 125 + 28 + 3, screen_width, 28}, "Bug Key"}; Button button_send_stop{{80, 273, 80, 32}, LanguageHelper::currentMessages[LANG_SEND]}; // Progress bar to display transmission progress. @@ -132,6 +137,82 @@ class OOKEditorAppView : public View { Waveform waveform{{0, 208, 240, 32}, waveform_buffer, 0, 0, true, Theme::getInstance()->fg_yellow->foreground}; }; +/******** bug key input view **********/ + +enum InsertType { + LOW_LEVEL_SHORT, + LOW_LEVEL_LONG, + HIGH_LEVEL_SHORT, + HIGH_LEVEL_LONG +}; + +class OOKEditorBugKeyView : public View { + public: + std::function on_save{}; + + OOKEditorBugKeyView(NavigationView& nav, std::string payload); + + std::string title() const override { return "Bug.K"; }; + void focus() override; + + private: + NavigationView& nav_; + std::string payload_ = ""; + std::string path_ = ""; + uint32_t delay_{0}; + std::string delay_str{""}; // needed by text_prompt + + void on_insert(InsertType type); + void on_delete(); + void update_console(); + std::string build_payload(); + + Labels labels{ + {{0 * 8, 0 * 16}, "Primary Step", Theme::getInstance()->fg_light->foreground}, + {{(screen_width / 2), 0 * 16}, "Secondary Step", Theme::getInstance()->fg_light->foreground}}; + + NumberField field_primary_step{ + {0 * 8, 1 * 16}, + 3, + {0, 550}, + 1, + ' '}; + + NumberField field_secondary_step{ + {(screen_width / 2), 1 * 16}, + 3, + {0, 550}, + 1, + ' '}; + + Console console{ + {0, 3 * 16, screen_width, screen_height - 10 * 16}}; + + Button button_insert_low_level_long{ + {0 * 8, 13 * 16, screen_width / 2, 2 * 16}, + "00"}; + + Button button_insert_low_level_short{ + {0 * 8, 15 * 16, screen_width / 2, 2 * 16}, + "0"}; + + Button button_insert_high_level_long{ + {(screen_width / 2), 13 * 16, screen_width / 2, 2 * 16}, + "11"}; + + Button button_insert_high_level_short{ + {(screen_width / 2), 15 * 16, screen_width / 2, 2 * 16}, + "1"}; + + Button button_delete{ + {1, 17 * 16, screen_width / 2 - 4, 2 * 16}, + "