#![no_std]
#[cfg(feature = "rttdebug")]
use panic_rtt_core::rprintln;
#[derive(Debug)]
pub enum Error<CommE> {
Comm(CommE),
Timeout,
}
pub const DEFAULT_I2C_ADDRESS: u8 = I2C_WRITE_ADDRESS;
pub struct Mt9v034<I2C> {
base_address: u8,
i2c: I2C,
}
impl<I2C, CommE> Mt9v034<I2C>
where
I2C: embedded_hal::blocking::i2c::Write<Error = CommE>
+ embedded_hal::blocking::i2c::Read<Error = CommE>
+ embedded_hal::blocking::i2c::WriteRead<Error = CommE>,
{
pub fn new(i2c: I2C, address: u8) -> Self {
Self {
base_address: address,
i2c,
}
}
pub fn default(i2c: I2C) -> Self {
Self::new(i2c, DEFAULT_I2C_ADDRESS)
}
pub fn set_context(
&mut self,
context: ParamContext,
) -> Result<(), crate::Error<CommE>> {
self.write_reg_u16(GeneralRegisters::Control as u8, context as u16)
}
pub fn setup(&mut self) -> Result<(), crate::Error<CommE>> {
#[cfg(feature = "rttdebug")]
rprintln!("mt9v034-i2c setup start");
let _version = self.read_reg_u8(GeneralRegisters::ChipVersion as u8)?;
self.write_reg_u8(GeneralRegisters::SoftReset as u8, 0b11)?;
#[cfg(feature = "rttdebug")]
rprintln!("mt9v034-i2c setup done");
Ok(())
}
pub fn simple_probe(&mut self) -> Result<(), crate::Error<CommE>> {
let mut recv_buf = [0u8];
self.i2c
.read(self.base_address, &mut recv_buf)
.map_err(Error::Comm)?;
Ok(())
}
pub fn read_reg_u8(&mut self, reg: u8) -> Result<u8, crate::Error<CommE>> {
let cmd_buf = [reg];
let mut recv_buf = [0u8];
self.i2c
.write(self.base_address, &cmd_buf)
.map_err(Error::Comm)?;
self.i2c
.read(self.base_address, &mut recv_buf)
.map_err(Error::Comm)?;
Ok(recv_buf[0])
}
pub fn read_reg_u16(
&mut self,
reg: u8,
) -> Result<u16, crate::Error<CommE>> {
let upper = (self.read_reg_u8(reg)? as u16) << 8;
let lower = self.read_reg_u8(FOLLOW_UP_ADDRESS)? as u16;
Ok(upper | lower)
}
pub fn write_reg_u8(
&mut self,
reg: u8,
val: u8,
) -> Result<(), crate::Error<CommE>> {
let write_buf = [reg, val];
self.i2c
.write(self.base_address, &write_buf)
.map_err(Error::Comm)?;
Ok(())
}
pub fn write_reg_u16(
&mut self,
reg: u8,
data: u16,
) -> Result<(), crate::Error<CommE>> {
self.write_reg_u8(reg, (data >> 8) as u8)?;
self.write_reg_u8(FOLLOW_UP_ADDRESS, (data & 0xFF) as u8)?;
Ok(())
}
}
const I2C_WRITE_ADDRESS: u8 = 0xB8;
const FOLLOW_UP_ADDRESS: u8 = 0xF0;
pub const MAX_FRAME_HEIGHT: u16 = 480;
pub const MAX_FRAME_WIDTH: u16 = 752;
#[repr(u8)]
pub enum GeneralRegisters {
ChipVersion = 0x00,
Control = 0x07,
SoftReset = 0x0c,
HdrEnable = 0x0f,
AdcResCtrl = 0x1c,
RowNoiseCorrCtrl = 0x70,
DigitalTest = 0x7f,
TiledDigitalGain = 0x80,
AgcAecDesiredBin = 0xa5,
AecUpdate = 0xa6,
AecLowpass = 0xa8,
AgcUpdate = 0xa9,
AgcLowpass = 0xaa,
MaxGain = 0xab,
MinExposure = 0xac,
MaxExposure = 0xad,
AecAgcEnable = 0xaf,
AgcAecPixelCount = 0xb0,
}
#[repr(u16)]
pub enum ParamContext {
ContextA = 0x0188,
ContextB = 0x8188,
}
#[repr(u8)]
pub enum ContextARegisters {
ColumnStart = 0x01,
}
#[repr(u8)]
pub enum ContextBRegisters {
ColumnStart = 0xc9,
}