From 491cb667cc48601adb9de3441dd2fa2bcea5f879 Mon Sep 17 00:00:00 2001 From: HTotoo Date: Sun, 10 Nov 2024 18:52:37 +0100 Subject: [PATCH] wf3 --- firmware/application/baseband_api.cpp | 5 + firmware/application/baseband_api.hpp | 1 + firmware/application/external/external.cmake | 6 + firmware/application/external/external.ld | 8 + .../application/external/wefax_rx/main.cpp | 82 +++++++++ .../external/wefax_rx/ui_wefax_rx.cpp | 104 +++++++++++ .../external/wefax_rx/ui_wefax_rx.hpp | 131 ++++++++++++++ firmware/baseband/CMakeLists.txt | 8 + firmware/baseband/proc_wefaxrx.cpp | 163 ++++++++++++++++++ firmware/baseband/proc_wefaxrx.hpp | 113 ++++++++++++ firmware/common/message.hpp | 37 ++++ firmware/common/spi_image.hpp | 1 + 12 files changed, 659 insertions(+) create mode 100644 firmware/application/external/wefax_rx/main.cpp create mode 100644 firmware/application/external/wefax_rx/ui_wefax_rx.cpp create mode 100644 firmware/application/external/wefax_rx/ui_wefax_rx.hpp create mode 100644 firmware/baseband/proc_wefaxrx.cpp create mode 100644 firmware/baseband/proc_wefaxrx.hpp diff --git a/firmware/application/baseband_api.cpp b/firmware/application/baseband_api.cpp index e288d9d66..2e1f814a9 100644 --- a/firmware/application/baseband_api.cpp +++ b/firmware/application/baseband_api.cpp @@ -304,6 +304,11 @@ void set_spectrum(const size_t sampling_rate, const size_t trigger) { send_message(&message); } +void set_wefax_config(uint8_t lpm = 120, uint8_t ioc = 0) { + const WeFaxRxConfigureMessage message{lpm, ioc}; + send_message(&message); +} + void set_siggen_tone(const uint32_t tone) { const SigGenToneMessage message{ TONES_F2D(tone, TONES_SAMPLERATE)}; diff --git a/firmware/application/baseband_api.hpp b/firmware/application/baseband_api.hpp index a594fc273..2481da4fa 100644 --- a/firmware/application/baseband_api.hpp +++ b/firmware/application/baseband_api.hpp @@ -89,6 +89,7 @@ void set_siggen_tone(const uint32_t tone); void set_siggen_config(const uint32_t bw, const uint32_t shape, const uint32_t duration); void set_spectrum_painter_config(const uint16_t width, const uint16_t height, bool update, int32_t bw); void set_subghzd_config(uint8_t modulation, uint32_t sampling_rate); +void set_wefax_config(uint8_t lpm, uint8_t ioc); void request_roger_beep(); void request_rssi_beep(); diff --git a/firmware/application/external/external.cmake b/firmware/application/external/external.cmake index 03844fcbf..ab3d1c9c6 100644 --- a/firmware/application/external/external.cmake +++ b/firmware/application/external/external.cmake @@ -107,6 +107,11 @@ set(EXTCPPSRC external/acars_rx/main.cpp external/acars_rx/acars_app.cpp + #wefax_rx + external/wefax_rx/main.cpp + external/wefax_rx/ui_wefax_rx.cpp + + #shoppingcart_lock external/shoppingcart_lock/main.cpp external/shoppingcart_lock/shoppingcart_lock.cpp @@ -143,5 +148,6 @@ set(EXTAPPLIST sstvtx random_password #acars_rx + wefax_rx shoppingcart_lock ) diff --git a/firmware/application/external/external.ld b/firmware/application/external/external.ld index 362cce897..2d9889d95 100644 --- a/firmware/application/external/external.ld +++ b/firmware/application/external/external.ld @@ -50,6 +50,7 @@ MEMORY ram_external_app_acars_rx(rwx) : org = 0xADC90000, len = 32k ram_external_app_shoppingcart_lock(rwx) : org = 0xADCA0000, len = 32k ram_external_app_cvs_spam(rwx) : org = 0xADCB0000, len = 32k + ram_external_app_wefax_rx(rwx) : org = 0xADCC0000, len = 32k } SECTIONS @@ -217,4 +218,11 @@ SECTIONS *(*ui*external_app*cvs_spam*); } > ram_external_app_cvs_spam + .external_app_wefax_rx : ALIGN(4) SUBALIGN(4) + { + KEEP(*(.external_app.app_wefax_rx.application_information)); + *(*ui*external_app*wefax_rx*); + } > ram_external_app_wefax_rx + + } diff --git a/firmware/application/external/wefax_rx/main.cpp b/firmware/application/external/wefax_rx/main.cpp new file mode 100644 index 000000000..0eccf2891 --- /dev/null +++ b/firmware/application/external/wefax_rx/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_wefax_rx.hpp" +#include "ui_navigation.hpp" +#include "external_app.hpp" + +namespace ui::external_app::wefax_rx { +void initialize_app(ui::NavigationView& nav) { + nav.push(); +} +} // namespace ui::external_app::wefax_rx + +extern "C" { + +__attribute__((section(".external_app.app_wefax_rx.application_information"), used)) application_information_t _application_information_wefax_rx = { + /*.memory_location = */ (uint8_t*)0x00000000, + /*.externalAppEntry = */ ui::external_app::wefax_rx::initialize_app, + /*.header_version = */ CURRENT_HEADER_VERSION, + /*.app_version = */ VERSION_MD5, + + /*.app_name = */ "WeFax", + /*.bitmap_data = */ { + 0x00, + 0x00, + 0xFC, + 0x07, + 0x04, + 0x0C, + 0x04, + 0x1C, + 0x04, + 0x3C, + 0x84, + 0x21, + 0x84, + 0x21, + 0x84, + 0x21, + 0xF4, + 0x2F, + 0xF4, + 0x2F, + 0x84, + 0x21, + 0x84, + 0x21, + 0x84, + 0x21, + 0x04, + 0x20, + 0xFC, + 0x3F, + 0x00, + 0x00, + }, + /*.icon_color = */ ui::Color::orange().v, + /*.menu_location = */ app_location_t::RX, + + /*.m4_app_tag = portapack::spi_flash::image_tag_wefaxrx */ {'P', 'W', 'F', 'X'}, + /*.m4_app_offset = */ 0x00000000, // will be filled at compile time +}; +} diff --git a/firmware/application/external/wefax_rx/ui_wefax_rx.cpp b/firmware/application/external/wefax_rx/ui_wefax_rx.cpp new file mode 100644 index 000000000..e6c669c53 --- /dev/null +++ b/firmware/application/external/wefax_rx/ui_wefax_rx.cpp @@ -0,0 +1,104 @@ +/* + * 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_wefax_rx.hpp" + +#include "audio.hpp" +#include "rtc_time.hpp" +#include "baseband_api.hpp" +#include "string_format.hpp" +#include "portapack_persistent_memory.hpp" +#include "lcd_ili9341.hpp" + +using namespace portapack; +using namespace modems; +using namespace ui; + +namespace ui::external_app::wefax_rx { + +void WeFaxRxView::focus() { + field_frequency.focus(); +} + +WeFaxRxView::WeFaxRxView(NavigationView& nav) + : nav_{nav} { + // baseband::run_image(portapack::spi_flash::image_tag_wefaxrx); + baseband::run_prepared_image(portapack::memory::map::m4_code.base()); + + add_children({&rssi, + &field_rf_amp, + &field_lna, + &field_vga, + &field_volume, + &field_frequency, + &txt_status, + &labels, + &options_lpm, + &options_ioc}); + + options_lpm.on_change = [this](size_t index, int32_t v) { + lpm_index = (uint8_t)index; + (void)v; + on_settings_changed(); + }; + options_ioc.on_change = [this](size_t index, int32_t v) { + ioc_index = (uint8_t)index; + (void)v; + on_settings_changed(); + }; + + options_lpm.set_selected_index(lpm_index, false); + options_ioc.set_selected_index(ioc_index, true); + + field_frequency.set_step(10); + audio::set_rate(audio::Rate::Hz_24000); + audio::output::start(); + receiver_model.enable(); + txt_status.set("Waiting for signal."); +} + +WeFaxRxView::~WeFaxRxView() { + receiver_model.disable(); + baseband::shutdown(); + audio::output::stop(); +} + +void WeFaxRxView::on_settings_changed() { + baseband::set_wefax_config(options_lpm.selected_index_value(), options_ioc.selected_index_value()); +} + +void WeFaxRxView::on_status(WeFaxRxStatusDataMessage msg) { + std::string tmp = to_string_dec_int(msg.freq) + " " + to_string_dec_int(msg.freqavg) + " " + to_string_dec_int(msg.freqmin) + " " + to_string_dec_int(msg.freqmax); + txt_status.set(tmp); +} + +void WeFaxRxView::on_image(WeFaxRxImageDataMessage msg) { + line_num++; + if (line_num >= 320 - 4 * 16) line_num = 0; + ui::Color line_buffer[240]; + for (uint16_t i = 0; i < 480; i += 2) { + uint8_t px = (msg.image[i] + msg.image[i + 1]) / 2; + line_buffer[i / 2] = {px, px, px}; + } + portapack::display.render_line({0, line_num + 4 * 16}, 240, line_buffer); +} + +} // namespace ui::external_app::wefax_rx diff --git a/firmware/application/external/wefax_rx/ui_wefax_rx.hpp b/firmware/application/external/wefax_rx/ui_wefax_rx.hpp new file mode 100644 index 000000000..40c67d08a --- /dev/null +++ b/firmware/application/external/wefax_rx/ui_wefax_rx.hpp @@ -0,0 +1,131 @@ +/* + * 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. + */ + +#ifndef __UI_WEFAX_RX_H__ +#define __UI_WEFAX_RX_H__ + +#include "ui.hpp" +#include "ui_language.hpp" +#include "ui_navigation.hpp" +#include "ui_receiver.hpp" +#include "ui_geomap.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::wefax_rx { + +class WeFaxRxView : public View { + public: + WeFaxRxView(NavigationView& nav); + ~WeFaxRxView(); + + void focus() override; + + std::string title() const override { return "WeFax"; }; + + private: + void on_settings_changed(); + void on_status(WeFaxRxStatusDataMessage msg); + void on_image(WeFaxRxImageDataMessage msg); + + uint8_t ioc_index{0}; + uint8_t lpm_index{0}; + uint16_t line_num = 0; + uint8_t txtDec = 0; + + NavigationView& nav_; + RxRadioState radio_state_{}; + app_settings::SettingsManager settings_{ + "rx_wefax", + app_settings::Mode::RX, + { + {"ioc_index"sv, &ioc_index}, + {"lpm_index"sv, &lpm_index}, + }}; + + 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{ + {{1 * 8, 1 * 16}, "LPM:", Theme::getInstance()->fg_light->foreground}, + {{13 * 8, 1 * 16}, "IOC:", Theme::getInstance()->fg_light->foreground}, + }; + + OptionsField options_lpm{ + {6 * 8, 1 * 16}, + 4, + { + {"60", 60}, + {"90", 90}, + {"100", 100}, + {"120", 120}, + {"180", 180}, + {"240", 240}, + }}; + + OptionsField options_ioc{ + {18 * 8, 1 * 16}, + 4, + { + {"576", 0}, + {"228", 1}, + }}; + + Text txt_status{ + {0 * 8, 2 * 16, 30 * 8, 16}, + }; + + MessageHandlerRegistration message_handler_stats{ + Message::ID::WeFaxRxStatusData, + [this](const Message* const p) { + const auto message = *reinterpret_cast(p); + on_status(message); + }}; + + MessageHandlerRegistration message_handler_image{ + Message::ID::WeFaxRxImageData, + [this](const Message* const p) { + const auto message = *reinterpret_cast(p); + on_image(message); + }}; +}; + +} // namespace ui::external_app::wefax_rx + +#endif /*__UI_WEFAX_RX_H__*/ diff --git a/firmware/baseband/CMakeLists.txt b/firmware/baseband/CMakeLists.txt index 51be53bec..7ca2d7f78 100644 --- a/firmware/baseband/CMakeLists.txt +++ b/firmware/baseband/CMakeLists.txt @@ -657,6 +657,14 @@ set(MODE_CPPSRC DeclareTargets(PADT adsbtx) +### WeFax Rx + +set(MODE_CPPSRC + proc_wefaxrx.cpp +) +DeclareTargets(PWFX wefaxrx) + + ### HackRF "factory" firmware add_custom_command( diff --git a/firmware/baseband/proc_wefaxrx.cpp b/firmware/baseband/proc_wefaxrx.cpp new file mode 100644 index 000000000..d8a0e6682 --- /dev/null +++ b/firmware/baseband/proc_wefaxrx.cpp @@ -0,0 +1,163 @@ +/* + * 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 "proc_wefaxrx.hpp" +#include "sine_table_int8.hpp" +#include "portapack_shared_memory.hpp" + +#include "audio_dma.hpp" +#include "math.h" +#include "event_m4.hpp" +#include "fxpt_atan2.hpp" + +#include +#include + +#define M_PI 3.14159265358979323846 + +// updates the per pixel timers +void WeFaxRx::update_params() { + switch (ioc_mode) { + case 1: + freq_start_tone = 675; + break; + default: + case 0: + freq_start_tone = 300; + break; + } + // 840 px / line with line start + time_per_pixel = 60000000 / lpm * 840; // micros (595,2380952 at 120 lpm) + pxRem = (double)baseband_fs / 8.0 / 8.0 / 4.0 / ((int)lpm * 14.0); // 840/60 = 228.57 sample / px + samples_per_pixel = pxRem; + pxRem -= samples_per_pixel; + pxRoll = 0; +} + +double WeFaxRx::calculatePhaseAngle(int16_t i, int16_t q) { + // return std::atan2(static_cast(q), static_cast(i)); + double ang = fxpt_atan2(q, i); + return ang / 32768.0 * M_PI; +} + +double WeFaxRx::calculateFrequencyDeviation(complex16_t& iq, complex16_t& iqlast) { + // Calculate phase difference between successive samples + double phaseDiff = calculatePhaseAngle(iq.imag(), iq.real()) - calculatePhaseAngle(iqlast.imag(), iqlast.real()); + // Ensure phase difference is within -pi to pi range + if (phaseDiff > M_PI) { + phaseDiff -= 2.0 * M_PI; + } else if (phaseDiff < -M_PI) { + phaseDiff += 2.0 * M_PI; + } + // Calculate frequency deviation + return (phaseDiff / (2.0 * M_PI)) * 12000.0; // (sample rate) +} + +void WeFaxRx::execute(const buffer_c8_t& buffer) { + // This is called at 3072000 / 2048 = 1500Hz + if (!configured) return; + + const auto decim_0_out = decim_0.execute(buffer, dst_buffer); // /8 = 256 + const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); // /8 = 32 + const auto decim_2_out = decim_2.execute(decim_1_out, dst_buffer); // /4 = 8 + // const auto channel_out = channel_filter.execute(decim_2_out, dst_buffer); // /1 = 8 + + // feed_channel_stats(channel_out); + // auto audio = demod.execute(channel_out, audio_buffer); + // audio_output.write(audio); + + // todo process + for (size_t c = 0; c < decim_2_out.count; c++) { + cnt++; + double freqq = calculateFrequencyDeviation(decim_2_out.p[c], iqlast); + if (status_message.freqmin > freqq) status_message.freqmin = freqq; + if (status_message.freqmax < freqq) status_message.freqmax = freqq; + status_message.freqavg += (freqq - status_message.freqavg) / cnt; + iqlast = decim_2_out.p[c]; + if (cnt >= (samples_per_pixel + (uint32_t)pxRoll)) { // got a pixel + cnt = 0; + if (pxRoll >= 1) pxRoll -= 1; + pxRoll += pxRem; + status_message.freq = freqq; + image_message.cnt++; // saves the pixel + if (image_message.cnt < 480) { + image_message.image[image_message.cnt] = status_message.freqavg < 2500 ? 0 : 255; // todo remove limit, send in multiple + /*if (status_message.freqavg >= 3000) + image_message.image[image_message.cnt] = 255; + else if (status_message.freqavg <= 2200) + image_message.image[image_message.cnt] = 0; + else { + image_message.image[image_message.cnt] = 256 - ((3000 - status_message.freqavg) / 3.1); + }*/ + } + if (image_message.cnt >= 840) { + shared_memory.application_queue.push(image_message); + image_message.cnt = 0; + shared_memory.application_queue.push(status_message); + status_message.freqmin = INT32_MAX; + status_message.freqmax = INT32_MIN; + } + status_message.freqavg = 0; + } + } +} + +void WeFaxRx::on_message(const Message* const message) { + switch (message->id) { + case Message::ID::WeFaxRxConfigure: + default: + configure(*reinterpret_cast(message)); + break; + } +} + +void WeFaxRx::configure(const WeFaxRxConfigureMessage& message) { + update_params(); + constexpr size_t decim_0_input_fs = baseband_fs; + constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0.decimation_factor; + + constexpr size_t decim_1_input_fs = decim_0_output_fs; + constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1.decimation_factor; + + constexpr size_t decim_2_input_fs = decim_1_output_fs; + constexpr size_t decim_2_output_fs = decim_2_input_fs / 4; + + constexpr size_t channel_filter_input_fs = decim_2_output_fs; + const size_t channel_filter_output_fs = channel_filter_input_fs / 1; // 12000ul + + lpm = message.lpm; + ioc_mode = message.ioc; + + decim_0.configure(taps_6k0_decim_0.taps); + decim_1.configure(taps_6k0_decim_1.taps); + decim_2.configure(taps_6k0_decim_2.taps, 4); + channel_filter.configure(taps_2k8_usb_channel.taps, 1); + demod.configure(channel_filter_output_fs, 3600); + audio_output.configure(audio_24k_hpf_300hz_config, audio_24k_deemph_300_6_config, 0); + configured = true; +} + +int main() { + audio::dma::init_audio_out(); + EventDispatcher event_dispatcher{std::make_unique()}; + event_dispatcher.run(); + return 0; +} diff --git a/firmware/baseband/proc_wefaxrx.hpp b/firmware/baseband/proc_wefaxrx.hpp new file mode 100644 index 000000000..6da018fa9 --- /dev/null +++ b/firmware/baseband/proc_wefaxrx.hpp @@ -0,0 +1,113 @@ +/* + * 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. + */ + +#ifndef __PROC_WEFAXRX_H__ +#define __PROC_WEFAXRX_H__ + +#include "baseband_processor.hpp" +#include "baseband_thread.hpp" +#include "rssi_thread.hpp" + +#include "dsp_decimate.hpp" +#include "dsp_demodulate.hpp" +#include "dsp_iir.hpp" + +#include "audio_output.hpp" +#include "spectrum_collector.hpp" + +#include + +class WeFaxRx : public BasebandProcessor { + public: + void execute(const buffer_c8_t& buffer) override; + void on_message(const Message* const message) override; + + private: + void configure(const WeFaxRxConfigureMessage& message); + void update_params(); + double calculateFrequencyDeviation(complex16_t& iq, complex16_t& iqlast); + double calculatePhaseAngle(int16_t i, int16_t q); + // todo rethink + uint8_t lpm = 120; // 60, 90, 100, 120, 180, 240 lpm + uint8_t ioc_mode = 0; // 0 - ioc576, 1 - ioc 288, 2 - colour fax + uint32_t time_per_pixel = 595; + uint32_t samples_per_pixel = 0; + uint32_t time_start_tone = 3000; // 3s - 5s + uint32_t freq_start_tone = 300; // 300hz for ioc576 675hz for ioc288, 200hz for colour fax + uint32_t freq_stop_tone = 450; // 450hz for the 3-5s stop tone + uint16_t max_lines = 2500; // to auto stop when too big + uint16_t curr_lines = 0; // current line number + uint16_t freq_px_max = 2300; // white + uint16_t freq_px_min = 1500; // black + + double pxRem = 0; // if has remainder, it'll store it + double pxRoll = 0; // summs remainders, so won't misalign + // float last_sig = 0; + uint32_t wcnt = 0; + uint32_t cnt = 0; + + static constexpr size_t baseband_fs = 3072000; + size_t decim_0_input_fs = 0; + size_t decim_0_output_fs = 0; + size_t decim_1_input_fs = 0; + size_t decim_1_output_fs = 0; + size_t decim_2_input_fs = 0; + size_t decim_2_output_fs = 0; + size_t channel_filter_input_fs = 0; + size_t channel_filter_output_fs = 0; + + bool configured{false}; + + complex16_t iqlast = 0; + + std::array dst{}; + const buffer_c16_t dst_buffer{ + dst.data(), + dst.size()}; + std::array audio{}; + const buffer_f32_t audio_buffer{ + audio.data(), + audio.size()}; + + dsp::demodulate::FM demod{}; + AudioOutput audio_output{}; + dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0{}; + dsp::decimate::FIRC16xR16x32Decim8 decim_1{}; + dsp::decimate::FIRAndDecimateComplex decim_2{}; + dsp::decimate::FIRAndDecimateComplex channel_filter{}; + + enum State { + WAIT_FLAG, + START, + PHASING, + IMAGE, + WAIT_STOP + }; + + WeFaxRxStatusDataMessage status_message{0, 0}; + WeFaxRxImageDataMessage image_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_WEFAXRX_H__*/ diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index a619816ca..a23496af8 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -127,6 +127,10 @@ class Message { FreqChangeCommand = 70, I2CDevListChanged = 71, LightData = 72, + WeFaxRxConfigure = 73, + WeFaxRxStatusData = 74, + WeFaxRxImageData = 75, + MAX }; @@ -1437,4 +1441,37 @@ class I2CDevListChangedMessage : public Message { : Message{ID::I2CDevListChanged} {} }; +class WeFaxRxConfigureMessage : public Message { + public: + constexpr WeFaxRxConfigureMessage(uint8_t lpm, uint8_t ioc) + : Message{ID::WeFaxRxConfigure}, + lpm{lpm}, + ioc{ioc} { + } + uint8_t lpm = 120; + uint8_t ioc = 0; +}; + +class WeFaxRxStatusDataMessage : public Message { + public: + constexpr WeFaxRxStatusDataMessage(uint8_t state, int32_t freq) + : Message{ID::WeFaxRxStatusData}, + state{state}, + freq{freq} { + } + uint8_t state = 0; + int32_t freq = 0; + int32_t freqmin = 0; + int32_t freqmax = 0; + int32_t freqavg = 0; +}; + +class WeFaxRxImageDataMessage : public Message { + public: + constexpr WeFaxRxImageDataMessage() + : Message{ID::WeFaxRxImageData} {} + uint8_t image[480]{0}; + uint32_t cnt = 0; +}; + #endif /*__MESSAGE_H__*/ diff --git a/firmware/common/spi_image.hpp b/firmware/common/spi_image.hpp index ccc3d9cbc..79610b81f 100644 --- a/firmware/common/spi_image.hpp +++ b/firmware/common/spi_image.hpp @@ -117,6 +117,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_wefaxrx{'P', 'W', 'F', 'X'}; constexpr image_tag_t image_tag_noop{'P', 'N', 'O', 'P'};