diff --git a/Cargo.toml b/Cargo.toml index f25587d..2735b42 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,17 +9,16 @@ rust-version = "1.71" [dependencies] bitfield = { version = "0.17.0" } cfg-if = "1.0.0" -critical-section = { version = "1.1.2" } +critical-section = { version = "1.2.0" } defmt = { version = "0.3.8", optional = true } embedded-graphics = { version = "0.8.1" } embedded-hal = { version = "1.0.0" } embedded-hal-async = { version = "1.0.0" } -esp-hal = { version = "0.22.0" } +esp-hal = { version = "0.22.0", features = ["unstable"] } esp-hal-procmacros = { version = "0.15.0", features = ["ram"] } fugit = { version = "0.3.7" } log = { version = "0.4.22", optional = true } static_cell = { version = "2.1", features = ["nightly"] } -xtensa-lx-rt = { version = "0.17.1", optional = true } [build-dependencies] esp-build = "0.1.0" @@ -61,15 +60,25 @@ esp32c6 = [ debug = ["esp-hal/debug"] defmt = [ "dep:defmt", + "esp-hal/defmt", "esp-backtrace/defmt", "fugit/defmt" ] log = [ "dep:log", + "esp-hal/log", "esp-backtrace/println", "esp-println/auto", "esp-println/log", "esp-println/colors", ] -xtensa-lx-rt = ["dep:xtensa-lx-rt"] valid-pin = [] # only for parl_io debugging + +[patch.crates-io] +esp-backtrace = { path = "../esp-hal/esp-backtrace" } +esp-build = { path = "../esp-hal/esp-build" } +esp-hal = { path = "../esp-hal/esp-hal" } +esp-hal-embassy = { path = "../esp-hal/esp-hal-embassy" } +esp-println = { path = "../esp-hal/esp-println" } +esp-riscv-rt = { path = "../esp-hal/esp-riscv-rt" } +xtensa-lx-rt = { path = "../esp-hal/xtensa-lx-rt" } diff --git a/examples/i2s_parallel.rs b/examples/i2s_parallel.rs index 2ada79b..a261697 100644 --- a/examples/i2s_parallel.rs +++ b/examples/i2s_parallel.rs @@ -13,16 +13,16 @@ //! - G1 => GPIO4 //! - B1 => GPIO17 //! - R2 => GPIO18 -//! - G2 => GPIO19 -//! - B2 => GPIO5 -//! - A => GPIO12 -//! - B => GPIO14 -//! - C => GPIO26 -//! - D => GPIO27 -//! - E => GPIO13 -//! - OE => GPIO32 -//! - CLK => GPIO25 -//! - LAT => GPIO33 +//! - G2 => GPIO5 +//! - B2 => GPIO19 +//! - A => GPIO15 +//! - B => GPIO13 +//! - C => GPIO12 +//! - D => GPIO14 +//! - E => GPIO2 +//! - OE => GPIO25 +//! - CLK => GPIO27 +//! - LAT => GPIO26 //! //! Note that you most likeliy need level converters 3.3v to 5v for all HUB75 //! signals @@ -53,9 +53,6 @@ use embedded_graphics::text::Alignment; use embedded_graphics::text::Text; use embedded_graphics::Drawable; use esp_backtrace as _; -use esp_hal::dma::Dma; -use esp_hal::dma::DmaPriority; -use esp_hal::dma::I2s0DmaChannelCreator; use esp_hal::gpio::AnyPin; use esp_hal::i2s::parallel::AnyI2s; use esp_hal::interrupt::software::SoftwareInterruptControl; @@ -242,7 +239,13 @@ async fn hub75_task( latch: peripherals.latch, }; - let mut hub75 = Hub75Type::new_async(peripherals.i2s, pins, channel, tx_descriptors, 19.MHz()); + let mut hub75 = Hub75Type::new_async( + >::into(peripherals.i2s), + pins, + channel, + tx_descriptors, + 19.MHz(), + ).expect("failed to construct Hub75!"); let mut count = 0u32; let mut start = Instant::now(); @@ -292,7 +295,6 @@ async fn main(spawner: Spawner) { let peripherals = esp_hal::init(config); let sw_ints = SoftwareInterruptControl::new(peripherals.SW_INTERRUPT); let software_interrupt = sw_ints.software_interrupt2; - let dma = Dma::new(peripherals.DMA); let timg0 = TimerGroup::new(peripherals.TIMG0); diff --git a/examples/lcd_cam.rs b/examples/lcd_cam.rs index 9a2313b..ff24f29 100644 --- a/examples/lcd_cam.rs +++ b/examples/lcd_cam.rs @@ -51,7 +51,7 @@ use embedded_graphics::Drawable; use esp_backtrace as _; use esp_hal::cpu_control::CpuControl; use esp_hal::cpu_control::Stack; -use esp_hal::dma::Dma; +use esp_hal::dma::DmaChannel; use esp_hal::dma::DmaPriority; use esp_hal::gpio::AnyPin; use esp_hal::interrupt::software::SoftwareInterruptControl; @@ -96,7 +96,7 @@ type FrameBufferExchange = Signal; pub struct Hub75Peripherals { pub lcd_cam: LCD_CAM, - pub dma_channel: esp_hal::dma::ChannelCreator<0>, + pub dma_channel: esp_hal::dma::DmaChannel0, pub red1: AnyPin, pub grn1: AnyPin, pub blu1: AnyPin, @@ -219,8 +219,8 @@ async fn hub75_task( ) { info!("hub75_task: starting!"); let channel = peripherals - .dma_channel - .configure(false, DmaPriority::Priority0); + .dma_channel; + channel.set_priority(DmaPriority::Priority0); let (_, tx_descriptors) = esp_hal::dma_descriptors!(0, SIZE * size_of::()); let pins = Hub75Pins { @@ -241,7 +241,8 @@ async fn hub75_task( }; let mut hub75 = - Hub75Type::new_async(peripherals.lcd_cam, pins, channel, tx_descriptors, 20.MHz()); + Hub75Type::new_async(peripherals.lcd_cam, pins, channel, tx_descriptors, 20.MHz()) + .expect("failed to construct Hub75!"); let mut count = 0u32; let mut start = Instant::now(); @@ -294,7 +295,6 @@ async fn main(_spawner: Spawner) { let sw_ints = SoftwareInterruptControl::new(peripherals.SW_INTERRUPT); let software_interrupt = sw_ints.software_interrupt2; let cpu_control = CpuControl::new(peripherals.CPU_CTRL); - let dma = Dma::new(peripherals.DMA); let timg0 = TimerGroup::new(peripherals.TIMG0); @@ -316,7 +316,7 @@ async fn main(_spawner: Spawner) { let hub75_peripherals = Hub75Peripherals { lcd_cam: peripherals.LCD_CAM, - dma_channel: dma.channel0, + dma_channel: peripherals.DMA_CH0, red1: peripherals.GPIO38.degrade(), grn1: peripherals.GPIO42.degrade(), blu1: peripherals.GPIO48.degrade(), diff --git a/examples/parl_io.rs b/examples/parl_io.rs index cb73500..7cac9ee 100644 --- a/examples/parl_io.rs +++ b/examples/parl_io.rs @@ -48,10 +48,9 @@ use embedded_graphics::text::Alignment; use embedded_graphics::text::Text; use embedded_graphics::Drawable; use esp_backtrace as _; -use esp_hal::dma::Dma; +use esp_hal::dma::DmaChannel; use esp_hal::dma::DmaPriority; use esp_hal::gpio::AnyPin; -use esp_hal::gpio::Io; use esp_hal::interrupt::software::SoftwareInterruptControl; use esp_hal::interrupt::Priority; use esp_hal::peripherals::PARL_IO; @@ -80,7 +79,7 @@ macro_rules! mk_static { pub struct DisplayPeripherals { pub parl_io: PARL_IO, - pub dma_channel: esp_hal::dma::ChannelCreator<0>, + pub dma_channel: esp_hal::dma::DmaChannel0, pub red1: AnyPin, pub grn1: AnyPin, pub blu1: AnyPin, @@ -212,9 +211,8 @@ async fn hub75_task( fb: &'static mut FBType, ) { info!("hub75_task: starting!"); - let channel = peripherals - .dma_channel - .configure(false, DmaPriority::Priority0); + let channel = peripherals.dma_channel; + channel.set_priority(DmaPriority::Priority0); let (_, tx_descriptors) = esp_hal::dma_descriptors!(0, SIZE * size_of::()); let pins = Hub75Pins { @@ -287,7 +285,6 @@ async fn main(spawner: Spawner) { let peripherals = esp_hal::init(config); let sw_ints = SoftwareInterruptControl::new(peripherals.SW_INTERRUPT); let software_interrupt = sw_ints.software_interrupt2; - let dma = Dma::new(peripherals.DMA); let timg0 = TimerGroup::new(peripherals.TIMG0); @@ -307,7 +304,7 @@ async fn main(spawner: Spawner) { let display_peripherals = DisplayPeripherals { parl_io: peripherals.PARL_IO, - dma_channel: dma.channel0, + dma_channel: peripherals.DMA_CH0, red1: peripherals.GPIO19.degrade(), grn1: peripherals.GPIO20.degrade(), blu1: peripherals.GPIO21.degrade(), diff --git a/src/i2s_parallel.rs b/src/i2s_parallel.rs index dda992a..384dca4 100644 --- a/src/i2s_parallel.rs +++ b/src/i2s_parallel.rs @@ -1,9 +1,7 @@ use core::cell::Cell; -use esp_hal::dma::Channel; -use esp_hal::dma::DmaChannelConvert; +use esp_hal::dma::DmaChannelFor; use esp_hal::dma::DmaDescriptor; -use esp_hal::dma::DmaEligible; use esp_hal::dma::DmaTxBuf; use esp_hal::gpio::NoPin; use esp_hal::i2s::parallel::AnyI2s; @@ -21,13 +19,16 @@ pub struct Hub75<'d, DM: esp_hal::Mode> { } impl<'d> Hub75<'d, esp_hal::Async> { - pub fn new_async::Dma>>( + pub fn new_async( i2s: impl Peripheral

+ 'd, hub75_pins: Hub75Pins, - channel: Channel<'d, esp_hal::Blocking, CH>, + channel: impl Peripheral

+ 'd, tx_descriptors: &'static mut [DmaDescriptor], frequency: HertzU32, - ) -> Self { + ) -> Result + where + CH: DmaChannelFor, + { let (_, blank) = hub75_pins.blank.split(); let pins = TxSixteenBits::new( hub75_pins.addr0, @@ -48,13 +49,13 @@ impl<'d> Hub75<'d, esp_hal::Async> { NoPin, ); - let i2s = I2sParallel::new(i2s, channel.into_async(), frequency, pins, hub75_pins.clock); + let i2s = I2sParallel::new(i2s, channel, frequency, pins, hub75_pins.clock).into_async(); let i2s = Cell::new(Some(i2s)); let tx_descriptors = Cell::new(Some(tx_descriptors)); - Self { + Ok(Self { i2s, tx_descriptors, - } + }) } pub async fn render_async< @@ -88,3 +89,7 @@ impl<'d> Hub75<'d, esp_hal::Async> { self.tx_descriptors.set(Some(tx_descriptors)); } } + +#[derive(Debug, Clone, Copy, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Hub75Error {} diff --git a/src/lcd_cam.rs b/src/lcd_cam.rs index f6d7cd6..1438a80 100644 --- a/src/lcd_cam.rs +++ b/src/lcd_cam.rs @@ -1,17 +1,20 @@ use core::cell::Cell; -use esp_hal::dma::Channel; -use esp_hal::dma::DmaChannelConvert; +#[cfg(feature = "defmt")] +use defmt::debug; use esp_hal::dma::DmaDescriptor; -use esp_hal::dma::DmaEligible; use esp_hal::dma::DmaTxBuf; +use esp_hal::dma::TxChannelFor; use esp_hal::gpio::NoPin; use esp_hal::lcd_cam::lcd::i8080; use esp_hal::lcd_cam::lcd::i8080::Command; use esp_hal::lcd_cam::lcd::i8080::TxSixteenBits; use esp_hal::lcd_cam::lcd::i8080::I8080; use esp_hal::lcd_cam::LcdCam; +use esp_hal::peripheral::Peripheral; use esp_hal::peripherals::LCD_CAM; +#[cfg(feature = "log")] +use log::debug; use crate::framebuffer::DmaFrameBuffer; use crate::HertzU32; @@ -26,12 +29,12 @@ impl<'d> Hub75<'d, esp_hal::Async> { pub fn new_async( lcd_cam: LCD_CAM, hub75_pins: Hub75Pins, - channel: Channel<'d, esp_hal::Blocking, CH>, + channel: impl Peripheral

+ 'd, tx_descriptors: &'static mut [DmaDescriptor], frequency: HertzU32, - ) -> Self + ) -> Result where - CH: DmaChannelConvert<::Dma>, + CH: TxChannelFor, { let lcd_cam = LcdCam::new(lcd_cam).into_async(); Self::new_internal(lcd_cam, hub75_pins, channel, tx_descriptors, frequency) @@ -55,10 +58,13 @@ impl<'d> Hub75<'d, esp_hal::Async> { core::slice::from_raw_parts_mut(ptr as *mut u8, len) }; let tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).expect("DmaTxBuf::new failed"); + debug!("lcd_cam: Sending buffer"); let mut xfer = i8080 .send(Command::::None, 0, tx_buf) .expect("send failed"); + debug!("lcd_cam: Waiting for transfer to complete"); xfer.wait_for_done().await; + debug!("lcd_cam: Transfer complete"); let (result, i8080, tx_buf) = xfer.wait(); result.expect("transfer failed"); let (tx_descriptors, _) = tx_buf.split(); @@ -71,12 +77,12 @@ impl<'d, DM: esp_hal::Mode> Hub75<'d, DM> { fn new_internal( lcd_cam: LcdCam<'d, DM>, hub75_pins: Hub75Pins, - channel: Channel<'d, esp_hal::Blocking, CH>, + channel: impl Peripheral

+ 'd, tx_descriptors: &'static mut [DmaDescriptor], frequency: HertzU32, - ) -> Self + ) -> Result where - CH: DmaChannelConvert<::Dma>, + CH: TxChannelFor, { let (_, blank) = hub75_pins.blank.split(); let pins = TxSixteenBits::new( @@ -98,19 +104,22 @@ impl<'d, DM: esp_hal::Mode> Hub75<'d, DM> { NoPin, ); - let i8080 = I8080::new( - lcd_cam.lcd, - channel.tx, - pins, - frequency, - i8080::Config::default(), - ) - .with_ctrl_pins(NoPin, hub75_pins.clock); + let mut config = esp_hal::lcd_cam::lcd::i8080::Config::default(); + config.frequency = frequency; + let i8080 = I8080::new(lcd_cam.lcd, channel, pins, i8080::Config::default()) + .map_err(Hub75Error::I8080)? + .with_ctrl_pins(NoPin, hub75_pins.clock); let i8080 = Cell::new(Some(i8080)); let tx_descriptors = Cell::new(Some(tx_descriptors)); - Self { + Ok(Self { i8080, tx_descriptors, - } + }) } } + +#[derive(Debug, Clone, Copy, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Hub75Error { + I8080(esp_hal::lcd_cam::lcd::i8080::ConfigError), +} diff --git a/src/parl_io.rs b/src/parl_io.rs index cc5b85c..769c9da 100644 --- a/src/parl_io.rs +++ b/src/parl_io.rs @@ -1,8 +1,6 @@ -use esp_hal::dma::Channel; -use esp_hal::dma::DmaChannelConvert; use esp_hal::dma::DmaDescriptor; -use esp_hal::dma::DmaEligible; use esp_hal::dma::ReadBuffer; +use esp_hal::dma::TxChannelFor; use esp_hal::gpio::NoPin; use esp_hal::parl_io::BitPackOrder; use esp_hal::parl_io::ClkOutPin; @@ -12,6 +10,7 @@ use esp_hal::parl_io::SampleEdge; #[cfg(feature = "valid-pin")] use esp_hal::parl_io::TxPinConfigIncludingValidPin; use esp_hal::parl_io::TxSixteenBits; +use esp_hal::peripheral::Peripheral; use esp_hal::peripherals::PARL_IO; use crate::framebuffer::DmaFrameBuffer; @@ -29,12 +28,12 @@ impl<'d> Hub75<'d, esp_hal::Async> { pub fn new_async( parl_io: PARL_IO, hub75_pins: Hub75Pins, // TODO: how can we make this non-static? - channel: Channel<'d, esp_hal::Blocking, CH>, + channel: impl Peripheral

+ 'd, tx_descriptors: &'static mut [DmaDescriptor], frequency: HertzU32, ) -> Self where - CH: DmaChannelConvert<::Dma>, + CH: TxChannelFor, { let (_, blank) = hub75_pins.blank.split(); @@ -86,8 +85,9 @@ impl<'d> Hub75<'d, esp_hal::Async> { // TODO: how can we make this non-static? static CLOCK_PIN: StaticCell = StaticCell::new(); let clock_pin = CLOCK_PIN.init(ClkOutPin::new(hub75_pins.clock)); - let parl_io = - ParlIoTxOnly::new(parl_io, channel.into_async(), tx_descriptors, frequency).unwrap(); // TODO: handle error + let parl_io = ParlIoTxOnly::new(parl_io, channel, tx_descriptors, frequency) + .unwrap() + .into_async(); // TODO: handle error let parl_io = parl_io .tx