mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-08-10 18:03:40 +00:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9f54f4b5eb | |||
| 178528ef96 | |||
| 5d9a2e560b | |||
| b02329019c | |||
| 8c1593fab9 | |||
| 1f27af660d | |||
| a9d2b2ff8a | |||
| a81d630d93 | |||
| efdefa85be | |||
| f25ce9ed45 | |||
| 6697d2533c | |||
| 6cf5990b0e | |||
| c97e1042b1 | |||
| 9d5ed65f6b | |||
| 2ba74d0413 | |||
| a824e30420 | |||
| 59d08a4203 | |||
| 51bc0f0100 | |||
| cebbc12084 | |||
| 4a0d42ed34 | |||
| 96879d3664 |
@@ -0,0 +1,93 @@
|
||||
name: Stable Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: echo "::set-output name=date::$(date +'%Y-%m-%d')"
|
||||
- name: Checkout
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: next
|
||||
submodules: true
|
||||
- name: Git Sumbodule Update
|
||||
run: |
|
||||
git submodule update --init --recursive
|
||||
- name: Get version
|
||||
id: version
|
||||
run: echo "::set-output name=version::$(cat .github/workflows/version.txt)"
|
||||
- name: Get past version
|
||||
id: past_version
|
||||
run: echo "::set-output name=past_version::$(cat .github/workflows/past_version.txt)"
|
||||
- name: Build the Docker image
|
||||
run: docker build -t portapack-dev -f dockerfile-nogit . --tag my-image-name:$(date +%s)
|
||||
- name: Make build folder
|
||||
run: mkdir ${{ github.workspace }}/build
|
||||
- name: Run the Docker image
|
||||
run: docker run -e VERSION_STRING=${{ steps.version.outputs.version }} -i -v ${{ github.workspace }}:/havoc portapack-dev
|
||||
- name: Create Firmware ZIP
|
||||
run: |
|
||||
zip -j firmware.zip build/firmware/portapack-h1_h2-mayhem.bin && cd flashing && zip -r ../firmware.zip *
|
||||
- name: Create SD Card ZIP
|
||||
run: |
|
||||
zip -r sdcard.zip sdcard
|
||||
- name: Create changelog
|
||||
run: |
|
||||
CHANGELOG=$(python3 .github/workflows/stable_changelog.py ${{ steps.past_version.outputs.past_version }})
|
||||
CHANGELOG="${CHANGELOG//'%'/'%25'}"
|
||||
CHANGELOG="${CHANGELOG//$'\n'/'%0A'}"
|
||||
CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
|
||||
echo "::set-output name=content::$CHANGELOG"
|
||||
id: changelog
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: v1.5.1
|
||||
release_name: Mayhem firmware ${{ steps.version.outputs.version }}
|
||||
body: |
|
||||
**Stable release - ${{ steps.version.outputs.version }}**
|
||||
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/). Please check the [readme](https://github.com/eried/portapack-mayhem/blob/master/README.md) for details.
|
||||
## Release notes
|
||||
### Revision (${{ steps.version.outputs.version }}):
|
||||
${{ steps.changelog.outputs.content }}
|
||||
|
||||
**Full Changelog**: https://github.com/eried/portapack-mayhem/compare/${{ steps.past_version.outputs.past_version }}...${{ steps.version.outputs.version }}
|
||||
|
||||
## Installation
|
||||
Check the [wiki](https://github.com/eried/portapack-havoc/wiki/Update-firmware) for details how to upgrade.
|
||||
|
||||
### MicroSD card files
|
||||
|
||||
For certain functionality, like the world map, GPS simulator, and others you need to uncompress (using [7-zip](https://www.7-zip.org/download.html)) the files from `mayhem_vX.Y.Z_COPY_TO_SDCARD.zip` to a FAT32 formatted MicroSD card.
|
||||
draft: true
|
||||
prerelease: false
|
||||
- name: Upload Firmware Asset
|
||||
id: upload-firmware-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./firmware.zip
|
||||
asset_name: mayhem_${{ steps.version.outputs.version }}_FIRMWARE.zip
|
||||
asset_content_type: application/zip
|
||||
- name: Upload SD Card Assets
|
||||
id: upload-sd-card-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./sdcard.zip
|
||||
asset_name: mayhem_${{ steps.version.outputs.version }}_COPY_TO_SDCARD.zip
|
||||
asset_content_type: application/zip
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
v1.5.0
|
||||
@@ -0,0 +1,30 @@
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
past_version = sys.argv[1]
|
||||
|
||||
raw_git = os.popen('git log ' + past_version + '..next --pretty=format:"- %h - {USERNAME}*+%al-%an*: %s"').read()
|
||||
|
||||
|
||||
def compute_username(line):
|
||||
stripped = re.search(r'(?<=\*)(.*?)(?=\*)', line).group(0)
|
||||
|
||||
pattern = re.compile("[$@+&?].*[$@+&?]")
|
||||
if pattern.match(stripped):
|
||||
stripped = re.sub("[$@+&?].*[$@+&?]", "", stripped)
|
||||
stripped = re.match(r'.+?(?=-)', stripped).group(0)
|
||||
else:
|
||||
stripped = re.sub(r'^.*?-', "", stripped)
|
||||
return "@" + stripped
|
||||
|
||||
|
||||
def compile_line(line):
|
||||
username = compute_username(line)
|
||||
line = re.sub(r'[*].*[*]', "", line)
|
||||
line = line.replace("{USERNAME}", username)
|
||||
return line
|
||||
|
||||
|
||||
for row in raw_git.splitlines():
|
||||
print(compile_line(row))
|
||||
@@ -0,0 +1 @@
|
||||
v1.5.1
|
||||
@@ -484,6 +484,7 @@ void ScannerView::scan_pause() {
|
||||
scan_thread->set_freq_lock(0); //Reset the scanner lock (because user paused, or MAX_FREQ_LOCK reached) for next freq scan
|
||||
scan_thread->set_scanning(false); // WE STOP SCANNING
|
||||
audio::output::start();
|
||||
on_headphone_volume_changed(field_volume.value()); // quick fix to make sure WM8731S chips don't stay silent after pause
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace ui {
|
||||
SetDateTimeView::SetDateTimeView(
|
||||
NavigationView& nav
|
||||
) {
|
||||
button_done.on_select = [&nav, this](Button&){
|
||||
button_save.on_select = [&nav, this](Button&){
|
||||
const auto model = this->form_collect();
|
||||
const rtc::RTC new_datetime {
|
||||
model.year, model.month, model.day,
|
||||
@@ -65,7 +65,7 @@ SetDateTimeView::SetDateTimeView(
|
||||
&field_hour,
|
||||
&field_minute,
|
||||
&field_second,
|
||||
&button_done,
|
||||
&button_save,
|
||||
&button_cancel,
|
||||
});
|
||||
|
||||
@@ -150,7 +150,7 @@ SetRadioView::SetRadioView(
|
||||
&value_freq_step,
|
||||
&labels_bias,
|
||||
&check_bias,
|
||||
&button_done,
|
||||
&button_save,
|
||||
&button_cancel
|
||||
});
|
||||
|
||||
@@ -200,7 +200,7 @@ SetRadioView::SetRadioView(
|
||||
EventDispatcher::send_message(message);
|
||||
};
|
||||
|
||||
button_done.on_select = [this, &nav](Button&){
|
||||
button_save.on_select = [this, &nav](Button&){
|
||||
const auto model = this->form_collect();
|
||||
portapack::persistent_memory::set_correction_ppb(model.ppm * 1000);
|
||||
portapack::persistent_memory::set_clkout_freq(model.freq);
|
||||
@@ -210,7 +210,7 @@ SetRadioView::SetRadioView(
|
||||
}
|
||||
|
||||
void SetRadioView::focus() {
|
||||
button_done.focus();
|
||||
button_save.focus();
|
||||
}
|
||||
|
||||
void SetRadioView::form_init(const SetFrequencyCorrectionModel& model) {
|
||||
@@ -224,76 +224,24 @@ SetFrequencyCorrectionModel SetRadioView::form_collect() {
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
SetPlayDeadView::SetPlayDeadView(NavigationView& nav) {
|
||||
add_children({
|
||||
&text_sequence,
|
||||
&button_enter,
|
||||
&button_cancel
|
||||
});
|
||||
|
||||
button_enter.on_select = [this, &nav](Button&){
|
||||
if (!entermode) {
|
||||
sequence = 0;
|
||||
keycount = 0;
|
||||
memset(sequence_txt, '-', 10);
|
||||
text_sequence.set(sequence_txt);
|
||||
entermode = true;
|
||||
button_cancel.hidden(true);
|
||||
set_dirty();
|
||||
} else {
|
||||
if (sequence == 0x8D1) // U D L R
|
||||
nav.display_modal("Warning", "Default sequence entered !", ABORT, nullptr);
|
||||
else {
|
||||
persistent_memory::set_playdead_sequence(sequence);
|
||||
nav.pop();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
button_enter.on_dir = [this](Button&, KeyEvent key){
|
||||
if ((entermode == true) && (keycount < 10)) {
|
||||
key_code = static_cast<std::underlying_type<KeyEvent>::type>(key);
|
||||
if (key_code == 0)
|
||||
sequence_txt[keycount] = 'R';
|
||||
else if (key_code == 1)
|
||||
sequence_txt[keycount] = 'L';
|
||||
else if (key_code == 2)
|
||||
sequence_txt[keycount] = 'D';
|
||||
else if (key_code == 3)
|
||||
sequence_txt[keycount] = 'U';
|
||||
text_sequence.set(sequence_txt);
|
||||
sequence = (sequence << 3) | (key_code + 1);
|
||||
keycount++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
button_cancel.on_select = [&nav](Button&){ nav.pop(); };
|
||||
}
|
||||
|
||||
void SetPlayDeadView::focus() {
|
||||
button_cancel.focus();
|
||||
}
|
||||
*/
|
||||
|
||||
SetUIView::SetUIView(NavigationView& nav) {
|
||||
add_children({
|
||||
//&checkbox_login,
|
||||
&checkbox_disable_touchscreen,
|
||||
&checkbox_speaker,
|
||||
&checkbox_bloff,
|
||||
&options_bloff,
|
||||
&checkbox_showsplash,
|
||||
&checkbox_showclock,
|
||||
&options_clockformat,
|
||||
&button_ok
|
||||
&options_clockformat,
|
||||
&button_save,
|
||||
&button_cancel
|
||||
});
|
||||
|
||||
checkbox_disable_touchscreen.set_value(persistent_memory::disable_touchscreen());
|
||||
checkbox_speaker.set_value(persistent_memory::config_speaker());
|
||||
checkbox_showsplash.set_value(persistent_memory::config_splash());
|
||||
checkbox_showclock.set_value(!persistent_memory::hide_clock());
|
||||
//checkbox_login.set_value(persistent_memory::config_login());
|
||||
|
||||
uint32_t backlight_timer = persistent_memory::config_backlight_timer();
|
||||
if (backlight_timer) {
|
||||
@@ -309,16 +257,14 @@ SetUIView::SetUIView(NavigationView& nav) {
|
||||
options_clockformat.set_selected_index(0);
|
||||
}
|
||||
|
||||
checkbox_speaker.on_select = [this](Checkbox&, bool v) {
|
||||
if (v) audio::output::speaker_mute(); //Just mute audio if speaker is disabled
|
||||
//checkbox_speaker.on_select = [this](Checkbox&, bool v) {
|
||||
// if (v) audio::output::speaker_mute(); //Just mute audio if speaker is disabled
|
||||
// persistent_memory::set_config_speaker(v); //Store Speaker status
|
||||
// StatusRefreshMessage message { }; //Refresh status bar with/out speaker
|
||||
// EventDispatcher::send_message(message);
|
||||
//};
|
||||
|
||||
persistent_memory::set_config_speaker(v); //Store Speaker status
|
||||
|
||||
StatusRefreshMessage message { }; //Refresh status bar with/out speaker
|
||||
EventDispatcher::send_message(message);
|
||||
};
|
||||
|
||||
button_ok.on_select = [&nav, this](Button&) {
|
||||
button_save.on_select = [&nav, this](Button&) {
|
||||
if (checkbox_bloff.value())
|
||||
persistent_memory::set_config_backlight_timer(options_bloff.selected_index() + 1);
|
||||
else
|
||||
@@ -329,225 +275,83 @@ SetUIView::SetUIView(NavigationView& nav) {
|
||||
persistent_memory::set_clock_with_date(true);
|
||||
else
|
||||
persistent_memory::set_clock_with_date(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (checkbox_speaker.value()) audio::output::speaker_mute(); //Just mute audio if speaker is disabled
|
||||
persistent_memory::set_config_speaker(checkbox_speaker.value()); //Store Speaker status
|
||||
StatusRefreshMessage message { }; //Refresh status bar with/out speaker
|
||||
EventDispatcher::send_message(message);
|
||||
|
||||
persistent_memory::set_config_splash(checkbox_showsplash.value());
|
||||
persistent_memory::set_clock_hidden(!checkbox_showclock.value());
|
||||
//persistent_memory::set_config_login(checkbox_login.value());
|
||||
persistent_memory::set_disable_touchscreen(checkbox_disable_touchscreen.value());
|
||||
nav.pop();
|
||||
};
|
||||
button_cancel.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
}
|
||||
|
||||
void SetUIView::focus() {
|
||||
button_ok.focus();
|
||||
button_save.focus();
|
||||
}
|
||||
|
||||
SetAudioView::SetAudioView(NavigationView& nav) {
|
||||
add_children({
|
||||
&labels,
|
||||
&field_tone_mix,
|
||||
&button_ok
|
||||
&button_save,
|
||||
&button_cancel
|
||||
});
|
||||
|
||||
field_tone_mix.set_value(persistent_memory::tone_mix());
|
||||
|
||||
button_ok.on_select = [&nav, this](Button&) {
|
||||
button_save.on_select = [&nav, this](Button&) {
|
||||
persistent_memory::set_tone_mix(field_tone_mix.value());
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
button_cancel.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
}
|
||||
|
||||
void SetAudioView::focus() {
|
||||
field_tone_mix.focus();
|
||||
button_save.focus();
|
||||
}
|
||||
|
||||
/*void ModInfoView::on_show() {
|
||||
if (modules_nb) update_infos(0);
|
||||
}
|
||||
SetQRCodeView::SetQRCodeView(NavigationView& nav) {
|
||||
add_children({
|
||||
&checkbox_bigger_qr,
|
||||
&button_save,
|
||||
&button_cancel
|
||||
});
|
||||
|
||||
void ModInfoView::update_infos(uint8_t modn) {
|
||||
char info_str[27];
|
||||
char ch;
|
||||
uint8_t c;
|
||||
Point pos = { 0, 0 };
|
||||
Rect rect = { { 16, 144 }, { 208, 144 } };
|
||||
checkbox_bigger_qr.set_value(persistent_memory::show_bigger_qr_code());
|
||||
|
||||
info_str[0] = 0;
|
||||
strcat(info_str, module_list[modn].name);
|
||||
text_namestr.set(info_str);
|
||||
|
||||
info_str[0] = 0;
|
||||
strcat(info_str, to_string_dec_uint(module_list[modn].size).c_str());
|
||||
strcat(info_str, " bytes");
|
||||
text_sizestr.set(info_str);
|
||||
|
||||
info_str[0] = 0;
|
||||
for (c = 0; c < 8; c++)
|
||||
strcat(info_str, to_string_hex(module_list[modn].md5[c], 2).c_str());
|
||||
text_md5_a.set(info_str);
|
||||
|
||||
info_str[0] = 0;
|
||||
for (c = 8; c < 16; c++)
|
||||
strcat(info_str, to_string_hex(module_list[modn].md5[c], 2).c_str());
|
||||
text_md5_b.set(info_str);
|
||||
|
||||
// TODO: Use ui_console
|
||||
display.fill_rectangle(rect, Color::black());
|
||||
|
||||
const Font& font = font::fixed_8x16;
|
||||
const auto line_height = font.line_height();
|
||||
c = 0;
|
||||
while((ch = module_list[modn].description[c++])) {
|
||||
const auto glyph = font.glyph(ch);
|
||||
const auto advance = glyph.advance();
|
||||
if((pos.x + advance.x) > rect.width()) {
|
||||
pos.x = 0;
|
||||
pos.y += line_height;
|
||||
}
|
||||
const Point pos_glyph {
|
||||
static_cast<Coord>(rect.pos.x + pos.x),
|
||||
static_cast<Coord>(rect.pos.y + pos.y)
|
||||
};
|
||||
display.draw_glyph(pos_glyph, glyph, Color::white(), Color::black());
|
||||
pos.x += advance.x;
|
||||
}
|
||||
}
|
||||
|
||||
ModInfoView::ModInfoView(NavigationView& nav) {
|
||||
const char magic[4] = {'P', 'P', 'M', ' '};
|
||||
UINT bw;
|
||||
uint8_t i;
|
||||
char read_buf[16];
|
||||
char info_str[25];
|
||||
FILINFO modinfo;
|
||||
FIL modfile;
|
||||
DIR rootdir;
|
||||
FRESULT res;
|
||||
uint8_t c;
|
||||
|
||||
using option_t = std::pair<std::string, int32_t>;
|
||||
using options_t = std::vector<option_t>;
|
||||
option_t opt;
|
||||
options_t opts;
|
||||
|
||||
static constexpr Style style_orange {
|
||||
.font = font::fixed_8x16,
|
||||
.background = Color::black(),
|
||||
.foreground = Color::orange(),
|
||||
};
|
||||
|
||||
add_children({{
|
||||
&text_modcount,
|
||||
&text_name,
|
||||
&text_namestr,
|
||||
&text_size,
|
||||
&text_sizestr,
|
||||
&text_md5,
|
||||
&text_md5_a,
|
||||
&text_md5_b,
|
||||
&button_ok
|
||||
}});
|
||||
|
||||
text_name.set_style(&style_orange);
|
||||
text_size.set_style(&style_orange);
|
||||
text_md5.set_style(&style_orange);
|
||||
|
||||
// TODO: Find a way to merge this with m4_load_image() in m4_startup.cpp
|
||||
|
||||
// Scan SD card root directory for files starting with the magic bytes
|
||||
c = 0;
|
||||
if (f_opendir(&rootdir, "/") == FR_OK) {
|
||||
for (;;) {
|
||||
res = f_readdir(&rootdir, &modinfo);
|
||||
if (res != FR_OK || modinfo.fname[0] == 0) break; // Reached last file, abort
|
||||
// Only care about files with .bin extension
|
||||
if ((!(modinfo.fattrib & AM_DIR)) && (modinfo.fname[9] == 'B') && (modinfo.fname[10] == 'I') && (modinfo.fname[11] == 'N')) {
|
||||
f_open(&modfile, modinfo.fname, FA_OPEN_EXISTING | FA_READ);
|
||||
// Magic bytes check
|
||||
f_read(&modfile, &read_buf, 4, &bw);
|
||||
for (i = 0; i < 4; i++)
|
||||
if (read_buf[i] != magic[i]) break;
|
||||
if (i == 4) {
|
||||
memcpy(&module_list[c].filename, modinfo.fname, 8);
|
||||
module_list[c].filename[8] = 0;
|
||||
|
||||
f_lseek(&modfile, 4);
|
||||
f_read(&modfile, &module_list[c].version, 2, &bw);
|
||||
f_lseek(&modfile, 6);
|
||||
f_read(&modfile, &module_list[c].size, 4, &bw);
|
||||
f_lseek(&modfile, 10);
|
||||
f_read(&modfile, &module_list[c].name, 16, &bw);
|
||||
f_lseek(&modfile, 26);
|
||||
f_read(&modfile, &module_list[c].md5, 16, &bw);
|
||||
f_lseek(&modfile, 42);
|
||||
f_read(&modfile, &module_list[c].description, 214, &bw);
|
||||
f_lseek(&modfile, 256);
|
||||
|
||||
// Sanitize
|
||||
module_list[c].name[15] = 0;
|
||||
module_list[c].description[213] = 0;
|
||||
|
||||
memcpy(info_str, module_list[c].filename, 16);
|
||||
strcat(info_str, "(V");
|
||||
strcat(info_str, to_string_dec_uint(module_list[c].version, 4, '0').c_str());
|
||||
strcat(info_str, ")");
|
||||
while(strlen(info_str) < 24)
|
||||
strcat(info_str, " ");
|
||||
|
||||
opt = std::make_pair(info_str, c);
|
||||
opts.insert(opts.end(), opt);
|
||||
|
||||
c++;
|
||||
}
|
||||
f_close(&modfile);
|
||||
}
|
||||
if (c == 8) break;
|
||||
}
|
||||
}
|
||||
f_closedir(&rootdir);
|
||||
|
||||
modules_nb = c;
|
||||
|
||||
if (modules_nb) {
|
||||
strcpy(info_str, "Found ");
|
||||
strcat(info_str, to_string_dec_uint(modules_nb, 1).c_str());
|
||||
strcat(info_str, " module(s)");
|
||||
|
||||
text_modcount.set(info_str);
|
||||
option_modules.set_options(opts);
|
||||
|
||||
add_child(&option_modules);
|
||||
|
||||
option_modules.on_change = [this](size_t n, OptionsField::value_t v) {
|
||||
(void)n;
|
||||
update_infos(v);
|
||||
};
|
||||
} else {
|
||||
strcpy(info_str, "No modules found");
|
||||
text_modcount.set(info_str);
|
||||
}
|
||||
|
||||
button_ok.on_select = [&nav,this](Button&){
|
||||
button_save.on_select = [&nav, this](Button&) {
|
||||
persistent_memory::set_show_bigger_qr_code(checkbox_bigger_qr.value());
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
button_cancel.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void ModInfoView::focus() {
|
||||
if (modules_nb)
|
||||
option_modules.focus();
|
||||
else
|
||||
button_ok.focus();
|
||||
}*/
|
||||
void SetQRCodeView::focus() {
|
||||
button_save.focus();
|
||||
}
|
||||
|
||||
SettingsMenuView::SettingsMenuView(NavigationView& nav) {
|
||||
add_items({
|
||||
//{ "..", ui::Color::light_grey(), &bitmap_icon_previous, [&nav](){ nav.pop(); } },
|
||||
{ "Audio", ui::Color::dark_cyan(), &bitmap_icon_speaker, [&nav](){ nav.push<SetAudioView>(); } },
|
||||
{ "Radio", ui::Color::dark_cyan(), &bitmap_icon_options_radio, [&nav](){ nav.push<SetRadioView>(); } },
|
||||
{ "Audio", ui::Color::dark_cyan(), &bitmap_icon_speaker, [&nav](){ nav.push<SetAudioView>(); } },
|
||||
{ "Radio", ui::Color::dark_cyan(), &bitmap_icon_options_radio, [&nav](){ nav.push<SetRadioView>(); } },
|
||||
{ "Interface", ui::Color::dark_cyan(), &bitmap_icon_options_ui, [&nav](){ nav.push<SetUIView>(); } },
|
||||
//{ "SD card modules", ui::Color::dark_cyan(), [&nav](){ nav.push<ModInfoView>(); } },
|
||||
{ "Date/Time", ui::Color::dark_cyan(), &bitmap_icon_options_datetime, [&nav](){ nav.push<SetDateTimeView>(); } },
|
||||
{ "Date/Time", ui::Color::dark_cyan(), &bitmap_icon_options_datetime, [&nav](){ nav.push<SetDateTimeView>(); } },
|
||||
{ "Touchscreen", ui::Color::dark_cyan(), &bitmap_icon_options_touch, [&nav](){ nav.push<TouchCalibrationView>(); } },
|
||||
//{ "Play dead", ui::Color::dark_cyan(), &bitmap_icon_playdead, [&nav](){ nav.push<SetPlayDeadView>(); } }
|
||||
{ "QR code", ui::Color::dark_cyan(), &bitmap_icon_qr_code, [&nav](){ nav.push<SetQRCodeView>(); } }
|
||||
});
|
||||
set_max_rows(2); // allow wider buttons
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ private:
|
||||
'0',
|
||||
};
|
||||
|
||||
Button button_done {
|
||||
Button button_save {
|
||||
{ 2 * 8, 16 * 16, 12 * 8, 32 },
|
||||
"Save"
|
||||
};
|
||||
@@ -197,7 +197,7 @@ private:
|
||||
"Turn on bias voltage"
|
||||
};
|
||||
|
||||
Button button_done {
|
||||
Button button_save {
|
||||
{ 2 * 8, 16 * 16, 12 * 8, 32 },
|
||||
"Save"
|
||||
};
|
||||
@@ -219,11 +219,12 @@ public:
|
||||
std::string title() const override { return "UI settings"; };
|
||||
|
||||
private:
|
||||
/*Checkbox checkbox_login {
|
||||
|
||||
Checkbox checkbox_disable_touchscreen {
|
||||
{ 3 * 8, 2 * 16 },
|
||||
20,
|
||||
"Login with play dead"
|
||||
};*/
|
||||
"Disable touchscreen"
|
||||
};
|
||||
|
||||
Checkbox checkbox_speaker {
|
||||
{ 3 * 8, 4 * 16 },
|
||||
@@ -271,10 +272,15 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
Button button_ok {
|
||||
Button button_save {
|
||||
{ 2 * 8, 16 * 16, 12 * 8, 32 },
|
||||
"Save"
|
||||
};
|
||||
|
||||
Button button_cancel {
|
||||
{ 16 * 8, 16 * 16, 12 * 8, 32 },
|
||||
"Cancel",
|
||||
};
|
||||
};
|
||||
|
||||
class SetAudioView : public View {
|
||||
@@ -298,111 +304,43 @@ private:
|
||||
'0'
|
||||
};
|
||||
|
||||
Button button_ok {
|
||||
Button button_save {
|
||||
{ 2 * 8, 16 * 16, 12 * 8, 32 },
|
||||
"Save"
|
||||
};
|
||||
|
||||
Button button_cancel {
|
||||
{ 16 * 8, 16 * 16, 12 * 8, 32 },
|
||||
"Cancel",
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
class SetPlayDeadView : public View {
|
||||
public:
|
||||
SetPlayDeadView(NavigationView& nav);
|
||||
|
||||
void focus() override;
|
||||
|
||||
std::string title() const override { return "Playdead settings"; };
|
||||
|
||||
private:
|
||||
bool entermode = false;
|
||||
uint32_t sequence { 0 };
|
||||
uint8_t keycount { 0 }, key_code { };
|
||||
char sequence_txt[11] = { 0 };
|
||||
|
||||
Text text_sequence {
|
||||
{ 64, 32, 14 * 8, 16 },
|
||||
"Enter sequence",
|
||||
};
|
||||
|
||||
Button button_enter {
|
||||
{ 16, 192, 96, 24 },
|
||||
"Enter"
|
||||
};
|
||||
Button button_cancel {
|
||||
{ 128, 192, 96, 24 },
|
||||
"Cancel"
|
||||
};
|
||||
};*/
|
||||
|
||||
/*class ModInfoView : public View {
|
||||
class SetQRCodeView : public View {
|
||||
public:
|
||||
ModInfoView(NavigationView& nav);
|
||||
SetQRCodeView(NavigationView& nav);
|
||||
|
||||
void focus() override;
|
||||
void on_show() override;
|
||||
|
||||
std::string title() const override { return "QR code"; };
|
||||
|
||||
private:
|
||||
void update_infos(uint8_t modn);
|
||||
|
||||
typedef struct moduleinfo_t{
|
||||
char filename[9];
|
||||
uint16_t version;
|
||||
uint32_t size;
|
||||
char md5[16];
|
||||
char name[16];
|
||||
char description[214];
|
||||
} moduleinfo_t;
|
||||
|
||||
moduleinfo_t module_list[8]; // 8 max for now
|
||||
|
||||
uint8_t modules_nb;
|
||||
|
||||
Text text_modcount {
|
||||
{ 2 * 8, 1 * 16, 18 * 8, 16 },
|
||||
"Searching..."
|
||||
Checkbox checkbox_bigger_qr {
|
||||
{ 3 * 8, 9 * 16 },
|
||||
20,
|
||||
"Show large QR code"
|
||||
};
|
||||
|
||||
OptionsField option_modules {
|
||||
{ 2 * 8, 2 * 16 },
|
||||
24,
|
||||
{
|
||||
{ "-", 0 }
|
||||
}
|
||||
Button button_save {
|
||||
{ 2 * 8, 16 * 16, 12 * 8, 32 },
|
||||
"Save"
|
||||
};
|
||||
|
||||
Text text_name {
|
||||
{ 2 * 8, 4 * 16, 5 * 8, 16 },
|
||||
"Name:"
|
||||
Button button_cancel {
|
||||
{ 16 * 8, 16 * 16, 12 * 8, 32 },
|
||||
"Cancel",
|
||||
};
|
||||
Text text_namestr {
|
||||
{ 8 * 8, 4 * 16, 16 * 8, 16 },
|
||||
"..."
|
||||
};
|
||||
Text text_size {
|
||||
{ 2 * 8, 5 * 16, 5 * 8, 16 },
|
||||
"Size:"
|
||||
};
|
||||
Text text_sizestr {
|
||||
{ 8 * 8, 5 * 16, 16 * 8, 16 },
|
||||
"..."
|
||||
};
|
||||
Text text_md5 {
|
||||
{ 2 * 8, 6 * 16, 4 * 8, 16 },
|
||||
"MD5:"
|
||||
};
|
||||
Text text_md5_a {
|
||||
{ 7 * 8, 6 * 16, 16 * 8, 16 },
|
||||
"..."
|
||||
};
|
||||
Text text_md5_b {
|
||||
{ 7 * 8, 7 * 16, 16 * 8, 16 },
|
||||
"..."
|
||||
};
|
||||
|
||||
Button button_ok {
|
||||
{ 4 * 8, 272, 64, 24 },
|
||||
"Ok"
|
||||
};
|
||||
};*/
|
||||
};
|
||||
|
||||
class SettingsMenuView : public BtnGridView {
|
||||
public:
|
||||
|
||||
@@ -1285,6 +1285,28 @@ static constexpr Bitmap bitmap_icon_previous {
|
||||
{ 16, 16 }, bitmap_icon_previous_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_qr_code_data[] = {
|
||||
0x00, 0x00,
|
||||
0xFE, 0x7E,
|
||||
0xC6, 0x62,
|
||||
0xFA, 0x5A,
|
||||
0xFA, 0x5A,
|
||||
0xDA, 0x5A,
|
||||
0xFE, 0x7E,
|
||||
0x7E, 0x7E,
|
||||
0x00, 0x00,
|
||||
0xFE, 0x46,
|
||||
0xC2, 0x06,
|
||||
0xFA, 0x18,
|
||||
0xFA, 0x18,
|
||||
0xC6, 0x60,
|
||||
0xFE, 0x62,
|
||||
0x00, 0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_qr_code {
|
||||
{ 16, 16 }, bitmap_icon_qr_code_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_rds_data[] = {
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
|
||||
@@ -167,7 +167,7 @@ int main(void) {
|
||||
if( portapack::init() ) {
|
||||
portapack::display.init();
|
||||
|
||||
sdcStart(&SDCD1, nullptr);
|
||||
// sdcStart(&SDCD1, nullptr); // Commented out as now happens in portapack.cpp
|
||||
|
||||
// controls_init(); // Commented out as now happens in portapack.cpp
|
||||
lcd_frame_sync_configure();
|
||||
@@ -175,6 +175,7 @@ int main(void) {
|
||||
|
||||
event_loop();
|
||||
|
||||
|
||||
sdcDisconnect(&SDCD1);
|
||||
sdcStop(&SDCD1);
|
||||
|
||||
|
||||
@@ -48,6 +48,10 @@ using asahi_kasei::ak4951::AK4951;
|
||||
#include "optional.hpp"
|
||||
#include "irq_controls.hpp"
|
||||
|
||||
#include "file.hpp"
|
||||
#include "sd_card.hpp"
|
||||
#include "string_format.hpp"
|
||||
|
||||
namespace portapack {
|
||||
|
||||
portapack::IO io {
|
||||
@@ -177,14 +181,84 @@ enum class PortaPackModel {
|
||||
R2_20170522,
|
||||
};
|
||||
|
||||
static bool save_config(int8_t value){
|
||||
persistent_memory::set_config_cpld(value);
|
||||
if(sd_card::status() == sd_card::Status::Mounted){
|
||||
make_new_directory("/hardware");
|
||||
File file;
|
||||
auto sucess = file.create("/hardware/settings.txt");
|
||||
if(!sucess.is_valid()) {
|
||||
file.write_line(to_string_dec_uint(value));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int read_file(std::string name) {
|
||||
std::string return_string = "";
|
||||
File file;
|
||||
auto success = file.open(name);
|
||||
|
||||
if(!success.is_valid()) {
|
||||
char one_char[1];
|
||||
for(size_t pointer = 0; pointer < file.size() ; pointer++) {
|
||||
file.seek(pointer);
|
||||
file.read(one_char, 1);
|
||||
return_string += one_char[0];
|
||||
}
|
||||
return std::stoi(return_string);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int load_config(){
|
||||
static Optional<int> config_value;
|
||||
if(!config_value.is_valid()){
|
||||
int8_t value = portapack::persistent_memory::config_cpld();
|
||||
if((value <= 0 || value >= 4) && sd_card::status() == sd_card::Status::Mounted){
|
||||
int data = read_file("/hardware/settings.txt");
|
||||
if(data != -1) {
|
||||
config_value = data;
|
||||
}
|
||||
} else {
|
||||
config_value = value;
|
||||
}
|
||||
}
|
||||
return config_value.value();
|
||||
}
|
||||
|
||||
|
||||
static PortaPackModel portapack_model() {
|
||||
static Optional<PortaPackModel> model;
|
||||
|
||||
if( !model.is_valid() ) {
|
||||
if( audio_codec_wm8731.detected() ) {
|
||||
model = PortaPackModel::R1_20150901; // H1R1
|
||||
const auto switches_state = get_switches_state();
|
||||
if (switches_state[(size_t)ui::KeyEvent::Up]){
|
||||
save_config(1);
|
||||
model = PortaPackModel::R2_20170522;
|
||||
}
|
||||
else if (switches_state[(size_t)ui::KeyEvent::Down]){
|
||||
save_config(2);
|
||||
model = PortaPackModel::R1_20150901;
|
||||
}
|
||||
else if (switches_state[(size_t)ui::KeyEvent::Left]){
|
||||
save_config(3);
|
||||
}
|
||||
else if (switches_state[(size_t)ui::KeyEvent::Select]){
|
||||
save_config(0);
|
||||
}
|
||||
|
||||
|
||||
if (load_config() == 1) {
|
||||
model = PortaPackModel::R2_20170522;
|
||||
} else if (load_config() == 2) {
|
||||
model = PortaPackModel::R1_20150901;
|
||||
} else {
|
||||
model = PortaPackModel::R2_20170522; // H1R2, H2+
|
||||
if( audio_codec_wm8731.detected() ) {
|
||||
model = PortaPackModel::R1_20150901; // H1R1
|
||||
} else {
|
||||
model = PortaPackModel::R2_20170522; // H1R2, H2, H2+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,28 +277,6 @@ static audio::Codec* portapack_audio_codec() {
|
||||
}
|
||||
|
||||
static const portapack::cpld::Config& portapack_cpld_config() {
|
||||
const auto switches_state = get_switches_state();
|
||||
if (switches_state[(size_t)ui::KeyEvent::Up]){
|
||||
persistent_memory::set_config_cpld(1);
|
||||
return portapack::cpld::rev_20170522::config;
|
||||
}
|
||||
if (switches_state[(size_t)ui::KeyEvent::Down]){
|
||||
persistent_memory::set_config_cpld(2);
|
||||
return portapack::cpld::rev_20150901::config;
|
||||
}
|
||||
if (switches_state[(size_t)ui::KeyEvent::Left]){
|
||||
persistent_memory::set_config_cpld(3);
|
||||
}
|
||||
if (switches_state[(size_t)ui::KeyEvent::Select]){
|
||||
persistent_memory::set_config_cpld(0);
|
||||
}
|
||||
|
||||
|
||||
if (portapack::persistent_memory::config_cpld() == 1) {
|
||||
return portapack::cpld::rev_20170522::config;
|
||||
} else if (portapack::persistent_memory::config_cpld() == 2) {
|
||||
return portapack::cpld::rev_20150901::config;
|
||||
}
|
||||
return (portapack_model() == PortaPackModel::R2_20170522)
|
||||
? portapack::cpld::rev_20170522::config
|
||||
: portapack::cpld::rev_20150901::config;
|
||||
@@ -361,7 +413,6 @@ bool init() {
|
||||
i2c0.stop();
|
||||
|
||||
set_clock_config(clock_config_irc);
|
||||
|
||||
cgu::pll1::disable();
|
||||
|
||||
/* Incantation from LPC43xx UM10503 section 12.2.1.1, to bring the M4
|
||||
@@ -409,17 +460,17 @@ bool init() {
|
||||
clock_manager.enable_first_if_clock();
|
||||
clock_manager.enable_second_if_clock();
|
||||
clock_manager.enable_codec_clocks();
|
||||
radio::init();
|
||||
radio::init();
|
||||
|
||||
sdcStart(&SDCD1, nullptr);
|
||||
sd_card::poll_inserted();
|
||||
|
||||
|
||||
LPC_CREG->DMAMUX = portapack::gpdma_mux;
|
||||
gpdma::controller.enable();
|
||||
|
||||
audio::init(portapack_audio_codec());
|
||||
chThdSleepMilliseconds(1);
|
||||
|
||||
if( !portapack::cpld::update_if_necessary(portapack_cpld_config()) ) {
|
||||
chThdSleepMilliseconds(1);
|
||||
// If using a "2021/12 QFP100", press and hold the left button while booting. Should only need to do once.
|
||||
if (portapack::persistent_memory::config_cpld() != 3){
|
||||
if (load_config() != 3){
|
||||
shutdown_base();
|
||||
return false;
|
||||
}
|
||||
@@ -429,6 +480,14 @@ bool init() {
|
||||
chSysHalt();
|
||||
}
|
||||
|
||||
chThdSleepMilliseconds(1); // This delay seems to solve white noise audio issues
|
||||
|
||||
LPC_CREG->DMAMUX = portapack::gpdma_mux;
|
||||
gpdma::controller.enable();
|
||||
|
||||
audio::init(portapack_audio_codec());
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ void Manager::feed(const Frame& frame) {
|
||||
|
||||
switch(state) {
|
||||
case State::NoTouch:
|
||||
if( touch_stable && touch_pressure ) {
|
||||
if( touch_stable && touch_pressure && !persistent_memory::disable_touchscreen()) {
|
||||
if( point_stable() ) {
|
||||
state = State::TouchDetected;
|
||||
touch_started();
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "ui_qrcode.hpp"
|
||||
#include "qrcodegen.hpp"
|
||||
#include "portapack.hpp"
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <stdio.h>
|
||||
@@ -43,25 +44,56 @@ QRCodeImage::QRCodeImage(
|
||||
}
|
||||
|
||||
void QRCodeImage::paint(Painter& painter) {
|
||||
|
||||
|
||||
// The structure to manage the QR code
|
||||
QRCode qrcode;
|
||||
int qr_version = 10; // bigger versions aren't handled very well
|
||||
|
||||
// Allocate a chunk of memory to store the QR code
|
||||
uint8_t qrcodeBytes[qrcode_getBufferSize(qr_version)];
|
||||
|
||||
qrcode_initText(&qrcode, qrcodeBytes, qr_version, ECC_HIGH, qr_text_);
|
||||
|
||||
|
||||
display.fill_rectangle(Rect(92, 97, 63, 63), Color::white());
|
||||
//Either small or large QR code can be shown..
|
||||
|
||||
for (uint8_t y = 0; y < qrcode.size; y++) {
|
||||
for (uint8_t x = 0; x < qrcode.size; x++) {
|
||||
if (qrcode_getModule(&qrcode, x, y)) {
|
||||
display.draw_pixel(Point(95+x,100+y), Color::black());
|
||||
if(portapack::persistent_memory::show_bigger_qr_code()) { // show large QR code
|
||||
int qr_version = 2;
|
||||
|
||||
// Allocate a chunk of memory to store the QR code
|
||||
uint8_t qrcodeBytes[qrcode_getBufferSize(qr_version)];
|
||||
|
||||
qrcode_initText(&qrcode, qrcodeBytes, qr_version, ECC_HIGH, qr_text_);
|
||||
|
||||
|
||||
display.fill_rectangle(Rect(10, 30, 220, 220), Color::white());
|
||||
|
||||
for (uint8_t y = 0; y < qrcode.size; y++) {
|
||||
for (uint8_t x = 0; x < qrcode.size; x++) {
|
||||
if (qrcode_getModule(&qrcode, x, y)) {
|
||||
display.fill_rectangle(Rect(20+(x*8), 40+(y*8), 8, 8), Color::black());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else { // show small QR code
|
||||
int qr_version = 10;
|
||||
|
||||
// Allocate a chunk of memory to store the QR code
|
||||
uint8_t qrcodeBytes[qrcode_getBufferSize(qr_version)];
|
||||
|
||||
qrcode_initText(&qrcode, qrcodeBytes, qr_version, ECC_HIGH, qr_text_);
|
||||
|
||||
|
||||
display.fill_rectangle(Rect(92, 97, 63, 63), Color::white());
|
||||
|
||||
for (uint8_t y = 0; y < qrcode.size; y++) {
|
||||
for (uint8_t x = 0; x < qrcode.size; x++) {
|
||||
if (qrcode_getModule(&qrcode, x, y)) {
|
||||
display.draw_pixel(Point(95+x,100+y), Color::black());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,10 +116,9 @@ QRCodeView::QRCodeView(
|
||||
|
||||
|
||||
add_children({
|
||||
&text_qr,
|
||||
&qr_code,
|
||||
&button_close});
|
||||
text_qr.set(qr_text);
|
||||
//text_qr.set(qr_text);
|
||||
qr_code.set_text(qr_text);
|
||||
|
||||
button_close.on_select = [&nav](Button&){
|
||||
|
||||
@@ -74,13 +74,13 @@ private:
|
||||
{ 50, 100, 100, 100 }
|
||||
};
|
||||
|
||||
Text text_qr {
|
||||
{ 0 * 8, 10 * 16, 32 * 8, 1 * 8 },
|
||||
"-"
|
||||
};
|
||||
//Text text_qr {
|
||||
// { 0 * 8, 10 * 16, 32 * 8, 1 * 8 },
|
||||
// "-"
|
||||
//};
|
||||
|
||||
Button button_close {
|
||||
{ 9 * 8, 15 * 16, 12 * 8, 3 * 16 },
|
||||
{ 9 * 8, 31 * 8, 12 * 8, 3 * 16 },
|
||||
"Back"
|
||||
};
|
||||
};
|
||||
|
||||
@@ -83,9 +83,6 @@ struct data_t {
|
||||
int32_t modem_baudrate;
|
||||
int32_t modem_repeat;
|
||||
|
||||
// Hardware
|
||||
uint32_t hardware_config;
|
||||
|
||||
// Play dead unlock
|
||||
uint32_t playdead_magic;
|
||||
uint32_t playing_dead;
|
||||
@@ -98,6 +95,9 @@ struct data_t {
|
||||
uint32_t pocsag_ignore_address;
|
||||
|
||||
int32_t tone_mix;
|
||||
|
||||
// Hardware
|
||||
uint32_t hardware_config;
|
||||
};
|
||||
|
||||
static_assert(sizeof(data_t) <= backup_ram.size(), "Persistent memory structure too large for VBAT-maintained region");
|
||||
@@ -227,9 +227,17 @@ void set_playdead_sequence(const uint32_t new_value) {
|
||||
|
||||
// ui_config is an uint32_t var storing information bitwise
|
||||
// bits 0,1,2 store the backlight timer
|
||||
// bits 31, 30,29,28,27, 26, 25 stores the different single bit configs depicted below
|
||||
// bits 31, 30,29,28,27, 26, 25, 24 stores the different single bit configs depicted below
|
||||
// bits on position 4 to 19 (16 bits) store the clkout frequency
|
||||
|
||||
bool disable_touchscreen() { // Option to disable touch screen
|
||||
return data->ui_config & (1 << 24);
|
||||
}
|
||||
|
||||
bool show_bigger_qr_code() { // show bigger QR code
|
||||
return data->ui_config & (1 << 23);
|
||||
}
|
||||
|
||||
bool hide_clock() { // clock hidden from main menu
|
||||
return data->ui_config & (1 << 25);
|
||||
}
|
||||
@@ -266,6 +274,14 @@ uint32_t config_backlight_timer() {
|
||||
return timer_seconds[data->ui_config & 7]; //first three bits, 8 possible values
|
||||
}
|
||||
|
||||
void set_disable_touchscreen(bool v) {
|
||||
data->ui_config = (data->ui_config & ~(1 << 24)) | (v << 24);
|
||||
}
|
||||
|
||||
void set_show_bigger_qr_code(bool v) {
|
||||
data->ui_config = (data->ui_config & ~(1 << 23)) | (v << 23);
|
||||
}
|
||||
|
||||
void set_clock_hidden(bool v) {
|
||||
data->ui_config = (data->ui_config & ~(1 << 25)) | (v << 25);
|
||||
}
|
||||
|
||||
@@ -78,18 +78,22 @@ uint8_t config_cpld();
|
||||
void set_config_cpld(uint8_t i);
|
||||
|
||||
bool config_splash();
|
||||
bool show_bigger_qr_code();
|
||||
bool hide_clock();
|
||||
bool clock_with_date();
|
||||
bool config_login();
|
||||
bool config_speaker();
|
||||
uint32_t config_backlight_timer();
|
||||
bool disable_touchscreen();
|
||||
|
||||
void set_config_splash(bool v);
|
||||
void set_show_bigger_qr_code(bool v);
|
||||
void set_clock_hidden(bool v);
|
||||
void set_clock_with_date(bool v);
|
||||
void set_config_login(bool v);
|
||||
void set_config_speaker(bool v);
|
||||
void set_config_backlight_timer(uint32_t i);
|
||||
void set_disable_touchscreen(bool v);
|
||||
|
||||
//uint8_t ui_config_textentry();
|
||||
//void set_config_textentry(uint8_t new_value);
|
||||
|
||||
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 427 B |
Reference in New Issue
Block a user