A program that records images from the OV7670 camera and displays them on a SPI TFT display. Working at 15fps

Dependencies:   mbed TFT_fonts_old

Committer:
ms523
Date:
Sat Mar 31 10:05:59 2012 +0000
Revision:
1:c98598814170
Parent:
0:aabbf2286bf2
Working at 15fps for 160*120 RGB565 video

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ms523 0:aabbf2286bf2 1 #include "mbed.h"
ms523 0:aabbf2286bf2 2 #include "ov7670reg.h"
ms523 0:aabbf2286bf2 3
ms523 0:aabbf2286bf2 4 #define OV7670_WRITE (0x42)
ms523 0:aabbf2286bf2 5 #define OV7670_READ (0x43)
ms523 0:aabbf2286bf2 6 #define OV7670_WRITEWAIT (20)
ms523 0:aabbf2286bf2 7 #define OV7670_NOACK (0)
ms523 0:aabbf2286bf2 8 #define OV7670_REGMAX (201)
ms523 0:aabbf2286bf2 9 #define OV7670_I2CFREQ (50000)
ms523 0:aabbf2286bf2 10
ms523 0:aabbf2286bf2 11 //
ms523 0:aabbf2286bf2 12 // OV7670 + FIFO AL422B camera board test
ms523 0:aabbf2286bf2 13 //
ms523 0:aabbf2286bf2 14 class OV7670 : public Base
ms523 0:aabbf2286bf2 15 {
ms523 0:aabbf2286bf2 16 public:
ms523 0:aabbf2286bf2 17 I2C camera ;
ms523 0:aabbf2286bf2 18 InterruptIn vsync,href;
ms523 0:aabbf2286bf2 19 DigitalOut wen ;
ms523 1:c98598814170 20 //BusIn data ;
ms523 1:c98598814170 21 PortIn data;
ms523 0:aabbf2286bf2 22 DigitalOut rrst,oe,rclk ;
ms523 0:aabbf2286bf2 23 volatile int LineCounter ;
ms523 0:aabbf2286bf2 24 volatile int LastLines ;
ms523 0:aabbf2286bf2 25 volatile bool CaptureReq ;
ms523 0:aabbf2286bf2 26 volatile bool Busy ;
ms523 1:c98598814170 27 volatile bool Done ;
ms523 1:c98598814170 28
ms523 0:aabbf2286bf2 29 OV7670(
ms523 0:aabbf2286bf2 30 PinName sda,// Camera I2C port
ms523 0:aabbf2286bf2 31 PinName scl,// Camera I2C port
ms523 0:aabbf2286bf2 32 PinName vs, // VSYNC
ms523 0:aabbf2286bf2 33 PinName hr, // HREF
ms523 0:aabbf2286bf2 34 PinName we, // WEN
ms523 1:c98598814170 35
ms523 1:c98598814170 36 /*
ms523 0:aabbf2286bf2 37 PinName d7, // D7
ms523 0:aabbf2286bf2 38 PinName d6, // D6
ms523 0:aabbf2286bf2 39 PinName d5, // D5
ms523 0:aabbf2286bf2 40 PinName d4, // D4
ms523 0:aabbf2286bf2 41 PinName d3, // D3
ms523 0:aabbf2286bf2 42 PinName d2, // D2
ms523 0:aabbf2286bf2 43 PinName d1, // D1
ms523 0:aabbf2286bf2 44 PinName d0, // D0
ms523 1:c98598814170 45 */
ms523 1:c98598814170 46 PortName port, // 8bit bus port
ms523 1:c98598814170 47 int mask, // 0b0000_0M65_4000_0321_L000_0000_0000_0000 = 0x07878000
ms523 1:c98598814170 48
ms523 0:aabbf2286bf2 49 PinName rt, // /RRST
ms523 0:aabbf2286bf2 50 PinName o, // /OE
ms523 0:aabbf2286bf2 51 PinName rc // RCLK
ms523 1:c98598814170 52 //) : camera(sda,scl),vsync(vs),href(hr),wen(we),data(d0,d1,d2,d3,d4,d5,d6,d7),rrst(rt),oe(o),rclk(rc)
ms523 1:c98598814170 53 ) : camera(sda,scl),vsync(vs),href(hr),wen(we),data(port,mask),rrst(rt),oe(o),rclk(rc)
ms523 0:aabbf2286bf2 54 {
ms523 0:aabbf2286bf2 55 camera.stop() ;
ms523 0:aabbf2286bf2 56 camera.frequency(OV7670_I2CFREQ) ;
ms523 0:aabbf2286bf2 57 vsync.fall(this,&OV7670::VsyncHandler) ;
ms523 0:aabbf2286bf2 58 href.rise(this,&OV7670::HrefHandler) ;
ms523 0:aabbf2286bf2 59 CaptureReq = false ;
ms523 0:aabbf2286bf2 60 Busy = false ;
ms523 0:aabbf2286bf2 61 Done = false ;
ms523 0:aabbf2286bf2 62 LineCounter = 0 ;
ms523 0:aabbf2286bf2 63 rrst = 1 ;
ms523 0:aabbf2286bf2 64 oe = 1 ;
ms523 0:aabbf2286bf2 65 rclk = 1 ;
ms523 0:aabbf2286bf2 66 wen = 0 ;
ms523 0:aabbf2286bf2 67 }
ms523 0:aabbf2286bf2 68
ms523 0:aabbf2286bf2 69 // capture request
ms523 0:aabbf2286bf2 70 void CaptureNext(void)
ms523 0:aabbf2286bf2 71 {
ms523 0:aabbf2286bf2 72 CaptureReq = true ;
ms523 0:aabbf2286bf2 73 Busy = true ;
ms523 0:aabbf2286bf2 74 }
ms523 0:aabbf2286bf2 75
ms523 0:aabbf2286bf2 76 // capture done? (with clear)
ms523 0:aabbf2286bf2 77 bool CaptureDone(void)
ms523 0:aabbf2286bf2 78 {
ms523 0:aabbf2286bf2 79 bool result ;
ms523 0:aabbf2286bf2 80 if (Busy) {
ms523 0:aabbf2286bf2 81 result = false ;
ms523 0:aabbf2286bf2 82 } else {
ms523 0:aabbf2286bf2 83 result = Done ;
ms523 0:aabbf2286bf2 84 Done = false ;
ms523 0:aabbf2286bf2 85 }
ms523 0:aabbf2286bf2 86 return result ;
ms523 0:aabbf2286bf2 87 }
ms523 0:aabbf2286bf2 88
ms523 0:aabbf2286bf2 89 // write to camera
ms523 0:aabbf2286bf2 90 void WriteReg(int addr,int data)
ms523 0:aabbf2286bf2 91 {
ms523 0:aabbf2286bf2 92 // WRITE 0x42,ADDR,DATA
ms523 0:aabbf2286bf2 93 camera.start() ;
ms523 0:aabbf2286bf2 94 camera.write(OV7670_WRITE) ;
ms523 0:aabbf2286bf2 95 wait_us(OV7670_WRITEWAIT);
ms523 0:aabbf2286bf2 96 camera.write(addr) ;
ms523 0:aabbf2286bf2 97 wait_us(OV7670_WRITEWAIT);
ms523 0:aabbf2286bf2 98 camera.write(data) ;
ms523 0:aabbf2286bf2 99 camera.stop() ;
ms523 0:aabbf2286bf2 100 }
ms523 0:aabbf2286bf2 101
ms523 0:aabbf2286bf2 102 // read from camera
ms523 0:aabbf2286bf2 103 int ReadReg(int addr)
ms523 0:aabbf2286bf2 104 {
ms523 0:aabbf2286bf2 105 int data ;
ms523 0:aabbf2286bf2 106
ms523 0:aabbf2286bf2 107 // WRITE 0x42,ADDR
ms523 0:aabbf2286bf2 108 camera.start() ;
ms523 0:aabbf2286bf2 109 camera.write(OV7670_WRITE) ;
ms523 0:aabbf2286bf2 110 wait_us(OV7670_WRITEWAIT);
ms523 0:aabbf2286bf2 111 camera.write(addr) ;
ms523 0:aabbf2286bf2 112 camera.stop() ;
ms523 0:aabbf2286bf2 113 wait_us(OV7670_WRITEWAIT);
ms523 0:aabbf2286bf2 114
ms523 0:aabbf2286bf2 115 // WRITE 0x43,READ
ms523 0:aabbf2286bf2 116 camera.start() ;
ms523 0:aabbf2286bf2 117 camera.write(OV7670_READ) ;
ms523 0:aabbf2286bf2 118 wait_us(OV7670_WRITEWAIT);
ms523 0:aabbf2286bf2 119 data = camera.read(OV7670_NOACK) ;
ms523 0:aabbf2286bf2 120 camera.stop() ;
ms523 0:aabbf2286bf2 121
ms523 0:aabbf2286bf2 122 return data ;
ms523 0:aabbf2286bf2 123 }
ms523 0:aabbf2286bf2 124
ms523 0:aabbf2286bf2 125 void Reset(void) {
ms523 0:aabbf2286bf2 126 WriteReg(0x12,0x80) ; // RESET CAMERA
ms523 0:aabbf2286bf2 127 wait_ms(200) ;
ms523 0:aabbf2286bf2 128 }
ms523 0:aabbf2286bf2 129
ms523 0:aabbf2286bf2 130 void InitQQVGA() {
ms523 0:aabbf2286bf2 131 // QQVGA RGB444
ms523 0:aabbf2286bf2 132 WriteReg(REG_CLKRC,0x80);
ms523 0:aabbf2286bf2 133 WriteReg(REG_COM11,0x0A) ;
ms523 0:aabbf2286bf2 134 WriteReg(REG_TSLB,0x04);
ms523 0:aabbf2286bf2 135 WriteReg(REG_COM7,0x04) ;
ms523 1:c98598814170 136
ms523 1:c98598814170 137 //WriteReg(REG_RGB444, 0x02);
ms523 1:c98598814170 138 //WriteReg(REG_COM15, 0xd0);
ms523 1:c98598814170 139 WriteReg(REG_RGB444, 0x00); // Disable RGB 444?
ms523 1:c98598814170 140 WriteReg(REG_COM15, 0xD0); // Set RGB 565?
ms523 1:c98598814170 141
ms523 0:aabbf2286bf2 142 WriteReg(REG_HSTART,0x16) ;
ms523 0:aabbf2286bf2 143 WriteReg(REG_HSTOP,0x04) ;
ms523 0:aabbf2286bf2 144 WriteReg(REG_HREF,0x24) ;
ms523 0:aabbf2286bf2 145 WriteReg(REG_VSTART,0x02) ;
ms523 0:aabbf2286bf2 146 WriteReg(REG_VSTOP,0x7a) ;
ms523 0:aabbf2286bf2 147 WriteReg(REG_VREF,0x0a) ;
ms523 0:aabbf2286bf2 148 WriteReg(REG_COM10,0x02) ;
ms523 0:aabbf2286bf2 149 WriteReg(REG_COM3, 0x04);
ms523 0:aabbf2286bf2 150 WriteReg(REG_COM14, 0x1a);
ms523 1:c98598814170 151 WriteReg(REG_MVFP,0x27) ;
ms523 0:aabbf2286bf2 152 WriteReg(0x72, 0x22);
ms523 0:aabbf2286bf2 153 WriteReg(0x73, 0xf2);
ms523 0:aabbf2286bf2 154
ms523 0:aabbf2286bf2 155 // COLOR SETTING
ms523 0:aabbf2286bf2 156 WriteReg(0x4f,0x80);
ms523 0:aabbf2286bf2 157 WriteReg(0x50,0x80);
ms523 0:aabbf2286bf2 158 WriteReg(0x51,0x00);
ms523 0:aabbf2286bf2 159 WriteReg(0x52,0x22);
ms523 0:aabbf2286bf2 160 WriteReg(0x53,0x5e);
ms523 0:aabbf2286bf2 161 WriteReg(0x54,0x80);
ms523 0:aabbf2286bf2 162 WriteReg(0x56,0x40);
ms523 0:aabbf2286bf2 163 WriteReg(0x58,0x9e);
ms523 0:aabbf2286bf2 164 WriteReg(0x59,0x88);
ms523 0:aabbf2286bf2 165 WriteReg(0x5a,0x88);
ms523 0:aabbf2286bf2 166 WriteReg(0x5b,0x44);
ms523 0:aabbf2286bf2 167 WriteReg(0x5c,0x67);
ms523 0:aabbf2286bf2 168 WriteReg(0x5d,0x49);
ms523 0:aabbf2286bf2 169 WriteReg(0x5e,0x0e);
ms523 0:aabbf2286bf2 170 WriteReg(0x69,0x00);
ms523 0:aabbf2286bf2 171 WriteReg(0x6a,0x40);
ms523 0:aabbf2286bf2 172 WriteReg(0x6b,0x0a);
ms523 0:aabbf2286bf2 173 WriteReg(0x6c,0x0a);
ms523 0:aabbf2286bf2 174 WriteReg(0x6d,0x55);
ms523 0:aabbf2286bf2 175 WriteReg(0x6e,0x11);
ms523 0:aabbf2286bf2 176 WriteReg(0x6f,0x9f);
ms523 0:aabbf2286bf2 177
ms523 0:aabbf2286bf2 178 WriteReg(0xb0,0x84);
ms523 0:aabbf2286bf2 179 }
ms523 0:aabbf2286bf2 180
ms523 0:aabbf2286bf2 181
ms523 0:aabbf2286bf2 182
ms523 0:aabbf2286bf2 183 // vsync handler
ms523 0:aabbf2286bf2 184 void VsyncHandler(void)
ms523 0:aabbf2286bf2 185 {
ms523 0:aabbf2286bf2 186 // Capture Enable
ms523 0:aabbf2286bf2 187 if (CaptureReq) {
ms523 0:aabbf2286bf2 188 wen = 1 ;
ms523 0:aabbf2286bf2 189 Done = false ;
ms523 0:aabbf2286bf2 190 CaptureReq = false ;
ms523 0:aabbf2286bf2 191 } else {
ms523 0:aabbf2286bf2 192 wen = 0 ;
ms523 0:aabbf2286bf2 193 if (Busy) {
ms523 0:aabbf2286bf2 194 Busy = false ;
ms523 0:aabbf2286bf2 195 Done = true ;
ms523 0:aabbf2286bf2 196 }
ms523 0:aabbf2286bf2 197 }
ms523 0:aabbf2286bf2 198
ms523 0:aabbf2286bf2 199 // Hline Counter
ms523 0:aabbf2286bf2 200 LastLines = LineCounter ;
ms523 0:aabbf2286bf2 201 LineCounter = 0 ;
ms523 0:aabbf2286bf2 202 }
ms523 0:aabbf2286bf2 203
ms523 0:aabbf2286bf2 204 // href handler
ms523 0:aabbf2286bf2 205 void HrefHandler(void)
ms523 0:aabbf2286bf2 206 {
ms523 0:aabbf2286bf2 207 LineCounter++ ;
ms523 0:aabbf2286bf2 208 }
ms523 0:aabbf2286bf2 209
ms523 0:aabbf2286bf2 210 // Data Read
ms523 0:aabbf2286bf2 211 int ReadOneByte(void)
ms523 0:aabbf2286bf2 212 {
ms523 1:c98598814170 213 int result;
ms523 1:c98598814170 214 rclk = 1;
ms523 1:c98598814170 215 result = data;
ms523 1:c98598814170 216
ms523 1:c98598814170 217 // Shift the bits around to form the byte
ms523 1:c98598814170 218 int top = result >> 19; // Isolate the top nibble
ms523 1:c98598814170 219 int middle = result >> 2; // Isolate bits 2 & 3
ms523 1:c98598814170 220 result = result & 0x00000003; // Isolate bits 0 & 1
ms523 1:c98598814170 221
ms523 1:c98598814170 222 result += middle;
ms523 1:c98598814170 223 result += top;
ms523 1:c98598814170 224
ms523 1:c98598814170 225 rclk = 0;
ms523 1:c98598814170 226 return result;
ms523 0:aabbf2286bf2 227 }
ms523 0:aabbf2286bf2 228
ms523 0:aabbf2286bf2 229 // Data Start
ms523 0:aabbf2286bf2 230 void ReadStart(void)
ms523 0:aabbf2286bf2 231 {
ms523 0:aabbf2286bf2 232 rrst = 0 ;
ms523 0:aabbf2286bf2 233 oe = 0 ;
ms523 0:aabbf2286bf2 234 wait_us(1) ;
ms523 0:aabbf2286bf2 235 rclk = 0 ;
ms523 0:aabbf2286bf2 236 wait_us(1) ;
ms523 0:aabbf2286bf2 237 rclk = 1 ;
ms523 0:aabbf2286bf2 238 wait_us(1) ;
ms523 0:aabbf2286bf2 239 rrst = 1 ;
ms523 0:aabbf2286bf2 240 }
ms523 0:aabbf2286bf2 241
ms523 0:aabbf2286bf2 242 // Data Stop
ms523 0:aabbf2286bf2 243 void ReadStop(void)
ms523 0:aabbf2286bf2 244 {
ms523 0:aabbf2286bf2 245 oe = 1 ;
ms523 0:aabbf2286bf2 246 ReadOneByte() ;
ms523 0:aabbf2286bf2 247 rclk = 1 ;
ms523 0:aabbf2286bf2 248 }
ms523 0:aabbf2286bf2 249 };