Added logging, serial number and battery voltage display to radiosonde RX

Added decimal degrees display to geopos widget
This commit is contained in:
furrtek 2017-10-28 19:16:06 +02:00
parent d47f292d3a
commit 6ff8249a4f
7 changed files with 106 additions and 80 deletions

View File

@ -29,12 +29,14 @@
using namespace portapack; using namespace portapack;
#include "string_format.hpp"
namespace ui { namespace ui {
GeoPos::GeoPos( GeoPos::GeoPos(
const Point pos const Point pos
) { ) {
set_parent_rect({pos, {30 * 8, 3 * 16}}); set_parent_rect({pos, { 30 * 8, 3 * 16 }});
add_children({ add_children({
&labels_position, &labels_position,
@ -42,9 +44,11 @@ GeoPos::GeoPos(
&field_lat_degrees, &field_lat_degrees,
&field_lat_minutes, &field_lat_minutes,
&field_lat_seconds, &field_lat_seconds,
&text_lat_decimal,
&field_lon_degrees, &field_lon_degrees,
&field_lon_minutes, &field_lon_minutes,
&field_lon_seconds &field_lon_seconds,
&text_lon_decimal
}); });
// Defaults // Defaults
@ -53,8 +57,22 @@ GeoPos::GeoPos(
set_lon(0); set_lon(0);
const auto changed_fn = [this](int32_t) { const auto changed_fn = [this](int32_t) {
float lat_value = lat();
float lon_value = lon();
double integer_part;
double fractional_part;
fractional_part = modf(lat_value, &integer_part) * 100000;
if (fractional_part < 0)
fractional_part = -fractional_part;
text_lat_decimal.set(to_string_dec_int(integer_part) + "." + to_string_dec_uint(fractional_part, 5));
fractional_part = modf(lon_value, &integer_part) * 100000;
if (fractional_part < 0)
fractional_part = -fractional_part;
text_lon_decimal.set(to_string_dec_int(integer_part) + "." + to_string_dec_uint(fractional_part, 5));
if (on_change && report_change) if (on_change && report_change)
on_change(altitude(), lat(), lon()); on_change(altitude(), lat_value, lon_value);
}; };
field_altitude.on_change = changed_fn; field_altitude.on_change = changed_fn;
@ -66,6 +84,11 @@ GeoPos::GeoPos(
field_lon_seconds.on_change = changed_fn; field_lon_seconds.on_change = changed_fn;
} }
void GeoPos::set_read_only(bool v) {
for(auto child : children_)
child->set_focusable(!v);
}
// Stupid hack to avoid an event loop // Stupid hack to avoid an event loop
void GeoPos::set_report_change(bool v) { void GeoPos::set_report_change(bool v) {
report_change = v; report_change = v;
@ -103,10 +126,6 @@ int32_t GeoPos::altitude() {
return field_altitude.value(); return field_altitude.value();
}; };
void GeoPos::set_read_only(bool v) {
set_focusable(~v);
};
GeoMap::GeoMap( GeoMap::GeoMap(
Rect parent_rect Rect parent_rect
) : Widget { parent_rect } ) : Widget { parent_rect }
@ -117,7 +136,6 @@ GeoMap::GeoMap(
void GeoMap::paint(Painter& painter) { void GeoMap::paint(Painter& painter) {
Coord line; Coord line;
std::array<ui::Color, 240> map_line_buffer; std::array<ui::Color, 240> map_line_buffer;
//Color border;
const auto r = screen_rect(); const auto r = screen_rect();
// Ony redraw map if it moved by at least 1 pixel // Ony redraw map if it moved by at least 1 pixel

View File

@ -60,13 +60,13 @@ private:
bool report_change { true }; bool report_change { true };
Labels labels_position { Labels labels_position {
{ { 2 * 8, 0 * 16 }, "Alt: feet", Color::light_grey() }, { { 1 * 8, 0 * 16 }, "Alt: feet", Color::light_grey() },
{ { 2 * 8, 1 * 16 }, "Lat: * ' \"", Color::light_grey() }, // No ° symbol in 8x16 font { { 1 * 8, 1 * 16 }, "Lat: * ' \"", Color::light_grey() }, // No ° symbol in 8x16 font
{ { 2 * 8, 2 * 16 }, "Lon: * ' \"", Color::light_grey() }, { { 1 * 8, 2 * 16 }, "Lon: * ' \"", Color::light_grey() },
}; };
NumberField field_altitude { NumberField field_altitude {
{ 7 * 8, 0 * 16 }, { 6 * 8, 0 * 16 },
5, 5,
{ -1000, 50000 }, { -1000, 50000 },
250, 250,
@ -74,23 +74,31 @@ private:
}; };
NumberField field_lat_degrees { NumberField field_lat_degrees {
{ 7 * 8, 1 * 16 }, 4, { -90, 90 }, 1, ' ' { 5 * 8, 1 * 16 }, 4, { -90, 90 }, 1, ' '
}; };
NumberField field_lat_minutes { NumberField field_lat_minutes {
{ 12 * 8, 1 * 16 }, 2, { 0, 59 }, 1, ' ' { 10 * 8, 1 * 16 }, 2, { 0, 59 }, 1, ' '
}; };
NumberField field_lat_seconds { NumberField field_lat_seconds {
{ 15 * 8, 1 * 16 }, 2, { 0, 59 }, 1, ' ' { 13 * 8, 1 * 16 }, 2, { 0, 59 }, 1, ' '
};
Text text_lat_decimal {
{ 17 * 8, 1 * 16, 13 * 8, 1 * 16 },
""
}; };
NumberField field_lon_degrees { NumberField field_lon_degrees {
{ 7 * 8, 2 * 16 }, 4, { -180, 180 }, 1, ' ' { 5 * 8, 2 * 16 }, 4, { -180, 180 }, 1, ' '
}; };
NumberField field_lon_minutes { NumberField field_lon_minutes {
{ 12 * 8, 2 * 16 }, 2, { 0, 59 }, 1, ' ' { 10 * 8, 2 * 16 }, 2, { 0, 59 }, 1, ' '
}; };
NumberField field_lon_seconds { NumberField field_lon_seconds {
{ 15 * 8, 2 * 16 }, 2, { 0, 59 }, 1, ' ' { 13 * 8, 2 * 16 }, 2, { 0, 59 }, 1, ' '
};
Text text_lon_decimal {
{ 17 * 8, 2 * 16, 13 * 8, 1 * 16 },
""
}; };
}; };

View File

@ -21,20 +21,17 @@
*/ */
#include "ui_sonde.hpp" #include "ui_sonde.hpp"
#include "baseband_api.hpp" #include "baseband_api.hpp"
#include "portapack.hpp" #include "portapack.hpp"
using namespace portapack; using namespace portapack;
//#include "manchester.hpp"
#include "string_format.hpp" #include "string_format.hpp"
/*void SondeLogger::on_packet(const sonde::Packet& packet) { void SondeLogger::on_packet(const sonde::Packet& packet) {
const auto formatted = packet.symbols_formatted(); const auto formatted = packet.symbols_formatted();
log_file.write_entry(packet.received_at(), formatted.data + "/" + formatted.errors); log_file.write_entry(packet.received_at(), formatted.data);
}*/ }
namespace ui { namespace ui {
@ -43,15 +40,15 @@ SondeView::SondeView(NavigationView& nav) {
add_children({ add_children({
&labels, &labels,
&field_frequency,
&field_rf_amp, &field_rf_amp,
&field_lna, &field_lna,
&field_vga, &field_vga,
&rssi, &rssi,
&field_frequency, &check_log,
&text_debug_a,
&text_debug_b,
&text_signature, &text_signature,
&text_sats, &text_serial,
&text_voltage,
&geopos, &geopos,
&button_see_map &button_see_map
}); });
@ -73,6 +70,10 @@ SondeView::SondeView(NavigationView& nav) {
geopos.set_read_only(true); geopos.set_read_only(true);
check_log.on_select = [this](Checkbox&, bool v) {
logging = v;
};
radio::enable({ radio::enable({
tuning_frequency(), tuning_frequency(),
sampling_rate, sampling_rate,
@ -92,10 +93,10 @@ SondeView::SondeView(NavigationView& nav) {
0); 0);
}; };
/*logger = std::make_unique<SondeLogger>(); logger = std::make_unique<SondeLogger>();
if( logger ) { if (logger)
logger->append(u"sonde.txt"); logger->append(u"sonde.txt");
}*/
} }
SondeView::~SondeView() { SondeView::~SondeView() {
@ -108,14 +109,11 @@ 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_debug_a.set(hex_formatted.data.substr(0, 30));
text_debug_b.set(hex_formatted.errors.substr(0, 30));
text_signature.set(packet.signature()); text_signature.set(packet.signature());
text_serial.set(packet.serial_number());
text_sats.set(to_string_dec_uint(packet.visible_sats())); text_voltage.set(to_string_dec_uint(packet.battery_voltage()) + "mV");
altitude = packet.GPS_altitude(); altitude = packet.GPS_altitude();
latitude = packet.GPS_latitude(); latitude = packet.GPS_latitude();
@ -125,9 +123,9 @@ void SondeView::on_packet(const sonde::Packet& packet) {
geopos.set_lat(latitude); geopos.set_lat(latitude);
geopos.set_lon(longitude); geopos.set_lon(longitude);
/*if( logger ) { if (logger && logging) {
logger->on_packet(packet); logger->on_packet(packet);
}*/ }
/*if( packet.crc_ok() ) { /*if( packet.crc_ok() ) {
}*/ }*/

View File

@ -26,7 +26,6 @@
#include "ui_navigation.hpp" #include "ui_navigation.hpp"
#include "ui_receiver.hpp" #include "ui_receiver.hpp"
#include "ui_rssi.hpp" #include "ui_rssi.hpp"
#include "ui_channel.hpp"
#include "ui_geomap.hpp" #include "ui_geomap.hpp"
#include "event_m0.hpp" #include "event_m0.hpp"
@ -35,12 +34,10 @@
#include "sonde_packet.hpp" #include "sonde_packet.hpp"
#include "recent_entries.hpp"
#include <cstddef> #include <cstddef>
#include <string> #include <string>
/*class SondeLogger { class SondeLogger {
public: public:
Optional<File::Error> append(const std::filesystem::path& filename) { Optional<File::Error> append(const std::filesystem::path& filename) {
return log_file.append(filename); return log_file.append(filename);
@ -50,7 +47,7 @@ public:
private: private:
LogFile log_file { }; LogFile log_file { };
};*/ };
namespace ui { namespace ui {
@ -67,16 +64,17 @@ public:
std::string title() const override { return "Radiosonde RX"; }; std::string title() const override { return "Radiosonde RX"; };
private: private:
//std::unique_ptr<SondeLogger> logger { }; std::unique_ptr<SondeLogger> logger { };
uint32_t target_frequency_ { 402000000 }; uint32_t target_frequency_ { 402000000 };
bool logging { false };
int32_t altitude { 0 }; int32_t altitude { 0 };
float latitude { 0 }; float latitude { 0 };
float longitude { 0 }; float longitude { 0 };
Labels labels { Labels labels {
{ { 3 * 8, 5 * 16 }, "Signature:", Color::light_grey() }, { { 0 * 8, 2 * 16 }, "Signature:", Color::light_grey() },
{ { 0 * 8, 6 * 16 }, "Visible sats:", Color::light_grey() }, { { 3 * 8, 3 * 16 }, "Serial:", Color::light_grey() },
//{ { 4 * 8, 7 * 16 }, "Altitude:", Color::light_grey() }, { { 4 * 8, 4 * 16 }, "Vbatt:", Color::light_grey() }
}; };
FrequencyField field_frequency { FrequencyField field_frequency {
@ -98,30 +96,31 @@ private:
{ 21 * 8, 0, 6 * 8, 4 }, { 21 * 8, 0, 6 * 8, 4 },
}; };
Text text_debug_a { Checkbox check_log {
{ 0, 2 * 16, 240, 16 }, { 22 * 8, 2 * 16 + 8 },
"Waiting for frame..." 3,
}; "Log"
Text text_debug_b {
{ 0, 3 * 16, 240, 16 },
"Waiting for frame..."
}; };
Text text_signature { Text text_signature {
{ 13 * 8, 5 * 16, 240, 16 }, { 10 * 8, 2 * 16, 10 * 8, 16 },
"..." "..."
}; };
Text text_sats { Text text_serial {
{ 13 * 8, 6 * 16, 240, 16 }, { 10 * 8, 3 * 16, 11 * 8, 16 },
"..."
};
Text text_voltage {
{ 10 * 8, 4 * 16, 10 * 8, 16 },
"..." "..."
}; };
GeoPos geopos { GeoPos geopos {
{ 0, 8 * 16 } { 0, 6 * 16 }
}; };
Button button_see_map { Button button_see_map {
{ 8 * 8, 12 * 16, 14 * 8, 3 * 16 }, { 8 * 8, 10 * 16, 14 * 8, 3 * 16 },
"See on map" "See on map"
}; };
@ -134,7 +133,6 @@ private:
} }
}; };
//void on_packet(const sonde::Packet& packet);
void on_packet(const sonde::Packet& packet); void on_packet(const sonde::Packet& packet);
void set_target_frequency(const uint32_t new_value); void set_target_frequency(const uint32_t new_value);
uint32_t tuning_frequency() const; uint32_t tuning_frequency() const;

View File

@ -123,7 +123,7 @@ private:
PacketBuilder<BitPattern, NeverMatch, FixedLength> packet_builder_fsk_4800_M10 { PacketBuilder<BitPattern, NeverMatch, FixedLength> packet_builder_fsk_4800_M10 {
{ 0b00110011001100110101100110110011, 32, 1 }, { 0b00110011001100110101100110110011, 32, 1 },
{ }, { },
{ 102 * 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::M10, packet };
shared_memory.application_queue.push(message); shared_memory.application_queue.push(message);

View File

@ -21,8 +21,7 @@
*/ */
#include "sonde_packet.hpp" #include "sonde_packet.hpp"
#include "string_format.hpp"
//#include "crc.hpp"
namespace sonde { namespace sonde {
@ -42,12 +41,8 @@ Packet::Type Packet::type() const {
return type_; return type_;
} }
uint32_t Packet::visible_sats() const {
return reader_.read(30 * 8, 8);
}
uint32_t Packet::GPS_altitude() const { uint32_t Packet::GPS_altitude() const {
return reader_.read(22 * 8, 32) / 1000; return (reader_.read(22 * 8, 32) / 1000) - 48;
} }
float Packet::GPS_latitude() const { float Packet::GPS_latitude() const {
@ -58,6 +53,10 @@ float Packet::GPS_longitude() const {
return reader_.read(18 * 8, 32) / ((1ULL << 32) / 360.0); return reader_.read(18 * 8, 32) / ((1ULL << 32) / 360.0);
} }
uint32_t Packet::battery_voltage() const {
return (reader_.read(69 * 8, 8) + (reader_.read(70 * 8, 8) << 8)) * 1000 / 150;
}
std::string Packet::signature() const { std::string Packet::signature() const {
const auto header = reader_.read(0, 24); const auto header = reader_.read(0, 24);
@ -66,18 +65,25 @@ std::string Packet::signature() const {
else if (header == 0x648F20) else if (header == 0x648F20)
return "M2K2"; return "M2K2";
else else
return symbols_formatted().data.substr(0, 6); return "0x" + symbols_formatted().data.substr(0, 6);
} }
SN Packet::serial_number() const { std::string Packet::serial_number() const {
if (type() == Type::M10) { if (type() == Type::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
return (reader_.read(2 * 8, 8) << 20) | // Starting at byte #93: 00000000 11111111 22222222 33333333 44444444
(reader_.read(0, 4) << 16) | // CCCC AAAABBBB
(reader_.read(4 * 8, 3) << 13) | // 44444444 33333333
(reader_.read(4 * 8 + 3, 5) << 8) | // DDDEEEEE EEEEEEEE
reader_.read(3 * 8, 8);
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 0; return 0;
} }

View File

@ -32,8 +32,6 @@
namespace sonde { namespace sonde {
using SN = uint64_t;
class Packet { class Packet {
public: public:
enum class Type : uint32_t { enum class Type : uint32_t {
@ -58,12 +56,12 @@ public:
Timestamp received_at() const; Timestamp received_at() const;
Type type() const; Type type() const;
SN serial_number() const; std::string serial_number() const;
uint32_t visible_sats() 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; std::string signature() const;
uint32_t battery_voltage() const;
FormattedSymbols symbols_formatted() const; FormattedSymbols symbols_formatted() const;