188 lines
7.5 KiB
Rust
188 lines
7.5 KiB
Rust
use std::{error::Error, thread::sleep, time::Duration};
|
|
|
|
use embedded_graphics::{image::Image, pixelcolor::Rgb565, prelude::*};
|
|
use esp_idf_hal::{
|
|
gpio::{Gpio12, Gpio14, Gpio16, Gpio17, Gpio18, Gpio23, Gpio5, Input, Output},
|
|
prelude::{Hertz, Peripherals},
|
|
spi::{self, Master, Pins, SPI3},
|
|
};
|
|
// If using the `binstart` feature of `esp-idf-sys`, always keep this module imported
|
|
use esp_idf_sys as _;
|
|
use rand::Rng;
|
|
use ssd1331::Ssd1331;
|
|
use tinybmp::Bmp;
|
|
|
|
fn secondary() -> Result<(), Box<dyn Error>> {
|
|
// Temporary. Will disappear once ESP-IDF 4.4 is released, but for now it is necessary to call this function once,
|
|
// or else some patches to the runtime implemented by esp-idf-sys might not link properly.
|
|
esp_idf_sys::link_patches();
|
|
|
|
// Bind the log crate to the ESP Logging facilities
|
|
esp_idf_svc::log::EspLogger::initialize_default();
|
|
let peripherals = Peripherals::take().unwrap();
|
|
let spi3 = peripherals.spi3;
|
|
let pins = peripherals.pins;
|
|
let cs: Gpio17<Output> = pins.gpio17.into_output()?;
|
|
let dc: Gpio16<Output> = pins.gpio16.into_output()?;
|
|
let mosi: Gpio23<Output> = pins.gpio23.into_output()?;
|
|
let sclk: Gpio18<Output> = pins.gpio18.into_output()?;
|
|
let reset: Gpio5<Output> = pins.gpio5.into_output()?;
|
|
|
|
let read: Gpio12<Input> = pins.gpio12.into_input()?;
|
|
let write: Gpio14<Output> = pins.gpio14.into_output()?;
|
|
|
|
let spiman =
|
|
spi::Master::<SPI3, Gpio18<Output>, Gpio23<Output>, Gpio5<Output>, Gpio17<Output>>::new(
|
|
spi3,
|
|
Pins {
|
|
sclk: sclk,
|
|
sdo: mosi,
|
|
sdi: Some(reset),
|
|
cs: Some(cs),
|
|
},
|
|
spi::config::Config {
|
|
baudrate: Hertz(24000000),
|
|
data_mode: embedded_hal::spi::MODE_0,
|
|
write_only: false,
|
|
dma: spi::Dma::Disabled,
|
|
},
|
|
)?;
|
|
let mut display = Ssd1331::new(spiman, dc, ssd1331::DisplayRotation::Rotate180);
|
|
display.init().unwrap();
|
|
display.flush().unwrap();
|
|
|
|
let (w, h) = display.dimensions();
|
|
println!("got resolution {} x {}", w.clone(), h.clone());
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let eye = Bmp::from_slice(include_bytes!("./eye.bmp")).expect("Failed to load BMP image");
|
|
let eye_closed =
|
|
Bmp::from_slice(include_bytes!("./eye_closed.bmp")).expect("Failed to load BMP image");
|
|
let emilis = Bmp::from_slice(include_bytes!("./emilis.bmp")).expect("Failed to load BMP image");
|
|
print_image(emilis, &mut display, h as u32, w as u32);
|
|
sleep(Duration::from_secs(3));
|
|
display.clear();
|
|
puff_idle(&mut display, h as u32, w as u32);
|
|
loop {
|
|
print_image(eye, &mut display, h as u32, w as u32);
|
|
sleep(Duration::from_secs(rng.gen_range(2..8)));
|
|
print_image(eye_closed, &mut display, h as u32, w as u32);
|
|
sleep(Duration::from_millis(190))
|
|
}
|
|
}
|
|
|
|
fn print_image(
|
|
img: Bmp<Rgb565>,
|
|
display: &mut Ssd1331<
|
|
Master<SPI3, Gpio18<Output>, Gpio23<Output>, Gpio5<Output>, Gpio17<Output>>,
|
|
Gpio16<Output>,
|
|
>,
|
|
h: u32,
|
|
w: u32,
|
|
) {
|
|
let im: Image<Bmp<Rgb565>> = Image::new(&img, Point::zero());
|
|
// Position image in the center of the display
|
|
let moved = im.translate(Point::new(
|
|
(w - img.size().width) as i32 / 2,
|
|
(h - img.size().height) as i32 / 2,
|
|
));
|
|
|
|
moved.draw(display).unwrap();
|
|
|
|
display.flush().unwrap();
|
|
}
|
|
|
|
fn puff_idle(
|
|
display: &mut Ssd1331<
|
|
Master<SPI3, Gpio18<Output>, Gpio23<Output>, Gpio5<Output>, Gpio17<Output>>,
|
|
Gpio16<Output>,
|
|
>,
|
|
h: u32,
|
|
w: u32,
|
|
) -> ! {
|
|
let raw = get_puff_raw();
|
|
let mut frames = Vec::<Bmp<Rgb565>>::new();
|
|
for raw_image in raw {
|
|
let frame_bmp = Bmp::from_slice(raw_image).unwrap();
|
|
frames.push(frame_bmp);
|
|
}
|
|
loop {
|
|
for frame in &frames {
|
|
print_image(*frame, display, h, w);
|
|
sleep(Duration::from_millis(1));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Manually unrolled because im gay
|
|
fn get_puff_raw() -> Vec<&'static [u8]> {
|
|
let mut raw = Vec::<&[u8]>::new();
|
|
raw.push(include_bytes!("../puff/puffidle-0.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-1.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-2.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-3.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-4.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-5.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-6.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-7.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-8.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-9.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-10.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-11.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-12.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-13.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-14.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-15.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-16.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-17.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-18.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-19.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-20.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-21.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-22.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-23.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-24.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-25.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-26.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-27.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-28.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-29.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-30.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-31.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-32.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-33.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-34.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-35.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-36.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-37.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-38.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-39.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-40.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-41.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-42.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-43.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-44.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-45.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-46.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-47.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-48.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-49.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-50.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-51.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-52.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-53.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-54.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-55.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-56.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-57.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-58.bmp"));
|
|
raw.push(include_bytes!("../puff/puffidle-59.bmp"));
|
|
|
|
raw
|
|
}
|
|
|
|
fn main() -> Result<(), Box<dyn Error>> {
|
|
sleep(Duration::from_secs(1));
|
|
Ok(secondary().unwrap())
|
|
}
|