mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-09-14 10:39:30 +00:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 809abb6842 | |||
| 31082c63af | |||
| ff14008b43 | |||
| 1377516dce | |||
| 4162820409 | |||
| 4bbe1175c1 | |||
| ecd1a217d7 | |||
| 335cace137 | |||
| dbd708a1c7 | |||
| 4d842b5fae | |||
| e24f1b131d | |||
| 3f2c7351f1 | |||
| afc75f6cda | |||
| 69b17faddf | |||
| 2c118ae584 | |||
| 75c34747cb | |||
| 7754c0f37f | |||
| 37cc35d3c6 | |||
| 8a7aa9c0f8 | |||
| 22d6e34cd6 | |||
| 2229381ce3 | |||
| 4a63bdd7a0 |
@@ -2,6 +2,7 @@ name: Hardware / QC / QA / selling
|
||||
description: Issues that related with hardware, quality control, quality assurance, selling, etc.
|
||||
labels:
|
||||
- question
|
||||
- hardware problem
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
@@ -11,9 +12,6 @@ body:
|
||||
We would like to inform you that we can't provide much help regarding hardware/QC/QA/selling issues because we are not controlling various vendors/manufacturers, and also we are not profiting from you buying your device.
|
||||
|
||||
You are still welcome to ask, but please be aware that for this kind of issue, ask the seller would be the best option.
|
||||
|
||||
> [!IMPORTANT]
|
||||
If you are a seller/vendor and your customer has directed you to this page as a reference/evidence of a "broken device" or similar issue, please be aware that we are not providing any "official guarantee of a faulty device." We are only offering suggestions based on what the submitter has stated. We do not guarantee that the device is broken or anything else.
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
name: Hardware Issue Warning
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [labeled]
|
||||
|
||||
jobs:
|
||||
add-comment:
|
||||
if: github.event.label.name == 'hardware problem'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Add warning comment
|
||||
uses: peter-evans/create-or-update-comment@v3
|
||||
with:
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
body: |
|
||||
> [!IMPORTANT]
|
||||
If you are a seller/vendor and your customer has directed you to this page as a reference/evidence of a "broken device" or similar issue, please be aware that we are not providing any "official guarantee of a faulty device." We are only offering suggestions based on what the submitter has stated. We do not guarantee that the device is broken or anything else.
|
||||
@@ -0,0 +1,128 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at
|
||||
https://github.com/portapack-mayhem/mayhem-firmware/issues/new/.
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
||||
@@ -0,0 +1 @@
|
||||
Please see [How-to-collaborate](https://github.com/portapack-mayhem/mayhem-firmware/wiki/How-to-collaborate)
|
||||
@@ -9,7 +9,9 @@
|
||||
|
||||
This is a fork of the [Havoc](https://github.com/furrtek/portapack-havoc/) firmware, which itself was a fork of the [PortaPack](https://github.com/sharebrained/portapack-hackrf) firmware, an add-on for the [HackRF](http://greatscottgadgets.com/hackrf/). A fork is a derivate, in this case one that has extra features and fixes when compared to the older versions.
|
||||
|
||||
[<img src="https://github.com/user-attachments/assets/dea337ab-fb64-4a2a-b419-69afd272e815" height="400">](https://github.com/portapack-mayhem/mayhem-firmware/wiki/PortaPack-Versions#new-h4m-mayhem-edition) [<img src="https://camo.githubusercontent.com/5c1f1da0688240ac7b2ccca0c8dbfd1d73f2540741ad8b1828ba4d5ea68af248/68747470733a2f2f6769746875622d70726f64756374696f6e2d757365722d61737365742d3632313064662e73332e616d617a6f6e6177732e636f6d2f343339333937392f3239353533323731382d38653562363631632d663934362d346365652d386232642d3061363135663737313566342e706e67" height="400">](https://github.com/portapack-mayhem/mayhem-firmware/wiki/PortaPack-Versions#h2m-mayhem-edition)
|
||||
[<img src="https://github.com/user-attachments/assets/dea337ab-fb64-4a2a-b419-69afd272e815" height="310">](https://github.com/portapack-mayhem/mayhem-firmware/wiki/PortaPack-Versions#new-h4m-mayhem-edition)
|
||||
[<img src="https://camo.githubusercontent.com/5c1f1da0688240ac7b2ccca0c8dbfd1d73f2540741ad8b1828ba4d5ea68af248/68747470733a2f2f6769746875622d70726f64756374696f6e2d757365722d61737365742d3632313064662e73332e616d617a6f6e6177732e636f6d2f343339333937392f3239353533323731382d38653562363631632d663934362d346365652d386232642d3061363135663737313566342e706e67" height="310">](https://github.com/portapack-mayhem/mayhem-firmware/wiki/PortaPack-Versions#h2m-mayhem-edition)
|
||||
[<img src="https://camo.githubusercontent.com/c1f7dd1e7672324f60a513f0de23de76da6a669e63896a9de535d8c8093fc3c7/68747470733a2f2f7261772e6769746875622e636f6d2f7368617265627261696e65642f706f7274617061636b2d6861636b72662f6d61737465722f646f632f696d616765732f68617264776172652f706f7274617061636b5f68315f6f7065726174696e672e6a7067" height="310">]([https://github.com/portapack-mayhem/mayhem-firmware/wiki/PortaPack-Versions#h2m-mayhem-edition](https://github.com/portapack-mayhem/mayhem-firmware/wiki/PortaPack-Versions#h1r1r2))
|
||||
|
||||
# What is this?
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Please check [Intended-Use-and-Legality](https://github.com/portapack-mayhem/mayhem-firmware/wiki/)
|
||||
@@ -191,7 +191,6 @@ set(CPPSRC
|
||||
clock_manager.cpp
|
||||
core_control.cpp
|
||||
database.cpp
|
||||
de_bruijn.cpp
|
||||
rfm69.cpp
|
||||
event_m0.cpp
|
||||
file_reader.cpp
|
||||
@@ -294,7 +293,6 @@ set(CPPSRC
|
||||
apps/ui_flash_utility.cpp
|
||||
apps/ui_freqman.cpp
|
||||
apps/ui_iq_trim.cpp
|
||||
apps/ui_level.cpp
|
||||
apps/ui_looking_glass_app.cpp
|
||||
apps/ui_mictx.cpp
|
||||
apps/ui_modemsetup.cpp
|
||||
@@ -303,7 +301,6 @@ set(CPPSRC
|
||||
apps/ui_rds.cpp
|
||||
apps/ui_recon_settings.cpp
|
||||
apps/ui_recon.cpp
|
||||
# apps/ui_scanner.cpp
|
||||
apps/ui_sd_over_usb.cpp
|
||||
apps/ui_search.cpp
|
||||
apps/ui_settings.cpp
|
||||
|
||||
@@ -52,20 +52,20 @@ AMOptionsView::AMOptionsView(
|
||||
&zoom_config,
|
||||
});
|
||||
|
||||
zoom_config.on_change = [this, view](size_t, OptionsField::value_t n) {
|
||||
receiver_model.set_am_configuration(previous_filter_array_index + n);
|
||||
zoom_config.on_change = [this, view](size_t, OptionsField::value_t n) { // n , has two option values. when GUI =zoom+1 => (0), when GUI=zoom+2 (6)
|
||||
receiver_model.set_am_configuration(view->get_previous_AM_mode_option() + n); // n (0 or 6)
|
||||
view->set_zoom_factor(AM_MODULATION, n);
|
||||
view->set_previous_zoom_option(n);
|
||||
};
|
||||
|
||||
// restore zoom selection
|
||||
zoom_config.set_by_value(view->get_zoom_factor(AM_MODULATION));
|
||||
|
||||
freqman_set_bandwidth_option(AM_MODULATION, options_config); // adding the common message from freqman.cpp to the options_config
|
||||
options_config.set_by_value(receiver_model.am_configuration());
|
||||
freqman_set_bandwidth_option(AM_MODULATION, options_config); // freqman.cpp to the options_config, only allowing 5 modes freqman_bandwidths[AM] {"DSB 9k", 0}, {"DSB 6k", 1}, {"USB+3k", 2}, {"LSB-3k", 3}, {"CW", 4},
|
||||
options_config.set_by_value(receiver_model.am_configuration() - view->get_previous_zoom_option()); // restore AM GUI option mode , AM FIR index filters (0..11) values , <baseband::AMConfig, 12> am_configs has 12 fir index elements.
|
||||
options_config.on_change = [this, view](size_t, OptionsField::value_t n) {
|
||||
receiver_model.set_am_configuration(n);
|
||||
previous_filter_array_index = n;
|
||||
zoom_config.set_by_value(view->get_zoom_factor(AM_MODULATION));
|
||||
receiver_model.set_am_configuration(n + view->get_previous_zoom_option()); // we select proper FIR AM filter (0..11), = 0..4 GUI AM modes + offset +6 (if zoom+2)
|
||||
view->set_previous_AM_mode_option(n); // (0..4) allowing 5 AM modes (DSB9K, DSB6K, USB,LSB, CW)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -282,6 +282,22 @@ void AnalogAudioView::set_zoom_factor(uint8_t mode, uint8_t zoom) { // define a
|
||||
zoom_factor_amfm = zoom;
|
||||
}
|
||||
|
||||
uint8_t AnalogAudioView::get_previous_AM_mode_option() {
|
||||
return previous_AM_mode_option;
|
||||
}
|
||||
|
||||
void AnalogAudioView::set_previous_AM_mode_option(uint8_t mode) {
|
||||
previous_AM_mode_option = mode;
|
||||
}
|
||||
|
||||
uint8_t AnalogAudioView::get_previous_zoom_option() {
|
||||
return previous_zoom;
|
||||
}
|
||||
|
||||
void AnalogAudioView::set_previous_zoom_option(uint8_t zoom) {
|
||||
previous_zoom = zoom;
|
||||
}
|
||||
|
||||
uint8_t AnalogAudioView::get_spec_iq_phase_calibration_value() { // define accessor functions inside AnalogAudioView to read iq_phase_calibration_value
|
||||
return iq_phase_calibration_value;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ class AnalogAudioView;
|
||||
class AMOptionsView : public View {
|
||||
public:
|
||||
AMOptionsView(AnalogAudioView* view, Rect parent_rect, const Style* style);
|
||||
int16_t previous_filter_array_index = 0;
|
||||
|
||||
private:
|
||||
Text label_config{
|
||||
@@ -59,7 +58,7 @@ class AMOptionsView : public View {
|
||||
{23 * 8, 0 * 16},
|
||||
7,
|
||||
{{"ZOOM x1", 0},
|
||||
{"ZOOM x2", 6}} // offset index array filters.
|
||||
{"ZOOM x2", 6}} // offset index AM modes array FIR filters.
|
||||
};
|
||||
};
|
||||
|
||||
@@ -200,6 +199,12 @@ class AnalogAudioView : public View {
|
||||
uint8_t get_zoom_factor(uint8_t mode);
|
||||
void set_zoom_factor(uint8_t mode, uint8_t zoom);
|
||||
|
||||
uint8_t get_previous_AM_mode_option();
|
||||
void set_previous_AM_mode_option(uint8_t mode);
|
||||
|
||||
uint8_t get_previous_zoom_option();
|
||||
void set_previous_zoom_option(uint8_t zoom);
|
||||
|
||||
private:
|
||||
static constexpr ui::Dim header_height = 3 * 16;
|
||||
|
||||
@@ -208,6 +213,9 @@ class AnalogAudioView : public View {
|
||||
uint8_t iq_phase_calibration_value{15}; // initial default RX IQ phase calibration value , used for both max2837 & max2839
|
||||
uint8_t zoom_factor_am{0}; // initial zoom factor in AM mode
|
||||
uint8_t zoom_factor_amfm{0}; // initial zoom factor in AMFM mode
|
||||
uint8_t previous_AM_mode_option{0}; // GUI 5 AM modes : (0..4 ) (DSB9K, DSB6K, USB,LSB, CW). Used to select proper FIR filter (0..11) AM mode + offset 0 (zoom+1) or +6 (if zoom+2)
|
||||
uint8_t previous_zoom{0}; // GUI ZOOM+1, ZOOM+2 , equivalent to two values offset 0 (zoom+1) or +6 (if zoom+2)
|
||||
//
|
||||
app_settings::SettingsManager settings_{
|
||||
"rx_audio",
|
||||
app_settings::Mode::RX,
|
||||
@@ -215,6 +223,8 @@ class AnalogAudioView : public View {
|
||||
{"iq_phase_calibration"sv, &iq_phase_calibration_value}, // we are saving and restoring that CAL from Settings.
|
||||
{"zoom_factor_am"sv, &zoom_factor_am}, // we are saving and restoring AM ZOOM factor from Settings.
|
||||
{"zoom_factor_amfm"sv, &zoom_factor_amfm}, // we are saving and restoring AMFM ZOOM factor from Settings.
|
||||
{"previous_AM_mode_option"sv, &previous_AM_mode_option}, // we are saving and restoring AMFM ZOOM factor from Settings.
|
||||
{"previous_zoom"sv, &previous_zoom}, // we are saving and restoring AMFM ZOOM factor from Settings.
|
||||
}};
|
||||
|
||||
const Rect options_view_rect{0 * 8, 1 * 16, 30 * 8, 1 * 16};
|
||||
|
||||
@@ -203,6 +203,7 @@ BleRecentEntryDetailView::BleRecentEntryDetailView(NavigationView& nav, const Bl
|
||||
nav,
|
||||
packetFileBuffer,
|
||||
64,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this, packetToSave](std::string& buffer) {
|
||||
on_save_file(buffer, packetToSave);
|
||||
});
|
||||
@@ -471,6 +472,7 @@ BLERxView::BLERxView(NavigationView& nav)
|
||||
nav_,
|
||||
filterBuffer,
|
||||
64,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& buffer) {
|
||||
on_filter_change(buffer);
|
||||
});
|
||||
@@ -493,6 +495,7 @@ BLERxView::BLERxView(NavigationView& nav)
|
||||
nav,
|
||||
listFileBuffer,
|
||||
64,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& buffer) {
|
||||
on_save_file(buffer);
|
||||
});
|
||||
|
||||
@@ -399,6 +399,7 @@ BLETxView::BLETxView(NavigationView& nav)
|
||||
nav,
|
||||
packetFileBuffer,
|
||||
64,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& buffer) {
|
||||
on_save_file(buffer);
|
||||
});
|
||||
|
||||
@@ -94,6 +94,7 @@ APRSTXView::APRSTXView(NavigationView& nav) {
|
||||
nav,
|
||||
payload,
|
||||
30,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& s) {
|
||||
text_payload.set(s);
|
||||
});
|
||||
|
||||
@@ -419,7 +419,6 @@ void DebugMenuView::on_populate() {
|
||||
}
|
||||
add_items({
|
||||
{"Buttons Test", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_controls, [this]() { nav_.push<DebugControlsView>(); }},
|
||||
{"Debug Dump", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_memory, [this]() { portapack::persistent_memory::debug_dump(); }},
|
||||
{"M0 Stack Dump", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_memory, [this]() { stack_dump(); }},
|
||||
{"Memory Dump", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_memory, [this]() { nav_.push<DebugMemoryDumpView>(); }},
|
||||
{"Peripherals", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_peripherals, [this]() { nav_.push<DebugPeripheralsMenuView>(); }},
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "ui_transmitter.hpp"
|
||||
#include "transmitter_model.hpp"
|
||||
#include "encoders.hpp"
|
||||
#include "de_bruijn.hpp"
|
||||
#include "app_settings.hpp"
|
||||
#include "radio_state.hpp"
|
||||
|
||||
|
||||
@@ -499,7 +499,7 @@ FileSaveView::FileSaveView(
|
||||
|
||||
button_edit_path.on_select = [this](Button&) {
|
||||
buffer_ = path_.string();
|
||||
text_prompt(nav_, buffer_, max_filename_length,
|
||||
text_prompt(nav_, buffer_, max_filename_length,ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string&) {
|
||||
path_ = buffer_;
|
||||
refresh_widgets();
|
||||
@@ -508,7 +508,7 @@ FileSaveView::FileSaveView(
|
||||
|
||||
button_edit_name.on_select = [this](Button&) {
|
||||
buffer_ = file_.string();
|
||||
text_prompt(nav_, buffer_, max_filename_length,
|
||||
text_prompt(nav_, buffer_, max_filename_length,ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string&) {
|
||||
file_ = buffer_;
|
||||
refresh_widgets();
|
||||
@@ -566,7 +566,7 @@ void FileManagerView::on_rename(std::string_view hint) {
|
||||
cursor_pos = pos;
|
||||
|
||||
text_prompt(
|
||||
nav_, name_buffer, cursor_pos, max_filename_length,
|
||||
nav_, name_buffer, cursor_pos, max_filename_length, ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& renamed) {
|
||||
auto renamed_path = fs::path{renamed};
|
||||
rename_file(get_selected_full_path(), current_path / renamed_path);
|
||||
@@ -640,7 +640,7 @@ void FileManagerView::on_clean() {
|
||||
|
||||
void FileManagerView::on_new_dir() {
|
||||
name_buffer = "";
|
||||
text_prompt(nav_, name_buffer, max_filename_length, [this](std::string& dir_name) {
|
||||
text_prompt(nav_, name_buffer, max_filename_length, ENTER_KEYBOARD_MODE_ALPHA, [this](std::string& dir_name) {
|
||||
make_new_directory(current_path / dir_name);
|
||||
reload_current(true);
|
||||
});
|
||||
@@ -671,7 +671,7 @@ void FileManagerView::on_paste() {
|
||||
|
||||
void FileManagerView::on_new_file() {
|
||||
name_buffer = "";
|
||||
text_prompt(nav_, name_buffer, max_filename_length, [this](std::string& file_name) {
|
||||
text_prompt(nav_, name_buffer, max_filename_length, ENTER_KEYBOARD_MODE_ALPHA, [this](std::string& file_name) {
|
||||
make_new_file(current_path / file_name);
|
||||
reload_current(true);
|
||||
});
|
||||
|
||||
@@ -240,7 +240,7 @@ void FrequencyManagerView::on_edit_freq() {
|
||||
|
||||
void FrequencyManagerView::on_edit_desc() {
|
||||
temp_buffer_ = current_entry().description;
|
||||
text_prompt(nav_, temp_buffer_, freqman_max_desc_size, [this](std::string& new_desc) {
|
||||
text_prompt(nav_, temp_buffer_, freqman_max_desc_size, ENTER_KEYBOARD_MODE_ALPHA, [this](std::string& new_desc) {
|
||||
auto entry = current_entry();
|
||||
entry.description = std::move(new_desc);
|
||||
db_.replace_entry(current_index(), entry);
|
||||
@@ -250,7 +250,7 @@ void FrequencyManagerView::on_edit_desc() {
|
||||
|
||||
void FrequencyManagerView::on_add_category() {
|
||||
temp_buffer_.clear();
|
||||
text_prompt(nav_, temp_buffer_, 20, [this](std::string& new_name) {
|
||||
text_prompt(nav_, temp_buffer_, 20, ENTER_KEYBOARD_MODE_ALPHA, [this](std::string& new_name) {
|
||||
if (!new_name.empty()) {
|
||||
create_freqman_file(new_name);
|
||||
refresh_categories();
|
||||
|
||||
@@ -153,7 +153,7 @@ void POCSAGTXView::paint(Painter&) {
|
||||
}
|
||||
|
||||
void POCSAGTXView::on_set_text(NavigationView& nav) {
|
||||
text_prompt(nav, buffer, MAX_POCSAG_LENGTH);
|
||||
text_prompt(nav, buffer, MAX_POCSAG_LENGTH, ENTER_KEYBOARD_MODE_ALPHA);
|
||||
}
|
||||
|
||||
POCSAGTXView::POCSAGTXView(
|
||||
|
||||
@@ -65,6 +65,7 @@ RDSPSNView::RDSPSNView(
|
||||
nav,
|
||||
PSN,
|
||||
8,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& s) {
|
||||
text_psn.set(s);
|
||||
});
|
||||
@@ -86,6 +87,7 @@ RDSRadioTextView::RDSRadioTextView(
|
||||
nav,
|
||||
radiotext,
|
||||
28,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& s) {
|
||||
text_radiotext.set(s);
|
||||
});
|
||||
|
||||
@@ -517,11 +517,7 @@ ReconView::ReconView(NavigationView& nav)
|
||||
};
|
||||
set_loop_config(continuous);
|
||||
|
||||
rssi.set_focusable(true);
|
||||
rssi.set_peak(true, 500);
|
||||
rssi.on_select = [this](RSSI&) {
|
||||
nav_.replace<LevelView>();
|
||||
};
|
||||
|
||||
// TODO: *BUG* Both transmitter_model and receiver_model share the same pmem setting for target_frequency.
|
||||
button_mic_app.on_select = [this](Button&) {
|
||||
@@ -1227,16 +1223,6 @@ size_t ReconView::change_mode(freqman_index_t new_mod) {
|
||||
text_ctcss.set(" ");
|
||||
recording_sampling_rate = 48000;
|
||||
break;
|
||||
case AMFM_MODULATION:
|
||||
freqman_set_bandwidth_option(new_mod, field_bw);
|
||||
baseband::run_image(portapack::spi_flash::image_tag_am_audio);
|
||||
receiver_model.set_modulation(ReceiverModel::Mode::AMAudioFMApt);
|
||||
receiver_model.set_amfm_configuration(5); // Fix index 5 manually, not from freqman: set to RX AM (USB+FM) mode to demod audio tone, and get Wefax_APT signal.
|
||||
field_bw.on_change = [this](size_t, OptionsField::value_t n) { (void)n; };
|
||||
field_bw.set_by_value(0);
|
||||
text_ctcss.set(" ");
|
||||
recording_sampling_rate = 12000;
|
||||
break;
|
||||
case SPEC_MODULATION:
|
||||
freqman_set_bandwidth_option(new_mod, field_bw);
|
||||
baseband::run_image(portapack::spi_flash::image_tag_capture);
|
||||
@@ -1267,9 +1253,17 @@ size_t ReconView::change_mode(freqman_index_t new_mod) {
|
||||
|
||||
field_mode.set_selected_index(new_mod);
|
||||
field_mode.on_change = [this](size_t, OptionsField::value_t v) {
|
||||
if (v != -1) {
|
||||
change_mode(v);
|
||||
// initialize to a value under SPEC
|
||||
static freqman_index_t last_mode = WFM_MODULATION;
|
||||
if (v > SPEC_MODULATION) {
|
||||
if (last_mode == SPEC_MODULATION)
|
||||
v = AM_MODULATION;
|
||||
else
|
||||
v = SPEC_MODULATION;
|
||||
field_mode.set_selected_index(v);
|
||||
}
|
||||
last_mode = v;
|
||||
change_mode(v);
|
||||
};
|
||||
// for some motive, audio output gets stopped.
|
||||
if (!recon && field_mode.selected_index_value() != SPEC_MODULATION)
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include "analog_audio_app.hpp"
|
||||
#include "audio.hpp"
|
||||
#include "ui_mictx.hpp"
|
||||
#include "ui_level.hpp"
|
||||
#include "ui_looking_glass_app.hpp"
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
#include "baseband_api.hpp"
|
||||
|
||||
@@ -82,7 +82,7 @@ ReconSetupViewMain::ReconSetupViewMain(NavigationView& nav, Rect parent_rect, st
|
||||
};
|
||||
|
||||
button_choose_output_name.on_select = [this, &nav](Button&) {
|
||||
text_prompt(nav, _output_file, 28, [this](std::string& buffer) {
|
||||
text_prompt(nav, _output_file, 28, ENTER_KEYBOARD_MODE_ALPHA, [this](std::string& buffer) {
|
||||
_output_file = buffer;
|
||||
button_choose_output_name.set_text(_output_file);
|
||||
});
|
||||
|
||||
@@ -1044,12 +1044,14 @@ SetBatteryView::SetBatteryView(NavigationView& nav) {
|
||||
add_children({&labels,
|
||||
&button_save,
|
||||
&button_cancel,
|
||||
&checkbox_overridebatt});
|
||||
&checkbox_overridebatt,
|
||||
&checkbox_battery_charge_hint});
|
||||
|
||||
if (i2cdev::I2CDevManager::get_dev_by_model(I2C_DEVMDL::I2CDEVMDL_MAX17055)) add_children({&button_reset, &labels2});
|
||||
|
||||
button_save.on_select = [&nav, this](Button&) {
|
||||
pmem::set_ui_override_batt_calc(checkbox_overridebatt.value());
|
||||
pmem::set_ui_battery_charge_hint(checkbox_battery_charge_hint.value());
|
||||
battery::BatteryManagement::set_calc_override(checkbox_overridebatt.value());
|
||||
send_system_refresh();
|
||||
nav.pop();
|
||||
@@ -1064,6 +1066,7 @@ SetBatteryView::SetBatteryView(NavigationView& nav) {
|
||||
};
|
||||
|
||||
checkbox_overridebatt.set_value(pmem::ui_override_batt_calc());
|
||||
checkbox_battery_charge_hint.set_value(pmem::ui_battery_charge_hint());
|
||||
|
||||
button_cancel.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
|
||||
@@ -978,9 +978,13 @@ class SetBatteryView : public View {
|
||||
int32_t selected = 0;
|
||||
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}};
|
||||
{{1 * 8, 2 * 16}, "method to voltage based", Theme::getInstance()->fg_light->foreground},
|
||||
/**/
|
||||
{{1 * 8, 6 * 16}, "Display a hint to remind you", Theme::getInstance()->fg_light->foreground},
|
||||
{{1 * 8, 7 * 16}, "when you charge", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Labels labels2{{{1 * 8, 11 * 16}, "Reset IC's learned params.", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Button button_save{
|
||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||
"Save"};
|
||||
@@ -990,13 +994,18 @@ class SetBatteryView : public View {
|
||||
23,
|
||||
"Override"};
|
||||
|
||||
Checkbox checkbox_battery_charge_hint{
|
||||
{2 * 8, 9 * 16},
|
||||
23,
|
||||
"Charge hint"};
|
||||
|
||||
Button button_cancel{
|
||||
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||
"Cancel",
|
||||
};
|
||||
|
||||
Button button_reset{
|
||||
{2 * 8, 8 * 16, 12 * 8, 32},
|
||||
{2 * 8, 13 * 16, 12 * 8, 32},
|
||||
"Reset",
|
||||
};
|
||||
};
|
||||
|
||||
@@ -617,6 +617,7 @@ void TextEditorView::show_edit_line() {
|
||||
edit_line_buffer_,
|
||||
viewer.col(),
|
||||
max_edit_length,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& buffer) {
|
||||
auto range = file_->line_range(viewer.line());
|
||||
if (!range)
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "ui.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "ui_widget.hpp"
|
||||
#include "ui_textentry.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
@@ -105,7 +106,7 @@ void bind(TextField& field, T& value, NavigationView& nav, Fn fn = Fn{}) {
|
||||
// Capture a new string and make the lambda mutable so it can be modified.
|
||||
field.on_select = [&nav, buf = std::string{}](TextField& tf) mutable {
|
||||
buf = tf.get_text();
|
||||
text_prompt(nav, buf, /*max_length*/ 255,
|
||||
text_prompt(nav, buf, /*max_length*/ 255, ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[&tf](std::string& str) {
|
||||
tf.set_text(str);
|
||||
});
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
unsigned char modal_warning_bmp[] = {
|
||||
0x42, 0x4d, 0xfa, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00,
|
||||
0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00,
|
||||
0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0xa8, 0x02,
|
||||
0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x07, 0x00,
|
||||
0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x42, 0x47, 0x52, 0x73, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xff, 0x00, 0x00, 0x5a,
|
||||
0xff, 0x00, 0x78, 0x78, 0x78, 0x00, 0x00, 0x7c, 0xff, 0x00, 0x00, 0xa9,
|
||||
0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x02, 0x03, 0x24, 0x66, 0x02, 0x30,
|
||||
0x00, 0x00, 0x02, 0x36, 0x24, 0x66, 0x02, 0x63, 0x00, 0x00, 0x02, 0x66,
|
||||
0x02, 0x63, 0x20, 0x00, 0x02, 0x36, 0x02, 0x66, 0x00, 0x00, 0x02, 0x36,
|
||||
0x02, 0x60, 0x20, 0x00, 0x02, 0x06, 0x02, 0x63, 0x00, 0x00, 0x02, 0x06,
|
||||
0x02, 0x60, 0x0c, 0x00, 0x00, 0x08, 0x03, 0x66, 0x66, 0x30, 0x0c, 0x00,
|
||||
0x02, 0x06, 0x02, 0x60, 0x00, 0x00, 0x02, 0x03, 0x02, 0x66, 0x0c, 0x00,
|
||||
0x00, 0x08, 0x06, 0x11, 0x11, 0x60, 0x0c, 0x00, 0x02, 0x66, 0x02, 0x30,
|
||||
0x00, 0x00, 0x02, 0x00, 0x02, 0x66, 0x0c, 0x00, 0x00, 0x08, 0x06, 0x21,
|
||||
0x21, 0x60, 0x0c, 0x00, 0x02, 0x66, 0x02, 0x00, 0x00, 0x00, 0x00, 0x06,
|
||||
0x00, 0x36, 0x60, 0x00, 0x0a, 0x00, 0x00, 0x08, 0x06, 0x42, 0x42, 0x60,
|
||||
0x0a, 0x00, 0x00, 0x06, 0x06, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
|
||||
0x00, 0x06, 0x60, 0x00, 0x0a, 0x00, 0x00, 0x08, 0x06, 0x54, 0x45, 0x60,
|
||||
0x0a, 0x00, 0x00, 0x06, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
|
||||
0x00, 0x03, 0x66, 0x00, 0x0a, 0x00, 0x00, 0x08, 0x03, 0x66, 0x66, 0x30,
|
||||
0x0a, 0x00, 0x00, 0x06, 0x66, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
|
||||
0x00, 0x00, 0x66, 0x00, 0x1c, 0x00, 0x00, 0x06, 0x66, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x36, 0x60, 0x18, 0x00, 0x00, 0x08,
|
||||
0x06, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x60,
|
||||
0x0a, 0x00, 0x02, 0x36, 0x02, 0x63, 0x0a, 0x00, 0x00, 0x08, 0x06, 0x60,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x66, 0x08, 0x00,
|
||||
0x00, 0x08, 0x03, 0x61, 0x16, 0x30, 0x08, 0x00, 0x00, 0x08, 0x66, 0x30,
|
||||
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x66, 0x08, 0x00, 0x00, 0x08,
|
||||
0x06, 0x11, 0x11, 0x60, 0x08, 0x00, 0x02, 0x66, 0x06, 0x00, 0x00, 0x00,
|
||||
0x06, 0x00, 0x02, 0x36, 0x02, 0x60, 0x06, 0x00, 0x00, 0x08, 0x06, 0x11,
|
||||
0x11, 0x60, 0x06, 0x00, 0x02, 0x06, 0x02, 0x63, 0x06, 0x00, 0x00, 0x00,
|
||||
0x06, 0x00, 0x02, 0x06, 0x02, 0x60, 0x06, 0x00, 0x00, 0x08, 0x06, 0x11,
|
||||
0x11, 0x60, 0x06, 0x00, 0x02, 0x06, 0x02, 0x60, 0x06, 0x00, 0x00, 0x00,
|
||||
0x06, 0x00, 0x02, 0x03, 0x02, 0x66, 0x06, 0x00, 0x00, 0x08, 0x06, 0x11,
|
||||
0x11, 0x60, 0x06, 0x00, 0x02, 0x66, 0x02, 0x30, 0x06, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x02, 0x66, 0x06, 0x00, 0x00, 0x08, 0x06, 0x11, 0x11, 0x60,
|
||||
0x06, 0x00, 0x02, 0x66, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x18,
|
||||
0x36, 0x60, 0x00, 0x00, 0x06, 0x11, 0x11, 0x60, 0x00, 0x00, 0x06, 0x63,
|
||||
0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x18, 0x06, 0x60, 0x00, 0x00,
|
||||
0x06, 0x21, 0x21, 0x60, 0x00, 0x00, 0x06, 0x60, 0x08, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x00, 0x18, 0x03, 0x66, 0x00, 0x00, 0x06, 0x12, 0x12, 0x60,
|
||||
0x00, 0x00, 0x66, 0x30, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x14,
|
||||
0x66, 0x00, 0x00, 0x06, 0x21, 0x21, 0x60, 0x00, 0x00, 0x66, 0x0a, 0x00,
|
||||
0x00, 0x00, 0x0a, 0x00, 0x00, 0x14, 0x36, 0x60, 0x00, 0x06, 0x22, 0x22,
|
||||
0x60, 0x00, 0x06, 0x63, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x14,
|
||||
0x06, 0x60, 0x00, 0x06, 0x24, 0x24, 0x60, 0x00, 0x06, 0x60, 0x0a, 0x00,
|
||||
0x00, 0x00, 0x0a, 0x00, 0x00, 0x14, 0x03, 0x66, 0x00, 0x06, 0x42, 0x42,
|
||||
0x60, 0x00, 0x66, 0x30, 0x0a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10,
|
||||
0x66, 0x00, 0x06, 0x54, 0x45, 0x60, 0x00, 0x66, 0x0c, 0x00, 0x00, 0x00,
|
||||
0x0c, 0x00, 0x00, 0x10, 0x36, 0x60, 0x03, 0x66, 0x66, 0x30, 0x06, 0x63,
|
||||
0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x02, 0x06, 0x02, 0x60, 0x08, 0x00,
|
||||
0x02, 0x06, 0x02, 0x60, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x02, 0x03,
|
||||
0x02, 0x66, 0x08, 0x00, 0x02, 0x66, 0x02, 0x30, 0x0c, 0x00, 0x00, 0x00,
|
||||
0x0e, 0x00, 0x02, 0x66, 0x08, 0x00, 0x02, 0x66, 0x0e, 0x00, 0x00, 0x00,
|
||||
0x0e, 0x00, 0x00, 0x0c, 0x36, 0x60, 0x00, 0x00, 0x06, 0x63, 0x0e, 0x00,
|
||||
0x00, 0x00, 0x0e, 0x00, 0x00, 0x0c, 0x06, 0x60, 0x00, 0x00, 0x06, 0x60,
|
||||
0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0c, 0x03, 0x66, 0x00, 0x00,
|
||||
0x66, 0x30, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x66, 0x00,
|
||||
0x00, 0x66, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x36, 0x60,
|
||||
0x06, 0x63, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x06, 0x60,
|
||||
0x06, 0x60, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x03, 0x66,
|
||||
0x66, 0x30, 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x66, 0x02, 0x66,
|
||||
0x12, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x36, 0x02, 0x63, 0x12, 0x00,
|
||||
0x00, 0x01};
|
||||
unsigned int modal_warning_bmp_len = 830;
|
||||
@@ -1,327 +0,0 @@
|
||||
// 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, 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, 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, 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,104 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2017 Furrtek
|
||||
*
|
||||
* 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 "de_bruijn.hpp"
|
||||
|
||||
/* How this works:
|
||||
* B(2,4) means:
|
||||
* Alphabet size = 2 (binary)
|
||||
* Code length = 4
|
||||
* The length of the bitstream is (2 ^ 4) + (4 - 1) = 19 bits
|
||||
* The primitive polynomials come from the de_bruijn_polys[] array (one for each code length)
|
||||
* The shift register is init with 1 and shifted left each step
|
||||
* The polynomial is kept on the right, and used as a AND mask applied on the corresponding shift register bits
|
||||
* The resulting bits are XORed together to produce the new bit pushed in the shift register
|
||||
*
|
||||
* 0001 (init)
|
||||
* AND 1001 (polynomial)
|
||||
* 0001 XOR'd -> 1
|
||||
*
|
||||
* 00011 (shift left)
|
||||
* AND 1001
|
||||
* 0001 XOR'd -> 1
|
||||
*
|
||||
* 000111 (shift left)
|
||||
* AND 1001
|
||||
* 0001 XOR'd -> 1
|
||||
*
|
||||
* 0001111 (shift left)
|
||||
* AND 1001
|
||||
* 1001 XOR'd -> 0
|
||||
*
|
||||
* 00011110 (shift left)
|
||||
* AND 1001
|
||||
* 1000 XOR'd -> 1
|
||||
* ...
|
||||
* After 16 steps: (0+) 000111101011001000
|
||||
* Each of the 16 possible values appears in the sequence:
|
||||
* -0000-111101011001000 0
|
||||
* 0-0001-11101011001000 1
|
||||
* 0000111101011-0010-00 2
|
||||
* 00-0011-1101011001000 3
|
||||
* 00001111010110-0100-0 4
|
||||
* 00001111-0101-1001000 5
|
||||
* 0000111101-0110-01000 6
|
||||
* 000-0111-101011001000 7
|
||||
* 000011110101100-1000- 8
|
||||
* 000011110101-1001-000 9
|
||||
* 0000111-1010-11001000 10
|
||||
* 000011110-1011-001000 11
|
||||
* 00001111010-1100-1000 12
|
||||
* 000011-1101-011001000 13
|
||||
* 00001-1110-1011001000 14
|
||||
* 0000-1111-01011001000 15
|
||||
*/
|
||||
|
||||
size_t de_bruijn::init(const uint32_t n) {
|
||||
// Cap
|
||||
if ((n < 3) || (n > 16))
|
||||
length = 3;
|
||||
else
|
||||
length = n;
|
||||
|
||||
poly = de_bruijn_polys[length - 3];
|
||||
shift_register = 1;
|
||||
|
||||
return (1U << length) + (length - 1);
|
||||
}
|
||||
|
||||
uint32_t de_bruijn::compute(const uint32_t steps) {
|
||||
uint32_t step, bits, masked;
|
||||
uint8_t new_bit;
|
||||
|
||||
for (step = 0; step < steps; step++) {
|
||||
masked = shift_register & poly;
|
||||
new_bit = 0;
|
||||
for (bits = 0; bits < length; bits++) {
|
||||
new_bit ^= (masked & 1);
|
||||
masked >>= 1;
|
||||
}
|
||||
shift_register <<= 1;
|
||||
shift_register |= new_bit;
|
||||
}
|
||||
|
||||
return shift_register;
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2017 Furrtek
|
||||
*
|
||||
* 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 <string>
|
||||
#include <cstdint>
|
||||
|
||||
#ifndef __DE_BRUIJN_H__
|
||||
#define __DE_BRUIJN_H__
|
||||
|
||||
// n from 3 to 16
|
||||
const uint32_t de_bruijn_polys[14]{
|
||||
0b0000000000000101,
|
||||
0b0000000000001001,
|
||||
0b0000000000011011,
|
||||
0b0000000000110011,
|
||||
0b0000000001010011,
|
||||
0b0000000010001101,
|
||||
0b0000000100100001,
|
||||
0b0000001000100001,
|
||||
0b0000010001100001,
|
||||
0b0000110101000011,
|
||||
0b0001001001100101,
|
||||
0b0010101100000011,
|
||||
0b0101000000001001,
|
||||
0b1010000101000101};
|
||||
|
||||
struct de_bruijn {
|
||||
public:
|
||||
size_t init(const uint32_t n);
|
||||
uint32_t compute(const uint32_t steps);
|
||||
|
||||
private:
|
||||
uint32_t length{};
|
||||
uint32_t poly{};
|
||||
uint32_t shift_register{};
|
||||
};
|
||||
|
||||
#endif /*__DE_BRUIJN_H__*/
|
||||
@@ -131,6 +131,7 @@ ADSBCallsignView::ADSBCallsignView(
|
||||
nav,
|
||||
callsign,
|
||||
8,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& s) {
|
||||
button_callsign.set_text(s);
|
||||
});
|
||||
|
||||
+9
-28
@@ -81,8 +81,6 @@ void CVSSpamView::start_tx(const uint32_t id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t sample_rate = 250000;
|
||||
|
||||
current_file = cvsfiles_dir / file_list[id].filename();
|
||||
|
||||
File capture_file;
|
||||
@@ -99,20 +97,13 @@ void CVSSpamView::start_tx(const uint32_t id) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto metadata_path = get_metadata_path(current_file);
|
||||
auto metadata = read_metadata_file(metadata_path);
|
||||
if (!metadata) {
|
||||
metadata = capture_metadata{transmitter_model.target_frequency(), sample_rate};
|
||||
}
|
||||
|
||||
auto file_size = capture_file.size();
|
||||
capture_file.close();
|
||||
|
||||
replay_thread.reset();
|
||||
transmitter_model.disable();
|
||||
ready_signal = false;
|
||||
|
||||
baseband::set_sample_rate(metadata->sample_rate, get_oversample_rate(metadata->sample_rate));
|
||||
baseband::set_sample_rate(SAMPLE_RATE, get_oversample_rate(SAMPLE_RATE));
|
||||
|
||||
auto reader = std::make_unique<FileConvertReader>();
|
||||
if (auto error = reader->open(current_file)) {
|
||||
@@ -120,10 +111,7 @@ void CVSSpamView::start_tx(const uint32_t id) {
|
||||
"Cannot read C16 data.\n"
|
||||
"Check file format/perms.\n"
|
||||
"Rate: " +
|
||||
to_string_dec_uint(metadata->sample_rate) +
|
||||
"\n"
|
||||
"Size: " +
|
||||
to_string_dec_uint(file_size) +
|
||||
to_string_dec_uint(SAMPLE_RATE) +
|
||||
"\n"
|
||||
"Error: " +
|
||||
std::to_string(static_cast<uint32_t>(error)));
|
||||
@@ -132,9 +120,9 @@ void CVSSpamView::start_tx(const uint32_t id) {
|
||||
|
||||
progressbar.set_value(0);
|
||||
|
||||
transmitter_model.set_sampling_rate(get_actual_sample_rate(metadata->sample_rate));
|
||||
transmitter_model.set_baseband_bandwidth(metadata->sample_rate <= 500000 ? 1750000 : 2500000);
|
||||
transmitter_model.set_target_frequency(metadata->center_frequency);
|
||||
transmitter_model.set_sampling_rate(get_actual_sample_rate(SAMPLE_RATE));
|
||||
transmitter_model.set_baseband_bandwidth(SAMPLE_RATE <= 500000 ? 1750000 : 2500000);
|
||||
transmitter_model.set_target_frequency(TARGET_FREQUENCY);
|
||||
transmitter_model.enable();
|
||||
|
||||
chThdSleepMilliseconds(100);
|
||||
@@ -164,7 +152,6 @@ void CVSSpamView::start_random_tx() {
|
||||
lfsr_v = lfsr_iterate(lfsr_v);
|
||||
size_t random_index = lfsr_v % file_list.size();
|
||||
|
||||
const uint32_t sample_rate = 250000;
|
||||
current_file = cvsfiles_dir / file_list[random_index].filename();
|
||||
|
||||
File capture_file;
|
||||
@@ -174,19 +161,13 @@ void CVSSpamView::start_random_tx() {
|
||||
return;
|
||||
}
|
||||
|
||||
auto metadata_path = get_metadata_path(current_file);
|
||||
auto metadata = read_metadata_file(metadata_path);
|
||||
if (!metadata) {
|
||||
metadata = capture_metadata{transmitter_model.target_frequency(), sample_rate};
|
||||
}
|
||||
|
||||
capture_file.close();
|
||||
|
||||
replay_thread.reset();
|
||||
transmitter_model.disable();
|
||||
ready_signal = false;
|
||||
|
||||
baseband::set_sample_rate(metadata->sample_rate, get_oversample_rate(metadata->sample_rate));
|
||||
baseband::set_sample_rate(SAMPLE_RATE, get_oversample_rate(SAMPLE_RATE));
|
||||
|
||||
auto reader = std::make_unique<FileConvertReader>();
|
||||
if (auto error = reader->open(current_file)) {
|
||||
@@ -196,9 +177,9 @@ void CVSSpamView::start_random_tx() {
|
||||
|
||||
progressbar.set_value(0);
|
||||
|
||||
transmitter_model.set_sampling_rate(get_actual_sample_rate(metadata->sample_rate));
|
||||
transmitter_model.set_baseband_bandwidth(metadata->sample_rate <= 500000 ? 1750000 : 2500000);
|
||||
transmitter_model.set_target_frequency(metadata->center_frequency);
|
||||
transmitter_model.set_sampling_rate(get_actual_sample_rate(SAMPLE_RATE));
|
||||
transmitter_model.set_baseband_bandwidth(SAMPLE_RATE <= 500000 ? 1750000 : 2500000);
|
||||
transmitter_model.set_target_frequency(TARGET_FREQUENCY);
|
||||
transmitter_model.enable();
|
||||
|
||||
chThdSleepMilliseconds(100);
|
||||
|
||||
@@ -16,6 +16,9 @@ using namespace portapack;
|
||||
|
||||
namespace ui::external_app::cvs_spam {
|
||||
|
||||
constexpr uint32_t SAMPLE_RATE = 250000;
|
||||
constexpr uint64_t TARGET_FREQUENCY = 433920000;
|
||||
|
||||
class CVSSpamView : public View {
|
||||
public:
|
||||
explicit CVSSpamView(NavigationView& nav);
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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_debug_pmem.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "external_app.hpp"
|
||||
|
||||
namespace ui::external_app::debug_pmem {
|
||||
void initialize_app(ui::NavigationView& nav) {
|
||||
nav.push<DebugDumpView>();
|
||||
}
|
||||
} // namespace ui::external_app::debug_pmem
|
||||
|
||||
extern "C" {
|
||||
|
||||
__attribute__((section(".external_app.app_debug_pmem.application_information"), used)) application_information_t _application_information_debug_pmem = {
|
||||
/*.memory_location = */ (uint8_t*)0x00000000,
|
||||
/*.externalAppEntry = */ ui::external_app::debug_pmem::initialize_app,
|
||||
/*.header_version = */ CURRENT_HEADER_VERSION,
|
||||
/*.app_version = */ VERSION_MD5,
|
||||
|
||||
/*.app_name = */ "DebugPMem",
|
||||
/*.bitmap_data = */ {
|
||||
0x54,
|
||||
0x15,
|
||||
0x54,
|
||||
0x15,
|
||||
0xFF,
|
||||
0x7F,
|
||||
0xFC,
|
||||
0x1F,
|
||||
0xFF,
|
||||
0x7F,
|
||||
0xCC,
|
||||
0x19,
|
||||
0xAF,
|
||||
0x7A,
|
||||
0x6C,
|
||||
0x1B,
|
||||
0xEF,
|
||||
0x7B,
|
||||
0xEC,
|
||||
0x1B,
|
||||
0xFF,
|
||||
0x7F,
|
||||
0xFC,
|
||||
0x1F,
|
||||
0xFF,
|
||||
0x7F,
|
||||
0x54,
|
||||
0x15,
|
||||
0x54,
|
||||
0x15,
|
||||
0x00,
|
||||
0x00,
|
||||
},
|
||||
/*.icon_color = */ ui::Color::cyan().v,
|
||||
/*.menu_location = */ app_location_t::DEBUG,
|
||||
/*.desired_menu_position = */ -1,
|
||||
|
||||
/*.m4_app_tag = portapack::spi_flash::image_tag_none */ {0, 0, 0, 0},
|
||||
/*.m4_app_offset = */ 0x00000000, // will be filled at compile time
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2018 Furrtek
|
||||
*
|
||||
* 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_debug_pmem.hpp"
|
||||
|
||||
namespace ui::external_app::debug_pmem {
|
||||
|
||||
// Dump pmem, receiver and transmitter models internals in human readable format
|
||||
bool DebugDumpView::debug_dump_func() {
|
||||
std::string debug_dir = "DEBUG";
|
||||
std::filesystem::path filename{};
|
||||
File pmem_dump_file{};
|
||||
// create new dump file name and DEBUG directory
|
||||
ensure_directory(debug_dir);
|
||||
filename = next_filename_matching_pattern(debug_dir + "/DEBUG_DUMP_????.TXT");
|
||||
if (filename.empty()) {
|
||||
dump_output.set("COULD NOT GET DUMP NAME !");
|
||||
dump_output.set_style(ui::Theme::getInstance()->fg_red);
|
||||
return false;
|
||||
}
|
||||
// dump data fo filename
|
||||
auto error = pmem_dump_file.create(filename);
|
||||
if (error) {
|
||||
dump_output.set("ERROR DUMPING " + filename.filename().string() + " !");
|
||||
dump_output.set_style(ui::Theme::getInstance()->fg_red);
|
||||
return false;
|
||||
}
|
||||
pmem_dump_file.write_line("FW version: " VERSION_STRING);
|
||||
pmem_dump_file.write_line("Ext APPS version req'd: 0x" + to_string_hex(VERSION_MD5));
|
||||
pmem_dump_file.write_line("GCC version: " + to_string_dec_int(__GNUC__) + "." + to_string_dec_int(__GNUC_MINOR__) + "." + to_string_dec_int(__GNUC_PATCHLEVEL__));
|
||||
|
||||
// firmware checksum
|
||||
pmem_dump_file.write_line("Firmware calculated checksum: 0x" + to_string_hex(simple_checksum(FLASH_STARTING_ADDRESS, FLASH_ROM_SIZE), 8));
|
||||
|
||||
// write persistent memory
|
||||
pmem_dump_file.write_line("\n[Persistent Memory]");
|
||||
|
||||
// full variables
|
||||
pmem_dump_file.write_line("structure_version: 0x" + to_string_hex(get_data_structure_version(), 8));
|
||||
pmem_dump_file.write_line("target_frequency: " + to_string_dec_int(target_frequency()));
|
||||
pmem_dump_file.write_line("correction_ppb: " + to_string_dec_int(correction_ppb()));
|
||||
pmem_dump_file.write_line("modem_def_index: " + to_string_dec_uint(get_modem_def_index()));
|
||||
pmem_dump_file.write_line("serial_format.data_bit: " + to_string_dec_uint(serial_format().data_bits));
|
||||
pmem_dump_file.write_line("serial_format.parity: " + to_string_dec_uint(serial_format().parity));
|
||||
pmem_dump_file.write_line("serial_format.stop_bits: " + to_string_dec_uint(serial_format().stop_bits));
|
||||
pmem_dump_file.write_line("serial_format.bit_order: " + to_string_dec_uint(serial_format().bit_order));
|
||||
pmem_dump_file.write_line("modem_bw: " + to_string_dec_int(modem_bw()));
|
||||
pmem_dump_file.write_line("afsk_mark_freq: " + to_string_dec_int(afsk_mark_freq()));
|
||||
pmem_dump_file.write_line("afsk_space_freq: " + to_string_dec_int(afsk_space_freq()));
|
||||
pmem_dump_file.write_line("modem_baudrate: " + to_string_dec_int(modem_baudrate()));
|
||||
pmem_dump_file.write_line("modem_repeat: " + to_string_dec_int(modem_repeat()));
|
||||
pmem_dump_file.write_line("pocsag_last_address: " + to_string_dec_uint(pocsag_last_address()));
|
||||
pmem_dump_file.write_line("pocsag_ignore_address: " + to_string_dec_uint(pocsag_ignore_address()));
|
||||
pmem_dump_file.write_line("tone_mix: " + to_string_dec_uint(tone_mix()));
|
||||
pmem_dump_file.write_line("hardware_config: " + to_string_dec_uint(config_cpld()));
|
||||
pmem_dump_file.write_line("recon_config: 0x" + to_string_hex(get_recon_config(), 16));
|
||||
pmem_dump_file.write_line("recon_repeat_nb: " + to_string_dec_int(recon_repeat_nb()));
|
||||
pmem_dump_file.write_line("recon_repeat_gain: " + to_string_dec_int(recon_repeat_gain()));
|
||||
pmem_dump_file.write_line("recon_repeat_delay: " + to_string_dec_int(recon_repeat_delay()));
|
||||
pmem_dump_file.write_line("converter: " + to_string_dec_int(config_converter()));
|
||||
pmem_dump_file.write_line("updown_converter: " + to_string_dec_int(config_updown_converter()));
|
||||
pmem_dump_file.write_line("updown_frequency_rx_correction: " + to_string_dec_int(config_freq_rx_correction_updown()));
|
||||
pmem_dump_file.write_line("updown_frequency_tx_correction: " + to_string_dec_int(config_freq_tx_correction_updown()));
|
||||
pmem_dump_file.write_line("lcd_inverted_mode: " + to_string_dec_uint(config_lcd_inverted_mode()));
|
||||
pmem_dump_file.write_line("converter_frequency_offset: " + to_string_dec_int(config_converter_freq()));
|
||||
pmem_dump_file.write_line("frequency_rx_correction: " + to_string_dec_uint(config_freq_rx_correction()));
|
||||
pmem_dump_file.write_line("frequency_tx_correction: " + to_string_dec_uint(config_freq_tx_correction()));
|
||||
pmem_dump_file.write_line("encoder_dial_sensitivity: " + to_string_dec_uint(encoder_dial_sensitivity()));
|
||||
pmem_dump_file.write_line("encoder_rate_multiplier: " + to_string_dec_uint(encoder_rate_multiplier()));
|
||||
pmem_dump_file.write_line("encoder_dial_direction: " + to_string_dec_uint(encoder_dial_direction())); // 0 = normal, 1 = reverse
|
||||
pmem_dump_file.write_line("config_mode_storage: 0x" + to_string_hex(config_mode_storage_direct(), 8));
|
||||
pmem_dump_file.write_line("dst_config: 0x" + to_string_hex((uint32_t)config_dst().v, 8));
|
||||
pmem_dump_file.write_line("fake_brightness_level: " + to_string_dec_uint(fake_brightness_level()));
|
||||
pmem_dump_file.write_line("menu_color: 0x" + to_string_hex(menu_color().v, 4));
|
||||
pmem_dump_file.write_line("touchscreen_threshold: " + to_string_dec_uint(touchscreen_threshold()));
|
||||
|
||||
// ui_config bits
|
||||
const auto backlight_timer = portapack::persistent_memory::config_backlight_timer();
|
||||
pmem_dump_file.write_line("ui_config clkout_freq: " + to_string_dec_uint(clkout_freq()));
|
||||
pmem_dump_file.write_line("ui_config backlight_timer.timeout_enabled: " + to_string_dec_uint(backlight_timer.timeout_enabled()));
|
||||
pmem_dump_file.write_line("ui_config backlight_timer.timeout_seconds: " + to_string_dec_uint(backlight_timer.timeout_seconds()));
|
||||
pmem_dump_file.write_line("ui_config show_gui_return_icon: " + to_string_dec_uint(show_gui_return_icon()));
|
||||
pmem_dump_file.write_line("ui_config load_app_settings: " + to_string_dec_uint(load_app_settings()));
|
||||
pmem_dump_file.write_line("ui_config save_app_settings: " + to_string_dec_uint(save_app_settings()));
|
||||
pmem_dump_file.write_line("ui_config disable_touchscreen: " + to_string_dec_uint(disable_touchscreen()));
|
||||
pmem_dump_file.write_line("ui_config hide_clock: " + to_string_dec_uint(hide_clock()));
|
||||
pmem_dump_file.write_line("ui_config clock_with_date: " + to_string_dec_uint(clock_with_date()));
|
||||
pmem_dump_file.write_line("ui_config clkout_enabled: " + to_string_dec_uint(clkout_enabled()));
|
||||
pmem_dump_file.write_line("ui_config apply_fake_brightness: " + to_string_dec_uint(apply_fake_brightness()));
|
||||
pmem_dump_file.write_line("ui_config stealth_mode: " + to_string_dec_uint(stealth_mode()));
|
||||
pmem_dump_file.write_line("ui_config config_login: " + to_string_dec_uint(config_login()));
|
||||
pmem_dump_file.write_line("ui_config config_splash: " + to_string_dec_uint(config_splash()));
|
||||
|
||||
// ui_config2 bits
|
||||
pmem_dump_file.write_line("ui_config2 hide_speaker: " + to_string_dec_uint(ui_hide_speaker()));
|
||||
pmem_dump_file.write_line("ui_config2 hide_converter: " + to_string_dec_uint(ui_hide_converter()));
|
||||
pmem_dump_file.write_line("ui_config2 hide_stealth: " + to_string_dec_uint(ui_hide_stealth()));
|
||||
pmem_dump_file.write_line("ui_config2 hide_camera: " + to_string_dec_uint(ui_hide_camera()));
|
||||
pmem_dump_file.write_line("ui_config2 hide_sleep: " + to_string_dec_uint(ui_hide_sleep()));
|
||||
pmem_dump_file.write_line("ui_config2 hide_bias_tee: " + to_string_dec_uint(ui_hide_bias_tee()));
|
||||
pmem_dump_file.write_line("ui_config2 hide_clock: " + to_string_dec_uint(ui_hide_clock()));
|
||||
pmem_dump_file.write_line("ui_config2 hide_sd_card: " + to_string_dec_uint(ui_hide_sd_card()));
|
||||
pmem_dump_file.write_line("ui_config2 hide_mute: " + to_string_dec_uint(ui_hide_mute()));
|
||||
pmem_dump_file.write_line("ui_config2 hide_fake_brightness: " + to_string_dec_uint(ui_hide_fake_brightness()));
|
||||
pmem_dump_file.write_line("ui_config2 hide_battery_icon: " + to_string_dec_uint(ui_hide_battery_icon()));
|
||||
pmem_dump_file.write_line("ui_config2 hide_numeric_battery: " + to_string_dec_uint(ui_hide_numeric_battery()));
|
||||
pmem_dump_file.write_line("ui_config2 theme_id: " + to_string_dec_uint(ui_theme_id()));
|
||||
pmem_dump_file.write_line("ui_config2 override_batt_calc: " + to_string_dec_uint(ui_override_batt_calc()));
|
||||
pmem_dump_file.write_line("ui_config2 button_repeat_delay: " + to_string_dec_uint(ui_button_repeat_delay()));
|
||||
pmem_dump_file.write_line("ui_config2 button_repeat_speed: " + to_string_dec_uint(ui_button_repeat_speed()));
|
||||
pmem_dump_file.write_line("ui_config2 button_long_press_delay: " + to_string_dec_uint(ui_button_long_press_delay()));
|
||||
pmem_dump_file.write_line("ui_config2 battery_charge_hint: " + to_string_dec_uint(ui_battery_charge_hint()));
|
||||
|
||||
// misc_config bits
|
||||
pmem_dump_file.write_line("misc_config config_audio_mute: " + to_string_dec_int(config_audio_mute()));
|
||||
pmem_dump_file.write_line("misc_config config_speaker_disable: " + to_string_dec_int(config_speaker_disable()));
|
||||
pmem_dump_file.write_line("misc_config config_disable_external_tcxo: " + to_string_dec_uint(config_disable_external_tcxo()));
|
||||
pmem_dump_file.write_line("misc_config config_sdcard_high_speed_io: " + to_string_dec_uint(config_sdcard_high_speed_io()));
|
||||
pmem_dump_file.write_line("misc_config config_disable_config_mode: " + to_string_dec_uint(config_disable_config_mode()));
|
||||
pmem_dump_file.write_line("misc_config beep_on_packets: " + to_string_dec_int(beep_on_packets()));
|
||||
|
||||
// receiver_model
|
||||
pmem_dump_file.write_line("\n[Receiver Model]");
|
||||
pmem_dump_file.write_line("target_frequency: " + to_string_dec_uint(receiver_model.target_frequency()));
|
||||
pmem_dump_file.write_line("frequency_step: " + to_string_dec_uint(receiver_model.frequency_step()));
|
||||
pmem_dump_file.write_line("lna: " + to_string_dec_int(receiver_model.lna()));
|
||||
pmem_dump_file.write_line("vga: " + to_string_dec_int(receiver_model.vga()));
|
||||
pmem_dump_file.write_line("rf_amp: " + to_string_dec_int(receiver_model.rf_amp()));
|
||||
pmem_dump_file.write_line("baseband_bandwidth: " + to_string_dec_uint(receiver_model.baseband_bandwidth()));
|
||||
pmem_dump_file.write_line("sampling_rate: " + to_string_dec_uint(receiver_model.sampling_rate()));
|
||||
switch (receiver_model.modulation()) {
|
||||
case ReceiverModel::Mode::AMAudio:
|
||||
pmem_dump_file.write_line("modulation: Mode::AMAudio");
|
||||
break;
|
||||
case ReceiverModel::Mode::NarrowbandFMAudio:
|
||||
pmem_dump_file.write_line("modulation: Mode::NarrowbandFMAudio");
|
||||
break;
|
||||
case ReceiverModel::Mode::WidebandFMAudio:
|
||||
pmem_dump_file.write_line("modulation: Mode::WidebandFMAudio");
|
||||
break;
|
||||
case ReceiverModel::Mode::SpectrumAnalysis:
|
||||
pmem_dump_file.write_line("modulation: Mode::SpectrumAnalysis");
|
||||
break;
|
||||
case ReceiverModel::Mode::Capture:
|
||||
pmem_dump_file.write_line("modulation: Mode::Capture");
|
||||
break;
|
||||
case ReceiverModel::Mode::AMAudioFMApt:
|
||||
pmem_dump_file.write_line("modulation: Mode::AMAudioFMApt");
|
||||
break;
|
||||
default:
|
||||
pmem_dump_file.write_line("modulation: !!unknown mode!!");
|
||||
break;
|
||||
}
|
||||
pmem_dump_file.write_line("headphone_volume.centibel: " + to_string_dec_int(receiver_model.headphone_volume().centibel()));
|
||||
pmem_dump_file.write_line("normalized_headphone_volume: " + to_string_dec_uint(receiver_model.normalized_headphone_volume()));
|
||||
pmem_dump_file.write_line("am_configuration: " + to_string_dec_uint(receiver_model.am_configuration()));
|
||||
pmem_dump_file.write_line("nbfm_configuration: " + to_string_dec_uint(receiver_model.nbfm_configuration()));
|
||||
pmem_dump_file.write_line("wfm_configuration: " + to_string_dec_uint(receiver_model.wfm_configuration()));
|
||||
|
||||
// transmitter_model
|
||||
pmem_dump_file.write_line("\n[Transmitter Model]");
|
||||
pmem_dump_file.write_line("target_frequency: " + to_string_dec_uint(transmitter_model.target_frequency()));
|
||||
pmem_dump_file.write_line("rf_amp: " + to_string_dec_int(transmitter_model.rf_amp()));
|
||||
pmem_dump_file.write_line("baseband_bandwidth: " + to_string_dec_uint(transmitter_model.baseband_bandwidth()));
|
||||
pmem_dump_file.write_line("sampling_rate: " + to_string_dec_uint(transmitter_model.sampling_rate()));
|
||||
pmem_dump_file.write_line("tx_gain: " + to_string_dec_int(transmitter_model.tx_gain()));
|
||||
pmem_dump_file.write_line("channel_bandwidth: " + to_string_dec_uint(transmitter_model.channel_bandwidth()));
|
||||
// on screen information
|
||||
dump_output.set(filename.filename().string() + " DUMPED !");
|
||||
dump_output.set_style(ui::Theme::getInstance()->fg_green);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DebugDumpView::DebugDumpView(NavigationView& nav)
|
||||
: nav_{nav} {
|
||||
add_children({&dump_output,
|
||||
&button_exit});
|
||||
|
||||
debug_dump_func();
|
||||
|
||||
button_exit.on_select = [this](Button&) {
|
||||
nav_.pop();
|
||||
};
|
||||
}
|
||||
|
||||
void DebugDumpView::focus() {
|
||||
button_exit.focus();
|
||||
}
|
||||
|
||||
} // namespace ui::external_app::debug_pmem
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2018 Furrtek
|
||||
*
|
||||
* 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 __UI_DEBUG_PMEM_APP_H__
|
||||
#define __UI_DEBUG_PMEM_APP_H__
|
||||
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
#include "ui_flash_utility.hpp"
|
||||
|
||||
using namespace portapack;
|
||||
using namespace portapack::persistent_memory;
|
||||
|
||||
namespace ui::external_app::debug_pmem {
|
||||
|
||||
class DebugDumpView : public View {
|
||||
public:
|
||||
DebugDumpView(NavigationView& nav);
|
||||
|
||||
void focus() override;
|
||||
|
||||
std::string title() const override { return "DebugPMem"; };
|
||||
bool debug_dump_func();
|
||||
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
|
||||
Text dump_output{
|
||||
{0 * 8, 19 * 8, 30 * 8, 16},
|
||||
""};
|
||||
|
||||
Button button_exit{
|
||||
{22 * 8, 34 * 8, 8 * 8, 32},
|
||||
"Exit"};
|
||||
};
|
||||
|
||||
} // namespace ui::external_app::debug_pmem
|
||||
|
||||
#endif /*__UI_DEBUG_PMEM_APP_H__*/
|
||||
+14
-4
@@ -192,9 +192,17 @@ set(EXTCPPSRC
|
||||
external/doom/main.cpp
|
||||
external/doom/ui_doom.cpp
|
||||
|
||||
#screening
|
||||
# external/screening/main.cpp
|
||||
# external/screening/ui_screening.cpp
|
||||
#debug_pmem
|
||||
external/debug_pmem/main.cpp
|
||||
external/debug_pmem/ui_debug_pmem.cpp
|
||||
|
||||
#scanner
|
||||
external/scanner/main.cpp
|
||||
external/scanner/ui_scanner.cpp
|
||||
|
||||
#level
|
||||
external/level/main.cpp
|
||||
external/level/ui_level.cpp
|
||||
)
|
||||
|
||||
set(EXTAPPLIST
|
||||
@@ -244,5 +252,7 @@ set(EXTAPPLIST
|
||||
stopwatch
|
||||
breakout
|
||||
doom
|
||||
# screening
|
||||
debug_pmem
|
||||
scanner
|
||||
level
|
||||
)
|
||||
|
||||
+18
-10
@@ -69,8 +69,9 @@ MEMORY
|
||||
ram_external_app_wefax_rx (rwx) : org = 0xADDC0000, len = 32k
|
||||
ram_external_app_breakout (rwx) : org = 0xADDD0000, len = 32k
|
||||
ram_external_app_doom (rwx) : org = 0xADDE0000, len = 32k
|
||||
/*ram_external_app_screening (rwx) : org = 0xADDF0000, len = 32k*/
|
||||
|
||||
ram_external_app_debug_pmem (rwx) : org = 0xADDF0000, len = 32k
|
||||
ram_external_app_scanner (rwx) : org = 0xADE00000, len = 32k
|
||||
ram_external_app_level (rwx) : org = 0xADE10000, len = 32k
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
@@ -349,15 +350,22 @@ SECTIONS
|
||||
KEEP(*(.external_app.app_doom.application_information));
|
||||
*(*ui*external_app*doom*);
|
||||
} > ram_external_app_doom
|
||||
|
||||
/*
|
||||
.external_app_screening : ALIGN(4) SUBALIGN(4)
|
||||
|
||||
.external_app_debug_pmem : ALIGN(4) SUBALIGN(4)
|
||||
{
|
||||
KEEP(*(.external_app.app_screening.application_information));
|
||||
*(*ui*external_app*screening*);
|
||||
} > ram_external_app_screening
|
||||
|
||||
*/
|
||||
KEEP(*(.external_app.app_debug_pmem.application_information));
|
||||
*(*ui*external_app*debug_pmem*);
|
||||
} > ram_external_app_debug_pmem
|
||||
|
||||
.external_app_scanner : ALIGN(4) SUBALIGN(4)
|
||||
{
|
||||
KEEP(*(.external_app.app_scanner.application_information));
|
||||
*(*ui*external_app*scanner*);
|
||||
} > ram_external_app_scanner
|
||||
|
||||
.external_app_level : ALIGN(4) SUBALIGN(4)
|
||||
{
|
||||
KEEP(*(.external_app.app_level.application_information));
|
||||
*(*ui*external_app*level*);
|
||||
} > ram_external_app_level
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ void DebugFontsView::paint(Painter& painter) {
|
||||
|
||||
line_pos = display_font(painter, 32, Theme::getInstance()->bg_darkest, "Fixed 8x16", true);
|
||||
display_font(painter, line_pos + 16, Theme::getInstance()->bg_darkest_small, "Fixed 5x8", false);
|
||||
paint_zoomed_text(painter);
|
||||
}
|
||||
|
||||
void DebugFontsView::update_address_text() {
|
||||
@@ -74,16 +75,29 @@ void DebugFontsView::update_address_text() {
|
||||
text_address.set("0x" + to_string_hex(ascii_value, 2));
|
||||
}
|
||||
|
||||
void DebugFontsView::paint_zoomed_text(Painter& painter) {
|
||||
if (field_zoom_level.value() == 0) return;
|
||||
uint8_t cursor_pos = field_cursor.value();
|
||||
painter.draw_char({screen_width / 2, screen_height / 2},
|
||||
*Theme::getInstance()->bg_darkest,
|
||||
(char)(cursor_pos + 0x20), field_zoom_level.value());
|
||||
}
|
||||
|
||||
DebugFontsView::DebugFontsView(NavigationView& nav)
|
||||
: nav_{nav} {
|
||||
add_children({&field_cursor,
|
||||
&text_address});
|
||||
&text_address,
|
||||
&field_zoom_level});
|
||||
set_focusable(true);
|
||||
|
||||
field_cursor.on_change = [&](int32_t) {
|
||||
update_address_text();
|
||||
set_dirty();
|
||||
};
|
||||
|
||||
field_zoom_level.on_change = [&](int32_t) {
|
||||
set_dirty();
|
||||
};
|
||||
}
|
||||
|
||||
void DebugFontsView::focus() {
|
||||
|
||||
@@ -46,10 +46,17 @@ class DebugFontsView : public View {
|
||||
private:
|
||||
uint16_t display_font(Painter& painter, uint16_t y_offset, const Style* font_style, std::string_view font_name, bool is_big_font);
|
||||
void update_address_text();
|
||||
void paint_zoomed_text(Painter& painter);
|
||||
|
||||
NumberField field_cursor{
|
||||
{0 * 8, 0 * 8},
|
||||
4,
|
||||
{0, 1000},
|
||||
1,
|
||||
' '};
|
||||
NumberField field_zoom_level{
|
||||
{6 * 8, 0 * 8},
|
||||
4,
|
||||
{0, 1000},
|
||||
1,
|
||||
' '};
|
||||
|
||||
@@ -227,6 +227,7 @@ void HopperView::save_list() {
|
||||
nav_,
|
||||
filename_buffer,
|
||||
64,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& value) {
|
||||
auto path = hopper_dir / (value + ".PHOP");
|
||||
|
||||
|
||||
@@ -189,6 +189,7 @@ void LCRView::on_button_set_am(NavigationView& nav, int16_t button_id) {
|
||||
nav,
|
||||
litteral[button_id],
|
||||
7,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this, button_id](std::string& buffer) {
|
||||
texts[button_id].set(buffer);
|
||||
});
|
||||
@@ -257,6 +258,7 @@ LCRView::LCRView(NavigationView& nav) {
|
||||
nav,
|
||||
rgsb,
|
||||
4,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& buffer) {
|
||||
button_set_rgsb.set_text(buffer);
|
||||
});
|
||||
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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_level.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "external_app.hpp"
|
||||
|
||||
namespace ui::external_app::level {
|
||||
void initialize_app(ui::NavigationView& nav) {
|
||||
nav.push<LevelView>();
|
||||
}
|
||||
} // namespace ui::external_app::level
|
||||
|
||||
extern "C" {
|
||||
|
||||
__attribute__((section(".external_app.app_level.application_information"), used)) application_information_t _application_information_level = {
|
||||
/*.memory_location = */ (uint8_t*)0x00000000,
|
||||
/*.externalAppEntry = */ ui::external_app::level::initialize_app,
|
||||
/*.header_version = */ CURRENT_HEADER_VERSION,
|
||||
/*.app_version = */ VERSION_MD5,
|
||||
|
||||
/*.app_name = */ "Level",
|
||||
/*.bitmap_data = */
|
||||
{
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x04,
|
||||
0x20,
|
||||
0x12,
|
||||
0x48,
|
||||
0x8A,
|
||||
0x51,
|
||||
0xCA,
|
||||
0x53,
|
||||
0xCA,
|
||||
0x53,
|
||||
0x8A,
|
||||
0x51,
|
||||
0x12,
|
||||
0x48,
|
||||
0x84,
|
||||
0x21,
|
||||
0xC0,
|
||||
0x03,
|
||||
0x40,
|
||||
0x02,
|
||||
0x60,
|
||||
0x06,
|
||||
0x20,
|
||||
0x04,
|
||||
0x30,
|
||||
0x0C,
|
||||
0xF0,
|
||||
0x0F},
|
||||
/*.icon_color = */ ui::Color::green().v,
|
||||
/*.menu_location = */ app_location_t::RX,
|
||||
/*.desired_menu_position = */ -1,
|
||||
|
||||
// this has to be the biggest baseband used by the app. Level is using AM,WFM,NFM,AMFM,SPEC and NFM is the biggest
|
||||
/*.m4_app_tag = portapack::spi_flash::image_tag_nfm */ {'P', 'N', 'F', 'M'},
|
||||
/*.m4_app_offset = */ 0x00000000, // will be filled at compile time
|
||||
};
|
||||
}
|
||||
+11
-13
@@ -33,7 +33,7 @@ using namespace portapack;
|
||||
using namespace tonekey;
|
||||
using portapack::memory::map::backup_ram;
|
||||
|
||||
namespace ui {
|
||||
namespace ui::external_app::level {
|
||||
|
||||
// Function to map the value from one range to another
|
||||
int32_t LevelView::map(int32_t value, int32_t fromLow, int32_t fromHigh, int32_t toLow, int32_t toHigh) {
|
||||
@@ -130,9 +130,16 @@ LevelView::LevelView(NavigationView& nav)
|
||||
|
||||
freqman_set_modulation_option(field_mode);
|
||||
field_mode.on_change = [this](size_t, OptionsField::value_t v) {
|
||||
if (v != -1) {
|
||||
change_mode(v);
|
||||
static freqman_index_t last_mode = WFM_MODULATION;
|
||||
if (v > SPEC_MODULATION) {
|
||||
if (last_mode == SPEC_MODULATION)
|
||||
v = AM_MODULATION;
|
||||
else
|
||||
v = SPEC_MODULATION;
|
||||
field_mode.set_selected_index(v);
|
||||
}
|
||||
last_mode = v;
|
||||
change_mode(v);
|
||||
};
|
||||
field_mode.set_by_value(radio_mode); // Reflect the mode into the manual selector
|
||||
field_bw.set_selected_index(radio_bw);
|
||||
@@ -277,15 +284,6 @@ size_t LevelView::change_mode(freqman_index_t new_mod) {
|
||||
field_bw.set_by_value(0);
|
||||
field_bw.on_change = [this](size_t index, OptionsField::value_t n) { radio_bw = index ; receiver_model.set_wfm_configuration(n); };
|
||||
break;
|
||||
case AMFM_MODULATION:
|
||||
audio_sampling_rate = audio::Rate::Hz_12000;
|
||||
freqman_set_bandwidth_option(new_mod, field_bw);
|
||||
baseband::run_image(portapack::spi_flash::image_tag_am_audio);
|
||||
receiver_model.set_modulation(ReceiverModel::Mode::AMAudioFMApt);
|
||||
receiver_model.set_amfm_configuration(5); // Fix index 5 manually, not from freqman: set to RX AM (USB+FM) mode to demod audio tone, and get Wefax_APT signal.
|
||||
field_bw.set_by_value(0);
|
||||
field_bw.on_change = [this](size_t, OptionsField::value_t n) { (void)n; };
|
||||
break;
|
||||
case SPEC_MODULATION:
|
||||
audio_sampling_rate = audio::Rate::Hz_24000;
|
||||
freqman_set_bandwidth_option(new_mod, field_bw);
|
||||
@@ -338,4 +336,4 @@ void LevelView::on_freqchg(int64_t freq) {
|
||||
button_frequency.set_text("<" + to_string_short_freq(freq) + " MHz>");
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
} // namespace ui::external_app::level
|
||||
+2
-2
@@ -39,7 +39,7 @@
|
||||
#include "ui_receiver.hpp"
|
||||
#include "ui_spectrum.hpp"
|
||||
|
||||
namespace ui {
|
||||
namespace ui::external_app::level {
|
||||
|
||||
class LevelView : public View {
|
||||
public:
|
||||
@@ -211,6 +211,6 @@ class LevelView : public View {
|
||||
}};
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
} // namespace ui::external_app::level
|
||||
|
||||
#endif
|
||||
@@ -311,6 +311,7 @@ LGEView::LGEView(NavigationView& nav) {
|
||||
nav,
|
||||
nickname,
|
||||
15,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& buffer) {
|
||||
button_text.set_text(buffer);
|
||||
});
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "baseband_api.hpp"
|
||||
#include "audio.hpp"
|
||||
#include "portapack.hpp"
|
||||
#include "ui_textentry.hpp"
|
||||
|
||||
using namespace portapack;
|
||||
|
||||
@@ -42,6 +43,7 @@ MetronomeView::MetronomeView(NavigationView& nav)
|
||||
&field_unaccent_beep_tune,
|
||||
&field_beep_flash_duration,
|
||||
&field_bpm,
|
||||
&button_enter_tap_tempo,
|
||||
&progressbar,
|
||||
});
|
||||
|
||||
@@ -59,6 +61,14 @@ MetronomeView::MetronomeView(NavigationView& nav)
|
||||
}
|
||||
};
|
||||
|
||||
button_enter_tap_tempo.on_select = [this](Button&) {
|
||||
auto tap_tempo_view = nav_.push<MetronomeTapTempoView>(field_bpm.value());
|
||||
|
||||
tap_tempo_view->on_apply = [this](uint16_t bpm) {
|
||||
field_bpm.set_value(bpm);
|
||||
};
|
||||
};
|
||||
|
||||
field_volume.set_value(0); // seems that a change is required to force update, so setting to 0 first
|
||||
field_volume.set_value(99);
|
||||
|
||||
@@ -174,4 +184,116 @@ void MetronomeView::run() {
|
||||
}
|
||||
}
|
||||
|
||||
MetronomeTapTempoView::MetronomeTapTempoView(NavigationView& nav, uint16_t bpm)
|
||||
: nav_{nav},
|
||||
bpm_{bpm} {
|
||||
add_children({
|
||||
&button_input,
|
||||
&button_tap,
|
||||
&button_cancel,
|
||||
&button_apply,
|
||||
});
|
||||
|
||||
bpm_when_entered_ = bpm; // save for if user cancel
|
||||
|
||||
// im aware that we have duplicated painter which means in this app, weo have two painter instances
|
||||
// here is the reason why this is necessary:
|
||||
// We need to draw the bpm big font once when enter, which would be at bad timing in constructor,
|
||||
// cuz it happened before the view is pushed to nav, which casued it actually didn't draw
|
||||
// which leads me have to override the paint func from father and draw inside of it.
|
||||
//
|
||||
// BUT I can't completely package the draw logic inside of the paint func,
|
||||
// cuz set_dirty has flaw and cause screen flicker during the char changes, if i just package there and use set_dirty()
|
||||
Painter painter_instance_2;
|
||||
|
||||
button_input.on_select = [this](Button&) {
|
||||
input_buffer = to_string_dec_uint(bpm_);
|
||||
text_prompt(
|
||||
nav_,
|
||||
input_buffer,
|
||||
3,
|
||||
ENTER_KEYBOARD_MODE_DIGITS,
|
||||
[this](std::string& buffer) {
|
||||
if (buffer.empty()) {
|
||||
return;
|
||||
}
|
||||
bpm_ = atoi(buffer.c_str());
|
||||
|
||||
if (on_apply) {
|
||||
on_apply(bpm_);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
button_tap.on_select = [&](Button&) {
|
||||
on_tap(painter_instance_2);
|
||||
};
|
||||
|
||||
button_apply.on_select = [this](Button&) {
|
||||
// it's dynamically applied in tap handler
|
||||
// the design allow user to hear changes before apply
|
||||
nav_.pop();
|
||||
};
|
||||
|
||||
button_cancel.on_select = [this](Button&) {
|
||||
bpm_ = bpm_when_entered_;
|
||||
if (on_apply) {
|
||||
on_apply(bpm_);
|
||||
}
|
||||
nav_.pop();
|
||||
};
|
||||
}
|
||||
|
||||
void MetronomeTapTempoView::focus() {
|
||||
button_tap.focus();
|
||||
}
|
||||
|
||||
void MetronomeTapTempoView::paint(Painter& painter) {
|
||||
View::paint(painter);
|
||||
painter.draw_char({(0 * 16) * 4 + 2 * 16, 3 * 16}, *Theme::getInstance()->fg_light, '0' + bpm_ / 100, 4);
|
||||
painter.draw_char({(1 * 16) * 4 + 2 * 16, 3 * 16}, *Theme::getInstance()->fg_light, '0' + (bpm_ / 10) % 10, 4);
|
||||
painter.draw_char({(2 * 16) * 4 + 2 * 16, 3 * 16}, *Theme::getInstance()->fg_light, '0' + bpm_ % 10, 4);
|
||||
}
|
||||
|
||||
/*
|
||||
NB: i don't really know if the cpu clock is 1000Hz AKA 1ms per tick for chTimeNow()
|
||||
but it should be, refering to the stop watch app.
|
||||
and also i compared with my real metronome and it's very close
|
||||
so I assume it's 1ms per tick
|
||||
*/
|
||||
void MetronomeTapTempoView::on_tap(Painter& painter) {
|
||||
/* ^ NB: this painter accepted from painter_instance_2*/
|
||||
systime_t current_time = chTimeNow();
|
||||
if (last_tap_time > 0) {
|
||||
uint32_t interval_ms = current_time - last_tap_time;
|
||||
|
||||
if (interval_ms > 100) {
|
||||
uint16_t this_time_bpm = 60000 / interval_ms;
|
||||
|
||||
if (this_time_bpm > 0 && this_time_bpm < 400) {
|
||||
bpms_deque.push_back(this_time_bpm);
|
||||
if (bpms_deque.size() > 4) { // one bar length cuz most music tempo is quarter note as 1 beat
|
||||
bpms_deque.pop_front();
|
||||
}
|
||||
|
||||
// avg
|
||||
uint32_t sum = 0;
|
||||
for (auto& bpm : bpms_deque) {
|
||||
sum += bpm;
|
||||
}
|
||||
bpm_ = sum / bpms_deque.size();
|
||||
|
||||
if (on_apply) {
|
||||
on_apply(bpm_);
|
||||
}
|
||||
|
||||
painter.draw_char({(0 * 16) * 4 + 2 * 16, 3 * 16}, *Theme::getInstance()->fg_light, '0' + bpm_ / 100, 4);
|
||||
painter.draw_char({(1 * 16) * 4 + 2 * 16, 3 * 16}, *Theme::getInstance()->fg_light, '0' + (bpm_ / 10) % 10, 4);
|
||||
painter.draw_char({(2 * 16) * 4 + 2 * 16, 3 * 16}, *Theme::getInstance()->fg_light, '0' + bpm_ % 10, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
last_tap_time = current_time;
|
||||
}
|
||||
|
||||
} // namespace ui::external_app::metronome
|
||||
@@ -27,6 +27,8 @@
|
||||
#include "audio.hpp"
|
||||
#include "ch.h"
|
||||
|
||||
#include <deque>
|
||||
|
||||
namespace ui::external_app::metronome {
|
||||
|
||||
class MetronomeView : public View {
|
||||
@@ -73,6 +75,11 @@ class MetronomeView : public View {
|
||||
1,
|
||||
' '};
|
||||
|
||||
Button button_enter_tap_tempo{
|
||||
{(sizeof("BPM:") + 6) * 8, 1 * 16, (sizeof("Tap Tempo") + 3) * 8, 16},
|
||||
"Tap Tempo",
|
||||
};
|
||||
|
||||
NumberField field_rythm_unaccent_time{// e.g. 3 in 3/4 beat
|
||||
{(sizeof("Rhythm:") + 1) * 8, 4 * 16},
|
||||
2,
|
||||
@@ -121,6 +128,45 @@ class MetronomeView : public View {
|
||||
{0 * 16, 8 * 16, screen_width, screen_height - 14 * 16}};
|
||||
};
|
||||
|
||||
class MetronomeTapTempoView : public View {
|
||||
public:
|
||||
std::function<void(uint16_t)> on_apply{};
|
||||
|
||||
MetronomeTapTempoView(NavigationView& nav, uint16_t bpm);
|
||||
|
||||
std::string title() const override { return "Tap.T"; };
|
||||
void focus() override;
|
||||
void paint(Painter& painter) override;
|
||||
|
||||
private:
|
||||
void on_tap(Painter& painter);
|
||||
|
||||
NavigationView& nav_;
|
||||
|
||||
uint16_t bpm_{0};
|
||||
uint16_t bpm_when_entered_{0}; // this pass from MetronomeView and need to restore if user cancel
|
||||
std::deque<uint16_t> bpms_deque = {0}; // take average for recent taps to debounce
|
||||
uint32_t last_tap_time{0};
|
||||
|
||||
std::string input_buffer{""}; // needed by text_prompt
|
||||
|
||||
Button button_input{
|
||||
{0, 0, screen_width, 2 * 16},
|
||||
"Input BPM"};
|
||||
|
||||
Button button_tap{
|
||||
{0, 8 * 16, screen_width, 7 * 16},
|
||||
"Tap BPM"};
|
||||
|
||||
Button button_cancel{
|
||||
{1, 17 * 16, screen_width / 2 - 4, 2 * 16},
|
||||
"Cancel"};
|
||||
|
||||
Button button_apply{
|
||||
{1 + screen_width / 2 + 1, 17 * 16, screen_width / 2 - 4, 2 * 16},
|
||||
"Apply"};
|
||||
};
|
||||
|
||||
} // namespace ui::external_app::metronome
|
||||
|
||||
#endif /*__UI_METRONOME_H__*/
|
||||
+1
-1
@@ -99,7 +99,7 @@ static msg_t loopthread_fn(void* arg) {
|
||||
}
|
||||
|
||||
void MorseView::on_set_text(NavigationView& nav) {
|
||||
text_prompt(nav, buffer, 28);
|
||||
text_prompt(nav, buffer, 28, ENTER_KEYBOARD_MODE_ALPHA);
|
||||
}
|
||||
|
||||
void MorseView::focus() {
|
||||
|
||||
@@ -210,6 +210,7 @@ OOKEditorAppView::OOKEditorAppView(NavigationView& nav)
|
||||
nav,
|
||||
outputFileBuffer,
|
||||
64,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& buffer) {
|
||||
on_save_file(buffer);
|
||||
});
|
||||
@@ -263,6 +264,7 @@ OOKEditorAppView::OOKEditorAppView(NavigationView& nav)
|
||||
nav,
|
||||
ook_data.payload,
|
||||
100,
|
||||
ENTER_KEYBOARD_MODE_DIGITS,
|
||||
[this](std::string& s) {
|
||||
text_payload.set(s);
|
||||
draw_waveform();
|
||||
|
||||
@@ -83,6 +83,7 @@ OOKBruteView::OOKBruteView(NavigationView& nav)
|
||||
nav_,
|
||||
text_input_buffer,
|
||||
8, // currently longest is princeton
|
||||
ENTER_KEYBOARD_MODE_DIGITS,
|
||||
[this](std::string& buffer) {
|
||||
field_start.set_value(atoi(buffer.c_str()));
|
||||
validate_start_stop();
|
||||
@@ -100,6 +101,7 @@ OOKBruteView::OOKBruteView(NavigationView& nav)
|
||||
nav_,
|
||||
text_input_buffer,
|
||||
8, // currently longest is princeton
|
||||
ENTER_KEYBOARD_MODE_DIGITS,
|
||||
[this](std::string& buffer) {
|
||||
field_stop.set_value(atoi(buffer.c_str()));
|
||||
validate_start_stop();
|
||||
|
||||
@@ -122,6 +122,7 @@ bool PlaylistEditorView::on_create_ppl() {
|
||||
nav_,
|
||||
current_ppl_name_buffer,
|
||||
100,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[&](std::string& s) {
|
||||
current_ppl_name_buffer = s;
|
||||
|
||||
@@ -307,6 +308,7 @@ PlaylistItemEditView::PlaylistItemEditView(
|
||||
nav_,
|
||||
delay_str,
|
||||
100,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[&](std::string& s) {
|
||||
delay_ = atoi(s.c_str());
|
||||
field_delay.set_value(delay_);
|
||||
|
||||
+2
-2
@@ -330,7 +330,7 @@ RemoteAppView::RemoteAppView(
|
||||
|
||||
field_title.on_select = [this, &nav](TextField&) {
|
||||
temp_buffer_ = model_.name;
|
||||
text_prompt(nav_, temp_buffer_, text_edit_max, [this](std::string& new_name) {
|
||||
text_prompt(nav_, temp_buffer_, text_edit_max, ENTER_KEYBOARD_MODE_ALPHA, [this](std::string& new_name) {
|
||||
model_.name = new_name;
|
||||
refresh_ui();
|
||||
set_needs_save();
|
||||
@@ -339,7 +339,7 @@ RemoteAppView::RemoteAppView(
|
||||
|
||||
field_filename.on_select = [this, &nav](TextField&) {
|
||||
temp_buffer_ = remote_path_.stem().string();
|
||||
text_prompt(nav_, temp_buffer_, text_edit_max, [this](std::string& new_name) {
|
||||
text_prompt(nav_, temp_buffer_, text_edit_max, ENTER_KEYBOARD_MODE_ALPHA, [this](std::string& new_name) {
|
||||
rename_remote(new_name);
|
||||
refresh_ui();
|
||||
});
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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_scanner.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "external_app.hpp"
|
||||
|
||||
namespace ui::external_app::scanner {
|
||||
void initialize_app(ui::NavigationView& nav) {
|
||||
nav.push<ScannerView>();
|
||||
}
|
||||
} // namespace ui::external_app::scanner
|
||||
|
||||
extern "C" {
|
||||
|
||||
__attribute__((section(".external_app.app_scanner.application_information"), used)) application_information_t _application_information_scanner = {
|
||||
/*.memory_location = */ (uint8_t*)0x00000000,
|
||||
/*.externalAppEntry = */ ui::external_app::scanner::initialize_app,
|
||||
/*.header_version = */ CURRENT_HEADER_VERSION,
|
||||
/*.app_version = */ VERSION_MD5,
|
||||
|
||||
/*.app_name = */ "Scanner",
|
||||
/*.bitmap_data = */ {0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x03, 0x01, 0x80, 0x01, 0xC3, 0x00, 0xE0, 0xFF, 0xEF, 0xFF, 0xC0, 0x00, 0x83, 0x01, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00},
|
||||
/*.icon_color = */ ui::Color::green().v,
|
||||
/*.menu_location = */ app_location_t::RX,
|
||||
/*.desired_menu_position = */ -1,
|
||||
|
||||
// this has to be the biggest baseband used by the app. Scanner is using AM,WFM,NFM and NFM is the biggest
|
||||
/*.m4_app_tag = portapack::spi_flash::image_tag_scanner */ {'P', 'N', 'F', 'M'},
|
||||
/*.m4_app_offset = */ 0x00000000, // will be filled at compile time
|
||||
};
|
||||
}
|
||||
Vendored
+9
-16
@@ -28,10 +28,11 @@
|
||||
#include "ui_freqman.hpp"
|
||||
#include "file_path.hpp"
|
||||
|
||||
using namespace ui;
|
||||
using namespace portapack;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace ui {
|
||||
namespace ui::external_app::scanner {
|
||||
|
||||
ScannerThread::ScannerThread(std::vector<rf::Frequency> frequency_list)
|
||||
: frequency_list_{std::move(frequency_list)} {
|
||||
@@ -451,13 +452,14 @@ ScannerView::ScannerView(
|
||||
|
||||
// Mode field was changed (AM/NFM/WFM)
|
||||
field_mode.on_change = [this](size_t, OptionsField::value_t v) {
|
||||
static freqman_index_t last_mode = AM_MODULATION;
|
||||
// initialize to a value under SPEC
|
||||
static freqman_index_t last_mode = WFM_MODULATION;
|
||||
// unsupported SPEC mode fix
|
||||
if (v == SPEC_MODULATION) {
|
||||
if (last_mode == AM_MODULATION)
|
||||
v = WFM_MODULATION;
|
||||
else
|
||||
if (v >= SPEC_MODULATION) {
|
||||
if (last_mode == WFM_MODULATION)
|
||||
v = AM_MODULATION;
|
||||
else
|
||||
v = WFM_MODULATION;
|
||||
field_mode.set_selected_index(v);
|
||||
}
|
||||
last_mode = v;
|
||||
@@ -725,14 +727,6 @@ void ScannerView::change_mode(freqman_index_t new_mod) {
|
||||
field_bw.set_by_value(receiver_model.wfm_configuration());
|
||||
field_bw.on_change = [this](size_t, OptionsField::value_t n) { receiver_model.set_wfm_configuration(n); };
|
||||
break;
|
||||
case AMFM_MODULATION:
|
||||
freqman_set_bandwidth_option(new_mod, field_bw);
|
||||
baseband::run_image(portapack::spi_flash::image_tag_am_audio);
|
||||
receiver_model.set_modulation(ReceiverModel::Mode::AMAudioFMApt);
|
||||
receiver_model.set_amfm_configuration(5);
|
||||
field_bw.set_by_value(0);
|
||||
field_bw.on_change = [this](size_t, OptionsField::value_t n) { (void)n; };
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -773,5 +767,4 @@ void ScannerView::restart_scan() {
|
||||
|
||||
start_scan_thread(); // RESTART SCANNER THREAD in selected mode
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
} // namespace ui::external_app::scanner
|
||||
Vendored
+5
-4
@@ -35,12 +35,14 @@
|
||||
#include "ui_mictx.hpp"
|
||||
#include "ui_receiver.hpp"
|
||||
|
||||
using namespace ui;
|
||||
|
||||
namespace ui::external_app::scanner {
|
||||
|
||||
#define SCANNER_SLEEP_MS 50 // ms that Scanner Thread sleeps per loop
|
||||
#define STATISTICS_UPDATES_PER_SEC 10
|
||||
#define MAX_FREQ_LOCK 10 // # of 50ms cycles scanner locks into freq when signal detected, to verify signal is not spurious
|
||||
|
||||
namespace ui {
|
||||
|
||||
// TODO: There is too much duplicated data in these classes.
|
||||
// ScannerThread should just use more from the View.
|
||||
// Or perhaps ScannerThread should just be in the View.
|
||||
@@ -314,5 +316,4 @@ class ScannerView : public View {
|
||||
this->on_statistics_update(static_cast<const ChannelStatisticsMessage*>(p)->statistics);
|
||||
}};
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
} // namespace ui::external_app::scanner
|
||||
@@ -1,6 +1,8 @@
|
||||
// CVS Spam app by RocketGod (@rocketgod-git) https://betaskynet.com
|
||||
// Original .cu8 files by @jimilinuxguy https://github.com/jimilinuxguy/customer-assistance-buttons-sdr
|
||||
// If you can read this, you're a nerd. :P
|
||||
// Come join us at https://discord.gg/thepiratesreborn
|
||||
|
||||
// RocketGod's Shopping Cart Lock app
|
||||
// https://betaskynet.com
|
||||
#include "ui.hpp"
|
||||
#include "shoppingcart_lock.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
@@ -57,10 +59,10 @@ __attribute__((section(".external_app.app_shoppingcart_lock.application_informat
|
||||
0x00,
|
||||
},
|
||||
/*.icon_color = */ ui::Color::red().v,
|
||||
/*.menu_location = */ app_location_t::TX,
|
||||
/*.menu_location = */ app_location_t::UTILITIES,
|
||||
/*.desired_menu_position = */ -1,
|
||||
|
||||
/*.m4_app_tag = portapack::spi_flash::image_tag_afsk_rx */ {'P', 'A', 'T', 'X'},
|
||||
/*.m4_app_offset = */ 0x00000000, // will be filled at compile time
|
||||
/*.m4_app_tag = portapack::spi_flash::image_tag_audio_tx */ {'P', 'A', 'T', 'X'},
|
||||
/*.m4_app_offset = */ 0x00000000,
|
||||
};
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
// RocketGod's Shopping Cart Lock app
|
||||
// https://betaskynet.com
|
||||
// CVS Spam app by RocketGod (@rocketgod-git) https://betaskynet.com
|
||||
// Original .cu8 files by @jimilinuxguy https://github.com/jimilinuxguy/customer-assistance-buttons-sdr
|
||||
// If you can read this, you're a nerd. :P
|
||||
// Come join us at https://discord.gg/thepiratesreborn
|
||||
|
||||
#include "shoppingcart_lock.hpp"
|
||||
|
||||
using namespace portapack;
|
||||
@@ -48,7 +51,6 @@ void ShoppingCartLock::stop() {
|
||||
audio::output::stop();
|
||||
|
||||
log_event("... Resetting State Variables");
|
||||
transmitter_model.disable();
|
||||
ready_signal = false;
|
||||
thread_sync_complete = false;
|
||||
looping = false;
|
||||
@@ -110,18 +112,24 @@ std::string ShoppingCartLock::list_wav_files() {
|
||||
}
|
||||
|
||||
void ShoppingCartLock::wait_for_thread() {
|
||||
uint32_t timeout = 100;
|
||||
uint32_t timeout = 1000;
|
||||
while (!ready_signal && timeout > 0) {
|
||||
chThdYield();
|
||||
timeout--;
|
||||
}
|
||||
if (!ready_signal) {
|
||||
log_event("!!! Timeout waiting for ReplayThread");
|
||||
}
|
||||
}
|
||||
|
||||
void ShoppingCartLock::restart_playback() {
|
||||
auto reader = std::make_unique<WAVFileReader>();
|
||||
std::string file_path = (wav_dir / current_file).string();
|
||||
|
||||
if (!reader->open(file_path)) return;
|
||||
if (!reader->open(file_path)) {
|
||||
log_event("!!! Failed to reopen " + current_file + " for restart");
|
||||
return;
|
||||
}
|
||||
|
||||
replay_thread = std::make_unique<ReplayThread>(
|
||||
std::move(reader),
|
||||
@@ -133,9 +141,8 @@ void ShoppingCartLock::restart_playback() {
|
||||
EventDispatcher::send_message(message);
|
||||
});
|
||||
|
||||
log_event(">> SENDING <<");
|
||||
log_event(">> RESTARTING AUDIO <<");
|
||||
audio::output::start();
|
||||
transmitter_model.enable();
|
||||
}
|
||||
|
||||
void ShoppingCartLock::play_audio(const std::string& filename, bool loop) {
|
||||
@@ -166,33 +173,24 @@ void ShoppingCartLock::play_audio(const std::string& filename, bool loop) {
|
||||
|
||||
wait_for_thread();
|
||||
|
||||
log_event("... Configuring Baseband");
|
||||
|
||||
const uint32_t bb_sample_rate = 1536000;
|
||||
const uint32_t decimation = bb_sample_rate / wav_sample_rate;
|
||||
|
||||
baseband::set_sample_rate(wav_sample_rate);
|
||||
audio::set_rate(wav_sample_rate <= 12000 ? audio::Rate::Hz_12000 : wav_sample_rate <= 24000 ? audio::Rate::Hz_24000
|
||||
: audio::Rate::Hz_48000);
|
||||
baseband::set_audiotx_config(
|
||||
bb_sample_rate / decimation,
|
||||
wav_sample_rate,
|
||||
0.0f,
|
||||
0.0f,
|
||||
5.0f,
|
||||
wav_bits_per_sample,
|
||||
wav_bits_per_sample,
|
||||
0,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false);
|
||||
|
||||
baseband::set_sample_rate(wav_sample_rate);
|
||||
|
||||
log_event("... Starting Audio Output");
|
||||
audio::output::start();
|
||||
log_event("... Setting Max Volume");
|
||||
audio::headphone::set_volume(audio::headphone::volume_range().max);
|
||||
|
||||
transmitter_model.enable();
|
||||
|
||||
log_event(">>> Playback Started <<<");
|
||||
volume_t max_volume = audio::headphone::volume_range().max;
|
||||
audio::headphone::set_volume(max_volume);
|
||||
}
|
||||
|
||||
ShoppingCartLock::ShoppingCartLock(NavigationView& nav)
|
||||
@@ -225,9 +223,6 @@ ShoppingCartLock::ShoppingCartLock(NavigationView& nav)
|
||||
log_event("[+] INITIALIZATION COMPLETE");
|
||||
log_event("[+] PORTAPACK ARMED");
|
||||
log_event("[*] STATUS: READY");
|
||||
log_event("This app use speaker to");
|
||||
log_event("produce LF signal, but");
|
||||
log_event("also trigger radio TX");
|
||||
}
|
||||
|
||||
ShoppingCartLock::~ShoppingCartLock() {
|
||||
@@ -235,4 +230,4 @@ ShoppingCartLock::~ShoppingCartLock() {
|
||||
baseband::shutdown();
|
||||
}
|
||||
|
||||
} // namespace ui::external_app::shoppingcart_lock
|
||||
} // namespace ui::external_app::shoppingcart_lock
|
||||
@@ -1,5 +1,8 @@
|
||||
// RocketGod's Shopping Cart Lock app
|
||||
// https://betaskynet.com
|
||||
// CVS Spam app by RocketGod (@rocketgod-git) https://betaskynet.com
|
||||
// Original .cu8 files by @jimilinuxguy https://github.com/jimilinuxguy/customer-assistance-buttons-sdr
|
||||
// If you can read this, you're a nerd. :P
|
||||
// Come join us at https://discord.gg/thepiratesreborn
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ui_widget.hpp"
|
||||
@@ -27,8 +30,8 @@ class ShoppingCartLock : public View {
|
||||
void focus() override;
|
||||
|
||||
private:
|
||||
static constexpr size_t BUFFER_SIZE = 8192;
|
||||
static constexpr size_t NUM_BUFFERS = 8;
|
||||
static constexpr size_t BUFFER_SIZE = 512;
|
||||
static constexpr size_t NUM_BUFFERS = 2;
|
||||
const std::string shoppingcart_lock_file{"shopping_cart_lock.wav"};
|
||||
const std::string shoppingcart_unlock_file{"shopping_cart_unlock.wav"};
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ SpectrumInputTextView::~SpectrumInputTextView() {
|
||||
}
|
||||
|
||||
void SpectrumInputTextView::on_set_text(NavigationView& nav) {
|
||||
text_prompt(nav, buffer, 300);
|
||||
text_prompt(nav, buffer, 300, ENTER_KEYBOARD_MODE_DIGITS);
|
||||
}
|
||||
|
||||
void SpectrumInputTextView::focus() {
|
||||
|
||||
+53
-14
@@ -62,6 +62,9 @@ bool but_SELECT = false;
|
||||
|
||||
static int x_pos{0};
|
||||
static int y_pos{0};
|
||||
|
||||
static int rotation_state = 0;
|
||||
|
||||
static int fg_color;
|
||||
static int bg_color;
|
||||
|
||||
@@ -259,25 +262,61 @@ void Initialize(unsigned char c) {
|
||||
boardX = 0;
|
||||
boardY = 4;
|
||||
copyCoordinates(X, Y, c - 1);
|
||||
rotation_state = 0;
|
||||
}
|
||||
|
||||
void Rotate() {
|
||||
short pivotX = X[1];
|
||||
short pivotY = Y[1];
|
||||
short newX[4];
|
||||
short newY[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
short tmp = X[i], tmp2 = Y[i];
|
||||
newX[i] = pivotX + pivotY - tmp2;
|
||||
newY[i] = tmp + pivotX - pivotY;
|
||||
if (OutOfBounds(boardY + newY[i], boardX + newX[i]) || board[boardX + newX[i]][boardY + newY[i]] != 0) return;
|
||||
short newX[4], newY[4];
|
||||
int next_state = (rotation_state + 1) % 4;
|
||||
|
||||
if (colorIndex == 2) {
|
||||
return;
|
||||
}
|
||||
DeleteFigure();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
X[i] = newX[i];
|
||||
Y[i] = newY[i];
|
||||
|
||||
const short kick_tests_I[4][5][2] = {
|
||||
{{0, 0}, {-2, 0}, {1, 0}, {-2, -1}, {1, 2}},
|
||||
{{0, 0}, {-1, 0}, {2, 0}, {-1, 2}, {2, -1}},
|
||||
{{0, 0}, {2, 0}, {-1, 0}, {2, 1}, {-1, -2}},
|
||||
{{0, 0}, {1, 0}, {-2, 0}, {1, -2}, {-2, 1}}};
|
||||
const short kick_tests_other[4][5][2] = {
|
||||
{{0, 0}, {-1, 0}, {-1, 1}, {0, -2}, {-1, -2}},
|
||||
{{0, 0}, {1, 0}, {1, -1}, {0, 2}, {1, 2}},
|
||||
{{0, 0}, {1, 0}, {1, 1}, {0, -2}, {1, -2}},
|
||||
{{0, 0}, {-1, 0}, {-1, -1}, {0, 2}, {-1, 2}}};
|
||||
|
||||
bool is_I_tetromino = (colorIndex == 1);
|
||||
const short(*kick_tests)[5][2] = is_I_tetromino ? kick_tests_I : kick_tests_other;
|
||||
|
||||
for (int test = 0; test < 5; test++) {
|
||||
short kickX = kick_tests[rotation_state][test][0];
|
||||
short kickY = kick_tests[rotation_state][test][1];
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
short tmpX = X[i] - X[1];
|
||||
short tmpY = Y[i] - Y[1];
|
||||
newX[i] = X[1] - tmpY;
|
||||
newY[i] = Y[1] + tmpX;
|
||||
int testX = boardX + newX[i] + kickX;
|
||||
int testY = boardY + newY[i] + kickY;
|
||||
if (OutOfBounds(testY, testX) || (testX >= 0 && board[testX][testY] != 0)) {
|
||||
goto next_test;
|
||||
}
|
||||
}
|
||||
|
||||
DeleteFigure();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
X[i] = newX[i];
|
||||
Y[i] = newY[i];
|
||||
}
|
||||
boardX += kickX;
|
||||
boardY += kickY;
|
||||
rotation_state = next_state;
|
||||
DrawFigure();
|
||||
return;
|
||||
|
||||
next_test:
|
||||
continue;
|
||||
}
|
||||
DrawFigure();
|
||||
}
|
||||
|
||||
void DrawFigure() {
|
||||
|
||||
@@ -32,7 +32,8 @@ namespace ui {
|
||||
AlphanumView::AlphanumView(
|
||||
NavigationView& nav,
|
||||
std::string& str,
|
||||
size_t max_length)
|
||||
size_t max_length,
|
||||
uint8_t enter_mode)
|
||||
: TextEntryView(nav, str, max_length) {
|
||||
size_t n;
|
||||
|
||||
@@ -76,7 +77,7 @@ AlphanumView::AlphanumView(
|
||||
n++;
|
||||
}
|
||||
|
||||
set_mode(mode);
|
||||
set_mode(enter_mode);
|
||||
|
||||
button_mode.on_select = [this](Button&) {
|
||||
set_mode(mode + 1);
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace ui {
|
||||
|
||||
class AlphanumView : public TextEntryView {
|
||||
public:
|
||||
AlphanumView(NavigationView& nav, std::string& str, size_t max_length);
|
||||
AlphanumView(NavigationView& nav, std::string& str, size_t max_length, uint8_t enter_mode);
|
||||
|
||||
AlphanumView(const AlphanumView&) = delete;
|
||||
AlphanumView(AlphanumView&&) = delete;
|
||||
|
||||
@@ -31,8 +31,9 @@ void text_prompt(
|
||||
NavigationView& nav,
|
||||
std::string& str,
|
||||
size_t max_length,
|
||||
uint8_t mode,
|
||||
std::function<void(std::string&)> on_done) {
|
||||
text_prompt(nav, str, str.length(), max_length, on_done);
|
||||
text_prompt(nav, str, str.length(), max_length, mode, on_done);
|
||||
}
|
||||
|
||||
void text_prompt(
|
||||
@@ -40,8 +41,9 @@ void text_prompt(
|
||||
std::string& str,
|
||||
uint32_t cursor_pos,
|
||||
size_t max_length,
|
||||
uint8_t mode,
|
||||
std::function<void(std::string&)> on_done) {
|
||||
auto te_view = nav.push<AlphanumView>(str, max_length);
|
||||
auto te_view = nav.push<AlphanumView>(str, max_length, mode);
|
||||
te_view->set_cursor(cursor_pos);
|
||||
te_view->on_changed = [on_done](std::string& value) {
|
||||
if (on_done)
|
||||
|
||||
@@ -26,6 +26,11 @@
|
||||
#include "ui.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
|
||||
#define ENTER_KEYBOARD_MODE_ALPHA 0
|
||||
#define ENTER_KEYBOARD_MODE_DIGITS 1
|
||||
#define ENTER_KEYBOARD_MODE_SYMBOLS 2
|
||||
#define ENTER_KEYBOARD_MODE_HEX 3
|
||||
|
||||
namespace ui {
|
||||
|
||||
class TextEntryView : public View {
|
||||
@@ -62,6 +67,7 @@ void text_prompt(
|
||||
NavigationView& nav,
|
||||
std::string& str,
|
||||
size_t max_length,
|
||||
uint8_t mode,
|
||||
std::function<void(std::string&)> on_done = nullptr);
|
||||
|
||||
void text_prompt(
|
||||
@@ -69,6 +75,7 @@ void text_prompt(
|
||||
std::string& str,
|
||||
uint32_t cursor_pos,
|
||||
size_t max_length,
|
||||
uint8_t mode, // enter mode: 123 abc etc
|
||||
std::function<void(std::string&)> on_done = nullptr);
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
|
||||
#include "ui_navigation.hpp"
|
||||
|
||||
#include "bmp_modal_warning.hpp"
|
||||
#include "bmp_splash.hpp"
|
||||
#include "event_m0.hpp"
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
@@ -44,7 +42,6 @@
|
||||
#include "ui_font_fixed_8x16.hpp"
|
||||
#include "ui_freqman.hpp"
|
||||
#include "ui_iq_trim.hpp"
|
||||
#include "ui_level.hpp"
|
||||
#include "ui_looking_glass_app.hpp"
|
||||
#include "ui_mictx.hpp"
|
||||
|
||||
@@ -52,7 +49,7 @@
|
||||
#include "ui_pocsag_tx.hpp"
|
||||
#include "ui_rds.hpp"
|
||||
#include "ui_recon.hpp"
|
||||
//#include "ui_scanner.hpp"
|
||||
// #include "ui_scanner.hpp"
|
||||
#include "ui_sd_over_usb.hpp"
|
||||
#include "ui_search.hpp"
|
||||
#include "ui_settings.hpp"
|
||||
@@ -133,22 +130,13 @@ const NavigationView::AppList NavigationView::appList = {
|
||||
{"ais", "AIS Boats", RX, Color::green(), &bitmap_icon_ais, new ViewFactory<AISAppView>()},
|
||||
{"aprsrx", "APRS", RX, Color::green(), &bitmap_icon_aprs, new ViewFactory<APRSRXView>()},
|
||||
{"audio", "Audio", RX, Color::green(), &bitmap_icon_speaker, new ViewFactory<AnalogAudioView>()},
|
||||
//{"blecomm", "BLE Comm", RX, ui::Color::orange(), &bitmap_icon_btle, new ViewFactory<BLECommView>()},
|
||||
{"blerx", "BLE Rx", RX, Color::green(), &bitmap_icon_btle, new ViewFactory<BLERxView>()},
|
||||
{"ert", "ERT Meter", RX, Color::green(), &bitmap_icon_ert, new ViewFactory<ERTAppView>()},
|
||||
{"level", "Level", RX, Color::green(), &bitmap_icon_options_radio, new ViewFactory<LevelView>()},
|
||||
{"pocsag", "POCSAG", RX, Color::green(), &bitmap_icon_pocsag, new ViewFactory<POCSAGAppView>()},
|
||||
{"radiosonde", "Radiosnde", RX, Color::green(), &bitmap_icon_sonde, new ViewFactory<SondeView>()},
|
||||
// {"scanner", "Scanner", RX, Color::green(), &bitmap_icon_scanner, new ViewFactory<ScannerView>()},
|
||||
{"search", "Search", RX, Color::yellow(), &bitmap_icon_search, new ViewFactory<SearchView>()},
|
||||
{"subghzd", "SubGhzD", RX, Color::yellow(), &bitmap_icon_remote, new ViewFactory<SubGhzDView>()},
|
||||
{"weather", "Weather", RX, Color::green(), &bitmap_icon_thermometer, new ViewFactory<WeatherView>()},
|
||||
//{"fskrx", "FSK RX", RX, Color::yellow(), &bitmap_icon_remote, new ViewFactory<FskxRxMainView>()}, //for JT
|
||||
//{"dmr", "DMR", RX, Color::dark_grey(), &bitmap_icon_dmr, new ViewFactory<NotImplementedView>()},
|
||||
//{"sigfox", "SIGFOX", RX, Color::dark_grey(), &bitmap_icon_fox, new ViewFactory<NotImplementedView>()},
|
||||
//{"lora", "LoRa", RX, Color::dark_grey(), &bitmap_icon_lora, new ViewFactory<NotImplementedView>()},
|
||||
//{"sstv", "SSTV", RX, Color::dark_grey(), &bitmap_icon_sstv, new ViewFactory<NotImplementedView>()},
|
||||
//{"tetra", "TETRA", RX, Color::dark_grey(), &bitmap_icon_tetra, new ViewFactory<NotImplementedView>()},
|
||||
/* TX ********************************************************************/
|
||||
{"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>()},
|
||||
@@ -158,7 +146,7 @@ const NavigationView::AppList NavigationView::appList = {
|
||||
{"rdstx", "RDS", TX, ui::Color::green(), &bitmap_icon_rds, new ViewFactory<RDSView>()},
|
||||
{"soundbrd", "Soundbrd", TX, ui::Color::green(), &bitmap_icon_soundboard, new ViewFactory<SoundBoardView>()},
|
||||
{"touchtune", "TouchTune", TX, ui::Color::green(), &bitmap_icon_touchtunes, new ViewFactory<TouchTunesView>()},
|
||||
{"signalgen", "Signal Gen", TX, Color::green(), &bitmap_icon_cwgen, new ViewFactory<SigGenView>()},
|
||||
{"signalgen", "SignalGen", TX, Color::green(), &bitmap_icon_cwgen, new ViewFactory<SigGenView>()},
|
||||
/* UTILITIES *************************************************************/
|
||||
{"filemanager", "File Manager", UTILITIES, Color::green(), &bitmap_icon_dir, new ViewFactory<FileManagerView>()},
|
||||
{"freqman", "Freq. Manager", UTILITIES, Color::green(), &bitmap_icon_freqman, new ViewFactory<FrequencyManagerView>()},
|
||||
@@ -355,7 +343,7 @@ void SystemStatusView::on_battery_data(const BatteryStateMessage* msg) {
|
||||
|
||||
// Check if charging state changed to charging
|
||||
static bool was_charging = false;
|
||||
if (msg->on_charger && !was_charging) {
|
||||
if (msg->on_charger && !was_charging && pmem::ui_battery_charge_hint()) {
|
||||
// Only show charging modal when transitioning to charging state
|
||||
nav_.display_modal(
|
||||
"CHARGING",
|
||||
@@ -1049,7 +1037,12 @@ SplashScreenView::SplashScreenView(NavigationView& nav)
|
||||
void SplashScreenView::paint(Painter&) {
|
||||
if (!portapack::display.draw_bmp_from_sdcard_file({0, 0}, splash_dot_bmp))
|
||||
// ^ try draw bmp file from sdcard at (0,0), and the (0,0) already bypassed the status bar, so actual pos is (0, STATUS_BAR_HEIGHT)
|
||||
portapack::display.draw_bmp_from_bmp_hex_arr({(240 - 230) / 2, (320 - 50) / 2 - 10}, splash_bmp, (const uint8_t[]){0x29, 0x18, 0x16});
|
||||
portapack::display.draw_bitmap({screen_width / 2 - 120,
|
||||
screen_height / 2},
|
||||
bitmap_titlebar_image.size,
|
||||
bitmap_titlebar_image.data,
|
||||
Theme::getInstance()->bg_darkest->foreground,
|
||||
Theme::getInstance()->bg_darkest->background, 3);
|
||||
// ^ draw BMP HEX arr in firmware, note that the BMP HEX arr only cover the image part (instead of fill the screen with background, this position is located it in the center)
|
||||
}
|
||||
|
||||
@@ -1144,7 +1137,12 @@ ModalMessageView::ModalMessageView(
|
||||
}
|
||||
|
||||
void ModalMessageView::paint(Painter& painter) {
|
||||
if (!compact) portapack::display.draw_bmp_from_bmp_hex_arr({100, 48}, modal_warning_bmp, (const uint8_t[]){0, 0, 0});
|
||||
if (!compact) portapack::display.draw_bitmap({screen_width / 2 - 3 * 16 / 2,
|
||||
screen_height / 2 - 3 * 16 / 2 - 100},
|
||||
bitmap_icon_utilities.size,
|
||||
bitmap_icon_utilities.data,
|
||||
Theme::getInstance()->bg_darkest->foreground,
|
||||
Theme::getInstance()->bg_darkest->background, 3);
|
||||
|
||||
// Break lines.
|
||||
auto lines = split_string(message_, '\n');
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2016 Furrtek
|
||||
* copyleft 2025 Whiterose of the Dark Army
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
@@ -646,31 +647,58 @@ void ILI9341::draw_bitmap(
|
||||
const ui::Size size,
|
||||
const uint8_t* const pixels,
|
||||
const ui::Color foreground,
|
||||
const ui::Color background) {
|
||||
// Not a transparent background
|
||||
if (ui::Color::magenta().v != background.v) {
|
||||
lcd_start_ram_write(p, size);
|
||||
const ui::Color background,
|
||||
uint8_t zoom_level) {
|
||||
if (zoom_level <= 1) {
|
||||
// Not a transparent background
|
||||
if (ui::Color::magenta().v != background.v) {
|
||||
lcd_start_ram_write(p, size);
|
||||
|
||||
const size_t count = size.width() * size.height();
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
const auto pixel = pixels[i >> 3] & (1U << (i & 0x7));
|
||||
io.lcd_write_pixel(pixel ? foreground : background);
|
||||
}
|
||||
} else {
|
||||
int x = p.x();
|
||||
int y = p.y();
|
||||
int maxX = x + size.width();
|
||||
const size_t count = size.width() * size.height();
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
const auto pixel = pixels[i >> 3] & (1U << (i & 0x7));
|
||||
if (pixel) {
|
||||
draw_pixel(ui::Point(x, y), foreground);
|
||||
const size_t count = size.width() * size.height();
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
const auto pixel = pixels[i >> 3] & (1U << (i & 0x7));
|
||||
io.lcd_write_pixel(pixel ? foreground : background);
|
||||
}
|
||||
// Move to the next pixel
|
||||
x++;
|
||||
if (x >= maxX) {
|
||||
x = p.x();
|
||||
y++;
|
||||
} else {
|
||||
// transparent bg
|
||||
int x = p.x();
|
||||
int y = p.y();
|
||||
int maxX = x + size.width();
|
||||
const size_t count = size.width() * size.height();
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
const auto pixel = pixels[i >> 3] & (1U << (i & 0x7));
|
||||
if (pixel) {
|
||||
draw_pixel(ui::Point(x, y), foreground);
|
||||
}
|
||||
// move to next px
|
||||
x++;
|
||||
if (x >= maxX) {
|
||||
x = p.x();
|
||||
y++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // zoom
|
||||
|
||||
// dot to square
|
||||
for (int y = 0; y < size.height(); y++) {
|
||||
for (int x = 0; x < size.width(); x++) {
|
||||
// pos
|
||||
size_t bit_index = y * size.width() + x;
|
||||
int byte_index = bit_index >> 3;
|
||||
int bit_pos = bit_index & 0x7;
|
||||
|
||||
// val
|
||||
const auto pixel = pixels[byte_index] & (1U << bit_pos);
|
||||
/* ^ the byte_index-th bit AKA current bit
|
||||
^ current px in current byte*/
|
||||
|
||||
if (pixel || background.v != ui::Color::magenta().v) {
|
||||
fill_rectangle(
|
||||
{p.x() + x * zoom_level, p.y() + y * zoom_level,
|
||||
zoom_level, zoom_level},
|
||||
pixel ? foreground : background);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -680,8 +708,9 @@ void ILI9341::draw_glyph(
|
||||
const ui::Point p,
|
||||
const ui::Glyph& glyph,
|
||||
const ui::Color foreground,
|
||||
const ui::Color background) {
|
||||
draw_bitmap(p, glyph.size(), glyph.pixels(), foreground, background);
|
||||
const ui::Color background,
|
||||
uint8_t zoom_level) {
|
||||
draw_bitmap(p, glyph.size(), glyph.pixels(), foreground, background, zoom_level);
|
||||
}
|
||||
|
||||
void ILI9341::scroll_set_area(
|
||||
|
||||
@@ -86,13 +86,15 @@ class ILI9341 {
|
||||
const ui::Size size,
|
||||
const uint8_t* const data,
|
||||
const ui::Color foreground,
|
||||
const ui::Color background);
|
||||
const ui::Color background,
|
||||
uint8_t zoom_level = 1);
|
||||
|
||||
void draw_glyph(
|
||||
const ui::Point p,
|
||||
const ui::Glyph& glyph,
|
||||
const ui::Color foreground,
|
||||
const ui::Color background);
|
||||
const ui::Color background,
|
||||
uint8_t zoom_level = 1);
|
||||
|
||||
/*** Scrolling ***
|
||||
* Scrolling support is implemented in the ILI9341 driver. Basically a region
|
||||
|
||||
@@ -137,9 +137,9 @@ struct ui_config2_t {
|
||||
bool button_repeat_delay : 1;
|
||||
bool button_repeat_speed : 1;
|
||||
bool button_long_press_delay : 1;
|
||||
bool battery_charge_hint : 1;
|
||||
|
||||
uint8_t theme_id;
|
||||
uint8_t PLACEHOLDER_3;
|
||||
};
|
||||
static_assert(sizeof(ui_config2_t) == sizeof(uint32_t));
|
||||
|
||||
@@ -480,6 +480,10 @@ void persist() {
|
||||
|
||||
} /* namespace cache */
|
||||
|
||||
uint32_t get_data_structure_version() {
|
||||
return data->structure_version;
|
||||
}
|
||||
|
||||
uint32_t pmem_data_word(uint32_t index) {
|
||||
return backup_ram->pmem_data_word(index);
|
||||
}
|
||||
@@ -562,6 +566,10 @@ void set_afsk_space(const int32_t new_value) {
|
||||
data->afsk_space_freq = afsk_freq_range.clip(new_value);
|
||||
}
|
||||
|
||||
uint32_t get_modem_def_index() {
|
||||
return data->modem_def_index;
|
||||
}
|
||||
|
||||
int32_t modem_baudrate() {
|
||||
modem_baudrate_range.reset_if_outside(data->modem_baudrate, modem_baudrate_reset_value);
|
||||
return data->modem_baudrate;
|
||||
@@ -571,13 +579,11 @@ void set_modem_baudrate(const int32_t new_value) {
|
||||
data->modem_baudrate = modem_baudrate_range.clip(new_value);
|
||||
}
|
||||
|
||||
/*
|
||||
int32_t modem_bw() {
|
||||
modem_bw_range.reset_if_outside(data->modem_bw, modem_bw_reset_value);
|
||||
return data->modem_bw;
|
||||
}
|
||||
|
||||
void set_modem_bw(const int32_t new_value) {
|
||||
/*void set_modem_bw(const int32_t new_value) {
|
||||
data->modem_bw = modem_bw_range.clip(new_value);
|
||||
}
|
||||
*/
|
||||
@@ -672,10 +678,18 @@ void set_gui_return_icon(bool v) {
|
||||
data->ui_config.show_gui_return_icon = v ? 1 : 0;
|
||||
}
|
||||
|
||||
bool load_app_settings() {
|
||||
return data->ui_config.load_app_settings;
|
||||
}
|
||||
|
||||
void set_load_app_settings(bool v) {
|
||||
data->ui_config.load_app_settings = v ? 1 : 0;
|
||||
}
|
||||
|
||||
bool save_app_settings() {
|
||||
return data->ui_config.save_app_settings;
|
||||
}
|
||||
|
||||
void set_save_app_settings(bool v) {
|
||||
data->ui_config.save_app_settings = v ? 1 : 0;
|
||||
}
|
||||
@@ -809,6 +823,9 @@ void set_recon_config_bit(uint8_t rc_bit, bool v) {
|
||||
auto bit_mask = 1LL << rc_bit;
|
||||
data->recon_config = v ? (data->recon_config | bit_mask) : (data->recon_config & ~bit_mask);
|
||||
}
|
||||
uint64_t get_recon_config() {
|
||||
return data->recon_config;
|
||||
}
|
||||
bool recon_autosave_freqs() {
|
||||
return check_recon_config_bit(RC_AUTOSAVE_FREQS);
|
||||
}
|
||||
@@ -964,6 +981,9 @@ bool ui_button_repeat_speed() {
|
||||
bool ui_button_long_press_delay() {
|
||||
return data->ui_config2.button_long_press_delay;
|
||||
}
|
||||
bool ui_battery_charge_hint() {
|
||||
return data->ui_config2.battery_charge_hint;
|
||||
}
|
||||
|
||||
void set_ui_hide_speaker(bool v) {
|
||||
data->ui_config2.hide_speaker = v;
|
||||
@@ -1018,6 +1038,9 @@ void set_ui_button_repeat_speed(bool v) {
|
||||
void set_ui_button_long_press_delay(bool v) {
|
||||
data->ui_config2.button_long_press_delay = v;
|
||||
}
|
||||
void set_ui_battery_charge_hint(bool v) {
|
||||
data->ui_config2.battery_charge_hint = v;
|
||||
}
|
||||
|
||||
/* Converter */
|
||||
bool config_converter() {
|
||||
@@ -1199,173 +1222,5 @@ size_t data_size() {
|
||||
return sizeof(data_t);
|
||||
}
|
||||
|
||||
// Dump pmem, receiver and transmitter models internals in human readable format
|
||||
|
||||
bool debug_dump() {
|
||||
ui::Painter painter{};
|
||||
std::string debug_dir = "DEBUG";
|
||||
std::filesystem::path filename{};
|
||||
File pmem_dump_file{};
|
||||
// create new dump file name and DEBUG directory
|
||||
ensure_directory(debug_dir);
|
||||
filename = next_filename_matching_pattern(debug_dir + "/DEBUG_DUMP_????.TXT");
|
||||
if (filename.empty()) {
|
||||
painter.draw_string({0, 320 - 16}, *ui::Theme::getInstance()->fg_red, "COULD NOT GET DUMP NAME !");
|
||||
return false;
|
||||
}
|
||||
// dump data fo filename
|
||||
auto error = pmem_dump_file.create(filename);
|
||||
if (error) {
|
||||
painter.draw_string({0, 320 - 16}, *ui::Theme::getInstance()->fg_red, "ERROR DUMPING " + filename.filename().string() + " !");
|
||||
return false;
|
||||
}
|
||||
pmem_dump_file.write_line("FW version: " VERSION_STRING);
|
||||
pmem_dump_file.write_line("Ext APPS version req'd: 0x" + to_string_hex(VERSION_MD5));
|
||||
pmem_dump_file.write_line("GCC version: " + to_string_dec_int(__GNUC__) + "." + to_string_dec_int(__GNUC_MINOR__) + "." + to_string_dec_int(__GNUC_PATCHLEVEL__));
|
||||
|
||||
// firmware checksum
|
||||
pmem_dump_file.write_line("Firmware calculated checksum: 0x" + to_string_hex(simple_checksum(FLASH_STARTING_ADDRESS, FLASH_ROM_SIZE), 8));
|
||||
|
||||
// write persistent memory
|
||||
pmem_dump_file.write_line("\n[Persistent Memory]");
|
||||
|
||||
// full variables
|
||||
pmem_dump_file.write_line("structure_version: 0x" + to_string_hex(data->structure_version, 8));
|
||||
pmem_dump_file.write_line("target_frequency: " + to_string_dec_int(data->target_frequency));
|
||||
pmem_dump_file.write_line("correction_ppb: " + to_string_dec_int(data->correction_ppb));
|
||||
pmem_dump_file.write_line("modem_def_index: " + to_string_dec_uint(data->modem_def_index));
|
||||
pmem_dump_file.write_line("serial_format.data_bit: " + to_string_dec_uint(data->serial_format.data_bits));
|
||||
pmem_dump_file.write_line("serial_format.parity: " + to_string_dec_uint(data->serial_format.parity));
|
||||
pmem_dump_file.write_line("serial_format.stop_bits: " + to_string_dec_uint(data->serial_format.stop_bits));
|
||||
pmem_dump_file.write_line("serial_format.bit_order: " + to_string_dec_uint(data->serial_format.bit_order));
|
||||
pmem_dump_file.write_line("modem_bw: " + to_string_dec_int(data->modem_bw));
|
||||
pmem_dump_file.write_line("afsk_mark_freq: " + to_string_dec_int(data->afsk_mark_freq));
|
||||
pmem_dump_file.write_line("afsk_space_freq: " + to_string_dec_int(data->afsk_space_freq));
|
||||
pmem_dump_file.write_line("modem_baudrate: " + to_string_dec_int(data->modem_baudrate));
|
||||
pmem_dump_file.write_line("modem_repeat: " + to_string_dec_int(data->modem_repeat));
|
||||
pmem_dump_file.write_line("pocsag_last_address: " + to_string_dec_uint(data->pocsag_last_address));
|
||||
pmem_dump_file.write_line("pocsag_ignore_address: " + to_string_dec_uint(data->pocsag_ignore_address));
|
||||
pmem_dump_file.write_line("tone_mix: " + to_string_dec_uint(data->tone_mix));
|
||||
pmem_dump_file.write_line("hardware_config: " + to_string_dec_uint(data->hardware_config));
|
||||
pmem_dump_file.write_line("recon_config: 0x" + to_string_hex(data->recon_config, 16));
|
||||
pmem_dump_file.write_line("recon_repeat_nb: " + to_string_dec_int(data->recon_repeat_nb));
|
||||
pmem_dump_file.write_line("recon_repeat_gain: " + to_string_dec_int(data->recon_repeat_gain));
|
||||
pmem_dump_file.write_line("recon_repeat_delay: " + to_string_dec_int(data->recon_repeat_delay));
|
||||
pmem_dump_file.write_line("converter: " + to_string_dec_int(data->converter));
|
||||
pmem_dump_file.write_line("updown_converter: " + to_string_dec_int(data->updown_converter));
|
||||
pmem_dump_file.write_line("updown_frequency_rx_correction: " + to_string_dec_int(data->updown_frequency_rx_correction));
|
||||
pmem_dump_file.write_line("updown_frequency_tx_correction: " + to_string_dec_int(data->updown_frequency_tx_correction));
|
||||
pmem_dump_file.write_line("lcd_inverted_mode: " + to_string_dec_uint(data->lcd_inverted_mode));
|
||||
// pmem_dump_file.write_line("UNUSED_5: " + to_string_dec_int(data->UNUSED_5));
|
||||
// pmem_dump_file.write_line("UNUSED_6: " + to_string_dec_int(data->UNUSED_6));
|
||||
// pmem_dump_file.write_line("UNUSED_7: " + to_string_dec_int(data->UNUSED_7));
|
||||
pmem_dump_file.write_line("converter_frequency_offset: " + to_string_dec_int(data->converter_frequency_offset));
|
||||
pmem_dump_file.write_line("frequency_rx_correction: " + to_string_dec_uint(data->frequency_rx_correction));
|
||||
pmem_dump_file.write_line("frequency_tx_correction: " + to_string_dec_uint(data->frequency_tx_correction));
|
||||
pmem_dump_file.write_line("encoder_dial_sensitivity: " + to_string_dec_uint(data->encoder_dial_sensitivity));
|
||||
pmem_dump_file.write_line("encoder_rate_multiplier: " + to_string_dec_uint(data->encoder_rate_multiplier));
|
||||
pmem_dump_file.write_line("encoder_dial_direction: " + to_string_dec_uint(data->encoder_dial_direction)); // 0 = normal, 1 = reverse
|
||||
pmem_dump_file.write_line("headphone_volume_cb: " + to_string_dec_int(data->headphone_volume_cb));
|
||||
pmem_dump_file.write_line("config_mode_storage: 0x" + to_string_hex(data->config_mode_storage, 8));
|
||||
pmem_dump_file.write_line("dst_config: 0x" + to_string_hex((uint32_t)data->dst_config.v, 8));
|
||||
pmem_dump_file.write_line("fake_brightness_level: " + to_string_dec_uint(data->fake_brightness_level));
|
||||
pmem_dump_file.write_line("menu_color: 0x" + to_string_hex(data->menu_color.v, 4));
|
||||
pmem_dump_file.write_line("touchscreen_threshold: " + to_string_dec_uint(data->touchscreen_threshold));
|
||||
|
||||
// ui_config bits
|
||||
const auto backlight_timer = portapack::persistent_memory::config_backlight_timer();
|
||||
pmem_dump_file.write_line("ui_config clkout_freq: " + to_string_dec_uint(clkout_freq()));
|
||||
pmem_dump_file.write_line("ui_config backlight_timer.timeout_enabled: " + to_string_dec_uint(backlight_timer.timeout_enabled()));
|
||||
pmem_dump_file.write_line("ui_config backlight_timer.timeout_seconds: " + to_string_dec_uint(backlight_timer.timeout_seconds()));
|
||||
pmem_dump_file.write_line("ui_config show_gui_return_icon: " + to_string_dec_uint(data->ui_config.show_gui_return_icon));
|
||||
pmem_dump_file.write_line("ui_config load_app_settings: " + to_string_dec_uint(data->ui_config.load_app_settings));
|
||||
pmem_dump_file.write_line("ui_config save_app_settings: " + to_string_dec_uint(data->ui_config.save_app_settings));
|
||||
pmem_dump_file.write_line("ui_config disable_touchscreen: " + to_string_dec_uint(data->ui_config.disable_touchscreen));
|
||||
pmem_dump_file.write_line("ui_config hide_clock: " + to_string_dec_uint(data->ui_config.hide_clock));
|
||||
pmem_dump_file.write_line("ui_config clock_with_date: " + to_string_dec_uint(data->ui_config.clock_show_date));
|
||||
pmem_dump_file.write_line("ui_config clkout_enabled: " + to_string_dec_uint(data->ui_config.clkout_enabled));
|
||||
pmem_dump_file.write_line("ui_config apply_fake_brightness: " + to_string_dec_uint(data->ui_config.apply_fake_brightness));
|
||||
pmem_dump_file.write_line("ui_config stealth_mode: " + to_string_dec_uint(data->ui_config.stealth_mode));
|
||||
pmem_dump_file.write_line("ui_config config_login: " + to_string_dec_uint(data->ui_config.config_login));
|
||||
pmem_dump_file.write_line("ui_config config_splash: " + to_string_dec_uint(data->ui_config.config_splash));
|
||||
|
||||
// ui_config2 bits
|
||||
pmem_dump_file.write_line("ui_config2 hide_speaker: " + to_string_dec_uint(data->ui_config2.hide_speaker));
|
||||
pmem_dump_file.write_line("ui_config2 hide_converter: " + to_string_dec_uint(data->ui_config2.hide_converter));
|
||||
pmem_dump_file.write_line("ui_config2 hide_stealth: " + to_string_dec_uint(data->ui_config2.hide_stealth));
|
||||
pmem_dump_file.write_line("ui_config2 hide_camera: " + to_string_dec_uint(data->ui_config2.hide_camera));
|
||||
pmem_dump_file.write_line("ui_config2 hide_sleep: " + to_string_dec_uint(data->ui_config2.hide_sleep));
|
||||
pmem_dump_file.write_line("ui_config2 hide_bias_tee: " + to_string_dec_uint(data->ui_config2.hide_bias_tee));
|
||||
pmem_dump_file.write_line("ui_config2 hide_clock: " + to_string_dec_uint(data->ui_config2.hide_clock));
|
||||
pmem_dump_file.write_line("ui_config2 hide_sd_card: " + to_string_dec_uint(data->ui_config2.hide_sd_card));
|
||||
pmem_dump_file.write_line("ui_config2 hide_mute: " + to_string_dec_uint(data->ui_config2.hide_mute));
|
||||
pmem_dump_file.write_line("ui_config2 hide_fake_brightness: " + to_string_dec_uint(data->ui_config2.hide_fake_brightness));
|
||||
pmem_dump_file.write_line("ui_config2 hide_battery_icon: " + to_string_dec_uint(data->ui_config2.hide_battery_icon));
|
||||
pmem_dump_file.write_line("ui_config2 hide_numeric_battery: " + to_string_dec_uint(data->ui_config2.hide_numeric_battery));
|
||||
pmem_dump_file.write_line("ui_config2 theme_id: " + to_string_dec_uint(data->ui_config2.theme_id));
|
||||
pmem_dump_file.write_line("ui_config2 override_batt_calc: " + to_string_dec_uint(data->ui_config2.override_batt_calc));
|
||||
pmem_dump_file.write_line("ui_config2 button_repeat_delay: " + to_string_dec_uint(data->ui_config2.button_repeat_delay));
|
||||
pmem_dump_file.write_line("ui_config2 button_repeat_speed: " + to_string_dec_uint(data->ui_config2.button_repeat_speed));
|
||||
pmem_dump_file.write_line("ui_config2 button_long_press_delay: " + to_string_dec_uint(data->ui_config2.button_long_press_delay));
|
||||
|
||||
// misc_config bits
|
||||
pmem_dump_file.write_line("misc_config config_audio_mute: " + to_string_dec_int(config_audio_mute()));
|
||||
pmem_dump_file.write_line("misc_config config_speaker_disable: " + to_string_dec_int(config_speaker_disable()));
|
||||
pmem_dump_file.write_line("misc_config config_disable_external_tcxo: " + to_string_dec_uint(config_disable_external_tcxo()));
|
||||
pmem_dump_file.write_line("misc_config config_sdcard_high_speed_io: " + to_string_dec_uint(config_sdcard_high_speed_io()));
|
||||
pmem_dump_file.write_line("misc_config config_disable_config_mode: " + to_string_dec_uint(config_disable_config_mode()));
|
||||
pmem_dump_file.write_line("misc_config beep_on_packets: " + to_string_dec_int(beep_on_packets()));
|
||||
|
||||
// receiver_model
|
||||
pmem_dump_file.write_line("\n[Receiver Model]");
|
||||
pmem_dump_file.write_line("target_frequency: " + to_string_dec_uint(receiver_model.target_frequency()));
|
||||
pmem_dump_file.write_line("frequency_step: " + to_string_dec_uint(receiver_model.frequency_step()));
|
||||
pmem_dump_file.write_line("lna: " + to_string_dec_int(receiver_model.lna()));
|
||||
pmem_dump_file.write_line("vga: " + to_string_dec_int(receiver_model.vga()));
|
||||
pmem_dump_file.write_line("rf_amp: " + to_string_dec_int(receiver_model.rf_amp()));
|
||||
pmem_dump_file.write_line("baseband_bandwidth: " + to_string_dec_uint(receiver_model.baseband_bandwidth()));
|
||||
pmem_dump_file.write_line("sampling_rate: " + to_string_dec_uint(receiver_model.sampling_rate()));
|
||||
switch (receiver_model.modulation()) {
|
||||
case ReceiverModel::Mode::AMAudio:
|
||||
pmem_dump_file.write_line("modulation: Mode::AMAudio");
|
||||
break;
|
||||
case ReceiverModel::Mode::NarrowbandFMAudio:
|
||||
pmem_dump_file.write_line("modulation: Mode::NarrowbandFMAudio");
|
||||
break;
|
||||
case ReceiverModel::Mode::WidebandFMAudio:
|
||||
pmem_dump_file.write_line("modulation: Mode::WidebandFMAudio");
|
||||
break;
|
||||
case ReceiverModel::Mode::SpectrumAnalysis:
|
||||
pmem_dump_file.write_line("modulation: Mode::SpectrumAnalysis");
|
||||
break;
|
||||
case ReceiverModel::Mode::Capture:
|
||||
pmem_dump_file.write_line("modulation: Mode::Capture");
|
||||
break;
|
||||
case ReceiverModel::Mode::AMAudioFMApt:
|
||||
pmem_dump_file.write_line("modulation: Mode::AMAudioFMApt");
|
||||
break;
|
||||
default:
|
||||
pmem_dump_file.write_line("modulation: !!unknown mode!!");
|
||||
break;
|
||||
}
|
||||
pmem_dump_file.write_line("headphone_volume.centibel: " + to_string_dec_int(receiver_model.headphone_volume().centibel()));
|
||||
pmem_dump_file.write_line("normalized_headphone_volume: " + to_string_dec_uint(receiver_model.normalized_headphone_volume()));
|
||||
pmem_dump_file.write_line("am_configuration: " + to_string_dec_uint(receiver_model.am_configuration()));
|
||||
pmem_dump_file.write_line("nbfm_configuration: " + to_string_dec_uint(receiver_model.nbfm_configuration()));
|
||||
pmem_dump_file.write_line("wfm_configuration: " + to_string_dec_uint(receiver_model.wfm_configuration()));
|
||||
|
||||
// transmitter_model
|
||||
pmem_dump_file.write_line("\n[Transmitter Model]");
|
||||
pmem_dump_file.write_line("target_frequency: " + to_string_dec_uint(transmitter_model.target_frequency()));
|
||||
pmem_dump_file.write_line("rf_amp: " + to_string_dec_int(transmitter_model.rf_amp()));
|
||||
pmem_dump_file.write_line("baseband_bandwidth: " + to_string_dec_uint(transmitter_model.baseband_bandwidth()));
|
||||
pmem_dump_file.write_line("sampling_rate: " + to_string_dec_uint(transmitter_model.sampling_rate()));
|
||||
pmem_dump_file.write_line("tx_gain: " + to_string_dec_int(transmitter_model.tx_gain()));
|
||||
pmem_dump_file.write_line("channel_bandwidth: " + to_string_dec_uint(transmitter_model.channel_bandwidth()));
|
||||
// on screen information
|
||||
painter.draw_string({0, 320 - 16}, *ui::Theme::getInstance()->fg_green, filename.filename().string() + " DUMPED !");
|
||||
return true;
|
||||
}
|
||||
|
||||
} /* namespace persistent_memory */
|
||||
} /* namespace portapack */
|
||||
|
||||
@@ -183,9 +183,13 @@ void set_afsk_mark(const int32_t new_value);
|
||||
int32_t afsk_space_freq();
|
||||
void set_afsk_space(const int32_t new_value);
|
||||
|
||||
uint32_t get_modem_def_index();
|
||||
|
||||
int32_t modem_baudrate();
|
||||
void set_modem_baudrate(const int32_t new_value);
|
||||
|
||||
int32_t modem_bw();
|
||||
|
||||
uint8_t modem_repeat();
|
||||
void set_modem_repeat(const uint32_t new_value);
|
||||
|
||||
@@ -214,7 +218,9 @@ backlight_config_t config_backlight_timer();
|
||||
bool disable_touchscreen();
|
||||
|
||||
void set_gui_return_icon(bool v);
|
||||
bool load_app_settings();
|
||||
void set_load_app_settings(bool v);
|
||||
bool save_app_settings();
|
||||
void set_save_app_settings(bool v);
|
||||
void set_config_disable_external_tcxo(bool v);
|
||||
void set_config_sdcard_high_speed_io(bool v, bool save);
|
||||
@@ -290,6 +296,7 @@ Color menu_color();
|
||||
void set_menu_color(Color v);
|
||||
|
||||
/* Recon app */
|
||||
uint64_t get_recon_config();
|
||||
bool recon_autosave_freqs();
|
||||
bool recon_autostart_recon();
|
||||
bool recon_continuous();
|
||||
@@ -343,6 +350,8 @@ bool ui_override_batt_calc();
|
||||
bool ui_button_repeat_delay();
|
||||
bool ui_button_repeat_speed();
|
||||
bool ui_button_long_press_delay();
|
||||
bool ui_battery_charge_hint();
|
||||
|
||||
void set_ui_hide_speaker(bool v);
|
||||
void set_ui_hide_mute(bool v);
|
||||
void set_ui_hide_converter(bool v);
|
||||
@@ -360,20 +369,20 @@ void set_ui_override_batt_calc(bool v);
|
||||
void set_ui_button_repeat_delay(bool v);
|
||||
void set_ui_button_repeat_speed(bool v);
|
||||
void set_ui_button_long_press_delay(bool v);
|
||||
void set_ui_battery_charge_hint(bool v);
|
||||
|
||||
// sd persisting settings
|
||||
bool should_use_sdcard_for_pmem();
|
||||
int save_persistent_settings_to_file();
|
||||
int load_persistent_settings_from_file();
|
||||
|
||||
uint32_t get_data_structure_version();
|
||||
uint32_t pmem_data_word(uint32_t index);
|
||||
uint32_t pmem_stored_checksum(void);
|
||||
uint32_t pmem_calculated_checksum(void);
|
||||
|
||||
size_t data_size();
|
||||
|
||||
bool debug_dump();
|
||||
|
||||
} /* namespace persistent_memory */
|
||||
|
||||
} /* namespace portapack */
|
||||
|
||||
@@ -36,34 +36,12 @@ Style Style::invert() const {
|
||||
.foreground = background};
|
||||
}
|
||||
|
||||
int Painter::draw_char(Point p, const Style& style, char c, uint8_t zoom_factor) {
|
||||
int Painter::draw_char(Point p, const Style& style, char c, uint8_t zoom_level) {
|
||||
const auto glyph = style.font.glyph(c);
|
||||
|
||||
if (zoom_factor <= 1) {
|
||||
display.draw_glyph(p, glyph, style.foreground, style.background);
|
||||
} else {
|
||||
// dot to square
|
||||
const uint8_t* pixels = glyph.pixels();
|
||||
for (int y = 0; y < glyph.h(); y++) { // each line
|
||||
for (int x = 0; x < glyph.w(); x++) { // each clum
|
||||
// pos
|
||||
int byte_index = (y * glyph.w() + x) / 8;
|
||||
int bit_pos = (y * glyph.w() + x) % 8;
|
||||
display.draw_glyph(p, glyph, style.foreground, style.background, zoom_level);
|
||||
|
||||
// fill
|
||||
Color pixel_color = ((pixels[byte_index] & (1 << bit_pos)) != 0) ? style.foreground : style.background;
|
||||
/* ^ true: fg, false: bg
|
||||
^ the byte_index-th bit AKA current bit
|
||||
^ current px in current byte */
|
||||
display.fill_rectangle(
|
||||
{p.x() + x * zoom_factor, p.y() + y * zoom_factor,
|
||||
zoom_factor, zoom_factor},
|
||||
pixel_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return glyph.advance().x() * zoom_factor;
|
||||
return glyph.advance().x() * zoom_level;
|
||||
}
|
||||
|
||||
int Painter::draw_string(Point p, const Style& style, std::string_view text) {
|
||||
|
||||
@@ -1136,7 +1136,7 @@ void ButtonWithEncoder::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);
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
bitmap.hpp
|
||||
@@ -0,0 +1,127 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (C) 2016 Furrtek
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
import sys
|
||||
import struct
|
||||
from PIL import Image
|
||||
from os import listdir
|
||||
from os import path
|
||||
from os import makedirs
|
||||
|
||||
usage_message = f"""
|
||||
1BPP PortaPack bitmap.hpp generator
|
||||
|
||||
Usage: {sys.argv[0]} <directory>
|
||||
"""
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print(usage_message)
|
||||
sys.exit(-1)
|
||||
|
||||
graphics_path = path.join(sys.argv[1], '')
|
||||
hex_output_dir = path.join(graphics_path, 'hex_files')
|
||||
|
||||
# Create hex output directory if it doesn't exist
|
||||
if not path.exists(hex_output_dir):
|
||||
makedirs(hex_output_dir)
|
||||
|
||||
def convert_png(file):
|
||||
c = 0
|
||||
data = 0
|
||||
|
||||
rgb_im = Image.open(file).convert('RGBA')
|
||||
|
||||
if rgb_im.size[0] % 8 or rgb_im.size[1] % 8:
|
||||
print((file + ": Size is not a multiple of 8. Image is not included in bitmap.hpp."))
|
||||
sys.exit(-1)
|
||||
|
||||
name = path.basename(file).split(".")[0].lower();
|
||||
|
||||
# Prepare data for both hpp and hex file
|
||||
hpp_lines = []
|
||||
hex_data = bytearray()
|
||||
|
||||
for i in range(rgb_im.size[1]):
|
||||
for j in range(rgb_im.size[0]):
|
||||
r, g, b, a = rgb_im.getpixel((j, i))
|
||||
|
||||
data >>= 1
|
||||
|
||||
if r > 127 and g > 127 and b > 127 and a > 127:
|
||||
data += 128
|
||||
|
||||
if j % 8 == 7:
|
||||
hpp_lines.append(" 0x%0.2X,\n" % data)
|
||||
hex_data.append(data)
|
||||
data = 0
|
||||
|
||||
# Write to hpp file
|
||||
f.write("static constexpr uint8_t bitmap_" + name + "_data[] = {\n")
|
||||
f.writelines(hpp_lines)
|
||||
f.write("};\n")
|
||||
f.write("static constexpr Bitmap bitmap_" + name + " {\n")
|
||||
f.write(" {" + str(rgb_im.size[0]) + ", " + str(rgb_im.size[1]) + "},\n bitmap_" + name + "_data};\n\n")
|
||||
|
||||
# Write to hex file
|
||||
hex_filename = path.join(hex_output_dir, name + ".hex")
|
||||
with open(hex_filename, 'wb') as hex_file:
|
||||
hex_file.write(hex_data)
|
||||
|
||||
return
|
||||
|
||||
count = 0
|
||||
|
||||
f = open('bitmap.hpp', 'w')
|
||||
f.write("/*\n"
|
||||
" * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.\n"
|
||||
" * Copyright (C) 2016 Furrtek\n"
|
||||
" *\n"
|
||||
" * This file is part of PortaPack.\n"
|
||||
" *\n"
|
||||
" * This program is free software; you can redistribute it and/or modify\n"
|
||||
" * it under the terms of the GNU General Public License as published by\n"
|
||||
" * the Free Software Foundation; either version 2, or (at your option)\n"
|
||||
" * any later version.\n"
|
||||
" *\n"
|
||||
" * This program is distributed in the hope that it will be useful,\n"
|
||||
" * but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||||
" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
||||
" * GNU General Public License for more details.\n"
|
||||
" *\n"
|
||||
" * You should have received a copy of the GNU General Public License\n"
|
||||
" * along with this program; see the file COPYING. If not, write to\n"
|
||||
" * the Free Software Foundation, Inc., 51 Franklin Street,\n"
|
||||
" * Boston, MA 02110-1301, USA.\n"
|
||||
" */\n\n"
|
||||
"// This file was generated by make_bitmap.py\n\n"
|
||||
"#ifndef __BITMAP_HPP__\n"
|
||||
"#define __BITMAP_HPP__\n\n"
|
||||
"#include \"ui.hpp\"\n\n"
|
||||
"namespace ui {\n\n")
|
||||
|
||||
for file in listdir(graphics_path):
|
||||
if file.endswith(".png") and path.isfile(graphics_path + file):
|
||||
convert_png(graphics_path + file)
|
||||
count += 1
|
||||
|
||||
f.write("} /* namespace ui */\n\n")
|
||||
f.write("#endif/*__BITMAP_HPP__*/\n")
|
||||
|
||||
print(("Converted " + str(count) + " files"))
|
||||
@@ -120,10 +120,10 @@ def main():
|
||||
if validate_memory_regions(regions):
|
||||
print("external app addr seems correct, pass")
|
||||
else:
|
||||
print("\nWARENING: It seems you are having incorrect external app addresses.")
|
||||
print("\nWARNING: It seems you are having incorrect external app addresses.")
|
||||
|
||||
except Exception as e:
|
||||
print(f"err: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
||||
@@ -137,7 +137,12 @@ def get_pp_device_linux():
|
||||
parts = clean_line.split()
|
||||
|
||||
if len(parts) >= 2 and SDCARD_LABEL in parts[1]: # checker
|
||||
print("found pp sd:")
|
||||
device_path = parts[0]
|
||||
#remove `- in it
|
||||
device_path = device_path.replace('-', '')
|
||||
device_path = device_path.replace('`', '')
|
||||
print(device_path)
|
||||
# if path valid
|
||||
if not os.path.exists(device_path):
|
||||
continue
|
||||
|
||||
@@ -199,7 +199,7 @@ try:
|
||||
if validate_memory_regions(regions):
|
||||
print("external app addr seems correct, pass")
|
||||
else:
|
||||
print("\nWARENING: It seems you are having incorrect external app addresses.")
|
||||
print("\nWARNING: It seems you are having incorrect external app addresses.")
|
||||
|
||||
except Exception as e:
|
||||
print(f"err: {e}")
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
## Brief description what you did
|
||||
|
||||
## Checklist
|
||||
- [ ] Kept changes minimal and limited to necessary files
|
||||
- [ ] Verified functionality remains intact and code compiles
|
||||
@@ -1,25 +0,0 @@
|
||||
# Description: WEather FAX list
|
||||
# Author: gullradriel
|
||||
|
||||
# Deutscher Wetterdienst (DWD) - Offenbach, Germany
|
||||
# Surface analysis: 04:30,10:50,16:36,22:00 UTC
|
||||
f=3855000,m=AMFM,bw=USB+FM,d=DWD DDH3 Analysis
|
||||
# Surface analysis, forecasts, warnings (continuous)
|
||||
f=7880000,m=AMFM,bw=USB+FM,d=DWD DDK3 Forecasts
|
||||
# Surface analysis & wave height (continuous)
|
||||
f=13882500,m=AMFM,bw=USB+FM,d=DWD DDK6 Waves
|
||||
|
||||
# Royal Navy (Northwood) - United Kingdom
|
||||
# Surface/Wave charts every 6 hrs
|
||||
f=2618500,m=AMFM,bw=USB+FM,d=Northwood 2.6MHz WX
|
||||
f=4610000,m=AMFM,bw=USB+FM,d=Northwood 4.6MHz WX
|
||||
f=8040000,m=AMFM,bw=USB+FM,d=Northwood 8.0MHz WX
|
||||
f=11086500,m=AMFM,bw=USB+FM,d=Northwood 11MHz WX
|
||||
|
||||
# United States Coast Guard (USCG) - Boston/NMF
|
||||
# Atlantic Analysis: 03:00,09:00,15:00,21:00 UTC
|
||||
f=6340500,m=AMFM,bw=USB+FM,d=USCG 6.3MHz Atlantic
|
||||
# Forecasts & Hurricane Warnings (continuous updates)
|
||||
f=9110000,m=AMFM,bw=USB+FM,d=USCG 9.1MHz WX Warn
|
||||
# Extended Marine Forecasts (continuous updates)
|
||||
f=12750000,m=AMFM,bw=USB+FM,d=USCG 12.7MHz Marine
|
||||
@@ -0,0 +1,51 @@
|
||||
# Description: WEather FAX list, part 1
|
||||
# See https://weatherfax.com/stations
|
||||
|
||||
# Australia
|
||||
f=2628000,m=AMFM,bw=USB+FM,d=VMC Charleville
|
||||
f=5100000,m=AMFM,bw=USB+FM,d=VMC Charleville
|
||||
f=11030000,m=AMFM,bw=USB+FM,d=VMC Charleville
|
||||
f=13920000,m=AMFM,bw=USB+FM,d=VMC Charleville
|
||||
f=20469000,m=AMFM,bw=USB+FM,d=VMC Charleville
|
||||
f=5755000,m=AMFM,bw=USB+FM,d=VMW Wiluna
|
||||
f=7535000,m=AMFM,bw=USB+FM,d=VMW Wiluna
|
||||
f=10555000,m=AMFM,bw=USB+FM,d=VMW Wiluna
|
||||
f=15615000,m=AMFM,bw=USB+FM,d=VMW Wiluna
|
||||
f=18060000,m=AMFM,bw=USB+FM,d=VMW Wiluna
|
||||
|
||||
# Canada
|
||||
f=4416000,m=AMFM,bw=USB+FM,d=VCO Sydney NS
|
||||
f=6915100,m=AMFM,bw=USB+FM,d=VCO Sydney NS
|
||||
f=4292000,m=AMFM,bw=USB+FM,d=VFA Inuvik
|
||||
f=8456000,m=AMFM,bw=USB+FM,d=VFA Inuvik
|
||||
f=3253000,m=AMFM,bw=USB+FM,d=VFF Iqaluit/VFR Resolute
|
||||
f=7710000,m=AMFM,bw=USB+FM,d=VFF Iqaluit/VFR Resolute
|
||||
|
||||
# Chile
|
||||
f=4322000,m=AMFM,bw=USB+FM,d=CBM Punta Arenas
|
||||
f=8696000,m=AMFM,bw=USB+FM,d=CBM Punta Arenas
|
||||
f=4228000,m=AMFM,bw=USB+FM,d=CBV Vaparaiso
|
||||
f=8677000,m=AMFM,bw=USB+FM,d=CBV Vaparaiso
|
||||
f=17146400,m=AMFM,bw=USB+FM,d=CBV Vaparaiso
|
||||
|
||||
# China
|
||||
f=4170000,m=AMFM,bw=USB+FM,d=XSG Shanghai
|
||||
f=8302000,m=AMFM,bw=USB+FM,d=XSG Shanghai
|
||||
f=12382000,m=AMFM,bw=USB+FM,d=XSG Shanghai
|
||||
f=16559000,m=AMFM,bw=USB+FM,d=XSG Shanghai
|
||||
f=4199800,m=AMFM,bw=USB+FM,d=XSQ Guangzhou
|
||||
f=8412500,m=AMFM,bw=USB+FM,d=XSQ Guangzhou
|
||||
f=12629300,m=AMFM,bw=USB+FM,d=XSQ Guangzhou
|
||||
f=16826300,m=AMFM,bw=USB+FM,d=XSQ Guangzhou
|
||||
|
||||
# Germany - Deutscher Wetterdienst (DWD) - Offenbach
|
||||
# Surface analysis: 04:30,10:50,16:36,22:00 UTC
|
||||
f=3855000,m=AMFM,bw=USB+FM,d=DWD DDH3 Analysis
|
||||
# Surface analysis, forecasts, warnings (continuous)
|
||||
f=7880000,m=AMFM,bw=USB+FM,d=DWD DDK3 Forecasts
|
||||
# Surface analysis & wave height (continuous)
|
||||
f=13882500,m=AMFM,bw=USB+FM,d=DWD DDK6 Waves
|
||||
|
||||
# Greece
|
||||
f=4482900,m=AMFM,bw=USB+FM,d=SVJ4 Athens
|
||||
f=8106900,m=AMFM,bw=USB+FM,d=SVJ4 Athens
|
||||
@@ -0,0 +1,58 @@
|
||||
# Description: WEather FAX list, part 2
|
||||
# See https://weatherfax.com/stations
|
||||
|
||||
# Japan
|
||||
f=3622500,m=AMFM,bw=USB+FM,d=JMH Tokyo
|
||||
f=7795000,m=AMFM,bw=USB+FM,d=JMH Tokyo
|
||||
f=13988500,m=AMFM,bw=USB+FM,d=JMH Tokyo
|
||||
f=16971000,m=AMFM,bw=USB+FM,d=JJC Tokyo
|
||||
f=4274000,m=AMFM,bw=USB+FM,d=JFX Kagoshima
|
||||
f=8658000,m=AMFM,bw=USB+FM,d=JFX Kagoshima
|
||||
f=13074000,m=AMFM,bw=USB+FM,d=JFX Kagoshima
|
||||
f=16907500,m=AMFM,bw=USB+FM,d=JFX Kagoshima
|
||||
f=22559600,m=AMFM,bw=USB+FM,d=JFX Kagoshima
|
||||
|
||||
# Korea
|
||||
f=3585000,m=AMFM,bw=USB+FM,d=HLL2 Seoul
|
||||
f=5857500,m=AMFM,bw=USB+FM,d=HLL2 Seoul
|
||||
f=7433500,m=AMFM,bw=USB+FM,d=HLL2 Seoul
|
||||
f=9165000,m=AMFM,bw=USB+FM,d=HLL2 Seoul
|
||||
f=13570000,m=AMFM,bw=USB+FM,d=HLL2 Seoul
|
||||
|
||||
# Russia
|
||||
f=6328500,m=AMFM,bw=USB+FM,d=UDK2 Murmansk
|
||||
f=8444000,m=AMFM,bw=USB+FM,d=UDK2 Murmansk
|
||||
f=2640000,m=AMFM,bw=USB+FM,d=St Petersburg RU
|
||||
f=4212000,m=AMFM,bw=USB+FM,d=St Petersburg RU
|
||||
f=6456900,m=AMFM,bw=USB+FM,d=Vanino RU
|
||||
|
||||
# Thailand
|
||||
f=7396900,m=AMFM,bw=USB+FM,d=HSW64 Bangkok
|
||||
|
||||
# United Kingdom - Royal Navy
|
||||
# Surface/Wave charts every 6 hrs
|
||||
f=2618500,m=AMFM,bw=USB+FM,d=GYA Northwood
|
||||
f=4610000,m=AMFM,bw=USB+FM,d=GYA Northwood
|
||||
f=8040000,m=AMFM,bw=USB+FM,d=GYA Northwood
|
||||
f=11086500,m=AMFM,bw=USB+FM,d=GYA Northwood
|
||||
|
||||
# United States - Coast Guard (USCG)
|
||||
f=4346000,m=AMFM,bw=USB+FM,d=NMC Point Reyes
|
||||
f=8682000,m=AMFM,bw=USB+FM,d=NMC Point Reyes
|
||||
f=12786000,m=AMFM,bw=USB+FM,d=NMC Point Reyes
|
||||
f=17151200,m=AMFM,bw=USB+FM,d=NMC Point Reyes
|
||||
f=22527000,m=AMFM,bw=USB+FM,d=NMC Point Reyes
|
||||
f=4235000,m=AMFM,bw=USB+FM,d=NMF Boston
|
||||
f=6340500,m=AMFM,bw=USB+FM,d=NMF Boston Atlantic
|
||||
f=9110000,m=AMFM,bw=USB+FM,d=NMF Boston WX Warn
|
||||
f=12750000,m=AMFM,bw=USB+FM,d=NMF Boston Marine
|
||||
f=4317900,m=AMFM,bw=USB+FM,d=NMG New Orleans
|
||||
f=8503900,m=AMFM,bw=USB+FM,d=NMG New Orleans
|
||||
f=12789900,m=AMFM,bw=USB+FM,d=NMG New Orleans
|
||||
f=17146400,m=AMFM,bw=USB+FM,d=NMG New Orleans
|
||||
f=4298000,m=AMFM,bw=USB+FM,d=NOJ Kodiak
|
||||
f=8459000,m=AMFM,bw=USB+FM,d=NOJ Kodiak
|
||||
f=12412500,m=AMFM,bw=USB+FM,d=NOJ Kodiak
|
||||
f=9982500,m=AMFM,bw=USB+FM,d=KVM70 Honolulu
|
||||
f=11090000,m=AMFM,bw=USB+FM,d=KVM70 Honolulu
|
||||
f=16135000,m=AMFM,bw=USB+FM,d=KVM70 Honolulu
|
||||
Reference in New Issue
Block a user