rate-limit scheme error spam to prevent serial log flood

This commit is contained in:
2026-05-28 00:36:17 +03:00
parent 3583ee0186
commit 328d1abbcd
59 changed files with 10063 additions and 25957 deletions
@@ -27,6 +27,9 @@ pub struct DebugDisplay {
}
impl DebugDisplay {
const CHAR_WIDTH: usize = 8;
const CHAR_HEIGHT: usize = 16;
pub(super) fn new(
width: usize,
height: usize,
@@ -40,8 +43,8 @@ impl DebugDisplay {
onscreen_ptr,
};
let w = display.width / 8;
let h = display.height / 16;
let w = display.width / Self::CHAR_WIDTH;
let h = display.height / Self::CHAR_HEIGHT;
DebugDisplay {
display,
x: 0,
@@ -52,11 +55,36 @@ impl DebugDisplay {
}
}
fn scroll_up(&mut self) {
let stride = self.display.stride;
let width = self.display.width;
let total_height = self.display.height;
let scroll_px = Self::CHAR_HEIGHT;
unsafe {
let ptr = self.display.onscreen_ptr;
for row in 0..total_height - scroll_px {
ptr::copy(
ptr.add((row + scroll_px) * stride),
ptr.add(row * stride),
width,
);
}
for row in total_height - scroll_px..total_height {
ptr::write_bytes(ptr.add(row * stride), 0, width);
}
}
}
pub fn write(&mut self, buf: &[u8]) {
for &b in buf {
if self.x >= self.w || b == b'\n' {
self.x = 0;
self.y = (self.y + 1) % self.h;
self.y += 1;
if self.y >= self.h {
self.scroll_up();
self.y = self.h - 1;
}
}
if b == b'\r' {
@@ -64,52 +92,44 @@ impl DebugDisplay {
}
match (b, &self.mode) {
// Byte 0x1B starts ESC sequence
(0x1B, _) => {
self.mode = Mode::Esc;
continue;
}
// Ignore other nonprintable characters
(0x00..=0x1F | 0x80..=0xFF, _) => {
self.mode = Mode::Plain;
continue;
}
// '[' after ESC starts CSI sequence
(b'[', Mode::Esc) => {
self.mode = Mode::Csi;
continue;
}
// Capture any bytes after ESC
(_, Mode::Esc) => {
self.mode = Mode::Plain;
continue;
}
// Byte 0x40 to 0x7E ends CSI
(0x40..=0x7E, Mode::Csi) => {
self.mode = Mode::Plain;
continue;
}
// Capture any bytes after CSI
(_, Mode::Csi) => {
continue;
}
// Allow any other bytes
(_, Mode::Plain) => {}
}
if self.x == 0 {
self.clear_row(self.y);
self.clear_row((self.y + 1) % self.h);
}
self.char(self.x * 8, self.y * 16, b as char, 0xFFFFFF);
self.char(self.x * Self::CHAR_WIDTH, self.y * Self::CHAR_HEIGHT, b as char, 0xFFFFFF);
self.x += 1;
}
}
fn clear_row(&mut self, y: usize) {
for row in y * 16..(y + 1) * 16 {
for row in y * Self::CHAR_HEIGHT..(y + 1) * Self::CHAR_HEIGHT {
unsafe {
ptr::write_bytes(
self.display.onscreen_ptr.add(row * self.display.stride),
@@ -120,36 +140,28 @@ impl DebugDisplay {
}
}
/// Draw a character
fn char(&mut self, x: usize, y: usize, character: char, color: u32) {
if x + 8 <= self.display.width && y + 16 <= self.display.height {
let phys_y = y % self.display.height;
let mut dst = unsafe {
self.display
.onscreen_ptr
.add(phys_y * self.display.stride + x)
};
if x + Self::CHAR_WIDTH > self.display.width || y + Self::CHAR_HEIGHT > self.display.height {
return;
}
let font_i = Self::CHAR_HEIGHT * (character as usize);
if font_i + Self::CHAR_HEIGHT > FONT.len() {
return;
}
let font_i = 16 * (character as usize);
if font_i + 16 <= FONT.len() {
for row in 0..16 {
let row_data = FONT[font_i + row];
for col in 0..8 {
if (row_data >> (7 - col)) & 1 == 1 {
unsafe {
let ptr = self.display.onscreen_ptr;
let stride = self.display.stride;
for row in 0..Self::CHAR_HEIGHT {
let row_data = FONT[font_i + row];
let dst = ptr.add((y + row) * stride + x);
for col in 0..Self::CHAR_WIDTH {
if (row_data >> (Self::CHAR_WIDTH - 1 - col)) & 1 == 1 {
*dst.add(col) = color;
}
}
}
let next_phys_y = (phys_y + row + 1) % self.display.height;
dst = unsafe {
self.display
.onscreen_ptr
.add(next_phys_y * self.display.stride + x)
};
}
}
}
}
}