├── Makefile ├── README ├── main.c ├── ov7670.c └── ov7670.h /Makefile: -------------------------------------------------------------------------------- 1 | 2 | ######### AVR Project Makefile Template ######### 3 | ###### ###### 4 | ###### Copyright (C) 2003-2005,Pat Deegan, ###### 5 | ###### Psychogenic Inc ###### 6 | ###### All Rights Reserved ###### 7 | ###### ###### 8 | ###### You are free to use this code as part ###### 9 | ###### of your own applications provided ###### 10 | ###### you keep this copyright notice intact ###### 11 | ###### and acknowledge its authorship with ###### 12 | ###### the words: ###### 13 | ###### ###### 14 | ###### "Contains software by Pat Deegan of ###### 15 | ###### Psychogenic Inc (www.psychogenic.com)" ###### 16 | ###### ###### 17 | ###### If you use it as part of a web site ###### 18 | ###### please include a link to our site, ###### 19 | ###### http://electrons.psychogenic.com or ###### 20 | ###### http://www.psychogenic.com ###### 21 | ###### ###### 22 | #################################################### 23 | 24 | 25 | ##### This Makefile will make compiling Atmel AVR 26 | ##### micro controller projects simple with Linux 27 | ##### or other Unix workstations and the AVR-GCC 28 | ##### tools. 29 | ##### 30 | ##### It supports C, C++ and Assembly source files. 31 | ##### 32 | ##### Customize the values as indicated below and : 33 | ##### make 34 | ##### make disasm 35 | ##### make stats 36 | ##### make hex 37 | ##### make writeflash 38 | ##### make gdbinit 39 | ##### or make clean 40 | ##### 41 | ##### See the http://electrons.psychogenic.com/ 42 | ##### website for detailed instructions 43 | 44 | 45 | #################################################### 46 | ##### ##### 47 | ##### Configuration ##### 48 | ##### ##### 49 | ##### Customize the values in this section for ##### 50 | ##### your project. MCU, PROJECTNAME and ##### 51 | ##### PRJSRC must be setup for all projects, ##### 52 | ##### the remaining variables are only ##### 53 | ##### relevant to those needing additional ##### 54 | ##### include dirs or libraries and those ##### 55 | ##### who wish to use the avrdude programmer ##### 56 | ##### ##### 57 | ##### See http://electrons.psychogenic.com/ ##### 58 | ##### for further details. ##### 59 | ##### ##### 60 | #################################################### 61 | 62 | 63 | ##### Target Specific Details ##### 64 | ##### Customize these for your project ##### 65 | 66 | # Name of target controller 67 | # (e.g. 'at90s8515', see the available avr-gcc mmcu 68 | # options for possible values) 69 | MCU=atmega328p 70 | 71 | # id to use with programmer 72 | # default: PROGRAMMER_MCU=$(MCU) 73 | # In case the programer used, e.g avrdude, doesn't 74 | # accept the same MCU name as avr-gcc (for example 75 | # for ATmega8s, avr-gcc expects 'atmega8' and 76 | # avrdude requires 'm8') 77 | PROGRAMMER_MCU=m328p 78 | 79 | # Name of our project 80 | # (use a single word, e.g. 'myproject') 81 | PROJECTNAME=ov7670NoRam 82 | 83 | # Source files 84 | # List C/C++/Assembly source files: 85 | # (list all files to compile, e.g. 'a.c b.cpp as.S'): 86 | # Use .cc, .cpp or .C suffix for C++ files, use .S 87 | # (NOT .s !!!) for assembly source code files. 88 | PRJSRC=main.c ov7670.c 89 | 90 | # additional includes (e.g. -I/path/to/mydir) 91 | INC= 92 | 93 | # libraries to link in (e.g. -lmylib) 94 | LIBS= 95 | 96 | # Optimization level, 97 | # use s (size opt), 1, 2, 3 or 0 (off) 98 | OPTLEVEL=2 99 | 100 | 101 | ##### AVR Dude 'writeflash' options ##### 102 | ##### If you are using the avrdude program 103 | ##### (http://www.bsdhome.com/avrdude/) to write 104 | ##### to the MCU, you can set the following config 105 | ##### options and use 'make writeflash' to program 106 | ##### the device. 107 | 108 | 109 | # programmer id--check the avrdude for complete list 110 | # of available opts. These should include stk500, 111 | # avr910, avrisp, bsd, pony and more. Set this to 112 | # one of the valid "-c PROGRAMMER-ID" values 113 | # described in the avrdude info page. 114 | # 115 | AVRDUDE_PROGRAMMERID=arduino 116 | 117 | # port--serial or parallel port to which your 118 | # hardware programmer is attached 119 | # 120 | AVRDUDE_PORT=/dev/ttyACM0 121 | 122 | 123 | #################################################### 124 | ##### Config Done ##### 125 | ##### ##### 126 | ##### You shouldn't need to edit anything ##### 127 | ##### below to use the makefile but may wish ##### 128 | ##### to override a few of the flags ##### 129 | ##### nonetheless ##### 130 | ##### ##### 131 | #################################################### 132 | 133 | 134 | ##### Flags #### 135 | 136 | # HEXFORMAT -- format for .hex file output 137 | HEXFORMAT=ihex 138 | 139 | # compiler 140 | CFLAGS=-L/usr/lib64/binutils/avr/2.23.1/ldscripts/ -I. $(INC) -g -mmcu=$(MCU) -O$(OPTLEVEL) -flto \ 141 | -fpack-struct -fshort-enums \ 142 | -funsigned-bitfields -funsigned-char \ 143 | -Wall -Wstrict-prototypes \ 144 | -Wa,-ahlms=$(firstword \ 145 | $(filter %.lst, $(<:.c=.lst))) 146 | 147 | # c++ specific flags 148 | CPPFLAGS=-fno-exceptions -flto\ 149 | -Wa,-ahlms=$(firstword \ 150 | $(filter %.lst, $(<:.cpp=.lst))\ 151 | $(filter %.lst, $(<:.cc=.lst)) \ 152 | $(filter %.lst, $(<:.C=.lst))) 153 | 154 | # assembler 155 | ASMFLAGS =-I. $(INC) -mmcu=$(MCU) \ 156 | -x assembler-with-cpp \ 157 | -Wa,-gstabs,-ahlms=$(firstword \ 158 | $(<:.S=.lst) $(<.s=.lst)) 159 | 160 | 161 | # linker 162 | LDFLAGS=-L/usr/lib64/binutils/avr/2.23.1/ldscripts/ -Wl,-gc-sections,-Map,$(TRG).map -mmcu=$(MCU) -flto -O$(OPTLEVEL) $(LIBS) 163 | 164 | ##### executables #### 165 | CC=avr-gcc 166 | OBJCOPY=avr-objcopy 167 | OBJDUMP=avr-objdump 168 | SIZE=avr-size 169 | AVRDUDE=avrdude 170 | REMOVE=rm -f 171 | 172 | ##### automatic target names #### 173 | TRG=$(PROJECTNAME).out 174 | DUMPTRG=$(PROJECTNAME).s 175 | 176 | HEXROMTRG=$(PROJECTNAME).hex 177 | HEXTRG=$(HEXROMTRG) $(PROJECTNAME).ee.hex 178 | GDBINITFILE=gdbinit-$(PROJECTNAME) 179 | 180 | # Define all object files. 181 | 182 | # Start by splitting source files by type 183 | # C++ 184 | CPPFILES=$(filter %.cpp, $(PRJSRC)) 185 | CCFILES=$(filter %.cc, $(PRJSRC)) 186 | BIGCFILES=$(filter %.C, $(PRJSRC)) 187 | # C 188 | CFILES=$(filter %.c, $(PRJSRC)) 189 | # Assembly 190 | ASMFILES=$(filter %.S, $(PRJSRC)) 191 | 192 | 193 | # List all object files we need to create 194 | OBJDEPS=$(CFILES:.c=.o) \ 195 | $(CPPFILES:.cpp=.o)\ 196 | $(BIGCFILES:.C=.o) \ 197 | $(CCFILES:.cc=.o) \ 198 | $(ASMFILES:.S=.o) 199 | 200 | # Define all lst files. 201 | LST=$(filter %.lst, $(OBJDEPS:.o=.lst)) 202 | 203 | # All the possible generated assembly 204 | # files (.s files) 205 | GENASMFILES=$(filter %.s, $(OBJDEPS:.o=.s)) 206 | 207 | 208 | .SUFFIXES : .c .cc .cpp .C .o .out .s .S \ 209 | .hex .ee.hex .h .hh .hpp 210 | 211 | 212 | .PHONY: writeflash clean stats gdbinit stats 213 | 214 | # Make targets: 215 | # all, disasm, stats, hex, writeflash/install, clean 216 | all: $(TRG) 217 | 218 | disasm: $(DUMPTRG) stats 219 | 220 | stats: $(TRG) 221 | $(OBJDUMP) -h $(TRG) 222 | $(SIZE) $(TRG) 223 | 224 | hex: $(HEXTRG) 225 | 226 | 227 | writeflash: hex 228 | $(AVRDUDE) -c $(AVRDUDE_PROGRAMMERID) \ 229 | -p $(PROGRAMMER_MCU) -P $(AVRDUDE_PORT) -e \ 230 | -U flash:w:$(HEXROMTRG) 231 | 232 | install: writeflash 233 | 234 | $(DUMPTRG): $(TRG) 235 | $(OBJDUMP) -S $< > $@ 236 | 237 | 238 | $(TRG): $(OBJDEPS) 239 | $(CC) $(LDFLAGS) -o $(TRG) $(OBJDEPS) 240 | 241 | 242 | #### Generating assembly #### 243 | # asm from C 244 | %.s: %.c 245 | $(CC) -S $(CFLAGS) $< -o $@ 246 | 247 | # asm from (hand coded) asm 248 | %.s: %.S 249 | $(CC) -S $(ASMFLAGS) $< > $@ 250 | 251 | 252 | # asm from C++ 253 | .cpp.s .cc.s .C.s : 254 | $(CC) -S $(CFLAGS) $(CPPFLAGS) $< -o $@ 255 | 256 | 257 | 258 | #### Generating object files #### 259 | # object from C 260 | .c.o: 261 | $(CC) $(CFLAGS) -c $< -o $@ 262 | 263 | 264 | # object from C++ (.cc, .cpp, .C files) 265 | .cc.o .cpp.o .C.o : 266 | $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ 267 | 268 | # object from asm 269 | .S.o : 270 | $(CC) $(ASMFLAGS) -c $< -o $@ 271 | 272 | 273 | #### Generating hex files #### 274 | # hex files from elf 275 | ##### Generating a gdb initialisation file ##### 276 | .out.hex: 277 | $(OBJCOPY) -j .text \ 278 | -j .data \ 279 | -O $(HEXFORMAT) $< $@ 280 | 281 | .out.ee.hex: 282 | $(OBJCOPY) -j .eeprom \ 283 | --change-section-lma .eeprom=0 \ 284 | -O $(HEXFORMAT) $< $@ 285 | 286 | 287 | ##### Generating a gdb initialisation file ##### 288 | ##### Use by launching simulavr and avr-gdb: ##### 289 | ##### avr-gdb -x gdbinit-myproject ##### 290 | gdbinit: $(GDBINITFILE) 291 | 292 | $(GDBINITFILE): $(TRG) 293 | @echo "file $(TRG)" > $(GDBINITFILE) 294 | 295 | @echo "target remote localhost:1212" \ 296 | >> $(GDBINITFILE) 297 | 298 | @echo "load" >> $(GDBINITFILE) 299 | @echo "break main" >> $(GDBINITFILE) 300 | @echo "continue" >> $(GDBINITFILE) 301 | @echo 302 | @echo "Use 'avr-gdb -x $(GDBINITFILE)'" 303 | 304 | 305 | #### Cleanup #### 306 | clean: 307 | $(REMOVE) $(TRG) $(TRG).map $(DUMPTRG) 308 | $(REMOVE) $(OBJDEPS) 309 | $(REMOVE) $(LST) $(GDBINITFILE) 310 | $(REMOVE) $(GENASMFILES) 311 | $(REMOVE) $(HEXTRG) 312 | 313 | 314 | 315 | ##### EOF ##### 316 | 317 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This is a version of code that sends data to the PC. 2 | Unlike previous code this requires no external ram or fifo. 3 | It just sends the data as it receives it. 4 | The transfer rate is 1 mbps or 128kbytes per second 5 | Connections 6 | Order Arduino ov7670 7 | A5->SIOC 8 | A4<->SIOD 9 | Note what I have just described (above) are I2C connections you will need pullup resistors to 3.3v for both SIOC and SIOD. 10 | You must not connect the resistors to 5v. 11 | I have found that certain resistor values do not work such as 1K and 2.2K but found 4.7K and 10K to work. 12 | 11-> (convert 5v to 3.3v) XCLK 13 | A0<-0 14 | A1<-1 15 | A2<-2 16 | A3<-3 17 | 4<-4 18 | 5<-5 19 | 6<-6 20 | 7<-7 21 | 3<-VSYNC 22 | 2<-PCLK 23 | GND->PWDN 24 | 3.3->RESET 25 | GND->GND 26 | 3.3v->3.3v 27 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #define F_CPU 16000000UL 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "ov7670.h" 9 | /* Configuration: this lets you easily change between different resolutions 10 | * You must only uncomment one 11 | * no more no less*/ 12 | #define useVga 13 | //#define useQvga 14 | //#define useQqvga 15 | 16 | static inline void serialWrB(uint8_t dat){ 17 | while(!( UCSR0A & (1< 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "ov7670.h" 8 | static const struct regval_list vga_ov7670[] PROGMEM = { 9 | {REG_HREF,0xF6}, // was B6 10 | {0x17,0x13}, // HSTART 11 | {0x18,0x01}, // HSTOP 12 | {0x19,0x02}, // VSTART 13 | {0x1a,0x7a}, // VSTOP 14 | {REG_VREF,0x0a}, // VREF 15 | {0xff, 0xff}, /* END MARKER */ 16 | }; 17 | static const struct regval_list qvga_ov7670[] PROGMEM = { 18 | {REG_COM14, 0x19}, 19 | {0x72, 0x11}, 20 | {0x73, 0xf1}, 21 | {REG_HSTART,0x16}, 22 | {REG_HSTOP,0x04}, 23 | {REG_HREF,0x24}, 24 | {REG_VSTART,0x02}, 25 | {REG_VSTOP,0x7a}, 26 | {REG_VREF,0x0a}, 27 | {0xff, 0xff}, /* END MARKER */ 28 | }; 29 | static const struct regval_list qqvga_ov7670[] PROGMEM = { 30 | {REG_COM14, 0x1a}, // divide by 4 31 | {0x72, 0x22}, // downsample by 4 32 | {0x73, 0xf2}, // divide by 4 33 | {REG_HSTART,0x16}, 34 | {REG_HSTOP,0x04}, 35 | {REG_HREF,0xa4}, 36 | {REG_VSTART,0x02}, 37 | {REG_VSTOP,0x7a}, 38 | {REG_VREF,0x0a}, 39 | {0xff, 0xff}, /* END MARKER */ 40 | }; 41 | static const struct regval_list yuv422_ov7670[] PROGMEM = { 42 | {REG_COM7, 0x0}, /* Selects YUV mode */ 43 | {REG_RGB444, 0}, /* No RGB444 please */ 44 | {REG_COM1, 0}, 45 | {REG_COM15, COM15_R00FF}, 46 | {REG_COM9, 0x6A}, /* 128x gain ceiling; 0x8 is reserved bit */ 47 | {0x4f, 0x80}, /* "matrix coefficient 1" */ 48 | {0x50, 0x80}, /* "matrix coefficient 2" */ 49 | {0x51, 0}, /* vb */ 50 | {0x52, 0x22}, /* "matrix coefficient 4" */ 51 | {0x53, 0x5e}, /* "matrix coefficient 5" */ 52 | {0x54, 0x80}, /* "matrix coefficient 6" */ 53 | {REG_COM13,/*COM13_GAMMA|*/COM13_UVSAT}, 54 | {0xff, 0xff}, /* END MARKER */ 55 | }; 56 | static const struct regval_list rgb565_ov7670[] PROGMEM = { 57 | {REG_COM7, COM7_RGB}, /* Selects RGB mode */ 58 | {REG_RGB444, 0}, /* No RGB444 please */ 59 | {REG_COM1, 0x0}, 60 | {REG_COM15, COM15_RGB565|COM15_R00FF}, 61 | {REG_COM9, 0x6A}, /* 128x gain ceiling; 0x8 is reserved bit */ 62 | {0x4f, 0xb3}, /* "matrix coefficient 1" */ 63 | {0x50, 0xb3}, /* "matrix coefficient 2" */ 64 | {0x51, 0}, /* vb */ 65 | {0x52, 0x3d}, /* "matrix coefficient 4" */ 66 | {0x53, 0xa7}, /* "matrix coefficient 5" */ 67 | {0x54, 0xe4}, /* "matrix coefficient 6" */ 68 | {REG_COM13, /*COM13_GAMMA|*/COM13_UVSAT}, 69 | {0xff, 0xff}, /* END MARKER */ 70 | }; 71 | static const struct regval_list bayerRGB_ov7670[] PROGMEM = { 72 | {REG_COM7, COM7_BAYER}, 73 | {REG_COM13, 0x08}, /* No gamma, magic rsvd bit */ 74 | {REG_COM16, 0x3d}, /* Edge enhancement, denoise */ 75 | {REG_REG76, 0xe1}, /* Pix correction, magic rsvd */ 76 | {0xff, 0xff}, /* END MARKER */ 77 | }; 78 | static const struct regval_list ov7670_default_regs[] PROGMEM = {//from the linux driver 79 | {REG_COM7, COM7_RESET}, 80 | {REG_TSLB, 0x04}, /* OV */ 81 | {REG_COM7, 0}, /* VGA */ 82 | /* 83 | * Set the hardware window. These values from OV don't entirely 84 | * make sense - hstop is less than hstart. But they work... 85 | */ 86 | {REG_HSTART, 0x13}, {REG_HSTOP, 0x01}, 87 | {REG_HREF, 0xb6}, {REG_VSTART, 0x02}, 88 | {REG_VSTOP, 0x7a}, {REG_VREF, 0x0a}, 89 | 90 | {REG_COM3, 0}, {REG_COM14, 0}, 91 | /* Mystery scaling numbers */ 92 | {0x70, 0x3a}, {0x71, 0x35}, 93 | {0x72, 0x11}, {0x73, 0xf0}, 94 | {0xa2,/* 0x02 changed to 1*/1},{REG_COM10, COM10_VS_NEG}, 95 | /* Gamma curve values */ 96 | {0x7a, 0x20}, {0x7b, 0x10}, 97 | {0x7c, 0x1e}, {0x7d, 0x35}, 98 | {0x7e, 0x5a}, {0x7f, 0x69}, 99 | {0x80, 0x76}, {0x81, 0x80}, 100 | {0x82, 0x88}, {0x83, 0x8f}, 101 | {0x84, 0x96}, {0x85, 0xa3}, 102 | {0x86, 0xaf}, {0x87, 0xc4}, 103 | {0x88, 0xd7}, {0x89, 0xe8}, 104 | /* AGC and AEC parameters. Note we start by disabling those features, 105 | then turn them only after tweaking the values. */ 106 | {REG_COM8, COM8_FASTAEC | COM8_AECSTEP}, 107 | {REG_GAIN, 0}, {REG_AECH, 0}, 108 | {REG_COM4, 0x40}, /* magic reserved bit */ 109 | {REG_COM9, 0x18}, /* 4x gain + magic rsvd bit */ 110 | {REG_BD50MAX, 0x05}, {REG_BD60MAX, 0x07}, 111 | {REG_AEW, 0x95}, {REG_AEB, 0x33}, 112 | {REG_VPT, 0xe3}, {REG_HAECC1, 0x78}, 113 | {REG_HAECC2, 0x68}, {0xa1, 0x03}, /* magic */ 114 | {REG_HAECC3, 0xd8}, {REG_HAECC4, 0xd8}, 115 | {REG_HAECC5, 0xf0}, {REG_HAECC6, 0x90}, 116 | {REG_HAECC7, 0x94}, 117 | {REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_AGC|COM8_AEC}, 118 | {0x30,0},{0x31,0},//disable some delays 119 | /* Almost all of these are magic "reserved" values. */ 120 | {REG_COM5, 0x61}, {REG_COM6, 0x4b}, 121 | {0x16, 0x02}, {REG_MVFP, 0x07}, 122 | {0x21, 0x02}, {0x22, 0x91}, 123 | {0x29, 0x07}, {0x33, 0x0b}, 124 | {0x35, 0x0b}, {0x37, 0x1d}, 125 | {0x38, 0x71}, {0x39, 0x2a}, 126 | {REG_COM12, 0x78}, {0x4d, 0x40}, 127 | {0x4e, 0x20}, {REG_GFIX, 0}, 128 | /*{0x6b, 0x4a},*/ {0x74,0x10}, 129 | {0x8d, 0x4f}, {0x8e, 0}, 130 | {0x8f, 0}, {0x90, 0}, 131 | {0x91, 0}, {0x96, 0}, 132 | {0x9a, 0}, {0xb0, 0x84}, 133 | {0xb1, 0x0c}, {0xb2, 0x0e}, 134 | {0xb3, 0x82}, {0xb8, 0x0a}, 135 | 136 | /* More reserved magic, some of which tweaks white balance */ 137 | {0x43, 0x0a}, {0x44, 0xf0}, 138 | {0x45, 0x34}, {0x46, 0x58}, 139 | {0x47, 0x28}, {0x48, 0x3a}, 140 | {0x59, 0x88}, {0x5a, 0x88}, 141 | {0x5b, 0x44}, {0x5c, 0x67}, 142 | {0x5d, 0x49}, {0x5e, 0x0e}, 143 | {0x6c, 0x0a}, {0x6d, 0x55}, 144 | {0x6e, 0x11}, {0x6f, 0x9e}, /* it was 0x9F "9e for advance AWB" */ 145 | {0x6a, 0x40}, {REG_BLUE, 0x40}, 146 | {REG_RED, 0x60}, 147 | {REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_AGC|COM8_AEC|COM8_AWB}, 148 | 149 | /* Matrix coefficients */ 150 | {0x4f, 0x80}, {0x50, 0x80}, 151 | {0x51, 0}, {0x52, 0x22}, 152 | {0x53, 0x5e}, {0x54, 0x80}, 153 | {0x58, 0x9e}, 154 | 155 | {REG_COM16, COM16_AWBGAIN}, {REG_EDGE, 0}, 156 | {0x75, 0x05}, {REG_REG76, 0xe1}, 157 | {0x4c, 0}, {0x77, 0x01}, 158 | {REG_COM13, /*0xc3*/0x48}, {0x4b, 0x09}, 159 | {0xc9, 0x60}, /*{REG_COM16, 0x38},*/ 160 | {0x56, 0x40}, 161 | 162 | {0x34, 0x11}, {REG_COM11, COM11_EXP|COM11_HZAUTO}, 163 | {0xa4, 0x82/*Was 0x88*/}, {0x96, 0}, 164 | {0x97, 0x30}, {0x98, 0x20}, 165 | {0x99, 0x30}, {0x9a, 0x84}, 166 | {0x9b, 0x29}, {0x9c, 0x03}, 167 | {0x9d, 0x4c}, {0x9e, 0x3f}, 168 | {0x78, 0x04}, 169 | 170 | /* Extra-weird stuff. Some sort of multiplexor register */ 171 | {0x79, 0x01}, {0xc8, 0xf0}, 172 | {0x79, 0x0f}, {0xc8, 0x00}, 173 | {0x79, 0x10}, {0xc8, 0x7e}, 174 | {0x79, 0x0a}, {0xc8, 0x80}, 175 | {0x79, 0x0b}, {0xc8, 0x01}, 176 | {0x79, 0x0c}, {0xc8, 0x0f}, 177 | {0x79, 0x0d}, {0xc8, 0x20}, 178 | {0x79, 0x09}, {0xc8, 0x80}, 179 | {0x79, 0x02}, {0xc8, 0xc0}, 180 | {0x79, 0x03}, {0xc8, 0x40}, 181 | {0x79, 0x05}, {0xc8, 0x30}, 182 | {0x79, 0x26}, 183 | 184 | {0xff, 0xff}, /* END MARKER */ 185 | }; 186 | static void errorLed(void){ 187 | DDRB|=32;//make sure led is output 188 | while(1){//wait for reset 189 | PORTB^=32;// toggle led 190 | _delay_ms(100); 191 | } 192 | } 193 | static void twiStart(void){ 194 | TWCR=_BV(TWINT)| _BV(TWSTA)| _BV(TWEN);//send start 195 | while(!(TWCR & (1<reg_num); 247 | uint8_t reg_val = pgm_read_byte(&next->value); 248 | if((reg_addr==255)&&(reg_val==255)) 249 | break; 250 | wrReg(reg_addr, reg_val); 251 | next++; 252 | } 253 | } 254 | void setColorSpace(enum COLORSPACE color){ 255 | switch(color){ 256 | case YUV422: 257 | wrSensorRegs8_8(yuv422_ov7670); 258 | break; 259 | case RGB565: 260 | wrSensorRegs8_8(rgb565_ov7670); 261 | {uint8_t temp=rdReg(0x11); 262 | _delay_ms(1); 263 | wrReg(0x11,temp);}//according to the Linux kernel driver rgb565 PCLK needs rewriting 264 | break; 265 | case BAYER_RGB: 266 | wrSensorRegs8_8(bayerRGB_ov7670); 267 | break; 268 | } 269 | } 270 | void setRes(enum RESOLUTION res){ 271 | switch(res){ 272 | case VGA: 273 | wrReg(REG_COM3,0); // REG_COM3 274 | wrSensorRegs8_8(vga_ov7670); 275 | break; 276 | case QVGA: 277 | wrReg(REG_COM3,4); // REG_COM3 enable scaling 278 | wrSensorRegs8_8(qvga_ov7670); 279 | break; 280 | case QQVGA: 281 | wrReg(REG_COM3,4); // REG_COM3 enable scaling 282 | wrSensorRegs8_8(qqvga_ov7670); 283 | break; 284 | } 285 | } 286 | void camInit(void){ 287 | wrReg(0x12, 0x80);//Reset the camera. 288 | _delay_ms(100); 289 | wrSensorRegs8_8(ov7670_default_regs); 290 | wrReg(REG_COM10,32);//PCLK does not toggle on HBLANK. 291 | } 292 | -------------------------------------------------------------------------------- /ov7670.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | void wrReg(uint8_t reg,uint8_t dat); 4 | uint8_t rdReg(uint8_t reg); 5 | enum RESOLUTION{VGA,QVGA,QQVGA}; 6 | enum COLORSPACE{YUV422,RGB565,BAYER_RGB}; 7 | struct regval_list{ 8 | uint8_t reg_num; 9 | uint8_t value; 10 | }; 11 | void setColorSpace(enum COLORSPACE color); 12 | void setRes(enum RESOLUTION res); 13 | void camInit(void); 14 | #define OV7670_I2C_ADDRESS 0x21 15 | /* Registers */ 16 | #define REG_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ 17 | #define REG_BLUE 0x01 /* blue gain */ 18 | #define REG_RED 0x02 /* red gain */ 19 | #define REG_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */ 20 | #define REG_COM1 0x04 /* Control 1 */ 21 | #define COM1_CCIR656 0x40 /* CCIR656 enable */ 22 | #define REG_BAVE 0x05 /* U/B Average level */ 23 | #define REG_GbAVE 0x06 /* Y/Gb Average level */ 24 | #define REG_AECHH 0x07 /* AEC MS 5 bits */ 25 | #define REG_RAVE 0x08 /* V/R Average level */ 26 | #define REG_COM2 0x09 /* Control 2 */ 27 | #define COM2_SSLEEP 0x10 /* Soft sleep mode */ 28 | #define REG_PID 0x0a /* Product ID MSB */ 29 | #define REG_VER 0x0b /* Product ID LSB */ 30 | #define REG_COM3 0x0c /* Control 3 */ 31 | #define COM3_SWAP 0x40 /* Byte swap */ 32 | #define COM3_SCALEEN 0x08 /* Enable scaling */ 33 | #define COM3_DCWEN 0x04 /* Enable downsamp/crop/window */ 34 | #define REG_COM4 0x0d /* Control 4 */ 35 | #define REG_COM5 0x0e /* All "reserved" */ 36 | #define REG_COM6 0x0f /* Control 6 */ 37 | #define REG_AECH 0x10 /* More bits of AEC value */ 38 | #define REG_CLKRC 0x11 /* Clocl control */ 39 | #define CLK_EXT 0x40 /* Use external clock directly */ 40 | #define CLK_SCALE 0x3f /* Mask for internal clock scale */ 41 | #define REG_COM7 0x12 /* Control 7 */ 42 | #define COM7_RESET 0x80 /* Register reset */ 43 | #define COM7_FMT_MASK 0x38 44 | #define COM7_FMT_VGA 0x00 45 | #define COM7_FMT_CIF 0x20 /* CIF format */ 46 | #define COM7_FMT_QVGA 0x10 /* QVGA format */ 47 | #define COM7_FMT_QCIF 0x08 /* QCIF format */ 48 | #define COM7_RGB 0x04 /* bits 0 and 2 - RGB format */ 49 | #define COM7_YUV 0x00 /* YUV */ 50 | #define COM7_BAYER 0x01 /* Bayer format */ 51 | #define COM7_PBAYER 0x05 /* "Processed bayer" */ 52 | #define REG_COM8 0x13 /* Control 8 */ 53 | #define COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */ 54 | #define COM8_AECSTEP 0x40 /* Unlimited AEC step size */ 55 | #define COM8_BFILT 0x20 /* Band filter enable */ 56 | #define COM8_AGC 0x04 /* Auto gain enable */ 57 | #define COM8_AWB 0x02 /* White balance enable */ 58 | #define COM8_AEC 0x01 /* Auto exposure enable */ 59 | #define REG_COM9 0x14 /* Control 9- gain ceiling */ 60 | #define REG_COM10 0x15 /* Control 10 */ 61 | #define COM10_HSYNC 0x40 /* HSYNC instead of HREF */ 62 | #define COM10_PCLK_HB 0x20 /* Suppress PCLK on horiz blank */ 63 | #define COM10_HREF_REV 0x08 /* Reverse HREF */ 64 | #define COM10_VS_LEAD 0x04 /* VSYNC on clock leading edge */ 65 | #define COM10_VS_NEG 0x02 /* VSYNC negative */ 66 | #define COM10_HS_NEG 0x01 /* HSYNC negative */ 67 | #define REG_HSTART 0x17 /* Horiz start high bits */ 68 | #define REG_HSTOP 0x18 /* Horiz stop high bits */ 69 | #define REG_VSTART 0x19 /* Vert start high bits */ 70 | #define REG_VSTOP 0x1a /* Vert stop high bits */ 71 | #define REG_PSHFT 0x1b /* Pixel delay after HREF */ 72 | #define REG_MIDH 0x1c /* Manuf. ID high */ 73 | #define REG_MIDL 0x1d /* Manuf. ID low */ 74 | #define REG_MVFP 0x1e /* Mirror / vflip */ 75 | #define MVFP_MIRROR 0x20 /* Mirror image */ 76 | #define MVFP_FLIP 0x10 /* Vertical flip */ 77 | 78 | #define REG_AEW 0x24 /* AGC upper limit */ 79 | #define REG_AEB 0x25 /* AGC lower limit */ 80 | #define REG_VPT 0x26 /* AGC/AEC fast mode op region */ 81 | #define REG_HSYST 0x30 /* HSYNC rising edge delay */ 82 | #define REG_HSYEN 0x31 /* HSYNC falling edge delay */ 83 | #define REG_HREF 0x32 /* HREF pieces */ 84 | #define REG_TSLB 0x3a /* lots of stuff */ 85 | #define TSLB_YLAST 0x04 /* UYVY or VYUY - see com13 */ 86 | #define REG_COM11 0x3b /* Control 11 */ 87 | #define COM11_NIGHT 0x80 /* NIght mode enable */ 88 | #define COM11_NMFR 0x60 /* Two bit NM frame rate */ 89 | #define COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */ 90 | #define COM11_50HZ 0x08 /* Manual 50Hz select */ 91 | #define COM11_EXP 0x02 92 | #define REG_COM12 0x3c /* Control 12 */ 93 | #define COM12_HREF 0x80 /* HREF always */ 94 | #define REG_COM13 0x3d /* Control 13 */ 95 | #define COM13_GAMMA 0x80 /* Gamma enable */ 96 | #define COM13_UVSAT 0x40 /* UV saturation auto adjustment */ 97 | #define COM13_UVSWAP 0x01 /* V before U - w/TSLB */ 98 | #define REG_COM14 0x3e /* Control 14 */ 99 | #define COM14_DCWEN 0x10 /* DCW/PCLK-scale enable */ 100 | #define REG_EDGE 0x3f /* Edge enhancement factor */ 101 | #define REG_COM15 0x40 /* Control 15 */ 102 | #define COM15_R10F0 0x00 /* Data range 10 to F0 */ 103 | #define COM15_R01FE 0x80 /* 01 to FE */ 104 | #define COM15_R00FF 0xc0 /* 00 to FF */ 105 | #define COM15_RGB565 0x10 /* RGB565 output */ 106 | #define COM15_RGB555 0x30 /* RGB555 output */ 107 | #define REG_COM16 0x41 /* Control 16 */ 108 | #define COM16_AWBGAIN 0x08 /* AWB gain enable */ 109 | #define REG_COM17 0x42 /* Control 17 */ 110 | #define COM17_AECWIN 0xc0 /* AEC window - must match COM4 */ 111 | #define COM17_CBAR 0x08 /* DSP Color bar */ 112 | /* 113 | * This matrix defines how the colors are generated, must be 114 | * tweaked to adjust hue and saturation. 115 | * 116 | * Order: v-red, v-green, v-blue, u-red, u-green, u-blue 117 | * They are nine-bit signed quantities, with the sign bit 118 | * stored in0x58.Sign for v-red is bit 0, and up from there. 119 | */ 120 | #define REG_CMATRIX_BASE0x4f 121 | #define CMATRIX_LEN 6 122 | #define REG_CMATRIX_SIGN0x58 123 | #define REG_BRIGHT 0x55 /* Brightness */ 124 | #define REG_CONTRAS 0x56 /* Contrast control */ 125 | #define REG_GFIX 0x69 /* Fix gain control */ 126 | #define REG_REG76 0x76 /* OV's name */ 127 | #define R76_BLKPCOR 0x80 /* Black pixel correction enable */ 128 | #define R76_WHTPCOR 0x40 /* White pixel correction enable */ 129 | #define REG_RGB444 0x8c /* RGB 444 control */ 130 | #define R444_ENABLE 0x02 /* Turn on RGB444, overrides 5x5 */ 131 | #define R444_RGBX 0x01 /* Empty nibble at end */ 132 | #define REG_HAECC1 0x9f /* Hist AEC/AGC control 1 */ 133 | #define REG_HAECC2 0xa0 /* Hist AEC/AGC control 2 */ 134 | #define REG_BD50MAX 0xa5 /* 50hz banding step limit */ 135 | #define REG_HAECC3 0xa6 /* Hist AEC/AGC control 3 */ 136 | #define REG_HAECC4 0xa7 /* Hist AEC/AGC control 4 */ 137 | #define REG_HAECC5 0xa8 /* Hist AEC/AGC control 5 */ 138 | #define REG_HAECC6 0xa9 /* Hist AEC/AGC control 6 */ 139 | #define REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ 140 | #define REG_BD60MAX 0xab /* 60hz banding step limit */ 141 | #define COM7_FMT_CIF 0x20 /* CIF format */ 142 | #define COM7_RGB 0x04 /* bits 0 and 2 - RGB format */ 143 | #define COM7_YUV 0x00 /* YUV */ 144 | #define COM7_BAYER 0x01 /* Bayer format */ 145 | #define COM7_PBAYER 0x05 /* "Processed bayer" */ 146 | #define COM10_VS_LEAD 0x04 /* VSYNC on clock leading edge */ 147 | #define COM11_50HZ 0x08 /* Manual 50Hz select */ 148 | #define COM13_UVSAT 0x40 /* UV saturation auto adjustment */ 149 | #define COM15_R01FE 0x80 /* 01 to FE */ 150 | #define MTX1 0x4f /* Matrix Coefficient 1 */ 151 | #define MTX2 0x50 /* Matrix Coefficient 2 */ 152 | #define MTX3 0x51 /* Matrix Coefficient 3 */ 153 | #define MTX4 0x52 /* Matrix Coefficient 4 */ 154 | #define MTX5 0x53 /* Matrix Coefficient 5 */ 155 | #define MTX6 0x54 /* Matrix Coefficient 6 */ 156 | #define MTXS 0x58 /* Matrix Coefficient Sign */ 157 | #define AWBC7 0x59 /* AWB Control 7 */ 158 | #define AWBC8 0x5a /* AWB Control 8 */ 159 | #define AWBC9 0x5b /* AWB Control 9 */ 160 | #define AWBC10 0x5c /* AWB Control 10 */ 161 | #define AWBC11 0x5d /* AWB Control 11 */ 162 | #define AWBC12 0x5e /* AWB Control 12 */ 163 | #define REG_GFI 0x69 /* Fix gain control */ 164 | #define GGAIN 0x6a /* G Channel AWB Gain */ 165 | #define DBLV 0x6b 166 | #define AWBCTR3 0x6c /* AWB Control 3 */ 167 | #define AWBCTR2 0x6d /* AWB Control 2 */ 168 | #define AWBCTR1 0x6e /* AWB Control 1 */ 169 | #define AWBCTR0 0x6f /* AWB Control 0 */ 170 | 171 | --------------------------------------------------------------------------------