mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-10-01 01:26:06 -04:00
Split ADSB TX into tabs
Simplified TabView a lot
This commit is contained in:
parent
89a3afcd74
commit
a5f0f72ea1
@ -276,7 +276,7 @@ ADSBRxView::ADSBRxView(NavigationView& nav) {
|
|||||||
};*/
|
};*/
|
||||||
|
|
||||||
/*button_ffw.on_select = [this, &nav](Button&) {
|
/*button_ffw.on_select = [this, &nav](Button&) {
|
||||||
//nav.push<GeoMapView>();
|
//nav.push<GeoMapView>(GeoMapView::Mode::SHOW);
|
||||||
while (!analyze(f_offset)) {
|
while (!analyze(f_offset)) {
|
||||||
f_offset++;
|
f_offset++;
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#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"
|
||||||
@ -49,7 +50,7 @@ Point Compass::polar_to_point(uint32_t angle, uint32_t 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);
|
||||||
|
|
||||||
new_value = clamp_value(new_value);
|
new_value = range.clip(new_value);
|
||||||
|
|
||||||
display.draw_line(
|
display.draw_line(
|
||||||
center,
|
center,
|
||||||
@ -77,12 +78,141 @@ void Compass::paint(Painter&) {
|
|||||||
set_value(value_);
|
set_value(value_);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Compass::clamp_value(uint32_t value) {
|
ADSBView::ADSBView() {
|
||||||
return range.clip(value);
|
add_child(&check_enable);
|
||||||
|
hidden(true);
|
||||||
|
|
||||||
|
check_enable.on_select = [this](Checkbox&, bool value) {
|
||||||
|
enabled = value;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADSBView::set_enabled(bool value) {
|
||||||
|
check_enable.set_value(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADSBView::set_type(std::string type) {
|
||||||
|
check_enable.set_text("Transmit " + type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADSBView::focus() {
|
||||||
|
check_enable.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
ADSBPositionView::ADSBPositionView(NavigationView& nav) {
|
||||||
|
set_type("position");
|
||||||
|
|
||||||
|
add_children({
|
||||||
|
&labels_position,
|
||||||
|
&field_altitude,
|
||||||
|
&field_lat_degrees,
|
||||||
|
&field_lat_minutes,
|
||||||
|
&field_lat_seconds,
|
||||||
|
&field_lon_degrees,
|
||||||
|
&field_lon_minutes,
|
||||||
|
&field_lon_seconds,
|
||||||
|
&button_set_map
|
||||||
|
});
|
||||||
|
|
||||||
|
field_altitude.set_value(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&) {
|
||||||
|
nav.push<GeoMapView>(GeoMapView::Mode::SET);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADSBPositionView::collect_frames(const uint32_t ICAO_address, std::vector<ADSBFrame>& frame_list) {
|
||||||
|
ADSBFrame temp_frame;
|
||||||
|
|
||||||
|
encode_frame_pos(temp_frame, ICAO_address, field_altitude.value(),
|
||||||
|
field_lat_degrees.value(), field_lon_degrees.value(), 0);
|
||||||
|
|
||||||
|
frame_list.emplace_back(temp_frame);
|
||||||
|
|
||||||
|
encode_frame_pos(temp_frame, ICAO_address, field_altitude.value(),
|
||||||
|
field_lat_degrees.value(), field_lon_degrees.value(), 1);
|
||||||
|
|
||||||
|
frame_list.emplace_back(temp_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
ADSBCallsignView::ADSBCallsignView(NavigationView& nav) {
|
||||||
|
set_type("callsign");
|
||||||
|
|
||||||
|
add_children({
|
||||||
|
&labels_callsign,
|
||||||
|
&button_callsign
|
||||||
|
});
|
||||||
|
|
||||||
|
set_enabled(true);
|
||||||
|
|
||||||
|
button_callsign.set_text(callsign);
|
||||||
|
|
||||||
|
button_callsign.on_select = [this, &nav](Button&) {
|
||||||
|
text_prompt(nav, &callsign, 8);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADSBCallsignView::collect_frames(const uint32_t ICAO_address, std::vector<ADSBFrame>& frame_list) {
|
||||||
|
ADSBFrame temp_frame;
|
||||||
|
|
||||||
|
encode_frame_id(temp_frame, ICAO_address, callsign);
|
||||||
|
|
||||||
|
frame_list.emplace_back(temp_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
ADSBSpeedView::ADSBSpeedView() {
|
||||||
|
set_type("speed");
|
||||||
|
|
||||||
|
add_children({
|
||||||
|
&labels_speed,
|
||||||
|
&compass,
|
||||||
|
&field_angle,
|
||||||
|
&field_speed
|
||||||
|
});
|
||||||
|
|
||||||
|
field_angle.set_value(0);
|
||||||
|
field_speed.set_value(400);
|
||||||
|
|
||||||
|
field_angle.on_change = [this](int32_t v) {
|
||||||
|
compass.set_value(v);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADSBSpeedView::collect_frames(const uint32_t ICAO_address, std::vector<ADSBFrame>& frame_list) {
|
||||||
|
ADSBFrame temp_frame;
|
||||||
|
|
||||||
|
encode_frame_velo(temp_frame, ICAO_address, field_speed.value(),
|
||||||
|
field_angle.value(), 0); // TODO: v_rate
|
||||||
|
|
||||||
|
frame_list.emplace_back(temp_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
ADSBSquawkView::ADSBSquawkView() {
|
||||||
|
set_type("squawk");
|
||||||
|
|
||||||
|
add_children({
|
||||||
|
&labels_squawk,
|
||||||
|
&field_squawk
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADSBSquawkView::collect_frames(const uint32_t ICAO_address, std::vector<ADSBFrame>& frame_list) {
|
||||||
|
ADSBFrame temp_frame;
|
||||||
|
(void)ICAO_address;
|
||||||
|
|
||||||
|
encode_frame_squawk(temp_frame, field_squawk.value_dec_u32());
|
||||||
|
|
||||||
|
frame_list.emplace_back(temp_frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ADSBTxView::focus() {
|
void ADSBTxView::focus() {
|
||||||
button_callsign.focus();
|
tab_view.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
ADSBTxView::~ADSBTxView() {
|
ADSBTxView::~ADSBTxView() {
|
||||||
@ -91,21 +221,19 @@ ADSBTxView::~ADSBTxView() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ADSBTxView::generate_frames() {
|
void ADSBTxView::generate_frames() {
|
||||||
uint8_t * bin_ptr = shared_memory.bb_data.data;
|
const uint32_t ICAO_address = sym_icao.value_hex_u64();
|
||||||
|
|
||||||
encode_frame_id(frames[0], sym_icao.value_hex_u64(), callsign);
|
view_position.collect_frames(ICAO_address, frames);
|
||||||
|
view_callsign.collect_frames(ICAO_address, frames);
|
||||||
|
view_speed.collect_frames(ICAO_address, frames);
|
||||||
|
view_squawk.collect_frames(ICAO_address, frames);
|
||||||
|
|
||||||
encode_frame_pos(frames[1], sym_icao.value_hex_u64(), field_altitude.value(),
|
//memset(bin_ptr, 0, 240);
|
||||||
field_lat_degrees.value(), field_lon_degrees.value(), 0);
|
|
||||||
encode_frame_pos(frames[2], sym_icao.value_hex_u64(), field_altitude.value(),
|
|
||||||
field_lat_degrees.value(), field_lon_degrees.value(), 1);
|
|
||||||
|
|
||||||
memset(bin_ptr, 0, 240);
|
//auto raw_ptr = frames[0].get_raw_data();
|
||||||
|
|
||||||
auto raw_ptr = frames[0].get_raw_data();
|
|
||||||
|
|
||||||
// The preamble isn't manchester encoded
|
// The preamble isn't manchester encoded
|
||||||
memcpy(bin_ptr, adsb_preamble, 16);
|
//memcpy(bin_ptr, adsb_preamble, 16);
|
||||||
|
|
||||||
// Convert to binary with manchester encoding (1 byte per bit, faster for baseband code)
|
// Convert to binary with manchester encoding (1 byte per bit, faster for baseband code)
|
||||||
/*for (c = 0; c < 112; c++) {
|
/*for (c = 0; c < 112; c++) {
|
||||||
@ -118,12 +246,12 @@ void ADSBTxView::generate_frames() {
|
|||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
manchester_encode(bin_ptr + 16, raw_ptr, 112, 0);
|
/*manchester_encode(bin_ptr + 16, raw_ptr, 112, 0);
|
||||||
|
|
||||||
// Display in hex for debug
|
// Display in hex for debug
|
||||||
text_frame.set(to_string_hex_array(frames[0].get_raw_data(), 14));
|
text_frame.set(to_string_hex_array(frames[0].get_raw_data(), 14));
|
||||||
|
|
||||||
button_callsign.set_text(callsign);
|
button_callsign.set_text(callsign);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void ADSBTxView::start_tx() {
|
void ADSBTxView::start_tx() {
|
||||||
@ -138,22 +266,22 @@ void ADSBTxView::start_tx() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ADSBTxView::on_txdone(const bool v) {
|
void ADSBTxView::on_txdone(const bool v) {
|
||||||
|
(void)v;
|
||||||
/*if (v) {
|
/*if (v) {
|
||||||
transmitter_model.disable();
|
transmitter_model.disable();
|
||||||
tx_view.set_transmitting(false);
|
tx_view.set_transmitting(false);
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void ADSBTxView::rotate_frames() {
|
void ADSBTxView::rotate_frames() {
|
||||||
// DEBUG
|
|
||||||
uint8_t * bin_ptr = shared_memory.bb_data.data;
|
uint8_t * bin_ptr = shared_memory.bb_data.data;
|
||||||
uint8_t * raw_ptr;
|
uint8_t * raw_ptr;
|
||||||
uint32_t frame_index = 0, plane_index = 0;
|
uint32_t frame_index = 0; //, plane_index = 0;
|
||||||
uint32_t c, regen = 0;
|
uint32_t c; //, regen = 0;
|
||||||
float offs = 0;
|
//float offs = 0;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!regen) {
|
/*if (!regen) {
|
||||||
regen = 10;
|
regen = 10;
|
||||||
|
|
||||||
encode_frame_id(frames[0], plane_index, "DEMO" + to_string_dec_uint(plane_index));
|
encode_frame_id(frames[0], plane_index, "DEMO" + to_string_dec_uint(plane_index));
|
||||||
@ -167,7 +295,7 @@ void ADSBTxView::on_txdone(const bool v) {
|
|||||||
plane_index++;
|
plane_index++;
|
||||||
|
|
||||||
offs += 0.001;
|
offs += 0.001;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
memset(bin_ptr, 0, 240);
|
memset(bin_ptr, 0, 240);
|
||||||
|
|
||||||
@ -188,91 +316,50 @@ void ADSBTxView::on_txdone(const bool v) {
|
|||||||
|
|
||||||
baseband::set_adsb();
|
baseband::set_adsb();
|
||||||
|
|
||||||
chThdSleepMilliseconds(5);
|
chThdSleepMilliseconds(50);
|
||||||
|
|
||||||
if (frame_index == 3) {
|
if (frame_index == frames.size()) {
|
||||||
frame_index = 0;
|
frame_index = 0;
|
||||||
if (regen)
|
//if (regen)
|
||||||
regen--;
|
// regen--;
|
||||||
} else {
|
} else {
|
||||||
frame_index++;
|
frame_index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
|
|
||||||
ADSBTxView::ADSBTxView(NavigationView& nav) {
|
ADSBTxView::ADSBTxView(
|
||||||
|
NavigationView& nav
|
||||||
|
) : nav_ { nav }
|
||||||
|
{
|
||||||
|
Rect view_rect = { 0, 7 * 8, 240, 192 };
|
||||||
baseband::run_image(portapack::spi_flash::image_tag_adsb_tx);
|
baseband::run_image(portapack::spi_flash::image_tag_adsb_tx);
|
||||||
|
|
||||||
add_children({
|
add_children({
|
||||||
&labels,
|
|
||||||
&tab_view,
|
&tab_view,
|
||||||
//&options_format,
|
&labels,
|
||||||
&sym_icao,
|
&sym_icao,
|
||||||
&button_callsign,
|
&view_position,
|
||||||
&field_altitude,
|
&view_callsign,
|
||||||
&field_lat_degrees,
|
&view_speed,
|
||||||
&field_lat_minutes,
|
&view_squawk,
|
||||||
&field_lat_seconds,
|
|
||||||
&field_lon_degrees,
|
|
||||||
&field_lon_minutes,
|
|
||||||
&field_lon_seconds,
|
|
||||||
&compass,
|
|
||||||
&field_angle,
|
|
||||||
&field_speed,
|
|
||||||
&check_emergency,
|
|
||||||
&field_squawk,
|
|
||||||
&text_frame,
|
&text_frame,
|
||||||
&tx_view
|
&tx_view
|
||||||
});
|
});
|
||||||
|
|
||||||
/*options_format.set_by_value(17); // Mode S
|
view_position.set_parent_rect(view_rect);
|
||||||
|
view_callsign.set_parent_rect(view_rect);
|
||||||
options_format.on_change = [this](size_t, int32_t) {
|
view_speed.set_parent_rect(view_rect);
|
||||||
generate_frames();
|
view_squawk.set_parent_rect(view_rect);
|
||||||
};*/
|
|
||||||
|
|
||||||
sym_icao.on_change = [this]() {
|
sym_icao.on_change = [this]() {
|
||||||
generate_frames();
|
generate_frames();
|
||||||
};
|
};
|
||||||
button_callsign.on_select = [this, &nav](Button&) {
|
|
||||||
text_prompt(nav, &callsign, 8);
|
|
||||||
};
|
|
||||||
|
|
||||||
field_altitude.set_value(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);
|
|
||||||
field_angle.set_value(0);
|
|
||||||
field_speed.set_value(0);
|
|
||||||
|
|
||||||
const auto update_fn = [this](int32_t) {
|
|
||||||
generate_frames();
|
|
||||||
};
|
|
||||||
|
|
||||||
field_altitude.on_change = update_fn;
|
|
||||||
field_lat_degrees.on_change = update_fn;
|
|
||||||
field_lat_minutes.on_change = update_fn;
|
|
||||||
field_lat_seconds.on_change = update_fn;
|
|
||||||
field_lon_degrees.on_change = update_fn;
|
|
||||||
field_lon_minutes.on_change = update_fn;
|
|
||||||
field_lon_seconds.on_change = update_fn;
|
|
||||||
|
|
||||||
field_angle.on_change = [this](int32_t v) {
|
|
||||||
compass.set_value(v);
|
|
||||||
generate_frames();
|
|
||||||
};
|
|
||||||
|
|
||||||
field_speed.on_change = update_fn;
|
|
||||||
|
|
||||||
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();
|
rotate_frames();
|
||||||
};
|
};
|
||||||
|
|
||||||
tx_view.on_stop = [this]() {
|
tx_view.on_stop = [this]() {
|
||||||
|
@ -51,8 +51,137 @@ private:
|
|||||||
|
|
||||||
const range_t<uint32_t> range { 0, 359 };
|
const range_t<uint32_t> range { 0, 359 };
|
||||||
uint32_t value_ { 0 };
|
uint32_t value_ { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
uint32_t clamp_value(uint32_t value);
|
class ADSBView : public View {
|
||||||
|
public:
|
||||||
|
ADSBView();
|
||||||
|
|
||||||
|
void focus() override;
|
||||||
|
|
||||||
|
void set_type(std::string type);
|
||||||
|
void collect_frames(const uint32_t ICAO_address, std::vector<ADSBFrame>& frame_list);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool enabled { false };
|
||||||
|
|
||||||
|
void set_enabled(bool value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Checkbox check_enable {
|
||||||
|
{ 2 * 8, 0 * 16 },
|
||||||
|
20,
|
||||||
|
"",
|
||||||
|
false
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
class ADSBPositionView : public ADSBView {
|
||||||
|
public:
|
||||||
|
ADSBPositionView(NavigationView& nav);
|
||||||
|
|
||||||
|
void collect_frames(const uint32_t ICAO_address, std::vector<ADSBFrame>& frame_list);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Labels labels_position {
|
||||||
|
{ { 2 * 8, 2 * 16 }, "Alt: feet", Color::light_grey() },
|
||||||
|
{ { 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 {
|
||||||
|
{ 7 * 8, 7 * 16, 14 * 8, 2 * 16 },
|
||||||
|
"Set from map"
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
class ADSBCallsignView : public ADSBView {
|
||||||
|
public:
|
||||||
|
ADSBCallsignView(NavigationView& nav);
|
||||||
|
|
||||||
|
void collect_frames(const uint32_t ICAO_address, std::vector<ADSBFrame>& frame_list);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string callsign = "TEST1234";
|
||||||
|
|
||||||
|
Labels labels_callsign {
|
||||||
|
{ { 2 * 8, 5 * 8 }, "Callsign:", Color::light_grey() }
|
||||||
|
};
|
||||||
|
|
||||||
|
Button button_callsign {
|
||||||
|
{ 12 * 8, 2 * 16, 10 * 8, 2 * 16 },
|
||||||
|
""
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
class ADSBSpeedView : public ADSBView {
|
||||||
|
public:
|
||||||
|
ADSBSpeedView();
|
||||||
|
|
||||||
|
void collect_frames(const uint32_t ICAO_address, std::vector<ADSBFrame>& frame_list);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Labels labels_speed {
|
||||||
|
{ { 1 * 8, 6 * 16 }, "Speed: kn Bearing: *", Color::light_grey() }
|
||||||
|
};
|
||||||
|
|
||||||
|
Compass compass {
|
||||||
|
{ 21 * 8, 2 * 16 }
|
||||||
|
};
|
||||||
|
|
||||||
|
NumberField field_angle {
|
||||||
|
{ 21 * 8 + 20, 6 * 16 }, 3, { 0, 359 }, 1, ' ', true
|
||||||
|
};
|
||||||
|
|
||||||
|
NumberField field_speed {
|
||||||
|
{ 8 * 8, 6 * 16 }, 3, { 0, 999 }, 5, ' '
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
class ADSBSquawkView : public ADSBView {
|
||||||
|
public:
|
||||||
|
ADSBSquawkView();
|
||||||
|
|
||||||
|
void collect_frames(const uint32_t ICAO_address, std::vector<ADSBFrame>& frame_list);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Labels labels_squawk {
|
||||||
|
{ { 2 * 8, 2 * 16 }, "Squawk:", Color::light_grey() }
|
||||||
|
};
|
||||||
|
|
||||||
|
SymField field_squawk {
|
||||||
|
{ 10 * 8, 2 * 16 },
|
||||||
|
4,
|
||||||
|
SymField::SYMFIELD_OCT
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
class ADSBTxView : public View {
|
class ADSBTxView : public View {
|
||||||
@ -101,133 +230,36 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
tx_modes tx_mode = IDLE;
|
tx_modes tx_mode = IDLE;
|
||||||
|
NavigationView& nav_;
|
||||||
std::string callsign = "TEST1234";
|
std::vector<ADSBFrame> frames { };
|
||||||
|
|
||||||
ADSBFrame frames[4] { };
|
|
||||||
|
|
||||||
void start_tx();
|
void start_tx();
|
||||||
void generate_frames();
|
void generate_frames();
|
||||||
//void rotate_frames();
|
void rotate_frames();
|
||||||
void on_txdone(const bool v);
|
void on_txdone(const bool v);
|
||||||
|
|
||||||
Labels labels {
|
ADSBPositionView view_position { nav_ };
|
||||||
//{ { 2 * 8, 2 * 8 }, "Format: 17 (ADS-B)", Color::light_grey() },
|
ADSBCallsignView view_callsign { nav_ };
|
||||||
{ { 2 * 8, 4 * 8 }, "ICAO24:", Color::light_grey() },
|
ADSBSpeedView view_speed { };
|
||||||
{ { 2 * 8, 7 * 8 }, "Callsign:", Color::light_grey() },
|
ADSBSquawkView view_squawk { };
|
||||||
{ { 1 * 8, 11 * 8 }, "Alt: feet", Color::light_grey() },
|
|
||||||
{ { 1 * 8, 13 * 8 }, "Lat: * ' \"", Color::light_grey() }, // No ° symbol in 8x16 font
|
|
||||||
{ { 1 * 8, 15 * 8 }, "Lon: * ' \"", Color::light_grey() },
|
|
||||||
{ { 1 * 8, 18 * 8 }, "Speed: kn Bearing: *", Color::light_grey() },
|
|
||||||
{ { 16 * 8, 22 * 8 }, "Squawk:", Color::light_grey() }
|
|
||||||
};
|
|
||||||
|
|
||||||
// Only ADS-B is implemented right now
|
|
||||||
/*OptionsField options_format {
|
|
||||||
{ 10 * 8, 1 * 16 },
|
|
||||||
9,
|
|
||||||
{
|
|
||||||
{ "17: ADS-B", 17 },
|
|
||||||
{ "18: TIS-B", 18 },
|
|
||||||
{ "19: MIL ", 19 },
|
|
||||||
}
|
|
||||||
};*/
|
|
||||||
|
|
||||||
TabView tab_view {
|
TabView tab_view {
|
||||||
{ "Position#", Color::cyan(),
|
{ "Position", Color::cyan(), &view_position },
|
||||||
{
|
{ "Callsign", Color::green(), &view_callsign },
|
||||||
&labels,
|
{ "Speed", Color::yellow(), &view_speed },
|
||||||
&field_altitude,
|
{ "Squawk", Color::orange(), &view_squawk }
|
||||||
&field_lat_degrees,
|
};
|
||||||
&field_lat_minutes,
|
|
||||||
&field_lat_seconds,
|
Labels labels {
|
||||||
&field_lon_degrees,
|
{ { 2 * 8, 4 * 8 }, "ICAO24:", Color::light_grey() }
|
||||||
&field_lon_minutes,
|
|
||||||
&field_lon_seconds
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ "Callsign", Color::green(),
|
|
||||||
{
|
|
||||||
&button_callsign,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ "Speed", Color::yellow(),
|
|
||||||
{
|
|
||||||
&compass,
|
|
||||||
&field_angle,
|
|
||||||
&field_speed
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ "Squawk", Color::orange(),
|
|
||||||
{
|
|
||||||
&check_emergency,
|
|
||||||
&field_squawk
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SymField sym_icao {
|
SymField sym_icao {
|
||||||
{ 10 * 8, 2 * 16 },
|
{ 10 * 8, 4 * 8 },
|
||||||
6,
|
6,
|
||||||
SymField::SYMFIELD_HEX
|
SymField::SYMFIELD_HEX
|
||||||
};
|
};
|
||||||
|
|
||||||
Button button_callsign {
|
|
||||||
{ 12 * 8, 3 * 16 + 4, 10 * 8, 24 },
|
|
||||||
""
|
|
||||||
};
|
|
||||||
|
|
||||||
NumberField field_altitude {
|
|
||||||
{ 6 * 8, 11 * 8 },
|
|
||||||
5,
|
|
||||||
{ -1000, 50000 },
|
|
||||||
250,
|
|
||||||
' '
|
|
||||||
};
|
|
||||||
|
|
||||||
NumberField field_lat_degrees {
|
|
||||||
{ 6 * 8, 13 * 8 }, 4, { -90, 90 }, 1, ' '
|
|
||||||
};
|
|
||||||
NumberField field_lat_minutes {
|
|
||||||
{ 11 * 8, 13 * 8 }, 2, { 0, 59 }, 1, ' '
|
|
||||||
};
|
|
||||||
NumberField field_lat_seconds {
|
|
||||||
{ 14 * 8, 13 * 8 }, 2, { 0, 59 }, 1, ' '
|
|
||||||
};
|
|
||||||
|
|
||||||
NumberField field_lon_degrees {
|
|
||||||
{ 6 * 8, 15 * 8 }, 4, { -180, 180 }, 1, ' '
|
|
||||||
};
|
|
||||||
NumberField field_lon_minutes {
|
|
||||||
{ 11 * 8, 15 * 8 }, 2, { 0, 59 }, 1, ' '
|
|
||||||
};
|
|
||||||
NumberField field_lon_seconds {
|
|
||||||
{ 14 * 8, 15 * 8 }, 2, { 0, 59 }, 1, ' '
|
|
||||||
};
|
|
||||||
|
|
||||||
Compass compass {
|
|
||||||
{ 21 * 8, 5 * 16 }
|
|
||||||
};
|
|
||||||
NumberField field_angle {
|
|
||||||
{ 21 * 8 + 20, 9 * 16 }, 3, { 0, 359 }, 1, ' ', true
|
|
||||||
};
|
|
||||||
|
|
||||||
NumberField field_speed {
|
|
||||||
{ 8 * 8, 18 * 8 }, 3, { 0, 999 }, 5, ' '
|
|
||||||
};
|
|
||||||
|
|
||||||
Checkbox check_emergency {
|
|
||||||
{ 2 * 8, 11 * 16 - 4 },
|
|
||||||
9,
|
|
||||||
"Emergency",
|
|
||||||
false
|
|
||||||
};
|
|
||||||
SymField field_squawk {
|
|
||||||
{ 24 * 8, 11 * 16 },
|
|
||||||
4,
|
|
||||||
SymField::SYMFIELD_OCT
|
|
||||||
};
|
|
||||||
|
|
||||||
Text text_frame {
|
Text text_frame {
|
||||||
{ 1 * 8, 29 * 8, 14 * 8, 16 },
|
{ 1 * 8, 29 * 8, 14 * 8, 16 },
|
||||||
"-"
|
"-"
|
||||||
|
@ -96,8 +96,10 @@ void GeoMapView::move_map() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GeoMapView::GeoMapView(
|
GeoMapView::GeoMapView(
|
||||||
NavigationView& nav
|
NavigationView& nav,
|
||||||
) : nav_ (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()) {
|
||||||
@ -113,19 +115,22 @@ GeoMapView::GeoMapView(
|
|||||||
|
|
||||||
add_children({
|
add_children({
|
||||||
&field_xpos,
|
&field_xpos,
|
||||||
&field_ypos,
|
&field_ypos
|
||||||
&field_angle
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (mode_ == SHOW) {
|
||||||
|
add_child(&field_angle);
|
||||||
|
field_angle.on_change = [this](int32_t) {
|
||||||
|
move_map();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
field_xpos.on_change = [this](int32_t) {
|
field_xpos.on_change = [this](int32_t) {
|
||||||
move_map();
|
move_map();
|
||||||
};
|
};
|
||||||
field_ypos.on_change = [this](int32_t) {
|
field_ypos.on_change = [this](int32_t) {
|
||||||
move_map();
|
move_map();
|
||||||
};
|
};
|
||||||
field_angle.on_change = [this](int32_t) {
|
|
||||||
move_map();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
@ -31,7 +31,12 @@ namespace ui {
|
|||||||
|
|
||||||
class GeoMapView : public View {
|
class GeoMapView : public View {
|
||||||
public:
|
public:
|
||||||
GeoMapView(NavigationView& nav);
|
enum Mode {
|
||||||
|
SHOW,
|
||||||
|
SET
|
||||||
|
};
|
||||||
|
|
||||||
|
GeoMapView(NavigationView& nav, Mode mode);
|
||||||
~GeoMapView();
|
~GeoMapView();
|
||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
@ -40,6 +45,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
|
Mode mode_ { };
|
||||||
|
|
||||||
File map_file { };
|
File map_file { };
|
||||||
bool file_error { false };
|
bool file_error { false };
|
||||||
|
@ -47,12 +47,12 @@ void Tab::set(
|
|||||||
|
|
||||||
void Tab::paint(Painter& painter) {
|
void Tab::paint(Painter& painter) {
|
||||||
const auto rect = screen_rect();
|
const auto rect = screen_rect();
|
||||||
const Color color = highlighted() ? Color::black() : Color::light_grey();
|
const Color color = highlighted() ? Color::black() : Color::grey();
|
||||||
|
|
||||||
painter.fill_rectangle({ rect.left(), rect.top(), rect.width() - 8, rect.height() }, color);
|
painter.fill_rectangle({ rect.left(), rect.top(), rect.width() - 8, rect.height() }, color);
|
||||||
|
|
||||||
if (!highlighted())
|
if (!highlighted())
|
||||||
painter.draw_hline({ rect.left(), rect.top() }, rect.width() - 9, Color::white());
|
painter.draw_hline({ rect.left(), rect.top() }, rect.width() - 9, Color::light_grey());
|
||||||
|
|
||||||
painter.draw_bitmap(
|
painter.draw_bitmap(
|
||||||
{ rect.right() - 8, rect.top() },
|
{ rect.right() - 8, rect.top() },
|
||||||
@ -105,50 +105,38 @@ void TabView::set_selected(uint16_t index) {
|
|||||||
if (index >= n_tabs)
|
if (index >= n_tabs)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//if (index == current_tab)
|
// Hide previous view
|
||||||
// return;
|
views[current_tab]->hidden(true);
|
||||||
|
|
||||||
// Hide all widgets
|
|
||||||
for (const auto widget : parent()->children()) {
|
|
||||||
widget->hidden(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Except this one :)
|
|
||||||
hidden(false);
|
|
||||||
|
|
||||||
tab = &tabs[current_tab];
|
tab = &tabs[current_tab];
|
||||||
tab->set_highlighted(false);
|
tab->set_highlighted(false);
|
||||||
tab->set_focusable(true);
|
tab->set_focusable(true);
|
||||||
tab->set_dirty();
|
tab->set_dirty();
|
||||||
|
|
||||||
// Show new tab's widgets
|
// Show new view
|
||||||
for (auto widget : widget_lists[index]) {
|
views[index]->hidden(false);
|
||||||
widget->hidden(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
tab = &tabs[index];
|
tab = &tabs[index];
|
||||||
current_tab = index;
|
current_tab = index;
|
||||||
tab->set_highlighted(true);
|
tab->set_highlighted(true);
|
||||||
tab->set_focusable(false);
|
tab->set_focusable(false);
|
||||||
tab->set_dirty();
|
tab->set_dirty();
|
||||||
|
|
||||||
parent()->set_dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabView::focus() {
|
|
||||||
tabs[current_tab].focus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabView::on_show() {
|
void TabView::on_show() {
|
||||||
set_selected(current_tab);
|
set_selected(current_tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabView::focus() {
|
||||||
|
views[current_tab]->focus();
|
||||||
|
}
|
||||||
|
|
||||||
TabView::TabView(std::initializer_list<TabDef> tab_definitions) {
|
TabView::TabView(std::initializer_list<TabDef> tab_definitions) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|
||||||
n_tabs = tab_definitions.size();
|
n_tabs = tab_definitions.size();
|
||||||
if (n_tabs > 5)
|
if (n_tabs > MAX_TABS)
|
||||||
n_tabs = 5;
|
n_tabs = MAX_TABS;
|
||||||
|
|
||||||
size_t tab_width = 240 / n_tabs;
|
size_t tab_width = 240 / n_tabs;
|
||||||
|
|
||||||
@ -156,12 +144,10 @@ TabView::TabView(std::initializer_list<TabDef> tab_definitions) {
|
|||||||
|
|
||||||
for (auto &tab_definition : tab_definitions) {
|
for (auto &tab_definition : tab_definitions) {
|
||||||
tabs[i].set(i, tab_width, tab_definition.text, tab_definition.color);
|
tabs[i].set(i, tab_width, tab_definition.text, tab_definition.color);
|
||||||
for (auto widget : tab_definition.widget_list) {
|
views[i] = tab_definition.view;
|
||||||
widget_lists[i].emplace_back(widget);
|
|
||||||
}
|
|
||||||
add_child(&tabs[i]);
|
add_child(&tabs[i]);
|
||||||
i++;
|
i++;
|
||||||
if (i == 5) break;
|
if (i == MAX_TABS) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,8 @@
|
|||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
|
#define MAX_TABS 5
|
||||||
|
|
||||||
class Tab : public Widget {
|
class Tab : public Widget {
|
||||||
public:
|
public:
|
||||||
Tab();
|
Tab();
|
||||||
@ -56,7 +58,7 @@ public:
|
|||||||
struct TabDef {
|
struct TabDef {
|
||||||
std::string text;
|
std::string text;
|
||||||
ui::Color color;
|
ui::Color color;
|
||||||
std::initializer_list<Widget*> widget_list;
|
View* view;
|
||||||
};
|
};
|
||||||
|
|
||||||
TabView(std::initializer_list<TabDef> tab_definitions);
|
TabView(std::initializer_list<TabDef> tab_definitions);
|
||||||
@ -69,8 +71,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
size_t n_tabs { };
|
size_t n_tabs { };
|
||||||
std::array<Tab, 5> tabs { };
|
std::array<Tab, MAX_TABS> tabs { };
|
||||||
std::array<std::vector<Widget*>, 5> widget_lists { };
|
std::array<View*, MAX_TABS> views { };
|
||||||
uint32_t current_tab { 0 };
|
uint32_t current_tab { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -74,8 +74,8 @@ void encode_frame_pos(ADSBFrame& frame, const uint32_t ICAO_address, const uint3
|
|||||||
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);
|
||||||
void encode_frame_emergency(ADSBFrame& frame, const uint32_t ICAO_address, const uint8_t code);
|
//void encode_frame_emergency(ADSBFrame& frame, const uint32_t ICAO_address, const uint8_t code);
|
||||||
void encode_frame_identity(ADSBFrame& frame, const uint32_t ICAO_address, const uint32_t code);
|
void encode_frame_squawk(ADSBFrame& frame, const uint32_t squawk);
|
||||||
|
|
||||||
} /* namespace adsb */
|
} /* namespace adsb */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user