Dear Arduino community,
I am currently trying to get my OmniVision camera OV 7670 running. In order to control its settings, I need to implement the SCCB (Serial Camera Control Bus) protocol which resembles I²C. Unfortunately, I always receive low bits during phase 2 of a read transmission cycle.
This is my code, which I have commented a bit:
const int SIOD = 9;
const int SIOC = 10;
const int QuarterCycle = 3; //3 ms per quarter cycle -> 4*3 = 12 ms per cycle (according to SCCB datasheet minimum of 10ms)
const int HalfCycle = 2 * QuarterCycle;
void initSCCB() //prepare: declare SIOD and SIOC as outputs and drive them 1
{
pinMode(SIOD, OUTPUT);
pinMode(SIOC, OUTPUT);
digitalWrite(SIOD, HIGH);
digitalWrite(SIOC, HIGH);
}
void beginSCCBTransmission()
{
digitalWrite(SIOD, LOW);
delayMicroseconds(QuarterCycle);
digitalWrite(SIOC, LOW);
delayMicroseconds(QuarterCycle);
}
void writeSCCBByte(byte Value) //phase 1 currently, phase 3 not yet implemented
{
for(byte i = 0; i < 9; i++) //9 because of the don't care bit
{
digitalWrite(SIOD, ((((Value >> (7 - i)) & 1) == 1) && (i < 8)) ? HIGH : LOW); //9th bit (don't care bit is LOW)
delayMicroseconds(QuarterCycle);
digitalWrite(SIOC, HIGH);
delayMicroseconds(HalfCycle);
digitalWrite(SIOC, LOW);
delayMicroseconds(QuarterCycle);
}
}
void endSCCBTransmission()
{
digitalWrite(SIOD, LOW);
delayMicroseconds(QuarterCycle);
digitalWrite(SIOC, HIGH);
delayMicroseconds(QuarterCycle);
digitalWrite(SIOD, HIGH);
}
byte readSCCBByte() //phase 2
{
byte Data = 0;
pinMode(SIOD, INPUT);
for(byte i=0; i < 8; i++)
{
delayMicroseconds(QuarterCycle);
digitalWrite(SIOC, HIGH);
delayMicroseconds(QuarterCycle);
if(digitalRead(SIOD) == HIGH) //NEVER TRUE --> WHY?
{
Data |= 1 << (7 - i);
}
delayMicroseconds(QuarterCycle);
digitalWrite(SIOC, LOW);
delayMicroseconds(QuarterCycle);
}
pinMode(SIOD, OUTPUT); //prepare for the NA bit
digitalWrite(SIOD, HIGH); //master driving NA bit 1
delayMicroseconds(QuarterCycle);
digitalWrite(SIOC, HIGH);
delayMicroseconds(HalfCycle);
digitalWrite(SIOC, LOW);
delayMicroseconds(QuarterCycle);
return Data;
}
byte requestFromSCCB(byte Address)
{
byte Value;
beginSCCBTransmission();
writeSCCBByte(Address);
Value = readSCCBByte();
endSCCBTransmission();
return Value;
}
void setup()
{
// put your setup code here, to run once:
Serial.begin(9600);
initSCCB();
//start 2-phase write transmissions cycle
beginSCCBTransmission();
writeSCCBByte(0x42); //0x42 to specify a write transmission cycle
writeSCCBByte(0x0A); //0x0A is the data register of the MSB of the product ID Number MSB -> should be 76
endSCCBTransmission();
//end 2-phase write transmission cycle
Serial.println(requestFromSCCB(0x43)); //0x43 specifies read transmission cycle -> prints 0, should be 76 for 76 in OV7670
}
void loop() {
// put your main code here, to run repeatedly:
}
All my functions concerning the SCCB-protocol are based on this document since the specification here actually did not really state much about the two-wire data transmission. The information of the register (0x0A) to read for testing was retreived from http://www.voti.nl/docs/OV7670.pdf (page 10/11).
Maybe someone can help me to find my mistake.
Thanks in advance.
Best regards
Birk