269 lines
8.3 KiB
Rust
269 lines
8.3 KiB
Rust
#![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::<u32>::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 {}
|
|
}
|