Merge branch 'v1.2' into add-heading-to-geomap

This commit is contained in:
Erwin Ried
2020-08-15 15:52:53 +02:00
committed by GitHub
19 changed files with 2499 additions and 2119 deletions

View File

@@ -214,7 +214,7 @@ set(CPPSRC
ui/ui_tabview.cpp
ui/ui_textentry.cpp
ui/ui_transmitter.cpp
apps/ui_about.cpp
apps/ui_about_simple.cpp
apps/ui_adsb_rx.cpp
apps/ui_adsb_tx.cpp
apps/ui_afsk_rx.cpp

View File

@@ -0,0 +1,75 @@
#include "ui_about_simple.hpp"
namespace ui
{
AboutView::AboutView(NavigationView &nav)
{
add_children({&console, &button_ok});
button_ok.on_select = [&nav](Button &) {
nav.pop();
};
console.writeln("\x1B\x07List of contributors:\x1B\x10");
console.writeln("");
}
void AboutView::update()
{
if (++timer > 200)
{
timer = 0;
switch (++frame)
{
case 1:
// TODO: Generate this automatically from github
// https://github.com/eried/portapack-mayhem/graphs/contributors?to=2022-01-01&from=2020-04-12&type=c
console.writeln("\x1B\x06Mayhem:\x1B\x10");
console.writeln("eried,euquiq,gregoryfenton");
console.writeln("johnelder,jwetzell,nnemanjan00");
console.writeln("N0vaPixel,klockee,jamesshao8");
console.writeln("");
break;
case 2:
// https://github.com/eried/portapack-mayhem/graphs/contributors?to=2020-04-12&from=2015-07-31&type=c
console.writeln("\x1B\x06Havoc:\x1B\x10");
console.writeln("furrtek,mrmookie,notpike");
console.writeln("mjwaxios,ImDroided,Giorgiofox");
console.writeln("F4GEV,z4ziggy,xmycroftx");
console.writeln("troussos,silascutler");
console.writeln("nickbouwhuis,msoose,leres");
console.writeln("joakar,dhoetger,clem-42");
console.writeln("brianlechthaler,ZeroChaos-...");
console.writeln("");
break;
case 3:
// https://github.com/eried/portapack-mayhem/graphs/contributors?from=2014-07-05&to=2015-07-31&type=c
console.writeln("\x1B\x06PortaPack:\x1B\x10");
console.writeln("jboone,argilo");
console.writeln("");
break;
case 4:
// https://github.com/mossmann/hackrf/graphs/contributors
console.writeln("\x1B\x06HackRF:\x1B\x10");
console.writeln("mossmann,dominicgs,bvernoux");
console.writeln("bgamari,schneider42,miek");
console.writeln("willcode,hessu,Sec42");
console.writeln("yhetti,ckuethe,smunaut");
console.writeln("wishi,mrbubble62,scateu...");
console.writeln("");
frame = 0; // Loop
break;
}
}
}
void AboutView::focus()
{
button_ok.focus();
}
} /* namespace ui */

View File

@@ -0,0 +1,40 @@
#ifndef __UI_ABOUT_SIMPLE_H__
#define __UI_ABOUT_SIMPLE_H__
#include "ui_widget.hpp"
#include "ui_navigation.hpp"
#include "ui_font_fixed_8x16.hpp"
#include <cstdint>
namespace ui
{
class AboutView : public View
{
public:
AboutView(NavigationView &nav);
void focus() override;
std::string title() const override { return "About"; };
int32_t timer{180};
short frame{0};
private:
void update();
Console console{
{0, 10, 240, 240}};
Button button_ok{
{240/3, 270, 240/3, 24},
"OK",
};
MessageHandlerRegistration message_handler_update{
Message::ID::DisplayFrameSync,
[this](const Message *const) {
this->update();
}};
};
} // namespace ui
#endif /*__UI_ABOUT_SIMPLE_H__*/

View File

@@ -92,31 +92,37 @@ FileManBaseView::FileManBaseView(
) : nav_ (nav),
extension_filter { filter }
{
load_directory_contents(current_path);
if (!entry_list.size())
empty_root = true;
add_children({
&labels,
&text_current,
&button_exit
});
menu_view.on_left = [&nav, this]() {
load_directory_contents(get_parent_dir());
refresh_list();
};
button_exit.on_select = [this, &nav](Button&) {
nav.pop();
};
};
if (!sdcIsCardInserted(&SDCD1)) {
empty_root=true;
text_current.set("NO SD CARD!");
} else {
load_directory_contents(current_path);
if (!entry_list.size())
{
empty_root = true;
text_current.set("EMPTY SD CARD!");
} else {
menu_view.on_left = [&nav, this]() {
load_directory_contents(get_parent_dir());
refresh_list();
};
}
}
}
void FileManBaseView::focus() {
if (empty_root) {
button_exit.focus();
nav_.display_modal("Error", "No files in root.", ABORT, nullptr);
} else {
menu_view.focus();
}
@@ -190,7 +196,6 @@ void FileManBaseView::refresh_list() {
nav_.pop();
});
}
FileSaveView::FileSaveView(
NavigationView& nav
) : FileManBaseView(nav)
@@ -244,7 +249,11 @@ FileLoadView::FileLoadView(
void FileManagerView::on_rename(NavigationView& nav) {
text_prompt(nav, name_buffer, max_filename_length, [this](std::string& buffer) {
rename_file(get_selected_path(), buffer);
std::string destination_path = current_path.string();
if (destination_path.back() != '/')
destination_path += '/';
destination_path = destination_path + buffer;
rename_file(get_selected_path(), destination_path);
load_directory_contents(current_path);
refresh_list();
});
@@ -271,57 +280,59 @@ FileManagerView::FileManagerView(
NavigationView& nav
) : FileManBaseView(nav, "")
{
on_refresh_widgets = [this](bool v) {
refresh_widgets(v);
};
add_children({
&menu_view,
&labels,
&text_date,
&button_rename,
&button_new_dir,
&button_delete
});
menu_view.on_highlight = [this]() {
text_date.set(to_string_FAT_timestamp(file_created_date(get_selected_path())));
};
refresh_list();
on_select_entry = [this]() {
if (entry_list[menu_view.highlighted_index()].is_directory) {
load_directory_contents(get_selected_path());
refresh_list();
} else
button_rename.focus();
};
button_new_dir.on_select = [this, &nav](Button&) {
name_buffer.clear();
if (!empty_root) {
on_refresh_widgets = [this](bool v) {
refresh_widgets(v);
};
text_prompt(nav, name_buffer, max_filename_length, [this](std::string& buffer) {
make_new_directory(current_path.string() + '/' + buffer);
load_directory_contents(current_path);
refresh_list();
add_children({
&menu_view,
&labels,
&text_date,
&button_rename,
&button_new_dir,
&button_delete
});
};
button_rename.on_select = [this, &nav](Button&) {
name_buffer = entry_list[menu_view.highlighted_index()].entry_path.filename().string().substr(0, max_filename_length);
on_rename(nav);
};
button_delete.on_select = [this, &nav](Button&) {
// Use display_modal ?
nav.push<ModalMessageView>("Delete", "Delete " + entry_list[menu_view.highlighted_index()].entry_path.filename().string() + "\nAre you sure?", YESNO,
[this](bool choice) {
if (choice)
on_delete();
}
);
};
menu_view.on_highlight = [this]() {
text_date.set(to_string_FAT_timestamp(file_created_date(get_selected_path())));
};
refresh_list();
on_select_entry = [this]() {
if (entry_list[menu_view.highlighted_index()].is_directory) {
load_directory_contents(get_selected_path());
refresh_list();
} else
button_rename.focus();
};
button_new_dir.on_select = [this, &nav](Button&) {
name_buffer.clear();
text_prompt(nav, name_buffer, max_filename_length, [this](std::string& buffer) {
make_new_directory(current_path.string() + '/' + buffer);
load_directory_contents(current_path);
refresh_list();
});
};
button_rename.on_select = [this, &nav](Button&) {
name_buffer = entry_list[menu_view.highlighted_index()].entry_path.filename().string().substr(0, max_filename_length);
on_rename(nav);
};
button_delete.on_select = [this, &nav](Button&) {
// Use display_modal ?
nav.push<ModalMessageView>("Delete", "Delete " + entry_list[menu_view.highlighted_index()].entry_path.filename().string() + "\nAre you sure?", YESNO,
[this](bool choice) {
if (choice)
on_delete();
}
);
};
}
}
}

View File

@@ -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,11 +86,11 @@ SondeView::SondeView(NavigationView& nav) {
button_see_map.on_select = [this, &nav](Button&) {
nav.push<GeoMapView>(
"",
altitude,
sonde_id,
gps_info.alt,
GeoPos::alt_unit::METERS,
latitude,
longitude,
gps_info.lat,
gps_info.lon,
999); //set a dummy heading out of range to draw a cross...probably not ideal?
};
@@ -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);

View File

@@ -65,11 +65,10 @@ public:
private:
std::unique_ptr<SondeLogger> 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() },

File diff suppressed because it is too large Load Diff

View File

@@ -95,6 +95,15 @@ void BtnGridView::set_parent_rect(const Rect new_parent_rect) {
update_items();
}
void BtnGridView::set_arrow_enabled(bool new_value) {
if(new_value){
add_child(&arrow_more);
}
else{
remove_child(&arrow_more);
}
};
void BtnGridView::on_tick_second() {
if (more && blink)
arrow_more.set_foreground(Color::white());

View File

@@ -62,6 +62,7 @@ public:
uint32_t highlighted_index();
void set_parent_rect(const Rect new_parent_rect) override;
void set_arrow_enabled(bool new_value);
void on_focus() override;
void on_blur() override;
bool on_key(const KeyEvent event) override;

View File

@@ -120,8 +120,8 @@ void FrequencyScale::paint(Painter& painter) {
if (_blink) {
const Rect r_cursor {
120 + cursor_position, r.bottom() - filter_band_height,
2, filter_band_height
118 + cursor_position, r.bottom() - filter_band_height,
5, filter_band_height
};
painter.fill_rectangle(
r_cursor,

View File

@@ -30,7 +30,7 @@
#include "bmp_modal_warning.hpp"
#include "portapack_persistent_memory.hpp"
#include "ui_about.hpp"
#include "ui_about_simple.hpp"
#include "ui_adsb_rx.hpp"
#include "ui_adsb_tx.hpp"
#include "ui_afsk_rx.hpp"
@@ -106,6 +106,7 @@ SystemStatusView::SystemStatusView(
&backdrop,
&button_back,
&title,
&button_title,
&button_speaker,
&button_stealth,
//&button_textentry,
@@ -138,6 +139,10 @@ SystemStatusView::SystemStatusView(
if (this->on_back)
this->on_back();
};
button_title.on_select = [this](ImageButton&) {
this->on_title();
};
button_speaker.on_select = [this](ImageButton&) {
this->on_speaker();
@@ -194,8 +199,23 @@ void SystemStatusView::refresh() {
}
void SystemStatusView::set_back_enabled(bool new_value) {
button_back.set_foreground(new_value ? Color::white() : Color::dark_grey());
button_back.set_focusable(new_value);
if(new_value){
add_child(&button_back);
}
else{
remove_child(&button_back);
}
}
void SystemStatusView::set_title_image_enabled(bool new_value) {
if(new_value){
add_child(&button_title);
}
else{
remove_child(&button_title);
}
}
void SystemStatusView::set_title(const std::string new_value) {
@@ -282,6 +302,39 @@ void SystemStatusView::on_camera() {
}
}
void SystemStatusView::on_title() {
if(nav_.is_top())
nav_.push<AboutView>();
else
nav_.pop();
}
/* Information View *****************************************************/
InformationView::InformationView(
NavigationView& nav
) : nav_ (nav)
{
static constexpr Style style_infobar {
.font = font::fixed_8x16,
.background = {33, 33, 33},
.foreground = Color::white(),
};
add_children({
&backdrop,
&version,
&ltime
});
version.set_style(&style_infobar);
ltime.set_style(&style_infobar);
ltime.set_seconds_enabled(true);
ltime.set_date_enabled(false);
set_dirty();
}
/* Navigation ************************************************************/
bool NavigationView::is_top() const {
@@ -383,7 +436,7 @@ ReceiversMenuView::ReceiversMenuView(NavigationView& nav) {
add_items({
//{ "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } },
{ "ADS-B", ui::Color::green(), &bitmap_icon_adsb, [&nav](){ nav.push<ADSBRxView>(); }, },
{ "ACARS", ui::Color::yellow(), &bitmap_icon_adsb, [&nav](){ nav.push<ACARSAppView>(); }, },
//{ "ACARS", ui::Color::yellow(), &bitmap_icon_adsb, [&nav](){ nav.push<ACARSAppView>(); }, },
{ "AIS Boats", ui::Color::green(), &bitmap_icon_ais, [&nav](){ nav.push<AISAppView>(); } },
{ "AFSK", ui::Color::yellow(), &bitmap_icon_modem, [&nav](){ nav.push<AFSKRxView>(); } },
{ "BTLE", ui::Color::yellow(), &bitmap_icon_btle, [&nav](){ nav.push<BTLERxView>(); } },
@@ -392,7 +445,7 @@ ReceiversMenuView::ReceiversMenuView(NavigationView& nav) {
{ "Analog TV", ui::Color::yellow(), &bitmap_icon_sstv, [&nav](){ nav.push<AnalogTvView>(); } },
{ "ERT Meter", ui::Color::green(), &bitmap_icon_ert, [&nav](){ nav.push<ERTAppView>(); } },
{ "POCSAG", ui::Color::green(), &bitmap_icon_pocsag, [&nav](){ nav.push<POCSAGAppView>(); } },
{ "Radiosnde", ui::Color::yellow(), &bitmap_icon_sonde, [&nav](){ nav.push<SondeView>(); } },
{ "Radiosnde", ui::Color::green(), &bitmap_icon_sonde, [&nav](){ nav.push<SondeView>(); } },
{ "TPMS Cars", ui::Color::green(), &bitmap_icon_tpms, [&nav](){ nav.push<TPMSAppView>(); } },
/*{ "APRS", ui::Color::dark_grey(), &bitmap_icon_aprs, [&nav](){ nav.push<NotImplementedView>(); } },
{ "DMR", ui::Color::dark_grey(), &bitmap_icon_dmr, [&nav](){ nav.push<NotImplementedView>(); } },
@@ -478,6 +531,7 @@ SystemMenuView::SystemMenuView(NavigationView& nav) {
//{ "About", ui::Color::cyan(), nullptr, [&nav](){ nav.push<AboutView>(); } }
});
set_max_rows(2); // allow wider buttons
set_arrow_enabled(false);
//set_highlighted(1); // Startup selection
}
@@ -498,6 +552,7 @@ SystemView::SystemView(
set_style(&style_default);
constexpr ui::Dim status_view_height = 16;
constexpr ui::Dim info_view_height = 16;
add_child(&status_view);
status_view.set_parent_rect({
@@ -513,11 +568,30 @@ SystemView::SystemView(
{ 0, status_view_height },
{ parent_rect.width(), static_cast<ui::Dim>(parent_rect.height() - status_view_height) }
});
add_child(&info_view);
info_view.set_parent_rect({
{0, 19 * 16},
{ parent_rect.width(), info_view_height }
});
navigation_view.on_view_changed = [this](const View& new_view) {
if(!this->navigation_view.is_top()){
remove_child(&info_view);
}
else{
add_child(&info_view);
}
this->status_view.set_back_enabled(!this->navigation_view.is_top());
this->status_view.set_title_image_enabled(this->navigation_view.is_top());
this->status_view.set_title(new_view.title());
this->status_view.set_dirty();
};
// portapack::persistent_memory::set_playdead_sequence(0x8D1);
// Initial view
@@ -530,6 +604,9 @@ SystemView::SystemView(
if (portapack::persistent_memory::config_splash())
navigation_view.push<BMPView>();
status_view.set_back_enabled(false);
status_view.set_title_image_enabled(true);
status_view.set_dirty();
//else
// navigation_view.push<SystemMenuView>();

View File

@@ -106,10 +106,11 @@ public:
SystemStatusView(NavigationView& nav);
void set_back_enabled(bool new_value);
void set_title_image_enabled(bool new_value);
void set_title(const std::string new_value);
private:
static constexpr auto default_title = "MAYHEM v1.1.1"; // TODO: Move the version somewhere
static constexpr auto default_title = "";
NavigationView& nav_;
@@ -130,6 +131,13 @@ private:
default_title,
};
ImageButton button_title {
{2, 0, 80, 16},
&bitmap_titlebar_image,
Color::white(),
Color::dark_grey()
};
ImageButton button_speaker {
{ 17 * 8, 0, 2 * 8, 1 * 16 },
&bitmap_icon_speaker_mute,
@@ -188,6 +196,7 @@ private:
void on_bias_tee();
//void on_textentry();
void on_camera();
void on_title();
void refresh();
MessageHandlerRegistration message_handler_refresh {
@@ -199,6 +208,29 @@ private:
};
};
class InformationView : public View {
public:
InformationView(NavigationView& nav);
private:
static constexpr auto version_string = "v1.1.1";
NavigationView& nav_;
Rectangle backdrop {
{ 0, 0 * 16, 240, 16 },
{33, 33, 33}
};
Text version {
{2, 0, 11 * 8, 16},
version_string
};
LiveDateTime ltime {
{174, 0, 8 * 8, 16}
};
};
class BMPView : public View {
public:
BMPView(NavigationView& nav);
@@ -253,6 +285,7 @@ public:
private:
SystemStatusView status_view { navigation_view };
InformationView info_view { navigation_view };
NavigationView navigation_view { };
Context& context_;
};

View File

@@ -140,7 +140,8 @@ private:
}
};
PacketBuilder<BitPattern, NeverMatch, FixedLength> 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) {

View File

@@ -22,9 +22,25 @@
#include "sonde_packet.hpp"
#include "string_format.hpp"
#include <cstring>
//#include <complex>
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 {

View File

@@ -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<BiphaseMDecoder, BitRemapNone> reader_bi_m;
Type type_;
using packetReader = FieldReader<baseband::Packet, BitRemapByteReverse>; //baseband::Packet instead of BiphaseMDecoder
bool crc_ok_M10() const;
};
} /* namespace sonde */
#endif/*__SONDE_PACKET_H__*/
#endif/*__SONDE_PACKET_H__*/

View File

@@ -409,10 +409,26 @@ void Labels::paint(Painter& painter) {
void LiveDateTime::on_tick_second() {
rtcGetTime(&RTCD1, &datetime);
text = "";
text = to_string_dec_uint(datetime.month(), 2, '0') + "/" + to_string_dec_uint(datetime.day(), 2, '0') + " " +
to_string_dec_uint(datetime.hour(), 2, '0') + ":" + to_string_dec_uint(datetime.minute(), 2, '0');
if(date_enabled){
text = to_string_dec_uint(datetime.month(), 2, '0') + "/" + to_string_dec_uint(datetime.day(), 2, '0') + " ";
}
text = text + to_string_dec_uint(datetime.hour(), 2, '0') + ":" + to_string_dec_uint(datetime.minute(), 2, '0');
if(seconds_enabled){
text += ":";
if(init_delay==0)
text += to_string_dec_uint(datetime.second(), 2, '0');
else
{
// Placeholder while the seconds are not updated
text += "XX";
init_delay--;
}
}
set_dirty();
}
@@ -444,6 +460,14 @@ void LiveDateTime::paint(Painter& painter) {
);
}
void LiveDateTime::set_date_enabled(bool new_value){
this->date_enabled = new_value;
}
void LiveDateTime::set_seconds_enabled(bool new_value) {
this->seconds_enabled = new_value;
}
/* BigFrequency **********************************************************/
BigFrequency::BigFrequency(
@@ -625,7 +649,8 @@ void Console::write(std::string message) {
void Console::writeln(std::string message) {
write(message);
crlf();
write("\n");
//crlf();
}
void Console::paint(Painter&) {

View File

@@ -243,7 +243,10 @@ public:
~LiveDateTime();
void paint(Painter& painter) override;
void set_seconds_enabled(bool new_value);
void set_date_enabled(bool new_value);
std::string& string() {
return text;
}
@@ -251,6 +254,10 @@ public:
private:
void on_tick_second();
uint16_t init_delay = 4;
bool date_enabled = true;
bool seconds_enabled = false;
rtc::RTC datetime { };
SignalToken signal_token_tick_second { };
std::string text { };

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB