diff --git a/firmware/application/apps/lge_app.cpp b/firmware/application/apps/lge_app.cpp index b0be496f..265a20e5 100644 --- a/firmware/application/apps/lge_app.cpp +++ b/firmware/application/apps/lge_app.cpp @@ -64,6 +64,15 @@ void LGEView::generate_lge_frame(const uint8_t command, const uint16_t address_a console.write(to_string_hex(b, 2) + " "); } +void LGEView::generate_frame_touche() { + // 0001.89s + // 0D 96 02 12 0E 00 46 28 01 45 27 01 44 23 66 30 + std::vector data { 0x46, 0x28, 0x01, 0x45, 0x27, 0x01, 0x44, 0x23 }; + + console.write("\n\x1B\x07Touche:\x1B\x10"); + generate_lge_frame(0x96, (field_joueur.value() << 8) | field_salle.value(), 0x0001, data); +} + void LGEView::generate_frame_pseudo() { // 0040.48s: // 30 02 1A 00 19 00 FF 00 02 19 42 52 45 42 49 53 20 00 00 00 00 00 00 00 00 00 @@ -112,7 +121,7 @@ void LGEView::generate_frame_equipe() { // 0041.83s: // 3D 03 FF FF FF FF 02 03 01 52 4F 55 47 45 00 00 00 00 00 00 00 00 00 00 00 00 // 02 56 45 52 54 45 00 00 00 00 00 00 00 00 00 00 00 01 03 42 4C 45 55 45 00 00 - // 00 00 00 00 00 00 00 00 00 02 43 29 + // 00 00 00 00 00 00 00 00 00 02 43 29 std::vector data { }; std::array data_header = { 0x02, 0x01 }; @@ -142,7 +151,7 @@ void LGEView::generate_frame_broadcast_pseudo() { // 0043.86s: // 3D 04 FF FF FF FF 02 03 19 42 52 45 42 49 53 20 00 00 00 00 00 00 00 00 00 04 // 07 50 4F 4E 45 59 20 00 00 00 00 00 00 00 00 00 00 05 1B 41 42 42 59 20 00 00 - // 00 00 00 00 00 00 00 00 00 04 0A 02 + // 00 00 00 00 00 00 00 00 00 04 0A 02 std::vector data { }; std::array data_header = { 0x02, 0x01 }; @@ -172,7 +181,7 @@ void LGEView::generate_frame_broadcast_pseudo() { void LGEView::generate_frame_start() { // 0166.13s: - // 0A 05 FF FF FF FF 02 EC FF FF FF A3 35 + // 0A 05 FF FF FF FF 02 EC FF FF FF A3 35 std::vector data { 0x02, 0xEC, 0xFF, 0xFF, 0xFF }; //data[0] = field_salle.value(); // ? @@ -182,12 +191,48 @@ void LGEView::generate_frame_start() { } void LGEView::generate_frame_gameover() { - std::vector data { field_salle.value() }; + std::vector data { (uint8_t)field_salle.value() }; console.write("\n\x1B\x0CGameover:\x1B\x10"); generate_lge_frame(0x0D, data); } +void LGEView::generate_frame_collier() { + uint8_t flags = 0; + + // Custom + // 0C 00 13 37 13 37 id flags channel playerid zapduty zaptime checksum CRC CRC + // channel: field_channel + // playerid: field_joueur + // zapduty: field_power + // zaptime: field_duration + + if (checkbox_heartbeat.value()) + flags |= 1; + if (checkbox_rxtick.value()) + flags |= 2; + + uint8_t checksum = 0; + uint8_t id = (uint8_t)field_id.value(); + + std::vector data { + id, + flags, + (uint8_t)field_salle.value(), + (uint8_t)field_joueur.value(), + (uint8_t)field_power.value(), + (uint8_t)(field_duration.value() * 10) + }; + + for (auto &v : data) + checksum += v; + + data.push_back(checksum - id); + + console.write("\n\x1B\x06" "Config:\x1B\x10"); + generate_lge_frame(0x00, 0x3713, 0x3713, data); +} + void LGEView::start_tx() { if (tx_mode == ALL) { transmitter_model.set_tuning_frequency(channels[channel_index]); @@ -217,11 +262,11 @@ void LGEView::on_tx_progress(const uint32_t progress, const bool done) { transmitter_model.disable(); - if (repeats < 2) { + /*if (repeats < 2) { chThdSleep(100); repeats++; start_tx(); - } else { + } else {*/ if (tx_mode == ALL) { if (channel_index < 2) { channel_index++; @@ -233,7 +278,7 @@ void LGEView::on_tx_progress(const uint32_t progress, const bool done) { } else { stop_tx(); } - } + //} } LGEView::LGEView(NavigationView& nav) { @@ -246,6 +291,11 @@ LGEView::LGEView(NavigationView& nav) { &button_texte, &field_equipe, &field_joueur, + &field_id, + &field_power, + &field_duration, + &checkbox_heartbeat, + &checkbox_rxtick, &checkbox_channels, &console, &tx_view @@ -254,7 +304,9 @@ LGEView::LGEView(NavigationView& nav) { field_salle.set_value(1); field_equipe.set_value(1); field_joueur.set_value(1); - checkbox_channels.set_value(true); + field_id.set_value(1); + field_power.set_value(1); + field_duration.set_value(2); button_texte.on_select = [this, &nav](Button&) { text_prompt( @@ -277,15 +329,19 @@ LGEView::LGEView(NavigationView& nav) { if (tx_mode == IDLE) { auto i = options_trame.selected_index_value(); if (i == 0) - generate_frame_pseudo(); + generate_frame_touche(); else if (i == 1) - generate_frame_equipe(); + generate_frame_pseudo(); else if (i == 2) - generate_frame_broadcast_pseudo(); + generate_frame_equipe(); else if (i == 3) - generate_frame_start(); + generate_frame_broadcast_pseudo(); else if (i == 4) + generate_frame_start(); + else if (i == 5) generate_frame_gameover(); + else if (i == 6) + generate_frame_collier(); repeats = 0; channel_index = 0; diff --git a/firmware/application/apps/lge_app.hpp b/firmware/application/apps/lge_app.hpp index 2fdea120..81825800 100644 --- a/firmware/application/apps/lge_app.hpp +++ b/firmware/application/apps/lge_app.hpp @@ -67,37 +67,52 @@ private: generate_lge_frame(command, 0xFFFF, 0xFFFF, data); } void generate_lge_frame(const uint8_t command, const uint16_t address_a, const uint16_t address_b, std::vector& data); + void generate_frame_touche(); void generate_frame_pseudo(); void generate_frame_equipe(); void generate_frame_broadcast_pseudo(); void generate_frame_start(); void generate_frame_gameover(); + void generate_frame_collier(); void on_tx_progress(const uint32_t progress, const bool done); Labels labels { - { { 7 * 8, 1 * 8 }, "NO FUN ALLOWED !", Color::red() }, - { { 4 * 8, 4 * 8 }, "Trame:", Color::light_grey() }, - { { 4 * 8, 6 * 8 }, "Salle:", Color::light_grey() }, - { { 14 * 8, 6 * 8 }, "Texte:", Color::light_grey() }, - { { 3 * 8, 8 * 8 }, "Equipe:", Color::light_grey() }, - { { 3 * 8, 10 * 8 }, "Joueur:", Color::light_grey() } + //{ { 7 * 8, 1 * 8 }, "NO FUN ALLOWED !", Color::red() }, + { { 1 * 8, 1 * 8 }, "Trame:", Color::light_grey() }, + { { 1 * 8, 3 * 8 }, "Salle:", Color::light_grey() }, + { { 14 * 8, 3 * 8 }, "Texte:", Color::light_grey() }, + { { 0 * 8, 5 * 8 }, "Equipe:", Color::light_grey() }, + { { 0 * 8, 7 * 8 }, "Joueur:", Color::light_grey() }, + { { 0 * 8, 10 * 8 }, "Collier:", Color::light_grey() }, + { { 4 * 8, 12 * 8 }, "ID:", Color::light_grey() }, + { { 3 * 8, 14 * 8 }, "Pow: /10", Color::light_grey() }, + { { 1 * 8, 16 * 8 }, "Duree: x100ms", Color::light_grey() } }; OptionsField options_trame { - { 10 * 8, 4 * 8 }, - 16, + { 7 * 8, 1 * 8 }, + 13, { - { "Set pseudo", 0 }, - { "Set equipe", 1 }, - { "Broadcast pseudo", 2 }, - { "Start", 3 }, - { "Game over", 4 } + { "Touche", 0 }, + { "Set pseudo", 1 }, + { "Set equipe", 2 }, + { "Brdcst pseudo", 3 }, + { "Start", 4 }, + { "Game over", 5 }, + { "Set collier", 6 } } }; + Checkbox checkbox_channels { + { 20 * 8, 1 * 8 }, + 7, + "All ch.", + true + }; + NumberField field_salle { - { 10 * 8, 6 * 8 }, + { 7 * 8, 3 * 8 }, 1, { 1, 2 }, 1, @@ -105,12 +120,12 @@ private: }; Button button_texte { - { 14 * 8, 8 * 8, 16 * 8, 3 * 8 }, + { 14 * 8, 5 * 8, 16 * 8, 3 * 8 }, "ABCDEF" }; NumberField field_equipe { - { 10 * 8, 8 * 8 }, + { 7 * 8, 5 * 8 }, 1, { 1, 6 }, 1, @@ -118,17 +133,45 @@ private: }; NumberField field_joueur { - { 10 * 8, 10 * 8 }, + { 7 * 8, 7 * 8 }, 2, { 1, 50 }, 1, '0' }; - Checkbox checkbox_channels { + Checkbox checkbox_heartbeat { + { 17 * 8, 12 * 8 }, + 9, + "Heartbeat", + true + }; + Checkbox checkbox_rxtick { + { 17 * 8, 15 * 8 }, + 7, + "RX tick", + true + }; + NumberField field_id { + { 7 * 8, 12 * 8 }, + 1, + { 1, 2 }, + 1, + '0' + }; + NumberField field_power { { 7 * 8, 14 * 8 }, - 12, - "All channels" + 2, + { 1, 10 }, + 1, + '0' + }; + NumberField field_duration { + { 7 * 8, 16 * 8 }, + 2, + { 1, 25 }, + 1, + '0' }; Console console { diff --git a/firmware/application/apps/replay_app.cpp b/firmware/application/apps/replay_app.cpp index 8bde0c2f..21bf10d6 100644 --- a/firmware/application/apps/replay_app.cpp +++ b/firmware/application/apps/replay_app.cpp @@ -218,8 +218,8 @@ ReplayAppView::ReplayAppView( }; button_open.on_select = [this, &nav](Button&) { - auto new_view = nav.push(".C16"); - new_view->on_changed = [this](std::filesystem::path new_file_path) { + auto open_view = nav.push(".C16"); + open_view->on_changed = [this](std::filesystem::path new_file_path) { on_file_changed(new_file_path); }; }; diff --git a/firmware/application/apps/ui_fileman.cpp b/firmware/application/apps/ui_fileman.cpp index d5a1edf6..e10f61fb 100644 --- a/firmware/application/apps/ui_fileman.cpp +++ b/firmware/application/apps/ui_fileman.cpp @@ -39,15 +39,24 @@ void FileManBaseView::load_directory_contents(const std::filesystem::path& dir_p auto filtering = (bool)extension_filter.size(); // List directories and files, put directories up top + if (dir_path.string().length()) + entry_list.push_back({ u"..", 0, true }); + for (const auto& entry : std::filesystem::directory_iterator(dir_path, u"*")) { if (std::filesystem::is_regular_file(entry.status())) { if (entry.path().string().length()) { - auto entry_extension = entry.path().extension().string(); - - for (auto &c: entry_extension) - c = toupper(c); + bool matched = true; + if (filtering) { + auto entry_extension = entry.path().extension().string(); - if ((entry_extension == extension_filter) || !filtering) + for (auto &c: entry_extension) + c = toupper(c); + + if (entry_extension != extension_filter) + matched = false; + } + + if (matched) entry_list.push_back({ entry.path(), (uint32_t)entry.size(), false }); } } else if (std::filesystem::is_directory(entry.status())) { @@ -57,15 +66,26 @@ void FileManBaseView::load_directory_contents(const std::filesystem::path& dir_p } std::filesystem::path FileManBaseView::get_selected_path() { - std::string selected_path_str = current_path.string(); + auto selected_path_str = current_path.string(); + auto entry_path = entry_list[menu_view.highlighted_index()].entry_path.string(); - if (selected_path_str.back() != '/') - selected_path_str += '/'; - selected_path_str += (entry_list[menu_view.highlighted_index()].entry_path.string()); + if (entry_path == "..") { + selected_path_str = get_parent_dir().string(); + } else { + if (selected_path_str.back() != '/') + selected_path_str += '/'; + + selected_path_str += entry_path; + } return selected_path_str; } +std::filesystem::path FileManBaseView::get_parent_dir() { + auto current_path_str = current_path.string(); + return current_path.string().substr(0, current_path_str.find_last_of('/')); +} + FileManBaseView::FileManBaseView( NavigationView& nav, std::string filter @@ -83,12 +103,8 @@ FileManBaseView::FileManBaseView( &button_exit }); - // Go back one level on left menu_view.on_left = [&nav, this]() { - std::string current_path_str = current_path.string(); - - current_path_str = current_path_str.substr(0, current_path_str.find_last_of('/')); - load_directory_contents(current_path_str); + load_directory_contents(get_parent_dir()); refresh_list(); }; @@ -107,73 +123,66 @@ void FileManBaseView::focus() { } void FileManBaseView::refresh_list() { - if (!entry_list.size()) { - // Hide widgets, show warning - if (on_refresh_widgets) - on_refresh_widgets(true); - } else { - // Hide warning, show widgets - if (on_refresh_widgets) - on_refresh_widgets(false); + if (on_refresh_widgets) + on_refresh_widgets(false); + + menu_view.clear(); - menu_view.clear(); + for (size_t n = 0; n < entry_list.size(); n++) { + auto entry = &entry_list[n]; + auto entry_name = entry->entry_path.filename().string().substr(0, 20); - for (size_t n = 0; n < entry_list.size(); n++) { - auto entry = &entry_list[n]; - auto entry_name = entry->entry_path.filename().string().substr(0, 20); + if (entry->is_directory) { - if (entry->is_directory) { - - menu_view.add_item({ - entry_name, - ui::Color::yellow(), - &bitmap_icon_dir, - [this](){ - if (on_select_entry) - on_select_entry(); - } - }); - - } else { - - auto file_size = entry->size; - size_t suffix_index = 0; - - while (file_size >= 1024) { - file_size /= 1024; - suffix_index++; + menu_view.add_item({ + entry_name, + ui::Color::yellow(), + &bitmap_icon_dir, + [this](){ + if (on_select_entry) + on_select_entry(); } - if (suffix_index > 4) - suffix_index = 4; - - std::string size_str = to_string_dec_uint(file_size) + suffix[suffix_index]; - - auto entry_extension = entry->entry_path.extension().string(); - for (auto &c: entry_extension) - c = toupper(c); - - // Associate extension to icon and color - size_t c; - for (c = 0; c < file_types.size() - 1; c++) { - if (entry_extension == file_types[c].extension) - break; - } - - menu_view.add_item({ - entry_name + std::string(21 - entry_name.length(), ' ') + size_str, - file_types[c].color, - file_types[c].icon, - [this](){ - if (on_select_entry) - on_select_entry(); - } - }); - + }); + + } else { + + auto file_size = entry->size; + size_t suffix_index = 0; + + while (file_size >= 1024) { + file_size /= 1024; + suffix_index++; } + if (suffix_index > 4) + suffix_index = 4; + + std::string size_str = to_string_dec_uint(file_size) + suffix[suffix_index]; + + auto entry_extension = entry->entry_path.extension().string(); + for (auto &c: entry_extension) + c = toupper(c); + + // Associate extension to icon and color + size_t c; + for (c = 0; c < file_types.size() - 1; c++) { + if (entry_extension == file_types[c].extension) + break; + } + + menu_view.add_item({ + entry_name + std::string(21 - entry_name.length(), ' ') + size_str, + file_types[c].color, + file_types[c].icon, + [this](){ + if (on_select_entry) + on_select_entry(); + } + }); + } - - menu_view.set_highlighted(0); // Refresh } + + menu_view.set_highlighted(0); // Refresh } /*void FileSaveView::on_save_name() { @@ -200,8 +209,6 @@ FileSaveView::FileSaveView( }*/ void FileLoadView::refresh_widgets(const bool v) { - menu_view.hidden(v); - text_empty.hidden(!v); set_dirty(); } @@ -215,8 +222,7 @@ FileLoadView::FileLoadView( }; add_children({ - &menu_view, - &text_empty + &menu_view }); // Resize menu view to fill screen @@ -254,8 +260,6 @@ void FileManagerView::refresh_widgets(const bool v) { button_rename.hidden(v); button_new_dir.hidden(v); button_delete.hidden(v); - menu_view.hidden(v); - text_empty.hidden(!v); set_dirty(); } @@ -273,7 +277,6 @@ FileManagerView::FileManagerView( add_children({ &menu_view, - &text_empty, &labels, &text_date, &button_rename, diff --git a/firmware/application/apps/ui_fileman.hpp b/firmware/application/apps/ui_fileman.hpp index e408d0fb..42c921ca 100644 --- a/firmware/application/apps/ui_fileman.hpp +++ b/firmware/application/apps/ui_fileman.hpp @@ -80,6 +80,7 @@ protected: std::string extension_filter { "" }; void change_category(int32_t category_id); + std::filesystem::path get_parent_dir(); void refresh_list(); Labels labels { @@ -94,10 +95,6 @@ protected: { 0, 2 * 8, 240, 26 * 8 }, true }; - Text text_empty { - { 7 * 8, 12 * 8, 16 * 8, 16 }, - "Empty directory !", - }; Button button_exit { { 20 * 8, 34 * 8, 10 * 8, 4 * 8 },