From b1e72c788b95aeaae61ff7ba9f55b9c71e71f29c Mon Sep 17 00:00:00 2001 From: furrtek Date: Sun, 5 May 2019 00:43:36 +0100 Subject: [PATCH] Added RFM69 helper LGE tool: new frames Text entry string length bugfix --- firmware/application/CMakeLists.txt | 3 +- firmware/application/apps/lge_app.cpp | 222 +++++++++++++++------ firmware/application/apps/lge_app.hpp | 72 +++++-- firmware/application/apps/ui_adsb_tx.cpp | 6 +- firmware/application/apps/ui_aprs_tx.cpp | 6 +- firmware/application/apps/ui_fileman.cpp | 10 +- firmware/application/apps/ui_freqman.cpp | 12 +- firmware/application/apps/ui_lcr.cpp | 12 +- firmware/application/apps/ui_morse.cpp | 2 +- firmware/application/apps/ui_pocsag_tx.cpp | 2 +- firmware/application/apps/ui_rds.cpp | 12 +- firmware/application/rfm69.cpp | 76 +++++++ firmware/application/rfm69.hpp | 58 ++++++ firmware/application/ui/ui_alphanum.cpp | 2 +- firmware/application/ui/ui_alphanum.hpp | 2 +- firmware/application/ui/ui_textentry.cpp | 38 ++-- firmware/application/ui/ui_textentry.hpp | 10 +- firmware/common/ui_widget.cpp | 2 +- 18 files changed, 417 insertions(+), 130 deletions(-) create mode 100644 firmware/application/rfm69.cpp create mode 100644 firmware/application/rfm69.hpp diff --git a/firmware/application/CMakeLists.txt b/firmware/application/CMakeLists.txt index c2b488a4f..a2c744503 100644 --- a/firmware/application/CMakeLists.txt +++ b/firmware/application/CMakeLists.txt @@ -159,7 +159,8 @@ set(CPPSRC clock_manager.cpp core_control.cpp de_bruijn.cpp - emu_cc1101.cpp + #emu_cc1101.cpp + rfm69.cpp event_m0.cpp file.cpp freqman.cpp diff --git a/firmware/application/apps/lge_app.cpp b/firmware/application/apps/lge_app.cpp index ac2b822e6..b0be496fa 100644 --- a/firmware/application/apps/lge_app.cpp +++ b/firmware/application/apps/lge_app.cpp @@ -20,12 +20,15 @@ * Boston, MA 02110-1301, USA. */ +// The UI for this app is in French because it concerns leisure centers +// only established in France. "LGE" stands for a trademark I'd rather +// not spell out completely here. + #include "lge_app.hpp" #include "baseband_api.hpp" -#include "portapack_persistent_memory.hpp" +#include "ui_textentry.hpp" -#include "crc.hpp" #include "string_format.hpp" #include @@ -36,7 +39,7 @@ using namespace portapack; namespace ui { void LGEView::focus() { - tx_view.focus(); + options_trame.focus(); } LGEView::~LGEView() { @@ -44,64 +47,145 @@ LGEView::~LGEView() { baseband::shutdown(); } -void LGEView::generate_frame() { - CRC<16> crc { 0x1021, 0x90BE }; - std::vector frame { }; - uint8_t payload[9] = { 0x06, 0x0D, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00 }; - uint8_t out = 0; +void LGEView::generate_lge_frame(const uint8_t command, const uint16_t address_a, const uint16_t address_b, std::vector& data) { + std::array header = { + command, + (uint8_t)(address_a & 255), + (uint8_t)(address_a >> 8), + (uint8_t)(address_b & 255), + (uint8_t)(address_b >> 8), + }; + + data.insert(data.begin(), header.begin(), header.end()); + + frame_size = rfm69.gen_frame(data); + + for (auto b : data) + console.write(to_string_hex(b, 2) + " "); +} + +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 + // 04 01 B0 04 7F 1F 11 33 40 1F 22 01 07 00 00 01 07 00 00 63 05 00 00 99 A2 + + std::vector data { }; + std::array data_header = { 0xFF, 0x00, 0x02 }; + std::array data_footer = { + 0x01, 0xB0, 0x04, 0x7F, + 0x1F, 0x11, 0x33, 0x40, + 0x1F, 0x22, 0x01, 0x07, + 0x00, 0x00, 0x01, 0x07, + 0x00, 0x00, 0x63, 0x05, + 0x00, 0x00 + }; uint32_t c; - payload[6] = field_zone.value(); // Zone + //data_header[2] = field_salle.value(); // ? + //data_footer[0] = field_salle.value(); // ? - // Preamble - // Really is 0xAA but the RFM69 skips the very last bit (bug ?) - // so the whole preamble should be shifted right 1 bit to simulate that - for (c = 0; c < 5; c++) - frame.push_back(0x55); + data.insert(data.begin(), data_header.begin(), data_header.end()); - frame.push_back(0x2D); // Sync word - frame.push_back(0xD4); + data.push_back(field_joueur.value()); - crc.process_bytes(payload, 9 - 2); - - payload[7] = crc.checksum() >> 8; - payload[8] = crc.checksum() & 0xFF; - - // Manchester-encode payload - for (c = 0; c < 9; c++) { - uint8_t byte = payload[c]; - for (uint32_t b = 0; b < 8; b++) { - out <<= 2; - - if (byte & 0x80) - out |= 0b10; - else - out |= 0b01; - - if ((b & 3) == 3) - frame.push_back(out); - - byte <<= 1; - } + c = 0; + for (auto &ch : pseudo) { + data.push_back(ch); + c++; } + // Space at the end, is this required ? + data.push_back(0x20); + // Pad with zeroes + while (++c < 16) + data.push_back(0x00); - frame_size = frame.size(); + data.push_back(field_equipe.value()); - /*std::string debug_str { "" }; + data.insert(data.end(), data_footer.begin(), data_footer.end()); - for (c = 0; c < 10; c++) - debug_str += (to_string_hex(frame[c], 2) + " "); + console.write("\n\x1B\x0ESet pseudo:\x1B\x10"); - text_messagea.set(debug_str); + generate_lge_frame(0x02, 0x001A, field_joueur.value(), data); +} - debug_str = ""; - for (c = 15; c < frame_size; c++) - debug_str += (to_string_hex(frame[c], 2) + " "); - - text_messageb.set(debug_str);*/ +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 - // Copy for baseband - memcpy(shared_memory.bb_data.data, frame.data(), frame_size); + std::vector data { }; + std::array data_header = { 0x02, 0x01 }; + uint32_t c; + + data.insert(data.begin(), data_header.begin(), data_header.end()); + + data.push_back(field_equipe.value()); + + c = 0; + for (auto &ch : pseudo) { + data.push_back(ch); + c++; + } + // Pad with zeroes + while (c++ < 16) + data.push_back(0x00); + + data.push_back(field_equipe.value() - 1); // Color ? + + console.write("\n\x1B\x0ASet equipe:\x1B\x10"); + + generate_lge_frame(0x03, data); +} + +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 + + std::vector data { }; + std::array data_header = { 0x02, 0x01 }; + uint32_t c; + + data.insert(data.begin(), data_header.begin(), data_header.end()); + + data.push_back(field_joueur.value()); + + c = 0; + for (auto &ch : pseudo) { + data.push_back(ch); + c++; + } + // Space at the end, is this required ? + data.push_back(0x20); + // Pad with zeroes + while (++c < 16) + data.push_back(0x00); + + data.push_back(field_equipe.value()); + + console.write("\n\x1B\x09" "Broadcast pseudo:\x1B\x10"); + + generate_lge_frame(0x04, data); +} + +void LGEView::generate_frame_start() { + // 0166.13s: + // 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(); // ? + + console.write("\n\x1B\x0DStart:\x1B\x10"); + generate_lge_frame(0x05, data); +} + +void LGEView::generate_frame_gameover() { + std::vector data { field_salle.value() }; + + console.write("\n\x1B\x0CGameover:\x1B\x10"); + generate_lge_frame(0x0D, data); } void LGEView::start_tx() { @@ -115,7 +199,7 @@ void LGEView::start_tx() { transmitter_model.set_baseband_bandwidth(1750000); transmitter_model.enable(); - chThdSleep(100); + chThdSleep(100); baseband::set_fsk_data(frame_size * 8, 2280000 / 9600, 4000, 256); } @@ -157,20 +241,29 @@ LGEView::LGEView(NavigationView& nav) { add_children({ &labels, - &field_zone, + &options_trame, + &field_salle, + &button_texte, + &field_equipe, + &field_joueur, &checkbox_channels, - &text_messagea, - &text_messageb, + &console, &tx_view }); - field_zone.set_value(1); + field_salle.set_value(1); + field_equipe.set_value(1); + field_joueur.set_value(1); checkbox_channels.set_value(true); - generate_frame(); - - field_zone.on_change = [this](int32_t) { - generate_frame(); + button_texte.on_select = [this, &nav](Button&) { + text_prompt( + nav, + pseudo, + 15, + [this](std::string& buffer) { + button_texte.set_text(buffer); + }); }; tx_view.on_edit_frequency = [this, &nav]() { @@ -182,7 +275,18 @@ LGEView::LGEView(NavigationView& nav) { tx_view.on_start = [this]() { if (tx_mode == IDLE) { - generate_frame(); + auto i = options_trame.selected_index_value(); + if (i == 0) + generate_frame_pseudo(); + else if (i == 1) + generate_frame_equipe(); + else if (i == 2) + generate_frame_broadcast_pseudo(); + else if (i == 3) + generate_frame_start(); + else if (i == 4) + generate_frame_gameover(); + repeats = 0; channel_index = 0; tx_mode = checkbox_channels.value() ? ALL : SINGLE; diff --git a/firmware/application/apps/lge_app.hpp b/firmware/application/apps/lge_app.hpp index 0581b9bf8..2fdea1208 100644 --- a/firmware/application/apps/lge_app.hpp +++ b/firmware/application/apps/lge_app.hpp @@ -25,6 +25,7 @@ #include "ui_navigation.hpp" #include "ui_transmitter.hpp" #include "ui_font_fixed_8x16.hpp" +#include "rfm69.hpp" #include "message.hpp" #include "transmitter_model.hpp" @@ -50,27 +51,77 @@ private: tx_modes tx_mode = IDLE; + RFM69 rfm69 { 5, 0x2DD4, true, true }; + uint32_t frame_size { 0 }; uint32_t repeats { 0 }; uint32_t channel_index { 0 }; + std::string pseudo { "ABCDEF" }; rf::Frequency channels[3] = { 868067000, 868183000, 868295000 }; void start_tx(); void stop_tx(); - void generate_frame(); + + void generate_lge_frame(const uint8_t command, std::vector& data) { + 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_pseudo(); + void generate_frame_equipe(); + void generate_frame_broadcast_pseudo(); + void generate_frame_start(); + void generate_frame_gameover(); + void on_tx_progress(const uint32_t progress, const bool done); Labels labels { - { { 7 * 8, 4 * 8 }, "NO FUN ALLOWED !", Color::red() }, - { { 11 * 8, 8 * 8 }, "Zone:", Color::light_grey() } + { { 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() } }; - NumberField field_zone { - { 16 * 8, 8 * 8 }, + OptionsField options_trame { + { 10 * 8, 4 * 8 }, + 16, + { + { "Set pseudo", 0 }, + { "Set equipe", 1 }, + { "Broadcast pseudo", 2 }, + { "Start", 3 }, + { "Game over", 4 } + } + }; + + NumberField field_salle { + { 10 * 8, 6 * 8 }, + 1, + { 1, 2 }, + 1, + '0' + }; + + Button button_texte { + { 14 * 8, 8 * 8, 16 * 8, 3 * 8 }, + "ABCDEF" + }; + + NumberField field_equipe { + { 10 * 8, 8 * 8 }, 1, { 1, 6 }, - 16, + 1, + '0' + }; + + NumberField field_joueur { + { 10 * 8, 10 * 8 }, + 2, + { 1, 50 }, + 1, '0' }; @@ -80,13 +131,8 @@ private: "All channels" }; - Text text_messagea { - { 0 * 8, 10 * 16, 30 * 8, 16 }, - "" - }; - Text text_messageb { - { 0 * 8, 11 * 16, 30 * 8, 16 }, - "" + Console console { + { 0, 18 * 8, 30 * 8, 7 * 16 } }; TransmitterView tx_view { diff --git a/firmware/application/apps/ui_adsb_tx.cpp b/firmware/application/apps/ui_adsb_tx.cpp index 49e847de1..5054f258d 100644 --- a/firmware/application/apps/ui_adsb_tx.cpp +++ b/firmware/application/apps/ui_adsb_tx.cpp @@ -134,10 +134,10 @@ ADSBCallsignView::ADSBCallsignView( button_callsign.on_select = [this, &nav](Button&) { text_prompt( nav, - &callsign, + callsign, 8, - [this](std::string* s) { - button_callsign.set_text(*s); + [this](std::string& s) { + button_callsign.set_text(s); } ); }; diff --git a/firmware/application/apps/ui_aprs_tx.cpp b/firmware/application/apps/ui_aprs_tx.cpp index 63aa1cf98..efdb916de 100644 --- a/firmware/application/apps/ui_aprs_tx.cpp +++ b/firmware/application/apps/ui_aprs_tx.cpp @@ -99,10 +99,10 @@ APRSTXView::APRSTXView(NavigationView& nav) { button_set.on_select = [this, &nav](Button&) { text_prompt( nav, - &payload, + payload, 30, - [this](std::string* s) { - text_payload.set(*s); + [this](std::string& s) { + text_payload.set(s); } ); }; diff --git a/firmware/application/apps/ui_fileman.cpp b/firmware/application/apps/ui_fileman.cpp index 021c628e2..d5a1edf6b 100644 --- a/firmware/application/apps/ui_fileman.cpp +++ b/firmware/application/apps/ui_fileman.cpp @@ -237,8 +237,8 @@ FileLoadView::FileLoadView( } void FileManagerView::on_rename(NavigationView& nav) { - text_prompt(nav, &name_buffer, max_filename_length, [this](std::string * buffer) { - rename_file(get_selected_path(), *buffer); + text_prompt(nav, name_buffer, max_filename_length, [this](std::string& buffer) { + rename_file(get_selected_path(), buffer); load_directory_contents(current_path); refresh_list(); }); @@ -298,10 +298,8 @@ FileManagerView::FileManagerView( button_new_dir.on_select = [this, &nav](Button&) { name_buffer.clear(); - text_prompt(nav, &name_buffer, max_filename_length, [this](std::string * buffer) { - std::string path_str = *buffer; - - make_new_directory(current_path.string() + '/' + path_str); + text_prompt(nav, name_buffer, max_filename_length, [this](std::string& buffer) { + make_new_directory(current_path.string() + '/' + buffer); load_directory_contents(current_path); refresh_list(); }); diff --git a/firmware/application/apps/ui_freqman.cpp b/firmware/application/apps/ui_freqman.cpp index 9587d3387..1813eb812 100644 --- a/firmware/application/apps/ui_freqman.cpp +++ b/firmware/application/apps/ui_freqman.cpp @@ -146,8 +146,8 @@ void FrequencySaveView::save_current_file() { } void FrequencySaveView::on_save_name() { - text_prompt(nav_, &desc_buffer, 28, [this](std::string * buffer) { - database.push_back({ value_, 0, *buffer, SINGLE }); + text_prompt(nav_, desc_buffer, 28, [this](std::string& buffer) { + database.push_back({ value_, 0, buffer, SINGLE }); save_current_file(); }); } @@ -249,17 +249,17 @@ void FrequencyManagerView::on_edit_freq(rf::Frequency f) { } void FrequencyManagerView::on_edit_desc(NavigationView& nav) { - text_prompt(nav, &desc_buffer, 28, [this](std::string * buffer) { - database[menu_view.highlighted_index()].description = *buffer; + text_prompt(nav, desc_buffer, 28, [this](std::string& buffer) { + database[menu_view.highlighted_index()].description = buffer; refresh_list(); save_freqman_file(file_list[categories[current_category_id].second], database); }); } void FrequencyManagerView::on_new_category(NavigationView& nav) { - text_prompt(nav, &desc_buffer, 8, [this](std::string * buffer) { + text_prompt(nav, desc_buffer, 8, [this](std::string& buffer) { File freqman_file; - create_freqman_file(*buffer, freqman_file); + create_freqman_file(buffer, freqman_file); }); populate_categories(); refresh_list(); diff --git a/firmware/application/apps/ui_lcr.cpp b/firmware/application/apps/ui_lcr.cpp index fb2a6f6a2..0944fbe65 100644 --- a/firmware/application/apps/ui_lcr.cpp +++ b/firmware/application/apps/ui_lcr.cpp @@ -149,10 +149,10 @@ void LCRView::start_tx(const bool scan) { void LCRView::on_button_set_am(NavigationView& nav, int16_t button_id) { text_prompt( nav, - &litteral[button_id], + litteral[button_id], 7, - [this, button_id](std::string* buffer) { - texts[button_id].set(*buffer); + [this, button_id](std::string& buffer) { + texts[button_id].set(buffer); }); } @@ -227,10 +227,10 @@ LCRView::LCRView(NavigationView& nav) { button_set_rgsb.on_select = [this, &nav](Button&) { text_prompt( nav, - &rgsb, + rgsb, 4, - [this](std::string* buffer) { - button_set_rgsb.set_text(*buffer); + [this](std::string& buffer) { + button_set_rgsb.set_text(buffer); }); }; diff --git a/firmware/application/apps/ui_morse.cpp b/firmware/application/apps/ui_morse.cpp index 2f1ae9214..1ccb24bb4 100644 --- a/firmware/application/apps/ui_morse.cpp +++ b/firmware/application/apps/ui_morse.cpp @@ -70,7 +70,7 @@ static msg_t ookthread_fn(void * arg) { } void MorseView::on_set_text(NavigationView& nav) { - text_prompt(nav, &buffer, 28); + text_prompt(nav, buffer, 28); } void MorseView::focus() { diff --git a/firmware/application/apps/ui_pocsag_tx.cpp b/firmware/application/apps/ui_pocsag_tx.cpp index e7c191792..ae57acad4 100644 --- a/firmware/application/apps/ui_pocsag_tx.cpp +++ b/firmware/application/apps/ui_pocsag_tx.cpp @@ -114,7 +114,7 @@ void POCSAGTXView::paint(Painter&) { } void POCSAGTXView::on_set_text(NavigationView& nav) { - text_prompt(nav, &buffer, 30); + text_prompt(nav, buffer, 30); } POCSAGTXView::POCSAGTXView( diff --git a/firmware/application/apps/ui_rds.cpp b/firmware/application/apps/ui_rds.cpp index b81eca091..e62e15294 100644 --- a/firmware/application/apps/ui_rds.cpp +++ b/firmware/application/apps/ui_rds.cpp @@ -66,10 +66,10 @@ RDSPSNView::RDSPSNView( button_set.on_select = [this, &nav](Button&) { text_prompt( nav, - &PSN, + PSN, 8, - [this](std::string* s) { - text_psn.set(*s); + [this](std::string& s) { + text_psn.set(s); } ); }; @@ -91,10 +91,10 @@ RDSRadioTextView::RDSRadioTextView( button_set.on_select = [this, &nav](Button&){ text_prompt( nav, - &radiotext, + radiotext, 28, - [this](std::string* s) { - text_radiotext.set(*s); + [this](std::string& s) { + text_radiotext.set(s); } ); }; diff --git a/firmware/application/rfm69.cpp b/firmware/application/rfm69.cpp new file mode 100644 index 000000000..0978098d4 --- /dev/null +++ b/firmware/application/rfm69.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2017 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2019 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 "rfm69.hpp" +#include "crc.hpp" +#include "portapack_shared_memory.hpp" + +uint32_t RFM69::gen_frame(std::vector& payload) { + CRC<16> crc { 0x1021, 0x1D0F, 0xFFFF }; + std::vector frame { }; + uint8_t byte_out = 0; + + // Preamble + // Really is 0xAA but the RFM69 skips the very last bit (bug ?) + // so the whole preamble is shifted right to simulate that + frame.insert(frame.begin(), num_preamble_, 0x55); + + // Sync word + frame.push_back(sync_word_ >> 8); + frame.push_back(sync_word_ & 0xFF); + + // Payload length + payload.insert(payload.begin(), payload.size()); + + crc.process_bytes(payload.data(), payload.size()); + + if (CRC_) { + payload.push_back(crc.checksum() >> 8); + payload.push_back(crc.checksum() & 0xFF); + } + + // Manchester-encode payload + if (manchester_) { + for (auto byte : payload) { + for (uint32_t b = 0; b < 8; b++) { + byte_out <<= 2; + + if (byte & 0x80) + byte_out |= 0b10; + else + byte_out |= 0b01; + + if ((b & 3) == 3) + frame.push_back(byte_out); + + byte <<= 1; + } + } + } else { + frame.insert(frame.end(), payload.begin(), payload.end()); + } + + memcpy(shared_memory.bb_data.data, frame.data(), frame.size()); + + // Copy for baseband + return frame.size(); +} diff --git a/firmware/application/rfm69.hpp b/firmware/application/rfm69.hpp new file mode 100644 index 000000000..f1053230e --- /dev/null +++ b/firmware/application/rfm69.hpp @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2017 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2019 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. + */ + +#ifndef __RFM69_H__ +#define __RFM69_H__ + +#include +#include + +#include "utility.hpp" + +class RFM69 { +public: + RFM69(const uint8_t num_preamble, const uint16_t sync_word, const bool CRC, const bool manchester) + : num_preamble_(num_preamble), sync_word_(sync_word), CRC_(CRC), manchester_(manchester) + { } + //~RFM69(); + + void set_sync_word(const uint16_t sync_word) { + sync_word_ = sync_word; + }; + void set_data_config(const bool CRC, const bool manchester) { + CRC_ = CRC; + manchester_ = manchester; + }; + void set_num_preamble(const uint8_t num_preamble) { + num_preamble_ = num_preamble; + }; + + uint32_t gen_frame(std::vector& payload); + +private: + uint8_t num_preamble_ { 5 }; + uint16_t sync_word_ { 0x2DD4 }; + bool CRC_ { true }; + bool manchester_ { false }; +}; + +#endif/*__RFM69_H__*/ diff --git a/firmware/application/ui/ui_alphanum.cpp b/firmware/application/ui/ui_alphanum.cpp index f9c2c98bb..7b77eb8df 100644 --- a/firmware/application/ui/ui_alphanum.cpp +++ b/firmware/application/ui/ui_alphanum.cpp @@ -36,7 +36,7 @@ void AlphanumView::paint(Painter&) { AlphanumView::AlphanumView( NavigationView& nav, - std::string * str, + std::string& str, size_t max_length ) : TextEntryView(nav, str, max_length) { diff --git a/firmware/application/ui/ui_alphanum.hpp b/firmware/application/ui/ui_alphanum.hpp index 0af8acc24..08b6e2508 100644 --- a/firmware/application/ui/ui_alphanum.hpp +++ b/firmware/application/ui/ui_alphanum.hpp @@ -33,7 +33,7 @@ namespace ui { class AlphanumView : public TextEntryView { public: - AlphanumView(NavigationView& nav, std::string * str, size_t max_length); + AlphanumView(NavigationView& nav, std::string& str, size_t max_length); AlphanumView(const AlphanumView&) = delete; AlphanumView(AlphanumView&&) = delete; diff --git a/firmware/application/ui/ui_textentry.cpp b/firmware/application/ui/ui_textentry.cpp index fe478546b..e4e008c11 100644 --- a/firmware/application/ui/ui_textentry.cpp +++ b/firmware/application/ui/ui_textentry.cpp @@ -29,10 +29,10 @@ using namespace portapack; namespace ui { -void text_prompt(NavigationView& nav, std::string * str, const size_t max_length, const std::function on_done) { +void text_prompt(NavigationView& nav, std::string& str, const size_t max_length, const std::function on_done) { //if (persistent_memory::ui_config_textentry() == 0) { auto te_view = nav.push(str, max_length); - te_view->on_changed = [on_done](std::string * value) { + te_view->on_changed = [on_done](std::string& value) { if (on_done) on_done(value); }; @@ -46,38 +46,40 @@ void text_prompt(NavigationView& nav, std::string * str, const size_t max_length } void TextEntryView::update_text() { - if (_cursor_pos <= 28) - text_input.set(' ' + *_str + std::string(_max_length - _str->length(), ' ')); + if (cursor_pos < 30) + text_input.set(_str + std::string(_max_length - _str.length(), ' ')); else - text_input.set('<' + _str->substr(_cursor_pos - 28, 28)); + text_input.set('<' + _str.substr(cursor_pos - 29, 29)); draw_cursor(); } void TextEntryView::char_delete() { - if (!_cursor_pos) return; + if (!cursor_pos) return; - _cursor_pos--; - _str->replace(_cursor_pos, 1, 1, 0); + cursor_pos--; + _str.resize(cursor_pos); } void TextEntryView::char_add(const char c) { - if (_cursor_pos >= _max_length) return; + if (cursor_pos >= _max_length) return; - _str->replace(_cursor_pos, 1, 1, c); - _cursor_pos++; + _str += c; + cursor_pos++; } void TextEntryView::draw_cursor() { Point draw_pos; - draw_pos = { text_input.screen_rect().location().x() + 8 + std::min((Coord)_cursor_pos, (Coord)28) * 8, + draw_pos = { text_input.screen_rect().location().x() + std::min((Coord)cursor_pos, (Coord)28) * 8, text_input.screen_rect().location().y() + 16 }; + // Erase previous display.fill_rectangle( { { text_input.screen_rect().location().x(), draw_pos.y() }, { text_input.screen_rect().size().width(), 4 } }, Color::black() ); + // Draw new display.fill_rectangle( { draw_pos, { 8, 4 } }, Color::white() @@ -90,17 +92,19 @@ void TextEntryView::focus() { TextEntryView::TextEntryView( NavigationView& nav, - std::string * str, + std::string& str, size_t max_length ) : _str(str), _max_length(max_length) { // Trim from right - _str->erase(std::find_if(_str->rbegin(), _str->rend(), std::not1(std::ptr_fun(std::isspace))).base(), _str->end()); - _cursor_pos = _str->length(); + //_str->erase(std::find_if(_str->rbegin(), _str->rend(), std::not1(std::ptr_fun(std::isspace))).base(), _str->end()); + if (_str.length() > _max_length) + _str.resize(_max_length); + _str.reserve(_max_length); - _str->reserve(_max_length); + cursor_pos = _str.length(); add_children({ &text_input, @@ -108,7 +112,7 @@ TextEntryView::TextEntryView( }); button_ok.on_select = [this, &nav](Button&) { - _str->substr(0, _cursor_pos); + _str.resize(cursor_pos); if (on_changed) on_changed(_str); nav.pop(); diff --git a/firmware/application/ui/ui_textentry.hpp b/firmware/application/ui/ui_textentry.hpp index 6e311a469..9cd6f519a 100644 --- a/firmware/application/ui/ui_textentry.hpp +++ b/firmware/application/ui/ui_textentry.hpp @@ -30,13 +30,13 @@ namespace ui { class TextEntryView : public View { public: - std::function on_changed { }; + std::function on_changed { }; void focus() override; std::string title() const override { return "Text entry"; }; protected: - TextEntryView(NavigationView& nav, std::string * str, size_t max_length); + TextEntryView(NavigationView& nav, std::string& str, size_t max_length); TextEntryView(const TextEntryView&) = delete; TextEntryView(TextEntryView&&) = delete; @@ -48,9 +48,9 @@ protected: void draw_cursor(); void update_text(); - std::string * _str; + std::string& _str; size_t _max_length; - uint32_t _cursor_pos { 0 }; + uint32_t cursor_pos { 0 }; Text text_input { { 0, 0, 240, 16 } @@ -62,7 +62,7 @@ protected: }; }; -void text_prompt(NavigationView& nav, std::string * str, size_t max_length, const std::function on_done = nullptr); +void text_prompt(NavigationView& nav, std::string& str, size_t max_length, const std::function on_done = nullptr); } /* namespace ui */ diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index f46b2bf43..02b9bc02c 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -590,7 +590,7 @@ void Console::write(std::string message) { for (const auto c : message) { if (escape) { if (c <= 15) - pen_color = term_colors[c & 15]; + pen_color = term_colors[(uint8_t)c]; else pen_color = s.foreground; escape = false;