diff --git a/src/main.rs b/src/main.rs index e7a11a9..1aafc9b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,334 @@ -fn main() { - println!("Hello, world!"); +#![no_std] +#![no_main] + +use core::convert::TryInto; +use cortex_m_rt::entry; +use embedded_graphics::{ + fonts::{Font24x32 as Font, Text}, + image::Image, + pixelcolor::BinaryColor, + prelude::*, + primitives::{Circle, Line, Triangle}, + style::{PrimitiveStyle, PrimitiveStyleBuilder, TextStyleBuilder}, +}; +use embedded_hal::digital::v2::OutputPin; +use embedded_sdmmc::{ + sdmmc::CardType, Block, BlockDevice, BlockIdx, Controller, Error, SdMmcError, SdMmcSpi, + VolumeIdx, +}; +use embedded_time::fixed_point::FixedPoint; +use embedded_time::rate::Extensions; +use epd_waveshare::{ + color::*, epd7in5_v2::Display7in5 as EPDisplay, epd7in5_v2::EPD7in5 as EPD, epd7in5_v2::HEIGHT, + epd7in5_v2::WIDTH, graphics::DisplayRotation, prelude::*, +}; +use num_format::{Buffer, Locale}; +use panic_probe as _; +use rp2040_hal as hal; +use tinytga::Tga; + +use hal::{ + clocks::{init_clocks_and_plls, Clock}, + pac, + sio::Sio, + watchdog::Watchdog, +}; + +fn error_to_str<'a>(error: SdMmcError) -> &'a str { + match error { + SdMmcError::Transport => "Transport", + SdMmcError::CantEnableCRC => "Cant Enable CRC", + SdMmcError::TimeoutReadBuffer => "TimeoutReadBuffer", + SdMmcError::TimeoutWaitNotBusy => "Timeout Wait Not Busy", + SdMmcError::TimeoutCommand(_) => "Timeout Command", + SdMmcError::TimeoutACommand(_) => "Timeout A Command", + SdMmcError::Cmd58Error => "Cmd 58 Error", + SdMmcError::RegisterReadError => "Register Read Error", + SdMmcError::CrcError(_, _) => "CRC Error", + SdMmcError::ReadError => "Read Error", + SdMmcError::WriteError => "Write Error", + SdMmcError::BadState => "Bad State", + SdMmcError::CardNotFound => "Card Not Found", + SdMmcError::GpioError => "GPIO Error", + } +} +fn error2_to_str<'a, E: core::fmt::Debug>(error: Error) -> Result<&'a str, Buffer> { + match error { + Error::DeviceError(_) => Ok("Device Error"), + Error::FormatError(s) => Ok(s), + Error::SignatureError(s) => Err(s), + Error::NoSuchVolume => Ok("No Such Volume"), + Error::FilenameError(_) => Ok("Filename Error"), + Error::TooManyOpenDirs => Ok("Too Many Open Dirs"), + Error::TooManyOpenFiles => Ok("Too Many Oopen Files"), + Error::FileNotFound => Ok("File Not Found"), + Error::FileAlreadyOpen => Ok("File Already Open"), + Error::DirAlreadyOpen => Ok("Dir Already Open"), + Error::OpenedDirAsFile => Ok("Opened Dir As File"), + Error::Unsupported => Ok("Unsopported"), + Error::EndOfFile => Ok("End Of File"), + Error::BadCluster => Ok("Bad Cluster"), + Error::ConversionError => Ok("Conversion Error"), + Error::NotEnoughSpace => Ok("Not EnoughSpace"), + Error::AllocationError => Ok("Allocation Error"), + Error::JumpedFree => Ok("Jumped Free"), + Error::ReadOnly => Ok("Read Only"), + Error::FileAlreadyExists => Ok("File Already Exists"), + Error::DeleteDirAsFile => Ok("Delete Dir As File"), + Error::FileIsOpen => Ok("File Is Open"), + Error::BadBlockSize(_) => Ok("Bad Block Size"), + Error::NotInBlock => Ok("Not In Block"), + } +} + +#[link_section = ".boot2"] +#[used] +pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080; + +struct ClockSD; + +impl embedded_sdmmc::TimeSource for ClockSD { + fn get_timestamp(&self) -> embedded_sdmmc::Timestamp { + embedded_sdmmc::Timestamp { + year_since_1970: 0, + zero_indexed_month: 0, + zero_indexed_day: 0, + hours: 0, + minutes: 0, + seconds: 0, + } + } +} + +#[entry] +fn main() -> ! { + let mut pac = pac::Peripherals::take().unwrap(); + let core = pac::CorePeripherals::take().unwrap(); + let mut watchdog = Watchdog::new(pac.WATCHDOG); + let sio = Sio::new(pac.SIO); + + // External high-speed crystal on the pico board is 12Mhz + let external_xtal_freq_hz = 12_000_000u32; + let clocks = init_clocks_and_plls( + external_xtal_freq_hz, + pac.XOSC, + pac.CLOCKS, + pac.PLL_SYS, + pac.PLL_USB, + &mut pac.RESETS, + &mut watchdog, + ) + .ok() + .unwrap(); + + let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().integer()); + + let pins = hal::gpio::Pins::new( + pac.IO_BANK0, + pac.PADS_BANK0, + sio.gpio_bank0, + &mut pac.RESETS, + ); + + // SPI screen declaration + let _spi1_sclk = pins.gpio10.into_mode::(); + let _spi1_mosi = pins.gpio11.into_mode::(); + let spi = hal::spi::Spi::<_, _, 8>::new(pac.SPI1); + + // Exchange the uninitialised SPI driver for an initialised one + let mut spi = spi.init( + &mut pac.RESETS, + clocks.peripheral_clock.freq(), + 4_000_000u32.Hz(), + // 16_000_000u32.Hz(), + &embedded_hal::spi::MODE_0, + ); + + let mut cs = pins.gpio9.into_push_pull_output(); // CS + cs.set_high().unwrap(); + let busy = pins.gpio13.into_pull_up_input(); // BUSY + let dc = pins.gpio8.into_push_pull_output(); // DC + let rst = pins.gpio12.into_push_pull_output(); // RST + + let _spi1_sclk = pins.gpio18.into_mode::(); + let _spi1_mosi = pins.gpio19.into_mode::(); + let _spi1_miso = pins.gpio16.into_mode::(); + let spi_sd = hal::spi::Spi::<_, _, 8>::new(pac.SPI0); + + // Exchange the uninitialised SPI driver for an initialised one + let mut spi_sd = spi_sd.init( + &mut pac.RESETS, + clocks.peripheral_clock.freq(), + 100_000u32.Hz(), + &embedded_hal::spi::MODE_0, + ); + + let mut cs_sd = pins.gpio17.into_push_pull_output(); // CS + // cs_sd.set_low().unwrap(); + + let mut epd = EPD::new( + &mut spi, // SPI + cs, // CS + busy, // BUSY + dc, // DC + rst, // RST + &mut delay, // DELAY + ) + .unwrap(); + let mut display = EPDisplay::default(); + + /* + Clear the full screen + */ + + epd.wake_up(&mut spi, &mut delay).unwrap(); + // epd.set_background_color(epd_waveshare::color::Color::Black); + // epd.clear_frame(&mut spi).unwrap(); + // epd.set_background_color(epd_waveshare::color::Color::White); + epd.clear_frame(&mut spi).unwrap(); + // epd.display_frame(&mut spi).unwrap(); + + display.clear_buffer(Color::Black); + + for i in 0..100 { + Pixel(Point::new(100, i), BinaryColor::Off) + .draw(&mut display) + .unwrap(); + } + + let style_text = TextStyleBuilder::new(Font) + .text_color(BinaryColor::Off) + .background_color(BinaryColor::On) + .build(); + let style_forms = PrimitiveStyleBuilder::new() + .stroke_width(10) + .stroke_color(BinaryColor::Off) + .fill_color(BinaryColor::Off) + .build(); + + for i in 0..(WIDTH / 10) as i32 { + Line::new(Point::new(i * 10, 0), Point::new(i * 10, HEIGHT as i32)) + .into_styled(PrimitiveStyle::with_stroke(BinaryColor::Off, 1)) + .draw(&mut display) + .unwrap(); + } + for i in 0..(HEIGHT / 10) as i32 { + Line::new(Point::new(0, i * 10), Point::new(WIDTH as i32, i * 10)) + .into_styled(PrimitiveStyle::with_stroke(BinaryColor::Off, 1)) + .draw(&mut display) + .unwrap(); + } + + display.set_rotation(DisplayRotation::Rotate270); + + // let mut cont = Controller::new(SdMmcSpi::new(spi_sd, cs_sd), ClockSD); + let mut sd_mmc = SdMmcSpi::new(spi_sd, cs_sd); + let mut controller = Controller::new(sd_mmc, ClockSD); + + match controller.device().init() { + Ok(_) => { + Text::new("Device detected", Point::new(1, 1)) + .into_styled(style_text) + .draw(&mut display) + .unwrap(); + let sd_type = match controller.device().card_type { + CardType::SD1 => "SD1", + CardType::SD2 => "SD2", + CardType::SDHC => "SDHC", + }; + Text::new(sd_type, Point::new(1, 70)) + .into_styled(style_text) + .draw(&mut display) + .unwrap(); + + controller + .device() + .spi() + .set_baudrate(clocks.peripheral_clock.freq(), 16_000_000u32.Hz()); + match controller.device().card_size_bytes() { + Ok(size) => { + let mut buffer = Buffer::default(); + buffer.write_formatted(&size, &Locale::en); + let s = buffer.as_str(); + Text::new(s, Point::new(1, 35)) + .into_styled(style_text) + .draw(&mut display) + .unwrap(); + } + Err(e) => { + Text::new(error_to_str(e), Point::new(1, 35)) + .into_styled(style_text) + .draw(&mut display) + .unwrap(); + } + } + + let block_count = controller.device().num_blocks().unwrap(); + let mut block = [Block::new()]; + controller + .device() + .read(&mut block, BlockIdx(0), "") + .unwrap(); + // for volume_idx in 0..=3 { + // let volume = controller.get_volume(VolumeIdx(volume_idx)); + // match volume { + // Ok(volume) => { + // let root_dir = controller.open_root_dir(&volume).unwrap(); + // let mut idx = 0; + // controller + // .iterate_dir(&volume, &root_dir, |x| { + // Text::new("Found!!", Point::new(1, (idx * 35) + 70)) + // .into_styled(style_text) + // .draw(&mut display) + // .unwrap(); + // idx += 1; + // }) + // .unwrap(); + // } + // Err(e) => { + // let b = error2_to_str(e); + // let mut buff = Buffer::default(); + // let mut s = match b { + // Ok(s) => s, + // Err(e) => { + // buff = e; + // "" + // } + // }; + // if s.len() == 0 { + // s = buff.as_str(); + // } + // Text::new( + // // error2_to_str(e), + // s, + // Point::new(1, 400 + (volume_idx as i32 * 35)), + // ) + // .into_styled(style_text) + // .draw(&mut display) + // .unwrap(); + // } + // } + // } + // + } + Err(e) => { + Text::new(error_to_str(e), Point::new(1, 1)) + .into_styled(style_text) + .draw(&mut display) + .unwrap(); + } + } + + epd.update_frame(&mut spi, display.buffer()).unwrap(); + epd.display_frame(&mut spi).unwrap(); + delay.delay_ms(1000); + + let mut led_pin = pins.gpio25.into_push_pull_output(); + + loop { + led_pin.set_high().unwrap(); + delay.delay_ms(500); + led_pin.set_low().unwrap(); + delay.delay_ms(500); + } }