Compare commits

...

6 Commits

Author SHA1 Message Date
Totoo 6b02ba6e5d Faster osm (#2874)
Much faster OSM map handler
2025-11-21 09:30:01 +01:00
Totoo c01597baf2 Pocsag manual baud option (#2870)
* baseband part of manual baud control of pocsag

* added manual pocsag baud to ui, to fix #2546

* fix adult toys settings filename
2025-11-18 14:05:27 +01:00
Totoo 43a5163b77 prevent sonde pos to change to 0 when the frame is invalid. fixes #2862 (#2869) 2025-11-18 19:07:40 +08:00
jLynx c46cc431c9 Revert "resolve conflicts merge" (#2860)
This reverts commit 344aa0c741.
2025-11-08 10:21:33 +13:00
jLynx a4d23768c1 Update version.txt (#2858) 2025-11-08 10:13:35 +13:00
gullradriel 344aa0c741 resolve conflicts merge 2025-11-07 21:36:41 +01:00
17 changed files with 179 additions and 35 deletions
+1 -1
View File
@@ -1 +1 @@
v2.3.0
v2.3.1
+5 -2
View File
@@ -56,6 +56,7 @@ POCSAGSettingsView::POCSAGSettingsView(
: settings_{settings} {
add_children(
{&labels,
&opt_baud_rate,
&check_log,
&check_log_raw,
&check_small_font,
@@ -65,6 +66,7 @@ POCSAGSettingsView::POCSAGSettingsView(
&field_filter_address,
&button_save});
opt_baud_rate.set_by_value(settings_.baud_rate);
check_log.set_value(settings_.enable_logging);
check_log_raw.set_value(settings_.enable_raw_log);
check_small_font.set_value(settings_.enable_small_font);
@@ -81,7 +83,7 @@ POCSAGSettingsView::POCSAGSettingsView(
settings_.hide_addr_only = check_hide_addr_only.value();
settings_.filter_mode = opt_filter_mode.selected_index_value();
settings_.filter_address = field_filter_address.to_integer();
settings_.baud_rate = opt_baud_rate.selected_index_value();
nav.pop();
};
}
@@ -142,7 +144,7 @@ POCSAGAppView::POCSAGAppView(NavigationView& nav)
audio::output::start();
receiver_model.enable();
baseband::set_pocsag();
baseband::set_pocsag((int8_t)settings_.baud_rate);
}
void POCSAGAppView::focus() {
@@ -182,6 +184,7 @@ void POCSAGAppView::refresh_ui() {
btn_text = "Filter Last";
break;
}
baseband::set_pocsag((int8_t)settings_.baud_rate);
button_filter_last.set_text(btn_text);
}
+11
View File
@@ -126,6 +126,7 @@ struct POCSAGSettings {
bool hide_bad_data = false;
bool hide_addr_only = false;
uint8_t filter_mode = false;
int32_t baud_rate = -1;
uint32_t filter_address = 0;
};
@@ -139,7 +140,16 @@ class POCSAGSettingsView : public View {
private:
POCSAGSettings& settings_;
OptionsField opt_baud_rate{
{8 * 8, 0 * 16},
4,
{{"Auto", -1},
{" 512", 0},
{"1200", 1},
{"2400", 2}}};
Labels labels{
{{2 * 8, 0 * 16}, "Baud:", Theme::getInstance()->fg_light->foreground},
{{2 * 8, 12 * 16}, "Filter Mode:", Theme::getInstance()->fg_light->foreground},
{{2 * 8, 13 * 16}, "Filter Addr:", Theme::getInstance()->fg_light->foreground},
};
@@ -221,6 +231,7 @@ class POCSAGAppView : public View {
{"filter_address"sv, &settings_.filter_address},
{"hide_bad_data"sv, &settings_.hide_bad_data},
{"hide_addr_only"sv, &settings_.hide_addr_only},
{"baud_rate"sv, &settings_.baud_rate},
}};
void refresh_ui();
+5 -4
View File
@@ -174,10 +174,11 @@ void SondeView::on_packet(const sonde::Packet& packet) {
gps_info = packet.get_GPS_data();
geopos.set_altitude(gps_info.alt);
geopos.set_lat(gps_info.lat);
geopos.set_lon(gps_info.lon);
if (gps_info.lat != 0 && gps_info.lon != 0) { // only update when valid, to prevent flashing
geopos.set_altitude(gps_info.alt);
geopos.set_lat(gps_info.lat);
geopos.set_lon(gps_info.lon);
}
if (logger && logging) {
logger->on_packet(packet);
}
+2 -2
View File
@@ -288,8 +288,8 @@ void set_fsk_data(const uint32_t stream_length, const uint32_t samples_per_bit,
send_message(&message);
}
void set_pocsag() {
const POCSAGConfigureMessage message{};
void set_pocsag(int8_t baud_config) {
const POCSAGConfigureMessage message{baud_config};
send_message(&message);
}
+1 -1
View File
@@ -91,7 +91,7 @@ void set_nrf(const uint32_t baudrate, const uint32_t word_length, const uint32_t
void set_ook_data(const uint32_t stream_length, const uint32_t samples_per_bit, const uint8_t repeat, const uint32_t pause_symbols, const uint8_t de_bruijn_length = 0);
void kill_ook();
void set_fsk_data(const uint32_t stream_length, const uint32_t samples_per_bit, const uint32_t shift, const uint32_t progress_notice);
void set_pocsag();
void set_pocsag(int8_t baud_config = -1);
void set_adsb();
void set_jammer(const bool run, const jammer::JammerType type, const uint32_t speed);
void set_rds_data(const uint16_t message_length);
@@ -104,7 +104,7 @@ class AdultToysView : public ui::View {
/*short_ui*/ true};
app_settings::SettingsManager settings_{
"Adult Toys", app_settings::Mode::TX};
"tx_adult_toys", app_settings::Mode::TX};
OptionsField options_target{
{UI_POS_X(6), UI_POS_Y(1)},
+15 -7
View File
@@ -454,14 +454,22 @@ bool GeoMap::draw_osm_file(int zoom, int tile_x, int tile_y, int relative_x, int
return false;
}
std::vector<ui::Color> line(clip_w);
for (int y = 0; y < clip_h; ++y) {
int source_row = src_y + y;
int dest_row = dest_y + y;
bmp.seek(src_x, source_row);
for (int x = 0; x < clip_w; ++x) {
bmp.read_next_px(line[x], true);
if (bmp.is_bottomup()) {
for (int y = clip_h - 1; y >= 0; --y) {
int source_row = src_y + y;
int dest_row = dest_y + y;
bmp.seek(src_x, source_row);
bmp.read_next_px_cnt(line.data(), clip_w, false);
display.draw_pixels({dest_x + r.left(), dest_row + r.top(), clip_w, 1}, line);
}
} else {
for (int y = 0; y < clip_h; ++y) {
int source_row = src_y + y;
int dest_row = dest_y + y;
bmp.seek(src_x, source_row);
bmp.read_next_px_cnt(line.data(), clip_w, false);
display.draw_pixels({dest_x + r.left(), dest_row + r.top(), clip_w, 1}, line);
}
display.draw_pixels({dest_x + r.left(), dest_row + r.top(), clip_w, 1}, line);
}
return true;
}
+19 -5
View File
@@ -159,13 +159,27 @@ void BitExtractor::configure(uint32_t sample_rate) {
// without needing to know exact transition boundaries.
for (auto& rate : known_rates_)
rate.sample_interval = sample_rate / (2.0 * rate.baud_rate);
if (baud_config_ >= 0 && baud_config_ < static_cast<int8_t>(known_rates_.size())) {
current_rate_ = &known_rates_[baud_config_];
} else {
current_rate_ = nullptr;
}
}
void BitExtractor::reset() {
current_rate_ = nullptr;
for (auto& rate : known_rates_)
rate.reset();
if (baud_config_ >= 0 && baud_config_ < static_cast<int8_t>(known_rates_.size())) {
current_rate_ = &known_rates_[baud_config_];
} else {
current_rate_ = nullptr;
}
}
void BitExtractor::set_baud_config(int8_t baud_config) {
baud_config_ = baud_config;
}
uint16_t BitExtractor::baud_rate() const {
@@ -352,7 +366,7 @@ void POCSAGProcessor::execute(const buffer_c8_t& buffer) {
void POCSAGProcessor::on_message(const Message* const message) {
switch (message->id) {
case Message::ID::POCSAGConfigure:
configure();
configure(reinterpret_cast<const POCSAGConfigureMessage*>(message)->baud_config);
break;
case Message::ID::NBFMConfigure: {
@@ -370,7 +384,7 @@ void POCSAGProcessor::on_message(const Message* const message) {
}
}
void POCSAGProcessor::configure() {
void POCSAGProcessor::configure(int8_t baud_config) {
constexpr size_t decim_0_output_fs = baseband_fs / decim_0.decimation_factor;
constexpr size_t decim_1_output_fs = decim_0_output_fs / decim_1.decimation_factor;
constexpr size_t channel_filter_output_fs = decim_1_output_fs / 2;
@@ -383,7 +397,7 @@ void POCSAGProcessor::configure() {
// Don't process the audio stream.
audio_output.configure(false);
bit_extractor.set_baud_config(baud_config);
bit_extractor.configure(demod_input_fs);
// Set ready to process data.
+3 -2
View File
@@ -84,6 +84,7 @@ class BitExtractor {
void extract_bits(const buffer_f32_t& audio);
void configure(uint32_t sample_rate);
void reset();
void set_baud_config(int8_t baud_config);
uint16_t baud_rate() const;
private:
@@ -117,7 +118,7 @@ class BitExtractor {
RateInfo{2400}};
BitQueue& bits_;
int8_t baud_config_ = -1;
uint32_t sample_rate_ = 0;
RateInfo* current_rate_ = nullptr;
};
@@ -207,7 +208,7 @@ class POCSAGProcessor : public BasebandProcessor {
static constexpr uint32_t stat_update_threshold =
baseband_fs / stat_update_interval;
void configure();
void configure(int8_t baud_config = -1);
void flush();
void reset();
void send_stats() const;
+47
View File
@@ -200,6 +200,53 @@ bool BMPFile::read_next_px(ui::Color& px, bool seek = true) {
return true;
}
bool BMPFile::read_next_px_cnt(ui::Color* px, uint32_t count, bool seek) {
if (!is_opened) return false;
size_t bytesneeded = byte_per_px * count;
while (bytesneeded > 0) { // read in batches
size_t currusedbytes = bytesneeded > 512 ? 170 * byte_per_px : bytesneeded; // don't mind this magic number.
uint8_t buffer[currusedbytes];
auto res = bmpimage.read(buffer, currusedbytes);
if (res.is_error()) return false;
for (uint32_t i = 0; i < currusedbytes; i += byte_per_px, px++) {
switch (type) {
case 5: {
// ARGB1555
uint16_t val = buffer[i] | (buffer[i + 1] << 8);
// Extract components
//*a = (val >> 15) & 0x01; // 1-bit alpha
uint8_t r = (val >> 10) & 0x1F; // 5-bit red
uint8_t g = (val >> 5) & 0x1F; // 5-bit green
uint8_t b = (val)&0x1F; // 5-bit blue
// expand
r = (r << 3) | (r >> 2);
g = (g << 3) | (g >> 2);
b = (b << 3) | (b >> 2);
*px = ui::Color(r, g, b);
break;
}
case 2: // 32
*px = ui::Color(buffer[i + 2], buffer[i + 1], buffer[i]);
break;
case 4: { // 8-bit
// uint8_t index = buffer[0];
// px = ui::Color(color_palette[index][2], color_palette[index][1], color_palette[index][0]); // Palette is BGR
// px = ui::Color(buffer[0]); // niy, since needs a lot of ram for the palette
break;
}
case 1: // 24
default:
*px = ui::Color(buffer[i + 2], buffer[i + 1], buffer[i]);
break;
}
}
bytesneeded -= currusedbytes;
}
if (seek) advance_curr_px(count);
return true;
}
// if you set this, then the expanded part (or the newly created) will be filled with this color. but the expansion or the creation will be slower.
void BMPFile::set_bg_color(ui::Color background) {
bg = background;
+1
View File
@@ -42,6 +42,7 @@ class BMPFile {
uint32_t getbpr() { return byte_per_row; };
bool read_next_px(ui::Color& px, bool seek);
bool read_next_px_cnt(ui::Color* px, uint32_t count, bool seek);
bool write_next_px(ui::Color& px);
uint32_t get_real_height();
uint32_t get_width();
+3 -2
View File
@@ -1187,9 +1187,10 @@ class FSKRxConfigureMessage : public Message {
class POCSAGConfigureMessage : public Message {
public:
constexpr POCSAGConfigureMessage()
: Message{ID::POCSAGConfigure} {
constexpr POCSAGConfigureMessage(int8_t baud_config = -1)
: Message{ID::POCSAGConfigure}, baud_config(baud_config) {
}
int8_t baud_config; //-1 auto, 0=512,1=1200,2=2400
};
class APRSPacketMessage : public Message {
+48 -1
View File
@@ -173,7 +173,7 @@ bool BMPFile::read_next_px(ui::Color& px, bool seek = true) {
//*a = (val >> 15) & 0x01; // 1-bit alpha
uint8_t r = (val >> 10) & 0x1F; // 5-bit red
uint8_t g = (val >> 5) & 0x1F; // 5-bit green
uint8_t b = (val)&0x1F; // 5-bit blue
uint8_t b = (val) & 0x1F; // 5-bit blue
// expand
r = (r << 3) | (r >> 2);
g = (g << 3) | (g >> 2);
@@ -200,6 +200,53 @@ bool BMPFile::read_next_px(ui::Color& px, bool seek = true) {
return true;
}
bool BMPFile::read_next_px_cnt(ui::Color* px, uint32_t count, bool seek) {
if (!is_opened) return false;
size_t bytesneeded = byte_per_px * count;
while (bytesneeded > 0) { // read in batches
size_t currusedbytes = bytesneeded > 256 ? 85 * byte_per_px : bytesneeded; // don't mind this magic number.
uint8_t buffer[currusedbytes];
auto res = bmpimage.read(buffer, currusedbytes);
if (res.is_error()) return false;
for (uint32_t i = 0; i < currusedbytes; i += byte_per_px, px++) {
switch (type) {
case 5: {
// ARGB1555
uint16_t val = buffer[i] | (buffer[i + 1] << 8);
// Extract components
//*a = (val >> 15) & 0x01; // 1-bit alpha
uint8_t r = (val >> 10) & 0x1F; // 5-bit red
uint8_t g = (val >> 5) & 0x1F; // 5-bit green
uint8_t b = (val) & 0x1F; // 5-bit blue
// expand
r = (r << 3) | (r >> 2);
g = (g << 3) | (g >> 2);
b = (b << 3) | (b >> 2);
*px = ui::Color(r, g, b);
break;
}
case 2: // 32
*px = ui::Color(buffer[i + 2], buffer[i + 1], buffer[i]);
break;
case 4: { // 8-bit
// uint8_t index = buffer[0];
// px = ui::Color(color_palette[index][2], color_palette[index][1], color_palette[index][0]); // Palette is BGR
// px = ui::Color(buffer[0]); // niy, since needs a lot of ram for the palette
break;
}
case 1: // 24
default:
*px = ui::Color(buffer[i + 2], buffer[i + 1], buffer[i]);
break;
}
}
bytesneeded -= currusedbytes;
}
if (seek) advance_curr_px(count);
return true;
}
// if you set this, then the expanded part (or the newly created) will be filled with this color. but the expansion or the creation will be slower.
void BMPFile::set_bg_color(ui::Color background) {
bg = background;
@@ -42,6 +42,7 @@ class BMPFile {
uint32_t getbpr() { return byte_per_row; };
bool read_next_px(ui::Color& px, bool seek);
bool read_next_px_cnt(ui::Color* px, uint32_t count, bool seek);
bool write_next_px(ui::Color& px);
uint32_t get_real_height();
uint32_t get_width();
+15 -7
View File
@@ -451,14 +451,22 @@ bool GeoMap::draw_osm_file(int zoom, int tile_x, int tile_y, int relative_x, int
return false;
}
std::vector<ui::Color> line(clip_w);
for (int y = 0; y < clip_h; ++y) {
int source_row = src_y + y;
int dest_row = dest_y + y;
bmp.seek(src_x, source_row);
for (int x = 0; x < clip_w; ++x) {
bmp.read_next_px(line[x], true);
if (bmp.is_bottomup()) {
for (int y = clip_h - 1; y >= 0; --y) {
int source_row = src_y + y;
int dest_row = dest_y + y;
bmp.seek(src_x, source_row);
bmp.read_next_px_cnt(line.data(), clip_w, false);
painter.draw_pixels({dest_x + r.left(), dest_row + r.top(), clip_w, 1}, line);
}
} else {
for (int y = 0; y < clip_h; ++y) {
int source_row = src_y + y;
int dest_row = dest_y + y;
bmp.seek(src_x, source_row);
bmp.read_next_px_cnt(line.data(), clip_w, false);
painter.draw_pixels({dest_x + r.left(), dest_row + r.top(), clip_w, 1}, line);
}
painter.draw_pixels({dest_x + r.left(), dest_row + r.top(), clip_w, 1}, line);
}
return true;
}
+1
View File
@@ -25,6 +25,7 @@
bool notouch(int, int, uint32_t) {
// do nothing
return false;
}
void nothing() {
// do nothing