Compare commits

...

11 Commits

Author SHA1 Message Date
jLynx 572776bb9e Update past_version.txt 2024-09-23 17:17:47 +12:00
jLynx 073c4ed9f2 Update version.txt 2024-09-23 17:17:38 +12:00
zxkmm 42233e62df transparent splash logo & fix tab widget color glitch (#2256) 2024-09-22 19:40:54 +02:00
zxkmm 9390317a75 add shift feat for protcol view tool (#2258)
* add shift

* add shift

* format

* add padding (wrote by AI)

* layout fine tune

* remove debug thing

* edit per request

* remove torjan (jk)

* int 16 should be good enough for it
2024-09-22 15:30:31 +02:00
Erwin Ried 89b51095bf New H4M version (#2259) 2024-09-21 16:15:17 +02:00
Totoo 9438c9a574 SSTV TX to ext (#2254)
* SSTV TX to ext
2024-09-20 21:41:44 +08:00
jLynx 7feef9d38b Learn ic fix (#2253)
* WIP

* Fixed merge

* Added test code

* WIP

* Clean up

* add reset learned params

* ui fix

* ui fix2

* Updated func

* Fixed english

* WIP

* WIP testing

* Added new debug app

* Got new app for debug

* Got new app for debug

* Got one full page showing

* Got app working with all reg

* Got app working with all reg

* Got full hex showing

* Fixed dp

* Fixed dp

* Moved entities

* Enabled apps again

* SHow battery debug if ic

* WIP

* Refactored further

* WIP

* Refactor and clean up

* Refactor and clean up

* fix warning, add tte/ttf, add cycles counter.

* wip

* morse tx to ext app

* fix morse crash

* fix ui

* Updated wording

* WIP

* WIP

* Updated to display hours and minutes

---------

Co-authored-by: HTotoo <ttotoo@gmail.com>
2024-09-20 09:59:17 +00:00
zxkmm 582bb02a75 add bitmap arr to file (or reverse) converter (#2248)
* add covert tool

* fix for generator

* fix for generator
2024-09-20 09:56:33 +02:00
Totoo bfa7f3ca6b Wardrive map improv (#2251)
Added paginator.
Added Flipper SUB file support.
2024-09-16 21:59:28 +02:00
Mark Thompson 21facd9cc3 Options to select 314.9 or 315MHz TPMS freq (#2252) 2024-09-15 23:20:04 -05:00
zxkmm d30234aaa6 reword of #2158 (#2249) 2024-09-11 19:11:11 +02:00
44 changed files with 1755 additions and 1112 deletions
+1 -1
View File
@@ -1 +1 @@
v2.0.0
v2.0.1
+1 -1
View File
@@ -1 +1 @@
v2.0.1
v2.0.2
+2 -2
View File
@@ -27,12 +27,12 @@ This repository expands upon the previous work by many people and aims to consta
## What to buy?
:heavy_check_mark: ![Static Badge](https://img.shields.io/badge/NEW-yellow) The fabulous [PortaPack H4M Mayhem](https://grabify.link/VPMPSL), featuring numerous improvements and accessories. Sold by our friends at OpenSourceSDRLab. Join their giveaways on discord (check the badge on top).
:heavy_check_mark: A recommended one is this [PortaPack H2](https://grabify.link/7T28JP), that includes everything you need with the plastic case "inspired" on [this](https://github.com/portapack-mayhem/mayhem-firmware/wiki/H2-Enclosure).
:heavy_check_mark: Some individuals lean towards the [H2 with a metal enclosure](https://grabify.link/HTDXG5), but its advantages remain debated. Share your insights on our [wiki](https://github.com/portapack-mayhem/mayhem-firmware/wiki/Hardware-overview).
:heavy_check_mark: Our friends at OpenSourceSDRLab give away five units every three months in our discord (check the badge on top) of one of their [PortaPack H2 bundle](https://grabify.link/T328XL) or [only metal case kits](https://grabify.link/LG0OUY), you can support them too by ordering.
:warning: Be cautious , *ask* the seller about compatibility with the latest releases. Look out for the description of the item, if they provide the firmware files for an older version or they have custom setup instructions, this means it might be **NOT compatible**, for example:
![image](https://user-images.githubusercontent.com/1091420/214579017-9ad970b9-0917-48f6-a550-588226d3f89b.png)
+4 -2
View File
@@ -206,6 +206,7 @@ set(CPPSRC
irq_rtc.cpp
log_file.cpp
metadata_file.cpp
flipper_subfile.cpp
portapack.cpp
usb_serial_shell.cpp
usb_serial_shell_filesystem.cpp
@@ -291,6 +292,7 @@ set(CPPSRC
apps/ui_btle_rx.cpp
# apps/ui_coasterp.cpp
apps/ui_debug.cpp
apps/ui_debug_battery.cpp
apps/ui_dfu_menu.cpp
apps/ui_encoders.cpp
apps/ui_fileman.cpp
@@ -305,7 +307,7 @@ set(CPPSRC
apps/ui_looking_glass_app.cpp
apps/ui_mictx.cpp
apps/ui_modemsetup.cpp
apps/ui_morse.cpp
# apps/ui_morse.cpp
# apps/ui_nrf_rx.cpp
# apps/ui_nuoptix.cpp
apps/ui_playlist.cpp
@@ -325,7 +327,7 @@ set(CPPSRC
# apps/ui_spectrum_painter_text.cpp
# apps/ui_spectrum_painter.cpp
apps/ui_ss_viewer.cpp
apps/ui_sstvtx.cpp
# apps/ui_sstvtx.cpp #moved to ext
apps/ui_standalone_view.cpp
apps/ui_subghzd.cpp
# apps/ui_test.cpp
+48 -1
View File
@@ -49,7 +49,10 @@ void BattinfoView::update_result() {
text_voltage.set("UNKNOWN");
text_current.set("-");
text_charge.set("-");
text_cycles.set("-");
text_ttef.set("-");
text_method.set("-");
text_warn.set("");
return;
}
bool uichg = false;
@@ -73,11 +76,52 @@ void BattinfoView::update_result() {
text_current.set(to_string_dec_int(current) + " mA");
text_charge.set(current >= 0 ? "Charging" : "Discharging");
labels_opt.hidden(false);
text_ttef.hidden(false);
} else {
if (!labels_opt.hidden()) uichg = true;
labels_opt.hidden(true);
text_current.hidden(true);
text_charge.hidden(true);
text_cycles.hidden(true);
text_ttef.hidden(true);
text_warn.set("");
}
if ((valid_mask & battery::BatteryManagement::BATT_VALID_CYCLES) == battery::BatteryManagement::BATT_VALID_CYCLES) {
text_cycles.hidden(false);
uint16_t cycles = battery::BatteryManagement::get_cycles();
if (cycles < 2)
text_warn.set("SoC improves after 2 cycles");
else
text_warn.set("");
text_cycles.set(to_string_dec_uint(cycles));
} else {
text_cycles.hidden(true);
text_warn.set("");
}
if ((valid_mask & battery::BatteryManagement::BATT_VALID_TTEF) == battery::BatteryManagement::BATT_VALID_TTEF) {
text_ttef.hidden(false);
float ttef = 0;
if (current <= 0) {
ttef = battery::BatteryManagement::get_tte();
} else {
ttef = battery::BatteryManagement::get_ttf();
}
// Convert ttef to hours and minutes
uint8_t hours = static_cast<uint8_t>(ttef);
uint8_t minutes = static_cast<uint8_t>((ttef - hours) * 60 + 0.5); // +0.5 for rounding
// Create the formatted string
std::string formatted_time;
if (hours > 0) {
formatted_time += to_string_dec_uint(hours) + "h ";
}
formatted_time += to_string_dec_uint(minutes) + "m";
text_ttef.set(formatted_time);
} else {
text_ttef.hidden(true);
}
if ((valid_mask & battery::BatteryManagement::BATT_VALID_PERCENT) == battery::BatteryManagement::BATT_VALID_PERCENT) {
text_method.set("IC");
@@ -102,7 +146,10 @@ BattinfoView::BattinfoView(NavigationView& nav)
&text_charge,
&text_method,
&button_mode,
&button_exit});
&button_exit,
&text_cycles,
&text_warn,
&text_ttef});
button_exit.on_select = [this, &nav](Button&) {
nav.pop();
+16 -3
View File
@@ -55,12 +55,15 @@ class BattinfoView : public View {
{{2 * 8, 1 * 16}, "Percent:", Theme::getInstance()->fg_light->foreground},
{{2 * 8, 2 * 16}, "Voltage:", Theme::getInstance()->fg_light->foreground},
{{2 * 8, 3 * 16}, "Method:", Theme::getInstance()->fg_light->foreground},
{{2 * 8, 7 * 16}, "Change method:", Theme::getInstance()->fg_light->foreground},
};
Labels labels_opt{
{{2 * 8, 4 * 16}, "Current:", Theme::getInstance()->fg_light->foreground},
{{2 * 8, 5 * 16}, "Charge:", Theme::getInstance()->fg_light->foreground}};
{{2 * 8, 5 * 16}, "Charge:", Theme::getInstance()->fg_light->foreground},
{{2 * 8, 6 * 16}, "TTF/E:", Theme::getInstance()->fg_light->foreground},
{{2 * 8, 7 * 16}, "Cycles:", Theme::getInstance()->fg_light->foreground},
{{2 * 8, 10 * 16}, "Change method:", Theme::getInstance()->fg_light->foreground},
};
Text text_percent{
{13 * 8, 1 * 16, 10 * 16, 16},
@@ -77,9 +80,19 @@ class BattinfoView : public View {
Text text_charge{
{13 * 8, 5 * 16, 10 * 16, 16},
"-"};
Text text_ttef{
{13 * 8, 6 * 16, 10 * 16, 16},
"-"};
Text text_cycles{
{13 * 8, 7 * 16, 10 * 16, 16},
"-"};
Text text_warn{
{2 * 8, 8 * 16, 30 * 8, 2 * 16},
""};
Button button_mode{
{2 * 8, 8 * 16 + 5, 5 * 16, 32},
{2 * 8, 11 * 16 + 5, 5 * 16, 32},
"Volt"};
Button button_exit{
+6
View File
@@ -36,6 +36,7 @@
#include "ui_font_fixed_8x16.hpp"
#include "ui_painter.hpp"
#include "ui_external_items_menu_loader.hpp"
#include "ui_debug_battery.hpp"
#include "portapack.hpp"
#include "portapack_persistent_memory.hpp"
@@ -511,6 +512,11 @@ void DebugMenuView::on_populate() {
{"Reboot", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_setup, [this]() { nav_.push<DebugReboot>(); }},
});
if (battery::BatteryManagement::detectedModule() == battery::BatteryManagement::BatteryModules::BATT_MAX17055) {
add_item(
{"Battery", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_batt_icon, [this]() { nav_.push<BatteryCapacityView>(); }});
}
for (auto const& gridItem : ExternalItemsMenuLoader::load_external_items(app_location_t::DEBUG, nav_)) {
add_item(gridItem);
};
@@ -0,0 +1,104 @@
#include "ui_debug_battery.hpp"
#include "string_format.hpp"
namespace ui {
BatteryCapacityView::RegisterEntry BatteryCapacityView::get_entry(size_t index) {
if (index < battery::max17055::MAX17055::entries_count) {
return battery::max17055::MAX17055::entries[index];
}
return {"", 0, "", 0, false, "", false, 0, false, false, false, 0, false};
}
BatteryCapacityView::BatteryCapacityView(NavigationView& nav) {
for (size_t i = 0; i < ENTRIES_PER_PAGE; ++i) {
name_texts[i].set_parent_rect({0 * 8, static_cast<int>((i + 1) * 16), 8 * 8, 16});
addr_texts[i].set_parent_rect({9 * 8, static_cast<int>((i + 1) * 16), 4 * 8, 16});
hex_texts[i].set_parent_rect({14 * 8, static_cast<int>((i + 1) * 16), 6 * 8, 16});
value_texts[i].set_parent_rect({21 * 8, static_cast<int>((i + 1) * 16), 10 * 8, 16});
add_child(&name_texts[i]);
add_child(&addr_texts[i]);
add_child(&hex_texts[i]);
add_child(&value_texts[i]);
}
add_children({&labels, &page_text, &button_done});
button_done.on_select = [&nav](Button&) { nav.pop(); };
populate_page(0);
update_page_text();
}
void BatteryCapacityView::focus() {
button_done.focus();
}
bool BatteryCapacityView::on_encoder(const EncoderEvent delta) {
int32_t new_page = current_page + delta;
if (new_page >= 0 && new_page < ((int32_t)battery::max17055::MAX17055::entries_count + ENTRIES_PER_PAGE - 1) / ENTRIES_PER_PAGE) {
current_page = new_page;
populate_page(current_page * ENTRIES_PER_PAGE);
update_page_text();
}
return true;
}
void BatteryCapacityView::update_values() {
for (size_t i = 0; i < ENTRIES_PER_PAGE; ++i) {
size_t entry_index = current_page * ENTRIES_PER_PAGE + i;
if (entry_index < battery::max17055::MAX17055::entries_count) {
const auto entry = get_entry(entry_index);
uint16_t raw_value = battery::BatteryManagement::read_register(entry.address);
hex_texts[i].set("0x" + to_string_hex(raw_value, 4));
float scaled_value;
if (entry.is_signed) {
int16_t signed_value = static_cast<int16_t>(raw_value);
scaled_value = signed_value * entry.scalar;
} else {
scaled_value = raw_value * entry.scalar;
}
// Format the value with appropriate decimal places
std::string formatted_value;
if (entry.resolution > 0) {
formatted_value = to_string_decimal(scaled_value, std::min(entry.resolution, 3));
} else {
formatted_value = to_string_dec_int(scaled_value); // Show up to 3 decimal places
}
value_texts[i].set(formatted_value + " " + entry.unit);
}
}
}
void BatteryCapacityView::populate_page(int start_index) {
for (size_t i = 0; i < ENTRIES_PER_PAGE; ++i) {
size_t entry_index = start_index + i;
if (entry_index < battery::max17055::MAX17055::entries_count) {
const auto entry = get_entry(entry_index);
name_texts[i].set(entry.name);
addr_texts[i].set("0x" + to_string_hex(entry.address, 2));
name_texts[i].hidden(false);
addr_texts[i].hidden(false);
hex_texts[i].hidden(false);
value_texts[i].hidden(false);
} else {
name_texts[i].hidden(true);
addr_texts[i].hidden(true);
hex_texts[i].hidden(true);
value_texts[i].hidden(true);
}
}
update_values();
}
void BatteryCapacityView::update_page_text() {
int total_pages = (battery::max17055::MAX17055::entries_count + ENTRIES_PER_PAGE - 1) / ENTRIES_PER_PAGE;
page_text.set("Page " + to_string_dec_uint(current_page + 1) + "/" + to_string_dec_uint(total_pages));
}
} // namespace ui
@@ -0,0 +1,48 @@
#ifndef __UI_DEBUG_BATTERY_HPP__
#define __UI_DEBUG_BATTERY_HPP__
#include "ui.hpp"
#include "ui_widget.hpp"
#include "ui_navigation.hpp"
#include "battery.hpp"
#include "max17055.hpp"
namespace ui {
class BatteryCapacityView : public View {
public:
BatteryCapacityView(NavigationView& nav);
void focus() override;
std::string title() const override { return "Battery Registers"; }
bool on_encoder(const EncoderEvent delta) override;
using RegisterEntry = battery::max17055::RegisterEntry;
private:
static RegisterEntry get_entry(size_t index);
Labels labels{
{{0 * 8, 0 * 16}, "Reg", Theme::getInstance()->fg_yellow->foreground},
{{9 * 8, 0 * 16}, "Addr", Theme::getInstance()->fg_yellow->foreground},
{{14 * 8, 0 * 16}, "Hex", Theme::getInstance()->fg_yellow->foreground},
{{21 * 8, 0 * 16}, "Value", Theme::getInstance()->fg_yellow->foreground},
};
std::array<Text, 16> name_texts = {};
std::array<Text, 16> addr_texts = {};
std::array<Text, 16> hex_texts = {};
std::array<Text, 16> value_texts = {};
Text page_text{{144, 284, 80, 16}, "Page 1/1"};
Button button_done{{16, 280, 96, 24}, "Done"};
void update_values();
void populate_page(int start_index);
void update_page_text();
int current_page = 0;
static constexpr int ENTRIES_PER_PAGE = 16;
};
} // namespace ui
#endif // __UI_DEBUG_BATTERY_HPP__
+10 -1
View File
@@ -969,6 +969,8 @@ SetBatteryView::SetBatteryView(NavigationView& nav) {
&button_cancel,
&checkbox_overridebatt});
if (battery::BatteryManagement::detectedModule() == battery::BatteryManagement::BATT_MAX17055) add_children({&button_reset, &labels2});
button_save.on_select = [&nav, this](Button&) {
pmem::set_ui_override_batt_calc(checkbox_overridebatt.value());
battery::BatteryManagement::set_calc_override(checkbox_overridebatt.value());
@@ -976,6 +978,13 @@ SetBatteryView::SetBatteryView(NavigationView& nav) {
nav.pop();
};
button_reset.on_select = [&nav, this](Button&) {
if (battery::BatteryManagement::reset_learned())
nav.display_modal("Reset", "Battery parameters reset");
else
nav.display_modal("Error", "Error parameter reset");
};
checkbox_overridebatt.set_value(pmem::ui_override_batt_calc());
button_cancel.on_select = [&nav, this](Button&) {
@@ -1017,7 +1026,7 @@ void SettingsMenuView::on_populate() {
{"Theme", ui::Color::dark_cyan(), &bitmap_icon_setup, [this]() { nav_.push<SetThemeView>(); }},
{"Autostart", ui::Color::dark_cyan(), &bitmap_icon_setup, [this]() { nav_.push<SetAutostartView>(); }},
});
if (battery::BatteryManagement::isDetected()) add_item({"Battery", ui::Color::dark_cyan(), &bitmap_icon_setup, [this]() { nav_.push<SetBatteryView>(); }});
if (battery::BatteryManagement::isDetected()) add_item({"Battery", ui::Color::dark_cyan(), &bitmap_icon_batt_icon, [this]() { nav_.push<SetBatteryView>(); }});
}
} /* namespace ui */
+8 -2
View File
@@ -906,13 +906,14 @@ class SetBatteryView : public View {
Labels labels{
{{1 * 8, 1 * 16}, "Override batt calculation", Theme::getInstance()->fg_light->foreground},
{{1 * 8, 2 * 16}, "method to voltage based", Theme::getInstance()->fg_light->foreground}};
Labels labels2{
{{1 * 8, 6 * 16}, "Reset IC's learned params.", Theme::getInstance()->fg_light->foreground}};
Button button_save{
{2 * 8, 16 * 16, 12 * 8, 32},
"Save"};
Checkbox checkbox_overridebatt{
{2 * 8, 6 * 16},
{2 * 8, 4 * 16},
23,
"Override"};
@@ -920,6 +921,11 @@ class SetBatteryView : public View {
{16 * 8, 16 * 16, 12 * 8, 32},
"Cancel",
};
Button button_reset{
{2 * 8, 8 * 16, 12 * 8, 32},
"Reset",
};
};
class SettingsMenuView : public BtnGridView {
+319 -313
View File
@@ -1,321 +1,327 @@
// converted by bmp_to_hex_cpp_arr.py at the firmware/tools dir
// fake transparent px should be the exact color rgb dec(41,24,22), then use true for the last arg when drawing bmp with the draw func
const unsigned char splash_bmp[] = {
0x42, 0x4d, 0xf4, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x00,
0x42, 0x4d, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x00,
0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xe6, 0x00, 0x00, 0x00, 0x32, 0x00,
0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x82, 0x0e,
0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x9c, 0x0e,
0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x0f, 0x00,
0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x19, 0xf6, 0x00, 0x00, 0x14,
0xc9, 0x00, 0x00, 0x0c, 0x78, 0x00, 0x16, 0x18, 0x29, 0x00, 0xfd, 0xfd,
0xfd, 0x00, 0xf0, 0xf0, 0xf0, 0x00, 0xe7, 0xe7, 0xe7, 0x00, 0xda, 0xda,
0xda, 0x00, 0xcd, 0xcd, 0xcd, 0x00, 0xc7, 0xc7, 0xc7, 0x00, 0xba, 0xba,
0xba, 0x00, 0xad, 0xad, 0xad, 0x00, 0x96, 0x96, 0x96, 0x00, 0x5c, 0x5c,
0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xee, 0x00, 0x00, 0xe6, 0xee,
0x00, 0x00, 0xe6, 0xee, 0x00, 0x00, 0xe6, 0xee, 0x00, 0x00, 0x00, 0x18,
0xee, 0x44, 0x44, 0x47, 0x3e, 0xee, 0xee, 0xee, 0xe3, 0xd5, 0x44, 0x7d,
0x08, 0xee, 0x00, 0x14, 0xe3, 0x44, 0x44, 0x48, 0x3e, 0xea, 0x44, 0x44,
0x44, 0xde, 0x12, 0xee, 0x00, 0x08, 0xa4, 0x44, 0x45, 0x9d, 0x08, 0xee,
0x00, 0x08, 0xc4, 0x44, 0x45, 0xce, 0x10, 0xee, 0x00, 0x08, 0x34, 0x44,
0x44, 0x6d, 0x16, 0xee, 0x00, 0x12, 0x34, 0x44, 0x44, 0x6d, 0xee, 0xee,
0xee, 0xe3, 0xd5, 0x00, 0x1a, 0x44, 0x00, 0x1c, 0x45, 0xce, 0xee, 0x44,
0x44, 0x47, 0x3e, 0xee, 0xee, 0xee, 0xe3, 0xd5, 0x44, 0x7d, 0x08, 0xee,
0x00, 0x0a, 0xe3, 0x44, 0x44, 0x48, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x34,
0xee, 0x49, 0x99, 0x95, 0xde, 0xee, 0xee, 0xee, 0xd4, 0x46, 0x89, 0x98,
0xb3, 0xee, 0xee, 0xee, 0xe3, 0x49, 0x99, 0x94, 0x3e, 0xed, 0x79, 0x99,
0x99, 0x73, 0x10, 0xee, 0x00, 0x0a, 0xed, 0x47, 0x99, 0x95, 0xae, 0x00,
0x08, 0xee, 0x00, 0x08, 0xc7, 0x99, 0x97, 0xae, 0x10, 0xee, 0x00, 0x08,
0x34, 0x99, 0x99, 0x7c, 0x16, 0xee, 0x00, 0x14, 0x34, 0x99, 0x99, 0x7c,
0xee, 0xee, 0xee, 0xb4, 0x56, 0x89, 0x18, 0x99, 0x00, 0x2e, 0x97, 0xae,
0xee, 0x49, 0x99, 0x95, 0xde, 0xee, 0xee, 0xee, 0xd4, 0x46, 0x89, 0x98,
0xb3, 0xee, 0xee, 0xee, 0xe3, 0x49, 0x99, 0x94, 0x3e, 0x00, 0x00, 0x00,
0x00, 0x34, 0xee, 0x49, 0x99, 0x95, 0xde, 0xee, 0xee, 0xe3, 0x55, 0x99,
0x99, 0x99, 0x9b, 0xee, 0xee, 0xee, 0xe3, 0x49, 0x99, 0x94, 0x3e, 0xee,
0xb9, 0x99, 0x99, 0x8d, 0x10, 0xee, 0x00, 0x0a, 0xe7, 0x69, 0x99, 0x74,
0xde, 0x00, 0x08, 0xee, 0x00, 0x08, 0xc7, 0x99, 0x97, 0xae, 0x10, 0xee,
0x00, 0x08, 0x34, 0x99, 0x99, 0x7c, 0x16, 0xee, 0x00, 0x10, 0x34, 0x99,
0x99, 0x7c, 0xee, 0xee, 0xea, 0x47, 0x1c, 0x99, 0x00, 0x2e, 0x97, 0xae,
0xee, 0x49, 0x99, 0x95, 0xde, 0xee, 0xee, 0xe3, 0x55, 0x99, 0x99, 0x99,
0x9b, 0xee, 0xee, 0xee, 0xe3, 0x49, 0x99, 0x94, 0x3e, 0x00, 0x00, 0x00,
0x00, 0x36, 0xee, 0x49, 0x99, 0x95, 0xde, 0xee, 0xee, 0xea, 0x48, 0x99,
0x99, 0x99, 0x98, 0xde, 0xee, 0xee, 0xe3, 0x49, 0x99, 0x94, 0x3e, 0xee,
0xd7, 0x99, 0x99, 0x98, 0x3e, 0x00, 0x0e, 0xee, 0x00, 0x08, 0xd4, 0x89,
0x99, 0x5a, 0x0a, 0xee, 0x00, 0x08, 0xc7, 0x99, 0x97, 0xae, 0x10, 0xee,
0x00, 0x08, 0x34, 0x99, 0x99, 0x7c, 0x16, 0xee, 0x00, 0x10, 0x34, 0x99,
0x99, 0x7c, 0xee, 0xee, 0xb4, 0x79, 0x1c, 0x99, 0x00, 0x2e, 0x97, 0xae,
0xee, 0x49, 0x99, 0x95, 0xde, 0xee, 0xee, 0xea, 0x48, 0x99, 0x99, 0x99,
0x98, 0xde, 0xee, 0xee, 0xe3, 0x49, 0x99, 0x94, 0x3e, 0x00, 0x00, 0x00,
0x00, 0x12, 0xee, 0x49, 0x99, 0x95, 0xde, 0xee, 0xee, 0xd4, 0x79, 0x00,
0x08, 0x99, 0x00, 0x1c, 0x73, 0xee, 0xee, 0xe3, 0x49, 0x99, 0x94, 0x3e,
0xee, 0xeb, 0x99, 0x99, 0x99, 0xce, 0x0c, 0xee, 0x00, 0x0a, 0xe3, 0x56,
0x99, 0x97, 0x4d, 0x00, 0x0a, 0xee, 0x00, 0x08, 0xc7, 0x99, 0x97, 0xae,
0x10, 0xee, 0x00, 0x08, 0x34, 0x99, 0x99, 0x7c, 0x16, 0xee, 0x00, 0x0e,
0x34, 0x99, 0x99, 0x7c, 0xee, 0xed, 0x47, 0x00, 0x1e, 0x99, 0x00, 0x16,
0x97, 0xae, 0xee, 0x49, 0x99, 0x95, 0xde, 0xee, 0xee, 0xd4, 0x79, 0x00,
0x08, 0x99, 0x00, 0x10, 0x73, 0xee, 0xee, 0xe3, 0x49, 0x99, 0x94, 0x3e,
0x00, 0x00, 0x00, 0x10, 0xee, 0x49, 0x99, 0x95, 0xde, 0xee, 0xee, 0xa5,
0x0a, 0x99, 0x00, 0x1c, 0x8d, 0xee, 0xee, 0xe3, 0x49, 0x99, 0x94, 0x3e,
0xee, 0xed, 0x79, 0x99, 0x99, 0x73, 0x0c, 0xee, 0x00, 0x0a, 0xec, 0x48,
0x99, 0x95, 0xae, 0x00, 0x0a, 0xee, 0x00, 0x08, 0xc7, 0x99, 0x97, 0xae,
0x10, 0xee, 0x00, 0x08, 0x34, 0x99, 0x99, 0x7c, 0x16, 0xee, 0x00, 0x0e,
0x34, 0x99, 0x99, 0x7c, 0xee, 0xe7, 0x69, 0x00, 0x1e, 0x99, 0x00, 0x14,
0x97, 0xae, 0xee, 0x49, 0x99, 0x95, 0xde, 0xee, 0xee, 0xa5, 0x0a, 0x99,
0x00, 0x10, 0x8d, 0xee, 0xee, 0xe3, 0x49, 0x99, 0x94, 0x3e, 0x00, 0x00,
0x00, 0x36, 0xee, 0x49, 0x99, 0x95, 0xde, 0xee, 0xed, 0x47, 0x99, 0x97,
0x89, 0x99, 0x99, 0x97, 0x3e, 0xee, 0xe3, 0x49, 0x99, 0x94, 0x3e, 0xee,
0xee, 0xb9, 0x99, 0x99, 0x9d, 0x00, 0x0c, 0xee, 0x00, 0x0a, 0x34, 0x69,
0x99, 0x74, 0xde, 0x00, 0x0a, 0xee, 0x00, 0x08, 0xc7, 0x99, 0x98, 0xae,
0x10, 0xee, 0x00, 0x08, 0x34, 0x99, 0x99, 0x7c, 0x16, 0xee, 0x00, 0x12,
0x34, 0x99, 0x99, 0x7c, 0xee, 0x34, 0x89, 0x99, 0x64, 0x00, 0x1c, 0x44,
0x00, 0x2c, 0xae, 0xee, 0x49, 0x99, 0x95, 0xde, 0xee, 0xed, 0x47, 0x99,
0x97, 0x89, 0x99, 0x99, 0x97, 0x3e, 0xee, 0xe3, 0x49, 0x99, 0x94, 0x3e,
0x00, 0x00, 0x00, 0x38, 0xee, 0x49, 0x99, 0x95, 0xde, 0xee, 0xec, 0x59,
0x99, 0x95, 0xbc, 0x99, 0x99, 0x98, 0xde, 0xee, 0xe3, 0x49, 0x99, 0x94,
0x3e, 0xee, 0xee, 0xd7, 0x99, 0x99, 0x99, 0x74, 0x0c, 0x44, 0x00, 0x06,
0x99, 0x99, 0x4b, 0x00, 0x0c, 0xee, 0x00, 0x08, 0xb7, 0x99, 0x99, 0xae,
0x10, 0xee, 0x00, 0x08, 0x34, 0x99, 0x99, 0x7c, 0x16, 0xee, 0x00, 0x12,
0x34, 0x99, 0x99, 0x7c, 0xee, 0xd5, 0x99, 0x99, 0x6d, 0x00, 0x20, 0xee,
0x00, 0x28, 0x49, 0x99, 0x95, 0xde, 0xee, 0xec, 0x59, 0x99, 0x95, 0xbc,
0x99, 0x99, 0x98, 0xde, 0xee, 0xe3, 0x49, 0x99, 0x94, 0x3e, 0x00, 0x00,
0x00, 0x30, 0xee, 0x49, 0x99, 0x95, 0xde, 0xee, 0x34, 0x79, 0x99, 0x84,
0xdd, 0x89, 0x99, 0x99, 0x8e, 0xee, 0xe3, 0x49, 0x99, 0x94, 0x3e, 0xee,
0xee, 0xeb, 0x16, 0x99, 0x02, 0x97, 0x02, 0x43, 0x0a, 0xee, 0x00, 0x0a,
0xed, 0x47, 0x99, 0x99, 0x9d, 0x00, 0x10, 0xee, 0x00, 0x08, 0x34, 0x99,
0x99, 0x9d, 0x16, 0xee, 0x00, 0x12, 0x34, 0x99, 0x99, 0x7c, 0xee, 0xd6,
0x99, 0x99, 0x6d, 0x00, 0x20, 0xee, 0x00, 0x28, 0x49, 0x99, 0x95, 0xde,
0xee, 0x34, 0x79, 0x99, 0x84, 0xdd, 0x89, 0x99, 0x99, 0x8e, 0xee, 0xe3,
0x49, 0x99, 0x94, 0x3e, 0x00, 0x00, 0x00, 0x32, 0xee, 0x49, 0x99, 0x95,
0xde, 0xee, 0xc4, 0x99, 0x99, 0x67, 0xee, 0x79, 0x99, 0x99, 0x8d, 0xee,
0xe3, 0x49, 0x99, 0x94, 0x3e, 0xee, 0xee, 0xed, 0x79, 0x00, 0x14, 0x99,
0x02, 0x94, 0x02, 0xce, 0x0a, 0xee, 0x00, 0x0c, 0x35, 0x59, 0x99, 0x99,
0x98, 0x3e, 0x0e, 0xee, 0x00, 0x0a, 0x34, 0x99, 0x99, 0x99, 0x74, 0x00,
0x16, 0x44, 0x00, 0x10, 0x99, 0x99, 0x7c, 0xee, 0xd6, 0x99, 0x99, 0x9d,
0x20, 0xee, 0x00, 0x28, 0x49, 0x99, 0x95, 0xde, 0xee, 0xc4, 0x99, 0x99,
0x67, 0xee, 0x79, 0x99, 0x99, 0x8d, 0xee, 0xe3, 0x49, 0x99, 0x94, 0x3e,
0x00, 0x00, 0x00, 0x32, 0xee, 0x49, 0x99, 0x95, 0xde, 0xe3, 0x57, 0x99,
0x99, 0x4d, 0xee, 0xd8, 0x99, 0x99, 0x98, 0xee, 0xe3, 0x49, 0x99, 0x94,
0x3e, 0xee, 0xee, 0xee, 0xc9, 0x00, 0x14, 0x99, 0x02, 0x74, 0x02, 0x3e,
0x08, 0xee, 0x00, 0x0e, 0xe3, 0x84, 0x89, 0x99, 0x99, 0x99, 0xa3, 0x00,
0x0e, 0xee, 0x02, 0x34, 0x22, 0x99, 0x00, 0x0e, 0x7c, 0xee, 0xd6, 0x99,
0x99, 0x99, 0x64, 0x00, 0x18, 0x44, 0x00, 0x2e, 0x45, 0xce, 0xee, 0x49,
0x99, 0x95, 0xde, 0xe3, 0x57, 0x99, 0x99, 0x4d, 0xee, 0xd8, 0x99, 0x99,
0x98, 0xee, 0xe3, 0x49, 0x99, 0x94, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x32,
0xee, 0x49, 0x99, 0x95, 0xde, 0xed, 0x48, 0x99, 0x97, 0x43, 0xee, 0x37,
0x99, 0x99, 0x97, 0xde, 0xe3, 0x49, 0x99, 0x94, 0x3e, 0xee, 0xee, 0xee,
0x37, 0x00, 0x14, 0x99, 0x02, 0x4c, 0x0a, 0xee, 0x02, 0xeb, 0x02, 0x48,
0x08, 0x99, 0x02, 0x9b, 0x0e, 0xee, 0x02, 0x34, 0x22, 0x99, 0x00, 0x06,
0x7c, 0xee, 0xd6, 0x00, 0x20, 0x99, 0x00, 0x2e, 0x97, 0xae, 0xee, 0x49,
0x99, 0x95, 0xde, 0xed, 0x48, 0x99, 0x97, 0x43, 0xee, 0x37, 0x99, 0x99,
0x97, 0xde, 0xe3, 0x49, 0x99, 0x94, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x32,
0xee, 0x49, 0x99, 0x95, 0xde, 0x35, 0x69, 0x99, 0x95, 0xce, 0xee, 0xec,
0x89, 0x99, 0x99, 0xbe, 0xe3, 0x49, 0x99, 0x94, 0x3e, 0xee, 0xee, 0xee,
0xec, 0x00, 0x12, 0x99, 0x02, 0x97, 0x02, 0x43, 0x0a, 0xee, 0x02, 0xd4,
0x02, 0x79, 0x0a, 0x99, 0x02, 0xde, 0x0c, 0xee, 0x02, 0x34, 0x22, 0x99,
0x00, 0x06, 0x7c, 0xee, 0xd6, 0x00, 0x20, 0x99, 0x00, 0x2e, 0x97, 0xae,
0xee, 0x49, 0x99, 0x95, 0xde, 0x35, 0x69, 0x99, 0x95, 0xce, 0xee, 0xec,
0x89, 0x99, 0x99, 0xbe, 0xe3, 0x49, 0x99, 0x94, 0x3e, 0x00, 0x00, 0x00,
0x00, 0x48, 0xee, 0x49, 0x99, 0x95, 0xde, 0xd4, 0x89, 0x99, 0x74, 0x3e,
0xee, 0xe3, 0x79, 0x99, 0x99, 0x7d, 0xe3, 0x49, 0x99, 0x94, 0x3e, 0xee,
0xee, 0xee, 0xe3, 0x79, 0x99, 0x99, 0x64, 0x44, 0x44, 0x89, 0x99, 0x99,
0x94, 0xce, 0x08, 0xee, 0x00, 0x12, 0xed, 0x46, 0x99, 0x98, 0x59, 0x99,
0x99, 0x99, 0x8d, 0x00, 0x0c, 0xee, 0x02, 0x34, 0x22, 0x99, 0x00, 0x06,
0x7c, 0xee, 0xd6, 0x00, 0x20, 0x99, 0x00, 0x2e, 0x97, 0xae, 0xee, 0x49,
0x99, 0x95, 0xde, 0xd4, 0x89, 0x99, 0x74, 0x3e, 0xee, 0xe3, 0x79, 0x99,
0x99, 0x7d, 0xe3, 0x49, 0x99, 0x94, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x2a,
0xee, 0x49, 0x99, 0x95, 0xde, 0x76, 0x99, 0x99, 0x6a, 0xee, 0xee, 0xee,
0xa9, 0x99, 0x99, 0x9b, 0xe3, 0x49, 0x99, 0x94, 0x3e, 0x00, 0x08, 0xee,
0x00, 0x16, 0xc9, 0x99, 0x99, 0x9c, 0xee, 0xee, 0x3b, 0x99, 0x99, 0x74,
0x3e, 0x00, 0x08, 0xee, 0x00, 0x14, 0x35, 0x59, 0x99, 0x95, 0x7d, 0x99,
0x99, 0x99, 0x9a, 0x3e, 0x0a, 0xee, 0x02, 0x34, 0x22, 0x99, 0x00, 0x06,
0x7c, 0xee, 0xd6, 0x00, 0x20, 0x99, 0x00, 0x2e, 0x97, 0xae, 0xee, 0x49,
0x99, 0x95, 0xde, 0x76, 0x99, 0x99, 0x6a, 0xee, 0xee, 0xee, 0xa9, 0x99,
0x99, 0x9b, 0xe3, 0x49, 0x99, 0x94, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x2a,
0xee, 0x49, 0x99, 0x95, 0x3d, 0x48, 0x99, 0x98, 0x4d, 0xee, 0xee, 0xee,
0xd7, 0x99, 0x99, 0x97, 0xd3, 0x49, 0x99, 0x94, 0x3e, 0x00, 0x08, 0xee,
0x00, 0x14, 0x37, 0x99, 0x99, 0x97, 0x3e, 0xee, 0xc4, 0x89, 0x99, 0x4c,
0x08, 0xee, 0x00, 0x16, 0xe3, 0x84, 0x89, 0x99, 0x64, 0x3e, 0xd9, 0x99,
0x99, 0x99, 0xa3, 0x00, 0x0a, 0xee, 0x00, 0x08, 0x34, 0x99, 0x99, 0x64,
0x16, 0x44, 0x00, 0x0c, 0x99, 0x99, 0x99, 0x7c, 0xee, 0xd6, 0x20, 0x99,
0x00, 0x2e, 0x97, 0xae, 0xee, 0x49, 0x99, 0x95, 0x3d, 0x48, 0x99, 0x98,
0x4d, 0xee, 0xee, 0xee, 0xd7, 0x99, 0x99, 0x97, 0xd3, 0x49, 0x99, 0x94,
0x3e, 0x00, 0x00, 0x00, 0x00, 0x2a, 0xee, 0x49, 0x99, 0x96, 0x3b, 0x69,
0x99, 0x96, 0x5e, 0xee, 0xee, 0xee, 0xe8, 0x99, 0x99, 0x99, 0xc3, 0x49,
0x99, 0x94, 0x3e, 0x00, 0x08, 0xee, 0x00, 0x14, 0xec, 0x99, 0x99, 0x99,
0xbe, 0xe3, 0x46, 0x99, 0x96, 0x43, 0x08, 0xee, 0x00, 0x16, 0xeb, 0x48,
0x99, 0x97, 0x4d, 0xee, 0xed, 0x99, 0x99, 0x99, 0x9c, 0x00, 0x0a, 0xee,
0x00, 0x08, 0x34, 0x99, 0x99, 0x6d, 0x16, 0xee, 0x00, 0x12, 0x39, 0x99,
0x99, 0x7c, 0xee, 0xd6, 0x99, 0x99, 0x54, 0x00, 0x1c, 0x44, 0x00, 0x2c,
0xae, 0xee, 0x49, 0x99, 0x96, 0x3b, 0x69, 0x99, 0x96, 0x5e, 0xee, 0xee,
0xee, 0xe8, 0x99, 0x99, 0x99, 0xc3, 0x49, 0x99, 0x94, 0x3e, 0x00, 0x00,
0x00, 0x2a, 0xee, 0x49, 0x99, 0x98, 0xd5, 0x79, 0x99, 0x94, 0xde, 0xee,
0xee, 0xee, 0xed, 0x89, 0x99, 0x99, 0x73, 0x49, 0x99, 0x94, 0x3e, 0x00,
0x08, 0xee, 0x00, 0x14, 0xe3, 0x79, 0x99, 0x99, 0x8d, 0xea, 0x59, 0x99,
0x84, 0xde, 0x08, 0xee, 0x00, 0x18, 0xd4, 0x79, 0x99, 0x84, 0xbe, 0xee,
0xee, 0xb9, 0x99, 0x99, 0x99, 0xde, 0x08, 0xee, 0x00, 0x08, 0x34, 0x99,
0x99, 0x6d, 0x16, 0xee, 0x00, 0x12, 0x34, 0x99, 0x99, 0x7c, 0xee, 0xd6,
0x99, 0x99, 0x5d, 0x00, 0x20, 0xee, 0x00, 0x28, 0x49, 0x99, 0x98, 0xd5,
0x79, 0x99, 0x94, 0xde, 0xee, 0xee, 0xee, 0xed, 0x89, 0x99, 0x99, 0x73,
0x49, 0x99, 0x94, 0x3e, 0x00, 0x00, 0x00, 0x2a, 0xee, 0x49, 0x99, 0x99,
0xa6, 0x99, 0x99, 0x74, 0x3e, 0xee, 0xee, 0xee, 0xe3, 0x79, 0x99, 0x99,
0x9c, 0x59, 0x99, 0x94, 0x3e, 0x00, 0x0a, 0xee, 0x00, 0x32, 0xc9, 0x99,
0x99, 0x9a, 0xd4, 0x79, 0x99, 0x65, 0x3e, 0xee, 0xee, 0xee, 0xed, 0x46,
0x99, 0x98, 0x48, 0x3e, 0xee, 0xee, 0x3a, 0x99, 0x99, 0x99, 0x83, 0x00,
0x08, 0xee, 0x00, 0x08, 0x34, 0x99, 0x99, 0x6d, 0x16, 0xee, 0x00, 0x12,
0x34, 0x99, 0x99, 0x7c, 0xee, 0xd6, 0x99, 0x99, 0x93, 0x00, 0x20, 0xee,
0x00, 0x28, 0x49, 0x99, 0x99, 0xa6, 0x99, 0x99, 0x74, 0x3e, 0xee, 0xee,
0xee, 0xe3, 0x79, 0x99, 0x99, 0x9c, 0x59, 0x99, 0x94, 0x3e, 0x00, 0x00,
0x00, 0x10, 0xee, 0x49, 0x99, 0x99, 0x98, 0x99, 0x99, 0x5c, 0x0a, 0xee,
0x00, 0x10, 0xd8, 0x99, 0x99, 0x99, 0x79, 0x99, 0x84, 0x3e, 0x0a, 0xee,
0x00, 0x10, 0x37, 0x99, 0x99, 0x99, 0x86, 0x99, 0x98, 0x4d, 0x08, 0xee,
0x00, 0x2a, 0x35, 0x59, 0x99, 0x95, 0x53, 0xee, 0xee, 0xee, 0xe3, 0x89,
0x99, 0x99, 0x9a, 0x3e, 0xee, 0xee, 0xee, 0x34, 0x99, 0x99, 0x6d, 0x00,
0x16, 0xee, 0x00, 0x14, 0x34, 0x99, 0x99, 0x7c, 0xee, 0x36, 0x99, 0x99,
0x99, 0x54, 0x18, 0x44, 0x00, 0x14, 0x45, 0xce, 0xee, 0x49, 0x99, 0x99,
0x98, 0x99, 0x99, 0x5c, 0x0a, 0xee, 0x00, 0x10, 0xd8, 0x99, 0x99, 0x99,
0x79, 0x99, 0x84, 0x3e, 0x00, 0x00, 0x02, 0xee, 0x02, 0x59, 0x08, 0x99,
0x02, 0x97, 0x02, 0x4d, 0x0a, 0xee, 0x02, 0x36, 0x0a, 0x99, 0x02, 0x75,
0x0c, 0xee, 0x02, 0xec, 0x0a, 0x99, 0x00, 0x16, 0x96, 0x53, 0xee, 0xee,
0xee, 0xe3, 0x84, 0x89, 0x99, 0x64, 0xde, 0x00, 0x08, 0xee, 0x00, 0x18,
0xd9, 0x99, 0x99, 0x99, 0xbe, 0xee, 0xee, 0xee, 0x34, 0x99, 0x99, 0x6d,
0x16, 0xee, 0x00, 0x0c, 0x34, 0x99, 0x99, 0x7c, 0xee, 0xe6, 0x20, 0x99,
0x00, 0x08, 0x97, 0xae, 0xee, 0x59, 0x08, 0x99, 0x02, 0x97, 0x02, 0x4d,
0x0a, 0xee, 0x02, 0x36, 0x0a, 0x99, 0x02, 0x75, 0x02, 0xee, 0x00, 0x00,
0x02, 0xee, 0x02, 0xa8, 0x08, 0x99, 0x02, 0x95, 0x02, 0xae, 0x0a, 0xee,
0x02, 0xec, 0x0a, 0x99, 0x02, 0x5b, 0x0c, 0xee, 0x02, 0xe3, 0x02, 0x89,
0x08, 0x99, 0x00, 0x14, 0x84, 0xde, 0xee, 0xee, 0xee, 0xeb, 0x48, 0x99,
0x97, 0x4c, 0x0a, 0xee, 0x00, 0x18, 0xed, 0x99, 0x99, 0x99, 0x9d, 0xee,
0xee, 0xee, 0x34, 0x99, 0x99, 0x6d, 0x16, 0xee, 0x00, 0x0e, 0x34, 0x99,
0x99, 0x7c, 0xee, 0xed, 0x89, 0x00, 0x1e, 0x99, 0x00, 0x08, 0x97, 0xae,
0xee, 0xa8, 0x08, 0x99, 0x02, 0x95, 0x02, 0xae, 0x0a, 0xee, 0x02, 0xec,
0x0a, 0x99, 0x02, 0x5b, 0x02, 0xee, 0x00, 0x00, 0x02, 0xee, 0x02, 0xd7,
0x08, 0x99, 0x02, 0x64, 0x02, 0x3e, 0x0a, 0xee, 0x00, 0x0e, 0xe3, 0x79,
0x99, 0x99, 0x99, 0x96, 0x4d, 0x00, 0x0e, 0xee, 0x00, 0x0c, 0xd8, 0x99,
0x99, 0x99, 0x98, 0x48, 0x08, 0xee, 0x00, 0x0a, 0xd4, 0x79, 0x99, 0x84,
0xbe, 0x00, 0x0c, 0xee, 0x00, 0x16, 0xb9, 0x99, 0x99, 0x98, 0xde, 0xee,
0xee, 0x34, 0x99, 0x99, 0x6d, 0x00, 0x16, 0xee, 0x00, 0x0c, 0x34, 0x99,
0x99, 0x7c, 0xee, 0xe3, 0x20, 0x99, 0x00, 0x08, 0x97, 0xae, 0xee, 0xd7,
0x08, 0x99, 0x02, 0x64, 0x02, 0x3e, 0x0a, 0xee, 0x00, 0x10, 0xe3, 0x79,
0x99, 0x99, 0x99, 0x96, 0x4d, 0xee, 0x00, 0x00, 0x00, 0x0e, 0xee, 0xec,
0x99, 0x99, 0x99, 0x96, 0x4d, 0x00, 0x0e, 0xee, 0x00, 0x0c, 0xd9, 0x99,
0x99, 0x99, 0x74, 0xce, 0x0e, 0xee, 0x00, 0x1e, 0xed, 0x99, 0x99, 0x99,
0x85, 0x53, 0xee, 0xee, 0xee, 0xed, 0x46, 0x99, 0x99, 0x57, 0x3e, 0x00,
0x0c, 0xee, 0x00, 0x16, 0x39, 0x99, 0x99, 0x99, 0xa3, 0xee, 0xee, 0x34,
0x99, 0x99, 0x6d, 0x00, 0x16, 0xee, 0x00, 0x0e, 0x34, 0x99, 0x99, 0x7c,
0xee, 0xee, 0x3a, 0x00, 0x1e, 0x99, 0x00, 0x12, 0x97, 0xae, 0xee, 0xec,
0x99, 0x99, 0x99, 0x96, 0x4d, 0x00, 0x0e, 0xee, 0x00, 0x0e, 0xd9, 0x99,
0x99, 0x99, 0x74, 0xce, 0xee, 0x00, 0x00, 0x00, 0x00, 0x0e, 0xee, 0xe3,
0xc8, 0x99, 0x96, 0x44, 0xde, 0x00, 0x0e, 0xee, 0x00, 0x0a, 0xed, 0x79,
0x99, 0x76, 0x4b, 0x00, 0x12, 0xee, 0x00, 0x1a, 0xc7, 0x99, 0x96, 0x45,
0xde, 0xee, 0xee, 0xee, 0x35, 0x59, 0x99, 0x96, 0x43, 0x00, 0x0e, 0xee,
0x00, 0x16, 0xe3, 0x89, 0x99, 0x99, 0x9a, 0x3e, 0xee, 0x34, 0x99, 0x99,
0x6d, 0x00, 0x16, 0xee, 0x00, 0x10, 0x34, 0x99, 0x99, 0x7c, 0xee, 0xee,
0xe3, 0xa6, 0x1c, 0x99, 0x00, 0x12, 0x97, 0xae, 0xee, 0xe3, 0xc8, 0x99,
0x96, 0x44, 0xde, 0x00, 0x0e, 0xee, 0x00, 0x0e, 0xed, 0x79, 0x99, 0x76,
0x4b, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xee, 0xee, 0xed, 0x84,
0x44, 0xc3, 0x12, 0xee, 0x00, 0x08, 0xdc, 0x44, 0x4a, 0xde, 0x12, 0xee,
0x00, 0x1a, 0xed, 0xa4, 0x44, 0xd3, 0xee, 0xee, 0xee, 0xe3, 0xc8, 0x44,
0x44, 0x44, 0xde, 0x00, 0x10, 0xee, 0x00, 0x14, 0xd4, 0x44, 0x44, 0x44,
0xae, 0xee, 0x38, 0x44, 0x44, 0x4d, 0x16, 0xee, 0x00, 0x12, 0x38, 0x44,
0x44, 0x4c, 0xee, 0xee, 0xee, 0xed, 0xc4, 0x00, 0x1c, 0x44, 0x00, 0x0e,
0xae, 0xee, 0xee, 0xed, 0x84, 0x44, 0xc3, 0x00, 0x12, 0xee, 0x00, 0x0c,
0xdc, 0x44, 0x4a, 0xde, 0xee, 0xee, 0x00, 0x00, 0xe6, 0xee, 0x00, 0x00,
0xe6, 0xee, 0x00, 0x00, 0xe6, 0xee, 0x00, 0x00, 0xe6, 0xee, 0x00, 0x00,
0xe6, 0xee, 0x00, 0x00, 0x00, 0x1e, 0xee, 0x20, 0x00, 0x2e, 0xe0, 0x00,
0x13, 0xe1, 0x00, 0x02, 0xe3, 0x00, 0x01, 0xee, 0xe2, 0x00, 0x08, 0x00,
0x00, 0x26, 0x1e, 0xe1, 0x00, 0x02, 0xe3, 0x00, 0x01, 0xee, 0x00, 0x00,
0x13, 0xe3, 0x00, 0x00, 0x1e, 0xe2, 0x00, 0x00, 0x2e, 0x00, 0x24, 0xee,
0x00, 0x06, 0xe2, 0x00, 0x02, 0x00, 0x08, 0xee, 0x00, 0x50, 0xe2, 0x00,
0x00, 0x00, 0x01, 0xee, 0xe1, 0x00, 0x02, 0xe3, 0x00, 0x01, 0xee, 0xee,
0xe2, 0x00, 0x02, 0xee, 0xee, 0xe0, 0x00, 0x13, 0xe2, 0x00, 0x02, 0xee,
0x00, 0x01, 0x3e, 0xee, 0xee, 0xee, 0x30, 0x00, 0x1e, 0xe1, 0x00, 0x02,
0xee, 0x30, 0x08, 0x00, 0x00, 0x10, 0x2e, 0x30, 0x00, 0x1e, 0xe1, 0x00,
0x02, 0xee, 0x00, 0x00, 0x00, 0x4c, 0xee, 0x20, 0x11, 0x1e, 0xe0, 0x11,
0x03, 0xe1, 0x11, 0x02, 0xe3, 0x01, 0x10, 0xee, 0x10, 0x10, 0x00, 0x00,
0x00, 0x0e, 0xe1, 0x11, 0x02, 0xe3, 0x01, 0x10, 0xee, 0x01, 0x11, 0x03,
0xe3, 0x01, 0x11, 0x1e, 0xe2, 0x01, 0x11, 0x2e, 0x24, 0xee, 0x00, 0x06,
0xe2, 0x01, 0x11, 0x00, 0x08, 0xee, 0x00, 0x68, 0x10, 0x10, 0x00, 0x11,
0x11, 0x0e, 0xe1, 0x11, 0x02, 0xe3, 0x01, 0x10, 0xee, 0xee, 0xe2, 0x01,
0x11, 0xee, 0xee, 0xe0, 0x11, 0x03, 0xe2, 0x01, 0x11, 0xee, 0x01, 0x10,
0x3e, 0xee, 0xee, 0xee, 0x30, 0x11, 0x0e, 0xe1, 0x11, 0x02, 0xe3, 0x00,
0x10, 0x00, 0x00, 0x00, 0x2e, 0x30, 0x11, 0x0e, 0xe1, 0x11, 0x02, 0xee,
0x00, 0x00, 0x00, 0x4c, 0xee, 0x20, 0x11, 0x1e, 0xe0, 0x11, 0x03, 0xe1,
0x11, 0x02, 0xe3, 0x01, 0x10, 0xee, 0x11, 0x10, 0x2e, 0xee, 0xee, 0xee,
0xe1, 0x11, 0x02, 0xe3, 0x01, 0x10, 0xee, 0x01, 0x11, 0x13, 0xe3, 0x01,
0x10, 0x1e, 0xe2, 0x01, 0x11, 0x2e, 0x24, 0xee, 0x00, 0x06, 0xe2, 0x01,
0x11, 0x00, 0x08, 0xee, 0x00, 0x52, 0x11, 0x10, 0x2e, 0x31, 0x11, 0x0e,
0xe1, 0x11, 0x02, 0xe3, 0x01, 0x10, 0xee, 0xee, 0xe2, 0x01, 0x11, 0xee,
0xee, 0xe0, 0x11, 0x03, 0xe2, 0x01, 0x11, 0xee, 0x01, 0x10, 0x3e, 0xee,
0xee, 0xee, 0x30, 0x11, 0x0e, 0xe1, 0x11, 0x02, 0xe3, 0x01, 0x10, 0x00,
0x08, 0xee, 0x00, 0x0e, 0x30, 0x11, 0x0e, 0xe1, 0x11, 0x02, 0xee, 0x00,
0x00, 0x00, 0x00, 0x50, 0xee, 0x20, 0x11, 0x2e, 0xe0, 0x11, 0x03, 0xe1,
0x11, 0x12, 0xe3, 0x01, 0x10, 0xee, 0x11, 0x10, 0x2e, 0xee, 0xee, 0xee,
0xe1, 0x11, 0x12, 0xe3, 0x01, 0x00, 0xee, 0x01, 0x11, 0x11, 0x00, 0x01,
0x12, 0xee, 0xe2, 0x01, 0x11, 0x11, 0x00, 0x2e, 0x20, 0xee, 0x00, 0x06,
0xe2, 0x01, 0x12, 0x00, 0x08, 0xee, 0x00, 0x52, 0x11, 0x10, 0x2e, 0x30,
0x11, 0x0e, 0xe1, 0x11, 0x12, 0xe3, 0x01, 0x00, 0xee, 0xee, 0xe2, 0x01,
0x11, 0xee, 0xee, 0xe0, 0x11, 0x13, 0xe2, 0x01, 0x11, 0xee, 0x01, 0x11,
0x3e, 0xee, 0xee, 0xee, 0x30, 0x11, 0x0e, 0xe1, 0x11, 0x02, 0xe3, 0x01,
0x10, 0x00, 0x08, 0xee, 0x00, 0x0e, 0x30, 0x11, 0x0e, 0xe1, 0x11, 0x02,
0xee, 0x00, 0x00, 0x00, 0x00, 0x38, 0xee, 0x20, 0x11, 0x11, 0x00, 0x11,
0x03, 0xe1, 0x11, 0x11, 0x00, 0x01, 0x10, 0xee, 0x11, 0x10, 0x2e, 0xee,
0xee, 0xee, 0xe1, 0x11, 0x11, 0x00, 0x01, 0x1e, 0xee, 0x01, 0x08, 0x11,
0x00, 0x10, 0x12, 0xee, 0xe2, 0x01, 0x11, 0x11, 0x10, 0x2e, 0x20, 0xee,
0x00, 0x60, 0xe2, 0x01, 0x11, 0x10, 0x00, 0x03, 0xee, 0x11, 0x10, 0x2e,
0x30, 0x11, 0x0e, 0xe1, 0x11, 0x12, 0x22, 0x01, 0x02, 0xee, 0xee, 0xe2,
0x01, 0x11, 0xee, 0xee, 0xe0, 0x11, 0x12, 0x21, 0x01, 0x11, 0xee, 0x01,
0x11, 0x22, 0x22, 0x23, 0xee, 0x30, 0x11, 0x12, 0x21, 0x11, 0x02, 0xe3,
0x01, 0x10, 0x08, 0xee, 0x00, 0x0e, 0x30, 0x11, 0x12, 0x21, 0x10, 0x13,
0xee, 0x00, 0x00, 0x00, 0x00, 0x50, 0xee, 0x20, 0x11, 0x00, 0x11, 0x11,
0x03, 0xe1, 0x11, 0x00, 0x01, 0x11, 0x10, 0xee, 0x11, 0x10, 0x2e, 0xee,
0xee, 0xee, 0xe1, 0x11, 0x00, 0x01, 0x11, 0x1e, 0xee, 0x01, 0x11, 0x00,
0x01, 0x11, 0x12, 0xee, 0xe2, 0x01, 0x11, 0x00, 0x00, 0x2e, 0x20, 0xee,
0x00, 0x60, 0xe2, 0x01, 0x10, 0x01, 0x11, 0x12, 0x3e, 0x11, 0x10, 0x2e,
0x30, 0x11, 0x0e, 0xe1, 0x11, 0x10, 0x10, 0x11, 0x1e, 0xee, 0xee, 0xe2,
0x01, 0x11, 0xee, 0xee, 0xe0, 0x11, 0x10, 0x10, 0x11, 0x11, 0xee, 0x01,
0x11, 0x01, 0x00, 0x01, 0x2e, 0x30, 0x11, 0x00, 0x10, 0x11, 0x02, 0xe3,
0x01, 0x10, 0x08, 0xee, 0x00, 0x0e, 0x30, 0x11, 0x00, 0x10, 0x11, 0x2e,
0xee, 0x00, 0x00, 0x00, 0x00, 0x4c, 0xee, 0x20, 0x11, 0x1e, 0xe1, 0x11,
0x03, 0xe1, 0x11, 0x02, 0xe3, 0x11, 0x10, 0xee, 0x11, 0x10, 0x2e, 0xee,
0xee, 0xee, 0xe1, 0x11, 0x02, 0xe3, 0x11, 0x10, 0xee, 0x01, 0x11, 0x03,
0xe3, 0x11, 0x11, 0x1e, 0xe2, 0x01, 0x11, 0x2e, 0x24, 0xee, 0x00, 0x60,
0xe2, 0x01, 0x11, 0xee, 0x11, 0x10, 0x3e, 0x11, 0x10, 0x2e, 0x30, 0x11,
0x0e, 0xe1, 0x11, 0x01, 0x22, 0x11, 0x12, 0xee, 0xee, 0xe2, 0x01, 0x11,
0xee, 0xee, 0xe0, 0x11, 0x02, 0x22, 0x11, 0x11, 0xee, 0x01, 0x10, 0x22,
0x21, 0x11, 0x1e, 0x30, 0x11, 0x02, 0x21, 0x11, 0x02, 0xe3, 0x01, 0x10,
0x08, 0xee, 0x00, 0x0e, 0x30, 0x11, 0x02, 0x21, 0x11, 0x23, 0xee, 0x00,
0x00, 0x00, 0x00, 0x4c, 0xee, 0x20, 0x11, 0x1e, 0xe0, 0x11, 0x03, 0xe1,
0x11, 0x02, 0xe3, 0x01, 0x10, 0xee, 0x11, 0x10, 0x2e, 0xee, 0xee, 0xee,
0xe1, 0x11, 0x02, 0xe3, 0x01, 0x10, 0xee, 0x01, 0x11, 0x13, 0xe3, 0x01,
0x11, 0x1e, 0xe2, 0x01, 0x11, 0x2e, 0x24, 0xee, 0x00, 0x60, 0xe2, 0x01,
0x11, 0xee, 0x01, 0x10, 0x3e, 0x11, 0x11, 0x2e, 0x30, 0x11, 0x0e, 0xe1,
0x11, 0x12, 0xe3, 0x11, 0x10, 0xee, 0xee, 0xe2, 0x01, 0x11, 0xee, 0xee,
0xe0, 0x11, 0x13, 0xe2, 0x11, 0x11, 0xee, 0x01, 0x11, 0x3e, 0x21, 0x11,
0x1e, 0x30, 0x11, 0x0e, 0xe1, 0x11, 0x02, 0xe3, 0x01, 0x10, 0x08, 0xee,
0x00, 0x0e, 0x30, 0x11, 0x0e, 0xe1, 0x11, 0x02, 0xee, 0x00, 0x00, 0x00,
0x00, 0x54, 0xee, 0x20, 0x11, 0x1e, 0xe0, 0x11, 0x03, 0xe1, 0x11, 0x12,
0xe3, 0x01, 0x00, 0xee, 0x11, 0x11, 0x2e, 0xee, 0xee, 0xee, 0xe1, 0x11,
0x02, 0xe3, 0x01, 0x10, 0xee, 0x01, 0x11, 0x11, 0x00, 0x01, 0x10, 0x1e,
0xe2, 0x01, 0x11, 0x11, 0x00, 0x00, 0x01, 0x2e, 0x1c, 0xee, 0x00, 0x60,
0xe2, 0x01, 0x12, 0xee, 0x01, 0x00, 0x3e, 0x11, 0x11, 0x22, 0x20, 0x11,
0x0e, 0xe1, 0x11, 0x12, 0x22, 0x01, 0x10, 0xee, 0xee, 0xe2, 0x01, 0x12,
0xee, 0xee, 0xe0, 0x11, 0x12, 0x21, 0x01, 0x11, 0xee, 0x01, 0x11, 0x22,
0x10, 0x11, 0x1e, 0x30, 0x11, 0x12, 0x21, 0x11, 0x02, 0xe3, 0x01, 0x11,
0x08, 0xee, 0x00, 0x0e, 0x30, 0x11, 0x0e, 0xe1, 0x11, 0x02, 0xee, 0x00,
0x00, 0x00, 0x00, 0x38, 0xee, 0x20, 0x11, 0x1e, 0xe0, 0x11, 0x03, 0xe2,
0x11, 0x11, 0x00, 0x01, 0x02, 0xee, 0x21, 0x11, 0x10, 0x00, 0x00, 0x1e,
0xe1, 0x11, 0x02, 0xe3, 0x01, 0x10, 0xee, 0x01, 0x08, 0x11, 0x00, 0x08,
0x12, 0xee, 0xe3, 0x21, 0x08, 0x11, 0x02, 0x10, 0x02, 0x2e, 0x1c, 0xee,
0x00, 0x76, 0xe2, 0x01, 0x11, 0x10, 0x01, 0x02, 0x3e, 0x11, 0x11, 0x11,
0x01, 0x10, 0x0e, 0xe1, 0x11, 0x11, 0x10, 0x11, 0x00, 0xee, 0x10, 0x00,
0x01, 0x11, 0x10, 0x1e, 0xe0, 0x11, 0x11, 0x10, 0x11, 0x01, 0xee, 0x01,
0x11, 0x11, 0x01, 0x10, 0x1e, 0x30, 0x11, 0x11, 0x00, 0x10, 0x02, 0xe3,
0x01, 0x11, 0x10, 0x00, 0x00, 0x2e, 0x30, 0x11, 0x0e, 0xe1, 0x11, 0x02,
0xee, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xee, 0x20, 0x00, 0x1e, 0xe1, 0x00,
0x03, 0xee, 0x20, 0x00, 0x00, 0x00, 0x1e, 0xee, 0xe2, 0x00, 0x08, 0x00,
0x00, 0x12, 0x0e, 0xe2, 0x00, 0x02, 0xe3, 0x10, 0x00, 0xee, 0x10, 0x00,
0x08, 0x00, 0x00, 0x08, 0x02, 0xee, 0xee, 0x30, 0x0a, 0x00, 0x02, 0x2e,
0x1c, 0xee, 0x02, 0xe2, 0x08, 0x00, 0x00, 0x12, 0x03, 0xee, 0xe2, 0x00,
0x00, 0x00, 0x01, 0xee, 0xe2, 0x00, 0x08, 0x00, 0x00, 0x06, 0x1e, 0xee,
0x20, 0x00, 0x08, 0x00, 0x00, 0x1e, 0x0e, 0xee, 0x10, 0x00, 0x00, 0x00,
0x2e, 0xee, 0x10, 0x00, 0x00, 0x00, 0x02, 0xee, 0xe3, 0x00, 0x08, 0x00,
0x00, 0x06, 0x2e, 0xee, 0x30, 0x00, 0x08, 0x00, 0x00, 0x10, 0x2e, 0x31,
0x00, 0x0e, 0xe2, 0x00, 0x02, 0xee, 0x00, 0x00, 0xe6, 0xee, 0x00, 0x00,
0xe6, 0xee, 0x00, 0x00, 0xe6, 0xee, 0x00, 0x00, 0xe6, 0xee, 0x00, 0x01};
unsigned int splash_bmp_len = 3828;
0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x33, 0x00, 0x00, 0xe6, 0x33,
0x00, 0x00, 0xe6, 0x33, 0x00, 0x00, 0xe6, 0x33, 0x00, 0x00, 0x00, 0x08,
0x33, 0x44, 0x44, 0x47, 0x0a, 0x33, 0x00, 0x06, 0xd5, 0x44, 0x7d, 0x00,
0x0a, 0x33, 0x00, 0x0a, 0x44, 0x44, 0x48, 0x33, 0x3a, 0x00, 0x06, 0x44,
0x02, 0xd3, 0x12, 0x33, 0x00, 0x08, 0xa4, 0x44, 0x45, 0x9d, 0x08, 0x33,
0x00, 0x08, 0xc4, 0x44, 0x45, 0xc3, 0x10, 0x33, 0x00, 0x08, 0x34, 0x44,
0x44, 0x6d, 0x16, 0x33, 0x00, 0x08, 0x34, 0x44, 0x44, 0x6d, 0x08, 0x33,
0x02, 0xd5, 0x1a, 0x44, 0x00, 0x0c, 0x45, 0xc3, 0x33, 0x44, 0x44, 0x47,
0x0a, 0x33, 0x00, 0x06, 0xd5, 0x44, 0x7d, 0x00, 0x0a, 0x33, 0x00, 0x08,
0x44, 0x44, 0x48, 0x33, 0x00, 0x00, 0x00, 0x0a, 0x33, 0x49, 0x99, 0x95,
0xd3, 0x00, 0x06, 0x33, 0x00, 0x0a, 0xd4, 0x46, 0x89, 0x98, 0xb3, 0x00,
0x08, 0x33, 0x00, 0x12, 0x49, 0x99, 0x94, 0x33, 0x3d, 0x79, 0x99, 0x99,
0x73, 0x00, 0x10, 0x33, 0x00, 0x0a, 0x3d, 0x47, 0x99, 0x95, 0xa3, 0x00,
0x08, 0x33, 0x00, 0x08, 0xc7, 0x99, 0x97, 0xa3, 0x10, 0x33, 0x00, 0x08,
0x34, 0x99, 0x99, 0x7c, 0x16, 0x33, 0x00, 0x08, 0x34, 0x99, 0x99, 0x7c,
0x06, 0x33, 0x00, 0x06, 0xb4, 0x56, 0x89, 0x00, 0x18, 0x99, 0x00, 0x0e,
0x97, 0xa3, 0x33, 0x49, 0x99, 0x95, 0xd3, 0x00, 0x06, 0x33, 0x00, 0x0a,
0xd4, 0x46, 0x89, 0x98, 0xb3, 0x00, 0x08, 0x33, 0x00, 0x08, 0x49, 0x99,
0x94, 0x33, 0x00, 0x00, 0x00, 0x0a, 0x33, 0x49, 0x99, 0x95, 0xd3, 0x00,
0x06, 0x33, 0x02, 0x55, 0x06, 0x99, 0x02, 0x9b, 0x08, 0x33, 0x00, 0x12,
0x49, 0x99, 0x94, 0x33, 0x33, 0xb9, 0x99, 0x99, 0x8d, 0x00, 0x10, 0x33,
0x00, 0x0a, 0x37, 0x69, 0x99, 0x74, 0xd3, 0x00, 0x08, 0x33, 0x00, 0x08,
0xc7, 0x99, 0x97, 0xa3, 0x10, 0x33, 0x00, 0x08, 0x34, 0x99, 0x99, 0x7c,
0x16, 0x33, 0x00, 0x10, 0x34, 0x99, 0x99, 0x7c, 0x33, 0x33, 0x3a, 0x47,
0x1c, 0x99, 0x00, 0x0e, 0x97, 0xa3, 0x33, 0x49, 0x99, 0x95, 0xd3, 0x00,
0x06, 0x33, 0x02, 0x55, 0x06, 0x99, 0x02, 0x9b, 0x08, 0x33, 0x00, 0x08,
0x49, 0x99, 0x94, 0x33, 0x00, 0x00, 0x00, 0x12, 0x33, 0x49, 0x99, 0x95,
0xd3, 0x33, 0x33, 0x3a, 0x48, 0x00, 0x06, 0x99, 0x02, 0x98, 0x02, 0xd3,
0x06, 0x33, 0x00, 0x12, 0x49, 0x99, 0x94, 0x33, 0x33, 0xd7, 0x99, 0x99,
0x98, 0x00, 0x10, 0x33, 0x00, 0x08, 0xd4, 0x89, 0x99, 0x5a, 0x0a, 0x33,
0x00, 0x08, 0xc7, 0x99, 0x97, 0xa3, 0x10, 0x33, 0x00, 0x08, 0x34, 0x99,
0x99, 0x7c, 0x16, 0x33, 0x00, 0x10, 0x34, 0x99, 0x99, 0x7c, 0x33, 0x33,
0xb4, 0x79, 0x1c, 0x99, 0x00, 0x16, 0x97, 0xa3, 0x33, 0x49, 0x99, 0x95,
0xd3, 0x33, 0x33, 0x3a, 0x48, 0x00, 0x06, 0x99, 0x02, 0x98, 0x02, 0xd3,
0x06, 0x33, 0x00, 0x08, 0x49, 0x99, 0x94, 0x33, 0x00, 0x00, 0x00, 0x12,
0x33, 0x49, 0x99, 0x95, 0xd3, 0x33, 0x33, 0xd4, 0x79, 0x00, 0x08, 0x99,
0x02, 0x73, 0x06, 0x33, 0x00, 0x0c, 0x49, 0x99, 0x94, 0x33, 0x33, 0x3b,
0x06, 0x99, 0x02, 0xc3, 0x0e, 0x33, 0x00, 0x08, 0x56, 0x99, 0x97, 0x4d,
0x0a, 0x33, 0x00, 0x08, 0xc7, 0x99, 0x97, 0xa3, 0x10, 0x33, 0x00, 0x08,
0x34, 0x99, 0x99, 0x7c, 0x16, 0x33, 0x00, 0x0e, 0x34, 0x99, 0x99, 0x7c,
0x33, 0x3d, 0x47, 0x00, 0x1e, 0x99, 0x00, 0x16, 0x97, 0xa3, 0x33, 0x49,
0x99, 0x95, 0xd3, 0x33, 0x33, 0xd4, 0x79, 0x00, 0x08, 0x99, 0x02, 0x73,
0x06, 0x33, 0x00, 0x08, 0x49, 0x99, 0x94, 0x33, 0x00, 0x00, 0x00, 0x10,
0x33, 0x49, 0x99, 0x95, 0xd3, 0x33, 0x33, 0xa5, 0x0a, 0x99, 0x02, 0x8d,
0x06, 0x33, 0x00, 0x14, 0x49, 0x99, 0x94, 0x33, 0x33, 0x3d, 0x79, 0x99,
0x99, 0x73, 0x0c, 0x33, 0x00, 0x0a, 0x3c, 0x48, 0x99, 0x95, 0xa3, 0x00,
0x0a, 0x33, 0x00, 0x08, 0xc7, 0x99, 0x97, 0xa3, 0x10, 0x33, 0x00, 0x08,
0x34, 0x99, 0x99, 0x7c, 0x16, 0x33, 0x00, 0x0e, 0x34, 0x99, 0x99, 0x7c,
0x33, 0x37, 0x69, 0x00, 0x1e, 0x99, 0x00, 0x14, 0x97, 0xa3, 0x33, 0x49,
0x99, 0x95, 0xd3, 0x33, 0x33, 0xa5, 0x0a, 0x99, 0x02, 0x8d, 0x06, 0x33,
0x00, 0x08, 0x49, 0x99, 0x94, 0x33, 0x00, 0x00, 0x00, 0x1c, 0x33, 0x49,
0x99, 0x95, 0xd3, 0x33, 0x3d, 0x47, 0x99, 0x97, 0x89, 0x99, 0x99, 0x97,
0x06, 0x33, 0x00, 0x06, 0x49, 0x99, 0x94, 0x00, 0x06, 0x33, 0x00, 0x08,
0xb9, 0x99, 0x99, 0x9d, 0x0c, 0x33, 0x00, 0x0a, 0x34, 0x69, 0x99, 0x74,
0xd3, 0x00, 0x0a, 0x33, 0x00, 0x08, 0xc7, 0x99, 0x98, 0xa3, 0x10, 0x33,
0x00, 0x08, 0x34, 0x99, 0x99, 0x7c, 0x16, 0x33, 0x00, 0x12, 0x34, 0x99,
0x99, 0x7c, 0x33, 0x34, 0x89, 0x99, 0x64, 0x00, 0x1c, 0x44, 0x00, 0x1e,
0xa3, 0x33, 0x49, 0x99, 0x95, 0xd3, 0x33, 0x3d, 0x47, 0x99, 0x97, 0x89,
0x99, 0x99, 0x97, 0x00, 0x06, 0x33, 0x00, 0x08, 0x49, 0x99, 0x94, 0x33,
0x00, 0x00, 0x00, 0x28, 0x33, 0x49, 0x99, 0x95, 0xd3, 0x33, 0x3c, 0x59,
0x99, 0x95, 0xbc, 0x99, 0x99, 0x98, 0xd3, 0x33, 0x33, 0x49, 0x99, 0x94,
0x06, 0x33, 0x02, 0xd7, 0x06, 0x99, 0x02, 0x74, 0x0c, 0x44, 0x00, 0x06,
0x99, 0x99, 0x4b, 0x00, 0x0c, 0x33, 0x00, 0x08, 0xb7, 0x99, 0x99, 0xa3,
0x10, 0x33, 0x00, 0x08, 0x34, 0x99, 0x99, 0x7c, 0x16, 0x33, 0x00, 0x12,
0x34, 0x99, 0x99, 0x7c, 0x33, 0xd5, 0x99, 0x99, 0x6d, 0x00, 0x20, 0x33,
0x00, 0x28, 0x49, 0x99, 0x95, 0xd3, 0x33, 0x3c, 0x59, 0x99, 0x95, 0xbc,
0x99, 0x99, 0x98, 0xd3, 0x33, 0x33, 0x49, 0x99, 0x94, 0x33, 0x00, 0x00,
0x00, 0x28, 0x33, 0x49, 0x99, 0x95, 0xd3, 0x33, 0x34, 0x79, 0x99, 0x84,
0xdd, 0x89, 0x99, 0x99, 0x83, 0x33, 0x33, 0x49, 0x99, 0x94, 0x06, 0x33,
0x02, 0x3b, 0x16, 0x99, 0x02, 0x97, 0x02, 0x43, 0x0a, 0x33, 0x00, 0x0a,
0x3d, 0x47, 0x99, 0x99, 0x9d, 0x00, 0x10, 0x33, 0x00, 0x08, 0x34, 0x99,
0x99, 0x9d, 0x16, 0x33, 0x00, 0x12, 0x34, 0x99, 0x99, 0x7c, 0x33, 0xd6,
0x99, 0x99, 0x6d, 0x00, 0x20, 0x33, 0x00, 0x28, 0x49, 0x99, 0x95, 0xd3,
0x33, 0x34, 0x79, 0x99, 0x84, 0xdd, 0x89, 0x99, 0x99, 0x83, 0x33, 0x33,
0x49, 0x99, 0x94, 0x33, 0x00, 0x00, 0x00, 0x28, 0x33, 0x49, 0x99, 0x95,
0xd3, 0x33, 0xc4, 0x99, 0x99, 0x67, 0x33, 0x79, 0x99, 0x99, 0x8d, 0x33,
0x33, 0x49, 0x99, 0x94, 0x06, 0x33, 0x02, 0x3d, 0x02, 0x79, 0x14, 0x99,
0x02, 0x94, 0x02, 0xc3, 0x0a, 0x33, 0x00, 0x0a, 0x35, 0x59, 0x99, 0x99,
0x98, 0x00, 0x10, 0x33, 0x02, 0x34, 0x06, 0x99, 0x02, 0x74, 0x16, 0x44,
0x00, 0x10, 0x99, 0x99, 0x7c, 0x33, 0xd6, 0x99, 0x99, 0x9d, 0x20, 0x33,
0x00, 0x28, 0x49, 0x99, 0x95, 0xd3, 0x33, 0xc4, 0x99, 0x99, 0x67, 0x33,
0x79, 0x99, 0x99, 0x8d, 0x33, 0x33, 0x49, 0x99, 0x94, 0x33, 0x00, 0x00,
0x00, 0x28, 0x33, 0x49, 0x99, 0x95, 0xd3, 0x33, 0x57, 0x99, 0x99, 0x4d,
0x33, 0xd8, 0x99, 0x99, 0x98, 0x33, 0x33, 0x49, 0x99, 0x94, 0x08, 0x33,
0x02, 0xc9, 0x14, 0x99, 0x02, 0x74, 0x0c, 0x33, 0x02, 0x84, 0x02, 0x89,
0x06, 0x99, 0x02, 0xa3, 0x0e, 0x33, 0x02, 0x34, 0x22, 0x99, 0x00, 0x06,
0x7c, 0x33, 0xd6, 0x00, 0x06, 0x99, 0x02, 0x64, 0x18, 0x44, 0x00, 0x2e,
0x45, 0xc3, 0x33, 0x49, 0x99, 0x95, 0xd3, 0x33, 0x57, 0x99, 0x99, 0x4d,
0x33, 0xd8, 0x99, 0x99, 0x98, 0x33, 0x33, 0x49, 0x99, 0x94, 0x33, 0x00,
0x00, 0x00, 0x00, 0x28, 0x33, 0x49, 0x99, 0x95, 0xd3, 0x3d, 0x48, 0x99,
0x97, 0x43, 0x33, 0x37, 0x99, 0x99, 0x97, 0xd3, 0x33, 0x49, 0x99, 0x94,
0x08, 0x33, 0x02, 0x37, 0x14, 0x99, 0x02, 0x4c, 0x0a, 0x33, 0x02, 0x3b,
0x02, 0x48, 0x08, 0x99, 0x02, 0x9b, 0x0e, 0x33, 0x02, 0x34, 0x22, 0x99,
0x00, 0x06, 0x7c, 0x33, 0xd6, 0x00, 0x20, 0x99, 0x00, 0x2e, 0x97, 0xa3,
0x33, 0x49, 0x99, 0x95, 0xd3, 0x3d, 0x48, 0x99, 0x97, 0x43, 0x33, 0x37,
0x99, 0x99, 0x97, 0xd3, 0x33, 0x49, 0x99, 0x94, 0x33, 0x00, 0x00, 0x00,
0x00, 0x28, 0x33, 0x49, 0x99, 0x95, 0xd3, 0x35, 0x69, 0x99, 0x95, 0xc3,
0x33, 0x3c, 0x89, 0x99, 0x99, 0xb3, 0x33, 0x49, 0x99, 0x94, 0x08, 0x33,
0x02, 0x3c, 0x12, 0x99, 0x02, 0x97, 0x02, 0x43, 0x0a, 0x33, 0x02, 0xd4,
0x02, 0x79, 0x0a, 0x99, 0x02, 0xd3, 0x0c, 0x33, 0x02, 0x34, 0x22, 0x99,
0x00, 0x06, 0x7c, 0x33, 0xd6, 0x00, 0x20, 0x99, 0x00, 0x2e, 0x97, 0xa3,
0x33, 0x49, 0x99, 0x95, 0xd3, 0x35, 0x69, 0x99, 0x95, 0xc3, 0x33, 0x3c,
0x89, 0x99, 0x99, 0xb3, 0x33, 0x49, 0x99, 0x94, 0x33, 0x00, 0x00, 0x00,
0x00, 0x12, 0x33, 0x49, 0x99, 0x95, 0xd3, 0xd4, 0x89, 0x99, 0x74, 0x00,
0x06, 0x33, 0x00, 0x10, 0x79, 0x99, 0x99, 0x7d, 0x33, 0x49, 0x99, 0x94,
0x0a, 0x33, 0x00, 0x16, 0x79, 0x99, 0x99, 0x64, 0x44, 0x44, 0x89, 0x99,
0x99, 0x94, 0xc3, 0x00, 0x08, 0x33, 0x00, 0x0a, 0x3d, 0x46, 0x99, 0x98,
0x59, 0x00, 0x06, 0x99, 0x02, 0x8d, 0x0c, 0x33, 0x02, 0x34, 0x22, 0x99,
0x00, 0x06, 0x7c, 0x33, 0xd6, 0x00, 0x20, 0x99, 0x00, 0x16, 0x97, 0xa3,
0x33, 0x49, 0x99, 0x95, 0xd3, 0xd4, 0x89, 0x99, 0x74, 0x00, 0x06, 0x33,
0x00, 0x12, 0x79, 0x99, 0x99, 0x7d, 0x33, 0x49, 0x99, 0x94, 0x33, 0x00,
0x00, 0x00, 0x00, 0x12, 0x33, 0x49, 0x99, 0x95, 0xd3, 0x76, 0x99, 0x99,
0x6a, 0x00, 0x06, 0x33, 0x00, 0x10, 0xa9, 0x99, 0x99, 0x9b, 0x33, 0x49,
0x99, 0x94, 0x0a, 0x33, 0x00, 0x14, 0xc9, 0x99, 0x99, 0x9c, 0x33, 0x33,
0x3b, 0x99, 0x99, 0x74, 0x0a, 0x33, 0x00, 0x0a, 0x35, 0x59, 0x99, 0x95,
0x7d, 0x00, 0x06, 0x99, 0x02, 0x9a, 0x0c, 0x33, 0x02, 0x34, 0x22, 0x99,
0x00, 0x06, 0x7c, 0x33, 0xd6, 0x00, 0x20, 0x99, 0x00, 0x16, 0x97, 0xa3,
0x33, 0x49, 0x99, 0x95, 0xd3, 0x76, 0x99, 0x99, 0x6a, 0x00, 0x06, 0x33,
0x00, 0x12, 0xa9, 0x99, 0x99, 0x9b, 0x33, 0x49, 0x99, 0x94, 0x33, 0x00,
0x00, 0x00, 0x00, 0x12, 0x33, 0x49, 0x99, 0x95, 0x3d, 0x48, 0x99, 0x98,
0x4d, 0x00, 0x06, 0x33, 0x00, 0x10, 0xd7, 0x99, 0x99, 0x97, 0xd3, 0x49,
0x99, 0x94, 0x0a, 0x33, 0x00, 0x14, 0x37, 0x99, 0x99, 0x97, 0x33, 0x33,
0xc4, 0x89, 0x99, 0x4c, 0x0a, 0x33, 0x00, 0x0c, 0x84, 0x89, 0x99, 0x64,
0x33, 0xd9, 0x06, 0x99, 0x02, 0xa3, 0x0a, 0x33, 0x00, 0x08, 0x34, 0x99,
0x99, 0x64, 0x16, 0x44, 0x06, 0x99, 0x00, 0x06, 0x7c, 0x33, 0xd6, 0x00,
0x20, 0x99, 0x00, 0x16, 0x97, 0xa3, 0x33, 0x49, 0x99, 0x95, 0x3d, 0x48,
0x99, 0x98, 0x4d, 0x00, 0x06, 0x33, 0x00, 0x12, 0xd7, 0x99, 0x99, 0x97,
0xd3, 0x49, 0x99, 0x94, 0x33, 0x00, 0x00, 0x00, 0x00, 0x12, 0x33, 0x49,
0x99, 0x96, 0x3b, 0x69, 0x99, 0x96, 0x53, 0x00, 0x06, 0x33, 0x02, 0x38,
0x06, 0x99, 0x00, 0x08, 0xc3, 0x49, 0x99, 0x94, 0x0a, 0x33, 0x02, 0x3c,
0x06, 0x99, 0x00, 0x0c, 0xb3, 0x33, 0x46, 0x99, 0x96, 0x43, 0x08, 0x33,
0x00, 0x0e, 0x3b, 0x48, 0x99, 0x97, 0x4d, 0x33, 0x3d, 0x00, 0x06, 0x99,
0x02, 0x9c, 0x0a, 0x33, 0x00, 0x08, 0x34, 0x99, 0x99, 0x6d, 0x16, 0x33,
0x00, 0x12, 0x39, 0x99, 0x99, 0x7c, 0x33, 0xd6, 0x99, 0x99, 0x54, 0x00,
0x1c, 0x44, 0x00, 0x14, 0xa3, 0x33, 0x49, 0x99, 0x96, 0x3b, 0x69, 0x99,
0x96, 0x53, 0x06, 0x33, 0x02, 0x38, 0x06, 0x99, 0x00, 0x0a, 0xc3, 0x49,
0x99, 0x94, 0x33, 0x00, 0x00, 0x00, 0x00, 0x12, 0x33, 0x49, 0x99, 0x98,
0xd5, 0x79, 0x99, 0x94, 0xd3, 0x00, 0x06, 0x33, 0x00, 0x10, 0x3d, 0x89,
0x99, 0x99, 0x73, 0x49, 0x99, 0x94, 0x0c, 0x33, 0x00, 0x12, 0x79, 0x99,
0x99, 0x8d, 0x3a, 0x59, 0x99, 0x84, 0xd3, 0x00, 0x08, 0x33, 0x00, 0x10,
0xd4, 0x79, 0x99, 0x84, 0xb3, 0x33, 0x33, 0xb9, 0x06, 0x99, 0x02, 0xd3,
0x08, 0x33, 0x00, 0x08, 0x34, 0x99, 0x99, 0x6d, 0x16, 0x33, 0x00, 0x12,
0x34, 0x99, 0x99, 0x7c, 0x33, 0xd6, 0x99, 0x99, 0x5d, 0x00, 0x20, 0x33,
0x00, 0x10, 0x49, 0x99, 0x98, 0xd5, 0x79, 0x99, 0x94, 0xd3, 0x06, 0x33,
0x00, 0x12, 0x3d, 0x89, 0x99, 0x99, 0x73, 0x49, 0x99, 0x94, 0x33, 0x00,
0x00, 0x00, 0x00, 0x10, 0x33, 0x49, 0x99, 0x99, 0xa6, 0x99, 0x99, 0x74,
0x0a, 0x33, 0x00, 0x0e, 0x79, 0x99, 0x99, 0x9c, 0x59, 0x99, 0x94, 0x00,
0x0c, 0x33, 0x00, 0x10, 0xc9, 0x99, 0x99, 0x9a, 0xd4, 0x79, 0x99, 0x65,
0x08, 0x33, 0x00, 0x0a, 0x3d, 0x46, 0x99, 0x98, 0x48, 0x00, 0x06, 0x33,
0x02, 0x3a, 0x06, 0x99, 0x02, 0x83, 0x08, 0x33, 0x00, 0x08, 0x34, 0x99,
0x99, 0x6d, 0x16, 0x33, 0x00, 0x12, 0x34, 0x99, 0x99, 0x7c, 0x33, 0xd6,
0x99, 0x99, 0x93, 0x00, 0x20, 0x33, 0x00, 0x0e, 0x49, 0x99, 0x99, 0xa6,
0x99, 0x99, 0x74, 0x00, 0x0a, 0x33, 0x00, 0x10, 0x79, 0x99, 0x99, 0x9c,
0x59, 0x99, 0x94, 0x33, 0x00, 0x00, 0x00, 0x10, 0x33, 0x49, 0x99, 0x99,
0x98, 0x99, 0x99, 0x5c, 0x0a, 0x33, 0x02, 0xd8, 0x06, 0x99, 0x00, 0x06,
0x79, 0x99, 0x84, 0x00, 0x0c, 0x33, 0x02, 0x37, 0x06, 0x99, 0x00, 0x08,
0x86, 0x99, 0x98, 0x4d, 0x08, 0x33, 0x00, 0x0a, 0x35, 0x59, 0x99, 0x95,
0x53, 0x00, 0x08, 0x33, 0x00, 0x08, 0x89, 0x99, 0x99, 0x9a, 0x08, 0x33,
0x00, 0x08, 0x34, 0x99, 0x99, 0x6d, 0x16, 0x33, 0x00, 0x0c, 0x34, 0x99,
0x99, 0x7c, 0x33, 0x36, 0x06, 0x99, 0x02, 0x54, 0x18, 0x44, 0x00, 0x14,
0x45, 0xc3, 0x33, 0x49, 0x99, 0x99, 0x98, 0x99, 0x99, 0x5c, 0x0a, 0x33,
0x02, 0xd8, 0x06, 0x99, 0x00, 0x08, 0x79, 0x99, 0x84, 0x33, 0x00, 0x00,
0x02, 0x33, 0x02, 0x59, 0x08, 0x99, 0x02, 0x97, 0x02, 0x4d, 0x0a, 0x33,
0x02, 0x36, 0x0a, 0x99, 0x02, 0x75, 0x0c, 0x33, 0x02, 0x3c, 0x0a, 0x99,
0x02, 0x96, 0x02, 0x53, 0x08, 0x33, 0x00, 0x0a, 0x84, 0x89, 0x99, 0x64,
0xd3, 0x00, 0x08, 0x33, 0x02, 0xd9, 0x06, 0x99, 0x02, 0xb3, 0x06, 0x33,
0x00, 0x08, 0x34, 0x99, 0x99, 0x6d, 0x16, 0x33, 0x00, 0x0c, 0x34, 0x99,
0x99, 0x7c, 0x33, 0x36, 0x20, 0x99, 0x00, 0x08, 0x97, 0xa3, 0x33, 0x59,
0x08, 0x99, 0x02, 0x97, 0x02, 0x4d, 0x0a, 0x33, 0x02, 0x36, 0x0a, 0x99,
0x02, 0x75, 0x02, 0x33, 0x00, 0x00, 0x02, 0x33, 0x02, 0xa8, 0x08, 0x99,
0x02, 0x95, 0x02, 0xa3, 0x0a, 0x33, 0x02, 0x3c, 0x0a, 0x99, 0x02, 0x5b,
0x0e, 0x33, 0x02, 0x89, 0x08, 0x99, 0x02, 0x84, 0x02, 0xd3, 0x06, 0x33,
0x00, 0x0a, 0x3b, 0x48, 0x99, 0x97, 0x4c, 0x00, 0x0a, 0x33, 0x02, 0x3d,
0x06, 0x99, 0x02, 0x9d, 0x06, 0x33, 0x00, 0x08, 0x34, 0x99, 0x99, 0x6d,
0x16, 0x33, 0x00, 0x0e, 0x34, 0x99, 0x99, 0x7c, 0x33, 0x3d, 0x89, 0x00,
0x1e, 0x99, 0x00, 0x08, 0x97, 0xa3, 0x33, 0xa8, 0x08, 0x99, 0x02, 0x95,
0x02, 0xa3, 0x0a, 0x33, 0x02, 0x3c, 0x0a, 0x99, 0x02, 0x5b, 0x02, 0x33,
0x00, 0x00, 0x02, 0x33, 0x02, 0xd7, 0x08, 0x99, 0x02, 0x64, 0x0e, 0x33,
0x02, 0x79, 0x06, 0x99, 0x02, 0x96, 0x02, 0x4d, 0x0e, 0x33, 0x02, 0xd8,
0x06, 0x99, 0x02, 0x98, 0x02, 0x48, 0x08, 0x33, 0x00, 0x0a, 0xd4, 0x79,
0x99, 0x84, 0xb3, 0x00, 0x0c, 0x33, 0x00, 0x16, 0xb9, 0x99, 0x99, 0x98,
0xd3, 0x33, 0x33, 0x34, 0x99, 0x99, 0x6d, 0x00, 0x16, 0x33, 0x00, 0x0c,
0x34, 0x99, 0x99, 0x7c, 0x33, 0x33, 0x20, 0x99, 0x00, 0x08, 0x97, 0xa3,
0x33, 0xd7, 0x08, 0x99, 0x02, 0x64, 0x0e, 0x33, 0x02, 0x79, 0x06, 0x99,
0x00, 0x06, 0x96, 0x4d, 0x33, 0x00, 0x00, 0x00, 0x02, 0x33, 0x02, 0x3c,
0x06, 0x99, 0x02, 0x96, 0x02, 0x4d, 0x0e, 0x33, 0x02, 0xd9, 0x06, 0x99,
0x02, 0x74, 0x02, 0xc3, 0x0e, 0x33, 0x02, 0x3d, 0x06, 0x99, 0x02, 0x85,
0x02, 0x53, 0x06, 0x33, 0x00, 0x0a, 0x3d, 0x46, 0x99, 0x99, 0x57, 0x00,
0x0e, 0x33, 0x02, 0x39, 0x06, 0x99, 0x00, 0x0e, 0xa3, 0x33, 0x33, 0x34,
0x99, 0x99, 0x6d, 0x00, 0x16, 0x33, 0x00, 0x0e, 0x34, 0x99, 0x99, 0x7c,
0x33, 0x33, 0x3a, 0x00, 0x1e, 0x99, 0x00, 0x08, 0x97, 0xa3, 0x33, 0x3c,
0x06, 0x99, 0x02, 0x96, 0x02, 0x4d, 0x0e, 0x33, 0x02, 0xd9, 0x06, 0x99,
0x00, 0x06, 0x74, 0xc3, 0x33, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x33, 0x33,
0xc8, 0x99, 0x96, 0x44, 0xd3, 0x00, 0x0e, 0x33, 0x00, 0x0a, 0x3d, 0x79,
0x99, 0x76, 0x4b, 0x00, 0x12, 0x33, 0x00, 0x0a, 0xc7, 0x99, 0x96, 0x45,
0xd3, 0x00, 0x06, 0x33, 0x00, 0x0a, 0x35, 0x59, 0x99, 0x96, 0x43, 0x00,
0x10, 0x33, 0x00, 0x14, 0x89, 0x99, 0x99, 0x9a, 0x33, 0x33, 0x34, 0x99,
0x99, 0x6d, 0x16, 0x33, 0x00, 0x08, 0x34, 0x99, 0x99, 0x7c, 0x06, 0x33,
0x02, 0xa6, 0x1c, 0x99, 0x00, 0x12, 0x97, 0xa3, 0x33, 0x33, 0xc8, 0x99,
0x96, 0x44, 0xd3, 0x00, 0x0e, 0x33, 0x00, 0x0e, 0x3d, 0x79, 0x99, 0x76,
0x4b, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x33, 0x33, 0x3d, 0x84,
0x44, 0xc3, 0x12, 0x33, 0x00, 0x08, 0xdc, 0x44, 0x4a, 0xd3, 0x12, 0x33,
0x00, 0x08, 0x3d, 0xa4, 0x44, 0xd3, 0x08, 0x33, 0x02, 0xc8, 0x06, 0x44,
0x02, 0xd3, 0x10, 0x33, 0x02, 0xd4, 0x06, 0x44, 0x00, 0x0c, 0xa3, 0x33,
0x38, 0x44, 0x44, 0x4d, 0x16, 0x33, 0x00, 0x08, 0x38, 0x44, 0x44, 0x4c,
0x06, 0x33, 0x02, 0x3d, 0x02, 0xc4, 0x1c, 0x44, 0x00, 0x0e, 0xa3, 0x33,
0x33, 0x3d, 0x84, 0x44, 0xc3, 0x00, 0x12, 0x33, 0x00, 0x0c, 0xdc, 0x44,
0x4a, 0xd3, 0x33, 0x33, 0x00, 0x00, 0xe6, 0x33, 0x00, 0x00, 0xe6, 0x33,
0x00, 0x00, 0xe6, 0x33, 0x00, 0x00, 0xe6, 0x33, 0x00, 0x00, 0xe6, 0x33,
0x00, 0x00, 0x00, 0x1e, 0x33, 0x20, 0x00, 0x23, 0x30, 0x00, 0x13, 0x31,
0x00, 0x02, 0x33, 0x00, 0x01, 0x33, 0x32, 0x00, 0x08, 0x00, 0x00, 0x26,
0x13, 0x31, 0x00, 0x02, 0x33, 0x00, 0x01, 0x33, 0x00, 0x00, 0x13, 0x33,
0x00, 0x00, 0x13, 0x32, 0x00, 0x00, 0x23, 0x00, 0x24, 0x33, 0x00, 0x06,
0x32, 0x00, 0x02, 0x00, 0x08, 0x33, 0x02, 0x32, 0x06, 0x00, 0x00, 0x30,
0x01, 0x33, 0x31, 0x00, 0x02, 0x33, 0x00, 0x01, 0x33, 0x33, 0x32, 0x00,
0x02, 0x33, 0x33, 0x30, 0x00, 0x13, 0x32, 0x00, 0x02, 0x33, 0x00, 0x01,
0x08, 0x33, 0x00, 0x10, 0x30, 0x00, 0x13, 0x31, 0x00, 0x02, 0x33, 0x30,
0x08, 0x00, 0x00, 0x10, 0x23, 0x30, 0x00, 0x13, 0x31, 0x00, 0x02, 0x33,
0x00, 0x00, 0x00, 0x20, 0x33, 0x20, 0x11, 0x13, 0x30, 0x11, 0x03, 0x31,
0x11, 0x02, 0x33, 0x01, 0x10, 0x33, 0x10, 0x10, 0x06, 0x00, 0x00, 0x26,
0x03, 0x31, 0x11, 0x02, 0x33, 0x01, 0x10, 0x33, 0x01, 0x11, 0x03, 0x33,
0x01, 0x11, 0x13, 0x32, 0x01, 0x11, 0x23, 0x00, 0x24, 0x33, 0x00, 0x06,
0x32, 0x01, 0x11, 0x00, 0x08, 0x33, 0x00, 0x38, 0x10, 0x10, 0x00, 0x11,
0x11, 0x03, 0x31, 0x11, 0x02, 0x33, 0x01, 0x10, 0x33, 0x33, 0x32, 0x01,
0x11, 0x33, 0x33, 0x30, 0x11, 0x03, 0x32, 0x01, 0x11, 0x33, 0x01, 0x10,
0x08, 0x33, 0x00, 0x12, 0x30, 0x11, 0x03, 0x31, 0x11, 0x02, 0x33, 0x00,
0x10, 0x00, 0x06, 0x00, 0x00, 0x10, 0x23, 0x30, 0x11, 0x03, 0x31, 0x11,
0x02, 0x33, 0x00, 0x00, 0x00, 0x22, 0x33, 0x20, 0x11, 0x13, 0x30, 0x11,
0x03, 0x31, 0x11, 0x02, 0x33, 0x01, 0x10, 0x33, 0x11, 0x10, 0x23, 0x00,
0x06, 0x33, 0x00, 0x24, 0x31, 0x11, 0x02, 0x33, 0x01, 0x10, 0x33, 0x01,
0x11, 0x13, 0x33, 0x01, 0x10, 0x13, 0x32, 0x01, 0x11, 0x23, 0x24, 0x33,
0x00, 0x06, 0x32, 0x01, 0x11, 0x00, 0x08, 0x33, 0x00, 0x38, 0x11, 0x10,
0x23, 0x31, 0x11, 0x03, 0x31, 0x11, 0x02, 0x33, 0x01, 0x10, 0x33, 0x33,
0x32, 0x01, 0x11, 0x33, 0x33, 0x30, 0x11, 0x03, 0x32, 0x01, 0x11, 0x33,
0x01, 0x10, 0x08, 0x33, 0x00, 0x12, 0x30, 0x11, 0x03, 0x31, 0x11, 0x02,
0x33, 0x01, 0x10, 0x00, 0x08, 0x33, 0x00, 0x0e, 0x30, 0x11, 0x03, 0x31,
0x11, 0x02, 0x33, 0x00, 0x00, 0x00, 0x00, 0x22, 0x33, 0x20, 0x11, 0x23,
0x30, 0x11, 0x03, 0x31, 0x11, 0x12, 0x33, 0x01, 0x10, 0x33, 0x11, 0x10,
0x23, 0x00, 0x06, 0x33, 0x00, 0x28, 0x31, 0x11, 0x12, 0x33, 0x01, 0x00,
0x33, 0x01, 0x11, 0x11, 0x00, 0x01, 0x12, 0x33, 0x32, 0x01, 0x11, 0x11,
0x00, 0x23, 0x20, 0x33, 0x00, 0x06, 0x32, 0x01, 0x12, 0x00, 0x08, 0x33,
0x00, 0x38, 0x11, 0x10, 0x23, 0x30, 0x11, 0x03, 0x31, 0x11, 0x12, 0x33,
0x01, 0x00, 0x33, 0x33, 0x32, 0x01, 0x11, 0x33, 0x33, 0x30, 0x11, 0x13,
0x32, 0x01, 0x11, 0x33, 0x01, 0x11, 0x08, 0x33, 0x00, 0x12, 0x30, 0x11,
0x03, 0x31, 0x11, 0x02, 0x33, 0x01, 0x10, 0x00, 0x08, 0x33, 0x00, 0x0e,
0x30, 0x11, 0x03, 0x31, 0x11, 0x02, 0x33, 0x00, 0x00, 0x00, 0x00, 0x22,
0x33, 0x20, 0x11, 0x11, 0x00, 0x11, 0x03, 0x31, 0x11, 0x11, 0x00, 0x01,
0x10, 0x33, 0x11, 0x10, 0x23, 0x00, 0x06, 0x33, 0x00, 0x10, 0x31, 0x11,
0x11, 0x00, 0x01, 0x13, 0x33, 0x01, 0x08, 0x11, 0x00, 0x10, 0x12, 0x33,
0x32, 0x01, 0x11, 0x11, 0x10, 0x23, 0x20, 0x33, 0x00, 0x60, 0x32, 0x01,
0x11, 0x10, 0x00, 0x03, 0x33, 0x11, 0x10, 0x23, 0x30, 0x11, 0x03, 0x31,
0x11, 0x12, 0x22, 0x01, 0x02, 0x33, 0x33, 0x32, 0x01, 0x11, 0x33, 0x33,
0x30, 0x11, 0x12, 0x21, 0x01, 0x11, 0x33, 0x01, 0x11, 0x22, 0x22, 0x23,
0x33, 0x30, 0x11, 0x12, 0x21, 0x11, 0x02, 0x33, 0x01, 0x10, 0x08, 0x33,
0x00, 0x0e, 0x30, 0x11, 0x12, 0x21, 0x10, 0x13, 0x33, 0x00, 0x00, 0x00,
0x00, 0x22, 0x33, 0x20, 0x11, 0x00, 0x11, 0x11, 0x03, 0x31, 0x11, 0x00,
0x01, 0x11, 0x10, 0x33, 0x11, 0x10, 0x23, 0x00, 0x06, 0x33, 0x00, 0x28,
0x31, 0x11, 0x00, 0x01, 0x11, 0x13, 0x33, 0x01, 0x11, 0x00, 0x01, 0x11,
0x12, 0x33, 0x32, 0x01, 0x11, 0x00, 0x00, 0x23, 0x20, 0x33, 0x00, 0x60,
0x32, 0x01, 0x10, 0x01, 0x11, 0x12, 0x33, 0x11, 0x10, 0x23, 0x30, 0x11,
0x03, 0x31, 0x11, 0x10, 0x10, 0x11, 0x13, 0x33, 0x33, 0x32, 0x01, 0x11,
0x33, 0x33, 0x30, 0x11, 0x10, 0x10, 0x11, 0x11, 0x33, 0x01, 0x11, 0x01,
0x00, 0x01, 0x23, 0x30, 0x11, 0x00, 0x10, 0x11, 0x02, 0x33, 0x01, 0x10,
0x08, 0x33, 0x00, 0x0e, 0x30, 0x11, 0x00, 0x10, 0x11, 0x23, 0x33, 0x00,
0x00, 0x00, 0x00, 0x22, 0x33, 0x20, 0x11, 0x13, 0x31, 0x11, 0x03, 0x31,
0x11, 0x02, 0x33, 0x11, 0x10, 0x33, 0x11, 0x10, 0x23, 0x00, 0x06, 0x33,
0x00, 0x24, 0x31, 0x11, 0x02, 0x33, 0x11, 0x10, 0x33, 0x01, 0x11, 0x03,
0x33, 0x11, 0x11, 0x13, 0x32, 0x01, 0x11, 0x23, 0x24, 0x33, 0x00, 0x60,
0x32, 0x01, 0x11, 0x33, 0x11, 0x10, 0x33, 0x11, 0x10, 0x23, 0x30, 0x11,
0x03, 0x31, 0x11, 0x01, 0x22, 0x11, 0x12, 0x33, 0x33, 0x32, 0x01, 0x11,
0x33, 0x33, 0x30, 0x11, 0x02, 0x22, 0x11, 0x11, 0x33, 0x01, 0x10, 0x22,
0x21, 0x11, 0x13, 0x30, 0x11, 0x02, 0x21, 0x11, 0x02, 0x33, 0x01, 0x10,
0x08, 0x33, 0x00, 0x0e, 0x30, 0x11, 0x02, 0x21, 0x11, 0x23, 0x33, 0x00,
0x00, 0x00, 0x00, 0x22, 0x33, 0x20, 0x11, 0x13, 0x30, 0x11, 0x03, 0x31,
0x11, 0x02, 0x33, 0x01, 0x10, 0x33, 0x11, 0x10, 0x23, 0x00, 0x06, 0x33,
0x00, 0x24, 0x31, 0x11, 0x02, 0x33, 0x01, 0x10, 0x33, 0x01, 0x11, 0x13,
0x33, 0x01, 0x11, 0x13, 0x32, 0x01, 0x11, 0x23, 0x24, 0x33, 0x00, 0x60,
0x32, 0x01, 0x11, 0x33, 0x01, 0x10, 0x33, 0x11, 0x11, 0x23, 0x30, 0x11,
0x03, 0x31, 0x11, 0x12, 0x33, 0x11, 0x10, 0x33, 0x33, 0x32, 0x01, 0x11,
0x33, 0x33, 0x30, 0x11, 0x13, 0x32, 0x11, 0x11, 0x33, 0x01, 0x11, 0x33,
0x21, 0x11, 0x13, 0x30, 0x11, 0x03, 0x31, 0x11, 0x02, 0x33, 0x01, 0x10,
0x08, 0x33, 0x00, 0x0e, 0x30, 0x11, 0x03, 0x31, 0x11, 0x02, 0x33, 0x00,
0x00, 0x00, 0x00, 0x22, 0x33, 0x20, 0x11, 0x13, 0x30, 0x11, 0x03, 0x31,
0x11, 0x12, 0x33, 0x01, 0x00, 0x33, 0x11, 0x11, 0x23, 0x00, 0x06, 0x33,
0x00, 0x2c, 0x31, 0x11, 0x02, 0x33, 0x01, 0x10, 0x33, 0x01, 0x11, 0x11,
0x00, 0x01, 0x10, 0x13, 0x32, 0x01, 0x11, 0x11, 0x00, 0x00, 0x01, 0x23,
0x1c, 0x33, 0x00, 0x60, 0x32, 0x01, 0x12, 0x33, 0x01, 0x00, 0x33, 0x11,
0x11, 0x22, 0x20, 0x11, 0x03, 0x31, 0x11, 0x12, 0x22, 0x01, 0x10, 0x33,
0x33, 0x32, 0x01, 0x12, 0x33, 0x33, 0x30, 0x11, 0x12, 0x21, 0x01, 0x11,
0x33, 0x01, 0x11, 0x22, 0x10, 0x11, 0x13, 0x30, 0x11, 0x12, 0x21, 0x11,
0x02, 0x33, 0x01, 0x11, 0x08, 0x33, 0x00, 0x0e, 0x30, 0x11, 0x03, 0x31,
0x11, 0x02, 0x33, 0x00, 0x00, 0x00, 0x00, 0x38, 0x33, 0x20, 0x11, 0x13,
0x30, 0x11, 0x03, 0x32, 0x11, 0x11, 0x00, 0x01, 0x02, 0x33, 0x21, 0x11,
0x10, 0x00, 0x00, 0x13, 0x31, 0x11, 0x02, 0x33, 0x01, 0x10, 0x33, 0x01,
0x08, 0x11, 0x00, 0x08, 0x12, 0x33, 0x33, 0x21, 0x08, 0x11, 0x02, 0x10,
0x02, 0x23, 0x1c, 0x33, 0x00, 0x0e, 0x32, 0x01, 0x11, 0x10, 0x01, 0x02,
0x33, 0x00, 0x06, 0x11, 0x00, 0x62, 0x01, 0x10, 0x03, 0x31, 0x11, 0x11,
0x10, 0x11, 0x00, 0x33, 0x10, 0x00, 0x01, 0x11, 0x10, 0x13, 0x30, 0x11,
0x11, 0x10, 0x11, 0x01, 0x33, 0x01, 0x11, 0x11, 0x01, 0x10, 0x13, 0x30,
0x11, 0x11, 0x00, 0x10, 0x02, 0x33, 0x01, 0x11, 0x10, 0x00, 0x00, 0x23,
0x30, 0x11, 0x03, 0x31, 0x11, 0x02, 0x33, 0x00, 0x00, 0x00, 0x00, 0x12,
0x33, 0x20, 0x00, 0x13, 0x31, 0x00, 0x03, 0x33, 0x20, 0x00, 0x06, 0x00,
0x00, 0x06, 0x13, 0x33, 0x32, 0x00, 0x08, 0x00, 0x00, 0x12, 0x03, 0x32,
0x00, 0x02, 0x33, 0x10, 0x00, 0x33, 0x10, 0x00, 0x08, 0x00, 0x00, 0x08,
0x02, 0x33, 0x33, 0x30, 0x0a, 0x00, 0x02, 0x23, 0x1c, 0x33, 0x02, 0x32,
0x08, 0x00, 0x00, 0x06, 0x03, 0x33, 0x32, 0x00, 0x06, 0x00, 0x00, 0x06,
0x01, 0x33, 0x32, 0x00, 0x08, 0x00, 0x00, 0x06, 0x13, 0x33, 0x20, 0x00,
0x08, 0x00, 0x00, 0x06, 0x03, 0x33, 0x10, 0x00, 0x06, 0x00, 0x00, 0x06,
0x23, 0x33, 0x10, 0x00, 0x06, 0x00, 0x00, 0x06, 0x02, 0x33, 0x33, 0x00,
0x08, 0x00, 0x00, 0x06, 0x23, 0x33, 0x30, 0x00, 0x08, 0x00, 0x00, 0x10,
0x23, 0x31, 0x00, 0x03, 0x32, 0x00, 0x02, 0x33, 0x00, 0x00, 0xe6, 0x33,
0x00, 0x00, 0xe6, 0x33, 0x00, 0x00, 0xe6, 0x33, 0x00, 0x00, 0xe6, 0x33,
0x00, 0x01};
unsigned int splash_new__new_t_len = 3854;
+1 -1
View File
@@ -76,7 +76,7 @@ __attribute__((section(".external_app.app_blespam.application_information"), use
/*.icon_color = */ ui::Color::yellow().v,
/*.menu_location = */ app_location_t::TX,
/*.m4_app_tag = portapack::spi_flash::image_tag_afsk_rx */ {'P', 'B', 'T', 'T'},
/*.m4_app_tag = portapack::spi_flash::image_tag_btle_tx */ {'P', 'B', 'T', 'T'},
/*.m4_app_offset = */ 0x00000000, // will be filled at compile time
};
}
+10
View File
@@ -88,6 +88,14 @@ set(EXTCPPSRC
#adsbtx
external/adsbtx/main.cpp
external/adsbtx/ui_adsb_tx.cpp
#morse_tx
external/morse_tx/main.cpp
external/morse_tx/ui_morse.cpp
#sstvtx
external/sstvtx/main.cpp
external/sstvtx/ui_sstvtx.cpp
)
set(EXTAPPLIST
@@ -112,4 +120,6 @@ set(EXTAPPLIST
tpmsrx
protoview
adsbtx
morse_tx
sstvtx
)
+16
View File
@@ -44,6 +44,8 @@ MEMORY
ram_external_app_tpmsrx(rwx) : org = 0xADC30000, len = 32k
ram_external_app_protoview(rwx) : org = 0xADC40000, len = 32k
ram_external_app_adsbtx(rwx) : org = 0xADC50000, len = 32k
ram_external_app_morse_tx(rwx) : org = 0xADC60000, len = 32k
ram_external_app_sstvtx(rwx) : org = 0xADC70000, len = 32k
}
SECTIONS
@@ -176,4 +178,18 @@ SECTIONS
} > ram_external_app_adsbtx
.external_app_morse_tx : ALIGN(4) SUBALIGN(4)
{
KEEP(*(.external_app.app_morse_tx.application_information));
*(*ui*external_app*morse_tx*);
} > ram_external_app_morse_tx
.external_app_sstvtx : ALIGN(4) SUBALIGN(4)
{
KEEP(*(.external_app.app_sstvtx.application_information));
*(*ui*external_app*sstvtx*);
} > ram_external_app_sstvtx
}
+82
View File
@@ -0,0 +1,82 @@
/*
* Copyright (C) 2023 Bernd Herzog
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "ui.hpp"
#include "ui_morse.hpp"
#include "ui_navigation.hpp"
#include "external_app.hpp"
namespace ui::external_app::morse_tx {
void initialize_app(ui::NavigationView& nav) {
nav.push<MorseView>();
}
} // namespace ui::external_app::morse_tx
extern "C" {
__attribute__((section(".external_app.app_morse_tx.application_information"), used)) application_information_t _application_information_morse_tx = {
/*.memory_location = */ (uint8_t*)0x00000000,
/*.externalAppEntry = */ ui::external_app::morse_tx::initialize_app,
/*.header_version = */ CURRENT_HEADER_VERSION,
/*.app_version = */ VERSION_MD5,
/*.app_name = */ "Morse",
/*.bitmap_data = */ {
0x00,
0x00,
0xFE,
0x7F,
0xFF,
0xFF,
0xBB,
0xD0,
0xFF,
0xFF,
0xFF,
0xFF,
0x0B,
0xE1,
0xFF,
0xFF,
0xFF,
0xFF,
0xEB,
0xD0,
0xFF,
0xFF,
0xFE,
0x7F,
0x70,
0x00,
0x30,
0x00,
0x10,
0x00,
0x00,
0x00,
},
/*.icon_color = */ ui::Color::green().v,
/*.menu_location = */ app_location_t::TX,
/*.m4_app_tag = portapack::spi_flash::image_tag_tones */ {'P', 'T', 'O', 'N'},
/*.m4_app_offset = */ 0x00000000, // will be filled at compile time
};
}
@@ -36,7 +36,7 @@ using namespace portapack;
using namespace morse;
using namespace hackrf::one;
namespace ui {
namespace ui::external_app::morse_tx {
static WORKING_AREA(ookthread_wa, 256);
@@ -194,7 +194,8 @@ void MorseView::set_foxhunt(size_t i) {
MorseView::MorseView(
NavigationView& nav)
: nav_(nav) {
baseband::run_image(portapack::spi_flash::image_tag_tones);
// baseband::run_image(portapack::spi_flash::image_tag_tones);
baseband::run_prepared_image(portapack::memory::map::m4_code.base());
add_children({&labels,
&checkbox_foxhunt,
@@ -284,4 +285,4 @@ MorseView::MorseView(
};
}
} /* namespace ui */
} // namespace ui::external_app::morse_tx
@@ -39,7 +39,7 @@
using namespace morse;
namespace ui {
namespace ui::external_app::morse_tx {
class MorseView : public View {
public:
@@ -179,6 +179,6 @@ class MorseView : public View {
}};
};
} /* namespace ui */
} // namespace ui::external_app::morse_tx
#endif /*__MORSE_TX_H__*/
+22 -5
View File
@@ -51,6 +51,7 @@ ProtoView::ProtoView(NavigationView& nav)
&field_frequency,
&labels,
&options_zoom,
&number_shift,
&button_reset,
&waveform,
&waveform2,
@@ -63,6 +64,11 @@ ProtoView::ProtoView(NavigationView& nav)
draw();
draw2();
};
number_shift.on_change = [this](int32_t value) {
waveform_shift = value;
draw();
draw2();
};
button_reset.on_select = [this](Button&) {
reset();
};
@@ -74,6 +80,8 @@ ProtoView::ProtoView(NavigationView& nav)
void ProtoView::reset() {
cnt = 0;
number_shift.set_value(0);
waveform_shift = 0;
for (uint16_t i = 0; i < MAXSIGNALBUFFER; i++) time_buffer[i] = 0;
needCntReset = false;
draw();
@@ -126,9 +134,19 @@ void ProtoView::draw() {
drawcnt = 0;
for (uint16_t i = 0; i < MAXDRAWCNT; i++) waveform_buffer[i] = 0; // reset
for (uint16_t i = 0; i < MAXSIGNALBUFFER; ++i) {
state = time_buffer[i] >= 0;
int32_t timeabs = state ? time_buffer[i] : -1 * time_buffer[i];
// add empty data for padding (so you can shift left/nagetive)
for (int32_t i = 0;
i < ((waveform_shift > 0) ? 0 : -waveform_shift) && drawcnt < MAXDRAWCNT; // this is for shift nagetive (left side)
++i) {
waveform_buffer[drawcnt++] = 0;
}
for (uint16_t i = ((waveform_shift < 0) ? -waveform_shift : 0); // this is for shift positive aka right side
i < MAXSIGNALBUFFER && drawcnt < MAXDRAWCNT; // prevent out of ranging
++i) {
uint16_t buffer_index = (i + waveform_shift + MAXSIGNALBUFFER) % MAXSIGNALBUFFER;
state = time_buffer[buffer_index] >= 0;
int32_t timeabs = state ? time_buffer[buffer_index] : -1 * time_buffer[buffer_index];
int32_t timesize = timeabs / zoom;
if (timesize == 0) {
remain += timeabs;
@@ -145,9 +163,8 @@ void ProtoView::draw() {
}
remain = 0;
lmax = 0;
for (int32_t ii = 0; ii < timesize; ++ii) {
for (int32_t ii = 0; ii < timesize && drawcnt < MAXDRAWCNT; ++ii) {
waveform_buffer[drawcnt++] = state;
if (drawcnt >= MAXDRAWCNT) return;
}
}
}
+16 -8
View File
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2017 Furrtek
* Copyright (C) 2024 HTotoo
*
* This file is part of PortaPack.
*
@@ -76,7 +75,8 @@ class ProtoView : public View {
{0 * 8, 0 * 16},
nav_};
Labels labels{
{{0 * 8, 1 * 16}, "Zoom: ", Theme::getInstance()->fg_light->foreground}};
{{0 * 8, 1 * 16}, "Zoom: ", Theme::getInstance()->fg_light->foreground},
{{0 * 8, 2 * 16}, "Shift: ", Theme::getInstance()->fg_light->foreground}};
OptionsField options_zoom{
{7 * 8, 1 * 16},
@@ -92,12 +92,19 @@ class ProtoView : public View {
{"500", 500},
{"1000", 1000}}};
NumberField number_shift{
{7 * 8, 2 * 16},
5,
{-MAXSIGNALBUFFER, MAXSIGNALBUFFER},
1,
' '};
Button button_reset{
{screen_width - 12 * 8, 1 * 16, 96, 24},
LanguageHelper::currentMessages[LANG_RESET]};
Waveform waveform{
{0, 5 * 8, 240, 50},
{0, 8 * 8, 240, 50},
waveform_buffer,
0,
0,
@@ -105,7 +112,7 @@ class ProtoView : public View {
Theme::getInstance()->fg_yellow->foreground};
Waveform waveform2{
{0, 5 * 8 + 55, 240, 50},
{0, 8 * 8 + 55, 240, 50},
&waveform_buffer[MAXDRAWCNTPERWF],
0,
0,
@@ -113,7 +120,7 @@ class ProtoView : public View {
Theme::getInstance()->fg_yellow->foreground};
Waveform waveform3{
{0, 5 * 8 + 110, 240, 50},
{0, 8 * 8 + 110, 240, 50},
&waveform_buffer[MAXDRAWCNTPERWF * 2],
0,
0,
@@ -121,7 +128,7 @@ class ProtoView : public View {
Theme::getInstance()->fg_yellow->foreground};
Waveform waveform4{
{0, 5 * 8 + 165, 240, 50},
{0, 8 * 8 + 165, 240, 50},
&waveform_buffer[MAXDRAWCNTPERWF * 3],
0,
0,
@@ -131,6 +138,7 @@ class ProtoView : public View {
bool needCntReset = false;
int16_t zoom = 1; // one value in ms
int16_t waveform_shift = 0;
uint16_t cnt = 0; // pointer to next element
uint16_t drawcnt = 0; // pointer to draw next element
@@ -170,4 +178,4 @@ class ProtoView : public View {
} // namespace ui::external_app::protoview
#endif /*__UI_PROTOVIEW_H__*/
#endif /*__UI_PROTOVIEW_H__*/
+82
View File
@@ -0,0 +1,82 @@
/*
* Copyright (C) 2023 Bernd Herzog
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "ui.hpp"
#include "ui_sstvtx.hpp"
#include "ui_navigation.hpp"
#include "external_app.hpp"
namespace ui::external_app::sstvtx {
void initialize_app(ui::NavigationView& nav) {
nav.push<SSTVTXView>();
}
} // namespace ui::external_app::sstvtx
extern "C" {
__attribute__((section(".external_app.app_sstvtx.application_information"), used)) application_information_t _application_information_sstvtx = {
/*.memory_location = */ (uint8_t*)0x00000000,
/*.externalAppEntry = */ ui::external_app::sstvtx::initialize_app,
/*.header_version = */ CURRENT_HEADER_VERSION,
/*.app_version = */ VERSION_MD5,
/*.app_name = */ "SSTV",
/*.bitmap_data = */ {
0x00,
0x00,
0x00,
0x00,
0xFE,
0x7F,
0x03,
0xC0,
0x53,
0xD5,
0xAB,
0xCA,
0x53,
0xD5,
0xAB,
0xCA,
0x53,
0xD5,
0xAB,
0xCA,
0x53,
0xD5,
0x03,
0xC0,
0xFF,
0xFF,
0xFB,
0xD7,
0xFE,
0x7F,
0x00,
0x00,
},
/*.icon_color = */ ui::Color::green().v,
/*.menu_location = */ app_location_t::TX,
/*.m4_app_tag = portapack::spi_flash::image_tag_sstvtx */ {'P', 'S', 'T', 'X'},
/*.m4_app_offset = */ 0x00000000, // will be filled at compile time
};
}
@@ -31,7 +31,7 @@
using namespace portapack;
namespace ui {
namespace ui::external_app::sstvtx {
void SSTVTXView::focus() {
if (file_error)
@@ -232,7 +232,8 @@ SSTVTXView::SSTVTXView(
// Maybe this could be merged with proc_tones ? Pretty much the same except lots
// of different tones (256+)
baseband::run_image(portapack::spi_flash::image_tag_sstv_tx);
// baseband::run_image(portapack::spi_flash::image_tag_sstv_tx);
baseband::run_prepared_image(portapack::memory::map::m4_code.base());
add_children({&labels,
&options_bitmaps,
@@ -283,4 +284,4 @@ SSTVTXView::SSTVTXView(
};
}
} /* namespace ui */
} // namespace ui::external_app::sstvtx
@@ -38,7 +38,7 @@
using namespace sstv;
namespace ui {
namespace ui::external_app::sstvtx {
class SSTVTXView : public View {
public:
@@ -110,6 +110,6 @@ class SSTVTXView : public View {
}};
};
} /* namespace ui */
} /* namespace ui::external_app::sstvtx */
#endif /*__UI_SSTVTX_H__*/
+7 -6
View File
@@ -107,7 +107,7 @@ class TPMSAppView : public View {
private:
RxRadioState radio_state_{
314950000 /* frequency*/
314900000 /* frequency*/
,
1750000 /* bandwidth */,
2457600 /* sampling rate */
@@ -147,20 +147,21 @@ class TPMSAppView : public View {
// "315 MHz" TPMS sensors transmit at either 314.9 or 315 MHz but we should pick up either
OptionsField options_band{
{0 * 8, 0 * 16},
3,
5,
{
{"315", 314950000},
{"434", 433920000},
{"314.9", 314900000},
{"315.0", 315000000},
{"433.9", 433920000},
}};
OptionsField options_pressure{
{5 * 8, 0 * 16},
{6 * 8, 0 * 16},
3,
{{"kPa", 0},
{"PSI", 1}}};
OptionsField options_temperature{
{9 * 8, 0 * 16},
{10 * 8, 0 * 16},
2,
{{STR_DEGREES_C, 0},
{STR_DEGREES_F, 1}}};
+80 -18
View File
@@ -23,6 +23,7 @@
#include "string_format.hpp"
#include "file_path.hpp"
#include "metadata_file.hpp"
#include "flipper_subfile.hpp"
#include "portapack_persistent_memory.hpp"
using namespace portapack;
@@ -36,14 +37,14 @@ void WardriveMapView::focus() {
// needs to load on every map change, because won't store or draw all while marker is not in the current view.
// todo optimize this somehow
bool WardriveMapView::load_markers() {
uint16_t cnt = 0;
void WardriveMapView::load_markers() {
uint16_t displayed_cnt = 0;
uint16_t cnt = 0;
geomap.clear_markers();
// serach for files with geotag, and add it to geomap as marker with tag. limit to N bc of mem limit.
for (const auto& entry : std::filesystem::directory_iterator(captures_dir, u"*.txt")) {
if (std::filesystem::is_regular_file(entry.status())) {
if (displayed_cnt > 30) break;
if (markers_counted && displayed_cnt > ui::GeoMap::NumMarkerListElements) return; // only if not fist iteration, since then not counted all elements
std::filesystem::path pth = captures_dir;
pth += u"/" + entry.path();
auto metadata_path = get_metadata_path(pth);
@@ -51,23 +52,65 @@ bool WardriveMapView::load_markers() {
if (metadata) {
if (metadata.value().latitude != 0 && metadata.value().longitude != 0 && metadata.value().latitude < 400 && metadata.value().longitude < 400) {
if (first_init == false) {
// move map there before add, so will display this.
geopos.set_report_change(false);
geopos.set_lat(metadata.value().latitude);
geopos.set_lon(metadata.value().longitude);
geopos.set_report_change(true);
geomap.move(metadata.value().longitude, metadata.value().latitude);
first_init = true;
// skip nth
if (marker_start <= cnt) {
if (first_init == false) {
// move map there before add, so will display this.
geopos.set_report_change(false);
geopos.set_lat(metadata.value().latitude);
geopos.set_lon(metadata.value().longitude);
geopos.set_report_change(true);
geomap.move(metadata.value().longitude, metadata.value().latitude);
first_init = true;
}
GeoMarker tmp{metadata.value().latitude, metadata.value().longitude, 400, entry.path().filename().string()};
if (geomap.store_marker(tmp) == MapMarkerStored::MARKER_STORED) displayed_cnt++;
if (!markers_counted) marker_cntall++;
}
GeoMarker tmp{metadata.value().latitude, metadata.value().longitude, 400, entry.path().filename().string()};
if (geomap.store_marker(tmp) == MapMarkerStored::MARKER_STORED) displayed_cnt++;
cnt++;
}
}
}
}
return (cnt > 0);
// load flipper files too
for (const auto& entry : std::filesystem::directory_iterator(flippersub_dir, u"*.sub")) {
if (std::filesystem::is_regular_file(entry.status())) {
if (markers_counted && displayed_cnt > ui::GeoMap::NumMarkerListElements) return; // only if not fist iteration, since then not counted all elements
std::filesystem::path pth = flippersub_dir;
pth += u"/" + entry.path();
auto metadata = read_flippersub_file(pth);
if (metadata) {
if (metadata.value().latitude != 0 && metadata.value().longitude != 0 && metadata.value().latitude < 400 && metadata.value().longitude < 400) {
// skip nth
if (marker_start <= cnt) {
if (first_init == false) {
// move map there before add, so will display this.
geopos.set_report_change(false);
geopos.set_lat(metadata.value().latitude);
geopos.set_lon(metadata.value().longitude);
geopos.set_report_change(true);
geomap.move(metadata.value().longitude, metadata.value().latitude);
first_init = true;
}
GeoMarker tmp{metadata.value().latitude, metadata.value().longitude, 400, entry.path().filename().string()};
if (geomap.store_marker(tmp) == MapMarkerStored::MARKER_STORED) displayed_cnt++;
if (!markers_counted) marker_cntall++;
}
cnt++;
}
}
}
}
markers_counted = true;
// show / hide paginator buttons
btn_back.hidden((marker_start == 0) || (marker_cntall == 0));
btn_next.hidden(((marker_start + ui::GeoMap::NumMarkerListElements) >= marker_cntall) || (marker_cntall == 0));
// update text
text_info.set(to_string_dec_uint(marker_start + 1) + " - " + to_string_dec_uint(displayed_cnt + marker_start) + " / " + to_string_dec_uint(marker_cntall));
set_dirty();
return;
}
WardriveMapView::WardriveMapView(NavigationView& nav)
@@ -75,7 +118,9 @@ WardriveMapView::WardriveMapView(NavigationView& nav)
add_children({&text_info,
&geomap,
&geopos,
&text_notfound});
&text_notfound,
&btn_back,
&btn_next});
geomap.set_mode(DISPLAY);
geomap.set_manual_panning(false);
@@ -100,21 +145,38 @@ WardriveMapView::WardriveMapView(NavigationView& nav)
load_markers();
geomap.set_dirty();
};
text_notfound.hidden(true);
geomap.init();
// load markers
if (load_markers()) {
load_markers();
if (marker_cntall > 0) {
text_notfound.hidden(true);
geomap.set_dirty();
} else {
geomap.hidden(true);
geopos.hidden(true);
text_notfound.hidden(false);
text_info.hidden(true);
}
// never move this before the first load() bc that will mess load up
geomap.on_move = [this](float lon, float lat) {
(void)lon;
(void)lat;
load_markers();
};
btn_back.on_select = [this, &nav](Button&) {
if (marker_start - ui::GeoMap::NumMarkerListElements >= 0)
marker_start = marker_start - ui::GeoMap::NumMarkerListElements;
else
marker_start = 0;
load_markers();
};
btn_next.on_select = [this, &nav](Button&) {
if (marker_start + ui::GeoMap::NumMarkerListElements <= marker_cntall)
marker_start = marker_start + ui::GeoMap::NumMarkerListElements;
else
marker_start = marker_cntall - ui::GeoMap::NumMarkerListElements;
load_markers();
};
}
WardriveMapView::~WardriveMapView() {
+12 -10
View File
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2017 Furrtek
* Copyright (C) 2024 HTotoo
*
* This file is part of PortaPack.
*
@@ -20,10 +19,6 @@
* Boston, MA 02110-1301, USA.
*/
// Code from https://github.com/Flipper-XFW/Xtreme-Apps/tree/04c3a60093e2c2378e79498b4505aa8072980a42/ble_spam/protocols
// Thanks for the work of the original creators!
// Saying thanks in the main view!
#ifndef __UI_WARDRIVEMAP_H__
#define __UI_WARDRIVEMAP_H__
@@ -50,22 +45,29 @@ class WardriveMapView : public View {
};
private:
const std::filesystem::path flippersub_dir = u"subghz";
NavigationView& nav_;
Text text_info{{0 * 8, 0 * 8, 30 * 8, 16 * 1}, "All GEOTAG from CAPTURES"};
Text text_notfound{{0 * 8, 3 * 8, 30 * 8, 16 * 1}, "No GeoTagged captures found"};
Text text_info{{0 * 8, 0 * 8, 20 * 8, 16 * 1}, "0 / 30"};
Text text_notfound{{0 * 8, 0 * 8, 30 * 8, 16 * 1}, "No GeoTagged captures found"};
GeoPos geopos{
{0, 20},
GeoPos::alt_unit::METERS,
GeoPos::spd_unit::HIDDEN};
GeoMap geomap{{0, 75, 240, 320 - 75}};
Button btn_back{{22 * 8, 0 * 8, 3 * 8, 16}, "<-"};
Button btn_next{{26 * 8, 0 * 8, 3 * 8, 16}, "->"};
void on_gps(const GPSPosDataMessage* msg);
void on_orientation(const OrientationDataMessage* msg);
bool load_markers(); // returns true if any exists, false if none.
void load_markers(); // returns true if any exists, false if none.
bool first_init = false;
bool first_init = false; // to center map to first marker, before callback is set
bool markers_counted = false; // to iterate all files on first, but only on first.
uint16_t marker_start = 0; // for paginator, this will be the first displayed
uint16_t marker_cntall = 0; // all geotagged marker count
MessageHandlerRegistration message_handler_gps{
Message::ID::GPSPosData,
+117
View File
@@ -0,0 +1,117 @@
/*
* Copyright (C) 2024 HTotoo
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "flipper_subfile.hpp"
#include "convert.hpp"
#include "file_reader.hpp"
#include "string_format.hpp"
#include <string_view>
namespace fs = std::filesystem;
using namespace std::literals;
const std::string_view filetype_name = "Filetype"sv;
const std::string_view frequency_name = "Frequency"sv;
const std::string_view latitude_name = "Latitute"sv;
const std::string_view longitude_name = "Longitude"sv;
const std::string_view protocol_name = "Protocol"sv;
const std::string_view preset_name = "Preset"sv;
const std::string_view te_name = "TE"sv; // only in BinRAW
/*
Filetype: Flipper SubGhz Key File
Version: 1
Frequency: 433920000
Preset: FuriHalSubGhzPresetOok650Async
Latitute: nan
Longitude: nan
Protocol: BinRAW
Bit: 1730
TE: 495
Bit_RAW: 1730
Data_RAW: 02 10 84
te: is the quantization interval, in us.
bit: all bit counts in file.
bit_raw: the bits stored in the next data_raw. this 2 can repeat
data_raw: is an encoded sequence of durations, where each bit in the sequence encodes one TE interval: 1 - high level (there is a carrier), 0 - low (no carrier). For example, TE=100, Bit_RAW=8, Data_RAW=0x37 => 0b00110111, that is, -200 200 -100 300 will be transmitted
Filetype: Flipper SubGhz RAW File
Version: 1
Frequency: 433920000
Preset: FuriHalSubGhzPresetOok650Async
Protocol: RAW
RAW_Data: 5832 -12188 130 -162
raw_data- positive: carrier for n time, negative: no carrier for n time. (us)
*/
Optional<flippersub_metadata> read_flippersub_file(const fs::path& path) {
File f;
auto error = f.open(path);
if (error)
return {};
flippersub_metadata metadata{};
auto reader = FileLineReader(f);
for (const auto& line : reader) {
auto cols = split_string(line, ':');
if (cols.size() != 2)
continue; // Bad line.
if (cols[1].length() <= 1) continue;
std::string fixed = cols[1].data() + 1;
fixed = trim(fixed);
if (cols[0] == filetype_name) {
if (fixed != "Flipper SubGhz Key File" && fixed != "Flipper SubGhz RAW File") return {}; // not supported
} else if (cols[0] == frequency_name)
parse_int(fixed, metadata.center_frequency);
else if (cols[0] == latitude_name)
parse_float_meta(fixed, metadata.latitude);
else if (cols[0] == longitude_name)
parse_float_meta(fixed, metadata.longitude);
else if (cols[0] == protocol_name) {
if (fixed == "RAW") metadata.protocol = FLIPPER_PROTO_RAW;
if (fixed == "BinRAW") metadata.protocol = FLIPPER_PROTO_BINRAW;
} else if (cols[0] == te_name) {
metadata.te = atoi(fixed.c_str());
} else if (cols[0] == preset_name) {
if (fixed.find("FSK") != std::string::npos) {
metadata.preset = FLIPPER_PRESET_2FSK;
} else if (fixed.find("Ook") != std::string::npos) {
metadata.preset = FLIPPER_PRESET_OOK;
} else if (fixed.find("Custom") != std::string::npos) {
metadata.preset = FLIPPER_PRESET_CUSTOM;
}
} else
continue;
}
if (metadata.center_frequency == 0) return {}; // Parse failed.
return metadata;
}
+53
View File
@@ -0,0 +1,53 @@
/*
* Copyright (C) 2024 HTotoo
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef __FLIPPER_SUBFILE_HPP__
#define __FLIPPER_SUBFILE_HPP__
#include "metadata_file.hpp"
typedef enum : uint8_t {
FLIPPER_PROTO_UNSUPPORTED = 0,
FLIPPER_PROTO_RAW = 1,
FLIPPER_PROTO_BINRAW = 2
} FlipperProto;
typedef enum : uint8_t {
FLIPPER_PRESET_UNK = 0,
FLIPPER_PRESET_CUSTOM = 1,
FLIPPER_PRESET_OOK = 2,
FLIPPER_PRESET_2FSK = 3,
} FlipperPreset;
struct flippersub_metadata {
rf::Frequency center_frequency;
float latitude = 0;
float longitude = 0;
FlipperProto protocol = FLIPPER_PROTO_UNSUPPORTED;
FlipperPreset preset = FLIPPER_PRESET_UNK;
uint16_t te = 0;
};
Optional<flippersub_metadata> read_flippersub_file(const std::filesystem::path& path);
// Maybe sometime there will be a data part reader / converter
#endif // __FLIPPER_SUBFILE_HPP__
+1 -1
View File
@@ -52,7 +52,7 @@ void Tab::paint(Painter& painter) {
painter.fill_rectangle({rect.left(), rect.top(), rect.width() - 8, rect.height()}, color);
if (!highlighted())
painter.draw_hline({rect.left(), rect.top()}, rect.width() - 9, Theme::getInstance()->fg_light->foreground);
painter.draw_hline({rect.left(), rect.top()}, rect.width() - 9, Theme::getInstance()->bg_light->background);
painter.draw_bitmap(
{rect.right() - 8, rect.top()},
+6 -6
View File
@@ -55,7 +55,7 @@
#include "ui_level.hpp"
#include "ui_looking_glass_app.hpp"
#include "ui_mictx.hpp"
#include "ui_morse.hpp"
// #include "ui_morse.hpp" //moved to ext
// #include "ui_nrf_rx.hpp" //moved to ext
// #include "ui_numbers.hpp"
// #include "ui_nuoptix.hpp"
@@ -74,7 +74,7 @@
#include "ui_sonde.hpp"
// #include "ui_spectrum_painter.hpp" //moved to ext app
#include "ui_ss_viewer.hpp"
#include "ui_sstvtx.hpp"
// #include "ui_sstvtx.hpp" //moved to ext
// #include "ui_test.hpp"
#include "ui_text_editor.hpp"
#include "ui_tone_search.hpp"
@@ -90,7 +90,7 @@
#include "ais_app.hpp"
#include "analog_audio_app.hpp"
// #include "analog_tv_app.hpp" //moved to ext
#include "ble_comm_app.hpp"
// #include "ble_comm_app.hpp"
#include "ble_rx_app.hpp"
#include "ble_tx_app.hpp"
#include "capture_app.hpp"
@@ -185,13 +185,13 @@ const NavigationView::AppList NavigationView::appList = {
{"aprstx", "APRS TX", TX, ui::Color::green(), &bitmap_icon_aprs, new ViewFactory<APRSTXView>()},
{"bht", "BHT Xy/EP", TX, ui::Color::green(), &bitmap_icon_bht, new ViewFactory<BHTView>()},
{"bletx", "BLE Tx", TX, ui::Color::green(), &bitmap_icon_btle, new ViewFactory<BLETxView>()},
{"morse", "Morse", TX, ui::Color::green(), &bitmap_icon_morse, new ViewFactory<MorseView>()},
//{"morse", "Morse", TX, ui::Color::green(), &bitmap_icon_morse, new ViewFactory<MorseView>()}, //moved to ext
//{"nuoptixdtmf", "Nuoptix DTMF", TX, ui::Color::green(), &bitmap_icon_nuoptix, new ViewFactory<NuoptixView>()},
{"ooktx", "OOK", TX, ui::Color::yellow(), &bitmap_icon_remote, new ViewFactory<EncodersView>()},
{"pocsagtx", "POCSAG TX", TX, ui::Color::green(), &bitmap_icon_pocsag, new ViewFactory<POCSAGTXView>()},
{"rdstx", "RDS", TX, ui::Color::green(), &bitmap_icon_rds, new ViewFactory<RDSView>()},
{"soundbrd", "Soundbrd", TX, ui::Color::green(), &bitmap_icon_soundboard, new ViewFactory<SoundBoardView>()},
{"sstvtx", "SSTV", TX, ui::Color::green(), &bitmap_icon_sstv, new ViewFactory<SSTVTXView>()},
//{"sstvtx", "SSTV", TX, ui::Color::green(), &bitmap_icon_sstv, new ViewFactory<SSTVTXView>()}, //moved to ext
{"touchtune", "TouchTune", TX, ui::Color::green(), &bitmap_icon_touchtunes, new ViewFactory<TouchTunesView>()},
/* UTILITIES *************************************************************/
{"antennalength", "Antenna Length", UTILITIES, Color::green(), &bitmap_icon_tools_antenna, new ViewFactory<WhipCalcView>()},
@@ -1006,7 +1006,7 @@ BMPView::BMPView(NavigationView& nav) {
void BMPView::paint(Painter&) {
if (!portapack::display.drawBMP2({0, 0}, splash_dot_bmp))
portapack::display.drawBMP({(240 - 230) / 2, (320 - 50) / 2 - 10}, splash_bmp, false);
portapack::display.drawBMP({(240 - 230) / 2, (320 - 50) / 2 - 10}, splash_bmp, true);
}
/* NotImplementedView ****************************************************/
+6 -6
View File
@@ -480,12 +480,6 @@ set(MODE_CPPSRC
DeclareTargets(PSIG siggen)
### SSTV TX
set(MODE_CPPSRC
proc_sstvtx.cpp
)
DeclareTargets(PSTX sstvtx)
### Tones
@@ -650,6 +644,12 @@ set(MODE_CPPSRC
DeclareTargets(PPVW protoview)
### SSTV TX
set(MODE_CPPSRC
proc_sstvtx.cpp
)
DeclareTargets(PSTX sstvtx)
### TPMS
+32 -5
View File
@@ -23,16 +23,16 @@ bool BatteryManagement::calcOverride = false;
void BatteryManagement::detect() {
// try to detect supported modules
detected_ = BATT_NONE;
if (battery_max17055.detect()) {
battery_max17055.init();
detected_ = BATT_MAX17055;
return;
}
if (battery_ads1110.detect()) {
battery_ads1110.init();
detected_ = BATT_ADS1110;
return;
}
if (battery_max17055.detect()) {
// battery_max17055.init(); //detect will call this on each "re detect"
detected_ = BATT_MAX17055;
return;
}
// add new supported module detect + init here
@@ -51,6 +51,13 @@ void BatteryManagement::init(bool override) {
create_thread();
}
bool BatteryManagement::reset_learned() {
if (detected_ == BATT_MAX17055) {
return battery_max17055.reset_learned();
}
return false;
}
// set if the default percentage calculation should be overrided by voltage based one
void BatteryManagement::set_calc_override(bool override) {
calcOverride = override;
@@ -90,6 +97,26 @@ void BatteryManagement::getBatteryInfo(uint8_t& valid_mask, uint8_t& batteryPerc
(void)current;
}
uint16_t BatteryManagement::get_cycles() {
if (detected_ == BATT_MAX17055) {
return (uint16_t)battery_max17055.getValue("Cycles");
}
return 0;
}
float BatteryManagement::get_tte() {
if (detected_ == BATT_MAX17055) {
return battery_max17055.getValue("TTE");
}
return 0;
}
float BatteryManagement::get_ttf() {
if (detected_ == BATT_MAX17055) {
return battery_max17055.getValue("TTF");
}
return 0;
}
uint16_t BatteryManagement::read_register(const uint8_t reg) {
if (detected_ == BATT_MAX17055) {
return battery_max17055.read_register(reg);
+6
View File
@@ -44,6 +44,8 @@ class BatteryManagement {
BATT_VALID_VOLTAGE = 1,
BATT_VALID_CURRENT = 2,
BATT_VALID_PERCENT = 4,
BATT_VALID_CYCLES = 8,
BATT_VALID_TTEF = 16,
};
static void init(bool override = false);
static void detect();
@@ -56,6 +58,10 @@ class BatteryManagement {
static bool write_register(const uint8_t reg, const uint16_t value);
static void set_calc_override(bool override);
static uint8_t calc_percent_voltage(uint16_t); // calculates battery percentage from the voltage
static bool reset_learned(); // resets the ic's learned parameters
static uint16_t get_cycles();
static float get_tte();
static float get_ttf();
private:
static void create_thread();
+4 -4
View File
@@ -359,12 +359,12 @@ void ILI9341::drawBMP(const ui::Point p, const uint8_t* bitmap, const bool trans
data_idx = bmp_header->image_data;
const bmp_palette_t* bmp_palette = (const bmp_palette_t*)&bitmap[bmp_header->BIH_size + 14];
// Convert palette and find pure magenta index (alpha color key)
// Convert palette and find pure magenta index (alpha color key) rgb dec(41,24,22)
for (c = 0; c < 16; c++) {
palette[c] = ui::Color(bmp_palette->color[c].R, bmp_palette->color[c].G, bmp_palette->color[c].B);
if ((bmp_palette->color[c].R == 0xFF) &&
(bmp_palette->color[c].G == 0x00) &&
(bmp_palette->color[c].B == 0xFF)) transp_idx = c;
if ((bmp_palette->color[c].R == 0x29) &&
(bmp_palette->color[c].G == 0x18) &&
(bmp_palette->color[c].B == 0x16)) transp_idx = c;
}
if (!transparency) {
File diff suppressed because it is too large Load Diff
+39 -25
View File
@@ -83,7 +83,7 @@
// Define Termination Current
#ifndef __MAX17055_Termination_Current__
#define __MAX17055_Termination_Current__ 0.1 // Termination Current
#define __MAX17055_Termination_Current__ 200 // Termination Current
#endif
// Define Minimum Temperature
@@ -253,49 +253,63 @@ namespace max17055 {
using address_t = uint8_t;
struct RegisterEntry {
const char* name;
uint8_t address;
const char* type;
float scalar;
bool is_signed;
const char* unit;
bool abbr_units;
int resolution;
bool is_user;
bool is_save_restore;
bool is_nv;
uint16_t por_data;
bool is_read_only;
};
class MAX17055 {
public:
constexpr MAX17055(I2C& bus, const I2C::address_t bus_address)
: bus(bus), bus_address(bus_address), detected_(false) {}
static const RegisterEntry entries[];
static constexpr size_t entries_count = 144;
uint16_t read_register(const uint8_t reg);
bool write_register(const uint8_t reg, const uint16_t value);
void init();
bool detect();
bool isDetected() const { return detected_; }
uint16_t readVoltage();
uint8_t readPercentage();
void getBatteryInfo(uint8_t& valid_mask, uint8_t& batteryPercentage, uint16_t& voltage, int32_t& current);
bool reset_learned();
uint16_t instantVoltage(void);
uint16_t averageVoltage(void);
uint16_t emptyVoltage(void);
uint16_t recoveryVoltage(void);
float getValue(const char* entityName);
uint16_t averageMVoltage(void);
int32_t instantCurrent(void);
int32_t averageCurrent(void);
uint16_t stateOfCharge(void);
uint16_t averageStateOfCharge(void);
uint16_t instantCapacity(void);
uint16_t designCapacity(void);
uint16_t fullCapacity(void);
uint16_t icTemperature(void);
uint16_t timeToEmpty(void);
uint16_t timeToFull(void);
uint16_t batteryAge(void);
uint16_t chargeCycle(void);
bool statusControl(const uint8_t _Status);
void statusClear(void);
uint16_t chargeTerminationCurrent(void);
uint16_t read_register(const uint8_t reg);
bool write_register(const uint8_t reg, const uint16_t value);
private:
I2C& bus;
const I2C::address_t bus_address;
bool detected_ = false;
bool readRegister(uint8_t reg, uint16_t& value);
bool readMultipleRegister(uint8_t reg, uint8_t* data, uint8_t length, bool endTransmission);
bool writeMultipleRegister(uint8_t reg, const uint8_t* data, uint8_t length);
const RegisterEntry* findEntry(const char* name) const;
bool needsInitialization();
void partialInit();
bool statusControl(const uint8_t _Status);
bool statusClear();
bool full_reset_and_init();
bool soft_reset();
bool clear_por();
bool initialize_custom_parameters();
bool load_custom_parameters();
bool setEmptyVoltage(uint16_t _Empty_Voltage);
bool setRecoveryVoltage(uint16_t _Recovery_Voltage);
@@ -953,18 +953,15 @@ bool ui_hide_sd_card() {
bool ui_hide_fake_brightness() {
return data->ui_config2.hide_fake_brightness;
}
bool ui_hide_numeric_battery() {
return data->ui_config2.hide_numeric_battery;
}
bool ui_hide_battery_icon() {
return data->ui_config2.hide_battery_icon;
}
uint8_t ui_theme_id() {
return data->ui_config2.theme_id;
}
bool ui_override_batt_calc() {
return data->ui_config2.override_batt_calc;
}
+2 -2
View File
@@ -971,7 +971,7 @@ void Button::paint(Painter& painter) {
const Style paint_style = {style().font, bg, fg};
painter.draw_rectangle({r.location(), {r.size().width(), 1}}, Theme::getInstance()->fg_light->foreground);
painter.draw_rectangle({r.location(), {r.size().width(), 1}}, Theme::getInstance()->bg_light->background);
painter.draw_rectangle({r.location().x(), r.location().y() + r.size().height() - 1, r.size().width(), 1}, Theme::getInstance()->bg_dark->background);
painter.draw_rectangle({r.location().x() + r.size().width() - 1, r.location().y(), 1, r.size().height()}, Theme::getInstance()->bg_dark->background);
@@ -1311,7 +1311,7 @@ void NewButton::paint(Painter& painter) {
const auto r = screen_rect();
const Style style = paint_style();
painter.draw_rectangle({r.location(), {r.width(), 1}}, Theme::getInstance()->fg_light->foreground);
painter.draw_rectangle({r.location(), {r.width(), 1}}, Theme::getInstance()->bg_light->background);
painter.draw_rectangle({r.left(), r.top() + r.height() - 1, r.width(), 1}, Theme::getInstance()->bg_dark->background);
painter.draw_rectangle({r.left() + r.width() - 1, r.top(), 1, r.height()}, Theme::getInstance()->bg_dark->background);
+1
View File
@@ -0,0 +1 @@
bitmap is for icons, it's colorless and headless; splash and modal isn't using bitmap
+1
View File
@@ -0,0 +1 @@
bmp is for splash and modal warning, it contains color info and file header; icons isn't using bmp.
@@ -0,0 +1,49 @@
# copyleft zxkmm 2024
import os
import sys
def bmp_to_hex_cpp_arr(input_file, output_file):
with open(input_file, 'rb') as f:
data = f.read()
name_without_extension = os.path.splitext(os.path.basename(input_file))[0]
with open(output_file, 'w') as f:
f.write(f"// converted by bmp_to_hex_cpp_arr.py at the firmware/tools dir\n")
f.write(f"// fake transparent px should be the exact color rgb(255,0,255), then use true for the last arg "
f"when drawing bmp with the draw func\n")
f.write(f"\n")
f.write(f"const unsigned char {name_without_extension}[] = {{\n")
# idk about the clang-format rule, but the splash arr is 12 item per line. but other bmp arr is 2 item per line
for i in range(0, len(data), 12):
line = data[i:i + 12]
hex_values = [f"0x{byte:02x}" for byte in line]
f.write(f" {', '.join(hex_values)},\n")
# this is for remove last the extra comma
f.seek(f.tell() - 2, os.SEEK_SET)
f.truncate()
f.write("};\n")
f.write(f"unsigned int {name_without_extension}_len = {len(data)};\n")
print(f"done, outputted, pls clang-format yourself before commit (if necessary){output_file}")
if __name__ == "__main__":
if len(sys.argv) != 3:
print("usage: python bmp_to_hex_cpp_arr.py INPUTFILE OUTPUTFILE")
sys.exit(1)
input_file = sys.argv[1]
output_file = sys.argv[2]
bmp_to_hex_cpp_arr(input_file, output_file)
@@ -0,0 +1,51 @@
# copyleft zxkmm 2024
import sys
import re
def hex_cpp_arr_to_bmp(input_file, output_file):
with open(input_file, 'r') as f:
content = f.read()
# in the mayhem code some of them not const
array_name_const = re.search(r'const unsigned char (\w+)\[\]', content)
array_name_no_const = re.search(r'unsigned char (\w+)\[]', content)
if array_name_const or array_name_no_const:
if array_name_const:
array_name = array_name_const.group(1)
else:
array_name = array_name_no_const.group(1)
print(f"Array name: {array_name}")
else:
print("the file provided seems doesn't contains needed arr.")
return
hex_data = re.findall(r'0x[0-9A-Fa-f]{2}', content)
if not hex_data:
print("Error: No hex data found.")
return
binary_data = bytes([int(x, 16) for x in hex_data])
with open(output_file, 'wb') as f:
f.write(binary_data)
print(f"Done. Output file: {output_file}")
print(f"Array name: {array_name}")
print(f"Data length: {len(binary_data)} bytes")
if __name__ == "__main__":
if len(sys.argv) != 3:
print("usage: python hex_cpp_arr_to_bmp.py INPUTFILE OUTPUTFILE")
sys.exit(1)
input_file = sys.argv[1]
output_file = sys.argv[2]
hex_cpp_arr_to_bmp(input_file, output_file)