ssd1675/examples/raspberry_pi_inky_phat.rs
2018-11-14 21:09:04 +11:00

201 lines
6.8 KiB
Rust

// the library for the embedded linux device
extern crate linux_embedded_hal;
use linux_embedded_hal::spidev::{self, SpidevOptions};
use linux_embedded_hal::sysfs_gpio::Direction;
use linux_embedded_hal::Delay;
use linux_embedded_hal::{Pin, Spidev};
// the eink library
extern crate ssd1675;
use ssd1675::{Display, DisplayInterface, Dimensions, GraphicDisplay, Color, Rotation};
// Graphics
extern crate embedded_graphics;
use embedded_graphics::coord::Coord;
use embedded_graphics::fonts::{Font12x16, Font6x8};
use embedded_graphics::prelude::*;
use embedded_graphics::primitives::{Circle, Line};
use embedded_graphics::Drawing;
// HAL (Traits)
extern crate embedded_hal;
use embedded_hal::prelude::*;
// activate spi, gpio in raspi-config
// needs to be run with sudo because of some sysfs_gpio permission problems and follow-up timing problems
// see https://github.com/rust-embedded/rust-sysfs-gpio/issues/5 and follow-up issues
const ROWS: u16 = 212;
const COLS: u8 = 104;
fn main() -> Result<(), std::io::Error> {
// Configure SPI
let mut spi = Spidev::open("/dev/spidev0.0").expect("SPI device");
let options = SpidevOptions::new()
.bits_per_word(8)
.max_speed_hz(4_000_000)
.mode(spidev::SPI_MODE_0)
.build();
spi.configure(&options).expect("SPI configuration");
// https://pinout.xyz/pinout/inky_phat#
// Configure Digital I/O Pin to be used as Chip Select for SPI
let cs = Pin::new(8); // BCM8
cs.export().expect("cs export");
while !cs.is_exported() {}
cs.set_direction(Direction::Out).expect("CS Direction");
cs.set_value(1).expect("CS Value set to 1");
let busy = Pin::new(17); // BCM17
busy.export().expect("busy export");
while !busy.is_exported() {}
busy.set_direction(Direction::In).expect("busy Direction");
let dc = Pin::new(22); // BCM22
dc.export().expect("dc export");
while !dc.is_exported() {}
dc.set_direction(Direction::Out).expect("dc Direction");
dc.set_value(1).expect("dc Value set to 1");
let reset = Pin::new(27); // BCM27
reset.export().expect("reset export");
while !reset.is_exported() {}
reset.set_direction(Direction::Out).expect("reset Direction");
reset.set_value(1).expect("reset Value set to 1");
println!("Pins configured");
let mut delay = Delay {};
let controller = ssd1675::Interface::new(spi, cs, busy, dc, reset);
// println!("Test all the rotations");
let dimensions = Dimensions { rows: ROWS, cols: COLS };
let mut black_buffer = [0u8; ROWS as usize * COLS as usize]; // FIXME: This is using 1 byte per pixel when it only needs to be one bit
let mut red_buffer = [0u8; ROWS as usize * COLS as usize];
let display = Display::new(controller, dimensions, Rotation::Rotate270);
let mut display = GraphicDisplay::new(display, &mut black_buffer, &mut red_buffer);
display.reset(&mut delay).expect("error resetting display");
// display.set_rotation(DisplayRotation::Rotate0);
println!("reset and initialised");
display.clear(Color::White);
println!("clear");
display.draw(
Font12x16::render_str("Hello Rust")
.with_stroke(Some(Color::Red))
.with_fill(Some(Color::White))
.translate(Coord::new(5, 10))
.into_iter(),
);
println!("draw");
display.update(&mut delay).expect("error updating display");
println!("update...");
// display.set_rotation(DisplayRotation::Rotate90);
// display.draw(
// Font::render_str("Rotate 90!")
// .with_stroke(Some(Color::Black))
// .with_fill(Some(Color::White))
// .translate(Coord::new(5, 50))
// .into_iter(),
// );
// display.set_rotation(DisplayRotation::Rotate180);
// display.draw(
// Font6x8::render_str("Rotate 180!")
// .with_stroke(Some(Color::Black))
// .with_fill(Some(Color::White))
// .translate(Coord::new(5, 50))
// .into_iter(),
// );
// display.set_rotation(DisplayRotation::Rotate270);
// display.draw(
// Font6x8::render_str("Rotate 270!")
// .with_stroke(Some(Color::Black))
// .with_fill(Some(Color::White))
// .translate(Coord::new(5, 50))
// .into_iter(),
// );
// epd4in2.update_frame(&mut spi, &display.buffer()).unwrap();
// epd4in2
// .display_frame(&mut spi)
// .expect("display frame new graphics");
// delay.delay_ms(5000u16);
// println!("Now test new graphics with default rotation and some special stuff:");
// display.clear_buffer(Color::White);
// // draw a analog clock
// display.draw(
// Circle::new(Coord::new(64, 64), 64)
// .with_stroke(Some(Color::Black))
// .into_iter(),
// );
// display.draw(
// Line::new(Coord::new(64, 64), Coord::new(0, 64))
// .with_stroke(Some(Color::Black))
// .into_iter(),
// );
// display.draw(
// Line::new(Coord::new(64, 64), Coord::new(80, 80))
// .with_stroke(Some(Color::Black))
// .into_iter(),
// );
// // draw white on black background
// display.draw(
// Font6x8::render_str("It's working-WoB!")
// // Using Style here
// .with_style(Style {
// fill_color: Some(Color::Black),
// stroke_color: Some(Color::White),
// stroke_width: 0u8, // Has no effect on fonts
// })
// .translate(Coord::new(175, 250))
// .into_iter(),
// );
// // use bigger/different font
// display.draw(
// Font12x16::render_str("It's working-BoW!")
// // Using Style here
// .with_style(Style {
// fill_color: Some(Color::White),
// stroke_color: Some(Color::Black),
// stroke_width: 0u8, // Has no effect on fonts
// })
// .translate(Coord::new(50, 200))
// .into_iter(),
// );
// // a moving `Hello World!`
// let limit = 10;
// for i in 0..limit {
// println!("Moving Hello World. Loop {} from {}", (i + 1), limit);
// display.draw(
// Font6x8::render_str(" Hello World! ")
// .with_style(Style {
// fill_color: Some(Color::White),
// stroke_color: Some(Color::Black),
// stroke_width: 0u8, // Has no effect on fonts
// })
// .translate(Coord::new(5 + i * 12, 50))
// .into_iter(),
// );
// epd4in2.update_frame(&mut spi, &display.buffer()).unwrap();
// epd4in2
// .display_frame(&mut spi)
// .expect("display frame new graphics");
// delay.delay_ms(1_000u16);
// }
println!("Finished - going to sleep");
display.deep_sleep()
}