トラ技 頒布カメラB(OV7670 FIFO AL422B)の動作確認

トラ技 頒布カメラB(画像メモリ搭載品)

接続

接続には、3番ピン(SCL)にプルアップ抵抗が必要。10kΩで動作した。そのほかは、直結で問題なかった。

ピント合わせ

レンズ先端が回せるようになっているので、そちらでピントを合わせることができる。 ピントを合わせた後は、ドライバでねじを固定すれば、動かない。

FIFO関連

レジスタの設定

OV7670のVSYNCとAL422のWriteReset(Active Low)が接続されているので、AL422のWriteResetを行うためにVSYNCの信号をネガティブにする必要がある。

        WriteReg(REG_COM10,0x02);

容量限界

FIFO(AL422B)は393,216Byteを搭載している。

RGB444/RGB555/RGB666フォーマットで出力した場合、1画素、2Byte使用するため、393,216 / 2 = 196,608画素まで、保存可能。

YUV422フォーマットで出力した場合、2画素、4Byte使用するため、393,216 / (4 / 2) = 196,608画素まで、保存可能(RGBフォーマットと同様の容量となる)。

VGA(640x480) = 307,200画素なので、メモリ内を読み込んでも崩れた画像が出力される。

RGB444/RGB555/RGB666/YUV422では、544x360 = 195,840画素で出力できることが確認できた。 544x360の設定は、下記の解像度の2byte 1pixelの場合のFIFOの容量限界近辺(544x360)を参照のこと。

Bayerフォーマットで出力した場合、1画素、1Byte(ただし、各画素RGBのどれか1色を保持)なので、VGA(640x480) = 307,200画素=Byte < FIFO(AL422B) 393,216Byteとなり、カメラの限界のVGA分の画素を保存できる。

データフォーマット

Linuxのov7670ドライバ及び、トラ技の2012年3月号の設定を元にしている。

定数を新たに設定/変更している部分があるので、参考のコードにそのまま追記してもコンパイルできない場合がある。

RGB444

        WriteReg(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);

取得したデータをRGB888に変換する場合。

        d1 = camera.ReadOneByte();
        d2 = camera.ReadOneByte();

        // RGB444 to RGB888
        b = (d1 & 0x0F) << 4;
        g = (d2 & 0xF0);
        r = (d2 & 0x0F) << 4;

RGB555

        WriteReg(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);

取得したデータをRGB888に変換する場合。

        d1 = camera.ReadOneByte();
        d2 = camera.ReadOneByte();

        // RGB555 to RGB888
        b = (d1 & 0x1F) << 3;
        g = (((d1 & 0xE0) >> 2) | ((d2 & 0x03) << 6));
        r = (d2 & 0x7c) << 1;

RGB565

        WriteReg(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);

取得したデータをRGB888に変換する場合。

        d1 = camera.ReadOneByte();
        d2 = camera.ReadOneByte();

        // RGB565 to RGB888
        b = (d1 & 0x1F) << 3;
        g = (((d1 & 0xE0) >> 3) | ((d2 & 0x07) << 5));
        r = (d2 & 0xF8);

YUV422

        WriteReg(REG_COM7, COM7_YUV);
        WriteReg(REG_RGB444, RGB444_DISABLE);
        WriteReg(REG_COM15, COM15_R00FF);

        WriteReg(REG_TSLB, 0x04);
//       WriteReg(REG_TSLB, 0x14); //この部分を有効にすると、UVの値を0x00固定できるので、
//       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);

取得したデータをRGB888に変換する場合。 データを確認したところ、Yのレンジは0-255までのようなので、下記の変換式を使ってRGB888に変換できた。

シフト演算と論理演算で効率化したいところだが、飽和計算のアルゴリズムが思い浮かばなかったので、非効率なままとしている。

        U0 = camera.ReadOneByte();
        Y0 = camera.ReadOneByte();
        V0 = camera.ReadOneByte();
        Y1 = camera.ReadOneByte();

        b0 = Y0 + 1.77200 * (U0 - 128);
        g0 = Y0 - 0.34414 * (U0 - 128) - 0.71414 * (V0 - 128);
        r0 = Y0 + 1.40200 * (V0 - 128);

        b1 = Y1 + 1.77200 * (U0 - 128);
        g1 = Y1 - 0.34414 * (U0 - 128) - 0.71414 * (V0 - 128);
        r1 = Y1 + 1.40200 * (V0 - 128);

        b0 = min(max(b0, 0), 255);
        g0 = min(max(g0, 0), 255);
        r0 = min(max(r0, 0), 255);

        b1 = min(max(b1, 0), 255);
        g1 = min(max(g1, 0), 255);
        r1 = min(max(r1, 0), 255);

Bayer RGB

        int reg_com7 = ReadReg(REG_COM7);

        WriteReg(REG_COM7, reg_com7|COM7_PBAYER);
        WriteReg(REG_RGB444, RGB444_DISABLE);
        WriteReg(REG_COM15, COM15_R00FF);

        WriteReg(REG_TSLB, 0x04);

        WriteReg(REG_COM13, 0x08); /* No gamma, magic rsvd bit */
        WriteReg(REG_COM16, 0x3d); /* Edge enhancement, denoise */
        WriteReg(REG_REG76, 0xe1); /* Pix correction, magic rsvd */

取得したデータをRGB888に変換する場合。 アド・サイエンス: ベイヤーパターンカメラとは? RGBカラー画像への変換方法というページを参考にして、変換を行った。

                unsigned char *bayer_line[2];      //操作行列を入れ替えるためのポインタ
                unsigned char *bayer_line_data[2]; //画像1行分のRGB情報を格納する2行分
                for(int i=0; i<2; i++) {
                    if((bayer_line_data[i] = (unsigned char *)malloc(sizeof(unsigned char)*sizex)) == NULL){
                       fprintf(stderr, "Error: Allocation error.\n");
                       return 1;
                    }
                }
                
                // 1行目の処理
                for (int x=0; x<sizex; x++) {
                    // odd line GBGB... even line RGRG...
                    bayer_line_data[0][x] = (unsigned char)camera.ReadOneByte();
                }
                bayer_line[1] = bayer_line_data[0];

                // 2行目以降の処理
                for (int y=1; y<sizey; y++) {
                    int line = y%2;

                    for (int x=0; x<sizex; x++) {
                        // odd line GBGB... even line RGRG...
                        bayer_line_data[line][x] = (unsigned char)camera.ReadOneByte();
                    }

                    // 操作行列のindex入れ替え
                    bayer_line[0] = bayer_line[1];
                    bayer_line[1] = bayer_line_data[line];

                    for (int x=0; x<sizex - 1; x++) {
                        if(y%2==1) {
                            if(x%2==0) {
                                // GB
                                // RG
                                b = bayer_line[0][x+1];
                                g = ((int)bayer_line[0][x] + bayer_line[1][x+1])>>1;
                                r = bayer_line[1][x];
                            } else {
                                // BG
                                // GR
                                b = bayer_line[0][x];
                                g = ((int)bayer_line[0][x+1] + bayer_line[1][x])>>1;
                                r = bayer_line[1][x+1];
                            }
                        } else {
                            if(x%2==0) {
                                // RG
                                // GB
                                b = bayer_line[1][x+1];
                                g = ((int)bayer_line[0][x+1] + bayer_line[1][x])>>1;
                                r = bayer_line[0][x];
                            } else {
                                // GR
                                // BG
                                b = bayer_line[1][x];
                                g = ((int)bayer_line[0][x] + bayer_line[1][x+1])>>1;
                                r = bayer_line[0][x+1];
                            }
                        }
                    }
                }

生成したbitmapファイルBayer VGAトラ技の表紙とワイヤーストリッパーを映してみた。

また、Bayerフォーマットの場合、QVGA、QQVGAの設定だと、正常に画像出力できなかった。

原因は不明。

解像度

Linuxのov7670ドライバ及び、トラ技の2012年3月号の設定を元にしている。

定数を新たに設定/変更している部分があるので、参考のコードにそのまま追記してもコンパイルできない場合がある。

トラ技の設定は、すべてREG_HREFでエッジオフセット設定されているが、設定しないことでTSLBで、ネガポジ反転しなくても良くなった。 QQVGAは、エッジオフセット設定を残したままにしている。

VGA(640x480)

※FIFOの容量の関係で、Bayerフォーマット指定時のみ、画像取得できる。

        WriteReg(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);

2Byte 1pixelの場合のFIFOの容量限界近辺のサイズ(544x360)

        WriteReg(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);

(HREF, VREFの設定も厳密にした方が良いかもしれない。)

VGAの4分の3サイズ(480x360)

        WriteReg(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);

QVGA

        WriteReg(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);

QQVGA

        WriteReg(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);

デフォルト設定

Linuxドライバのデフォルト設定から、不都合なものを除外した設定。

        // 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);

定数表

// 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
#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

// 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 */

bitmapファイル

実際にmbed内でbitmapファイル化した画像データ集

上記の設定の組み合わせて、トラ技の2012年3月号の表紙を保存してみた。

RGB444 2Byte 1pixelの場合のFIFOの容量限界近辺のサイズ(544x360)

RGB444 VGAの4分の3サイズ(480x360)

RGB444 QVGA

RGB444 QQVGA

RGB555 2Byte 1pixelの場合のFIFOの容量限界近辺のサイズ(544x360)

RGB555 VGAの4分の3サイズ(480x360)

RGB555 QVGA

RGB555 QQVGA

RGB565 2Byte 1pixelの場合のFIFOの容量限界近辺のサイズ(544x360)

RGB565 VGAの4分の3サイズ(480x360)

RGB565 QVGA

RGB565 QQVGA

YUV422 2Byte 1pixelの場合のFIFOの容量限界近辺のサイズ(544x360)

YUV422 VGAの4分の3サイズ(480x360)

YUV422 QVGA

YUV422 QQVGA

検証に使用したコードはこちら。

Import programOV7670_with_AL422B_Color_Size_test

OV7670_with_AL422B Color & Size Test Program

参考

OV7670_with_AL422B_test

Import programOV7670_with_AL422B_QQVGA_test

OV7670 with FIFO AL422B (TORAGI Camera TYPE B) test program

OV7670+FIFOカメラモジュール(SCCBインタフェース)

HR2_blog: mbedでトラ技3月号の頒布カメラBを使う

Robot No.8080のブログ: mbed + トラ技カメラBの実験。(その1)

MIBC備忘録: OV7670 + FIFOカメラ

チョコっとカメラ奮闘記

FPGAの部屋: Spartan-3A Starter KitでCMOSカメラ・ディスプレイ回路

FPGAの部屋: YUV-RGB変換1(方式の検討)

諏訪工房: ネットワークカメラの製作

Bitmapファイルを入出力してみる


2 comments on トラ技 頒布カメラB(OV7670 FIFO AL422B)の動作確認:

06 Apr 2017

何のマイコンを利用している?

27 Dec 2017

Cristian Fuentes wrote:

何のマイコンを利用している?

返信が遅くてすみません。mbed LPC1768を使用しています。

Please log in to post comments.