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
{
// 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);
was_read_zero = true;
} 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
// original deinit only disabled SM 0 and 1, but SM 2 (G_DAT0_SM) was left running
pio_set_sm_mask_enabled(pio1, 0x7, false); // disable SM 0, 1, AND 2 (0x7 = 0b111)
// 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);
// clean up GPIO pins
for (int i = PIN_CLK; i <= PIN_DAT; i++)

View file

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

View file

@ -65,8 +65,7 @@ void init_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 (mask 0x7 = 0b111) need to be disabled
// SM 2 (G_DAT0_SM) is also used, so all 3 state machines need to be disabled (0x7 = 0b111)
pio_set_sm_mask_enabled(pio1, 0x7, false);
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;
// Green pulsing implementation.
// Blue pulsing implementation.
void inc_tries()
{
tries += 1;
if(tries & 1)
put_pixel(PIX_g);
put_pixel(PIX_b);
else
put_pixel(PIX_gre);
put_pixel(PIX_blu);
}
// random() for glitch offset array generation

167
main.c
View file

@ -21,23 +21,24 @@
bool write_payload();
// optimized: increased voltage for better stability at higher clock
// overclock to 200 MHz
void init_system() {
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];
void rewrite_payload()
{
put_pixel(PIX_whi);
write_payload();
put_pixel(PIX_gre);
put_pixel(PIX_blu);
// used to automatically rewrite payload when eMMC/console changes
init_config(cid_buf + 1);
}
// optimized: reduced timeout and combined checks
bool safe_test_voltage(int pin, float target, float range)
{
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);
}
// optimized: reduced timeout from 2500ms to 1500ms, faster convergence
// test all ADC pins
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();
uint8_t check_mask = 0; // bit flags: 0=rst, 1=cmd, 2=d0
while (!time_reached(tio_time) && check_mask != 0x07) {
if (!(check_mask & 0x01))
check_mask |= safe_test_voltage(PIN_RST, 1.8f, 0.2f) ? 0x01 : 0;
if (!(check_mask & 0x02))
check_mask |= safe_test_voltage(PIN_CMD, 1.8f, 0.2f) ? 0x02 : 0;
if (!(check_mask & 0x04))
check_mask |= safe_test_voltage(PIN_DAT, 1.8f, 0.2f) ? 0x04 : 0;
bool rst_ok = false, cmd_ok = false, d0_ok = false, clk_ok = false;
while (!time_reached(tio_time)) {
if (!rst_ok)
rst_ok |= safe_test_voltage(PIN_RST, 1.8f, 0.2f);
if (!cmd_ok)
cmd_ok |= safe_test_voltage(PIN_CMD, 1.8f, 0.2f);
if (!d0_ok)
d0_ok |= safe_test_voltage(PIN_DAT, 1.8f, 0.2f);
if (rst_ok && cmd_ok && d0_ok)
break;
}
if(!(check_mask & 0x01))
if(!rst_ok)
{
halt_with_error(0, 2);
if(!(check_mask & 0x02))
}
if(!cmd_ok)
{
halt_with_error(1, 2);
if(!(check_mask & 0x04))
}
if(!d0_ok)
{
halt_with_error(2, 2);
}
}
extern bool was_self_reset;
@ -79,125 +86,89 @@ int main()
{
// stop watchdog
*(uint32_t*)(0x40058000 + 0x3000) = (1 << 30);
// init board detection
// init reset, mosfet and LED
detect_board();
// clocks & voltage
init_system();
init_system();
// fuses counter
init_fuses();
// LED & glitch & emmc PIO
upload_pio();
if (is_tiny())
{
gpio_put(led_pin(), 0);
sleep_us(50); // optimized: reduced from 100us
sleep_us(100);
put_pixel(0);
sleep_us(50); // optimized: reduced from 100us
sleep_us(100);
}
// check if this is the very first start
if (watchdog_caused_reboot() && boot_try == 0)
halt_with_error(1, 1);
{
halt_with_error(1, 1);
}
// is chip reset required
bool force_button = detect_by_pull(1, 0, 1);
// start LED
put_pixel(PIX_gre);
put_pixel(PIX_blu);
// test pins
self_test();
// 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
bool force_check = fast_check();
was_self_reset = force_button || !is_configured(cid_buf + 1);
// perform payload rewrite if required
if (!force_check || was_self_reset) {
rewrite_payload();
}
// setup the glitch trigger for Mariko
if (mariko) {
pio1->instr_mem[gtrig_pio_offset + 4] = pio_encode_nop();
pio1->instr_mem[gtrig_pio_offset + 5] = pio_encode_nop();
}
// optimized: start with slightly lower width for faster convergence
int width = 140;
// start from some default width
int width = 150;
bool glitched = false;
int offset = 0;
// optimized: removed outer loop since it just repeats rewrite_payload
// try saved records first
for (int y = 0; (y < 2) && !glitched; y++) {
int max_weight = -1;
while (1) {
offset = find_best_record(&max_weight);
if (offset == -1)
break;
// optimized: reduced attempts from 3 to 2 for faster iteration
glitched = glitch_try_offset(offset, &width, 2);
if (glitched)
break;
}
}
// try random offsets if saved records failed
if (!glitched) {
for(int z = 0; (z < 2) && !glitched; z++) {
prepare_random_array();
for(int y = 0; y < OFFSET_CNT; y++)
{
offset = offsets_array[y];
// optimized: reduced attempts from 4 to 3
for (int full_try = 0; full_try < 2; full_try++) {
// try saved records
for (int y = 0; (y < 2) && !glitched; y++) {
int max_weight = -1;
while (1) {
offset = find_best_record(&max_weight);
if (offset == -1)
break;
// try glitch
glitched = glitch_try_offset(offset, &width, 3);
if (glitched)
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) {
for(int z = 0; (z < 2) && !glitched; z++) {
prepare_random_array();
for(int y = 0; y < OFFSET_CNT; y++)
{
offset = offsets_array[y];
glitched = glitch_try_offset(offset, &width, 4);
if (glitched)
break;
}
}
}
if (glitched) {
if ((count_fuses() & 1) != boot_slot)
{
// finish update / rollback
burn_fuse();
}
add_boot_record(offset);
halt_with_error(0, 1);
}
if (full_try == 0) {
rewrite_payload();
}
}
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)
{
// finish update / rollback
burn_fuse();
}
add_boot_record(offset);
halt_with_error(0, 1);
}
// attempts limit
halt_with_error(7, 3);
}

63
misc.c
View file

@ -10,14 +10,13 @@
extern int ws_pio_offset;
// optimized: reduced timing constants for faster error signaling
#define BLINK_TIME 500
#define BLINK_TIME 700
#define SHORT_TIME ( BLINK_TIME * 2 / 10 )
#define SHORT_PAUSE_TIME ((BLINK_TIME - SHORT_TIME) / 2)
#define LONG_TIME ( BLINK_TIME * 8 / 10 )
#define LONG_PAUSE_TIME ((BLINK_TIME - LONG_TIME) / 2)
#define PAUSE_BETWEEN 1500
#define PAUSE_BEFORE 500
#define PAUSE_BETWEEN 2000
#define PAUSE_BEFORE 750
#define CODE_REPEATS 3
#define GPIO_OD PADS_BANK0_GPIO0_OD_BITS
@ -26,7 +25,6 @@ extern int ws_pio_offset;
typedef void nopar();
// optimized: streamlined power down sequence
void __not_in_flash_func(zzz)() {
*(uint32_t*)(0x4000803C + 0x3000) = 1; // go to 12 MHz
uint32_t * vreg = (uint32_t*)0x40064000;
@ -34,27 +32,30 @@ void __not_in_flash_func(zzz)() {
*(uint32_t*)0x40060000 = 0x00d1e000; // disable rosc
vreg[0] = 1; // lowest possible power
*(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() {
for(int pin = 0; pin <= 29; pin++) {
for(int pin = 0; pin <= 29; pin += 1) {
if (pin == led_pin() || pin == pwr_pin())
continue;
if (pin == PIN_GLI_PICO || pin == PIN_GLI_XIAO || pin == PIN_GLI_WS || pin == PIN_GLI_ITSY)
{
gpio_pull_down(pin);
}
else
{
gpio_disable_pulls(pin);
}
gpio_disable_input_output(pin);
}
}
void finish_pins_leds() {
if (!is_tiny())
{
gpio_disable_input_output(led_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);
set_sys_clock_khz(48000, true);
vreg_set_voltage(VREG_VOLTAGE_0_95);
if (bits != 1)
{
put_pixel(0);
sleep_ms(PAUSE_BEFORE);
}
for(int j = 0; j < CODE_REPEATS; j++)
{
for(int i = 0; i < bits; i++)
{
bool is_long = err & (1 << (bits - i - 1));
sleep_ms(is_long ? LONG_PAUSE_TIME : SHORT_PAUSE_TIME);
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);
put_pixel(0);
if (i != bits - 1 || j != CODE_REPEATS - 1)
sleep_ms(is_long ? LONG_PAUSE_TIME : SHORT_PAUSE_TIME);
if (i == bits - 1 && j != CODE_REPEATS - 1)
sleep_ms(PAUSE_BETWEEN);
}
// first write case, do not repeat this kind of error code
if (bits == 1)
break;
}
finish_pins_leds();
zzz();
}
// optimized: reduced LED delays for faster startup
void put_pixel(uint32_t pixel_rgb)
void put_pixel(uint32_t pixel_grb)
{
static bool led_enabled = false;
if (is_pico())
{
gpio_init(led_pin());
if (pixel_rgb) {
if (pixel_grb) {
gpio_set_dir(led_pin(), true);
gpio_put(led_pin(), 1);
}
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);
if (!led_enabled && pwr_pin() != 31)
{
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_dir(pwr_pin(), true);
gpio_put(pwr_pin(), 1);
sleep_us(100); // optimized: reduced from 200us
sleep_us(200);
}
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);
if (!is_tiny())
{
gpio_init(led_pin());
}
}
// optimized: direct register access
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 + 0x3000) = GPIO_IE;
}
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 + 0x2000) = GPIO_IE;
}
// optimized: reduced delays for faster reset cycles
void reset_cpu() {
gpio_enable_input_output(PIN_RST);
gpio_pull_up(PIN_RST);
sleep_us(800); // optimized: reduced from 1000us
sleep_us(1000);
gpio_init(PIN_RST);
gpio_set_dir(PIN_RST, true);
sleep_us(1800); // decreased slightly for button detection stability
sleep_us(2000);
gpio_deinit(PIN_RST);
gpio_disable_pulls(PIN_RST);
gpio_disable_input_output(PIN_RST);

9
misc.h
View file

@ -1,8 +1,9 @@
#define PIX_gre 0x16537e
#define PIX_red 0xc90000
#define PIX_whi 0xff9200
#define RGB(r, g, b) (((g) << 16) | ((r) << 8) | (b))
#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);

View file

@ -81,7 +81,7 @@ extern bool mariko;
static inline uint16_t crc_itu_t_byte(uint16_t crc, const uint8_t data)
{
return (crc << 8) ^ crc_itu_t_table[((crc >> 8) ^ data) & 0xff];
return (crc << 8) ^ crc_itu_t_table[((crc >> 8) ^ data) & 0xff];
}
uint16_t crc_itu_t(uint16_t crc, const uint8_t *buffer, size_t len)
@ -91,9 +91,9 @@ uint16_t crc_itu_t(uint16_t crc, const uint8_t *buffer, size_t len)
{
crc_prepare_table();
}
while (len--)
crc = crc_itu_t_byte(crc, *buffer++);
return crc;
while (len--)
crc = crc_itu_t_byte(crc, *buffer++);
return crc;
}
extern void zzz();
@ -108,18 +108,18 @@ uint16_t payload_crc()
int crc7(uint8_t *buffer, int size)
{
uint8_t crc = 0;
for (int i = 0; i < size; i++) {
uint8_t c = buffer[i];
for (int j = 0; j < 8; j++) {
crc <<= 1;
if ((crc ^ c) & 0x80)
crc ^= 9;
c <<= 1;
}
crc &= 0x7Fu;
}
return crc;
uint8_t crc = 0;
for (int i = 0; i < size; i++) {
uint8_t c = buffer[i];
for (int j = 0; j < 8; j++) {
crc <<= 1;
if ((crc ^ c) & 0x80)
crc ^= 9;
c <<= 1;
}
crc &= 0x7Fu;
}
return crc;
}
void __time_critical_func(cmd_write)(uint8_t cmd, uint32_t argument)
@ -130,9 +130,9 @@ void __time_critical_func(cmd_write)(uint8_t cmd, uint32_t argument)
pio_sm_set_out_pins(pio0, SM_OUT, PIN_CMD, 1);
pio_sm_set_enabled(pio0, SM_OUT, true);
data[0] = cmd | 0x40;
*(uint32_t *) &data[1] = __builtin_bswap32(argument);
data[5] = (crc7(data, 5) << 1) | 1;
data[0] = cmd | 0x40;
*(uint32_t *) &data[1] = __builtin_bswap32(argument);
data[5] = (crc7(data, 5) << 1) | 1;
uint32_t fifo[3];
fifo[0] = 0xFFCF0000 | (data[0] << 8) | data[1];
fifo[1] = __builtin_bswap32(*(uint32_t*)(data + 2));
@ -151,7 +151,7 @@ bool __time_critical_func(dat_write)()
pio_sm_set_out_pins(pio0, SM_OUT, PIN_DAT, 1);
pio_sm_set_enabled(pio0, SM_OUT, true);
uint8_t * buffer = data_buf;
uint16_t crc = crc_itu_t(0, buffer, 512);
uint16_t crc = crc_itu_t(0, buffer, 512);
uint32_t words[130];
int size_bits = 514 * 8 + 2;
words[0] = ((size_bits ^ 0xFFFF) << 16) | (buffer[0] << 7) | (buffer[1] >> 1);
@ -413,13 +413,13 @@ uint32_t mmc_init_table[] = {
};
bool mmc_initialize() {
if (!init_op_cond()) {
if (!init_op_cond()) {
return false;
}
if (!cmd_exec_cid()) {
return false;
}
for (int i = 0; i < sizeof(mmc_init_table)/sizeof(mmc_init_table[0]); i += 4)
for (int i = 0; i < sizeof(mmc_init_table)/sizeof(mmc_init_table[0]); i += 4)
{
uint32_t res= 0;
if (!simple_cmd_exec_with_ret(mmc_init_table[i], mmc_init_table[i+1], &res)) {
@ -495,9 +495,9 @@ extern int boot_slot;
uint8_t temp_buf[512];
struct fw_header {
uint32_t size;
uint32_t crc;
uint8_t data[];
uint32_t size;
uint32_t crc;
uint8_t data[];
};
#define fw_slot_0 ((struct fw_header *) (XIP_BASE + 0x10000))