mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-08-25 08:59:03 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ed834e3553 | |||
| ce08d93ae2 | |||
| 13fd1b1f3b | |||
| d04c781ada | |||
| 24605777a6 | |||
| b5ac792853 | |||
| 44c319dcc6 | |||
| a442971b81 | |||
| 8b5adb6bc1 | |||
| c3add0ce84 | |||
| 8725b01995 | |||
| 936e8279f9 | |||
| 6193023c8f |
@@ -1 +1 @@
|
||||
v1.9.0
|
||||
v1.9.1
|
||||
|
||||
@@ -1 +1 @@
|
||||
v1.9.1
|
||||
v2.0.0
|
||||
|
||||
@@ -44,7 +44,7 @@ if(cpp20_supported)
|
||||
else()
|
||||
set(USE_CPPOPT "-std=c++17")
|
||||
endif()
|
||||
set(USE_CPPOPT "${USE_CPPOPT} -flto -fno-rtti -fno-exceptions -Weffc++ -Wuninitialized -Wno-volatile")
|
||||
set(USE_CPPOPT "${USE_CPPOPT} -fno-rtti -fno-exceptions -Weffc++ -Wuninitialized -Wno-volatile")
|
||||
|
||||
# Enable this if you want the linker to remove unused code and data
|
||||
set(USE_LINK_GC yes)
|
||||
@@ -347,10 +347,12 @@ set(CPPSRC
|
||||
${HACKRF_CPLD_DATA_CPP}
|
||||
ui_external_items_menu_loader.cpp
|
||||
view_factory_base.cpp
|
||||
|
||||
${EXTCPPSRC}
|
||||
)
|
||||
|
||||
set_source_files_properties(${CPPSRC} PROPERTIES COMPILE_FLAGS -flto) # Add lto flag to the non-external sources only
|
||||
|
||||
list (APPEND CPPSRC ${EXTCPPSRC}) # Append external sources after setting lto flag to internal ones
|
||||
|
||||
# C sources to be compiled in ARM mode regardless of the global setting.
|
||||
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
|
||||
# option that results in lower performance and larger code size.
|
||||
@@ -492,7 +494,6 @@ add_custom_command(
|
||||
)
|
||||
|
||||
add_executable(${PROJECT_NAME}.elf ${CSRC} ${CPPSRC} ${ASMSRC})
|
||||
set_source_files_properties(${EXTCPPSRC} PROPERTIES COMPILE_FLAGS -fno-lto)
|
||||
set_target_properties(${PROJECT_NAME}.elf PROPERTIES LINK_DEPENDS ${LDSCRIPT})
|
||||
add_definitions(${DEFS})
|
||||
include_directories(. ${INCDIR})
|
||||
|
||||
@@ -323,6 +323,11 @@ bool ControlsSwitchesWidget::on_key(const KeyEvent key) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ControlsSwitchesWidget::on_encoder(const EncoderEvent delta) {
|
||||
last_delta = delta;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ControlsSwitchesWidget::paint(Painter& painter) {
|
||||
const auto pos = screen_pos();
|
||||
|
||||
@@ -405,6 +410,8 @@ void ControlsSwitchesWidget::paint(Painter& painter) {
|
||||
|
||||
switches_event >>= 1;
|
||||
}
|
||||
|
||||
painter.draw_string({5 * 8, 12 * 16}, Styles::light_grey, to_string_dec_int(last_delta, 3));
|
||||
}
|
||||
|
||||
void ControlsSwitchesWidget::on_frame_sync() {
|
||||
@@ -450,6 +457,17 @@ DebugPeripheralsMenuView::DebugPeripheralsMenuView(NavigationView& nav) {
|
||||
set_max_rows(2); // allow wider buttons
|
||||
}
|
||||
|
||||
/* DebugReboot **********************************************/
|
||||
|
||||
DebugReboot::DebugReboot(NavigationView& nav) {
|
||||
(void)nav;
|
||||
|
||||
LPC_RGU->RESET_CTRL[0] = (1 << 0);
|
||||
|
||||
while (1)
|
||||
__WFE();
|
||||
}
|
||||
|
||||
/* DebugMenuView *********************************************************/
|
||||
|
||||
DebugMenuView::DebugMenuView(NavigationView& nav) {
|
||||
@@ -465,6 +483,7 @@ DebugMenuView::DebugMenuView(NavigationView& nav) {
|
||||
{"Peripherals", ui::Color::dark_cyan(), &bitmap_icon_peripherals, [&nav]() { nav.push<DebugPeripheralsMenuView>(); }},
|
||||
{"Pers. Memory", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav]() { nav.push<DebugPmemView>(); }},
|
||||
//{ "Radio State", ui::Color::white(), nullptr, [&nav](){ nav.push<NotImplementedView>(); } },
|
||||
{"Reboot", ui::Color::dark_cyan(), &bitmap_icon_setup, [&nav]() { nav.push<DebugReboot>(); }},
|
||||
{"SD Card", ui::Color::dark_cyan(), &bitmap_icon_sdcard, [&nav]() { nav.push<SDCardDebugView>(); }},
|
||||
{"Temperature", ui::Color::dark_cyan(), &bitmap_icon_temperature, [&nav]() { nav.push<TemperatureView>(); }},
|
||||
{"Touch Test", ui::Color::dark_cyan(), &bitmap_icon_notepad, [&nav]() { nav.push<DebugScreenTest>(); }},
|
||||
|
||||
@@ -252,18 +252,21 @@ class ControlsSwitchesWidget : public Widget {
|
||||
Rect parent_rect)
|
||||
: Widget{parent_rect},
|
||||
key_event_mask(0),
|
||||
long_press_key_event_mask{0} {
|
||||
long_press_key_event_mask{0},
|
||||
last_delta{0} {
|
||||
set_focusable(true);
|
||||
}
|
||||
|
||||
void on_show() override;
|
||||
bool on_key(const KeyEvent key) override;
|
||||
bool on_encoder(const EncoderEvent delta) override;
|
||||
|
||||
void paint(Painter& painter) override;
|
||||
|
||||
private:
|
||||
uint8_t key_event_mask;
|
||||
uint8_t long_press_key_event_mask;
|
||||
EncoderEvent last_delta;
|
||||
|
||||
MessageHandlerRegistration message_handler_frame_sync{
|
||||
Message::ID::DisplayFrameSync,
|
||||
@@ -285,6 +288,7 @@ class DebugControlsView : public View {
|
||||
private:
|
||||
Labels labels{
|
||||
{{8 * 8, 1 * 16}, "Controls State", Color::white()},
|
||||
{{0 * 8, 11 * 16}, "Dial:", Color::grey()},
|
||||
{{0 * 8, 14 * 16}, "Long-Press Mode:", Color::grey()}};
|
||||
|
||||
ControlsSwitchesWidget switches_widget{
|
||||
@@ -420,6 +424,11 @@ class DebugPeripheralsMenuView : public BtnGridView {
|
||||
std::string title() const override { return "Peripherals"; };
|
||||
};
|
||||
|
||||
class DebugReboot : public BtnGridView {
|
||||
public:
|
||||
DebugReboot(NavigationView& nav);
|
||||
};
|
||||
|
||||
class DebugMenuView : public BtnGridView {
|
||||
public:
|
||||
DebugMenuView(NavigationView& nav);
|
||||
|
||||
@@ -44,6 +44,7 @@ namespace fs = std::filesystem;
|
||||
|
||||
#include "string_format.hpp"
|
||||
#include "ui_styles.hpp"
|
||||
#include "ui_font_fixed_8x16.hpp"
|
||||
#include "cpld_update.hpp"
|
||||
#include "config_mode.hpp"
|
||||
|
||||
@@ -612,6 +613,8 @@ SetPersistentMemoryView::SetPersistentMemoryView(NavigationView& nav) {
|
||||
[this](bool choice) {
|
||||
if (choice) {
|
||||
pmem::cache::defaults();
|
||||
// Refresh status bar
|
||||
send_system_refresh();
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -755,7 +758,7 @@ void SetConfigModeView::focus() {
|
||||
button_save.focus();
|
||||
}
|
||||
|
||||
/* FakeBrightnessView ************************************/
|
||||
/* SetFakeBrightnessView ************************************/
|
||||
|
||||
SetFakeBrightnessView::SetFakeBrightnessView(NavigationView& nav) {
|
||||
add_children({&labels,
|
||||
@@ -783,6 +786,53 @@ void SetFakeBrightnessView::focus() {
|
||||
button_save.focus();
|
||||
}
|
||||
|
||||
/* SetMenuColorView ************************************/
|
||||
|
||||
void SetMenuColorView::paint_sample() {
|
||||
Color c = Color(field_red_level.value(), field_green_level.value(), field_blue_level.value());
|
||||
button_sample.set_bg_color(c);
|
||||
}
|
||||
|
||||
SetMenuColorView::SetMenuColorView(NavigationView& nav) {
|
||||
add_children({&labels,
|
||||
&button_sample,
|
||||
&field_red_level,
|
||||
&field_green_level,
|
||||
&field_blue_level,
|
||||
&button_save,
|
||||
&button_cancel});
|
||||
|
||||
button_sample.set_focusable(false);
|
||||
|
||||
Color c = pmem::menu_color();
|
||||
field_red_level.set_value(c.r());
|
||||
field_green_level.set_value(c.g());
|
||||
field_blue_level.set_value(c.b());
|
||||
paint_sample();
|
||||
|
||||
const auto color_changed_fn = [this](int32_t) {
|
||||
paint_sample();
|
||||
};
|
||||
field_red_level.on_change = color_changed_fn;
|
||||
field_green_level.on_change = color_changed_fn;
|
||||
field_blue_level.on_change = color_changed_fn;
|
||||
|
||||
button_save.on_select = [&nav, this](Button&) {
|
||||
Color c = Color(field_red_level.value(), field_green_level.value(), field_blue_level.value());
|
||||
pmem::set_menu_color(c);
|
||||
send_system_refresh();
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
button_cancel.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
}
|
||||
|
||||
void SetMenuColorView::focus() {
|
||||
button_save.focus();
|
||||
}
|
||||
|
||||
/* SettingsMenuView **************************************/
|
||||
|
||||
SettingsMenuView::SettingsMenuView(NavigationView& nav) {
|
||||
@@ -804,6 +854,7 @@ SettingsMenuView::SettingsMenuView(NavigationView& nav) {
|
||||
{"User Interface", ui::Color::dark_cyan(), &bitmap_icon_options_ui, [&nav]() { nav.push<SetUIView>(); }},
|
||||
{"QR Code", ui::Color::dark_cyan(), &bitmap_icon_qr_code, [&nav]() { nav.push<SetQRCodeView>(); }},
|
||||
{"Brightness", ui::Color::dark_cyan(), &bitmap_icon_brightness, [&nav]() { nav.push<SetFakeBrightnessView>(); }},
|
||||
{"Menu Color", ui::Color::dark_cyan(), &bitmap_icon_brightness, [&nav]() { nav.push<SetMenuColorView>(); }},
|
||||
});
|
||||
set_max_rows(2); // allow wider buttons
|
||||
}
|
||||
|
||||
@@ -588,7 +588,7 @@ class SetEncoderDialView : public View {
|
||||
NumberField field_encoder_rate_multiplier{
|
||||
{20 * 8, 12 * 16},
|
||||
2,
|
||||
{1, 10},
|
||||
{1, 15},
|
||||
1,
|
||||
' '};
|
||||
|
||||
@@ -731,6 +731,64 @@ class SetFakeBrightnessView : public View {
|
||||
};
|
||||
};
|
||||
|
||||
class SetMenuColorView : public View {
|
||||
public:
|
||||
SetMenuColorView(NavigationView& nav);
|
||||
|
||||
void focus() override;
|
||||
|
||||
std::string title() const override { return "Menu Color"; };
|
||||
|
||||
private:
|
||||
void paint_sample();
|
||||
|
||||
Labels labels{
|
||||
{{3 * 8, 1 * 16}, "Menu Button Color Scheme", Color::light_grey()},
|
||||
{{2 * 8, 8 * 16}, "Red Level:", Color::light_grey()},
|
||||
{{2 * 8, 9 * 16}, "Green Level:", Color::light_grey()},
|
||||
{{2 * 8, 10 * 16}, "Blue Level:", Color::light_grey()},
|
||||
};
|
||||
|
||||
NewButton button_sample{
|
||||
{8 * 8, 4 * 16, 14 * 8, 3 * 16},
|
||||
"New Color",
|
||||
&bitmap_icon_brightness,
|
||||
};
|
||||
|
||||
NumberField field_red_level{
|
||||
{15 * 8, 8 * 16},
|
||||
3,
|
||||
{8, 248},
|
||||
8,
|
||||
' ',
|
||||
};
|
||||
|
||||
NumberField field_green_level{
|
||||
{15 * 8, 9 * 16},
|
||||
3,
|
||||
{8, 248},
|
||||
8,
|
||||
' ',
|
||||
};
|
||||
|
||||
NumberField field_blue_level{
|
||||
{15 * 8, 10 * 16},
|
||||
3,
|
||||
{8, 248},
|
||||
8,
|
||||
' ',
|
||||
};
|
||||
|
||||
Button button_save{
|
||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||
"Save"};
|
||||
|
||||
Button button_cancel{
|
||||
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||
"Cancel",
|
||||
};
|
||||
};
|
||||
|
||||
class SettingsMenuView : public BtnGridView {
|
||||
public:
|
||||
SettingsMenuView(NavigationView& nav);
|
||||
|
||||
@@ -427,6 +427,9 @@ TextEditorView::TextEditorView(NavigationView& nav)
|
||||
&text_size,
|
||||
});
|
||||
|
||||
text_position.set_style(&Styles::bg_dark_blue);
|
||||
text_size.set_style(&Styles::bg_dark_blue);
|
||||
|
||||
viewer.set_font_zoom(enable_zoom);
|
||||
|
||||
viewer.on_select = [this]() {
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
set(EXTCPPSRC
|
||||
|
||||
#pacman
|
||||
# external/pacman/main.cpp
|
||||
# external/pacman/ui_pacman.cpp
|
||||
external/pacman/main.cpp
|
||||
external/pacman/ui_pacman.cpp
|
||||
|
||||
#tetris
|
||||
external/tetris/main.cpp
|
||||
@@ -65,7 +65,7 @@ set(EXTCPPSRC
|
||||
)
|
||||
|
||||
set(EXTAPPLIST
|
||||
# pacman
|
||||
pacman
|
||||
afsk_rx
|
||||
calculator
|
||||
font_viewer
|
||||
|
||||
+22
-7
@@ -13,8 +13,6 @@ namespace ui::external_app::pacman {
|
||||
#include "playfield.hpp"
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
Playfield _game;
|
||||
|
||||
PacmanView::PacmanView(NavigationView& nav)
|
||||
: nav_(nav) {
|
||||
add_children({&dummy});
|
||||
@@ -26,19 +24,36 @@ void PacmanView::focus() {
|
||||
|
||||
void PacmanView::paint(Painter& painter) {
|
||||
(void)painter;
|
||||
static Playfield _game;
|
||||
static bool wait_for_button_release{false};
|
||||
|
||||
if (!initialized) {
|
||||
initialized = true;
|
||||
_game.Init();
|
||||
}
|
||||
|
||||
auto switches_raw = swizzled_switches() & ((1 << (int)Switch::Right) | (1 << (int)Switch::Left) | (1 << (int)Switch::Down) | (1 << (int)Switch::Up) | (1 << (int)Switch::Sel) | (1 << (int)Switch::Dfu));
|
||||
auto switches_debounced = get_switches_state().to_ulong();
|
||||
|
||||
but_RIGHT = (switches_debounced & 0x01) == 0x01;
|
||||
but_LEFT = (switches_debounced & 0x02) == 0x02;
|
||||
but_DOWN = (switches_debounced & 0x04) == 0x04;
|
||||
but_UP = (switches_debounced & 0x08) == 0x08;
|
||||
but_A = (switches_debounced & 0x10) == 0x10;
|
||||
// For the Select (Start/Pause) button, wait for release to avoid repeat
|
||||
uint8_t buttons_to_wait_for = (1 << (int)Switch::Sel);
|
||||
if (wait_for_button_release) {
|
||||
if ((switches_debounced & buttons_to_wait_for) == 0)
|
||||
wait_for_button_release = false;
|
||||
switches_debounced &= ~buttons_to_wait_for;
|
||||
} else {
|
||||
if (switches_debounced & buttons_to_wait_for)
|
||||
wait_for_button_release = true;
|
||||
}
|
||||
|
||||
// For the directional buttons, use the raw inputs for fastest response time
|
||||
but_RIGHT = (switches_raw & (1 << (int)Switch::Right)) != 0;
|
||||
but_LEFT = (switches_raw & (1 << (int)Switch::Left)) != 0;
|
||||
but_DOWN = (switches_raw & (1 << (int)Switch::Down)) != 0;
|
||||
but_UP = (switches_raw & (1 << (int)Switch::Up)) != 0;
|
||||
|
||||
// For the pause button, use the debounced input to avoid glitches, and OR in the value to make sure that we don't clear it before it's seen
|
||||
but_A |= (switches_debounced & (1 << (int)Switch::Sel)) != 0;
|
||||
|
||||
_game.Step();
|
||||
}
|
||||
|
||||
@@ -162,6 +162,8 @@ static void event_loop() {
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
first_if.init(); /* To avoid initial short Ant_DC_Bias pulse ,we need quick set up GP01_RFF507X =1 */
|
||||
|
||||
if (config_mode_should_enter()) {
|
||||
config_mode_clear();
|
||||
config_mode_run();
|
||||
@@ -169,15 +171,13 @@ int main(void) {
|
||||
|
||||
config_mode_set();
|
||||
|
||||
first_if.init(); /* To avoid initial short Ant_DC_Bias pulse ,we need quick set up GP01_RFF507X =1 */
|
||||
|
||||
switch (portapack::init()) {
|
||||
case portapack::init_status_t::INIT_HACKRF_CPLD_FAILED:
|
||||
portapack::init_error = "HACKRF CPLD FAILED";
|
||||
[[fallthrough]];
|
||||
|
||||
case portapack::init_status_t::INIT_SUCCESS:
|
||||
portapack::display.init();
|
||||
|
||||
config_mode_clear();
|
||||
|
||||
lcd_frame_sync_configure();
|
||||
|
||||
+194
-128
@@ -28,6 +28,7 @@
|
||||
#include "hackrf_hal.hpp"
|
||||
#include "hackrf_gpio.hpp"
|
||||
using namespace hackrf::one;
|
||||
#include "jtag_target_gpio.hpp"
|
||||
|
||||
#include "clock_manager.hpp"
|
||||
#include "event_m0.hpp"
|
||||
@@ -50,6 +51,7 @@ using asahi_kasei::ak4951::AK4951;
|
||||
#include "file.hpp"
|
||||
#include "sd_card.hpp"
|
||||
#include "string_format.hpp"
|
||||
#include "bitmap.hpp"
|
||||
|
||||
namespace portapack {
|
||||
|
||||
@@ -174,50 +176,21 @@ constexpr I2CConfig i2c_config_fast_clock{
|
||||
enum class PortaPackModel {
|
||||
R1_20150901,
|
||||
R2_20170522,
|
||||
AGM,
|
||||
AUTODETECT,
|
||||
};
|
||||
|
||||
static bool save_config(int8_t value) {
|
||||
persistent_memory::set_config_cpld(value);
|
||||
if (sd_card::status() == sd_card::Status::Mounted) {
|
||||
ensure_directory("/hardware");
|
||||
File file;
|
||||
auto sucess = file.create("/hardware/settings.txt");
|
||||
if (!sucess.is_valid()) {
|
||||
file.write_line(to_string_dec_uint(value));
|
||||
}
|
||||
}
|
||||
portapack::persistent_memory::cache::persist();
|
||||
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 >= 5) && sd_card::status() == sd_card::Status::Mounted) {
|
||||
int data = read_file("/hardware/settings.txt");
|
||||
if (data != -1) {
|
||||
config_value = data;
|
||||
}
|
||||
} else {
|
||||
config_value = value;
|
||||
}
|
||||
config_value = value;
|
||||
}
|
||||
return config_value.value();
|
||||
}
|
||||
@@ -226,39 +199,49 @@ static PortaPackModel portapack_model() {
|
||||
static Optional<PortaPackModel> model;
|
||||
|
||||
if (!model.is_valid()) {
|
||||
const auto switches_state = get_switches_state();
|
||||
// Only save config if no other multi key boot action is triggered (like pmem reset)
|
||||
if (switches_state.count() == 1) {
|
||||
if (switches_state[(size_t)ui::KeyEvent::Up]) {
|
||||
jtag::GPIOTarget target{
|
||||
portapack::gpio_cpld_tck,
|
||||
portapack::gpio_cpld_tms,
|
||||
portapack::gpio_cpld_tdi,
|
||||
portapack::gpio_cpld_tdo};
|
||||
jtag::JTAG jtag{target};
|
||||
portapack::cpld::CPLD cpld{jtag};
|
||||
|
||||
cpld.reset();
|
||||
cpld.run_test_idle();
|
||||
uint32_t idcode = cpld.get_idcode();
|
||||
if (idcode == 0x25610) {
|
||||
model = PortaPackModel::AGM;
|
||||
} else {
|
||||
const auto switches_state = swizzled_switches();
|
||||
// chDbgPanic(to_string_hex((uint32_t)switches_state.count(), 8).c_str());
|
||||
// Only save config if no other multi key boot action is triggered (like pmem reset)
|
||||
if (((switches_state >> (size_t)ui::KeyEvent::Up) & 1) == 1) {
|
||||
save_config(1);
|
||||
// model = PortaPackModel::R2_20170522; // Commented these out as they should be set down below anyway
|
||||
} else if (switches_state[(size_t)ui::KeyEvent::Down]) {
|
||||
} else if (((switches_state >> (size_t)ui::KeyEvent::Down) & 1) == 1) {
|
||||
save_config(2);
|
||||
// model = PortaPackModel::R1_20150901;
|
||||
} else if (switches_state[(size_t)ui::KeyEvent::Left]) {
|
||||
} else if (((switches_state >> (size_t)ui::KeyEvent::Left) & 1) == 1) {
|
||||
save_config(3);
|
||||
// model = PortaPackModel::R1_20150901;
|
||||
} else if (switches_state[(size_t)ui::KeyEvent::Right]) {
|
||||
} else if (((switches_state >> (size_t)ui::KeyEvent::Right) & 1) == 1) {
|
||||
save_config(4);
|
||||
// model = PortaPackModel::R2_20170522;
|
||||
} else if (switches_state[(size_t)ui::KeyEvent::Select]) {
|
||||
} else if (((switches_state >> (size_t)ui::KeyEvent::Select) & 1) == 1) {
|
||||
save_config(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (load_config() == 1) {
|
||||
model = PortaPackModel::R2_20170522;
|
||||
} else if (load_config() == 2) {
|
||||
model = PortaPackModel::R1_20150901;
|
||||
} else if (load_config() == 3) {
|
||||
model = PortaPackModel::R1_20150901;
|
||||
} else if (load_config() == 4) {
|
||||
model = PortaPackModel::R2_20170522;
|
||||
} else {
|
||||
if (audio_codec_wm8731.detected()) {
|
||||
model = PortaPackModel::R1_20150901; // H1R1
|
||||
if (load_config() == 1) {
|
||||
model = PortaPackModel::R2_20170522;
|
||||
} else if (load_config() == 2) {
|
||||
model = PortaPackModel::R1_20150901;
|
||||
} else if (load_config() == 3) {
|
||||
model = PortaPackModel::R1_20150901;
|
||||
} else if (load_config() == 4) {
|
||||
model = PortaPackModel::R2_20170522;
|
||||
} else {
|
||||
model = PortaPackModel::R2_20170522; // H1R2, H2, H2+
|
||||
model = PortaPackModel::AUTODETECT;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -345,6 +328,129 @@ static void shutdown_base() {
|
||||
clock_manager.shutdown();
|
||||
}
|
||||
|
||||
static void set_cpu_clock_speed() {
|
||||
/* Incantation from LPC43xx UM10503 section 12.2.1.1, to bring the M4
|
||||
* core clock speed to the 110 - 204MHz range.
|
||||
*/
|
||||
|
||||
/* Step into the 90-110MHz M4 clock range */
|
||||
/* OG:
|
||||
* Fclkin = 40M
|
||||
* /N=2 = 20M = PFDin
|
||||
* Fcco = PFDin * (M=10) = 200M
|
||||
* r9:
|
||||
* Fclkin = 10M
|
||||
* /N=1 = 10M = PFDin
|
||||
* Fcco = PFDin * (M=20) = 200M
|
||||
* Fclk = Fcco / (2*(P=1)) = 100M
|
||||
*/
|
||||
cgu::pll1::ctrl({
|
||||
.pd = 1,
|
||||
.bypass = 0,
|
||||
.fbsel = 0,
|
||||
.direct = 0,
|
||||
.psel = 0,
|
||||
.autoblock = 1,
|
||||
.nsel = hackrf_r9 ? 0UL : 1UL,
|
||||
.msel = hackrf_r9 ? 19UL : 9UL,
|
||||
.clk_sel = cgu::CLK_SEL::GP_CLKIN,
|
||||
});
|
||||
|
||||
cgu::pll1::enable();
|
||||
while (!cgu::pll1::is_locked())
|
||||
;
|
||||
|
||||
set_clock_config(clock_config_pll1_step);
|
||||
|
||||
/* Delay >50us at 90-110MHz clock speed */
|
||||
volatile uint32_t delay = 1400;
|
||||
while (delay--)
|
||||
;
|
||||
|
||||
set_clock_config(clock_config_pll1);
|
||||
|
||||
/* Remove /2P divider from PLL1 output to achieve full speed */
|
||||
cgu::pll1::direct();
|
||||
}
|
||||
|
||||
static void draw_splash_screen_icon(int16_t n, const ui::Bitmap& bitmap) {
|
||||
ui::Painter painter;
|
||||
|
||||
painter.draw_bitmap(
|
||||
{portapack::display.width() / 2 - 8 - 40 + (n * 20), portapack::display.height() / 2 - 8 + 40},
|
||||
bitmap,
|
||||
ui::Color::white(),
|
||||
ui::Color::black());
|
||||
}
|
||||
|
||||
static bool is_portapack_present() {
|
||||
systime_t timeout = 50;
|
||||
uint8_t wm8731_reset_command[] = {0x0f, 0x00};
|
||||
if (i2c0.transmit(0x1a /* wm8731 */, wm8731_reset_command, 2, timeout) == false) {
|
||||
audio_codec_ak4951.reset();
|
||||
uint8_t ak4951_init_command[] = {0x00, 0x00};
|
||||
i2c0.transmit(0x12 /* ak4951 */, ak4951_init_command, 2, timeout);
|
||||
chThdSleepMilliseconds(10);
|
||||
if (i2c0.transmit(0x12 /* ak4951 */, ak4951_init_command, 2, timeout) == false) {
|
||||
shutdown_base();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool check_portapack_cpld() {
|
||||
switch (portapack_model()) {
|
||||
case PortaPackModel::AUTODETECT: {
|
||||
portapack::cpld::CpldUpdateStatus result = portapack::cpld::update_autodetect(
|
||||
portapack::cpld::rev_20150901::config, portapack::cpld::rev_20170522::config);
|
||||
if (result != portapack::cpld::CpldUpdateStatus::Success) {
|
||||
shutdown_base();
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
|
||||
case PortaPackModel::R1_20150901:
|
||||
case PortaPackModel::R2_20170522: {
|
||||
portapack::cpld::CpldUpdateStatus result = portapack::cpld::update_if_necessary(portapack_cpld_config());
|
||||
if (result == portapack::cpld::CpldUpdateStatus::Program_failed) {
|
||||
chThdSleepMilliseconds(10);
|
||||
// Mode left (R1) and right (R2,H2,H2+) bypass going into hackrf mode after failing CPLD update
|
||||
// Mode center (autodetect), up (R1) and down (R2,H2,H2+) will go into hackrf mode after failing CPLD update
|
||||
if (load_config() != 3 /* left */ && load_config() != 4 /* right */) {
|
||||
shutdown_base();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case PortaPackModel::AGM:
|
||||
// the AGM devices are always factory flashed. so do nothing
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void initialize_boot_splash_screen() {
|
||||
ui::Painter painter;
|
||||
portapack::display.init();
|
||||
|
||||
painter.fill_rectangle(
|
||||
{0, 0, portapack::display.width(), portapack::display.height()},
|
||||
ui::Color::black());
|
||||
|
||||
chThdSleepMilliseconds(17);
|
||||
portapack::backlight()->on();
|
||||
|
||||
painter.draw_bitmap(
|
||||
{portapack::display.width() / 2 - 40, portapack::display.height() / 2 - 8},
|
||||
ui::bitmap_titlebar_image,
|
||||
ui::Color::white(),
|
||||
ui::Color::black());
|
||||
}
|
||||
|
||||
/* Clock scheme after exiting bootloader in SPIFI mode:
|
||||
*
|
||||
* XTAL_OSC = powered down
|
||||
@@ -396,23 +502,24 @@ init_status_t init() {
|
||||
|
||||
i2c0.start(i2c_config_boot_clock);
|
||||
|
||||
// Keeping this here for now incase we need to revert
|
||||
// if( !portapack::cpld::update_if_necessary(portapack_cpld_config()) ) {
|
||||
// shutdown_base();
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// if( !hackrf::cpld::load_sram() ) {
|
||||
// chSysHalt();
|
||||
// }
|
||||
chThdSleepMilliseconds(100);
|
||||
|
||||
configure_pins_portapack();
|
||||
|
||||
portapack::io.init();
|
||||
persistent_memory::cache::init();
|
||||
|
||||
const auto switches_state = swizzled_switches() & (~(0xC0 | 0x80));
|
||||
bool lcd_fast_setup = switches_state == 0 && portapack::display.read_display_status();
|
||||
|
||||
if (lcd_fast_setup) {
|
||||
initialize_boot_splash_screen();
|
||||
} else {
|
||||
if (check_portapack_cpld() == false)
|
||||
return init_status_t::INIT_PORTAPACK_CPLD_FAILED;
|
||||
}
|
||||
|
||||
/* Cache some configuration data from persistent memory. */
|
||||
persistent_memory::cache::init();
|
||||
rtc_time::dst_init();
|
||||
chThdSleepMilliseconds(10);
|
||||
|
||||
@@ -425,48 +532,10 @@ init_status_t init() {
|
||||
set_clock_config(clock_config_irc);
|
||||
cgu::pll1::disable();
|
||||
|
||||
/* Incantation from LPC43xx UM10503 section 12.2.1.1, to bring the M4
|
||||
* core clock speed to the 110 - 204MHz range.
|
||||
*/
|
||||
set_cpu_clock_speed();
|
||||
|
||||
/* Step into the 90-110MHz M4 clock range */
|
||||
/* OG:
|
||||
* Fclkin = 40M
|
||||
* /N=2 = 20M = PFDin
|
||||
* Fcco = PFDin * (M=10) = 200M
|
||||
* r9:
|
||||
* Fclkin = 10M
|
||||
* /N=1 = 10M = PFDin
|
||||
* Fcco = PFDin * (M=20) = 200M
|
||||
* Fclk = Fcco / (2*(P=1)) = 100M
|
||||
*/
|
||||
cgu::pll1::ctrl({
|
||||
.pd = 1,
|
||||
.bypass = 0,
|
||||
.fbsel = 0,
|
||||
.direct = 0,
|
||||
.psel = 0,
|
||||
.autoblock = 1,
|
||||
.nsel = hackrf_r9 ? 0UL : 1UL,
|
||||
.msel = hackrf_r9 ? 19UL : 9UL,
|
||||
.clk_sel = cgu::CLK_SEL::GP_CLKIN,
|
||||
});
|
||||
|
||||
cgu::pll1::enable();
|
||||
while (!cgu::pll1::is_locked())
|
||||
;
|
||||
|
||||
set_clock_config(clock_config_pll1_step);
|
||||
|
||||
/* Delay >50us at 90-110MHz clock speed */
|
||||
volatile uint32_t delay = 1400;
|
||||
while (delay--)
|
||||
;
|
||||
|
||||
set_clock_config(clock_config_pll1);
|
||||
|
||||
/* Remove /2P divider from PLL1 output to achieve full speed */
|
||||
cgu::pll1::direct();
|
||||
if (lcd_fast_setup)
|
||||
draw_splash_screen_icon(0, ui::bitmap_icon_memory);
|
||||
|
||||
usb_serial.initialize();
|
||||
|
||||
@@ -474,18 +543,11 @@ init_status_t init() {
|
||||
chThdSleepMilliseconds(10);
|
||||
|
||||
/* Check if portapack is attached by checking if any of the two audio chips is present. */
|
||||
systime_t timeout = 50;
|
||||
uint8_t wm8731_reset_command[] = {0x0f, 0x00};
|
||||
if (i2c0.transmit(0x1a /* wm8731 */, wm8731_reset_command, 2, timeout) == false) {
|
||||
audio_codec_ak4951.reset();
|
||||
uint8_t ak4951_init_command[] = {0x00, 0x00};
|
||||
i2c0.transmit(0x12 /* ak4951 */, ak4951_init_command, 2, timeout);
|
||||
chThdSleepMilliseconds(10);
|
||||
if (i2c0.transmit(0x12 /* ak4951 */, ak4951_init_command, 2, timeout) == false) {
|
||||
shutdown_base();
|
||||
return init_status_t::INIT_NO_PORTAPACK;
|
||||
}
|
||||
}
|
||||
if (lcd_fast_setup == false && is_portapack_present() == false)
|
||||
return init_status_t::INIT_NO_PORTAPACK;
|
||||
|
||||
if (lcd_fast_setup)
|
||||
draw_splash_screen_icon(1, ui::bitmap_icon_remote);
|
||||
|
||||
touch::adc::init();
|
||||
controls_init();
|
||||
@@ -501,23 +563,20 @@ init_status_t init() {
|
||||
|
||||
chThdSleepMilliseconds(10);
|
||||
|
||||
portapack::cpld::CpldUpdateStatus result = portapack::cpld::update_if_necessary(portapack_cpld_config());
|
||||
if (result == portapack::cpld::CpldUpdateStatus::Program_failed) {
|
||||
chThdSleepMilliseconds(10);
|
||||
// Mode left (R1) and right (R2,H2,H2+) bypass going into hackrf mode after failing CPLD update
|
||||
// Mode center (autodetect), up (R1) and down (R2,H2,H2+) will go into hackrf mode after failing CPLD update
|
||||
if (load_config() != 3 /* left */ && load_config() != 4 /* right */) {
|
||||
shutdown_base();
|
||||
return init_status_t::INIT_PORTAPACK_CPLD_FAILED;
|
||||
}
|
||||
}
|
||||
if (lcd_fast_setup)
|
||||
draw_splash_screen_icon(2, ui::bitmap_icon_sd);
|
||||
|
||||
init_status_t return_code = init_status_t::INIT_SUCCESS;
|
||||
|
||||
if (!hackrf::cpld::load_sram()) {
|
||||
if (lcd_fast_setup)
|
||||
chDbgPanic("HACKRF CPLD FAILED");
|
||||
|
||||
return_code = init_status_t::INIT_HACKRF_CPLD_FAILED;
|
||||
}
|
||||
|
||||
if (lcd_fast_setup)
|
||||
draw_splash_screen_icon(3, ui::bitmap_icon_hackrf);
|
||||
|
||||
chThdSleepMilliseconds(10); // This delay seems to solve white noise audio issues
|
||||
|
||||
LPC_CREG->DMAMUX = portapack::gpdma_mux;
|
||||
@@ -527,6 +586,13 @@ init_status_t init() {
|
||||
|
||||
audio::init(portapack_audio_codec());
|
||||
|
||||
if (lcd_fast_setup)
|
||||
draw_splash_screen_icon(4, ui::bitmap_icon_speaker);
|
||||
else {
|
||||
portapack::display.init();
|
||||
portapack::backlight()->on();
|
||||
}
|
||||
|
||||
return return_code;
|
||||
}
|
||||
|
||||
|
||||
@@ -127,6 +127,7 @@ void BtnGridView::add_item(GridItem new_item) {
|
||||
|
||||
void BtnGridView::update_items() {
|
||||
size_t i = 0;
|
||||
Color bg_color = portapack::persistent_memory::menu_color();
|
||||
|
||||
if ((menu_items.size()) > (displayed_max + offset)) {
|
||||
more = true;
|
||||
@@ -147,6 +148,7 @@ void BtnGridView::update_items() {
|
||||
item->set_text(menu_items[i + offset].text);
|
||||
item->set_bitmap(menu_items[i + offset].bitmap);
|
||||
item->set_color(menu_items[i + offset].color);
|
||||
item->set_bg_color(bg_color);
|
||||
item->on_select = menu_items[i + offset].on_select;
|
||||
item->set_dirty();
|
||||
}
|
||||
@@ -171,15 +173,19 @@ bool BtnGridView::set_highlighted(int32_t new_value) {
|
||||
if (((uint32_t)new_value > offset) && ((new_value - offset) >= displayed_max)) {
|
||||
// Shift BtnGridView up
|
||||
highlighted_item = new_value;
|
||||
offset += rows_;
|
||||
// rounding up new offset to next multiple of rows
|
||||
offset = new_value - displayed_max + rows_;
|
||||
offset -= (offset % rows_);
|
||||
update_items();
|
||||
set_dirty();
|
||||
// refresh whole screen (display flickers) only if scrolling last row up and a blank button is needed at the bottom
|
||||
if ((new_value + rows_ >= item_count) && (item_count % rows_) != 0)
|
||||
set_dirty();
|
||||
} else if ((uint32_t)new_value < offset) {
|
||||
// Shift BtnGridView down
|
||||
highlighted_item = new_value;
|
||||
offset = (new_value / rows_) * rows_;
|
||||
update_items();
|
||||
set_dirty();
|
||||
// no need to set_dirty() here since all buttons have been repainted
|
||||
} else {
|
||||
// Just update highlight
|
||||
highlighted_item = new_value;
|
||||
|
||||
@@ -86,6 +86,12 @@ const Style Styles::bg_blue{
|
||||
.foreground = Color::white(),
|
||||
};
|
||||
|
||||
const Style Styles::bg_dark_blue{
|
||||
.font = font::fixed_8x16,
|
||||
.background = Color::dark_blue(),
|
||||
.foreground = Color::white(),
|
||||
};
|
||||
|
||||
const Style Styles::light_grey{
|
||||
.font = font::fixed_8x16,
|
||||
.background = Color::black(),
|
||||
|
||||
@@ -58,6 +58,9 @@ class Styles {
|
||||
/* Blue background. */
|
||||
static const Style bg_blue;
|
||||
|
||||
/* Dark blue background. */
|
||||
static const Style bg_dark_blue;
|
||||
|
||||
/* Light grey foreground. */
|
||||
static const Style light_grey;
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "hackrf_gpio.hpp"
|
||||
#include "portapack_hal.hpp"
|
||||
#include "portapack.hpp"
|
||||
|
||||
#include "jtag_target_gpio.hpp"
|
||||
#include "cpld_max5.hpp"
|
||||
@@ -30,11 +31,15 @@
|
||||
#include "portapack_cpld_data.hpp"
|
||||
#include "hackrf_cpld_data.hpp"
|
||||
|
||||
#include "crc.hpp"
|
||||
|
||||
#define REV_20150901_CHECKSUM 0xE0EF80FB
|
||||
#define REV_20170522_CHECKSUM 0xD1BEB722
|
||||
|
||||
namespace portapack {
|
||||
namespace cpld {
|
||||
|
||||
CpldUpdateStatus update_if_necessary(
|
||||
const Config config) {
|
||||
CpldUpdateStatus update_if_necessary(const Config config) {
|
||||
jtag::GPIOTarget target{
|
||||
portapack::gpio_cpld_tck,
|
||||
portapack::gpio_cpld_tms,
|
||||
@@ -87,6 +92,121 @@ CpldUpdateStatus update_if_necessary(
|
||||
return ok ? CpldUpdateStatus::Success : CpldUpdateStatus::Program_failed;
|
||||
}
|
||||
|
||||
static CpldUpdateStatus enter_maintenance_mode(CPLD& cpld) {
|
||||
/* Unknown state */
|
||||
cpld.reset();
|
||||
cpld.run_test_idle();
|
||||
|
||||
/* Run-Test/Idle */
|
||||
if (!cpld.idcode_ok()) {
|
||||
return CpldUpdateStatus::Idcode_check_failed;
|
||||
}
|
||||
|
||||
cpld.sample();
|
||||
cpld.bypass();
|
||||
cpld.enable();
|
||||
|
||||
/* If silicon ID doesn't match, there's a serious problem. Leave CPLD
|
||||
* in passive state.
|
||||
*/
|
||||
if (!cpld.silicon_id_ok()) {
|
||||
return CpldUpdateStatus::Silicon_id_check_failed;
|
||||
}
|
||||
|
||||
return CpldUpdateStatus::Success;
|
||||
}
|
||||
|
||||
static void exit_maintenance_mode(CPLD& cpld) {
|
||||
cpld.disable();
|
||||
cpld.bypass();
|
||||
|
||||
/* Initiate SRAM reload from flash we just programmed. */
|
||||
cpld.sample();
|
||||
cpld.clamp();
|
||||
cpld.disable();
|
||||
}
|
||||
|
||||
static uint32_t get_firmware_crc(CPLD& cpld) {
|
||||
CRC<32> crc{0x04c11db7, 0xffffffff, 0xffffffff};
|
||||
cpld.prepare_read(0x0000);
|
||||
|
||||
for (size_t i = 0; i < 3328; i++) {
|
||||
uint16_t data = cpld.read();
|
||||
crc.process_byte((data >> 0) & 0xff);
|
||||
crc.process_byte((data >> 8) & 0xff);
|
||||
crc.process_byte((data >> 16) & 0xff);
|
||||
crc.process_byte((data >> 24) & 0xff);
|
||||
}
|
||||
|
||||
cpld.prepare_read(0x0001);
|
||||
|
||||
for (size_t i = 0; i < 512; i++) {
|
||||
uint16_t data = cpld.read();
|
||||
crc.process_byte((data >> 0) & 0xff);
|
||||
crc.process_byte((data >> 8) & 0xff);
|
||||
crc.process_byte((data >> 16) & 0xff);
|
||||
crc.process_byte((data >> 24) & 0xff);
|
||||
}
|
||||
|
||||
return crc.checksum();
|
||||
}
|
||||
|
||||
CpldUpdateStatus update_autodetect(const Config config_rev_20150901, const Config config_rev_20170522) {
|
||||
jtag::GPIOTarget target{
|
||||
portapack::gpio_cpld_tck,
|
||||
portapack::gpio_cpld_tms,
|
||||
portapack::gpio_cpld_tdi,
|
||||
portapack::gpio_cpld_tdo};
|
||||
jtag::JTAG jtag{target};
|
||||
CPLD cpld{jtag};
|
||||
|
||||
if (portapack::display.read_display_status())
|
||||
return CpldUpdateStatus::Success; // LCD is ready
|
||||
|
||||
CpldUpdateStatus result = enter_maintenance_mode(cpld);
|
||||
if (result != CpldUpdateStatus::Success)
|
||||
return result;
|
||||
|
||||
uint32_t checksum = get_firmware_crc(cpld);
|
||||
|
||||
if (checksum == REV_20170522_CHECKSUM) {
|
||||
// H2 firmware present
|
||||
if (!cpld.program(config_rev_20150901.block_0, config_rev_20150901.block_1))
|
||||
return CpldUpdateStatus::Program_failed;
|
||||
} else if (checksum == REV_20150901_CHECKSUM) {
|
||||
// H1 firmware present
|
||||
if (!cpld.program(config_rev_20170522.block_0, config_rev_20170522.block_1))
|
||||
return CpldUpdateStatus::Program_failed;
|
||||
} else {
|
||||
// no firmware present
|
||||
if (!cpld.program(config_rev_20150901.block_0, config_rev_20150901.block_1))
|
||||
return CpldUpdateStatus::Program_failed;
|
||||
}
|
||||
|
||||
exit_maintenance_mode(cpld);
|
||||
|
||||
if (portapack::display.read_display_status())
|
||||
return CpldUpdateStatus::Success; // LCD is ready
|
||||
|
||||
if (checksum != REV_20150901_CHECKSUM && checksum != REV_20170522_CHECKSUM) {
|
||||
// try the other one
|
||||
CpldUpdateStatus result = enter_maintenance_mode(cpld);
|
||||
|
||||
if (result != CpldUpdateStatus::Success)
|
||||
return result;
|
||||
|
||||
if (!cpld.program(config_rev_20170522.block_0, config_rev_20170522.block_1))
|
||||
return CpldUpdateStatus::Program_failed;
|
||||
|
||||
exit_maintenance_mode(cpld);
|
||||
|
||||
if (portapack::display.read_display_status())
|
||||
return CpldUpdateStatus::Success; // LCD is ready
|
||||
}
|
||||
|
||||
return CpldUpdateStatus::Program_failed;
|
||||
}
|
||||
|
||||
} /* namespace cpld */
|
||||
} /* namespace portapack */
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@ enum class CpldUpdateStatus {
|
||||
Program_failed = 3
|
||||
};
|
||||
|
||||
CpldUpdateStatus update_if_necessary(
|
||||
const Config config);
|
||||
CpldUpdateStatus update_if_necessary(const Config config);
|
||||
CpldUpdateStatus update_autodetect(const Config config_rev_20150901, const Config config_rev_20170522);
|
||||
|
||||
} /* namespace cpld */
|
||||
} /* namespace portapack */
|
||||
|
||||
@@ -84,6 +84,17 @@ void lcd_wake() {
|
||||
lcd_display_on();
|
||||
}
|
||||
|
||||
uint32_t lcd_read_display_status() {
|
||||
io.lcd_data_write_command_and_data(0x09, {});
|
||||
io.lcd_read_word();
|
||||
|
||||
uint32_t value2 = io.lcd_read_word();
|
||||
uint32_t value3 = io.lcd_read_word();
|
||||
uint32_t value4 = io.lcd_read_word();
|
||||
uint32_t value5 = io.lcd_read_word();
|
||||
return value5 + (value4 << 8) + (value3 << 16) + (value2 << 24);
|
||||
}
|
||||
|
||||
void lcd_init() {
|
||||
// LCDs are configured for IM[2:0] = 001
|
||||
// 8080-I system, 16-bit parallel bus
|
||||
@@ -260,6 +271,25 @@ void lcd_vertical_scrolling_start_address(
|
||||
|
||||
} // namespace
|
||||
|
||||
bool ILI9341::read_display_status() {
|
||||
lcd_reset();
|
||||
uint32_t display_status = lcd_read_display_status();
|
||||
|
||||
/* This tries to validate the display_status.
|
||||
* The value could vary from device to device, so we are less specific here.
|
||||
* 0xFFFFFEFF was seen when the display was not reachable
|
||||
* 0x00610000 was seen when the display was reachable
|
||||
*/
|
||||
|
||||
if (display_status > 0x0E000000ULL)
|
||||
return false;
|
||||
|
||||
if (display_status < 0x00000100ULL)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ILI9341::init() {
|
||||
lcd_reset();
|
||||
lcd_init();
|
||||
|
||||
@@ -42,6 +42,8 @@ class ILI9341 {
|
||||
ILI9341(ILI9341&&) = delete;
|
||||
void operator=(const ILI9341&) = delete;
|
||||
|
||||
bool read_display_status();
|
||||
|
||||
void init();
|
||||
void shutdown();
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "memory_map.hpp"
|
||||
#include "portapack.hpp"
|
||||
#include "string_format.hpp"
|
||||
#include "ui.hpp"
|
||||
#include "ui_styles.hpp"
|
||||
#include "ui_painter.hpp"
|
||||
#include "ui_flash_utility.hpp"
|
||||
@@ -46,6 +47,7 @@
|
||||
#include <hal.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace ui;
|
||||
|
||||
namespace portapack {
|
||||
namespace persistent_memory {
|
||||
@@ -229,7 +231,9 @@ struct data_t {
|
||||
uint16_t fake_brightness_level : 4;
|
||||
|
||||
// Encoder rotation rate multiplier for larger increments when rotated rapidly
|
||||
uint16_t encoder_rate_multiplier : 8;
|
||||
uint16_t encoder_rate_multiplier : 4;
|
||||
|
||||
uint16_t UNUSED : 4;
|
||||
|
||||
// Headphone volume in centibels.
|
||||
int16_t headphone_volume_cb;
|
||||
@@ -246,6 +250,11 @@ struct data_t {
|
||||
// Daylight savings time
|
||||
dst_config_t dst_config;
|
||||
|
||||
// Menu Color Scheme
|
||||
Color menu_color;
|
||||
|
||||
uint16_t UNUSED_16;
|
||||
|
||||
constexpr data_t()
|
||||
: structure_version(data_structure_version_enum::VERSION_CURRENT),
|
||||
target_frequency(target_frequency_reset_value),
|
||||
@@ -296,11 +305,15 @@ struct data_t {
|
||||
encoder_dial_sensitivity(DIAL_SENSITIVITY_NORMAL),
|
||||
fake_brightness_level(BRIGHTNESS_50),
|
||||
encoder_rate_multiplier(1),
|
||||
UNUSED(0),
|
||||
|
||||
headphone_volume_cb(-600),
|
||||
misc_config(),
|
||||
ui_config2(),
|
||||
config_mode_storage(CONFIG_MODE_NORMAL_VALUE),
|
||||
dst_config() {
|
||||
dst_config(),
|
||||
menu_color(Color::grey()),
|
||||
UNUSED_16() {
|
||||
}
|
||||
};
|
||||
|
||||
@@ -408,6 +421,7 @@ void defaults() {
|
||||
set_config_disable_external_tcxo(false);
|
||||
set_encoder_dial_sensitivity(DIAL_SENSITIVITY_NORMAL);
|
||||
set_config_speaker_disable(true); // Disable AK4951 speaker by default (in case of OpenSourceSDRLab H2)
|
||||
set_menu_color(Color::grey());
|
||||
|
||||
// Default values for recon app.
|
||||
set_recon_autosave_freqs(false);
|
||||
@@ -430,13 +444,15 @@ void defaults() {
|
||||
}
|
||||
|
||||
void init() {
|
||||
const auto switches_state = get_switches_state();
|
||||
const auto switches_state = swizzled_switches();
|
||||
|
||||
// ignore for valid check
|
||||
auto config_mode_backup = config_mode_storage_direct();
|
||||
set_config_mode_storage_direct(CONFIG_MODE_NORMAL_VALUE);
|
||||
|
||||
if (!(switches_state[(size_t)ui::KeyEvent::Left] && switches_state[(size_t)ui::KeyEvent::Right]) && backup_ram->is_valid()) {
|
||||
if (!(((switches_state >> (size_t)ui::KeyEvent::Left & 1) == 1) &&
|
||||
((switches_state >> (size_t)ui::KeyEvent::Right & 1) == 1)) &&
|
||||
backup_ram->is_valid()) {
|
||||
// Copy valid persistent data into cache.
|
||||
cached_backup_ram = *backup_ram;
|
||||
|
||||
@@ -455,7 +471,7 @@ void init() {
|
||||
|
||||
// Firmware upgrade handling - adjust newly defined fields where 0 is an invalid default
|
||||
if (fake_brightness_level() == 0) set_fake_brightness_level(BRIGHTNESS_50);
|
||||
if (encoder_rate_multiplier() == 0) set_encoder_rate_multiplier(1);
|
||||
if (menu_color().v == 0) set_menu_color(Color::grey());
|
||||
}
|
||||
|
||||
void persist() {
|
||||
@@ -987,7 +1003,9 @@ void set_encoder_dial_sensitivity(uint8_t v) {
|
||||
data->encoder_dial_sensitivity = v;
|
||||
}
|
||||
uint8_t encoder_rate_multiplier() {
|
||||
return data->encoder_rate_multiplier;
|
||||
uint8_t v = data->encoder_rate_multiplier;
|
||||
if (v == 0) v = 1; // minimum value is 1; treat 0 the same as 1
|
||||
return v;
|
||||
}
|
||||
void set_encoder_rate_multiplier(uint8_t v) {
|
||||
data->encoder_rate_multiplier = v;
|
||||
@@ -1045,6 +1063,14 @@ void toggle_fake_brightness_level() {
|
||||
}
|
||||
}
|
||||
|
||||
// Menu Color Scheme
|
||||
Color menu_color() {
|
||||
return data->menu_color;
|
||||
}
|
||||
void set_menu_color(Color v) {
|
||||
data->menu_color = v;
|
||||
}
|
||||
|
||||
// PMem to sdcard settings
|
||||
|
||||
bool should_use_sdcard_for_pmem() {
|
||||
@@ -1151,6 +1177,7 @@ bool debug_dump() {
|
||||
pmem_dump_file.write_line("config_mode_storage: 0x" + to_string_hex(data->config_mode_storage, 8));
|
||||
pmem_dump_file.write_line("dst_config: 0x" + to_string_hex((uint32_t)data->dst_config.v, 8));
|
||||
pmem_dump_file.write_line("fake_brightness_level: " + to_string_dec_uint(data->fake_brightness_level));
|
||||
pmem_dump_file.write_line("menu_color: 0x" + to_string_hex(data->menu_color.v, 4));
|
||||
|
||||
// ui_config bits
|
||||
const auto backlight_timer = portapack::persistent_memory::config_backlight_timer();
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "serializer.hpp"
|
||||
#include "volume.hpp"
|
||||
#include "config_mode.hpp"
|
||||
#include "ui.hpp"
|
||||
|
||||
// persistent memory from/to sdcard flag file
|
||||
#define PMEM_FILEFLAG u"/SETTINGS/PMEM_FILEFLAG"
|
||||
@@ -46,6 +47,7 @@
|
||||
|
||||
using namespace modems;
|
||||
using namespace serializer;
|
||||
using namespace ui;
|
||||
|
||||
namespace portapack {
|
||||
|
||||
@@ -282,6 +284,9 @@ uint8_t fake_brightness_level();
|
||||
void set_fake_brightness_level(uint8_t v);
|
||||
void toggle_fake_brightness_level();
|
||||
|
||||
Color menu_color();
|
||||
void set_menu_color(Color v);
|
||||
|
||||
/* Recon app */
|
||||
bool recon_autosave_freqs();
|
||||
bool recon_autostart_recon();
|
||||
|
||||
@@ -78,6 +78,18 @@ struct Color {
|
||||
((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3))} {
|
||||
}
|
||||
|
||||
uint8_t r() {
|
||||
return (uint8_t)((v >> 8) & 0xf8);
|
||||
}
|
||||
|
||||
uint8_t g() {
|
||||
return (uint8_t)((v >> 3) & 0xfc);
|
||||
}
|
||||
|
||||
uint8_t b() {
|
||||
return (uint8_t)((v << 3) & 0xf8);
|
||||
}
|
||||
|
||||
uint8_t to_greyscale() {
|
||||
uint32_t r = (v >> 8) & 0xf8;
|
||||
uint32_t g = (v >> 3) & 0xfc;
|
||||
|
||||
@@ -1290,6 +1290,11 @@ void NewButton::set_color(Color color) {
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
void NewButton::set_bg_color(Color color) {
|
||||
bg_color_ = color;
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
void NewButton::set_vertical_center(bool value) {
|
||||
vertical_center_ = value;
|
||||
set_dirty();
|
||||
@@ -1343,7 +1348,7 @@ Style NewButton::paint_style() {
|
||||
s.background = style().foreground;
|
||||
s.foreground = Color::black();
|
||||
} else {
|
||||
s.background = Color::grey();
|
||||
s.background = bg_color_;
|
||||
s.foreground = style().foreground;
|
||||
}
|
||||
|
||||
|
||||
@@ -504,6 +504,7 @@ class NewButton : public Widget {
|
||||
void set_bitmap(const Bitmap* bitmap);
|
||||
void set_text(const std::string value);
|
||||
void set_color(Color value);
|
||||
void set_bg_color(Color value);
|
||||
void set_vertical_center(bool value);
|
||||
std::string text() const;
|
||||
const Bitmap* bitmap();
|
||||
@@ -522,6 +523,7 @@ class NewButton : public Widget {
|
||||
protected:
|
||||
virtual Style paint_style();
|
||||
Color color_;
|
||||
Color bg_color_{Color::light_grey()};
|
||||
|
||||
private:
|
||||
std::string text_;
|
||||
|
||||
Reference in New Issue
Block a user