From 9211975868ff8c55d584e0a0e1a1b9cd9a98b1a2 Mon Sep 17 00:00:00 2001 From: Totoo Date: Mon, 29 Jul 2024 07:45:56 +0200 Subject: [PATCH] Protoview (#2206) * ProtoView first tests * Imp * fix, reset --- firmware/application/external/external.cmake | 5 + firmware/application/external/external.ld | 9 + .../application/external/protoview/main.cpp | 82 ++++++++ .../external/protoview/ui_protoview.cpp | 195 ++++++++++++++++++ .../external/protoview/ui_protoview.hpp | 164 +++++++++++++++ firmware/baseband/CMakeLists.txt | 9 + firmware/baseband/proc_protoview.cpp | 112 ++++++++++ firmware/baseband/proc_protoview.hpp | 74 +++++++ firmware/baseband/proc_subghzd.cpp | 1 + firmware/baseband/proc_weather.cpp | 1 + firmware/baseband/proc_weather.hpp | 2 - firmware/common/message.hpp | 10 + firmware/common/spi_image.hpp | 1 + firmware/common/ui_language.cpp | 2 +- firmware/common/ui_language.hpp | 3 +- firmware/common/ui_widget.cpp | 6 +- firmware/graphics/icon_protoview.png | Bin 0 -> 231 bytes 17 files changed, 669 insertions(+), 7 deletions(-) create mode 100644 firmware/application/external/protoview/main.cpp create mode 100644 firmware/application/external/protoview/ui_protoview.cpp create mode 100644 firmware/application/external/protoview/ui_protoview.hpp create mode 100644 firmware/baseband/proc_protoview.cpp create mode 100644 firmware/baseband/proc_protoview.hpp create mode 100644 firmware/graphics/icon_protoview.png diff --git a/firmware/application/external/external.cmake b/firmware/application/external/external.cmake index baba494f..2e821875 100644 --- a/firmware/application/external/external.cmake +++ b/firmware/application/external/external.cmake @@ -80,6 +80,10 @@ set(EXTCPPSRC #tpmsrx external/tpmsrx/main.cpp external/tpmsrx/tpms_app.cpp + + #protoview + external/protoview/main.cpp + external/protoview/ui_protoview.cpp ) set(EXTAPPLIST @@ -102,4 +106,5 @@ set(EXTAPPLIST audio_test wardrivemap tpmsrx + protoview ) diff --git a/firmware/application/external/external.ld b/firmware/application/external/external.ld index aab54bda..00333f8f 100644 --- a/firmware/application/external/external.ld +++ b/firmware/application/external/external.ld @@ -42,6 +42,7 @@ MEMORY ram_external_app_audio_test(rwx) : org = 0xADC10000, len = 32k ram_external_app_wardrivemap(rwx) : org = 0xADC20000, len = 32k ram_external_app_tpmsrx(rwx) : org = 0xADC30000, len = 32k + ram_external_app_protoview(rwx) : org = 0xADC40000, len = 32k } SECTIONS @@ -160,4 +161,12 @@ SECTIONS *(*ui*external_app*tpmsrx*); } > ram_external_app_tpmsrx + + .external_app_protoview : ALIGN(4) SUBALIGN(4) + { + KEEP(*(.external_app.app_protoview.application_information)); + *(*ui*external_app*protoview*); + } > ram_external_app_protoview + + } diff --git a/firmware/application/external/protoview/main.cpp b/firmware/application/external/protoview/main.cpp new file mode 100644 index 00000000..403bef32 --- /dev/null +++ b/firmware/application/external/protoview/main.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2024 HTotoo + * + * 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_protoview.hpp" +#include "ui_navigation.hpp" +#include "external_app.hpp" + +namespace ui::external_app::protoview { +void initialize_app(ui::NavigationView& nav) { + nav.push(); +} +} // namespace ui::external_app::protoview + +extern "C" { + +__attribute__((section(".external_app.app_protoview.application_information"), used)) application_information_t _application_information_protoview = { + /*.memory_location = */ (uint8_t*)0x00000000, + /*.externalAppEntry = */ ui::external_app::protoview::initialize_app, + /*.header_version = */ CURRENT_HEADER_VERSION, + /*.app_version = */ VERSION_MD5, + + /*.app_name = */ "ProtoView", + /*.bitmap_data = */ { + 0x00, + 0x00, + 0x00, + 0x00, + 0xF8, + 0x87, + 0x08, + 0x84, + 0x0F, + 0xFC, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xF3, + 0xE0, + 0x92, + 0xA0, + 0x9E, + 0xBF, + 0x00, + 0x00, + 0x00, + 0x00, + 0xFC, + 0xF3, + 0x04, + 0x12, + 0x07, + 0x1E, + }, + /*.icon_color = */ ui::Color::orange().v, + /*.menu_location = */ app_location_t::RX, + + /*.m4_app_tag = portapack::spi_flash::image_tag_protoview */ {'P', 'P', 'V', 'W'}, + /*.m4_app_offset = */ 0x00000000, // will be filled at compile time +}; +} diff --git a/firmware/application/external/protoview/ui_protoview.cpp b/firmware/application/external/protoview/ui_protoview.cpp new file mode 100644 index 00000000..47e5f047 --- /dev/null +++ b/firmware/application/external/protoview/ui_protoview.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2017 Furrtek + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "ui_protoview.hpp" + +#include "audio.hpp" +#include "rtc_time.hpp" +#include "baseband_api.hpp" +#include "string_format.hpp" +#include "portapack_persistent_memory.hpp" +#include "file_path.hpp" + +using namespace portapack; +using namespace modems; +using namespace ui; + +namespace ui::external_app::protoview { + +void ProtoView::focus() { + field_frequency.focus(); +} + +ProtoView::ProtoView(NavigationView& nav) + : nav_{nav} { + baseband::run_prepared_image(portapack::memory::map::m4_code.base()); + + add_children({&rssi, + &field_rf_amp, + &field_lna, + &field_vga, + &field_volume, + &field_frequency, + &labels, + &options_zoom, + &button_reset, + &waveform, + &waveform2, + &waveform3, + &waveform4}); + + field_frequency.set_step(100); + options_zoom.on_change = [this](size_t, int32_t v) { + zoom = v; + draw(); + draw2(); + }; + button_reset.on_select = [this](Button&) { + reset(); + }; + baseband::set_subghzd_config(0, receiver_model.sampling_rate()); + audio::set_rate(audio::Rate::Hz_24000); + audio::output::start(); + receiver_model.enable(); +} + +void ProtoView::reset() { + cnt = 0; + for (uint16_t i = 0; i < MAXSIGNALBUFFER; i++) time_buffer[i] = 0; + needCntReset = false; + draw(); + draw2(); +} + +void ProtoView::on_timer() { + timercnt++; + if ((timercnt % 90) == 0) { + if (datacnt == 0) { + needCntReset = true; + } + datacnt = 0; + } +} + +void ProtoView::draw2() { + if (drawcnt < MAXDRAWCNTPERWF) { + waveform.set_length(drawcnt); + waveform2.set_length(0); + waveform3.set_length(0); + waveform4.set_length(0); + } else if (drawcnt < MAXDRAWCNTPERWF * 2) { + waveform.set_length(MAXDRAWCNTPERWF); + waveform2.set_length(drawcnt - MAXDRAWCNTPERWF); + waveform3.set_length(0); + waveform4.set_length(0); + } else if (drawcnt < MAXDRAWCNTPERWF * 3) { + waveform.set_length(MAXDRAWCNTPERWF); + waveform2.set_length(MAXDRAWCNTPERWF); + waveform3.set_length(drawcnt - MAXDRAWCNTPERWF * 2); + waveform4.set_length(0); + } else { + waveform.set_length(MAXDRAWCNTPERWF); + waveform2.set_length(MAXDRAWCNTPERWF); + waveform3.set_length(MAXDRAWCNTPERWF); + waveform4.set_length(drawcnt - MAXDRAWCNTPERWF * 3); + } + waveform.set_dirty(); + waveform2.set_dirty(); + waveform3.set_dirty(); + waveform4.set_dirty(); +} + +void ProtoView::draw() { + uint32_t remain = 0; + int32_t lmax = 0; + bool lmaxstate = false; + bool state = false; + drawcnt = 0; + for (uint16_t i = 0; i < MAXDRAWCNT; i++) waveform_buffer[i] = 0; // reset + + for (uint16_t i = 0; i < MAXSIGNALBUFFER; ++i) { + state = time_buffer[i] >= 0; + int32_t timeabs = state ? time_buffer[i] : -1 * time_buffer[i]; + int32_t timesize = timeabs / zoom; + if (timesize == 0) { + remain += timeabs; + if (lmax < timeabs) { + lmax = timeabs; + lmaxstate = state; + } + if (remain / zoom > 0) { + timesize = remain / zoom; + state = lmaxstate; + } else { + continue; + } + } + remain = 0; + lmax = 0; + for (int32_t ii = 0; ii < timesize; ++ii) { + waveform_buffer[drawcnt++] = state; + if (drawcnt >= MAXDRAWCNT) return; + } + } +} + +void ProtoView::add_time(int32_t time) { + if (cnt >= MAXSIGNALBUFFER) cnt = 0; + time_buffer[cnt++] = time; +} + +void ProtoView::on_data(const ProtoViewDataMessage* message) { + // filter out invalid ones. + uint16_t start = 0; + uint16_t stop = 0; + bool has_valid = false; + for (uint16_t i = 0; i <= message->maxptr; ++i) { + if (message->times[i] >= 30000 || message->times[i] <= -30000) { + if (!has_valid) { + start = i; + } + } else { + has_valid = true; + stop = i; + } + } + if (!has_valid) return; // no valid data arrived + // if (needCntReset) reset(); //todo implement auto reset + + datacnt++; + + // valid data, redraw + for (uint16_t i = start; i <= stop; i++) { + add_time(message->times[i]); + } + + draw(); + draw2(); +} + +ProtoView::~ProtoView() { + audio::output::stop(); + receiver_model.disable(); + baseband::shutdown(); +} + +} // namespace ui::external_app::protoview diff --git a/firmware/application/external/protoview/ui_protoview.hpp b/firmware/application/external/protoview/ui_protoview.hpp new file mode 100644 index 00000000..b5991110 --- /dev/null +++ b/firmware/application/external/protoview/ui_protoview.hpp @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2017 Furrtek + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __UI_PROTOVIEW_H__ +#define __UI_PROTOVIEW_H__ + +#define MAXSIGNALBUFFER 400 +#define MAXDRAWCNT 600 +#define MAXDRAWCNTPERWF 150 + +#include "ui.hpp" +#include "ui_language.hpp" +#include "ui_navigation.hpp" +#include "ui_receiver.hpp" +#include "ui_freq_field.hpp" +#include "ui_record_view.hpp" +#include "app_settings.hpp" +#include "radio_state.hpp" +#include "log_file.hpp" +#include "utility.hpp" + +using namespace ui; + +namespace ui::external_app::protoview { + +class ProtoView : public View { + public: + ProtoView(NavigationView& nav); + ~ProtoView(); + + void focus() override; + + std::string title() const override { return "ProtoView"; }; + + private: + int16_t waveform_buffer[MAXDRAWCNT]; + int32_t time_buffer[MAXSIGNALBUFFER]; + + NavigationView& nav_; + RxRadioState radio_state_{}; + app_settings::SettingsManager settings_{ + "rx_protoview", app_settings::Mode::RX}; + + RFAmpField field_rf_amp{ + {13 * 8, 0 * 16}}; + LNAGainField field_lna{ + {15 * 8, 0 * 16}}; + VGAGainField field_vga{ + {18 * 8, 0 * 16}}; + RSSI rssi{ + {21 * 8, 0, 6 * 8, 4}}; + + AudioVolumeField field_volume{ + {28 * 8, 0 * 16}}; + + RxFrequencyField field_frequency{ + {0 * 8, 0 * 16}, + nav_}; + Labels labels{ + {{0 * 8, 1 * 16}, "Zoom: ", Theme::getInstance()->fg_light->foreground}}; + + OptionsField options_zoom{ + {7 * 8, 1 * 16}, + 4, + {{"1", 1}, + {"2", 2}, + {"5", 5}, + {"15", 15}, + {"30", 30}, + {"50", 50}, + {"100", 100}, + {"200", 200}, + {"500", 500}, + {"1000", 1000}}}; + + Button button_reset{ + {screen_width - 12 * 8, 1 * 16, 96, 24}, + LanguageHelper::currentMessages[LANG_RESET]}; + + Waveform waveform{ + {0, 5 * 8, 240, 50}, + waveform_buffer, + 0, + 0, + true, + Theme::getInstance()->fg_yellow->foreground}; + + Waveform waveform2{ + {0, 5 * 8 + 55, 240, 50}, + &waveform_buffer[MAXDRAWCNTPERWF], + 0, + 0, + true, + Theme::getInstance()->fg_yellow->foreground}; + + Waveform waveform3{ + {0, 5 * 8 + 110, 240, 50}, + &waveform_buffer[MAXDRAWCNTPERWF * 2], + 0, + 0, + true, + Theme::getInstance()->fg_yellow->foreground}; + + Waveform waveform4{ + {0, 5 * 8 + 165, 240, 50}, + &waveform_buffer[MAXDRAWCNTPERWF * 3], + 0, + 0, + true, + Theme::getInstance()->fg_yellow->foreground}; + + bool needCntReset = false; + + int16_t zoom = 1; // one value in ms + + uint16_t cnt = 0; // pointer to next element + uint16_t drawcnt = 0; // pointer to draw next element + + uint16_t timercnt = 0; // screen refresh count + uint16_t datacnt = 0; // how many data i got. these are for track if there is no data, so need a cnt reset + + void add_time(int32_t time); + void on_timer(); + void on_data(const ProtoViewDataMessage* message); + void draw(); + void draw2(); + void reset(); + + MessageHandlerRegistration message_handler_packet{ + Message::ID::ProtoViewData, + [this](Message* const p) { + const auto message = static_cast(p); + this->on_data(message); + }}; + + MessageHandlerRegistration message_handler_frame_sync{ + Message::ID::DisplayFrameSync, + [this](const Message* const) { + this->on_timer(); + }}; +}; + +} // namespace ui::external_app::protoview + +#endif /*__UI_PROTOVIEW_H__*/ diff --git a/firmware/baseband/CMakeLists.txt b/firmware/baseband/CMakeLists.txt index 5efc3687..0345cbda 100644 --- a/firmware/baseband/CMakeLists.txt +++ b/firmware/baseband/CMakeLists.txt @@ -648,6 +648,15 @@ set(MODE_CPPSRC DeclareTargets(PABP audio_beep) +### ProtoView + +set(MODE_CPPSRC + proc_protoview.cpp +) +DeclareTargets(PPVW protoview) + + + ### TPMS set(MODE_CPPSRC diff --git a/firmware/baseband/proc_protoview.cpp b/firmware/baseband/proc_protoview.cpp new file mode 100644 index 00000000..7f8abd89 --- /dev/null +++ b/firmware/baseband/proc_protoview.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "proc_protoview.hpp" +#include "portapack_shared_memory.hpp" +#include "event_m4.hpp" +#include "audio_dma.hpp" + +void ProtoViewProcessor::execute(const buffer_c8_t& buffer) { + if (!configured) return; + + // SR = 4Mhz , and we are decimating by /8 in total , decim1_out clock 4Mhz /8= 500khz samples/sec. + // buffer has 2048 complex i8 I,Q signed samples + // decim0 out: 2048/4 = 512 complex i16 I,Q signed samples + // decim1 out: 512/2 = 256 complex i16 I,Q signed samples + // Regarding Filters, we are re-using existing FIR filters, @4Mhz, FIR decim1 ilter, BW =+-220Khz (at -3dB's). BW = 440kHZ. + + const auto decim_0_out = decim_0.execute(buffer, dst_buffer); // Input:2048 complex/4 (decim factor) = 512_output complex (1024 I/Q samples) + const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); // Input:512 complex/2 (decim factor) = 256_output complex ( 512 I/Q samples) + feed_channel_stats(decim_1_out); + + for (size_t i = 0; i < decim_1_out.count; i++) { + int16_t re = decim_1_out.p[i].real(); + int16_t im = decim_1_out.p[i].imag(); + uint32_t mag = ((uint32_t)re * (uint32_t)re) + ((uint32_t)im * (uint32_t)im); + + mag = (mag >> 12); // Decim samples are calculated with saturated gain . (we could also reduce that sat. param at configure time) + + bool meashl = (mag > threshold); + tm += mag; + if (meashl == currentHiLow && currentDuration < 30'000'000) // allow pass 'end' signal + { + currentDuration += nsPerDecSamp; + } else { // called on change, so send the last duration and dir. + message.times[message.timeptr++] = currentHiLow ? (int32_t)(currentDuration / 1000) : -1 * (int32_t)(currentDuration / 1000); + if (message.timeptr > message.maxptr) { + shared_memory.application_queue.push(message); + message.timeptr = 0; + } + currentDuration = nsPerDecSamp; + currentHiLow = meashl; + } + } + + cnt += decim_1_out.count; // TODO , check if it is necessary that xdecim factor. + if (cnt > 90'000) { + threshold = (tm / cnt) / 2; + cnt = 0; + tm = 0; + if (threshold < 50) threshold = 50; + if (threshold > 1700) threshold = 1700; + } +} + +void ProtoViewProcessor::on_message(const Message* const message) { + switch (message->id) { + case Message::ID::SubGhzFPRxConfigure: + configure(*reinterpret_cast(message)); + break; + + case Message::ID::AudioBeep: + on_beep_message(*reinterpret_cast(message)); + break; + + default: + break; + } +} + +void ProtoViewProcessor::configure(const SubGhzFPRxConfigureMessage& message) { + baseband_fs = message.sampling_rate; + baseband_thread.set_sampling_rate(baseband_fs); + nsPerDecSamp = 1'000'000'000 / baseband_fs * 8; // Scaled it due to less array buffer sampes due to /8 decimation. 250 nseg (4Mhz) * 8 + + // constexpr size_t decim_0_output_fs = baseband_fs / decim_0.decimation_factor; //unused + // constexpr size_t decim_1_output_fs = decim_0_output_fs / decim_1.decimation_factor; //unused + + decim_0.configure(taps_200k_wfm_decim_0.taps); + decim_1.configure(taps_200k_wfm_decim_1.taps); + + configured = true; +} + +void ProtoViewProcessor::on_beep_message(const AudioBeepMessage& message) { + audio::dma::beep_start(message.freq, message.sample_rate, message.duration_ms); +} + +int main() { + audio::dma::init_audio_out(); + EventDispatcher event_dispatcher{std::make_unique()}; + event_dispatcher.run(); + return 0; +} diff --git a/firmware/baseband/proc_protoview.hpp b/firmware/baseband/proc_protoview.hpp new file mode 100644 index 00000000..abe56d7f --- /dev/null +++ b/firmware/baseband/proc_protoview.hpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ +/* + Creator: @htotoo +*/ + +#ifndef __PROC_PROTOVIEW_H__ +#define __PROC_PROTOVIEW_H__ + +#include "baseband_processor.hpp" +#include "baseband_thread.hpp" +#include "rssi_thread.hpp" +#include "message.hpp" +#include "dsp_decimate.hpp" + +class ProtoViewProcessor : public BasebandProcessor { + public: + void execute(const buffer_c8_t& buffer) override; + void on_message(const Message* const message) override; + + private: + size_t baseband_fs = 0; // will be set later by configure message. + uint32_t nsPerDecSamp = 0; + + /* Array Buffer aux. used in decim0 and decim1 IQ c16 signed data ; (decim0 defines the max length of the array) */ + std::array dst{}; // decim0 /4 , 2048/4 = 512 complex I,Q + const buffer_c16_t dst_buffer{ + dst.data(), + dst.size()}; + + /* Decimates */ + dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0{}; + dsp::decimate::FIRC16xR16x16Decim2 decim_1{}; + + uint32_t currentDuration = 0; + uint32_t threshold = 0x0630; // will overwrite after the first iteration + + bool currentHiLow = false; + bool configured{false}; + + // for threshold + uint32_t cnt = 0; + uint32_t tm = 0; + + void configure(const SubGhzFPRxConfigureMessage& message); + void on_beep_message(const AudioBeepMessage& message); + + ProtoViewDataMessage message = {}; + + /* NB: Threads should be the last members in the class definition. */ + BasebandThread baseband_thread{baseband_fs, this, baseband::Direction::Receive}; + RSSIThread rssi_thread{}; +}; + +#endif /*__PROC_PROTOVIEW_H__*/ diff --git a/firmware/baseband/proc_subghzd.cpp b/firmware/baseband/proc_subghzd.cpp index acd09d4b..4743d872 100644 --- a/firmware/baseband/proc_subghzd.cpp +++ b/firmware/baseband/proc_subghzd.cpp @@ -35,6 +35,7 @@ void SubGhzDProcessor::execute(const buffer_c8_t& buffer) { const auto decim_0_out = decim_0.execute(buffer, dst_buffer); // Input:2048 complex/4 (decim factor) = 512_output complex (1024 I/Q samples) const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); // Input:512 complex/2 (decim factor) = 256_output complex ( 512 I/Q samples) + feed_channel_stats(decim_1_out); for (size_t i = 0; i < decim_1_out.count; i++) { int16_t re = decim_1_out.p[i].real(); diff --git a/firmware/baseband/proc_weather.cpp b/firmware/baseband/proc_weather.cpp index 3d661c60..6939af8e 100644 --- a/firmware/baseband/proc_weather.cpp +++ b/firmware/baseband/proc_weather.cpp @@ -36,6 +36,7 @@ void WeatherProcessor::execute(const buffer_c8_t& buffer) { const auto decim_0_out = decim_0.execute(buffer, dst_buffer); // Input:2048 complex/4 (decim factor) = 512_output complex (1024 I/Q samples) const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); // Input:512 complex/2 (decim factor) = 256_output complex ( 512 I/Q samples) + feed_channel_stats(decim_1_out); for (size_t i = 0; i < decim_1_out.count; i++) { int16_t re = decim_1_out.p[i].real(); diff --git a/firmware/baseband/proc_weather.hpp b/firmware/baseband/proc_weather.hpp index c668f604..4945db34 100644 --- a/firmware/baseband/proc_weather.hpp +++ b/firmware/baseband/proc_weather.hpp @@ -58,8 +58,6 @@ class WeatherProcessor : public BasebandProcessor { bool currentHiLow = false; bool configured{false}; - uint8_t modulation = 255; // 0 AM, 1 FM 255 = Not set - uint8_t protoMode = 255; // 0 weather, 1 subghzd, 255 = Not set // for threshold uint32_t cnt = 0; uint32_t tm = 0; diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 6cd41585..c5ce6b90 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -124,6 +124,7 @@ class Message { AudioBeep = 66, PocsagTosend = 67, BatteryStateData = 68, + ProtoViewData = 69, MAX }; @@ -1426,4 +1427,13 @@ class BatteryStateMessage : public Message { uint16_t voltage = 0; // mV }; +class ProtoViewDataMessage : public Message { + public: + constexpr ProtoViewDataMessage() + : Message{ID::ProtoViewData} {} + int32_t times[100] = {0}; // positive: high, negative: low + uint16_t timeptr = 0; + const uint16_t maxptr = 99; +}; + #endif /*__MESSAGE_H__*/ diff --git a/firmware/common/spi_image.hpp b/firmware/common/spi_image.hpp index 0a95455c..ccc3d9cb 100644 --- a/firmware/common/spi_image.hpp +++ b/firmware/common/spi_image.hpp @@ -116,6 +116,7 @@ constexpr image_tag_t image_tag_usb_sd{'P', 'U', 'S', 'B'}; constexpr image_tag_t image_tag_weather{'P', 'W', 'T', 'H'}; constexpr image_tag_t image_tag_subghzd{'P', 'S', 'G', 'D'}; +constexpr image_tag_t image_tag_protoview{'P', 'P', 'V', 'W'}; constexpr image_tag_t image_tag_noop{'P', 'N', 'O', 'P'}; diff --git a/firmware/common/ui_language.cpp b/firmware/common/ui_language.cpp index 0d625e64..73b8a9e7 100644 --- a/firmware/common/ui_language.cpp +++ b/firmware/common/ui_language.cpp @@ -1,6 +1,6 @@ #include "ui_language.hpp" -const char* LanguageHelper::englishMessages[] = {"OK", "Cancel", "Error", "Modem setup", "Debug", "Log", "Done", "Start", "Stop", "Scan", "Clear", "Ready", "Data:", "Loop"}; +const char* LanguageHelper::englishMessages[] = {"OK", "Cancel", "Error", "Modem setup", "Debug", "Log", "Done", "Start", "Stop", "Scan", "Clear", "Ready", "Data:", "Loop", "Reset"}; const char** LanguageHelper::currentMessages = englishMessages; diff --git a/firmware/common/ui_language.hpp b/firmware/common/ui_language.hpp index caa03950..4b39e17a 100644 --- a/firmware/common/ui_language.hpp +++ b/firmware/common/ui_language.hpp @@ -19,7 +19,8 @@ enum LangConsts { LANG_CLEAR, LANG_READY, LANG_DATADP, - LANG_LOOP + LANG_LOOP, + LANG_RESET }; class LanguageHelper { diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index 6075ef05..47db283b 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -2630,13 +2630,13 @@ void Waveform::paint(Painter& painter) { const float y_scale = (float)(h - 1) / 65536.0; int16_t* data_start = data_ + offset_; + // Clear + painter.fill_rectangle_unrolled8(screen_rect(), Theme::getInstance()->bg_darkest->background); + if (!length_) return; x_inc = (float)screen_rect().size().width() / length_; - // Clear - painter.fill_rectangle_unrolled8(screen_rect(), Theme::getInstance()->bg_darkest->background); - if (digital_) { // Digital waveform: each value is an horizontal line x = 0; diff --git a/firmware/graphics/icon_protoview.png b/firmware/graphics/icon_protoview.png new file mode 100644 index 0000000000000000000000000000000000000000..31be6fbdb7f5bd20e16881d9fe31c92127ec1aa4 GIT binary patch literal 231 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBufiR<}hF1enu*TEHF~q`u?WBi74GJ917r)o17hUrb_}f@p zepB|g?}Dz5jOt5Qp3gm2vS3&KGLakh59TxN>2!%&zx8m;Zte~P*%XVoM?b?K@LBAh zZ+h$GiH;G?yRVccRje=?TFn( Z?$R3X-*%BcRX}$zc)I$ztaD0e0swq5SQ7vM literal 0 HcmV?d00001