revert some previous optimization changes, implement *proper* GRB to RGB conversion. these changes were on my mind for a while but they should fix error code display as well as have less jank error code indicators. rehius' usk was used as 'base' in this instance.

This commit is contained in:
DefenderOfHyrule 2026-03-31 07:15:36 +02:00
parent 9cce154f9c
commit 9e2544dbe3
8 changed files with 147 additions and 190 deletions

View file

@ -53,7 +53,7 @@ bool wait_for_boot(int timeout_ms) {
else if (last_word == 0x51000000 && word == 0x0055) //read block 0 else if (last_word == 0x51000000 && word == 0x0055) //read block 0
{ {
// OLED models sometimes need more time between block 0 and block 1 // OLED models sometimes need more time between block 0 and block 1
// original was 100ms, increased to 250ms for (hopefully) better OLED compatibility // original was 100ms, increased to 250ms for better OLED compatibility
tio_full = make_timeout_time_ms(250); tio_full = make_timeout_time_ms(250);
was_read_zero = true; was_read_zero = true;
} else if (was_read_zero && last_word == 0x4D000200 && word == 0x00B1) // read status - erista only } else if (was_read_zero && last_word == 0x4D000200 && word == 0x00B1) // read status - erista only
@ -69,9 +69,8 @@ bool wait_for_boot(int timeout_ms) {
} }
// properly clean up all state machines before retrying // properly clean up all state machines before retrying
// original deinit only disabled SM 0 and 1, but SM 2 (G_DAT0_SM) was left running // SM 2 (G_DAT0_SM) must also be disabled (0x7 = 0b111 covers SM 0, 1, and 2)
pio_set_sm_mask_enabled(pio1, 0x7, false);
pio_set_sm_mask_enabled(pio1, 0x7, false); // disable SM 0, 1, AND 2 (0x7 = 0b111)
// clean up GPIO pins // clean up GPIO pins
for (int i = PIN_CLK; i <= PIN_DAT; i++) for (int i = PIN_CLK; i <= PIN_DAT; i++)

View file

@ -1,7 +1,7 @@
#include "hardware/flash.h" #include "hardware/flash.h"
#define OFFSET_DIV 8 #define OFFSET_DIV 8
#define OFFSET_MIN 6200 #define OFFSET_MIN 6200
#define OFFSET_MAX 6950 #define OFFSET_MAX 6900
#define VER_HI 2 #define VER_HI 2
#define VER_LO 81 #define VER_LO 81

View file

@ -65,8 +65,7 @@ void init_glitch_pio() {
} }
void deinit_glitch_pio() { void deinit_glitch_pio() {
// original code only disabled SM 0 and 1 (mask 0x3 = 0b011) // SM 2 (G_DAT0_SM) is also used, so all 3 state machines need to be disabled (0x7 = 0b111)
// SM 2 (G_DAT0_SM) is also used, so all 3 (mask 0x7 = 0b111) need to be disabled
pio_set_sm_mask_enabled(pio1, 0x7, false); pio_set_sm_mask_enabled(pio1, 0x7, false);
for (int i = PIN_CLK; i <= PIN_DAT; i++) for (int i = PIN_CLK; i <= PIN_DAT; i++)
{ {
@ -136,14 +135,14 @@ int do_glitch(int delay, int width, int total_ms, int after_ms) {
int tries = 0; int tries = 0;
// Green pulsing implementation. // Blue pulsing implementation.
void inc_tries() void inc_tries()
{ {
tries += 1; tries += 1;
if(tries & 1) if(tries & 1)
put_pixel(PIX_g); put_pixel(PIX_b);
else else
put_pixel(PIX_gre); put_pixel(PIX_blu);
} }
// random() for glitch offset array generation // random() for glitch offset array generation

115
main.c
View file

@ -21,23 +21,24 @@
bool write_payload(); bool write_payload();
// optimized: increased voltage for better stability at higher clock // overclock to 200 MHz
void init_system() { void init_system() {
vreg_set_voltage(VREG_VOLTAGE_1_30); vreg_set_voltage(VREG_VOLTAGE_1_30);
set_sys_clock_khz(200000, true); set_sys_clock_khz(200000, true);
} }
// filled within "fast check" on eMMC init
extern uint8_t cid_buf[17]; extern uint8_t cid_buf[17];
void rewrite_payload() void rewrite_payload()
{ {
put_pixel(PIX_whi); put_pixel(PIX_whi);
write_payload(); write_payload();
put_pixel(PIX_gre); put_pixel(PIX_blu);
// used to automatically rewrite payload when eMMC/console changes
init_config(cid_buf + 1); init_config(cid_buf + 1);
} }
// optimized: reduced timeout and combined checks
bool safe_test_voltage(int pin, float target, float range) bool safe_test_voltage(int pin, float target, float range)
{ {
gpio_enable_input_output(pin); gpio_enable_input_output(pin);
@ -49,28 +50,34 @@ bool safe_test_voltage(int pin, float target, float range)
return voltage >= (target - range) && voltage <= (target + range); return voltage >= (target - range) && voltage <= (target + range);
} }
// optimized: reduced timeout from 2500ms to 1500ms, faster convergence // test all ADC pins
void self_test() void self_test()
{ {
absolute_time_t tio_time = make_timeout_time_ms(1500); absolute_time_t tio_time = make_timeout_time_ms(2500);
adc_init(); adc_init();
uint8_t check_mask = 0; // bit flags: 0=rst, 1=cmd, 2=d0 bool rst_ok = false, cmd_ok = false, d0_ok = false, clk_ok = false;
while (!time_reached(tio_time)) {
while (!time_reached(tio_time) && check_mask != 0x07) { if (!rst_ok)
if (!(check_mask & 0x01)) rst_ok |= safe_test_voltage(PIN_RST, 1.8f, 0.2f);
check_mask |= safe_test_voltage(PIN_RST, 1.8f, 0.2f) ? 0x01 : 0; if (!cmd_ok)
if (!(check_mask & 0x02)) cmd_ok |= safe_test_voltage(PIN_CMD, 1.8f, 0.2f);
check_mask |= safe_test_voltage(PIN_CMD, 1.8f, 0.2f) ? 0x02 : 0; if (!d0_ok)
if (!(check_mask & 0x04)) d0_ok |= safe_test_voltage(PIN_DAT, 1.8f, 0.2f);
check_mask |= safe_test_voltage(PIN_DAT, 1.8f, 0.2f) ? 0x04 : 0; if (rst_ok && cmd_ok && d0_ok)
break;
} }
if(!rst_ok)
if(!(check_mask & 0x01)) {
halt_with_error(0, 2); halt_with_error(0, 2);
if(!(check_mask & 0x02)) }
if(!cmd_ok)
{
halt_with_error(1, 2); halt_with_error(1, 2);
if(!(check_mask & 0x04)) }
if(!d0_ok)
{
halt_with_error(2, 2); halt_with_error(2, 2);
}
} }
extern bool was_self_reset; extern bool was_self_reset;
@ -79,116 +86,77 @@ int main()
{ {
// stop watchdog // stop watchdog
*(uint32_t*)(0x40058000 + 0x3000) = (1 << 30); *(uint32_t*)(0x40058000 + 0x3000) = (1 << 30);
// init reset, mosfet and LED
// init board detection
detect_board(); detect_board();
// clocks & voltage // clocks & voltage
init_system(); init_system();
// fuses counter // fuses counter
init_fuses(); init_fuses();
// LED & glitch & emmc PIO // LED & glitch & emmc PIO
upload_pio(); upload_pio();
if (is_tiny()) if (is_tiny())
{ {
gpio_put(led_pin(), 0); gpio_put(led_pin(), 0);
sleep_us(50); // optimized: reduced from 100us sleep_us(100);
put_pixel(0); put_pixel(0);
sleep_us(50); // optimized: reduced from 100us sleep_us(100);
} }
// check if this is the very first start // check if this is the very first start
if (watchdog_caused_reboot() && boot_try == 0) if (watchdog_caused_reboot() && boot_try == 0)
{
halt_with_error(1, 1); halt_with_error(1, 1);
}
// is chip reset required // is chip reset required
bool force_button = detect_by_pull(1, 0, 1); bool force_button = detect_by_pull(1, 0, 1);
// start LED // start LED
put_pixel(PIX_gre); put_pixel(PIX_blu);
// test pins // test pins
self_test(); self_test();
// wait till the CPU has proper power & started reading the eMMC // wait till the CPU has proper power & started reading the eMMC
wait_for_boot(2490); wait_for_boot(2500);
// ensure the BCT has not been overwritten by system update // ensure the BCT has not been overwritten by system update
bool force_check = fast_check(); bool force_check = fast_check();
was_self_reset = force_button || !is_configured(cid_buf + 1); was_self_reset = force_button || !is_configured(cid_buf + 1);
// perform payload rewrite if required // perform payload rewrite if required
if (!force_check || was_self_reset) { if (!force_check || was_self_reset) {
rewrite_payload(); rewrite_payload();
} }
// setup the glitch trigger for Mariko // setup the glitch trigger for Mariko
if (mariko) { if (mariko) {
pio1->instr_mem[gtrig_pio_offset + 4] = pio_encode_nop(); pio1->instr_mem[gtrig_pio_offset + 4] = pio_encode_nop();
pio1->instr_mem[gtrig_pio_offset + 5] = pio_encode_nop(); pio1->instr_mem[gtrig_pio_offset + 5] = pio_encode_nop();
} }
// start from some default width
// optimized: start with slightly lower width for faster convergence int width = 150;
int width = 140;
bool glitched = false; bool glitched = false;
int offset = 0; int offset = 0;
for (int full_try = 0; full_try < 2; full_try++) {
// optimized: removed outer loop since it just repeats rewrite_payload // try saved records
// try saved records first
for (int y = 0; (y < 2) && !glitched; y++) { for (int y = 0; (y < 2) && !glitched; y++) {
int max_weight = -1; int max_weight = -1;
while (1) { while (1) {
offset = find_best_record(&max_weight); offset = find_best_record(&max_weight);
if (offset == -1) if (offset == -1)
break; break;
// optimized: reduced attempts from 3 to 2 for faster iteration // try glitch
glitched = glitch_try_offset(offset, &width, 2); glitched = glitch_try_offset(offset, &width, 3);
if (glitched) if (glitched)
break; break;
} }
} }
// try random offsets if saved records failed
if (!glitched) { if (!glitched) {
for(int z = 0; (z < 2) && !glitched; z++) { for(int z = 0; (z < 2) && !glitched; z++) {
prepare_random_array(); prepare_random_array();
for(int y = 0; y < OFFSET_CNT; y++) for(int y = 0; y < OFFSET_CNT; y++)
{ {
offset = offsets_array[y]; offset = offsets_array[y];
// optimized: reduced attempts from 4 to 3 glitched = glitch_try_offset(offset, &width, 4);
glitched = glitch_try_offset(offset, &width, 3);
if (glitched) if (glitched)
break; break;
} }
} }
} }
// if still not glitched, try one more time with payload rewrite
if (!glitched) {
rewrite_payload();
// one more attempt with saved records
int max_weight = -1;
for (int y = 0; (y < 3) && !glitched; y++) {
offset = find_best_record(&max_weight);
if (offset == -1)
break;
glitched = glitch_try_offset(offset, &width, 2);
}
}
if (glitched) { if (glitched) {
// ensure all glitching operations are complete
sleep_us(100);
// force success LED display
put_pixel(0); // clear any previous LED state
sleep_ms(50);
put_pixel(PIX_whi); // show white success
sleep_ms(200); // longer delay to ensure visibility
if ((count_fuses() & 1) != boot_slot) if ((count_fuses() & 1) != boot_slot)
{ {
// finish update / rollback // finish update / rollback
@ -197,7 +165,10 @@ int main()
add_boot_record(offset); add_boot_record(offset);
halt_with_error(0, 1); halt_with_error(0, 1);
} }
if (full_try == 0) {
rewrite_payload();
}
}
// attempts limit // attempts limit
halt_with_error(7, 3); halt_with_error(7, 3);
} }

63
misc.c
View file

@ -10,14 +10,13 @@
extern int ws_pio_offset; extern int ws_pio_offset;
// optimized: reduced timing constants for faster error signaling #define BLINK_TIME 700
#define BLINK_TIME 500
#define SHORT_TIME ( BLINK_TIME * 2 / 10 ) #define SHORT_TIME ( BLINK_TIME * 2 / 10 )
#define SHORT_PAUSE_TIME ((BLINK_TIME - SHORT_TIME) / 2) #define SHORT_PAUSE_TIME ((BLINK_TIME - SHORT_TIME) / 2)
#define LONG_TIME ( BLINK_TIME * 8 / 10 ) #define LONG_TIME ( BLINK_TIME * 8 / 10 )
#define LONG_PAUSE_TIME ((BLINK_TIME - LONG_TIME) / 2) #define LONG_PAUSE_TIME ((BLINK_TIME - LONG_TIME) / 2)
#define PAUSE_BETWEEN 1500 #define PAUSE_BETWEEN 2000
#define PAUSE_BEFORE 500 #define PAUSE_BEFORE 750
#define CODE_REPEATS 3 #define CODE_REPEATS 3
#define GPIO_OD PADS_BANK0_GPIO0_OD_BITS #define GPIO_OD PADS_BANK0_GPIO0_OD_BITS
@ -26,7 +25,6 @@ extern int ws_pio_offset;
typedef void nopar(); typedef void nopar();
// optimized: streamlined power down sequence
void __not_in_flash_func(zzz)() { void __not_in_flash_func(zzz)() {
*(uint32_t*)(0x4000803C + 0x3000) = 1; // go to 12 MHz *(uint32_t*)(0x4000803C + 0x3000) = 1; // go to 12 MHz
uint32_t * vreg = (uint32_t*)0x40064000; uint32_t * vreg = (uint32_t*)0x40064000;
@ -34,27 +32,30 @@ void __not_in_flash_func(zzz)() {
*(uint32_t*)0x40060000 = 0x00d1e000; // disable rosc *(uint32_t*)0x40060000 = 0x00d1e000; // disable rosc
vreg[0] = 1; // lowest possible power vreg[0] = 1; // lowest possible power
*(uint32_t*)0x40024000 = 0x00d1e000; // disable xosc *(uint32_t*)0x40024000 = 0x00d1e000; // disable xosc
while(1) __asm volatile("wfi"); // optimized: use WFI to save more power while(1);
} }
// optimized: combined loop for faster execution
void finish_pins_except_leds() { void finish_pins_except_leds() {
for(int pin = 0; pin <= 29; pin++) { for(int pin = 0; pin <= 29; pin += 1) {
if (pin == led_pin() || pin == pwr_pin()) if (pin == led_pin() || pin == pwr_pin())
continue; continue;
if (pin == PIN_GLI_PICO || pin == PIN_GLI_XIAO || pin == PIN_GLI_WS || pin == PIN_GLI_ITSY) if (pin == PIN_GLI_PICO || pin == PIN_GLI_XIAO || pin == PIN_GLI_WS || pin == PIN_GLI_ITSY)
{
gpio_pull_down(pin); gpio_pull_down(pin);
}
else else
{
gpio_disable_pulls(pin); gpio_disable_pulls(pin);
}
gpio_disable_input_output(pin); gpio_disable_input_output(pin);
} }
} }
void finish_pins_leds() { void finish_pins_leds() {
if (!is_tiny()) if (!is_tiny())
{
gpio_disable_input_output(led_pin()); gpio_disable_input_output(led_pin());
}
gpio_disable_input_output(pwr_pin()); gpio_disable_input_output(pwr_pin());
} }
@ -65,62 +66,50 @@ void halt_with_error(uint32_t err, uint32_t bits)
pio_set_sm_mask_enabled(pio1, 0xF, false); pio_set_sm_mask_enabled(pio1, 0xF, false);
set_sys_clock_khz(48000, true); set_sys_clock_khz(48000, true);
vreg_set_voltage(VREG_VOLTAGE_0_95); vreg_set_voltage(VREG_VOLTAGE_0_95);
if (bits != 1) if (bits != 1)
{ {
put_pixel(0); put_pixel(0);
sleep_ms(PAUSE_BEFORE); sleep_ms(PAUSE_BEFORE);
} }
for(int j = 0; j < CODE_REPEATS; j++) for(int j = 0; j < CODE_REPEATS; j++)
{ {
for(int i = 0; i < bits; i++) for(int i = 0; i < bits; i++)
{ {
bool is_long = err & (1 << (bits - i - 1)); bool is_long = err & (1 << (bits - i - 1));
sleep_ms(is_long ? LONG_PAUSE_TIME : SHORT_PAUSE_TIME); sleep_ms(is_long ? LONG_PAUSE_TIME : SHORT_PAUSE_TIME);
bool success = bits == 1 && is_long == 0; bool success = bits == 1 && is_long == 0;
put_pixel(success ? PIX_whi : PIX_red); if (success)
put_pixel(PIX_whi);
else
put_pixel(PIX_red);
sleep_ms(is_long ? LONG_TIME : success ? SHORT_TIME * 2 : SHORT_TIME); sleep_ms(is_long ? LONG_TIME : success ? SHORT_TIME * 2 : SHORT_TIME);
put_pixel(0); put_pixel(0);
if (i != bits - 1 || j != CODE_REPEATS - 1) if (i != bits - 1 || j != CODE_REPEATS - 1)
sleep_ms(is_long ? LONG_PAUSE_TIME : SHORT_PAUSE_TIME); sleep_ms(is_long ? LONG_PAUSE_TIME : SHORT_PAUSE_TIME);
if (i == bits - 1 && j != CODE_REPEATS - 1) if (i == bits - 1 && j != CODE_REPEATS - 1)
sleep_ms(PAUSE_BETWEEN); sleep_ms(PAUSE_BETWEEN);
} }
// first write case, do not repeat this kind of error code // first write case, do not repeat this kind of error code
if (bits == 1) if (bits == 1)
break; break;
} }
finish_pins_leds(); finish_pins_leds();
zzz(); zzz();
} }
// optimized: reduced LED delays for faster startup void put_pixel(uint32_t pixel_grb)
void put_pixel(uint32_t pixel_rgb)
{ {
static bool led_enabled = false; static bool led_enabled = false;
if (is_pico()) if (is_pico())
{ {
gpio_init(led_pin()); gpio_init(led_pin());
if (pixel_rgb) { if (pixel_grb) {
gpio_set_dir(led_pin(), true); gpio_set_dir(led_pin(), true);
gpio_put(led_pin(), 1); gpio_put(led_pin(), 1);
} }
return; return;
} }
uint8_t red = (pixel_rgb >> 16) & 0xFF;
uint8_t green = (pixel_rgb >> 8) & 0xFF;
uint8_t blue = pixel_rgb & 0xFF;
uint32_t pixel_grb = (green << 16) | (red << 8) | blue;
ws2812_program_init(pio0, 3, ws_pio_offset, led_pin(), 800000, true); ws2812_program_init(pio0, 3, ws_pio_offset, led_pin(), 800000, true);
if (!led_enabled && pwr_pin() != 31) if (!led_enabled && pwr_pin() != 31)
{ {
led_enabled = true; led_enabled = true;
@ -128,40 +117,38 @@ void put_pixel(uint32_t pixel_rgb)
gpio_set_drive_strength(pwr_pin(), GPIO_DRIVE_STRENGTH_12MA); gpio_set_drive_strength(pwr_pin(), GPIO_DRIVE_STRENGTH_12MA);
gpio_set_dir(pwr_pin(), true); gpio_set_dir(pwr_pin(), true);
gpio_put(pwr_pin(), 1); gpio_put(pwr_pin(), 1);
sleep_us(100); // optimized: reduced from 200us sleep_us(200);
} }
pio_sm_put_blocking(pio0, 3, pixel_grb << 8u); pio_sm_put_blocking(pio0, 3, pixel_grb << 8u);
sleep_us(30); // optimized: reduced from 50us sleep_us(50);
pio_sm_set_enabled(pio0, 3, false); pio_sm_set_enabled(pio0, 3, false);
if (!is_tiny()) if (!is_tiny())
{
gpio_init(led_pin()); gpio_init(led_pin());
}
} }
// optimized: direct register access
void gpio_disable_input_output(int pin) void gpio_disable_input_output(int pin)
{ {
uint32_t pad_reg = 0x4001c000 + 4 + (pin << 2); // optimized: Use shift instead of multiply uint32_t pad_reg = 0x4001c000 + 4 + pin*4;
*(uint32_t*)(pad_reg + 0x2000) = GPIO_OD; *(uint32_t*)(pad_reg + 0x2000) = GPIO_OD;
*(uint32_t*)(pad_reg + 0x3000) = GPIO_IE; *(uint32_t*)(pad_reg + 0x3000) = GPIO_IE;
} }
void gpio_enable_input_output(int pin) void gpio_enable_input_output(int pin)
{ {
uint32_t pad_reg = 0x4001c000 + 4 + (pin << 2); // optimized: Use shift instead of multiply uint32_t pad_reg = 0x4001c000 + 4 + pin*4;
*(uint32_t*)(pad_reg + 0x3000) = GPIO_OD; *(uint32_t*)(pad_reg + 0x3000) = GPIO_OD;
*(uint32_t*)(pad_reg + 0x2000) = GPIO_IE; *(uint32_t*)(pad_reg + 0x2000) = GPIO_IE;
} }
// optimized: reduced delays for faster reset cycles
void reset_cpu() { void reset_cpu() {
gpio_enable_input_output(PIN_RST); gpio_enable_input_output(PIN_RST);
gpio_pull_up(PIN_RST); gpio_pull_up(PIN_RST);
sleep_us(800); // optimized: reduced from 1000us sleep_us(1000);
gpio_init(PIN_RST); gpio_init(PIN_RST);
gpio_set_dir(PIN_RST, true); gpio_set_dir(PIN_RST, true);
sleep_us(1800); // decreased slightly for button detection stability sleep_us(2000);
gpio_deinit(PIN_RST); gpio_deinit(PIN_RST);
gpio_disable_pulls(PIN_RST); gpio_disable_pulls(PIN_RST);
gpio_disable_input_output(PIN_RST); gpio_disable_input_output(PIN_RST);

9
misc.h
View file

@ -1,8 +1,9 @@
#define PIX_gre 0x16537e #define RGB(r, g, b) (((g) << 16) | ((r) << 8) | (b))
#define PIX_red 0xc90000
#define PIX_whi 0xff9200
#define PIX_g 0x6fa8dc #define PIX_blu RGB(0x16, 0x53, 0x7e) // blue (glitching)
#define PIX_b RGB(0x6f, 0xa8, 0xdc) // light blue dim (glitch pulse)
#define PIX_whi RGB(0xff, 0x92, 0x00) // amber/yellow (success + comparison)
#define PIX_red RGB(0xc9, 0x00, 0x00) // red (error codes)
void put_pixel(uint32_t pixel_grb); void put_pixel(uint32_t pixel_grb);