mirror of
https://github.com/eried/portapack-mayhem.git
synced 2025-04-19 07:25:56 -04:00
Compare commits
No commits in common. "next" and "nightly-tag-2025-03-27" have entirely different histories.
next
...
nightly-ta
@ -2,7 +2,6 @@ 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:
|
||||
@ -12,6 +11,9 @@ 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:
|
||||
|
20
.github/workflows/hardware_issue_warning.yml
vendored
20
.github/workflows/hardware_issue_warning.yml
vendored
@ -1,20 +0,0 @@
|
||||
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.
|
@ -9,9 +9,7 @@
|
||||
|
||||
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="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))
|
||||
[<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)
|
||||
|
||||
# What is this?
|
||||
|
||||
|
@ -191,7 +191,6 @@ set(CPPSRC
|
||||
clock_manager.cpp
|
||||
core_control.cpp
|
||||
database.cpp
|
||||
gradient.cpp
|
||||
rfm69.cpp
|
||||
event_m0.cpp
|
||||
file_reader.cpp
|
||||
|
@ -52,20 +52,20 @@ AMOptionsView::AMOptionsView(
|
||||
&zoom_config,
|
||||
});
|
||||
|
||||
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)
|
||||
zoom_config.on_change = [this, view](size_t, OptionsField::value_t n) {
|
||||
receiver_model.set_am_configuration(previous_filter_array_index + n);
|
||||
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); // 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.
|
||||
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());
|
||||
options_config.on_change = [this, view](size_t, OptionsField::value_t n) {
|
||||
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)
|
||||
receiver_model.set_am_configuration(n);
|
||||
previous_filter_array_index = n;
|
||||
zoom_config.set_by_value(view->get_zoom_factor(AM_MODULATION));
|
||||
};
|
||||
}
|
||||
|
||||
@ -282,22 +282,6 @@ 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,6 +40,7 @@ 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{
|
||||
@ -58,7 +59,7 @@ class AMOptionsView : public View {
|
||||
{23 * 8, 0 * 16},
|
||||
7,
|
||||
{{"ZOOM x1", 0},
|
||||
{"ZOOM x2", 6}} // offset index AM modes array FIR filters.
|
||||
{"ZOOM x2", 6}} // offset index array filters.
|
||||
};
|
||||
};
|
||||
|
||||
@ -199,12 +200,6 @@ 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;
|
||||
|
||||
@ -213,9 +208,6 @@ 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,
|
||||
@ -223,8 +215,6 @@ 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};
|
||||
|
@ -21,6 +21,7 @@
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "ble_rx_app.hpp"
|
||||
#include "ble_rx_app.hpp"
|
||||
#include "ui_modemsetup.hpp"
|
||||
|
||||
@ -202,7 +203,6 @@ BleRecentEntryDetailView::BleRecentEntryDetailView(NavigationView& nav, const Bl
|
||||
nav,
|
||||
packetFileBuffer,
|
||||
64,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this, packetToSave](std::string& buffer) {
|
||||
on_save_file(buffer, packetToSave);
|
||||
});
|
||||
@ -471,7 +471,6 @@ BLERxView::BLERxView(NavigationView& nav)
|
||||
nav_,
|
||||
filterBuffer,
|
||||
64,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& buffer) {
|
||||
on_filter_change(buffer);
|
||||
});
|
||||
@ -494,7 +493,6 @@ BLERxView::BLERxView(NavigationView& nav)
|
||||
nav,
|
||||
listFileBuffer,
|
||||
64,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& buffer) {
|
||||
on_save_file(buffer);
|
||||
});
|
||||
|
@ -399,7 +399,6 @@ BLETxView::BLETxView(NavigationView& nav)
|
||||
nav,
|
||||
packetFileBuffer,
|
||||
64,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& buffer) {
|
||||
on_save_file(buffer);
|
||||
});
|
||||
|
@ -94,7 +94,6 @@ APRSTXView::APRSTXView(NavigationView& nav) {
|
||||
nav,
|
||||
payload,
|
||||
30,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& s) {
|
||||
text_payload.set(s);
|
||||
});
|
||||
|
@ -92,9 +92,6 @@ void ExternalModuleView::on_tick_second() {
|
||||
case app_location_t::TX:
|
||||
btnText += " (TX)";
|
||||
break;
|
||||
case app_location_t::TRX:
|
||||
btnText += " (TRX)";
|
||||
break;
|
||||
case app_location_t::SETTINGS:
|
||||
btnText += " (Settings)";
|
||||
break;
|
||||
|
@ -419,17 +419,6 @@ void FileManBaseView::reload_current(bool reset_pagination) {
|
||||
refresh_list();
|
||||
}
|
||||
|
||||
void FileManBaseView::copy_waterfall(std::filesystem::path path) {
|
||||
nav_.push<ModalMessageView>(
|
||||
"Install", " Use this gradient file\n for all waterfalls?", YESNO,
|
||||
[this, path](bool choice) {
|
||||
if (choice) {
|
||||
delete_file(default_gradient_file);
|
||||
copy_file(path, default_gradient_file);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const FileManBaseView::file_assoc_t& FileManBaseView::get_assoc(
|
||||
const fs::path& ext) const {
|
||||
size_t index = 0;
|
||||
@ -510,7 +499,7 @@ FileSaveView::FileSaveView(
|
||||
|
||||
button_edit_path.on_select = [this](Button&) {
|
||||
buffer_ = path_.string();
|
||||
text_prompt(nav_, buffer_, max_filename_length,ENTER_KEYBOARD_MODE_ALPHA,
|
||||
text_prompt(nav_, buffer_, max_filename_length,
|
||||
[this](std::string&) {
|
||||
path_ = buffer_;
|
||||
refresh_widgets();
|
||||
@ -519,7 +508,7 @@ FileSaveView::FileSaveView(
|
||||
|
||||
button_edit_name.on_select = [this](Button&) {
|
||||
buffer_ = file_.string();
|
||||
text_prompt(nav_, buffer_, max_filename_length,ENTER_KEYBOARD_MODE_ALPHA,
|
||||
text_prompt(nav_, buffer_, max_filename_length,
|
||||
[this](std::string&) {
|
||||
file_ = buffer_;
|
||||
refresh_widgets();
|
||||
@ -577,7 +566,7 @@ void FileManagerView::on_rename(std::string_view hint) {
|
||||
cursor_pos = pos;
|
||||
|
||||
text_prompt(
|
||||
nav_, name_buffer, cursor_pos, max_filename_length, ENTER_KEYBOARD_MODE_ALPHA,
|
||||
nav_, name_buffer, cursor_pos, max_filename_length,
|
||||
[this](std::string& renamed) {
|
||||
auto renamed_path = fs::path{renamed};
|
||||
rename_file(get_selected_full_path(), current_path / renamed_path);
|
||||
@ -651,7 +640,7 @@ void FileManagerView::on_clean() {
|
||||
|
||||
void FileManagerView::on_new_dir() {
|
||||
name_buffer = "";
|
||||
text_prompt(nav_, name_buffer, max_filename_length, ENTER_KEYBOARD_MODE_ALPHA, [this](std::string& dir_name) {
|
||||
text_prompt(nav_, name_buffer, max_filename_length, [this](std::string& dir_name) {
|
||||
make_new_directory(current_path / dir_name);
|
||||
reload_current(true);
|
||||
});
|
||||
@ -682,7 +671,7 @@ void FileManagerView::on_paste() {
|
||||
|
||||
void FileManagerView::on_new_file() {
|
||||
name_buffer = "";
|
||||
text_prompt(nav_, name_buffer, max_filename_length, ENTER_KEYBOARD_MODE_ALPHA, [this](std::string& file_name) {
|
||||
text_prompt(nav_, name_buffer, max_filename_length, [this](std::string& file_name) {
|
||||
make_new_file(current_path / file_name);
|
||||
reload_current(true);
|
||||
});
|
||||
@ -696,11 +685,7 @@ bool FileManagerView::handle_file_open() {
|
||||
auto ext = path.extension();
|
||||
|
||||
if (path_iequal(txt_ext, ext)) {
|
||||
if (path_iequal(current_path, u"/" + waterfalls_dir)) {
|
||||
copy_waterfall(path);
|
||||
} else {
|
||||
nav_.push<TextEditorView>(path);
|
||||
}
|
||||
nav_.push<TextEditorView>(path);
|
||||
return true;
|
||||
} else if (is_cxx_capture_file(path) || path_iequal(ppl_ext, ext)) {
|
||||
// TODO: Enough memory to push?
|
||||
|
@ -96,7 +96,6 @@ class FileManBaseView : public View {
|
||||
void load_directory_contents(const std::filesystem::path& dir_path);
|
||||
void load_directory_contents_unordered(const std::filesystem::path& dir_path, size_t file_cnt);
|
||||
const file_assoc_t& get_assoc(const std::filesystem::path& ext) const;
|
||||
void copy_waterfall(std::filesystem::path path);
|
||||
|
||||
NavigationView& nav_;
|
||||
|
||||
|
@ -46,7 +46,7 @@ using options_db_t = std::vector<option_db_t>;
|
||||
|
||||
extern options_db_t freqman_modulations;
|
||||
extern options_db_t freqman_bandwidths[5];
|
||||
// extern options_db_t freqman_steps; // now included via ui_receiver.hpp
|
||||
extern options_db_t freqman_steps;
|
||||
extern options_db_t freqman_steps_short;
|
||||
|
||||
options_t dboptions_to_options(const options_db_t& dboptions) {
|
||||
@ -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, ENTER_KEYBOARD_MODE_ALPHA, [this](std::string& new_desc) {
|
||||
text_prompt(nav_, temp_buffer_, freqman_max_desc_size, [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, ENTER_KEYBOARD_MODE_ALPHA, [this](std::string& new_name) {
|
||||
text_prompt(nav_, temp_buffer_, 20, [this](std::string& new_name) {
|
||||
if (!new_name.empty()) {
|
||||
create_freqman_file(new_name);
|
||||
refresh_categories();
|
||||
|
@ -126,7 +126,7 @@ void GlassView::reset_live_view() {
|
||||
}
|
||||
|
||||
void GlassView::add_spectrum_pixel(uint8_t power) {
|
||||
spectrum_row[pixel_index] = gradient.lut[power]; // row of colors
|
||||
spectrum_row[pixel_index] = spectrum_rgb3_lut[power]; // row of colors
|
||||
spectrum_data[pixel_index] = (live_frequency_integrate * spectrum_data[pixel_index] + power) / (live_frequency_integrate + 1); // smoothing
|
||||
pixel_index++;
|
||||
|
||||
@ -359,10 +359,6 @@ GlassView::GlassView(
|
||||
: nav_(nav) {
|
||||
baseband::run_image(portapack::spi_flash::image_tag_wideband_spectrum);
|
||||
|
||||
if (!gradient.load_file(default_gradient_file)) {
|
||||
gradient.set_default();
|
||||
}
|
||||
|
||||
add_children({&labels,
|
||||
&field_frequency_min,
|
||||
&field_frequency_max,
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include "ui_receiver.hpp"
|
||||
#include "string_format.hpp"
|
||||
#include "analog_audio_app.hpp"
|
||||
#include "gradient.hpp"
|
||||
#include "spectrum_color_lut.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
@ -74,7 +74,6 @@ class GlassView : public View {
|
||||
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
Gradient gradient{};
|
||||
RxRadioState radio_state_{ReceiverModel::Mode::SpectrumAnalysis};
|
||||
// Settings
|
||||
rf::Frequency f_min = 260 * MHZ_DIV; // Default to 315/433 remote range.
|
||||
|
@ -153,7 +153,7 @@ void POCSAGTXView::paint(Painter&) {
|
||||
}
|
||||
|
||||
void POCSAGTXView::on_set_text(NavigationView& nav) {
|
||||
text_prompt(nav, buffer, MAX_POCSAG_LENGTH, ENTER_KEYBOARD_MODE_ALPHA);
|
||||
text_prompt(nav, buffer, MAX_POCSAG_LENGTH);
|
||||
}
|
||||
|
||||
POCSAGTXView::POCSAGTXView(
|
||||
|
@ -65,7 +65,6 @@ RDSPSNView::RDSPSNView(
|
||||
nav,
|
||||
PSN,
|
||||
8,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& s) {
|
||||
text_psn.set(s);
|
||||
});
|
||||
@ -87,7 +86,6 @@ RDSRadioTextView::RDSRadioTextView(
|
||||
nav,
|
||||
radiotext,
|
||||
28,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& s) {
|
||||
text_radiotext.set(s);
|
||||
});
|
||||
|
@ -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, ENTER_KEYBOARD_MODE_ALPHA, [this](std::string& buffer) {
|
||||
text_prompt(nav, _output_file, 28, [this](std::string& buffer) {
|
||||
_output_file = buffer;
|
||||
button_choose_output_name.set_text(_output_file);
|
||||
});
|
||||
|
@ -56,10 +56,6 @@ SearchView::SearchView(
|
||||
: nav_(nav) {
|
||||
baseband::run_image(portapack::spi_flash::image_tag_wideband_spectrum);
|
||||
|
||||
if (!gradient.load_file(default_gradient_file)) {
|
||||
gradient.set_default();
|
||||
}
|
||||
|
||||
add_children({&labels,
|
||||
&field_frequency_min,
|
||||
&field_frequency_max,
|
||||
@ -294,7 +290,7 @@ void SearchView::on_channel_spectrum(const ChannelSpectrum& spectrum) {
|
||||
power = spectrum.db[bin - 128];
|
||||
}
|
||||
|
||||
add_spectrum_pixel(gradient.lut[power]);
|
||||
add_spectrum_pixel(spectrum_rgb3_lut[power]);
|
||||
|
||||
mean_acc += power;
|
||||
if (power > max_power) {
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "receiver_model.hpp"
|
||||
#include "recent_entries.hpp"
|
||||
#include "radio_state.hpp"
|
||||
#include "gradient.hpp"
|
||||
#include "spectrum_color_lut.hpp"
|
||||
#include "ui_receiver.hpp"
|
||||
|
||||
namespace ui {
|
||||
@ -88,7 +88,6 @@ class SearchView : public View {
|
||||
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
Gradient gradient{};
|
||||
RxRadioState radio_state_{
|
||||
100'000'000 /* frequency */,
|
||||
2500000 /* bandwidth */,
|
||||
|
@ -810,29 +810,30 @@ SetDisplayView::SetDisplayView(NavigationView& nav) {
|
||||
&field_fake_brightness,
|
||||
&button_save,
|
||||
&button_cancel,
|
||||
&checkbox_ips_screen_switch,
|
||||
&checkbox_invert_switch,
|
||||
&checkbox_brightness_switch});
|
||||
|
||||
field_fake_brightness.set_by_value(pmem::fake_brightness_level());
|
||||
checkbox_brightness_switch.set_value(pmem::apply_fake_brightness());
|
||||
checkbox_ips_screen_switch.set_value(pmem::config_lcd_normally_black());
|
||||
checkbox_invert_switch.set_value(pmem::config_lcd_inverted_mode());
|
||||
|
||||
button_save.on_select = [&nav, this](Button&) {
|
||||
pmem::set_apply_fake_brightness(checkbox_brightness_switch.value());
|
||||
pmem::set_fake_brightness_level(field_fake_brightness.selected_index_value());
|
||||
if (checkbox_ips_screen_switch.value() != pmem::config_lcd_normally_black()) {
|
||||
pmem::set_lcd_normally_black(checkbox_ips_screen_switch.value());
|
||||
if (checkbox_invert_switch.value() != pmem::config_lcd_inverted_mode()) {
|
||||
display.set_inverted(checkbox_invert_switch.value());
|
||||
pmem::set_lcd_inverted_mode(checkbox_invert_switch.value());
|
||||
}
|
||||
send_system_refresh();
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
// only enable invert OR fake brightness
|
||||
checkbox_ips_screen_switch.on_select = [this](Checkbox&, bool v) {
|
||||
checkbox_invert_switch.on_select = [this](Checkbox&, bool v) {
|
||||
if (v) checkbox_brightness_switch.set_value(false);
|
||||
};
|
||||
checkbox_brightness_switch.on_select = [this](Checkbox&, bool v) {
|
||||
if (v) checkbox_ips_screen_switch.set_value(false);
|
||||
if (v) checkbox_invert_switch.set_value(false);
|
||||
};
|
||||
|
||||
button_cancel.on_select = [&nav, this](Button&) {
|
||||
@ -1043,14 +1044,12 @@ SetBatteryView::SetBatteryView(NavigationView& nav) {
|
||||
add_children({&labels,
|
||||
&button_save,
|
||||
&button_cancel,
|
||||
&checkbox_overridebatt,
|
||||
&checkbox_battery_charge_hint});
|
||||
&checkbox_overridebatt});
|
||||
|
||||
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();
|
||||
@ -1065,7 +1064,6 @@ 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();
|
||||
|
@ -762,8 +762,6 @@ class SetDisplayView : public View {
|
||||
{{1 * 8, 2 * 16}, "(has a small performance", Theme::getInstance()->fg_light->foreground},
|
||||
{{1 * 8, 3 * 16}, "impact when enabled).", Theme::getInstance()->fg_light->foreground},
|
||||
{{2 * 8, 8 * 16}, "Brightness:", Theme::getInstance()->fg_light->foreground},
|
||||
{{2 * 8, 10 * 16}, "REBOOT TO APPLY SCREEN TYPE", Theme::getInstance()->fg_light->foreground},
|
||||
|
||||
};
|
||||
|
||||
OptionsField field_fake_brightness{
|
||||
@ -778,10 +776,10 @@ class SetDisplayView : public View {
|
||||
16,
|
||||
"Enable brightness adjust"};
|
||||
|
||||
Checkbox checkbox_ips_screen_switch{
|
||||
{1 * 8, 12 * 16},
|
||||
Checkbox checkbox_invert_switch{
|
||||
{1 * 8, 10 * 16},
|
||||
23,
|
||||
"IPS Screen"};
|
||||
"Invert colors (For IPS)"};
|
||||
|
||||
Button button_save{
|
||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||
@ -980,13 +978,9 @@ 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},
|
||||
/**/
|
||||
{{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}};
|
||||
|
||||
{{1 * 8, 2 * 16}, "method to voltage based", Theme::getInstance()->fg_light->foreground}};
|
||||
Labels labels2{
|
||||
{{1 * 8, 6 * 16}, "Reset IC's learned params.", Theme::getInstance()->fg_light->foreground}};
|
||||
Button button_save{
|
||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||
"Save"};
|
||||
@ -996,18 +990,13 @@ 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, 13 * 16, 12 * 8, 32},
|
||||
{2 * 8, 8 * 16, 12 * 8, 32},
|
||||
"Reset",
|
||||
};
|
||||
};
|
||||
|
@ -617,7 +617,6 @@ 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,7 +25,6 @@
|
||||
#include "ui.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "ui_widget.hpp"
|
||||
#include "ui_textentry.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
@ -106,7 +105,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, ENTER_KEYBOARD_MODE_ALPHA,
|
||||
text_prompt(nav, buf, /*max_length*/ 255,
|
||||
[&tf](std::string& str) {
|
||||
tf.set_text(str);
|
||||
});
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -131,7 +131,6 @@ ADSBCallsignView::ADSBCallsignView(
|
||||
nav,
|
||||
callsign,
|
||||
8,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& s) {
|
||||
button_callsign.set_text(s);
|
||||
});
|
||||
|
@ -80,7 +80,7 @@ bool DebugDumpView::debug_dump_func() {
|
||||
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_normally_black: " + to_string_dec_uint(config_lcd_normally_black()));
|
||||
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()));
|
||||
@ -128,7 +128,6 @@ bool DebugDumpView::debug_dump_func() {
|
||||
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()));
|
||||
|
5
firmware/application/external/external.cmake
vendored
5
firmware/application/external/external.cmake
vendored
@ -203,10 +203,6 @@ set(EXTCPPSRC
|
||||
#level
|
||||
external/level/main.cpp
|
||||
external/level/ui_level.cpp
|
||||
|
||||
#gfxEQ
|
||||
external/gfxeq/main.cpp
|
||||
external/gfxeq/ui_gfxeq.cpp
|
||||
)
|
||||
|
||||
set(EXTAPPLIST
|
||||
@ -259,5 +255,4 @@ set(EXTAPPLIST
|
||||
debug_pmem
|
||||
scanner
|
||||
level
|
||||
gfxeq
|
||||
)
|
||||
|
7
firmware/application/external/external.ld
vendored
7
firmware/application/external/external.ld
vendored
@ -72,7 +72,6 @@ MEMORY
|
||||
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
|
||||
ram_external_app_gfxeq (rwx) : org = 0xADE20000, len = 32k
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
@ -369,10 +368,4 @@ SECTIONS
|
||||
KEEP(*(.external_app.app_level.application_information));
|
||||
*(*ui*external_app*level*);
|
||||
} > ram_external_app_level
|
||||
|
||||
.external_app_gfxeq : ALIGN(4) SUBALIGN(4)
|
||||
{
|
||||
KEEP(*(.external_app.app_gfxeq.application_information));
|
||||
*(*ui*external_app*gfxeq*);
|
||||
} > ram_external_app_gfxeq
|
||||
}
|
||||
|
36
firmware/application/external/gfxeq/main.cpp
vendored
36
firmware/application/external/gfxeq/main.cpp
vendored
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* ------------------------------------------------------------
|
||||
* | Made by RocketGod |
|
||||
* | Find me at https://betaskynet.com |
|
||||
* | Argh matey! |
|
||||
* ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "ui_gfxeq.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "external_app.hpp"
|
||||
|
||||
namespace ui::external_app::gfxeq {
|
||||
void initialize_app(ui::NavigationView& nav) {
|
||||
nav.push<gfxEQView>();
|
||||
}
|
||||
} // namespace ui::external_app::gfxeq
|
||||
|
||||
extern "C" {
|
||||
__attribute__((section(".external_app.app_gfxeq.application_information"), used)) application_information_t _application_information_gfxeq = {
|
||||
(uint8_t*)0x00000000,
|
||||
ui::external_app::gfxeq::initialize_app,
|
||||
CURRENT_HEADER_VERSION,
|
||||
VERSION_MD5,
|
||||
"gfxEQ",
|
||||
{0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
||||
ui::Color::green().v,
|
||||
app_location_t::RX,
|
||||
-1,
|
||||
{'P', 'N', 'F', 'M'},
|
||||
0x00000000,
|
||||
};
|
||||
|
||||
} // namespace ui::external_app::gfxeq
|
196
firmware/application/external/gfxeq/ui_gfxeq.cpp
vendored
196
firmware/application/external/gfxeq/ui_gfxeq.cpp
vendored
@ -1,196 +0,0 @@
|
||||
/*
|
||||
* ------------------------------------------------------------
|
||||
* | Made by RocketGod |
|
||||
* | Find me at https://betaskynet.com |
|
||||
* | Argh matey! |
|
||||
* ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "ui_gfxeq.hpp"
|
||||
#include "ui.hpp"
|
||||
#include "ui_freqman.hpp"
|
||||
#include "tone_key.hpp"
|
||||
#include "analog_audio_app.hpp"
|
||||
#include "portapack.hpp"
|
||||
#include "audio.hpp"
|
||||
#include "baseband_api.hpp"
|
||||
#include "dsp_fir_taps.hpp"
|
||||
|
||||
using namespace portapack;
|
||||
|
||||
namespace ui::external_app::gfxeq {
|
||||
|
||||
gfxEQView::gfxEQView(NavigationView& nav)
|
||||
: nav_{nav}, bar_heights(NUM_BARS, 0), prev_bar_heights(NUM_BARS, 0) {
|
||||
add_children({&button_frequency, &field_rf_amp, &field_lna, &field_vga,
|
||||
&button_mood, &field_volume});
|
||||
|
||||
audio::output::stop();
|
||||
receiver_model.disable();
|
||||
baseband::shutdown();
|
||||
|
||||
baseband::run_image(portapack::spi_flash::image_tag_wfm_audio);
|
||||
|
||||
receiver_model.set_modulation(ReceiverModel::Mode::WidebandFMAudio);
|
||||
receiver_model.set_wfm_configuration(1); // 200k => 0 , 180k => 1 , 40k => 2. Set to 1 or 2 for better reception
|
||||
receiver_model.set_sampling_rate(3072000);
|
||||
receiver_model.set_baseband_bandwidth(1750000);
|
||||
|
||||
audio::set_rate(audio::Rate::Hz_48000);
|
||||
audio::output::start();
|
||||
receiver_model.set_headphone_volume(receiver_model.headphone_volume()); // WM8731 hack
|
||||
//
|
||||
receiver_model.enable();
|
||||
|
||||
receiver_model.set_target_frequency(frequency_value); // Retune to actual freq
|
||||
button_frequency.set_text("<" + to_string_short_freq(frequency_value) + ">");
|
||||
|
||||
button_frequency.on_select = [this, &nav](ButtonWithEncoder& button) {
|
||||
auto new_view = nav_.push<FrequencyKeypadView>(frequency_value);
|
||||
new_view->on_changed = [this, &button](rf::Frequency f) {
|
||||
frequency_value = f;
|
||||
receiver_model.set_target_frequency(f); // Retune to actual freq
|
||||
button_frequency.set_text("<" + to_string_short_freq(frequency_value) + ">");
|
||||
};
|
||||
};
|
||||
|
||||
button_frequency.on_change = [this]() {
|
||||
int64_t def_step = 25000;
|
||||
frequency_value = frequency_value + (button_frequency.get_encoder_delta() * def_step);
|
||||
if (frequency_value < 1) {
|
||||
frequency_value = 1;
|
||||
}
|
||||
if (frequency_value > (MAX_UFREQ - def_step)) {
|
||||
frequency_value = MAX_UFREQ;
|
||||
}
|
||||
button_frequency.set_encoder_delta(0);
|
||||
receiver_model.set_target_frequency(frequency_value); // Retune to actual freq
|
||||
button_frequency.set_text("<" + to_string_short_freq(frequency_value) + ">");
|
||||
};
|
||||
|
||||
button_mood.on_select = [this](Button&) { this->cycle_theme(); };
|
||||
}
|
||||
|
||||
// needed to answer usb serial frequency set
|
||||
void gfxEQView::on_freqchg(int64_t freq) {
|
||||
receiver_model.set_target_frequency(freq); // Retune to actual freq
|
||||
button_frequency.set_text("<" + to_string_short_freq(freq) + ">");
|
||||
}
|
||||
|
||||
gfxEQView::~gfxEQView() {
|
||||
audio::output::stop();
|
||||
receiver_model.disable();
|
||||
baseband::shutdown();
|
||||
}
|
||||
|
||||
void gfxEQView::focus() {
|
||||
button_frequency.focus();
|
||||
}
|
||||
|
||||
void gfxEQView::on_show() {
|
||||
needs_background_redraw = true;
|
||||
}
|
||||
|
||||
void gfxEQView::on_hide() {
|
||||
needs_background_redraw = true;
|
||||
}
|
||||
|
||||
void gfxEQView::update_audio_spectrum(const AudioSpectrum& spectrum) {
|
||||
const float bin_frequency_size = 48000.0f / 128;
|
||||
|
||||
for (int bar = 0; bar < NUM_BARS; bar++) {
|
||||
float start_freq = FREQUENCY_BANDS[bar];
|
||||
float end_freq = FREQUENCY_BANDS[bar + 1];
|
||||
|
||||
int start_bin = std::max(1, (int)(start_freq / bin_frequency_size));
|
||||
int end_bin = std::min(127, (int)(end_freq / bin_frequency_size));
|
||||
|
||||
if (start_bin >= end_bin) {
|
||||
end_bin = start_bin + 1;
|
||||
}
|
||||
|
||||
float total_energy = 0;
|
||||
int bin_count = 0;
|
||||
|
||||
for (int bin = start_bin; bin <= end_bin; bin++) {
|
||||
total_energy += spectrum.db[bin];
|
||||
bin_count++;
|
||||
}
|
||||
|
||||
float avg_db = bin_count > 0 ? (total_energy / bin_count) : 0;
|
||||
|
||||
// Manually boost highs for better visual balance
|
||||
float treble_boost = 1.0f;
|
||||
if (bar == 10)
|
||||
treble_boost = 1.7f;
|
||||
else if (bar >= 9)
|
||||
treble_boost = 1.3f;
|
||||
else if (bar >= 7)
|
||||
treble_boost = 1.3f;
|
||||
|
||||
// Mid emphasis for a V-shape effect
|
||||
float mid_boost = 1.0f;
|
||||
if (bar == 4 || bar == 5 || bar == 6) mid_boost = 1.2f;
|
||||
|
||||
float amplified_db = avg_db * treble_boost * mid_boost;
|
||||
|
||||
if (amplified_db > 255) amplified_db = 255;
|
||||
|
||||
float band_scale = 1.0f;
|
||||
int target_height = (amplified_db * RENDER_HEIGHT * band_scale) / 255;
|
||||
|
||||
if (target_height > RENDER_HEIGHT) {
|
||||
target_height = RENDER_HEIGHT;
|
||||
}
|
||||
|
||||
// Adjusted to look nice to my eyes
|
||||
float rise_speed = 0.8f;
|
||||
float fall_speed = 1.0f;
|
||||
|
||||
if (target_height > bar_heights[bar]) {
|
||||
bar_heights[bar] = bar_heights[bar] * (1.0f - rise_speed) + target_height * rise_speed;
|
||||
} else {
|
||||
bar_heights[bar] = bar_heights[bar] * (1.0f - fall_speed) + target_height * fall_speed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gfxEQView::render_equalizer(Painter& painter) {
|
||||
const int num_segments = RENDER_HEIGHT / SEGMENT_HEIGHT;
|
||||
const ColorTheme& theme = themes[current_theme];
|
||||
|
||||
for (int bar = 0; bar < NUM_BARS; bar++) {
|
||||
int x = HORIZONTAL_OFFSET + bar * (BAR_WIDTH + BAR_SPACING);
|
||||
int active_segments = (bar_heights[bar] * num_segments) / RENDER_HEIGHT;
|
||||
|
||||
if (prev_bar_heights[bar] > active_segments) {
|
||||
int clear_height = (prev_bar_heights[bar] - active_segments) * SEGMENT_HEIGHT;
|
||||
int clear_y = SCREEN_HEIGHT - prev_bar_heights[bar] * SEGMENT_HEIGHT;
|
||||
painter.fill_rectangle({x, clear_y, BAR_WIDTH, clear_height}, Color(0, 0, 0));
|
||||
}
|
||||
|
||||
for (int seg = 0; seg < active_segments; seg++) {
|
||||
int y = SCREEN_HEIGHT - (seg + 1) * SEGMENT_HEIGHT;
|
||||
if (y < header_height) break;
|
||||
|
||||
Color segment_color = (seg >= active_segments - 2 && seg < active_segments) ? theme.peak_color : theme.base_color;
|
||||
painter.fill_rectangle({x, y, BAR_WIDTH, SEGMENT_HEIGHT - 1}, segment_color);
|
||||
}
|
||||
|
||||
prev_bar_heights[bar] = active_segments;
|
||||
}
|
||||
}
|
||||
|
||||
void gfxEQView::paint(Painter& painter) {
|
||||
if (needs_background_redraw) {
|
||||
painter.fill_rectangle({0, header_height, SCREEN_WIDTH, RENDER_HEIGHT}, Color(0, 0, 0));
|
||||
needs_background_redraw = false;
|
||||
}
|
||||
render_equalizer(painter);
|
||||
}
|
||||
|
||||
void gfxEQView::cycle_theme() {
|
||||
current_theme = (current_theme + 1) % themes.size();
|
||||
}
|
||||
|
||||
} // namespace ui::external_app::gfxeq
|
138
firmware/application/external/gfxeq/ui_gfxeq.hpp
vendored
138
firmware/application/external/gfxeq/ui_gfxeq.hpp
vendored
@ -1,138 +0,0 @@
|
||||
/*
|
||||
* ------------------------------------------------------------
|
||||
* | Made by RocketGod |
|
||||
* | Find me at https://betaskynet.com |
|
||||
* | Argh matey! |
|
||||
* ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef __UI_GFXEQ_HPP__
|
||||
#define __UI_GFXEQ_HPP__
|
||||
|
||||
#include "ui_widget.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "ui_receiver.hpp"
|
||||
#include "message.hpp"
|
||||
#include "baseband_api.hpp"
|
||||
#include "portapack.hpp"
|
||||
#include "ui_spectrum.hpp"
|
||||
#include "ui_freq_field.hpp"
|
||||
#include "app_settings.hpp"
|
||||
#include "radio_state.hpp"
|
||||
|
||||
namespace ui::external_app::gfxeq {
|
||||
|
||||
class gfxEQView : public View {
|
||||
public:
|
||||
gfxEQView(NavigationView& nav);
|
||||
~gfxEQView();
|
||||
|
||||
gfxEQView(const gfxEQView&) = delete;
|
||||
gfxEQView& operator=(const gfxEQView&) = delete;
|
||||
|
||||
void focus() override;
|
||||
std::string title() const override { return "gfxEQ"; }
|
||||
void on_show() override;
|
||||
void on_hide() override;
|
||||
|
||||
void paint(Painter& painter) override;
|
||||
void on_freqchg(int64_t freq);
|
||||
|
||||
private:
|
||||
static constexpr ui::Dim header_height = 2 * 16;
|
||||
static constexpr int SCREEN_WIDTH = 240;
|
||||
static constexpr int SCREEN_HEIGHT = 320;
|
||||
static constexpr int RENDER_HEIGHT = 288;
|
||||
static constexpr int NUM_BARS = 11;
|
||||
static constexpr int BAR_SPACING = 2;
|
||||
static constexpr int BAR_WIDTH = (SCREEN_WIDTH - (BAR_SPACING * (NUM_BARS - 1))) / NUM_BARS;
|
||||
static constexpr int HORIZONTAL_OFFSET = 2;
|
||||
static constexpr int SEGMENT_HEIGHT = 10;
|
||||
|
||||
static constexpr std::array<int, NUM_BARS + 1> FREQUENCY_BANDS = {
|
||||
375, // Bass warmth and low rumble (e.g., deep basslines, kick drum body)
|
||||
750, // Upper bass punch (e.g., bass guitar punch, kick drum attack)
|
||||
1500, // Lower midrange fullness (e.g., warmth in vocals, guitar body)
|
||||
2250, // Midrange clarity (e.g., vocal presence, snare crack)
|
||||
3375, // Upper midrange bite (e.g., instrument definition, vocal articulation)
|
||||
4875, // Presence and edge (e.g., guitar bite, vocal sibilance start)
|
||||
6750, // Lower brilliance (e.g., cymbal shimmer, vocal clarity)
|
||||
9375, // Brilliance and air (e.g., hi-hat crispness, breathy vocals)
|
||||
13125, // High treble sparkle (e.g., subtle overtones, synth shimmer)
|
||||
16875, // Upper treble airiness (e.g., faint harmonics, room ambiance)
|
||||
20625, // Top-end sheen (e.g., ultra-high harmonics, noise floor)
|
||||
24375 // Extreme treble limit (e.g., inaudible overtones, signal cutoff, static)
|
||||
};
|
||||
|
||||
struct ColorTheme {
|
||||
Color base_color;
|
||||
Color peak_color;
|
||||
};
|
||||
|
||||
NavigationView& nav_;
|
||||
bool needs_background_redraw{false};
|
||||
std::vector<int> bar_heights;
|
||||
std::vector<int> prev_bar_heights;
|
||||
uint32_t current_theme{0};
|
||||
const std::array<ColorTheme, 20> themes{
|
||||
ColorTheme{Color(255, 0, 255), Color(255, 255, 255)},
|
||||
ColorTheme{Color(0, 255, 0), Color(255, 0, 0)},
|
||||
ColorTheme{Color(0, 0, 255), Color(255, 255, 0)},
|
||||
ColorTheme{Color(255, 128, 0), Color(255, 0, 128)},
|
||||
ColorTheme{Color(128, 0, 255), Color(0, 255, 255)},
|
||||
ColorTheme{Color(255, 255, 0), Color(0, 255, 128)},
|
||||
ColorTheme{Color(255, 0, 0), Color(0, 128, 255)},
|
||||
ColorTheme{Color(0, 255, 128), Color(255, 128, 255)},
|
||||
ColorTheme{Color(128, 128, 128), Color(255, 255, 255)},
|
||||
ColorTheme{Color(255, 64, 0), Color(0, 255, 64)},
|
||||
ColorTheme{Color(0, 128, 128), Color(255, 192, 0)},
|
||||
ColorTheme{Color(0, 255, 0), Color(0, 128, 0)},
|
||||
ColorTheme{Color(32, 64, 32), Color(0, 255, 0)},
|
||||
ColorTheme{Color(64, 0, 128), Color(255, 0, 255)},
|
||||
ColorTheme{Color(0, 64, 0), Color(0, 255, 128)},
|
||||
ColorTheme{Color(255, 255, 255), Color(0, 0, 255)},
|
||||
ColorTheme{Color(128, 0, 0), Color(255, 128, 0)},
|
||||
ColorTheme{Color(0, 128, 255), Color(255, 255, 128)},
|
||||
ColorTheme{Color(64, 64, 64), Color(255, 0, 0)},
|
||||
ColorTheme{Color(255, 192, 0), Color(0, 64, 128)}};
|
||||
|
||||
ButtonWithEncoder button_frequency{{0 * 8, 0 * 16 + 4, 11 * 8, 1 * 8}, ""};
|
||||
RFAmpField field_rf_amp{{13 * 8, 0 * 16}};
|
||||
LNAGainField field_lna{{15 * 8, 0 * 16}};
|
||||
VGAGainField field_vga{{18 * 8, 0 * 16}};
|
||||
Button button_mood{{21 * 8, 0, 6 * 8, 16}, "MOOD"};
|
||||
AudioVolumeField field_volume{{28 * 8, 0 * 16}};
|
||||
|
||||
rf::Frequency frequency_value{93100000};
|
||||
|
||||
RxRadioState rx_radio_state_{};
|
||||
|
||||
app_settings::SettingsManager settings_{
|
||||
"rx_gfx_eq",
|
||||
app_settings::Mode::RX,
|
||||
{{"theme", ¤t_theme},
|
||||
{"frequency", &frequency_value}}};
|
||||
|
||||
void update_audio_spectrum(const AudioSpectrum& spectrum);
|
||||
void render_equalizer(Painter& painter);
|
||||
void cycle_theme();
|
||||
|
||||
MessageHandlerRegistration message_handler_audio_spectrum{
|
||||
Message::ID::AudioSpectrum,
|
||||
[this](const Message* const p) {
|
||||
const auto message = *reinterpret_cast<const AudioSpectrumMessage*>(p);
|
||||
this->update_audio_spectrum(*message.data);
|
||||
this->set_dirty();
|
||||
}};
|
||||
|
||||
MessageHandlerRegistration message_handler_freqchg{
|
||||
Message::ID::FreqChangeCommand,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||
this->on_freqchg(message->freq);
|
||||
}};
|
||||
};
|
||||
|
||||
} // namespace ui::external_app::gfxeq
|
||||
|
||||
#endif
|
@ -227,7 +227,6 @@ void HopperView::save_list() {
|
||||
nav_,
|
||||
filename_buffer,
|
||||
64,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& value) {
|
||||
auto path = hopper_dir / (value + ".PHOP");
|
||||
|
||||
|
2
firmware/application/external/lcr/ui_lcr.cpp
vendored
2
firmware/application/external/lcr/ui_lcr.cpp
vendored
@ -189,7 +189,6 @@ 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);
|
||||
});
|
||||
@ -258,7 +257,6 @@ LCRView::LCRView(NavigationView& nav) {
|
||||
nav,
|
||||
rgsb,
|
||||
4,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& buffer) {
|
||||
button_set_rgsb.set_text(buffer);
|
||||
});
|
||||
|
@ -311,7 +311,6 @@ LGEView::LGEView(NavigationView& nav) {
|
||||
nav,
|
||||
nickname,
|
||||
15,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& buffer) {
|
||||
button_text.set_text(buffer);
|
||||
});
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include "baseband_api.hpp"
|
||||
#include "audio.hpp"
|
||||
#include "portapack.hpp"
|
||||
#include "ui_textentry.hpp"
|
||||
|
||||
using namespace portapack;
|
||||
|
||||
@ -43,7 +42,6 @@ MetronomeView::MetronomeView(NavigationView& nav)
|
||||
&field_unaccent_beep_tune,
|
||||
&field_beep_flash_duration,
|
||||
&field_bpm,
|
||||
&button_enter_tap_tempo,
|
||||
&progressbar,
|
||||
});
|
||||
|
||||
@ -61,14 +59,6 @@ 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);
|
||||
|
||||
@ -184,116 +174,4 @@ 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,8 +27,6 @@
|
||||
#include "audio.hpp"
|
||||
#include "ch.h"
|
||||
|
||||
#include <deque>
|
||||
|
||||
namespace ui::external_app::metronome {
|
||||
|
||||
class MetronomeView : public View {
|
||||
@ -75,11 +73,6 @@ 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,
|
||||
@ -128,45 +121,6 @@ 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__*/
|
@ -99,7 +99,7 @@ static msg_t loopthread_fn(void* arg) {
|
||||
}
|
||||
|
||||
void MorseView::on_set_text(NavigationView& nav) {
|
||||
text_prompt(nav, buffer, 28, ENTER_KEYBOARD_MODE_ALPHA);
|
||||
text_prompt(nav, buffer, 28);
|
||||
}
|
||||
|
||||
void MorseView::focus() {
|
||||
|
@ -210,7 +210,6 @@ OOKEditorAppView::OOKEditorAppView(NavigationView& nav)
|
||||
nav,
|
||||
outputFileBuffer,
|
||||
64,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[this](std::string& buffer) {
|
||||
on_save_file(buffer);
|
||||
});
|
||||
@ -264,7 +263,6 @@ OOKEditorAppView::OOKEditorAppView(NavigationView& nav)
|
||||
nav,
|
||||
ook_data.payload,
|
||||
100,
|
||||
ENTER_KEYBOARD_MODE_DIGITS,
|
||||
[this](std::string& s) {
|
||||
text_payload.set(s);
|
||||
draw_waveform();
|
||||
|
@ -83,7 +83,6 @@ 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();
|
||||
@ -101,7 +100,6 @@ 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,7 +122,6 @@ bool PlaylistEditorView::on_create_ppl() {
|
||||
nav_,
|
||||
current_ppl_name_buffer,
|
||||
100,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[&](std::string& s) {
|
||||
current_ppl_name_buffer = s;
|
||||
|
||||
@ -308,7 +307,6 @@ PlaylistItemEditView::PlaylistItemEditView(
|
||||
nav_,
|
||||
delay_str,
|
||||
100,
|
||||
ENTER_KEYBOARD_MODE_ALPHA,
|
||||
[&](std::string& s) {
|
||||
delay_ = atoi(s.c_str());
|
||||
field_delay.set_value(delay_);
|
||||
|
@ -75,7 +75,7 @@ __attribute__((section(".external_app.app_remote.application_information"), used
|
||||
},
|
||||
/*.icon_color = */ ui::Color::green().v,
|
||||
/*.menu_location = */ app_location_t::HOME,
|
||||
/*.desired_menu_position = */ 6,
|
||||
/*.desired_menu_position = */ 4,
|
||||
|
||||
/*.m4_app_tag = portapack::spi_flash::image_tag_replay */ {'P', 'R', 'E', 'P'},
|
||||
/*.m4_app_offset = */ 0x00000000, // will be filled at compile time
|
||||
|
@ -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, ENTER_KEYBOARD_MODE_ALPHA, [this](std::string& new_name) {
|
||||
text_prompt(nav_, temp_buffer_, text_edit_max, [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, ENTER_KEYBOARD_MODE_ALPHA, [this](std::string& new_name) {
|
||||
text_prompt(nav_, temp_buffer_, text_edit_max, [this](std::string& new_name) {
|
||||
rename_remote(new_name);
|
||||
refresh_ui();
|
||||
});
|
||||
|
@ -1,8 +1,6 @@
|
||||
// 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"
|
||||
@ -59,10 +57,10 @@ __attribute__((section(".external_app.app_shoppingcart_lock.application_informat
|
||||
0x00,
|
||||
},
|
||||
/*.icon_color = */ ui::Color::red().v,
|
||||
/*.menu_location = */ app_location_t::UTILITIES,
|
||||
/*.menu_location = */ app_location_t::TX,
|
||||
/*.desired_menu_position = */ -1,
|
||||
|
||||
/*.m4_app_tag = portapack::spi_flash::image_tag_audio_tx */ {'P', 'A', 'T', 'X'},
|
||||
/*.m4_app_offset = */ 0x00000000,
|
||||
/*.m4_app_tag = portapack::spi_flash::image_tag_afsk_rx */ {'P', 'A', 'T', 'X'},
|
||||
/*.m4_app_offset = */ 0x00000000, // will be filled at compile time
|
||||
};
|
||||
}
|
@ -1,8 +1,5 @@
|
||||
// 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 "shoppingcart_lock.hpp"
|
||||
|
||||
using namespace portapack;
|
||||
@ -51,6 +48,7 @@ void ShoppingCartLock::stop() {
|
||||
audio::output::stop();
|
||||
|
||||
log_event("... Resetting State Variables");
|
||||
transmitter_model.disable();
|
||||
ready_signal = false;
|
||||
thread_sync_complete = false;
|
||||
looping = false;
|
||||
@ -112,24 +110,18 @@ std::string ShoppingCartLock::list_wav_files() {
|
||||
}
|
||||
|
||||
void ShoppingCartLock::wait_for_thread() {
|
||||
uint32_t timeout = 1000;
|
||||
uint32_t timeout = 100;
|
||||
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)) {
|
||||
log_event("!!! Failed to reopen " + current_file + " for restart");
|
||||
return;
|
||||
}
|
||||
if (!reader->open(file_path)) return;
|
||||
|
||||
replay_thread = std::make_unique<ReplayThread>(
|
||||
std::move(reader),
|
||||
@ -141,8 +133,9 @@ void ShoppingCartLock::restart_playback() {
|
||||
EventDispatcher::send_message(message);
|
||||
});
|
||||
|
||||
log_event(">> RESTARTING AUDIO <<");
|
||||
log_event(">> SENDING <<");
|
||||
audio::output::start();
|
||||
transmitter_model.enable();
|
||||
}
|
||||
|
||||
void ShoppingCartLock::play_audio(const std::string& filename, bool loop) {
|
||||
@ -173,24 +166,33 @@ void ShoppingCartLock::play_audio(const std::string& filename, bool loop) {
|
||||
|
||||
wait_for_thread();
|
||||
|
||||
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);
|
||||
log_event("... Configuring Baseband");
|
||||
|
||||
const uint32_t bb_sample_rate = 1536000;
|
||||
const uint32_t decimation = bb_sample_rate / wav_sample_rate;
|
||||
|
||||
baseband::set_audiotx_config(
|
||||
wav_sample_rate,
|
||||
0.0f,
|
||||
bb_sample_rate / decimation,
|
||||
0.0f,
|
||||
5.0f,
|
||||
wav_bits_per_sample,
|
||||
wav_bits_per_sample,
|
||||
0,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false);
|
||||
|
||||
baseband::set_sample_rate(wav_sample_rate);
|
||||
|
||||
log_event("... Starting Audio Output");
|
||||
audio::output::start();
|
||||
volume_t max_volume = audio::headphone::volume_range().max;
|
||||
audio::headphone::set_volume(max_volume);
|
||||
log_event("... Setting Max Volume");
|
||||
audio::headphone::set_volume(audio::headphone::volume_range().max);
|
||||
|
||||
transmitter_model.enable();
|
||||
|
||||
log_event(">>> Playback Started <<<");
|
||||
}
|
||||
|
||||
ShoppingCartLock::ShoppingCartLock(NavigationView& nav)
|
||||
@ -223,6 +225,9 @@ 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() {
|
||||
@ -230,4 +235,4 @@ ShoppingCartLock::~ShoppingCartLock() {
|
||||
baseband::shutdown();
|
||||
}
|
||||
|
||||
} // namespace ui::external_app::shoppingcart_lock
|
||||
} // namespace ui::external_app::shoppingcart_lock
|
||||
|
@ -1,8 +1,5 @@
|
||||
// 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
|
||||
#pragma once
|
||||
|
||||
#include "ui_widget.hpp"
|
||||
@ -30,8 +27,8 @@ class ShoppingCartLock : public View {
|
||||
void focus() override;
|
||||
|
||||
private:
|
||||
static constexpr size_t BUFFER_SIZE = 512;
|
||||
static constexpr size_t NUM_BUFFERS = 2;
|
||||
static constexpr size_t BUFFER_SIZE = 8192;
|
||||
static constexpr size_t NUM_BUFFERS = 8;
|
||||
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, ENTER_KEYBOARD_MODE_DIGITS);
|
||||
text_prompt(nav, buffer, 300);
|
||||
}
|
||||
|
||||
void SpectrumInputTextView::focus() {
|
||||
|
@ -51,4 +51,3 @@ const std::filesystem::path whipcalc_dir = u"WHIPCALC";
|
||||
const std::filesystem::path ook_editor_dir = u"OOKFILES";
|
||||
const std::filesystem::path hopper_dir = u"HOPPER";
|
||||
const std::filesystem::path subghz_dir = u"SUBGHZ";
|
||||
const std::filesystem::path waterfalls_dir = u"WATERFALLS";
|
||||
|
@ -53,6 +53,5 @@ extern const std::filesystem::path whipcalc_dir;
|
||||
extern const std::filesystem::path ook_editor_dir;
|
||||
extern const std::filesystem::path hopper_dir;
|
||||
extern const std::filesystem::path subghz_dir;
|
||||
extern const std::filesystem::path waterfalls_dir;
|
||||
|
||||
#endif /* __FILE_PATH_H__ */
|
||||
|
@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2025 Belousov Oleg
|
||||
*
|
||||
* 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 "gradient.hpp"
|
||||
|
||||
#include "convert.hpp"
|
||||
#include "file_reader.hpp"
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
const std::filesystem::path default_gradient_file = u"waterfall.txt";
|
||||
|
||||
Gradient::Gradient() {
|
||||
prev_index = 0;
|
||||
prev_r = 0;
|
||||
prev_g = 0;
|
||||
prev_b = 0;
|
||||
}
|
||||
|
||||
void Gradient::set_default() {
|
||||
step(86, 0, 0, 255);
|
||||
step(171, 0, 255, 0);
|
||||
step(255, 255, 0, 0);
|
||||
}
|
||||
|
||||
bool Gradient::load_file(const std::filesystem::path& file_path) {
|
||||
File gradient_file;
|
||||
auto error = gradient_file.open(file_path.string());
|
||||
|
||||
if (error)
|
||||
return false;
|
||||
|
||||
auto reader = FileLineReader(gradient_file);
|
||||
for (const auto& line : reader) {
|
||||
if (line.length() == 0 || line[0] == '#')
|
||||
continue; // Empty or comment line.
|
||||
|
||||
auto cols = split_string(line, ',');
|
||||
|
||||
if (cols.size() == 4) {
|
||||
int16_t index, r, g, b;
|
||||
|
||||
if (!parse_int(cols[0], index) || index < 0 || index > 255)
|
||||
continue;
|
||||
|
||||
if (!parse_int(cols[1], r) || r < 0 || r > 255)
|
||||
continue;
|
||||
|
||||
if (!parse_int(cols[2], g) || g < 0 || g > 255)
|
||||
continue;
|
||||
|
||||
if (!parse_int(cols[3], b) || b < 0 || b > 255)
|
||||
continue;
|
||||
|
||||
step(index, r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Gradient::step(int16_t index, int16_t r, int16_t g, int16_t b) {
|
||||
for (int16_t i = prev_index; i <= index; i++) {
|
||||
float x = (float)(i - prev_index) / (index - prev_index);
|
||||
float y = 1.0f - x;
|
||||
|
||||
int16_t new_r = prev_r * y + r * x;
|
||||
int16_t new_g = prev_g * y + g * x;
|
||||
int16_t new_b = prev_b * y + b * x;
|
||||
|
||||
lut[i] = ui::Color(new_r, new_g, new_b);
|
||||
}
|
||||
|
||||
prev_index = index;
|
||||
prev_r = r;
|
||||
prev_g = g;
|
||||
prev_b = b;
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2025 Belousov Oleg
|
||||
*
|
||||
* 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 __GRADIENT_H__
|
||||
#define __GRADIENT_H__
|
||||
|
||||
#include "ui.hpp"
|
||||
#include "file.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
|
||||
extern const std::filesystem::path default_gradient_file;
|
||||
|
||||
class Gradient {
|
||||
public:
|
||||
std::array<ui::Color, 256> lut{};
|
||||
|
||||
Gradient();
|
||||
|
||||
void set_default();
|
||||
bool load_file(const std::filesystem::path& file_path);
|
||||
|
||||
private:
|
||||
int16_t prev_index = 0;
|
||||
int16_t prev_r = 0;
|
||||
int16_t prev_g = 0;
|
||||
int16_t prev_b = 0;
|
||||
|
||||
void step(int16_t index, int16_t r, int16_t g, int16_t b);
|
||||
};
|
||||
|
||||
#endif /* __GRADIENT_H__ */
|
@ -538,6 +538,7 @@ init_status_t init() {
|
||||
|
||||
set_cpu_clock_speed();
|
||||
|
||||
if (persistent_memory::config_lcd_inverted_mode()) display.set_inverted(true);
|
||||
/* sample max: 1023 sample_t AKA uint16_t
|
||||
* touch_sensitivity: range: 1 to 128
|
||||
* threshold range: 1023/1 to 1023/128 = 1023 to 8
|
||||
|
@ -280,6 +280,265 @@ const std::array<ui::Color, 256> spectrum_rgb2_lut{{
|
||||
{132, 0, 0},
|
||||
}};
|
||||
|
||||
const std::array<ui::Color, 256> spectrum_rgb3_lut{{
|
||||
{0, 0, 0},
|
||||
{0, 0, 3},
|
||||
{0, 0, 6},
|
||||
{0, 0, 9},
|
||||
{0, 0, 12},
|
||||
{0, 0, 15},
|
||||
{0, 0, 18},
|
||||
{0, 0, 21},
|
||||
{0, 0, 24},
|
||||
{0, 0, 27},
|
||||
{0, 0, 30},
|
||||
{0, 0, 33},
|
||||
{0, 0, 36},
|
||||
{0, 0, 39},
|
||||
{0, 0, 42},
|
||||
{0, 0, 45},
|
||||
{0, 0, 48},
|
||||
{0, 0, 51},
|
||||
{0, 0, 54},
|
||||
{0, 0, 57},
|
||||
{0, 0, 60},
|
||||
{0, 0, 63},
|
||||
{0, 0, 66},
|
||||
{0, 0, 69},
|
||||
{0, 0, 72},
|
||||
{0, 0, 75},
|
||||
{0, 0, 78},
|
||||
{0, 0, 81},
|
||||
{0, 0, 84},
|
||||
{0, 0, 87},
|
||||
{0, 0, 90},
|
||||
{0, 0, 93},
|
||||
{0, 0, 96},
|
||||
{0, 0, 99},
|
||||
{0, 0, 102},
|
||||
{0, 0, 105},
|
||||
{0, 0, 108},
|
||||
{0, 0, 111},
|
||||
{0, 0, 114},
|
||||
{0, 0, 117},
|
||||
{0, 0, 120},
|
||||
{0, 0, 123},
|
||||
{0, 0, 126},
|
||||
{0, 0, 129},
|
||||
{0, 0, 132},
|
||||
{0, 0, 135},
|
||||
{0, 0, 138},
|
||||
{0, 0, 141},
|
||||
{0, 0, 144},
|
||||
{0, 0, 147},
|
||||
{0, 0, 150},
|
||||
{0, 0, 153},
|
||||
{0, 0, 156},
|
||||
{0, 0, 159},
|
||||
{0, 0, 162},
|
||||
{0, 0, 165},
|
||||
{0, 0, 168},
|
||||
{0, 0, 171},
|
||||
{0, 0, 174},
|
||||
{0, 0, 177},
|
||||
{0, 0, 180},
|
||||
{0, 0, 183},
|
||||
{0, 0, 186},
|
||||
{0, 0, 189},
|
||||
{0, 0, 192},
|
||||
{0, 0, 195},
|
||||
{0, 0, 198},
|
||||
{0, 0, 201},
|
||||
{0, 0, 204},
|
||||
{0, 0, 207},
|
||||
{0, 0, 210},
|
||||
{0, 0, 213},
|
||||
{0, 0, 216},
|
||||
{0, 0, 219},
|
||||
{0, 0, 222},
|
||||
{0, 0, 225},
|
||||
{0, 0, 228},
|
||||
{0, 0, 231},
|
||||
{0, 0, 234},
|
||||
{0, 0, 237},
|
||||
{0, 0, 240},
|
||||
{0, 0, 243},
|
||||
{0, 0, 246},
|
||||
{0, 0, 249},
|
||||
{0, 0, 252},
|
||||
{0, 0, 255},
|
||||
{0, 3, 252},
|
||||
{0, 6, 249},
|
||||
{0, 9, 246},
|
||||
{0, 12, 243},
|
||||
{0, 15, 240},
|
||||
{0, 18, 237},
|
||||
{0, 21, 234},
|
||||
{0, 24, 231},
|
||||
{0, 27, 228},
|
||||
{0, 30, 225},
|
||||
{0, 33, 222},
|
||||
{0, 36, 219},
|
||||
{0, 39, 216},
|
||||
{0, 42, 213},
|
||||
{0, 45, 210},
|
||||
{0, 48, 207},
|
||||
{0, 51, 204},
|
||||
{0, 54, 201},
|
||||
{0, 57, 198},
|
||||
{0, 60, 195},
|
||||
{0, 63, 192},
|
||||
{0, 66, 189},
|
||||
{0, 69, 186},
|
||||
{0, 72, 183},
|
||||
{0, 75, 180},
|
||||
{0, 78, 177},
|
||||
{0, 81, 174},
|
||||
{0, 84, 171},
|
||||
{0, 87, 168},
|
||||
{0, 90, 165},
|
||||
{0, 93, 162},
|
||||
{0, 96, 159},
|
||||
{0, 99, 156},
|
||||
{0, 102, 153},
|
||||
{0, 105, 150},
|
||||
{0, 108, 147},
|
||||
{0, 111, 144},
|
||||
{0, 114, 141},
|
||||
{0, 117, 138},
|
||||
{0, 120, 135},
|
||||
{0, 123, 132},
|
||||
{0, 126, 129},
|
||||
{0, 129, 126},
|
||||
{0, 132, 123},
|
||||
{0, 135, 120},
|
||||
{0, 138, 117},
|
||||
{0, 141, 114},
|
||||
{0, 144, 111},
|
||||
{0, 147, 108},
|
||||
{0, 150, 105},
|
||||
{0, 153, 102},
|
||||
{0, 156, 99},
|
||||
{0, 159, 96},
|
||||
{0, 162, 93},
|
||||
{0, 165, 90},
|
||||
{0, 168, 87},
|
||||
{0, 171, 84},
|
||||
{0, 174, 81},
|
||||
{0, 177, 78},
|
||||
{0, 180, 75},
|
||||
{0, 183, 72},
|
||||
{0, 186, 69},
|
||||
{0, 189, 66},
|
||||
{0, 192, 63},
|
||||
{0, 195, 60},
|
||||
{0, 198, 57},
|
||||
{0, 201, 54},
|
||||
{0, 204, 51},
|
||||
{0, 207, 48},
|
||||
{0, 210, 45},
|
||||
{0, 213, 42},
|
||||
{0, 216, 39},
|
||||
{0, 219, 36},
|
||||
{0, 222, 33},
|
||||
{0, 225, 30},
|
||||
{0, 228, 27},
|
||||
{0, 231, 24},
|
||||
{0, 234, 21},
|
||||
{0, 237, 18},
|
||||
{0, 240, 15},
|
||||
{0, 243, 12},
|
||||
{0, 246, 9},
|
||||
{0, 249, 6},
|
||||
{0, 252, 3},
|
||||
{0, 255, 0},
|
||||
{3, 252, 0},
|
||||
{6, 249, 0},
|
||||
{9, 246, 0},
|
||||
{12, 243, 0},
|
||||
{15, 240, 0},
|
||||
{18, 237, 0},
|
||||
{21, 234, 0},
|
||||
{24, 231, 0},
|
||||
{27, 228, 0},
|
||||
{30, 225, 0},
|
||||
{33, 222, 0},
|
||||
{36, 219, 0},
|
||||
{39, 216, 0},
|
||||
{42, 213, 0},
|
||||
{45, 210, 0},
|
||||
{48, 207, 0},
|
||||
{51, 204, 0},
|
||||
{54, 201, 0},
|
||||
{57, 198, 0},
|
||||
{60, 195, 0},
|
||||
{63, 192, 0},
|
||||
{66, 189, 0},
|
||||
{69, 186, 0},
|
||||
{72, 183, 0},
|
||||
{75, 180, 0},
|
||||
{78, 177, 0},
|
||||
{81, 174, 0},
|
||||
{84, 171, 0},
|
||||
{87, 168, 0},
|
||||
{90, 165, 0},
|
||||
{93, 162, 0},
|
||||
{96, 159, 0},
|
||||
{99, 156, 0},
|
||||
{102, 153, 0},
|
||||
{105, 150, 0},
|
||||
{108, 147, 0},
|
||||
{111, 144, 0},
|
||||
{114, 141, 0},
|
||||
{117, 138, 0},
|
||||
{120, 135, 0},
|
||||
{123, 132, 0},
|
||||
{126, 129, 0},
|
||||
{129, 126, 0},
|
||||
{132, 123, 0},
|
||||
{135, 120, 0},
|
||||
{138, 117, 0},
|
||||
{141, 114, 0},
|
||||
{144, 111, 0},
|
||||
{147, 108, 0},
|
||||
{150, 105, 0},
|
||||
{153, 102, 0},
|
||||
{156, 99, 0},
|
||||
{159, 96, 0},
|
||||
{162, 93, 0},
|
||||
{165, 90, 0},
|
||||
{168, 87, 0},
|
||||
{171, 84, 0},
|
||||
{174, 81, 0},
|
||||
{177, 78, 0},
|
||||
{180, 75, 0},
|
||||
{183, 72, 0},
|
||||
{186, 69, 0},
|
||||
{189, 66, 0},
|
||||
{192, 63, 0},
|
||||
{195, 60, 0},
|
||||
{198, 57, 0},
|
||||
{201, 54, 0},
|
||||
{204, 51, 0},
|
||||
{207, 48, 0},
|
||||
{210, 45, 0},
|
||||
{213, 42, 0},
|
||||
{216, 39, 0},
|
||||
{219, 36, 0},
|
||||
{222, 33, 0},
|
||||
{225, 30, 0},
|
||||
{228, 27, 0},
|
||||
{231, 24, 0},
|
||||
{234, 21, 0},
|
||||
{237, 18, 0},
|
||||
{240, 15, 0},
|
||||
{243, 12, 0},
|
||||
{246, 9, 0},
|
||||
{249, 6, 0},
|
||||
{252, 3, 0},
|
||||
{255, 0, 0},
|
||||
}};
|
||||
|
||||
const std::array<ui::Color, 256> spectrum_rgb4_lut{{
|
||||
{0, 0, 0},
|
||||
{1, 1, 1},
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <array>
|
||||
|
||||
extern const std::array<ui::Color, 256> spectrum_rgb2_lut;
|
||||
extern const std::array<ui::Color, 256> spectrum_rgb3_lut;
|
||||
extern const std::array<ui::Color, 256> spectrum_rgb4_lut;
|
||||
|
||||
#endif /*__SPECTRUM_COLOR_LUT_H__*/
|
||||
|
@ -32,8 +32,7 @@ namespace ui {
|
||||
AlphanumView::AlphanumView(
|
||||
NavigationView& nav,
|
||||
std::string& str,
|
||||
size_t max_length,
|
||||
uint8_t enter_mode)
|
||||
size_t max_length)
|
||||
: TextEntryView(nav, str, max_length) {
|
||||
size_t n;
|
||||
|
||||
@ -77,7 +76,7 @@ AlphanumView::AlphanumView(
|
||||
n++;
|
||||
}
|
||||
|
||||
set_mode(enter_mode);
|
||||
set_mode(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, uint8_t enter_mode);
|
||||
AlphanumView(NavigationView& nav, std::string& str, size_t max_length);
|
||||
|
||||
AlphanumView(const AlphanumView&) = delete;
|
||||
AlphanumView(AlphanumView&&) = delete;
|
||||
|
@ -29,7 +29,6 @@
|
||||
|
||||
#include "irq_controls.hpp"
|
||||
#include "rf_path.hpp"
|
||||
#include "freqman_db.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
@ -38,10 +37,6 @@
|
||||
|
||||
#define MAX_UFREQ 7200000000 // maximum usable frequency
|
||||
|
||||
using option_db_t = std::pair<std::string_view, int32_t>;
|
||||
using options_db_t = std::vector<option_db_t>;
|
||||
extern options_db_t freqman_steps;
|
||||
|
||||
namespace ui {
|
||||
|
||||
class FrequencyField : public Widget {
|
||||
@ -268,12 +263,22 @@ class FrequencyStepView : public OptionsField {
|
||||
: OptionsField{
|
||||
parent_pos,
|
||||
5,
|
||||
{}} {
|
||||
options_t options;
|
||||
for (const auto& step : freqman_steps) {
|
||||
options.emplace_back(step.first, step.second);
|
||||
}
|
||||
set_options(options);
|
||||
{
|
||||
{" 10", 10}, /* Fine tuning SSB voice pitch,in HF and QO-100 sat #669 */
|
||||
{" 50", 50}, /* added 50Hz/10Hz,but we do not increase GUI digit decimal */
|
||||
{" 100", 100},
|
||||
{" 1k ", 1000},
|
||||
{" 3k ", 3000}, /* Approximate SSB bandwidth */
|
||||
{" 5k ", 5000},
|
||||
{" 6k3", 6250},
|
||||
{" 9k ", 9000}, /* channel spacing for LF, MF in some regions */
|
||||
{" 10k ", 10000},
|
||||
{" 12k5", 12500},
|
||||
{" 25k ", 25000},
|
||||
{"100k ", 100000},
|
||||
{" 1M ", 1000000},
|
||||
{" 10M ", 10000000},
|
||||
}} {
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyleft Mr. Robot 2025
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
@ -22,6 +21,8 @@
|
||||
|
||||
#include "ui_spectrum.hpp"
|
||||
|
||||
#include "spectrum_color_lut.hpp"
|
||||
|
||||
#include "portapack.hpp"
|
||||
using namespace portapack;
|
||||
|
||||
@ -101,15 +102,6 @@ void FrequencyScale::set_channel_filter(
|
||||
}
|
||||
}
|
||||
|
||||
void FrequencyScale::set_cursor_position(const int32_t position) {
|
||||
cursor_position = position;
|
||||
|
||||
cursor_position = std::min<int32_t>(cursor_position, 119);
|
||||
cursor_position = std::max<int32_t>(cursor_position, -120);
|
||||
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
void FrequencyScale::paint(Painter& painter) {
|
||||
const auto r = screen_rect();
|
||||
|
||||
@ -250,15 +242,6 @@ bool FrequencyScale::on_key(const KeyEvent key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FrequencyScale::on_touch(const TouchEvent touch) {
|
||||
if (touch.type == TouchEvent::Type::Start) {
|
||||
if (on_select) {
|
||||
on_select((touch.point.x() * spectrum_sampling_rate) / 240);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void FrequencyScale::on_tick_second() {
|
||||
set_dirty();
|
||||
_blink = !_blink;
|
||||
@ -288,12 +271,12 @@ void WaterfallWidget::on_channel_spectrum(
|
||||
|
||||
std::array<Color, 240> pixel_row;
|
||||
for (size_t i = 0; i < 120; i++) {
|
||||
const auto pixel_color = gradient.lut[spectrum.db[256 - 120 + i]];
|
||||
const auto pixel_color = spectrum_rgb3_lut[spectrum.db[256 - 120 + i]];
|
||||
pixel_row[i] = pixel_color;
|
||||
}
|
||||
|
||||
for (size_t i = 120; i < 240; i++) {
|
||||
const auto pixel_color = gradient.lut[spectrum.db[i - 120]];
|
||||
const auto pixel_color = spectrum_rgb3_lut[spectrum.db[i - 120]];
|
||||
pixel_row[i] = pixel_color;
|
||||
}
|
||||
|
||||
@ -304,15 +287,6 @@ void WaterfallWidget::on_channel_spectrum(
|
||||
pixel_row);
|
||||
}
|
||||
|
||||
bool WaterfallWidget::on_touch(const TouchEvent event) {
|
||||
if (event.type == TouchEvent::Type::Start) {
|
||||
if (on_touch_select) {
|
||||
on_touch_select(event.point.x(), event.point.y());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void WaterfallWidget::clear() {
|
||||
display.fill_rectangle(
|
||||
screen_rect(),
|
||||
@ -331,22 +305,6 @@ WaterfallView::WaterfallView(const bool cursor) {
|
||||
frequency_scale.on_select = [this](int32_t offset) {
|
||||
if (on_select) on_select(offset);
|
||||
};
|
||||
|
||||
waterfall_widget.on_touch_select = [this](int32_t x, int32_t y) {
|
||||
if (y > screen_height - screen_height * 0.1) return; // prevent ghost touch
|
||||
|
||||
frequency_scale.focus(); // focus on frequency scale to show cursor
|
||||
|
||||
if (sampling_rate) {
|
||||
// screen x to frequency scale x, NB we need two widgets align
|
||||
int32_t cursor_position = x - (screen_width / 2);
|
||||
frequency_scale.set_cursor_position(cursor_position);
|
||||
}
|
||||
};
|
||||
|
||||
if (!waterfall_widget.gradient.load_file(default_gradient_file)) {
|
||||
waterfall_widget.gradient.set_default();
|
||||
}
|
||||
}
|
||||
|
||||
void WaterfallView::on_show() {
|
||||
|
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyleft Mr. Robot 2025
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
@ -25,7 +24,6 @@
|
||||
|
||||
#include "ui.hpp"
|
||||
#include "ui_widget.hpp"
|
||||
#include "gradient.hpp"
|
||||
|
||||
#include "event_m0.hpp"
|
||||
|
||||
@ -80,11 +78,9 @@ class FrequencyScale : public Widget {
|
||||
|
||||
bool on_encoder(const EncoderEvent delta) override;
|
||||
bool on_key(const KeyEvent key) override;
|
||||
bool on_touch(const TouchEvent touch) override;
|
||||
|
||||
void set_spectrum_sampling_rate(const int new_sampling_rate);
|
||||
void set_channel_filter(const int low_frequency, const int high_frequency, const int transition);
|
||||
void set_cursor_position(const int32_t position);
|
||||
|
||||
void paint(Painter& painter) override;
|
||||
|
||||
@ -115,14 +111,9 @@ class FrequencyScale : public Widget {
|
||||
|
||||
class WaterfallWidget : public Widget {
|
||||
public:
|
||||
std::function<void(int32_t offset, int32_t y)> on_touch_select{};
|
||||
|
||||
Gradient gradient{};
|
||||
|
||||
void on_show() override;
|
||||
void on_hide() override;
|
||||
void paint(Painter&) override {}
|
||||
bool on_touch(const TouchEvent event) override;
|
||||
|
||||
void on_channel_spectrum(const ChannelSpectrum& spectrum);
|
||||
|
||||
|
@ -31,9 +31,8 @@ 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, mode, on_done);
|
||||
text_prompt(nav, str, str.length(), max_length, on_done);
|
||||
}
|
||||
|
||||
void text_prompt(
|
||||
@ -41,9 +40,8 @@ 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, mode);
|
||||
auto te_view = nav.push<AlphanumView>(str, max_length);
|
||||
te_view->set_cursor(cursor_pos);
|
||||
te_view->on_changed = [on_done](std::string& value) {
|
||||
if (on_done)
|
||||
|
@ -26,11 +26,6 @@
|
||||
#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 {
|
||||
@ -67,7 +62,6 @@ 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(
|
||||
@ -75,7 +69,6 @@ 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 */
|
||||
|
@ -117,10 +117,10 @@ const NavigationView::AppList NavigationView::appList = {
|
||||
/* HOME ******************************************************************/
|
||||
{nullptr, "Receive", HOME, Color::cyan(), &bitmap_icon_receivers, new ViewFactory<ReceiversMenuView>()},
|
||||
{nullptr, "Transmit", HOME, Color::cyan(), &bitmap_icon_transmit, new ViewFactory<TransmittersMenuView>()},
|
||||
{nullptr, "Tranceiver", HOME, Color::cyan(), &bitmap_icon_tranceivers, new ViewFactory<TranceiversMenuView>()},
|
||||
{"recon", "Recon", HOME, Color::green(), &bitmap_icon_scanner, new ViewFactory<ReconView>()},
|
||||
{"capture", "Capture", HOME, Color::red(), &bitmap_icon_capture, new ViewFactory<CaptureAppView>()},
|
||||
{"replay", "Replay", HOME, Color::green(), &bitmap_icon_replay, new ViewFactory<PlaylistView>()},
|
||||
{"recon", "Recon", HOME, Color::green(), &bitmap_icon_scanner, new ViewFactory<ReconView>()},
|
||||
{"microphone", "Microphone", HOME, Color::green(), &bitmap_icon_microphone, new ViewFactory<MicTXView>()},
|
||||
{"lookingglass", "Looking Glass", HOME, Color::green(), &bitmap_icon_looking, new ViewFactory<GlassView>()},
|
||||
{nullptr, "Utilities", HOME, Color::cyan(), &bitmap_icon_utilities, new ViewFactory<UtilitiesMenuView>()},
|
||||
{nullptr, "Games", HOME, Color::cyan(), &bitmap_icon_games, new ViewFactory<GamesMenuView>()},
|
||||
@ -146,9 +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", "SignalGen", TX, Color::green(), &bitmap_icon_cwgen, new ViewFactory<SigGenView>()},
|
||||
/* TRX ********************************************************************/
|
||||
{"microphone", "Mic", TRX, Color::green(), &bitmap_icon_microphone, new ViewFactory<MicTXView>()},
|
||||
{"signalgen", "Signal Gen", 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>()},
|
||||
@ -345,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 && pmem::ui_battery_charge_hint()) {
|
||||
if (msg->on_charger && !was_charging) {
|
||||
// Only show charging modal when transitioning to charging state
|
||||
nav_.display_modal(
|
||||
"CHARGING",
|
||||
@ -382,7 +380,7 @@ void SystemStatusView::refresh() {
|
||||
// Display "Disable speaker" icon only if AK4951 Codec which has separate speaker/headphone control
|
||||
if (audio::speaker_disable_supported() && !pmem::ui_hide_speaker()) status_icons.add(&toggle_speaker);
|
||||
|
||||
if (!pmem::ui_hide_fake_brightness()) status_icons.add(&button_fake_brightness);
|
||||
if (!pmem::ui_hide_fake_brightness() && !pmem::config_lcd_inverted_mode()) status_icons.add(&button_fake_brightness);
|
||||
if (battery::BatteryManagement::isDetected()) {
|
||||
batt_was_inited = true;
|
||||
if (!pmem::ui_hide_battery_icon()) {
|
||||
@ -416,7 +414,7 @@ void SystemStatusView::refresh() {
|
||||
button_converter.set_foreground(pmem::config_converter() ? Theme::getInstance()->fg_red->foreground : Theme::getInstance()->fg_light->foreground);
|
||||
|
||||
// Fake Brightness
|
||||
button_fake_brightness.set_foreground(pmem::apply_fake_brightness() ? *Theme::getInstance()->status_active : Theme::getInstance()->fg_light->foreground);
|
||||
button_fake_brightness.set_foreground((pmem::apply_fake_brightness() & (!pmem::config_lcd_inverted_mode())) ? *Theme::getInstance()->status_active : Theme::getInstance()->fg_light->foreground);
|
||||
|
||||
set_dirty();
|
||||
}
|
||||
@ -843,22 +841,6 @@ void TransmittersMenuView::on_populate() {
|
||||
add_external_items(nav_, app_location_t::TX, *this, return_icon ? 1 : 0);
|
||||
}
|
||||
|
||||
/* TranceiversMenuView **************************************************/
|
||||
|
||||
TranceiversMenuView::TranceiversMenuView(NavigationView& nav)
|
||||
: nav_(nav) {}
|
||||
|
||||
void TranceiversMenuView::on_populate() {
|
||||
bool return_icon = pmem::show_gui_return_icon();
|
||||
if (return_icon) {
|
||||
add_items({{"..", Theme::getInstance()->fg_light->foreground, &bitmap_icon_previous, [this]() { nav_.pop(); }}});
|
||||
}
|
||||
add_apps(nav_, *this, TRX);
|
||||
// add_external_items(nav_, app_location_t::TRX, *this, return_icon ? 1 : 0);
|
||||
// this folder doesn't have external apps, comment to prevent pop the err msg.
|
||||
// NB: when has external app someday, uncomment this.
|
||||
}
|
||||
|
||||
/* UtilitiesMenuView *****************************************************/
|
||||
|
||||
UtilitiesMenuView::UtilitiesMenuView(NavigationView& nav)
|
||||
|
@ -379,16 +379,6 @@ class TransmittersMenuView : public BtnGridView {
|
||||
void on_populate() override;
|
||||
};
|
||||
|
||||
class TranceiversMenuView : public BtnGridView {
|
||||
public:
|
||||
TranceiversMenuView(NavigationView& nav);
|
||||
std::string title() const override { return "Tranceiver"; };
|
||||
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
void on_populate() override;
|
||||
};
|
||||
|
||||
class UtilitiesMenuView : public BtnGridView {
|
||||
public:
|
||||
UtilitiesMenuView(NavigationView& nav);
|
||||
|
@ -691,9 +691,6 @@ static void printAppInfo(BaseSequentialStream* chp, ui::AppInfoConsole& element)
|
||||
case TX:
|
||||
chprintf(chp, "[TX]\r\n");
|
||||
break;
|
||||
case TRX:
|
||||
chprintf(chp, "[TRX]\r\n");
|
||||
break;
|
||||
case UTILITIES:
|
||||
chprintf(chp, "[UTIL]\r\n");
|
||||
break;
|
||||
@ -718,9 +715,6 @@ static void printAppInfo(BaseSequentialStream* chp, const ui::AppInfo& element)
|
||||
case TX:
|
||||
chprintf(chp, "[TX]\r\n");
|
||||
break;
|
||||
case TRX:
|
||||
chprintf(chp, "[TRX]\r\n");
|
||||
break;
|
||||
case UTILITIES:
|
||||
chprintf(chp, "[UTIL]\r\n");
|
||||
break;
|
||||
|
@ -33,8 +33,6 @@ using namespace portapack;
|
||||
|
||||
#include "file.hpp"
|
||||
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
|
||||
#include <complex>
|
||||
|
||||
#include <cstring>
|
||||
@ -145,13 +143,7 @@ void lcd_init() {
|
||||
// REV = 1 (normally white)
|
||||
// NL = 0b100111 (default)
|
||||
// PCDIV = 0b000000 (default?)
|
||||
|
||||
/*as per the datasheet chapter 8.3.7, addr B6h,
|
||||
data "REV" bit, liquid crystal type:*/
|
||||
if (portapack::persistent_memory::config_lcd_normally_black())
|
||||
io.lcd_data_write_command_and_data(0xB6, {0x0A, 0x22, 0x27, 0x00}); // IPS : normally black : 0
|
||||
else
|
||||
io.lcd_data_write_command_and_data(0xB6, {0x0A, 0xA2, 0x27, 0x00}); // TFT : normally white : 1
|
||||
io.lcd_data_write_command_and_data(0xB6, {0x0A, 0xA2, 0x27, 0x00});
|
||||
|
||||
// Power Control 1
|
||||
// VRH[5:0]
|
||||
@ -317,6 +309,14 @@ void ILI9341::wake() {
|
||||
lcd_wake();
|
||||
}
|
||||
|
||||
void ILI9341::set_inverted(bool invert) {
|
||||
if (invert) {
|
||||
io.lcd_data_write_command_and_data(0x21, {});
|
||||
} else {
|
||||
io.lcd_data_write_command_and_data(0x20, {});
|
||||
}
|
||||
}
|
||||
|
||||
void ILI9341::fill_rectangle(ui::Rect r, const ui::Color c) {
|
||||
const auto r_clipped = r.intersect(screen_rect());
|
||||
if (!r_clipped.is_empty()) {
|
||||
|
@ -50,6 +50,8 @@ class ILI9341 {
|
||||
void sleep();
|
||||
void wake();
|
||||
|
||||
void set_inverted(bool invert);
|
||||
|
||||
void fill_rectangle(ui::Rect r, const ui::Color c);
|
||||
void fill_rectangle_unrolled8(ui::Rect r, const ui::Color c);
|
||||
void draw_line(const ui::Point start, const ui::Point end, const ui::Color color);
|
||||
|
@ -78,11 +78,11 @@ void IO::reference_oscillator(const bool enable) {
|
||||
}
|
||||
|
||||
bool IO::get_dark_cover() {
|
||||
return portapack::persistent_memory::apply_fake_brightness();
|
||||
return portapack::persistent_memory::apply_fake_brightness() & (!portapack::persistent_memory::config_lcd_inverted_mode());
|
||||
}
|
||||
|
||||
bool IO::get_is_normally_black() {
|
||||
return portapack::persistent_memory::config_lcd_normally_black();
|
||||
bool IO::get_is_inverted() {
|
||||
return portapack::persistent_memory::config_lcd_inverted_mode();
|
||||
}
|
||||
|
||||
uint8_t IO::get_brightness() {
|
||||
@ -90,7 +90,7 @@ uint8_t IO::get_brightness() {
|
||||
}
|
||||
|
||||
void IO::update_cached_values() {
|
||||
lcd_normally_black = get_is_normally_black();
|
||||
inverted_enabled = get_is_inverted();
|
||||
dark_cover_enabled = get_dark_cover();
|
||||
brightness = get_brightness();
|
||||
}
|
||||
|
@ -231,10 +231,10 @@ class IO {
|
||||
|
||||
return switches_raw;
|
||||
}
|
||||
bool lcd_normally_black = false;
|
||||
bool inverted_enabled = false;
|
||||
bool dark_cover_enabled = false;
|
||||
uint8_t brightness = 0;
|
||||
bool get_is_normally_black();
|
||||
bool get_is_inverted();
|
||||
bool get_dark_cover();
|
||||
uint8_t get_brightness();
|
||||
void update_cached_values();
|
||||
@ -419,7 +419,7 @@ class IO {
|
||||
const auto value_low = data_read();
|
||||
uint32_t original_value = (value_high << 8) | value_low;
|
||||
|
||||
if (lcd_normally_black) return original_value;
|
||||
if (inverted_enabled) return original_value;
|
||||
|
||||
if (dark_cover_enabled) {
|
||||
// this is read data, so if the fake brightness is enabled AKA get_dark_cover() == true,
|
||||
|
@ -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));
|
||||
|
||||
@ -211,7 +211,7 @@ struct data_t {
|
||||
bool updown_converter;
|
||||
bool updown_frequency_rx_correction;
|
||||
bool updown_frequency_tx_correction;
|
||||
bool lcd_normally_black : 1;
|
||||
bool lcd_inverted_mode : 1;
|
||||
bool encoder_dial_direction : 1; // false = normal, true = reverse
|
||||
bool UNUSED_6 : 1;
|
||||
bool UNUSED_7 : 1;
|
||||
@ -289,7 +289,7 @@ struct data_t {
|
||||
updown_converter(false),
|
||||
updown_frequency_rx_correction(false),
|
||||
updown_frequency_tx_correction(false),
|
||||
lcd_normally_black(false),
|
||||
lcd_inverted_mode(false),
|
||||
encoder_dial_direction(false),
|
||||
UNUSED_6(false),
|
||||
UNUSED_7(false),
|
||||
@ -981,9 +981,6 @@ 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;
|
||||
@ -1038,9 +1035,6 @@ 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() {
|
||||
@ -1090,12 +1084,12 @@ void set_config_freq_rx_correction(uint32_t v) {
|
||||
data->frequency_rx_correction = v;
|
||||
}
|
||||
|
||||
// IPS vs TFT
|
||||
bool config_lcd_normally_black() {
|
||||
return data->lcd_normally_black;
|
||||
// LCD invert
|
||||
bool config_lcd_inverted_mode() {
|
||||
return data->lcd_inverted_mode;
|
||||
}
|
||||
void set_lcd_normally_black(bool v) {
|
||||
data->lcd_normally_black = v;
|
||||
void set_lcd_inverted_mode(bool v) {
|
||||
data->lcd_inverted_mode = v;
|
||||
}
|
||||
|
||||
// Rotary encoder dial settings
|
||||
@ -1164,6 +1158,7 @@ void set_fake_brightness_level(uint8_t v) {
|
||||
// Cycle through 4 brightness options: disabled -> enabled/50% -> enabled/25% -> enabled/12.5% -> disabled
|
||||
void toggle_fake_brightness_level() {
|
||||
bool fbe = apply_fake_brightness();
|
||||
if (config_lcd_inverted_mode()) return; // for now only inverted mode OR fake brightness
|
||||
if ((!fbe) || (data->fake_brightness_level >= BRIGHTNESS_12p5)) {
|
||||
set_apply_fake_brightness(!fbe);
|
||||
data->fake_brightness_level = BRIGHTNESS_50;
|
||||
|
@ -249,8 +249,8 @@ void set_config_audio_mute(bool v);
|
||||
void set_config_speaker_disable(bool v);
|
||||
void set_config_backlight_timer(const backlight_config_t& new_value);
|
||||
void set_disable_touchscreen(bool v);
|
||||
bool config_lcd_normally_black();
|
||||
void set_lcd_normally_black(bool v);
|
||||
bool config_lcd_inverted_mode();
|
||||
void set_lcd_inverted_mode(bool v);
|
||||
|
||||
uint8_t encoder_dial_sensitivity();
|
||||
void set_encoder_dial_sensitivity(uint8_t v);
|
||||
@ -350,8 +350,6 @@ 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);
|
||||
@ -369,7 +367,6 @@ 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();
|
||||
|
@ -73,8 +73,7 @@ enum app_location_t : uint32_t {
|
||||
DEBUG,
|
||||
HOME,
|
||||
SETTINGS,
|
||||
GAMES,
|
||||
TRX
|
||||
GAMES
|
||||
};
|
||||
|
||||
struct standalone_application_information_t {
|
||||
|
@ -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()->bg_light->background);
|
||||
painter.draw_rectangle({r.location(), {r.size().width(), 1}}, Theme::getInstance()->fg_light->foreground);
|
||||
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);
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 185 B |
@ -98,12 +98,12 @@ f.write("/*\n"
|
||||
"#include \"ui.hpp\"\n\n"
|
||||
"namespace ui {\n\n")
|
||||
|
||||
for file in sorted(listdir(graphics_path)):
|
||||
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")
|
||||
f.write("#endif/*__BITMAP_HPP__*/\n")
|
||||
|
||||
print(("Converted " + str(count) + " files"))
|
||||
|
@ -137,12 +137,7 @@ 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
|
||||
|
@ -1,14 +0,0 @@
|
||||
# 0% black
|
||||
0,0,0,0
|
||||
|
||||
# 25% blue
|
||||
64,0,0,255
|
||||
|
||||
# 50% magenta
|
||||
128,255,0,255
|
||||
|
||||
# 75% green
|
||||
192,0,255,0
|
||||
|
||||
# 100% white
|
||||
255,255,255,255
|
@ -1,12 +0,0 @@
|
||||
#lines are index,r,g,b
|
||||
#if index 0 is not set, it's starting at 0,0,0,0
|
||||
#all values are ranging from 0 to 255
|
||||
|
||||
#pure blue
|
||||
86,0,0,255
|
||||
|
||||
#bright green
|
||||
171,0,255,0
|
||||
|
||||
#pure red
|
||||
255,255,0,0
|
@ -1,11 +0,0 @@
|
||||
# 0% black
|
||||
0,0,0,0
|
||||
|
||||
# 33% red
|
||||
84,255,0,0
|
||||
|
||||
# 66% yellow
|
||||
168,255,255,0
|
||||
|
||||
# 100% white
|
||||
255,255,255,255
|
@ -1,8 +0,0 @@
|
||||
# 0% black
|
||||
0,0,0,0
|
||||
|
||||
# 50% green
|
||||
128,0,255,0
|
||||
|
||||
# 100% white
|
||||
255,255,255,255
|
@ -1,14 +0,0 @@
|
||||
# 0% black
|
||||
0,0,0,0
|
||||
|
||||
# 25% blue
|
||||
64,0,0,255
|
||||
|
||||
# 50% red
|
||||
128,255,0,0
|
||||
|
||||
# 75% yellow
|
||||
192,255,255,0
|
||||
|
||||
# 100% white
|
||||
255,255,255,255
|
Loading…
x
Reference in New Issue
Block a user