mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-10-01 01:26:06 -04:00
Started adding decoders for RS41 radiosondes
Hopefully fixed M2K2 radiosonde battery voltage decoding Updated binary
This commit is contained in:
parent
1b93dd53e8
commit
dc82f15ece
@ -112,7 +112,7 @@ void SondeView::focus() {
|
|||||||
void SondeView::on_packet(const sonde::Packet& packet) {
|
void SondeView::on_packet(const sonde::Packet& packet) {
|
||||||
//const auto hex_formatted = packet.symbols_formatted();
|
//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_serial.set(packet.serial_number());
|
||||||
text_voltage.set(unit_auto_scale(packet.battery_voltage(), 2, 3) + "V");
|
text_voltage.set(unit_auto_scale(packet.battery_voltage(), 2, 3) + "V");
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||||
* Copyright (C) 2017 Furrtek
|
* Copyright (C) 2017 Furrtek
|
||||||
|
* Copyright (C) 2017 NotPike (notpike@horsefucker.org)
|
||||||
*
|
*
|
||||||
* This file is part of PortaPack.
|
* This file is part of PortaPack.
|
||||||
*
|
*
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||||
* Copyright (C) 2017 Furrtek
|
* Copyright (C) 2017 Furrtek
|
||||||
|
* Copyright (C) 2017 NotPike (notpike@horsefucker.org)
|
||||||
*
|
*
|
||||||
* This file is part of PortaPack.
|
* This file is part of PortaPack.
|
||||||
*
|
*
|
||||||
|
@ -43,6 +43,7 @@ void SondeProcessor::execute(const buffer_c8_t& buffer) {
|
|||||||
|
|
||||||
for (size_t i=0; i<decimator_out.count; i++) {
|
for (size_t i=0; i<decimator_out.count; i++) {
|
||||||
if( mf.execute_once(decimator_out.p[i]) ) {
|
if( mf.execute_once(decimator_out.p[i]) ) {
|
||||||
|
clock_recovery_fsk_9600(mf.get_output());
|
||||||
clock_recovery_fsk_4800(mf.get_output());
|
clock_recovery_fsk_4800(mf.get_output());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||||
* Copyright (C) 2017 Furrtek
|
* Copyright (C) 2017 Furrtek
|
||||||
|
* Copyright (C) 2014 zilog80
|
||||||
*
|
*
|
||||||
* This file is part of PortaPack.
|
* This file is part of PortaPack.
|
||||||
*
|
*
|
||||||
@ -113,19 +114,37 @@ private:
|
|||||||
dsp::decimate::FIRC16xR16x32Decim8 decim_1 { };
|
dsp::decimate::FIRC16xR16x32Decim8 decim_1 { };
|
||||||
dsp::matched_filter::MatchedFilter mf { baseband::ais::square_taps_38k4_1t_p, 2 };
|
dsp::matched_filter::MatchedFilter mf { baseband::ais::square_taps_38k4_1t_p, 2 };
|
||||||
|
|
||||||
clock_recovery::ClockRecovery<clock_recovery::FixedErrorFilter> clock_recovery_fsk_4800 {
|
// Actually 4800bits/s but the Manchester coding doubles the symbol rate
|
||||||
|
clock_recovery::ClockRecovery<clock_recovery::FixedErrorFilter> clock_recovery_fsk_9600 {
|
||||||
19200, 9600, { 0.0555f },
|
19200, 9600, { 0.0555f },
|
||||||
[this](const float raw_symbol) {
|
[this](const float raw_symbol) {
|
||||||
const uint_fast8_t sliced_symbol = (raw_symbol >= 0.0f) ? 1 : 0;
|
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<BitPattern, NeverMatch, FixedLength> packet_builder_fsk_4800_M10 {
|
PacketBuilder<BitPattern, NeverMatch, FixedLength> packet_builder_fsk_9600_Meteomodem {
|
||||||
{ 0b00110011001100110101100110110011, 32, 1 },
|
{ 0b00110011001100110101100110110011, 32, 1 },
|
||||||
{ },
|
{ },
|
||||||
{ 88 * 2 * 8 },
|
{ 88 * 2 * 8 },
|
||||||
[this](const baseband::Packet& packet) {
|
[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::FixedErrorFilter> 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<BitPattern, NeverMatch, FixedLength> 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);
|
shared_memory.application_queue.push(message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -62,7 +62,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::bitset<1408> data { };
|
std::bitset<2560> data { };
|
||||||
Timestamp timestamp_ { };
|
Timestamp timestamp_ { };
|
||||||
size_t count { 0 };
|
size_t count { 0 };
|
||||||
};
|
};
|
||||||
|
@ -25,12 +25,31 @@
|
|||||||
|
|
||||||
namespace sonde {
|
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 {
|
size_t Packet::length() const {
|
||||||
return decoder_.symbols_count();
|
return decoder_.symbols_count();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Packet::is_valid() const {
|
bool Packet::is_valid() const {
|
||||||
return true;
|
return true; // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
Timestamp Packet::received_at() const {
|
Timestamp Packet::received_at() const {
|
||||||
@ -41,49 +60,74 @@ Packet::Type Packet::type() const {
|
|||||||
return type_;
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
std::string Packet::type_string() const {
|
||||||
const auto header = reader_.read(0, 24);
|
switch (type_) {
|
||||||
|
case Type::Unknown: return "Unknown";
|
||||||
if (header == 0x649F20)
|
case Type::Meteomodem_unknown: return "Meteomodem ???";
|
||||||
return "M10";
|
case Type::Meteomodem_M10: return "Meteomodem M10";
|
||||||
else if ((header == 0x648F20) || (header == 0x648F23))
|
case Type::Meteomodem_M2K2: return "Meteomodem M2K2";
|
||||||
return "M2K2";
|
case Type::Vaisala_RS41_SG: return "Vaisala RS41-SG";
|
||||||
else
|
default: return "? 0x" + symbols_formatted().data.substr(0, 6);
|
||||||
return "0x" + symbols_formatted().data.substr(0, 6);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Packet::serial_number() const {
|
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
|
// See https://github.com/rs1729/RS/blob/master/m10/m10x.c line 606
|
||||||
// Starting at byte #93: 00000000 11111111 22222222 33333333 44444444
|
// Starting at byte #93: 00000000 11111111 22222222 33333333 44444444
|
||||||
// CCCC AAAABBBB
|
// CCCC AAAABBBB
|
||||||
// 44444444 33333333
|
// 44444444 33333333
|
||||||
// DDDEEEEE EEEEEEEE
|
// DDDEEEEE EEEEEEEE
|
||||||
|
|
||||||
return to_string_hex(reader_.read(93 * 8 + 16, 4), 1) +
|
return to_string_hex(reader_bi_m.read(93 * 8 + 16, 4), 1) +
|
||||||
to_string_dec_uint(reader_.read(93 * 8 + 20, 4), 2, '0') + " " +
|
to_string_dec_uint(reader_bi_m.read(93 * 8 + 20, 4), 2, '0') + " " +
|
||||||
to_string_hex(reader_.read(93 * 8 + 4, 4), 1) + " " +
|
to_string_hex(reader_bi_m.read(93 * 8 + 4, 4), 1) + " " +
|
||||||
to_string_dec_uint(reader_.read(93 * 8 + 24, 3), 1) +
|
to_string_dec_uint(reader_bi_m.read(93 * 8 + 24, 3), 1) +
|
||||||
to_string_dec_uint(reader_.read(93 * 8 + 27, 13), 4, '0');
|
to_string_dec_uint(reader_bi_m.read(93 * 8 + 27, 13), 4, '0');
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
} else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +137,7 @@ FormattedSymbols Packet::symbols_formatted() const {
|
|||||||
|
|
||||||
bool Packet::crc_ok() const {
|
bool Packet::crc_ok() const {
|
||||||
switch(type()) {
|
switch(type()) {
|
||||||
case Type::M10: return crc_ok_M10();
|
case Type::Meteomodem_M10: return crc_ok_M10();
|
||||||
default: return false;
|
default: return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,18 +36,13 @@ class Packet {
|
|||||||
public:
|
public:
|
||||||
enum class Type : uint32_t {
|
enum class Type : uint32_t {
|
||||||
Unknown = 0,
|
Unknown = 0,
|
||||||
M10 = 1,
|
Meteomodem_unknown = 1,
|
||||||
|
Meteomodem_M10 = 2,
|
||||||
|
Meteomodem_M2K2 = 3,
|
||||||
|
Vaisala_RS41_SG = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
Packet(
|
Packet(const baseband::Packet& packet, const Type type);
|
||||||
const baseband::Packet& packet,
|
|
||||||
const Type type
|
|
||||||
) : packet_ { packet },
|
|
||||||
decoder_ { packet_ },
|
|
||||||
reader_ { decoder_ },
|
|
||||||
type_ { type }
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t length() const;
|
size_t length() const;
|
||||||
|
|
||||||
@ -56,24 +51,37 @@ public:
|
|||||||
Timestamp received_at() const;
|
Timestamp received_at() const;
|
||||||
|
|
||||||
Type type() const;
|
Type type() const;
|
||||||
|
std::string type_string() const;
|
||||||
|
|
||||||
std::string serial_number() const;
|
std::string serial_number() const;
|
||||||
|
uint32_t battery_voltage() const;
|
||||||
|
|
||||||
uint32_t GPS_altitude() const;
|
uint32_t GPS_altitude() const;
|
||||||
float GPS_latitude() const;
|
float GPS_latitude() const;
|
||||||
float GPS_longitude() const;
|
float GPS_longitude() const;
|
||||||
std::string signature() const;
|
|
||||||
uint32_t battery_voltage() const;
|
|
||||||
|
|
||||||
FormattedSymbols symbols_formatted() const;
|
FormattedSymbols symbols_formatted() const;
|
||||||
|
|
||||||
bool crc_ok() const;
|
bool crc_ok() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Reader = FieldReader<BiphaseMDecoder, BitRemapNone>;
|
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 baseband::Packet packet_;
|
||||||
const BiphaseMDecoder decoder_;
|
const BiphaseMDecoder decoder_;
|
||||||
const Reader reader_;
|
const FieldReader<BiphaseMDecoder, BitRemapNone> reader_bi_m;
|
||||||
const Type type_;
|
Type type_;
|
||||||
|
|
||||||
bool crc_ok_M10() const;
|
bool crc_ok_M10() const;
|
||||||
};
|
};
|
||||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user