Understanding the SPI Bus timing on Arducam mini camera

The following timing diagrams show the complete procedure how ArduCAM 5MP Plus (OV5642) module works:

Check the sensor model ID:
OV5642 I2C slave address 0x78 for write, 0x79 for read, OV5642 model ID register is 0x300A=0x56 and 0x300B=0x42


2SPI operations based on Arduino UNO board at 4MHz SPI speed.
2.1 SPI Bus Test
Write 0x55 to 0x00 address and read the value from 0x00 address.

2.2 Image Data Transfer
After issue a capture command, pooling the capture completion flag by reading 0x41 register until euqals to 0x08.

Then read the image length from register 0x42~0x44, this is total length of the valid image data

Next issue burst FIFO read command 0x3C and followed by bytes read from the FIFO, in the following diagram the 0xFF, 0xD8 are read from the beginning which is JPEG header in this case. Note each burst read cycle should be started with 0x3C command, followed by any numbers of data to be read. Here read 256 bytes in this example. When reading data, you have to send a dummy data over MOSI line, here sending 0x00 for example.

JPEG tail can also be read from the end of the valid data, 0xFF, 0xD9 in this case.

2.3 Complete capture and read timing diagram
The CS pin only active low during the 256 bytes burst read, CS pull high when send the 256 bytes over the UART. One frame has multiple burst read cycle.

3.Very important code in the burst read function
/**important code in the burst read function/
myCAM.CS_LOW();
myCAM.set_fifo_burst();
while ( length– )
{
temp_last = temp;
temp = SPI.transfer(0x00);
//Read JPEG data from FIFO
if ( (temp == 0xD9) && (temp_last == 0xFF) ) //If find the end ,break while,
{
buf[i++] = temp; //save the last 0XD9
//Write the remain bytes in the buffer
myCAM.CS_HIGH();
Serial.write(buf,i);
is_header = false;
i = 0;
}
if (is_header == true)
{
//Write image data to buffer if not full
if (i < 256)
buf[i++] = temp;
else
{
//Write 256 bytes image data to file
myCAM.CS_HIGH();
Serial.write(buf,256);
delay(5);
i = 0;
buf[i++] = temp;
myCAM.CS_LOW();
myCAM.set_fifo_burst();
}

}
else if ((temp == 0xD8) & (temp_last == 0xFF))
{
is_header = true;
Serial.println(F(“ACK IMG”));
buf[i++] = temp_last;
buf[i++] = temp;
}

}

Arducam host application