Compare commits

..

10 commits

Author SHA1 Message Date
Robin Löhn 0334c851f8
Fixed Code 2025-11-17 15:10:19 +01:00
Mathias Pius 89a2a8bfb9
Bump example version 2024-08-02 13:40:30 +02:00
Mathias Pius ef3485aac4
Update esp32-camera reference 2024-08-01 14:22:51 +02:00
Mathias Pius 02f8e9369d
Update dependencies for example too 2024-08-01 14:19:25 +02:00
Mathias Pius baad96db64
Bump minor version, just cause 2024-08-01 14:17:35 +02:00
Mathias Pius 473db19347
Update dependencies, specify esp branch in rust-toolchain.toml 2024-08-01 14:15:09 +02:00
Mathias Pius ac874b19db
Remove quotation formatting for list 2024-05-21 12:28:30 +02:00
Mathias Pius f8d1aaec7f
Add example 2024-05-21 12:26:35 +02:00
Mathias Pius 50bea85af0
Update esp32-camera 2024-05-04 22:58:19 +02:00
Mohammad-Mohsen Aseman-Manzar dcbe205e68
Update lib.rs 2024-04-06 23:42:54 +03:30
13 changed files with 421 additions and 277 deletions

View file

@ -1,16 +1,16 @@
[package]
name = "esp-camera-rs"
version = "0.1.0"
version = "0.1.1"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
esp-idf-hal = "0.43.1"
esp-idf-sys = "0.34.1"
esp-idf-hal = "0.45.2"
esp-idf-sys = "0.36.1"
[patch.crates-io]
esp-idf-sys = {git = "https://github.com/esp-rs/esp-idf-sys", branch = "master"}
esp-idf-sys = { git = "https://github.com/esp-rs/esp-idf-sys", branch = "master" }
[[package.metadata.esp-idf-sys.extra_components]]
component_dirs = "esp32-camera"

8
components_esp32.lock Normal file
View file

@ -0,0 +1,8 @@
dependencies:
idf:
source:
type: idf
version: 5.4.3
manifest_hash: 06a76c1bdea0ee9953dbe66dc1eb5ea4b157dbc5999962e4b65153dbefdb7f21
target: esp32
version: 2.0.0

@ -1 +1 @@
Subproject commit e689c3b082985ee7b90198be32d330ce51ac5367
Subproject commit 7aa37d4f22503fdac9ccd449e4678c4894c40055

View file

@ -0,0 +1,17 @@
[build]
target = "xtensa-esp32-espidf"
[target.xtensa-esp32-espidf]
linker = "ldproxy"
# runner = "espflash --monitor" # Select this runner for espflash v1.x.x
runner = "espflash flash --monitor" # Select this runner for espflash v2.x.x
rustflags = [ "--cfg", "espidf_time64"] # Extending time_t for ESP IDF 5: https://github.com/esp-rs/rust/issues/110
[unstable]
build-std = ["std", "panic_abort"]
[env]
MCU="esp32"
# Note: this variable is not used by the pio builder (`cargo build --features pio`)
ESP_IDF_VERSION = "v5.1.3"

4
examples/camera-example/.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
.embuild/
target/
components_esp32.lock
Cargo.lock

View file

@ -0,0 +1,26 @@
[package]
name = "camera-example"
version = "0.1.2"
authors = ["Mathias Pius <contact@pius.io>"]
edition = "2021"
rust-version = "1.71"
[profile.release]
opt-level = "s"
[profile.dev]
debug = true # Symbols are nice and they don't increase the size on Flash
opt-level = "z"
[dependencies]
esp-camera-rs = { path = "../../", version = "*" }
log = { version = "0.4", default-features = false }
anyhow = "1.0.100"
esp-idf-svc = { version = "0.51.0", default-features = false, features = [
"binstart",
"std",
] }
esp-idf-sys = { version = "0.36.1" }
[build-dependencies]
embuild = "0.33.1"

View file

@ -0,0 +1,12 @@
This example assumes you have already set up all the tools necessary to compile Rust for ESP32.
When run using `cargo run`, it will compile and flash the program to an ESP32-CAM mounted on an
ESP32-CAM-MB board connected via USB to the host machine.
The program will:
1. Initialize the onboard OV2640 camera as well as the bright white LED (flash).
2. Turn on the flash.
3. Take a jpeg-encoded picture using the camera.
4. Print information about the image: width, height and size in bytes.
5. Enter deep sleep for 60 seconds, after which the device starts the process.

View file

@ -0,0 +1,3 @@
fn main() {
embuild::espidf::sysenv::output();
}

View file

@ -0,0 +1,2 @@
[toolchain]
channel = "esp"

View file

@ -0,0 +1,5 @@
# I think larger stack size is required for rust? Not sure where I got this info
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8000
# Enable PSRAM, which allows us to store larger images
CONFIG_ESP32_SPIRAM_SUPPORT=y

View file

@ -0,0 +1,76 @@
use esp_idf_svc::hal::{gpio::PinDriver, peripherals::Peripherals};
use esp_idf_sys::esp_deep_sleep;
use log::info;
use std::time::Duration;
fn main() -> anyhow::Result<()> {
// It is necessary to call this function once. Otherwise some patches to the runtime
// implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
esp_idf_svc::sys::link_patches();
// Bind the log crate to the ESP Logging facilities
esp_idf_svc::log::EspLogger::initialize_default();
info!("initializing camera and flash");
let peripherals = Peripherals::take().unwrap();
// ESP32-CAM has an onboard Flash LED addressed at GPIO-4
let mut flash = PinDriver::output(peripherals.pins.gpio4)?;
flash.set_low()?;
// Initialize the camera
let camera = esp_camera_rs::Camera::new(
peripherals.pins.gpio32,
peripherals.pins.gpio0,
peripherals.pins.gpio5,
peripherals.pins.gpio18,
peripherals.pins.gpio19,
peripherals.pins.gpio21,
peripherals.pins.gpio36,
peripherals.pins.gpio39,
peripherals.pins.gpio34,
peripherals.pins.gpio35,
peripherals.pins.gpio25,
peripherals.pins.gpio23,
peripherals.pins.gpio22,
peripherals.pins.gpio26,
peripherals.pins.gpio27,
esp_idf_sys::camera::pixformat_t_PIXFORMAT_JPEG,
esp_idf_sys::camera::framesize_t_FRAMESIZE_UXGA,
esp_idf_sys::camera::camera_fb_location_t_CAMERA_FB_IN_PSRAM,
)?;
info!("initialization complete!");
// Turn on the flash and take a picture.
// You probably want to keep it on for a while and adjust
// the camera exposure to get a good image, but this is
// mainly here to show that the program is working.
info!("taking a picture");
flash.set_high()?;
let framebuffer = camera.get_framebuffer();
flash.set_low()?;
if let Some(framebuffer) = framebuffer {
info!(
"took picture: {width}x{height} {size} bytes",
width = framebuffer.width(),
height = framebuffer.height(),
size = framebuffer.data().len(),
);
// TODO: Do something with the framebuffer.
// the JPEG-encoded byte data is in framebuffer.data()
// so you can just dump this to a file or send it over
// the network as "image.jpeg" and it should work.
} else {
panic!("failed to take image");
};
// Send the board into deep sleep. This will basically turn off everything
// and consume very little power, and then "reboot" the device, restarting
// the pin initialization and taking another picture.
let delay = Duration::from_secs(60);
info!("finished, entering deep sleep for {delay:#?}");
unsafe { esp_deep_sleep(delay.as_micros() as u64) }
}

2
rust-toolchain.toml Normal file
View file

@ -0,0 +1,2 @@
[toolchain]
channel = "esp"

View file

@ -7,313 +7,302 @@ use esp_idf_hal::peripheral::Peripheral;
use esp_idf_sys::*;
pub struct FrameBuffer<'a> {
fb: *mut camera::camera_fb_t,
_p: PhantomData<&'a camera::camera_fb_t>,
fb: *mut camera::camera_fb_t,
_p: PhantomData<&'a camera::camera_fb_t>,
}
impl<'a> FrameBuffer<'a> {
pub fn data(&self) -> &'a [u8] {
unsafe { std::slice::from_raw_parts((*self.fb).buf, (*self.fb).len) }
}
pub fn data(&self) -> &'a [u8] {
unsafe { std::slice::from_raw_parts((*self.fb).buf, (*self.fb).len) }
}
pub fn width(&self) -> usize {
unsafe { (*self.fb).width }
}
pub fn width(&self) -> usize {
unsafe { (*self.fb).width }
}
pub fn height(&self) -> usize {
unsafe { (*self.fb).height }
}
pub fn height(&self) -> usize {
unsafe { (*self.fb).height }
}
pub fn format(&self) -> camera::pixformat_t {
unsafe { (*self.fb).format }
}
pub fn format(&self) -> camera::pixformat_t {
unsafe { (*self.fb).format }
}
pub fn timestamp(&self) -> camera::timeval {
unsafe { (*self.fb).timestamp }
}
pub fn timestamp(&self) -> camera::timeval {
unsafe { (*self.fb).timestamp }
}
pub fn fb_return(&self) {
unsafe { camera::esp_camera_fb_return(self.fb) }
}
pub fn fb_return(&self) {
unsafe { camera::esp_camera_fb_return(self.fb) }
}
}
impl Drop for FrameBuffer<'_> {
fn drop(&mut self) {
self.fb_return();
}
fn drop(&mut self) {
self.fb_return();
}
}
pub struct CameraSensor<'a> {
sensor: *mut camera::sensor_t,
_p: PhantomData<&'a camera::sensor_t>,
sensor: *mut camera::sensor_t,
_p: PhantomData<&'a camera::sensor_t>,
}
impl<'a> CameraSensor<'a> {
pub fn init_status(&self) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).init_status.unwrap()(self.sensor) })
}
pub fn reset(&self) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).reset.unwrap()(self.sensor) })
}
pub fn set_pixformat(&self, format: camera::pixformat_t) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_pixformat.unwrap()(self.sensor, format) })
}
pub fn set_framesize(&self, framesize: camera::framesize_t) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_framesize.unwrap()(self.sensor, framesize) })
}
pub fn set_contrast(&self, level: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_contrast.unwrap()(self.sensor, level) })
}
pub fn set_brightness(&self, level: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_brightness.unwrap()(self.sensor, level) })
}
pub fn set_saturation(&self, level: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_saturation.unwrap()(self.sensor, level) })
}
pub fn set_sharpness(&self, level: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_sharpness.unwrap()(self.sensor, level) })
}
pub fn set_denoise(&self, level: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_denoise.unwrap()(self.sensor, level) })
}
pub fn set_gainceiling(&self, gainceiling: camera::gainceiling_t) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_gainceiling.unwrap()(self.sensor, gainceiling) })
}
pub fn set_quality(&self, quality: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_quality.unwrap()(self.sensor, quality) })
}
pub fn set_colorbar(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe {
(*self.sensor).set_colorbar.unwrap()(self.sensor, if enable { 1 } else { 0 })
})
}
pub fn set_whitebal(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe {
(*self.sensor).set_whitebal.unwrap()(self.sensor, if enable { 1 } else { 0 })
})
}
pub fn set_gain_ctrl(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe {
(*self.sensor).set_gain_ctrl.unwrap()(self.sensor, if enable { 1 } else { 0 })
})
}
pub fn set_exposure_ctrl(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe {
(*self.sensor).set_exposure_ctrl.unwrap()(self.sensor, if enable { 1 } else { 0 })
})
}
pub fn set_hmirror(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe {
(*self.sensor).set_hmirror.unwrap()(self.sensor, if enable { 1 } else { 0 })
})
}
pub fn set_vflip(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_vflip.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
}
pub fn set_aec2(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_aec2.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
}
pub fn set_awb_gain(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe {
(*self.sensor).set_awb_gain.unwrap()(self.sensor, if enable { 1 } else { 0 })
})
}
pub fn set_agc_gain(&self, gain: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_agc_gain.unwrap()(self.sensor, gain) })
}
pub fn set_aec_value(&self, gain: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_aec_value.unwrap()(self.sensor, gain) })
}
pub fn set_special_effect(&self, effect: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_special_effect.unwrap()(self.sensor, effect) })
}
pub fn set_wb_mode(&self, mode: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_wb_mode.unwrap()(self.sensor, mode) })
}
pub fn set_ae_level(&self, level: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_ae_level.unwrap()(self.sensor, level) })
}
pub fn set_dcw(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_dcw.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
}
pub fn set_bpc(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_bpc.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
}
pub fn set_wpc(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_wpc.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
}
pub fn set_raw_gma(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe {
(*self.sensor).set_raw_gma.unwrap()(self.sensor, if enable { 1 } else { 0 })
})
}
pub fn set_lenc(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_lenc.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
}
pub fn get_reg(&self, reg: i32, mask: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).get_reg.unwrap()(self.sensor, reg, mask) })
}
pub fn set_reg(&self, reg: i32, mask: i32, value: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_reg.unwrap()(self.sensor, reg, mask, value) })
}
pub fn set_res_raw(
&self,
start_x: i32,
start_y: i32,
end_x: i32,
end_y: i32,
offset_x: i32,
offset_y: i32,
total_x: i32,
total_y: i32,
output_x: i32,
output_y: i32,
scale: bool,
binning: bool,
) -> Result<(), EspError> {
esp!(unsafe {
(*self.sensor).set_res_raw.unwrap()(
self.sensor,
start_x,
start_y,
end_x,
end_y,
offset_x,
offset_y,
total_x,
total_y,
output_x,
output_y,
scale,
binning,
)
})
}
pub fn set_pll(
&self,
bypass: i32,
mul: i32,
sys: i32,
root: i32,
pre: i32,
seld5: i32,
pclken: i32,
pclk: i32,
) -> Result<(), EspError> {
esp!(unsafe {
(*self.sensor).set_pll.unwrap()(
self.sensor,
bypass,
mul,
sys,
root,
pre,
seld5,
pclken,
pclk,
)
})
}
pub fn set_xclk(&self, timer: i32, xclk: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_xclk.unwrap()(self.sensor, timer, xclk) })
}
pub fn init_status(&self) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).init_status.unwrap()(self.sensor) })
}
pub fn reset(&self) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).reset.unwrap()(self.sensor) })
}
pub fn set_pixformat(&self, format: camera::pixformat_t) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_pixformat.unwrap()(self.sensor, format) })
}
pub fn set_framesize(&self, framesize: camera::framesize_t) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_framesize.unwrap()(self.sensor, framesize) })
}
pub fn set_contrast(&self, level: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_contrast.unwrap()(self.sensor, level) })
}
pub fn set_brightness(&self, level: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_brightness.unwrap()(self.sensor, level) })
}
pub fn set_saturation(&self, level: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_saturation.unwrap()(self.sensor, level) })
}
pub fn set_sharpness(&self, level: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_sharpness.unwrap()(self.sensor, level) })
}
pub fn set_denoise(&self, level: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_denoise.unwrap()(self.sensor, level) })
}
pub fn set_gainceiling(&self, gainceiling: camera::gainceiling_t) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_gainceiling.unwrap()(self.sensor, gainceiling) })
}
pub fn set_quality(&self, quality: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_quality.unwrap()(self.sensor, quality) })
}
pub fn set_colorbar(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_colorbar.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
}
pub fn set_whitebal(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_whitebal.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
}
pub fn set_gain_ctrl(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_gain_ctrl.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
}
pub fn set_exposure_ctrl(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe {
(*self.sensor).set_exposure_ctrl.unwrap()(self.sensor, if enable { 1 } else { 0 })
})
}
pub fn set_hmirror(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_hmirror.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
}
pub fn set_vflip(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_vflip.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
}
pub fn set_aec2(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_aec2.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
}
pub fn set_awb_gain(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_awb_gain.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
}
pub fn set_agc_gain(&self, gain: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_agc_gain.unwrap()(self.sensor, gain) })
}
pub fn set_aec_value(&self, gain: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_aec_value.unwrap()(self.sensor, gain) })
}
pub fn set_special_effect(&self, effect: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_special_effect.unwrap()(self.sensor, effect) })
}
pub fn set_wb_mode(&self, mode: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_wb_mode.unwrap()(self.sensor, mode) })
}
pub fn set_ae_level(&self, level: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_ae_level.unwrap()(self.sensor, level) })
}
pub fn set_dcw(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_dcw.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
}
pub fn set_bpc(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_bpc.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
}
pub fn set_wpc(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_wpc.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
}
pub fn set_raw_gma(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_raw_gma.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
}
pub fn set_lenc(&self, enable: bool) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_lenc.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
}
pub fn get_reg(&self, reg: i32, mask: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).get_reg.unwrap()(self.sensor, reg, mask) })
}
pub fn set_reg(&self, reg: i32, mask: i32, value: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_reg.unwrap()(self.sensor, reg, mask, value) })
}
pub fn set_res_raw(
&self,
start_x: i32,
start_y: i32,
end_x: i32,
end_y: i32,
offset_x: i32,
offset_y: i32,
total_x: i32,
total_y: i32,
output_x: i32,
output_y: i32,
scale: bool,
binning: bool,
) -> Result<(), EspError> {
esp!(unsafe {
(*self.sensor).set_res_raw.unwrap()(
self.sensor,
start_x,
start_y,
end_x,
end_y,
offset_x,
offset_y,
total_x,
total_y,
output_x,
output_y,
scale,
binning,
)
})
}
pub fn set_pll(
&self,
bypass: i32,
mul: i32,
sys: i32,
root: i32,
pre: i32,
seld5: i32,
pclken: i32,
pclk: i32,
) -> Result<(), EspError> {
esp!(unsafe {
(*self.sensor).set_pll.unwrap()(
self.sensor,
bypass,
mul,
sys,
root,
pre,
seld5,
pclken,
pclk,
)
})
}
pub fn set_xclk(&self, timer: i32, xclk: i32) -> Result<(), EspError> {
esp!(unsafe { (*self.sensor).set_xclk.unwrap()(self.sensor, timer, xclk) })
}
}
pub struct Camera<'a> {
_p: PhantomData<&'a ()>,
_p: PhantomData<&'a ()>,
}
impl<'a> Camera<'a> {
pub fn new(
pin_pwdn: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pin_xclk: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pin_d0: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pin_d1: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pin_d2: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pin_d3: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pin_d4: impl Peripheral<P = impl InputPin> + 'a,
pin_d5: impl Peripheral<P = impl InputPin> + 'a,
pin_d6: impl Peripheral<P = impl InputPin> + 'a,
pin_d7: impl Peripheral<P = impl InputPin> + 'a,
pin_vsync: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pin_href: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pin_pclk: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pin_sda: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pin_scl: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pixel_format: camera::pixformat_t,
frame_size: camera::framesize_t,
) -> Result<Self, esp_idf_sys::EspError> {
esp_idf_hal::into_ref!(
pin_pwdn, pin_xclk, pin_d0, pin_d1, pin_d2, pin_d3, pin_d4, pin_d5, pin_d6, pin_d7,
pin_vsync, pin_href, pin_pclk, pin_sda, pin_scl
);
let config = camera::camera_config_t {
pin_pwdn: pin_pwdn.pin(),
pin_xclk: pin_xclk.pin(),
pin_reset: 0xff,
pub fn new(
pin_pwdn: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pin_xclk: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pin_d0: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pin_d1: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pin_d2: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pin_d3: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pin_d4: impl Peripheral<P = impl InputPin> + 'a,
pin_d5: impl Peripheral<P = impl InputPin> + 'a,
pin_d6: impl Peripheral<P = impl InputPin> + 'a,
pin_d7: impl Peripheral<P = impl InputPin> + 'a,
pin_vsync: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pin_href: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pin_pclk: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pin_sda: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pin_scl: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
pixel_format: camera::pixformat_t,
frame_size: camera::framesize_t,
fb_location: camera::camera_fb_location_t,
) -> Result<Self, esp_idf_sys::EspError> {
esp_idf_hal::into_ref!(
pin_pwdn, pin_xclk, pin_d0, pin_d1, pin_d2, pin_d3, pin_d4, pin_d5, pin_d6, pin_d7,
pin_vsync, pin_href, pin_pclk, pin_sda, pin_scl
);
let config = camera::camera_config_t {
pin_pwdn: pin_pwdn.pin(),
pin_xclk: pin_xclk.pin(),
pin_reset: 0xff,
pin_d0: pin_d0.pin(),
pin_d1: pin_d1.pin(),
pin_d2: pin_d2.pin(),
pin_d3: pin_d3.pin(),
pin_d4: pin_d4.pin(),
pin_d5: pin_d5.pin(),
pin_d6: pin_d6.pin(),
pin_d7: pin_d7.pin(),
pin_vsync: pin_vsync.pin(),
pin_href: pin_href.pin(),
pin_pclk: pin_pclk.pin(),
pin_d0: pin_d0.pin(),
pin_d1: pin_d1.pin(),
pin_d2: pin_d2.pin(),
pin_d3: pin_d3.pin(),
pin_d4: pin_d4.pin(),
pin_d5: pin_d5.pin(),
pin_d6: pin_d6.pin(),
pin_d7: pin_d7.pin(),
pin_vsync: pin_vsync.pin(),
pin_href: pin_href.pin(),
pin_pclk: pin_pclk.pin(),
xclk_freq_hz: 20000000,
ledc_timer: esp_idf_sys::ledc_timer_t_LEDC_TIMER_0,
ledc_channel: esp_idf_sys::ledc_channel_t_LEDC_CHANNEL_0,
xclk_freq_hz: 20000000,
ledc_timer: esp_idf_sys::ledc_timer_t_LEDC_TIMER_0,
ledc_channel: esp_idf_sys::ledc_channel_t_LEDC_CHANNEL_0,
pixel_format,
frame_size,
pixel_format,
frame_size,
jpeg_quality: 12,
fb_count: 1,
grab_mode: camera::camera_grab_mode_t_CAMERA_GRAB_WHEN_EMPTY,
jpeg_quality: 12,
fb_count: 1,
grab_mode: camera::camera_grab_mode_t_CAMERA_GRAB_WHEN_EMPTY,
fb_location: camera::camera_fb_location_t_CAMERA_FB_IN_PSRAM,
fb_location,
__bindgen_anon_1: camera::camera_config_t__bindgen_ty_1 {
pin_sccb_sda: pin_sda.pin(),
},
__bindgen_anon_2: camera::camera_config_t__bindgen_ty_2 {
pin_sccb_scl: pin_scl.pin(),
},
__bindgen_anon_1: camera::camera_config_t__bindgen_ty_1 {
pin_sccb_sda: pin_sda.pin(),
},
__bindgen_anon_2: camera::camera_config_t__bindgen_ty_2 {
pin_sccb_scl: pin_scl.pin(),
},
..Default::default()
};
..Default::default()
};
esp_idf_sys::esp!(unsafe { camera::esp_camera_init(&config) })?;
Ok(Self { _p: PhantomData })
esp_idf_sys::esp!(unsafe { camera::esp_camera_init(&config) })?;
Ok(Self { _p: PhantomData })
}
pub fn get_framebuffer(&self) -> Option<FrameBuffer<'_>> {
let fb = unsafe { camera::esp_camera_fb_get() };
if fb.is_null() {
//unsafe { camera::esp_camera_fb_return(fb); }
None
} else {
Some(FrameBuffer {
fb,
_p: PhantomData,
})
}
}
pub fn get_framebuffer(&self) -> Option<FrameBuffer> {
let fb = unsafe { camera::esp_camera_fb_get() };
if fb.is_null() {
//unsafe { camera::esp_camera_fb_return(fb); }
None
} else {
Some(FrameBuffer {
fb,
_p: PhantomData,
})
}
}
pub fn sensor(&self) -> CameraSensor<'a> {
CameraSensor {
sensor: unsafe { camera::esp_camera_sensor_get() },
_p: PhantomData,
}
pub fn sensor(&self) -> CameraSensor<'a> {
CameraSensor {
sensor: unsafe { camera::esp_camera_sensor_get() },
_p: PhantomData,
}
}
}
impl<'a> Drop for Camera<'a> {
fn drop(&mut self) {
esp!(unsafe { camera::esp_camera_deinit() }).expect("error during esp_camera_deinit")
}
fn drop(&mut self) {
esp!(unsafe { camera::esp_camera_deinit() }).expect("error during esp_camera_deinit")
}
}