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 ba0804812..66b7900b4 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 bb474e83f..a63b7eb26 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 862e375d4..335c6d214 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 82d177e49..f3a2f3ac0 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 66b7900b4..b91771b4c 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 335c6d214..f43ff4787 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 b91771b4c..884749230 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 a63b7eb26..c55ec6805 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 1aa365e68..c639923e0 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 0555db8e4..a588ef959 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 0f4809dc8..1d09880df 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 f43ff4787..3d0e43ef5 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 f3a2f3ac0..7e4d3bce8 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 884749230..25667fe63 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 c639923e0..22b02d0b8 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 3d0e43ef5..d1d117073 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 f527b4853..6af138ba1 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 b91771b4c..25667fe63 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 a63b7eb26..c55ec6805 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 60981c70e..617f22ac7 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 c3216654e..bef08025e 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 1aa365e68..22b02d0b8 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 0555db8e4..a588ef959 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 0f4809dc8..1d09880df 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 acc305746..6cfb19bf0 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 da5ce7998..e38aea834 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 f43ff4787..d1d117073 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 f3a2f3ac0..7e4d3bce8 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);