esp-hal/hil-test/tests/lcd_cam.rs
Dániel Buga 8c69e8cb51
Newtype fugit Rate, Instant and Duration (#3083)
* Newtype fugit Rate, Instant and Duration

* Document, remove time::now

* Fix perf

* Tweak docs
2025-02-04 17:23:08 +00:00

149 lines
4.6 KiB
Rust

//! LCD_CAM Camera and DPI tests
//% CHIPS: esp32s3
//% FEATURES: unstable
#![no_std]
#![no_main]
use esp_hal::{
dma::{DmaChannel, DmaRxBuf, DmaTxBuf},
dma_buffers,
gpio::Level,
lcd_cam::{
cam::{self, Camera, RxEightBits},
lcd::{
dpi,
dpi::{Dpi, Format, FrameTiming},
ClockMode,
Phase,
Polarity,
},
LcdCam,
},
peripherals::Peripherals,
time::Rate,
};
use hil_test as _;
struct Context {
peripherals: Peripherals,
dma_tx_buf: DmaTxBuf,
dma_rx_buf: DmaRxBuf,
}
#[cfg(test)]
#[embedded_test::tests]
mod tests {
use super::*;
#[init]
fn init() -> Context {
let peripherals = esp_hal::init(esp_hal::Config::default());
let (rx_buffer, rx_descriptors, tx_buffer, tx_descriptors) = dma_buffers!(50 * 50);
let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap();
let dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap();
Context {
peripherals,
dma_tx_buf,
dma_rx_buf,
}
}
#[test]
fn test_camera_can_receive_from_rgb(ctx: Context) {
let peripherals = ctx.peripherals;
let lcd_cam = LcdCam::new(peripherals.LCD_CAM);
let (rx_channel, tx_channel) = peripherals.DMA_CH2.split();
let (vsync_in, vsync_out) = peripherals.GPIO6.split();
let (hsync_in, hsync_out) = peripherals.GPIO7.split();
let (de_in, de_out) = peripherals.GPIO14.split();
let (pclk_in, pclk_out) = peripherals.GPIO13.split();
let (d0_in, d0_out) = peripherals.GPIO11.split();
let (d1_in, d1_out) = peripherals.GPIO9.split();
let (d2_in, d2_out) = peripherals.GPIO8.split();
let (d3_in, d3_out) = peripherals.GPIO47.split();
let (d4_in, d4_out) = peripherals.GPIO12.split();
let (d5_in, d5_out) = peripherals.GPIO18.split();
let (d6_in, d6_out) = peripherals.GPIO17.split();
let (d7_in, d7_out) = peripherals.GPIO16.split();
let config = dpi::Config::default()
.with_clock_mode(ClockMode {
polarity: Polarity::IdleHigh,
phase: Phase::ShiftLow,
})
.with_frequency(Rate::from_khz(500))
.with_format(Format {
enable_2byte_mode: false,
..Default::default()
})
// Send a 50x50 video
.with_timing(FrameTiming {
horizontal_total_width: 65,
hsync_width: 5,
horizontal_blank_front_porch: 10,
horizontal_active_width: 50,
vertical_total_height: 65,
vsync_width: 5,
vertical_blank_front_porch: 10,
vertical_active_height: 50,
hsync_position: 0,
})
.with_vsync_idle_level(Level::High)
.with_hsync_idle_level(Level::High)
.with_de_idle_level(Level::Low)
.with_disable_black_region(false);
let dpi = Dpi::new(lcd_cam.lcd, tx_channel, config)
.unwrap()
.with_vsync(vsync_out)
.with_hsync(hsync_out)
.with_de(de_out)
.with_pclk(pclk_out)
.with_data0(d0_out)
.with_data1(d1_out)
.with_data2(d2_out)
.with_data3(d3_out)
.with_data4(d4_out)
.with_data5(d5_out)
.with_data6(d6_out)
.with_data7(d7_out);
let camera = Camera::new(
lcd_cam.cam,
rx_channel,
RxEightBits::new(d0_in, d1_in, d2_in, d3_in, d4_in, d5_in, d6_in, d7_in),
cam::Config::default().with_frequency(Rate::from_mhz(1)),
)
.unwrap()
.with_ctrl_pins_and_de(vsync_in, hsync_in, de_in)
.with_pixel_clock(pclk_in);
let mut dma_tx_buf = ctx.dma_tx_buf;
let mut dma_rx_buf = ctx.dma_rx_buf;
for (i, b) in dma_tx_buf.as_mut_slice().iter_mut().enumerate() {
*b = ((i + 0) % 256) as u8;
}
let camera_transfer = camera.receive(dma_rx_buf).map_err(|e| e.0).unwrap();
// Note: next_frame_en is not false because the RGB driver doesn't send a VSYNC
// at the end of the frame, which means the DMA doesn't flush the last
// few bytes it receives.
let dpi_transfer = dpi.send(true, dma_tx_buf).map_err(|e| e.0).unwrap();
(_, _, dma_rx_buf) = camera_transfer.wait();
(_, dma_tx_buf) = dpi_transfer.stop();
assert_eq!(dma_tx_buf.as_slice(), dma_rx_buf.as_slice());
}
}