diff --git a/firmware/application/ui_sonde.cpp b/firmware/application/ui_sonde.cpp index 3854373c..16506b3f 100644 --- a/firmware/application/ui_sonde.cpp +++ b/firmware/application/ui_sonde.cpp @@ -112,7 +112,7 @@ void SondeView::focus() { void SondeView::on_packet(const sonde::Packet& packet) { //const auto hex_formatted = packet.symbols_formatted(); - text_signature.set(packet.signature()); + text_signature.set(packet.type_string()); text_serial.set(packet.serial_number()); text_voltage.set(unit_auto_scale(packet.battery_voltage(), 2, 3) + "V"); diff --git a/firmware/application/ui_touchtunes.cpp b/firmware/application/ui_touchtunes.cpp index 15fe2ae6..2c9a1ec5 100644 --- a/firmware/application/ui_touchtunes.cpp +++ b/firmware/application/ui_touchtunes.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. * Copyright (C) 2017 Furrtek + * Copyright (C) 2017 NotPike (notpike@horsefucker.org) * * This file is part of PortaPack. * diff --git a/firmware/application/ui_touchtunes.hpp b/firmware/application/ui_touchtunes.hpp index 610d4b20..0aa36f51 100644 --- a/firmware/application/ui_touchtunes.hpp +++ b/firmware/application/ui_touchtunes.hpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. * Copyright (C) 2017 Furrtek + * Copyright (C) 2017 NotPike (notpike@horsefucker.org) * * This file is part of PortaPack. * diff --git a/firmware/baseband/proc_sonde.cpp b/firmware/baseband/proc_sonde.cpp index 35e8791e..f670dd36 100644 --- a/firmware/baseband/proc_sonde.cpp +++ b/firmware/baseband/proc_sonde.cpp @@ -41,8 +41,9 @@ void SondeProcessor::execute(const buffer_c8_t& buffer) { /* 38.4kHz, 32 samples */ feed_channel_stats(decimator_out); - for(size_t i=0; i clock_recovery_fsk_4800 { + // Actually 4800bits/s but the Manchester coding doubles the symbol rate + clock_recovery::ClockRecovery clock_recovery_fsk_9600 { 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); + this->packet_builder_fsk_9600_Meteomodem.execute(sliced_symbol); } }; - PacketBuilder packet_builder_fsk_4800_M10 { + PacketBuilder packet_builder_fsk_9600_Meteomodem { { 0b00110011001100110101100110110011, 32, 1 }, { }, { 88 * 2 * 8 }, [this](const baseband::Packet& packet) { - const SondePacketMessage message { sonde::Packet::Type::M10, packet }; + const SondePacketMessage message { sonde::Packet::Type::Meteomodem_unknown, packet }; + shared_memory.application_queue.push(message); + } + }; + + clock_recovery::ClockRecovery clock_recovery_fsk_4800 { + 19200, 4800, { 0.0555f }, + [this](const float raw_symbol) { + const uint_fast8_t sliced_symbol = (raw_symbol >= 0.0f) ? 1 : 0; + this->packet_builder_fsk_4800_Vaisala.execute(sliced_symbol); + } + }; + PacketBuilder packet_builder_fsk_4800_Vaisala { + { 0b00001000011011010101001110001000, 32, 1 }, + { }, + { 320 * 8 }, + [this](const baseband::Packet& packet) { + const SondePacketMessage message { sonde::Packet::Type::Vaisala_RS41_SG, packet }; shared_memory.application_queue.push(message); } }; diff --git a/firmware/common/baseband_packet.hpp b/firmware/common/baseband_packet.hpp index eb9fd9fb..c947fac4 100644 --- a/firmware/common/baseband_packet.hpp +++ b/firmware/common/baseband_packet.hpp @@ -62,7 +62,7 @@ public: } private: - std::bitset<1408> data { }; + std::bitset<2560> data { }; Timestamp timestamp_ { }; size_t count { 0 }; }; diff --git a/firmware/common/sonde_packet.cpp b/firmware/common/sonde_packet.cpp index 5eba330c..eb23508c 100644 --- a/firmware/common/sonde_packet.cpp +++ b/firmware/common/sonde_packet.cpp @@ -25,12 +25,31 @@ namespace sonde { +Packet::Packet( + const baseband::Packet& packet, + const Type type +) : packet_ { packet }, + decoder_ { packet_ }, + reader_bi_m { decoder_ }, + type_ { type } +{ + if (type_ == Type::Meteomodem_unknown) { + // Right now we're just sure that the sync is from a Meteomodem sonde, differentiate between models now + const uint32_t id_byte = reader_bi_m.read(1 * 8, 16); + + if (id_byte == 0x649F) + type_ = Type::Meteomodem_M10; + else if (id_byte == 0x648F) + type_ = Type::Meteomodem_M2K2; + } +} + size_t Packet::length() const { return decoder_.symbols_count(); } bool Packet::is_valid() const { - return true; + return true; // TODO } Timestamp Packet::received_at() const { @@ -41,50 +60,75 @@ Packet::Type Packet::type() const { return type_; } +/*uint8_t Packet::vaisala_descramble(const uint32_t pos) { + return reader_raw.read(pos * 8, 8) ^ vaisala_mask[pos & 63]; +};*/ + uint32_t Packet::GPS_altitude() const { - return (reader_.read(22 * 8, 32) / 1000) - 48; + if ((type_ == Type::Meteomodem_M10) || (type_ == Type::Meteomodem_M2K2)) + return (reader_bi_m.read(22 * 8, 32) / 1000) - 48; + else if (type_ == Type::Vaisala_RS41_SG) { + /*uint32_t altitude_ecef = 0; + for (uint32_t i = 0; i < 4; i++) + altitude_ecef = (altitude_ecef << 8) + vaisala_descramble(0x11C + i);*/ + // TODO: and a bunch of maths (see ecef2elli() from RS1729) + return 0; + } else + return 0; // Unknown } float Packet::GPS_latitude() const { - return reader_.read(14 * 8, 32) / ((1ULL << 32) / 360.0); + if ((type_ == Type::Meteomodem_M10) || (type_ == Type::Meteomodem_M2K2)) + return reader_bi_m.read(14 * 8, 32) / ((1ULL << 32) / 360.0); + //else if (type_ == Type::Vaisala_RS41_SG) + // return vaisala_descramble(); + else + return 0; // Unknown } float Packet::GPS_longitude() const { - return reader_.read(18 * 8, 32) / ((1ULL << 32) / 360.0); + if ((type_ == Type::Meteomodem_M10) || (type_ == Type::Meteomodem_M2K2)) + return reader_bi_m.read(18 * 8, 32) / ((1ULL << 32) / 360.0); + else + return 0; // Unknown } uint32_t Packet::battery_voltage() const { - return (reader_.read(69 * 8, 8) + (reader_.read(70 * 8, 8) << 8)) * 1000 / 150; + if (type_ == Type::Meteomodem_M10) + return (reader_bi_m.read(69 * 8, 8) + (reader_bi_m.read(70 * 8, 8) << 8)) * 1000 / 150; + else if (type_ == Type::Meteomodem_M2K2) + return reader_bi_m.read(69 * 8, 8) * 66; // Actually 65.8 + else + return 0; // Unknown } -std::string Packet::signature() const { - const auto header = reader_.read(0, 24); - - if (header == 0x649F20) - return "M10"; - else if ((header == 0x648F20) || (header == 0x648F23)) - return "M2K2"; - else - return "0x" + symbols_formatted().data.substr(0, 6); +std::string Packet::type_string() const { + switch (type_) { + case Type::Unknown: return "Unknown"; + case Type::Meteomodem_unknown: return "Meteomodem ???"; + case Type::Meteomodem_M10: return "Meteomodem M10"; + case Type::Meteomodem_M2K2: return "Meteomodem M2K2"; + case Type::Vaisala_RS41_SG: return "Vaisala RS41-SG"; + default: return "? 0x" + symbols_formatted().data.substr(0, 6); + } } std::string Packet::serial_number() const { - if (type() == Type::M10) { + if (type() == Type::Meteomodem_M10) { // See https://github.com/rs1729/RS/blob/master/m10/m10x.c line 606 // 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 to_string_hex(reader_bi_m.read(93 * 8 + 16, 4), 1) + + to_string_dec_uint(reader_bi_m.read(93 * 8 + 20, 4), 2, '0') + " " + + to_string_hex(reader_bi_m.read(93 * 8 + 4, 4), 1) + " " + + to_string_dec_uint(reader_bi_m.read(93 * 8 + 24, 3), 1) + + to_string_dec_uint(reader_bi_m.read(93 * 8 + 27, 13), 4, '0'); - } - - return 0; + } else + return 0; } FormattedSymbols Packet::symbols_formatted() const { @@ -93,8 +137,8 @@ FormattedSymbols Packet::symbols_formatted() const { bool Packet::crc_ok() const { switch(type()) { - case Type::M10: return crc_ok_M10(); - default: return false; + case Type::Meteomodem_M10: return crc_ok_M10(); + default: return false; } } diff --git a/firmware/common/sonde_packet.hpp b/firmware/common/sonde_packet.hpp index d9658a54..4ecbc08a 100644 --- a/firmware/common/sonde_packet.hpp +++ b/firmware/common/sonde_packet.hpp @@ -36,18 +36,13 @@ class Packet { public: enum class Type : uint32_t { Unknown = 0, - M10 = 1, + Meteomodem_unknown = 1, + Meteomodem_M10 = 2, + Meteomodem_M2K2 = 3, + Vaisala_RS41_SG = 4, }; - - Packet( - const baseband::Packet& packet, - const Type type - ) : packet_ { packet }, - decoder_ { packet_ }, - reader_ { decoder_ }, - type_ { type } - { - } + + Packet(const baseband::Packet& packet, const Type type); size_t length() const; @@ -56,24 +51,37 @@ public: Timestamp received_at() const; Type type() const; + std::string type_string() const; + std::string serial_number() const; + uint32_t battery_voltage() 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; bool crc_ok() const; private: - using Reader = FieldReader; + static constexpr uint8_t vaisala_mask[64] = { + 0x96, 0x83, 0x3E, 0x51, 0xB1, 0x49, 0x08, 0x98, + 0x32, 0x05, 0x59, 0x0E, 0xF9, 0x44, 0xC6, 0x26, + 0x21, 0x60, 0xC2, 0xEA, 0x79, 0x5D, 0x6D, 0xA1, + 0x54, 0x69, 0x47, 0x0C, 0xDC, 0xE8, 0x5C, 0xF1, + 0xF7, 0x76, 0x82, 0x7F, 0x07, 0x99, 0xA2, 0x2C, + 0x93, 0x7C, 0x30, 0x63, 0xF5, 0x10, 0x2E, 0x61, + 0xD0, 0xBC, 0xB4, 0xB6, 0x06, 0xAA, 0xF4, 0x23, + 0x78, 0x6E, 0x3B, 0xAE, 0xBF, 0x7B, 0x4C, 0xC1 + }; + + //uint8_t vaisala_descramble(const uint32_t pos); const baseband::Packet packet_; const BiphaseMDecoder decoder_; - const Reader reader_; - const Type type_; + const FieldReader reader_bi_m; + Type type_; bool crc_ok_M10() const; }; diff --git a/firmware/portapack-h1-havoc.bin b/firmware/portapack-h1-havoc.bin index fe122fd2..dbb88114 100644 Binary files a/firmware/portapack-h1-havoc.bin and b/firmware/portapack-h1-havoc.bin differ