wip text buffer for terminal

This commit is contained in:
2025-06-27 21:23:38 -06:00
parent a687122696
commit 06a158623d
2 changed files with 109 additions and 42 deletions

View File

@@ -2,23 +2,38 @@ use defmt::info;
use embassy_rp::{
gpio::{Level, Output},
peripherals::{PIN_13, PIN_14, PIN_15, SPI1},
spi::{Async, Blocking, Spi},
spi::{Async, Spi},
};
use embassy_time::{Delay, Instant, Timer};
use embassy_time::{Delay, Timer};
use embedded_graphics::{
Drawable, Pixel,
geometry::Dimensions,
mono_font::{MonoTextStyle, ascii::FONT_6X10},
pixelcolor::{Rgb565, raw::RawU16},
prelude::{DrawTarget, OriginDimensions, Point, Primitive, RawData, RgbColor, Size, WebColors},
primitives::{PrimitiveStyle, Rectangle, StyledDrawable},
text::{Alignment, Text, TextStyle},
Drawable,
mono_font::{MonoFont, MonoTextStyle, ascii::FONT_10X20},
pixelcolor::Rgb565,
prelude::{Point, WebColors},
text::{Baseline, Text, TextStyle},
};
use embedded_hal_bus::spi::ExclusiveDevice;
use st7365p_lcd::{FrameBuffer, Orientation, ST7365P};
use st7365p_lcd::{FrameBuffer, ST7365P};
type SPI = Spi<'static, SPI1, Async>;
type FRAMEBUFFER = FrameBuffer<
SCREEN_WIDTH,
SCREEN_HEIGHT,
ExclusiveDevice<Spi<'static, SPI1, Async>, Output<'static>, Delay>,
Output<'static>,
Output<'static>,
>;
const SCREEN_WIDTH: usize = 320;
const SCREEN_HEIGHT: usize = 320;
const SCREEN_ROWS: usize = 15;
const SCREEN_COLS: usize = 31;
const FONT: MonoFont = FONT_10X20;
const COLOR: Rgb565 = Rgb565::CSS_LAWN_GREEN;
#[embassy_executor::task]
pub async fn display_task(spi: Spi<'static, SPI1, Async>, cs: PIN_13, data: PIN_14, reset: PIN_15) {
pub async fn display_task(spi: SPI, cs: PIN_13, data: PIN_14, reset: PIN_15) {
let spi_device = ExclusiveDevice::new(spi, Output::new(cs, Level::Low), Delay).unwrap();
let display = ST7365P::new(
spi_device,
@@ -26,16 +41,10 @@ pub async fn display_task(spi: Spi<'static, SPI1, Async>, cs: PIN_13, data: PIN_
Some(Output::new(reset, Level::High)),
false,
true,
320,
320,
SCREEN_WIDTH as u32,
SCREEN_HEIGHT as u32,
);
let mut framebuffer: FrameBuffer<
320,
320,
ExclusiveDevice<Spi<'static, SPI1, Async>, Output<'_>, Delay>,
Output<'_>,
Output<'_>,
> = FrameBuffer::new(display);
let mut framebuffer: FRAMEBUFFER = FrameBuffer::new(display);
framebuffer.init(&mut Delay).await.unwrap();
framebuffer.display.set_offset(0, 0);
@@ -45,31 +54,88 @@ pub async fn display_task(spi: Spi<'static, SPI1, Async>, cs: PIN_13, data: PIN_
.await
.unwrap();
let t_style = MonoTextStyle::new(&FONT_6X10, Rgb565::BLUE);
Text::with_alignment(
"0, 0\n new line",
Point::new(0, 0),
t_style,
Alignment::Right,
)
.draw(&mut framebuffer)
.unwrap();
Text::new("319, 319", Point { x: 320, y: 300 }, t_style)
.draw(&mut framebuffer)
.unwrap();
Text::with_alignment(
"160, 160",
framebuffer.bounding_box().center(),
t_style,
Alignment::Center,
)
.draw(&mut framebuffer)
.unwrap();
let mut textbuffer = TextBuffer::new();
textbuffer.fill('A');
textbuffer.draw(&mut framebuffer);
info!("finished rendering");
loop {
framebuffer.draw().await.unwrap();
Timer::after_millis(500).await;
}
}
pub struct Cursor {
x: u16,
y: u16,
}
impl Cursor {
fn new(x: u16, y: u16) -> Self {
Self { x, y }
}
}
pub struct TextBuffer {
grid: [[Option<char>; SCREEN_COLS]; SCREEN_ROWS],
cursor: Cursor,
}
impl TextBuffer {
pub fn new() -> Self {
Self {
grid: [[None; SCREEN_COLS]; SCREEN_ROWS],
cursor: Cursor { x: 0, y: 0 },
}
}
/// writes char at cursor
pub fn write_char(&mut self, ch: char) {
for (i, row) in self.grid.iter_mut().enumerate() {
for (j, col) in row.iter_mut().enumerate() {
if i as u16 == self.cursor.x && j as u16 == self.cursor.y {
*col = Some(ch)
}
}
}
}
/// fills text buffer with char
pub fn fill(&mut self, ch: char) {
for i in 0..SCREEN_ROWS {
for j in 0..SCREEN_COLS {
self.cursor = Cursor::new(i as u16, j as u16);
self.write_char(ch);
}
}
}
pub fn scroll_up(&mut self) {
let (top, bottom) = self.grid.split_at_mut(SCREEN_ROWS - 1);
for (dest, src) in top.iter_mut().zip(&bottom[1..]) {
dest.copy_from_slice(src);
}
self.grid[SCREEN_ROWS - 1].fill(None);
}
pub fn draw(&mut self, target: &mut FRAMEBUFFER) {
let baseline = TextStyle::with_baseline(Baseline::Top);
let style = MonoTextStyle::new(&FONT, COLOR);
for (i, row) in self.grid.iter().enumerate() {
for (j, cell) in row.iter().enumerate() {
if let Some(ch) = cell {
let pos = Point::new(
(j as i32) * FONT.character_size.width as i32,
(i as i32) * FONT.character_size.height as i32 + baseline.baseline as i32,
);
Text::new(ch.as_ascii().unwrap().as_str(), pos, style)
.draw(target)
.unwrap();
}
}
}
}
}

View File

@@ -1,4 +1,5 @@
#![feature(impl_trait_in_assoc_type)]
#![feature(ascii_char)]
#![no_std]
#![no_main]