Merge pull request #21 from almusil/do_not_hardcode_size

Do not hardcode display size
This commit is contained in:
Yuri Iozzelli 2020-11-07 12:46:48 +01:00 committed by GitHub
commit 509060bb5d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -34,8 +34,29 @@ pub trait Interface {
) -> Result<(), Self::Error>; ) -> Result<(), Self::Error>;
} }
/// Trait that defines display size information
pub trait DisplaySize {
/// Width in pixels
const WIDTH: usize;
/// Height in pixels
const HEIGHT: usize;
}
/// Generic display size of 240x320 pixels
pub struct DisplaySize240x320;
impl DisplaySize for DisplaySize240x320 {
const WIDTH: usize = 240; const WIDTH: usize = 240;
const HEIGHT: usize = 320; const HEIGHT: usize = 320;
}
/// Generic display size of 320x480 pixels
pub struct DisplaySize320x480;
impl DisplaySize for DisplaySize320x480 {
const WIDTH: usize = 320;
const HEIGHT: usize = 480;
}
#[derive(Debug)] #[derive(Debug)]
pub enum Error<PinE> { pub enum Error<PinE> {
@ -72,6 +93,7 @@ pub struct Ili9341<IFACE, RESET> {
reset: RESET, reset: RESET,
width: usize, width: usize,
height: usize, height: usize,
mode: Orientation,
} }
impl<PinE, IFACE, RESET> Ili9341<IFACE, RESET> impl<PinE, IFACE, RESET> Ili9341<IFACE, RESET>
@ -79,16 +101,23 @@ where
IFACE: WriteOnlyDataCommand, IFACE: WriteOnlyDataCommand,
RESET: OutputPin<Error = PinE>, RESET: OutputPin<Error = PinE>,
{ {
pub fn new<DELAY: DelayMs<u16>>( pub fn new<DELAY, SIZE>(
interface: IFACE, interface: IFACE,
reset: RESET, reset: RESET,
delay: &mut DELAY, delay: &mut DELAY,
) -> Result<Self, Error<PinE>> { mode: Orientation,
_display_size: SIZE,
) -> Result<Self, Error<PinE>>
where
DELAY: DelayMs<u16>,
SIZE: DisplaySize,
{
let mut ili9341 = Ili9341 { let mut ili9341 = Ili9341 {
interface, interface,
reset, reset,
width: WIDTH, width: SIZE::WIDTH,
height: HEIGHT, height: SIZE::HEIGHT,
mode: Orientation::Portrait,
}; };
// Do hardware reset by holding reset low for at least 10us // Do hardware reset by holding reset low for at least 10us
@ -108,7 +137,7 @@ where
// and 120ms before sending Sleep Out // and 120ms before sending Sleep Out
delay.delay_ms(120); delay.delay_ms(120);
ili9341.set_orientation(Orientation::Portrait)?; ili9341.set_orientation(mode)?;
// Set pixel format to 16 bits per pixel // Set pixel format to 16 bits per pixel
ili9341.command(Command::PixelFormatSet, &[0x55])?; ili9341.command(Command::PixelFormatSet, &[0x55])?;
@ -167,7 +196,11 @@ where
fixed_top_lines: u16, fixed_top_lines: u16,
fixed_bottom_lines: u16, fixed_bottom_lines: u16,
) -> Result<Scroller, Error<PinE>> { ) -> Result<Scroller, Error<PinE>> {
let scroll_lines = HEIGHT as u16 - fixed_top_lines - fixed_bottom_lines; let height = match self.mode {
Orientation::Landscape | Orientation::LandscapeFlipped => self.width,
Orientation::Portrait | Orientation::PortraitFlipped => self.height,
} as u16;
let scroll_lines = height as u16 - fixed_top_lines - fixed_bottom_lines;
self.command( self.command(
Command::VerticalScrollDefine, Command::VerticalScrollDefine,
@ -181,7 +214,7 @@ where
], ],
)?; )?;
Ok(Scroller::new(fixed_top_lines, fixed_bottom_lines)) Ok(Scroller::new(fixed_top_lines, fixed_bottom_lines, height))
} }
pub fn scroll_vertically( pub fn scroll_vertically(
@ -189,11 +222,10 @@ where
scroller: &mut Scroller, scroller: &mut Scroller,
num_lines: u16, num_lines: u16,
) -> Result<(), Error<PinE>> { ) -> Result<(), Error<PinE>> {
let height = HEIGHT as u16;
scroller.top_offset += num_lines; scroller.top_offset += num_lines;
if scroller.top_offset > (height - scroller.fixed_bottom_lines) { if scroller.top_offset > (scroller.height - scroller.fixed_bottom_lines) {
scroller.top_offset = scroller.fixed_top_lines scroller.top_offset = scroller.fixed_top_lines
+ (scroller.top_offset - height + scroller.fixed_bottom_lines) + (scroller.top_offset - scroller.height + scroller.fixed_bottom_lines)
} }
self.command( self.command(
@ -249,28 +281,33 @@ where
/// Change the orientation of the screen /// Change the orientation of the screen
pub fn set_orientation(&mut self, mode: Orientation) -> Result<(), Error<PinE>> { pub fn set_orientation(&mut self, mode: Orientation) -> Result<(), Error<PinE>> {
match mode { let was_landscape = match self.mode {
Orientation::Landscape | Orientation::LandscapeFlipped => true,
Orientation::Portrait | Orientation::PortraitFlipped => false,
};
let is_landscape = match mode {
Orientation::Portrait => { Orientation::Portrait => {
self.width = WIDTH; self.command(Command::MemoryAccessControl, &[0x40 | 0x08])?;
self.height = HEIGHT; false
self.command(Command::MemoryAccessControl, &[0x40 | 0x08])
} }
Orientation::Landscape => { Orientation::Landscape => {
self.width = HEIGHT; self.command(Command::MemoryAccessControl, &[0x20 | 0x08])?;
self.height = WIDTH; true
self.command(Command::MemoryAccessControl, &[0x20 | 0x08])
} }
Orientation::PortraitFlipped => { Orientation::PortraitFlipped => {
self.width = WIDTH; self.command(Command::MemoryAccessControl, &[0x80 | 0x08])?;
self.height = HEIGHT; false
self.command(Command::MemoryAccessControl, &[0x80 | 0x08])
} }
Orientation::LandscapeFlipped => { Orientation::LandscapeFlipped => {
self.width = HEIGHT; self.command(Command::MemoryAccessControl, &[0x40 | 0x80 | 0x20 | 0x08])?;
self.height = WIDTH; true
self.command(Command::MemoryAccessControl, &[0x40 | 0x80 | 0x20 | 0x08])
} }
};
if was_landscape ^ is_landscape {
core::mem::swap(&mut self.height, &mut self.width);
} }
self.mode = mode;
Ok(())
} }
/// Get the current screen width. It can change based on the current orientation /// Get the current screen width. It can change based on the current orientation
@ -290,14 +327,16 @@ pub struct Scroller {
top_offset: u16, top_offset: u16,
fixed_bottom_lines: u16, fixed_bottom_lines: u16,
fixed_top_lines: u16, fixed_top_lines: u16,
height: u16,
} }
impl Scroller { impl Scroller {
fn new(fixed_top_lines: u16, fixed_bottom_lines: u16) -> Scroller { fn new(fixed_top_lines: u16, fixed_bottom_lines: u16, height: u16) -> Scroller {
Scroller { Scroller {
top_offset: fixed_top_lines, top_offset: fixed_top_lines,
fixed_top_lines, fixed_top_lines,
fixed_bottom_lines, fixed_bottom_lines,
height,
} }
} }
} }