Made a GeoPos widget for lon/lat/alt entry and display (APRS...)

Cleaned up the GeoMap view, can be used as input
This commit is contained in:
furrtek 2017-08-03 19:06:59 +01:00
parent a5f0f72ea1
commit fba5b507ad
10 changed files with 285 additions and 165 deletions

View file

@ -24,19 +24,20 @@
// Gimp image > indexed colors (16), then "xxd -i *.bmp" // Gimp image > indexed colors (16), then "xxd -i *.bmp"
//TEST: ADS-B tx manchester encoder, velocity and squawk frames //TEST: ADS-B tx manchester encoder, velocity and squawk frames
//TEST: Mic tx
//TEST: Menuview refresh, seems to blink a lot //TEST: Menuview refresh, seems to blink a lot
//TEST: Check AFSK transmit end, skips last bits ? //TEST: Check AFSK transmit end, skips last bits ?
//TEST: Imperial in whipcalc //TEST: Imperial in whipcalc
//BUG: ADSB transmit baseband code works only if stuck in a loop (txdone message makes everything go nuts)
//BUG: CPLD-related rx ok, tx bad, see portapack.cpp lines 214+ to disable CPLD overlay //BUG: CPLD-related rx ok, tx bad, see portapack.cpp lines 214+ to disable CPLD overlay
//BUG: REPLAY See what's wrong with quality (format, or need for interpolation filter ?) //BUG: REPLAY See what's wrong with quality (format, or need for interpolation filter ?)
//TODO: REPLAY Convert C16 to C8 on M0 core
//BUG: SCANNER Lock on frequency, if frequency jump, still locked on first one //BUG: SCANNER Lock on frequency, if frequency jump, still locked on first one
//BUG: SCANNER Multiple slices //BUG: SCANNER Multiple slices
//BUG: REPLAY freezes when SD card not present //BUG: REPLAY freezes when SD card not present
//BUG: RDS doesn't stop baseband when stopping tx ? //BUG: RDS doesn't stop baseband when stopping tx ?
//TODO: REPLAY Convert C16 to C8 on M0 core
//TODO: Use TabView
//TODO: De bruijn sequence scanner for encoders //TODO: De bruijn sequence scanner for encoders
//TODO: Make freqman refresh simpler (use previous black rectangle method) //TODO: Make freqman refresh simpler (use previous black rectangle method)
//TODO: Merge AFSK and TONES procs ? //TODO: Merge AFSK and TONES procs ?

View file

@ -22,7 +22,6 @@
#include "ui_adsb_tx.hpp" #include "ui_adsb_tx.hpp"
#include "ui_alphanum.hpp" #include "ui_alphanum.hpp"
#include "ui_geomap.hpp"
#include "manchester.hpp" #include "manchester.hpp"
#include "string_format.hpp" #include "string_format.hpp"
@ -43,10 +42,6 @@ Compass::Compass(
{ {
} }
Point Compass::polar_to_point(uint32_t angle, uint32_t distance) {
return Point(sin_f32(DEG_TO_RAD(angle) + (pi / 2)) * distance, -sin_f32(DEG_TO_RAD(angle)) * distance);
}
void Compass::set_value(uint32_t new_value) { void Compass::set_value(uint32_t new_value) {
Point center = screen_pos() + Point(32, 32); Point center = screen_pos() + Point(32, 32);
@ -103,40 +98,35 @@ ADSBPositionView::ADSBPositionView(NavigationView& nav) {
set_type("position"); set_type("position");
add_children({ add_children({
&labels_position, &geopos,
&field_altitude,
&field_lat_degrees,
&field_lat_minutes,
&field_lat_seconds,
&field_lon_degrees,
&field_lon_minutes,
&field_lon_seconds,
&button_set_map &button_set_map
}); });
field_altitude.set_value(36000); geopos.set_altitude(36000);
field_lat_degrees.set_value(0);
field_lat_minutes.set_value(0);
field_lat_seconds.set_value(0);
field_lon_degrees.set_value(0);
field_lon_minutes.set_value(0);
field_lon_seconds.set_value(0);
button_set_map.on_select = [this, &nav](Button&) { button_set_map.on_select = [this, &nav](Button&) {
nav.push<GeoMapView>(GeoMapView::Mode::SET); nav.push<GeoMapView>(
geopos.altitude(),
geopos.lat(),
geopos.lon(),
[this](int32_t altitude, float lat, float lon) {
geopos.set_altitude(altitude);
geopos.set_lat(lat);
geopos.set_lon(lon);
});
}; };
} }
void ADSBPositionView::collect_frames(const uint32_t ICAO_address, std::vector<ADSBFrame>& frame_list) { void ADSBPositionView::collect_frames(const uint32_t ICAO_address, std::vector<ADSBFrame>& frame_list) {
ADSBFrame temp_frame; ADSBFrame temp_frame;
encode_frame_pos(temp_frame, ICAO_address, field_altitude.value(), encode_frame_pos(temp_frame, ICAO_address, geopos.altitude(),
field_lat_degrees.value(), field_lon_degrees.value(), 0); geopos.lat(), geopos.lon(), 0);
frame_list.emplace_back(temp_frame); frame_list.emplace_back(temp_frame);
encode_frame_pos(temp_frame, ICAO_address, field_altitude.value(), encode_frame_pos(temp_frame, ICAO_address, geopos.altitude(),
field_lat_degrees.value(), field_lon_degrees.value(), 1); geopos.lat(), geopos.lon(), 1);
frame_list.emplace_back(temp_frame); frame_list.emplace_back(temp_frame);
} }
@ -223,11 +213,18 @@ ADSBTxView::~ADSBTxView() {
void ADSBTxView::generate_frames() { void ADSBTxView::generate_frames() {
const uint32_t ICAO_address = sym_icao.value_hex_u64(); const uint32_t ICAO_address = sym_icao.value_hex_u64();
/* This scheme kinda sucks. Each "tab"'s collect_frames method
* is called to generate its related frame(s). Getting values
* from each widget of each tab would be better ?
* */
view_position.collect_frames(ICAO_address, frames); view_position.collect_frames(ICAO_address, frames);
view_callsign.collect_frames(ICAO_address, frames); view_callsign.collect_frames(ICAO_address, frames);
view_speed.collect_frames(ICAO_address, frames); view_speed.collect_frames(ICAO_address, frames);
view_squawk.collect_frames(ICAO_address, frames); view_squawk.collect_frames(ICAO_address, frames);
// DEBUG: Show how many frames were generated
text_frame.set(to_string_dec_uint(frames.size()) + " frame(s).");
//memset(bin_ptr, 0, 240); //memset(bin_ptr, 0, 240);
//auto raw_ptr = frames[0].get_raw_data(); //auto raw_ptr = frames[0].get_raw_data();
@ -352,14 +349,11 @@ ADSBTxView::ADSBTxView(
view_speed.set_parent_rect(view_rect); view_speed.set_parent_rect(view_rect);
view_squawk.set_parent_rect(view_rect); view_squawk.set_parent_rect(view_rect);
sym_icao.on_change = [this]() {
generate_frames();
};
tx_view.on_start = [this]() { tx_view.on_start = [this]() {
start_tx(); start_tx();
tx_view.set_transmitting(true); tx_view.set_transmitting(true);
rotate_frames(); // Disable for DEBUG
//rotate_frames();
}; };
tx_view.on_stop = [this]() { tx_view.on_stop = [this]() {

View file

@ -23,9 +23,9 @@
#include "ui.hpp" #include "ui.hpp"
#include "adsb.hpp" #include "adsb.hpp"
#include "utility.hpp" #include "utility.hpp"
#include "sine_table.hpp"
#include "ui_textentry.hpp" #include "ui_textentry.hpp"
#include "ui_widget.hpp" #include "ui_widget.hpp"
#include "ui_geomap.hpp"
#include "ui_tabview.hpp" #include "ui_tabview.hpp"
#include "ui_navigation.hpp" #include "ui_navigation.hpp"
#include "ui_transmitter.hpp" #include "ui_transmitter.hpp"
@ -47,8 +47,6 @@ public:
void paint(Painter&) override; void paint(Painter&) override;
private: private:
Point polar_to_point(uint32_t angle, uint32_t distance);
const range_t<uint32_t> range { 0, 359 }; const range_t<uint32_t> range { 0, 359 };
uint32_t value_ { 0 }; uint32_t value_ { 0 };
}; };
@ -83,38 +81,8 @@ public:
void collect_frames(const uint32_t ICAO_address, std::vector<ADSBFrame>& frame_list); void collect_frames(const uint32_t ICAO_address, std::vector<ADSBFrame>& frame_list);
private: private:
Labels labels_position { GeoPos geopos {
{ { 2 * 8, 2 * 16 }, "Alt: feet", Color::light_grey() }, { 0, 2 * 16 }
{ { 2 * 8, 4 * 16 }, "Lat: * ' \"", Color::light_grey() }, // No ° symbol in 8x16 font
{ { 2 * 8, 5 * 16 }, "Lon: * ' \"", Color::light_grey() },
};
NumberField field_altitude {
{ 7 * 8, 2 * 16 },
5,
{ -1000, 50000 },
250,
' '
};
NumberField field_lat_degrees {
{ 7 * 8, 4 * 16 }, 4, { -90, 90 }, 1, ' '
};
NumberField field_lat_minutes {
{ 12 * 8, 4 * 16 }, 2, { 0, 59 }, 1, ' '
};
NumberField field_lat_seconds {
{ 15 * 8, 4 * 16 }, 2, { 0, 59 }, 1, ' '
};
NumberField field_lon_degrees {
{ 7 * 8, 5 * 16 }, 4, { -180, 180 }, 1, ' '
};
NumberField field_lon_minutes {
{ 12 * 8, 5 * 16 }, 2, { 0, 59 }, 1, ' '
};
NumberField field_lon_seconds {
{ 15 * 8, 5 * 16 }, 2, { 0, 59 }, 1, ' '
}; };
Button button_set_map { Button button_set_map {
@ -194,13 +162,13 @@ public:
std::string title() const override { return "ADS-B transmit"; }; std::string title() const override { return "ADS-B transmit"; };
private: private:
enum tx_modes { /*enum tx_modes {
IDLE = 0, IDLE = 0,
SINGLE, SINGLE,
SEQUENCE SEQUENCE
}; };*/
const float plane_lats[12] = { /*const float plane_lats[12] = {
0, 0,
-1, -1,
-2, -2,
@ -227,9 +195,9 @@ private:
-1, -1,
-1, -1,
-1 -1
}; };*/
tx_modes tx_mode = IDLE; //tx_modes tx_mode = IDLE;
NavigationView& nav_; NavigationView& nav_;
std::vector<ADSBFrame> frames { }; std::vector<ADSBFrame> frames { };

View file

@ -23,8 +23,6 @@
#include "ui_geomap.hpp" #include "ui_geomap.hpp"
#include "adsb.hpp" #include "adsb.hpp"
//#include "string_format.hpp"
#include "sine_table_int8.hpp"
#include "portapack.hpp" #include "portapack.hpp"
#include <cstring> #include <cstring>
@ -34,9 +32,80 @@ using namespace portapack;
namespace ui { namespace ui {
GeoPos::GeoPos(
const Point pos
) {
set_parent_rect({pos, {30 * 8, 3 * 16}});
add_children({
&labels_position,
&field_altitude,
&field_lat_degrees,
&field_lat_minutes,
&field_lat_seconds,
&field_lon_degrees,
&field_lon_minutes,
&field_lon_seconds
});
// Defaults
set_altitude(0);
set_lat(0);
set_lon(0);
const auto changed = [this](int32_t) {
if (on_change)
on_change();
};
field_altitude.on_change = changed;
field_lat_degrees.on_change = changed;
field_lat_minutes.on_change = changed;
field_lat_seconds.on_change = changed;
field_lon_degrees.on_change = changed;
field_lon_minutes.on_change = changed;
field_lon_seconds.on_change = changed;
}
void GeoPos::focus() {
field_altitude.focus();
}
void GeoPos::set_altitude(int32_t altitude) {
field_altitude.set_value(altitude);
}
void GeoPos::set_lat(float lat) {
field_lat_degrees.set_value(lat);
field_lat_minutes.set_value((uint32_t)(lat / (1.0 / 60)) % 60);
field_lat_seconds.set_value((uint32_t)(lat / (1.0 / 3600)) % 60);
}
void GeoPos::set_lon(float lon) {
field_lon_degrees.set_value(lon);
field_lon_minutes.set_value((uint32_t)(lon / (1.0 / 60)) % 60);
field_lon_seconds.set_value((uint32_t)(lon / (1.0 / 3600)) % 60);
}
float GeoPos::lat() {
return field_lat_degrees.value() + (field_lat_minutes.value() / 60.0) + (field_lat_seconds.value() / 3600.0);
};
float GeoPos::lon() {
return field_lon_degrees.value() + (field_lon_minutes.value() / 60.0) + (field_lon_seconds.value() / 3600.0);
};
int32_t GeoPos::altitude() {
return field_altitude.value();
};
void GeoPos::set_read_only(bool v) {
set_focusable(~v);
};
void GeoMapView::focus() { void GeoMapView::focus() {
if (!file_error) { if (!file_error) {
field_xpos.focus(); geopos.focus();
move_map(); move_map();
} else } else
nav_.display_modal("No map", "No world_map.bin file in\n/ADSB/ directory", ABORT, nullptr); nav_.display_modal("No map", "No world_map.bin file in\n/ADSB/ directory", ABORT, nullptr);
@ -46,61 +115,58 @@ GeoMapView::~GeoMapView() {
} }
Point GeoMapView::polar_to_point(const uint8_t angle, const uint32_t size) { void GeoMapView::draw_bearing(const Point origin, const uint32_t angle, uint32_t size, const Color color) {
return { (Coord)(sine_table_i8[(angle + 64) & 0xFF] * size) >> 7, (Coord)(sine_table_i8[angle] * size) >> 7 };
}
void GeoMapView::draw_bearing(const Point origin, const uint8_t angle, uint32_t size, const Color color) {
Point arrow_a, arrow_b, arrow_c; Point arrow_a, arrow_b, arrow_c;
for (size_t thickness = 0; thickness < 3; thickness++) {
arrow_a = polar_to_point(angle, size) + origin; arrow_a = polar_to_point(angle, size) + origin;
arrow_b = polar_to_point(angle + 128 - 16, size) + origin; arrow_b = polar_to_point(angle + 180 - 30, size) + origin;
arrow_c = polar_to_point(angle + 128 + 16, size) + origin; arrow_c = polar_to_point(angle + 180 + 30, size) + origin;
display.draw_line(arrow_a, arrow_b, color); display.draw_line(arrow_a, arrow_b, color);
display.draw_line(arrow_b, arrow_c, color); display.draw_line(arrow_b, arrow_c, color);
display.draw_line(arrow_c, arrow_a, color); display.draw_line(arrow_c, arrow_a, color);
size--; size--;
arrow_a = polar_to_point(angle, size) + origin; }
arrow_b = polar_to_point(angle + 128 - 16, size) + origin;
arrow_c = polar_to_point(angle + 128 + 16, size) + origin;
display.draw_line(arrow_a, arrow_b, color);
display.draw_line(arrow_b, arrow_c, color);
display.draw_line(arrow_c, arrow_a, color);
} }
void GeoMapView::move_map() { void GeoMapView::move_map() {
Coord line; Coord line;
int32_t x_pos, y_pos; int32_t x_pos, y_pos;
std::array<ui::Color, 240> map_buffer; std::array<ui::Color, 240> map_line_buffer;
auto r = screen_rect();
Rect map_rect = { r.left(), r.top() + banner_height, r.width(), r.height() - banner_height };
altitude_ = geopos.altitude();
lat_ = geopos.lat();
lon_ = geopos.lon();
// Map is in Equidistant "Plate Carrée" projection // Map is in Equidistant "Plate Carrée" projection
x_pos = map_center_x - 120 + ((((field_xpos.value() * map_center_x) << 8) / 180) >> 8); x_pos = map_center_x - (map_rect.width() / 2) + ((lat_ * map_center_x) / 180);
y_pos = map_center_y - 144 + ((((field_ypos.value() * map_center_y) << 8) / 90) >> 8); y_pos = map_center_y - (map_rect.height() / 2) + ((lon_ * map_center_y) / 90);
if (x_pos > (map_width - 240)) if (x_pos > (map_width - map_rect.width()))
x_pos = map_width - 240; x_pos = map_width - map_rect.width();
if (y_pos > (map_height + 288)) if (y_pos > (map_height + map_rect.height()))
y_pos = map_height - 288; y_pos = map_height - map_rect.height();
for (line = 0; line < 288; line++) { for (line = 0; line < map_rect.height(); line++) {
map_file.seek(4 + ((x_pos + (map_width * (y_pos + line))) << 1)); map_file.seek(4 + ((x_pos + (map_width * (y_pos + line))) << 1));
map_file.read(map_buffer.data(), 240 * 2); map_file.read(map_line_buffer.data(), map_rect.width() << 1);
display.draw_pixels({ 0, 32 + line, 240, 1 }, map_buffer); display.draw_pixels({ 0, map_rect.top() + line, map_rect.width(), 1 }, map_line_buffer);
} }
draw_bearing({ 120, 32 + 144 }, field_angle.value(), 16, Color::red()); if (mode_ == PROMPT) {
display.fill_rectangle({ map_rect.center() - Point(16, 1), { 32, 2 } }, Color::red());
//display.fill_rectangle({ 120-16, 176-1, 32, 2 }, Color::red()); display.fill_rectangle({ map_rect.center() - Point(1, 16), { 2, 32 } }, Color::red());
//display.fill_rectangle({ 120-1, 176-16, 2, 32 }, Color::red()); } else {
draw_bearing({ 120, 32 + 144 }, angle_, 16, Color::red());
}
} }
GeoMapView::GeoMapView( void GeoMapView::setup() {
NavigationView& nav,
Mode mode
) : nav_ (nav),
mode_ (mode)
{
auto result = map_file.open("ADSB/world_map.bin"); auto result = map_file.open("ADSB/world_map.bin");
if (result.is_valid()) { if (result.is_valid()) {
file_error = true; file_error = true;
@ -113,23 +179,59 @@ GeoMapView::GeoMapView(
map_center_x = map_width >> 1; map_center_x = map_width >> 1;
map_center_y = map_height >> 1; map_center_y = map_height >> 1;
add_children({ add_child(&geopos);
&field_xpos,
&field_ypos
});
if (mode_ == SHOW) { geopos.set_altitude(altitude_);
add_child(&field_angle); geopos.set_lat(lat_);
field_angle.on_change = [this](int32_t) { geopos.set_lon(lon_);
geopos.on_change = [this]() {
move_map(); move_map();
}; };
} }
field_xpos.on_change = [this](int32_t) { // Display mode
move_map(); GeoMapView::GeoMapView(
}; NavigationView& nav,
field_ypos.on_change = [this](int32_t) { std::string* tag,
move_map(); int32_t altitude,
float lat,
float lon,
float angle
) : nav_ (nav),
tag_ (tag),
altitude_ (altitude),
lat_ (lat),
lon_ (lon),
angle_ (angle)
{
mode_ = DISPLAY;
setup();
geopos.set_read_only(true);
}
// Prompt mode
GeoMapView::GeoMapView(
NavigationView& nav,
int32_t altitude,
float lat,
float lon,
const std::function<void(int32_t, float, float)> on_done
) : nav_ (nav),
altitude_ (altitude),
lat_ (lat),
lon_ (lon)
{
mode_ = PROMPT;
setup();
add_child(&button_ok);
button_ok.on_select = [this, on_done, &nav](Button&) {
if (on_done)
on_done(altitude_, lat_, lon_);
nav.pop();
}; };
} }

View file

@ -29,14 +29,70 @@
namespace ui { namespace ui {
class GeoMapView : public View { class GeoPos : public View {
public: public:
enum Mode { std::function<void(void)> on_change { };
SHOW,
SET GeoPos(const Point pos);
void focus() override;
void set_read_only(bool v);
void set_altitude(int32_t altitude);
void set_lat(float lat);
void set_lon(float lon);
float lat();
float lon();
int32_t altitude();
private:
bool read_only { false };
Labels labels_position {
{ { 2 * 8, 0 * 16 }, "Alt: feet", Color::light_grey() },
{ { 2 * 8, 1 * 16 }, "Lat: * ' \"", Color::light_grey() }, // No ° symbol in 8x16 font
{ { 2 * 8, 2 * 16 }, "Lon: * ' \"", Color::light_grey() },
}; };
GeoMapView(NavigationView& nav, Mode mode); NumberField field_altitude {
{ 7 * 8, 0 * 16 },
5,
{ -1000, 50000 },
250,
' '
};
NumberField field_lat_degrees {
{ 7 * 8, 1 * 16 }, 4, { -90, 90 }, 1, ' '
};
NumberField field_lat_minutes {
{ 12 * 8, 1 * 16 }, 2, { 0, 59 }, 1, ' '
};
NumberField field_lat_seconds {
{ 15 * 8, 1 * 16 }, 2, { 0, 59 }, 1, ' '
};
NumberField field_lon_degrees {
{ 7 * 8, 2 * 16 }, 4, { -180, 180 }, 1, ' '
};
NumberField field_lon_minutes {
{ 12 * 8, 2 * 16 }, 2, { 0, 59 }, 1, ' '
};
NumberField field_lon_seconds {
{ 15 * 8, 2 * 16 }, 2, { 0, 59 }, 1, ' '
};
};
class GeoMapView : public View {
public:
GeoMapView(NavigationView& nav, std::string* tag, int32_t altitude, float lat, float lon, float angle);
GeoMapView(NavigationView& nav, int32_t altitude, float lat, float lon, const std::function<void(int32_t, float, float)> on_done);
GeoMapView(const GeoMapView&) = delete;
GeoMapView(GeoMapView&&) = delete;
GeoMapView& operator=(const GeoMapView&) = delete;
GeoMapView& operator=(GeoMapView&&) = delete;
~GeoMapView(); ~GeoMapView();
void focus() override; void focus() override;
@ -44,42 +100,37 @@ public:
std::string title() const override { return "Map view"; }; std::string title() const override { return "Map view"; };
private: private:
enum Mode {
DISPLAY,
PROMPT
};
const Dim banner_height = 3 * 16;
NavigationView& nav_; NavigationView& nav_;
const std::function<void(int32_t, float, float)> on_done { };
Mode mode_ { }; Mode mode_ { };
std::string* tag_ { };
int32_t altitude_ { };
float lat_ { };
float lon_ { };
float angle_ { };
File map_file { }; File map_file { };
bool file_error { false }; bool file_error { false };
uint16_t map_width { }, map_height { }; uint16_t map_width { }, map_height { };
int32_t map_center_x { }, map_center_y { }; int32_t map_center_x { }, map_center_y { };
void setup();
void move_map(); void move_map();
Point polar_to_point(const uint8_t angle, const uint32_t size); void draw_bearing(const Point origin, const uint32_t angle, uint32_t size, const Color color);
void draw_bearing(const Point origin, const uint8_t angle, uint32_t size, const Color color);
Labels labels { GeoPos geopos {
{ { 0 * 8, 0 * 8 }, "Test", Color::light_grey() } { 0, 0 }
}; };
NumberField field_xpos { Button button_ok {
{ 0, 0 }, { 20 * 8, 8, 8 * 8, 2 * 16 },
4, "OK"
{ -180, 180 },
1,
'0'
};
NumberField field_ypos {
{ 6 * 8, 0 },
4,
{ -90, 90 },
1,
'0'
};
NumberField field_angle {
{ 12 * 8, 0 },
3,
{ 0, 255 },
1,
'0'
}; };
}; };

View file

@ -27,8 +27,6 @@
#include "ui_widget.hpp" #include "ui_widget.hpp"
#include "ui_navigation.hpp" #include "ui_navigation.hpp"
#include "ui_painter.hpp" #include "ui_painter.hpp"
#include "ui_receiver.hpp"
#include "ui_font_fixed_8x16.hpp"
namespace ui { namespace ui {
@ -53,8 +51,6 @@ private:
class TabView : public View { class TabView : public View {
public: public:
//std::function<void(void)> on_change { };
struct TabDef { struct TabDef {
std::string text; std::string text;
ui::Color color; ui::Color color;

View file

@ -161,7 +161,7 @@ int cpr_N(float lat, int is_odd) {
// ... and ... // ... and ...
// if (lon > 180) lon -= 360; // if (lon > 180) lon -= 360;
void encode_frame_pos(ADSBFrame& frame, const uint32_t ICAO_address, const uint32_t altitude, void encode_frame_pos(ADSBFrame& frame, const uint32_t ICAO_address, const int32_t altitude,
const float latitude, const float longitude, const uint32_t time_parity) { const float latitude, const float longitude, const uint32_t time_parity) {
uint32_t altitude_coded; uint32_t altitude_coded;

View file

@ -24,14 +24,13 @@
#define __ADSB_H__ #define __ADSB_H__
#include "adsb_frame.hpp" #include "adsb_frame.hpp"
#include "ui.hpp"
#include <cstring> #include <cstring>
#include <string> #include <string>
namespace adsb { namespace adsb {
#define DEG_TO_RAD(d) (d * (2 * pi) / 360.0)
enum downlink_format { enum downlink_format {
DF_ADSB = 17, DF_ADSB = 17,
DF_EHS_SQUAWK = 21 DF_EHS_SQUAWK = 21
@ -70,7 +69,7 @@ const float adsb_lat_lut[58] = {
void make_frame_adsb(ADSBFrame& frame, const uint32_t ICAO_address); 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); void encode_frame_id(ADSBFrame& frame, const uint32_t ICAO_address, const std::string& callsign);
void encode_frame_pos(ADSBFrame& frame, const uint32_t ICAO_address, const uint32_t altitude, void encode_frame_pos(ADSBFrame& frame, const uint32_t ICAO_address, const int32_t altitude,
const float latitude, const float longitude, const uint32_t time_parity); const float latitude, const float longitude, const uint32_t time_parity);
void encode_frame_velo(ADSBFrame& frame, const uint32_t ICAO_address, const uint32_t speed, void encode_frame_velo(ADSBFrame& frame, const uint32_t ICAO_address, const uint32_t speed,
const float angle, const int32_t v_rate); const float angle, const int32_t v_rate);

View file

@ -20,6 +20,7 @@
*/ */
#include "ui.hpp" #include "ui.hpp"
#include "sine_table.hpp"
#include <algorithm> #include <algorithm>
@ -69,4 +70,8 @@ Rect& Rect::operator-=(const Point& p) {
return *this; return *this;
} }
Point polar_to_point(float angle, uint32_t distance) {
return Point(sin_f32(DEG_TO_RAD(angle) + (pi / 2)) * distance, -sin_f32(DEG_TO_RAD(angle)) * distance);
}
} /* namespace ui */ } /* namespace ui */

View file

@ -26,6 +26,8 @@
namespace ui { namespace ui {
#define DEG_TO_RAD(d) (d * (2 * pi) / 360.0)
using Coord = int16_t; using Coord = int16_t;
using Dim = int16_t; using Dim = int16_t;
@ -326,6 +328,8 @@ struct TouchEvent {
Type type; Type type;
}; };
Point polar_to_point(float angle, uint32_t distance);
} /* namespace ui */ } /* namespace ui */
#endif/*__UI_H__*/ #endif/*__UI_H__*/