From 2ceb49e4f2790f76c791c4791bc2c2725036619b Mon Sep 17 00:00:00 2001 From: teixeluis Date: Sat, 19 Jun 2021 23:41:06 +0100 Subject: [PATCH 1/5] Added more precise function to calculate NL (based on cmath lib). Created constants for some of the values scattered in the code. --- firmware/application/apps/ui_adsb_rx.cpp | 11 +++++--- firmware/application/apps/ui_adsb_rx.hpp | 32 +++++++++++++++++++++--- firmware/common/adsb.cpp | 16 +++++++++--- firmware/common/adsb.hpp | 4 +++ 4 files changed, 51 insertions(+), 12 deletions(-) diff --git a/firmware/application/apps/ui_adsb_rx.cpp b/firmware/application/apps/ui_adsb_rx.cpp index ba080481..66b7900b 100644 --- a/firmware/application/apps/ui_adsb_rx.cpp +++ b/firmware/application/apps/ui_adsb_rx.cpp @@ -205,7 +205,7 @@ void ADSBRxView::on_frame(const ADSBFrameMessage * message) { auto frame = message->frame; uint32_t ICAO_address = frame.get_ICAO_address(); - if (frame.check_CRC() && frame.get_ICAO_address()) { + if (frame.check_CRC() && ICAO_address) { rtcGetTime(&RTCD1, &datetime); auto& entry = ::on_packet(recent, ICAO_address); frame.set_rx_timestamp(datetime.minute() * 60 + datetime.second()); @@ -222,11 +222,14 @@ void ADSBRxView::on_frame(const ADSBFrameMessage * message) { uint8_t msg_sub = frame.get_msg_sub(); uint8_t * raw_data = frame.get_raw_data(); - if ((msg_type >= 1) && (msg_type <= 4)) { + if ((msg_type >= AIRCRAFT_ID_L) && (msg_type <= AIRCRAFT_ID_H)) { callsign = decode_frame_id(frame); entry.set_callsign(callsign); logentry+=callsign+" "; - } else if (((msg_type >= 9) && (msg_type <= 18)) || ((msg_type >= 20) && (msg_type <= 22))) { + } + // + else if (((msg_type >= AIRBORNE_POS_BARO_L) && (msg_type <= AIRBORNE_POS_BARO_H)) || + ((msg_type >= AIRBORNE_POS_GPS_L) && (msg_type <= AIRBORNE_POS_GPS_H))) { entry.set_frame_pos(frame, raw_data[6] & 4); if (entry.pos.valid) { @@ -242,7 +245,7 @@ void ADSBRxView::on_frame(const ADSBFrameMessage * message) { if (send_updates) details_view->update(entry); } - } else if(msg_type == 19 && msg_sub >= 1 && msg_sub <= 4){ + } else if(msg_type == AIRBORNE_VEL && msg_sub >= VEL_GND_SUBSONIC && msg_sub <= VEL_AIR_SUPERSONIC){ entry.set_frame_velo(frame); logentry += "Type:" + to_string_dec_uint(msg_sub) + " Hdg:" + to_string_dec_uint(entry.velo.heading) + diff --git a/firmware/application/apps/ui_adsb_rx.hpp b/firmware/application/apps/ui_adsb_rx.hpp index bb474e83..a63b7eb2 100644 --- a/firmware/application/apps/ui_adsb_rx.hpp +++ b/firmware/application/apps/ui_adsb_rx.hpp @@ -36,9 +36,33 @@ using namespace adsb; namespace ui { -#define ADSB_DECAY_A 10 // In seconds -#define ADSB_DECAY_B 30 -#define ADSB_DECAY_C 60 // Can be used for removing old entries, RecentEntries already caps to 64 +#define ADSB_DECAY_A 10 // In seconds +#define ADSB_DECAY_B 30 +#define ADSB_DECAY_C 60 // Can be used for removing old entries, RecentEntries already caps to 64 + +#define AIRCRAFT_ID_L 1 // aircraft ID message type (lowest type id) +#define AIRCRAFT_ID_H 4 // aircraft ID message type (highest type id) + +#define SURFACE_POS_L 5 // surface position (lowest type id) +#define SURFACE_POS_H 8 // surface position (highest type id) + +#define AIRBORNE_POS_BARO_L 9 // airborne position (lowest type id) +#define AIRBORNE_POS_BARO_H 18 // airborne position (highest type id) + +#define AIRBORNE_VEL 19 // airborne velocities + +#define AIRBORNE_POS_GPS_L 20 // airborne position (lowest type id) +#define AIRBORNE_POS_GPS_H 22 // airborne position (highest type id) + +#define RESERVED_L 23 // reserved for other uses +#define RESERVED_H 31 // reserved for other uses + +#define VEL_GND_SUBSONIC 1 +#define VEL_GND_SUPERSONIC 2 +#define VEL_AIR_SUBSONIC 3 +#define VEL_AIR_SUPERSONIC 4 + +#define O_E_FRAME_TIMEOUT 20 // timeout between odd and even frames struct AircraftRecentEntry { using Key = uint32_t; @@ -82,7 +106,7 @@ struct AircraftRecentEntry { frame_pos_odd = frame; if (!frame_pos_even.empty() && !frame_pos_odd.empty()) { - if (abs(frame_pos_even.get_rx_timestamp() - frame_pos_odd.get_rx_timestamp()) < 20) + if (abs(frame_pos_even.get_rx_timestamp() - frame_pos_odd.get_rx_timestamp()) < O_E_FRAME_TIMEOUT) pos = decode_frame_pos(frame_pos_even, frame_pos_odd); } } diff --git a/firmware/common/adsb.cpp b/firmware/common/adsb.cpp index 862e375d..335c6d21 100644 --- a/firmware/common/adsb.cpp +++ b/firmware/common/adsb.cpp @@ -141,7 +141,11 @@ float cpr_mod(float a, float b) { return a - (b * floor(a / b)); } -int cpr_NL(float lat) { +int cpr_NL_precise(float lat) { + return (int) floor(2 * PI / acos(1 - ((1 - cos(PI / (2 * NZ))) / pow(cos(PI * lat / 180), 2)))); +} + +int cpr_NL_approx(float lat) { if (lat < 0) lat = -lat; // Symmetry @@ -150,7 +154,11 @@ int cpr_NL(float lat) { return 59 - c; } - return 1; + return 1; +} + +int cpr_NL(float lat) { + return cpr_NL_precise(lat); } int cpr_N(float lat, int is_odd) { @@ -258,7 +266,7 @@ adsb_pos decode_frame_pos(ADSBFrame& frame_even, ADSBFrame& frame_odd) { // Compute longitude if (time_even > time_odd) { - // Use even frame + // Use even frame2 ni = cpr_N(latE, 0); Dlon = 360.0 / ni; @@ -279,7 +287,7 @@ adsb_pos decode_frame_pos(ADSBFrame& frame_even, ADSBFrame& frame_odd) { position.latitude = latO; } - if (position.longitude > 180) position.longitude -= 360; + if (position.longitude >= 180) position.longitude -= 360; position.valid = true; diff --git a/firmware/common/adsb.hpp b/firmware/common/adsb.hpp index 82d177e4..f3a2f3ac 100644 --- a/firmware/common/adsb.hpp +++ b/firmware/common/adsb.hpp @@ -83,6 +83,10 @@ const float adsb_lat_lut[58] = { 86.53536998, 87.00000000 }; +const float PI = 3.14159265358979323846; + +const float NZ = 15; + void make_frame_adsb(ADSBFrame& frame, const uint32_t ICAO_address); void encode_frame_id(ADSBFrame& frame, const uint32_t ICAO_address, const std::string& callsign); From 97349b06ef32f26df046f135cb87bdc645cb7fad Mon Sep 17 00:00:00 2001 From: teixeluis Date: Wed, 23 Jun 2021 19:54:34 +0100 Subject: [PATCH 2/5] Fixes to the log and screen rendering of the geo coordinates. --- firmware/application/apps/ui_adsb_rx.cpp | 37 ++++++++++++++++++++---- firmware/common/adsb.cpp | 6 ++++ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/firmware/application/apps/ui_adsb_rx.cpp b/firmware/application/apps/ui_adsb_rx.cpp index 66b7900b..b91771b4 100644 --- a/firmware/application/apps/ui_adsb_rx.cpp +++ b/firmware/application/apps/ui_adsb_rx.cpp @@ -20,6 +20,7 @@ * Boston, MA 02110-1301, USA. */ + #include "ui_adsb_rx.hpp" #include "ui_alphanum.hpp" @@ -233,14 +234,38 @@ void ADSBRxView::on_frame(const ADSBFrameMessage * message) { entry.set_frame_pos(frame, raw_data[6] & 4); if (entry.pos.valid) { + std::string latitude_str(8, '\0'); + std::string longitude_str(8, '\0'); + + int written = std::snprintf(&latitude_str[0], latitude_str.size(), "%.2f", entry.pos.latitude); + latitude_str.resize(written); + + written = std::snprintf(&longitude_str[0], longitude_str.size(), "%.2f", entry.pos.longitude); + longitude_str.resize(written); + str_info = "Alt:" + to_string_dec_int(entry.pos.altitude) + - " Lat:" + to_string_dec_int(entry.pos.latitude) + - "." + to_string_dec_int((int)abs(entry.pos.latitude * 1000) % 100, 2, '0') + - " Lon:" + to_string_dec_int(entry.pos.longitude) + - "." + to_string_dec_int((int)abs(entry.pos.longitude * 1000) % 100, 2, '0'); - + " Lat:" + latitude_str + + " Lon:" + longitude_str; + + // printing the coordinates in the log file with more + // resolution, as we are not constrained by screen + // real estate there: + + latitude_str.resize(13, '\0'); + longitude_str.resize(13, '\0'); + + written = std::snprintf(&latitude_str[0], latitude_str.size(), "%.7f", entry.pos.latitude); + latitude_str.resize(written); + + written = std::snprintf(&longitude_str[0], longitude_str.size(), "%.7f", entry.pos.longitude); + longitude_str.resize(written); + + std::string log_info = "Alt:" + to_string_dec_int(entry.pos.altitude) + + " Lat:" + latitude_str + + " Lon:" + longitude_str; + entry.set_info_string(str_info); - logentry+=str_info+ " "; + logentry+=log_info + " "; if (send_updates) details_view->update(entry); diff --git a/firmware/common/adsb.cpp b/firmware/common/adsb.cpp index 335c6d21..f43ff478 100644 --- a/firmware/common/adsb.cpp +++ b/firmware/common/adsb.cpp @@ -158,6 +158,12 @@ int cpr_NL_approx(float lat) { } int cpr_NL(float lat) { + // TODO prove that the approximate function is good + // enough for the precision we need. Uncomment if + // that is true: + + //return cpr_NL_approx(lat); + return cpr_NL_precise(lat); } From b09439afb118c3b23d2509ce42d221b027c5625a Mon Sep 17 00:00:00 2001 From: teixeluis Date: Wed, 23 Jun 2021 23:52:15 +0100 Subject: [PATCH 3/5] Fixed the mixing of aircraft coordinates in the details view, by checking if the ICAO address of the frame and the current item in the details view match. Slight refactor by placing the decimal to string conversion function into the string_format module. --- firmware/application/apps/ui_adsb_rx.cpp | 38 +++++++++--------------- firmware/application/apps/ui_adsb_rx.hpp | 2 ++ firmware/application/string_format.cpp | 17 +++++++++++ firmware/application/string_format.hpp | 2 ++ firmware/application/ui/ui_geomap.cpp | 14 ++------- firmware/common/adsb.cpp | 12 ++++---- firmware/common/adsb.hpp | 2 +- 7 files changed, 45 insertions(+), 42 deletions(-) diff --git a/firmware/application/apps/ui_adsb_rx.cpp b/firmware/application/apps/ui_adsb_rx.cpp index b91771b4..88474923 100644 --- a/firmware/application/apps/ui_adsb_rx.cpp +++ b/firmware/application/apps/ui_adsb_rx.cpp @@ -20,6 +20,7 @@ * Boston, MA 02110-1301, USA. */ +#include #include "ui_adsb_rx.hpp" #include "ui_alphanum.hpp" @@ -234,49 +235,38 @@ void ADSBRxView::on_frame(const ADSBFrameMessage * message) { entry.set_frame_pos(frame, raw_data[6] & 4); if (entry.pos.valid) { - std::string latitude_str(8, '\0'); - std::string longitude_str(8, '\0'); - - int written = std::snprintf(&latitude_str[0], latitude_str.size(), "%.2f", entry.pos.latitude); - latitude_str.resize(written); - - written = std::snprintf(&longitude_str[0], longitude_str.size(), "%.2f", entry.pos.longitude); - longitude_str.resize(written); - str_info = "Alt:" + to_string_dec_int(entry.pos.altitude) + - " Lat:" + latitude_str + - " Lon:" + longitude_str; + " Lat:" + to_string_decimal(entry.pos.latitude, 2) + + " Lon:" + to_string_decimal(entry.pos.longitude, 2); // printing the coordinates in the log file with more // resolution, as we are not constrained by screen // real estate there: - latitude_str.resize(13, '\0'); - longitude_str.resize(13, '\0'); - - written = std::snprintf(&latitude_str[0], latitude_str.size(), "%.7f", entry.pos.latitude); - latitude_str.resize(written); - - written = std::snprintf(&longitude_str[0], longitude_str.size(), "%.7f", entry.pos.longitude); - longitude_str.resize(written); - std::string log_info = "Alt:" + to_string_dec_int(entry.pos.altitude) + - " Lat:" + latitude_str + - " Lon:" + longitude_str; + " Lat:" + to_string_decimal(entry.pos.latitude, 7) + + " Lon:" + to_string_decimal(entry.pos.longitude, 7); entry.set_info_string(str_info); logentry+=log_info + " "; - if (send_updates) + if(send_updates && details_view->get_current_entry().ICAO_address == ICAO_address) { + // we only want to update the details view if the frame + // we received has the same ICAO address, i.e. belongs to + // the same aircraft: details_view->update(entry); + } } } else if(msg_type == AIRBORNE_VEL && msg_sub >= VEL_GND_SUBSONIC && msg_sub <= VEL_AIR_SUPERSONIC){ entry.set_frame_velo(frame); logentry += "Type:" + to_string_dec_uint(msg_sub) + " Hdg:" + to_string_dec_uint(entry.velo.heading) + " Spd: "+ to_string_dec_int(entry.velo.speed); - if (send_updates) + + if (send_updates && details_view->get_current_entry().ICAO_address == ICAO_address) { + // same here: details_view->update(entry); + } } } recent_entries_view.set_dirty(); diff --git a/firmware/application/apps/ui_adsb_rx.hpp b/firmware/application/apps/ui_adsb_rx.hpp index a63b7eb2..c55ec680 100644 --- a/firmware/application/apps/ui_adsb_rx.hpp +++ b/firmware/application/apps/ui_adsb_rx.hpp @@ -161,6 +161,8 @@ public: void update(const AircraftRecentEntry& entry); std::string title() const override { return "Details"; }; + + AircraftRecentEntry get_current_entry() { return entry_copy; } private: AircraftRecentEntry entry_copy { 0 }; diff --git a/firmware/application/string_format.cpp b/firmware/application/string_format.cpp index 1aa365e6..c639923e 100644 --- a/firmware/application/string_format.cpp +++ b/firmware/application/string_format.cpp @@ -112,6 +112,23 @@ std::string to_string_dec_int( return q; } +std::string to_string_decimal(float decimal, int8_t precision) { + double integer_part; + double fractional_part; + + std::string result; + + fractional_part = modf(decimal, &integer_part) * pow(10, precision); + + if (fractional_part < 0) { + fractional_part = -fractional_part; + } + + result = to_string_dec_int(integer_part) + "." + to_string_dec_uint(fractional_part, precision); + + return result; +} + std::string to_string_short_freq(const uint64_t f) { auto final_str = to_string_dec_int(f / 1000000,4) + "." + to_string_dec_int((f / 100) % 10000, 4, '0'); return final_str; diff --git a/firmware/application/string_format.hpp b/firmware/application/string_format.hpp index 0555db8e..a588ef95 100644 --- a/firmware/application/string_format.hpp +++ b/firmware/application/string_format.hpp @@ -43,6 +43,8 @@ const char unit_prefix[7] { 'n', 'u', 'm', 0, 'k', 'M', 'G' }; std::string to_string_bin(const uint32_t n, const uint8_t l = 0); std::string to_string_dec_uint(const uint32_t n, const int32_t l = 0, const char fill = ' '); std::string to_string_dec_int(const int32_t n, const int32_t l = 0, const char fill = 0); +std::string to_string_decimal(float decimal, int8_t precision); + std::string to_string_hex(const uint64_t n, const int32_t l = 0); std::string to_string_hex_array(uint8_t * const array, const int32_t l = 0); diff --git a/firmware/application/ui/ui_geomap.cpp b/firmware/application/ui/ui_geomap.cpp index 0f4809dc..1d09880d 100644 --- a/firmware/application/ui/ui_geomap.cpp +++ b/firmware/application/ui/ui_geomap.cpp @@ -63,17 +63,9 @@ GeoPos::GeoPos( 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)); + + text_lat_decimal.set(to_string_decimal(lat_value, 5)); + text_lon_decimal.set(to_string_decimal(lon_value, 5)); if (on_change && report_change) on_change(altitude(), lat_value, lon_value); diff --git a/firmware/common/adsb.cpp b/firmware/common/adsb.cpp index f43ff478..3d0e43ef 100644 --- a/firmware/common/adsb.cpp +++ b/firmware/common/adsb.cpp @@ -199,18 +199,18 @@ void encode_frame_pos(ADSBFrame& frame, const uint32_t ICAO_address, const int32 // CPR encoding // Info from: http://antena.fe.uni-lj.si/literatura/Razno/Avionika/modes/CPRencoding.pdf - delta_lat = 360.0 / ((4.0 * 15.0) - time_parity); // NZ = 15 - yz = floor(131072.0 * (cpr_mod(latitude, delta_lat) / delta_lat) + 0.5); - rlat = delta_lat * ((yz / 131072.0) + floor(latitude / delta_lat)); + delta_lat = 360.0 / ((4.0 * NZ) - time_parity); // NZ = 15 + yz = floor(CPR_MAX_VALUE * (cpr_mod(latitude, delta_lat) / delta_lat) + 0.5); + rlat = delta_lat * ((yz / CPR_MAX_VALUE) + floor(latitude / delta_lat)); if ((cpr_NL(rlat) - time_parity) > 0) delta_lon = 360.0 / cpr_N(rlat, time_parity); else delta_lon = 360.0; - xz = floor(131072.0 * (cpr_mod(longitude, delta_lon) / delta_lon) + 0.5); + xz = floor(CPR_MAX_VALUE * (cpr_mod(longitude, delta_lon) / delta_lon) + 0.5); - lat = cpr_mod(yz, 131072.0); - lon = cpr_mod(xz, 131072.0); + lat = cpr_mod(yz, CPR_MAX_VALUE); + lon = cpr_mod(xz, CPR_MAX_VALUE); frame.push_byte((altitude_coded << 4) | ((uint32_t)time_parity << 2) | (lat >> 15)); // T = 0 frame.push_byte(lat >> 7); diff --git a/firmware/common/adsb.hpp b/firmware/common/adsb.hpp index f3a2f3ac..7e4d3bce 100644 --- a/firmware/common/adsb.hpp +++ b/firmware/common/adsb.hpp @@ -85,7 +85,7 @@ const float adsb_lat_lut[58] = { const float PI = 3.14159265358979323846; -const float NZ = 15; +const float NZ = 15.0; void make_frame_adsb(ADSBFrame& frame, const uint32_t ICAO_address); From 22e8add4dd8a1577a23e3c2a89182eff0fbdc9e4 Mon Sep 17 00:00:00 2001 From: teixeluis Date: Thu, 24 Jun 2021 15:10:06 +0100 Subject: [PATCH 4/5] Fixed left padding of the decimal part of the numbers. --- firmware/application/apps/ui_adsb_rx.cpp | 8 ++++---- firmware/application/string_format.cpp | 2 +- firmware/common/adsb.cpp | 4 +++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/firmware/application/apps/ui_adsb_rx.cpp b/firmware/application/apps/ui_adsb_rx.cpp index 88474923..25667fe6 100644 --- a/firmware/application/apps/ui_adsb_rx.cpp +++ b/firmware/application/apps/ui_adsb_rx.cpp @@ -250,10 +250,10 @@ void ADSBRxView::on_frame(const ADSBFrameMessage * message) { entry.set_info_string(str_info); logentry+=log_info + " "; + // we only want to update the details view if the frame + // we received has the same ICAO address, i.e. belongs to + // the same aircraft: if(send_updates && details_view->get_current_entry().ICAO_address == ICAO_address) { - // we only want to update the details view if the frame - // we received has the same ICAO address, i.e. belongs to - // the same aircraft: details_view->update(entry); } } @@ -263,8 +263,8 @@ void ADSBRxView::on_frame(const ADSBFrameMessage * message) { " Hdg:" + to_string_dec_uint(entry.velo.heading) + " Spd: "+ to_string_dec_int(entry.velo.speed); + // same here: if (send_updates && details_view->get_current_entry().ICAO_address == ICAO_address) { - // same here: details_view->update(entry); } } diff --git a/firmware/application/string_format.cpp b/firmware/application/string_format.cpp index c639923e..22b02d0b 100644 --- a/firmware/application/string_format.cpp +++ b/firmware/application/string_format.cpp @@ -124,7 +124,7 @@ std::string to_string_decimal(float decimal, int8_t precision) { fractional_part = -fractional_part; } - result = to_string_dec_int(integer_part) + "." + to_string_dec_uint(fractional_part, precision); + result = to_string_dec_int(integer_part) + "." + to_string_dec_uint(fractional_part, precision, '0'); return result; } diff --git a/firmware/common/adsb.cpp b/firmware/common/adsb.cpp index 3d0e43ef..d1d11707 100644 --- a/firmware/common/adsb.cpp +++ b/firmware/common/adsb.cpp @@ -160,7 +160,9 @@ int cpr_NL_approx(float lat) { int cpr_NL(float lat) { // TODO prove that the approximate function is good // enough for the precision we need. Uncomment if - // that is true: + // that is true. No performance penalty was noticed + // from testing, but if you find it might be an issue, + // switch to cpr_NL_approx() instead: //return cpr_NL_approx(lat); From fe806b7bdc3cf611d3a47a053e8d3a8f2ad762fd Mon Sep 17 00:00:00 2001 From: teixeluis Date: Wed, 23 Jun 2021 23:52:15 +0100 Subject: [PATCH 5/5] Fixed the mixing of aircraft coordinates in the details view, by checking if the ICAO address of the frame and the current item in the details view match. Slight refactor by placing the decimal to string conversion function into the string_format module. Added fix in the scope of issue #365 FrequencyStepView field in TransmitterView class FrequencyStepView field in TransmitterView class Update ui_transmitter.hpp Update credits Fixed left padding of the decimal part of the numbers. --- firmware/application/apps/ui_about_simple.cpp | 3 +- firmware/application/apps/ui_adsb_rx.cpp | 38 +++++++------------ firmware/application/apps/ui_adsb_rx.hpp | 2 + firmware/application/radio.cpp | 14 +++---- firmware/application/receiver_model.cpp | 8 ++++ firmware/application/string_format.cpp | 17 +++++++++ firmware/application/string_format.hpp | 2 + firmware/application/ui/ui_geomap.cpp | 14 ++----- firmware/application/ui/ui_transmitter.cpp | 6 +++ firmware/application/ui/ui_transmitter.hpp | 10 +++-- firmware/common/adsb.cpp | 16 ++++---- firmware/common/adsb.hpp | 2 +- 12 files changed, 77 insertions(+), 55 deletions(-) diff --git a/firmware/application/apps/ui_about_simple.cpp b/firmware/application/apps/ui_about_simple.cpp index f527b485..6af138ba 100644 --- a/firmware/application/apps/ui_about_simple.cpp +++ b/firmware/application/apps/ui_about_simple.cpp @@ -31,8 +31,9 @@ namespace ui console.writeln("N0vaPixel,klockee,GullCode"); console.writeln("jamesshao8,ITAxReal,rascafr"); console.writeln("mcules,dqs105,strijar"); - console.writeln("zhang00963,RedFox-Fr"); + console.writeln("zhang00963,RedFox-Fr,aldude999"); console.writeln("East2West,fossum,ArjanOnwezen"); + console.writeln("vXxOinvizioNxX,teixeluis"); console.writeln(""); break; diff --git a/firmware/application/apps/ui_adsb_rx.cpp b/firmware/application/apps/ui_adsb_rx.cpp index b91771b4..25667fe6 100644 --- a/firmware/application/apps/ui_adsb_rx.cpp +++ b/firmware/application/apps/ui_adsb_rx.cpp @@ -20,6 +20,7 @@ * Boston, MA 02110-1301, USA. */ +#include #include "ui_adsb_rx.hpp" #include "ui_alphanum.hpp" @@ -234,49 +235,38 @@ void ADSBRxView::on_frame(const ADSBFrameMessage * message) { entry.set_frame_pos(frame, raw_data[6] & 4); if (entry.pos.valid) { - std::string latitude_str(8, '\0'); - std::string longitude_str(8, '\0'); - - int written = std::snprintf(&latitude_str[0], latitude_str.size(), "%.2f", entry.pos.latitude); - latitude_str.resize(written); - - written = std::snprintf(&longitude_str[0], longitude_str.size(), "%.2f", entry.pos.longitude); - longitude_str.resize(written); - str_info = "Alt:" + to_string_dec_int(entry.pos.altitude) + - " Lat:" + latitude_str + - " Lon:" + longitude_str; + " Lat:" + to_string_decimal(entry.pos.latitude, 2) + + " Lon:" + to_string_decimal(entry.pos.longitude, 2); // printing the coordinates in the log file with more // resolution, as we are not constrained by screen // real estate there: - latitude_str.resize(13, '\0'); - longitude_str.resize(13, '\0'); - - written = std::snprintf(&latitude_str[0], latitude_str.size(), "%.7f", entry.pos.latitude); - latitude_str.resize(written); - - written = std::snprintf(&longitude_str[0], longitude_str.size(), "%.7f", entry.pos.longitude); - longitude_str.resize(written); - std::string log_info = "Alt:" + to_string_dec_int(entry.pos.altitude) + - " Lat:" + latitude_str + - " Lon:" + longitude_str; + " Lat:" + to_string_decimal(entry.pos.latitude, 7) + + " Lon:" + to_string_decimal(entry.pos.longitude, 7); entry.set_info_string(str_info); logentry+=log_info + " "; - if (send_updates) + // we only want to update the details view if the frame + // we received has the same ICAO address, i.e. belongs to + // the same aircraft: + if(send_updates && details_view->get_current_entry().ICAO_address == ICAO_address) { details_view->update(entry); + } } } else if(msg_type == AIRBORNE_VEL && msg_sub >= VEL_GND_SUBSONIC && msg_sub <= VEL_AIR_SUPERSONIC){ entry.set_frame_velo(frame); logentry += "Type:" + to_string_dec_uint(msg_sub) + " Hdg:" + to_string_dec_uint(entry.velo.heading) + " Spd: "+ to_string_dec_int(entry.velo.speed); - if (send_updates) + + // same here: + if (send_updates && details_view->get_current_entry().ICAO_address == ICAO_address) { details_view->update(entry); + } } } recent_entries_view.set_dirty(); diff --git a/firmware/application/apps/ui_adsb_rx.hpp b/firmware/application/apps/ui_adsb_rx.hpp index a63b7eb2..c55ec680 100644 --- a/firmware/application/apps/ui_adsb_rx.hpp +++ b/firmware/application/apps/ui_adsb_rx.hpp @@ -161,6 +161,8 @@ public: void update(const AircraftRecentEntry& entry); std::string title() const override { return "Details"; }; + + AircraftRecentEntry get_current_entry() { return entry_copy; } private: AircraftRecentEntry entry_copy { 0 }; diff --git a/firmware/application/radio.cpp b/firmware/application/radio.cpp index 60981c70..617f22ac 100644 --- a/firmware/application/radio.cpp +++ b/firmware/application/radio.cpp @@ -111,14 +111,12 @@ void set_direction(const rf::Direction new_direction) { // Hack to fix the CPLD (clocking ?) bug: toggle CPLD SRAM overlay depending on new direction // Use CPLD's EEPROM config when transmitting // Use the SRAM overlay when receiving - if (direction != new_direction) { - if (new_direction == rf::Direction::Transmit) { - hackrf::cpld::init_from_eeprom(); - } else { - if( !hackrf::cpld::load_sram() ) { - chSysHalt(); - } - } + + // teixeluis: undone "Hack to fix the CPLD (clocking ?) bug". + // Apparently with current CPLD code from the hackrf repo, + // toggling CPLD overlay should no longer be necessary: + if (direction != new_direction && new_direction == rf::Direction::Transmit) { + hackrf::cpld::init_from_eeprom(); } direction = new_direction; diff --git a/firmware/application/receiver_model.cpp b/firmware/application/receiver_model.cpp index c3216654..bef08025 100644 --- a/firmware/application/receiver_model.cpp +++ b/firmware/application/receiver_model.cpp @@ -171,7 +171,11 @@ void ReceiverModel::enable() { update_baseband_bandwidth(); update_sampling_rate(); update_modulation(); + + // TODO: would challenge if this should belong to the + // receiver_model namespace: update_headphone_volume(); + led_rx.on(); } @@ -182,6 +186,10 @@ void ReceiverModel::disable() { // TODO: Responsibility for enabling/disabling the radio is muddy. // Some happens in ReceiverModel, some inside radio namespace. radio::disable(); + + // TODO: we are doing this repeatedly in different levels of the + // call stack. Keeping it for now, but there seem to be too many + // redundant calls: led_rx.off(); } diff --git a/firmware/application/string_format.cpp b/firmware/application/string_format.cpp index 1aa365e6..22b02d0b 100644 --- a/firmware/application/string_format.cpp +++ b/firmware/application/string_format.cpp @@ -112,6 +112,23 @@ std::string to_string_dec_int( return q; } +std::string to_string_decimal(float decimal, int8_t precision) { + double integer_part; + double fractional_part; + + std::string result; + + fractional_part = modf(decimal, &integer_part) * pow(10, precision); + + if (fractional_part < 0) { + fractional_part = -fractional_part; + } + + result = to_string_dec_int(integer_part) + "." + to_string_dec_uint(fractional_part, precision, '0'); + + return result; +} + std::string to_string_short_freq(const uint64_t f) { auto final_str = to_string_dec_int(f / 1000000,4) + "." + to_string_dec_int((f / 100) % 10000, 4, '0'); return final_str; diff --git a/firmware/application/string_format.hpp b/firmware/application/string_format.hpp index 0555db8e..a588ef95 100644 --- a/firmware/application/string_format.hpp +++ b/firmware/application/string_format.hpp @@ -43,6 +43,8 @@ const char unit_prefix[7] { 'n', 'u', 'm', 0, 'k', 'M', 'G' }; std::string to_string_bin(const uint32_t n, const uint8_t l = 0); std::string to_string_dec_uint(const uint32_t n, const int32_t l = 0, const char fill = ' '); std::string to_string_dec_int(const int32_t n, const int32_t l = 0, const char fill = 0); +std::string to_string_decimal(float decimal, int8_t precision); + std::string to_string_hex(const uint64_t n, const int32_t l = 0); std::string to_string_hex_array(uint8_t * const array, const int32_t l = 0); diff --git a/firmware/application/ui/ui_geomap.cpp b/firmware/application/ui/ui_geomap.cpp index 0f4809dc..1d09880d 100644 --- a/firmware/application/ui/ui_geomap.cpp +++ b/firmware/application/ui/ui_geomap.cpp @@ -63,17 +63,9 @@ GeoPos::GeoPos( 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)); + + text_lat_decimal.set(to_string_decimal(lat_value, 5)); + text_lon_decimal.set(to_string_decimal(lon_value, 5)); if (on_change && report_change) on_change(altitude(), lat_value, lon_value); diff --git a/firmware/application/ui/ui_transmitter.cpp b/firmware/application/ui/ui_transmitter.cpp index acc30574..6cfb19bf 100644 --- a/firmware/application/ui/ui_transmitter.cpp +++ b/firmware/application/ui/ui_transmitter.cpp @@ -103,6 +103,7 @@ void TransmitterView::set_transmitting(const bool transmitting) { void TransmitterView::on_show() { field_frequency.set_value(transmitter_model.tuning_frequency()); + field_frequency_step.set_by_value(receiver_model.frequency_step()); field_gain.set_value(transmitter_model.tx_gain()); field_amp.set_value(transmitter_model.rf_amp() ? 14 : 0); @@ -122,6 +123,7 @@ TransmitterView::TransmitterView( add_children({ &field_frequency, + &field_frequency_step, &text_gain, &field_gain, &button_start, @@ -157,6 +159,10 @@ TransmitterView::TransmitterView( if (on_edit_frequency) on_edit_frequency(); }; + + field_frequency_step.on_change = [this](size_t, OptionsField::value_t v) { + this->field_frequency.set_step(v); + }; field_gain.on_change = [this](uint32_t tx_gain) { on_tx_gain_changed(tx_gain); diff --git a/firmware/application/ui/ui_transmitter.hpp b/firmware/application/ui/ui_transmitter.hpp index da5ce799..e38aea83 100644 --- a/firmware/application/ui/ui_transmitter.hpp +++ b/firmware/application/ui/ui_transmitter.hpp @@ -124,11 +124,11 @@ private: }; Text text_bw { - { 11 * 8, 1 * 8, 9 * 8, 1 * 16 }, - "BW: kHz" + { 18 * 8, 1 * 8, 3 * 8, 1 * 16 }, + "kHz" }; NumberField field_bw { - { 14 * 8, 1 * 8 }, + { 15 * 8, 1 * 8 }, 3, { 1, 150 }, 1, @@ -152,6 +152,10 @@ private: { 21 * 8, 1 * 8, 9 * 8, 32 }, "START" }; + + FrequencyStepView field_frequency_step { + { 10 * 8 - 4, 1 * 8 }, + }; void on_tuning_frequency_changed(rf::Frequency f); void on_channel_bandwidth_changed(uint32_t channel_bandwidth); diff --git a/firmware/common/adsb.cpp b/firmware/common/adsb.cpp index f43ff478..d1d11707 100644 --- a/firmware/common/adsb.cpp +++ b/firmware/common/adsb.cpp @@ -160,7 +160,9 @@ int cpr_NL_approx(float lat) { int cpr_NL(float lat) { // TODO prove that the approximate function is good // enough for the precision we need. Uncomment if - // that is true: + // that is true. No performance penalty was noticed + // from testing, but if you find it might be an issue, + // switch to cpr_NL_approx() instead: //return cpr_NL_approx(lat); @@ -199,18 +201,18 @@ void encode_frame_pos(ADSBFrame& frame, const uint32_t ICAO_address, const int32 // CPR encoding // Info from: http://antena.fe.uni-lj.si/literatura/Razno/Avionika/modes/CPRencoding.pdf - delta_lat = 360.0 / ((4.0 * 15.0) - time_parity); // NZ = 15 - yz = floor(131072.0 * (cpr_mod(latitude, delta_lat) / delta_lat) + 0.5); - rlat = delta_lat * ((yz / 131072.0) + floor(latitude / delta_lat)); + delta_lat = 360.0 / ((4.0 * NZ) - time_parity); // NZ = 15 + yz = floor(CPR_MAX_VALUE * (cpr_mod(latitude, delta_lat) / delta_lat) + 0.5); + rlat = delta_lat * ((yz / CPR_MAX_VALUE) + floor(latitude / delta_lat)); if ((cpr_NL(rlat) - time_parity) > 0) delta_lon = 360.0 / cpr_N(rlat, time_parity); else delta_lon = 360.0; - xz = floor(131072.0 * (cpr_mod(longitude, delta_lon) / delta_lon) + 0.5); + xz = floor(CPR_MAX_VALUE * (cpr_mod(longitude, delta_lon) / delta_lon) + 0.5); - lat = cpr_mod(yz, 131072.0); - lon = cpr_mod(xz, 131072.0); + lat = cpr_mod(yz, CPR_MAX_VALUE); + lon = cpr_mod(xz, CPR_MAX_VALUE); frame.push_byte((altitude_coded << 4) | ((uint32_t)time_parity << 2) | (lat >> 15)); // T = 0 frame.push_byte(lat >> 7); diff --git a/firmware/common/adsb.hpp b/firmware/common/adsb.hpp index f3a2f3ac..7e4d3bce 100644 --- a/firmware/common/adsb.hpp +++ b/firmware/common/adsb.hpp @@ -85,7 +85,7 @@ const float adsb_lat_lut[58] = { const float PI = 3.14159265358979323846; -const float NZ = 15; +const float NZ = 15.0; void make_frame_adsb(ADSBFrame& frame, const uint32_t ICAO_address);