From 44a0475be6baea4dcabe3cc3b68cf7a6a55ce7f4 Mon Sep 17 00:00:00 2001 From: RocketGod <57732082+RocketGod-git@users.noreply.github.com> Date: Thu, 27 Mar 2025 07:43:16 -0700 Subject: [PATCH] Make the beginnings of rf3d --- firmware/application/external/external.cmake | 5 + firmware/application/external/external.ld | 7 ++ firmware/application/external/rf3d/main.cpp | 30 ++++++ .../application/external/rf3d/ui_rf3d.cpp | 97 +++++++++++++++++++ .../application/external/rf3d/ui_rf3d.hpp | 45 +++++++++ 5 files changed, 184 insertions(+) create mode 100644 firmware/application/external/rf3d/main.cpp create mode 100644 firmware/application/external/rf3d/ui_rf3d.cpp create mode 100644 firmware/application/external/rf3d/ui_rf3d.hpp diff --git a/firmware/application/external/external.cmake b/firmware/application/external/external.cmake index f944d85c2..f706e82f5 100644 --- a/firmware/application/external/external.cmake +++ b/firmware/application/external/external.cmake @@ -203,6 +203,10 @@ set(EXTCPPSRC #level external/level/main.cpp external/level/ui_level.cpp + + #rf3d + external/rf3d/main.cpp + external/rf3d/ui_rf3d.cpp ) set(EXTAPPLIST @@ -255,4 +259,5 @@ set(EXTAPPLIST debug_pmem scanner level + rf3d ) diff --git a/firmware/application/external/external.ld b/firmware/application/external/external.ld index 5b83ae36a..7aa291beb 100644 --- a/firmware/application/external/external.ld +++ b/firmware/application/external/external.ld @@ -72,6 +72,7 @@ MEMORY ram_external_app_debug_pmem (rwx) : org = 0xADDF0000, len = 32k ram_external_app_scanner (rwx) : org = 0xADE00000, len = 32k ram_external_app_level (rwx) : org = 0xADE10000, len = 32k + ram_external_app_rf3d (rwx) : org = 0xADE20000, len = 32k } SECTIONS @@ -368,4 +369,10 @@ SECTIONS KEEP(*(.external_app.app_level.application_information)); *(*ui*external_app*level*); } > ram_external_app_level + + .external_app_rf3d : ALIGN(4) SUBALIGN(4) + { + KEEP(*(.external_app.app_rf3d.application_information)); + *(*ui*external_app*rf3d*); + } > ram_external_app_rf3d } diff --git a/firmware/application/external/rf3d/main.cpp b/firmware/application/external/rf3d/main.cpp new file mode 100644 index 000000000..5146b7656 --- /dev/null +++ b/firmware/application/external/rf3d/main.cpp @@ -0,0 +1,30 @@ +#include "ui_rf3d.hpp" +#include "ui_navigation.hpp" +#include "external_app.hpp" + +namespace ui::external_app::rf3d { +void initialize_app(ui::NavigationView& nav) { + nav.push(); +} +} + +extern "C" { +__attribute__((section(".external_app.app_3drf.application_information"), used)) application_information_t _application_information_3drf = { + (uint8_t*)0x00000000, + ui::external_app::rf3d::initialize_app, + CURRENT_HEADER_VERSION, + VERSION_MD5, + "RF3D", + { + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }, + /*.icon_color = */ ui::Color::green().v, + /*.menu_location = */ app_location_t::RX, + /*.desired_menu_position = */ -1, + + /*.m4_app_tag = portapack::spi_flash::image_tag_wfm_audio */ {'P', 'N', 'F', 'M'}, + /*.m4_app_offset = */ 0x00000000, // will be filled at compile time +}; +} \ No newline at end of file diff --git a/firmware/application/external/rf3d/ui_rf3d.cpp b/firmware/application/external/rf3d/ui_rf3d.cpp new file mode 100644 index 000000000..031e19937 --- /dev/null +++ b/firmware/application/external/rf3d/ui_rf3d.cpp @@ -0,0 +1,97 @@ +#include "ui_rf3d.hpp" +#include +#include + +namespace ui::external_app::rf3d { + +RF3DView::RF3DView(NavigationView& nav) + : nav_{nav} { + add_children({&dummy}); + spectrum_data.resize(240, std::vector(64, 0)); +} + +void RF3DView::on_show() { + if (!initialized) { + initialized = true; + baseband::run_image(portapack::spi_flash::image_tag_nfm_audio); + start(); + } +} + +void RF3DView::start() { + if (!running) { + baseband::spectrum_streaming_start(); + running = true; + } +} + +void RF3DView::stop() { + if (running) { + baseband::spectrum_streaming_stop(); + running = false; + } +} + +void RF3DView::update_spectrum() { + for (int x = 0; x < 240; x++) { + for (int z = 63; z > 0; z--) { + spectrum_data[x][z] = spectrum_data[x][z - 1]; + } + spectrum_data[x][0] = rand() % 256; + } +} + +void RF3DView::render_3d_waterfall(Painter& painter) { + painter.fill_rectangle({0, 0, 240, 320}, Color::black()); + + float fov = 60.0f; + float half_fov = fov * 0.5f * 3.14159f / 180.0f; + float aspect = 240.0f / 320.0f; + float near = 1.0f; + float far = 64.0f; + + angle += 0.01f; + if (angle > 6.28f) angle -= 6.28f; + + for (int x = 0; x < 240; x++) { + float ray_angle = (x - 120) * (half_fov / 120.0f) + angle; + for (int z = 0; z < 64; z++) { + float depth = z + near; + float proj_x = (x - 120) * aspect / (depth * tan(half_fov)); + float proj_y = spectrum_data[x][z] / 255.0f * 100.0f / (depth * tan(half_fov)); + int screen_x = (proj_x + 1.0f) * 120; + int screen_y = (1.0f - proj_y) * 160; + + if (screen_x >= 0 && screen_x < 240 && screen_y >= 0 && screen_y < 320) { + int height = spectrum_data[x][z] * 200 / (z + 1); + int top = 160 - height / 2; + int bottom = 160 + height / 2; + if (top < 0) top = 0; + if (bottom > 320) bottom = 320; + + uint8_t r = spectrum_data[x][z]; + uint8_t g = 255 - spectrum_data[x][z]; + uint8_t b = 0; + painter.fill_rectangle({screen_x, top, 1, bottom - top}, Color(r, g, b)); + } + } + } +} + +void RF3DView::paint(Painter& painter) { + if (!initialized) { + initialized = true; + baseband::run_image(portapack::spi_flash::image_tag_nfm_audio); + start(); + } + render_3d_waterfall(painter); +} + +void RF3DView::frame_sync() { + if (running) { + update_spectrum(); + set_dirty(); + } +} + +} // namespace ui::external_app::rf3d \ No newline at end of file diff --git a/firmware/application/external/rf3d/ui_rf3d.hpp b/firmware/application/external/rf3d/ui_rf3d.hpp new file mode 100644 index 000000000..55ac47518 --- /dev/null +++ b/firmware/application/external/rf3d/ui_rf3d.hpp @@ -0,0 +1,45 @@ +#ifndef __UI_RF3D_HPP__ +#define __UI_RF3D_HPP__ + +#include "ui_widget.hpp" +#include "ui_navigation.hpp" +#include "message.hpp" +#include "baseband_api.hpp" +#include "portapack.hpp" + +namespace ui::external_app::rf3d { + +class RF3DView : public View { +public: + RF3DView(NavigationView& nav); + void on_show() override; + std::string title() const override { return "RF3D"; } + void focus() override { dummy.focus(); } + void paint(Painter& painter) override; + void frame_sync(); + +private: + NavigationView& nav_; + Button dummy{{240, 0, 0, 0}, ""}; + bool initialized{false}; + std::vector> spectrum_data; + uint32_t sampling_rate{24000}; + double angle{0.0}; + bool running{false}; + + void start(); + void stop(); + void update_spectrum(); + void render_3d_waterfall(Painter& painter); + + MessageHandlerRegistration message_handler_frame_sync{ + Message::ID::DisplayFrameSync, + [this](const Message* const) { + this->frame_sync(); + } + }; +}; + +} // namespace ui::external_app::rf3d + +#endif /*__UI_3D_RF_HPP__*/ \ No newline at end of file