2017-10-05 00:38:45 -04:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
|
|
|
* Copyright (C) 2017 Furrtek
|
|
|
|
*
|
|
|
|
* This file is part of PortaPack.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
|
|
* any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; see the file COPYING. If not, write to
|
|
|
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
|
|
|
* Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "sonde_packet.hpp"
|
2017-10-28 13:16:06 -04:00
|
|
|
#include "string_format.hpp"
|
2017-10-05 00:38:45 -04:00
|
|
|
|
|
|
|
namespace sonde {
|
|
|
|
|
2017-11-09 21:20:44 -05:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-05 00:38:45 -04:00
|
|
|
size_t Packet::length() const {
|
|
|
|
return decoder_.symbols_count();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Packet::is_valid() const {
|
2017-11-09 21:20:44 -05:00
|
|
|
return true; // TODO
|
2017-10-05 00:38:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
Timestamp Packet::received_at() const {
|
|
|
|
return packet_.timestamp();
|
|
|
|
}
|
|
|
|
|
|
|
|
Packet::Type Packet::type() const {
|
|
|
|
return type_;
|
|
|
|
}
|
|
|
|
|
2017-11-09 21:20:44 -05:00
|
|
|
/*uint8_t Packet::vaisala_descramble(const uint32_t pos) {
|
|
|
|
return reader_raw.read(pos * 8, 8) ^ vaisala_mask[pos & 63];
|
|
|
|
};*/
|
|
|
|
|
2017-10-27 12:54:50 -04:00
|
|
|
uint32_t Packet::GPS_altitude() const {
|
2017-11-09 21:20:44 -05:00
|
|
|
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
|
2017-10-27 12:54:50 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
float Packet::GPS_latitude() const {
|
2017-11-09 21:20:44 -05:00
|
|
|
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
|
2017-10-27 12:54:50 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
float Packet::GPS_longitude() const {
|
2017-11-09 21:20:44 -05:00
|
|
|
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
|
2017-10-27 12:54:50 -04:00
|
|
|
}
|
|
|
|
|
2017-10-28 13:16:06 -04:00
|
|
|
uint32_t Packet::battery_voltage() const {
|
2017-11-09 21:20:44 -05:00
|
|
|
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
|
2017-10-28 13:16:06 -04:00
|
|
|
}
|
|
|
|
|
2017-11-09 21:20:44 -05:00
|
|
|
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);
|
|
|
|
}
|
2017-10-27 12:54:50 -04:00
|
|
|
}
|
|
|
|
|
2017-10-28 13:16:06 -04:00
|
|
|
std::string Packet::serial_number() const {
|
2017-11-09 21:20:44 -05:00
|
|
|
if (type() == Type::Meteomodem_M10) {
|
2017-10-05 00:38:45 -04:00
|
|
|
// See https://github.com/rs1729/RS/blob/master/m10/m10x.c line 606
|
2017-10-28 13:16:06 -04:00
|
|
|
// Starting at byte #93: 00000000 11111111 22222222 33333333 44444444
|
|
|
|
// CCCC AAAABBBB
|
|
|
|
// 44444444 33333333
|
|
|
|
// DDDEEEEE EEEEEEEE
|
|
|
|
|
2017-11-09 21:20:44 -05:00
|
|
|
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');
|
2017-10-28 13:16:06 -04:00
|
|
|
|
2017-11-09 21:20:44 -05:00
|
|
|
} else
|
|
|
|
return 0;
|
2017-10-05 00:38:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
FormattedSymbols Packet::symbols_formatted() const {
|
|
|
|
return format_symbols(decoder_);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Packet::crc_ok() const {
|
|
|
|
switch(type()) {
|
2017-11-09 21:20:44 -05:00
|
|
|
case Type::Meteomodem_M10: return crc_ok_M10();
|
|
|
|
default: return false;
|
2017-10-05 00:38:45 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Packet::crc_ok_M10() const {
|
|
|
|
uint16_t cs { 0 };
|
|
|
|
uint32_t c0, c1, t, t6, t7, s,b ;
|
|
|
|
|
|
|
|
for (size_t i = 0; i < packet_.size(); i++) {
|
|
|
|
b = packet_[i];
|
|
|
|
c1 = cs & 0xFF;
|
|
|
|
|
|
|
|
// B
|
|
|
|
b = (b >> 1) | ((b & 1) << 7);
|
|
|
|
b ^= (b >> 2) & 0xFF;
|
|
|
|
|
|
|
|
// A1
|
|
|
|
t6 = (cs & 1) ^ ((cs >> 2) & 1) ^ ((cs >> 4) & 1);
|
|
|
|
t7 = ((cs >> 1) & 1) ^ ((cs >> 3) & 1) ^ ((cs >> 5) & 1);
|
|
|
|
t = (cs & 0x3F) | (t6 << 6) | (t7 << 7);
|
|
|
|
|
|
|
|
// A2
|
|
|
|
s = (cs >> 7) & 0xFF;
|
|
|
|
s ^= (s >> 2) & 0xFF;
|
|
|
|
|
|
|
|
c0 = b ^ t ^ s;
|
|
|
|
|
|
|
|
cs = ((c1<<8) | c0) & 0xFFFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ((cs & 0xFFFF) == ((packet_[0x63] << 8) | (packet_[0x63 + 1])));
|
|
|
|
}
|
|
|
|
|
|
|
|
} /* namespace sonde */
|