use embedded_hal::i2c::I2c as _;
use crate::i2c::I2c;
use crate::pac::BSC0;
use crate::timer::Timer;
pub const ADDR: u8 = 0x36;
const SENSOR_OE_ENABLE: &[(u16, u8)] = &[(0x3000, 0x0f), (0x3001, 0xff), (0x3002, 0xe4)];
const STREAM_STOP: &[(u16, u8)] = &[(0x4800, 0x25), (0x4202, 0x0f), (0x300d, 0x01)];
const COMMON_REGS: &[(u16, u8)] = &[
(0x3034, 0x1a),
(0x3035, 0x21),
(0x303c, 0x11),
(0x3106, 0xf5),
(0x3827, 0xec),
(0x370c, 0x03),
(0x5000, 0x06),
(0x5003, 0x08),
(0x5a00, 0x08),
(0x3000, 0x00),
(0x3001, 0x00),
(0x3002, 0x00),
(0x3016, 0x08),
(0x3017, 0xe0),
(0x3018, 0x44),
(0x301c, 0xf8),
(0x301d, 0xf0),
(0x3a18, 0x00),
(0x3a19, 0xf8),
(0x3c01, 0x80),
(0x3b07, 0x0c),
(0x3630, 0x2e),
(0x3632, 0xe2),
(0x3633, 0x23),
(0x3634, 0x44),
(0x3636, 0x06),
(0x3620, 0x64),
(0x3621, 0xe0),
(0x3600, 0x37),
(0x3704, 0xa0),
(0x3703, 0x5a),
(0x3715, 0x78),
(0x3717, 0x01),
(0x3731, 0x02),
(0x370b, 0x60),
(0x3705, 0x1a),
(0x3f05, 0x02),
(0x3f06, 0x10),
(0x3f01, 0x0a),
(0x3a08, 0x01),
(0x3a0f, 0x58),
(0x3a10, 0x50),
(0x3a1b, 0x58),
(0x3a1e, 0x50),
(0x3a11, 0x60),
(0x3a1f, 0x28),
(0x4001, 0x02),
(0x4000, 0x09),
(0x3503, 0x03),
];
const VGA_640X480: &[(u16, u8)] = &[
(0x3036, 0x46),
(0x3821, 0x03),
(0x3820, 0x41),
(0x3612, 0x59),
(0x3618, 0x00),
(0x3814, 0x35),
(0x3815, 0x35),
(0x3708, 0x64),
(0x3709, 0x52),
(0x3800, 0x00),
(0x3801, 0x10),
(0x3802, 0x00),
(0x3803, 0x00),
(0x3804, 0x0a),
(0x3805, 0x2f),
(0x3806, 0x07),
(0x3807, 0x9f),
(0x3808, 0x02),
(0x3809, 0x80),
(0x380a, 0x01),
(0x380b, 0xe0),
(0x3a09, 0x2e),
(0x3a0a, 0x00),
(0x3a0b, 0xfb),
(0x3a0d, 0x02),
(0x3a0e, 0x01),
(0x4004, 0x02),
(0x4800, 0x34),
(0x0100, 0x01),
];
const STREAM_START: &[(u16, u8)] = &[(0x4800, 0x34), (0x4202, 0x00), (0x300d, 0x00)];
pub fn write_reg(
i2c: &mut I2c<'_, BSC0>,
register: u16,
value: u8,
) -> Result<(), crate::i2c::Error> {
let [hi, lo] = register.to_be_bytes();
i2c.write(ADDR, &[hi, lo, value])
}
pub fn read_reg(i2c: &mut I2c<'_, BSC0>, register: u16) -> Result<u8, crate::i2c::Error> {
let mut value = [0u8];
i2c.write_read(ADDR, ®ister.to_be_bytes(), &mut value)?;
Ok(value[0])
}
fn apply(i2c: &mut I2c<'_, BSC0>, table: &[(u16, u8)]) -> bool {
for &(register, value) in table {
if write_reg(i2c, register, value).is_err() {
return false;
}
}
true
}
pub fn detect(i2c: &mut I2c<'_, BSC0>) -> bool {
matches!(
(read_reg(i2c, 0x300a), read_reg(i2c, 0x300b)),
(Ok(0x56), Ok(0x47))
)
}
pub fn start_streaming(i2c: &mut I2c<'_, BSC0>, timer: &Timer, test_pattern: bool) -> bool {
let reset_ok = apply(i2c, SENSOR_OE_ENABLE)
&& apply(i2c, STREAM_STOP)
&& write_reg(i2c, 0x0100, 0x00).is_ok()
&& write_reg(i2c, 0x0103, 0x01).is_ok();
if !reset_ok {
return false;
}
timer.delay_ms(5);
if !apply(i2c, COMMON_REGS) || !apply(i2c, VGA_640X480) {
return false;
}
if write_reg(i2c, 0x3503, 0x00).is_err() {
return false;
}
if test_pattern && write_reg(i2c, 0x503d, 0x80).is_err() {
return false;
}
match read_reg(i2c, 0x4814) {
Ok(ctrl14) => {
if write_reg(i2c, 0x4814, ctrl14 & 0x3f).is_err() {
return false;
}
}
Err(_) => return false,
}
apply(i2c, STREAM_START)
}