esp-hal/examples/src/bin/lcd_cam_ov2640.rs
Sergio Gasquez Arcos b5f0246129
Reordered RX-TX pairs to be consistent (#2074)
* feat: Update rx-tx order in i2s

* feat: Update rx-tx order in dma macros

* feat: Update rx-tx order in spi

* feat: Update rx-tx order in aes

* feat: Update rx-tx order in mem2mem

* feat: Update rx-tx order in twai and split methods

* feat: Update rx-tx order in twai

* feat: Update rx-tx order in twai and uart docs

* docs: Add sentence about order

* docs: Update changelog

* feat: Update rx-tx order in embassy_interrupt_spi_dma tests

* style: Rustfmt

* docs: Migrating guide

* fix: Typo

Co-authored-by: Dániel Buga <bugadani@gmail.com>

* fix: Diff

Co-authored-by: Dániel Buga <bugadani@gmail.com>

* fix: Tests rx-tx order

* fix: Update new_with_default_pins order

* feat: Update rx/tx order in hil_test::common_test_pins!

* feat: Update dma_extmem2mem example

* fix: Revert deleted input arg

* style: rustfmt

* feat: Disable test_asymmetric_dma_transfer for S2

---------

Co-authored-by: Dániel Buga <bugadani@gmail.com>
2024-09-06 09:56:10 +00:00

414 lines
8.5 KiB
Rust

//! Drives the camera on a Freenove ESP32-S3 WROOM (also works as is on the ESP32S3-EYE)
//!
//! This example reads a JPEG from an OV2640 and writes it to the console as hex.
//!
//! The following wiring is assumed:
//! - SIOD => GPIO4
//! - SIOC => GPIO5
//! - XCLK => GPIO15
//! - VSYNC => GPIO6
//! - HREF => GPIO7
//! - PCLK => GPIO13
//! - D2 => GPIO11
//! - D3 => GPIO9
//! - D4 => GPIO8
//! - D5 => GPIO10
//! - D6 => GPIO12
//! - D7 => GPIO18
//! - D8 => GPIO17
//! - D9 => GPIO16
//% CHIPS: esp32s3
#![no_std]
#![no_main]
use esp_backtrace as _;
use esp_hal::{
delay::Delay,
dma::{Dma, DmaPriority},
dma_buffers,
gpio::Io,
i2c,
i2c::I2C,
lcd_cam::{
cam::{Camera, RxEightBits},
LcdCam,
},
prelude::*,
Blocking,
};
use esp_println::println;
#[entry]
fn main() -> ! {
let peripherals = esp_hal::init(esp_hal::Config::default());
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let dma = Dma::new(peripherals.DMA);
let channel = dma.channel0;
let (rx_buffer, rx_descriptors, _, _) = dma_buffers!(0, 32678);
let channel = channel.configure(false, DmaPriority::Priority0);
let cam_siod = io.pins.gpio4;
let cam_sioc = io.pins.gpio5;
let cam_xclk = io.pins.gpio15;
let cam_vsync = io.pins.gpio6;
let cam_href = io.pins.gpio7;
let cam_pclk = io.pins.gpio13;
let cam_data_pins = RxEightBits::new(
io.pins.gpio11,
io.pins.gpio9,
io.pins.gpio8,
io.pins.gpio10,
io.pins.gpio12,
io.pins.gpio18,
io.pins.gpio17,
io.pins.gpio16,
);
let lcd_cam = LcdCam::new(peripherals.LCD_CAM);
let mut camera = Camera::new(
lcd_cam.cam,
channel.rx,
rx_descriptors,
cam_data_pins,
20u32.MHz(),
)
.with_master_clock(cam_xclk)
.with_pixel_clock(cam_pclk)
.with_ctrl_pins(cam_vsync, cam_href);
let delay = Delay::new();
let mut buffer = rx_buffer;
buffer.fill(0u8);
delay.delay_millis(500u32);
let i2c = I2C::new(peripherals.I2C0, cam_siod, cam_sioc, 100u32.kHz());
let mut sccb = Sccb::new(i2c);
// Checking camera address
sccb.probe(OV2640_ADDRESS).unwrap();
println!("Probe successful!");
sccb.write(OV2640_ADDRESS, 0xFF, 0x01).unwrap(); // bank sensor
let pid = sccb.read(OV2640_ADDRESS, 0x0A).unwrap();
println!("Found PID of {:#02X}, and was expecting 0x26", pid);
// Start waiting for camera before initialising it to prevent missing the first few bytes.
// This can be improved with a VSYNC interrupt but would complicate this example.
let transfer = camera.read_dma(&mut buffer).unwrap();
for (reg, value) in FIRST_BLOCK {
sccb.write(OV2640_ADDRESS, *reg, *value).unwrap();
}
delay.delay_millis(10u32);
for (reg, value) in SECOND_BLOCK {
sccb.write(OV2640_ADDRESS, *reg, *value).unwrap();
if *reg == 0xDD && *value == 0x7F {
delay.delay_millis(10u32);
}
}
transfer.wait().unwrap();
// Note: JPEGs starts with "FF, D8, FF, E0" and end with "FF, D9"
let index_of_end = buffer.windows(2).position(|c| c[0] == 0xFF && c[1] == 0xD9);
let index_of_end = if let Some(idx) = index_of_end {
idx + 2
} else {
println!("Failed to find JPEG terminator");
buffer.len()
};
println!("Frame data (parse with `xxd -r -p <uart>.txt image.jpg`):");
println!("{:02X?}", &buffer[..index_of_end]);
loop {}
}
pub const OV2640_ADDRESS: u8 = 0x30;
pub struct Sccb<'d, T> {
i2c: I2C<'d, T, Blocking>,
}
impl<'d, T> Sccb<'d, T>
where
T: i2c::Instance,
{
pub fn new(i2c: I2C<'d, T, Blocking>) -> Self {
Self { i2c }
}
pub fn probe(&mut self, address: u8) -> Result<(), i2c::Error> {
self.i2c.write(address, &[])
}
pub fn read(&mut self, address: u8, reg: u8) -> Result<u8, i2c::Error> {
self.i2c.write(address, &[reg])?;
let mut bytes = [0u8; 1];
self.i2c.read(address, &mut bytes)?;
Ok(bytes[0])
}
pub fn write(&mut self, address: u8, reg: u8, data: u8) -> Result<(), i2c::Error> {
self.i2c.write(address, &[reg, data])
}
}
const FIRST_BLOCK: &[(u8, u8)] = &[(0xFF, 0x01), (0x12, 0x80)];
const SECOND_BLOCK: &[(u8, u8)] = &[
(0xFF, 0x00),
(0x2C, 0xFF),
(0x2E, 0xDF),
(0xFF, 0x01),
(0x3C, 0x32),
(0x11, 0x01),
(0x09, 0x02),
(0x04, 0x28),
(0x13, 0xE5),
(0x14, 0x48),
(0x2C, 0x0C),
(0x33, 0x78),
(0x3A, 0x33),
(0x3B, 0xFB),
(0x3E, 0x00),
(0x43, 0x11),
(0x16, 0x10),
(0x39, 0x92),
(0x35, 0xDA),
(0x22, 0x1A),
(0x37, 0xC3),
(0x23, 0x00),
(0x34, 0xC0),
(0x06, 0x88),
(0x07, 0xC0),
(0x0D, 0x87),
(0x0E, 0x41),
(0x4C, 0x00),
(0x4A, 0x81),
(0x21, 0x99),
(0x24, 0x40),
(0x25, 0x38),
(0x26, 0x82),
(0x5C, 0x00),
(0x63, 0x00),
(0x61, 0x70),
(0x62, 0x80),
(0x7C, 0x05),
(0x20, 0x80),
(0x28, 0x30),
(0x6C, 0x00),
(0x6D, 0x80),
(0x6E, 0x00),
(0x70, 0x02),
(0x71, 0x94),
(0x73, 0xC1),
(0x3D, 0x34),
(0x5A, 0x57),
(0x4F, 0xBB),
(0x50, 0x9C),
(0x12, 0x20),
(0x17, 0x11),
(0x18, 0x43),
(0x19, 0x00),
(0x1A, 0x25),
(0x32, 0x89),
(0x37, 0xC0),
(0x4F, 0xCA),
(0x50, 0xA8),
(0x6D, 0x00),
(0x3D, 0x38),
(0xFF, 0x00),
(0xE5, 0x7F),
(0xF9, 0xC0),
(0x41, 0x24),
(0xE0, 0x14),
(0x76, 0xFF),
(0x33, 0xA0),
(0x42, 0x20),
(0x43, 0x18),
(0x4C, 0x00),
(0x87, 0x50),
(0x88, 0x3F),
(0xD7, 0x03),
(0xD9, 0x10),
(0xD3, 0x82),
(0xC8, 0x08),
(0xC9, 0x80),
(0x7C, 0x00),
(0x7D, 0x00),
(0x7C, 0x03),
(0x7D, 0x48),
(0x7D, 0x48),
(0x7C, 0x08),
(0x7D, 0x20),
(0x7D, 0x10),
(0x7D, 0x0E),
(0x90, 0x00),
(0x91, 0x0E),
(0x91, 0x1A),
(0x91, 0x31),
(0x91, 0x5A),
(0x91, 0x69),
(0x91, 0x75),
(0x91, 0x7E),
(0x91, 0x88),
(0x91, 0x8F),
(0x91, 0x96),
(0x91, 0xA3),
(0x91, 0xAF),
(0x91, 0xC4),
(0x91, 0xD7),
(0x91, 0xE8),
(0x91, 0x20),
(0x92, 0x00),
(0x93, 0x06),
(0x93, 0xE3),
(0x93, 0x05),
(0x93, 0x05),
(0x93, 0x00),
(0x93, 0x04),
(0x93, 0x00),
(0x93, 0x00),
(0x93, 0x00),
(0x93, 0x00),
(0x93, 0x00),
(0x93, 0x00),
(0x93, 0x00),
(0x96, 0x00),
(0x97, 0x08),
(0x97, 0x19),
(0x97, 0x02),
(0x97, 0x0C),
(0x97, 0x24),
(0x97, 0x30),
(0x97, 0x28),
(0x97, 0x26),
(0x97, 0x02),
(0x97, 0x98),
(0x97, 0x80),
(0x97, 0x00),
(0x97, 0x00),
(0xA4, 0x00),
(0xA8, 0x00),
(0xC5, 0x11),
(0xC6, 0x51),
(0xBF, 0x80),
(0xC7, 0x10),
(0xB6, 0x66),
(0xB8, 0xA5),
(0xB7, 0x64),
(0xB9, 0x7C),
(0xB3, 0xAF),
(0xB4, 0x97),
(0xB5, 0xFF),
(0xB0, 0xC5),
(0xB1, 0x94),
(0xB2, 0x0F),
(0xC4, 0x5C),
(0xC3, 0xFD),
(0x7F, 0x00),
(0xE5, 0x1F),
(0xE1, 0x67),
(0xDD, 0x7F),
(0xDA, 0x00),
(0xE0, 0x00),
(0x05, 0x00),
(0x05, 0x01),
(0xFF, 0x01),
(0x12, 0x40),
(0x03, 0x0A),
(0x32, 0x09),
(0x17, 0x11),
(0x18, 0x43),
(0x19, 0x00),
(0x1A, 0x4B),
(0x37, 0xC0),
(0x4F, 0xCA),
(0x50, 0xA8),
(0x5A, 0x23),
(0x6D, 0x00),
(0x3D, 0x38),
(0x39, 0x92),
(0x35, 0xDA),
(0x22, 0x1A),
(0x37, 0xC3),
(0x23, 0x00),
(0x34, 0xC0),
(0x06, 0x88),
(0x07, 0xC0),
(0x0D, 0x87),
(0x0E, 0x41),
(0x42, 0x03),
(0x4C, 0x00),
(0xFF, 0x00),
(0xE0, 0x04),
(0xC0, 0x64),
(0xC1, 0x4B),
(0x8C, 0x00),
(0x51, 0xC8),
(0x52, 0x96),
(0x53, 0x00),
(0x54, 0x00),
(0x55, 0x00),
(0x57, 0x00),
(0x86, 0x3D),
(0x50, 0x80),
(0x51, 0xC8),
(0x52, 0x96),
(0x53, 0x00),
(0x54, 0x00),
(0x55, 0x00),
(0x57, 0x00),
(0x5A, 0xA0),
(0x5B, 0x78),
(0x5C, 0x00),
(0xFF, 0x01),
(0x11, 0x00),
(0xFF, 0x00),
(0xD3, 0x10),
(0x05, 0x00),
(0xE0, 0x14),
(0xDA, 0x12),
(0xD7, 0x03),
(0xE1, 0x77),
(0xE5, 0x1F),
(0xD9, 0x10),
(0xDF, 0x80),
(0x33, 0x80),
(0x3C, 0x10),
(0xEB, 0x30),
(0xDD, 0x7F),
(0xE0, 0x00),
(0xE0, 0x14),
(0xDA, 0x12),
(0xD7, 0x03),
(0xE1, 0x77),
(0xE5, 0x1F),
(0xD9, 0x10),
(0xDF, 0x80),
(0x33, 0x80),
(0x3C, 0x10),
(0xEB, 0x30),
(0xDD, 0x7F),
(0xE0, 0x00),
(0xFF, 0x01),
(0x14, 0x08),
(0xFF, 0x00),
(0x87, 0x50),
(0x87, 0x10),
(0xC3, 0xFD),
(0x44, 0x0C),
];