Hi, I'm trying to set OV7670 with I2C protocol. To do this, I decided to use TWI. But, when i want to start the transmission, code freezes on waiting the transmission end (waiting for TWINT).
//main.cpp
#include <Arduino.h>
#include "twi.h"
#include "register.h"
struct reg{
uint8_t reg_num;
uint16_t value;
};
const struct reg regs[] PROGMEM = {//from the linux driver
{ REG_COM7, COM7_RESET },
{ REG_TSLB, 0x04 }, /* OV */
{ REG_COM7, 4 }, /* RGB */
/*
* Set the hardware window. These values from OV don't entirely
* make sense - hstop is less than hstart. But they work...
*/
{ REG_COM3, 0x04 }, { REG_COM14, 0x19 },
{ 0x72, 0x11 }, { 0x73, 0xf1 },
{ REG_HSTART, 0x16 }, { REG_HSTOP, 0x04 },
{ REG_HREF, 0xa4 }, { REG_VSTART, 0x02 },
{ REG_VSTOP, 0x7a }, { REG_VREF, 0x0a },
/* Mystery scaling numbers */
{ 0x70, 0x3a }, { 0x71, 0x35 },
{ 0x72, 0x11 }, { 0x73, 0xf0 },
{ 0xa2,/* 0x02 changed to 1*/1 }, { REG_COM10, 0x0 },
/* Gamma curve values */
{ 0x7a, 0x20 }, { 0x7b, 0x10 },
{ 0x7c, 0x1e }, { 0x7d, 0x35 },
{ 0x7e, 0x5a }, { 0x7f, 0x69 },
{ 0x80, 0x76 }, { 0x81, 0x80 },
{ 0x82, 0x88 }, { 0x83, 0x8f },
{ 0x84, 0x96 }, { 0x85, 0xa3 },
{ 0x86, 0xaf }, { 0x87, 0xc4 },
{ 0x88, 0xd7 }, { 0x89, 0xe8 },
/* AGC and AEC parameters. Note we start by disabling those features,
then turn them only after tweaking the values. */
{ REG_COM8, COM8_FASTAEC | COM8_AECSTEP },
{ REG_GAIN, 0 }, { REG_AECH, 0 },
{ REG_COM4, 0x40 }, /* magic reserved bit */
{ REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
{ REG_BD50MAX, 0x05 }, { REG_BD60MAX, 0x07 },
{ REG_AEW, 0x95 }, { REG_AEB, 0x33 },
{ REG_VPT, 0xe3 }, { REG_HAECC1, 0x78 },
{ REG_HAECC2, 0x68 }, { 0xa1, 0x03 }, /* magic */
{ REG_HAECC3, 0xd8 }, { REG_HAECC4, 0xd8 },
{ REG_HAECC5, 0xf0 }, { REG_HAECC6, 0x90 },
{ REG_HAECC7, 0x94 },
{ REG_COM8, COM8_FASTAEC | COM8_AECSTEP | COM8_AGC | COM8_AEC },
{ 0x30, 0 }, { 0x31, 0 },//disable some delays
/* Almost all of these are magic "reserved" values. */
{ REG_COM5, 0x61 }, { REG_COM6, 0x4b },
{ 0x16, 0x02 }, { REG_MVFP, 0x07 },
{ 0x21, 0x02 }, { 0x22, 0x91 },
{ 0x29, 0x07 }, { 0x33, 0x0b },
{ 0x35, 0x0b }, { 0x37, 0x1d },
{ 0x38, 0x71 }, { 0x39, 0x2a },
{ REG_COM12, 0x78 }, { 0x4d, 0x40 },
{ 0x4e, 0x20 }, { REG_GFIX, 0 },
/*{0x6b, 0x4a},*/{ 0x74, 0x10 },
{ 0x8d, 0x4f }, { 0x8e, 0 },
{ 0x8f, 0 }, { 0x90, 0 },
{ 0x91, 0 }, { 0x96, 0 },
{ 0x9a, 0 }, { 0xb0, 0x84 },
{ 0xb1, 0x0c }, { 0xb2, 0x0e },
{ 0xb3, 0x82 }, { 0xb8, 0x0a },
/* More reserved magic, some of which tweaks white balance */
{ 0x43, 0x0a }, { 0x44, 0xf0 },
{ 0x45, 0x34 }, { 0x46, 0x58 },
{ 0x47, 0x28 }, { 0x48, 0x3a },
{ 0x59, 0x88 }, { 0x5a, 0x88 },
{ 0x5b, 0x44 }, { 0x5c, 0x67 },
{ 0x5d, 0x49 }, { 0x5e, 0x0e },
{ 0x6c, 0x0a }, { 0x6d, 0x55 },
{ 0x6e, 0x11 }, { 0x6f, 0x9e }, /* it was 0x9F "9e for advance AWB" */
{ 0x6a, 0x40 }, { REG_BLUE, 0x40 },
{ REG_RED, 0x60 },
{ REG_COM8, COM8_FASTAEC | COM8_AECSTEP | COM8_AGC | COM8_AEC | COM8_AWB },
/* Matrix coefficients */
{ 0x4f, 0x80 }, { 0x50, 0x80 },
{ 0x51, 0 }, { 0x52, 0x22 },
{ 0x53, 0x5e }, { 0x54, 0x80 },
{ 0x58, 0x9e },
{ REG_COM16, COM16_AWBGAIN }, { REG_EDGE, 0 },
{ 0x75, 0x05 }, { REG_REG76, 0xe1 },
{ 0x4c, 0 }, { 0x77, 0x01 },
{ REG_COM13, /*0xc3*/0x48 }, { 0x4b, 0x09 },
{ 0xc9, 0x60 }, /*{REG_COM16, 0x38},*/
{ 0x56, 0x40 },
{ 0x34, 0x11 }, { REG_COM11, COM11_EXP | COM11_HZAUTO },
{ 0xa4, 0x82/*Was 0x88*/ }, { 0x96, 0 },
{ 0x97, 0x30 }, { 0x98, 0x20 },
{ 0x99, 0x30 }, { 0x9a, 0x84 },
{ 0x9b, 0x29 }, { 0x9c, 0x03 },
{ 0x9d, 0x4c }, { 0x9e, 0x3f },
{ 0x78, 0x04 },
/* Extra-weird stuff. Some sort of multiplexor register */
{ 0x79, 0x01 }, { 0xc8, 0xf0 },
{ 0x79, 0x0f }, { 0xc8, 0x00 },
{ 0x79, 0x10 }, { 0xc8, 0x7e },
{ 0x79, 0x0a }, { 0xc8, 0x80 },
{ 0x79, 0x0b }, { 0xc8, 0x01 },
{ 0x79, 0x0c }, { 0xc8, 0x0f },
{ 0x79, 0x0d }, { 0xc8, 0x20 },
{ 0x79, 0x09 }, { 0xc8, 0x80 },
{ 0x79, 0x02 }, { 0xc8, 0xc0 },
{ 0x79, 0x03 }, { 0xc8, 0x40 },
{ 0x79, 0x05 }, { 0xc8, 0x30 },
{ 0x79, 0x26 },
{ 0xff, 0xff }, /* END MARKER */
};
void writeToCamera(int addr, int value){
writeTWI(42, *(bytes(2).add(addr)->add(value)));
delay(1);
}
void initCamera(){
const reg* r = regs;
uint8_t numm, vall;
while (numm != 0xff)
{
numm = pgm_read_byte(&r -> reg_num);
vall = pgm_read_byte(&r -> value);
Serial.println(numm);
Serial.println(vall);
writeToCamera(numm, vall);
r++;
}
writeToCamera(REG_COM10, 1 << 5); // pclk hblank async
}
void setup(){
cli();
Serial.begin(9600);
pinMode(11, OUTPUT);
pinMode(8, OUTPUT);
pinMode(7, OUTPUT);
pinMode(6, OUTPUT);
pinMode(5, OUTPUT);
pinMode(4, OUTPUT);
pinMode(3, OUTPUT);
pinMode(2, OUTPUT);
pinMode(A0, INPUT);
pinMode(A1, INPUT);
pinMode(A2, INPUT);
pinMode(A3, INPUT);
//Timer 9-11
TCCR2A = (1 << COM2A0) | (1 << WGM20) | (1 << WGM21);
TCCR2B = (1 << WGM22) | (1 << CS20); // 8mhz
OCR2A = 0;
initCamera();
}
void loop(){
/*Serial.println(analogRead(A0));
Serial.println(analogRead(A1));
Serial.println(analogRead(A2));
Serial.println(analogRead(A3));
Serial.println();*/
}
//twi.h
#pragma once
#include <Arduino.h>
struct bytes{
private:
int _index;
public:
int* _bytes;
int _len;
bytes(int len){
_len = len;
_index = 0;
_bytes = new int[len];
}
~bytes(){
delete _bytes;
}
bytes* add(int byte){
_bytes[_index++] = byte;
return this;
}
};
void setupTWI(int khz){
TWBR = 8000.0 / khz - 8;
}
void waitTWINT(){
while ((TWCR & (1 << TWINT)) <= 0); //freezes there
}
int startTWI(){
TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
waitTWINT();
return TWSR == 0x08;
}
void stopTWI(){
TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN);
}
int enableTWI(int address){
TWDR = address;
TWCR = (1 << TWINT) | (1 << TWEN);
}
int writeTWI(int address, bytes _bytes){
Serial.println("s");
if (!startTWI())
return 0;
Serial.println("sd");
enableTWI(address);
for (int i = 0; i < _bytes._len; i++)
{
TWDR = (_bytes)._bytes[i];
TWCR = (1 << TWINT) | (1 << TWEN);
waitTWINT();
}
stopTWI();
return 1;
}
int readTWI(int address, int stopCode, int* read, int buffer = 128){
if (!startTWI())
return 0;
enableTWI(address);
read = new int[buffer];
int r, i = 0;
while ((r = TWDR) != stopCode)
{
read[i++] = r;
}
return 1;
}