//! Place a series of bitmap images on the screen
//!
//! Ferris pngs from , convert png to .bmp bytes:
//! * Resize and export images directly from image editor by saving as .bmp and
//! choosing 16bit R5 G6 B5
//! * OR Convert with imagemagick: convert rustacean-flat-noshadow.png -type
//! truecolor -define bmp:subtype=RGB565 -depth 16 -strip -resize 86x64
//! ferris.bmp
//! * SD card should have one (or at least, the first) primary partition of type
//! W95 FAT32, formatted eg `sudo mkfs.fat /dev/path/to/sdcardp1`
//! * Put assets/ferris*.bmp in the root directory of the sd card `cp
//! assets/ferris*.bmp /Volumes/SDCARD/`
#![no_std]
#![no_main]
use bsp::{entry, hal, pac, Pins, RedLed};
#[cfg(not(feature = "panic_led"))]
use panic_halt as _;
use pygamer as bsp;
use embedded_graphics::prelude::*;
use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle};
use embedded_graphics::{image::Image, pixelcolor::Rgb565};
use embedded_hal_bus::spi::ExclusiveDevice;
use embedded_sdmmc::{Mode, TimeSource, Timestamp, VolumeIdx, VolumeManager};
use hal::clock::GenericClockController;
use hal::delay::Delay;
use hal::nb;
use hal::prelude::*;
use hal::time::Hertz;
use hal::timer::TimerCounter;
use pac::{CorePeripherals, Peripherals};
use tinybmp::Bmp;
#[entry]
fn main() -> ! {
let mut peripherals = Peripherals::take().unwrap();
let core = CorePeripherals::take().unwrap();
let mut clocks = GenericClockController::with_internal_32kosc(
peripherals.gclk,
&mut peripherals.mclk,
&mut peripherals.osc32kctrl,
&mut peripherals.oscctrl,
&mut peripherals.nvmctrl,
);
let mut delay = Delay::new(core.SYST, &mut clocks);
let pins = Pins::new(peripherals.port).split();
let mut red_led: RedLed = pins.led_pin.into();
let (mut display, _backlight) = pins
.display
.init(
&mut clocks,
peripherals.sercom4,
&mut peripherals.mclk,
peripherals.tc2,
&mut delay,
)
.unwrap();
// black out the screen
Rectangle::with_corners(Point::new(0, 0), Point::new(160, 128))
.into_styled(
PrimitiveStyleBuilder::new()
.fill_color(Rgb565::BLACK)
.build(),
)
.draw(&mut display)
.unwrap();
let gclk0 = clocks.gclk0();
let timer_clock = clocks.tc4_tc5(&gclk0).unwrap();
let mut khz_timer = TimerCounter::tc4_(&timer_clock, peripherals.tc4, &mut peripherals.mclk);
InterruptDrivenTimer::start(&mut khz_timer, Hertz::kHz(1).into_duration());
let sdmmc_cs = pins.sd_cs_pin.into_push_pull_output();
let sdmmc_spi_bus = pins.spi.init(
&mut clocks,
3.MHz(),
peripherals.sercom1,
&mut peripherals.mclk,
);
let sdmmc_spi =
ExclusiveDevice::new_no_delay(sdmmc_spi_bus, sdmmc_cs).expect("Failed to create SpiDevice");
let card = embedded_sdmmc::SdCard::new(sdmmc_spi, delay);
let mut volume_mgr = VolumeManager::new(card, Clock {});
let mut volume = volume_mgr
.open_volume(VolumeIdx(0))
.expect("Failed to open volume");
let mut dir = volume.open_root_dir().expect("Failed to open root dir");
let mut scratch = [0u8; 11008];
// "animation" order of files to open
let images = ["ferris.bmp", "ferris1.bmp", "ferris2.bmp", "ferris1.bmp"];
loop {
for image in images.iter() {
match dir.open_file_in_dir(*image, Mode::ReadOnly) {
Ok(mut f) => {
let _ = f.read(&mut scratch);
let raw_image: Bmp = Bmp::from_slice(&scratch).unwrap();
let ferris = Image::new(&raw_image, Point::new(32, 32));
let _ = ferris.draw(&mut display);
let _ = f.close();
}
Err(_err) => {
red_led.set_high().ok();
}
}
for _ in 0..100 {
nb::block!(InterruptDrivenTimer::wait(&mut khz_timer)).unwrap();
}
}
}
}
struct Clock;
impl TimeSource for Clock {
fn get_timestamp(&self) -> Timestamp {
Timestamp {
year_since_1970: 0,
zero_indexed_month: 0,
zero_indexed_day: 0,
hours: 0,
minutes: 0,
seconds: 0,
}
}
}