diff --git a/examples/hpm5300evk/src/bin/qspi.rs b/examples/hpm5300evk/src/bin/qspi.rs index ec652d5..e8ee56d 100644 --- a/examples/hpm5300evk/src/bin/qspi.rs +++ b/examples/hpm5300evk/src/bin/qspi.rs @@ -2,23 +2,27 @@ #![no_std] use defmt::info; -use embedded_graphics::draw_target::{DrawTarget, DrawTargetExt as _}; -use embedded_graphics::framebuffer::Framebuffer; -use embedded_graphics::geometry::{Point, Size}; -use embedded_graphics::image::ImageDrawable; -use embedded_graphics::pixelcolor::raw::{BigEndian, ToBytes}; +use embedded_graphics::draw_target::DrawTarget; +use embedded_graphics::geometry::{Dimensions, Point, Size}; +use embedded_graphics::image::{Image, ImageRawLE}; +use embedded_graphics::mono_font::ascii::FONT_10X20; +use embedded_graphics::mono_font::MonoTextStyle; +use embedded_graphics::pixelcolor::raw::ToBytes; use embedded_graphics::pixelcolor::{Rgb565, RgbColor}; use embedded_graphics::prelude::OriginDimensions; use embedded_graphics::primitives::Rectangle; -use embedded_graphics::Pixel; +use embedded_graphics::text::Text; +use embedded_graphics::transform::Transform; +use embedded_graphics::{Drawable, Pixel}; use embedded_hal::delay::DelayNs; use embedded_hal::digital::OutputPin; use hpm_hal::gpio::{Level, Output, Speed}; use hpm_hal::mode::Blocking; use hpm_hal::spi::enums::{AddressSize, SpiWidth, TransferMode}; -use hpm_hal::spi::{Error, Spi, TransferConfig}; +use hpm_hal::spi::{Config, Error, Spi, TransferConfig}; +use hpm_hal::time::Hertz; use riscv::delay::McycleDelay; -use {defmt_rtt as _, hpm_hal as hal, panic_halt as _, riscv_rt as _}; +use {defmt_rtt as _, hpm_hal as hal, riscv_rt as _}; #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] pub enum Orientation { @@ -78,12 +82,9 @@ impl RM67162<'_> { dummy_cnt: 0, ..Default::default() }; - // info!("Sending cmd 0x{:X}, data: {=[u8]:X}", cmd, data); if data.len() == 0 { transfer_config.transfer_mode = TransferMode::NoData; - // transfer_config.addr = Some(cmd); - // transfer_config.addr_size = AddressSize::_16Bit; self.qspi.blocking_write(&[], &transfer_config)?; } else { self.qspi.blocking_write(data, &transfer_config)?; @@ -106,9 +107,6 @@ impl RM67162<'_> { if data.len() == 0 { transfer_config.transfer_mode = TransferMode::NoData; - // transfer_config.addr = Some(cmd); - // transfer_config.addr_size = AddressSize::_16Bit; - // transfer_config.data_width = SpiWidth::SING; self.qspi.blocking_write(&[], &transfer_config)?; } else { self.qspi.blocking_write(data, &transfer_config)?; @@ -119,7 +117,6 @@ impl RM67162<'_> { /// rm67162_qspi_init pub fn init(&mut self, delay: &mut impl embedded_hal::delay::DelayNs) -> Result<(), Error> { - // for _ in 0..3 { self.send_cmd(0x11, &[])?; // sleep out delay.delay_ms(120); @@ -131,9 +128,8 @@ impl RM67162<'_> { delay.delay_ms(120); self.send_cmd(0x51, &[0xD0])?; // write brightness - // } - // self.set_orientation(self.orientation)?; + self.set_orientation(self.orientation)?; Ok(()) } @@ -152,8 +148,9 @@ impl RM67162<'_> { pub fn draw_point(&mut self, x: u16, y: u16, color: Rgb565) -> Result<(), Error> { self.set_address(x, y, x, y)?; - self.send_cmd_114(0x2C, &color.to_le_bytes()[..])?; - self.send_cmd_114(0x3C, &color.to_le_bytes()[..])?; + self.send_cmd_114(0x2C, &color.to_be_bytes()[..])?; + // self.send_cmd_114(0x2C, &color.to_le_bytes()[..])?; + // self.send_cmd_114(0x3C, &color.to_le_bytes()[..])?; Ok(()) } @@ -168,7 +165,7 @@ impl RM67162<'_> { self.set_address(x, y, x + w - 1, y + h - 1)?; for _ in 1..((w as u32) * (h as u32)) { - self.send_cmd_114(0x2C, &colors.next().unwrap().to_be_bytes()[..])?; + self.send_cmd_114(0x3C, &colors.next().unwrap().to_be_bytes()[..])?; } Ok(()) @@ -176,28 +173,37 @@ impl RM67162<'_> { fn fill_color(&mut self, x: u16, y: u16, w: u16, h: u16, color: Rgb565) -> Result<(), Error> { self.set_address(x, y, x + w - 1, y + h - 1)?; - // self.cs.set_low().unwrap(); - let mut buffer: [u8; 536 * 240] = [0; 536 * 240]; - info!("get buffer: {}", buffer.len()); - // Convert color rectangle to buffer - for i in 0..(w as u32) * (h as u32) { - if i > 536 * 240 - 2 { + let mut buffer: [u8; 536 * 240] = [0; 536 * 240]; + let total_size = (w as usize) * (h as usize); + let mut i: usize = 0; + let mut buffer_idx = 0; + while i < total_size * 2 { + if buffer_idx >= buffer.len() { + i += buffer.len(); + // Write buffer + self.send_cmd_114(0x3C, &buffer).unwrap(); + buffer_idx = 0; + } + if i + buffer_idx >= total_size * 2 { break; } - buffer[i as usize] = color.to_be_bytes()[0]; - buffer[i as usize + 1] = color.to_be_bytes()[1]; + // Fill the buffer + buffer[buffer_idx] = color.to_be_bytes()[0]; + buffer[buffer_idx + 1] = color.to_be_bytes()[1]; + buffer_idx += 2; } - info!("writing buffer: {}", buffer.len()); - self.send_cmd_114(0x2C, &buffer).unwrap(); - info!("wrote buffer: {}", buffer.len()); + if buffer_idx > 0 { + self.send_cmd_114(0x3C, &buffer[..buffer_idx]).unwrap(); + } Ok(()) } + pub unsafe fn fill_with_framebuffer(&mut self, raw_framebuffer: &[u8]) -> Result<(), Error> { self.set_address(0, 0, self.size().width as u16 - 1, self.size().height as u16 - 1)?; - self.send_cmd_114(0x2C, raw_framebuffer)?; + self.send_cmd_114(0x3C, raw_framebuffer)?; Ok(()) } @@ -266,7 +272,7 @@ fn main() -> ! { let mut rst = Output::new(p.PA09, Level::High, Speed::Fast); - let mut im = Output::new(p.PA00, Level::High, Speed::Fast); + let mut im = Output::new(p.PB12, Level::High, Speed::Fast); im.set_high(); let mut iovcc = Output::new(p.PB13, Level::High, Speed::Fast); @@ -275,56 +281,65 @@ fn main() -> ! { // PA10 let mut led = Output::new(p.PA10, Level::Low, Speed::Fast); - let mut spi: hal::spi::Spi<'_, Blocking> = - Spi::new_blocking_quad(p.SPI1, p.PA26, p.PA27, p.PA29, p.PA28, p.PA30, p.PA31, Default::default()); - - let config = TransferConfig { - cmd: None, - addr: None, - addr_width: SpiWidth::SING, - data_width: SpiWidth::SING, - transfer_mode: TransferMode::WriteOnly, + let spi_config = Config { + addr_len: AddressSize::_24Bit, + frequency: Hertz(40_000_000), + cs2sclk: hpm_hal::spi::enums::ChipSelect2SCLK::_3HalfSclk, + csht: hpm_hal::spi::enums::ChipSelectHighTime::_11HalfSclk, + mode: hpm_hal::spi::enums::PolarityMode::Mode0, ..Default::default() }; - if let Err(e) = spi.blocking_write(&[1, 2, 3, 4, 5, 6, 7, 8], &config) { - defmt::panic!("Error: {:?}", e); - } + let spi: hal::spi::Spi<'_, Blocking> = + Spi::new_blocking_quad(p.SPI1, p.PA26, p.PA27, p.PA29, p.PA28, p.PA30, p.PA31, spi_config); - let mut rm67162 = RM67162::new(spi); - rm67162.reset(&mut rst, &mut delay).unwrap(); + let mut display = RM67162::new(spi); + display.reset(&mut rst, &mut delay).unwrap(); info!("reset display"); - if let Err(e) = rm67162.init(&mut delay) { - info!("Error: {:?}", e); + if let Err(e) = display.init(&mut delay) { + panic!("Error: {:?}", e); } info!("clearing display"); - if let Err(e) = rm67162.clear(Rgb565::WHITE) { - info!("Error: {:?}", e); + if let Err(e) = display.clear(Rgb565::BLACK) { + panic!("Error: {:?}", e); } - info!("Load gif"); - let gif = tinygif::Gif::from_slice(include_bytes!("assets/ferris.gif")).unwrap(); - - let mut fb = Framebuffer::< - Rgb565, - _, - BigEndian, - 536, - 240, - { embedded_graphics::framebuffer::buffer_size::(536, 240) }, - >::new(); - - fb.clear(Rgb565::WHITE).unwrap(); - unsafe { rm67162.fill_with_framebuffer(fb.data()).unwrap() }; - info!("Start drawing"); + + let img_width = 86; + let raw_image_data = ImageRawLE::new(include_bytes!("./assets/ferris.raw"), img_width); + let style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE); + + Text::new("Hello HPM!", Point::new(200, 150), style) + .draw(&mut display) + .unwrap(); + let diff = 1; + let mut ferris = Image::new(&raw_image_data, Point::new(0, 40)); + info!("Looping"); loop { - for frame in gif.frames() { - frame.draw(&mut fb.translated(Point::new(0, 0))).unwrap(); - unsafe { - rm67162.fill_with_framebuffer(fb.data()).unwrap(); - } - // info!("tick"); - } led.toggle(); - delay.delay_ms(200); + let mut clear = Rectangle::new( + Point { + x: ferris.bounding_box().top_left.x, + y: 40, + }, + Size { + width: diff as u32, + height: raw_image_data.bounding_box().size.height as u32, + }, + ); + let f = if ferris.bounding_box().top_left.x + img_width as i32 >= 536 { + clear.size.width = img_width; + ferris.translate_mut(Point::new(-450, 0)) + } else { + ferris.translate_mut(Point::new(diff, 0)) + }; + + f.draw(&mut display).unwrap(); + display.fill_solid(&clear, Rgb565::BLACK).unwrap(); } } + +#[panic_handler] +fn panic(info: &core::panic::PanicInfo) -> ! { + defmt::error!("{:?}", defmt::Debug2Format(info)); + loop {} +} diff --git a/examples/hpm5300evk/src/bin/spi.rs b/examples/hpm5300evk/src/bin/spi.rs index 2f257f2..363ef6a 100644 --- a/examples/hpm5300evk/src/bin/spi.rs +++ b/examples/hpm5300evk/src/bin/spi.rs @@ -18,7 +18,7 @@ use embedded_hal::digital::OutputPin; use embedded_hal::spi::SpiDevice; use hpm_hal::gpio::{Level, Output, Speed}; use hpm_hal::mode::Blocking; -use hpm_hal::spi::{Config, Spi, TransferConfig}; +use hpm_hal::spi::{Config, Spi}; use hpm_hal::time::Hertz; use riscv::delay::McycleDelay; use {defmt_rtt as _, hpm_hal as hal, panic_halt as _, riscv_rt as _}; @@ -305,5 +305,4 @@ fn main() -> ! { f.draw(&mut display).unwrap(); display.fill_solid(&clear, Rgb565::BLACK).unwrap(); } - } diff --git a/src/spi/enums.rs b/src/spi/enums.rs index e4a62b7..24f26b9 100644 --- a/src/spi/enums.rs +++ b/src/spi/enums.rs @@ -298,4 +298,4 @@ pub enum PolarityMode { Mode2, /// Mode3, CPOL=1, CPHA=1 Mode3, -} \ No newline at end of file +} diff --git a/src/spi/mod.rs b/src/spi/mod.rs index 7d6d2d7..a603434 100644 --- a/src/spi/mod.rs +++ b/src/spi/mod.rs @@ -9,7 +9,9 @@ use core::marker::PhantomData; use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; +use embedded_hal::delay::DelayNs; use enums::*; +use riscv::delay::McycleDelay; use crate::gpio::AnyPin; use crate::mode::{Blocking, Mode}; @@ -31,9 +33,7 @@ pub struct Config { pub cs2sclk: ChipSelect2SCLK, /// Time the Chip Select line stays high. pub csht: ChipSelectHighTime, - /// F(SCLK) = F(SPI_SOURCE) / (2 * (sclk_div + 1). - /// If sclk_div = 0xff, F(SCLK) = F(SPI_SOURCE). - // pub sclk_div: u8, + /// SPI frequency. pub frequency: Hertz, } @@ -128,16 +128,10 @@ impl<'d> Spi<'d, Blocking> { T::add_resource_group(0); - cs.ioc_pad().func_ctl().write(|w| { - w.set_alt_select(cs.alt_num()); - }); - mosi.ioc_pad().func_ctl().write(|w| { - w.set_alt_select(mosi.alt_num()); - }); - miso.ioc_pad().func_ctl().write(|w| { - w.set_alt_select(miso.alt_num()); - }); - sclk.ioc_pad().func_ctl().write(|w| { + cs.set_as_alt(cs.alt_num()); + mosi.set_as_alt(mosi.alt_num()); + miso.set_as_alt(miso.alt_num()); + sclk.ioc_pad().func_ctl().modify(|w| { w.set_alt_select(sclk.alt_num()); w.set_loop_back(true); }); @@ -170,25 +164,15 @@ impl<'d> Spi<'d, Blocking> { T::add_resource_group(0); - cs.ioc_pad().func_ctl().write(|w| { - w.set_alt_select(cs.alt_num()); - }); - mosi.ioc_pad().func_ctl().write(|w| { - w.set_alt_select(mosi.alt_num()); - }); - miso.ioc_pad().func_ctl().write(|w| { - w.set_alt_select(miso.alt_num()); - }); - sclk.ioc_pad().func_ctl().write(|w| { + cs.set_as_alt(cs.alt_num()); + mosi.set_as_alt(mosi.alt_num()); + miso.set_as_alt(miso.alt_num()); + sclk.ioc_pad().func_ctl().modify(|w| { w.set_alt_select(sclk.alt_num()); w.set_loop_back(true); }); - d2.ioc_pad().func_ctl().write(|w| { - w.set_alt_select(d2.alt_num()); - }); - d3.ioc_pad().func_ctl().write(|w| { - w.set_alt_select(d3.alt_num()); - }); + d2.set_as_alt(d2.alt_num()); + d3.set_as_alt(d3.alt_num()); let cs_index = cs.cs_index(); Self::_new_inner( @@ -221,6 +205,7 @@ impl<'d, M: Mode> Spi<'d, M> { info: T::info(), state: T::state(), kernel_clock: T::frequency(), + delay: McycleDelay::new(crate::sysctl::clocks().cpu0.0), cs, sclk, mosi, @@ -311,7 +296,7 @@ impl<'d, M: Mode> Spi<'d, M> { w.set_slvdataonly(config.slave_data_only_mode); w.set_cmden(config.cmd.is_some()); w.set_addren(config.addr.is_some()); - // Addr fmt: false: 1 line, true: 2/4 lines(same with data) + // Addr fmt: false: 1 line, true: 2/4 lines(same with data, aka `dualquad` field) w.set_addrfmt(match config.addr_width { SpiWidth::SING => false, SpiWidth::DUAL | SpiWidth::QUAD => true, @@ -389,9 +374,10 @@ impl<'d, M: Mode> Spi<'d, M> { let r = self.info.regs; // Write data byte by byte - for &b in data { + for b in data { + // TODO: Add timeout while r.status().read().txfull() {} - r.data().write(|w| w.set_data(b as u32)); + r.data().write(|w| w.set_data(*b as u32)); } Ok(()) @@ -403,6 +389,7 @@ impl<'d, M: Mode> Spi<'d, M> { let r = self.info.regs; for i in 0..data.len() { + // TODO: Add timeout while r.status().read().rxempty() {} let b = r.data().read().0 as u8; data[i] = b;