mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-12-29 01:06:27 -05:00
Cpld autodetect & boot splash screen (#1888)
* added delayed error message when hackrf cpld initialization fails * refactoring * implemented portapack cpld autodetection * refactoring * fixed valid config range * added lcd fast setup * added boot splash screen * added one frame delay to remove flickering * fixed config persistence
This commit is contained in:
parent
8725b01995
commit
c3add0ce84
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -430,13 +430,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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user