From 1098b3156c4e7e6fe86b61d32af21615276547c9 Mon Sep 17 00:00:00 2001 From: Gergo ERDI Date: Sun, 18 Dec 2022 18:03:35 +0800 Subject: [PATCH] Upgrade to latest `chirp8-engine` --- chirp8-engine | 2 +- src/framebuffer.rs | 62 ++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 62 +++++++++++++++------------------------------- src/pcd8544.rs | 8 +++--- 4 files changed, 86 insertions(+), 48 deletions(-) create mode 100644 src/framebuffer.rs diff --git a/chirp8-engine b/chirp8-engine index 244f876..51fc76a 160000 --- a/chirp8-engine +++ b/chirp8-engine @@ -1 +1 @@ -Subproject commit 244f8768a053f52c58f473aff3910c7399598bc7 +Subproject commit 51fc76a4d2be6dea781b136aee671d4e76f44b0a diff --git a/src/framebuffer.rs b/src/framebuffer.rs new file mode 100644 index 0000000..0da4781 --- /dev/null +++ b/src/framebuffer.rs @@ -0,0 +1,62 @@ +use pcd8544; +use chirp8::prelude::*; + +const FB_X_START: u8 = (pcd8544::SCREEN_WIDTH - SCREEN_WIDTH) / 2; +const FB_X_END: u8 = FB_X_START + SCREEN_WIDTH; +const FB_Y_START: u8 = (pcd8544::SCREEN_HEIGHT - SCREEN_HEIGHT) / 2; +const FB_Y_END: u8 = FB_Y_START + SCREEN_HEIGHT; + +pub struct FBIter<'a> { + data: &'a [u64; SCREEN_HEIGHT as usize], + x: u8, + y: u8 +} + +impl<'a> FBIter<'a> { + pub fn new(data: &'a [u64; SCREEN_HEIGHT as usize]) -> FBIter<'a> { + FBIter { + data: data, + x: 0, + y: 0 + } + } + + fn stripe(&self) -> u8 { + if self.x < FB_X_START || self.x >= FB_X_END { return 0x00 }; + let x = self.x - FB_X_START; + if self.y < FB_Y_START || self.y >= FB_Y_END { return 0x00 }; + let y = self.y - FB_Y_START; + + let mut stripe = 0x00; + let mask = 1 << (63 - x); + + for i in (y..y+8).rev() { + let row: u64 = self.data[i as usize]; + let pixel = if row & mask == 0 { 0 } else { 1 }; + + stripe = (stripe << 1) | pixel; + } + + stripe + } +} + +impl<'a> Iterator for FBIter<'a> { + type Item = u8; + + fn next(&mut self) -> Option { + if self.x >= pcd8544::SCREEN_WIDTH { + return None + } + + let result = self.stripe(); + + self.y += 8; + if self.y >= pcd8544::SCREEN_HEIGHT { + self.y = 0; + self.x += 1; + } + + Some(result) + } +} diff --git a/src/main.rs b/src/main.rs index 60b4375..75b6687 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,16 +21,18 @@ mod timer; mod keypad; mod serial_ram; mod rom; +mod framebuffer; use rom::*; use timer::sleep_ms; +use framebuffer::FBIter; use chirp8::prelude::*; use chirp8::peripherals::*; struct Board { fb_dirty: bool, - fb_pixels: [[u8; (pcd8544::SCREEN_HEIGHT / 8) as usize]; pcd8544::SCREEN_WIDTH as usize], + fb_rows: [u64; SCREEN_HEIGHT as usize], countdown: u8, prng_state: u16, } @@ -39,7 +41,7 @@ impl Board { pub const fn new() -> Board { Board { fb_dirty: false, - fb_pixels: [[0; (pcd8544::SCREEN_HEIGHT / 8) as usize]; pcd8544::SCREEN_WIDTH as usize], + fb_rows: [0; SCREEN_HEIGHT as usize], countdown: 0, prng_state: 0x0001 } @@ -47,46 +49,18 @@ impl Board { } static mut BOARD: Board = Board::new(); -fn xy_from_chirp8(x: u8, y: u8) -> (u8, u8) { - let dx = (pcd8544::SCREEN_WIDTH - SCREEN_WIDTH) / 2; - let dy = (pcd8544::SCREEN_HEIGHT - SCREEN_HEIGHT) / 2; - (x + dx, y + dy) -} - impl Peripherals for Board { fn keep_running(&self) -> bool { true } - fn clear_pixels(&mut self) { - for col in self.fb_pixels.iter_mut() { - for pixel in col.iter_mut() { - *pixel = 0; - } - } - self.fb_dirty = true + fn get_pixel_row(&self, y: u8) -> u64 { + self.fb_rows[y as usize] } - fn set_pixel(&mut self, x: Byte, y: Byte, v: bool) { - let (x, y) = xy_from_chirp8(x, y); - - let row = y >> 3; - let offset = y - (row << 3); - let mask = 1 << offset; - let bit = (if v {1} else {0}) << offset; - - self.fb_pixels[x as usize][row as usize] = (self.fb_pixels[x as usize][row as usize] & !mask) | bit; + fn set_pixel_row(&mut self, y: u8, row: u64) { + self.fb_rows[y as usize] = row; self.fb_dirty = true; } - fn get_pixel(&self, x: Byte, y: Byte) -> bool { - let (x, y) = xy_from_chirp8(x, y); - - let row = y >> 3; - let offset = y - (row << 3); - let mask = 1 << offset; - - self.fb_pixels[x as usize][row as usize] & mask != 0 - } - fn redraw(&mut self) { // Not really needed? timer will take care of it? } @@ -147,7 +121,7 @@ impl Peripherals for Board { fn redraw(board: &mut Board) { if board.fb_dirty { - pcd8544::send(&board.fb_pixels); + pcd8544::send(FBIter::new(&board.fb_rows)); board.fb_dirty = false; } } @@ -162,19 +136,23 @@ pub fn tick() { fn draw_test_pattern(board: &mut Board) { let dx = (SCREEN_WIDTH - SCREEN_HEIGHT) / 2; - for i in 0..SCREEN_HEIGHT { - board.set_pixel(i + dx, SCREEN_HEIGHT - (i + 1), false); - board.set_pixel(i + dx, i, true); + let mut row: u64 = 1 << 47; + for i in 0..32 { + board.set_pixel_row(i, row); + row >>= 1; } + sleep_ms(500); + let mut row: u64 = 1 << 47; + for i in (0..32).rev() { + board.set_pixel_row(i, row); + row >>= 1; + } sleep_ms(500); for i in 0..SCREEN_HEIGHT { - board.set_pixel(i + dx, SCREEN_HEIGHT - (i + 1), true); - board.set_pixel(i + dx, i, false); + board.set_pixel_row(i, 0) } - sleep_ms(500); - board.clear_pixels(); } #[no_mangle] diff --git a/src/pcd8544.rs b/src/pcd8544.rs index f4e094d..4b3a95f 100644 --- a/src/pcd8544.rs +++ b/src/pcd8544.rs @@ -32,7 +32,7 @@ pub fn setup() { port::D3::set_high(); // Unselect LCD } -pub fn send(pixels: &[[u8; (SCREEN_HEIGHT / 8) as usize]; SCREEN_WIDTH as usize]) { +pub fn send(pixels: I) where I: IntoIterator { port::D3::set_low(); // Chip select LCD port::D5::set_low(); // Set Command mode @@ -41,10 +41,8 @@ pub fn send(pixels: &[[u8; (SCREEN_HEIGHT / 8) as usize]; SCREEN_WIDTH as usize] spi::sync(0x40 | 0); // Set Y address port::D5::set_high(); // Set Data mode - for col in pixels.iter() { - for &pixel in col.iter() { - spi::sync(pixel); - } + for stripe in pixels.into_iter() { + spi::sync(stripe); } port::D3::set_high(); // Unselect LCD