diff --git a/firmware/application/ui_geomap.hpp b/firmware/application/ui_geomap.hpp index 4608742c..cd105ac3 100644 --- a/firmware/application/ui_geomap.hpp +++ b/firmware/application/ui_geomap.hpp @@ -136,7 +136,7 @@ public: float lat, float lon, float angle, - const std::function on_close + const std::function on_close = nullptr ); GeoMapView(NavigationView& nav, int32_t altitude, diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index a31edb48..8abdb841 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -297,7 +297,7 @@ ReceiversMenuView::ReceiversMenuView(NavigationView& nav) { { "POCSAG", ui::Color::green(), &bitmap_icon_pocsag, [&nav](){ nav.push(); } }, { "SIGFOX", ui::Color::grey(), &bitmap_icon_fox, [&nav](){ nav.push(); } }, // SIGFRXView { "LoRa", ui::Color::grey(), nullptr, [&nav](){ nav.push(); } }, - { "Radiosondes", ui::Color::red(), &bitmap_icon_sonde, [&nav](){ nav.push(); } }, + { "Radiosondes", ui::Color::yellow(),&bitmap_icon_sonde, [&nav](){ nav.push(); } }, { "SSTV", ui::Color::grey(), &bitmap_icon_sstv, [&nav](){ nav.push(); } }, { "TPMS: Cars", ui::Color::green(), &bitmap_icon_tpms, [&nav](){ nav.push(); } }, }); diff --git a/firmware/application/ui_sonde.cpp b/firmware/application/ui_sonde.cpp index 92720dc0..33a7132c 100644 --- a/firmware/application/ui_sonde.cpp +++ b/firmware/application/ui_sonde.cpp @@ -42,16 +42,22 @@ SondeView::SondeView(NavigationView& nav) { baseband::run_image(portapack::spi_flash::image_tag_sonde); add_children({ - &field_frequency, - &text_debug, + &labels, &field_rf_amp, &field_lna, &field_vga, - &rssi + &rssi, + &field_frequency, + &text_debug_a, + &text_debug_b, + &text_signature, + &text_sats, + &geopos, + &button_see_map }); - field_frequency.set_value(receiver_model.tuning_frequency()); - field_frequency.set_step(receiver_model.frequency_step()); + field_frequency.set_value(target_frequency_); + field_frequency.set_step(10000); field_frequency.on_change = [this](rf::Frequency f) { set_target_frequency(f); field_frequency.set_value(f); @@ -65,8 +71,10 @@ SondeView::SondeView(NavigationView& nav) { }; }; + geopos.set_read_only(true); + radio::enable({ - receiver_model.tuning_frequency(), + tuning_frequency(), sampling_rate, baseband_bandwidth, rf::Direction::Receive, @@ -74,9 +82,16 @@ SondeView::SondeView(NavigationView& nav) { static_cast(receiver_model.lna()), static_cast(receiver_model.vga()), }); - - set_target_frequency(402000000); + button_see_map.on_select = [this, &nav](Button&) { + nav.push( + "", + altitude, + latitude, + longitude, + 0); + }; + /*logger = std::make_unique(); if( logger ) { logger->append(u"sonde.txt"); @@ -92,19 +107,28 @@ void SondeView::focus() { field_vga.focus(); } -void SondeView::on_packet(const baseband::Packet& packet) { - std::string bin_string; +void SondeView::on_packet(const sonde::Packet& packet) { + const auto hex_formatted = packet.symbols_formatted(); - for (size_t i = 0; i < 30; i++) { - bin_string += to_string_dec_uint(packet[i]); - } + text_debug_a.set(hex_formatted.data.substr(0, 30)); + text_debug_b.set(hex_formatted.errors.substr(0, 30)); - text_debug.set(bin_string); + text_signature.set(packet.signature()); + + text_sats.set(to_string_dec_uint(packet.visible_sats())); + + altitude = packet.GPS_altitude(); + latitude = packet.GPS_latitude(); + longitude = packet.GPS_longitude(); + + geopos.set_altitude(altitude); + geopos.set_lat(latitude); + geopos.set_lon(longitude); /*if( logger ) { logger->on_packet(packet); }*/ - + /*if( packet.crc_ok() ) { }*/ } diff --git a/firmware/application/ui_sonde.hpp b/firmware/application/ui_sonde.hpp index b00b6336..c0863251 100644 --- a/firmware/application/ui_sonde.hpp +++ b/firmware/application/ui_sonde.hpp @@ -27,6 +27,7 @@ #include "ui_receiver.hpp" #include "ui_rssi.hpp" #include "ui_channel.hpp" +#include "ui_geomap.hpp" #include "event_m0.hpp" @@ -67,7 +68,16 @@ public: private: //std::unique_ptr logger { }; - uint32_t target_frequency_ { }; + uint32_t target_frequency_ { 402000000 }; + 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() }, + }; FrequencyField field_frequency { { 0 * 8, 0 * 8 }, @@ -88,23 +98,44 @@ private: { 21 * 8, 0, 6 * 8, 4 }, }; - Text text_debug { - { 0, 32, 240, 16 }, + Text text_debug_a { + { 0, 2 * 16, 240, 16 }, "Waiting for frame..." }; + Text text_debug_b { + { 0, 3 * 16, 240, 16 }, + "Waiting for frame..." + }; + + Text text_signature { + { 13 * 8, 5 * 16, 240, 16 }, + "..." + }; + Text text_sats { + { 13 * 8, 6 * 16, 240, 16 }, + "..." + }; + + GeoPos geopos { + { 0, 8 * 16 } + }; + + Button button_see_map { + { 8 * 8, 12 * 16, 14 * 8, 3 * 16 }, + "See on map" + }; MessageHandlerRegistration message_handler_packet { Message::ID::SondePacket, [this](Message* const p) { const auto message = static_cast(p); - //const sonde::Packet packet { message->type, message->packet }; - //this->on_packet(packet); - this->on_packet(message->packet); + const sonde::Packet packet { message->packet, message->type }; + this->on_packet(packet); } }; //void on_packet(const sonde::Packet& packet); - void on_packet(const baseband::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.cpp b/firmware/baseband/proc_sonde.cpp index 9743beb6..35e8791e 100644 --- a/firmware/baseband/proc_sonde.cpp +++ b/firmware/baseband/proc_sonde.cpp @@ -23,7 +23,6 @@ #include "proc_sonde.hpp" #include "dsp_fir_taps.hpp" -//#include "portapack_shared_memory.hpp" #include "event_m4.hpp" diff --git a/firmware/baseband/proc_sonde.hpp b/firmware/baseband/proc_sonde.hpp index e5dba34e..40b8f8db 100644 --- a/firmware/baseband/proc_sonde.hpp +++ b/firmware/baseband/proc_sonde.hpp @@ -28,8 +28,8 @@ * Since the applied shift in ui_sonde.cpp is -fs/4 = -2457600/4 = -614400Hz to avoid the DC spike, the FSK signal ends up being * shifted by 614400 / 8 / 8 = 9600Hz. So decim_1_out should look like this: * - * _______________|__/'\__________ - * -C A B C + * _______________|______/'\______ + * -C A B C * * A is the DC spike at 0Hz * B is the FSK signal shifted right at 9600Hz @@ -40,7 +40,7 @@ * ______________/'\______________ * -C D C * - * A should have been filtered off ? + * Anything unwanted (like A) should have been filtered off * D is B around 0Hz now * * Then the clock_recovery function should be happy :) @@ -113,18 +113,17 @@ private: dsp::decimate::FIRC16xR16x32Decim8 decim_1 { }; dsp::matched_filter::MatchedFilter mf { baseband::ais::square_taps_38k4_1t_p, 2 }; - // AIS: 19200, 9600 clock_recovery::ClockRecovery clock_recovery_fsk_4800 { - 19200, 4800, { 0.0555f }, + 19200, 9600, { 0.0555f }, [this](const float raw_symbol) { const uint_fast8_t sliced_symbol = (raw_symbol >= 0.0f) ? 1 : 0; this->packet_builder_fsk_4800_M10.execute(sliced_symbol); } }; PacketBuilder packet_builder_fsk_4800_M10 { - { 0b11001100110011001010011001001100, 32, 1 }, + { 0b00110011001100110101100110110011, 32, 1 }, { }, - { 50 }, // { 102 * 8 }, + { 102 * 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/manchester.cpp b/firmware/common/manchester.cpp index 8c02ad20..bc14c0c1 100644 --- a/firmware/common/manchester.cpp +++ b/firmware/common/manchester.cpp @@ -23,6 +23,10 @@ #include "string_format.hpp" +size_t ManchesterBase::symbols_count() const { + return packet.size() / 2; +} + DecodedSymbol ManchesterDecoder::operator[](const size_t index) const { const size_t encoded_index = index * 2; if( (encoded_index + 1) < packet.size() ) { @@ -34,12 +38,19 @@ DecodedSymbol ManchesterDecoder::operator[](const size_t index) const { } } -size_t ManchesterDecoder::symbols_count() const { - return packet.size() / 2; +DecodedSymbol BiphaseMDecoder::operator[](const size_t index) const { + const size_t encoded_index = index * 2; + if( (encoded_index + 1) < packet.size() ) { + const auto value = packet[encoded_index + 0] != packet[encoded_index + 1]; + const uint_fast8_t error = encoded_index ? (packet[encoded_index - 1] == packet[encoded_index + 0]) : 0; + return { value, error }; + } else { + return { 0, 1 }; + } } FormattedSymbols format_symbols( - const ManchesterDecoder& decoder + const ManchesterBase& decoder ) { const size_t payload_length_decoded = decoder.symbols_count(); const size_t payload_length_hex_characters = (payload_length_decoded + 3) / 4; diff --git a/firmware/common/manchester.hpp b/firmware/common/manchester.hpp index ca2f1e43..91bd1f19 100644 --- a/firmware/common/manchester.hpp +++ b/firmware/common/manchester.hpp @@ -34,25 +34,39 @@ struct DecodedSymbol { uint_fast8_t error; }; -class ManchesterDecoder { +class ManchesterBase { public: - constexpr ManchesterDecoder( + constexpr ManchesterBase( const baseband::Packet& packet, const size_t sense = 0 ) : packet { packet }, sense { sense } { } + + virtual DecodedSymbol operator[](const size_t index) const = 0; - DecodedSymbol operator[](const size_t index) const; - - size_t symbols_count() const; - -private: + virtual size_t symbols_count() const; + + virtual ~ManchesterBase() { }; + +protected: const baseband::Packet& packet; const size_t sense; }; +class ManchesterDecoder : public ManchesterBase { +public: + using ManchesterBase::ManchesterBase; + DecodedSymbol operator[](const size_t index) const; +}; + +class BiphaseMDecoder : public ManchesterBase { +public: + using ManchesterBase::ManchesterBase; + DecodedSymbol operator[](const size_t index) const; +}; + template T operator|(const T& l, const DecodedSymbol& r) { return l | r.value; @@ -64,7 +78,7 @@ struct FormattedSymbols { }; FormattedSymbols format_symbols( - const ManchesterDecoder& decoder + const ManchesterBase& decoder ); void manchester_encode(uint8_t * dest, uint8_t * src, const size_t length, const size_t sense = 0); diff --git a/firmware/common/sonde_packet.cpp b/firmware/common/sonde_packet.cpp index d4e1f097..e3cf2fbe 100644 --- a/firmware/common/sonde_packet.cpp +++ b/firmware/common/sonde_packet.cpp @@ -42,6 +42,33 @@ 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; +} + +float Packet::GPS_latitude() const { + return reader_.read(14 * 8, 32) / ((1ULL << 32) / 360.0); +} + +float Packet::GPS_longitude() const { + return reader_.read(18 * 8, 32) / ((1ULL << 32) / 360.0); +} + +std::string Packet::signature() const { + const auto header = reader_.read(0, 24); + + if (header == 0x649F20) + return "M10"; + else if (header == 0x648F20) + return "M2K2"; + else + return symbols_formatted().data.substr(0, 6); +} + SN Packet::serial_number() const { if (type() == Type::M10) { // See https://github.com/rs1729/RS/blob/master/m10/m10x.c line 606 diff --git a/firmware/common/sonde_packet.hpp b/firmware/common/sonde_packet.hpp index 73612a0f..acd5ef4d 100644 --- a/firmware/common/sonde_packet.hpp +++ b/firmware/common/sonde_packet.hpp @@ -42,8 +42,8 @@ public: }; Packet( - const Type type, - const baseband::Packet& packet + const baseband::Packet& packet, + const Type type ) : packet_ { packet }, decoder_ { packet_ }, reader_ { decoder_ }, @@ -59,16 +59,21 @@ public: Type type() const; SN serial_number() const; + uint32_t visible_sats() const; + uint32_t GPS_altitude() const; + float GPS_latitude() const; + float GPS_longitude() const; + std::string signature() const; FormattedSymbols symbols_formatted() const; bool crc_ok() const; private: - using Reader = FieldReader; + using Reader = FieldReader; const baseband::Packet packet_; - const ManchesterDecoder decoder_; + const BiphaseMDecoder decoder_; const Reader reader_; const Type type_; diff --git a/firmware/portapack-h1-havoc.bin b/firmware/portapack-h1-havoc.bin index fc5a836c..77fb313a 100644 Binary files a/firmware/portapack-h1-havoc.bin and b/firmware/portapack-h1-havoc.bin differ