#![no_main] #![no_std] use crate::hal::{ dsi::{ ColorCoding, DsiChannel, DsiCmdModeTransmissionKind, DsiConfig, DsiHost, DsiInterrupts, DsiMode, DsiPhyTimers, DsiPllConfig, DsiVideoMode, LaneCount, }, ltdc::{DisplayConfig, DisplayController, PixelFormat}, pac::{CorePeripherals, Peripherals}, prelude::*, }; use cortex_m_rt::entry; use defmt_rtt as _; use otm8009a::{Otm8009A, Otm8009AConfig}; use panic_probe as _; use stm32f4xx_hal::{self as hal, ltdc, rcc::Config}; defmt::timestamp!("{=u32}", 0u32); const WIDTH: usize = 480; const HEIGHT: usize = 800; const DISPLAY_CONFIGURATION: DisplayConfig = DisplayConfig { active_width: WIDTH as _, active_height: HEIGHT as _, h_back_porch: 34, h_front_porch: 34, v_back_porch: 15, v_front_porch: 16, h_sync: 2, v_sync: 1, frame_rate: 60, h_sync_pol: true, v_sync_pol: true, no_data_enable_pol: false, pixel_clock_pol: true, }; #[entry] fn main() -> ! { let peripherals = Peripherals::take().unwrap(); let core_peripherals = CorePeripherals::take().unwrap(); let hse_freq = 8.MHz(); let mut rcc = peripherals.RCC.freeze( Config::hse(hse_freq) .hclk(180.MHz()) .pclk1(45.MHz()) .pclk2(32.MHz()) .sysclk(180.MHz()), ); let mut delay = core_peripherals.SYST.delay(&rcc.clocks); let fmc = peripherals.FMC; let gpioc = peripherals.GPIOC.split(&mut rcc); let gpiod = peripherals.GPIOD.split(&mut rcc); let gpioe = peripherals.GPIOE.split(&mut rcc); let gpiof = peripherals.GPIOF.split(&mut rcc); let gpiog = peripherals.GPIOG.split(&mut rcc); let gpioh = peripherals.GPIOH.split(&mut rcc); let gpioi = peripherals.GPIOI.split(&mut rcc); let _pc0 = gpioc.pc0.into_alternate::<12>(); let _pd0 = gpiod.pd0.into_alternate::<12>(); let _pd1 = gpiod.pd1.into_alternate::<12>(); let _pd8 = gpiod.pd8.into_alternate::<12>(); let _pd9 = gpiod.pd9.into_alternate::<12>(); let _pd10 = gpiod.pd10.into_alternate::<12>(); let _pd14 = gpiod.pd14.into_alternate::<12>(); let _pd15 = gpiod.pd15.into_alternate::<12>(); let _pe0 = gpioe.pe0.into_alternate::<12>(); let _pe1 = gpioe.pe1.into_alternate::<12>(); let _pe7 = gpioe.pe7.into_alternate::<12>(); let _pe8 = gpioe.pe8.into_alternate::<12>(); let _pe9 = gpioe.pe9.into_alternate::<12>(); let _pe10 = gpioe.pe10.into_alternate::<12>(); let _pe11 = gpioe.pe11.into_alternate::<12>(); let _pe12 = gpioe.pe12.into_alternate::<12>(); let _pe13 = gpioe.pe13.into_alternate::<12>(); let _pe14 = gpioe.pe14.into_alternate::<12>(); let _pe15 = gpioe.pe15.into_alternate::<12>(); let _pf0 = gpiof.pf0.into_alternate::<12>(); let _pf1 = gpiof.pf1.into_alternate::<12>(); let _pf2 = gpiof.pf2.into_alternate::<12>(); let _pf3 = gpiof.pf3.into_alternate::<12>(); let _pf4 = gpiof.pf4.into_alternate::<12>(); let _pf5 = gpiof.pf5.into_alternate::<12>(); let _pf11 = gpiof.pf11.into_alternate::<12>(); let _pf12 = gpiof.pf12.into_alternate::<12>(); let _pf13 = gpiof.pf13.into_alternate::<12>(); let _pf14 = gpiof.pf14.into_alternate::<12>(); let _pf15 = gpiof.pf15.into_alternate::<12>(); let _pg0 = gpiog.pg0.into_alternate::<12>(); let _pg1 = gpiog.pg1.into_alternate::<12>(); let _pg4 = gpiog.pg4.into_alternate::<12>(); let _pg5 = gpiog.pg5.into_alternate::<12>(); let _pg8 = gpiog.pg8.into_alternate::<12>(); let _pg15 = gpiog.pg15.into_alternate::<12>(); let _ph2 = gpioh.ph2.into_alternate::<12>(); let _ph3 = gpioh.ph3.into_alternate::<12>(); let _ph8 = gpioh.ph8.into_alternate::<12>(); let _ph9 = gpioh.ph9.into_alternate::<12>(); let _ph10 = gpioh.ph10.into_alternate::<12>(); let _ph11 = gpioh.ph11.into_alternate::<12>(); let _ph12 = gpioh.ph12.into_alternate::<12>(); let _ph13 = gpioh.ph13.into_alternate::<12>(); let _ph14 = gpioh.ph14.into_alternate::<12>(); let _ph15 = gpioh.ph15.into_alternate::<12>(); let _pi0 = gpioi.pi0.into_alternate::<12>(); let _pi1 = gpioi.pi1.into_alternate::<12>(); let _pi2 = gpioi.pi2.into_alternate::<12>(); let _pi3 = gpioi.pi3.into_alternate::<12>(); let _pi4 = gpioi.pi4.into_alternate::<12>(); let _pi5 = gpioi.pi5.into_alternate::<12>(); let _pi6 = gpioi.pi6.into_alternate::<12>(); let _pi7 = gpioi.pi7.into_alternate::<12>(); let _pi9 = gpioi.pi9.into_alternate::<12>(); let _pi10 = gpioi.pi10.into_alternate::<12>(); rcc.ahb3enr().modify(|_, w| w.fmcen().set_bit()); fmc.sdcr1().write(|w| { w.wp().disabled(); w.nc().bits8(); w.nb().nb4(); w.nr().bits12(); w.cas().clocks3(); w.mwid().bits32(); w.rpipe().no_delay(); w.sdclk().div2(); w.rburst().enabled() }); fmc.sdtr1().write(|w| { w.twr().set(2); w.trc().set(7); w.trp().set(2); w.tras().set(4); w.txsr().set(7); w.trcd().set(2); w.tmrd().set(2) }); fmc.sdcmr().write(|w| { w.mode().clock_configuration_enable(); w.ctb1().issued(); w.nrfs().set(1); w.mrd().set(0) }); while fmc.sdsr().read().busy().bit_is_set() {} delay.delay_us(200u32); fmc.sdcmr().write(|w| { w.mode().pall(); w.ctb1().issued(); w.nrfs().set(1); w.mrd().set(0) }); while fmc.sdsr().read().busy().bit_is_set() {} fmc.sdcmr().write(|w| { w.mode().auto_refresh_command(); w.ctb1().issued(); w.nrfs().set(8); w.mrd().set(0) }); while fmc.sdsr().read().busy().bit_is_set() {} fmc.sdcmr().write(|w| { w.mode().load_mode_register(); w.ctb1().issued(); w.nrfs().set(1); w.mrd().set(0b1000110001) }); while fmc.sdsr().read().busy().bit_is_set() {} fmc.sdrtr().write(|w| w.count().set(1385)); let mut lcd_reset = gpioh.ph7.into_push_pull_output(); lcd_reset.set_low(); delay.delay_ms(20u32); lcd_reset.set_high(); delay.delay_ms(10u32); #[unsafe(link_section = ".sdram")] static mut BUFF: [u32; 480 * 800] = [0; 480 * 800]; let mut display = DisplayController::::new( peripherals.LTDC, peripherals.DMA2D, None, PixelFormat::ARGB8888, DISPLAY_CONFIGURATION, Some(hse_freq), ); display.enable_layer(ltdc::Layer::L1); display.config_layer( ltdc::Layer::L1, unsafe { &mut BUFF[..] }, PixelFormat::ARGB8888, ); let dsi_pll_config = unsafe { DsiPllConfig::manual(125, 2, 0, 4) }; let dsi_config = DsiConfig { mode: DsiMode::Video { mode: DsiVideoMode::Burst, }, lane_count: LaneCount::DoubleLane, channel: DsiChannel::Ch0, hse_freq, ltdc_freq: 27_429.kHz(), interrupts: DsiInterrupts::None, color_coding_host: ColorCoding::TwentyFourBits, color_coding_wrapper: ColorCoding::TwentyFourBits, lp_size: 4, vlp_size: 4, }; let mut dsi_host = DsiHost::init( dsi_pll_config, DISPLAY_CONFIGURATION, dsi_config, peripherals.DSI, &mut rcc, ) .unwrap(); dsi_host.configure_phy_timers(DsiPhyTimers { dataline_hs2lp: 35, dataline_lp2hs: 35, clock_hs2lp: 35, clock_lp2hs: 35, dataline_max_read_time: 0, stop_wait_time: 10, }); dsi_host.set_command_mode_transmission_kind(DsiCmdModeTransmissionKind::AllInLowPower); dsi_host.start(); dsi_host.enable_bus_turn_around(); dsi_host.set_command_mode_transmission_kind(DsiCmdModeTransmissionKind::AllInHighSpeed); dsi_host.force_rx_low_power(true); dsi_host.enable_color_test(); let mut otm = Otm8009A::new(); otm.init( &mut dsi_host, Otm8009AConfig { frame_rate: otm8009a::FrameRate::_60Hz, mode: otm8009a::Mode::Portrait, color_map: otm8009a::ColorMap::Rgb, cols: WIDTH as u16, rows: HEIGHT as u16, }, &mut delay, ) .unwrap(); gpiog.pg6.into_push_pull_output().set_low(); gpiod.pd4.into_push_pull_output().set_low(); gpiod.pd5.into_push_pull_output().set_low(); peripherals .GPIOK .split(&mut rcc) .pk3 .into_push_pull_output() .set_low(); loop {} }