From d40016ffdabd2d1f14778a51c676a6409856ba4e Mon Sep 17 00:00:00 2001 From: furrtek Date: Mon, 9 May 2016 20:42:20 +0200 Subject: [PATCH] Fixed LCR and Xylos transmitters --- firmware/Makefile | 2 +- firmware/application/Makefile | 2 + firmware/application/touch.hpp | 6 +- firmware/application/ui_audiotx.hpp | 1 - firmware/application/ui_handwrite.cpp | 404 +++++++++++++++++++++ firmware/application/ui_handwrite.hpp | 105 ++++++ firmware/application/ui_lcr.cpp | 57 ++- firmware/application/ui_lcr.hpp | 11 +- firmware/application/ui_loadmodule.cpp | 14 +- firmware/application/ui_loadmodule.hpp | 2 +- firmware/application/ui_menu.cpp | 2 +- firmware/application/ui_navigation.cpp | 40 +- firmware/application/ui_soundboard.cpp | 145 ++++++++ firmware/application/ui_soundboard.hpp | 93 +++++ firmware/application/ui_xylos.cpp | 23 +- firmware/application/ui_xylos.hpp | 55 ++- firmware/baseband-tx.bin | Bin 33280 -> 33280 bytes firmware/baseband-tx/Makefile | 2 + firmware/baseband-tx/audio_compressor.cpp | 52 +++ firmware/baseband-tx/audio_compressor.hpp | 102 ++++++ firmware/baseband-tx/baseband_thread.cpp | 4 + firmware/baseband-tx/ook.hpp | 93 +++++ firmware/baseband-tx/phase_accumulator.hpp | 50 +++ firmware/baseband-tx/phase_detector.hpp | 68 ++++ firmware/baseband-tx/proc_audiotx.cpp | 56 +-- firmware/baseband-tx/proc_audiotx.hpp | 6 - firmware/baseband-tx/proc_tpms.cpp | 72 ++++ firmware/baseband-tx/proc_tpms.hpp | 125 +++++++ firmware/baseband-tx/proc_xylos.cpp | 6 +- firmware/baseband-tx/proc_xylos.hpp | 15 +- firmware/baseband-tx/stream_input.hpp | 73 ++++ firmware/baseband.bin | Bin 33280 -> 33280 bytes firmware/common/modules.h | 4 +- firmware/common/ui.hpp | 14 +- firmware/common/ui_widget.cpp | 46 ++- firmware/common/ui_widget.hpp | 15 + firmware/portapack-h1-firmware.bin | Bin 454488 -> 459560 bytes sdcard/baseband-tx.bin | Bin 33280 -> 33280 bytes sdcard/baseband.bin | Bin 33280 -> 33280 bytes 39 files changed, 1614 insertions(+), 151 deletions(-) create mode 100644 firmware/application/ui_handwrite.cpp create mode 100644 firmware/application/ui_handwrite.hpp create mode 100644 firmware/application/ui_soundboard.cpp create mode 100644 firmware/application/ui_soundboard.hpp create mode 100644 firmware/baseband-tx/audio_compressor.cpp create mode 100644 firmware/baseband-tx/audio_compressor.hpp create mode 100644 firmware/baseband-tx/ook.hpp create mode 100644 firmware/baseband-tx/phase_accumulator.hpp create mode 100644 firmware/baseband-tx/phase_detector.hpp create mode 100644 firmware/baseband-tx/proc_tpms.cpp create mode 100644 firmware/baseband-tx/proc_tpms.hpp create mode 100644 firmware/baseband-tx/stream_input.hpp diff --git a/firmware/Makefile b/firmware/Makefile index 18302e65..5bce1a9f 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -64,7 +64,7 @@ modules: $(TARGET_BASEBAND).bin $(TARGET_BASEBAND_TX).bin cp $(PATH_BASEBAND).bin ../sdcard/$(PATH_BASEBAND).bin cp $(PATH_BASEBAND_TX).bin ../sdcard/$(PATH_BASEBAND_TX).bin -$(TARGET).bin: modules $(MAKE_SPI_IMAGE) $(TARGET_BOOTSTRAP).bin $(TARGET_HACKRF_FIRMWARE).dfu $(TARGET_BASEBAND)_inc.bin $(TARGET_APPLICATION).bin +$(TARGET).bin: modules $(MAKE_SPI_IMAGE) $(TARGET_BOOTSTRAP).bin $(TARGET_HACKRF_FIRMWARE).dfu $(TARGET_BASEBAND_TX)_inc.bin $(TARGET_APPLICATION).bin $(MAKE_SPI_IMAGE) $(TARGET_BOOTSTRAP).bin $(TARGET_HACKRF_FIRMWARE).dfu $(TARGET_BASEBAND)_inc.bin $(TARGET_APPLICATION).bin $(TARGET).bin $(TARGET_BOOTSTRAP).bin: $(TARGET_BOOTSTRAP).elf diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 4aeff3f0..caef1a99 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -151,6 +151,7 @@ CPPSRC = main.cpp \ lcd_ili9341.cpp \ ui.cpp \ ui_alphanum.cpp \ + ui_handwrite.cpp \ ui_about.cpp \ ui_text.cpp \ ui_widget.cpp \ @@ -162,6 +163,7 @@ CPPSRC = main.cpp \ ui_channel.cpp \ ui_audio.cpp \ ui_audiotx.cpp \ + ui_soundboard.cpp \ ui_lcr.cpp \ ui_rds.cpp \ ui_jammer.cpp \ diff --git a/firmware/application/touch.hpp b/firmware/application/touch.hpp index 0402243a..c814db2c 100644 --- a/firmware/application/touch.hpp +++ b/firmware/application/touch.hpp @@ -180,12 +180,12 @@ private: static constexpr size_t touch_count_threshold { 4 }; static constexpr uint32_t touch_stable_bound { 4 }; - static constexpr float calib_x_low = 0.07f; - static constexpr float calib_x_high = 0.94f; + static constexpr float calib_x_low = 0.15f; + static constexpr float calib_x_high = 0.98f; static constexpr float calib_x_range = calib_x_high - calib_x_low; static constexpr float calib_y_low = 0.04f; - static constexpr float calib_y_high = 0.91f; + static constexpr float calib_y_high = 0.80f; //91 static constexpr float calib_y_range = calib_y_high - calib_y_low; // Ensure filter length is equal or less than touch_count_threshold, diff --git a/firmware/application/ui_audiotx.hpp b/firmware/application/ui_audiotx.hpp index 4cc7ede4..d9074cf5 100644 --- a/firmware/application/ui_audiotx.hpp +++ b/firmware/application/ui_audiotx.hpp @@ -40,7 +40,6 @@ public: AudioTXView(NavigationView& nav); ~AudioTXView(); - void focus() override; private: diff --git a/firmware/application/ui_handwrite.cpp b/firmware/application/ui_handwrite.cpp new file mode 100644 index 00000000..243ea88a --- /dev/null +++ b/firmware/application/ui_handwrite.cpp @@ -0,0 +1,404 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * 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 "ui_handwrite.hpp" + +#include "ch.h" + +#include "ff.h" +#include "portapack.hpp" +#include "event_m0.hpp" +#include "string_format.hpp" +#include "hackrf_hal.hpp" +#include "portapack_shared_memory.hpp" +#include "time.hpp" + +#include + +using namespace portapack; + +namespace ui { + +HandWriteView::~HandWriteView() { + time::signal_tick_second -= signal_token_tick_second; +} + +HandWriteView::HandWriteView( + NavigationView& nav, + char txt[], + uint8_t max_len +) { + _max_len = max_len; + _lowercase = false; + + txtidx = 0; + //memcpy(txtinput, txt, max_len+1); + + add_child(&text_input); + + const auto button_fn = [this](Button& button) { + this->on_button(button); + }; + + size_t n = 0; + for(auto& button : num_buttons) { + add_child(&button); + button.on_select = button_fn; + button.set_parent_rect({ + static_cast(n * 24), + static_cast(240), + 24, 20 + }); + const std::string label { + n + 0x30 + }; + button.set_text(label); + button.id = n; + n++; + } + //set_uppercase(); + + /*add_child(&button_lowercase); + button_lowercase.on_select = [this, &nav, txt, max_len](Button&) { + if (_lowercase == true) { + _lowercase = false; + button_lowercase.set_text("UC"); + set_uppercase(); + } else { + _lowercase = true; + button_lowercase.set_text("LC"); + set_lowercase(); + } + };*/ + + add_child(&text_debug_x); + add_child(&text_debug_y); + add_child(&text_debug_write); + add_child(&button_done); + button_done.on_select = [this, &nav, txt, max_len](Button&) { + //memcpy(txt, txtinput, max_len+1); + //on_changed(this->value()); + nav.pop(); + }; + + signal_token_tick_second = time::signal_tick_second += [this]() { + this->on_tick_second(); + }; + + //update_text(); +} + +bool HandWriteView::MM(uint8_t idx, char cmp) { + if (idx < move_index) { + if ((cmp == 'U') && ((move_list[idx] & 0xF0) == 0x00)) return true; + if ((cmp == 'D') && ((move_list[idx] & 0xF0) == 0x10)) return true; + if ((cmp == 'L') && ((move_list[idx] & 0x0F) == 0x00)) return true; + if ((cmp == 'R') && ((move_list[idx] & 0x0F) == 0x01)) return true; + } + return false; +} + +bool HandWriteView::MM(uint8_t idx, char cmpud, char cmplr) { + if (idx < move_index) { + if (cmpud == 'U') cmpud = 0; + if (cmpud == 'D') cmpud = 1; + if (cmpud == '?') cmpud = 2; + if (cmplr == 'L') cmplr = 0; + if (cmplr == 'R') cmplr = 1; + if (cmplr == '?') cmplr = 2; + if (((move_list[idx] >> 4) == cmpud) && ((move_list[idx] & 0x0F) == cmplr)) return true; + } + return false; +} + +bool HandWriteView::MI(uint8_t idx) { + if (move_index - 1 < idx) + return true; + else + return false; +} + +bool HandWriteView::MLAST(char cmp) { + if ((cmp == 'U') && ((move_list[move_index - 1] & 0xF0) == 0x00)) return true; + if ((cmp == 'D') && ((move_list[move_index - 1] & 0xF0) == 0x10)) return true; + if ((cmp == 'L') && ((move_list[move_index - 1] & 0x0F) == 0x00)) return true; + if ((cmp == 'R') && ((move_list[move_index - 1] & 0x0F) == 0x01)) return true; + return false; +} + +bool HandWriteView::on_touch(const TouchEvent event) { + char guess; + + if (event.type == ui::TouchEvent::Type::Start) { + move_index = 0; + move_wait = 4; + tracing = true; + } + if (event.type == ui::TouchEvent::Type::End) { + tracing = false; + + display.fill_rectangle( + {{0, 16}, {240, 230}}, + Color::black() + ); + + // Letter guessing + guess = '?'; + + if (MM(0, 'U')) { + if (MM(0, 'U', '?')) { + if (MI(1)) + guess = 'A'; + else + guess = 'F'; + } else if (MM(0, 'U', 'R')) { + if (MI(1)) { + guess = 'K'; + } else { + if (MM(1, 'L')) { + if (txt_idx > 0) txtinput[txt_idx--] = 0; // Erase + } else { + guess = 'N'; + } + } + } else if (MM(0, 'U', 'L')) { + if (MM(1, 'U', 'R')) guess = 'C'; + if (MM(1, 'D', 'L')) guess = 'M'; + } + } else if (MM(0, 'D')) { + if (MM(0, 'D', 'R') || MM(1, 'R')) + guess = 'P'; + else + guess = 'Q'; + if (MM(0, 'D', '?')) { + if (MI(1)) { + guess = 'I'; + } else { + if (MM(1, 'R') && MI(2)) { + guess = 'L'; + } else if (MM(1, 'L')) { + if (MI(2)) guess = 'J'; + } else if (MM(1, 'U', 'R')) { + if (MM(2, 'D')) guess = 'W'; + } + } + } + if (MM(0, 'D', 'R')) { + if (MI(1)) guess = 'R'; + if (MM(1, 'U', 'R') && MI(2)) guess = 'V'; + if (MM(1, 'D', 'L')) guess = 'B'; + } else if (MM(0, 'D', 'L')) { + if (MI(1)) guess = 'Y'; + if (MM(1, 'U', 'L') && MI(2)) guess = 'U'; + if (MM(1, 'D', 'R')) guess = 'D'; + } + } + + if (MM(0, 'L')) { + if (!MI(2) && (MLAST('U') || MLAST('L'))) guess = 'O'; + if (MM(0, '?', 'L')) { + if (MI(1)) + guess = 'E'; + else + guess = 'S'; + } + } else if (MM(0, 'R')) { + if (!MI(2) && (MLAST('U') || MLAST('R'))) guess = 'X'; + if (MM(0, '?', 'R')) { + if (MM(1, 'U') && MI(2)) { + guess = 'G'; + } else if (MM(1, 'D', '?') && MI(2)) { + guess = 'H'; + } else if (MM(1, 'L')) { + guess = 'Z'; + } else if (MI(1)) { + guess = 'T'; + } + } + } + + // if (guess = '?') guess = ' '; + if (guess != '!') txtinput[txt_idx++] = guess; + update_text(); + } + if (event.type == ui::TouchEvent::Type::Move) { + if (tracing) { + current_pos = event.point; + } + } + return true; +} + +void HandWriteView::sample_pen() { + int16_t diff_x, diff_y; + uint8_t dir, i; + + if (!(sample_skip & 1)) { + if (tracing) { + if (move_wait) { + move_wait--; // ~133ms delay + } else { + diff_x = current_pos.x - last_pos.x; + diff_y = current_pos.y - last_pos.y; + + text_debug_x.set(to_string_dec_int(diff_x)); + text_debug_y.set(to_string_dec_int(diff_y)); + + display.fill_rectangle( + {{current_pos.x, current_pos.y}, {4, 4}}, + Color::grey() + ); + + dir = 0; + if (abs(diff_x) > 7) { + if (diff_x > 0) + dir |= 0x01; // R + } else { + dir |= 0x02; // ? + } + if (abs(diff_y) > 7) { + if (diff_y > 0) + dir |= 0x10; // D + } else { + dir |= 0x20; // ? + } + + if ((dir & 0x11) == (dir_prev & 0x11)) + dir_cnt++; + else + dir_cnt = 0; + dir_prev = dir; + + // text_debug_d.set(to_string_dec_uint(dir)); + + if (dir_cnt > 1) { + dir_cnt = 0; + if (move_index) { + if ((move_list[move_index - 1] != dir) && (dir != 0x22)) { + if ((dir & 0xF0) == 0x20) { + if ((move_list[move_index - 1] & 0x0F) != (dir & 0x0F)) { + move_list[move_index] = dir; + move_index++; + } + } else if ((dir & 0x0F) == 0x02) { + if ((move_list[move_index - 1] & 0xF0) != (dir & 0xF0)) { + move_list[move_index] = dir; + move_index++; + } + } else { + // Replacement ? + if (((move_list[move_index - 1] & 0xF0) == 0x20) && ((dir & 0xF0) != 0x20)) { + if ((move_list[move_index - 1] & 0x0F) == (dir & 0x0F)) { + move_list[move_index - 1] = dir; + } else if ((dir & 0x0F) == 0x02) { + // Merge + move_list[move_index - 1] = (dir & 0xF0) | (move_list[move_index - 1] & 0x0F); + } else { + move_list[move_index] = dir; + move_index++; + } + } else if (((move_list[move_index - 1] & 0x0F) == 0x02) && ((dir & 0x0F) != 0x02)) { + if ((move_list[move_index - 1] & 0xF0) == (dir & 0xF0)) { + move_list[move_index - 1] = dir; + } else if ((dir & 0xF0) == 0x20) { + // Merge + move_list[move_index - 1] = (dir & 0x0F) | (move_list[move_index - 1] & 0xF0); + } else { + move_list[move_index] = dir; + move_index++; + } + } else { + move_list[move_index] = dir; + move_index++; + } + } + } + } else { + if (dir != 0x22) { + move_list[move_index] = dir; + move_index++; + } + } + + // DEBUG + /*if (move_index) { + memset(txtinput, 0, 20); + txtidx = 0; + for (i = 0; i < move_index; i++) { + if ((move_list[i] & 0x03) == 0) char_add('L'); + if ((move_list[i] & 0x03) == 1) char_add('R'); + if ((move_list[i] & 0x03) == 2) char_add('?'); + if ((move_list[i] >> 4) == 0) char_add('U'); + if ((move_list[i] >> 4) == 1) char_add('D'); + if ((move_list[i] >> 4) == 2) char_add('?'); + char_add(' '); + } + update_text(); + }*/ + + } + } + + last_pos = current_pos; + } + } + + sample_skip++; +} + +void HandWriteView::on_show() { + // Use screen refresh rate as sampling frequency + EventDispatcher::message_map().unregister_handler(Message::ID::DisplayFrameSync); + EventDispatcher::message_map().register_handler(Message::ID::DisplayFrameSync, + [this](const Message* const) { + sample_pen(); + } + ); +} + +char * HandWriteView::value() { + return txtinput; +} + +void HandWriteView::on_button(Button& button) { + char_add(button.id + 0x30); + update_text(); +} + +void HandWriteView::char_add(const char c) { + if (txtidx < _max_len) { + txtinput[txtidx] = c; + txtidx++; + } +} + +void HandWriteView::char_delete() { + if (txtidx) { + txtidx--; + txtinput[txtidx] = ' '; + } +} + +void HandWriteView::update_text() { + text_input.set(txtinput); +} + +} diff --git a/firmware/application/ui_handwrite.hpp b/firmware/application/ui_handwrite.hpp new file mode 100644 index 00000000..25aee983 --- /dev/null +++ b/firmware/application/ui_handwrite.hpp @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * 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 "ui.hpp" +#include "ui_widget.hpp" +#include "ui_painter.hpp" +#include "ui_menu.hpp" +#include "ui_navigation.hpp" +#include "ui_font_fixed_8x16.hpp" +#include "clock_manager.hpp" +#include "message.hpp" +#include "signal.hpp" + +namespace ui { + +class HandWriteView : public View { +public: + std::function on_changed; + + HandWriteView(NavigationView& nav, char txt[], uint8_t max_len); + ~HandWriteView(); + + void on_show() override; + bool on_touch(const TouchEvent event) override; + + char * value(); + + uint8_t txtidx; + + void char_add(const char c); + void char_delete(); + +private: + SignalToken signal_token_tick_second; + + uint8_t _max_len, txt_idx = 0; + uint8_t dir_cnt = 0; + uint8_t dir_prev; + bool tracing = false; + uint8_t move_index; + uint8_t sample_skip, move_wait; + uint8_t move_list[32]; // TODO: Cap ! + Point start_pos, current_pos, last_pos; + bool _lowercase = false; + static constexpr size_t button_w = 240 / 5; + static constexpr size_t button_h = 28; + char txtinput[21] = {0}; // DEBUG + + bool MM(uint8_t idx, char cmp); + bool MM(uint8_t idx, char cmpud, char cmplr); + bool MI(uint8_t idx); + bool MLAST(char cmp); + + void sample_pen(); + + Text text_input { + { 0, 0, 240, 16 } + }; + + Text text_debug_x { + { 0, 16, 32, 16 } + }; + Text text_debug_y { + { 0, 32, 32, 16 } + }; + Text text_debug_write { + { 80, 24, 150, 16 } + }; + + std::array num_buttons; + + Button button_lowercase { + { 88+64+16, 270, 32, 24 }, + "UC" + }; + + Button button_done { + { 88, 270, 64, 24 }, + "Done" + }; + + void on_button(Button& button); + + void update_text(); +}; + +} /* namespace ui */ diff --git a/firmware/application/ui_lcr.cpp b/firmware/application/ui_lcr.cpp index a0d8f60d..fd333957 100644 --- a/firmware/application/ui_lcr.cpp +++ b/firmware/application/ui_lcr.cpp @@ -78,6 +78,10 @@ void LCRView::make_frame() { lcrframe[5] = 127; lcrframe[6] = 127; lcrframe[7] = 15; // SOM + + strcpy(rgsb, RGSB_list[adr_code.value()]); + button_setrgsb.set_text(rgsb); + strcat(lcrframe, rgsb); strcat(lcrframe, "PA "); if (checkbox_am_a.value() == true) { @@ -191,7 +195,7 @@ LCRView::LCRView( }; transmitter_model.set_baseband_configuration({ - .mode = 1, + .mode = 3, .sampling_rate = 2280000, // Is this right ? .decimation_factor = 1, }); @@ -200,11 +204,12 @@ LCRView::LCRView( memset(litteral, 0, 5*8); memset(rgsb, 0, 5); - strcpy(rgsb, RGSB_list[29]); + strcpy(rgsb, RGSB_list[adr_code.value()]); button_setrgsb.set_text(rgsb); add_children({ { &text_recap, + &adr_code, &button_setrgsb, &button_txsetup, &checkbox_am_a, @@ -290,7 +295,9 @@ LCRView::LCRView( memcpy(shared_memory.lcrdata, lcrframe_f, 256); shared_memory.afsk_transmit_done = false; - shared_memory.afsk_repeat = (portapack::persistent_memory::afsk_config() >> 8) & 0xFF; + shared_memory.afsk_repeat = 5; //(portapack::persistent_memory::afsk_config() >> 8) & 0xFF; + + EventDispatcher::message_map().unregister_handler(Message::ID::TXDone); EventDispatcher::message_map().register_handler(Message::ID::TXDone, [this,&transmitter_model](Message* const p) { @@ -316,7 +323,49 @@ LCRView::LCRView( transmitter_model.enable(); }; - + /* + button_transmit_scan.on_select() = [this,&transmitter_model](Button&){ + make_frame(); + + shared_memory.afsk_samples_per_bit = 228000/portapack::persistent_memory::afsk_bitrate(); + shared_memory.afsk_phase_inc_mark = portapack::persistent_memory::afsk_mark_freq()*(0x40000*256)/2280; + shared_memory.afsk_phase_inc_space = portapack::persistent_memory::afsk_space_freq()*(0x40000*256)/2280; + + shared_memory.afsk_fmmod = portapack::persistent_memory::afsk_bw() * 8; + + memset(shared_memory.lcrdata, 0, 256); + memcpy(shared_memory.lcrdata, lcrframe_f, 256); + + shared_memory.afsk_transmit_done = false; + shared_memory.afsk_repeat = 5; //(portapack::persistent_memory::afsk_config() >> 8) & 0xFF; + + EventDispatcher::message_map().unregister_handler(Message::ID::TXDone); + + EventDispatcher::message_map().register_handler(Message::ID::TXDone, + [this,&transmitter_model](Message* const p) { + char str[8]; + const auto message = static_cast(p); + if (message->n > 0) { + text_status.set(" "); + strcpy(str, to_string_dec_int(message->n).c_str()); + strcat(str, "/"); + strcat(str, to_string_dec_int((portapack::persistent_memory::afsk_config() >> 8) & 0xFF).c_str()); + text_status.set(str); + } else { + text_status.set("Done ! "); + transmitter_model.disable(); + } + } + ); + + char str[8]; + strcpy(str, "0/"); + strcat(str, to_string_dec_int(shared_memory.afsk_repeat).c_str()); + text_status.set(str); + + transmitter_model.enable(); + }; + */ button_txsetup.on_select = [&nav](Button&){ nav.push(); }; diff --git a/firmware/application/ui_lcr.hpp b/firmware/application/ui_lcr.hpp index 0d282ed4..11cfb8eb 100644 --- a/firmware/application/ui_lcr.hpp +++ b/firmware/application/ui_lcr.hpp @@ -44,6 +44,7 @@ public: void paint(Painter& painter) override; private: + uint8_t adri = 22; const char RGSB_list[37][5] = { "EAA0", "EAB0", "EAC0", "EAD0", "EbA0", "EbB0", "EbC0", "EbD0", @@ -70,9 +71,17 @@ private: }; Text text_recap { - { 32, 6, 192, 16 }, + { 8, 6, 18 * 8, 16 }, "-" }; + + NumberField adr_code { + { 220, 6 }, + 2, + { 0, 36 }, + 1, + '0' + }; Button button_setrgsb { { 16, 24, 96, 32 }, diff --git a/firmware/application/ui_loadmodule.cpp b/firmware/application/ui_loadmodule.cpp index a183a9a6..b045bee2 100644 --- a/firmware/application/ui_loadmodule.cpp +++ b/firmware/application/ui_loadmodule.cpp @@ -35,8 +35,10 @@ #include "ui_rds.hpp" #include "ui_xylos.hpp" #include "ui_lcr.hpp" -#include "ui_audiotx.hpp" +#include "analog_audio_app.hpp" +#include "ui_soundboard.hpp" #include "ui_debug.hpp" +#include "ui_audiotx.hpp" #include #include @@ -150,9 +152,12 @@ void LoadModuleView::loadmodule() { LoadModuleView::LoadModuleView( NavigationView& nav, const char * hash, - uint8_t ViewID + uint8_t ViewID, + bool loadplz ) { + if (loadplz == false) nav.pop(); // Useless, remove ! + add_children({ { &text_info, &text_infob, @@ -163,10 +168,11 @@ LoadModuleView::LoadModuleView( button_ok.on_select = [this, &nav, ViewID](Button&){ if (_mod_loaded == true) { - if (ViewID == 0) nav.push(); + if (ViewID == 0) nav.push(); //nav.push(); if (ViewID == 1) nav.push(); if (ViewID == 2) nav.push(); - if (ViewID == 3) nav.push(); + if (ViewID == 3) nav.push(); + if (ViewID == 10) nav.push(); } else { nav.pop(); } diff --git a/firmware/application/ui_loadmodule.hpp b/firmware/application/ui_loadmodule.hpp index 37b78cd2..fa7c05a8 100644 --- a/firmware/application/ui_loadmodule.hpp +++ b/firmware/application/ui_loadmodule.hpp @@ -32,7 +32,7 @@ namespace ui { class LoadModuleView : public View { public: - LoadModuleView(NavigationView& nav, const char * hash, uint8_t ViewID); + LoadModuleView(NavigationView& nav, const char * hash, uint8_t ViewID, bool loadplz); void loadmodule(); void on_show() override; diff --git a/firmware/application/ui_menu.cpp b/firmware/application/ui_menu.cpp index 5f584eeb..30ec2c26 100644 --- a/firmware/application/ui_menu.cpp +++ b/firmware/application/ui_menu.cpp @@ -53,7 +53,7 @@ void MenuItemView::paint(Painter& painter) { paint_style.background ); - ui::Color final_item_color = item.color; + ui::Color final_item_color = (highlighted() && parent()->has_focus()) ? ui::Color::black() : item.color; if (final_item_color.v == paint_style.background.v) final_item_color = paint_style.foreground; diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index a58e4fe0..077fc372 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -33,6 +33,9 @@ #include "ui_setup.hpp" #include "ui_debug.hpp" +#include "ui_handwrite.hpp" // DEBUG +#include "ui_soundboard.hpp" // DEBUG + #include "analog_audio_app.hpp" #include "ais_app.hpp" #include "ert_app.hpp" @@ -155,7 +158,7 @@ void NavigationView::focus() { } } -/* TransceiversMenuView **************************************************/ +/* TranspondersMenuView **************************************************/ TranspondersMenuView::TranspondersMenuView(NavigationView& nav) { add_items<3>({ { @@ -170,7 +173,9 @@ TranspondersMenuView::TranspondersMenuView(NavigationView& nav) { ReceiverMenuView::ReceiverMenuView(NavigationView& nav) { add_items<2>({ { - { "Audio", ui::Color::white(), [&nav](){ nav.push(); } }, + { "Audio", ui::Color::white(), [&nav](){ nav.push(md5_baseband, 10, true); } }, + + //{ "Audio", ui::Color::white(), [&nav](){ nav.push(); } }, { "Transponders", ui::Color::white(), [&nav](){ nav.push(); } }, } }); on_left = [&nav](){ nav.pop(); }; @@ -180,18 +185,18 @@ ReceiverMenuView::ReceiverMenuView(NavigationView& nav) { SystemMenuView::SystemMenuView(NavigationView& nav) { add_items<10>({ { - { "Play dead", ui::Color::red(), [&nav](){ nav.push(false); } }, - { "Receiver", ui::Color::cyan(), [&nav](){ nav.push(); } }, - { "RDS TX", ui::Color::yellow(), [&nav](){ nav.push(md5_baseband_tx, 0); } }, - { "Xylos TX", ui::Color::yellow(), [&nav](){ nav.push(md5_baseband_tx, 1); } }, - { "TEDI/LCR TX", ui::Color::yellow(), [&nav](){ nav.push(md5_baseband_tx, 2); } }, - { "Audio TX", ui::Color::orange(), [&nav](){ nav.push(md5_baseband_tx, 3); } }, - //{ "Capture", ui::Color::white(), [&nav](){ nav.push(); } }, - //{ "Analyze", ui::Color::white(), [&nav](){ nav.push(); } }, - { "Setup", ui::Color::white(), [&nav](){ nav.push(); } }, - { "About", ui::Color::white(), [&nav](){ nav.push(); } }, - { "Debug", ui::Color::white(), [&nav](){ nav.push(); } }, - { "HackRF", ui::Color::white(), [&nav](){ nav.push(); } }, + { "Play dead", ui::Color::red(), [&nav](){ nav.push(false); } }, + { "Receiver RX", ui::Color::cyan(), [&nav](){ nav.push(); } }, + { "Soundboard TX", ui::Color::orange(), [&nav](){ nav.push(md5_baseband_tx, 3, true); } }, + { "Audio TX TX", ui::Color::yellow(), [&nav](){ nav.push(md5_baseband_tx, 0, true); } }, + { "Xylos TX", ui::Color::yellow(), [&nav](){ nav.push(md5_baseband_tx, 1, true); } }, + { "TEDI/LCR TX", ui::Color::yellow(), [&nav](){ nav.push(md5_baseband_tx, 2, true); } }, + //{ "Capture", ui::Color::white(), [&nav](){ nav.push(); } }, + //{ "Analyze", ui::Color::white(), [&nav](){ nav.push(); } }, + { "Setup", ui::Color::white(), [&nav](){ nav.push(); } }, + { "About", ui::Color::white(), [&nav](){ nav.push(); } }, + { "Debug", ui::Color::white(), [&nav](){ nav.push(); } }, + { "HackRF", ui::Color::white(), [&nav](){ nav.push(); } }, } }); /* @@ -224,7 +229,8 @@ SystemView::SystemView( set_style(&style_default); constexpr ui::Dim status_view_height = 16; - + char debugtxt[21] = {0}; + add_child(&status_view); status_view.set_parent_rect({ { 0, 0 }, @@ -255,7 +261,9 @@ SystemView::SystemView( if (portapack::persistent_memory::ui_config() & 1) navigation_view.push(); else - navigation_view.push(); + //navigation_view.push(); + //navigation_view.push(); + navigation_view.push(debugtxt, 20); } Context& SystemView::context() const { diff --git a/firmware/application/ui_soundboard.cpp b/firmware/application/ui_soundboard.cpp new file mode 100644 index 00000000..c45b2667 --- /dev/null +++ b/firmware/application/ui_soundboard.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * 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 "ui_soundboard.hpp" + +#include "ch.h" + +#include "ui_alphanum.hpp" +#include "ff.h" +#include "hackrf_gpio.hpp" +#include "portapack.hpp" +#include "radio.hpp" +#include "event_m0.hpp" +#include "string_format.hpp" + +#include "hackrf_hal.hpp" +#include "portapack_shared_memory.hpp" + +#include + +using namespace portapack; + +namespace ui { + +void SoundBoardView::on_show() { + /* + // Just in case + EventDispatcher::message_map().unregister_handler(Message::ID::DisplayFrameSync); + + // "Vertical blank interrupt" + EventDispatcher::message_map().register_handler(Message::ID::DisplayFrameSync, + [this](const Message* const) { + pbar_test.set_value(testv/4); + testv++; + } + );*/ +} + +std::string SoundBoardView::title() const { + return "Sound board"; +}; + +void SoundBoardView::focus() { + buttons[0].focus(); +} + +void SoundBoardView::on_tuning_frequency_changed(rf::Frequency f) { + transmitter_model.set_tuning_frequency(f); +} + +void SoundBoardView::on_button(Button& button) { + text_test.set(to_string_dec_uint(button.id)); +} + +SoundBoardView::SoundBoardView( + NavigationView& nav +) +{ + size_t n; + + for (n = 0; n < 12; n++) { + sounds[n].filename = ""; + sounds[n].shortname = "Empty"; + sounds[n].min = 0; + sounds[n].sec = 0; + } + + add_children({ { + &text_test, + &field_frequency, + &number_bw, + &pbar_test, + &button_load, + &button_exit + } }); + + const auto button_fn = [this](Button& button) { + this->on_button(button); + }; + + for(auto& button : buttons) { + add_child(&button); + button.id = n; + button.on_select = button_fn; + button.set_parent_rect({ + static_cast((n % 3) * 70 + 15), + static_cast((n / 3) * 50 + 30), + 70, 50 + }); + button.set_text(sounds[n].shortname); + n++; + } + + field_frequency.set_value(transmitter_model.tuning_frequency()); + field_frequency.set_step(receiver_model.frequency_step()); + field_frequency.on_change = [this](rf::Frequency f) { + this->on_tuning_frequency_changed(f); + }; + field_frequency.on_edit = [this, &nav]() { + // TODO: Provide separate modal method/scheme? + auto new_view = nav.push(receiver_model.tuning_frequency()); + new_view->on_changed = [this](rf::Frequency f) { + this->on_tuning_frequency_changed(f); + this->field_frequency.set_value(f); + }; + }; + + /*button_transmit.on_select = [](Button&){ + transmitter_model.set_baseband_configuration({ + .mode = 1, + .sampling_rate = 1536000, + .decimation_factor = 1, + }); + transmitter_model.set_rf_amp(true); + transmitter_model.enable(); + };*/ + + button_exit.on_select = [&nav](Button&){ + nav.pop(); + }; +} + +SoundBoardView::~SoundBoardView() { + transmitter_model.disable(); +} + +} diff --git a/firmware/application/ui_soundboard.hpp b/firmware/application/ui_soundboard.hpp new file mode 100644 index 00000000..398c5b0d --- /dev/null +++ b/firmware/application/ui_soundboard.hpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * 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 "ui.hpp" +#include "ui_widget.hpp" +#include "ui_painter.hpp" +#include "ui_menu.hpp" +#include "ui_navigation.hpp" +#include "ui_font_fixed_8x16.hpp" +#include "clock_manager.hpp" +#include "message.hpp" +#include "rf_path.hpp" +#include "max2837.hpp" +#include "volume.hpp" +#include "ui_receiver.hpp" +#include "transmitter_model.hpp" + +namespace ui { + +class SoundBoardView : public View { +public: + SoundBoardView(NavigationView& nav); + ~SoundBoardView(); + + std::string title() const; + void on_show() override; + void focus() override; + +private: + struct sound { + std::string filename; + std::string shortname; + uint8_t min; + uint8_t sec; + }; + + sound sounds[12]; + + std::array buttons; + void on_button(Button& button); + + void on_tuning_frequency_changed(rf::Frequency f); + + Text text_test { + { 120, 4, 64, 16 } + }; + + FrequencyField field_frequency { + { 1 * 8, 4 }, + }; + + NumberField number_bw { + { 16 * 8, 4 }, + 5, + {1000, 50000}, + 500, + ' ' + }; + + ProgressBar pbar_test { + { 45, 236, 150, 16 } + }; + + Button button_load { + { 8, 270, 64, 32 }, + "Load" + }; + + Button button_exit { + { 96, 270, 64, 32 }, + "Exit" + }; +}; + +} /* namespace ui */ diff --git a/firmware/application/ui_xylos.cpp b/firmware/application/ui_xylos.cpp index 22ff1b17..56de2e67 100644 --- a/firmware/application/ui_xylos.cpp +++ b/firmware/application/ui_xylos.cpp @@ -135,10 +135,10 @@ void XylosView::paint(Painter& painter) { void XylosView::upd_message() { uint8_t c; - ccirmessage[0] = '0'; - ccirmessage[1] = '0'; - ccirmessage[2] = '0'; - ccirmessage[3] = '0'; + ccirmessage[0] = (header_code_a.value() / 10) + 0x30; + ccirmessage[1] = (header_code_a.value() % 10) + 0x30; + ccirmessage[2] = (header_code_b.value() / 10) + 0x30; + ccirmessage[3] = (header_code_b.value() % 10) + 0x30; ccirmessage[4] = (city_code.value() / 10) + 0x30; ccirmessage[5] = (city_code.value() % 10) + 0x30; @@ -228,7 +228,7 @@ XylosView::XylosView( }; transmitter_model.set_baseband_configuration({ - .mode = 4, + .mode = 2, .sampling_rate = 1536000, .decimation_factor = 1, }); @@ -236,6 +236,9 @@ XylosView::XylosView( add_children({ { &text_title, &button_txtest, + &text_header, + &header_code_a, + &header_code_b, &text_city, &city_code, &text_family, @@ -265,11 +268,21 @@ XylosView::XylosView( family_code.set_value(1); subfamily_code.set_value(1); receiver_code.set_value(1); + header_code_a.set_value(0); + header_code_b.set_value(0); options_freq.set_selected_index(5); checkbox_wcsubfamily.set_value(true); checkbox_wcid.set_value(true); + header_code_a.on_change = [this](int32_t v) { + (void)v; + XylosView::upd_message(); + }; + header_code_b.on_change = [this](int32_t v) { + (void)v; + XylosView::upd_message(); + }; city_code.on_change = [this](int32_t v) { (void)v; XylosView::upd_message(); diff --git a/firmware/application/ui_xylos.hpp b/firmware/application/ui_xylos.hpp index 586dbb54..0d8d79c6 100644 --- a/firmware/application/ui_xylos.hpp +++ b/firmware/application/ui_xylos.hpp @@ -41,8 +41,6 @@ namespace ui { #define XYLOS_VOICE_RELAYS 21 #define XYLOS_VOICE_TRAILER 25 -void do_something(); - class XylosRXView : public View { public: XylosRXView(NavigationView& nav); @@ -152,47 +150,38 @@ public: private: bool txing = false; const rf::Frequency xylos_freqs[7] = { 31325000, 31387500, 31437500, 31475000, 31687500, 31975000, 88000000 }; - uint8_t xylos_voice_phrase[32] = { 0xFF }; - const char * xylos_voice_filenames[26] = { "zero.wav", - "one.wav", - "two.wav", - "three.wav", - "four.wav", - "five.wav", - "six.wav", - "seven.wav", - "eight.wav", - "nine.wav", - "a.wav", - "b.wav", - "c.wav", - "d.wav", - "e.wav", - "f.wav", - "header.wav", - "city.wav", - "family.wav", - "subfamily.wav", - "address.wav", - "relays.wav", - "ignored.wav", - "off.wav", - "on.wav", - "trailer.wav" - }; char ccirmessage[21]; char ccir_received[21]; Text text_title { - { 1 * 8, 1 * 16, 11, 16 }, + { 8, 8, 11, 16 }, "BH Xylos TX" }; Button button_txtest { - { 170, 1 * 16, 40, 24 }, + { 180, 8, 40, 24 }, "TEST" }; + Text text_header { + { 8 * 8, 2 * 16, 7 * 8, 16 }, + "Header:" + }; + NumberField header_code_a { + { 16 * 8, 2 * 16 }, + 2, + { 0, 99 }, + 1, + '0' + }; + NumberField header_code_b { + { 18 * 8, 2 * 16 }, + 2, + { 0, 99 }, + 1, + '0' + }; + Text text_city { { 4 * 8, 3 * 16, 11 * 8, 16 }, "Code ville:" @@ -256,7 +245,7 @@ private: "Frequence:" }; OptionsField options_freq { - { 16 * 8, 9 * 16 }, + { 16 * 8, 9 * 16 + 4}, 7, { { "31.3250", 0 }, diff --git a/firmware/baseband-tx.bin b/firmware/baseband-tx.bin index f456c721be28b4e5f21ebcb04db5527c0fe4ef42..3e65f73aba06c9806744978e5d16d24199b5488e 100644 GIT binary patch delta 3875 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 af#IV90|TSt=1(sFY&JKzE)WzzFQ)-QN*xIR diff --git a/firmware/baseband-tx/Makefile b/firmware/baseband-tx/Makefile index 0b07fa9d..48f288b7 100755 --- a/firmware/baseband-tx/Makefile +++ b/firmware/baseband-tx/Makefile @@ -140,6 +140,8 @@ CPPSRC = main.cpp \ matched_filter.cpp \ proc_audiotx.cpp \ proc_playaudio.cpp \ + proc_xylos.cpp \ + proc_fsk_lcr.cpp \ dsp_squelch.cpp \ clock_recovery.cpp \ packet_builder.cpp \ diff --git a/firmware/baseband-tx/audio_compressor.cpp b/firmware/baseband-tx/audio_compressor.cpp new file mode 100644 index 00000000..95bbaee3 --- /dev/null +++ b/firmware/baseband-tx/audio_compressor.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc. + * + * 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 "audio_compressor.hpp" + +float GainComputer::operator()(const float x) const { + const auto abs_x = std::abs(x); + const auto db = (abs_x < lin_floor) ? db_floor : log2_db_k * fast_log2(abs_x); + const auto overshoot_db = db - threshold_db; + if( knee_width_db > 0.0f ) { + const auto w2 = knee_width_db / 2.0f; + const auto a = w2 / (knee_width_db * knee_width_db); + const auto in_transition = (overshoot_db > -w2) && (overshoot_db < w2); + const auto rectified_overshoot = in_transition ? (a * std::pow(overshoot_db + w2, 2.0f)) : std::max(overshoot_db, 0.0f); + return rectified_overshoot * slope; + } else { + const auto rectified_overshoot = std::max(overshoot_db, 0.0f); + return rectified_overshoot * slope; + } +} + +void FeedForwardCompressor::execute_in_place(const buffer_f32_t& buffer) { + constexpr float makeup_gain = std::pow(10.0f, (threshold - (threshold / ratio)) / -20.0f); + for(size_t i=0; i + +/* Code based on article in Journal of the Audio Engineering Society + * Vol. 60, No. 6, 2012 June, by Dimitrios Giannoulis, Michael Massberg, + * Joshua D. Reiss "Digital Dynamic Range Compressor Design – A Tutorial + * and Analysis" + */ + +class GainComputer { +public: + constexpr GainComputer( + float ratio, + float threshold + ) : ratio { ratio }, + slope { 1.0f / ratio - 1.0f }, + threshold_db { threshold } + { + } + + float operator()(const float x) const; + +private: + const float ratio; + const float slope; + const float threshold_db; + + static constexpr float knee_width_db = 0.0f; + + static constexpr float db_floor = -120.0f; + static constexpr float lin_floor = std::pow(10.0f, db_floor / 20.0f); + static constexpr float log2_db_k = 20.0f * std::log10(2.0f); +}; + +class PeakDetectorBranchingSmooth { +public: + constexpr PeakDetectorBranchingSmooth( + float att_a, + float rel_a + ) : att_a { att_a }, + rel_a { rel_a } + { + } + + float operator()(const float db) { + const auto a = (db > state) ? att_a : rel_a; + state = db + a * (state - db); + return state; + } + +private: + float state { 0.0f }; + const float att_a; + const float rel_a; +}; + +class FeedForwardCompressor { +public: + void execute_in_place(const buffer_f32_t& buffer); + +private: + static constexpr float fs = 12000.0f; + static constexpr float ratio = 10.0f; + static constexpr float threshold = -30.0f; + + GainComputer gain_computer { ratio, threshold }; + PeakDetectorBranchingSmooth peak_detector { tau_alpha(0.010f, fs), tau_alpha(0.300f, fs) }; + + float execute_once(const float x); + + static constexpr float tau_alpha(const float tau, const float fs) { + return std::exp(-1.0f / (tau * fs)); + } +}; + +#endif/*__AUDIO_COMPRESSOR_H__*/ diff --git a/firmware/baseband-tx/baseband_thread.cpp b/firmware/baseband-tx/baseband_thread.cpp index d87f43b0..e6d77a70 100644 --- a/firmware/baseband-tx/baseband_thread.cpp +++ b/firmware/baseband-tx/baseband_thread.cpp @@ -33,6 +33,8 @@ #include "proc_playaudio.hpp" #include "proc_audiotx.hpp" +#include "proc_xylos.hpp" +#include "proc_fsk_lcr.hpp" #include "portapack_shared_memory.hpp" @@ -120,6 +122,8 @@ BasebandProcessor* BasebandThread::create_processor(const int32_t mode) { switch(mode) { case 0: return new PlayAudioProcessor(); case 1: return new AudioTXProcessor(); + case 2: return new XylosProcessor(); + case 3: return new LCRFSKProcessor(); default: return nullptr; } } diff --git a/firmware/baseband-tx/ook.hpp b/firmware/baseband-tx/ook.hpp new file mode 100644 index 00000000..27333922 --- /dev/null +++ b/firmware/baseband-tx/ook.hpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc. + * + * 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 __OOK_HPP__ +#define __OOK_HPP__ + +#include "phase_detector.hpp" +#include "phase_accumulator.hpp" + +#include +#include +#include +#include + +class OOKSlicerMagSquaredInt { +public: + using symbol_t = bool; + + constexpr OOKSlicerMagSquaredInt( + const float samples_per_symbol + ) : mag2_threshold_leak_factor { + static_cast( + factor_sq(-1.0f / (8.0f * samples_per_symbol)) * float(1ULL << 32) + ) + } + { + } + + symbol_t operator()(const std::complex in) { + const uint32_t real2 = in.real() * in.real(); + const uint32_t imag2 = in.imag() * in.imag(); + const uint32_t mag2 = real2 + imag2; + + const uint32_t mag2_attenuated = mag2 >> 3; // Approximation of (-4.5dB)^2 + mag2_threshold = (uint64_t(mag2_threshold) * uint64_t(mag2_threshold_leak_factor)) >> 32; + mag2_threshold = std::max(mag2_threshold, mag2_attenuated); + const bool symbol = (mag2 > mag2_threshold); + return symbol; + } + +private: + const uint32_t mag2_threshold_leak_factor; + uint32_t mag2_threshold = 0; + + constexpr float factor_sq(float db) { + return std::pow(10.0f, db / (10.0f / 2)); + } +}; + +class OOKClockRecovery { +public: + constexpr OOKClockRecovery( + const float samples_per_symbol + ) : symbol_phase_inc_nominal { static_cast(std::round((1ULL << 32) / samples_per_symbol)) }, + phase_detector { samples_per_symbol }, + phase_accumulator { symbol_phase_inc_nominal } + { + } + + template + void operator()(const uint32_t slicer_history, SymbolHandler symbol_handler) { + if( phase_accumulator() ) { + const auto detector_result = phase_detector(slicer_history); + phase_accumulator.set_inc(symbol_phase_inc_nominal + detector_result.error * (symbol_phase_inc_nominal >> 3)); + symbol_handler(detector_result.symbol); + } + } + +private: + const uint32_t symbol_phase_inc_nominal; + PhaseDetectorEarlyLateGate phase_detector; + PhaseAccumulator phase_accumulator; +}; + +#endif/*__OOK_HPP__*/ diff --git a/firmware/baseband-tx/phase_accumulator.hpp b/firmware/baseband-tx/phase_accumulator.hpp new file mode 100644 index 00000000..bf3b331a --- /dev/null +++ b/firmware/baseband-tx/phase_accumulator.hpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc. + * + * 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 __PHASE_ACCUMULATOR_HPP__ +#define __PHASE_ACCUMULATOR_HPP__ + +#include + +class PhaseAccumulator { +public: + constexpr PhaseAccumulator( + const uint32_t phase_inc + ) : phase_inc { phase_inc } + { + } + + bool operator()() { + const auto last_phase = phase; + phase += phase_inc; + return (phase < last_phase); + } + + void set_inc(const uint32_t new_phase_inc) { + phase_inc = new_phase_inc; + } + +private: + uint32_t phase { 0 }; + uint32_t phase_inc; +}; + +#endif/*__PHASE_ACCUMULATOR_HPP__*/ diff --git a/firmware/baseband-tx/phase_detector.hpp b/firmware/baseband-tx/phase_detector.hpp new file mode 100644 index 00000000..89cf4b5c --- /dev/null +++ b/firmware/baseband-tx/phase_detector.hpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc. + * + * 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 __PHASE_DETECTOR_HPP__ +#define __PHASE_DETECTOR_HPP__ + +#include +#include +#include + +class PhaseDetectorEarlyLateGate { +public: + using history_t = uint32_t; + + using symbol_t = bool; + using error_t = int; + + struct result_t { + symbol_t symbol; + error_t error; + }; + + constexpr PhaseDetectorEarlyLateGate( + const float samples_per_symbol + ) : late_mask { (1U << static_cast(std::ceil(samples_per_symbol / 2))) - 1 }, + early_mask { late_mask << static_cast(std::floor(samples_per_symbol / 2)) }, + sample_bit { static_cast(std::floor(samples_per_symbol / 2)) } + { + } + + result_t operator()(const history_t symbol_history) const { + // history = ...0111, early + // history = ...1110, late + + const symbol_t symbol = (symbol_history >> sample_bit) & 1; + const int late_side = __builtin_popcount(symbol_history & late_mask); + const int early_side = __builtin_popcount(symbol_history & early_mask); + const int lateness = late_side - early_side; + const int direction = lateness; //std::min(std::max(lateness, -1), 1); + const error_t error = direction; + return { symbol, error }; + } + +private: + const history_t late_mask; + const history_t early_mask; + const size_t sample_bit; +}; + +#endif/*__PHASE_DETECTOR_HPP__*/ diff --git a/firmware/baseband-tx/proc_audiotx.cpp b/firmware/baseband-tx/proc_audiotx.cpp index a619a620..b47cd02c 100644 --- a/firmware/baseband-tx/proc_audiotx.cpp +++ b/firmware/baseband-tx/proc_audiotx.cpp @@ -23,63 +23,9 @@ #include "proc_audiotx.hpp" #include "portapack_shared_memory.hpp" #include "sine_table.hpp" -#include "audio_output.hpp" -#include "lfsr_random.hpp" #include -uint32_t lfsr(uint32_t v) { - - enum { - length = 31, - tap_0 = 31, - tap_1 = 18, - shift_amount_0 = 12, - shift_amount_1 = 12, - shift_amount_2 = 8 - }; - - const lfsr_word_t zero = 0; - v = ( - ( - v << shift_amount_0 - ) | ( - ( - (v >> (tap_0 - shift_amount_0)) ^ - (v >> (tap_1 - shift_amount_0)) - ) & ( - ~(~zero << shift_amount_0) - ) - ) - ); - v = ( - ( - v << shift_amount_1 - ) | ( - ( - (v >> (tap_0 - shift_amount_1)) ^ - (v >> (tap_1 - shift_amount_1)) - ) & ( - ~(~zero << shift_amount_1) - ) - ) - ); - v = ( - ( - v << shift_amount_2 - ) | ( - ( - (v >> (tap_0 - shift_amount_2)) ^ - (v >> (tap_1 - shift_amount_2)) - ) & ( - ~(~zero << shift_amount_2) - ) - ) - ); - - return v; -} - void AudioTXProcessor::execute(const buffer_c8_t& buffer){ for (size_t i = 0; i class AudioTXProcessor : public BasebandProcessor { diff --git a/firmware/baseband-tx/proc_tpms.cpp b/firmware/baseband-tx/proc_tpms.cpp new file mode 100644 index 00000000..9d401a1c --- /dev/null +++ b/firmware/baseband-tx/proc_tpms.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * 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 "proc_tpms.hpp" + +#include "dsp_fir_taps.hpp" + +TPMSProcessor::TPMSProcessor() { + decim_0.configure(taps_200k_decim_0.taps, 33554432); + decim_1.configure(taps_200k_decim_1.taps, 131072); +} + +void TPMSProcessor::execute(const buffer_c8_t& buffer) { + /* 2.4576MHz, 2048 samples */ + + const auto decim_0_out = decim_0.execute(buffer, dst_buffer); + const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); + const auto decimator_out = decim_1_out; + + /* 307.2kHz, 256 samples */ + feed_channel_stats(decimator_out); + + for(size_t i=0; ipacket_builder_ook_subaru.execute(symbol); + }); + ook_clock_recovery_gmc(slicer_history, [this](const bool symbol) { + this->packet_builder_ook_gmc.execute(symbol); + }); + } +} + +void TPMSProcessor::consume_symbol( + const float raw_symbol +) { + const uint_fast8_t sliced_symbol = (raw_symbol >= 0.0f) ? 1 : 0; + packet_builder.execute(sliced_symbol); +} + +void TPMSProcessor::payload_handler( + const baseband::Packet& packet +) { + const TPMSPacketMessage message { tpms::SignalType::FLM, packet }; + shared_memory.application_queue.push(message); +} diff --git a/firmware/baseband-tx/proc_tpms.hpp b/firmware/baseband-tx/proc_tpms.hpp new file mode 100644 index 00000000..759f7383 --- /dev/null +++ b/firmware/baseband-tx/proc_tpms.hpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * 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 __PROC_TPMS_H__ +#define __PROC_TPMS_H__ + +#include "baseband_processor.hpp" + +#include "channel_decimator.hpp" +#include "matched_filter.hpp" + +#include "clock_recovery.hpp" +#include "symbol_coding.hpp" +#include "packet_builder.hpp" +#include "baseband_packet.hpp" + +#include "ook.hpp" + +#include "message.hpp" +#include "portapack_shared_memory.hpp" + +#include +#include +#include + +// Translate+rectangular filter +// sample=307.2k, deviation=38400, symbol=19200 +// Length: 16 taps, 1 symbols, 2 cycles of sinusoid +constexpr std::array, 16> rect_taps_307k2_1t_p { { + { 6.2500000000e-02f, 0.0000000000e+00f }, { 4.4194173824e-02f, 4.4194173824e-02f }, + { 0.0000000000e+00f, 6.2500000000e-02f }, { -4.4194173824e-02f, 4.4194173824e-02f }, + { -6.2500000000e-02f, 0.0000000000e+00f }, { -4.4194173824e-02f, -4.4194173824e-02f }, + { 0.0000000000e+00f, -6.2500000000e-02f }, { 4.4194173824e-02f, -4.4194173824e-02f }, + { 6.2500000000e-02f, 0.0000000000e+00f }, { 4.4194173824e-02f, 4.4194173824e-02f }, + { 0.0000000000e+00f, 6.2500000000e-02f }, { -4.4194173824e-02f, 4.4194173824e-02f }, + { -6.2500000000e-02f, 0.0000000000e+00f }, { -4.4194173824e-02f, -4.4194173824e-02f }, + { 0.0000000000e+00f, -6.2500000000e-02f }, { 4.4194173824e-02f, -4.4194173824e-02f }, +} }; + +class TPMSProcessor : public BasebandProcessor { +public: + TPMSProcessor(); + + void execute(const buffer_c8_t& buffer) override; + +private: + std::array dst; + const buffer_c16_t dst_buffer { + dst.data(), + dst.size() + }; + + dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0; + dsp::decimate::FIRC16xR16x16Decim2 decim_1; + + dsp::matched_filter::MatchedFilter mf { rect_taps_307k2_1t_p, 8 }; + + clock_recovery::ClockRecovery clock_recovery { + 38400, 19200, { 0.0555f }, + [this](const float symbol) { this->consume_symbol(symbol); } + }; + PacketBuilder packet_builder { + { 0b010101010101010101010101010110, 30, 1 }, + { }, + { 256 }, + [this](const baseband::Packet& packet) { + this->payload_handler(packet); + } + }; + + static constexpr float channel_rate_in = 307200.0f; + static constexpr size_t channel_decimation = 8; + static constexpr float channel_sample_rate = channel_rate_in / channel_decimation; + OOKSlicerMagSquaredInt ook_slicer_5sps { 5 }; + uint32_t slicer_history { 0 }; + + OOKClockRecovery ook_clock_recovery_subaru { + channel_sample_rate / 8192.0f + }; + + PacketBuilder packet_builder_ook_subaru { + { 0b010101010101010101011110, 24, 0 }, + { }, + { 80 }, + [](const baseband::Packet& packet) { + const TPMSPacketMessage message { tpms::SignalType::Subaru, packet }; + shared_memory.application_queue.push(message); + } + }; + OOKClockRecovery ook_clock_recovery_gmc { + channel_sample_rate / 8400.0f + }; + + PacketBuilder packet_builder_ook_gmc { + { 0b01010101010101010101010101100101, 32, 0 }, + { }, + { 192 }, + [](const baseband::Packet& packet) { + const TPMSPacketMessage message { tpms::SignalType::GMC, packet }; + shared_memory.application_queue.push(message); + } + }; + void consume_symbol(const float symbol); + void payload_handler(const baseband::Packet& packet); +}; + +#endif/*__PROC_TPMS_H__*/ diff --git a/firmware/baseband-tx/proc_xylos.cpp b/firmware/baseband-tx/proc_xylos.cpp index b3da393d..61cdd241 100644 --- a/firmware/baseband-tx/proc_xylos.cpp +++ b/firmware/baseband-tx/proc_xylos.cpp @@ -23,7 +23,7 @@ #include "proc_xylos.hpp" #include "dsp_iir_config.hpp" -//#include "audio_output.hpp" +#include "audio_output.hpp" #include "portapack_shared_memory.hpp" #include "sine_table.hpp" @@ -75,7 +75,7 @@ void XylosProcessor::execute(const buffer_c8_t& buffer) { // Audio preview sample generation: 1536000/48000 = 32 if (as >= 31) { as = 0; - preview_audio_buffer.p[ai++] = sample * 128; + audio[ai++] = sample * 128; } else { as++; } @@ -92,5 +92,5 @@ void XylosProcessor::execute(const buffer_c8_t& buffer) { buffer.p[i] = {(int8_t)re,(int8_t)im}; } - //audio_output.write(preview_audio_buffer); + //audio_output.write(audio_buffer); } diff --git a/firmware/baseband-tx/proc_xylos.hpp b/firmware/baseband-tx/proc_xylos.hpp index 0add6712..97695997 100644 --- a/firmware/baseband-tx/proc_xylos.hpp +++ b/firmware/baseband-tx/proc_xylos.hpp @@ -28,7 +28,7 @@ #include "dsp_decimate.hpp" #include "dsp_demodulate.hpp" -//#include "audio_output.hpp" +#include "audio_output.hpp" #include "baseband_processor.hpp" #define CCIR_TONELENGTH 15360-1 // 1536000/10/10 @@ -40,11 +40,12 @@ public: private: int16_t audio_data[64]; - - const buffer_s16_t preview_audio_buffer { - audio_data, - sizeof(int16_t)*64 - }; + + std::array audio; + /*const buffer_s16_t audio_buffer { + audio.data(), + audio.size() + };*/ uint32_t ccir_phases[16] = { (uint32_t)(1981*PHASEV), @@ -74,7 +75,7 @@ private: int32_t sample, frq; TXDoneMessage message; - //AudioOutput audio_output; + AudioOutput audio_output; }; #endif diff --git a/firmware/baseband-tx/stream_input.hpp b/firmware/baseband-tx/stream_input.hpp new file mode 100644 index 00000000..1b1ec552 --- /dev/null +++ b/firmware/baseband-tx/stream_input.hpp @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc. + * + * 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 __STREAM_INPUT_H__ +#define __STREAM_INPUT_H__ + +#include "portapack_shared_memory.hpp" + +#include "fifo.hpp" + +#include +#include +#include + +class StreamInput { +public: + StreamInput(const size_t K) : + K { K }, + data { std::make_unique(1UL << K) }, + fifo { data.get(), K } + { + // TODO: Send stream creation message. + shared_memory.FIFO_HACK = &fifo; + } + + ~StreamInput() { + // TODO: Send stream distruction message. + shared_memory.FIFO_HACK = nullptr; + } + + size_t write(const void* const data, const size_t length) { + const auto written = fifo.in(reinterpret_cast(data), length); + + const auto last_bytes_written = bytes_written; + bytes_written += written; + if( (bytes_written & event_bytes_mask) < (last_bytes_written & event_bytes_mask) ) { + creg::m4txevent::assert(); + } + + return written; + } + + uint64_t written() const { + return bytes_written; + } + +private: + const size_t K; + const uint64_t event_bytes_mask = (1ULL << (K - 2)) - 1; + uint64_t bytes_written = 0; + std::unique_ptr data; + FIFO fifo; +}; + +#endif/*__STREAM_INPUT_H__*/ diff --git a/firmware/baseband.bin b/firmware/baseband.bin index ab19dc42d8862b65674f575fa305a3b8d9a2e020..7f9b8511d687d43282727ca37b7314cd379891a3 100644 GIT binary patch delta 70 zcmZo@VQOe$(h3OhRbXP6Qq8~+l$xBHS(aMF#Q*`H81?oadN-fXtdwtiyN2i9jatVV H1<(Zn{S_FB delta 70 zcmZo@VQOe$(h3OhRbXQHP|v^+l$xBHS(aMF#Q*{3EZ+k&(z+Ci7ktlL^k|FKMy+Fw H0_cJO5Cj?K diff --git a/firmware/common/modules.h b/firmware/common/modules.h index 5810db69..3cd201d0 100644 --- a/firmware/common/modules.h +++ b/firmware/common/modules.h @@ -1,2 +1,2 @@ -const char md5_baseband[16] = {0x37,0x04,0xf7,0x51,0x68,0x66,0x8a,0x20,0x73,0xa0,0xf7,0x69,0xa2,0xe2,0xb4,0x3a,}; -const char md5_baseband_tx[16] = {0x6c,0x1a,0x90,0x6b,0x68,0x78,0x6e,0xd2,0x08,0x3b,0x05,0xb1,0xbe,0x61,0xf8,0xe7,}; +const char md5_baseband[16] = {0xf2,0x01,0x2e,0xbf,0xc2,0xee,0x9f,0x0e,0x36,0x75,0x0e,0xb7,0x87,0x28,0x49,0xbd,}; +const char md5_baseband_tx[16] = {0xb1,0xe1,0xca,0x79,0x83,0x86,0x2f,0x20,0xba,0x94,0xd3,0x0c,0xc7,0x9d,0x43,0xe2,}; diff --git a/firmware/common/ui.hpp b/firmware/common/ui.hpp index fa2f0fa5..bee55b86 100644 --- a/firmware/common/ui.hpp +++ b/firmware/common/ui.hpp @@ -30,12 +30,18 @@ using Coord = int16_t; using Dim = int16_t; struct Color { - uint16_t v; + uint16_t v; // rrrrrGGGGGGbbbbb constexpr Color( ) : v { 0 } { } + + constexpr Color( + uint16_t v + ) : v { v } + { + } constexpr Color( uint8_t r, @@ -49,6 +55,10 @@ struct Color { )} { } + + Color operator-() const { + return (v ^ 0xffff); + } static constexpr Color black() { return { 0, 0, 0 }; @@ -75,7 +85,7 @@ struct Color { } static constexpr Color cyan() { - return { 0, 128, 255 }; + return { 0, 255, 255 }; } static constexpr Color white() { diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index 31d03ebf..d8a0aee9 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -292,6 +292,36 @@ void Text::paint(Painter& painter) { ); } +/* ProgressBar ***********************************************************/ + +ProgressBar::ProgressBar( + Rect parent_rect +) : Widget { parent_rect } +{ +} + +void ProgressBar::set_value(const uint16_t value) { + if (value > 100) + _value = 100; + else + _value = value; + set_dirty(); +} + +void ProgressBar::paint(Painter& painter) { + uint16_t v_sized; + + const auto rect = screen_rect(); + const auto s = style(); + + v_sized = (rect.size.w * _value) / 100; + + painter.fill_rectangle({rect.pos, {v_sized, rect.size.h}}, ui::Color::green()); + painter.fill_rectangle({{rect.pos.x + v_sized, rect.pos.y}, {rect.size.w - v_sized, rect.size.h}}, s.background); + + painter.draw_rectangle(rect, s.foreground); +} + /* Checkbox **************************************************************/ Checkbox::Checkbox( @@ -427,12 +457,16 @@ void Button::paint(Painter& painter) { paint_style.background ); - const auto label_r = paint_style.font.size_of(text_); - painter.draw_string( - { r.pos.x + (r.size.w - label_r.w) / 2, r.pos.y + (r.size.h - label_r.h) / 2 }, - paint_style, - text_ - ); + //char *token = strtok(text_.c_str(), "\n"); + //while(token) { + const auto label_r = paint_style.font.size_of(text_); + painter.draw_string( + { r.pos.x + (r.size.w - label_r.w) / 2, r.pos.y + (r.size.h - label_r.h) / 2 }, + paint_style, + text_ + ); + // token = strtok(NULL, " "); + //} } bool Button::on_key(const KeyEvent key) { diff --git a/firmware/common/ui_widget.hpp b/firmware/common/ui_widget.hpp index f154b86b..4a22f3f2 100644 --- a/firmware/common/ui_widget.hpp +++ b/firmware/common/ui_widget.hpp @@ -111,6 +111,8 @@ public: bool highlighted() const; void set_highlighted(const bool value); + + uint16_t id = 0; protected: void dirty_overlapping_children_in_rect(const Rect& child_rect); @@ -195,6 +197,19 @@ private: std::string text; }; +class ProgressBar : public Widget { +public: + ProgressBar(Rect parent_rect); + + void set_value(const uint16_t value); + uint16_t value() const; + + void paint(Painter& painter) override; + +private: + uint16_t _value = 0; +}; + class Checkbox : public Widget { public: std::function on_select; diff --git a/firmware/portapack-h1-firmware.bin b/firmware/portapack-h1-firmware.bin index a28ebe8f4a3254a0bb4747b48f79aff2a80d6b1b..47fe1947800134c5c042279fdfe56345be803f87 100644 GIT binary patch delta 70815 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 delta 66208 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⁡D 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 E06yz^h5!Hn diff --git a/sdcard/baseband-tx.bin b/sdcard/baseband-tx.bin index f456c721be28b4e5f21ebcb04db5527c0fe4ef42..3e65f73aba06c9806744978e5d16d24199b5488e 100644 GIT binary patch delta 3875 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 af#IV90|TSt=1(sFY&JKzE)WzzFQ)-QN*xIR diff --git a/sdcard/baseband.bin b/sdcard/baseband.bin index ab19dc42d8862b65674f575fa305a3b8d9a2e020..7f9b8511d687d43282727ca37b7314cd379891a3 100644 GIT binary patch delta 70 zcmZo@VQOe$(h3OhRbXP6Qq8~+l$xBHS(aMF#Q*`H81?oadN-fXtdwtiyN2i9jatVV H1<(Zn{S_FB delta 70 zcmZo@VQOe$(h3OhRbXQHP|v^+l$xBHS(aMF#Q*{3EZ+k&(z+Ci7ktlL^k|FKMy+Fw H0_cJO5Cj?K