diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml
index 1b427b6..d48ba71 100644
--- a/.settings/language.settings.xml
+++ b/.settings/language.settings.xml
@@ -5,7 +5,7 @@
-
+
@@ -16,7 +16,7 @@
-
+
diff --git a/Core/Src/main.c b/Core/Src/main.c
index 6a0f7ea..e49e4f2 100644
--- a/Core/Src/main.c
+++ b/Core/Src/main.c
@@ -2,232 +2,151 @@
/**
******************************************************************************
* @file : main.c
- * @brief : Main program body
- ******************************************************************************
- * @attention
- *
- * Copyright (c) 2026 STMicroelectronics.
- * All rights reserved.
- *
- * This software is licensed under terms that can be found in the LICENSE file
- * in the root directory of this software component.
- * If no LICENSE file comes with this software, it is provided AS-IS.
- *
+ * @brief : Arrive LED sign firmware
******************************************************************************
*/
/* USER CODE END Header */
-/* Includes ------------------------------------------------------------------*/
#include "main.h"
-/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include
#include
/* USER CODE END Includes */
-/* Private typedef -----------------------------------------------------------*/
-/* USER CODE BEGIN PTD */
-
-/* USER CODE END PTD */
-
-/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define ROWS 7
#define COLS 96
-#define NUM_CHIPS 12 /* 12 x 8 bits = 96 column bits */
-#define ROW_DWELL 500 /* microseconds per row — tune for flicker/ghosting */
+#define NUM_CHIPS 12
+#define ROW_DWELL 500
#define UART_BUF 128
-#define WIDE_COLS 512 /* pre-render buffer width */
+#define WIDE_COLS 512
+
+/* Commands */
+#define CMD_CLEAR 0x01
+#define CMD_VALUES 0x02
+#define CMD_HW_DEPT 0x03
+#define CMD_SCROLL 0x04
/* USER CODE END PD */
-/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
-
/* USER CODE END PM */
-/* Private variables ---------------------------------------------------------*/
SPI_HandleTypeDef hspi1;
UART_HandleTypeDef huart2;
/* USER CODE BEGIN PV */
-/* Row pin lookup — matches CubeMX GPIO labels */
typedef struct { GPIO_TypeDef *port; uint16_t pin; } RowPin;
static const RowPin ROW_PINS[ROWS] = {
- {ROW_0_GPIO_Port, ROW_0_Pin}, /* ROW_0 — PB0 */
- {ROW_1_GPIO_Port, ROW_1_Pin}, /* ROW_1 — PA0 */
- {ROW_2_GPIO_Port, ROW_2_Pin}, /* ROW_2 — PA1 */
- {ROW_3_GPIO_Port, ROW_3_Pin}, /* ROW_3 — PB4 */
- {ROW_4_GPIO_Port, ROW_4_Pin}, /* ROW_4 — PB5 */
- {ROW_5_GPIO_Port, ROW_5_Pin}, /* ROW_5 — PA11 */
- {ROW_6_GPIO_Port, ROW_6_Pin}, /* ROW_6 — PA8 */
+ {ROW_0_GPIO_Port, ROW_0_Pin},
+ {ROW_1_GPIO_Port, ROW_1_Pin},
+ {ROW_2_GPIO_Port, ROW_2_Pin},
+ {ROW_3_GPIO_Port, ROW_3_Pin},
+ {ROW_4_GPIO_Port, ROW_4_Pin},
+ {ROW_5_GPIO_Port, ROW_5_Pin},
+ {ROW_6_GPIO_Port, ROW_6_Pin},
};
-/* Framebuffer — fb[row][chip], each byte = 8 column bits */
-static uint8_t fb[ROWS][NUM_CHIPS];
-
-/* Pre-rendered wide scroll buffer */
+static uint8_t fb[ROWS][NUM_CHIPS];
static uint8_t wide[ROWS][WIDE_COLS];
-static uint16_t wide_cols = 0; /* 0 = no message yet, display stays blank */
-static int32_t scroll_x = 0;
+static uint16_t wide_cols = 0;
+static int32_t scroll_x = 0;
-/* UART receive */
+/* UART protocol state */
static uint8_t uart_rx_byte;
static char uart_buf[UART_BUF];
static uint8_t uart_idx = 0;
-static uint8_t new_message = 0;
+static uint8_t uart_cs_acc = 0;
+static uint8_t uart_cs1 = 0;
+static uint8_t uart_cs2 = 0;
+static uint8_t uart_len = 0;
+static uint8_t uart_cmd = 0;
+
+/* Command queue — set by ISR, read by main loop */
+static volatile uint8_t pending_cmd = 0;
+static volatile uint8_t pending_cmd_rdy = 0;
+static char pending_msg[UART_BUF];
+
+/* Current mode */
+static uint8_t current_cmd = 0;
static char message[UART_BUF] = "";
-
-
/* USER CODE END PV */
-/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);
static void MX_USART2_UART_Init(void);
/* USER CODE BEGIN PFP */
-
/* USER CODE END PFP */
-/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
-/* 5x7 font, ASCII 32-90
- Each glyph = 5 bytes (columns), bit0 = top row */
+/* ── 5x7 font ASCII 32-90 ── */
static const uint8_t FONT[][5] = {
- {0x00,0x00,0x00,0x00,0x00}, /* ' ' 32 */
- {0x00,0x00,0x5F,0x00,0x00}, /* '!' */
- {0x00,0x07,0x00,0x07,0x00}, /* '"' */
- {0x14,0x7F,0x14,0x7F,0x14}, /* '#' */
- {0x24,0x2A,0x7F,0x2A,0x12}, /* '$' */
- {0x23,0x13,0x08,0x64,0x62}, /* '%' */
- {0x36,0x49,0x55,0x22,0x50}, /* '&' */
- {0x00,0x05,0x03,0x00,0x00}, /* ''' */
- {0x00,0x1C,0x22,0x41,0x00}, /* '(' */
- {0x00,0x41,0x22,0x1C,0x00}, /* ')' */
- {0x08,0x2A,0x1C,0x2A,0x08}, /* '*' */
- {0x08,0x08,0x3E,0x08,0x08}, /* '+' */
- {0x00,0x50,0x30,0x00,0x00}, /* ',' */
- {0x08,0x08,0x08,0x08,0x08}, /* '-' */
- {0x00,0x60,0x60,0x00,0x00}, /* '.' */
- {0x20,0x10,0x08,0x04,0x02}, /* '/' */
- {0x3E,0x51,0x49,0x45,0x3E}, /* '0' */
- {0x00,0x42,0x7F,0x40,0x00}, /* '1' */
- {0x42,0x61,0x51,0x49,0x46}, /* '2' */
- {0x21,0x41,0x45,0x4B,0x31}, /* '3' */
- {0x18,0x14,0x12,0x7F,0x10}, /* '4' */
- {0x27,0x45,0x45,0x45,0x39}, /* '5' */
- {0x3C,0x4A,0x49,0x49,0x30}, /* '6' */
- {0x01,0x71,0x09,0x05,0x03}, /* '7' */
- {0x36,0x49,0x49,0x49,0x36}, /* '8' */
- {0x06,0x49,0x49,0x29,0x1E}, /* '9' */
- {0x00,0x36,0x36,0x00,0x00}, /* ':' */
- {0x00,0x56,0x36,0x00,0x00}, /* ';' */
- {0x00,0x08,0x14,0x22,0x41}, /* '<' */
- {0x14,0x14,0x14,0x14,0x14}, /* '=' */
- {0x41,0x22,0x14,0x08,0x00}, /* '>' */
- {0x02,0x01,0x51,0x09,0x06}, /* '?' */
- {0x32,0x49,0x79,0x41,0x3E}, /* '@' */
- {0x7E,0x09,0x09,0x09,0x7E}, /* 'A' */
- {0x7F,0x49,0x49,0x49,0x36}, /* 'B' */
- {0x3E,0x41,0x41,0x41,0x22}, /* 'C' */
- {0x7F,0x41,0x41,0x41,0x3E}, /* 'D' */
- {0x7F,0x49,0x49,0x49,0x41}, /* 'E' */
- {0x7F,0x09,0x09,0x09,0x01}, /* 'F' */
- {0x3E,0x41,0x49,0x49,0x7A}, /* 'G' */
- {0x7F,0x08,0x08,0x08,0x7F}, /* 'H' */
- {0x41,0x7F,0x41,0x00,0x00}, /* 'I' */
- {0x20,0x40,0x41,0x3F,0x01}, /* 'J' */
- {0x7F,0x08,0x14,0x22,0x41}, /* 'K' */
- {0x7F,0x40,0x40,0x40,0x40}, /* 'L' */
- {0x7F,0x02,0x04,0x02,0x7F}, /* 'M' */
- {0x7F,0x04,0x08,0x10,0x7F}, /* 'N' */
- {0x3E,0x41,0x41,0x41,0x3E}, /* 'O' */
- {0x7F,0x09,0x09,0x09,0x06}, /* 'P' */
- {0x3E,0x41,0x51,0x21,0x5E}, /* 'Q' */
- {0x7F,0x09,0x19,0x29,0x46}, /* 'R' */
- {0x46,0x49,0x49,0x49,0x31}, /* 'S' */
- {0x01,0x01,0x7F,0x01,0x01}, /* 'T' */
- {0x3F,0x40,0x40,0x40,0x3F}, /* 'U' */
- {0x1F,0x20,0x40,0x20,0x1F}, /* 'V' */
- {0x7F,0x20,0x10,0x20,0x7F}, /* 'W' */
- {0x63,0x14,0x08,0x14,0x63}, /* 'X' */
- {0x03,0x04,0x78,0x04,0x03}, /* 'Y' */
- {0x61,0x51,0x49,0x45,0x43}, /* 'Z' */
+ {0x00,0x00,0x00,0x00,0x00}, /* ' ' */
+ {0x00,0x00,0x5F,0x00,0x00}, /* ! */
+ {0x00,0x07,0x00,0x07,0x00}, /* " */
+ {0x14,0x7F,0x14,0x7F,0x14}, /* # */
+ {0x24,0x2A,0x7F,0x2A,0x12}, /* $ */
+ {0x23,0x13,0x08,0x64,0x62}, /* % */
+ {0x36,0x49,0x55,0x22,0x50}, /* & */
+ {0x00,0x05,0x03,0x00,0x00}, /* ' */
+ {0x00,0x1C,0x22,0x41,0x00}, /* ( */
+ {0x00,0x41,0x22,0x1C,0x00}, /* ) */
+ {0x08,0x2A,0x1C,0x2A,0x08}, /* * */
+ {0x08,0x08,0x3E,0x08,0x08}, /* + */
+ {0x00,0x50,0x30,0x00,0x00}, /* , */
+ {0x08,0x08,0x08,0x08,0x08}, /* - */
+ {0x00,0x60,0x60,0x00,0x00}, /* . */
+ {0x20,0x10,0x08,0x04,0x02}, /* / */
+ {0x3E,0x51,0x49,0x45,0x3E}, /* 0 */
+ {0x00,0x42,0x7F,0x40,0x00}, /* 1 */
+ {0x42,0x61,0x51,0x49,0x46}, /* 2 */
+ {0x21,0x41,0x45,0x4B,0x31}, /* 3 */
+ {0x18,0x14,0x12,0x7F,0x10}, /* 4 */
+ {0x27,0x45,0x45,0x45,0x39}, /* 5 */
+ {0x3C,0x4A,0x49,0x49,0x30}, /* 6 */
+ {0x01,0x71,0x09,0x05,0x03}, /* 7 */
+ {0x36,0x49,0x49,0x49,0x36}, /* 8 */
+ {0x06,0x49,0x49,0x29,0x1E}, /* 9 */
+ {0x00,0x36,0x36,0x00,0x00}, /* : */
+ {0x00,0x56,0x36,0x00,0x00}, /* ; */
+ {0x00,0x08,0x14,0x22,0x41}, /* < */
+ {0x14,0x14,0x14,0x14,0x14}, /* = */
+ {0x41,0x22,0x14,0x08,0x00}, /* > */
+ {0x02,0x01,0x51,0x09,0x06}, /* ? */
+ {0x32,0x49,0x79,0x41,0x3E}, /* @ */
+ {0x7E,0x09,0x09,0x09,0x7E}, /* A */
+ {0x7F,0x49,0x49,0x49,0x36}, /* B */
+ {0x3E,0x41,0x41,0x41,0x22}, /* C */
+ {0x7F,0x41,0x41,0x41,0x3E}, /* D */
+ {0x7F,0x49,0x49,0x49,0x41}, /* E */
+ {0x7F,0x09,0x09,0x09,0x01}, /* F */
+ {0x3E,0x41,0x49,0x49,0x7A}, /* G */
+ {0x7F,0x08,0x08,0x08,0x7F}, /* H */
+ {0x41,0x7F,0x41,0x00,0x00}, /* I */
+ {0x20,0x40,0x41,0x3F,0x01}, /* J */
+ {0x7F,0x08,0x14,0x22,0x41}, /* K */
+ {0x7F,0x40,0x40,0x40,0x40}, /* L */
+ {0x7F,0x02,0x04,0x02,0x7F}, /* M */
+ {0x7F,0x04,0x08,0x10,0x7F}, /* N */
+ {0x3E,0x41,0x41,0x41,0x3E}, /* O */
+ {0x7F,0x09,0x09,0x09,0x06}, /* P */
+ {0x3E,0x41,0x51,0x21,0x5E}, /* Q */
+ {0x7F,0x09,0x19,0x29,0x46}, /* R */
+ {0x46,0x49,0x49,0x49,0x31}, /* S */
+ {0x01,0x01,0x7F,0x01,0x01}, /* T */
+ {0x3F,0x40,0x40,0x40,0x3F}, /* U */
+ {0x1F,0x20,0x40,0x20,0x1F}, /* V */
+ {0x7F,0x20,0x10,0x20,0x7F}, /* W */
+ {0x63,0x14,0x08,0x14,0x63}, /* X */
+ {0x03,0x04,0x78,0x04,0x03}, /* Y */
+ {0x61,0x51,0x49,0x45,0x43}, /* Z */
};
-/* ── Microsecond busy-wait using DWT cycle counter ── */
-static void delay_us(uint32_t us)
-{
- uint32_t start = DWT->CYCCNT;
- uint32_t ticks = (SystemCoreClock / 1000000U) * us;
- while ((DWT->CYCCNT - start) < ticks);
-}
-
-/* ── Turn all row pins off (HIGH = ULN2803A pulls gate low = MOSFET off) ── */
-static void all_rows_off(void)
-{
- for (int i = 0; i < ROWS; i++)
- HAL_GPIO_WritePin(ROW_PINS[i].port, ROW_PINS[i].pin, GPIO_PIN_SET);
-}
-
-/* ── Send one row of column data via SPI then enable that row ── */
-static void display_refresh(void)
-{
- for (int row = 0; row < ROWS; row++) {
- all_rows_off();
- HAL_SPI_Transmit(&hspi1, fb[row], NUM_CHIPS, HAL_MAX_DELAY);
- /* LOW = ULN2803A releases gate = MOSFET on = row enabled */
- HAL_GPIO_WritePin(ROW_PINS[row].port, ROW_PINS[row].pin, GPIO_PIN_RESET);
- delay_us(ROW_DWELL);
- }
- all_rows_off();
-}
-
-/* ── Render message string into wide[] pixel buffer ── */
-static void render_message(const char *msg)
-{
- memset(wide, 0, sizeof(wide));
- uint16_t col = COLS; /* lead with one blank screen so text scrolls in */
-
- while (*msg && col < (WIDE_COLS - 6)) {
- uint8_t c = (uint8_t)*msg++;
- /* Convert lowercase to uppercase */
- if (c >= 'a' && c <= 'z') c -= 32;
- if (c >= 32 && c <= 90) {
- const uint8_t *glyph = FONT[c - 32];
- for (int g = 0; g < 5 && col < WIDE_COLS; g++, col++) {
- for (int row = 0; row < ROWS; row++) {
- wide[row][col] = (glyph[g] >> row) & 1;
- }
- }
- }
- col++; /* one gap column between characters */
- }
- wide_cols = col + COLS; /* scroll until text fully exits left edge */
- scroll_x = 0;
-}
-
-/* ── Copy current scroll window from wide[] into fb[][] ── */
-static void update_fb_from_scroll(void)
-{
- for (int row = 0; row < ROWS; row++) {
- memset(fb[row], 0, NUM_CHIPS);
- for (int col = 0; col < COLS; col++) {
- uint16_t src = (uint16_t)(scroll_x + col);
- if (src < WIDE_COLS && wide[row][src]) {
- int chip = col / 8;
- int bit = 7 - (col % 8);
- fb[row][chip] |= (uint8_t)(1 << bit);
- }
- }
- }
-}
-
-/* ── Arrive north star pixel map, 7 rows x 11 cols ── */
+/* ── North star ── */
static const uint8_t STAR[7][11] = {
{0,0,0,0,1,0,0,0,0,0,0},
{0,0,0,1,1,1,0,0,0,0,0},
@@ -238,55 +157,87 @@ static const uint8_t STAR[7][11] = {
{0,0,0,0,1,0,0,0,0,0,0},
};
-/* ARRIVE — 6 chars, each 5 cols wide + 1 col gap = 36 cols total
- Rows 0-6, col order left to right: A R R I V E */
+/* ── ARRIVE glyph 7x36 ── */
static const uint8_t ARRIVE_GLYPH[7][36] = {
-/* A R R I V E */
-/* r0 */ {0,1,1,1,0,0, 0,1,1,1,0,0, 0,1,1,1,0,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 1,1,1,1,1,0},
-/* r1 */ {1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,0,1,0,0,0, 1,0,0,0,1,0, 1,0,0,0,0,0},
-/* r2 */ {1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,0,1,0,0,0, 1,0,0,0,1,0, 1,0,0,0,0,0},
-/* r3 */ {1,1,1,1,1,0, 1,1,1,1,0,0, 1,1,1,1,0,0, 0,0,1,0,0,0, 0,1,0,1,0,0, 1,1,1,1,0,0},
-/* r4 */ {1,0,0,0,1,0, 1,0,1,0,0,0, 1,0,1,0,0,0, 0,0,1,0,0,0, 0,1,0,1,0,0, 1,0,0,0,0,0},
-/* r5 */ {1,0,0,0,1,0, 1,0,0,1,0,0, 1,0,0,1,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 1,0,0,0,0,0},
-/* r6 */ {1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,1,1,1,0,0, 0,0,1,0,0,0, 1,1,1,1,1,0},
+ {0,1,1,1,0,0, 0,1,1,1,0,0, 0,1,1,1,0,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 1,1,1,1,1,0},
+ {1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,0,1,0,0,0, 1,0,0,0,1,0, 1,0,0,0,0,0},
+ {1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,0,1,0,0,0, 1,0,0,0,1,0, 1,0,0,0,0,0},
+ {1,1,1,1,1,0, 1,1,1,1,0,0, 1,1,1,1,0,0, 0,0,1,0,0,0, 0,1,0,1,0,0, 1,1,1,1,0,0},
+ {1,0,0,0,1,0, 1,0,1,0,0,0, 1,0,1,0,0,0, 0,0,1,0,0,0, 0,1,0,1,0,0, 1,0,0,0,0,0},
+ {1,0,0,0,1,0, 1,0,0,1,0,0, 1,0,0,1,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 1,0,0,0,0,0},
+ {1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,1,1,1,0,0, 0,0,1,0,0,0, 1,1,1,1,1,0},
};
-/* ── Render logo into fb
- mask_col: columns < mask_col are hidden (wipe reveals right-to-left), -1 = show all ── */
+/* ════════════════════════════════════════════════
+ Low level display helpers
+ ════════════════════════════════════════════════ */
+
+static void delay_us(uint32_t us)
+{
+ uint32_t start = DWT->CYCCNT;
+ uint32_t ticks = (SystemCoreClock / 1000000U) * us;
+ while ((DWT->CYCCNT - start) < ticks);
+}
+
+static void all_rows_off(void)
+{
+ for (int i = 0; i < ROWS; i++)
+ HAL_GPIO_WritePin(ROW_PINS[i].port, ROW_PINS[i].pin, GPIO_PIN_SET);
+}
+
+static void display_refresh(void)
+{
+ for (int row = 0; row < ROWS; row++) {
+ all_rows_off();
+ HAL_SPI_Transmit(&hspi1, fb[row], NUM_CHIPS, HAL_MAX_DELAY);
+ HAL_GPIO_WritePin(ROW_PINS[row].port, ROW_PINS[row].pin, GPIO_PIN_RESET);
+ delay_us(ROW_DWELL);
+ }
+ all_rows_off();
+}
+
+static void refresh_for(uint32_t ms)
+{
+ uint32_t t = HAL_GetTick();
+ while ((HAL_GetTick() - t) < ms) { display_refresh(); }
+}
+
+/* ── Check if a new command arrived — call from long-running loops ── */
+static uint8_t check_new_cmd(void)
+{
+ return pending_cmd_rdy;
+}
+
+/* ════════════════════════════════════════════════
+ Framebuffer helpers
+ ════════════════════════════════════════════════ */
+
+static void fb_set_pixel(int col, int row, uint8_t on)
+{
+ if (col < 0 || col >= COLS || row < 0 || row >= ROWS) return;
+ int chip = col / 8;
+ int bit = 7 - (col % 8);
+ if (on) fb[row][chip] |= (uint8_t)(1 << bit);
+ else fb[row][chip] &= ~(uint8_t)(1 << bit);
+}
+
static void render_logo(int star_col, int text_col, int mask_col)
{
memset(fb, 0, sizeof(fb));
-
- /* Draw star */
for (int row = 0; row < 7; row++) {
for (int sc = 0; sc < 11; sc++) {
int col = star_col + sc;
- if (col >= 0 && col < COLS && STAR[row][sc]) {
- if (mask_col < 0 || col >= mask_col) {
- int chip = col / 8;
- int bit = 7 - (col % 8);
- fb[row][chip] |= (uint8_t)(1 << bit);
- }
- }
+ if (STAR[row][sc] && (mask_col < 0 || col >= mask_col))
+ fb_set_pixel(col, row, 1);
}
- }
-
- /* Draw ARRIVE text */
- for (int row = 0; row < 7; row++) {
for (int tc = 0; tc < 36; tc++) {
int col = text_col + tc;
- if (col >= 0 && col < COLS && ARRIVE_GLYPH[row][tc]) {
- if (mask_col < 0 || col >= mask_col) {
- int chip = col / 8;
- int bit = 7 - (col % 8);
- fb[row][chip] |= (uint8_t)(1 << bit);
- }
- }
+ if (ARRIVE_GLYPH[row][tc] && (mask_col < 0 || col >= mask_col))
+ fb_set_pixel(col, row, 1);
}
}
}
-/* ── Blank fb but keep specific rows lit (bitmask) ── */
static void render_logo_rows(int star_col, int text_col, uint8_t row_mask)
{
memset(fb, 0, sizeof(fb));
@@ -294,154 +245,340 @@ static void render_logo_rows(int star_col, int text_col, uint8_t row_mask)
if (!(row_mask & (1 << row))) continue;
for (int sc = 0; sc < 11; sc++) {
int col = star_col + sc;
- if (col >= 0 && col < COLS && STAR[row][sc]) {
- int chip = col / 8; int bit = 7 - (col % 8);
- fb[row][chip] |= (uint8_t)(1 << bit);
- }
+ if (STAR[row][sc]) fb_set_pixel(col, row, 1);
}
- for (int tc = 0; tc < 30; tc++) {
+ for (int tc = 0; tc < 36; tc++) {
int col = text_col + tc;
- if (col >= 0 && col < COLS && ARRIVE_GLYPH[row][tc]) {
- int chip = col / 8; int bit = 7 - (col % 8);
- fb[row][chip] |= (uint8_t)(1 << bit);
- }
+ if (ARRIVE_GLYPH[row][tc]) fb_set_pixel(col, row, 1);
}
}
}
-/* ── Refresh for a given number of milliseconds ── */
-static void refresh_for(uint32_t ms)
+/* ── Draw text string into fb at given x offset, return end col ── */
+static int render_text_to_fb(const char *txt, int x_offset)
{
- uint32_t t = HAL_GetTick();
- while ((HAL_GetTick() - t) < ms) { display_refresh(); }
+ int col = x_offset;
+ while (*txt) {
+ uint8_t c = (uint8_t)*txt++;
+ if (c >= 'a' && c <= 'z') c -= 32;
+ if (c >= 32 && c <= 90) {
+ const uint8_t *g = FONT[c - 32];
+ for (int i = 0; i < 5; i++, col++) {
+ for (int row = 0; row < ROWS; row++) {
+ if (g[i] & (1 << row)) fb_set_pixel(col, row, 1);
+ }
+ }
+ }
+ col++;
+ }
+ return col;
}
-/* ── Arrive boot animation ── */
+/* ── Render text centred on display ── */
+static void render_centred_text(const char *txt)
+{
+ int len = 0;
+ const char *p = txt;
+ while (*p++) len++;
+ int text_width = len * 6 - 1;
+ int x = (COLS - text_width) / 2;
+ memset(fb, 0, sizeof(fb));
+ render_text_to_fb(txt, x);
+}
+
+/* ── Render word into wide[] for scrolling, returns total width ── */
+static uint16_t render_scroll(const char *txt, int x_start)
+{
+ memset(wide, 0, sizeof(wide));
+ int col = x_start;
+ while (*txt && col < WIDE_COLS - 6) {
+ uint8_t c = (uint8_t)*txt++;
+ if (c >= 'a' && c <= 'z') c -= 32;
+ if (c >= 32 && c <= 90) {
+ const uint8_t *g = FONT[c - 32];
+ for (int i = 0; i < 5 && col < WIDE_COLS; i++, col++) {
+ for (int row = 0; row < ROWS; row++) {
+ if (g[i] & (1 << row)) wide[row][col] = 1;
+ }
+ }
+ }
+ col++;
+ }
+ return (uint16_t)(col + COLS);
+}
+
+static void update_fb_from_scroll(void)
+{
+ for (int row = 0; row < ROWS; row++) {
+ memset(fb[row], 0, NUM_CHIPS);
+ for (int col = 0; col < COLS; col++) {
+ uint16_t src = (uint16_t)(scroll_x + col);
+ if (src < WIDE_COLS && wide[row][src])
+ fb_set_pixel(col, row, 1);
+ }
+ }
+}
+
+/* ── Update fb from scroll but only write to cols >= clip_left ── */
+static void update_fb_from_scroll_clipped(int clip_left)
+{
+ for (int row = 0; row < ROWS; row++) {
+ for (int col = clip_left; col < COLS; col++) {
+ uint16_t src = (uint16_t)(scroll_x + (col - clip_left));
+ if (src < WIDE_COLS)
+ fb_set_pixel(col, row, wide[row][src]);
+ }
+ }
+}
+
+/* ── Fade rows out (centre outward to top+bottom) ── */
+static void fade_out_rows(int star_col, int text_col, uint8_t is_logo)
+{
+ uint8_t masks[] = {0x7E, 0x7C, 0x3C, 0x1C, 0x0C, 0x08, 0x00};
+ uint8_t snap[ROWS][NUM_CHIPS];
+ memcpy(snap, fb, sizeof(fb));
+ for (int i = 0; i < 7; i++) {
+ if (is_logo) {
+ render_logo_rows(star_col, text_col, masks[i]);
+ } else {
+ memset(fb, 0, sizeof(fb));
+ for (int row = 0; row < ROWS; row++) {
+ if (masks[i] & (1 << row))
+ memcpy(fb[row], snap[row], NUM_CHIPS);
+ }
+ }
+ refresh_for(60);
+ }
+ memset(fb, 0, sizeof(fb));
+}
+
+/* ════════════════════════════════════════════════
+ Arrive boot / splash animation
+ ════════════════════════════════════════════════ */
+
static void arrive_animation(void)
{
- /* Logo layout — text LEFT, star RIGHT:
- ARRIVE = 36 cols, gap = 2, star = 11 cols → total = 49 cols
- centred on 96: start = (96 - 49) / 2 = 23
- text_col = 23, star_col = 23 + 36 + 2 = 61 */
const int text_col = 23;
const int star_col = 61;
- /* ── Phase 1: Star builds from centre outward ── */
- /* Frame 1 — just centre cross */
+ /* Phase 1 — star builds */
memset(fb, 0, sizeof(fb));
- for (int row = 0; row < 7; row++) {
- int col = star_col + 4; /* centre column of star */
- int chip = col / 8; int bit = 7 - (col % 8);
- fb[row][chip] |= (uint8_t)(1 << bit);
- }
- /* horizontal bar centre */
- for (int sc = 3; sc <= 5; sc++) {
- int col = star_col + sc;
- int chip = col / 8; int bit = 7 - (col % 8);
- fb[3][chip] |= (uint8_t)(1 << bit);
- }
+ for (int row = 0; row < 7; row++) fb_set_pixel(star_col + 4, row, 1);
+ for (int sc = 3; sc <= 5; sc++) fb_set_pixel(star_col + sc, 3, 1);
refresh_for(120);
- /* Frame 2 — inner star shape */
memset(fb, 0, sizeof(fb));
- for (int row = 0; row < 7; row++) {
- for (int sc = 3; sc <= 7; sc++) {
- if (STAR[row][sc]) {
- int col = star_col + sc;
- int chip = col / 8; int bit = 7 - (col % 8);
- fb[row][chip] |= (uint8_t)(1 << bit);
- }
- }
- }
+ for (int row = 0; row < 7; row++)
+ for (int sc = 3; sc <= 7; sc++)
+ if (STAR[row][sc]) fb_set_pixel(star_col + sc, row, 1);
refresh_for(120);
- /* Frame 3 — full star, text still hidden */
- render_logo(star_col, text_col, star_col); /* mask hides everything left of star */
+ render_logo(star_col, text_col, star_col);
refresh_for(150);
- /* ── Phase 2: Glint pulse ── */
- memset(fb, 0, sizeof(fb));
- refresh_for(80);
- render_logo(star_col, text_col, star_col);
- refresh_for(80);
- memset(fb, 0, sizeof(fb));
- refresh_for(60);
- render_logo(star_col, text_col, star_col);
- refresh_for(100);
+ /* Phase 2 — glint pulse */
+ memset(fb, 0, sizeof(fb)); refresh_for(80);
+ render_logo(star_col, text_col, star_col); refresh_for(80);
+ memset(fb, 0, sizeof(fb)); refresh_for(60);
+ render_logo(star_col, text_col, star_col); refresh_for(100);
- /* ── Phase 3: Wipe right-to-left — reveal ARRIVE sweeping from star leftward ── */
+ /* Phase 3 — wipe reveal */
for (int mask = star_col; mask >= text_col - 1; mask -= 2) {
render_logo(star_col, text_col, mask);
refresh_for(18);
}
render_logo(star_col, text_col, -1);
- refresh_for(18);
- /* ── Phase 4: Hold ── */
+ /* Phase 4 — hold */
refresh_for(2000);
- /* ── Phase 5: Fade out — rows extinguish top+bottom inward ── */
- /* Order: 0,6 then 1,5 then 2,4 then 3 */
- uint8_t row_mask = 0x7F; /* all 7 rows on */
-
- row_mask &= ~(1 << 0); row_mask &= ~(1 << 6);
- render_logo_rows(star_col, text_col, row_mask); refresh_for(80);
-
- row_mask &= ~(1 << 1); row_mask &= ~(1 << 5);
- render_logo_rows(star_col, text_col, row_mask); refresh_for(80);
-
- row_mask &= ~(1 << 2); row_mask &= ~(1 << 4);
- render_logo_rows(star_col, text_col, row_mask); refresh_for(80);
-
- row_mask &= ~(1 << 3);
- memset(fb, 0, sizeof(fb)); refresh_for(80);
-
- /* Brief blank before scroll */
+ /* Phase 5 — fade out */
+ fade_out_rows(star_col, text_col, 1);
refresh_for(200);
}
+
+/* ════════════════════════════════════════════════
+ CMD_VALUES — Curious / Focused / Together loop
+ ════════════════════════════════════════════════ */
+
+static const char *VALUES_WORDS[] = { "CURIOUS", "FOCUSED", "TOGETHER" };
+#define VALUES_COUNT 3
+
+static void run_values(void)
+{
+ uint8_t idx = 0;
+
+ while (!check_new_cmd()) {
+ /* Arrive splash with fade out */
+ arrive_animation();
+ if (check_new_cmd()) break;
+
+ /* Display word centred — no fade in, just show it */
+ render_centred_text(VALUES_WORDS[idx]);
+ refresh_for(2500);
+ if (check_new_cmd()) break;
+
+ /* Fade out same as arrive splash — rows collapse inward */
+ fade_out_rows(0, 0, 0);
+ if (check_new_cmd()) break;
+
+ /* Wait before next cycle */
+ memset(fb, 0, sizeof(fb));
+ refresh_for(600);
+ if (check_new_cmd()) break;
+
+ idx = (idx + 1) % VALUES_COUNT;
+ }
+}
+
+/* ════════════════════════════════════════════════
+ CMD_HW_DEPT — logo left, scrolling text right
+ ════════════════════════════════════════════════ */
+
+/* Small logo: text_col=2, star_col=40, total=53 cols
+ Leaves cols 54-95 (42 cols) for scroll text */
+#define HW_TEXT_COL 2
+#define HW_STAR_COL 40
+#define HW_SCROLL_START 54
+
+static void run_hw_dept(void)
+{
+ const char *hw_txt = "HARDWARE DEPT ";
+ /* Start text one scroll-zone width to the right so it scrolls in from edge */
+ const int scroll_zone = COLS - HW_SCROLL_START; /* ~42 cols */
+ uint16_t hw_wide_cols = render_scroll(hw_txt, scroll_zone);
+ int32_t hw_scroll_x = 0;
+ uint32_t last_scroll = HAL_GetTick();
+ const uint32_t scroll_ms = 40;
+
+ while (!check_new_cmd()) {
+ /* Draw logo into fb */
+ render_logo(HW_STAR_COL, HW_TEXT_COL, -1);
+
+ /* Overlay scrolling text on right side */
+ update_fb_from_scroll_clipped(HW_SCROLL_START);
+
+ /* Advance scroll */
+ if ((HAL_GetTick() - last_scroll) >= scroll_ms) {
+ last_scroll = HAL_GetTick();
+ hw_scroll_x++;
+ if (hw_scroll_x >= hw_wide_cols) hw_scroll_x = 0;
+ scroll_x = hw_scroll_x;
+ }
+
+ display_refresh();
+ }
+}
+
+/* ════════════════════════════════════════════════
+ CMD_SCROLL — scroll arbitrary text
+ ════════════════════════════════════════════════ */
+
+static void run_scroll(void)
+{
+ wide_cols = render_scroll(message, COLS);
+ scroll_x = 0;
+ update_fb_from_scroll();
+
+ uint32_t last_scroll = HAL_GetTick();
+ const uint32_t scroll_ms = 40;
+
+ while (!check_new_cmd()) {
+ if ((HAL_GetTick() - last_scroll) >= scroll_ms) {
+ last_scroll = HAL_GetTick();
+ scroll_x++;
+ if (scroll_x >= wide_cols) scroll_x = 0;
+ update_fb_from_scroll();
+ }
+ display_refresh();
+ }
+}
+
+/* ════════════════════════════════════════════════
+ UART protocol state machine
+ Packet: 'A' 'R' CMD LEN CS1 CS2 [MSG...]
+ CS1 = sum(msg) & 0xFF
+ CS2 = ~CS1 & 0xFF
+ ════════════════════════════════════════════════ */
+
+typedef enum {
+ UART_WAIT_A, UART_WAIT_R, UART_WAIT_CMD,
+ UART_WAIT_LEN, UART_WAIT_CS1, UART_WAIT_CS2, UART_WAIT_DATA,
+} UartState;
+
+static UartState uart_state = UART_WAIT_A;
+
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
- if (huart->Instance == USART2) {
- char b = (char)uart_rx_byte;
- if (b == '\n' || b == '\r') {
- if (uart_idx > 0) {
- uart_buf[uart_idx] = '\0';
- memcpy(message, uart_buf, uart_idx + 1);
- uart_idx = 0;
- new_message = 1;
+ if (huart->Instance != USART2) return;
+ uint8_t b = uart_rx_byte;
+
+ switch (uart_state) {
+ case UART_WAIT_A:
+ if (b == 'A') uart_state = UART_WAIT_R;
+ break;
+ case UART_WAIT_R:
+ uart_state = (b == 'R') ? UART_WAIT_CMD : UART_WAIT_A;
+ break;
+ case UART_WAIT_CMD:
+ uart_cmd = b;
+ uart_state = UART_WAIT_LEN;
+ break;
+ case UART_WAIT_LEN:
+ uart_len = b;
+ uart_idx = 0;
+ uart_cs_acc = 0;
+ uart_state = UART_WAIT_CS1;
+ break;
+ case UART_WAIT_CS1:
+ uart_cs1 = b;
+ uart_state = UART_WAIT_CS2;
+ break;
+ case UART_WAIT_CS2:
+ uart_cs2 = b;
+ uart_state = (uart_len > 0) ? UART_WAIT_DATA : UART_WAIT_A;
+ if (uart_len == 0) {
+ /* No payload — validate empty checksum (cs1=cs2=0 for empty) */
+ pending_cmd = uart_cmd;
+ pending_msg[0] = '\0';
+ pending_cmd_rdy = 1;
}
- } else if (uart_idx < UART_BUF - 1) {
- uart_buf[uart_idx++] = b;
- }
- /* Re-arm for next byte */
- HAL_UART_Receive_IT(&huart2, &uart_rx_byte, 1);
+ break;
+ case UART_WAIT_DATA:
+ uart_buf[uart_idx++] = (char)b;
+ uart_cs_acc += b;
+ if (uart_idx >= uart_len) {
+ uart_buf[uart_idx] = '\0';
+ uint8_t cs1c = uart_cs_acc & 0xFF;
+ uint8_t cs2c = (~uart_cs_acc) & 0xFF;
+ if (cs1c == uart_cs1 && cs2c == uart_cs2) {
+ memcpy(pending_msg, uart_buf, uart_idx + 1);
+ pending_cmd = uart_cmd;
+ pending_cmd_rdy = 1;
+ }
+ uart_state = UART_WAIT_A;
+ uart_idx = 0;
+ }
+ break;
}
+ HAL_UART_Receive_IT(&huart2, &uart_rx_byte, 1);
}
/* USER CODE END 0 */
-/**
- * @brief The application entry point.
- * @retval int
- */
int main(void)
{
-
/* USER CODE BEGIN 1 */
-
/* USER CODE END 1 */
- /* MCU Configuration--------------------------------------------------------*/
HAL_Init();
/* USER CODE BEGIN Init */
-
/* USER CODE END Init */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
-
/* USER CODE END SysInit */
MX_GPIO_Init();
@@ -449,54 +586,52 @@ int main(void)
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
-
- /* Enable DWT cycle counter for microsecond delays */
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
- /* All rows off, blank display */
all_rows_off();
memset(fb, 0, sizeof(fb));
- /* Start UART receive interrupt */
HAL_UART_Receive_IT(&huart2, &uart_rx_byte, 1);
- /* Render default message */
- render_message(message);
- update_fb_from_scroll();
-
+ arrive_animation();
+ memset(fb, 0, sizeof(fb));
+ current_cmd = 0;
/* USER CODE END 2 */
/* USER CODE BEGIN WHILE */
-
- /* Run boot animation */
- arrive_animation();
-
- update_fb_from_scroll();
-
- uint32_t last_scroll = HAL_GetTick();
- const uint32_t scroll_ms = 40;
-
while (1)
{
- if (new_message) {
- new_message = 0;
- render_message(message);
+ if (pending_cmd_rdy) {
+ pending_cmd_rdy = 0;
+ current_cmd = pending_cmd;
+ memcpy(message, pending_msg, sizeof(pending_msg));
}
- if ((HAL_GetTick() - last_scroll) >= scroll_ms) {
- last_scroll = HAL_GetTick();
- scroll_x++;
- if (scroll_x >= wide_cols) {
- /* End of message — switch to next */
- scroll_x = 0;
- }
- update_fb_from_scroll();
+ switch (current_cmd) {
+ case CMD_CLEAR:
+ memset(fb, 0, sizeof(fb));
+ display_refresh();
+ current_cmd = 0;
+ break;
+
+ case CMD_VALUES:
+ run_values();
+ break;
+
+ case CMD_HW_DEPT:
+ run_hw_dept();
+ break;
+
+ case CMD_SCROLL:
+ run_scroll();
+ break;
+
+ default:
+ display_refresh();
+ break;
}
-
- display_refresh();
-
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
@@ -504,17 +639,12 @@ int main(void)
/* USER CODE END 3 */
}
-/**
- * @brief System Clock Configuration
- * @retval None
- */
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST);
-
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
@@ -525,10 +655,7 @@ void SystemClock_Config(void)
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
- {
- Error_Handler();
- }
+ if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) Error_Handler();
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
@@ -536,24 +663,14 @@ void SystemClock_Config(void)
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
-
- if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
- {
- Error_Handler();
- }
+ if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) Error_Handler();
}
-/**
- * @brief SPI1 Initialization Function
- */
static void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
-
/* USER CODE END SPI1_Init 0 */
-
/* USER CODE BEGIN SPI1_Init 1 */
-
/* USER CODE END SPI1_Init 1 */
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
@@ -569,26 +686,16 @@ static void MX_SPI1_Init(void)
hspi1.Init.CRCPolynomial = 7;
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
- if (HAL_SPI_Init(&hspi1) != HAL_OK)
- {
- Error_Handler();
- }
+ if (HAL_SPI_Init(&hspi1) != HAL_OK) Error_Handler();
/* USER CODE BEGIN SPI1_Init 2 */
-
/* USER CODE END SPI1_Init 2 */
}
-/**
- * @brief USART2 Initialization Function
- */
static void MX_USART2_UART_Init(void)
{
/* USER CODE BEGIN USART2_Init 0 */
-
/* USER CODE END USART2_Init 0 */
-
/* USER CODE BEGIN USART2_Init 1 */
-
/* USER CODE END USART2_Init 1 */
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
@@ -601,35 +708,18 @@ static void MX_USART2_UART_Init(void)
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
- if (HAL_UART_Init(&huart2) != HAL_OK)
- {
- Error_Handler();
- }
- if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
- {
- Error_Handler();
- }
- if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
- {
- Error_Handler();
- }
- if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK)
- {
- Error_Handler();
- }
+ if (HAL_UART_Init(&huart2) != HAL_OK) Error_Handler();
+ if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK) Error_Handler();
+ if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK) Error_Handler();
+ if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK) Error_Handler();
/* USER CODE BEGIN USART2_Init 2 */
-
/* USER CODE END USART2_Init 2 */
}
-/**
- * @brief GPIO Initialization Function
- */
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
-
/* USER CODE END MX_GPIO_Init_1 */
__HAL_RCC_GPIOA_CLK_ENABLE();
@@ -657,31 +747,20 @@ static void MX_GPIO_Init(void)
HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct);
/* USER CODE BEGIN MX_GPIO_Init_2 */
-
/* USER CODE END MX_GPIO_Init_2 */
}
/* USER CODE BEGIN 4 */
-
/* USER CODE END 4 */
-/**
- * @brief This function is executed in case of error occurrence.
- */
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
__disable_irq();
- while (1)
- {
- }
+ while (1) {}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
-void assert_failed(uint8_t *file, uint32_t line)
-{
- /* USER CODE BEGIN 6 */
- /* USER CODE END 6 */
-}
-#endif /* USE_FULL_ASSERT */
+void assert_failed(uint8_t *file, uint32_t line) {}
+#endif
diff --git a/Debug/Core/Src/main.cyclo b/Debug/Core/Src/main.cyclo
index e2d613b..5c28e52 100644
--- a/Debug/Core/Src/main.cyclo
+++ b/Debug/Core/Src/main.cyclo
@@ -1,16 +1,25 @@
-../Core/Src/main.c:163:13:delay_us 2
-../Core/Src/main.c:171:13:all_rows_off 2
-../Core/Src/main.c:178:13:display_refresh 2
-../Core/Src/main.c:191:13:render_message 10
-../Core/Src/main.c:215:13:update_fb_from_scroll 6
-../Core/Src/main.c:256:13:render_logo 17
-../Core/Src/main.c:290:13:render_logo_rows 13
-../Core/Src/main.c:313:13:refresh_for 2
-../Core/Src/main.c:320:13:arrive_animation 10
-../Core/Src/main.c:402:6:HAL_UART_RxCpltCallback 6
-../Core/Src/main.c:427:5:main 4
-../Core/Src/main.c:511:6:SystemClock_Config 3
-../Core/Src/main.c:549:13:MX_SPI1_Init 2
-../Core/Src/main.c:584:13:MX_USART2_UART_Init 5
-../Core/Src/main.c:628:13:MX_GPIO_Init 1
-../Core/Src/main.c:671:6:Error_Handler 1
+../Core/Src/main.c:175:13:delay_us 2
+../Core/Src/main.c:182:13:all_rows_off 2
+../Core/Src/main.c:188:13:display_refresh 2
+../Core/Src/main.c:199:13:refresh_for 2
+../Core/Src/main.c:206:16:check_new_cmd 1
+../Core/Src/main.c:215:13:fb_set_pixel 7
+../Core/Src/main.c:224:13:render_logo 10
+../Core/Src/main.c:241:13:render_logo_rows 7
+../Core/Src/main.c:258:12:render_text_to_fb 9
+../Core/Src/main.c:278:13:render_centred_text 2
+../Core/Src/main.c:290:17:render_scroll 11
+../Core/Src/main.c:310:13:update_fb_from_scroll 5
+../Core/Src/main.c:323:13:update_fb_from_scroll_clipped 4
+../Core/Src/main.c:335:13:fade_out_rows 5
+../Core/Src/main.c:359:13:arrive_animation 7
+../Core/Src/main.c:407:13:run_values 6
+../Core/Src/main.c:444:13:run_hw_dept 4
+../Core/Src/main.c:477:13:run_scroll 4
+../Core/Src/main.c:511:6:HAL_UART_RxCpltCallback 16
+../Core/Src/main.c:569:5:main 6
+../Core/Src/main.c:642:6:SystemClock_Config 3
+../Core/Src/main.c:669:13:MX_SPI1_Init 2
+../Core/Src/main.c:694:13:MX_USART2_UART_Init 5
+../Core/Src/main.c:719:13:MX_GPIO_Init 1
+../Core/Src/main.c:756:6:Error_Handler 1
diff --git a/Debug/Core/Src/main.o b/Debug/Core/Src/main.o
index bdc1636..c775fb7 100644
Binary files a/Debug/Core/Src/main.o and b/Debug/Core/Src/main.o differ
diff --git a/Debug/Core/Src/main.su b/Debug/Core/Src/main.su
index afcfa76..f63faad 100644
--- a/Debug/Core/Src/main.su
+++ b/Debug/Core/Src/main.su
@@ -1,16 +1,25 @@
-../Core/Src/main.c:163:13:delay_us 24 static
-../Core/Src/main.c:171:13:all_rows_off 16 static
-../Core/Src/main.c:178:13:display_refresh 16 static
-../Core/Src/main.c:191:13:render_message 32 static
-../Core/Src/main.c:215:13:update_fb_from_scroll 32 static
-../Core/Src/main.c:256:13:render_logo 64 static
-../Core/Src/main.c:290:13:render_logo_rows 64 static
-../Core/Src/main.c:313:13:refresh_for 24 static
-../Core/Src/main.c:320:13:arrive_animation 80 static
-../Core/Src/main.c:402:6:HAL_UART_RxCpltCallback 24 static
-../Core/Src/main.c:427:5:main 16 static
-../Core/Src/main.c:511:6:SystemClock_Config 88 static
-../Core/Src/main.c:549:13:MX_SPI1_Init 8 static
-../Core/Src/main.c:584:13:MX_USART2_UART_Init 8 static
-../Core/Src/main.c:628:13:MX_GPIO_Init 40 static
-../Core/Src/main.c:671:6:Error_Handler 4 static,ignoring_inline_asm
+../Core/Src/main.c:175:13:delay_us 24 static
+../Core/Src/main.c:182:13:all_rows_off 16 static
+../Core/Src/main.c:188:13:display_refresh 16 static
+../Core/Src/main.c:199:13:refresh_for 24 static
+../Core/Src/main.c:206:16:check_new_cmd 4 static
+../Core/Src/main.c:215:13:fb_set_pixel 32 static
+../Core/Src/main.c:224:13:render_logo 48 static
+../Core/Src/main.c:241:13:render_logo_rows 48 static
+../Core/Src/main.c:258:12:render_text_to_fb 40 static
+../Core/Src/main.c:278:13:render_centred_text 32 static
+../Core/Src/main.c:290:17:render_scroll 40 static
+../Core/Src/main.c:310:13:update_fb_from_scroll 24 static
+../Core/Src/main.c:323:13:update_fb_from_scroll_clipped 32 static
+../Core/Src/main.c:335:13:fade_out_rows 128 static
+../Core/Src/main.c:359:13:arrive_animation 40 static
+../Core/Src/main.c:407:13:run_values 16 static
+../Core/Src/main.c:444:13:run_hw_dept 32 static
+../Core/Src/main.c:477:13:run_scroll 16 static
+../Core/Src/main.c:511:6:HAL_UART_RxCpltCallback 24 static
+../Core/Src/main.c:569:5:main 8 static
+../Core/Src/main.c:642:6:SystemClock_Config 88 static
+../Core/Src/main.c:669:13:MX_SPI1_Init 8 static
+../Core/Src/main.c:694:13:MX_USART2_UART_Init 8 static
+../Core/Src/main.c:719:13:MX_GPIO_Init 40 static
+../Core/Src/main.c:756:6:Error_Handler 4 static,ignoring_inline_asm
diff --git a/Debug/HW_DEPT_NEXIO_SIGN.elf b/Debug/HW_DEPT_NEXIO_SIGN.elf
index 631b689..56b0370 100644
Binary files a/Debug/HW_DEPT_NEXIO_SIGN.elf and b/Debug/HW_DEPT_NEXIO_SIGN.elf differ
diff --git a/Debug/HW_DEPT_NEXIO_SIGN.list b/Debug/HW_DEPT_NEXIO_SIGN.list
index 060cbda..dc91f85 100644
--- a/Debug/HW_DEPT_NEXIO_SIGN.list
+++ b/Debug/HW_DEPT_NEXIO_SIGN.list
@@ -5,47 +5,47 @@ Sections:
Idx Name Size VMA LMA File off Algn
0 .isr_vector 000001d8 08000000 08000000 00001000 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
- 1 .text 00005314 080001d8 080001d8 000011d8 2**2
+ 1 .text 00005604 080001d8 080001d8 000011d8 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
- 2 .rodata 000002ec 080054ec 080054ec 000064ec 2**2
+ 2 .rodata 00000324 080057dc 080057dc 000067dc 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
- 3 .ARM.extab 00000000 080057d8 080057d8 0000700c 2**0
+ 3 .ARM.extab 00000000 08005b00 08005b00 00007018 2**0
CONTENTS, READONLY
- 4 .ARM 00000008 080057d8 080057d8 000067d8 2**2
+ 4 .ARM 00000008 08005b00 08005b00 00006b00 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
- 5 .preinit_array 00000000 080057e0 080057e0 0000700c 2**0
+ 5 .preinit_array 00000000 08005b08 08005b08 00007018 2**0
CONTENTS, ALLOC, LOAD, DATA
- 6 .init_array 00000004 080057e0 080057e0 000067e0 2**2
+ 6 .init_array 00000004 08005b08 08005b08 00006b08 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
- 7 .fini_array 00000004 080057e4 080057e4 000067e4 2**2
+ 7 .fini_array 00000004 08005b0c 08005b0c 00006b0c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
- 8 .data 0000000c 20000000 080057e8 00007000 2**2
+ 8 .data 00000018 20000000 08005b10 00007000 2**2
CONTENTS, ALLOC, LOAD, DATA
- 9 .bss 0000107c 2000000c 080057f4 0000700c 2**2
+ 9 .bss 00001108 20000018 08005b28 00007018 2**2
ALLOC
- 10 ._user_heap_stack 00000600 20001088 080057f4 00007088 2**0
+ 10 ._user_heap_stack 00000600 20001120 08005b28 00007120 2**0
ALLOC
- 11 .ARM.attributes 00000030 00000000 00000000 0000700c 2**0
+ 11 .ARM.attributes 00000030 00000000 00000000 00007018 2**0
CONTENTS, READONLY
- 12 .debug_info 0000f3cc 00000000 00000000 0000703c 2**0
+ 12 .debug_info 0000f68f 00000000 00000000 00007048 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
- 13 .debug_abbrev 00002085 00000000 00000000 00016408 2**0
+ 13 .debug_abbrev 000020e0 00000000 00000000 000166d7 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
- 14 .debug_aranges 00000c38 00000000 00000000 00018490 2**3
+ 14 .debug_aranges 00000c80 00000000 00000000 000187b8 2**3
CONTENTS, READONLY, DEBUGGING, OCTETS
- 15 .debug_rnglists 00000976 00000000 00000000 000190c8 2**0
+ 15 .debug_rnglists 000009b2 00000000 00000000 00019438 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
- 16 .debug_macro 0001d1bb 00000000 00000000 00019a3e 2**0
+ 16 .debug_macro 0001d1ef 00000000 00000000 00019dea 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
- 17 .debug_line 0000ec7a 00000000 00000000 00036bf9 2**0
+ 17 .debug_line 0000ef3a 00000000 00000000 00036fd9 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
- 18 .debug_str 000b86c2 00000000 00000000 00045873 2**0
+ 18 .debug_str 000b8906 00000000 00000000 00045f13 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
- 19 .comment 00000043 00000000 00000000 000fdf35 2**0
+ 19 .comment 00000043 00000000 00000000 000fe819 2**0
CONTENTS, READONLY
- 20 .debug_frame 00002f7c 00000000 00000000 000fdf78 2**2
+ 20 .debug_frame 000030b4 00000000 00000000 000fe85c 2**2
CONTENTS, READONLY, DEBUGGING, OCTETS
- 21 .debug_line_str 00000071 00000000 00000000 00100ef4 2**0
+ 21 .debug_line_str 00000071 00000000 00000000 00101910 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
Disassembly of section .text:
@@ -62,9 +62,9 @@ Disassembly of section .text:
80001ea: 2301 movs r3, #1
80001ec: 7023 strb r3, [r4, #0]
80001ee: bd10 pop {r4, pc}
- 80001f0: 2000000c .word 0x2000000c
+ 80001f0: 20000018 .word 0x20000018
80001f4: 00000000 .word 0x00000000
- 80001f8: 080054d4 .word 0x080054d4
+ 80001f8: 080057c4 .word 0x080057c4
080001fc :
80001fc: b508 push {r3, lr}
@@ -75,8 +75,8 @@ Disassembly of section .text:
8000206: f3af 8000 nop.w
800020a: bd08 pop {r3, pc}
800020c: 00000000 .word 0x00000000
- 8000210: 20000010 .word 0x20000010
- 8000214: 080054d4 .word 0x080054d4
+ 8000210: 2000001c .word 0x2000001c
+ 8000214: 080057c4 .word 0x080057c4
08000218 <__aeabi_uldivmod>:
8000218: b953 cbnz r3, 8000230 <__aeabi_uldivmod+0x18>
@@ -370,10 +370,10 @@ Disassembly of section .text:
8000542: bf00 nop
08000544 :
- {0x61,0x51,0x49,0x45,0x43}, /* 'Z' */
-};
+/* ════════════════════════════════════════════════
+ Low level display helpers
+ ════════════════════════════════════════════════ */
-/* ── Microsecond busy-wait using DWT cycle counter ── */
static void delay_us(uint32_t us)
{
8000544: b480 push {r7}
@@ -410,12 +410,11 @@ static void delay_us(uint32_t us)
800057e: f85d 7b04 ldr.w r7, [sp], #4
8000582: 4770 bx lr
8000584: e0001000 .word 0xe0001000
- 8000588: 20000000 .word 0x20000000
+ 8000588: 2000000c .word 0x2000000c
800058c: 431bde83 .word 0x431bde83
08000590 :
-/* ── Turn all row pins off (HIGH = ULN2803A pulls gate low = MOSFET off) ── */
static void all_rows_off(void)
{
8000590: b580 push {r7, lr}
@@ -436,7 +435,7 @@ static void all_rows_off(void)
80005ac: 889b ldrh r3, [r3, #4]
80005ae: 2201 movs r2, #1
80005b0: 4619 mov r1, r3
- 80005b2: f001 fb5d bl 8001c70
+ 80005b2: f001 fcd5 bl 8001f60
for (int i = 0; i < ROWS; i++)
80005b6: 687b ldr r3, [r7, #4]
80005b8: 3301 adds r3, #1
@@ -450,11 +449,10 @@ static void all_rows_off(void)
80005c6: 3708 adds r7, #8
80005c8: 46bd mov sp, r7
80005ca: bd80 pop {r7, pc}
- 80005cc: 080054ec .word 0x080054ec
+ 80005cc: 08005814 .word 0x08005814
080005d0 :
-/* ── Send one row of column data via SPI then enable that row ── */
static void display_refresh(void)
{
80005d0: b580 push {r7, lr}
@@ -477,8 +475,7 @@ static void display_refresh(void)
80005ee: f04f 33ff mov.w r3, #4294967295
80005f2: 220c movs r2, #12
80005f4: 4810 ldr r0, [pc, #64] @ (8000638 )
- 80005f6: f002 fbd0 bl 8002d9a
- /* LOW = ULN2803A releases gate = MOSFET on = row enabled */
+ 80005f6: f002 fd48 bl 800308a
HAL_GPIO_WritePin(ROW_PINS[row].port, ROW_PINS[row].pin, GPIO_PIN_RESET);
80005fa: 4a10 ldr r2, [pc, #64] @ (800063c )
80005fc: 687b ldr r3, [r7, #4]
@@ -490,7 +487,7 @@ static void display_refresh(void)
800060a: 889b ldrh r3, [r3, #4]
800060c: 2200 movs r2, #0
800060e: 4619 mov r1, r3
- 8000610: f001 fb2e bl 8001c70
+ 8000610: f001 fca6 bl 8001f60
delay_us(ROW_DWELL);
8000614: f44f 70fa mov.w r0, #500 @ 0x1f4
8000618: f7ff ff94 bl 8000544
@@ -509,13113 +506,13575 @@ static void display_refresh(void)
800062e: 3708 adds r7, #8
8000630: 46bd mov sp, r7
8000632: bd80 pop {r7, pc}
- 8000634: 20000120 .word 0x20000120
- 8000638: 20000028 .word 0x20000028
- 800063c: 080054ec .word 0x080054ec
+ 8000634: 2000012c .word 0x2000012c
+ 8000638: 20000034 .word 0x20000034
+ 800063c: 08005814 .word 0x08005814
-08000640 :
+08000640 :
-/* ── Render message string into wide[] pixel buffer ── */
-static void render_message(const char *msg)
-{
- 8000640: b580 push {r7, lr}
- 8000642: b086 sub sp, #24
- 8000644: af00 add r7, sp, #0
- 8000646: 6078 str r0, [r7, #4]
- memset(wide, 0, sizeof(wide));
- 8000648: f44f 6260 mov.w r2, #3584 @ 0xe00
- 800064c: 2100 movs r1, #0
- 800064e: 4833 ldr r0, [pc, #204] @ (800071c )
- 8000650: f004 ff06 bl 8005460
- uint16_t col = COLS; /* lead with one blank screen so text scrolls in */
- 8000654: 2360 movs r3, #96 @ 0x60
- 8000656: 82fb strh r3, [r7, #22]
-
- while (*msg && col < (WIDE_COLS - 6)) {
- 8000658: e04c b.n 80006f4
- uint8_t c = (uint8_t)*msg++;
- 800065a: 687b ldr r3, [r7, #4]
- 800065c: 1c5a adds r2, r3, #1
- 800065e: 607a str r2, [r7, #4]
- 8000660: 781b ldrb r3, [r3, #0]
- 8000662: 757b strb r3, [r7, #21]
- /* Convert lowercase to uppercase */
- if (c >= 'a' && c <= 'z') c -= 32;
- 8000664: 7d7b ldrb r3, [r7, #21]
- 8000666: 2b60 cmp r3, #96 @ 0x60
- 8000668: d905 bls.n 8000676
- 800066a: 7d7b ldrb r3, [r7, #21]
- 800066c: 2b7a cmp r3, #122 @ 0x7a
- 800066e: d802 bhi.n 8000676
- 8000670: 7d7b ldrb r3, [r7, #21]
- 8000672: 3b20 subs r3, #32
- 8000674: 757b strb r3, [r7, #21]
- if (c >= 32 && c <= 90) {
- 8000676: 7d7b ldrb r3, [r7, #21]
- 8000678: 2b1f cmp r3, #31
- 800067a: d938 bls.n 80006ee
- 800067c: 7d7b ldrb r3, [r7, #21]
- 800067e: 2b5a cmp r3, #90 @ 0x5a
- 8000680: d835 bhi.n 80006ee
- const uint8_t *glyph = FONT[c - 32];
- 8000682: 7d7b ldrb r3, [r7, #21]
- 8000684: f1a3 0220 sub.w r2, r3, #32
- 8000688: 4613 mov r3, r2
- 800068a: 009b lsls r3, r3, #2
- 800068c: 4413 add r3, r2
- 800068e: 4a24 ldr r2, [pc, #144] @ (8000720 )
- 8000690: 4413 add r3, r2
- 8000692: 60bb str r3, [r7, #8]
- for (int g = 0; g < 5 && col < WIDE_COLS; g++, col++) {
- 8000694: 2300 movs r3, #0
- 8000696: 613b str r3, [r7, #16]
- 8000698: e022 b.n 80006e0
- for (int row = 0; row < ROWS; row++) {
- 800069a: 2300 movs r3, #0
- 800069c: 60fb str r3, [r7, #12]
- 800069e: e016 b.n 80006ce
- wide[row][col] = (glyph[g] >> row) & 1;
- 80006a0: 693b ldr r3, [r7, #16]
- 80006a2: 68ba ldr r2, [r7, #8]
- 80006a4: 4413 add r3, r2
- 80006a6: 781b ldrb r3, [r3, #0]
- 80006a8: 461a mov r2, r3
- 80006aa: 68fb ldr r3, [r7, #12]
- 80006ac: fa42 f303 asr.w r3, r2, r3
- 80006b0: b2da uxtb r2, r3
- 80006b2: 8afb ldrh r3, [r7, #22]
- 80006b4: f002 0201 and.w r2, r2, #1
- 80006b8: b2d0 uxtb r0, r2
- 80006ba: 4918 ldr r1, [pc, #96] @ (800071c )
- 80006bc: 68fa ldr r2, [r7, #12]
- 80006be: 0252 lsls r2, r2, #9
- 80006c0: 440a add r2, r1
- 80006c2: 4413 add r3, r2
- 80006c4: 4602 mov r2, r0
- 80006c6: 701a strb r2, [r3, #0]
- for (int row = 0; row < ROWS; row++) {
- 80006c8: 68fb ldr r3, [r7, #12]
- 80006ca: 3301 adds r3, #1
- 80006cc: 60fb str r3, [r7, #12]
- 80006ce: 68fb ldr r3, [r7, #12]
- 80006d0: 2b06 cmp r3, #6
- 80006d2: dde5 ble.n 80006a0
- for (int g = 0; g < 5 && col < WIDE_COLS; g++, col++) {
- 80006d4: 693b ldr r3, [r7, #16]
- 80006d6: 3301 adds r3, #1
- 80006d8: 613b str r3, [r7, #16]
- 80006da: 8afb ldrh r3, [r7, #22]
- 80006dc: 3301 adds r3, #1
- 80006de: 82fb strh r3, [r7, #22]
- 80006e0: 693b ldr r3, [r7, #16]
- 80006e2: 2b04 cmp r3, #4
- 80006e4: dc03 bgt.n 80006ee
- 80006e6: 8afb ldrh r3, [r7, #22]
- 80006e8: f5b3 7f00 cmp.w r3, #512 @ 0x200
- 80006ec: d3d5 bcc.n 800069a
- }
- }
- }
- col++; /* one gap column between characters */
- 80006ee: 8afb ldrh r3, [r7, #22]
- 80006f0: 3301 adds r3, #1
- 80006f2: 82fb strh r3, [r7, #22]
- while (*msg && col < (WIDE_COLS - 6)) {
- 80006f4: 687b ldr r3, [r7, #4]
- 80006f6: 781b ldrb r3, [r3, #0]
- 80006f8: 2b00 cmp r3, #0
- 80006fa: d003 beq.n 8000704
- 80006fc: 8afb ldrh r3, [r7, #22]
- 80006fe: f5b3 7ffd cmp.w r3, #506 @ 0x1fa
- 8000702: d3aa bcc.n 800065a
- }
- wide_cols = col + COLS; /* scroll until text fully exits left edge */
- 8000704: 8afb ldrh r3, [r7, #22]
- 8000706: 3360 adds r3, #96 @ 0x60
- 8000708: b29a uxth r2, r3
- 800070a: 4b06 ldr r3, [pc, #24] @ (8000724 )
- 800070c: 801a strh r2, [r3, #0]
- scroll_x = 0;
- 800070e: 4b06 ldr r3, [pc, #24] @ (8000728 )
- 8000710: 2200 movs r2, #0
- 8000712: 601a str r2, [r3, #0]
-}
- 8000714: bf00 nop
- 8000716: 3718 adds r7, #24
- 8000718: 46bd mov sp, r7
- 800071a: bd80 pop {r7, pc}
- 800071c: 20000174 .word 0x20000174
- 8000720: 08005524 .word 0x08005524
- 8000724: 20000f74 .word 0x20000f74
- 8000728: 20000f78 .word 0x20000f78
-
-0800072c :
-
-/* ── Copy current scroll window from wide[] into fb[][] ── */
-static void update_fb_from_scroll(void)
-{
- 800072c: b580 push {r7, lr}
- 800072e: b086 sub sp, #24
- 8000730: af00 add r7, sp, #0
- for (int row = 0; row < ROWS; row++) {
- 8000732: 2300 movs r3, #0
- 8000734: 617b str r3, [r7, #20]
- 8000736: e058 b.n 80007ea
- memset(fb[row], 0, NUM_CHIPS);
- 8000738: 697a ldr r2, [r7, #20]
- 800073a: 4613 mov r3, r2
- 800073c: 005b lsls r3, r3, #1
- 800073e: 4413 add r3, r2
- 8000740: 009b lsls r3, r3, #2
- 8000742: 4a2e ldr r2, [pc, #184] @ (80007fc )
- 8000744: 4413 add r3, r2
- 8000746: 220c movs r2, #12
- 8000748: 2100 movs r1, #0
- 800074a: 4618 mov r0, r3
- 800074c: f004 fe88 bl 8005460
- for (int col = 0; col < COLS; col++) {
- 8000750: 2300 movs r3, #0
- 8000752: 613b str r3, [r7, #16]
- 8000754: e043 b.n 80007de
- uint16_t src = (uint16_t)(scroll_x + col);
- 8000756: 4b2a ldr r3, [pc, #168] @ (8000800 )
- 8000758: 681b ldr r3, [r3, #0]
- 800075a: b29a uxth r2, r3
- 800075c: 693b ldr r3, [r7, #16]
- 800075e: b29b uxth r3, r3
- 8000760: 4413 add r3, r2
- 8000762: 81fb strh r3, [r7, #14]
- if (src < WIDE_COLS && wide[row][src]) {
- 8000764: 89fb ldrh r3, [r7, #14]
- 8000766: f5b3 7f00 cmp.w r3, #512 @ 0x200
- 800076a: d235 bcs.n 80007d8
- 800076c: 89fb ldrh r3, [r7, #14]
- 800076e: 4925 ldr r1, [pc, #148] @ (8000804 )
- 8000770: 697a ldr r2, [r7, #20]
- 8000772: 0252 lsls r2, r2, #9
- 8000774: 440a add r2, r1
- 8000776: 4413 add r3, r2
- 8000778: 781b ldrb r3, [r3, #0]
- 800077a: 2b00 cmp r3, #0
- 800077c: d02c beq.n 80007d8
- int chip = col / 8;
- 800077e: 693b ldr r3, [r7, #16]
- 8000780: 2b00 cmp r3, #0
- 8000782: da00 bge.n 8000786
- 8000784: 3307 adds r3, #7
- 8000786: 10db asrs r3, r3, #3
- 8000788: 60bb str r3, [r7, #8]
- int bit = 7 - (col % 8);
- 800078a: 693b ldr r3, [r7, #16]
- 800078c: 425a negs r2, r3
- 800078e: f003 0307 and.w r3, r3, #7
- 8000792: f002 0207 and.w r2, r2, #7
- 8000796: bf58 it pl
- 8000798: 4253 negpl r3, r2
- 800079a: f1c3 0307 rsb r3, r3, #7
- 800079e: 607b str r3, [r7, #4]
- fb[row][chip] |= (uint8_t)(1 << bit);
- 80007a0: 4916 ldr r1, [pc, #88] @ (80007fc )
- 80007a2: 697a ldr r2, [r7, #20]
- 80007a4: 4613 mov r3, r2
- 80007a6: 005b lsls r3, r3, #1
- 80007a8: 4413 add r3, r2
- 80007aa: 009b lsls r3, r3, #2
- 80007ac: 18ca adds r2, r1, r3
- 80007ae: 68bb ldr r3, [r7, #8]
- 80007b0: 4413 add r3, r2
- 80007b2: 781a ldrb r2, [r3, #0]
- 80007b4: 2101 movs r1, #1
- 80007b6: 687b ldr r3, [r7, #4]
- 80007b8: fa01 f303 lsl.w r3, r1, r3
- 80007bc: b2db uxtb r3, r3
- 80007be: 4313 orrs r3, r2
- 80007c0: b2d8 uxtb r0, r3
- 80007c2: 490e ldr r1, [pc, #56] @ (80007fc )
- 80007c4: 697a ldr r2, [r7, #20]
- 80007c6: 4613 mov r3, r2
- 80007c8: 005b lsls r3, r3, #1
- 80007ca: 4413 add r3, r2
- 80007cc: 009b lsls r3, r3, #2
- 80007ce: 18ca adds r2, r1, r3
- 80007d0: 68bb ldr r3, [r7, #8]
- 80007d2: 4413 add r3, r2
- 80007d4: 4602 mov r2, r0
- 80007d6: 701a strb r2, [r3, #0]
- for (int col = 0; col < COLS; col++) {
- 80007d8: 693b ldr r3, [r7, #16]
- 80007da: 3301 adds r3, #1
- 80007dc: 613b str r3, [r7, #16]
- 80007de: 693b ldr r3, [r7, #16]
- 80007e0: 2b5f cmp r3, #95 @ 0x5f
- 80007e2: ddb8 ble.n 8000756
- for (int row = 0; row < ROWS; row++) {
- 80007e4: 697b ldr r3, [r7, #20]
- 80007e6: 3301 adds r3, #1
- 80007e8: 617b str r3, [r7, #20]
- 80007ea: 697b ldr r3, [r7, #20]
- 80007ec: 2b06 cmp r3, #6
- 80007ee: dda3 ble.n 8000738
- }
- }
- }
-}
- 80007f0: bf00 nop
- 80007f2: bf00 nop
- 80007f4: 3718 adds r7, #24
- 80007f6: 46bd mov sp, r7
- 80007f8: bd80 pop {r7, pc}
- 80007fa: bf00 nop
- 80007fc: 20000120 .word 0x20000120
- 8000800: 20000f78 .word 0x20000f78
- 8000804: 20000174 .word 0x20000174
-
-08000808 :
-};
-
-/* ── Render logo into fb
- mask_col: columns < mask_col are hidden (wipe reveals right-to-left), -1 = show all ── */
-static void render_logo(int star_col, int text_col, int mask_col)
-{
- 8000808: b580 push {r7, lr}
- 800080a: b08e sub sp, #56 @ 0x38
- 800080c: af00 add r7, sp, #0
- 800080e: 60f8 str r0, [r7, #12]
- 8000810: 60b9 str r1, [r7, #8]
- 8000812: 607a str r2, [r7, #4]
- memset(fb, 0, sizeof(fb));
- 8000814: 2254 movs r2, #84 @ 0x54
- 8000816: 2100 movs r1, #0
- 8000818: 4860 ldr r0, [pc, #384] @ (800099c )
- 800081a: f004 fe21 bl 8005460
-
- /* Draw star */
- for (int row = 0; row < 7; row++) {
- 800081e: 2300 movs r3, #0
- 8000820: 637b str r3, [r7, #52] @ 0x34
- 8000822: e056 b.n 80008d2
- for (int sc = 0; sc < 11; sc++) {
- 8000824: 2300 movs r3, #0
- 8000826: 633b str r3, [r7, #48] @ 0x30
- 8000828: e04d b.n 80008c6
- int col = star_col + sc;
- 800082a: 68fa ldr r2, [r7, #12]
- 800082c: 6b3b ldr r3, [r7, #48] @ 0x30
- 800082e: 4413 add r3, r2
- 8000830: 61bb str r3, [r7, #24]
- if (col >= 0 && col < COLS && STAR[row][sc]) {
- 8000832: 69bb ldr r3, [r7, #24]
- 8000834: 2b00 cmp r3, #0
- 8000836: db43 blt.n 80008c0
- 8000838: 69bb ldr r3, [r7, #24]
- 800083a: 2b5f cmp r3, #95 @ 0x5f
- 800083c: dc40 bgt.n 80008c0
- 800083e: 4958 ldr r1, [pc, #352] @ (80009a0 )
- 8000840: 6b7a ldr r2, [r7, #52] @ 0x34
- 8000842: 4613 mov r3, r2
- 8000844: 009b lsls r3, r3, #2
- 8000846: 4413 add r3, r2
- 8000848: 005b lsls r3, r3, #1
- 800084a: 4413 add r3, r2
- 800084c: 18ca adds r2, r1, r3
- 800084e: 6b3b ldr r3, [r7, #48] @ 0x30
- 8000850: 4413 add r3, r2
- 8000852: 781b ldrb r3, [r3, #0]
- 8000854: 2b00 cmp r3, #0
- 8000856: d033 beq.n 80008c0
- if (mask_col < 0 || col >= mask_col) {
- 8000858: 687b ldr r3, [r7, #4]
- 800085a: 2b00 cmp r3, #0
- 800085c: db03 blt.n 8000866
- 800085e: 69ba ldr r2, [r7, #24]
- 8000860: 687b ldr r3, [r7, #4]
- 8000862: 429a cmp r2, r3
- 8000864: db2c blt.n 80008c0
- int chip = col / 8;
- 8000866: 69bb ldr r3, [r7, #24]
- 8000868: 2b00 cmp r3, #0
- 800086a: da00 bge.n 800086e
- 800086c: 3307 adds r3, #7
- 800086e: 10db asrs r3, r3, #3
- 8000870: 617b str r3, [r7, #20]
- int bit = 7 - (col % 8);
- 8000872: 69bb ldr r3, [r7, #24]
- 8000874: 425a negs r2, r3
- 8000876: f003 0307 and.w r3, r3, #7
- 800087a: f002 0207 and.w r2, r2, #7
- 800087e: bf58 it pl
- 8000880: 4253 negpl r3, r2
- 8000882: f1c3 0307 rsb r3, r3, #7
- 8000886: 613b str r3, [r7, #16]
- fb[row][chip] |= (uint8_t)(1 << bit);
- 8000888: 4944 ldr r1, [pc, #272] @ (800099c )
- 800088a: 6b7a ldr r2, [r7, #52] @ 0x34
- 800088c: 4613 mov r3, r2
- 800088e: 005b lsls r3, r3, #1
- 8000890: 4413 add r3, r2
- 8000892: 009b lsls r3, r3, #2
- 8000894: 18ca adds r2, r1, r3
- 8000896: 697b ldr r3, [r7, #20]
- 8000898: 4413 add r3, r2
- 800089a: 781a ldrb r2, [r3, #0]
- 800089c: 2101 movs r1, #1
- 800089e: 693b ldr r3, [r7, #16]
- 80008a0: fa01 f303 lsl.w r3, r1, r3
- 80008a4: b2db uxtb r3, r3
- 80008a6: 4313 orrs r3, r2
- 80008a8: b2d8 uxtb r0, r3
- 80008aa: 493c ldr r1, [pc, #240] @ (800099c )
- 80008ac: 6b7a ldr r2, [r7, #52] @ 0x34
- 80008ae: 4613 mov r3, r2
- 80008b0: 005b lsls r3, r3, #1
- 80008b2: 4413 add r3, r2
- 80008b4: 009b lsls r3, r3, #2
- 80008b6: 18ca adds r2, r1, r3
- 80008b8: 697b ldr r3, [r7, #20]
- 80008ba: 4413 add r3, r2
- 80008bc: 4602 mov r2, r0
- 80008be: 701a strb r2, [r3, #0]
- for (int sc = 0; sc < 11; sc++) {
- 80008c0: 6b3b ldr r3, [r7, #48] @ 0x30
- 80008c2: 3301 adds r3, #1
- 80008c4: 633b str r3, [r7, #48] @ 0x30
- 80008c6: 6b3b ldr r3, [r7, #48] @ 0x30
- 80008c8: 2b0a cmp r3, #10
- 80008ca: ddae ble.n 800082a
- for (int row = 0; row < 7; row++) {
- 80008cc: 6b7b ldr r3, [r7, #52] @ 0x34
- 80008ce: 3301 adds r3, #1
- 80008d0: 637b str r3, [r7, #52] @ 0x34
- 80008d2: 6b7b ldr r3, [r7, #52] @ 0x34
- 80008d4: 2b06 cmp r3, #6
- 80008d6: dda5 ble.n 8000824
- }
- }
- }
-
- /* Draw ARRIVE text */
- for (int row = 0; row < 7; row++) {
- 80008d8: 2300 movs r3, #0
- 80008da: 62fb str r3, [r7, #44] @ 0x2c
- 80008dc: e055 b.n 800098a
- for (int tc = 0; tc < 36; tc++) {
- 80008de: 2300 movs r3, #0
- 80008e0: 62bb str r3, [r7, #40] @ 0x28
- 80008e2: e04c b.n 800097e
- int col = text_col + tc;
- 80008e4: 68ba ldr r2, [r7, #8]
- 80008e6: 6abb ldr r3, [r7, #40] @ 0x28
- 80008e8: 4413 add r3, r2
- 80008ea: 627b str r3, [r7, #36] @ 0x24
- if (col >= 0 && col < COLS && ARRIVE_GLYPH[row][tc]) {
- 80008ec: 6a7b ldr r3, [r7, #36] @ 0x24
- 80008ee: 2b00 cmp r3, #0
- 80008f0: db42 blt.n 8000978
- 80008f2: 6a7b ldr r3, [r7, #36] @ 0x24
- 80008f4: 2b5f cmp r3, #95 @ 0x5f
- 80008f6: dc3f bgt.n 8000978
- 80008f8: 492a ldr r1, [pc, #168] @ (80009a4 )
- 80008fa: 6afa ldr r2, [r7, #44] @ 0x2c
- 80008fc: 4613 mov r3, r2
- 80008fe: 00db lsls r3, r3, #3
- 8000900: 4413 add r3, r2
- 8000902: 009b lsls r3, r3, #2
- 8000904: 18ca adds r2, r1, r3
- 8000906: 6abb ldr r3, [r7, #40] @ 0x28
- 8000908: 4413 add r3, r2
- 800090a: 781b ldrb r3, [r3, #0]
- 800090c: 2b00 cmp r3, #0
- 800090e: d033 beq.n 8000978
- if (mask_col < 0 || col >= mask_col) {
- 8000910: 687b ldr r3, [r7, #4]
- 8000912: 2b00 cmp r3, #0
- 8000914: db03 blt.n 800091e
- 8000916: 6a7a ldr r2, [r7, #36] @ 0x24
- 8000918: 687b ldr r3, [r7, #4]
- 800091a: 429a cmp r2, r3
- 800091c: db2c blt.n 8000978
- int chip = col / 8;
- 800091e: 6a7b ldr r3, [r7, #36] @ 0x24
- 8000920: 2b00 cmp r3, #0
- 8000922: da00 bge.n 8000926
- 8000924: 3307 adds r3, #7
- 8000926: 10db asrs r3, r3, #3
- 8000928: 623b str r3, [r7, #32]
- int bit = 7 - (col % 8);
- 800092a: 6a7b ldr r3, [r7, #36] @ 0x24
- 800092c: 425a negs r2, r3
- 800092e: f003 0307 and.w r3, r3, #7
- 8000932: f002 0207 and.w r2, r2, #7
- 8000936: bf58 it pl
- 8000938: 4253 negpl r3, r2
- 800093a: f1c3 0307 rsb r3, r3, #7
- 800093e: 61fb str r3, [r7, #28]
- fb[row][chip] |= (uint8_t)(1 << bit);
- 8000940: 4916 ldr r1, [pc, #88] @ (800099c )
- 8000942: 6afa ldr r2, [r7, #44] @ 0x2c
- 8000944: 4613 mov r3, r2
- 8000946: 005b lsls r3, r3, #1
- 8000948: 4413 add r3, r2
- 800094a: 009b lsls r3, r3, #2
- 800094c: 18ca adds r2, r1, r3
- 800094e: 6a3b ldr r3, [r7, #32]
- 8000950: 4413 add r3, r2
- 8000952: 781a ldrb r2, [r3, #0]
- 8000954: 2101 movs r1, #1
- 8000956: 69fb ldr r3, [r7, #28]
- 8000958: fa01 f303 lsl.w r3, r1, r3
- 800095c: b2db uxtb r3, r3
- 800095e: 4313 orrs r3, r2
- 8000960: b2d8 uxtb r0, r3
- 8000962: 490e ldr r1, [pc, #56] @ (800099c )
- 8000964: 6afa ldr r2, [r7, #44] @ 0x2c
- 8000966: 4613 mov r3, r2
- 8000968: 005b lsls r3, r3, #1
- 800096a: 4413 add r3, r2
- 800096c: 009b lsls r3, r3, #2
- 800096e: 18ca adds r2, r1, r3
- 8000970: 6a3b ldr r3, [r7, #32]
- 8000972: 4413 add r3, r2
- 8000974: 4602 mov r2, r0
- 8000976: 701a strb r2, [r3, #0]
- for (int tc = 0; tc < 36; tc++) {
- 8000978: 6abb ldr r3, [r7, #40] @ 0x28
- 800097a: 3301 adds r3, #1
- 800097c: 62bb str r3, [r7, #40] @ 0x28
- 800097e: 6abb ldr r3, [r7, #40] @ 0x28
- 8000980: 2b23 cmp r3, #35 @ 0x23
- 8000982: ddaf ble.n 80008e4
- for (int row = 0; row < 7; row++) {
- 8000984: 6afb ldr r3, [r7, #44] @ 0x2c
- 8000986: 3301 adds r3, #1
- 8000988: 62fb str r3, [r7, #44] @ 0x2c
- 800098a: 6afb ldr r3, [r7, #44] @ 0x2c
- 800098c: 2b06 cmp r3, #6
- 800098e: dda6 ble.n 80008de
- }
- }
- }
- }
-}
- 8000990: bf00 nop
- 8000992: bf00 nop
- 8000994: 3738 adds r7, #56 @ 0x38
- 8000996: 46bd mov sp, r7
- 8000998: bd80 pop {r7, pc}
- 800099a: bf00 nop
- 800099c: 20000120 .word 0x20000120
- 80009a0: 0800564c .word 0x0800564c
- 80009a4: 0800569c .word 0x0800569c
-
-080009a8 :
-
-/* ── Blank fb but keep specific rows lit (bitmask) ── */
-static void render_logo_rows(int star_col, int text_col, uint8_t row_mask)
-{
- 80009a8: b580 push {r7, lr}
- 80009aa: b08e sub sp, #56 @ 0x38
- 80009ac: af00 add r7, sp, #0
- 80009ae: 60f8 str r0, [r7, #12]
- 80009b0: 60b9 str r1, [r7, #8]
- 80009b2: 4613 mov r3, r2
- 80009b4: 71fb strb r3, [r7, #7]
- memset(fb, 0, sizeof(fb));
- 80009b6: 2254 movs r2, #84 @ 0x54
- 80009b8: 2100 movs r1, #0
- 80009ba: 485b ldr r0, [pc, #364] @ (8000b28 )
- 80009bc: f004 fd50 bl 8005460
- for (int row = 0; row < 7; row++) {
- 80009c0: 2300 movs r3, #0
- 80009c2: 637b str r3, [r7, #52] @ 0x34
- 80009c4: e0a6 b.n 8000b14
- if (!(row_mask & (1 << row))) continue;
- 80009c6: 79fa ldrb r2, [r7, #7]
- 80009c8: 6b7b ldr r3, [r7, #52] @ 0x34
- 80009ca: fa42 f303 asr.w r3, r2, r3
- 80009ce: f003 0301 and.w r3, r3, #1
- 80009d2: 2b00 cmp r3, #0
- 80009d4: f000 809a beq.w 8000b0c
- for (int sc = 0; sc < 11; sc++) {
- 80009d8: 2300 movs r3, #0
- 80009da: 633b str r3, [r7, #48] @ 0x30
- 80009dc: e046 b.n 8000a6c
- int col = star_col + sc;
- 80009de: 68fa ldr r2, [r7, #12]
- 80009e0: 6b3b ldr r3, [r7, #48] @ 0x30
- 80009e2: 4413 add r3, r2
- 80009e4: 61fb str r3, [r7, #28]
- if (col >= 0 && col < COLS && STAR[row][sc]) {
- 80009e6: 69fb ldr r3, [r7, #28]
- 80009e8: 2b00 cmp r3, #0
- 80009ea: db3c blt.n 8000a66
- 80009ec: 69fb ldr r3, [r7, #28]
- 80009ee: 2b5f cmp r3, #95 @ 0x5f
- 80009f0: dc39 bgt.n 8000a66
- 80009f2: 494e ldr r1, [pc, #312] @ (8000b2c )
- 80009f4: 6b7a ldr r2, [r7, #52] @ 0x34
- 80009f6: 4613 mov r3, r2
- 80009f8: 009b lsls r3, r3, #2
- 80009fa: 4413 add r3, r2
- 80009fc: 005b lsls r3, r3, #1
- 80009fe: 4413 add r3, r2
- 8000a00: 18ca adds r2, r1, r3
- 8000a02: 6b3b ldr r3, [r7, #48] @ 0x30
- 8000a04: 4413 add r3, r2
- 8000a06: 781b ldrb r3, [r3, #0]
- 8000a08: 2b00 cmp r3, #0
- 8000a0a: d02c beq.n 8000a66
- int chip = col / 8; int bit = 7 - (col % 8);
- 8000a0c: 69fb ldr r3, [r7, #28]
- 8000a0e: 2b00 cmp r3, #0
- 8000a10: da00 bge.n 8000a14
- 8000a12: 3307 adds r3, #7
- 8000a14: 10db asrs r3, r3, #3
- 8000a16: 61bb str r3, [r7, #24]
- 8000a18: 69fb ldr r3, [r7, #28]
- 8000a1a: 425a negs r2, r3
- 8000a1c: f003 0307 and.w r3, r3, #7
- 8000a20: f002 0207 and.w r2, r2, #7
- 8000a24: bf58 it pl
- 8000a26: 4253 negpl r3, r2
- 8000a28: f1c3 0307 rsb r3, r3, #7
- 8000a2c: 617b str r3, [r7, #20]
- fb[row][chip] |= (uint8_t)(1 << bit);
- 8000a2e: 493e ldr r1, [pc, #248] @ (8000b28 )
- 8000a30: 6b7a ldr r2, [r7, #52] @ 0x34
- 8000a32: 4613 mov r3, r2
- 8000a34: 005b lsls r3, r3, #1
- 8000a36: 4413 add r3, r2
- 8000a38: 009b lsls r3, r3, #2
- 8000a3a: 18ca adds r2, r1, r3
- 8000a3c: 69bb ldr r3, [r7, #24]
- 8000a3e: 4413 add r3, r2
- 8000a40: 781a ldrb r2, [r3, #0]
- 8000a42: 2101 movs r1, #1
- 8000a44: 697b ldr r3, [r7, #20]
- 8000a46: fa01 f303 lsl.w r3, r1, r3
- 8000a4a: b2db uxtb r3, r3
- 8000a4c: 4313 orrs r3, r2
- 8000a4e: b2d8 uxtb r0, r3
- 8000a50: 4935 ldr r1, [pc, #212] @ (8000b28 )
- 8000a52: 6b7a ldr r2, [r7, #52] @ 0x34
- 8000a54: 4613 mov r3, r2
- 8000a56: 005b lsls r3, r3, #1
- 8000a58: 4413 add r3, r2
- 8000a5a: 009b lsls r3, r3, #2
- 8000a5c: 18ca adds r2, r1, r3
- 8000a5e: 69bb ldr r3, [r7, #24]
- 8000a60: 4413 add r3, r2
- 8000a62: 4602 mov r2, r0
- 8000a64: 701a strb r2, [r3, #0]
- for (int sc = 0; sc < 11; sc++) {
- 8000a66: 6b3b ldr r3, [r7, #48] @ 0x30
- 8000a68: 3301 adds r3, #1
- 8000a6a: 633b str r3, [r7, #48] @ 0x30
- 8000a6c: 6b3b ldr r3, [r7, #48] @ 0x30
- 8000a6e: 2b0a cmp r3, #10
- 8000a70: ddb5 ble.n 80009de
- }
- }
- for (int tc = 0; tc < 30; tc++) {
- 8000a72: 2300 movs r3, #0
- 8000a74: 62fb str r3, [r7, #44] @ 0x2c
- 8000a76: e045 b.n 8000b04
- int col = text_col + tc;
- 8000a78: 68ba ldr r2, [r7, #8]
- 8000a7a: 6afb ldr r3, [r7, #44] @ 0x2c
- 8000a7c: 4413 add r3, r2
- 8000a7e: 62bb str r3, [r7, #40] @ 0x28
- if (col >= 0 && col < COLS && ARRIVE_GLYPH[row][tc]) {
- 8000a80: 6abb ldr r3, [r7, #40] @ 0x28
- 8000a82: 2b00 cmp r3, #0
- 8000a84: db3b blt.n 8000afe
- 8000a86: 6abb ldr r3, [r7, #40] @ 0x28
- 8000a88: 2b5f cmp r3, #95 @ 0x5f
- 8000a8a: dc38 bgt.n 8000afe
- 8000a8c: 4928 ldr r1, [pc, #160] @ (8000b30 )
- 8000a8e: 6b7a ldr r2, [r7, #52] @ 0x34
- 8000a90: 4613 mov r3, r2
- 8000a92: 00db lsls r3, r3, #3
- 8000a94: 4413 add r3, r2
- 8000a96: 009b lsls r3, r3, #2
- 8000a98: 18ca adds r2, r1, r3
- 8000a9a: 6afb ldr r3, [r7, #44] @ 0x2c
- 8000a9c: 4413 add r3, r2
- 8000a9e: 781b ldrb r3, [r3, #0]
- 8000aa0: 2b00 cmp r3, #0
- 8000aa2: d02c beq.n 8000afe
- int chip = col / 8; int bit = 7 - (col % 8);
- 8000aa4: 6abb ldr r3, [r7, #40] @ 0x28
- 8000aa6: 2b00 cmp r3, #0
- 8000aa8: da00 bge.n 8000aac
- 8000aaa: 3307 adds r3, #7
- 8000aac: 10db asrs r3, r3, #3
- 8000aae: 627b str r3, [r7, #36] @ 0x24
- 8000ab0: 6abb ldr r3, [r7, #40] @ 0x28
- 8000ab2: 425a negs r2, r3
- 8000ab4: f003 0307 and.w r3, r3, #7
- 8000ab8: f002 0207 and.w r2, r2, #7
- 8000abc: bf58 it pl
- 8000abe: 4253 negpl r3, r2
- 8000ac0: f1c3 0307 rsb r3, r3, #7
- 8000ac4: 623b str r3, [r7, #32]
- fb[row][chip] |= (uint8_t)(1 << bit);
- 8000ac6: 4918 ldr r1, [pc, #96] @ (8000b28 )
- 8000ac8: 6b7a ldr r2, [r7, #52] @ 0x34
- 8000aca: 4613 mov r3, r2
- 8000acc: 005b lsls r3, r3, #1
- 8000ace: 4413 add r3, r2
- 8000ad0: 009b lsls r3, r3, #2
- 8000ad2: 18ca adds r2, r1, r3
- 8000ad4: 6a7b ldr r3, [r7, #36] @ 0x24
- 8000ad6: 4413 add r3, r2
- 8000ad8: 781a ldrb r2, [r3, #0]
- 8000ada: 2101 movs r1, #1
- 8000adc: 6a3b ldr r3, [r7, #32]
- 8000ade: fa01 f303 lsl.w r3, r1, r3
- 8000ae2: b2db uxtb r3, r3
- 8000ae4: 4313 orrs r3, r2
- 8000ae6: b2d8 uxtb r0, r3
- 8000ae8: 490f ldr r1, [pc, #60] @ (8000b28 )
- 8000aea: 6b7a ldr r2, [r7, #52] @ 0x34
- 8000aec: 4613 mov r3, r2
- 8000aee: 005b lsls r3, r3, #1
- 8000af0: 4413 add r3, r2
- 8000af2: 009b lsls r3, r3, #2
- 8000af4: 18ca adds r2, r1, r3
- 8000af6: 6a7b ldr r3, [r7, #36] @ 0x24
- 8000af8: 4413 add r3, r2
- 8000afa: 4602 mov r2, r0
- 8000afc: 701a strb r2, [r3, #0]
- for (int tc = 0; tc < 30; tc++) {
- 8000afe: 6afb ldr r3, [r7, #44] @ 0x2c
- 8000b00: 3301 adds r3, #1
- 8000b02: 62fb str r3, [r7, #44] @ 0x2c
- 8000b04: 6afb ldr r3, [r7, #44] @ 0x2c
- 8000b06: 2b1d cmp r3, #29
- 8000b08: ddb6 ble.n 8000a78
- 8000b0a: e000 b.n 8000b0e
- if (!(row_mask & (1 << row))) continue;
- 8000b0c: bf00 nop
- for (int row = 0; row < 7; row++) {
- 8000b0e: 6b7b ldr r3, [r7, #52] @ 0x34
- 8000b10: 3301 adds r3, #1
- 8000b12: 637b str r3, [r7, #52] @ 0x34
- 8000b14: 6b7b ldr r3, [r7, #52] @ 0x34
- 8000b16: 2b06 cmp r3, #6
- 8000b18: f77f af55 ble.w 80009c6
- }
- }
- }
-}
- 8000b1c: bf00 nop
- 8000b1e: bf00 nop
- 8000b20: 3738 adds r7, #56 @ 0x38
- 8000b22: 46bd mov sp, r7
- 8000b24: bd80 pop {r7, pc}
- 8000b26: bf00 nop
- 8000b28: 20000120 .word 0x20000120
- 8000b2c: 0800564c .word 0x0800564c
- 8000b30: 0800569c .word 0x0800569c
-
-08000b34 :
-
-/* ── Refresh for a given number of milliseconds ── */
static void refresh_for(uint32_t ms)
{
- 8000b34: b580 push {r7, lr}
- 8000b36: b084 sub sp, #16
- 8000b38: af00 add r7, sp, #0
- 8000b3a: 6078 str r0, [r7, #4]
+ 8000640: b580 push {r7, lr}
+ 8000642: b084 sub sp, #16
+ 8000644: af00 add r7, sp, #0
+ 8000646: 6078 str r0, [r7, #4]
uint32_t t = HAL_GetTick();
- 8000b3c: f000 fd2c bl 8001598
- 8000b40: 60f8 str r0, [r7, #12]
+ 8000648: f001 f91e bl 8001888
+ 800064c: 60f8 str r0, [r7, #12]
while ((HAL_GetTick() - t) < ms) { display_refresh(); }
- 8000b42: e001 b.n 8000b48
- 8000b44: f7ff fd44 bl 80005d0
- 8000b48: f000 fd26 bl 8001598
- 8000b4c: 4602 mov r2, r0
- 8000b4e: 68fb ldr r3, [r7, #12]
- 8000b50: 1ad3 subs r3, r2, r3
- 8000b52: 687a ldr r2, [r7, #4]
- 8000b54: 429a cmp r2, r3
- 8000b56: d8f5 bhi.n 8000b44
+ 800064e: e001 b.n 8000654
+ 8000650: f7ff ffbe bl 80005d0
+ 8000654: f001 f918 bl 8001888
+ 8000658: 4602 mov r2, r0
+ 800065a: 68fb ldr r3, [r7, #12]
+ 800065c: 1ad3 subs r3, r2, r3
+ 800065e: 687a ldr r2, [r7, #4]
+ 8000660: 429a cmp r2, r3
+ 8000662: d8f5 bhi.n 8000650
}
- 8000b58: bf00 nop
- 8000b5a: bf00 nop
- 8000b5c: 3710 adds r7, #16
- 8000b5e: 46bd mov sp, r7
- 8000b60: bd80 pop {r7, pc}
+ 8000664: bf00 nop
+ 8000666: bf00 nop
+ 8000668: 3710 adds r7, #16
+ 800066a: 46bd mov sp, r7
+ 800066c: bd80 pop {r7, pc}
...
-08000b64 :
+08000670 :
+
+/* ── Check if a new command arrived — call from long-running loops ── */
+static uint8_t check_new_cmd(void)
+{
+ 8000670: b480 push {r7}
+ 8000672: af00 add r7, sp, #0
+ return pending_cmd_rdy;
+ 8000674: 4b03 ldr r3, [pc, #12] @ (8000684 )
+ 8000676: 781b ldrb r3, [r3, #0]
+ 8000678: b2db uxtb r3, r3
+}
+ 800067a: 4618 mov r0, r3
+ 800067c: 46bd mov sp, r7
+ 800067e: f85d 7b04 ldr.w r7, [sp], #4
+ 8000682: 4770 bx lr
+ 8000684: 20001013 .word 0x20001013
+
+08000688 :
+/* ════════════════════════════════════════════════
+ Framebuffer helpers
+ ════════════════════════════════════════════════ */
+
+static void fb_set_pixel(int col, int row, uint8_t on)
+{
+ 8000688: b480 push {r7}
+ 800068a: b087 sub sp, #28
+ 800068c: af00 add r7, sp, #0
+ 800068e: 60f8 str r0, [r7, #12]
+ 8000690: 60b9 str r1, [r7, #8]
+ 8000692: 4613 mov r3, r2
+ 8000694: 71fb strb r3, [r7, #7]
+ if (col < 0 || col >= COLS || row < 0 || row >= ROWS) return;
+ 8000696: 68fb ldr r3, [r7, #12]
+ 8000698: 2b00 cmp r3, #0
+ 800069a: db5a blt.n 8000752
+ 800069c: 68fb ldr r3, [r7, #12]
+ 800069e: 2b5f cmp r3, #95 @ 0x5f
+ 80006a0: dc57 bgt.n 8000752
+ 80006a2: 68bb ldr r3, [r7, #8]
+ 80006a4: 2b00 cmp r3, #0
+ 80006a6: db54 blt.n 8000752
+ 80006a8: 68bb ldr r3, [r7, #8]
+ 80006aa: 2b06 cmp r3, #6
+ 80006ac: dc51 bgt.n 8000752
+ int chip = col / 8;
+ 80006ae: 68fb ldr r3, [r7, #12]
+ 80006b0: 2b00 cmp r3, #0
+ 80006b2: da00 bge.n 80006b6
+ 80006b4: 3307 adds r3, #7
+ 80006b6: 10db asrs r3, r3, #3
+ 80006b8: 617b str r3, [r7, #20]
+ int bit = 7 - (col % 8);
+ 80006ba: 68fb ldr r3, [r7, #12]
+ 80006bc: 425a negs r2, r3
+ 80006be: f003 0307 and.w r3, r3, #7
+ 80006c2: f002 0207 and.w r2, r2, #7
+ 80006c6: bf58 it pl
+ 80006c8: 4253 negpl r3, r2
+ 80006ca: f1c3 0307 rsb r3, r3, #7
+ 80006ce: 613b str r3, [r7, #16]
+ if (on) fb[row][chip] |= (uint8_t)(1 << bit);
+ 80006d0: 79fb ldrb r3, [r7, #7]
+ 80006d2: 2b00 cmp r3, #0
+ 80006d4: d01c beq.n 8000710
+ 80006d6: 4922 ldr r1, [pc, #136] @ (8000760 )
+ 80006d8: 68ba ldr r2, [r7, #8]
+ 80006da: 4613 mov r3, r2
+ 80006dc: 005b lsls r3, r3, #1
+ 80006de: 4413 add r3, r2
+ 80006e0: 009b lsls r3, r3, #2
+ 80006e2: 18ca adds r2, r1, r3
+ 80006e4: 697b ldr r3, [r7, #20]
+ 80006e6: 4413 add r3, r2
+ 80006e8: 781a ldrb r2, [r3, #0]
+ 80006ea: 2101 movs r1, #1
+ 80006ec: 693b ldr r3, [r7, #16]
+ 80006ee: fa01 f303 lsl.w r3, r1, r3
+ 80006f2: b2db uxtb r3, r3
+ 80006f4: 4313 orrs r3, r2
+ 80006f6: b2d8 uxtb r0, r3
+ 80006f8: 4919 ldr r1, [pc, #100] @ (8000760 )
+ 80006fa: 68ba ldr r2, [r7, #8]
+ 80006fc: 4613 mov r3, r2
+ 80006fe: 005b lsls r3, r3, #1
+ 8000700: 4413 add r3, r2
+ 8000702: 009b lsls r3, r3, #2
+ 8000704: 18ca adds r2, r1, r3
+ 8000706: 697b ldr r3, [r7, #20]
+ 8000708: 4413 add r3, r2
+ 800070a: 4602 mov r2, r0
+ 800070c: 701a strb r2, [r3, #0]
+ 800070e: e021 b.n 8000754
+ else fb[row][chip] &= ~(uint8_t)(1 << bit);
+ 8000710: 4913 ldr r1, [pc, #76] @ (8000760 )
+ 8000712: 68ba ldr r2, [r7, #8]
+ 8000714: 4613 mov r3, r2
+ 8000716: 005b lsls r3, r3, #1
+ 8000718: 4413 add r3, r2
+ 800071a: 009b lsls r3, r3, #2
+ 800071c: 18ca adds r2, r1, r3
+ 800071e: 697b ldr r3, [r7, #20]
+ 8000720: 4413 add r3, r2
+ 8000722: 781b ldrb r3, [r3, #0]
+ 8000724: b25a sxtb r2, r3
+ 8000726: 2101 movs r1, #1
+ 8000728: 693b ldr r3, [r7, #16]
+ 800072a: fa01 f303 lsl.w r3, r1, r3
+ 800072e: b25b sxtb r3, r3
+ 8000730: 43db mvns r3, r3
+ 8000732: b25b sxtb r3, r3
+ 8000734: 4013 ands r3, r2
+ 8000736: b25b sxtb r3, r3
+ 8000738: b2d8 uxtb r0, r3
+ 800073a: 4909 ldr r1, [pc, #36] @ (8000760 )
+ 800073c: 68ba ldr r2, [r7, #8]
+ 800073e: 4613 mov r3, r2
+ 8000740: 005b lsls r3, r3, #1
+ 8000742: 4413 add r3, r2
+ 8000744: 009b lsls r3, r3, #2
+ 8000746: 18ca adds r2, r1, r3
+ 8000748: 697b ldr r3, [r7, #20]
+ 800074a: 4413 add r3, r2
+ 800074c: 4602 mov r2, r0
+ 800074e: 701a strb r2, [r3, #0]
+ 8000750: e000 b.n 8000754
+ if (col < 0 || col >= COLS || row < 0 || row >= ROWS) return;
+ 8000752: bf00 nop
+}
+ 8000754: 371c adds r7, #28
+ 8000756: 46bd mov sp, r7
+ 8000758: f85d 7b04 ldr.w r7, [sp], #4
+ 800075c: 4770 bx lr
+ 800075e: bf00 nop
+ 8000760: 2000012c .word 0x2000012c
+
+08000764 :
+
+static void render_logo(int star_col, int text_col, int mask_col)
+{
+ 8000764: b580 push {r7, lr}
+ 8000766: b08a sub sp, #40 @ 0x28
+ 8000768: af00 add r7, sp, #0
+ 800076a: 60f8 str r0, [r7, #12]
+ 800076c: 60b9 str r1, [r7, #8]
+ 800076e: 607a str r2, [r7, #4]
+ memset(fb, 0, sizeof(fb));
+ 8000770: 2254 movs r2, #84 @ 0x54
+ 8000772: 2100 movs r1, #0
+ 8000774: 482d ldr r0, [pc, #180] @ (800082c )
+ 8000776: f004 ffeb bl 8005750
+ for (int row = 0; row < 7; row++) {
+ 800077a: 2300 movs r3, #0
+ 800077c: 627b str r3, [r7, #36] @ 0x24
+ 800077e: e04d b.n 800081c
+ for (int sc = 0; sc < 11; sc++) {
+ 8000780: 2300 movs r3, #0
+ 8000782: 623b str r3, [r7, #32]
+ 8000784: e01f b.n 80007c6
+ int col = star_col + sc;
+ 8000786: 68fa ldr r2, [r7, #12]
+ 8000788: 6a3b ldr r3, [r7, #32]
+ 800078a: 4413 add r3, r2
+ 800078c: 617b str r3, [r7, #20]
+ if (STAR[row][sc] && (mask_col < 0 || col >= mask_col))
+ 800078e: 4928 ldr r1, [pc, #160] @ (8000830 )
+ 8000790: 6a7a ldr r2, [r7, #36] @ 0x24
+ 8000792: 4613 mov r3, r2
+ 8000794: 009b lsls r3, r3, #2
+ 8000796: 4413 add r3, r2
+ 8000798: 005b lsls r3, r3, #1
+ 800079a: 4413 add r3, r2
+ 800079c: 18ca adds r2, r1, r3
+ 800079e: 6a3b ldr r3, [r7, #32]
+ 80007a0: 4413 add r3, r2
+ 80007a2: 781b ldrb r3, [r3, #0]
+ 80007a4: 2b00 cmp r3, #0
+ 80007a6: d00b beq.n 80007c0
+ 80007a8: 687b ldr r3, [r7, #4]
+ 80007aa: 2b00 cmp r3, #0
+ 80007ac: db03 blt.n 80007b6
+ 80007ae: 697a ldr r2, [r7, #20]
+ 80007b0: 687b ldr r3, [r7, #4]
+ 80007b2: 429a cmp r2, r3
+ 80007b4: db04 blt.n 80007c0
+ fb_set_pixel(col, row, 1);
+ 80007b6: 2201 movs r2, #1
+ 80007b8: 6a79 ldr r1, [r7, #36] @ 0x24
+ 80007ba: 6978 ldr r0, [r7, #20]
+ 80007bc: f7ff ff64 bl 8000688
+ for (int sc = 0; sc < 11; sc++) {
+ 80007c0: 6a3b ldr r3, [r7, #32]
+ 80007c2: 3301 adds r3, #1
+ 80007c4: 623b str r3, [r7, #32]
+ 80007c6: 6a3b ldr r3, [r7, #32]
+ 80007c8: 2b0a cmp r3, #10
+ 80007ca: dddc ble.n 8000786
+ }
+ for (int tc = 0; tc < 36; tc++) {
+ 80007cc: 2300 movs r3, #0
+ 80007ce: 61fb str r3, [r7, #28]
+ 80007d0: e01e b.n 8000810
+ int col = text_col + tc;
+ 80007d2: 68ba ldr r2, [r7, #8]
+ 80007d4: 69fb ldr r3, [r7, #28]
+ 80007d6: 4413 add r3, r2
+ 80007d8: 61bb str r3, [r7, #24]
+ if (ARRIVE_GLYPH[row][tc] && (mask_col < 0 || col >= mask_col))
+ 80007da: 4916 ldr r1, [pc, #88] @ (8000834 )
+ 80007dc: 6a7a ldr r2, [r7, #36] @ 0x24
+ 80007de: 4613 mov r3, r2
+ 80007e0: 00db lsls r3, r3, #3
+ 80007e2: 4413 add r3, r2
+ 80007e4: 009b lsls r3, r3, #2
+ 80007e6: 18ca adds r2, r1, r3
+ 80007e8: 69fb ldr r3, [r7, #28]
+ 80007ea: 4413 add r3, r2
+ 80007ec: 781b ldrb r3, [r3, #0]
+ 80007ee: 2b00 cmp r3, #0
+ 80007f0: d00b beq.n 800080a
+ 80007f2: 687b ldr r3, [r7, #4]
+ 80007f4: 2b00 cmp r3, #0
+ 80007f6: db03 blt.n 8000800
+ 80007f8: 69ba ldr r2, [r7, #24]
+ 80007fa: 687b ldr r3, [r7, #4]
+ 80007fc: 429a cmp r2, r3
+ 80007fe: db04 blt.n 800080a
+ fb_set_pixel(col, row, 1);
+ 8000800: 2201 movs r2, #1
+ 8000802: 6a79 ldr r1, [r7, #36] @ 0x24
+ 8000804: 69b8 ldr r0, [r7, #24]
+ 8000806: f7ff ff3f bl 8000688
+ for (int tc = 0; tc < 36; tc++) {
+ 800080a: 69fb ldr r3, [r7, #28]
+ 800080c: 3301 adds r3, #1
+ 800080e: 61fb str r3, [r7, #28]
+ 8000810: 69fb ldr r3, [r7, #28]
+ 8000812: 2b23 cmp r3, #35 @ 0x23
+ 8000814: dddd ble.n 80007d2
+ for (int row = 0; row < 7; row++) {
+ 8000816: 6a7b ldr r3, [r7, #36] @ 0x24
+ 8000818: 3301 adds r3, #1
+ 800081a: 627b str r3, [r7, #36] @ 0x24
+ 800081c: 6a7b ldr r3, [r7, #36] @ 0x24
+ 800081e: 2b06 cmp r3, #6
+ 8000820: ddae ble.n 8000780
+ }
+ }
+}
+ 8000822: bf00 nop
+ 8000824: bf00 nop
+ 8000826: 3728 adds r7, #40 @ 0x28
+ 8000828: 46bd mov sp, r7
+ 800082a: bd80 pop {r7, pc}
+ 800082c: 2000012c .word 0x2000012c
+ 8000830: 08005974 .word 0x08005974
+ 8000834: 080059c4 .word 0x080059c4
+
+08000838 :
+
+static void render_logo_rows(int star_col, int text_col, uint8_t row_mask)
+{
+ 8000838: b580 push {r7, lr}
+ 800083a: b08a sub sp, #40 @ 0x28
+ 800083c: af00 add r7, sp, #0
+ 800083e: 60f8 str r0, [r7, #12]
+ 8000840: 60b9 str r1, [r7, #8]
+ 8000842: 4613 mov r3, r2
+ 8000844: 71fb strb r3, [r7, #7]
+ memset(fb, 0, sizeof(fb));
+ 8000846: 2254 movs r2, #84 @ 0x54
+ 8000848: 2100 movs r1, #0
+ 800084a: 482c ldr r0, [pc, #176] @ (80008fc )
+ 800084c: f004 ff80 bl 8005750
+ for (int row = 0; row < 7; row++) {
+ 8000850: 2300 movs r3, #0
+ 8000852: 627b str r3, [r7, #36] @ 0x24
+ 8000854: e049 b.n 80008ea
+ if (!(row_mask & (1 << row))) continue;
+ 8000856: 79fa ldrb r2, [r7, #7]
+ 8000858: 6a7b ldr r3, [r7, #36] @ 0x24
+ 800085a: fa42 f303 asr.w r3, r2, r3
+ 800085e: f003 0301 and.w r3, r3, #1
+ 8000862: 2b00 cmp r3, #0
+ 8000864: d03d beq.n 80008e2
+ for (int sc = 0; sc < 11; sc++) {
+ 8000866: 2300 movs r3, #0
+ 8000868: 623b str r3, [r7, #32]
+ 800086a: e018 b.n 800089e
+ int col = star_col + sc;
+ 800086c: 68fa ldr r2, [r7, #12]
+ 800086e: 6a3b ldr r3, [r7, #32]
+ 8000870: 4413 add r3, r2
+ 8000872: 617b str r3, [r7, #20]
+ if (STAR[row][sc]) fb_set_pixel(col, row, 1);
+ 8000874: 4922 ldr r1, [pc, #136] @ (8000900 )
+ 8000876: 6a7a ldr r2, [r7, #36] @ 0x24
+ 8000878: 4613 mov r3, r2
+ 800087a: 009b lsls r3, r3, #2
+ 800087c: 4413 add r3, r2
+ 800087e: 005b lsls r3, r3, #1
+ 8000880: 4413 add r3, r2
+ 8000882: 18ca adds r2, r1, r3
+ 8000884: 6a3b ldr r3, [r7, #32]
+ 8000886: 4413 add r3, r2
+ 8000888: 781b ldrb r3, [r3, #0]
+ 800088a: 2b00 cmp r3, #0
+ 800088c: d004 beq.n 8000898
+ 800088e: 2201 movs r2, #1
+ 8000890: 6a79 ldr r1, [r7, #36] @ 0x24
+ 8000892: 6978 ldr r0, [r7, #20]
+ 8000894: f7ff fef8 bl 8000688
+ for (int sc = 0; sc < 11; sc++) {
+ 8000898: 6a3b ldr r3, [r7, #32]
+ 800089a: 3301 adds r3, #1
+ 800089c: 623b str r3, [r7, #32]
+ 800089e: 6a3b ldr r3, [r7, #32]
+ 80008a0: 2b0a cmp r3, #10
+ 80008a2: dde3 ble.n 800086c
+ }
+ for (int tc = 0; tc < 36; tc++) {
+ 80008a4: 2300 movs r3, #0
+ 80008a6: 61fb str r3, [r7, #28]
+ 80008a8: e017 b.n 80008da
+ int col = text_col + tc;
+ 80008aa: 68ba ldr r2, [r7, #8]
+ 80008ac: 69fb ldr r3, [r7, #28]
+ 80008ae: 4413 add r3, r2
+ 80008b0: 61bb str r3, [r7, #24]
+ if (ARRIVE_GLYPH[row][tc]) fb_set_pixel(col, row, 1);
+ 80008b2: 4914 ldr r1, [pc, #80] @ (8000904 )
+ 80008b4: 6a7a ldr r2, [r7, #36] @ 0x24
+ 80008b6: 4613 mov r3, r2
+ 80008b8: 00db lsls r3, r3, #3
+ 80008ba: 4413 add r3, r2
+ 80008bc: 009b lsls r3, r3, #2
+ 80008be: 18ca adds r2, r1, r3
+ 80008c0: 69fb ldr r3, [r7, #28]
+ 80008c2: 4413 add r3, r2
+ 80008c4: 781b ldrb r3, [r3, #0]
+ 80008c6: 2b00 cmp r3, #0
+ 80008c8: d004 beq.n 80008d4
+ 80008ca: 2201 movs r2, #1
+ 80008cc: 6a79 ldr r1, [r7, #36] @ 0x24
+ 80008ce: 69b8 ldr r0, [r7, #24]
+ 80008d0: f7ff feda bl 8000688
+ for (int tc = 0; tc < 36; tc++) {
+ 80008d4: 69fb ldr r3, [r7, #28]
+ 80008d6: 3301 adds r3, #1
+ 80008d8: 61fb str r3, [r7, #28]
+ 80008da: 69fb ldr r3, [r7, #28]
+ 80008dc: 2b23 cmp r3, #35 @ 0x23
+ 80008de: dde4 ble.n 80008aa
+ 80008e0: e000 b.n 80008e4
+ if (!(row_mask & (1 << row))) continue;
+ 80008e2: bf00 nop
+ for (int row = 0; row < 7; row++) {
+ 80008e4: 6a7b ldr r3, [r7, #36] @ 0x24
+ 80008e6: 3301 adds r3, #1
+ 80008e8: 627b str r3, [r7, #36] @ 0x24
+ 80008ea: 6a7b ldr r3, [r7, #36] @ 0x24
+ 80008ec: 2b06 cmp r3, #6
+ 80008ee: ddb2 ble.n 8000856
+ }
+ }
+}
+ 80008f0: bf00 nop
+ 80008f2: bf00 nop
+ 80008f4: 3728 adds r7, #40 @ 0x28
+ 80008f6: 46bd mov sp, r7
+ 80008f8: bd80 pop {r7, pc}
+ 80008fa: bf00 nop
+ 80008fc: 2000012c .word 0x2000012c
+ 8000900: 08005974 .word 0x08005974
+ 8000904: 080059c4 .word 0x080059c4
+
+08000908 :
+
+/* ── Draw text string into fb at given x offset, return end col ── */
+static int render_text_to_fb(const char *txt, int x_offset)
+{
+ 8000908: b580 push {r7, lr}
+ 800090a: b088 sub sp, #32
+ 800090c: af00 add r7, sp, #0
+ 800090e: 6078 str r0, [r7, #4]
+ 8000910: 6039 str r1, [r7, #0]
+ int col = x_offset;
+ 8000912: 683b ldr r3, [r7, #0]
+ 8000914: 61fb str r3, [r7, #28]
+ while (*txt) {
+ 8000916: e045 b.n 80009a4
+ uint8_t c = (uint8_t)*txt++;
+ 8000918: 687b ldr r3, [r7, #4]
+ 800091a: 1c5a adds r2, r3, #1
+ 800091c: 607a str r2, [r7, #4]
+ 800091e: 781b ldrb r3, [r3, #0]
+ 8000920: 76fb strb r3, [r7, #27]
+ if (c >= 'a' && c <= 'z') c -= 32;
+ 8000922: 7efb ldrb r3, [r7, #27]
+ 8000924: 2b60 cmp r3, #96 @ 0x60
+ 8000926: d905 bls.n 8000934
+ 8000928: 7efb ldrb r3, [r7, #27]
+ 800092a: 2b7a cmp r3, #122 @ 0x7a
+ 800092c: d802 bhi.n 8000934
+ 800092e: 7efb ldrb r3, [r7, #27]
+ 8000930: 3b20 subs r3, #32
+ 8000932: 76fb strb r3, [r7, #27]
+ if (c >= 32 && c <= 90) {
+ 8000934: 7efb ldrb r3, [r7, #27]
+ 8000936: 2b1f cmp r3, #31
+ 8000938: d931 bls.n 800099e
+ 800093a: 7efb ldrb r3, [r7, #27]
+ 800093c: 2b5a cmp r3, #90 @ 0x5a
+ 800093e: d82e bhi.n 800099e
+ const uint8_t *g = FONT[c - 32];
+ 8000940: 7efb ldrb r3, [r7, #27]
+ 8000942: f1a3 0220 sub.w r2, r3, #32
+ 8000946: 4613 mov r3, r2
+ 8000948: 009b lsls r3, r3, #2
+ 800094a: 4413 add r3, r2
+ 800094c: 4a1a ldr r2, [pc, #104] @ (80009b8 )
+ 800094e: 4413 add r3, r2
+ 8000950: 60fb str r3, [r7, #12]
+ for (int i = 0; i < 5; i++, col++) {
+ 8000952: 2300 movs r3, #0
+ 8000954: 617b str r3, [r7, #20]
+ 8000956: e01f b.n 8000998
+ for (int row = 0; row < ROWS; row++) {
+ 8000958: 2300 movs r3, #0
+ 800095a: 613b str r3, [r7, #16]
+ 800095c: e013 b.n 8000986
+ if (g[i] & (1 << row)) fb_set_pixel(col, row, 1);
+ 800095e: 697b ldr r3, [r7, #20]
+ 8000960: 68fa ldr r2, [r7, #12]
+ 8000962: 4413 add r3, r2
+ 8000964: 781b ldrb r3, [r3, #0]
+ 8000966: 461a mov r2, r3
+ 8000968: 693b ldr r3, [r7, #16]
+ 800096a: fa42 f303 asr.w r3, r2, r3
+ 800096e: f003 0301 and.w r3, r3, #1
+ 8000972: 2b00 cmp r3, #0
+ 8000974: d004 beq.n 8000980
+ 8000976: 2201 movs r2, #1
+ 8000978: 6939 ldr r1, [r7, #16]
+ 800097a: 69f8 ldr r0, [r7, #28]
+ 800097c: f7ff fe84 bl 8000688
+ for (int row = 0; row < ROWS; row++) {
+ 8000980: 693b ldr r3, [r7, #16]
+ 8000982: 3301 adds r3, #1
+ 8000984: 613b str r3, [r7, #16]
+ 8000986: 693b ldr r3, [r7, #16]
+ 8000988: 2b06 cmp r3, #6
+ 800098a: dde8 ble.n 800095e
+ for (int i = 0; i < 5; i++, col++) {
+ 800098c: 697b ldr r3, [r7, #20]
+ 800098e: 3301 adds r3, #1
+ 8000990: 617b str r3, [r7, #20]
+ 8000992: 69fb ldr r3, [r7, #28]
+ 8000994: 3301 adds r3, #1
+ 8000996: 61fb str r3, [r7, #28]
+ 8000998: 697b ldr r3, [r7, #20]
+ 800099a: 2b04 cmp r3, #4
+ 800099c: dddc ble.n 8000958
+ }
+ }
+ }
+ col++;
+ 800099e: 69fb ldr r3, [r7, #28]
+ 80009a0: 3301 adds r3, #1
+ 80009a2: 61fb str r3, [r7, #28]
+ while (*txt) {
+ 80009a4: 687b ldr r3, [r7, #4]
+ 80009a6: 781b ldrb r3, [r3, #0]
+ 80009a8: 2b00 cmp r3, #0
+ 80009aa: d1b5 bne.n 8000918
+ }
+ return col;
+ 80009ac: 69fb ldr r3, [r7, #28]
+}
+ 80009ae: 4618 mov r0, r3
+ 80009b0: 3720 adds r7, #32
+ 80009b2: 46bd mov sp, r7
+ 80009b4: bd80 pop {r7, pc}
+ 80009b6: bf00 nop
+ 80009b8: 0800584c .word 0x0800584c
+
+080009bc :
+
+/* ── Render text centred on display ── */
+static void render_centred_text(const char *txt)
+{
+ 80009bc: b580 push {r7, lr}
+ 80009be: b086 sub sp, #24
+ 80009c0: af00 add r7, sp, #0
+ 80009c2: 6078 str r0, [r7, #4]
+ int len = 0;
+ 80009c4: 2300 movs r3, #0
+ 80009c6: 617b str r3, [r7, #20]
+ const char *p = txt;
+ 80009c8: 687b ldr r3, [r7, #4]
+ 80009ca: 613b str r3, [r7, #16]
+ while (*p++) len++;
+ 80009cc: e002 b.n 80009d4
+ 80009ce: 697b ldr r3, [r7, #20]
+ 80009d0: 3301 adds r3, #1
+ 80009d2: 617b str r3, [r7, #20]
+ 80009d4: 693b ldr r3, [r7, #16]
+ 80009d6: 1c5a adds r2, r3, #1
+ 80009d8: 613a str r2, [r7, #16]
+ 80009da: 781b ldrb r3, [r3, #0]
+ 80009dc: 2b00 cmp r3, #0
+ 80009de: d1f6 bne.n 80009ce
+ int text_width = len * 6 - 1;
+ 80009e0: 697a ldr r2, [r7, #20]
+ 80009e2: 4613 mov r3, r2
+ 80009e4: 005b lsls r3, r3, #1
+ 80009e6: 4413 add r3, r2
+ 80009e8: 005b lsls r3, r3, #1
+ 80009ea: 3b01 subs r3, #1
+ 80009ec: 60fb str r3, [r7, #12]
+ int x = (COLS - text_width) / 2;
+ 80009ee: 68fb ldr r3, [r7, #12]
+ 80009f0: f1c3 0360 rsb r3, r3, #96 @ 0x60
+ 80009f4: 0fda lsrs r2, r3, #31
+ 80009f6: 4413 add r3, r2
+ 80009f8: 105b asrs r3, r3, #1
+ 80009fa: 60bb str r3, [r7, #8]
+ memset(fb, 0, sizeof(fb));
+ 80009fc: 2254 movs r2, #84 @ 0x54
+ 80009fe: 2100 movs r1, #0
+ 8000a00: 4805 ldr r0, [pc, #20] @ (8000a18 )
+ 8000a02: f004 fea5 bl 8005750
+ render_text_to_fb(txt, x);
+ 8000a06: 68b9 ldr r1, [r7, #8]
+ 8000a08: 6878 ldr r0, [r7, #4]
+ 8000a0a: f7ff ff7d bl 8000908
+}
+ 8000a0e: bf00 nop
+ 8000a10: 3718 adds r7, #24
+ 8000a12: 46bd mov sp, r7
+ 8000a14: bd80 pop {r7, pc}
+ 8000a16: bf00 nop
+ 8000a18: 2000012c .word 0x2000012c
+
+08000a1c :
+
+/* ── Render word into wide[] for scrolling, returns total width ── */
+static uint16_t render_scroll(const char *txt, int x_start)
+{
+ 8000a1c: b580 push {r7, lr}
+ 8000a1e: b088 sub sp, #32
+ 8000a20: af00 add r7, sp, #0
+ 8000a22: 6078 str r0, [r7, #4]
+ 8000a24: 6039 str r1, [r7, #0]
+ memset(wide, 0, sizeof(wide));
+ 8000a26: f44f 6260 mov.w r2, #3584 @ 0xe00
+ 8000a2a: 2100 movs r1, #0
+ 8000a2c: 4831 ldr r0, [pc, #196] @ (8000af4 )
+ 8000a2e: f004 fe8f bl 8005750
+ int col = x_start;
+ 8000a32: 683b ldr r3, [r7, #0]
+ 8000a34: 61fb str r3, [r7, #28]
+ while (*txt && col < WIDE_COLS - 6) {
+ 8000a36: e04c b.n 8000ad2
+ uint8_t c = (uint8_t)*txt++;
+ 8000a38: 687b ldr r3, [r7, #4]
+ 8000a3a: 1c5a adds r2, r3, #1
+ 8000a3c: 607a str r2, [r7, #4]
+ 8000a3e: 781b ldrb r3, [r3, #0]
+ 8000a40: 76fb strb r3, [r7, #27]
+ if (c >= 'a' && c <= 'z') c -= 32;
+ 8000a42: 7efb ldrb r3, [r7, #27]
+ 8000a44: 2b60 cmp r3, #96 @ 0x60
+ 8000a46: d905 bls.n 8000a54
+ 8000a48: 7efb ldrb r3, [r7, #27]
+ 8000a4a: 2b7a cmp r3, #122 @ 0x7a
+ 8000a4c: d802 bhi.n 8000a54
+ 8000a4e: 7efb ldrb r3, [r7, #27]
+ 8000a50: 3b20 subs r3, #32
+ 8000a52: 76fb strb r3, [r7, #27]
+ if (c >= 32 && c <= 90) {
+ 8000a54: 7efb ldrb r3, [r7, #27]
+ 8000a56: 2b1f cmp r3, #31
+ 8000a58: d938 bls.n 8000acc
+ 8000a5a: 7efb ldrb r3, [r7, #27]
+ 8000a5c: 2b5a cmp r3, #90 @ 0x5a
+ 8000a5e: d835 bhi.n 8000acc
+ const uint8_t *g = FONT[c - 32];
+ 8000a60: 7efb ldrb r3, [r7, #27]
+ 8000a62: f1a3 0220 sub.w r2, r3, #32
+ 8000a66: 4613 mov r3, r2
+ 8000a68: 009b lsls r3, r3, #2
+ 8000a6a: 4413 add r3, r2
+ 8000a6c: 4a22 ldr r2, [pc, #136] @ (8000af8 )
+ 8000a6e: 4413 add r3, r2
+ 8000a70: 60fb str r3, [r7, #12]
+ for (int i = 0; i < 5 && col < WIDE_COLS; i++, col++) {
+ 8000a72: 2300 movs r3, #0
+ 8000a74: 617b str r3, [r7, #20]
+ 8000a76: e022 b.n 8000abe
+ for (int row = 0; row < ROWS; row++) {
+ 8000a78: 2300 movs r3, #0
+ 8000a7a: 613b str r3, [r7, #16]
+ 8000a7c: e016 b.n 8000aac
+ if (g[i] & (1 << row)) wide[row][col] = 1;
+ 8000a7e: 697b ldr r3, [r7, #20]
+ 8000a80: 68fa ldr r2, [r7, #12]
+ 8000a82: 4413 add r3, r2
+ 8000a84: 781b ldrb r3, [r3, #0]
+ 8000a86: 461a mov r2, r3
+ 8000a88: 693b ldr r3, [r7, #16]
+ 8000a8a: fa42 f303 asr.w r3, r2, r3
+ 8000a8e: f003 0301 and.w r3, r3, #1
+ 8000a92: 2b00 cmp r3, #0
+ 8000a94: d007 beq.n 8000aa6
+ 8000a96: 4a17 ldr r2, [pc, #92] @ (8000af4 )
+ 8000a98: 693b ldr r3, [r7, #16]
+ 8000a9a: 025b lsls r3, r3, #9
+ 8000a9c: 441a add r2, r3
+ 8000a9e: 69fb ldr r3, [r7, #28]
+ 8000aa0: 4413 add r3, r2
+ 8000aa2: 2201 movs r2, #1
+ 8000aa4: 701a strb r2, [r3, #0]
+ for (int row = 0; row < ROWS; row++) {
+ 8000aa6: 693b ldr r3, [r7, #16]
+ 8000aa8: 3301 adds r3, #1
+ 8000aaa: 613b str r3, [r7, #16]
+ 8000aac: 693b ldr r3, [r7, #16]
+ 8000aae: 2b06 cmp r3, #6
+ 8000ab0: dde5 ble.n 8000a7e
+ for (int i = 0; i < 5 && col < WIDE_COLS; i++, col++) {
+ 8000ab2: 697b ldr r3, [r7, #20]
+ 8000ab4: 3301 adds r3, #1
+ 8000ab6: 617b str r3, [r7, #20]
+ 8000ab8: 69fb ldr r3, [r7, #28]
+ 8000aba: 3301 adds r3, #1
+ 8000abc: 61fb str r3, [r7, #28]
+ 8000abe: 697b ldr r3, [r7, #20]
+ 8000ac0: 2b04 cmp r3, #4
+ 8000ac2: dc03 bgt.n 8000acc
+ 8000ac4: 69fb ldr r3, [r7, #28]
+ 8000ac6: f5b3 7f00 cmp.w r3, #512 @ 0x200
+ 8000aca: dbd5 blt.n 8000a78
+ }
+ }
+ }
+ col++;
+ 8000acc: 69fb ldr r3, [r7, #28]
+ 8000ace: 3301 adds r3, #1
+ 8000ad0: 61fb str r3, [r7, #28]
+ while (*txt && col < WIDE_COLS - 6) {
+ 8000ad2: 687b ldr r3, [r7, #4]
+ 8000ad4: 781b ldrb r3, [r3, #0]
+ 8000ad6: 2b00 cmp r3, #0
+ 8000ad8: d003 beq.n 8000ae2
+ 8000ada: 69fb ldr r3, [r7, #28]
+ 8000adc: f5b3 7ffd cmp.w r3, #506 @ 0x1fa
+ 8000ae0: dbaa blt.n 8000a38
+ }
+ return (uint16_t)(col + COLS);
+ 8000ae2: 69fb ldr r3, [r7, #28]
+ 8000ae4: b29b uxth r3, r3
+ 8000ae6: 3360 adds r3, #96 @ 0x60
+ 8000ae8: b29b uxth r3, r3
+}
+ 8000aea: 4618 mov r0, r3
+ 8000aec: 3720 adds r7, #32
+ 8000aee: 46bd mov sp, r7
+ 8000af0: bd80 pop {r7, pc}
+ 8000af2: bf00 nop
+ 8000af4: 20000180 .word 0x20000180
+ 8000af8: 0800584c .word 0x0800584c
+
+08000afc :
+
+static void update_fb_from_scroll(void)
+{
+ 8000afc: b580 push {r7, lr}
+ 8000afe: b084 sub sp, #16
+ 8000b00: af00 add r7, sp, #0
+ for (int row = 0; row < ROWS; row++) {
+ 8000b02: 2300 movs r3, #0
+ 8000b04: 60fb str r3, [r7, #12]
+ 8000b06: e030 b.n 8000b6a
+ memset(fb[row], 0, NUM_CHIPS);
+ 8000b08: 68fa ldr r2, [r7, #12]
+ 8000b0a: 4613 mov r3, r2
+ 8000b0c: 005b lsls r3, r3, #1
+ 8000b0e: 4413 add r3, r2
+ 8000b10: 009b lsls r3, r3, #2
+ 8000b12: 4a1a ldr r2, [pc, #104] @ (8000b7c )
+ 8000b14: 4413 add r3, r2
+ 8000b16: 220c movs r2, #12
+ 8000b18: 2100 movs r1, #0
+ 8000b1a: 4618 mov r0, r3
+ 8000b1c: f004 fe18 bl 8005750
+ for (int col = 0; col < COLS; col++) {
+ 8000b20: 2300 movs r3, #0
+ 8000b22: 60bb str r3, [r7, #8]
+ 8000b24: e01b b.n 8000b5e
+ uint16_t src = (uint16_t)(scroll_x + col);
+ 8000b26: 4b16 ldr r3, [pc, #88] @ (8000b80 )
+ 8000b28: 681b ldr r3, [r3, #0]
+ 8000b2a: b29a uxth r2, r3
+ 8000b2c: 68bb ldr r3, [r7, #8]
+ 8000b2e: b29b uxth r3, r3
+ 8000b30: 4413 add r3, r2
+ 8000b32: 80fb strh r3, [r7, #6]
+ if (src < WIDE_COLS && wide[row][src])
+ 8000b34: 88fb ldrh r3, [r7, #6]
+ 8000b36: f5b3 7f00 cmp.w r3, #512 @ 0x200
+ 8000b3a: d20d bcs.n 8000b58
+ 8000b3c: 88fb ldrh r3, [r7, #6]
+ 8000b3e: 4911 ldr r1, [pc, #68] @ (8000b84 )
+ 8000b40: 68fa ldr r2, [r7, #12]
+ 8000b42: 0252 lsls r2, r2, #9
+ 8000b44: 440a add r2, r1
+ 8000b46: 4413 add r3, r2
+ 8000b48: 781b ldrb r3, [r3, #0]
+ 8000b4a: 2b00 cmp r3, #0
+ 8000b4c: d004 beq.n 8000b58
+ fb_set_pixel(col, row, 1);
+ 8000b4e: 2201 movs r2, #1
+ 8000b50: 68f9 ldr r1, [r7, #12]
+ 8000b52: 68b8 ldr r0, [r7, #8]
+ 8000b54: f7ff fd98 bl 8000688
+ for (int col = 0; col < COLS; col++) {
+ 8000b58: 68bb ldr r3, [r7, #8]
+ 8000b5a: 3301 adds r3, #1
+ 8000b5c: 60bb str r3, [r7, #8]
+ 8000b5e: 68bb ldr r3, [r7, #8]
+ 8000b60: 2b5f cmp r3, #95 @ 0x5f
+ 8000b62: dde0 ble.n 8000b26
+ for (int row = 0; row < ROWS; row++) {
+ 8000b64: 68fb ldr r3, [r7, #12]
+ 8000b66: 3301 adds r3, #1
+ 8000b68: 60fb str r3, [r7, #12]
+ 8000b6a: 68fb ldr r3, [r7, #12]
+ 8000b6c: 2b06 cmp r3, #6
+ 8000b6e: ddcb ble.n 8000b08
+ }
+ }
+}
+ 8000b70: bf00 nop
+ 8000b72: bf00 nop
+ 8000b74: 3710 adds r7, #16
+ 8000b76: 46bd mov sp, r7
+ 8000b78: bd80 pop {r7, pc}
+ 8000b7a: bf00 nop
+ 8000b7c: 2000012c .word 0x2000012c
+ 8000b80: 20000f84 .word 0x20000f84
+ 8000b84: 20000180 .word 0x20000180
+
+08000b88 :
+
+/* ── Update fb from scroll but only write to cols >= clip_left ── */
+static void update_fb_from_scroll_clipped(int clip_left)
+{
+ 8000b88: b580 push {r7, lr}
+ 8000b8a: b086 sub sp, #24
+ 8000b8c: af00 add r7, sp, #0
+ 8000b8e: 6078 str r0, [r7, #4]
+ for (int row = 0; row < ROWS; row++) {
+ 8000b90: 2300 movs r3, #0
+ 8000b92: 617b str r3, [r7, #20]
+ 8000b94: e026 b.n 8000be4
+ for (int col = clip_left; col < COLS; col++) {
+ 8000b96: 687b ldr r3, [r7, #4]
+ 8000b98: 613b str r3, [r7, #16]
+ 8000b9a: e01d b.n 8000bd8
+ uint16_t src = (uint16_t)(scroll_x + (col - clip_left));
+ 8000b9c: 4b15 ldr r3, [pc, #84] @ (8000bf4 )
+ 8000b9e: 681b ldr r3, [r3, #0]
+ 8000ba0: b29a uxth r2, r3
+ 8000ba2: 693b ldr r3, [r7, #16]
+ 8000ba4: b299 uxth r1, r3
+ 8000ba6: 687b ldr r3, [r7, #4]
+ 8000ba8: b29b uxth r3, r3
+ 8000baa: 1acb subs r3, r1, r3
+ 8000bac: b29b uxth r3, r3
+ 8000bae: 4413 add r3, r2
+ 8000bb0: 81fb strh r3, [r7, #14]
+ if (src < WIDE_COLS)
+ 8000bb2: 89fb ldrh r3, [r7, #14]
+ 8000bb4: f5b3 7f00 cmp.w r3, #512 @ 0x200
+ 8000bb8: d20b bcs.n 8000bd2
+ fb_set_pixel(col, row, wide[row][src]);
+ 8000bba: 89fb ldrh r3, [r7, #14]
+ 8000bbc: 490e ldr r1, [pc, #56] @ (8000bf8 )
+ 8000bbe: 697a ldr r2, [r7, #20]
+ 8000bc0: 0252 lsls r2, r2, #9
+ 8000bc2: 440a add r2, r1
+ 8000bc4: 4413 add r3, r2
+ 8000bc6: 781b ldrb r3, [r3, #0]
+ 8000bc8: 461a mov r2, r3
+ 8000bca: 6979 ldr r1, [r7, #20]
+ 8000bcc: 6938 ldr r0, [r7, #16]
+ 8000bce: f7ff fd5b bl 8000688
+ for (int col = clip_left; col < COLS; col++) {
+ 8000bd2: 693b ldr r3, [r7, #16]
+ 8000bd4: 3301 adds r3, #1
+ 8000bd6: 613b str r3, [r7, #16]
+ 8000bd8: 693b ldr r3, [r7, #16]
+ 8000bda: 2b5f cmp r3, #95 @ 0x5f
+ 8000bdc: ddde ble.n 8000b9c
+ for (int row = 0; row < ROWS; row++) {
+ 8000bde: 697b ldr r3, [r7, #20]
+ 8000be0: 3301 adds r3, #1
+ 8000be2: 617b str r3, [r7, #20]
+ 8000be4: 697b ldr r3, [r7, #20]
+ 8000be6: 2b06 cmp r3, #6
+ 8000be8: ddd5 ble.n 8000b96
+ }
+ }
+}
+ 8000bea: bf00 nop
+ 8000bec: bf00 nop
+ 8000bee: 3718 adds r7, #24
+ 8000bf0: 46bd mov sp, r7
+ 8000bf2: bd80 pop {r7, pc}
+ 8000bf4: 20000f84 .word 0x20000f84
+ 8000bf8: 20000180 .word 0x20000180
+
+08000bfc :
+
+/* ── Fade rows out (centre outward to top+bottom) ── */
+static void fade_out_rows(int star_col, int text_col, uint8_t is_logo)
+{
+ 8000bfc: b580 push {r7, lr}
+ 8000bfe: b09e sub sp, #120 @ 0x78
+ 8000c00: af00 add r7, sp, #0
+ 8000c02: 60f8 str r0, [r7, #12]
+ 8000c04: 60b9 str r1, [r7, #8]
+ 8000c06: 4613 mov r3, r2
+ 8000c08: 71fb strb r3, [r7, #7]
+ uint8_t masks[] = {0x7E, 0x7C, 0x3C, 0x1C, 0x0C, 0x08, 0x00};
+ 8000c0a: 4a32 ldr r2, [pc, #200] @ (8000cd4 )
+ 8000c0c: f107 0368 add.w r3, r7, #104 @ 0x68
+ 8000c10: e892 0003 ldmia.w r2, {r0, r1}
+ 8000c14: 6018 str r0, [r3, #0]
+ 8000c16: 3304 adds r3, #4
+ 8000c18: 8019 strh r1, [r3, #0]
+ 8000c1a: 3302 adds r3, #2
+ 8000c1c: 0c0a lsrs r2, r1, #16
+ 8000c1e: 701a strb r2, [r3, #0]
+ uint8_t snap[ROWS][NUM_CHIPS];
+ memcpy(snap, fb, sizeof(fb));
+ 8000c20: 4a2d ldr r2, [pc, #180] @ (8000cd8 )
+ 8000c22: f107 0314 add.w r3, r7, #20
+ 8000c26: 4611 mov r1, r2
+ 8000c28: 2254 movs r2, #84 @ 0x54
+ 8000c2a: 4618 mov r0, r3
+ 8000c2c: f004 fdbc bl 80057a8
+ for (int i = 0; i < 7; i++) {
+ 8000c30: 2300 movs r3, #0
+ 8000c32: 677b str r3, [r7, #116] @ 0x74
+ 8000c34: e041 b.n 8000cba
+ if (is_logo) {
+ 8000c36: 79fb ldrb r3, [r7, #7]
+ 8000c38: 2b00 cmp r3, #0
+ 8000c3a: d00a beq.n 8000c52
+ render_logo_rows(star_col, text_col, masks[i]);
+ 8000c3c: f107 0268 add.w r2, r7, #104 @ 0x68
+ 8000c40: 6f7b ldr r3, [r7, #116] @ 0x74
+ 8000c42: 4413 add r3, r2
+ 8000c44: 781b ldrb r3, [r3, #0]
+ 8000c46: 461a mov r2, r3
+ 8000c48: 68b9 ldr r1, [r7, #8]
+ 8000c4a: 68f8 ldr r0, [r7, #12]
+ 8000c4c: f7ff fdf4 bl 8000838
+ 8000c50: e02d b.n 8000cae
+ } else {
+ memset(fb, 0, sizeof(fb));
+ 8000c52: 2254 movs r2, #84 @ 0x54
+ 8000c54: 2100 movs r1, #0
+ 8000c56: 4820 ldr r0, [pc, #128] @ (8000cd8 )
+ 8000c58: f004 fd7a bl 8005750
+ for (int row = 0; row < ROWS; row++) {
+ 8000c5c: 2300 movs r3, #0
+ 8000c5e: 673b str r3, [r7, #112] @ 0x70
+ 8000c60: e022 b.n 8000ca8
+ if (masks[i] & (1 << row))
+ 8000c62: f107 0268 add.w r2, r7, #104 @ 0x68
+ 8000c66: 6f7b ldr r3, [r7, #116] @ 0x74
+ 8000c68: 4413 add r3, r2
+ 8000c6a: 781b ldrb r3, [r3, #0]
+ 8000c6c: 461a mov r2, r3
+ 8000c6e: 6f3b ldr r3, [r7, #112] @ 0x70
+ 8000c70: fa42 f303 asr.w r3, r2, r3
+ 8000c74: f003 0301 and.w r3, r3, #1
+ 8000c78: 2b00 cmp r3, #0
+ 8000c7a: d012 beq.n 8000ca2
+ memcpy(fb[row], snap[row], NUM_CHIPS);
+ 8000c7c: 6f3a ldr r2, [r7, #112] @ 0x70
+ 8000c7e: 4613 mov r3, r2
+ 8000c80: 005b lsls r3, r3, #1
+ 8000c82: 4413 add r3, r2
+ 8000c84: 009b lsls r3, r3, #2
+ 8000c86: 4a14 ldr r2, [pc, #80] @ (8000cd8 )
+ 8000c88: 1898 adds r0, r3, r2
+ 8000c8a: f107 0114 add.w r1, r7, #20
+ 8000c8e: 6f3a ldr r2, [r7, #112] @ 0x70
+ 8000c90: 4613 mov r3, r2
+ 8000c92: 005b lsls r3, r3, #1
+ 8000c94: 4413 add r3, r2
+ 8000c96: 009b lsls r3, r3, #2
+ 8000c98: 440b add r3, r1
+ 8000c9a: 220c movs r2, #12
+ 8000c9c: 4619 mov r1, r3
+ 8000c9e: f004 fd83 bl 80057a8
+ for (int row = 0; row < ROWS; row++) {
+ 8000ca2: 6f3b ldr r3, [r7, #112] @ 0x70
+ 8000ca4: 3301 adds r3, #1
+ 8000ca6: 673b str r3, [r7, #112] @ 0x70
+ 8000ca8: 6f3b ldr r3, [r7, #112] @ 0x70
+ 8000caa: 2b06 cmp r3, #6
+ 8000cac: ddd9 ble.n 8000c62
+ }
+ }
+ refresh_for(60);
+ 8000cae: 203c movs r0, #60 @ 0x3c
+ 8000cb0: f7ff fcc6 bl 8000640
+ for (int i = 0; i < 7; i++) {
+ 8000cb4: 6f7b ldr r3, [r7, #116] @ 0x74
+ 8000cb6: 3301 adds r3, #1
+ 8000cb8: 677b str r3, [r7, #116] @ 0x74
+ 8000cba: 6f7b ldr r3, [r7, #116] @ 0x74
+ 8000cbc: 2b06 cmp r3, #6
+ 8000cbe: ddba ble.n 8000c36
+ }
+ memset(fb, 0, sizeof(fb));
+ 8000cc0: 2254 movs r2, #84 @ 0x54
+ 8000cc2: 2100 movs r1, #0
+ 8000cc4: 4804 ldr r0, [pc, #16] @ (8000cd8 )
+ 8000cc6: f004 fd43 bl 8005750
+}
+ 8000cca: bf00 nop
+ 8000ccc: 3778 adds r7, #120 @ 0x78
+ 8000cce: 46bd mov sp, r7
+ 8000cd0: bd80 pop {r7, pc}
+ 8000cd2: bf00 nop
+ 8000cd4: 080057dc .word 0x080057dc
+ 8000cd8: 2000012c .word 0x2000012c
+
+08000cdc :
+/* ════════════════════════════════════════════════
+ Arrive boot / splash animation
+ ════════════════════════════════════════════════ */
-/* ── Arrive boot animation ── */
static void arrive_animation(void)
{
- 8000b64: b580 push {r7, lr}
- 8000b66: b092 sub sp, #72 @ 0x48
- 8000b68: af00 add r7, sp, #0
- /* Logo layout — text LEFT, star RIGHT:
- ARRIVE = 36 cols, gap = 2, star = 11 cols → total = 49 cols
- centred on 96: start = (96 - 49) / 2 = 23
- text_col = 23, star_col = 23 + 36 + 2 = 61 */
+ 8000cdc: b580 push {r7, lr}
+ 8000cde: b088 sub sp, #32
+ 8000ce0: af00 add r7, sp, #0
const int text_col = 23;
- 8000b6a: 2317 movs r3, #23
- 8000b6c: 633b str r3, [r7, #48] @ 0x30
+ 8000ce2: 2317 movs r3, #23
+ 8000ce4: 60bb str r3, [r7, #8]
const int star_col = 61;
- 8000b6e: 233d movs r3, #61 @ 0x3d
- 8000b70: 62fb str r3, [r7, #44] @ 0x2c
+ 8000ce6: 233d movs r3, #61 @ 0x3d
+ 8000ce8: 607b str r3, [r7, #4]
- /* ── Phase 1: Star builds from centre outward ── */
- /* Frame 1 — just centre cross */
+ /* Phase 1 — star builds */
memset(fb, 0, sizeof(fb));
- 8000b72: 2254 movs r2, #84 @ 0x54
- 8000b74: 2100 movs r1, #0
- 8000b76: 48b4 ldr r0, [pc, #720] @ (8000e48 )
- 8000b78: f004 fc72 bl 8005460
- for (int row = 0; row < 7; row++) {
- 8000b7c: 2300 movs r3, #0
- 8000b7e: 647b str r3, [r7, #68] @ 0x44
- 8000b80: e032 b.n 8000be8
- int col = star_col + 4; /* centre column of star */
- 8000b82: 6afb ldr r3, [r7, #44] @ 0x2c
- 8000b84: 3304 adds r3, #4
- 8000b86: 60fb str r3, [r7, #12]
- int chip = col / 8; int bit = 7 - (col % 8);
- 8000b88: 68fb ldr r3, [r7, #12]
- 8000b8a: 2b00 cmp r3, #0
- 8000b8c: da00 bge.n 8000b90
- 8000b8e: 3307 adds r3, #7
- 8000b90: 10db asrs r3, r3, #3
- 8000b92: 60bb str r3, [r7, #8]
- 8000b94: 68fb ldr r3, [r7, #12]
- 8000b96: 425a negs r2, r3
- 8000b98: f003 0307 and.w r3, r3, #7
- 8000b9c: f002 0207 and.w r2, r2, #7
- 8000ba0: bf58 it pl
- 8000ba2: 4253 negpl r3, r2
- 8000ba4: f1c3 0307 rsb r3, r3, #7
- 8000ba8: 607b str r3, [r7, #4]
- fb[row][chip] |= (uint8_t)(1 << bit);
- 8000baa: 49a7 ldr r1, [pc, #668] @ (8000e48 )
- 8000bac: 6c7a ldr r2, [r7, #68] @ 0x44
- 8000bae: 4613 mov r3, r2
- 8000bb0: 005b lsls r3, r3, #1
- 8000bb2: 4413 add r3, r2
- 8000bb4: 009b lsls r3, r3, #2
- 8000bb6: 18ca adds r2, r1, r3
- 8000bb8: 68bb ldr r3, [r7, #8]
- 8000bba: 4413 add r3, r2
- 8000bbc: 781a ldrb r2, [r3, #0]
- 8000bbe: 2101 movs r1, #1
- 8000bc0: 687b ldr r3, [r7, #4]
- 8000bc2: fa01 f303 lsl.w r3, r1, r3
- 8000bc6: b2db uxtb r3, r3
- 8000bc8: 4313 orrs r3, r2
- 8000bca: b2d8 uxtb r0, r3
- 8000bcc: 499e ldr r1, [pc, #632] @ (8000e48 )
- 8000bce: 6c7a ldr r2, [r7, #68] @ 0x44
- 8000bd0: 4613 mov r3, r2
- 8000bd2: 005b lsls r3, r3, #1
- 8000bd4: 4413 add r3, r2
- 8000bd6: 009b lsls r3, r3, #2
- 8000bd8: 18ca adds r2, r1, r3
- 8000bda: 68bb ldr r3, [r7, #8]
- 8000bdc: 4413 add r3, r2
- 8000bde: 4602 mov r2, r0
- 8000be0: 701a strb r2, [r3, #0]
- for (int row = 0; row < 7; row++) {
- 8000be2: 6c7b ldr r3, [r7, #68] @ 0x44
- 8000be4: 3301 adds r3, #1
- 8000be6: 647b str r3, [r7, #68] @ 0x44
- 8000be8: 6c7b ldr r3, [r7, #68] @ 0x44
- 8000bea: 2b06 cmp r3, #6
- 8000bec: ddc9 ble.n 8000b82
- }
- /* horizontal bar centre */
- for (int sc = 3; sc <= 5; sc++) {
- 8000bee: 2303 movs r3, #3
- 8000bf0: 643b str r3, [r7, #64] @ 0x40
- 8000bf2: e029 b.n 8000c48