wip text buffer for terminal
This commit is contained in:
150
src/display.rs
150
src/display.rs
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
#![feature(ascii_char)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user