Update embedded-graphics,
remove useless Featuregates (Doesn't change size) Update and integrate a few important examples and remove the othersembedded-hal-1.0
parent
dcaed6fb3e
commit
8da294dd5e
|
|
@ -0,0 +1,35 @@
|
||||||
|
|
||||||
|
name: Rust
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
rust:
|
||||||
|
- stable
|
||||||
|
- beta
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- name: Install ARM toolchain
|
||||||
|
run: rustup target add thumbv7em-none-eabihf
|
||||||
|
- name: Check Fmt
|
||||||
|
run: cargo fmt --all -- --check
|
||||||
|
- name: Build lib
|
||||||
|
run: cargo check --verbose
|
||||||
|
- name: Clippy
|
||||||
|
run: cargo clippy --all-targets --all-features -- -D warnings -A clippy::new_ret_no_self
|
||||||
|
- name: Build examples
|
||||||
|
run: cargo build --examples --verbose
|
||||||
|
#- name: Run tests
|
||||||
|
# run: cargo test --verbose
|
||||||
|
|
||||||
22
.travis.yml
22
.travis.yml
|
|
@ -53,12 +53,9 @@ matrix:
|
||||||
script:
|
script:
|
||||||
- cargo fmt --all -- --check
|
- cargo fmt --all -- --check
|
||||||
- cargo doc --all-features --release
|
- cargo doc --all-features --release
|
||||||
- cd examples/epd4in2_full && cargo fmt --all -- --check && cd ../../
|
- name: "check"
|
||||||
- cd examples/epd2in9_full && cargo fmt --all -- --check && cd ../../
|
script:
|
||||||
- cd examples/epd1in54_full && cargo fmt --all -- --check && cd ../../
|
- cargo check --examples --all-features
|
||||||
- cd examples/epd1in54_no_graphics && cargo fmt --all -- --check && cd ../../
|
|
||||||
- cd examples/epd4in2_var_display_buffer && cargo fmt --all -- --check && cd ../../
|
|
||||||
- cd examples/epd4in2_full_blue_pill && cargo fmt --all -- --check && cd ../../
|
|
||||||
- name: "clippy"
|
- name: "clippy"
|
||||||
rust: stable
|
rust: stable
|
||||||
env: RUN=FMT
|
env: RUN=FMT
|
||||||
|
|
@ -66,19 +63,6 @@ matrix:
|
||||||
- rustup component add clippy
|
- rustup component add clippy
|
||||||
script:
|
script:
|
||||||
- cargo clippy --all-targets --all-features -- -D warnings -A clippy::new_ret_no_self
|
- cargo clippy --all-targets --all-features -- -D warnings -A clippy::new_ret_no_self
|
||||||
|
|
||||||
- name: "check examples"
|
|
||||||
rust: stable
|
|
||||||
before_script:
|
|
||||||
- rustup target add thumbv7m-none-eabi
|
|
||||||
script:
|
|
||||||
- cd examples/epd4in2_full_blue_pill && cargo check && cd ../../
|
|
||||||
- cd examples/epd4in2_full && cargo check && cd ../../
|
|
||||||
- cd examples/epd2in9_full && cargo check && cd ../../
|
|
||||||
- cd examples/epd1in54_full && cargo check && cd ../../
|
|
||||||
- cd examples/epd1in54_no_graphics && cargo check && cd ../../
|
|
||||||
- cd examples/epd4in2_var_display_buffer && cargo check && cd ../../
|
|
||||||
- name
|
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- set -e
|
- set -e
|
||||||
|
|
|
||||||
28
Cargo.toml
28
Cargo.toml
|
|
@ -13,28 +13,20 @@ version = "0.3.2"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
# Travis CI: `repository` in format "<user>/<project>" is required.
|
# travis-ci = { repository = "caemor/epd-waveshare" }
|
||||||
# `branch` is optional; default is `master`
|
|
||||||
travis-ci = { repository = "caemor/epd-waveshare" }
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embedded-graphics = { version = "0.6.0-beta.2", optional = true}
|
embedded-graphics = { version = "0.6.0", optional = true}
|
||||||
|
embedded-hal = {version = "0.2.3", features = ["unproven"]}
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
linux-embedded-hal = "0.3"
|
||||||
|
embedded-hal-mock = "0.7"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["epd1in54", "epd1in54b", "epd2in9", "epd4in2", "epd7in5", "epd7in5_v2", "graphics"]
|
default = ["graphics"]
|
||||||
|
|
||||||
graphics = ["embedded-graphics"]
|
graphics = ["embedded-graphics"]
|
||||||
epd1in54 = []
|
|
||||||
epd1in54b = []
|
# Offers an alternative fast full lut for type_a displays, but the refreshed screen isnt as clean looking
|
||||||
epd2in9 = []
|
|
||||||
epd4in2 = []
|
|
||||||
epd7in5 = []
|
|
||||||
epd7in5_v2 = []
|
|
||||||
# offers an alternative fast full lut for type_a displays, but the refresh isnt as clean looking
|
|
||||||
type_a_alternative_faster_lut = []
|
type_a_alternative_faster_lut = []
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[dependencies.embedded-hal]
|
|
||||||
features = ["unproven"]
|
|
||||||
version = "0.2.3"
|
|
||||||
|
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
# Examples:
|
|
||||||
|
|
||||||
All of these examples are projects of their own.
|
|
||||||
|
|
||||||
A few notes:
|
|
||||||
- If not stated otherwise the example is for a Raspberry Pi running Linux.
|
|
||||||
- epdXinYY_full showcase most of what can be done with this crate. This means that they are using graphics feature and use the DisplayXinYY with its buffer.
|
|
||||||
|
|
||||||
Special Examples:
|
|
||||||
|
|
||||||
### epd4in2_var_display_buffer
|
|
||||||
|
|
||||||
This examples used the graphics feature with VarDisplay and therefore a variable buffer(size).
|
|
||||||
|
|
||||||
### epd1in54_no_graphics (Fastest Example)
|
|
||||||
|
|
||||||
This example doesn't use the graphics feature and handles all the "drawing" by itself. It also has a speeddemonstration included.
|
|
||||||
|
|
||||||
### epd4in2_full_blue_pill
|
|
||||||
|
|
||||||
Connect epd4in2 display to blue pill board:
|
|
||||||
- BUSY -> A10
|
|
||||||
- RST -> A9
|
|
||||||
- DC -> A8
|
|
||||||
- CS -> B12
|
|
||||||
- CLK -> B13
|
|
||||||
- DIN -> B15
|
|
||||||
- GND -> G
|
|
||||||
- VCC -> 3.3
|
|
||||||
|
|
||||||
For compiling and flashing, please refer to [TeXitois blue pill quickstart](https://github.com/TeXitoi/blue-pill-quickstart/blob/master/README.md).
|
|
||||||
|
|
||||||
Basically:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
curl https://sh.rustup.rs -sSf | sh
|
|
||||||
rustup target add thumbv7m-none-eabi
|
|
||||||
sudo apt-get install gdb-arm-none-eabi openocd
|
|
||||||
cd epd4in2_full_blue_pill
|
|
||||||
# connect ST-Link v2 to the blue pill and the computer
|
|
||||||
# openocd in another terminal
|
|
||||||
cargo run --release
|
|
||||||
```
|
|
||||||
|
|
||||||
Ff you can't connect to openocd you might need to adapt your udev rules or use sudo ([openOCD Problems](https://rust-embedded.github.io/discovery/03-setup/linux.html#udev-rules))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "embedded_linux_eink_example"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Christoph Groß <christoph-gross@mailbox.org>"]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
|
|
||||||
epd-waveshare = { path = "../../", default-features = false, features = ["epd1in54", "graphics"]}
|
|
||||||
|
|
||||||
linux-embedded-hal = "0.2.2"
|
|
||||||
embedded-graphics = "0.5.2"
|
|
||||||
embedded-hal = { version = "0.2.2", features = ["unproven"] }
|
|
||||||
|
|
@ -1,150 +0,0 @@
|
||||||
#![deny(warnings)]
|
|
||||||
|
|
||||||
use embedded_graphics::{fonts::Font6x8, prelude::*, Drawing, Point::Point};
|
|
||||||
use embedded_hal::prelude::*;
|
|
||||||
use epd_waveshare::{
|
|
||||||
epd1in54::{Display1in54, EPD1in54},
|
|
||||||
graphics::{Display, DisplayRotation},
|
|
||||||
prelude::*,
|
|
||||||
};
|
|
||||||
use linux_embedded_hal::{
|
|
||||||
spidev::{self, SpidevOptions},
|
|
||||||
sysfs_gpio::Direction,
|
|
||||||
Delay, Pin, Spidev,
|
|
||||||
};
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
if let Err(e) = run() {
|
|
||||||
eprintln!("Program exited early with error: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run() -> Result<(), std::io::Error> {
|
|
||||||
// Configure SPI
|
|
||||||
// SPI settings are from eink-waveshare-rs documenation
|
|
||||||
let mut spi = Spidev::open("/dev/spidev0.0").expect("spidev directory");
|
|
||||||
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");
|
|
||||||
|
|
||||||
// Configure Digital I/O Pin to be used as Chip Select for SPI
|
|
||||||
let cs_pin = Pin::new(26); //BCM7 CE0
|
|
||||||
cs_pin.export().expect("cs_pin export");
|
|
||||||
while !cs_pin.is_exported() {}
|
|
||||||
cs_pin
|
|
||||||
.set_direction(Direction::Out)
|
|
||||||
.expect("cs_pin Direction");
|
|
||||||
cs_pin.set_value(1).expect("cs_pin Value set to 1");
|
|
||||||
|
|
||||||
// Configure Busy Input Pin
|
|
||||||
let busy = Pin::new(5); //pin 29
|
|
||||||
busy.export().expect("busy export");
|
|
||||||
while !busy.is_exported() {}
|
|
||||||
busy.set_direction(Direction::In).expect("busy Direction");
|
|
||||||
//busy.set_value(1).expect("busy Value set to 1");
|
|
||||||
|
|
||||||
// Configure Data/Command OutputPin
|
|
||||||
let dc = Pin::new(6); //pin 31 //bcm6
|
|
||||||
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");
|
|
||||||
|
|
||||||
// Configure Reset OutputPin
|
|
||||||
let rst = Pin::new(16); //pin 36 //bcm16
|
|
||||||
rst.export().expect("rst export");
|
|
||||||
while !rst.is_exported() {}
|
|
||||||
rst.set_direction(Direction::Out).expect("rst Direction");
|
|
||||||
rst.set_value(1).expect("rst Value set to 1");
|
|
||||||
|
|
||||||
// Configure Delay
|
|
||||||
let mut delay = Delay {};
|
|
||||||
|
|
||||||
// Setup of the needed pins is finished here
|
|
||||||
// Now the "real" usage of the eink-waveshare-rs crate begins
|
|
||||||
let mut epd = EPD1in54::new(&mut spi, cs_pin, busy, dc, rst, &mut delay)?;
|
|
||||||
|
|
||||||
// Clear the full screen
|
|
||||||
epd.clear_frame(&mut spi).expect("clear frame 1");
|
|
||||||
epd.display_frame(&mut spi).expect("disp 1");
|
|
||||||
|
|
||||||
println!("Test all the rotations");
|
|
||||||
let mut display = Display1in54::default();
|
|
||||||
display.set_rotation(DisplayRotation::Rotate0);
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("Rotate 0!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
display.set_rotation(DisplayRotation::Rotate90);
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("Rotate 90!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
display.set_rotation(DisplayRotation::Rotate180);
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("Rotate 180!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
display.set_rotation(DisplayRotation::Rotate270);
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("Rotate 270!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Display updated frame
|
|
||||||
epd.update_frame(&mut spi, &display.buffer()).unwrap();
|
|
||||||
epd.display_frame(&mut spi)
|
|
||||||
.expect("display frame new graphics");
|
|
||||||
delay.delay_ms(5000u16);
|
|
||||||
|
|
||||||
// a quickly moving `Hello World!`
|
|
||||||
display.set_rotation(DisplayRotation::Rotate0);
|
|
||||||
epd.set_lut(&mut spi, Some(RefreshLUT::QUICK))
|
|
||||||
.expect("SET LUT QUICK error");
|
|
||||||
let limit = 20;
|
|
||||||
for i in 0..limit {
|
|
||||||
println!("Moving Hello World. Loop {} from {}", (i + 1), limit);
|
|
||||||
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str(" Hello World! ")
|
|
||||||
.style(Style {
|
|
||||||
fill_color: Some(Color::White),
|
|
||||||
stroke_color: Some(Color::Black),
|
|
||||||
stroke_width: 0u8, // Has no effect on fonts
|
|
||||||
})
|
|
||||||
.translate(Point::new(5 + i * 6, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
epd.update_frame(&mut spi, &display.buffer()).unwrap();
|
|
||||||
epd.display_frame(&mut spi)
|
|
||||||
.expect("display frame new graphics");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the EPD to sleep
|
|
||||||
epd.sleep(&mut spi).expect("sleep");
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
@ -12,20 +12,14 @@ use linux_embedded_hal::{
|
||||||
// needs to be run with sudo because of some sysfs_gpio permission problems and follow-up timing problems
|
// 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
|
// see https://github.com/rust-embedded/rust-sysfs-gpio/issues/5 and follow-up issues
|
||||||
|
|
||||||
fn main() {
|
fn main() -> Result<(), std::io::Error> {
|
||||||
if let Err(e) = run() {
|
|
||||||
eprintln!("Program exited early with error: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run() -> Result<(), std::io::Error> {
|
|
||||||
// Configure SPI
|
// Configure SPI
|
||||||
// SPI settings are from eink-waveshare-rs documenation
|
// SPI settings are from eink-waveshare-rs documenation
|
||||||
let mut spi = Spidev::open("/dev/spidev0.0")?;
|
let mut spi = Spidev::open("/dev/spidev0.0")?;
|
||||||
let options = SpidevOptions::new()
|
let options = SpidevOptions::new()
|
||||||
.bits_per_word(8)
|
.bits_per_word(8)
|
||||||
.max_speed_hz(4_000_000)
|
.max_speed_hz(4_000_000)
|
||||||
.mode(spidev::SPI_MODE_0)
|
.mode(spidev::SpiModeFlags::SPI_MODE_0)
|
||||||
.build();
|
.build();
|
||||||
spi.configure(&options).expect("spi configuration");
|
spi.configure(&options).expect("spi configuration");
|
||||||
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "embedded_linux_eink_example"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Christoph Groß <christoph-gross@mailbox.org>"]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
|
|
||||||
epd-waveshare = { path = "../../", default-features = false, features = ["epd1in54"]}
|
|
||||||
|
|
||||||
linux-embedded-hal = "0.2.2"
|
|
||||||
embedded-hal = { version = "0.2.2", features = ["unproven"] }
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "embedded_linux_eink_example"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Christoph Groß <christoph-gross@mailbox.org>"]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
|
|
||||||
epd-waveshare = { path = "../../", default-features = false, features = ["epd2in9", "graphics"]}
|
|
||||||
|
|
||||||
linux-embedded-hal = "0.2.2"
|
|
||||||
embedded-graphics = "0.5.2"
|
|
||||||
embedded-hal = { version = "0.2.2", features = ["unproven"] }
|
|
||||||
|
|
@ -1,154 +0,0 @@
|
||||||
#![deny(warnings)]
|
|
||||||
|
|
||||||
use embedded_graphics::{fonts::Font6x8, prelude::*, Drawing, Point::Point};
|
|
||||||
use embedded_hal::prelude::*;
|
|
||||||
use epd_waveshare::{
|
|
||||||
epd2in9::{Display2in9, EPD2in9},
|
|
||||||
graphics::{Display, DisplayRotation},
|
|
||||||
prelude::*,
|
|
||||||
};
|
|
||||||
use linux_embedded_hal::{
|
|
||||||
spidev::{self, SpidevOptions},
|
|
||||||
sysfs_gpio::Direction,
|
|
||||||
Delay, Pin, Spidev,
|
|
||||||
};
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
//TODO: Test this implemenation with a new display
|
|
||||||
fn main() {
|
|
||||||
if let Err(e) = run() {
|
|
||||||
eprintln!("Program exited early with error: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run() -> Result<(), std::io::Error> {
|
|
||||||
// Configure SPI
|
|
||||||
// SPI settings are from eink-waveshare-rs documenation
|
|
||||||
let mut spi = Spidev::open("/dev/spidev0.0").expect("spidev directory");
|
|
||||||
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");
|
|
||||||
|
|
||||||
// Configure Digital I/O Pin to be used as Chip Select for SPI
|
|
||||||
let cs_pin = Pin::new(26); //BCM7 CE0
|
|
||||||
cs_pin.export().expect("cs_pin export");
|
|
||||||
while !cs_pin.is_exported() {}
|
|
||||||
cs_pin
|
|
||||||
.set_direction(Direction::Out)
|
|
||||||
.expect("cs_pin Direction");
|
|
||||||
cs_pin.set_value(1).expect("cs_pin Value set to 1");
|
|
||||||
|
|
||||||
// Configure Busy Input Pin
|
|
||||||
let busy = Pin::new(5); //pin 29
|
|
||||||
busy.export().expect("busy export");
|
|
||||||
while !busy.is_exported() {}
|
|
||||||
busy.set_direction(Direction::In).expect("busy Direction");
|
|
||||||
//busy.set_value(1).expect("busy Value set to 1");
|
|
||||||
|
|
||||||
// Configure Data/Command OutputPin
|
|
||||||
let dc = Pin::new(6); //pin 31 //bcm6
|
|
||||||
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");
|
|
||||||
|
|
||||||
// Configure Reset OutputPin
|
|
||||||
let rst = Pin::new(16); //pin 36 //bcm16
|
|
||||||
rst.export().expect("rst export");
|
|
||||||
while !rst.is_exported() {}
|
|
||||||
rst.set_direction(Direction::Out).expect("rst Direction");
|
|
||||||
rst.set_value(1).expect("rst Value set to 1");
|
|
||||||
|
|
||||||
// Configure Delay
|
|
||||||
let mut delay = Delay {};
|
|
||||||
|
|
||||||
// Setup of the needed pins is finished here
|
|
||||||
// Now the "real" usage of the eink-waveshare-rs crate begins
|
|
||||||
let mut epd = EPD2in9::new(&mut spi, cs_pin, busy, dc, rst, &mut delay)?;
|
|
||||||
|
|
||||||
// Clear the full screen
|
|
||||||
epd.clear_frame(&mut spi).expect("clear frame 1");
|
|
||||||
epd.display_frame(&mut spi).expect("disp 1");
|
|
||||||
|
|
||||||
println!("Test all the rotations");
|
|
||||||
let mut display = Display2in9::default();
|
|
||||||
epd.update_frame(&mut spi, display.buffer()).unwrap();
|
|
||||||
epd.display_frame(&mut spi).expect("display frame x03");
|
|
||||||
|
|
||||||
display.set_rotation(DisplayRotation::Rotate0);
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("Rotate 0!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
display.set_rotation(DisplayRotation::Rotate90);
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("Rotate 90!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
display.set_rotation(DisplayRotation::Rotate180);
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("Rotate 180!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
display.set_rotation(DisplayRotation::Rotate270);
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("Rotate 270!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Display updated frame
|
|
||||||
epd.update_frame(&mut spi, &display.buffer()).unwrap();
|
|
||||||
epd.display_frame(&mut spi)
|
|
||||||
.expect("display frame new graphics");
|
|
||||||
delay.delay_ms(5000u16);
|
|
||||||
|
|
||||||
// a quickly moving `Hello World!`
|
|
||||||
display.set_rotation(DisplayRotation::Rotate0);
|
|
||||||
epd.set_lut(&mut spi, Some(RefreshLUT::QUICK))
|
|
||||||
.expect("SET LUT QUICK error");
|
|
||||||
let limit = 20;
|
|
||||||
for i in 0..limit {
|
|
||||||
println!("Moving Hello World. Loop {} from {}", (i + 1), limit);
|
|
||||||
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str(" Hello World! ")
|
|
||||||
.style(Style {
|
|
||||||
fill_color: Some(Color::White),
|
|
||||||
stroke_color: Some(Color::Black),
|
|
||||||
stroke_width: 0u8, // Has no effect on fonts
|
|
||||||
})
|
|
||||||
.translate(Point::new(5 + i * 6, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
epd.update_frame(&mut spi, &display.buffer()).unwrap();
|
|
||||||
epd.display_frame(&mut spi)
|
|
||||||
.expect("display frame new graphics");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the EPD to sleep
|
|
||||||
epd.sleep(&mut spi).expect("sleep");
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
@ -1,72 +1,69 @@
|
||||||
#![no_main]
|
#![deny(warnings)]
|
||||||
#![no_std]
|
|
||||||
|
|
||||||
// set the panic handler
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
use panic_semihosting;
|
|
||||||
|
|
||||||
use cortex_m_rt::entry;
|
|
||||||
use stm32f1xx_hal::prelude::*;
|
|
||||||
use stm32f1xx_hal::{delay, spi};
|
|
||||||
|
|
||||||
use embedded_graphics::{
|
use embedded_graphics::{
|
||||||
fonts::{Font12x16, Font6x8, Text},
|
fonts::{Font12x16, Font6x8, Text},
|
||||||
pixelcolor::BinaryColor,
|
|
||||||
prelude::*,
|
prelude::*,
|
||||||
primitives::{Circle, Line},
|
primitives::{Circle, Line},
|
||||||
style::{PrimitiveStyle, Styled},
|
style::PrimitiveStyle,
|
||||||
text_style, DrawTarget,
|
text_style,
|
||||||
};
|
};
|
||||||
|
use embedded_hal::prelude::*;
|
||||||
use epd_waveshare::{
|
use epd_waveshare::{
|
||||||
color::*,
|
color::*,
|
||||||
epd4in2::Display4in2,
|
epd4in2::{Display4in2, EPD4in2},
|
||||||
graphics::{Display, DisplayRotation},
|
graphics::{Display, DisplayRotation},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
|
use linux_embedded_hal::{
|
||||||
|
spidev::{self, SpidevOptions},
|
||||||
|
sysfs_gpio::Direction,
|
||||||
|
Delay, Pin, Spidev,
|
||||||
|
};
|
||||||
|
|
||||||
#[entry]
|
// activate spi, gpio in raspi-config
|
||||||
fn main() -> ! {
|
// needs to be run with sudo because of some sysfs_gpio permission problems and follow-up timing problems
|
||||||
let core = cortex_m::Peripherals::take().unwrap();
|
// see https://github.com/rust-embedded/rust-sysfs-gpio/issues/5 and follow-up issues
|
||||||
let device = stm32f1xx_hal::stm32::Peripherals::take().unwrap();
|
|
||||||
let mut rcc = device.RCC.constrain();
|
|
||||||
let mut flash = device.FLASH.constrain();
|
|
||||||
|
|
||||||
let clocks = rcc
|
fn main() -> Result<(), std::io::Error> {
|
||||||
.cfgr
|
// Configure SPI
|
||||||
.use_hse(8.mhz())
|
// Settings are taken from
|
||||||
.sysclk(72.mhz())
|
let mut spi = Spidev::open("/dev/spidev0.0").expect("spidev directory");
|
||||||
.pclk1(36.mhz())
|
let options = SpidevOptions::new()
|
||||||
.freeze(&mut flash.acr);
|
.bits_per_word(8)
|
||||||
|
.max_speed_hz(4_000_000)
|
||||||
|
.mode(spidev::SpiModeFlags::SPI_MODE_0)
|
||||||
|
.build();
|
||||||
|
spi.configure(&options).expect("spi configuration");
|
||||||
|
|
||||||
let mut gpioa = device.GPIOA.split(&mut rcc.apb2);
|
// Configure Digital I/O Pin to be used as Chip Select for SPI
|
||||||
let mut gpiob = device.GPIOB.split(&mut rcc.apb2);
|
let cs = Pin::new(26); //BCM7 CE0
|
||||||
|
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 mut delay = delay::Delay::new(core.SYST, clocks);
|
let busy = Pin::new(5); //pin 29
|
||||||
|
busy.export().expect("busy export");
|
||||||
|
while !busy.is_exported() {}
|
||||||
|
busy.set_direction(Direction::In).expect("busy Direction");
|
||||||
|
//busy.set_value(1).expect("busy Value set to 1");
|
||||||
|
|
||||||
// spi setup
|
let dc = Pin::new(6); //pin 31 //bcm6
|
||||||
let sck = gpiob.pb13.into_alternate_push_pull(&mut gpiob.crh);
|
dc.export().expect("dc export");
|
||||||
let miso = gpiob.pb14;
|
while !dc.is_exported() {}
|
||||||
let mosi = gpiob.pb15.into_alternate_push_pull(&mut gpiob.crh);
|
dc.set_direction(Direction::Out).expect("dc Direction");
|
||||||
let mut spi = spi::Spi::spi2(
|
dc.set_value(1).expect("dc Value set to 1");
|
||||||
device.SPI2,
|
|
||||||
(sck, miso, mosi),
|
let rst = Pin::new(16); //pin 36 //bcm16
|
||||||
epd_waveshare::SPI_MODE,
|
rst.export().expect("rst export");
|
||||||
4.mhz(),
|
while !rst.is_exported() {}
|
||||||
clocks,
|
rst.set_direction(Direction::Out).expect("rst Direction");
|
||||||
&mut rcc.apb1,
|
rst.set_value(1).expect("rst Value set to 1");
|
||||||
);
|
|
||||||
// epd setup
|
let mut delay = Delay {};
|
||||||
let mut epd4in2 = epd_waveshare::epd4in2::EPD4in2::new(
|
|
||||||
&mut spi,
|
let mut epd4in2 =
|
||||||
gpiob.pb12.into_push_pull_output(&mut gpiob.crh),
|
EPD4in2::new(&mut spi, cs, busy, dc, rst, &mut delay).expect("eink initalize error");
|
||||||
gpioa.pa10.into_floating_input(&mut gpioa.crh),
|
|
||||||
gpioa.pa8.into_push_pull_output(&mut gpioa.crh),
|
|
||||||
gpioa.pa9.into_push_pull_output(&mut gpioa.crh),
|
|
||||||
&mut delay,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
epd4in2.set_lut(&mut spi, Some(RefreshLUT::QUICK)).unwrap();
|
|
||||||
epd4in2.clear_frame(&mut spi).unwrap();
|
|
||||||
|
|
||||||
//println!("Test all the rotations");
|
//println!("Test all the rotations");
|
||||||
let mut display = Display4in2::default();
|
let mut display = Display4in2::default();
|
||||||
|
|
@ -83,7 +80,7 @@ fn main() -> ! {
|
||||||
display.set_rotation(DisplayRotation::Rotate270);
|
display.set_rotation(DisplayRotation::Rotate270);
|
||||||
draw_text(&mut display, "Rotate 270!", 5, 50);
|
draw_text(&mut display, "Rotate 270!", 5, 50);
|
||||||
|
|
||||||
epd4in2.update_frame(&mut spi, &display.buffer()).unwrap();
|
epd4in2.update_frame(&mut spi, &display.buffer())?;
|
||||||
epd4in2
|
epd4in2
|
||||||
.display_frame(&mut spi)
|
.display_frame(&mut spi)
|
||||||
.expect("display frame new graphics");
|
.expect("display frame new graphics");
|
||||||
|
|
@ -93,13 +90,13 @@ fn main() -> ! {
|
||||||
display.clear_buffer(Color::White);
|
display.clear_buffer(Color::White);
|
||||||
|
|
||||||
// draw a analog clock
|
// draw a analog clock
|
||||||
Circle::new(Point::new(64, 64), 64)
|
let _ = Circle::new(Point::new(64, 64), 64)
|
||||||
.into_styled(PrimitiveStyle::with_stroke(Black, 1))
|
.into_styled(PrimitiveStyle::with_stroke(Black, 1))
|
||||||
.draw(&mut display);
|
.draw(&mut display);
|
||||||
Line::new(Point::new(64, 64), Point::new(0, 64))
|
let _ = Line::new(Point::new(64, 64), Point::new(0, 64))
|
||||||
.into_styled(PrimitiveStyle::with_stroke(Black, 1))
|
.into_styled(PrimitiveStyle::with_stroke(Black, 1))
|
||||||
.draw(&mut display);
|
.draw(&mut display);
|
||||||
Line::new(Point::new(64, 64), Point::new(80, 80))
|
let _ = Line::new(Point::new(64, 64), Point::new(80, 80))
|
||||||
.into_styled(PrimitiveStyle::with_stroke(Black, 1))
|
.into_styled(PrimitiveStyle::with_stroke(Black, 1))
|
||||||
.draw(&mut display);
|
.draw(&mut display);
|
||||||
|
|
||||||
|
|
@ -138,13 +135,8 @@ fn main() -> ! {
|
||||||
delay.delay_ms(1_000u16);
|
delay.delay_ms(1_000u16);
|
||||||
}
|
}
|
||||||
|
|
||||||
//println!("Finished tests - going to sleep");
|
println!("Finished tests - going to sleep");
|
||||||
epd4in2.sleep(&mut spi).expect("epd goes to sleep");
|
epd4in2.sleep(&mut spi)
|
||||||
|
|
||||||
loop {
|
|
||||||
// sleep
|
|
||||||
cortex_m::asm::wfi();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_text(display: &mut Display4in2, text: &str, x: i32, y: i32) {
|
fn draw_text(display: &mut Display4in2, text: &str, x: i32, y: i32) {
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "embedded_linux_eink_example"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Christoph Groß <christoph-gross@mailbox.org>"]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
|
|
||||||
## The Only difference between this one and the one without default features sizewise seems to be a different .d-file Size (dependencies-file)
|
|
||||||
#epd_waveshare = { path = "../../"}
|
|
||||||
epd-waveshare = { path = "../../", default-features = false, features = ["epd4in2", "graphics"]}
|
|
||||||
|
|
||||||
linux-embedded-hal = "0.2.2"
|
|
||||||
embedded-graphics = "0.5.2"
|
|
||||||
embedded-hal = { version = "0.2.2", features = ["unproven"] }
|
|
||||||
|
|
@ -1,189 +0,0 @@
|
||||||
#![deny(warnings)]
|
|
||||||
|
|
||||||
use embedded_graphics::{
|
|
||||||
fonts::{Font12x16, Font6x8},
|
|
||||||
prelude::*,
|
|
||||||
primitives::{Circle, Line},
|
|
||||||
Drawing,
|
|
||||||
Point::Point,
|
|
||||||
};
|
|
||||||
use embedded_hal::prelude::*;
|
|
||||||
use epd_waveshare::{
|
|
||||||
epd4in2::{Display4in2, EPD4in2},
|
|
||||||
graphics::{Display, DisplayRotation},
|
|
||||||
prelude::*,
|
|
||||||
};
|
|
||||||
use linux_embedded_hal::{
|
|
||||||
spidev::{self, SpidevOptions},
|
|
||||||
sysfs_gpio::Direction,
|
|
||||||
Delay, Pin, Spidev,
|
|
||||||
};
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
if let Err(e) = run() {
|
|
||||||
eprintln!("Program exited early with error: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run() -> Result<(), std::io::Error> {
|
|
||||||
// Configure SPI
|
|
||||||
// Settings are taken from
|
|
||||||
let mut spi = Spidev::open("/dev/spidev0.0").expect("spidev directory");
|
|
||||||
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");
|
|
||||||
|
|
||||||
// Configure Digital I/O Pin to be used as Chip Select for SPI
|
|
||||||
let cs = Pin::new(26); //BCM7 CE0
|
|
||||||
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(5); //pin 29
|
|
||||||
busy.export().expect("busy export");
|
|
||||||
while !busy.is_exported() {}
|
|
||||||
busy.set_direction(Direction::In).expect("busy Direction");
|
|
||||||
//busy.set_value(1).expect("busy Value set to 1");
|
|
||||||
|
|
||||||
let dc = Pin::new(6); //pin 31 //bcm6
|
|
||||||
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 rst = Pin::new(16); //pin 36 //bcm16
|
|
||||||
rst.export().expect("rst export");
|
|
||||||
while !rst.is_exported() {}
|
|
||||||
rst.set_direction(Direction::Out).expect("rst Direction");
|
|
||||||
rst.set_value(1).expect("rst Value set to 1");
|
|
||||||
|
|
||||||
let mut delay = Delay {};
|
|
||||||
|
|
||||||
let mut epd4in2 =
|
|
||||||
EPD4in2::new(&mut spi, cs, busy, dc, rst, &mut delay).expect("eink initalize error");
|
|
||||||
|
|
||||||
println!("Test all the rotations");
|
|
||||||
let mut display = Display4in2::default();
|
|
||||||
display.set_rotation(DisplayRotation::Rotate0);
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("Rotate 0!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
display.set_rotation(DisplayRotation::Rotate90);
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("Rotate 90!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
display.set_rotation(DisplayRotation::Rotate180);
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("Rotate 180!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
display.set_rotation(DisplayRotation::Rotate270);
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("Rotate 270!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::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(Point::new(64, 64), 64)
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
display.draw(
|
|
||||||
let _ = Line::new(Point::new(64, 64), Point::new(0, 64))
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
display.draw(
|
|
||||||
let _ = Line::new(Point::new(64, 64), Point::new(80, 80))
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// draw white on black background
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("It's working-WoB!")
|
|
||||||
// Using Style here
|
|
||||||
.style(Style {
|
|
||||||
fill_color: Some(Color::Black),
|
|
||||||
stroke_color: Some(Color::White),
|
|
||||||
stroke_width: 0u8, // Has no effect on fonts
|
|
||||||
})
|
|
||||||
.translate(Point::new(175, 250))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// use bigger/different font
|
|
||||||
display.draw(
|
|
||||||
Font12x16::render_str("It's working-BoW!")
|
|
||||||
// Using Style here
|
|
||||||
.style(Style {
|
|
||||||
fill_color: Some(Color::White),
|
|
||||||
stroke_color: Some(Color::Black),
|
|
||||||
stroke_width: 0u8, // Has no effect on fonts
|
|
||||||
})
|
|
||||||
.translate(Point::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! ")
|
|
||||||
.style(Style {
|
|
||||||
fill_color: Some(Color::White),
|
|
||||||
stroke_color: Some(Color::Black),
|
|
||||||
stroke_width: 0u8, // Has no effect on fonts
|
|
||||||
})
|
|
||||||
.translate(Point::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 tests - going to sleep");
|
|
||||||
epd4in2.sleep(&mut spi)
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
[target.thumbv7m-none-eabi]
|
|
||||||
|
|
||||||
# uncomment ONE of these three option to make `cargo run` start a GDB session
|
|
||||||
# which option to pick depends on your system
|
|
||||||
runner = "arm-none-eabi-gdb -q -x openocd.gdb"
|
|
||||||
# runner = "gdb-multiarch -q -x openocd.gdb"
|
|
||||||
# runner = "gdb -q -x openocd.gdb"
|
|
||||||
|
|
||||||
rustflags = ["-C", "link-arg=-Tlink.x"]
|
|
||||||
|
|
||||||
[build]
|
|
||||||
target = "thumbv7m-none-eabi"
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "embedded_linux_eink_example"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Christoph Groß <christoph-gross@mailbox.org>"]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
|
|
||||||
## The Only difference between this one and the one without default features sizewise seems to be a different .d-file Size (dependencies-file)
|
|
||||||
#epd_waveshare = { path = "../../"}
|
|
||||||
epd-waveshare = { path = "../../", default-features = false, features = ["epd4in2", "graphics"]}
|
|
||||||
|
|
||||||
embedded-graphics = "0.6.0-beta.2"
|
|
||||||
embedded-hal = { version = "0.2.3", features = ["unproven"] }
|
|
||||||
|
|
||||||
stm32f1xx-hal = { version = "0.2", features = ["rt", "stm32f103" ] }
|
|
||||||
cortex-m = "0.5.0"
|
|
||||||
cortex-m-rt = { version = "0.6.6", features = ["device"] }
|
|
||||||
panic-semihosting = "0.5"
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
/* Linker script for the STM32F103C8T6 */
|
|
||||||
MEMORY
|
|
||||||
{
|
|
||||||
FLASH : ORIGIN = 0x08000000, LENGTH = 64K
|
|
||||||
RAM : ORIGIN = 0x20000000, LENGTH = 20K
|
|
||||||
}
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
source [find interface/stlink-v2.cfg]
|
|
||||||
source [find target/stm32f1x.cfg]
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
target remote :3333
|
|
||||||
set print asm-demangle on
|
|
||||||
monitor arm semihosting enable
|
|
||||||
|
|
||||||
# detect unhandled exceptions, hard faults and panics
|
|
||||||
break DefaultHandler
|
|
||||||
break HardFault
|
|
||||||
break rust_begin_unwind
|
|
||||||
|
|
||||||
load
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "embedded_linux_eink_example"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Christoph Groß <christoph-gross@mailbox.org>"]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
|
|
||||||
## The Only difference between this one and the one without default features sizewise seems to be a different .d-file Size (dependencies-file)
|
|
||||||
#epd_waveshare = { path = "../../"}
|
|
||||||
epd-waveshare = { path = "../../", default-features = false, features = ["epd4in2", "graphics"]}
|
|
||||||
|
|
||||||
linux-embedded-hal = "0.2.2"
|
|
||||||
embedded-graphics = "0.5.2"
|
|
||||||
embedded-hal = { version = "0.2.2", features = ["unproven"] }
|
|
||||||
|
|
@ -1,14 +1,16 @@
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
|
#![deny(warnings)]
|
||||||
|
|
||||||
use embedded_graphics::{
|
use embedded_graphics::{
|
||||||
fonts::{Font12x16, Font6x8},
|
fonts::{Font12x16, Font6x8, Text},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
primitives::{Circle, Line},
|
primitives::{Circle, Line},
|
||||||
Drawing,
|
style::PrimitiveStyle,
|
||||||
Point::Point,
|
text_style,
|
||||||
};
|
};
|
||||||
use embedded_hal::prelude::*;
|
use embedded_hal::prelude::*;
|
||||||
use epd_waveshare::{
|
use epd_waveshare::{
|
||||||
|
color::*,
|
||||||
epd4in2::{self, EPD4in2},
|
epd4in2::{self, EPD4in2},
|
||||||
graphics::{Display, DisplayRotation, VarDisplay},
|
graphics::{Display, DisplayRotation, VarDisplay},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
|
|
@ -23,20 +25,14 @@ use linux_embedded_hal::{
|
||||||
// needs to be run with sudo because of some sysfs_gpio permission problems and follow-up timing problems
|
// 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
|
// see https://github.com/rust-embedded/rust-sysfs-gpio/issues/5 and follow-up issues
|
||||||
|
|
||||||
fn main() {
|
fn main() -> Result<(), std::io::Error> {
|
||||||
if let Err(e) = run() {
|
|
||||||
eprintln!("Program exited early with error: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run() -> Result<(), std::io::Error> {
|
|
||||||
// Configure SPI
|
// Configure SPI
|
||||||
// Settings are taken from
|
// Settings are taken from
|
||||||
let mut spi = Spidev::open("/dev/spidev0.0").expect("spidev directory");
|
let mut spi = Spidev::open("/dev/spidev0.0").expect("spidev directory");
|
||||||
let options = SpidevOptions::new()
|
let options = SpidevOptions::new()
|
||||||
.bits_per_word(8)
|
.bits_per_word(8)
|
||||||
.max_speed_hz(4_000_000)
|
.max_speed_hz(4_000_000)
|
||||||
.mode(spidev::SPI_MODE_0)
|
.mode(spidev::SpiModeFlags::SPI_MODE_0)
|
||||||
.build();
|
.build();
|
||||||
spi.configure(&options).expect("spi configuration");
|
spi.configure(&options).expect("spi configuration");
|
||||||
|
|
||||||
|
|
@ -77,40 +73,16 @@ fn run() -> Result<(), std::io::Error> {
|
||||||
let mut buffer = [epd4in2::DEFAULT_BACKGROUND_COLOR.get_byte_value(); 62500]; //250*250
|
let mut buffer = [epd4in2::DEFAULT_BACKGROUND_COLOR.get_byte_value(); 62500]; //250*250
|
||||||
let mut display = VarDisplay::new(width, height, &mut buffer);
|
let mut display = VarDisplay::new(width, height, &mut buffer);
|
||||||
display.set_rotation(DisplayRotation::Rotate0);
|
display.set_rotation(DisplayRotation::Rotate0);
|
||||||
display.draw(
|
draw_text(&mut display, "Rotate 0!", 5, 50);
|
||||||
Font6x8::render_str("Rotate 0!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
display.set_rotation(DisplayRotation::Rotate90);
|
display.set_rotation(DisplayRotation::Rotate90);
|
||||||
display.draw(
|
draw_text(&mut display, "Rotate 90!", 5, 50);
|
||||||
Font6x8::render_str("Rotate 90!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
display.set_rotation(DisplayRotation::Rotate180);
|
display.set_rotation(DisplayRotation::Rotate180);
|
||||||
display.draw(
|
draw_text(&mut display, "Rotate 180!", 5, 50);
|
||||||
Font6x8::render_str("Rotate 180!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
display.set_rotation(DisplayRotation::Rotate270);
|
display.set_rotation(DisplayRotation::Rotate270);
|
||||||
display.draw(
|
draw_text(&mut display, "Rotate 270!", 5, 50);
|
||||||
Font6x8::render_str("Rotate 270!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
epd4in2
|
epd4in2
|
||||||
.update_partial_frame(&mut spi, &display.buffer(), x, y, width, height)
|
.update_partial_frame(&mut spi, &display.buffer(), x, y, width, height)
|
||||||
|
|
@ -121,68 +93,49 @@ fn run() -> Result<(), std::io::Error> {
|
||||||
delay.delay_ms(5000u16);
|
delay.delay_ms(5000u16);
|
||||||
|
|
||||||
println!("Now test new graphics with default rotation and some special stuff:");
|
println!("Now test new graphics with default rotation and some special stuff:");
|
||||||
|
display.set_rotation(DisplayRotation::Rotate0);
|
||||||
display.clear_buffer(Color::White);
|
display.clear_buffer(Color::White);
|
||||||
|
|
||||||
// draw a analog clock
|
// draw a analog clock
|
||||||
display.draw(
|
// draw a analog clock
|
||||||
Circle::new(Point::new(64, 64), 64)
|
let _ = Circle::new(Point::new(64, 64), 64)
|
||||||
.stroke(Some(Color::Black))
|
.into_styled(PrimitiveStyle::with_stroke(Black, 1))
|
||||||
.into_iter(),
|
.draw(&mut display);
|
||||||
);
|
let _ = Line::new(Point::new(64, 64), Point::new(0, 64))
|
||||||
display.draw(
|
.into_styled(PrimitiveStyle::with_stroke(Black, 1))
|
||||||
let _ = Line::new(Point::new(64, 64), Point::new(0, 64))
|
.draw(&mut display);
|
||||||
.stroke(Some(Color::Black))
|
let _ = Line::new(Point::new(64, 64), Point::new(80, 80))
|
||||||
.into_iter(),
|
.into_styled(PrimitiveStyle::with_stroke(Black, 1))
|
||||||
);
|
.draw(&mut display);
|
||||||
display.draw(
|
|
||||||
let _ = Line::new(Point::new(64, 64), Point::new(80, 80))
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// draw white on black background
|
// draw white on black background
|
||||||
display.draw(
|
let _ = Text::new("It's working-WoB!", Point::new(175, 250))
|
||||||
Font6x8::render_str("It's working-WoB!")
|
.into_styled(text_style!(
|
||||||
// Using Style here
|
font = Font6x8,
|
||||||
.style(Style {
|
text_color = White,
|
||||||
fill_color: Some(Color::Black),
|
background_color = Black
|
||||||
stroke_color: Some(Color::White),
|
))
|
||||||
stroke_width: 0u8, // Has no effect on fonts
|
.draw(&mut display);
|
||||||
})
|
|
||||||
.translate(Point::new(175, 250))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// use bigger/different font
|
// use bigger/different font
|
||||||
display.draw(
|
let _ = Text::new("It's working-WoB!", Point::new(50, 200))
|
||||||
Font12x16::render_str("It's working-BoW!")
|
.into_styled(text_style!(
|
||||||
// Using Style here
|
font = Font12x16,
|
||||||
.style(Style {
|
text_color = White,
|
||||||
fill_color: Some(Color::White),
|
background_color = Black
|
||||||
stroke_color: Some(Color::Black),
|
))
|
||||||
stroke_width: 0u8, // Has no effect on fonts
|
.draw(&mut display);
|
||||||
})
|
|
||||||
.translate(Point::new(50, 200))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// a moving `Hello World!`
|
// a moving `Hello World!`
|
||||||
let limit = 10;
|
let limit = 10;
|
||||||
for i in 0..limit {
|
for i in 0..limit {
|
||||||
println!("Moving Hello World. Loop {} from {}", (i + 1), limit);
|
println!("Moving Hello World. Loop {} from {}", (i + 1), limit);
|
||||||
|
|
||||||
display.draw(
|
draw_text(&mut display, " Hello World! ", 5 + i * 12, 50);
|
||||||
Font6x8::render_str(" Hello World! ")
|
|
||||||
.style(Style {
|
|
||||||
fill_color: Some(Color::White),
|
|
||||||
stroke_color: Some(Color::Black),
|
|
||||||
stroke_width: 0u8, // Has no effect on fonts
|
|
||||||
})
|
|
||||||
.translate(Point::new(5 + i * 12, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
epd4in2.update_frame(&mut spi, &display.buffer()).unwrap();
|
epd4in2
|
||||||
|
.update_partial_frame(&mut spi, &display.buffer(), x, y, width, height)
|
||||||
|
.unwrap();
|
||||||
epd4in2
|
epd4in2
|
||||||
.display_frame(&mut spi)
|
.display_frame(&mut spi)
|
||||||
.expect("display frame new graphics");
|
.expect("display frame new graphics");
|
||||||
|
|
@ -193,3 +146,13 @@ fn run() -> Result<(), std::io::Error> {
|
||||||
println!("Finished tests - going to sleep");
|
println!("Finished tests - going to sleep");
|
||||||
epd4in2.sleep(&mut spi)
|
epd4in2.sleep(&mut spi)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn draw_text(display: &mut VarDisplay, 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
|
||||||
|
))
|
||||||
|
.draw(display);
|
||||||
|
}
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "embedded_linux_eink_example"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = [
|
|
||||||
"Christoph Groß <christoph-gross@mailbox.org>",
|
|
||||||
"Jack Grigg <thestr4d@gmail.com>",
|
|
||||||
]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
embedded-graphics = "0.5.2"
|
|
||||||
embedded-hal = { version = "0.2.2", features = ["unproven"] }
|
|
||||||
epd-waveshare = { path = "../../", default-features = false, features = ["epd7in5", "graphics"]}
|
|
||||||
linux-embedded-hal = "0.2.2"
|
|
||||||
|
|
@ -1,188 +0,0 @@
|
||||||
#![deny(warnings)]
|
|
||||||
|
|
||||||
use embedded_graphics::{
|
|
||||||
fonts::{Font12x16, Font6x8},
|
|
||||||
prelude::*,
|
|
||||||
primitives::{Circle, Line},
|
|
||||||
Drawing,
|
|
||||||
Point::Point,
|
|
||||||
};
|
|
||||||
use embedded_hal::prelude::*;
|
|
||||||
use epd_waveshare::{
|
|
||||||
epd7in5::{Display7in5, EPD7in5},
|
|
||||||
graphics::{Display, DisplayRotation},
|
|
||||||
prelude::*,
|
|
||||||
};
|
|
||||||
use linux_embedded_hal::{
|
|
||||||
spidev::{self, SpidevOptions},
|
|
||||||
sysfs_gpio::Direction,
|
|
||||||
Delay, Pin, Spidev,
|
|
||||||
};
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
if let Err(e) = run() {
|
|
||||||
eprintln!("Program exited early with error: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run() -> Result<(), std::io::Error> {
|
|
||||||
// Configure SPI
|
|
||||||
// Settings are taken from
|
|
||||||
let mut spi = Spidev::open("/dev/spidev0.0").expect("spidev directory");
|
|
||||||
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");
|
|
||||||
|
|
||||||
// Configure Digital I/O Pin to be used as Chip Select for SPI
|
|
||||||
let cs = Pin::new(8);
|
|
||||||
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(24);
|
|
||||||
busy.export().expect("busy export");
|
|
||||||
while !busy.is_exported() {}
|
|
||||||
busy.set_direction(Direction::In).expect("busy Direction");
|
|
||||||
|
|
||||||
let dc = Pin::new(25);
|
|
||||||
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 rst = Pin::new(17);
|
|
||||||
rst.export().expect("rst export");
|
|
||||||
while !rst.is_exported() {}
|
|
||||||
rst.set_direction(Direction::Out).expect("rst Direction");
|
|
||||||
rst.set_value(1).expect("rst Value set to 1");
|
|
||||||
|
|
||||||
let mut delay = Delay {};
|
|
||||||
|
|
||||||
let mut epd7in5 =
|
|
||||||
EPD7in5::new(&mut spi, cs, busy, dc, rst, &mut delay).expect("eink initalize error");
|
|
||||||
|
|
||||||
println!("Test all the rotations");
|
|
||||||
let mut display = Display7in5::default();
|
|
||||||
display.set_rotation(DisplayRotation::Rotate0);
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("Rotate 0!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
display.set_rotation(DisplayRotation::Rotate90);
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("Rotate 90!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
display.set_rotation(DisplayRotation::Rotate180);
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("Rotate 180!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
display.set_rotation(DisplayRotation::Rotate270);
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("Rotate 270!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
epd7in5.update_frame(&mut spi, &display.buffer()).unwrap();
|
|
||||||
epd7in5
|
|
||||||
.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(Point::new(64, 64), 64)
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
display.draw(
|
|
||||||
let _ = Line::new(Point::new(64, 64), Point::new(0, 64))
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
display.draw(
|
|
||||||
let _ = Line::new(Point::new(64, 64), Point::new(80, 80))
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// draw white on black background
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("It's working-WoB!")
|
|
||||||
// Using Style here
|
|
||||||
.style(Style {
|
|
||||||
fill_color: Some(Color::Black),
|
|
||||||
stroke_color: Some(Color::White),
|
|
||||||
stroke_width: 0u8, // Has no effect on fonts
|
|
||||||
})
|
|
||||||
.translate(Point::new(175, 250))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// use bigger/different font
|
|
||||||
display.draw(
|
|
||||||
Font12x16::render_str("It's working-BoW!")
|
|
||||||
// Using Style here
|
|
||||||
.style(Style {
|
|
||||||
fill_color: Some(Color::White),
|
|
||||||
stroke_color: Some(Color::Black),
|
|
||||||
stroke_width: 0u8, // Has no effect on fonts
|
|
||||||
})
|
|
||||||
.translate(Point::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! ")
|
|
||||||
.style(Style {
|
|
||||||
fill_color: Some(Color::White),
|
|
||||||
stroke_color: Some(Color::Black),
|
|
||||||
stroke_width: 0u8, // Has no effect on fonts
|
|
||||||
})
|
|
||||||
.translate(Point::new(5 + i * 12, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
epd7in5.update_frame(&mut spi, &display.buffer()).unwrap();
|
|
||||||
epd7in5
|
|
||||||
.display_frame(&mut spi)
|
|
||||||
.expect("display frame new graphics");
|
|
||||||
|
|
||||||
delay.delay_ms(1_000u16);
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("Finished tests - going to sleep");
|
|
||||||
epd7in5.sleep(&mut spi)
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "embedded_linux_eink_example"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = [
|
|
||||||
"Christoph Groß <christoph-gross@mailbox.org>",
|
|
||||||
"Jack Grigg <thestr4d@gmail.com>",
|
|
||||||
"Christoph Grabo <asaaki@mannaz.cc>",
|
|
||||||
]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
embedded-graphics = "0.5.2"
|
|
||||||
embedded-hal = { version = "0.2.3", features = ["unproven"] }
|
|
||||||
epd-waveshare = { path = "../../", default-features = false, features = ["epd7in5_v2", "graphics"]}
|
|
||||||
linux-embedded-hal = "0.3.0"
|
|
||||||
|
|
@ -1,188 +0,0 @@
|
||||||
#![deny(warnings)]
|
|
||||||
|
|
||||||
use embedded_graphics::{
|
|
||||||
fonts::{Font12x16, Font6x8},
|
|
||||||
prelude::*,
|
|
||||||
primitives::{Circle, Line},
|
|
||||||
Drawing,
|
|
||||||
Point::Point,
|
|
||||||
};
|
|
||||||
use embedded_hal::prelude::*;
|
|
||||||
use epd_waveshare::{
|
|
||||||
epd7in5_v2::{Display7in5, EPD7in5},
|
|
||||||
graphics::{Display, DisplayRotation},
|
|
||||||
prelude::*,
|
|
||||||
};
|
|
||||||
use linux_embedded_hal::{
|
|
||||||
spidev::{self, SpidevOptions},
|
|
||||||
sysfs_gpio::Direction,
|
|
||||||
Delay, Pin, Spidev,
|
|
||||||
};
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
if let Err(e) = run() {
|
|
||||||
eprintln!("Program exited early with error: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run() -> Result<(), std::io::Error> {
|
|
||||||
// Configure SPI
|
|
||||||
// Settings are taken from
|
|
||||||
let mut spi = Spidev::open("/dev/spidev0.0").expect("spidev directory");
|
|
||||||
let options = SpidevOptions::new()
|
|
||||||
.bits_per_word(8)
|
|
||||||
.max_speed_hz(4_000_000)
|
|
||||||
.mode(spidev::SpiModeFlags::SPI_MODE_0)
|
|
||||||
.build();
|
|
||||||
spi.configure(&options).expect("spi configuration");
|
|
||||||
|
|
||||||
// Configure Digital I/O Pin to be used as Chip Select for SPI
|
|
||||||
let cs = Pin::new(8);
|
|
||||||
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(24);
|
|
||||||
busy.export().expect("busy export");
|
|
||||||
while !busy.is_exported() {}
|
|
||||||
busy.set_direction(Direction::In).expect("busy Direction");
|
|
||||||
|
|
||||||
let dc = Pin::new(25);
|
|
||||||
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 rst = Pin::new(17);
|
|
||||||
rst.export().expect("rst export");
|
|
||||||
while !rst.is_exported() {}
|
|
||||||
rst.set_direction(Direction::Out).expect("rst Direction");
|
|
||||||
rst.set_value(1).expect("rst Value set to 1");
|
|
||||||
|
|
||||||
let mut delay = Delay {};
|
|
||||||
|
|
||||||
let mut epd7in5 =
|
|
||||||
EPD7in5::new(&mut spi, cs, busy, dc, rst, &mut delay).expect("eink initalize error");
|
|
||||||
|
|
||||||
println!("Test all the rotations");
|
|
||||||
let mut display = Display7in5::default();
|
|
||||||
display.set_rotation(DisplayRotation::Rotate0);
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("Rotate 0!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
display.set_rotation(DisplayRotation::Rotate90);
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("Rotate 90!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
display.set_rotation(DisplayRotation::Rotate180);
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("Rotate 180!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
display.set_rotation(DisplayRotation::Rotate270);
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("Rotate 270!")
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.fill(Some(Color::White))
|
|
||||||
.translate(Point::new(5, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
epd7in5.update_frame(&mut spi, &display.buffer()).unwrap();
|
|
||||||
epd7in5
|
|
||||||
.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(Point::new(64, 64), 64)
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
display.draw(
|
|
||||||
Line::new(Point::new(64, 64), Point::new(0, 64))
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
display.draw(
|
|
||||||
Line::new(Point::new(64, 64), Point::new(80, 80))
|
|
||||||
.stroke(Some(Color::Black))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// draw white on black background
|
|
||||||
display.draw(
|
|
||||||
Font6x8::render_str("It's working-WoB!")
|
|
||||||
// Using Style here
|
|
||||||
.style(Style {
|
|
||||||
fill_color: Some(Color::Black),
|
|
||||||
stroke_color: Some(Color::White),
|
|
||||||
stroke_width: 0u8, // Has no effect on fonts
|
|
||||||
})
|
|
||||||
.translate(Point::new(175, 250))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// use bigger/different font
|
|
||||||
display.draw(
|
|
||||||
Font12x16::render_str("It's working-BoW!")
|
|
||||||
// Using Style here
|
|
||||||
.style(Style {
|
|
||||||
fill_color: Some(Color::White),
|
|
||||||
stroke_color: Some(Color::Black),
|
|
||||||
stroke_width: 0u8, // Has no effect on fonts
|
|
||||||
})
|
|
||||||
.translate(Point::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! ")
|
|
||||||
.style(Style {
|
|
||||||
fill_color: Some(Color::White),
|
|
||||||
stroke_color: Some(Color::Black),
|
|
||||||
stroke_width: 0u8, // Has no effect on fonts
|
|
||||||
})
|
|
||||||
.translate(Point::new(5 + i * 12, 50))
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
|
|
||||||
epd7in5.update_frame(&mut spi, &display.buffer()).unwrap();
|
|
||||||
epd7in5
|
|
||||||
.display_frame(&mut spi)
|
|
||||||
.expect("display frame new graphics");
|
|
||||||
|
|
||||||
delay.delay_ms(1_000u16);
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("Finished tests - going to sleep");
|
|
||||||
epd7in5.sleep(&mut spi)
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +1,13 @@
|
||||||
//! B/W Color for EPDs
|
//! B/W Color for EPDs
|
||||||
|
|
||||||
|
#[cfg(feature = "graphics")]
|
||||||
use embedded_graphics::pixelcolor::BinaryColor;
|
use embedded_graphics::pixelcolor::BinaryColor;
|
||||||
|
|
||||||
|
#[cfg(feature = "graphics")]
|
||||||
pub use BinaryColor::Off as White;
|
pub use BinaryColor::Off as White;
|
||||||
|
#[cfg(feature = "graphics")]
|
||||||
pub use BinaryColor::On as Black;
|
pub use BinaryColor::On as Black;
|
||||||
|
|
||||||
/// Only for the Black/White-Displays
|
/// Only for the Black/White-Displays
|
||||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||||
pub enum Color {
|
pub enum Color {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
//!
|
//!
|
||||||
//! # Example for the 1.54 in E-Ink Display
|
//! # Example for the 1.54 in E-Ink Display
|
||||||
//!
|
//!
|
||||||
//! ```rust,ignore
|
//! ```rust,no_run
|
||||||
//! use epd_waveshare::{
|
//! use epd_waveshare::{
|
||||||
//! epd1in54::{EPD1in54, Display1in54},
|
//! epd1in54::{EPD1in54, Display1in54},
|
||||||
//! graphics::{Display, DisplayRotation},
|
//! graphics::{Display, DisplayRotation},
|
||||||
|
|
@ -17,13 +17,9 @@
|
||||||
//! let mut display = Display1in54::default();
|
//! let mut display = Display1in54::default();
|
||||||
//!
|
//!
|
||||||
//! // Write some hello world in the screenbuffer
|
//! // Write some hello world in the screenbuffer
|
||||||
//! display.draw(
|
//! let _ = Line::new(Point::new(0, 120), Point::new(0, 295))
|
||||||
//! Font6x8::render_str("Hello World!")
|
//! .into_styled(PrimitiveStyle::with_stroke(BinaryColor::On, 1))
|
||||||
//! .stroke(Some(Color::Black))
|
//! .draw(&mut display);
|
||||||
//! .fill(Some(Color::White))
|
|
||||||
//! .translate(Point::new(5, 50))
|
|
||||||
//! .into_iter(),
|
|
||||||
//! );
|
|
||||||
//!
|
//!
|
||||||
//! // Display updated frame
|
//! // Display updated frame
|
||||||
//! epd.update_frame(&mut spi, &display.buffer()).unwrap();
|
//! epd.update_frame(&mut spi, &display.buffer()).unwrap();
|
||||||
|
|
|
||||||
19
src/lib.rs
19
src/lib.rs
|
|
@ -64,31 +64,18 @@ pub mod color;
|
||||||
/// Interface for the physical connection between display and the controlling device
|
/// Interface for the physical connection between display and the controlling device
|
||||||
mod interface;
|
mod interface;
|
||||||
|
|
||||||
#[cfg(feature = "epd7in5")]
|
|
||||||
pub mod epd7in5;
|
|
||||||
#[cfg(feature = "epd7in5_v2")]
|
|
||||||
pub mod epd7in5_v2;
|
|
||||||
|
|
||||||
#[cfg(feature = "epd4in2")]
|
|
||||||
pub mod epd4in2;
|
|
||||||
|
|
||||||
#[cfg(feature = "epd1in54")]
|
|
||||||
pub mod epd1in54;
|
pub mod epd1in54;
|
||||||
|
|
||||||
#[cfg(feature = "epd1in54b")]
|
|
||||||
pub mod epd1in54b;
|
pub mod epd1in54b;
|
||||||
|
|
||||||
#[cfg(feature = "epd2in9")]
|
|
||||||
pub mod epd2in9;
|
pub mod epd2in9;
|
||||||
|
pub mod epd4in2;
|
||||||
#[cfg(any(feature = "epd1in54", feature = "epd2in9"))]
|
pub mod epd7in5;
|
||||||
|
pub mod epd7in5_v2;
|
||||||
pub(crate) mod type_a;
|
pub(crate) mod type_a;
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use crate::color::Color;
|
pub use crate::color::Color;
|
||||||
pub use crate::traits::{RefreshLUT, WaveshareDisplay, WaveshareThreeColorDisplay};
|
pub use crate::traits::{RefreshLUT, WaveshareDisplay, WaveshareThreeColorDisplay};
|
||||||
|
|
||||||
#[cfg(feature = "epd7in5_v2")]
|
|
||||||
pub use crate::traits::WaveshareDisplayExt;
|
pub use crate::traits::WaveshareDisplayExt;
|
||||||
|
|
||||||
pub use crate::SPI_MODE;
|
pub use crate::SPI_MODE;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue