From 6ff8249a4f4710960c6e7cb2187f2e4276983866 Mon Sep 17 00:00:00 2001 From: furrtek Date: Sat, 28 Oct 2017 19:16:06 +0200 Subject: [PATCH] Added logging, serial number and battery voltage display to radiosonde RX Added decimal degrees display to geopos widget --- firmware/application/ui_geomap.cpp | 34 ++++++++++++++++++------ firmware/application/ui_geomap.hpp | 28 +++++++++++++------- firmware/application/ui_sonde.cpp | 40 ++++++++++++++-------------- firmware/application/ui_sonde.hpp | 42 ++++++++++++++---------------- firmware/baseband/proc_sonde.hpp | 2 +- firmware/common/sonde_packet.cpp | 34 ++++++++++++++---------- firmware/common/sonde_packet.hpp | 6 ++--- 7 files changed, 106 insertions(+), 80 deletions(-) diff --git a/firmware/application/ui_geomap.cpp b/firmware/application/ui_geomap.cpp index a81527c2..27a1b106 100644 --- a/firmware/application/ui_geomap.cpp +++ b/firmware/application/ui_geomap.cpp @@ -29,12 +29,14 @@ using namespace portapack; +#include "string_format.hpp" + namespace ui { GeoPos::GeoPos( const Point pos ) { - set_parent_rect({pos, {30 * 8, 3 * 16}}); + set_parent_rect({pos, { 30 * 8, 3 * 16 }}); add_children({ &labels_position, @@ -42,9 +44,11 @@ GeoPos::GeoPos( &field_lat_degrees, &field_lat_minutes, &field_lat_seconds, + &text_lat_decimal, &field_lon_degrees, &field_lon_minutes, - &field_lon_seconds + &field_lon_seconds, + &text_lon_decimal }); // Defaults @@ -53,8 +57,22 @@ GeoPos::GeoPos( set_lon(0); const auto changed_fn = [this](int32_t) { + float lat_value = lat(); + float lon_value = lon(); + double integer_part; + double fractional_part; + + fractional_part = modf(lat_value, &integer_part) * 100000; + if (fractional_part < 0) + fractional_part = -fractional_part; + text_lat_decimal.set(to_string_dec_int(integer_part) + "." + to_string_dec_uint(fractional_part, 5)); + fractional_part = modf(lon_value, &integer_part) * 100000; + if (fractional_part < 0) + fractional_part = -fractional_part; + text_lon_decimal.set(to_string_dec_int(integer_part) + "." + to_string_dec_uint(fractional_part, 5)); + if (on_change && report_change) - on_change(altitude(), lat(), lon()); + on_change(altitude(), lat_value, lon_value); }; field_altitude.on_change = changed_fn; @@ -66,6 +84,11 @@ GeoPos::GeoPos( field_lon_seconds.on_change = changed_fn; } +void GeoPos::set_read_only(bool v) { + for(auto child : children_) + child->set_focusable(!v); +} + // Stupid hack to avoid an event loop void GeoPos::set_report_change(bool v) { report_change = v; @@ -103,10 +126,6 @@ int32_t GeoPos::altitude() { return field_altitude.value(); }; -void GeoPos::set_read_only(bool v) { - set_focusable(~v); -}; - GeoMap::GeoMap( Rect parent_rect ) : Widget { parent_rect } @@ -117,7 +136,6 @@ GeoMap::GeoMap( void GeoMap::paint(Painter& painter) { Coord line; std::array map_line_buffer; - //Color border; const auto r = screen_rect(); // Ony redraw map if it moved by at least 1 pixel diff --git a/firmware/application/ui_geomap.hpp b/firmware/application/ui_geomap.hpp index cd105ac3..df994006 100644 --- a/firmware/application/ui_geomap.hpp +++ b/firmware/application/ui_geomap.hpp @@ -60,13 +60,13 @@ private: bool report_change { true }; Labels labels_position { - { { 2 * 8, 0 * 16 }, "Alt: feet", Color::light_grey() }, - { { 2 * 8, 1 * 16 }, "Lat: * ' \"", Color::light_grey() }, // No ° symbol in 8x16 font - { { 2 * 8, 2 * 16 }, "Lon: * ' \"", Color::light_grey() }, + { { 1 * 8, 0 * 16 }, "Alt: feet", Color::light_grey() }, + { { 1 * 8, 1 * 16 }, "Lat: * ' \"", Color::light_grey() }, // No ° symbol in 8x16 font + { { 1 * 8, 2 * 16 }, "Lon: * ' \"", Color::light_grey() }, }; NumberField field_altitude { - { 7 * 8, 0 * 16 }, + { 6 * 8, 0 * 16 }, 5, { -1000, 50000 }, 250, @@ -74,23 +74,31 @@ private: }; NumberField field_lat_degrees { - { 7 * 8, 1 * 16 }, 4, { -90, 90 }, 1, ' ' + { 5 * 8, 1 * 16 }, 4, { -90, 90 }, 1, ' ' }; NumberField field_lat_minutes { - { 12 * 8, 1 * 16 }, 2, { 0, 59 }, 1, ' ' + { 10 * 8, 1 * 16 }, 2, { 0, 59 }, 1, ' ' }; NumberField field_lat_seconds { - { 15 * 8, 1 * 16 }, 2, { 0, 59 }, 1, ' ' + { 13 * 8, 1 * 16 }, 2, { 0, 59 }, 1, ' ' + }; + Text text_lat_decimal { + { 17 * 8, 1 * 16, 13 * 8, 1 * 16 }, + "" }; NumberField field_lon_degrees { - { 7 * 8, 2 * 16 }, 4, { -180, 180 }, 1, ' ' + { 5 * 8, 2 * 16 }, 4, { -180, 180 }, 1, ' ' }; NumberField field_lon_minutes { - { 12 * 8, 2 * 16 }, 2, { 0, 59 }, 1, ' ' + { 10 * 8, 2 * 16 }, 2, { 0, 59 }, 1, ' ' }; NumberField field_lon_seconds { - { 15 * 8, 2 * 16 }, 2, { 0, 59 }, 1, ' ' + { 13 * 8, 2 * 16 }, 2, { 0, 59 }, 1, ' ' + }; + Text text_lon_decimal { + { 17 * 8, 2 * 16, 13 * 8, 1 * 16 }, + "" }; }; diff --git a/firmware/application/ui_sonde.cpp b/firmware/application/ui_sonde.cpp index 33a7132c..b02b9fcc 100644 --- a/firmware/application/ui_sonde.cpp +++ b/firmware/application/ui_sonde.cpp @@ -21,20 +21,17 @@ */ #include "ui_sonde.hpp" - #include "baseband_api.hpp" #include "portapack.hpp" using namespace portapack; -//#include "manchester.hpp" - #include "string_format.hpp" -/*void SondeLogger::on_packet(const sonde::Packet& packet) { +void SondeLogger::on_packet(const sonde::Packet& packet) { const auto formatted = packet.symbols_formatted(); - log_file.write_entry(packet.received_at(), formatted.data + "/" + formatted.errors); -}*/ + log_file.write_entry(packet.received_at(), formatted.data); +} namespace ui { @@ -43,15 +40,15 @@ SondeView::SondeView(NavigationView& nav) { add_children({ &labels, + &field_frequency, &field_rf_amp, &field_lna, &field_vga, &rssi, - &field_frequency, - &text_debug_a, - &text_debug_b, + &check_log, &text_signature, - &text_sats, + &text_serial, + &text_voltage, &geopos, &button_see_map }); @@ -73,6 +70,10 @@ SondeView::SondeView(NavigationView& nav) { geopos.set_read_only(true); + check_log.on_select = [this](Checkbox&, bool v) { + logging = v; + }; + radio::enable({ tuning_frequency(), sampling_rate, @@ -92,10 +93,10 @@ SondeView::SondeView(NavigationView& nav) { 0); }; - /*logger = std::make_unique(); - if( logger ) { + logger = std::make_unique(); + if (logger) logger->append(u"sonde.txt"); - }*/ + } SondeView::~SondeView() { @@ -108,14 +109,11 @@ void SondeView::focus() { } void SondeView::on_packet(const sonde::Packet& packet) { - const auto hex_formatted = packet.symbols_formatted(); - - text_debug_a.set(hex_formatted.data.substr(0, 30)); - text_debug_b.set(hex_formatted.errors.substr(0, 30)); + //const auto hex_formatted = packet.symbols_formatted(); text_signature.set(packet.signature()); - - text_sats.set(to_string_dec_uint(packet.visible_sats())); + text_serial.set(packet.serial_number()); + text_voltage.set(to_string_dec_uint(packet.battery_voltage()) + "mV"); altitude = packet.GPS_altitude(); latitude = packet.GPS_latitude(); @@ -125,9 +123,9 @@ void SondeView::on_packet(const sonde::Packet& packet) { geopos.set_lat(latitude); geopos.set_lon(longitude); - /*if( logger ) { + if (logger && logging) { logger->on_packet(packet); - }*/ + } /*if( packet.crc_ok() ) { }*/ diff --git a/firmware/application/ui_sonde.hpp b/firmware/application/ui_sonde.hpp index c0863251..d2630c8f 100644 --- a/firmware/application/ui_sonde.hpp +++ b/firmware/application/ui_sonde.hpp @@ -26,7 +26,6 @@ #include "ui_navigation.hpp" #include "ui_receiver.hpp" #include "ui_rssi.hpp" -#include "ui_channel.hpp" #include "ui_geomap.hpp" #include "event_m0.hpp" @@ -35,12 +34,10 @@ #include "sonde_packet.hpp" -#include "recent_entries.hpp" - #include #include -/*class SondeLogger { +class SondeLogger { public: Optional append(const std::filesystem::path& filename) { return log_file.append(filename); @@ -50,7 +47,7 @@ public: private: LogFile log_file { }; -};*/ +}; namespace ui { @@ -67,16 +64,17 @@ public: std::string title() const override { return "Radiosonde RX"; }; private: - //std::unique_ptr logger { }; + std::unique_ptr logger { }; uint32_t target_frequency_ { 402000000 }; + bool logging { false }; int32_t altitude { 0 }; float latitude { 0 }; float longitude { 0 }; Labels labels { - { { 3 * 8, 5 * 16 }, "Signature:", Color::light_grey() }, - { { 0 * 8, 6 * 16 }, "Visible sats:", Color::light_grey() }, - //{ { 4 * 8, 7 * 16 }, "Altitude:", Color::light_grey() }, + { { 0 * 8, 2 * 16 }, "Signature:", Color::light_grey() }, + { { 3 * 8, 3 * 16 }, "Serial:", Color::light_grey() }, + { { 4 * 8, 4 * 16 }, "Vbatt:", Color::light_grey() } }; FrequencyField field_frequency { @@ -98,30 +96,31 @@ private: { 21 * 8, 0, 6 * 8, 4 }, }; - Text text_debug_a { - { 0, 2 * 16, 240, 16 }, - "Waiting for frame..." - }; - Text text_debug_b { - { 0, 3 * 16, 240, 16 }, - "Waiting for frame..." + Checkbox check_log { + { 22 * 8, 2 * 16 + 8 }, + 3, + "Log" }; Text text_signature { - { 13 * 8, 5 * 16, 240, 16 }, + { 10 * 8, 2 * 16, 10 * 8, 16 }, "..." }; - Text text_sats { - { 13 * 8, 6 * 16, 240, 16 }, + Text text_serial { + { 10 * 8, 3 * 16, 11 * 8, 16 }, + "..." + }; + Text text_voltage { + { 10 * 8, 4 * 16, 10 * 8, 16 }, "..." }; GeoPos geopos { - { 0, 8 * 16 } + { 0, 6 * 16 } }; Button button_see_map { - { 8 * 8, 12 * 16, 14 * 8, 3 * 16 }, + { 8 * 8, 10 * 16, 14 * 8, 3 * 16 }, "See on map" }; @@ -134,7 +133,6 @@ private: } }; - //void on_packet(const sonde::Packet& packet); void on_packet(const sonde::Packet& packet); void set_target_frequency(const uint32_t new_value); uint32_t tuning_frequency() const; diff --git a/firmware/baseband/proc_sonde.hpp b/firmware/baseband/proc_sonde.hpp index 40b8f8db..9f6cca05 100644 --- a/firmware/baseband/proc_sonde.hpp +++ b/firmware/baseband/proc_sonde.hpp @@ -123,7 +123,7 @@ private: PacketBuilder packet_builder_fsk_4800_M10 { { 0b00110011001100110101100110110011, 32, 1 }, { }, - { 102 * 8 }, + { 88 * 2 * 8 }, [this](const baseband::Packet& packet) { const SondePacketMessage message { sonde::Packet::Type::M10, packet }; shared_memory.application_queue.push(message); diff --git a/firmware/common/sonde_packet.cpp b/firmware/common/sonde_packet.cpp index e3cf2fbe..088d8777 100644 --- a/firmware/common/sonde_packet.cpp +++ b/firmware/common/sonde_packet.cpp @@ -21,8 +21,7 @@ */ #include "sonde_packet.hpp" - -//#include "crc.hpp" +#include "string_format.hpp" namespace sonde { @@ -42,12 +41,8 @@ Packet::Type Packet::type() const { return type_; } -uint32_t Packet::visible_sats() const { - return reader_.read(30 * 8, 8); -} - uint32_t Packet::GPS_altitude() const { - return reader_.read(22 * 8, 32) / 1000; + return (reader_.read(22 * 8, 32) / 1000) - 48; } float Packet::GPS_latitude() const { @@ -58,6 +53,10 @@ float Packet::GPS_longitude() const { return reader_.read(18 * 8, 32) / ((1ULL << 32) / 360.0); } +uint32_t Packet::battery_voltage() const { + return (reader_.read(69 * 8, 8) + (reader_.read(70 * 8, 8) << 8)) * 1000 / 150; +} + std::string Packet::signature() const { const auto header = reader_.read(0, 24); @@ -66,18 +65,25 @@ std::string Packet::signature() const { else if (header == 0x648F20) return "M2K2"; else - return symbols_formatted().data.substr(0, 6); + return "0x" + symbols_formatted().data.substr(0, 6); } -SN Packet::serial_number() const { +std::string Packet::serial_number() const { if (type() == Type::M10) { // See https://github.com/rs1729/RS/blob/master/m10/m10x.c line 606 - return (reader_.read(2 * 8, 8) << 20) | - (reader_.read(0, 4) << 16) | - (reader_.read(4 * 8, 3) << 13) | - (reader_.read(4 * 8 + 3, 5) << 8) | - reader_.read(3 * 8, 8); + // Starting at byte #93: 00000000 11111111 22222222 33333333 44444444 + // CCCC AAAABBBB + // 44444444 33333333 + // DDDEEEEE EEEEEEEE + + return to_string_hex(reader_.read(93 * 8 + 16, 4), 1) + + to_string_dec_uint(reader_.read(93 * 8 + 20, 4), 2, '0') + " " + + to_string_hex(reader_.read(93 * 8 + 4, 4), 1) + " " + + to_string_dec_uint(reader_.read(93 * 8 + 24, 3), 1) + + to_string_dec_uint(reader_.read(93 * 8 + 27, 13), 4, '0'); + } + return 0; } diff --git a/firmware/common/sonde_packet.hpp b/firmware/common/sonde_packet.hpp index acd5ef4d..d9658a54 100644 --- a/firmware/common/sonde_packet.hpp +++ b/firmware/common/sonde_packet.hpp @@ -32,8 +32,6 @@ namespace sonde { -using SN = uint64_t; - class Packet { public: enum class Type : uint32_t { @@ -58,12 +56,12 @@ public: Timestamp received_at() const; Type type() const; - SN serial_number() const; - uint32_t visible_sats() const; + std::string serial_number() const; uint32_t GPS_altitude() const; float GPS_latitude() const; float GPS_longitude() const; std::string signature() const; + uint32_t battery_voltage() const; FormattedSymbols symbols_formatted() const;