First release

Dependencies:   EthernetInterface HTTPServer TextLCD mbed-rpc mbed-rtos mbed

Sample code of section 5 in Oct 2014 issue of the Interface Magazine, published by CQ publishing in Japan. CQ出版社インターフェース誌 2014年10月号5章に掲載のサンプルコードです.

LPC1768にトラ技OV7670モジュールとサーボを接続したうえで,リモート操作可能なネットワーク・カメラにしています.このコードのうちカメラ制御部には,Sadaei Osakabe氏のコードを流用させていただいています.

また,次のHTMLファイルをダウンロードして,LPC1768のフラッシュメモリに置いてください.ネットワーク経由で,このHTMLにアクセスをします(ブラウザで開く). /media/uploads/smorioka/netcam.htm

Files at this revision

API Documentation at this revision

Comitter:
smorioka
Date:
Tue Aug 26 16:49:26 2014 +0000
Commit message:
Sample code of section 5 in Oct 2014 issue of the Interface Magazine, published by CQ publishing in Japan.

Changed in this revision

EthernetInterface.lib Show annotated file Show diff for this revision Revisions of this file
HTTPServer.lib Show annotated file Show diff for this revision Revisions of this file
TextLCD.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-rpc.lib Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
ov7670.h Show annotated file Show diff for this revision Revisions of this file
ov7670reg.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 993f719c9352 EthernetInterface.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EthernetInterface.lib	Tue Aug 26 16:49:26 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/EthernetInterface/#097a9996f8d5
diff -r 000000000000 -r 993f719c9352 HTTPServer.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPServer.lib	Tue Aug 26 16:49:26 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/leihen/code/HTTPServer/#cc3f5c53d0d5
diff -r 000000000000 -r 993f719c9352 TextLCD.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TextLCD.lib	Tue Aug 26 16:49:26 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/simon/code/TextLCD/#308d188a2d3a
diff -r 000000000000 -r 993f719c9352 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Aug 26 16:49:26 2014 +0000
@@ -0,0 +1,421 @@
+/*
+ * Copyright (c) 2014, Sumio Morioka
+ * All rights reserved.
+ *
+ * This source code was originally written by Dr.Sumio Morioka for use in the Oct 2014 issue of 
+ * "the Interface magazine", published by CQ publishing Co.Ltd in Japan (http://www.cqpub.co.jp).
+ * The author has no responsibility on any results caused by using this code.
+ *
+ * - Distribution date of this code: Aug 26, 2014
+ * - Author: Dr.Sumio Morioka (http://www002.upp.so-net.ne.jp/morioka)
+ *
+ *
+ * IMPORTANT NOTICE:
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the name of the copyright holder nor the
+ *     names of its contributors may be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+ 
+#include "mbed.h"
+#include "mbed_rpc.h"
+
+#include "TextLCD.h"
+#include "LocalFileSystem.h"
+
+#include "EthernetInterface.h"
+#include "HTTPServer.h"
+#include "FsHandler.h"
+#include "RpcHandler.h"
+
+#include "ov7670.h"
+
+TextLCD lcd(p24, p26, p27, p28, p29, p30);
+
+
+//#define USE_RPCOUT
+#undef USE_RPCOUT
+
+#ifndef USE_RPCOUT
+DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4);
+PwmOut sv0(p21), sv1(p22), sv2(p23);
+#else
+RpcDigitalOut led1(LED1, "led1");
+RpcDigitalOut led2(LED2, "led2");
+RpcDigitalOut led3(LED3, "led3");
+RpcDigitalOut led4(LED4, "led4");
+
+RpcPwmOut sv0(p21, "sv0");
+RpcPwmOut sv1(p22, "sv1");
+RpcPwmOut sv2(p23, "sv2");
+#endif
+
+
+LocalFileSystem local("webfs");
+
+OV7670 camera(
+    p9,p10,			// SDA,SCL(I2C / SCCB)
+    p5,p6,p7,		// VSYNC,HREF,WEN(FIFO)
+    p20,p19,p18,p17,p16,p15,p14,p13,	// D7-D0
+    p8,p11,p12);	// RRST,OE,RCLK
+
+//Timer tmr;
+
+#define QQVGA
+//#define QVGA
+//#define VGA34
+
+#ifdef QQVGA
+#define SIZEX 160
+#define SIZEY 120
+#endif
+
+#ifdef QVGA
+#define SIZEX 320
+#define SIZEY 240
+#endif
+
+#ifdef VGA34
+#define SIZEX 480
+#define SIZEY 360
+#endif
+
+
+//void cam_cap(void);
+void cam_cap(Arguments* input, Reply* output);
+RPCFunction rpcFunc(&cam_cap, "cam_cap");
+
+#ifndef USE_RPCOUT
+float	sv0_rpc;
+float	sv1_rpc;
+float	sv2_rpc;
+
+RPCVariable<float> rpc_sv0_val(&sv0_rpc, "sv0");
+RPCVariable<float> rpc_sv1_val(&sv1_rpc, "sv1");
+RPCVariable<float> rpc_sv2_val(&sv2_rpc, "sv2");
+#endif
+
+int		cap_flag;
+RPCVariable<int> rpc_cap_flag(&cap_flag, "cap_flag");
+
+
+int memfree(void)
+{
+	int	ret = 1;
+	while (1) {
+		char	*p	= (char *)malloc(ret);
+		if (p == NULL)
+			break;
+		free(p);
+		ret++;
+	}
+	return (ret);
+}
+
+
+float deg_to_pulsewidth(float deg)
+{
+	// limit range
+	if (deg < -90.0f)
+		deg	= -90.0f;
+	else if (deg > 90.0f)
+		deg = 90.0f;
+
+	// return result
+	return (0.00145f + 0.001f * (deg / 90.0f));
+}
+
+int main() 
+{
+	float	sv0_val, sv1_val, sv2_val;
+	
+#ifndef USE_RPCOUT
+    led1 = 0;
+    led2 = 0;
+    led3 = 0;
+    led4 = 0;
+#else
+	led1.write(0);
+	led2.write(0);
+	led3.write(0);
+	led4.write(0);
+#endif
+
+#ifdef USE_RPCOUT
+	sv0_val	= 0.00045f;			// unit: sec
+	sv1_val	= 0.00145f;			// unit: sec
+	sv2_val	= 0.00245f;			// unit: sec
+
+	sv0.period(0.02f);			// unit: sec
+	sv0.pulsewidth(sv0_val);
+
+	sv1.period(0.02f);			// unit: sec
+	sv1.pulsewidth(sv1_val);
+
+	sv2.period(0.02f);			// unit: sec
+	sv2.pulsewidth(sv2_val);
+
+#else
+	sv0_val	= 0.0f;				// unit: deg
+	sv1_val	= 0.0f;				// unit: deg
+	sv2_val	= 0.0f;				// unit: deg
+	
+	sv0.period(0.02f);			// unit: sec
+	sv0.pulsewidth(deg_to_pulsewidth(sv0_val));
+
+	sv1.period(0.02f);			// unit: sec
+	sv1.pulsewidth(deg_to_pulsewidth(sv1_val));
+
+	sv2.period(0.02f);			// unit: sec
+	sv2.pulsewidth(deg_to_pulsewidth(sv2_val));
+
+	sv0_rpc	= sv0_val;
+	sv1_rpc	= sv1_val;
+	sv2_rpc	= sv2_val;
+#endif
+	
+	cap_flag	= 0;
+
+	////////////////////////////////////////////////////////////////////////////
+    camera.WriteReg(0x12, 0x80);			// com7; reset
+    wait_ms(200);
+
+	camera.InitDefaultReg();
+
+    // negate vsync
+    camera.WriteReg(0x15, 0x02);			// com10; negative vsync
+
+#ifdef QQVGA
+	camera.InitQQVGA();
+#endif
+#ifdef QVGA
+	camera.InitQVGA();
+#endif
+#ifdef VGA34
+	camera.InitVGA_3_4();
+#endif
+
+    // data format
+    camera.WriteReg(0x12, 0x04 + 0);    // com7 RGB	(bit1...test pattern)
+    camera.WriteReg(0x40, 0xD0);    // com15 RGB565
+    camera.WriteReg(0x8c, 0x00);    // RGB444
+
+    wait_ms(300);
+
+//{
+//FILE *f = fopen("/webfs/REG.TXT", "wt");
+//for (int i = 0; i < 256; i++) {
+//    int val = camera.ReadReg(i);
+//	fprintf(f, "%02X ", val);
+//	if ((i % 16) == 15)
+//		fprintf(f, "\n");
+//}
+//fclose(f);
+//}
+
+    //////////////////////////////////////////////////
+
+    // network
+    EthernetInterface   eth;    // locate here
+
+//  //Static IP
+//	char *ip		= "192.168.0.20";
+//	char *mask		= "255.255.255.0";
+//	char *gateway	= "192.168.0.1";
+//	eth.init(ip, mask, gateway);
+    //DHCP
+	eth.init();
+
+    eth.connect();
+
+    lcd.locate(0, 0);
+    lcd.printf("IP %s", eth.getIPAddress());
+
+	// rcp
+#ifdef USE_RPCOUT
+//    RPC::add_rpc_class<RpcDigitalIn>();		// read
+    RPC::add_rpc_class<RpcDigitalOut>();		// read,write
+//    RPC::add_rpc_class<RpcDigitalInOut>();	// read,write,input,output
+    RPC::add_rpc_class<RpcPwmOut>();			// read,write,period,period_ms,pulsewidth,pulsewidth_ms
+//    RPC::add_rpc_class<RpcAnalogIn>();		// read,read_u16
+//    RPC::add_rpc_class<RpcAnalogOut>();		// read,write,write_u16
+//    RPC::add_rpc_class<RpcSPI>();				// format,frequency,write
+//    RPC::add_rpc_class<RpcSerial>();			// baud,readable,writeable(SPELL?),putc,getc,puts
+//    RPC::add_rpc_class<RpcTimer>();			// start,stop,reset,read,read_ms,read_us
+#endif
+
+    // http
+    HTTPServer svr;         // locate here
+    HTTPFsRequestHandler::mount("/webfs/", "/");
+    svr.addHandler<HTTPFsRequestHandler>("/");
+    svr.addHandler<HTTPRpcRequestHandler>("/rpc");
+
+    svr.start(80, &eth);
+
+//    lcd.locate(0, 1);
+//    lcd.printf("mem %d", memfree());
+		
+#ifndef USE_RPCOUT
+	led1 = 1;
+#else
+	led1.write(1);
+#endif
+
+    while (1) {
+		svr.poll();
+
+#ifndef USE_RPCOUT
+		if (sv0_val != sv0_rpc) {
+			sv0_val	= sv0_rpc;
+			// limit
+			if (sv0_val < -90.0f)
+				sv0_val	= -90.0f;
+			else if (sv0_val > 90.0f)
+				sv0_val	= 90.0f;
+
+			sv0_rpc	= sv0_val;
+			sv0.pulsewidth(deg_to_pulsewidth(sv0_val));
+
+    		lcd.locate(0, 1);
+    		lcd.printf("0:%f ", sv0_val);
+    	}
+
+		if (sv1_val != sv1_rpc) {
+			sv1_val	= sv1_rpc;
+			// limit
+			if (sv1_val < -90.0f)
+				sv1_val	= -90.0f;
+			else if (sv1_val > 90.0f)
+				sv1_val	= 90.0f;
+
+			sv1_rpc	= sv1_val;
+			sv1.pulsewidth(deg_to_pulsewidth(sv1_val));
+
+    		lcd.locate(0, 1);
+    		lcd.printf("1:%f ", sv1_val);
+    	}
+
+		if (sv2_val != sv2_rpc) {
+			sv2_val	= sv2_rpc;
+			// limit
+			if (sv2_val < -90.0f)
+				sv2_val	= -90.0f;
+			else if (sv2_val > 90.0f)
+				sv2_val	= 90.0f;
+
+			sv2_rpc	= sv2_val;
+			sv2.pulsewidth(deg_to_pulsewidth(sv2_val));
+
+    		lcd.locate(0, 1);
+    		lcd.printf("2:%f ", sv2_val);
+    	}
+#endif
+
+		wait_ms(10);
+   }
+}
+
+
+//void cam_capture(char *input, char *output)		// compile error
+void cam_cap(Arguments* input, Reply* output)
+//void cam_cap(void)
+{
+	FILE *fp_bmp;
+    unsigned int d1, d2;
+    unsigned char sort[3];
+
+#ifndef USE_RPCOUT
+	led2 = 1;
+#else
+	led2.write(1);
+#endif
+
+	cap_flag	= 0;
+
+    fp_bmp	= fopen("/webfs/cam.bmp", "wb");
+
+    /////////////////////////
+    // file header
+    /////////////////////////
+    fprintf(fp_bmp, "BM");
+    int val = 14 + 40 + SIZEX * SIZEY * 3;   // file size
+    fprintf(fp_bmp, "%c%c%c%c", val % 0x100, val / 0x100, val / 0x10000, val / 0x1000000);
+    fprintf(fp_bmp, "%c%c%c%c%c%c%c%c", 0, 0, 0, 0, 0x36, 0, 0, 0);
+
+    /////////////////////////
+    // information header
+    /////////////////////////
+    fprintf(fp_bmp, "%c%c%c%c", 0x28, 0, 0, 0);  // header size
+    fprintf(fp_bmp, "%c%c%c%c", SIZEX % 0x100, SIZEX / 0x100, SIZEX / 0x10000, SIZEX / 0x1000000);
+    fprintf(fp_bmp, "%c%c%c%c", SIZEY % 0x100, SIZEY / 0x100, SIZEY / 0x10000, SIZEY / 0x1000000);
+    fprintf(fp_bmp, "%c%c", 1, 0);               // # of plane
+    fprintf(fp_bmp, "%c%c", 24, 0);              // bit count
+    fprintf(fp_bmp, "%c%c%c%c", 0, 0, 0, 0);     // compression
+    val = SIZEX * SIZEY * 3;         // data size
+    fprintf(fp_bmp, "%c%c%c%c", val % 0x100, val / 0x100, val / 0x10000, val / 0x1000000);
+    fprintf(fp_bmp, "%c%c%c%c", 0, 0, 0, 0);
+    fprintf(fp_bmp, "%c%c%c%c", 0, 0, 0, 0);
+    fprintf(fp_bmp, "%c%c%c%c", 0, 0, 0, 0);
+    fprintf(fp_bmp, "%c%c%c%c", 0, 0, 0, 0);
+
+    camera.CaptureNext();   // sample start!
+
+    while(camera.CaptureDone() == false)
+        ;
+
+    camera.ReadStart();     // reset pointer
+
+#ifndef USE_RPCOUT
+	led3 = 1;
+#else
+	led3.write(1);
+#endif
+
+    for (int y = 0;y < SIZEY;y++) {    
+        for (int x = 0;x < SIZEX;x++) {
+            d1 = camera.ReadOneByte() ; // upper nibble is XXX , lower nibble is B
+            d2 = camera.ReadOneByte() ; // upper nibble is G   , lower nibble is R
+
+			// RGB565
+			sort[0]	= ((d1 & 0xF8) >> 3) << 3;		// R
+			sort[1] = ( ((d1 & 0x07) << 3) + ((d2 & 0xE0) >> 5) ) << 2;		// G
+			sort[2]	= (d2 & 0x1F) << 3;				// B
+
+			fprintf(fp_bmp, "%c%c%c", sort[2], sort[1], sort[0]);		// B,G,R
+        }
+    }
+
+    camera.ReadStop();
+	fclose(fp_bmp);
+
+#ifndef USE_RPCOUT
+	led2 = 0;
+	led3 = 0;
+	led4 = 0;
+#else
+	led2.write(0);
+	led3.write(0);
+	led4.write(0);
+#endif
+
+	cap_flag	= 1;
+}
+
+// end of file
diff -r 000000000000 -r 993f719c9352 mbed-rpc.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rpc.lib	Tue Aug 26 16:49:26 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed-rpc/#4490a0d9cb2a
diff -r 000000000000 -r 993f719c9352 mbed-rtos.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rtos.lib	Tue Aug 26 16:49:26 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed-rtos/#5dfe422a963d
diff -r 000000000000 -r 993f719c9352 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Tue Aug 26 16:49:26 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/8a40adfe8776
\ No newline at end of file
diff -r 000000000000 -r 993f719c9352 ov7670.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ov7670.h	Tue Aug 26 16:49:26 2014 +0000
@@ -0,0 +1,584 @@
+// This code was written by Mr.Sadaei Osakabe.
+// Original code is located at
+// https://mbed.org/users/diasea/code/OV7670_with_AL422B_Color_Size_test/
+
+#include "mbed.h"
+#include "ov7670reg.h"
+
+#define OV7670_WRITE (0x42)
+#define OV7670_READ  (0x43)
+#define OV7670_WRITEWAIT (20)
+#define OV7670_NOACK (0)
+#define OV7670_REGMAX (201)
+#define OV7670_I2CFREQ (50000)
+
+//
+// OV7670 + FIFO AL422B camera board test
+//
+class OV7670
+{
+public:
+    I2C camera;
+    InterruptIn vsync,href;
+    DigitalOut wen;
+    BusIn data;
+    DigitalOut rrst,oe,rclk;
+    volatile int LineCounter;
+    volatile int LastLines;
+    volatile bool CaptureReq;
+    volatile bool Busy;
+    volatile bool Done;
+
+    OV7670(
+        PinName sda,// Camera I2C port
+        PinName scl,// Camera I2C port
+        PinName vs, // VSYNC
+        PinName hr, // HREF
+        PinName we, // WEN
+        PinName d7, // D7
+        PinName d6, // D6
+        PinName d5, // D5
+        PinName d4, // D4
+        PinName d3, // D3
+        PinName d2, // D2
+        PinName d1, // D1
+        PinName d0, // D0
+        PinName rt, // /RRST
+        PinName o,  // /OE
+        PinName rc  // RCLK      
+        ) : camera(sda,scl),vsync(vs),href(hr),wen(we),data(d0,d1,d2,d3,d4,d5,d6,d7),rrst(rt),oe(o),rclk(rc)
+    {
+        camera.stop();
+        camera.frequency(OV7670_I2CFREQ);
+        vsync.fall(this,&OV7670::VsyncHandler);
+        href.rise(this,&OV7670::HrefHandler);
+        CaptureReq = false;
+        Busy = false;
+        Done = false;
+        LineCounter = 0;
+        rrst = 1;
+        oe = 1;
+        rclk = 1;
+        wen = 0;
+    }
+
+    // capture request
+    void CaptureNext(void)
+    {
+        CaptureReq = true;
+        Busy = true;
+    }
+    
+    // capture done? (with clear)
+    bool CaptureDone(void)
+    {
+        bool result;
+        if (Busy) {
+            result = false;
+        } else {
+            result = Done;
+            Done = false;
+        }
+        return result;
+    }
+
+    // write to camera
+    void WriteReg(int addr,int data)
+    {
+        // WRITE 0x42,ADDR,DATA
+        camera.start();
+        camera.write(OV7670_WRITE);
+        wait_us(OV7670_WRITEWAIT);
+        camera.write(addr);
+        wait_us(OV7670_WRITEWAIT);
+        camera.write(data);
+        camera.stop();
+    }
+
+    // read from camera
+    int ReadReg(int addr)
+    {
+        int data;
+
+        // WRITE 0x42,ADDR
+        camera.start();
+        camera.write(OV7670_WRITE);
+        wait_us(OV7670_WRITEWAIT);
+        camera.write(addr);
+        camera.stop();
+        wait_us(OV7670_WRITEWAIT);    
+
+        // WRITE 0x43,READ
+        camera.start();
+        camera.write(OV7670_READ);
+        wait_us(OV7670_WRITEWAIT);
+        data = camera.read(OV7670_NOACK);
+        camera.stop();
+    
+        return data;
+    }
+
+    // print register
+    void PrintRegister(void) {   
+        printf("AD : +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F");
+        for (int i=0;i<OV7670_REGMAX;i++) {
+            int data;
+            data = ReadReg(i); // READ REG
+            if ((i & 0x0F) == 0) {
+                printf("\r\n%02X : ",i);
+            }
+            printf("%02X ",data);
+        }
+        printf("\r\n");
+    }
+
+    void Reset(void) {    
+        WriteReg(REG_COM7,COM7_RESET); // RESET CAMERA
+        wait_ms(200);
+    }
+
+    void InitForFIFOWriteReset(void) {
+        WriteReg(REG_COM10, COM10_VS_NEG);
+    }
+
+    void InitSetColorbar(void)  {
+        int reg_com7 = ReadReg(REG_COM7);
+        // color bar
+        WriteReg(REG_COM17, reg_com7|COM17_CBAR);
+    }
+
+    void InitDefaultReg(void) {
+        // Gamma curve values
+        WriteReg(0x7a, 0x20);
+        WriteReg(0x7b, 0x10);
+        WriteReg(0x7c, 0x1e);
+        WriteReg(0x7d, 0x35);
+        WriteReg(0x7e, 0x5a);
+        WriteReg(0x7f, 0x69);
+        WriteReg(0x80, 0x76);
+        WriteReg(0x81, 0x80);
+        WriteReg(0x82, 0x88);
+        WriteReg(0x83, 0x8f);
+        WriteReg(0x84, 0x96);
+        WriteReg(0x85, 0xa3);
+        WriteReg(0x86, 0xaf);
+        WriteReg(0x87, 0xc4);
+        WriteReg(0x88, 0xd7);
+        WriteReg(0x89, 0xe8);
+        
+        // AGC and AEC parameters.  Note we start by disabling those features,
+        //then turn them only after tweaking the values.
+        WriteReg(REG_COM8, COM8_FASTAEC | COM8_AECSTEP | COM8_BFILT);
+        WriteReg(REG_GAIN, 0);
+        WriteReg(REG_AECH, 0);
+        WriteReg(REG_COM4, 0x40);
+        // magic reserved bit
+        WriteReg(REG_COM9, 0x18);
+        // 4x gain + magic rsvd bit
+        WriteReg(REG_BD50MAX, 0x05);
+        WriteReg(REG_BD60MAX, 0x07);
+        WriteReg(REG_AEW, 0x95);
+        WriteReg(REG_AEB, 0x33);
+        WriteReg(REG_VPT, 0xe3);
+        WriteReg(REG_HAECC1, 0x78);
+        WriteReg(REG_HAECC2, 0x68);
+        WriteReg(0xa1, 0x03);
+        // magic
+        WriteReg(REG_HAECC3, 0xd8);
+        WriteReg(REG_HAECC4, 0xd8);
+        WriteReg(REG_HAECC5, 0xf0);
+        WriteReg(REG_HAECC6, 0x90);
+        WriteReg(REG_HAECC7, 0x94);
+        WriteReg(REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC);
+        
+        // Almost all of these are magic "reserved" values.
+        WriteReg(REG_COM5, 0x61);
+        WriteReg(REG_COM6, 0x4b);
+        WriteReg(0x16, 0x02);
+        WriteReg(REG_MVFP, 0x07);
+        WriteReg(0x21, 0x02);
+        WriteReg(0x22, 0x91);
+        WriteReg(0x29, 0x07);
+        WriteReg(0x33, 0x0b);
+        WriteReg(0x35, 0x0b);
+        WriteReg(0x37, 0x1d);
+        WriteReg(0x38, 0x71);
+        WriteReg(0x39, 0x2a);
+        WriteReg(REG_COM12, 0x78);
+        WriteReg(0x4d, 0x40);
+        WriteReg(0x4e, 0x20);
+        WriteReg(REG_GFIX, 0);
+        WriteReg(0x6b, 0x0a);
+        WriteReg(0x74, 0x10);
+        WriteReg(0x8d, 0x4f);
+        WriteReg(0x8e, 0);
+        WriteReg(0x8f, 0);
+        WriteReg(0x90, 0);
+        WriteReg(0x91, 0);
+        WriteReg(0x96, 0);
+        WriteReg(0x9a, 0);
+        WriteReg(0xb0, 0x84);
+        WriteReg(0xb1, 0x0c);
+        WriteReg(0xb2, 0x0e);
+        WriteReg(0xb3, 0x82);
+        WriteReg(0xb8, 0x0a);
+        
+        // More reserved magic, some of which tweaks white balance
+        WriteReg(0x43, 0x0a);
+        WriteReg(0x44, 0xf0);
+        WriteReg(0x45, 0x34);
+        WriteReg(0x46, 0x58);
+        WriteReg(0x47, 0x28);
+        WriteReg(0x48, 0x3a);
+        WriteReg(0x59, 0x88);
+        WriteReg(0x5a, 0x88);
+        WriteReg(0x5b, 0x44);
+        WriteReg(0x5c, 0x67);
+        WriteReg(0x5d, 0x49);
+        WriteReg(0x5e, 0x0e);
+        WriteReg(0x6c, 0x0a);
+        WriteReg(0x6d, 0x55);
+        WriteReg(0x6e, 0x11);
+        WriteReg(0x6f, 0x9f);
+        // "9e for advance AWB"
+        WriteReg(0x6a, 0x40);
+        WriteReg(REG_BLUE, 0x40);
+        WriteReg(REG_RED, 0x60);
+        WriteReg(REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC|COM8_AWB);
+        
+        // Matrix coefficients
+        WriteReg(0x4f, 0x80);
+        WriteReg(0x50, 0x80);
+        WriteReg(0x51, 0);
+        WriteReg(0x52, 0x22);
+        WriteReg(0x53, 0x5e);
+        WriteReg(0x54, 0x80);
+        WriteReg(0x58, 0x9e);
+        
+        WriteReg(REG_COM16, COM16_AWBGAIN);
+        WriteReg(REG_EDGE, 0);
+        WriteReg(0x75, 0x05);
+        WriteReg(0x76, 0xe1);
+        WriteReg(0x4c, 0);
+        WriteReg(0x77, 0x01);
+        WriteReg(0x4b, 0x09);
+        WriteReg(0xc9, 0x60);
+        WriteReg(REG_COM16, 0x38);
+        WriteReg(0x56, 0x40);
+        
+        WriteReg(0x34, 0x11);
+        WriteReg(REG_COM11, COM11_EXP|COM11_HZAUTO_ON);
+        WriteReg(0xa4, 0x88);
+        WriteReg(0x96, 0);
+        WriteReg(0x97, 0x30);
+        WriteReg(0x98, 0x20);
+        WriteReg(0x99, 0x30);
+        WriteReg(0x9a, 0x84);
+        WriteReg(0x9b, 0x29);
+        WriteReg(0x9c, 0x03);
+        WriteReg(0x9d, 0x4c);
+        WriteReg(0x9e, 0x3f);
+        WriteReg(0x78, 0x04);
+        
+        // Extra-weird stuff.  Some sort of multiplexor register
+        WriteReg(0x79, 0x01);
+        WriteReg(0xc8, 0xf0);
+        WriteReg(0x79, 0x0f);
+        WriteReg(0xc8, 0x00);
+        WriteReg(0x79, 0x10);
+        WriteReg(0xc8, 0x7e);
+        WriteReg(0x79, 0x0a);
+        WriteReg(0xc8, 0x80);
+        WriteReg(0x79, 0x0b);
+        WriteReg(0xc8, 0x01);
+        WriteReg(0x79, 0x0c);
+        WriteReg(0xc8, 0x0f);
+        WriteReg(0x79, 0x0d);
+        WriteReg(0xc8, 0x20);
+        WriteReg(0x79, 0x09);
+        WriteReg(0xc8, 0x80);
+        WriteReg(0x79, 0x02);
+        WriteReg(0xc8, 0xc0);
+        WriteReg(0x79, 0x03);
+        WriteReg(0xc8, 0x40);
+        WriteReg(0x79, 0x05);
+        WriteReg(0xc8, 0x30);
+        WriteReg(0x79, 0x26);
+    }
+
+    void InitRGB444(void){
+        int reg_com7 = ReadReg(REG_COM7);
+
+        WriteReg(REG_COM7, reg_com7|COM7_RGB);
+        WriteReg(REG_RGB444, RGB444_ENABLE|RGB444_XBGR);
+        WriteReg(REG_COM15, COM15_R01FE|COM15_RGB444);
+
+        WriteReg(REG_COM1, 0x40);                          // Magic reserved bit
+        WriteReg(REG_COM9, 0x38);                          // 16x gain ceiling; 0x8 is reserved bit
+        WriteReg(0x4f, 0xb3);                              // "matrix coefficient 1"
+        WriteReg(0x50, 0xb3);                              // "matrix coefficient 2"
+        WriteReg(0x51, 0x00);                              // vb
+        WriteReg(0x52, 0x3d);                              // "matrix coefficient 4"
+        WriteReg(0x53, 0xa7);                              // "matrix coefficient 5"
+        WriteReg(0x54, 0xe4);                              // "matrix coefficient 6"
+        WriteReg(REG_COM13, COM13_GAMMA|COM13_UVSAT|0x2);  // Magic rsvd bit
+
+        WriteReg(REG_TSLB, 0x04);
+    }
+
+    void InitRGB555(void){
+        int reg_com7 = ReadReg(REG_COM7);
+
+        WriteReg(REG_COM7, reg_com7|COM7_RGB);
+        WriteReg(REG_RGB444, RGB444_DISABLE);
+        WriteReg(REG_COM15, COM15_RGB555|COM15_R00FF);
+
+        WriteReg(REG_TSLB, 0x04);
+
+        WriteReg(REG_COM1, 0x00);
+        WriteReg(REG_COM9, 0x38);      // 16x gain ceiling; 0x8 is reserved bit
+        WriteReg(0x4f, 0xb3);          // "matrix coefficient 1"
+        WriteReg(0x50, 0xb3);          // "matrix coefficient 2"
+        WriteReg(0x51, 0x00);          // vb
+        WriteReg(0x52, 0x3d);          // "matrix coefficient 4"
+        WriteReg(0x53, 0xa7);          // "matrix coefficient 5"
+        WriteReg(0x54, 0xe4);          // "matrix coefficient 6"
+        WriteReg(REG_COM13, COM13_GAMMA|COM13_UVSAT);
+    }
+
+    void InitRGB565(void){
+        int reg_com7 = ReadReg(REG_COM7);
+
+        WriteReg(REG_COM7, reg_com7|COM7_RGB);
+        WriteReg(REG_RGB444, RGB444_DISABLE);
+        WriteReg(REG_COM15, COM15_R00FF|COM15_RGB565);
+
+        WriteReg(REG_TSLB, 0x04);
+
+        WriteReg(REG_COM1, 0x00);
+        WriteReg(REG_COM9, 0x38);      // 16x gain ceiling; 0x8 is reserved bit
+        WriteReg(0x4f, 0xb3);          // "matrix coefficient 1"
+        WriteReg(0x50, 0xb3);          // "matrix coefficient 2"
+        WriteReg(0x51, 0x00);          // vb
+        WriteReg(0x52, 0x3d);          // "matrix coefficient 4"
+        WriteReg(0x53, 0xa7);          // "matrix coefficient 5"
+        WriteReg(0x54, 0xe4);          // "matrix coefficient 6"
+        WriteReg(REG_COM13, COM13_GAMMA|COM13_UVSAT);
+    }
+
+    void InitYUV(void){
+        int reg_com7 = ReadReg(REG_COM7);
+
+        WriteReg(REG_COM7, reg_com7|COM7_YUV);
+        WriteReg(REG_RGB444, RGB444_DISABLE);
+        WriteReg(REG_COM15, COM15_R00FF);
+
+        WriteReg(REG_TSLB, 0x04);
+//       WriteReg(REG_TSLB, 0x14);
+//       WriteReg(REG_MANU, 0x00);
+//       WriteReg(REG_MANV, 0x00);
+        
+        WriteReg(REG_COM1, 0x00);
+        WriteReg(REG_COM9, 0x18);     // 4x gain ceiling; 0x8 is reserved bit
+        WriteReg(0x4f, 0x80);         // "matrix coefficient 1"
+        WriteReg(0x50, 0x80);         // "matrix coefficient 2"
+        WriteReg(0x51, 0x00);         // vb
+        WriteReg(0x52, 0x22);         // "matrix coefficient 4"
+        WriteReg(0x53, 0x5e);         // "matrix coefficient 5"
+        WriteReg(0x54, 0x80);         // "matrix coefficient 6"
+        WriteReg(REG_COM13, COM13_GAMMA|COM13_UVSAT|COM13_UVSWAP);
+    }
+
+    void InitBayerRGB(void){
+        int reg_com7 = ReadReg(REG_COM7);
+
+        // odd line BGBG... even line GRGR...
+        WriteReg(REG_COM7, reg_com7|COM7_BAYER);
+        // odd line GBGB... even line RGRG...
+        //WriteReg(REG_COM7, reg_com7|COM7_PBAYER);
+
+        WriteReg(REG_RGB444, RGB444_DISABLE);
+        WriteReg(REG_COM15, COM15_R00FF);
+
+        WriteReg(REG_COM13, 0x08); /* No gamma, magic rsvd bit */
+        WriteReg(REG_COM16, 0x3d); /* Edge enhancement, denoise */
+        WriteReg(REG_REG76, 0xe1); /* Pix correction, magic rsvd */
+
+        WriteReg(REG_TSLB, 0x04);
+    }
+
+    void InitVGA(void) {
+        // VGA
+        int reg_com7 = ReadReg(REG_COM7);
+
+        WriteReg(REG_COM7,reg_com7|COM7_VGA);
+
+        WriteReg(REG_HSTART,HSTART_VGA);
+        WriteReg(REG_HSTOP,HSTOP_VGA);
+        WriteReg(REG_HREF,HREF_VGA);
+        WriteReg(REG_VSTART,VSTART_VGA);
+        WriteReg(REG_VSTOP,VSTOP_VGA);
+        WriteReg(REG_VREF,VREF_VGA);
+        WriteReg(REG_COM3, COM3_VGA);
+        WriteReg(REG_COM14, COM14_VGA);
+        WriteReg(REG_SCALING_XSC, SCALING_XSC_VGA);
+        WriteReg(REG_SCALING_YSC, SCALING_YSC_VGA);
+        WriteReg(REG_SCALING_DCWCTR, SCALING_DCWCTR_VGA);
+        WriteReg(REG_SCALING_PCLK_DIV, SCALING_PCLK_DIV_VGA);
+        WriteReg(REG_SCALING_PCLK_DELAY, SCALING_PCLK_DELAY_VGA);
+    }
+
+    void InitFIFO_2bytes_color_nealy_limit_size(void) {
+        // nealy FIFO limit 544x360
+        int reg_com7 = ReadReg(REG_COM7);
+
+        WriteReg(REG_COM7,reg_com7|COM7_VGA);
+
+        WriteReg(REG_HSTART,HSTART_VGA);
+        WriteReg(REG_HSTOP,HSTOP_VGA);
+        WriteReg(REG_HREF,HREF_VGA);
+        WriteReg(REG_VSTART,VSTART_VGA);
+        WriteReg(REG_VSTOP,VSTOP_VGA);
+        WriteReg(REG_VREF,VREF_VGA);
+        WriteReg(REG_COM3, COM3_VGA);
+        WriteReg(REG_COM14, COM14_VGA);
+        WriteReg(REG_SCALING_XSC, SCALING_XSC_VGA);
+        WriteReg(REG_SCALING_YSC, SCALING_YSC_VGA);
+        WriteReg(REG_SCALING_DCWCTR, SCALING_DCWCTR_VGA);
+        WriteReg(REG_SCALING_PCLK_DIV, SCALING_PCLK_DIV_VGA);
+        WriteReg(REG_SCALING_PCLK_DELAY, SCALING_PCLK_DELAY_VGA);
+
+        WriteReg(REG_HSTART, 0x17);
+        WriteReg(REG_HSTOP, 0x5b);
+        WriteReg(REG_VSTART, 0x12);
+        WriteReg(REG_VSTOP, 0x6c);
+    }
+
+    void InitVGA_3_4(void) {
+        // VGA 3/4 -> 480x360
+        int reg_com7 = ReadReg(REG_COM7);
+
+        WriteReg(REG_COM7,reg_com7|COM7_VGA);
+
+        WriteReg(REG_HSTART,HSTART_VGA);
+        WriteReg(REG_HSTOP,HSTOP_VGA);
+        WriteReg(REG_HREF,HREF_VGA);
+        WriteReg(REG_VSTART,VSTART_VGA);
+        WriteReg(REG_VSTOP,VSTOP_VGA);
+        WriteReg(REG_VREF,VREF_VGA);
+        WriteReg(REG_COM3, COM3_VGA);
+        WriteReg(REG_COM14, COM14_VGA);
+        WriteReg(REG_SCALING_XSC, SCALING_XSC_VGA);
+        WriteReg(REG_SCALING_YSC, SCALING_YSC_VGA);
+        WriteReg(REG_SCALING_DCWCTR, SCALING_DCWCTR_VGA);
+        WriteReg(REG_SCALING_PCLK_DIV, SCALING_PCLK_DIV_VGA);
+        WriteReg(REG_SCALING_PCLK_DELAY, SCALING_PCLK_DELAY_VGA);
+
+        WriteReg(REG_HSTART, 0x1b);
+        WriteReg(REG_HSTOP, 0x57);
+        WriteReg(REG_VSTART, 0x12);
+        WriteReg(REG_VSTOP, 0x6c);
+    }
+
+    void InitQVGA(void) {
+        // QQVGA
+        int reg_com7 = ReadReg(REG_COM7);
+        
+        WriteReg(REG_COM7,reg_com7|COM7_QVGA);
+        
+        WriteReg(REG_HSTART,HSTART_QVGA);
+        WriteReg(REG_HSTOP,HSTOP_QVGA);
+        WriteReg(REG_HREF,HREF_QVGA);
+        WriteReg(REG_VSTART,VSTART_QVGA);
+        WriteReg(REG_VSTOP,VSTOP_QVGA);
+        WriteReg(REG_VREF,VREF_QVGA);
+        WriteReg(REG_COM3, COM3_QVGA);
+        WriteReg(REG_COM14, COM14_QVGA);
+        WriteReg(REG_SCALING_XSC, SCALING_XSC_QVGA);
+        WriteReg(REG_SCALING_YSC, SCALING_YSC_QVGA);
+        WriteReg(REG_SCALING_DCWCTR, SCALING_DCWCTR_QVGA);
+        WriteReg(REG_SCALING_PCLK_DIV, SCALING_PCLK_DIV_QVGA);
+        WriteReg(REG_SCALING_PCLK_DELAY, SCALING_PCLK_DELAY_QVGA);
+    }
+
+    void InitQQVGA(void) {
+        // QQVGA
+        int reg_com7 = ReadReg(REG_COM7);
+        
+        WriteReg(REG_COM7,reg_com7|COM7_QQVGA);
+
+        WriteReg(REG_HSTART,HSTART_QQVGA);
+        WriteReg(REG_HSTOP,HSTOP_QQVGA);
+        WriteReg(REG_HREF,HREF_QQVGA);
+        WriteReg(REG_VSTART,VSTART_QQVGA);
+        WriteReg(REG_VSTOP,VSTOP_QQVGA);
+        WriteReg(REG_VREF,VREF_QQVGA);
+        WriteReg(REG_COM3, COM3_QQVGA);
+        WriteReg(REG_COM14, COM14_QQVGA);
+        WriteReg(REG_SCALING_XSC, SCALING_XSC_QQVGA);
+        WriteReg(REG_SCALING_YSC, SCALING_YSC_QQVGA);
+        WriteReg(REG_SCALING_DCWCTR, SCALING_DCWCTR_QQVGA);
+        WriteReg(REG_SCALING_PCLK_DIV, SCALING_PCLK_DIV_QQVGA);
+        WriteReg(REG_SCALING_PCLK_DELAY, SCALING_PCLK_DELAY_QQVGA);
+    }
+
+    // vsync handler
+    void VsyncHandler(void)
+    {
+        // Capture Enable
+        if (CaptureReq) {
+            wen = 1;
+            Done = false;
+            CaptureReq = false;
+        } else {
+            wen = 0;
+            if (Busy) {
+                Busy = false;
+                Done = true;
+            }
+        }
+
+        // Hline Counter
+        LastLines = LineCounter;
+        LineCounter = 0;
+    }
+    
+    // href handler
+    void HrefHandler(void)
+    {
+        LineCounter++;
+    }
+    
+    // Data Read
+    int ReadOneByte(void)
+    {
+        int result;
+        rclk = 1;
+//        wait_us(1);
+        result = data;
+        rclk = 0;
+        return result;
+    }
+    
+    // Data Start
+    void ReadStart(void)
+    {        
+        rrst = 0;
+        oe = 0;
+        wait_us(1);
+        rclk = 0;
+        wait_us(1);
+        rclk = 1;
+        wait_us(1);        
+        rrst = 1;
+    }
+    
+    // Data Stop
+    void ReadStop(void)
+    {
+        oe = 1;
+        ReadOneByte();
+        rclk = 1;
+    }
+};
+
diff -r 000000000000 -r 993f719c9352 ov7670reg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ov7670reg.h	Tue Aug 26 16:49:26 2014 +0000
@@ -0,0 +1,259 @@
+// This code was written by Mr.Sadaei Osakabe.
+// Original code is located at
+// https://mbed.org/users/diasea/code/OV7670_with_AL422B_Color_Size_test/
+
+// size register
+#define REG_COM7                    0x12    /* Control 7 */
+#define REG_HSTART                  0x17    /* Horiz start high bits */
+#define REG_HSTOP                   0x18    /* Horiz stop high bits */
+#define REG_HREF                    0x32    /* HREF pieces */
+#define REG_VSTART                  0x19    /* Vert start high bits */
+#define REG_VSTOP                   0x1a    /* Vert stop high bits */
+#define REG_VREF                    0x03    /* Pieces of GAIN, VSTART, VSTOP */
+#define REG_COM3                    0x0c    /* Control 3 */
+#define REG_COM14                   0x3e    /* Control 14 */
+#define REG_SCALING_XSC             0x70
+#define REG_SCALING_YSC             0x71
+#define REG_SCALING_DCWCTR          0x72
+#define REG_SCALING_PCLK_DIV        0x73
+#define REG_SCALING_PCLK_DELAY      0xa2
+
+// VGA setting
+#define COM7_VGA                    0x00
+#define HSTART_VGA                  0x13
+#define HSTOP_VGA                   0x01
+#define HREF_VGA                    0x36 //0xb6 0x36
+#define VSTART_VGA                  0x02
+#define VSTOP_VGA                   0x7a
+#define VREF_VGA                    0x0a
+#define COM3_VGA                    0x00
+#define COM14_VGA                   0x00
+#define SCALING_XSC_VGA             0x3a
+#define SCALING_YSC_VGA             0x35
+#define SCALING_DCWCTR_VGA          0x11
+#define SCALING_PCLK_DIV_VGA        0xf0
+#define SCALING_PCLK_DELAY_VGA      0x02
+
+// QVGA setting
+#define COM7_QVGA                   0x00
+#define HSTART_QVGA                 0x16
+#define HSTOP_QVGA                  0x04
+#define HREF_QVGA                   0x00
+#define VSTART_QVGA                 0x02
+#define VSTOP_QVGA                  0x7a
+#define VREF_QVGA                   0x0a
+#define COM3_QVGA                   0x04
+#define COM14_QVGA                  0x19
+#define SCALING_XSC_QVGA            0x3a
+#define SCALING_YSC_QVGA            0x35
+#define SCALING_DCWCTR_QVGA         0x11
+#define SCALING_PCLK_DIV_QVGA       0xf1
+#define SCALING_PCLK_DELAY_QVGA     0x02
+
+// QQVGA setting
+#define COM7_QQVGA                  0x00
+#define HSTART_QQVGA                0x16
+#define HSTOP_QQVGA                 0x04
+#define HREF_QQVGA                  0xa4  //0x24? 0xa4? 
+#define VSTART_QQVGA                0x02
+#define VSTOP_QQVGA                 0x7a
+#define VREF_QQVGA                  0x0a
+#define COM3_QQVGA                  0x04
+#define COM14_QQVGA                 0x1a
+#define SCALING_XSC_QQVGA           0x3a
+#define SCALING_YSC_QQVGA           0x35
+#define SCALING_DCWCTR_QQVGA        0x22
+#define SCALING_PCLK_DIV_QQVGA      0xf2
+#define SCALING_PCLK_DELAY_QQVGA    0x02
+
+// CIF setting no tested linux src 2.6.29-rc5 ov7670_soc.c
+#define COM7_CIF                    0x00
+#define HSTART_CIF                  0x15
+#define HSTOP_CIF                   0x0b
+#define HREF_CIF                    0xb6
+#define VSTART_CIF                  0x03
+#define VSTOP_CIF                   0x7b
+#define VREF_CIF                    0x02
+#define COM3_CIF                    0x08
+#define COM14_CIF                   0x11
+#define SCALING_XSC_CIF             0x3a
+#define SCALING_YSC_CIF             0x35
+#define SCALING_DCWCTR_CIF          0x11
+#define SCALING_PCLK_DIV_CIF        0xf1
+#define SCALING_PCLK_DELAY_CIF      0x02
+
+// QCIF setting no tested no tested linux src 2.6.29-rc5 ov7670_soc.c
+#define COM7_QCIF                   0x00
+#define HSTART_QCIF                 0x39
+#define HSTOP_QCIF                  0x03
+#define HREF_QCIF                   0x80
+#define VSTART_QCIF                 0x03
+#define VSTOP_QCIF                  0x7b
+#define VREF_QCIF                   0x02
+#define COM3_QCIF                   0x0c
+#define COM14_QCIF                  0x11
+#define SCALING_XSC_QCIF            0x3a
+#define SCALING_YSC_QCIF            0x35
+#define SCALING_DCWCTR_QCIF         0x11
+#define SCALING_PCLK_DIV_QCIF       0xf1
+#define SCALING_PCLK_DELAY_QCIF     0x52
+
+// YUV
+#define REG_COM13                   0x3d    /* Control 13 */
+#define REG_TSLB                    0x3a    /* lots of stuff */
+
+#define COM7_YUV                    0x00    /* YUV */
+#define COM13_UV                    0x00    /* U before V - w/TSLB */
+#define COM13_UVSWAP                0x01    /* V before U - w/TSLB */
+#define TSLB_VLAST                  0x00    /* YUYV  - see com13 */
+#define TSLB_ULAST                  0x00    /* YVYU  - see com13 */
+#define TSLB_YLAST                  0x08    /* UYVY or VYUY - see com13 */
+
+// RGB
+#define COM7_RGB                    0x04    /* bits 0 and 2 - RGB format */
+
+// RGB444
+#define REG_RGB444                  0x8c    /* RGB 444 control */
+#define REG_COM15                   0x40    /* Control 15 */
+
+#define RGB444_ENABLE               0x02    /* Turn on RGB444, overrides 5x5 */
+#define RGB444_XBGR                 0x00
+#define RGB444_BGRX                 0x01    /* Empty nibble at end */
+#define COM15_RGB444                0x10    /* RGB444 output */
+
+// RGB555
+#define RGB444_DISABLE              0x00    /* Turn off RGB444, overrides 5x5 */
+#define COM15_RGB555                0x30    /* RGB555 output */
+
+// RGB565
+#define COM15_RGB565                0x10    /* RGB565 output */
+
+// Bayer RGB
+#define COM7_BAYER                  0x01    /* Bayer format */
+#define COM7_PBAYER                 0x05    /* "Processed bayer" */
+
+
+// data format
+#define COM15_R10F0                 0x00    /* Data range 10 to F0 */
+#define COM15_R01FE                 0x80    /*            01 to FE */
+#define COM15_R00FF                 0xc0    /*            00 to FF */
+
+// Night mode, flicker, banding / 
+#define REG_COM11                   0x3b    /* Control 11 */
+#define COM11_NIGHT                 0x80    /* NIght mode enable */
+#define COM11_NIGHT_MIN_RATE_1_1    0x00    /* Normal mode same */
+#define COM11_NIGHT_MIN_RATE_1_2    0x20    /* Normal mode 1/2 */
+#define COM11_NIGHT_MIN_RATE_1_4    0x40    /* Normal mode 1/4 */
+#define COM11_NIGHT_MIN_RATE_1_8    0x60    /* Normal mode 1/5 */
+#define COM11_HZAUTO_ON             0x10    /* Auto detect 50/60 Hz on */
+#define COM11_HZAUTO_OFF            0x00    /* Auto detect 50/60 Hz off */
+#define COM11_60HZ                  0x00    /* Manual 60Hz select */
+#define COM11_50HZ                  0x08    /* Manual 50Hz select */
+#define COM11_EXP                   0x02
+
+#define REG_MTX1                    0x4f
+#define REG_MTX2                    0x50
+#define REG_MTX3                    0x51
+#define REG_MTX4                    0x52
+#define REG_MTX5                    0x53
+#define REG_MTX6                    0x54
+#define REG_BRIGHT                  0x55    /* Brightness */
+#define REG_CONTRAS                 0x56    /* Contrast control */
+#define REG_CONTRAS_CENTER          0x57
+#define REG_MTXS                    0x58
+#define REG_MANU                    0x67
+#define REG_MANV                    0x68
+#define REG_GFIX                    0x69    /* Fix gain control */
+#define REG_GGAIN                   0x6a
+#define REG_DBLV                    0x6b
+
+#define REG_COM9        0x14        // Control 9  - gain ceiling
+#define COM9_AGC_2X     0x00
+#define COM9_AGC_4X     0x10
+#define COM9_AGC_8X     0x20
+#define COM9_AGC_16X    0x30
+#define COM9_AGC_32X    0x40
+#define COM9_AGC_64X    0x50
+#define COM9_AGC_128X   0x60
+#define COM9_AGC_MASK   0x70
+#define COM9_FREEZE     0x01
+#define COM13_GAMMA     0x80    /* Gamma enable */
+#define COM13_UVSAT     0x40    /* UV saturation auto adjustment */
+#define REG_GAIN        0x00    /* Gain lower 8 bits (rest in vref) */
+#define REG_BLUE        0x01    /* blue gain */
+#define REG_RED         0x02    /* red gain */
+#define REG_COM1        0x04    /* Control 1 */
+#define COM1_CCIR656    0x40    /* CCIR656 enable */
+#define REG_BAVE        0x05    /* U/B Average level */
+#define REG_GbAVE       0x06    /* Y/Gb Average level */
+#define REG_AECHH       0x07    /* AEC MS 5 bits */
+#define REG_RAVE        0x08    /* V/R Average level */
+#define REG_COM2        0x09    /* Control 2 */
+#define COM2_SSLEEP     0x10    /* Soft sleep mode */
+#define REG_PID         0x0a    /* Product ID MSB */
+#define REG_VER         0x0b    /* Product ID LSB */
+#define COM3_SWAP       0x40    /* Byte swap */
+#define COM3_SCALEEN    0x08    /* Enable scaling */
+#define COM3_DCWEN      0x04    /* Enable downsamp/crop/window */
+#define REG_COM4        0x0d    /* Control 4 */
+#define REG_COM5        0x0e    /* All "reserved" */
+#define REG_COM6        0x0f    /* Control 6 */
+#define REG_AECH        0x10    /* More bits of AEC value */
+#define REG_CLKRC       0x11    /* Clocl control */
+#define CLK_EXT         0x40    /* Use external clock directly */
+#define CLK_SCALE       0x3f    /* Mask for internal clock scale */
+#define COM7_RESET      0x80    /* Register reset */
+#define COM7_FMT_MASK   0x38
+#define COM7_FMT_VGA    0x00
+#define COM7_FMT_CIF    0x20    /* CIF format */
+#define COM7_FMT_QVGA   0x10    /* QVGA format */
+#define COM7_FMT_QCIF   0x08    /* QCIF format */
+#define REG_COM8        0x13    /* Control 8 */
+#define COM8_FASTAEC    0x80    /* Enable fast AGC/AEC */
+#define COM8_AECSTEP    0x40    /* Unlimited AEC step size */
+#define COM8_BFILT      0x20    /* Band filter enable */
+#define COM8_AGC        0x04    /* Auto gain enable */
+#define COM8_AWB        0x02    /* White balance enable */
+#define COM8_AEC        0x01    /* Auto exposure enable */
+#define REG_COM9        0x14    /* Control 9  - gain ceiling */
+#define REG_COM10       0x15    /* Control 10 */
+#define COM10_HSYNC     0x40    /* HSYNC instead of HREF */
+#define COM10_PCLK_HB   0x20    /* Suppress PCLK on horiz blank */
+#define COM10_HREF_REV  0x08    /* Reverse HREF */
+#define COM10_VS_LEAD   0x04    /* VSYNC on clock leading edge */
+#define COM10_VS_NEG    0x02    /* VSYNC negative */
+#define COM10_HS_NEG    0x01    /* HSYNC negative */
+#define REG_PSHFT       0x1b    /* Pixel delay after HREF */
+#define REG_MIDH        0x1c    /* Manuf. ID high */
+#define REG_MIDL        0x1d    /* Manuf. ID low */
+#define REG_MVFP        0x1e    /* Mirror / vflip */
+#define MVFP_MIRROR     0x20    /* Mirror image */
+#define MVFP_FLIP       0x10    /* Vertical flip */
+#define REG_AEW         0x24    /* AGC upper limit */
+#define REG_AEB         0x25    /* AGC lower limit */
+#define REG_VPT         0x26    /* AGC/AEC fast mode op region */
+#define REG_HSYST       0x30    /* HSYNC rising edge delay */
+#define REG_HSYEN       0x31    /* HSYNC falling edge delay */
+#define REG_COM12       0x3c    /* Control 12 */
+#define COM12_HREF      0x80    /* HREF always */
+#define COM14_DCWEN     0x10    /* DCW/PCLK-scale enable */
+#define REG_EDGE        0x3f    /* Edge enhancement factor */
+#define REG_COM16       0x41    /* Control 16 */
+#define COM16_AWBGAIN   0x08    /* AWB gain enable */
+#define REG_COM17       0x42    /* Control 17 */
+#define COM17_AECWIN    0xc0    /* AEC window - must match COM4 */
+#define COM17_CBAR      0x08    /* DSP Color bar */
+#define REG_CMATRIX_BASE 0x4f
+#define CMATRIX_LEN         6
+#define REG_REG76       0x76    /* OV's name */
+#define R76_BLKPCOR     0x80    /* Black pixel correction enable */
+#define R76_WHTPCOR     0x40    /* White pixel correction enable */
+#define REG_HAECC1      0x9f    /* Hist AEC/AGC control 1 */
+#define REG_HAECC2      0xa0    /* Hist AEC/AGC control 2 */
+#define REG_BD50MAX     0xa5    /* 50hz banding step limit */
+#define REG_HAECC3      0xa6    /* Hist AEC/AGC control 3 */
+#define REG_HAECC4      0xa7    /* Hist AEC/AGC control 4 */
+#define REG_HAECC5      0xa8    /* Hist AEC/AGC control 5 */
+#define REG_HAECC6      0xa9    /* Hist AEC/AGC control 6 */
+#define REG_HAECC7      0xaa    /* Hist AEC/AGC control 7 */
+#define REG_BD60MAX     0xab    /* 60hz banding step limit */