Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable drawing in three colors for epd2in13 #76

Merged
merged 4 commits into from
Jun 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 28 additions & 25 deletions examples/epd2in13bc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use embedded_hal::prelude::*;
use epd_waveshare::{
color::*,
epd2in13bc::{Display2in13bc, Epd2in13bc},
graphics::{Display, DisplayRotation},
graphics::{DisplayRotation, TriDisplay},
prelude::*,
};
use linux_embedded_hal::{
Expand Down Expand Up @@ -77,7 +77,7 @@ fn main() -> Result<(), std::io::Error> {

println!("Test all the rotations");
let mut display = Display2in13bc::default();
let mut display_chromatic = Display2in13bc::default();
display.clear_buffer(TriColor::White);

display.set_rotation(DisplayRotation::Rotate0);
draw_text(&mut display, "Rotation 0!", 5, 50);
Expand All @@ -91,59 +91,62 @@ fn main() -> Result<(), std::io::Error> {
display.set_rotation(DisplayRotation::Rotate270);
draw_text(&mut display, "Rotation 270!", 5, 50);

// Since we only used black and white, we can resort to updating only
// the bw-buffer of this tri-color screen

epd2in13
.update_and_display_frame(&mut spi, &display.buffer(), &mut delay)
.update_and_display_frame(&mut spi, &display.bw_buffer(), &mut delay)
.expect("display frame new graphics");

println!("First frame done. Waiting 5s");
delay.delay_ms(5000u16);

println!("Now test new graphics with default rotation:");
display.clear_buffer(Color::White);
display_chromatic.clear_buffer(Color::White);
// keep both displays on same rotation
display_chromatic.set_rotation(DisplayRotation::Rotate270);
println!("Now test new graphics with default rotation and three colors:");
display.clear_buffer(TriColor::White);

// draw a analog clock
// draw a analog clock in black
let _ = Circle::new(Point::new(64, 64), 40)
.into_styled(PrimitiveStyle::with_stroke(Black, 1))
.into_styled(PrimitiveStyle::with_stroke(TriColor::Black, 1))
.draw(&mut display);
let _ = Line::new(Point::new(64, 64), Point::new(30, 40))
.into_styled(PrimitiveStyle::with_stroke(Black, 4))
.into_styled(PrimitiveStyle::with_stroke(TriColor::Black, 4))
.draw(&mut display);
let _ = Line::new(Point::new(64, 64), Point::new(80, 40))
.into_styled(PrimitiveStyle::with_stroke(Black, 1))
.into_styled(PrimitiveStyle::with_stroke(TriColor::Black, 1))
.draw(&mut display);

// draw text white on Red background by using the chromatic buffer
// draw text white on chromatic (red or yellow) background

let _ = Text::new("It's working-WoB!", Point::new(90, 10))
.into_styled(text_style!(
font = Font6x8,
text_color = White,
background_color = Black
text_color = TriColor::White,
background_color = TriColor::Chromatic
))
.draw(&mut display_chromatic);
.draw(&mut display);

// use bigger/different font
let _ = Text::new("It's working-WoB!", Point::new(90, 40))
.into_styled(text_style!(
font = Font12x16,
text_color = White,
background_color = Black
text_color = TriColor::White,
background_color = TriColor::Chromatic
))
.draw(&mut display_chromatic);
.draw(&mut display);

epd2in13.update_color_frame(&mut spi, &display.buffer(), &display_chromatic.buffer())?;
// we used three colors, so we need to update both bw-buffer and chromatic-buffer

epd2in13.update_color_frame(&mut spi, display.bw_buffer(), display.chromatic_buffer())?;
epd2in13
.display_frame(&mut spi, &mut delay)
.expect("display frame new graphics");

println!("Second frame done. Waiting 5s");
delay.delay_ms(5000u16);

display.clear_buffer(Color::White);
display_chromatic.clear_buffer(Color::White);
epd2in13.update_color_frame(&mut spi, &display.buffer(), &display_chromatic.buffer())?;
// clear both bw buffer and chromatic buffer
display.clear_buffer(TriColor::White);
epd2in13.update_color_frame(&mut spi, display.bw_buffer(), display.chromatic_buffer())?;
epd2in13.display_frame(&mut spi, &mut delay)?;

println!("Finished tests - going to sleep");
Expand All @@ -154,8 +157,8 @@ fn draw_text(display: &mut Display2in13bc, text: &str, x: i32, y: i32) {
let _ = Text::new(text, Point::new(x, y))
.into_styled(text_style!(
font = Font6x8,
text_color = Black,
background_color = White
text_color = TriColor::Black,
background_color = TriColor::White
))
.draw(display);
}
23 changes: 23 additions & 0 deletions src/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,29 @@ impl From<u8> for Color {
}
}

impl TriColor {
/// Get the color encoding of the color for one bit
pub fn get_bit_value(self) -> u8 {
match self {
TriColor::White => 1u8,
TriColor::Black | TriColor::Chromatic => 0u8,
}
}

/// Gets a full byte of black or white pixels
pub fn get_byte_value(self) -> u8 {
match self {
TriColor::White => 0xff,
TriColor::Black | TriColor::Chromatic => 0x00,
}
}
}

#[cfg(feature = "graphics")]
impl PixelColor for TriColor {
type Raw = ();
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
33 changes: 24 additions & 9 deletions src/epd2in13bc/graphics.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,41 @@
use crate::color::TriColor;
use crate::epd2in13bc::{DEFAULT_BACKGROUND_COLOR, HEIGHT, NUM_DISPLAY_BITS, WIDTH};
use crate::graphics::{Display, DisplayRotation};
use embedded_graphics::pixelcolor::BinaryColor;
use crate::graphics::{DisplayRotation, TriDisplay};
use embedded_graphics::prelude::*;

/// Full size buffer for use with the 2in13b/c EPD
/// Full size buffer for use with the 2.13" b/c EPD
///
/// Can also be manually constructed and be used together with VarDisplay
pub struct Display2in13bc {
buffer: [u8; NUM_DISPLAY_BITS as usize],
// one buffer for both b/w and for chromatic:
// * &buffer[0..NUM_DISPLAY_BITS] for b/w buffer and
// * &buffer[NUM_DISPLAY_BITS..2*NUM_DISPLAY_BITS] for chromatic buffer
buffer: [u8; 2 * NUM_DISPLAY_BITS as usize],
caemor marked this conversation as resolved.
Show resolved Hide resolved
rotation: DisplayRotation,
}

impl Default for Display2in13bc {
fn default() -> Self {
Display2in13bc {
buffer: [DEFAULT_BACKGROUND_COLOR.get_byte_value(); NUM_DISPLAY_BITS as usize],
buffer: [DEFAULT_BACKGROUND_COLOR.get_byte_value(); 2 * NUM_DISPLAY_BITS as usize],
rotation: DisplayRotation::default(),
}
}
}

impl DrawTarget<BinaryColor> for Display2in13bc {
impl DrawTarget<TriColor> for Display2in13bc {
type Error = core::convert::Infallible;

fn draw_pixel(&mut self, pixel: Pixel<BinaryColor>) -> Result<(), Self::Error> {
self.draw_helper(WIDTH, HEIGHT, pixel)
fn draw_pixel(&mut self, pixel: Pixel<TriColor>) -> Result<(), Self::Error> {
self.draw_helper_tri(WIDTH, HEIGHT, pixel)
}

fn size(&self) -> Size {
Size::new(WIDTH, HEIGHT)
}
}

impl Display for Display2in13bc {
impl TriDisplay for Display2in13bc {
fn buffer(&self) -> &[u8] {
&self.buffer
}
Expand All @@ -48,4 +51,16 @@ impl Display for Display2in13bc {
fn rotation(&self) -> DisplayRotation {
self.rotation
}

fn chromatic_offset(&self) -> usize {
NUM_DISPLAY_BITS as usize
}

fn bw_buffer(&self) -> &[u8] {
&self.buffer[0..self.chromatic_offset()]
}

fn chromatic_buffer(&self) -> &[u8] {
&self.buffer[self.chromatic_offset()..]
}
}
45 changes: 20 additions & 25 deletions src/epd2in13bc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@
//!```rust, no_run
//!# use embedded_hal_mock::*;
//!# fn main() -> Result<(), MockError> {
//!use embedded_graphics::{
//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::Line, style::PrimitiveStyle,
//!};
//!use epd_waveshare::{epd2in13bc::*, prelude::*};
//!use embedded_graphics::{prelude::*, primitives::Line, style::PrimitiveStyle};
//!use epd_waveshare::{epd2in13bc::*, prelude::*, color::TriColor};
//!#
//!# let expectations = [];
//!# let mut spi = spi::Mock::new(&expectations);
Expand All @@ -25,28 +23,24 @@
//!let mut epd = Epd2in13bc::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay)?;
//!
//!// Use display graphics from embedded-graphics
//!// This display is for the black/white pixels
//!let mut mono_display = Display2in13bc::default();
//!// This display is for the black/white/chromatic pixels
//!let mut tricolor_display = Display2in13bc::default();
//!
//!// Use embedded graphics for drawing
//!// A black line
//!// Use embedded graphics for drawing a black line
//!let _ = Line::new(Point::new(0, 120), Point::new(0, 200))
//! .into_styled(PrimitiveStyle::with_stroke(Black, 1))
//! .draw(&mut mono_display);
//! .into_styled(PrimitiveStyle::with_stroke(TriColor::Black, 1))
//! .draw(&mut tricolor_display);
//!
//!// Use a second display for red/yellow
//!let mut chromatic_display = Display2in13bc::default();
//!
//!// We use `Black` but it will be shown as red/yellow
//!// We use `chromatic` but it will be shown as red/yellow
//!let _ = Line::new(Point::new(15, 120), Point::new(15, 200))
//! .into_styled(PrimitiveStyle::with_stroke(Black, 1))
//! .draw(&mut chromatic_display);
//! .into_styled(PrimitiveStyle::with_stroke(TriColor::Chromatic, 1))
//! .draw(&mut tricolor_display);
//!
//!// Display updated frame
//!epd.update_color_frame(
//! &mut spi,
//! &mono_display.buffer(),
//! &chromatic_display.buffer()
//! &tricolor_display.bw_buffer(),
//! &tricolor_display.chromatic_buffer()
//!)?;
//!epd.display_frame(&mut spi, &mut delay)?;
//!
Expand All @@ -70,8 +64,9 @@ pub const WIDTH: u32 = 104;
/// Height of epd2in13bc in pixels
pub const HEIGHT: u32 = 212;
/// Default background color (white) of epd2in13bc display
pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White;
pub const DEFAULT_BACKGROUND_COLOR: TriColor = TriColor::White;

/// Number of bits for b/w buffer and same for chromatic buffer
const NUM_DISPLAY_BITS: u32 = WIDTH * HEIGHT / 8;

const IS_BUSY_LOW: bool = true;
Expand All @@ -81,7 +76,7 @@ const BLACK_BORDER: u8 = 0x30;
const CHROMATIC_BORDER: u8 = 0xb0;
const FLOATING_BORDER: u8 = 0xF0;

use crate::color::{Color, TriColor};
use crate::color::TriColor;

pub(crate) mod command;
use self::command::Command;
Expand All @@ -91,10 +86,10 @@ mod graphics;
#[cfg(feature = "graphics")]
pub use self::graphics::Display2in13bc;

/// Epd2in9bc driver
/// Epd2in13bc driver
pub struct Epd2in13bc<SPI, CS, BUSY, DC, RST, DELAY> {
interface: DisplayInterface<SPI, CS, BUSY, DC, RST, DELAY>,
color: Color,
color: TriColor,
}

impl<SPI, CS, BUSY, DC, RST, DELAY> InternalWiAdditions<SPI, CS, BUSY, DC, RST, DELAY>
Expand Down Expand Up @@ -196,7 +191,7 @@ where
RST: OutputPin,
DELAY: DelayMs<u8>,
{
type DisplayColor = Color;
type DisplayColor = TriColor;
fn new(
spi: &mut SPI,
cs: CS,
Expand Down Expand Up @@ -236,11 +231,11 @@ where
self.init(spi, delay)
}

fn set_background_color(&mut self, color: Color) {
fn set_background_color(&mut self, color: TriColor) {
self.color = color;
}

fn background_color(&self) -> &Color {
fn background_color(&self) -> &TriColor {
&self.color
}

Expand Down
Loading