From c522d3d8e49ceadf4e6f8aaeeb932f205d59058f Mon Sep 17 00:00:00 2001 From: Erwin Ried <1091420+eried@users.noreply.github.com> Date: Thu, 13 Aug 2020 23:11:36 +0200 Subject: [PATCH 1/4] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 47510f0f..a7d53270 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # PortaPack Mayhem -[![Build Status](https://travis-ci.com/eried/portapack-mayhem.svg?branch=master)](https://travis-ci.com/eried/portapack-mayhem) [![buddy pipeline](https://app.buddy.works/eried/portapack/pipelines/pipeline/252276/badge.svg?token=48cd59d53de0589a8fbe26bc751d77a59a011cf72581da049343879402991c34 "buddy pipeline")](https://app.buddy.works/eried/portapack/pipelines/pipeline/252276) [![CodeScene Code Health](https://codescene.io/projects/8381/status-badges/code-health)](https://codescene.io/projects/8381) [![GitHub All Releases](https://img.shields.io/github/downloads/eried/portapack-mayhem/total)](https://github.com/eried/portapack-mayhem/releases) [![GitHub Releases](https://img.shields.io/github/downloads/eried/portapack-mayhem/latest/total)](https://github.com/eried/portapack-mayhem/releases/latest) [![Docker Hub Pulls](https://img.shields.io/docker/pulls/eried/portapack.svg)](https://hub.docker.com/r/eried/portapack) [![Discord Chat](https://img.shields.io/discord/719669764804444213.svg)](https://discord.gg/tuwVMv3) [![Check bounties!](https://api.bountysource.com/badge/team?team_id=550206)](https://www.bountysource.com/teams/portapack-mayhem/issues) +[![Build Status](https://travis-ci.com/eried/portapack-mayhem.svg?branch=master)](https://travis-ci.com/eried/portapack-mayhem) [![buddy pipeline](https://app.buddy.works/eried/portapack/pipelines/pipeline/252276/badge.svg?token=48cd59d53de0589a8fbe26bc751d77a59a011cf72581da049343879402991c34 "buddy pipeline")](https://app.buddy.works/eried/portapack/pipelines/pipeline/252276) [![CodeScene Code Health](https://codescene.io/projects/8381/status-badges/code-health)](https://codescene.io/projects/8381) [![GitHub All Releases](https://img.shields.io/github/downloads/eried/portapack-mayhem/total)](https://github.com/eried/portapack-mayhem/releases) [![GitHub Releases](https://img.shields.io/github/downloads/eried/portapack-mayhem/latest/total)](https://github.com/eried/portapack-mayhem/releases/latest) [![Docker Hub Pulls](https://img.shields.io/docker/pulls/eried/portapack.svg)](https://hub.docker.com/r/eried/portapack) [![Discord Chat](https://img.shields.io/discord/719669764804444213.svg)](https://discord.gg/tuwVMv3) [![Check bounties!](https://img.shields.io/bountysource/team/portapack-mayhem/activity)](https://www.bountysource.com/teams/portapack-mayhem/issues) This is a fork of the [Havoc](https://github.com/furrtek/portapack-havoc/) firmware, which itself was a fork of the [PortaPack](https://github.com/sharebrained/portapack-hackrf) firmware, an add-on for the [HackRF](http://greatscottgadgets.com/hackrf/). A fork is a derivate, in this case one that has extra features and fixes when compared to the older versions. From 6eabd9f1bcfb5b90e98dc2692281895e8abdc3ae Mon Sep 17 00:00:00 2001 From: Erwin Ried <1091420+eried@users.noreply.github.com> Date: Thu, 13 Aug 2020 23:17:25 +0200 Subject: [PATCH 2/4] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a7d53270..6323efd9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # PortaPack Mayhem -[![Build Status](https://travis-ci.com/eried/portapack-mayhem.svg?branch=master)](https://travis-ci.com/eried/portapack-mayhem) [![buddy pipeline](https://app.buddy.works/eried/portapack/pipelines/pipeline/252276/badge.svg?token=48cd59d53de0589a8fbe26bc751d77a59a011cf72581da049343879402991c34 "buddy pipeline")](https://app.buddy.works/eried/portapack/pipelines/pipeline/252276) [![CodeScene Code Health](https://codescene.io/projects/8381/status-badges/code-health)](https://codescene.io/projects/8381) [![GitHub All Releases](https://img.shields.io/github/downloads/eried/portapack-mayhem/total)](https://github.com/eried/portapack-mayhem/releases) [![GitHub Releases](https://img.shields.io/github/downloads/eried/portapack-mayhem/latest/total)](https://github.com/eried/portapack-mayhem/releases/latest) [![Docker Hub Pulls](https://img.shields.io/docker/pulls/eried/portapack.svg)](https://hub.docker.com/r/eried/portapack) [![Discord Chat](https://img.shields.io/discord/719669764804444213.svg)](https://discord.gg/tuwVMv3) [![Check bounties!](https://img.shields.io/bountysource/team/portapack-mayhem/activity)](https://www.bountysource.com/teams/portapack-mayhem/issues) +[![Build Status](https://travis-ci.com/eried/portapack-mayhem.svg?branch=master)](https://travis-ci.com/eried/portapack-mayhem) [![buddy pipeline](https://app.buddy.works/eried/portapack/pipelines/pipeline/252276/badge.svg?token=48cd59d53de0589a8fbe26bc751d77a59a011cf72581da049343879402991c34 "buddy pipeline")](https://app.buddy.works/eried/portapack/pipelines/pipeline/252276) [![CodeScene Code Health](https://codescene.io/projects/8381/status-badges/code-health)](https://codescene.io/projects/8381) [![GitHub All Releases](https://img.shields.io/github/downloads/eried/portapack-mayhem/total)](https://github.com/eried/portapack-mayhem/releases) [![GitHub Releases](https://img.shields.io/github/downloads/eried/portapack-mayhem/latest/total)](https://github.com/eried/portapack-mayhem/releases/latest) [![Docker Hub Pulls](https://img.shields.io/docker/pulls/eried/portapack.svg)](https://hub.docker.com/r/eried/portapack) [![Discord Chat](https://img.shields.io/discord/719669764804444213.svg)](https://discord.gg/tuwVMv3) [![Check bounties!](https://img.shields.io/bountysource/team/portapack-mayhem/activity?color=%2333ccff&label=bountysource%20%28USD%29&style=plastic)](https://www.bountysource.com/teams/portapack-mayhem/issues) This is a fork of the [Havoc](https://github.com/furrtek/portapack-havoc/) firmware, which itself was a fork of the [PortaPack](https://github.com/sharebrained/portapack-hackrf) firmware, an add-on for the [HackRF](http://greatscottgadgets.com/hackrf/). A fork is a derivate, in this case one that has extra features and fixes when compared to the older versions. From c7b0fbc35914ded0236f6c5154238760dd80ab87 Mon Sep 17 00:00:00 2001 From: euquiq <31453004+euquiq@users.noreply.github.com> Date: Fri, 14 Aug 2020 15:51:12 -0300 Subject: [PATCH 3/4] Radiosonde-app-Vaisala-rs41-decoding Added the Vaisala RS41 data packet decoding. Changed the default freq from 402.0 to 402.7 Mhz, since it is more popular freq. Lowered the frequency stepping, so it is easier to fine-tune the exact freq center, if needed. Sonde's Serial ID is passed into the VIEW MAP, so now the sonde is labelled on the map. --- firmware/application/apps/ui_sonde.cpp | 27 +++-- firmware/application/apps/ui_sonde.hpp | 7 +- firmware/baseband/proc_sonde.hpp | 3 +- firmware/common/sonde_packet.cpp | 132 +++++++++++++++++++------ firmware/common/sonde_packet.hpp | 19 ++-- 5 files changed, 132 insertions(+), 56 deletions(-) diff --git a/firmware/application/apps/ui_sonde.cpp b/firmware/application/apps/ui_sonde.cpp index 16506b3f..e61139ac 100644 --- a/firmware/application/apps/ui_sonde.cpp +++ b/firmware/application/apps/ui_sonde.cpp @@ -54,7 +54,7 @@ SondeView::SondeView(NavigationView& nav) { }); field_frequency.set_value(target_frequency_); - field_frequency.set_step(10000); + field_frequency.set_step(500); //euquiq: was 10000, but we are using this for fine-tunning field_frequency.on_change = [this](rf::Frequency f) { set_target_frequency(f); field_frequency.set_value(f); @@ -86,12 +86,12 @@ SondeView::SondeView(NavigationView& nav) { button_see_map.on_select = [this, &nav](Button&) { nav.push( - "", - altitude, + sonde_id, + gps_info.alt, GeoPos::alt_unit::METERS, - latitude, - longitude, - 0); + gps_info.lat, + gps_info.lon, + 999); //set a dummy heading out of range to draw a cross...probably not ideal? }; logger = std::make_unique(); @@ -113,16 +113,15 @@ void SondeView::on_packet(const sonde::Packet& packet) { //const auto hex_formatted = packet.symbols_formatted(); text_signature.set(packet.type_string()); - text_serial.set(packet.serial_number()); + sonde_id = packet.serial_number(); //used also as tag on the geomap + text_serial.set(sonde_id); text_voltage.set(unit_auto_scale(packet.battery_voltage(), 2, 3) + "V"); + + gps_info = packet.get_GPS_data(); - altitude = packet.GPS_altitude(); - latitude = packet.GPS_latitude(); - longitude = packet.GPS_longitude(); - - geopos.set_altitude(altitude); - geopos.set_lat(latitude); - geopos.set_lon(longitude); + geopos.set_altitude(gps_info.alt); + geopos.set_lat(gps_info.lat); + geopos.set_lon(gps_info.lon); if (logger && logging) { logger->on_packet(packet); diff --git a/firmware/application/apps/ui_sonde.hpp b/firmware/application/apps/ui_sonde.hpp index 5dc7fe86..9e7743b1 100644 --- a/firmware/application/apps/ui_sonde.hpp +++ b/firmware/application/apps/ui_sonde.hpp @@ -65,11 +65,10 @@ public: private: std::unique_ptr logger { }; - uint32_t target_frequency_ { 402000000 }; + uint32_t target_frequency_ { 402700000 }; bool logging { false }; - int32_t altitude { 0 }; - float latitude { 0 }; - float longitude { 0 }; + sonde::GPS_data gps_info; + std::string sonde_id; Labels labels { { { 0 * 8, 2 * 16 }, "Signature:", Color::light_grey() }, diff --git a/firmware/baseband/proc_sonde.hpp b/firmware/baseband/proc_sonde.hpp index de15fff0..92e53580 100644 --- a/firmware/baseband/proc_sonde.hpp +++ b/firmware/baseband/proc_sonde.hpp @@ -140,7 +140,8 @@ private: } }; PacketBuilder packet_builder_fsk_4800_Vaisala { - { 0b00001000011011010101001110001000, 32, 1 }, + { 0b00001000011011010101001110001000, 32, 1 }, //euquiq Header detects 4 of 8 bytes 0x10B6CA11 /this is in raw format) (these bits are not passed at the beginning of packet) + //{ 0b0000100001101101010100111000100001000100011010010100100000011111, 64, 1 }, //euquiq whole header detection would be 8 bytes. { }, { 320 * 8 }, [this](const baseband::Packet& packet) { diff --git a/firmware/common/sonde_packet.cpp b/firmware/common/sonde_packet.cpp index 22f54793..b1c22430 100644 --- a/firmware/common/sonde_packet.cpp +++ b/firmware/common/sonde_packet.cpp @@ -22,9 +22,25 @@ #include "sonde_packet.hpp" #include "string_format.hpp" +#include +//#include namespace sonde { +//Defines for Vaisala RS41, from https://github.com/rs1729/RS/blob/master/rs41/rs41sg.c +#define MASK_LEN 64 +#define pos_FrameNb 0x37 //0x03B // 2 byte +#define pos_SondeID 0x39 //0x03D // 8 byte +#define pos_Voltage 0x041 //0x045 // 3 bytes (but first one is the important one) voltage x 10 ie: 26 = 2.6v +#define pos_CalData 0x04E //0x052 // 1 byte, counter 0x00..0x32 +#define pos_GPSweek 0x091 //0x095 // 2 byte +#define pos_GPSTOW 0x093 //0x097 // 4 byte +#define pos_GPSecefX 0x110 //0x114 // 4 byte +#define pos_GPSecefY 0x114 //0x118 // 4 byte (not actually used since Y and Z are following X, and grabbed in that same loop) +#define pos_GPSecefZ 0x118 //0x11C // 4 byte (same as Y) + +#define PI 3.1415926535897932384626433832795 //3.1416 //(3.1415926535897932384626433832795) + Packet::Packet( const baseband::Packet& packet, const Type type @@ -60,37 +76,65 @@ 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]; -};*/ +//euquiq here: +//RS41SG 320 bits header, 320bytes frame (or more if it is an "extended frame") +//The raw data is xor-scrambled with the values in the 64 bytes vaisala_mask (see.hpp) -uint32_t Packet::GPS_altitude() const { - 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 { - 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 -} +uint8_t Packet::vaisala_descramble(const uint32_t pos) const { + //return reader_raw.read(pos * 8, 8) ^ vaisala_mask[pos & 63]; + // packet_[i]; its a bit; packet_.size the total (should be 2560 bits) + uint8_t value = 0; + for (uint8_t i = 0; i < 8; i++) + value = (value << 1) | packet_[(pos * 8) + (7 -i)]; //get the byte from the bits collection -float Packet::GPS_longitude() const { - 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 + //packetReader reader { packet_ }; //This works just as above. + //value = reader.read(pos * 8,8); + //shift pos because first 4 bytes are consumed by proc_sonde in finding the vaisala signature + uint32_t mask_pos = pos + 4; + value = value ^ vaisala_mask[mask_pos % MASK_LEN]; //descramble with the xor pseudorandom table + return value; +}; + +GPS_data Packet::get_GPS_data() const { + GPS_data result; + if ((type_ == Type::Meteomodem_M10) || (type_ == Type::Meteomodem_M2K2)) { + + result.alt = (reader_bi_m.read(22 * 8, 32) / 1000) - 48; + result.lat = reader_bi_m.read(14 * 8, 32) / ((1ULL << 32) / 360.0); + result.lon = reader_bi_m.read(18 * 8, 32) / ((1ULL << 32) / 360.0); + + } else if (type_ == Type::Vaisala_RS41_SG) { + + uint8_t XYZ_bytes[4]; + int32_t XYZ; // 32bit + double_t X[3]; + for (int32_t k = 0; k < 3; k++) { //Get X,Y,Z ECEF position from GPS + for (int32_t i = 0; i < 4; i++) //each one is 4 bytes (32 bits) + XYZ_bytes[i] = vaisala_descramble(pos_GPSecefX + (4*k) + i); + memcpy(&XYZ, XYZ_bytes, 4); + X[k] = XYZ / 100.0; + } + + double_t a = 6378137.0; + double_t b = 6356752.31424518; + double_t e = sqrt( (a*a - b*b) / (a*a) ); + double_t ee = sqrt( (a*a - b*b) / (b*b) ); + + double_t lam = atan2( X[1] , X[0] ); + double_t p = sqrt( X[0]*X[0] + X[1]*X[1] ); + double_t t = atan2( X[2]*a , p*b ); + double_t phi = atan2( X[2] + ee*ee * b * sin(t)*sin(t)*sin(t) , + p - e*e * a * cos(t)*cos(t)*cos(t) ); + + double_t R = a / sqrt( 1 - e*e*sin(phi)*sin(phi) ); + + result.alt = p / cos(phi) - R; + result.lat = phi*180/PI; + result.lon = lam*180/PI; + + } + return result; } uint32_t Packet::battery_voltage() const { @@ -98,8 +142,13 @@ uint32_t Packet::battery_voltage() const { 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 + else if (type_ == Type::Vaisala_RS41_SG) { + uint32_t voltage = vaisala_descramble(pos_Voltage) * 100; //byte 69 = voltage * 10 (check if this value needs to be multiplied) + return voltage; + } + else { return 0; // Unknown + } } std::string Packet::type_string() const { @@ -127,12 +176,33 @@ std::string Packet::serial_number() const { 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'); - } else + } else if(type() == Type::Vaisala_RS41_SG) { + std::string serial_id = ""; + uint8_t achar; + for (uint8_t i=0; i<8; i++) { //euquiq: Serial ID is 8 bytes long, each byte a char + achar = vaisala_descramble(pos_SondeID + i); + if (achar < 32 || achar > 126) return "?"; //Maybe there are ids with less than 8 bytes and this is not OK. + serial_id += (char)achar; + } + return serial_id; + } else return "?"; } FormattedSymbols Packet::symbols_formatted() const { - return format_symbols(decoder_); + if (type() == Type::Vaisala_RS41_SG) { //Euquiq: now we distinguish different types + uint32_t bytes = packet_.size() / 8; //Need the byte amount, which if full, it SHOULD be 320 size() should return 2560 + std::string hex_data; + std::string hex_error; + hex_data.reserve(bytes * 2); //2 hexa chars per byte + hex_error.reserve(1); + for (uint32_t i=0; i < bytes; i++) //log will show the packet starting on the last 4 bytes from signature 93DF1A60 + hex_data += to_string_hex(vaisala_descramble(i),2); + return { hex_data, hex_error }; + + } else { + return format_symbols(decoder_); + } } bool Packet::crc_ok() const { diff --git a/firmware/common/sonde_packet.hpp b/firmware/common/sonde_packet.hpp index 4ecbc08a..746d42e3 100644 --- a/firmware/common/sonde_packet.hpp +++ b/firmware/common/sonde_packet.hpp @@ -32,6 +32,12 @@ namespace sonde { + struct GPS_data { + uint32_t alt { 0 }; + float lat { 0 }; + float lon { 0 }; + }; + class Packet { public: enum class Type : uint32_t { @@ -41,7 +47,7 @@ public: Meteomodem_M2K2 = 3, Vaisala_RS41_SG = 4, }; - + Packet(const baseband::Packet& packet, const Type type); size_t length() const; @@ -56,9 +62,7 @@ public: std::string serial_number() const; uint32_t battery_voltage() const; - uint32_t GPS_altitude() const; - float GPS_latitude() const; - float GPS_longitude() const; + GPS_data get_GPS_data() const; FormattedSymbols symbols_formatted() const; @@ -75,17 +79,20 @@ private: 0xD0, 0xBC, 0xB4, 0xB6, 0x06, 0xAA, 0xF4, 0x23, 0x78, 0x6E, 0x3B, 0xAE, 0xBF, 0x7B, 0x4C, 0xC1 }; + + GPS_data ecef_to_gps() const; - //uint8_t vaisala_descramble(const uint32_t pos); + uint8_t vaisala_descramble(uint32_t pos) const; const baseband::Packet packet_; const BiphaseMDecoder decoder_; const FieldReader reader_bi_m; Type type_; + using packetReader = FieldReader; //baseband::Packet instead of BiphaseMDecoder bool crc_ok_M10() const; }; } /* namespace sonde */ -#endif/*__SONDE_PACKET_H__*/ +#endif/*__SONDE_PACKET_H__*/ \ No newline at end of file From 7b19c0a35fcd907bfe119329bfbc523b94279eb8 Mon Sep 17 00:00:00 2001 From: euquiq <31453004+euquiq@users.noreply.github.com> Date: Fri, 14 Aug 2020 20:11:24 -0300 Subject: [PATCH 4/4] Update ui_navigation.cpp Now the Sonde App icon is in green: All sondes in the original proposal are working! --- firmware/application/ui_navigation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index e4ee6490..ee46bc61 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -416,7 +416,7 @@ ReceiversMenuView::ReceiversMenuView(NavigationView& nav) { { "Analog TV", ui::Color::yellow(), &bitmap_icon_sstv, [&nav](){ nav.push(); } }, { "ERT Meter", ui::Color::green(), &bitmap_icon_ert, [&nav](){ nav.push(); } }, { "POCSAG", ui::Color::green(), &bitmap_icon_pocsag, [&nav](){ nav.push(); } }, - { "Radiosnde", ui::Color::yellow(), &bitmap_icon_sonde, [&nav](){ nav.push(); } }, + { "Radiosnde", ui::Color::green(), &bitmap_icon_sonde, [&nav](){ nav.push(); } }, { "TPMS Cars", ui::Color::green(), &bitmap_icon_tpms, [&nav](){ nav.push(); } }, /*{ "APRS", ui::Color::dark_grey(), &bitmap_icon_aprs, [&nav](){ nav.push(); } }, { "DMR", ui::Color::dark_grey(), &bitmap_icon_dmr, [&nav](){ nav.push(); } },