pm-grid: start main.rs modularization (extract fonts module)
Move the 3x5 LED font (DIGITS, glyph, build_name_cols) into src/fonts.rs. Pure code move, compiler-verified identical behavior; main.rs 1835 -> ~1770 lines. First step of the recommended main.rs split; further extraction (FAT/MSC storage, views) to continue incrementally as those areas are touched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
72dbb2ecd0
commit
bdf69cfd30
2 changed files with 80 additions and 75 deletions
78
rust/pm-grid/src/fonts.rs
Normal file
78
rust/pm-grid/src/fonts.rs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
//! 3x5 LED font (bit2 = leftmost column) — shared by the views, the scrolling name, and the splash.
|
||||
//! Same bit convention as pico-scroll/app.py: glyph row value's bit `(1 << (2 - col))` lights a column.
|
||||
use alloc::vec::Vec;
|
||||
|
||||
pub const DIGITS: [[u8; 5]; 10] = [
|
||||
[7, 5, 5, 5, 7], // 0
|
||||
[2, 6, 2, 2, 7], // 1
|
||||
[7, 1, 7, 4, 7], // 2
|
||||
[7, 1, 7, 1, 7], // 3
|
||||
[5, 5, 7, 1, 1], // 4
|
||||
[7, 4, 7, 1, 7], // 5
|
||||
[7, 4, 7, 5, 7], // 6
|
||||
[7, 1, 2, 2, 2], // 7
|
||||
[7, 5, 7, 5, 7], // 8
|
||||
[7, 5, 7, 1, 7], // 9
|
||||
];
|
||||
|
||||
/// Full 3x5 uppercase glyph for a character (used by the scrolling name + boot splash).
|
||||
/// Unknown characters render blank. Digits reuse `DIGITS`.
|
||||
fn glyph(c: char) -> [u8; 5] {
|
||||
match c {
|
||||
'0'..='9' => DIGITS[c as usize - '0' as usize],
|
||||
'A' => [2, 5, 7, 5, 5],
|
||||
'B' => [6, 5, 6, 5, 6],
|
||||
'C' => [3, 4, 4, 4, 3],
|
||||
'D' => [6, 5, 5, 5, 6],
|
||||
'E' => [7, 4, 6, 4, 7],
|
||||
'F' => [7, 4, 6, 4, 4],
|
||||
'G' => [7, 4, 5, 5, 7],
|
||||
'H' => [5, 5, 7, 5, 5],
|
||||
'I' => [7, 2, 2, 2, 7],
|
||||
'J' => [1, 1, 1, 5, 2],
|
||||
'K' => [5, 6, 4, 6, 5],
|
||||
'L' => [4, 4, 4, 4, 7],
|
||||
'M' => [5, 7, 7, 5, 5],
|
||||
'N' => [5, 7, 7, 7, 5],
|
||||
'O' => [2, 5, 5, 5, 2],
|
||||
'P' => [7, 5, 7, 4, 4],
|
||||
'Q' => [2, 5, 5, 6, 3],
|
||||
'R' => [7, 5, 7, 6, 5],
|
||||
'S' => [3, 4, 2, 1, 6],
|
||||
'T' => [7, 2, 2, 2, 2],
|
||||
'U' => [5, 5, 5, 5, 7],
|
||||
'V' => [5, 5, 5, 5, 2],
|
||||
'W' => [5, 5, 7, 7, 5],
|
||||
'X' => [5, 5, 2, 5, 5],
|
||||
'Y' => [5, 5, 2, 2, 2],
|
||||
'Z' => [7, 1, 2, 4, 7],
|
||||
'-' => [0, 0, 7, 0, 0],
|
||||
'/' => [1, 1, 2, 4, 4],
|
||||
'(' => [1, 2, 2, 2, 1],
|
||||
')' => [4, 2, 2, 2, 4],
|
||||
'.' => [0, 0, 0, 0, 2],
|
||||
'+' => [0, 2, 7, 2, 0],
|
||||
'&' => [2, 5, 2, 5, 3],
|
||||
_ => [0, 0, 0, 0, 0], // space + anything unmapped
|
||||
}
|
||||
}
|
||||
|
||||
/// Render a string into a list of 5-bit column slices (3 columns per glyph + a 1px gap), for the
|
||||
/// horizontal scrollers (Ticker name + boot splash). Lowercase is folded to uppercase.
|
||||
pub fn build_name_cols(name: &str) -> Vec<u8> {
|
||||
let mut cols = Vec::new();
|
||||
for ch in name.chars() {
|
||||
let g = glyph(ch.to_ascii_uppercase());
|
||||
for c in 0..3 {
|
||||
let mut col = 0u8;
|
||||
for r in 0..5 {
|
||||
if g[r] & (1 << (2 - c)) != 0 {
|
||||
col |= 1 << r;
|
||||
}
|
||||
}
|
||||
cols.push(col);
|
||||
}
|
||||
cols.push(0); // 1px gap between glyphs
|
||||
}
|
||||
cols
|
||||
}
|
||||
|
|
@ -19,6 +19,8 @@
|
|||
#![no_main]
|
||||
|
||||
extern crate alloc;
|
||||
mod fonts;
|
||||
use fonts::{build_name_cols, DIGITS};
|
||||
use alloc::collections::VecDeque;
|
||||
use alloc::string::{String, ToString};
|
||||
use alloc::vec::Vec;
|
||||
|
|
@ -311,63 +313,6 @@ const APP_VERSION: &str = "0.1.0";
|
|||
const BRIGHTNESS: u8 = 160; // accent
|
||||
const NAME_BRIGHT: u8 = 120; // ticker name pixels
|
||||
|
||||
// ============================== FONTS (3x5; bit2 = leftmost column) ==============================
|
||||
// Same bit convention as pico-scroll/app.py: glyph row value's bit (1<<(2-col)) lights that column.
|
||||
const DIGITS: [[u8; 5]; 10] = [
|
||||
[7, 5, 5, 5, 7], // 0
|
||||
[2, 6, 2, 2, 7], // 1
|
||||
[7, 1, 7, 4, 7], // 2
|
||||
[7, 1, 7, 1, 7], // 3
|
||||
[5, 5, 7, 1, 1], // 4
|
||||
[7, 4, 7, 1, 7], // 5
|
||||
[7, 4, 7, 5, 7], // 6
|
||||
[7, 1, 2, 2, 2], // 7
|
||||
[7, 5, 7, 5, 7], // 8
|
||||
[7, 5, 7, 1, 7], // 9
|
||||
];
|
||||
|
||||
/// Full 3x5 uppercase glyph for a character (used by the scrolling name + boot splash).
|
||||
/// Unknown characters render blank. Digits reuse `DIGITS`.
|
||||
fn glyph(c: char) -> [u8; 5] {
|
||||
match c {
|
||||
'0'..='9' => DIGITS[c as usize - '0' as usize],
|
||||
'A' => [2, 5, 7, 5, 5],
|
||||
'B' => [6, 5, 6, 5, 6],
|
||||
'C' => [3, 4, 4, 4, 3],
|
||||
'D' => [6, 5, 5, 5, 6],
|
||||
'E' => [7, 4, 6, 4, 7],
|
||||
'F' => [7, 4, 6, 4, 4],
|
||||
'G' => [7, 4, 5, 5, 7],
|
||||
'H' => [5, 5, 7, 5, 5],
|
||||
'I' => [7, 2, 2, 2, 7],
|
||||
'J' => [1, 1, 1, 5, 2],
|
||||
'K' => [5, 6, 4, 6, 5],
|
||||
'L' => [4, 4, 4, 4, 7],
|
||||
'M' => [5, 7, 7, 5, 5],
|
||||
'N' => [5, 7, 7, 7, 5],
|
||||
'O' => [2, 5, 5, 5, 2],
|
||||
'P' => [7, 5, 7, 4, 4],
|
||||
'Q' => [2, 5, 5, 6, 3],
|
||||
'R' => [7, 5, 7, 6, 5],
|
||||
'S' => [3, 4, 2, 1, 6],
|
||||
'T' => [7, 2, 2, 2, 2],
|
||||
'U' => [5, 5, 5, 5, 7],
|
||||
'V' => [5, 5, 5, 5, 2],
|
||||
'W' => [5, 5, 7, 7, 5],
|
||||
'X' => [5, 5, 2, 5, 5],
|
||||
'Y' => [5, 5, 2, 2, 2],
|
||||
'Z' => [7, 1, 2, 4, 7],
|
||||
'-' => [0, 0, 7, 0, 0],
|
||||
'/' => [1, 1, 2, 4, 4],
|
||||
'(' => [1, 2, 2, 2, 1],
|
||||
')' => [4, 2, 2, 2, 4],
|
||||
'.' => [0, 0, 0, 0, 2],
|
||||
'+' => [0, 2, 7, 2, 0],
|
||||
'&' => [2, 5, 2, 5, 3],
|
||||
_ => [0, 0, 0, 0, 0], // space + anything unmapped
|
||||
}
|
||||
}
|
||||
|
||||
// ============================== IS31FL3731 DRIVER (bulk framebuffer) ==============================
|
||||
// Faithful port of pico-scroll/app.py's `Matrix`: keep a 144-byte PWM framebuffer and push the
|
||||
// WHOLE thing in one I2C block write per frame (per-pixel I2C is far too slow to animate). The
|
||||
|
|
@ -559,24 +504,6 @@ fn master_bar_ns(track: &track_format::Track, tempo: i64) -> i64 {
|
|||
beat * beats.max(1)
|
||||
}
|
||||
|
||||
fn build_name_cols(name: &str) -> Vec<u8> {
|
||||
let mut cols = Vec::new();
|
||||
for ch in name.chars() {
|
||||
let g = glyph(ch.to_ascii_uppercase());
|
||||
for c in 0..3 {
|
||||
let mut col = 0u8;
|
||||
for r in 0..5 {
|
||||
if g[r] & (1 << (2 - c)) != 0 {
|
||||
col |= 1 << r;
|
||||
}
|
||||
}
|
||||
cols.push(col);
|
||||
}
|
||||
cols.push(0); // 1px gap between glyphs
|
||||
}
|
||||
cols
|
||||
}
|
||||
|
||||
const SCROLL_GAP: i32 = 13; // blank columns between repeats (>= name region width) for a clean loop
|
||||
|
||||
impl App {
|
||||
|
|
|
|||
Loading…
Reference in a new issue