| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- #![no_main]
- #![no_std]
-
- mod pins;
- mod assets {
- include!(concat!(env!("OUT_DIR"), "/assets.rs"));
- }
-
- use cortex_m_semihosting::{debug, hprintln};
- use embedded_epd as epd;
- use embedded_epd::{gui, Display};
- use embedded_hal::blocking::delay::DelayMs;
- use embedded_hal::digital::v2::OutputPin;
- use embedded_hal::timer::CountDown;
- use epd_waveshare::{epd4in2::*, prelude::*};
- use mkl25z4_hal as hal;
- use mkl25z4_hal::clocks::ClockConfiguration;
- use mkl25z4_hal::time::NonCopyableMonoTimer;
- use mkl25z4_hal::time::U32Ext;
- use mkl25z4_hal::timer::Timer;
- use nb::block;
- use panic_semihosting as _;
-
- struct EPDTimer<Timer> {
- timer: Timer,
- }
-
- impl<Timer> CountDown for EPDTimer<Timer>
- where
- Timer: CountDown<Time = hal::time::Hertz>,
- {
- type Time = epd::Hertz;
-
- fn start<T>(&mut self, timeout: T)
- where
- T: Into<epd::Hertz>,
- {
- self.timer.start(hal::time::Hertz(timeout.into().0))
- }
-
- fn wait(&mut self) -> nb::Result<(), void::Void> {
- self.timer.wait()
- }
- }
-
- #[rtfm::app(device = mkl25z4_hal::mkl25z4, peripherals = true)]
- const APP: () = {
- struct Resources {}
-
- #[init]
- fn init(ctx: init::Context) {
- let mut sim = ctx.device.SIM;
- mkl25z4_hal::watchdog::disable(&mut sim);
- let clocks = ClockConfiguration::new()
- .use_irc()
- .core_clock(24.mhz())
- .bus_clock(24.mhz())
- .apply(&mut sim, ctx.device.OSC0, ctx.device.MCG);
-
- let mut pins = pins::Pins::configure(
- &mut sim,
- clocks,
- ctx.device.GPIOA,
- ctx.device.GPIOB,
- ctx.device.GPIOC,
- ctx.device.GPIOD,
- ctx.device.GPIOE,
- ctx.device.SPI0,
- ctx.device.SPI1,
- );
-
- // Enable power.
- pins.display_pwr.set_low().ok();
- pins.display_rst.set_high().unwrap();
- pins.display_dc.set_high().unwrap();
- pins.display_cs.set_high().unwrap();
-
- let mut timer = NonCopyableMonoTimer::new(ctx.device.PIT, clocks, &mut sim);
-
- let mut epd = EPD4in2::new(
- &mut pins.display_bme_spi,
- pins.display_cs,
- pins.display_busy,
- pins.display_dc,
- pins.display_rst,
- &mut timer,
- )
- .unwrap();
-
- epd.set_background_color(Color::Black);
- let checkerboard = Checkerboard::new(400, 300, true);
- epd.update_frame_stream(&mut pins.display_bme_spi, checkerboard)
- .unwrap();
- epd.display_frame(&mut pins.display_bme_spi).unwrap();
- }
-
- #[idle]
- fn idle(_cx: idle::Context) -> ! {
- // Sleep
- loop {
- // wfi needs to be disabled for GDB
- /*// add some side effect to prevent this from turning into a UDF instruction
- // see rust-lang/rust#28728 for details
- atomic::compiler_fence(Ordering::SeqCst);*/
- cortex_m::asm::wfi();
- }
- }
- };
-
- struct Checkerboard {
- width: usize,
- height: usize,
- index: usize,
- buffer: [u8; 1],
- }
-
- impl Checkerboard {
- fn new(width: usize, height: usize, start_black: bool) -> Self {
- Self {
- width: width / 8,
- height,
- index: 0,
- buffer: [if start_black { 0x55 } else { 0xaa }],
- }
- }
- }
-
- impl DisplayStream for Checkerboard {
- fn next<'a>(&'a mut self) -> Option<&'a [u8]> {
- if self.index != self.width * self.height {
- self.index += 1;
- if (self.index - 1) % self.width == 0 {
- self.buffer[0] = !self.buffer[0];
- }
- Some(&self.buffer)
- } else {
- None
- }
- }
- }
|