1#![no_std]
56#![no_main]
57
58use core::{fmt, slice::IterMut};
59
60use embedded_hal::{blocking::{spi::{self, Transfer}, i2c, delay::DelayMs}, digital::v2::OutputPin};
61use ov2640_registers::*;
62
63mod ov2640_registers;
64
65const ARDUCHIP_TEST1: u8 = 0x00;
66const ARDUCHIP_FIFO: u8 = 0x04;
67const ARDUCHIP_TRIG: u8 = 0x41;
68const OV2640_ADDR: u8 = 0x60 >> 1;
69const OV2640_CHIPID_HIGH: u8 = 0x0A;
70const OV2640_CHIPID_LOW: u8 = 0x0B;
71const FIFO_CLEAR_MASK: u8 = 0x01;
72const FIFO_START_MASK: u8 = 0x02;
73const FIFO_BURST: u8 = 0x3C;
74const FIFO_SIZE1: u8 = 0x42;
75const FIFO_SIZE2: u8 = 0x43;
76const FIFO_SIZE3: u8 = 0x44;
77const CAP_DONE_MASK: u8 = 0x08;
78
79#[derive(fmt::Debug)]
80pub enum Error<SpiErr, I2cErr, PinErr> {
82 Spi(SpiErr),
83 I2c(I2cErr),
84 Pin(PinErr),
85 OutOfBounds
86}
87
88#[derive(Debug)]
89pub enum Resolution {
91 Res160x120,
92 Res176x144,
93 Res320x240,
94 Res352x288,
95 Res640x480,
96 Res800x600,
97 Res1024x768,
98 Res1280x1024,
99 Res1600x1200
100}
101
102#[derive(PartialEq, Eq, Debug)]
103pub enum ImageFormat {
105 JPEG
108}
109
110pub struct Arducam<SPI, I2C, CS> {
112 spi: SPI,
113 spi_cs: CS,
114 i2c: I2C,
115 format: ImageFormat,
116 resolution: Resolution
117}
118
119impl<SPI, I2C, CS, SpiErr, I2cErr, PinErr> Arducam<SPI, I2C, CS>
120where
121 SPI: Transfer<u8, Error = SpiErr> + spi::Write<u8, Error = SpiErr>,
122 I2C: i2c::Write<Error = I2cErr> + i2c::WriteRead<Error = I2cErr>,
123 CS: OutputPin<Error = PinErr>
124{
125 pub fn new(spi: SPI, i2c: I2C, cs_pin: CS, resolution: Resolution, format: ImageFormat) -> Arducam<SPI, I2C, CS> {
127 Arducam {
128 spi,
129 spi_cs: cs_pin,
130 i2c,
131 format,
132 resolution,
133 }
134 }
135
136 pub fn init<D>(&mut self, delay: &mut D) -> Result<(), Error<SpiErr, I2cErr, PinErr>>
138 where
139 D: DelayMs<u32>
140 {
141 self.arduchip_write_reg(0x07, 0x80)?;
142 delay.delay_ms(100);
143 self.arduchip_write_reg(0x07, 0x00)?;
144 delay.delay_ms(100);
145 self.sensor_writereg8_8(0xFF, 0x01)?;
146 self.sensor_writereg8_8(0x12, 0x80)?;
147 delay.delay_ms(100);
148
149 unsafe {
151 self.sensor_writeregs8_8(&OV2640_JPEG_INIT)?;
152 self.sensor_writeregs8_8(&OV2640_YUV422)?;
153 }
154 self.sensor_writereg8_8(0xFF, 0x01)?;
155 self.sensor_writereg8_8(0x15, 0x00)?;
156 self.send_resolution()?;
157 Ok(())
163 }
164
165 pub fn set_resolution(&mut self, resolution: Resolution) -> Result<(), Error<SpiErr, I2cErr, PinErr>> {
167 self.resolution = resolution;
168 self.send_resolution()?;
169 Ok(())
170 }
171
172 pub fn is_connected(&mut self) -> Result<bool, Error<SpiErr, I2cErr, PinErr>> {
174 let test_value = 0x52;
175 self.arduchip_write_reg(ARDUCHIP_TEST1, test_value)?;
176 let result = self.arduchip_read_reg(ARDUCHIP_TEST1)?;
177
178 let valid_ov2640_chipid1 = [0x26, 0x41];
179 let valid_ov2640_chipid2 = [0x26, 0x42];
180 let chipid = self.get_sensor_chipid()?;
181
182 if test_value == result && chipid == valid_ov2640_chipid1 || chipid == valid_ov2640_chipid2 {
183 Ok(true)
184 }
185 else {
186 Ok(false)
187 }
188 }
189
190 pub fn start_capture(&mut self) -> Result<(), Error<SpiErr, I2cErr, PinErr>> {
192 self.flush_fifo()?;
193 self.start_fifo()?;
194 Ok(())
195 }
196
197 pub fn is_capture_done(&mut self) -> Result<bool, Error<SpiErr, I2cErr, PinErr>> {
199 self.arduchip_read_reg(ARDUCHIP_TRIG).map(|result| { result & CAP_DONE_MASK != 0 })
200 }
201
202 pub fn read_captured_image(&mut self, data_out: IterMut<u8>) -> Result<usize, Error<SpiErr, I2cErr, PinErr>>
209 {
210 let length = self.get_fifo_length()?;
211 let mut final_length = 0;
212 self.spi_cs.set_low().map_err(Error::Pin)?;
213 self.set_fifo_burst()?;
214 let mut curr_byte = 0;
215 #[allow(unused_assignments)]
216 let mut prev_byte = 0;
217 for (i, b) in data_out.enumerate() {
218 prev_byte = curr_byte;
219 curr_byte = self.spi.transfer(&mut [0x00]).map_err(Error::Spi)?[0];
220 *b = curr_byte;
221 if prev_byte == 0xFF && curr_byte == 0xD9 || i as u32 > length {
222 final_length = i;
223 break;
224 }
225 }
226 self.flush_fifo()?;
227 Ok(final_length)
228 }
229
230 pub fn get_fifo_length(&mut self) -> Result<u32, Error<SpiErr, I2cErr, PinErr>> {
232 let mut len_builder = (0u32, 0u32, 0u32);
233 len_builder.0 = self.arduchip_read_reg(FIFO_SIZE1)?.into();
234 len_builder.1 = self.arduchip_read_reg(FIFO_SIZE2)?.into();
235 len_builder.2 = (self.arduchip_read_reg(FIFO_SIZE3)? & 0x7F).into();
236 Ok((len_builder.2 << 16 | len_builder.1 << 8 | len_builder.0) as u32 & 0x7FFFFFu32)
237 }
238
239 pub fn get_sensor_chipid(&mut self) -> Result<[u8; 2], Error<SpiErr, I2cErr, PinErr>> {
241 let mut chipid: [u8; 2] = [0; 2];
242 self.sensor_writereg8_8(0xFF, 0x01)?;
243 self.sensor_readreg8_8(OV2640_CHIPID_HIGH, &mut chipid[0..1])?;
244 self.sensor_readreg8_8(OV2640_CHIPID_LOW, &mut chipid[1..2])?;
245 Ok(chipid)
246 }
247
248 fn send_resolution(&mut self) -> Result<(), Error<SpiErr, I2cErr, PinErr>> {
249 unsafe {
250 match self.resolution {
251 Resolution::Res160x120 => { self.sensor_writeregs8_8(&OV2640_160x120_JPEG)? },
252 Resolution::Res1024x768 => { self.sensor_writeregs8_8(&OV2640_1024x768_JPEG)? },
253 Resolution::Res1280x1024 => { self.sensor_writeregs8_8(&OV2640_1280x1024_JPEG)? },
254 Resolution::Res1600x1200 => { self.sensor_writeregs8_8(&OV2640_1600x1200_JPEG)? },
255 Resolution::Res176x144 => { self.sensor_writeregs8_8(&OV2640_176x144_JPEG)? },
256 Resolution::Res320x240 => { self.sensor_writeregs8_8(&OV2640_320x240_JPEG)? },
257 Resolution::Res352x288 => { self.sensor_writeregs8_8(&OV2640_352x288_JPEG)? },
258 Resolution::Res640x480 => { self.sensor_writeregs8_8(&OV2640_640x480_JPEG)? },
259 Resolution::Res800x600 => { self.sensor_writeregs8_8(&OV2640_800x600_JPEG)? },
260 }
261 }
262
263 Ok(())
264 }
265
266 fn flush_fifo(&mut self) -> Result<(), Error<SpiErr, I2cErr, PinErr>> {
267 self.arduchip_write_reg(ARDUCHIP_FIFO, FIFO_CLEAR_MASK)
268 }
269
270 fn start_fifo(&mut self) -> Result<(), Error<SpiErr, I2cErr, PinErr>> {
271 self.arduchip_write_reg(ARDUCHIP_FIFO, FIFO_START_MASK)
272 }
273
274 fn set_fifo_burst(&mut self) -> Result<(), Error<SpiErr, I2cErr, PinErr>> {
275 self.spi.write(&[FIFO_BURST]).map_err(Error::Spi)
276 }
277
278 fn arduchip_write(&mut self, addr: u8, data: u8) -> Result<(), Error<SpiErr, I2cErr, PinErr>> {
279 self.spi_cs.set_low().map_err(Error::Pin)?;
280 self.spi.write(&[addr; 1]).map_err(Error::Spi)?;
281 self.spi.write(&[data; 1]).map_err(Error::Spi)?;
282 self.spi_cs.set_high().map_err(Error::Pin)?;
283 Ok(())
284 }
285
286 fn arduchip_read(&mut self, addr: u8) -> Result<u8, Error<SpiErr, I2cErr, PinErr>> {
287 self.spi_cs.set_low().map_err(Error::Pin)?;
288 self.spi.transfer(&mut [addr; 1]).map_err(Error::Spi)?;
289 let value = self.spi.transfer(&mut [0; 1]).map_err(Error::Spi)?[0];
290 self.spi_cs.set_high().map_err(Error::Pin)?;
291 Ok(value)
292 }
293
294 fn arduchip_write_reg(&mut self, addr: u8, data: u8) -> Result<(), Error<SpiErr, I2cErr, PinErr>> {
295 self.arduchip_write(addr | 0x80, data)
296 }
297
298 fn arduchip_read_reg(&mut self, addr: u8) -> Result<u8, Error<SpiErr, I2cErr, PinErr>> {
299 self.arduchip_read(addr & 0x7F)
300 }
301
302 fn sensor_writeregs8_8(&mut self, regs: &[[u8; 2]]) -> Result<(), Error<SpiErr, I2cErr, PinErr>> {
303 for reg in regs {
304 self.sensor_writereg8_8(reg[0], reg[1])?;
305 }
306 Ok(())
307 }
308
309 fn sensor_writereg8_8(&mut self, reg: u8, data: u8) -> Result<(), Error<SpiErr, I2cErr, PinErr>> {
310 self.i2c.write(OV2640_ADDR, &[reg & 0xFF, data & 0xFF]).map_err(Error::I2c)
311 }
312
313 fn sensor_readreg8_8(&mut self, reg: u8, out: &mut [u8]) -> Result<(), Error<SpiErr, I2cErr, PinErr>> {
314 self.i2c.write_read(OV2640_ADDR, &[reg & 0xFF], out).map_err(Error::I2c)
315 }
316}
317
318impl<SPI, I2C, CS> fmt::Debug for Arducam<SPI, I2C, CS>
319where
320 SPI: fmt::Debug,
321 I2C: fmt::Debug,
322 CS: fmt::Debug,
323{
324 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
325 f.debug_struct("Arducam")
326 .field("Spi", &self.spi)
327 .field("I2C", &self.i2c)
328 .field("Resolution", &self.resolution)
329 .field("Image format", &self.format)
330 .finish()
331 }
332}