diff --git a/firmware/application/emu_cc1101.cpp b/firmware/application/emu_cc1101.cpp index bcb986ad8..090894823 100644 --- a/firmware/application/emu_cc1101.cpp +++ b/firmware/application/emu_cc1101.cpp @@ -24,4 +24,23 @@ namespace cc1101 { +void CC1101Emu::whitening_init() { + whitening_pn = 0x1FF; +} + +// See TI app note DN509 +uint8_t CC1101Emu::whiten_byte(uint8_t byte) { + uint_fast8_t new_bit; + + byte ^= (whitening_pn & 0xFF); + + for (size_t step = 0; step < 8; step++) { + new_bit = (whitening_pn & 1) ^ ((whitening_pn >> 5) & 1); + whitening_pn >>= 1; + whitening_pn |= (new_bit << 8); + } + + return byte; +} + } /* namespace cc1101 */ diff --git a/firmware/application/modems.cpp b/firmware/application/modems.cpp index dfd106d60..bc8f815f3 100644 --- a/firmware/application/modems.cpp +++ b/firmware/application/modems.cpp @@ -30,20 +30,21 @@ using namespace portapack; namespace modems { void generate_data(const std::string& in_message, uint16_t * out_data) { - serial_format_t serial_format; - uint8_t parity_init, parity, data_bits, bits, bit, cur_byte; - uint16_t ordered_word, bytes; + uint8_t parity_init, parity, bits, bit, cur_byte; + uint16_t ordered_word; + size_t bytes; - serial_format = persistent_memory::serial_format(); + serial_format_t serial_format = persistent_memory::serial_format(); + size_t message_length = in_message.length(); if (serial_format.parity == ODD) parity_init = 1; else parity_init = 0; - data_bits = serial_format.data_bits; + uint8_t data_bits = serial_format.data_bits; - for (bytes = 0; bytes < in_message.length(); bytes++) { + for (bytes = 0; bytes < message_length; bytes++) { parity = parity_init; cur_byte = in_message[bytes]; bit = 0; @@ -81,18 +82,17 @@ void generate_data(const std::string& in_message, uint16_t * out_data) { // This accepts a word with start and stop bits removed ! uint32_t deframe_word(uint32_t raw_word) { - serial_format_t serial_format; - uint32_t parity, cur_bit, deframed_word { 0 }; - size_t bit, bits; + uint32_t cur_bit, deframed_word { 0 }; + size_t bit; - serial_format = persistent_memory::serial_format(); + serial_format_t serial_format = persistent_memory::serial_format(); /*if (serial_format.parity == ODD) parity = 1; else parity = 0;*/ - bits = serial_format.data_bits; + size_t data_bits = serial_format.data_bits; // Ignore parity for now if (serial_format.parity) @@ -100,7 +100,7 @@ uint32_t deframe_word(uint32_t raw_word) { if (serial_format.bit_order == LSB_FIRST) { // Reverse data bits - for (bit = 0; bit < bits; bit++) { + for (bit = 0; bit < data_bits; bit++) { cur_bit = raw_word & 1; deframed_word <<= 1; diff --git a/firmware/application/modems.hpp b/firmware/application/modems.hpp index e39fd3916..3582dfe7c 100644 --- a/firmware/application/modems.hpp +++ b/firmware/application/modems.hpp @@ -30,6 +30,7 @@ namespace modems { #define MODEM_DEF_COUNT 7 +#define AFSK_TX_SAMPLERATE 1536000U enum ModemModulation { AFSK = 0, diff --git a/firmware/application/protocols/encoders.hpp b/firmware/application/protocols/encoders.hpp index 1da137f10..4b9d55397 100644 --- a/firmware/application/protocols/encoders.hpp +++ b/firmware/application/protocols/encoders.hpp @@ -38,7 +38,7 @@ namespace encoders { struct encoder_def_t { std::string name; // Encoder chip ref/name - std::string address_symbols; // "01", "01F"... + std::string address_symbols; // List of possible symbols like "01", "01F"... std::string data_symbols; // Same uint16_t clk_per_symbol; // Oscillator periods per symbol uint16_t clk_per_fragment; // Oscillator periods per symbol fragment (state) @@ -51,7 +51,7 @@ namespace encoders { uint16_t pause_symbols; // Length of pause between repeats in symbols }; - // Warning ! If this is changed, make sure that the UM3750 index is still good in ui_bht_tx.cpp ! + // Warning ! If this is changed, make sure that ENCODER_UM3750 is still valid ! const encoder_def_t encoder_defs[ENC_TYPES_COUNT] = { // PT2260-R2 { diff --git a/firmware/application/serializer.cpp b/firmware/application/serializer.cpp index 778d80a3c..38c896753 100644 --- a/firmware/application/serializer.cpp +++ b/firmware/application/serializer.cpp @@ -30,21 +30,20 @@ namespace serializer { /* Raw: 00110110100111 * NRZ-L: 00110110100111 - * NRZ-M: 00100100111010 - * NRZ-S: 10001110010000 - * RZ: 00 00 10 10 00 10 10 00 10 00 00 10 10 10 - * Bi-L: 01 01 10 10 01 10 10 01 10 01 01 10 10 10 - * Bi-M: 00 11 01 01 00 10 10 11 01 00 11 01 01 01 - * Bi-S: 01 01 00 11 01 00 11 01 00 10 10 11 00 11 + * NRZ-M: 00100100111010 (1 = transition) + * NRZ-S: ?0001110010000 (0 = transition) + * RZ: 00 00 10 10 00 10 10 00 10 00 00 10 10 10 (half bits) + * Bi-L: 01 01 10 10 01 10 10 01 10 01 01 10 10 10 (1 = high to low, 0 = low to high) + * Bi-M: 00 11 01 01 00 10 10 11 01 00 11 01 01 01 (1 = mid-bit transition, 0 = invert last level) + * Bi-S: 01 01 00 11 01 00 11 01 00 10 10 11 00 11 (the opposite) * Diff M.: ... */ size_t symbol_count(const serial_format_t& serial_format) { size_t count; - count = 1 + serial_format.data_bits; // Start + count = 1 + serial_format.data_bits + serial_format.stop_bits; // Start + data + stop if (serial_format.parity) count++; - count += serial_format.stop_bits; return count; }; diff --git a/firmware/application/ui_aprs_tx.cpp b/firmware/application/ui_aprs_tx.cpp index b43415316..257e892e2 100644 --- a/firmware/application/ui_aprs_tx.cpp +++ b/firmware/application/ui_aprs_tx.cpp @@ -63,8 +63,10 @@ void APRSTXView::start_tx() { transmitter_model.enable();*/ } -void APRSTXView::on_txdone(const bool v) { - if (v) { +void APRSTXView::on_tx_progress(const uint32_t progress, const bool done) { + (void)progress; + + if (done) { transmitter_model.disable(); tx_view.set_transmitting(false); //progress.set_value(0); diff --git a/firmware/application/ui_aprs_tx.hpp b/firmware/application/ui_aprs_tx.hpp index c61eb7ef5..d920684b9 100644 --- a/firmware/application/ui_aprs_tx.hpp +++ b/firmware/application/ui_aprs_tx.hpp @@ -56,7 +56,7 @@ private: void start_tx(); void generate_frame(); void generate_frame_pos(); - void on_txdone(const bool v); + void on_tx_progress(const uint32_t progress, const bool done); Labels labels { { { 2 * 8, 2 * 8 }, "Work in progress...", Color::light_grey() } @@ -74,11 +74,11 @@ private: true }; - MessageHandlerRegistration message_handler_tx_done { - Message::ID::TXDone, + MessageHandlerRegistration message_handler_tx_progress { + Message::ID::TXProgress, [this](const Message* const p) { - const auto message = *reinterpret_cast(p); - this->on_txdone(message.done); + const auto message = *reinterpret_cast(p); + this->on_tx_progress(message.progress, message.done); } }; }; diff --git a/firmware/application/ui_bht_tx.cpp b/firmware/application/ui_bht_tx.cpp index b65c79681..8b0d22a58 100644 --- a/firmware/application/ui_bht_tx.cpp +++ b/firmware/application/ui_bht_tx.cpp @@ -81,7 +81,7 @@ void BHTView::start_tx() { } } -void BHTView::on_tx_progress(const int progress, const bool done) { +void BHTView::on_tx_progress(const uint32_t progress, const bool done) { //if (view_xylos.tx_mode == XylosView::tx_modes::SINGLE) { if (done) { diff --git a/firmware/application/ui_bht_tx.hpp b/firmware/application/ui_bht_tx.hpp index cac62b118..b7ca6f2e6 100644 --- a/firmware/application/ui_bht_tx.hpp +++ b/firmware/application/ui_bht_tx.hpp @@ -221,7 +221,7 @@ public: std::string title() const override { return "BHT transmit"; }; private: - void on_tx_progress(const int progress, const bool done); + void on_tx_progress(const uint32_t progress, const bool done); void start_tx(); enum tx_type_t { @@ -272,10 +272,10 @@ private: 12 }; - MessageHandlerRegistration message_handler_tx_done { - Message::ID::TXDone, + MessageHandlerRegistration message_handler_tx_progress { + Message::ID::TXProgress, [this](const Message* const p) { - const auto message = *reinterpret_cast(p); + const auto message = *reinterpret_cast(p); this->on_tx_progress(message.progress, message.done); } }; diff --git a/firmware/application/ui_coasterp.cpp b/firmware/application/ui_coasterp.cpp index 26faf6020..0d5668e3e 100644 --- a/firmware/application/ui_coasterp.cpp +++ b/firmware/application/ui_coasterp.cpp @@ -75,8 +75,9 @@ void CoasterPagerView::start_tx() { baseband::set_fsk_data(19 * 8, 2280000 / 1000, 5000, 32); } -void CoasterPagerView::on_tx_progress(const int progress, const bool done) { +void CoasterPagerView::on_tx_progress(const uint32_t progress, const bool done) { (void)progress; + uint16_t address = 0; uint32_t c; diff --git a/firmware/application/ui_coasterp.hpp b/firmware/application/ui_coasterp.hpp index 432cec788..be91be8e3 100644 --- a/firmware/application/ui_coasterp.hpp +++ b/firmware/application/ui_coasterp.hpp @@ -52,7 +52,7 @@ private: void start_tx(); void generate_frame(); - void on_tx_progress(const int progress, const bool done); + void on_tx_progress(const uint32_t progress, const bool done); Labels labels { { { 1 * 8, 3 * 8 }, "Syscall pager TX beta", Color::light_grey() }, @@ -85,10 +85,10 @@ private: 12 }; - MessageHandlerRegistration message_handler_tx_done { - Message::ID::TXDone, + MessageHandlerRegistration message_handler_tx_progress { + Message::ID::TXProgress, [this](const Message* const p) { - const auto message = *reinterpret_cast(p); + const auto message = *reinterpret_cast(p); this->on_tx_progress(message.progress, message.done); } }; diff --git a/firmware/application/ui_encoders.cpp b/firmware/application/ui_encoders.cpp index b003dd396..9e4bb5fd7 100644 --- a/firmware/application/ui_encoders.cpp +++ b/firmware/application/ui_encoders.cpp @@ -219,7 +219,7 @@ void EncodersView::update_progress() { if (tx_mode == SINGLE) { str_buffer = to_string_dec_uint(repeat_index) + "/" + to_string_dec_uint(repeat_min); text_status.set(str_buffer); - progress.set_value(repeat_index); + progressbar.set_value(repeat_index); /*} else if (tx_mode == SCAN) { strcpy(str, to_string_dec_uint(repeat_index).c_str()); @@ -233,16 +233,16 @@ void EncodersView::update_progress() { progress.set_value(scan_progress);*/ } else { text_status.set("Ready"); - progress.set_value(0); + progressbar.set_value(0); } } -void EncodersView::on_txdone(int n, const bool txdone) { +void EncodersView::on_tx_progress(const uint32_t progress, const bool done) { //char str[16]; - if (!txdone) { + if (!done) { // Repeating... - repeat_index = n + 1; + repeat_index = progress + 1; /*if (tx_mode == SCAN) { scan_progress++; @@ -277,7 +277,7 @@ void EncodersView::on_txdone(int n, const bool txdone) { transmitter_model.disable(); tx_mode = IDLE; text_status.set("Done"); - progress.set_value(0); + progressbar.set_value(0); tx_view.set_transmitting(false); //} } @@ -303,7 +303,7 @@ void EncodersView::start_tx(const bool scan) { } else {*/ tx_mode = SINGLE; repeat_index = 1; - progress.set_max(repeat_min); + progressbar.set_max(repeat_min); update_progress(); //} @@ -335,7 +335,7 @@ EncodersView::EncodersView( &view_config, &view_scan, &text_status, - &progress, + &progressbar, &tx_view }); diff --git a/firmware/application/ui_encoders.hpp b/firmware/application/ui_encoders.hpp index be1d8352f..4684db35d 100644 --- a/firmware/application/ui_encoders.hpp +++ b/firmware/application/ui_encoders.hpp @@ -175,7 +175,7 @@ private: void update_progress(); void start_tx(const bool scan); - void on_txdone(int n, const bool txdone); + void on_tx_progress(const uint32_t progress, const bool done); /*const Style style_address { .font = font::fixed_8x16, @@ -203,7 +203,7 @@ private: "Ready" }; - ProgressBar progress { + ProgressBar progressbar { { 2 * 8, 13 * 16 + 20, 208, 16 } }; @@ -213,11 +213,11 @@ private: 9 }; - MessageHandlerRegistration message_handler_tx_done { - Message::ID::TXDone, + MessageHandlerRegistration message_handler_tx_progress { + Message::ID::TXProgress, [this](const Message* const p) { - const auto message = *reinterpret_cast(p); - this->on_txdone(message.progress, message.done); + const auto message = *reinterpret_cast(p); + this->on_tx_progress(message.progress, message.done); } }; }; diff --git a/firmware/application/ui_lcr.cpp b/firmware/application/ui_lcr.cpp index 0a596e04d..fb2a6f6a2 100644 --- a/firmware/application/ui_lcr.cpp +++ b/firmware/application/ui_lcr.cpp @@ -35,7 +35,7 @@ using namespace portapack; namespace ui { void LCRView::focus() { - button_setrgsb.focus(); + button_set_rgsb.focus(); } LCRView::~LCRView() { @@ -43,92 +43,52 @@ LCRView::~LCRView() { baseband::shutdown(); } -void LCRView::paint(Painter& painter) { - std::string final_str; - - static constexpr Style style_orange { - .font = font::fixed_8x16, - .background = Color::black(), - .foreground = Color::orange(), - }; - - Point offset = { - static_cast(104), - static_cast(68) - }; - - for (size_t i = 0; i < 5; i++) { - painter.draw_string( - screen_pos() + offset, - style_orange, - litteral[i] - ); - offset += { 0, 32 }; - } - - button_setrgsb.set_text(rgsb); - - // Recap: frequency @ baudrate - final_str = to_string_short_freq(persistent_memory::tuned_frequency()); - final_str += '@'; - final_str += to_string_dec_int(persistent_memory::modem_baudrate(), 4); - final_str += "bps "; - //final_str += modem_defs[persistent_memory::modem_def_index()].name; - text_recap.set(final_str); -} - -std::vector LCRView::parse_litterals() { - std::vector litterals; - - for (size_t i = 0; i < 5; i++) { - if (checkboxes[i].value()) - litterals.push_back(litteral[i]); - } - - return litterals; -} +/* +// Recap: frequency @ baudrate +final_str = to_string_short_freq(persistent_memory::tuned_frequency()); +final_str += '@'; +final_str += to_string_dec_int(persistent_memory::modem_baudrate(), 4); +final_str += "bps "; +//final_str += modem_defs[persistent_memory::modem_def_index()].name; +text_recap.set(final_str);*/ void LCRView::update_progress() { - std::string progress_str; - - text_status.set(" "); // Clear - - progress_str = to_string_dec_uint(repeat_index) + "/" + to_string_dec_uint(persistent_memory::modem_repeat()); - progress_str += " " + to_string_dec_uint(scan_index + 1) + "/" + to_string_dec_uint(scan_count); - - if (tx_mode == SINGLE) { - text_status.set(progress_str); - progress.set_value(repeat_index); - } else if (tx_mode == SCAN) { - text_status.set(progress_str); - progress.set_value(scan_progress); - } else { + if (tx_mode == IDLE) { text_status.set("Ready"); progress.set_value(0); + } else { + std::string progress_str = to_string_dec_uint(repeat_index) + "/" + to_string_dec_uint(persistent_memory::modem_repeat()) + + " " + to_string_dec_uint(scan_index + 1) + "/" + to_string_dec_uint(scan_count); + + text_status.set(progress_str); + + if (tx_mode == SINGLE) + progress.set_value(repeat_index); + else if (tx_mode == SCAN) + progress.set_value(scan_progress); } } -void LCRView::on_txdone(int n) { - if (n) { +void LCRView::on_tx_progress(const uint32_t progress, const bool done) { + if (!done) { // Repeating... - repeat_index = n + 1; + repeat_index = progress + 1; if (tx_mode == SCAN) scan_progress++; } else { // Done transmitting + tx_view.set_transmitting(false); + transmitter_model.disable(); + if ((tx_mode == SCAN) && (scan_index < (scan_count - 1))) { - transmitter_model.disable(); // Next address scan_index++; scan_progress++; repeat_index = 1; start_tx(true); } else { - transmitter_model.disable(); tx_mode = IDLE; - button_scan.set_style(&style_val); - button_scan.set_text("SCAN"); } } @@ -136,9 +96,7 @@ void LCRView::on_txdone(int n) { } void LCRView::start_tx(const bool scan) { - uint8_t repeats; - - repeats = persistent_memory::modem_repeat(); + uint32_t repeats = persistent_memory::modem_repeat(); if (scan) { if (tx_mode != SCAN) { @@ -151,6 +109,7 @@ void LCRView::start_tx(const bool scan) { update_progress(); } rgsb = scan_list[options_scanlist.selected_index()].addresses[scan_index]; + button_set_rgsb.set_text(rgsb); } else { tx_mode = SINGLE; repeat_index = 1; @@ -160,11 +119,17 @@ void LCRView::start_tx(const bool scan) { update_progress(); } - button_setrgsb.set_text(rgsb); - modems::generate_data(lcr::generate_message(rgsb, parse_litterals(), options_ec.selected_index()), lcr_message_data); + std::vector litterals_list; + + for (size_t i = 0; i < LCR_MAX_AM; i++) { + if (checkboxes[i].value()) + litterals_list.push_back(litteral[i]); + } + + modems::generate_data(lcr::generate_message(rgsb, litterals_list, options_ec.selected_index()), lcr_message_data); transmitter_model.set_tuning_frequency(persistent_memory::tuned_frequency()); - transmitter_model.set_sampling_rate(1536000U); + transmitter_model.set_sampling_rate(AFSK_TX_SAMPLERATE); transmitter_model.set_rf_amp(true); transmitter_model.set_baseband_bandwidth(1750000); transmitter_model.enable(); @@ -172,17 +137,23 @@ void LCRView::start_tx(const bool scan) { memcpy(shared_memory.bb_data.data, lcr_message_data, sizeof(lcr_message_data)); baseband::set_afsk_data( - 1536000 / persistent_memory::modem_baudrate(), + AFSK_TX_SAMPLERATE / persistent_memory::modem_baudrate(), persistent_memory::afsk_mark_freq(), persistent_memory::afsk_space_freq(), repeats, - persistent_memory::modem_bw(), + transmitter_model.channel_bandwidth(), serializer::symbol_count(persistent_memory::serial_format()) ); } -void LCRView::on_button_setam(NavigationView& nav, Button& button) { - text_prompt(nav, &litteral[button.id], 7); +void LCRView::on_button_set_am(NavigationView& nav, int16_t button_id) { + text_prompt( + nav, + &litteral[button_id], + 7, + [this, button_id](std::string* buffer) { + texts[button_id].set(*buffer); + }); } LCRView::LCRView(NavigationView& nav) { @@ -190,116 +161,126 @@ LCRView::LCRView(NavigationView& nav) { baseband::run_image(portapack::spi_flash::image_tag_afsk); - rgsb = scan_list[0].addresses[0]; - add_children({ &labels, - &text_recap, &options_ec, - &button_setrgsb, + &button_set_rgsb, &button_modem_setup, &text_status, &progress, - &button_transmit, &options_scanlist, - &button_scan, - &button_clear + &check_scan, + &button_clear, + &tx_view }); options_scanlist.set_selected_index(0); - const auto button_setam_fn = [this, &nav](Button& button) { - this->on_button_setam(nav, button); + const auto button_set_am_fn = [this, &nav](Button& button) { + on_button_set_am(nav, button.id); }; - size_t n = 0; - for (auto& button : buttons) { - button.on_select = button_setam_fn; - button.id = n; - button.set_text("AM " + to_string_dec_uint(n + 1, 1)); - button.set_parent_rect({ + for (size_t n = 0; n < LCR_MAX_AM; n++) { + Button* button = &buttons[n]; + button->on_select = button_set_am_fn; + button->id = n; + button->set_text("AM " + to_string_dec_uint(n + 1)); + button->set_parent_rect({ static_cast(40), static_cast(n * 32 + 64), 48, 24 }); - add_child(&button); - n++; - } - - n = 0; - for (auto& checkbox : checkboxes) { - checkbox.set_parent_rect({ + add_child(button); + + Checkbox* checkbox = &checkboxes[n]; + checkbox->set_parent_rect({ static_cast(8), static_cast(n * 32 + 64), 48, 24 }); - checkbox.set_value(false); - add_child(&checkbox); - n++; - } - - n = 0; - for (auto& rectangle : rectangles) { - rectangle.set_parent_rect({ + checkbox->set_value(false); + add_child(checkbox); + + Rectangle* rectangle = &rectangles[n]; + rectangle->set_parent_rect({ static_cast(98), - static_cast(n * 32 + 68 - 2), + static_cast(n * 32 + 66), 68, 20 }); - rectangle.set_color(ui::Color::grey()); - rectangle.set_outline(true); - add_child(&rectangle); - n++; + rectangle->set_color(ui::Color::grey()); + rectangle->set_outline(true); + add_child(rectangle); + + Text* text = &texts[n]; + text->set_parent_rect({ + static_cast(104), + static_cast(n * 32 + 68), + 7 * 8, 16 + }); + add_child(text); } - button_setrgsb.set_text(rgsb); + button_set_rgsb.set_text(rgsb); options_ec.set_selected_index(0); // Auto checkboxes[0].set_value(true); - button_transmit.set_style(&style_val); - button_scan.set_style(&style_val); - - button_setrgsb.on_select = [this,&nav](Button&) { - text_prompt(nav, &rgsb, 4); + button_set_rgsb.on_select = [this, &nav](Button&) { + text_prompt( + nav, + &rgsb, + 4, + [this](std::string* buffer) { + button_set_rgsb.set_text(*buffer); + }); }; - button_modem_setup.on_select = [&nav](Button&) { - nav.push(); - }; - - button_transmit.on_select = [this](Button&) { + button_modem_setup.on_select = [this, &nav](Button&) { if (tx_mode == IDLE) - start_tx(false); - }; - - button_scan.on_select = [this](Button&) { - std::string str_temp; - - if (tx_mode == IDLE) { - button_scan.set_style(&style_cancel); - button_scan.set_text("ABORT"); - start_tx(true); - } else { - // Kill scan process - baseband::kill_afsk(); - text_status.set("Abort @" + rgsb); - progress.set_value(0); - tx_mode = IDLE; - button_scan.set_style(&style_val); - button_scan.set_text("SCAN"); - } + nav.push(); }; button_clear.on_select = [this, &nav](Button&) { - if (tx_mode == IDLE) { - options_ec.set_selected_index(0); // Auto - for (size_t n = 0; n < 5; n++) { - litteral[n] = " "; - checkboxes[n].set_value(true); - } - set_dirty(); - start_tx(false); + options_ec.set_selected_index(0); // Auto + for (size_t n = 0; n < LCR_MAX_AM; n++) { + litteral[n] = " "; + checkboxes[n].set_value(true); } }; + + tx_view.on_edit_frequency = [this, &nav]() { + auto new_view = nav.push(transmitter_model.tuning_frequency()); + new_view->on_changed = [this](rf::Frequency f) { + transmitter_model.set_tuning_frequency(f); + }; + }; + + tx_view.on_start = [this]() { + if (check_scan.value()) { + if (tx_mode == IDLE) { + start_tx(true); + tx_view.set_transmitting(true); + } else { + // Kill scan process + baseband::kill_afsk(); + tx_view.set_transmitting(false); + transmitter_model.disable(); + text_status.set("Abort @" + rgsb); + progress.set_value(0); + tx_mode = IDLE; + } + } else { + if (tx_mode == IDLE) { + start_tx(false); + tx_view.set_transmitting(true); + } + } + }; + + tx_view.on_stop = [this]() { + tx_view.set_transmitting(false); + transmitter_model.disable(); + tx_mode = IDLE; + }; } } /* namespace ui */ diff --git a/firmware/application/ui_lcr.hpp b/firmware/application/ui_lcr.hpp index 5b5d76862..a9c7548ac 100644 --- a/firmware/application/ui_lcr.hpp +++ b/firmware/application/ui_lcr.hpp @@ -23,10 +23,14 @@ #include "ui.hpp" #include "ui_widget.hpp" #include "ui_textentry.hpp" +#include "ui_transmitter.hpp" + #include "message.hpp" #include "transmitter_model.hpp" namespace ui { + +#define LCR_MAX_AM 5 class LCRView : public View { public: @@ -34,7 +38,6 @@ public: ~LCRView(); void focus() override; - void paint(Painter& painter) override; std::string title() const override { return "LCR transmit"; }; @@ -48,7 +51,7 @@ private: { 36, &RGSB_list_Lille[0] }, { 20, &RGSB_list_Reims[0] } }; - + const std::string RGSB_list_Lille[36] = { "AI10", "AI20", "AI30", "AI40", "AI50", "AI60", "AI70", "AJ10", @@ -81,46 +84,28 @@ private: tx_modes tx_mode = IDLE; uint8_t scan_count { 0 }, scan_index { 0 }; uint32_t scan_progress { 0 }; - std::string litteral[5] { { " " } }; - std::string rgsb { " " }; - char lcr_message[512]; + std::array litteral { { " " } }; + std::string rgsb { "AI10" }; uint16_t lcr_message_data[256]; - rf::Frequency f { 0 }; uint8_t repeat_index { 0 }; - std::vector parse_litterals(); void update_progress(); void start_tx(const bool scan); - void on_txdone(int n); - void on_button_setam(NavigationView& nav, Button& button); - - const Style style_val { - .font = font::fixed_8x16, - .background = Color::black(), - .foreground = Color::green(), - }; - const Style style_cancel { - .font = font::fixed_8x16, - .background = Color::black(), - .foreground = Color::red(), - }; + void on_tx_progress(const uint32_t progress, const bool done); + void on_button_set_am(NavigationView& nav, int16_t button_id); Labels labels { - { { 2 * 8, 4 }, "EC:", Color::light_grey() }, - { { 84, 268 }, "Scan list:", Color::light_grey() } + { { 0, 8 }, "EC: RGSB:", Color::light_grey() }, + { { 17 * 8, 4 * 8 }, "List:", Color::light_grey() } }; - std::array buttons { }; - std::array checkboxes { }; - std::array rectangles { }; - - Text text_recap { - { 12 * 8, 4, 18 * 8, 16 }, - "-" - }; + std::array buttons { }; + std::array checkboxes { }; + std::array rectangles { }; + std::array texts { }; OptionsField options_ec { - { 40, 4 }, + { 3 * 8, 8 }, 4, { { "Auto", 0 }, @@ -130,51 +115,52 @@ private: } }; - Button button_setrgsb { - { 8, 24, 80, 32 }, + Button button_set_rgsb { + { 13 * 8, 4, 8 * 8, 24 }, "RGSB" }; + Checkbox check_scan { + { 22 * 8, 4 }, + 4, + "Scan" + }; + Button button_modem_setup { - { 13 * 8, 24, 128, 32 }, + { 1 * 8, 4 * 8 + 2, 14 * 8, 24 }, "Modem setup" }; - - Button button_clear { - { 174, 64, 58, 19 * 8 }, - "CLEAR" - }; - - Text text_status { - { 16, 222, 128, 16 }, - "Ready" - }; - ProgressBar progress { - { 16, 242, 208, 16 } - }; - - Button button_transmit { - { 8, 270, 64, 32 }, - "TX" - }; - OptionsField options_scanlist { - { 84, 284 }, + { 22 * 8, 4 * 8 }, 6, { { "Reims ", 1 } } }; - Button button_scan { - { 166, 270, 64, 32 }, - "SCAN" + Button button_clear { + { 22 * 8, 8 * 8, 7 * 8, 19 * 8 }, + "CLEAR" }; - MessageHandlerRegistration message_handler_tx_done { - Message::ID::TXDone, + Text text_status { + { 2 * 8, 27 * 8 + 4, 26 * 8, 16 }, + "Ready" + }; + ProgressBar progress { + { 2 * 8, 29 * 8 + 4, 26 * 8, 16 } + }; + + TransmitterView tx_view { + 16 * 16, + 10000, + 12 + }; + + MessageHandlerRegistration message_handler_tx_progress { + Message::ID::TXProgress, [this](const Message* const p) { - const auto message = *reinterpret_cast(p); - this->on_txdone(message.progress); + const auto message = *reinterpret_cast(p); + this->on_tx_progress(message.progress, message.done); } }; }; diff --git a/firmware/application/ui_mictx.cpp b/firmware/application/ui_mictx.cpp index 4b74bea8d..ab6c1dbd1 100644 --- a/firmware/application/ui_mictx.cpp +++ b/firmware/application/ui_mictx.cpp @@ -47,7 +47,10 @@ void MicTXView::update_vumeter() { vumeter.set_value(audio_level); } -void MicTXView::on_tx_done() { +void MicTXView::on_tx_progress(const uint32_t progress, const bool done) { + (void)progress; + (void)done; + // Roger beep transmitted, stop transmitting set_tx(false); } diff --git a/firmware/application/ui_mictx.hpp b/firmware/application/ui_mictx.hpp index 2d1d2a1d3..0e09d8002 100644 --- a/firmware/application/ui_mictx.hpp +++ b/firmware/application/ui_mictx.hpp @@ -64,7 +64,7 @@ private: void set_tx(bool enable); void on_tuning_frequency_changed(rf::Frequency f); void on_ctcss_changed(uint32_t v); - void on_tx_done(); + void on_tx_progress(const uint32_t progress, const bool done); bool transmitting { false }; bool va_enabled { }; @@ -184,11 +184,11 @@ private: } }; - MessageHandlerRegistration message_handler_tx_done { - Message::ID::TXDone, + MessageHandlerRegistration message_handler_tx_progress { + Message::ID::TXProgress, [this](const Message* const p) { - const auto message = *reinterpret_cast(p); - if (message.done) this->on_tx_done(); + const auto message = *reinterpret_cast(p); + this->on_tx_progress(message.progress, message.done); } }; }; diff --git a/firmware/application/ui_modemsetup.cpp b/firmware/application/ui_modemsetup.cpp index 0b4f2efef..6d28cf90f 100644 --- a/firmware/application/ui_modemsetup.cpp +++ b/firmware/application/ui_modemsetup.cpp @@ -21,12 +21,9 @@ */ #include "ui_modemsetup.hpp" -#include "ui_receiver.hpp" #include "portapack.hpp" -#include "string_format.hpp" -#include "portapack_shared_memory.hpp" #include "portapack_persistent_memory.hpp" using namespace portapack; @@ -38,12 +35,6 @@ void ModemSetupView::focus() { field_baudrate.focus(); } -/*void ModemSetupView::update_freq(rf::Frequency f) { - persistent_memory::set_tuned_frequency(f); - - button_setfreq.set_text(to_string_short_freq(f)); -}*/ - ModemSetupView::ModemSetupView( NavigationView& nav ) @@ -54,11 +45,9 @@ ModemSetupView::ModemSetupView( add_children({ &labels, - //&button_setfreq, &field_baudrate, &field_mark, &field_space, - //&field_bw, &field_repeat, &options_modem, &button_set_modem, @@ -66,6 +55,7 @@ ModemSetupView::ModemSetupView( &button_save }); + // Only list AFSK modems for now for (size_t i = 0; i < MODEM_DEF_COUNT; i++) { if (modem_defs[i].modulation == AFSK) modem_options.emplace_back(std::make_pair(modem_defs[i].name, i)); @@ -83,20 +73,10 @@ ModemSetupView::ModemSetupView( sym_format.set_sym(2, persistent_memory::serial_format().stop_bits); sym_format.set_sym(3, persistent_memory::serial_format().bit_order); - //update_freq(persistent_memory::tuned_frequency()); - field_mark.set_value(persistent_memory::afsk_mark_freq()); field_space.set_value(persistent_memory::afsk_space_freq()); - //field_bw.set_value(persistent_memory::modem_bw() / 1000); field_repeat.set_value(persistent_memory::modem_repeat()); - /*button_setfreq.on_select = [this, &nav](Button&) { - auto new_view = nav.push(persistent_memory::tuned_frequency()); - new_view->on_changed = [this](rf::Frequency f) { - update_freq(f); - }; - };*/ - field_baudrate.set_value(persistent_memory::modem_baudrate()); button_set_modem.on_select = [this, &nav](Button&) { @@ -114,7 +94,6 @@ ModemSetupView::ModemSetupView( persistent_memory::set_afsk_space(field_space.value()); persistent_memory::set_modem_baudrate(field_baudrate.value()); - //persistent_memory::set_modem_bw(field_bw.value() * 1000); persistent_memory::set_modem_repeat(field_repeat.value()); serial_format.data_bits = sym_format.get_sym(0) + 6; diff --git a/firmware/application/ui_modemsetup.hpp b/firmware/application/ui_modemsetup.hpp index fc47ee0fe..e50cb98a5 100644 --- a/firmware/application/ui_modemsetup.hpp +++ b/firmware/application/ui_modemsetup.hpp @@ -41,20 +41,13 @@ private: void update_freq(rf::Frequency f); Labels labels { - //{ { 2 * 8, 4 * 8 }, "Frequency:", Color::light_grey() }, { { 2 * 8, 11 * 8 }, "Baudrate:", Color::light_grey() }, { { 2 * 8, 13 * 8 }, "Mark: Hz", Color::light_grey() }, { { 2 * 8, 15 * 8 }, "Space: Hz", Color::light_grey() }, - //{ { 140, 13 * 8 }, "BW: kHz", Color::light_grey() }, { { 140, 15 * 8 }, "Repeat:", Color::light_grey() }, { { 1 * 8, 6 * 8 }, "Modem preset:", Color::light_grey() }, { { 2 * 8, 22 * 8 }, "Serial format:", Color::light_grey() } }; - - /*Button button_setfreq { - { 13 * 8, 3 * 8, 12 * 8, 32 }, - "----.----" - };*/ NumberField field_baudrate { { 11 * 8, 11 * 8 }, @@ -80,14 +73,6 @@ private: ' ' }; - /*NumberField field_bw { - { 172, 104 }, - 2, - { 1, 50 }, - 1, - ' ' - };*/ - NumberField field_repeat { { 204, 15 * 8 }, 2, diff --git a/firmware/application/ui_morse.cpp b/firmware/application/ui_morse.cpp index 195cde88e..2f1ae9214 100644 --- a/firmware/application/ui_morse.cpp +++ b/firmware/application/ui_morse.cpp @@ -42,14 +42,13 @@ static WORKING_AREA(ookthread_wa, 256); static msg_t ookthread_fn(void * arg) { uint32_t v = 0, delay = 0; - size_t i = 0; uint8_t * message_symbols = shared_memory.bb_data.tones_data.message; uint8_t symbol; MorseView * arg_c = (MorseView*)arg; chRegSetThreadName("ookthread"); - for (i = 0; i < arg_c->symbol_count; i++) { + for (uint32_t i = 0; i < arg_c->symbol_count; i++) { if (chThdShouldTerminate()) break; symbol = message_symbols[i]; @@ -128,7 +127,7 @@ void MorseView::update_tx_duration() { } } -void MorseView::on_tx_progress(const int progress, const bool done) { +void MorseView::on_tx_progress(const uint32_t progress, const bool done) { if (done) { transmitter_model.disable(); progressbar.set_value(0); diff --git a/firmware/application/ui_morse.hpp b/firmware/application/ui_morse.hpp index 20fdc7070..a9dcb79e7 100644 --- a/firmware/application/ui_morse.hpp +++ b/firmware/application/ui_morse.hpp @@ -52,8 +52,8 @@ public: void focus() override; void paint(Painter& painter) override; - - void on_tx_progress(const int progress, const bool done); + + void on_tx_progress(const uint32_t progress, const bool done); std::string title() const override { return "Morse TX"; }; @@ -159,10 +159,10 @@ private: 12 }; - MessageHandlerRegistration message_handler_tx_done { - Message::ID::TXDone, + MessageHandlerRegistration message_handler_tx_progress { + Message::ID::TXProgress, [this](const Message* const p) { - const auto message = *reinterpret_cast(p); + const auto message = *reinterpret_cast(p); this->on_tx_progress(message.progress, message.done); } }; diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 6367a9321..6ee1552ce 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -298,7 +298,8 @@ ReceiversMenuView::ReceiversMenuView(NavigationView& nav) { { "TPMS: Cars", ui::Color::green(), &bitmap_icon_tpms, [&nav](){ nav.push(); } }, }); on_left = [&nav](){ nav.pop(); }; - //set_highlighted(4); // Default selection is "Audio" + + set_highlighted(4); // Default selection is "Audio" } /* TransmittersMenuView **************************************************/ @@ -312,7 +313,6 @@ TransmittersMenuView::TransmittersMenuView(NavigationView& nav) { { "Microphone", ui::Color::green(), &bitmap_icon_microphone, [&nav](){ nav.push(); } }, { "Morse code", ui::Color::green(), &bitmap_icon_morse, [&nav](){ nav.push(); } }, { "NTTWorks burger pager", ui::Color::yellow(), &bitmap_icon_burger, [&nav](){ nav.push(); } }, - { "TouchTunes remote", ui::Color::orange(), nullptr, [&nav](){ nav.push(); } }, { "Nuoptix DTMF timecode", ui::Color::green(), &bitmap_icon_nuoptix, [&nav](){ nav.push(); } }, { "OOK remote encoders", ui::Color::yellow(), &bitmap_icon_remote, [&nav](){ nav.push(); } }, { "POCSAG", ui::Color::green(), &bitmap_icon_pocsag, [&nav](){ nav.push(); } }, @@ -321,6 +321,7 @@ TransmittersMenuView::TransmittersMenuView(NavigationView& nav) { { "Soundboard", ui::Color::green(), &bitmap_icon_soundboard, [&nav](){ nav.push(); } }, { "SSTV", ui::Color::green(), &bitmap_icon_sstv, [&nav](){ nav.push(); } }, { "TEDI/LCR AFSK", ui::Color::yellow(), &bitmap_icon_lcr, [&nav](){ nav.push(); } }, + { "TouchTunes remote", ui::Color::orange(), nullptr, [&nav](){ nav.push(); } }, }); on_left = [&nav](){ nav.pop(); }; } diff --git a/firmware/application/ui_nuoptix.cpp b/firmware/application/ui_nuoptix.cpp index b003868be..541d5a264 100644 --- a/firmware/application/ui_nuoptix.cpp +++ b/firmware/application/ui_nuoptix.cpp @@ -45,6 +45,13 @@ NuoptixView::~NuoptixView() { baseband::shutdown(); } +void NuoptixView::on_tx_progress(const uint32_t progress, const bool done) { + if (done) + transmit(false); + else + progressbar.set_value(progress); +} + void NuoptixView::transmit(bool setup) { uint8_t mod, tone_code; uint8_t c; diff --git a/firmware/application/ui_nuoptix.hpp b/firmware/application/ui_nuoptix.hpp index a305d75b5..9fa36d52e 100644 --- a/firmware/application/ui_nuoptix.hpp +++ b/firmware/application/ui_nuoptix.hpp @@ -59,6 +59,7 @@ private: void on_tuning_frequency_changed(rf::Frequency f); void transmit(bool setup); + void on_tx_progress(const uint32_t progress, const bool done); uint32_t timecode { 0 }; @@ -95,14 +96,11 @@ private: 15 }; - MessageHandlerRegistration message_handler_tx_done { - Message::ID::TXDone, + MessageHandlerRegistration message_handler_tx_progress { + Message::ID::TXProgress, [this](const Message* const p) { - const auto message = *reinterpret_cast(p); - if (message.done) - transmit(false); - else - progressbar.set_value(message.progress); + const auto message = *reinterpret_cast(p); + this->on_tx_progress(message.progress, message.done); } }; }; diff --git a/firmware/application/ui_pocsag_tx.cpp b/firmware/application/ui_pocsag_tx.cpp index f025eba3d..e7c191792 100644 --- a/firmware/application/ui_pocsag_tx.cpp +++ b/firmware/application/ui_pocsag_tx.cpp @@ -42,7 +42,7 @@ POCSAGTXView::~POCSAGTXView() { baseband::shutdown(); } -void POCSAGTXView::on_tx_progress(const int progress, const bool done) { +void POCSAGTXView::on_tx_progress(const uint32_t progress, const bool done) { if (done) { transmitter_model.disable(); progressbar.set_value(0); diff --git a/firmware/application/ui_pocsag_tx.hpp b/firmware/application/ui_pocsag_tx.hpp index 5a7fb24a0..60c3aeb9a 100644 --- a/firmware/application/ui_pocsag_tx.hpp +++ b/firmware/application/ui_pocsag_tx.hpp @@ -63,7 +63,7 @@ private: }; void on_set_text(NavigationView& nav); - void on_tx_progress(const int progress, const bool done); + void on_tx_progress(const uint32_t progress, const bool done); bool start_tx(); Labels labels { @@ -131,10 +131,10 @@ private: 9 }; - MessageHandlerRegistration message_handler_tx_done { - Message::ID::TXDone, + MessageHandlerRegistration message_handler_tx_progress { + Message::ID::TXProgress, [this](const Message* const p) { - const auto message = *reinterpret_cast(p); + const auto message = *reinterpret_cast(p); this->on_tx_progress(message.progress, message.done); } }; diff --git a/firmware/application/ui_siggen.cpp b/firmware/application/ui_siggen.cpp index dfc280289..7d55213db 100644 --- a/firmware/application/ui_siggen.cpp +++ b/firmware/application/ui_siggen.cpp @@ -60,7 +60,9 @@ void SigGenView::update_tone() { baseband::set_siggen_tone(symfield_tone.value_dec_u32()); } -void SigGenView::on_tx_progress(const bool done) { +void SigGenView::on_tx_progress(const uint32_t progress, const bool done) { + (void) progress; + if (done) tx_view.set_transmitting(false); } diff --git a/firmware/application/ui_siggen.hpp b/firmware/application/ui_siggen.hpp index ce8ce16fa..20ac4af69 100644 --- a/firmware/application/ui_siggen.hpp +++ b/firmware/application/ui_siggen.hpp @@ -45,7 +45,7 @@ public: private: void start_tx(); void update_tone(); - void on_tx_progress(const bool done); + void on_tx_progress(const uint32_t progress, const bool done); const std::string shape_strings[7] = { "CW", @@ -123,11 +123,11 @@ private: 12 }; - MessageHandlerRegistration message_handler_tx_done { - Message::ID::TXDone, + MessageHandlerRegistration message_handler_tx_progress { + Message::ID::TXProgress, [this](const Message* const p) { - const auto message = *reinterpret_cast(p); - this->on_tx_progress(message.done); + const auto message = *reinterpret_cast(p); + this->on_tx_progress(message.progress, message.done); } }; }; diff --git a/firmware/application/ui_touchtunes.cpp b/firmware/application/ui_touchtunes.cpp index 7a880f5a6..69feb9bec 100644 --- a/firmware/application/ui_touchtunes.cpp +++ b/firmware/application/ui_touchtunes.cpp @@ -40,27 +40,29 @@ TouchTunesView::~TouchTunesView() { baseband::shutdown(); } -void TouchTunesView::on_tx_progress(const int progress, const bool done) { +void TouchTunesView::stop_tx() { + transmitter_model.disable(); + tx_mode = IDLE; + progressbar.set_value(0); + text_status.set("Ready"); +} + +void TouchTunesView::on_tx_progress(const uint32_t progress, const bool done) { if (!done) { - // Repeating - if (tx_mode == SINGLE) { + // Progress + if (tx_mode == SINGLE) progressbar.set_value(progress); - } else if (tx_mode == SCAN) { - progressbar.set_value((pin * 4) + progress); - } + else if (tx_mode == SCAN) + progressbar.set_value((pin * TOUCHTUNES_REPEATS) + progress); } else { // Done transmitting if (tx_mode == SINGLE) { - transmitter_model.disable(); - tx_mode = IDLE; - progressbar.set_value(0); + stop_tx(); } else if (tx_mode == SCAN) { - pin++; - if (pin == 256) { - transmitter_model.disable(); - tx_mode = IDLE; - progressbar.set_value(0); + if (pin == TOUCHTUNES_MAX_PIN) { + stop_tx(); } else { + pin++; field_pin.set_value(pin); start_tx(scan_button_index); } @@ -76,28 +78,36 @@ void TouchTunesView::start_tx(const uint32_t button_index) { if (check_scan.value()) { scan_button_index = button_index; tx_mode = SCAN; - progressbar.set_max(256 * 4); + progressbar.set_max(TOUCHTUNES_MAX_PIN * TOUCHTUNES_REPEATS); + text_status.set("Scanning..."); } else { tx_mode = SINGLE; - progressbar.set_max(4); + progressbar.set_max(TOUCHTUNES_REPEATS); + text_status.set("Transmitting..."); } - frame_data = 0x5D; // Sync word + frame_data = TOUCHTUNES_SYNC_WORD; // Sync word + // Insert pin value (LSB first) for (bit = 0; bit < 8; bit++) { frame_data <<= 1; if (pin & (1 << bit)) frame_data |= 1; } + // Insert button code (and its complement) frame_data <<= 16; - frame_data |= button_codes[button_index]; + frame_data |= (button_codes[button_index] << 8); + frame_data |= (button_codes[button_index] ^ 0xFF); + // Convert to OOK symbols for (bit = 0; bit < (8 + 8 + 16); bit++) { fragments += (frame_data & 0x80000000UL) ? "1000" : "10"; frame_data <<= 1; } - fragments = "111111111111111100000000" + fragments + "1000"; // End pulse + + // Sync and end pulse + fragments = "111111111111111100000000" + fragments + "1000"; size_t bitstream_length = make_bitstream(fragments); @@ -109,28 +119,20 @@ void TouchTunesView::start_tx(const uint32_t button_index) { baseband::set_ook_data( bitstream_length, - OOK_SAMPLERATE / 1766, // 1766 baud, 566us/bit - 4, // Repeats - 100 + OOK_SAMPLERATE / 1786, // 560us + TOUCHTUNES_REPEATS, + 100 // Pause ); } TouchTunesView::TouchTunesView( NavigationView& -) -{ +) { baseband::run_image(portapack::spi_flash::image_tag_ook); add_children({ &labels, &field_pin, - &button_on_off, - &button_pause, - &button_p1, - &button_ok, - &button_vol_inc1, - &button_vol_inc2, - &button_vol_inc3, &check_scan, &text_status, &progressbar @@ -142,28 +144,22 @@ TouchTunesView::TouchTunesView( pin = v; }; - button_on_off.on_select = [this](Button&) { - start_tx(0); + const auto button_fn = [this](Button& button) { + start_tx(button.id); }; - button_pause.on_select = [this](Button&) { - start_tx(1); - }; - button_p1.on_select = [this](Button&) { - start_tx(2); - }; - button_ok.on_select = [this](Button&) { - start_tx(3); - }; - button_vol_inc1.on_select = [this](Button&) { - start_tx(4); - }; - button_vol_inc2.on_select = [this](Button&) { - start_tx(5); - }; - button_vol_inc3.on_select = [this](Button&) { - start_tx(6); - }; + size_t n = 0; + for (auto& entry : remote_layout) { + buttons[n].on_select = button_fn; + buttons[n].id = n; + buttons[n].set_text(entry.text); + buttons[n].set_parent_rect({ + entry.position + Point(8, 0), + { (Dim)(entry.text.length() + 2) * 8, 4 * 8 } + }); + add_child(&buttons[n]); + n++; + } } } /* namespace ui */ diff --git a/firmware/application/ui_touchtunes.hpp b/firmware/application/ui_touchtunes.hpp index dfa1a4edd..610d4b201 100644 --- a/firmware/application/ui_touchtunes.hpp +++ b/firmware/application/ui_touchtunes.hpp @@ -25,7 +25,9 @@ #include "transmitter_model.hpp" // The coding in notpike's script is quite complex, using multiple LUTs to form the data sent to the YSO. -// The format is actually very simple if it is rather seen as short and long gaps between pulses (as seen in many OOK remotes): +// The format is actually very simple if it is rather seen as short and long gaps between pulses (as seen in many OOK remotes). +// The frames and data rate suspiciously match the NEC infrared protocol (http://www.sbprojects.com/knowledge/ir/nec.php) without +// the address complement. The exact data rate would be 1786 baud (560us/fragment). // Pin 0 - On/Off // ffff00 a2888a2aaaa8888aa2aa2220 @@ -57,14 +59,44 @@ // The hex data only seems scrambled because of the shift induced by the short or long gaps (10 or 1000) // The radio frame's duration depends on the value of the bits -const uint16_t button_codes[7] = { - 0x7887, // On/Off - 0xB34C, // Pause - 0xF10E, // P1 - 0xDD22, // OK - 0xF40B, // Zone 1 Vol+ - 0xF609, // Zone 2 Vol+ - 0xFC03 // Zone 3 Vol+ +#define TOUCHTUNES_MAX_PIN 255 +#define TOUCHTUNES_REPEATS 4 +#define TOUCHTUNES_SYNC_WORD 0x5D + +// Each 16bit button code is actually 8bit followed by its complement +const uint8_t button_codes[32] = { + 0xB3, // Pause + 0x78, // On/Off + 0xF1, // P1 + 0x60, // P2 + 0xCA, // P3 + 0x20, // F1 + 0xF2, // Up + 0xA0, // F2 + 0x84, // Left + 0xDD, // OK + 0xC4, // Right + 0x30, // F3 + 0x80, // Down + 0xB0, // F4 + 0xF0, // 1 + 0x08, // 2 + 0x88, // 3 + 0x48, // 4 + 0xC8, // 5 + 0x28, // 6 + 0xA8, // 7 + 0x68, // 8 + 0xE8, // 9 + 0x18, // Music_Karaoke + 0x98, // 0 + 0x58, // Lock_Queue + 0xF4, // Zone 1 Vol+ + 0xF6, // Zone 2 Vol+ + 0xFC, // Zone 3 Vol+ + 0x50, // Zone 1 Vol- + 0x10, // Zone 2 Vol- + 0x40, // Zone 3 Vol- }; namespace ui { @@ -79,10 +111,6 @@ public: std::string title() const override { return "TouchTunes TX"; }; private: - Labels labels { - { { 2 * 8, 2 * 8 }, "PIN:", Color::light_grey() } - }; - uint32_t scan_button_index { }; uint32_t pin { 0 }; @@ -95,66 +123,90 @@ private: tx_modes tx_mode = IDLE; void start_tx(const uint32_t button_index); - void on_tx_progress(const int progress, const bool done); + void stop_tx(); + void on_tx_progress(const uint32_t progress, const bool done); + + struct remote_layout_t { + Point position; + std::string text; + }; + + const std::array remote_layout { { + { { 12 * 8, 0 }, "PAUSE" }, + { { 21 * 8, 0 }, "POWER" }, + + { { 14 * 8, 5 * 8 }, "P1" }, + { { 18 * 8, 5 * 8 }, "P2" }, + { { 22 * 8, 5 * 8 }, "P3" }, + + { { 14 * 8, 10 * 8 }, "F1" }, + { { 18 * 8 + 4, 10 * 8 }, "^" }, + { { 22 * 8, 10 * 8 }, "F2" }, + + { { 14 * 8, 14 * 8 }, "<" }, + { { 18 * 8, 14 * 8 }, "OK" }, + { { 23 * 8, 14 * 8 }, ">" }, + + { { 14 * 8, 18 * 8 }, "F3" }, + { { 18 * 8 + 4, 18 * 8 }, "V" }, + { { 22 * 8, 18 * 8 }, "F4" }, + + { { 0 * 8, 5 * 8 }, "1" }, + { { 4 * 8, 5 * 8 }, "2" }, + { { 8 * 8, 5 * 8 }, "3" }, + { { 0 * 8, 10 * 8 }, "4" }, + { { 4 * 8, 10 * 8 }, "5" }, + { { 8 * 8, 10 * 8 }, "6" }, + { { 0 * 8, 15 * 8 }, "7" }, + { { 4 * 8, 15 * 8 }, "8" }, + { { 8 * 8, 15 * 8 }, "9" }, + { { 0 * 8, 20 * 8 }, "*" }, + { { 4 * 8, 20 * 8 }, "0" }, + { { 8 * 8, 20 * 8 }, "#" }, + + { { 13 * 8, 23 * 8 }, "+" }, + { { 18 * 8, 23 * 8 }, "+" }, + { { 23 * 8, 23 * 8 }, "+" }, + + { { 13 * 8, 29 * 8 }, "-" }, + { { 18 * 8, 29 * 8 }, "-" }, + { { 23 * 8, 29 * 8 }, "-" } + } }; + + Labels labels { + { { 2 * 8, 1 * 8 }, "PIN:", Color::light_grey() }, + { { 13 * 8 + 4, 27 * 8 }, "VOL1 VOL2 VOL3", Color::light_grey() } + }; + + std::array buttons { }; NumberField field_pin { - { 6 * 8, 1 * 16 }, + { 6 * 8, 1 * 8 }, 3, { 0, 255 }, 1, - ' ' - }; - - Button button_on_off { - { 2 * 8, 3 * 16, 8 * 8, 2 * 16 }, - "ON/OFF" - }; - - Button button_pause { - { 2 * 8, 6 * 16, 8 * 8, 2 * 16 }, - "PAUSE" - }; - Button button_p1 { - { 11 * 8, 6 * 16, 8 * 8, 2 * 16 }, - "P1" - }; - Button button_ok { - { 20 * 8, 6 * 16, 8 * 8, 2 * 16 }, - "OK" - }; - - Button button_vol_inc1 { - { 2 * 8, 9 * 16, 8 * 8, 2 * 16 }, - "VOL+ 1" - }; - Button button_vol_inc2 { - { 11 * 8, 9 * 16, 8 * 8, 2 * 16 }, - "VOL+ 2" - }; - Button button_vol_inc3 { - { 20 * 8, 9 * 16, 8 * 8, 2 * 16 }, - "VOL+ 3" + '0' }; Checkbox check_scan { - { 2 * 8, 13 * 16 }, + { 2 * 8, 27 * 8 }, 4, "Scan" }; Text text_status { - { 2 * 8, 15 * 16, 128, 16 }, + { 2 * 8, 33 * 8, 128, 16 }, "Ready" }; ProgressBar progressbar { - { 2 * 8, 15 * 16 + 20, 208, 16 } + { 2 * 8, 35 * 8, 208, 16 } }; - MessageHandlerRegistration message_handler_tx_done { - Message::ID::TXDone, + MessageHandlerRegistration message_handler_tx_progress { + Message::ID::TXProgress, [this](const Message* const p) { - const auto message = *reinterpret_cast(p); + const auto message = *reinterpret_cast(p); this->on_tx_progress(message.progress, message.done); } }; diff --git a/firmware/baseband/proc_adsbtx.hpp b/firmware/baseband/proc_adsbtx.hpp index 6d2b8d358..a92f05a64 100644 --- a/firmware/baseband/proc_adsbtx.hpp +++ b/firmware/baseband/proc_adsbtx.hpp @@ -48,7 +48,7 @@ private: uint32_t cur_bit { 0 }; uint32_t phase { 0 }; - TXDoneMessage message { }; + TXProgressMessage txprogress_message { }; }; #endif diff --git a/firmware/baseband/proc_afsk.cpp b/firmware/baseband/proc_afsk.cpp index 600058d04..081087a5b 100644 --- a/firmware/baseband/proc_afsk.cpp +++ b/firmware/baseband/proc_afsk.cpp @@ -46,14 +46,15 @@ void AFSKProcessor::execute(const buffer_c8_t& buffer) { bit_pos = 0; word_ptr = (uint16_t*)shared_memory.bb_data.data; cur_word = *word_ptr; - message.progress = repeat_counter + 1; - shared_memory.application_queue.push(message); + txprogress_message.done = false; + txprogress_message.progress = repeat_counter + 1; + shared_memory.application_queue.push(txprogress_message); repeat_counter++; } else { // Stop cur_word = 0; - message.progress = 0; - shared_memory.application_queue.push(message); + txprogress_message.done = true; + shared_memory.application_queue.push(txprogress_message); configured = false; } } @@ -101,7 +102,7 @@ void AFSKProcessor::on_message(const Message* const msg) { afsk_phase_inc_mark = message.phase_inc_mark * AFSK_DELTA_COEF; afsk_phase_inc_space = message.phase_inc_space * AFSK_DELTA_COEF; afsk_repeat = message.repeat - 1; - fm_delta = message.fm_delta * (0xFFFFFFULL / 1536000); + fm_delta = message.fm_delta * (0xFFFFFFULL / AFSK_SAMPLERATE); symbol_count = message.symbol_count - 1; sample_count = afsk_samples_per_bit; diff --git a/firmware/baseband/proc_afsk.hpp b/firmware/baseband/proc_afsk.hpp index e021c4e05..2085022c4 100644 --- a/firmware/baseband/proc_afsk.hpp +++ b/firmware/baseband/proc_afsk.hpp @@ -38,7 +38,7 @@ public: private: bool configured = false; - BasebandThread baseband_thread { 1536000, this, NORMALPRIO + 20, baseband::Direction::Transmit }; + BasebandThread baseband_thread { AFSK_SAMPLERATE, this, NORMALPRIO + 20, baseband::Direction::Transmit }; uint32_t afsk_samples_per_bit { 0 }; uint32_t afsk_phase_inc_mark { 0 }; @@ -58,7 +58,7 @@ private: int8_t re { 0 }, im { 0 }; - TXDoneMessage message { }; + TXProgressMessage txprogress_message { }; }; #endif diff --git a/firmware/baseband/proc_fsk.cpp b/firmware/baseband/proc_fsk.cpp index cbbe282ac..f5f565887 100644 --- a/firmware/baseband/proc_fsk.cpp +++ b/firmware/baseband/proc_fsk.cpp @@ -40,16 +40,17 @@ void FSKProcessor::execute(const buffer_c8_t& buffer) { if (bit_pos > length) { // End of data cur_bit = 0; - txdone_message.done = true; - shared_memory.application_queue.push(txdone_message); + txprogress_message.done = true; + shared_memory.application_queue.push(txprogress_message); configured = false; } else { cur_bit = (shared_memory.bb_data.data[bit_pos >> 3] << (bit_pos & 7)) & 0x80; bit_pos++; if (progress_count >= progress_notice) { progress_count = 0; - txdone_message.progress++; - shared_memory.application_queue.push(txdone_message); + txprogress_message.progress++; + txprogress_message.done = false; + shared_memory.application_queue.push(txprogress_message); } else { progress_count++; } @@ -95,8 +96,8 @@ void FSKProcessor::on_message(const Message* const p) { bit_pos = 0; cur_bit = 0; - txdone_message.progress = 0; - txdone_message.done = false; + txprogress_message.progress = 0; + txprogress_message.done = false; configured = true; } } diff --git a/firmware/baseband/proc_fsk.hpp b/firmware/baseband/proc_fsk.hpp index 9685b5968..77ba82eb9 100644 --- a/firmware/baseband/proc_fsk.hpp +++ b/firmware/baseband/proc_fsk.hpp @@ -47,7 +47,7 @@ private: uint32_t sample_count { 0 }; uint32_t phase { 0 }, sphase { 0 }; - TXDoneMessage txdone_message { }; + TXProgressMessage txprogress_message { }; }; #endif diff --git a/firmware/baseband/proc_mictx.cpp b/firmware/baseband/proc_mictx.cpp index e9e740431..9a1aa0ec6 100644 --- a/firmware/baseband/proc_mictx.cpp +++ b/firmware/baseband/proc_mictx.cpp @@ -60,7 +60,7 @@ void MicTXProcessor::execute(const buffer_c8_t& buffer){ if (beep_index == BEEP_TONES_NB) { configured = false; fm_delta = 0; // Zero-out the IQ output for the rest of the buffer - shared_memory.application_queue.push(txdone_message); + shared_memory.application_queue.push(txprogress_message); } else { beep_phase_inc = beep_deltas[beep_index]; beep_index++; @@ -108,7 +108,7 @@ void MicTXProcessor::on_message(const Message* const msg) { ctcss_enabled = config_message.ctcss_enabled; ctcss_phase_inc = config_message.ctcss_phase_inc; - txdone_message.done = true; + txprogress_message.done = true; play_beep = false; configured = true; diff --git a/firmware/baseband/proc_mictx.hpp b/firmware/baseband/proc_mictx.hpp index 0590d15d5..003b9fc1a 100644 --- a/firmware/baseband/proc_mictx.hpp +++ b/firmware/baseband/proc_mictx.hpp @@ -60,7 +60,7 @@ private: int8_t re { 0 }, im { 0 }; AudioLevelReportMessage level_message { }; - TXDoneMessage txdone_message { }; + TXProgressMessage txprogress_message { }; }; #endif diff --git a/firmware/baseband/proc_ook.cpp b/firmware/baseband/proc_ook.cpp index 4d2039328..0bf8dfb60 100644 --- a/firmware/baseband/proc_ook.cpp +++ b/firmware/baseband/proc_ook.cpp @@ -51,14 +51,15 @@ void OOKProcessor::execute(const buffer_c8_t& buffer) { // Repeat bit_pos = 0; cur_bit = shared_memory.bb_data.data[0] & 0x80; - txdone_message.progress = repeat_counter + 1; - shared_memory.application_queue.push(txdone_message); + txprogress_message.progress = repeat_counter + 1; + txprogress_message.done = false; + shared_memory.application_queue.push(txprogress_message); repeat_counter++; } else { // Stop cur_bit = 0; - txdone_message.done = true; - shared_memory.application_queue.push(txdone_message); + txprogress_message.done = true; + shared_memory.application_queue.push(txprogress_message); configured = false; } pause_counter = 0; @@ -109,8 +110,8 @@ void OOKProcessor::on_message(const Message* const p) { repeat_counter = 0; bit_pos = 0; cur_bit = 0; - txdone_message.progress = 0; - txdone_message.done = false; + txprogress_message.progress = 0; + txprogress_message.done = false; configured = true; } } diff --git a/firmware/baseband/proc_ook.hpp b/firmware/baseband/proc_ook.hpp index 75865fd03..e678b45c5 100644 --- a/firmware/baseband/proc_ook.hpp +++ b/firmware/baseband/proc_ook.hpp @@ -51,7 +51,7 @@ private: uint32_t tone_phase { 0 }, phase { 0 }, sphase { 0 }; int32_t tone_sample { 0 }, sig { 0 }, frq { 0 }; - TXDoneMessage txdone_message { }; + TXProgressMessage txprogress_message { }; }; #endif diff --git a/firmware/baseband/proc_siggen.cpp b/firmware/baseband/proc_siggen.cpp index a10c12410..905acda8d 100644 --- a/firmware/baseband/proc_siggen.cpp +++ b/firmware/baseband/proc_siggen.cpp @@ -33,8 +33,8 @@ void SigGenProcessor::execute(const buffer_c8_t& buffer) { for (size_t i = 0; i < buffer.count; i++) { if (!sample_count && auto_off) { - message.done = true; - shared_memory.application_queue.push(message); + txprogress_message.done = true; + shared_memory.application_queue.push(txprogress_message); } else sample_count--; diff --git a/firmware/baseband/proc_siggen.hpp b/firmware/baseband/proc_siggen.hpp index 18a25bfd8..f547cc0f0 100644 --- a/firmware/baseband/proc_siggen.hpp +++ b/firmware/baseband/proc_siggen.hpp @@ -46,7 +46,7 @@ private: int8_t sample { 0 }; int8_t re { 0 }, im { 0 }; - TXDoneMessage message { }; + TXProgressMessage txprogress_message { }; }; #endif diff --git a/firmware/baseband/proc_tones.cpp b/firmware/baseband/proc_tones.cpp index 27aa1921d..2e93ef3d4 100644 --- a/firmware/baseband/proc_tones.cpp +++ b/firmware/baseband/proc_tones.cpp @@ -52,12 +52,13 @@ void TonesProcessor::execute(const buffer_c8_t& buffer) { digit = shared_memory.bb_data.tones_data.message[digit_pos]; if (digit_pos >= message_length) { configured = false; - txdone_message.done = true; - shared_memory.application_queue.push(txdone_message); + txprogress_message.done = true; + shared_memory.application_queue.push(txprogress_message); return; } else { - txdone_message.progress = digit_pos; // Inform UI about progress - shared_memory.application_queue.push(txdone_message); + txprogress_message.progress = digit_pos; // Inform UI about progress + txprogress_message.done = false; + shared_memory.application_queue.push(txprogress_message); } digit_pos++; @@ -136,8 +137,8 @@ void TonesProcessor::on_message(const Message* const p) { if (audio_out) audio_output.configure(false); - txdone_message.done = false; - txdone_message.progress = 0; + txprogress_message.done = false; + txprogress_message.progress = 0; digit_pos = 0; sample_count = 0; @@ -148,8 +149,8 @@ void TonesProcessor::on_message(const Message* const p) { configured = true; } else { configured = false; - txdone_message.done = true; - shared_memory.application_queue.push(txdone_message); + txprogress_message.done = true; + shared_memory.application_queue.push(txprogress_message); } } } diff --git a/firmware/baseband/proc_tones.hpp b/firmware/baseband/proc_tones.hpp index d298922e3..85d9d1ba2 100644 --- a/firmware/baseband/proc_tones.hpp +++ b/firmware/baseband/proc_tones.hpp @@ -62,7 +62,7 @@ private: int8_t re { 0 }, im { 0 }; uint8_t as { 0 }, ai { 0 }; - TXDoneMessage txdone_message { }; + TXProgressMessage txprogress_message { }; AudioOutput audio_output { }; }; diff --git a/firmware/common/emu_cc1101.hpp b/firmware/common/emu_cc1101.hpp index 724e0049f..549535fe1 100644 --- a/firmware/common/emu_cc1101.hpp +++ b/firmware/common/emu_cc1101.hpp @@ -32,7 +32,6 @@ namespace cc1101 { // Data rate (Bauds) // Whitening: Everything except preamble and sync word, init value = 111111111 -// See datasheet page 38 for logic schematic // Packet format: preamble, sync word, (opt) length, (opt) address, payload, (opt) CRC // Preamble: 8*n bits of 10101010 // Sync word: 2 bytes (can be repeated twice) @@ -100,6 +99,12 @@ private: modulation_t modulation_ { TWO_FSK }; uint8_t num_preamble_ { 4 }; size_t deviation_ { 4000 }; + + uint16_t whitening_pn { 0x1FF }; + + void whitening_init(); + uint8_t whiten_byte(uint8_t byte); + }; } /* namespace cc1101 */ diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index d193cad80..c9c244958 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -73,7 +73,7 @@ public: ReplayThreadDone = 20, AFSKRxConfigure = 21, - TXDone = 30, + TXProgress = 30, Retune = 31, TonesConfigure = 32, @@ -604,10 +604,10 @@ public: ReplayConfig* const config; }; -class TXDoneMessage : public Message { +class TXProgressMessage : public Message { public: - constexpr TXDoneMessage( - ) : Message { ID::TXDone } + constexpr TXProgressMessage( + ) : Message { ID::TXProgress } { } diff --git a/firmware/common/portapack_persistent_memory.cpp b/firmware/common/portapack_persistent_memory.cpp index 37360ac52..7d8e7478e 100644 --- a/firmware/common/portapack_persistent_memory.cpp +++ b/firmware/common/portapack_persistent_memory.cpp @@ -51,9 +51,9 @@ using modem_baudrate_range_t = range_t; constexpr modem_baudrate_range_t modem_baudrate_range { 50, 9600 }; constexpr int32_t modem_baudrate_reset_value { 1200 }; -using modem_bw_range_t = range_t; +/*using modem_bw_range_t = range_t; constexpr modem_bw_range_t modem_bw_range { 1000, 50000 }; -constexpr int32_t modem_bw_reset_value { 15000 }; +constexpr int32_t modem_bw_reset_value { 15000 };*/ using modem_repeat_range_t = range_t; constexpr modem_repeat_range_t modem_repeat_range { 1, 99 }; @@ -151,14 +151,14 @@ void set_modem_baudrate(const int32_t new_value) { data->modem_baudrate = modem_baudrate_range.clip(new_value); } -int32_t modem_bw() { +/*int32_t modem_bw() { modem_bw_range.reset_if_outside(data->modem_bw, modem_bw_reset_value); return data->modem_bw; } void set_modem_bw(const int32_t new_value) { data->modem_bw = modem_bw_range.clip(new_value); -} +}*/ uint8_t modem_repeat() { modem_repeat_range.reset_if_outside(data->modem_repeat, modem_repeat_reset_value); diff --git a/firmware/common/portapack_persistent_memory.hpp b/firmware/common/portapack_persistent_memory.hpp index d1ece441d..5ff21dd69 100644 --- a/firmware/common/portapack_persistent_memory.hpp +++ b/firmware/common/portapack_persistent_memory.hpp @@ -61,8 +61,6 @@ void set_modem_baudrate(const int32_t new_value); uint8_t modem_repeat(); void set_modem_repeat(const uint32_t new_value); -int32_t modem_bw(); -void set_modem_bw(const int32_t new_value); uint32_t playing_dead(); void set_playing_dead(const uint32_t new_value); diff --git a/firmware/portapack-h1-havoc.bin b/firmware/portapack-h1-havoc.bin index 5c01174be..f890984ba 100644 Binary files a/firmware/portapack-h1-havoc.bin and b/firmware/portapack-h1-havoc.bin differ