Compare commits

...
5 Commits
Author SHA1 Message Date
PoliEcho 831501ea41 fix possible wraparound 2026-08-11 12:06:03 +02:00
PoliEcho abf1226b47 bug fixes 2026-08-08 11:24:27 +02:00
PoliEcho 6ac93f0a5b make compilation better 2026-08-08 09:49:25 +02:00
PoliEcho 66bdf9327a add arc and alt 2026-08-07 16:36:56 +02:00
PoliEcho 95225a5811 add usage of text 2026-08-07 15:37:13 +02:00
13 changed files with 325 additions and 154 deletions
+28 -49
View File
@@ -1,6 +1,13 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
option(BUILD_FOR_PICO "Build for Raspberry Pi Pico" ON) set(BUILD_PLATFORM "Linux" CACHE STRING "Target platform: Pico or Linux")
set_property(CACHE BUILD_PLATFORM PROPERTY STRINGS Pico Linux)
if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/platform_${BUILD_PLATFORM}_pre.cmake")
message(FATAL_ERROR "Unknown BUILD_PLATFORM '${BUILD_PLATFORM}' (no cmake/platform_${BUILD_PLATFORM}_pre.cmake found)")
endif()
string(TOLOWER ${BUILD_PLATFORM} BUILD_PLATFORM_LOWER)
set(GEOGRAPHICLIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/geographiclib) set(GEOGRAPHICLIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/geographiclib)
@@ -10,55 +17,27 @@ set(BUILD_DOCUMENTATION OFF CACHE BOOL "" FORCE)
set(BUILD_BOTH_LIBRARIES OFF CACHE BOOL "" FORCE) set(BUILD_BOTH_LIBRARIES OFF CACHE BOOL "" FORCE)
set(PACKAGE_DEBIAN OFF CACHE BOOL "" FORCE) set(PACKAGE_DEBIAN OFF CACHE BOOL "" FORCE)
# Automatically collect core sources and platform-specific HAL files # Pre-project platform setup (e.g. Pico's pico_sdk_import.cmake must run
# before project(), and it must set PROJECT_LANGUAGES).
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/platform_${BUILD_PLATFORM}_pre.cmake)
project(p-rad ${PROJECT_LANGUAGES})
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_compile_options(-Wall -Wextra -Wpedantic -Wno-write-strings)
# NOTE: don't use add_link_options/add_compile_options here - they apply to
# every target including pico-sdk's bs2_default, whose binary gets fully
# garbage-collected. Scope them to the p-rad target instead (see platform files).
# Automatically collect core sources and platform-specific HAL files.
# HAL files are matched by suffix convention: src/hal/*_<platform>.cpp
file(GLOB CORE_SOURCES CONFIGURE_DEPENDS "src/core/*.cpp" "src/core/*.c") file(GLOB CORE_SOURCES CONFIGURE_DEPENDS "src/core/*.cpp" "src/core/*.c")
file(GLOB HAL_PICO_SOURCES CONFIGURE_DEPENDS "src/hal/*_pico.cpp") file(GLOB HAL_SOURCES CONFIGURE_DEPENDS "src/hal/*_${BUILD_PLATFORM_LOWER}.cpp")
file(GLOB HAL_LINUX_SOURCES CONFIGURE_DEPENDS "src/hal/*_linux.cpp")
if(BUILD_FOR_PICO)
set(PICO_BOARD pico_w CACHE STRING "Board type")
include(pico_sdk_import.cmake)
project(p-rad C CXX ASM)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
pico_sdk_init()
add_subdirectory(${GEOGRAPHICLIB_DIR} EXCLUDE_FROM_ALL)
target_compile_options(GeographicLib INTERFACE -fexceptions -frtti)
add_executable(p-rad
src/main.cpp
${CORE_SOURCES}
${HAL_PICO_SOURCES}
)
target_compile_definitions(p-rad PRIVATE PICO_BUILD)
target_include_directories(p-rad PRIVATE src)
target_link_libraries(p-rad pico_stdlib pico_cyw43_arch_lwip_threadsafe_background hardware_rtc GeographicLib)
pico_enable_stdio_usb(p-rad 1)
pico_enable_stdio_uart(p-rad 0)
pico_add_extra_outputs(p-rad)
else()
project(p-rad CXX)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_subdirectory(${GEOGRAPHICLIB_DIR} EXCLUDE_FROM_ALL) add_subdirectory(${GEOGRAPHICLIB_DIR} EXCLUDE_FROM_ALL)
add_executable(p-rad # Post-project platform setup: add_executable, link libraries, platform-specific calls.
src/main.cpp include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/platform_${BUILD_PLATFORM}.cmake)
${CORE_SOURCES}
${HAL_LINUX_SOURCES}
)
target_include_directories(p-rad PRIVATE src)
find_package(Threads REQUIRED)
find_package(SDL3 REQUIRED CONFIG)
find_package(CURL REQUIRED)
target_link_libraries(p-rad Threads::Threads SDL3::SDL3 CURL::libcurl GeographicLib)
endif()
+5 -1
View File
@@ -68,6 +68,10 @@ config CHARACTER_SPACING
range 1 255 range 1 255
default 1 default 1
config NO_CALLSIGN_IDENTIFICATION
string "Callsign used for aircraft with unknown callsign"
default "UNK"
comment "Receiver configuration" comment "Receiver configuration"
config FALLBACK_LAT config FALLBACK_LAT
@@ -88,7 +92,7 @@ config METRIC
bool "Use metric units" bool "Use metric units"
default y default y
help help
Show altitudes in meters instead of feet. Show units in metric instead of aeronautical.
comment "Platform dependent options" comment "Platform dependent options"
+4 -2
View File
@@ -12,12 +12,14 @@ all: linux pico
linux: $(AUTOHEADER) linux: $(AUTOHEADER)
mkdir -p build-linux mkdir -p build-linux
(cd build-linux && cmake .. -DBUILD_FOR_PICO=OFF && make -j$(nproc)) (cd build-linux && cmake .. -DBUILD_PLATFORM=Linux && make -j$(nproc))
pico: $(AUTOHEADER) pico: $(AUTOHEADER)
mkdir -p build-pico mkdir -p build-pico
(cd build-pico && cmake .. -DBUILD_FOR_PICO=ON && make -j$(nproc)) (cd build-pico && cmake .. -DBUILD_PLATFORM=Pico && make -j$(nproc))
clean:
rm -fr build*
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# kconfig targets # kconfig targets
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
+23
View File
@@ -0,0 +1,23 @@
add_executable(p-rad
src/main.cpp
${CORE_SOURCES}
${HAL_SOURCES}
)
target_compile_options(p-rad PRIVATE -ffunction-sections -fdata-sections)
target_link_options(p-rad PRIVATE -Wl,--gc-sections)
if(CMAKE_BUILD_TYPE EQUAL Release)
add_compile_options(-O3 -s)
endif()
target_include_directories(p-rad PRIVATE src)
find_package(Threads REQUIRED)
find_package(SDL3 REQUIRED CONFIG)
find_package(CURL REQUIRED)
target_link_libraries(p-rad
Threads::Threads
SDL3::SDL3
CURL::libcurl
GeographicLib
)
+1
View File
@@ -0,0 +1 @@
set(PROJECT_LANGUAGES CXX)
+31
View File
@@ -0,0 +1,31 @@
pico_sdk_init()
target_compile_options(GeographicLib INTERFACE -fexceptions -frtti)
add_executable(p-rad
src/main.cpp
${CORE_SOURCES}
${HAL_SOURCES}
)
target_compile_options(p-rad PRIVATE -ffunction-sections -fdata-sections)
target_link_options(p-rad PRIVATE -Wl,--gc-sections)
if(CMAKE_BUILD_TYPE EQUAL Release)
add_compile_options(-Os -s)
endif()
target_compile_definitions(p-rad PRIVATE PICO_BUILD)
target_include_directories(p-rad PRIVATE src)
target_link_libraries(p-rad
pico_stdlib
pico_cyw43_arch_lwip_threadsafe_background
hardware_rtc
GeographicLib
)
pico_enable_stdio_usb(p-rad 1)
pico_enable_stdio_uart(p-rad 0)
pico_add_extra_outputs(p-rad)
+4
View File
@@ -0,0 +1,4 @@
set(PROJECT_LANGUAGES C CXX ASM)
set(PICO_BOARD pico_w CACHE STRING "Board type")
include(${CMAKE_SOURCE_DIR}/pico_sdk_import.cmake)
+6 -8
View File
@@ -42,7 +42,7 @@ draw::color_t interpolateColor(double value,
return stops.back().color; return stops.back().color;
} }
#ifdef CONFIG_METRIC
draw::color_t get_altitude_color(uint32_t value) { draw::color_t get_altitude_color(uint32_t value) {
static constexpr std::array<color_stop, 11> stops = {{ static constexpr std::array<color_stop, 11> stops = {{
#ifdef CONFIG_METRIC #ifdef CONFIG_METRIC
@@ -57,8 +57,7 @@ draw::color_t get_altitude_color(uint32_t value) {
{6000, {40, 175, 215}}, {6000, {40, 175, 215}},
{9000, {50, 110, 240}}, {9000, {50, 110, 240}},
{12000, {140, 50, 220}} {12000, {140, 50, 220}}
#endif #else
#ifndef CONFIG_METRIC
{0, {220, 90, 20}}, // Brown/Dark Orange {0, {220, 90, 20}}, // Brown/Dark Orange
{500, {245, 115, 25}}, // Orange {500, {245, 115, 25}}, // Orange
{1000, {250, 150, 30}}, // Light Orange {1000, {250, 150, 30}}, // Light Orange
@@ -74,7 +73,6 @@ draw::color_t get_altitude_color(uint32_t value) {
}}; }};
return interpolateColor(value, stops); return interpolateColor(value, stops);
} }
#endif
enum letter_id { enum letter_id {
LETTER_A, LETTER_A,
@@ -159,10 +157,10 @@ void putchar(const char c, uint16_t x, uint16_t y, const draw::color_t color) {
x = x_orig; x = x_orig;
for (uint8_t j = 0; j < FONT_WIDTH; j++) { for (uint8_t j = 0; j < FONT_WIDTH; j++) {
if (get_Nth_bit_in_grid(_5x7_dotmatrix_charset, if (get_Nth_bit_in_grid(_5x7_dotmatrix_charset,
static_cast<typeof(character_bit_offset)>( static_cast<std::remove_const_t<decltype(character_bit_offset)>>(
character_bit_offset + j), character_bit_offset + j),
static_cast<typeof(character_bit_offset)>(i), static_cast<std::remove_const_t<decltype(character_bit_offset)>>(i),
static_cast<typeof(character_bit_offset)>( static_cast<std::remove_const_t<decltype(character_bit_offset)>>(
_5X7_DOTMATRIX_CHARSET_WIDTH))) { _5X7_DOTMATRIX_CHARSET_WIDTH))) {
draw::pixel(x, y, color); draw::pixel(x, y, color);
} }
@@ -171,7 +169,7 @@ void putchar(const char c, uint16_t x, uint16_t y, const draw::color_t color) {
y++; y++;
} }
} }
void puts(const std::string &s, uint16_t x, uint16_t y, draw::color_t color) { void puts(const std::string &s, const uint16_t x, const uint16_t y, const draw::color_t color) {
for (size_t i = 0; i < s.length(); i++) { for (size_t i = 0; i < s.length(); i++) {
putchar(s[i], x+((FONT_WIDTH+CONFIG_CHARACTER_SPACING)*i), y, color); putchar(s[i], x+((FONT_WIDTH+CONFIG_CHARACTER_SPACING)*i), y, color);
} }
+15 -2
View File
@@ -1,9 +1,22 @@
#pragma once #pragma once
#include "config.hpp"
template<typename T> template<typename T>
static inline T feet_to_meters(T ft) { static inline T feet_to_meters(T ft) {
return static_cast<T>(ft * 0.3048); return static_cast<T>(ft * 0.3048);
} }
template<typename T> template<typename T>
static inline T knot_to_km(T kn) { static inline T knot_to_km(T kt) {
return static_cast<T>(kn * 0.5399568); return static_cast<T>(kt * 1.852);
} }
#ifdef CONFIG_METRIC
#define SPEED_UNIT "kmph"
#else
#define SPEED_UNIT "knot"
#endif
#ifdef CONFIG_METRIC
#define ALTITUDE_UNIT "m"
#else
#define ALTITUDE_UNIT "ft"
#endif
+1
View File
@@ -20,4 +20,5 @@ struct rect_t {
void circle(const uint16_t x_center, const uint16_t y_center,const uint16_t radius, const color_t color); void circle(const uint16_t x_center, const uint16_t y_center,const uint16_t radius, const color_t color);
void rhombus(const uint16_t x_center, const uint16_t y_center,const uint16_t radius, const color_t color); void rhombus(const uint16_t x_center, const uint16_t y_center,const uint16_t radius, const color_t color);
void line(const uint16_t x1,const uint16_t y1,const uint16_t x2,const uint16_t y2, const color_t color); void line(const uint16_t x1,const uint16_t y1,const uint16_t x2,const uint16_t y2, const color_t color);
void arc(uint16_t start_x, uint16_t start_y, float start_angle, float speed /*in pps*/,float angular_speed, uint16_t duration, color_t color);
} }
+48 -3
View File
@@ -25,6 +25,7 @@
#include <iostream> #include <iostream>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <nlohmann/json_fwd.hpp> #include <nlohmann/json_fwd.hpp>
#include <numbers>
#include <tuple> #include <tuple>
struct sdl_session { struct sdl_session {
@@ -95,7 +96,7 @@ void start_frame() {
SDL_RenderClear(main_sdl_session.renderer); SDL_RenderClear(main_sdl_session.renderer);
} }
const Uint64 frame_delay_ns = 1000000000ULL / 1; constexpr Uint64 frame_delay_ns = 1000000000ULL / 1;
void end_frame() { void end_frame() {
SDL_Event event; SDL_Event event;
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
@@ -108,7 +109,7 @@ void end_frame() {
if (event.key.key != SDLK_Q) { if (event.key.key != SDLK_Q) {
break; break;
} }
[[fallthrough]];
case SDL_EVENT_QUIT: case SDL_EVENT_QUIT:
SDL_Quit(); SDL_Quit();
std::exit(0); std::exit(0);
@@ -163,7 +164,6 @@ void circle(const uint16_t x_center, const uint16_t y_center,
SDL_RenderPoint(main_sdl_session.renderer, x + x_center, -y + y_center); SDL_RenderPoint(main_sdl_session.renderer, x + x_center, -y + y_center);
SDL_RenderPoint(main_sdl_session.renderer, y + x_center, x + y_center); SDL_RenderPoint(main_sdl_session.renderer, y + x_center, x + y_center);
SDL_RenderPoint(main_sdl_session.renderer, -y + x_center, x + y_center); SDL_RenderPoint(main_sdl_session.renderer, -y + x_center, x + y_center);
std::cout << "\n";
} }
// Initialising the value of P // Initialising the value of P
@@ -221,6 +221,51 @@ void line(const uint16_t x1, const uint16_t y1, const uint16_t x2,
0xff); 0xff);
SDL_RenderLine(main_sdl_session.renderer, x1, y1, x2, y2); SDL_RenderLine(main_sdl_session.renderer, x1, y1, x2, y2);
} }
#ifdef CONFIG_VECTOR_FOLLOW_TRACK_RATE
void arc(uint16_t start_x, uint16_t start_y, float start_angle_rad, float speed /*in pps*/,float angular_speed_rads, uint16_t duration, color_t color) {
SDL_SetRenderDrawColor(main_sdl_session.renderer, color.r, color.g, color.b,
0xff);
if (speed == 0) {
SDL_RenderPoint(main_sdl_session.renderer, start_x, start_y);
return;
}
// Handle straight line case
if (std::fabs(angular_speed_rads) < 1e-6f) {
uint16_t steps = static_cast<int>(speed * duration);
for (uint16_t i = 0; i <= steps; ++i) {
float t = i / speed;
float x = start_x + std::cos(start_angle_rad) * speed * t;
float y = start_y + std::sin(start_angle_rad) * speed * t;
SDL_RenderPoint(main_sdl_session.renderer,static_cast<int>(std::round(x)), static_cast<int>(std::round(y)));
}
return;
}
float r = speed / angular_speed_rads;
// Center of circle: perpendicular to heading
float center_x = start_x - r * std::sin(start_angle_rad);
float center_y = start_y + r * std::cos(start_angle_rad);
// Angle from center to start point
float radius_angle = std::atan2(start_y - center_y, start_x - center_x);
// Step size in time — approx 1 pixel arc-length per step
float dt = 1.0f / std::max(std::fabs(speed), 1.0f);
uint16_t steps = static_cast<int>(duration / dt);
for (uint16_t i = 0; i <= steps; ++i) {
float t = i * dt;
float a = radius_angle + angular_speed_rads * t;
float x = center_x + std::fabs(r) * std::cos(a);
float y = center_y + std::fabs(r) * std::sin(a);
SDL_RenderPoint(main_sdl_session.renderer,static_cast<int>(std::round(x)), static_cast<int>(std::round(y)));
}
}
#endif
} // namespace draw } // namespace draw
namespace net { namespace net {
+2
View File
@@ -54,6 +54,8 @@ void circle(const uint16_t x_center, const uint16_t y_center,const uint16_t radi
} }
void rhombus(const uint16_t x_center, const uint16_t y_center, const uint16_t radius, const color_t color) {} void rhombus(const uint16_t x_center, const uint16_t y_center, const uint16_t radius, const color_t color) {}
void line(const uint16_t x1, const uint16_t y1, const uint16_t x2, const uint16_t y2, const color_t color) {} void line(const uint16_t x1, const uint16_t y1, const uint16_t x2, const uint16_t y2, const color_t color) {}
void arc(uint16_t start_x, uint16_t start_y, float start_angle, float speed /*in pps*/,float angular_speed, uint16_t duration, color_t color) {}
} // namespace draw } // namespace draw
namespace net { namespace net {
+94 -26
View File
@@ -2,28 +2,28 @@
#include "core/color.h" #include "core/color.h"
#include "core/config.hpp" #include "core/config.hpp"
#include "core/font.hpp" #include "core/font.hpp"
#include "core/geo.hpp"
#include "core/gfx.hpp"
#include "core/global.hpp"
#include "core/units.hpp" #include "core/units.hpp"
#include "hal/draw.hpp" #include "hal/draw.hpp"
#include "hal/hal.hpp" #include "hal/hal.hpp"
#include "hal/net.hpp" #include "hal/net.hpp"
#include "nlohmann/json_fwd.hpp" #include "nlohmann/json_fwd.hpp"
#include <cmath>
#include <cstdint> #include <cstdint>
#include <cstdlib> #include <cstdlib>
#include <cmath>
#include <format> #include <format>
#include <iostream> #include <iostream>
#include <numbers> #include <numbers>
#include <string> #include <string>
#include "core/global.hpp" #include <algorithm>
#include "core/geo.hpp"
#include "core/gfx.hpp"
#ifndef CONFIG_AUTOSCALE #ifndef CONFIG_AUTOSCALE
constexpr constexpr
#endif #endif
uint16_t max_range = CONFIG_MAX_RANGE; uint16_t max_range = CONFIG_MAX_RANGE;
int main() { int main() {
if (hal::init() != 0) { if (hal::init() != 0) {
return 1; return 1;
@@ -92,7 +92,8 @@ int main() {
#endif #endif
{ // draw planes { // draw planes
nlohmann::json aircraft = net::http_get_json(std::format("{}/aircraft.json", CONFIG_BASE_URL)); nlohmann::json aircraft = net::http_get_json(
std::format("{}/aircraft.json", CONFIG_BASE_URL));
if (aircraft != nullptr) { if (aircraft != nullptr) {
for (nlohmann::json &craft : aircraft["aircraft"]) { for (nlohmann::json &craft : aircraft["aircraft"]) {
@@ -107,62 +108,129 @@ int main() {
#endif #endif
} }
} catch (...) { } catch (...) {
std::clog << YELLOW"[WARNING]" RESET " aircraft with no alt data detected!\n"; std::clog << YELLOW "[WARNING]" RESET
" aircraft with no alt data detected!\n";
altitude = 0; altitude = 0;
} }
#ifndef CONFIG_METRIC
// aircraft gorund speed in km/h // aircraft ground speed in knots
float speed_knot;
#endif
// aircraft ground speed in km/h
float speed; float speed;
// aircraft track in degreees // aircraft track in degreees
float track; float track;
try { try {
#ifdef CONFIG_METRIC
speed = knot_to_km(craft["gs"].get<float>()); speed = knot_to_km(craft["gs"].get<float>());
#else
speed_knot = craft["gs"].get<float>();
speed = knot_to_km(speed_knot);
#endif
track = craft["track"].get<float>(); track = craft["track"].get<float>();
} catch (...) { } catch (...) {
std::clog << YELLOW"[WARNING]" RESET " aircraft with no ground speed or track data detected!\n"; std::clog << YELLOW
"[WARNING]" RESET
" aircraft with no ground speed or track data detected!\n";
speed = 0; speed = 0;
track = 0;
#ifndef CONFIG_METRIC
speed_knot = 0;
#endif
} }
draw::color_t color = get_altitude_color(altitude); draw::color_t color = get_altitude_color(altitude);
try { try {
const auto [x_offset,y_offset] = get_offset_from_station(craft["lat"].get<double>(), craft["lon"].get<double>()); const auto [x_offset, y_offset] = get_offset_from_station(
craft["lat"].get<double>(), craft["lon"].get<double>());
#ifdef CONFIG_AUTOSCALE #ifdef CONFIG_AUTOSCALE
if(std::abs(x_offset)/1000 > fardest_aircraft_distance_linear) { if (std::abs(x_offset) / 1000 >
fardest_aircraft_distance_linear) {
fardest_aircraft_distance_linear = std::abs(x_offset) / 1000; fardest_aircraft_distance_linear = std::abs(x_offset) / 1000;
} }
if(std::abs(y_offset)/1000 > fardest_aircraft_distance_linear) { if (std::abs(y_offset) / 1000 >
fardest_aircraft_distance_linear) {
fardest_aircraft_distance_linear = std::abs(y_offset) / 1000; fardest_aircraft_distance_linear = std::abs(y_offset) / 1000;
} }
#endif #endif
const uint16_t x_center = middle_x+((x_offset/1000)*pixels_per_km); const uint16_t x_center =
const uint16_t y_center = middle_y+((y_offset/1000)*pixels_per_km); middle_x + ((x_offset / 1000) * pixels_per_km);
const uint16_t y_center =
middle_y + ((y_offset / 1000) * pixels_per_km);
// draw::pixel(x_center, y_center, color); // draw::pixel(x_center, y_center, color);
// speed in pixels per hour // speed in pixels per hour
const float speed_pph = speed * pixels_per_km; const float speed_pph = speed * pixels_per_km;
// lenght of Time-Based Vector
const float vector_lenght = (speed_pph/60) * CONFIG_TIME_BASED_VECTOR_LENGHT;
// track in radians // track in radians
const float track_rad = std::fmod((track-90),365.0f) * (static_cast<float>(std::numbers::pi)/180.0f); const float track_rad =
std::fmod((track - 90), 360.0f) *
(static_cast<float>(std::numbers::pi) / 180.0f);
draw::line(x_center, y_center,x_center + (vector_lenght*std::cos(track_rad)), y_center + (vector_lenght*std::sin(track_rad)), color); #ifdef CONFIG_VECTOR_FOLLOW_TRACK_RATE
draw::rhombus(x_center, y_center, 8/*TODO: remove magic*/,color); {
font::puts("TEST123", x_center+10, y_center, color); float track_rate_rads;
try {
track_rate_rads = craft["track_rate"].get<float>() * (static_cast<float>(std::numbers::pi) / 180.0f);
} catch (...) { } catch (...) {
std::clog << YELLOW"[WARNING]" RESET " aircraft with no lat/lon data detected!\n"; std::clog << YELLOW
"[WARNING]" RESET
" aircraft with no track_rate data detected!\n";
track_rate_rads = 0;
} }
draw::arc(x_center, y_center,track_rad,speed_pph/3600,track_rate_rads,CONFIG_TIME_BASED_VECTOR_LENGHT*60,color);
}
#else
// lenght of Time-Based Vector
const float vector_lenght =
(speed_pph / 60) * CONFIG_TIME_BASED_VECTOR_LENGHT;
draw::line(x_center, y_center,
std::clamp(x_center + (vector_lenght * std::cos(track_rad)),0.0f, static_cast<float>(UINT16_MAX)),
std::clamp(y_center + (vector_lenght * std::sin(track_rad)),0.0f,static_cast<float>(UINT16_MAX)), color);
#endif
draw::rhombus(x_center, y_center, 8 /*TODO: remove magic*/,
color);
{
std::string callsign;
try {
callsign = craft["flight"].get<std::string>();
} catch (...) {
std::clog << YELLOW "[WARNING]" RESET
" aircraft with no callsign detected!\n";
callsign = CONFIG_NO_CALLSIGN_IDENTIFICATION;
}
// print some info
font::puts(callsign, x_center + 10 /*TODO: remove magic*/,
y_center, color);
font::puts(std::to_string(static_cast<uint16_t>(
#ifdef CONFIG_METRIC
speed
#else
speed_knot
#endif
)) +
SPEED_UNIT,
x_center + 10 /*TODO: remove magic*/,
y_center + FONT_HEIGHT + CONFIG_CHARACTER_SPACING,
color);
font::puts(std::to_string(altitude) + ALTITUDE_UNIT, x_center + 10 /*TODO: remove magic*/, y_center + (FONT_HEIGHT + CONFIG_CHARACTER_SPACING)*2,color);
}
} catch (...) {
std::clog << YELLOW "[WARNING]" RESET
" aircraft with no lat/lon data detected!\n";
}
} }
} else { } else {
// TODO draw vizual error // TODO draw visual error
std::cerr << RED "[ERROR]" RESET " failed to get aircraft\n"; std::cerr << RED "[ERROR]" RESET " failed to get aircraft\n";
} }
} }
#ifdef CONFIG_AUTOSCALE #ifdef CONFIG_AUTOSCALE
if (fardest_aircraft_distance_linear > 0) { if (fardest_aircraft_distance_linear > 0) {
for (uint16_t i = CONFIG_FIRST_RING_DISTANCE; i < UINT16_MAX; i *= 2) { for (uint16_t i = CONFIG_FIRST_RING_DISTANCE; i < UINT16_MAX; i *= 2) {
if (i+(CONFIG_RANGE_PADDING/2) >= fardest_aircraft_distance_linear) { if (i + (CONFIG_RANGE_PADDING / 2) >=
fardest_aircraft_distance_linear) {
max_range = i + CONFIG_RANGE_PADDING; max_range = i + CONFIG_RANGE_PADDING;
pixels_per_km = pixels_per_km =
static_cast<float>(screen_h > screen_w ? screen_w : screen_h) / static_cast<float>(screen_h > screen_w ? screen_w : screen_h) /