GC0328C移植指南

摄像头,Ov7670,GalaxyCoreInc

Views:  times Updated on June 13, 2023 Posted by elmagnifico on June 1, 2023

Foreword

Ov7670由于都是拆机货,质量太差了,所以找了个替换,GC0328C,不过GC0328C的资料比较少,很多地方没解释清楚,现成代码注释写的很少,大部分都要自己重新对一遍寄存器

GC0328C

参考仓库

https://github.com/RT-Thread-Studio/sdk-bsp-stm32h750-realthread-artpi/blob/master/libraries/drivers/include/drv_gc0328c.h

https://github.com/fukuen/Maixduino_GC0328/tree/master

https://github.com/Hengbote/RT-Thread_GC0308

可以参考的板子比较多,ART-Pi,MaixPy,K210,MT62xx,MT65xx,SC6531,SP7731

多数资料里都有一个类似的图

image-20230601101313100

寄存器

GC0328C的寄存器比较复杂,比较多,所以他用了一个切页的方式来切换寄存器映射

image-20230601101440403

所以可以看到手册里P0:xxx P1:xxx 就是不同页的寄存器

读取和写入的时候都需要注意当前是哪一页

地址

一般GC0328地址有2种,一个是0x21,一个是0x42,其实都指同一个

21是主地址,42是加了写偏移的,43是读偏移后的地址

时钟

Timing 这里比较复杂,基本都是参考别人的设置

image-20230601155001432

image-20230601155109395

总结一下需要注意P0:05-08和P0:0f-13

image-20230607154828939

输出极性

image-20230601114313171

输出极性,需要和配置的DMA或者DCMI,CSI等匹配上

HSYNC和VSYNC,一般设置的极性都是1有效

{0x46 , 0x03}, // SYNC_mode

在ST中这个极性和DCMI的极性设置是反过来的,需要注意一下

帧率控制

帧率主要是通过曝光时间来控制

image-20230601102705640

const rt_uint8_t gc0328c_10pfs_talbe[][2] =
{
    // all AEC_EXP_LEVEL_X set to 0x51e = 1310
    {0xFE,0x01},  // page p1

    {0x2B,0x05},  // AEC_EXP_LEVEL_0 [11:8]
    {0x2C,0x1e},  // AEC_EXP_LEVEL_0 [7:0]

    {0x2D,0x05},  // AEC_EXP_LEVEL_1
    {0x2E,0x1e},

    {0x2F,0x05},  // AEC_EXP_LEVEL_2
    {0x30,0x1e},

    {0x31,0x05},  // AEC_EXP_LEVEL_3
    {0x32,0x1e},

    //{0x33,0x25},  // // AEC_EXP_MIN
    //{0x34,0x1e},
};

至于为什么1310就是10fps,暂时我也不知道,但是基于此可以调整为20fps或者5fps

目前实测如果这里填的是512,fps大概是29-30

这里就具体计算和原因没有任何说明,只能用现有代码反推了

输出格式

image-20230601111252245

输出格式主要是0x44控制,一般用的多的就是RGB565和YUV422,YUV其实就是Y Cb Y Cr

YUV444,每个分量都一样,所以没啥可说的
YUV422,实际数据返回是YUYV,两个Y分别代表了2个像素,但是他们共用了一组U和V,这种方式减少了数据量,但是会有一点点失真
YUV420,实际数据返回是YYYY...uvuvuvuv,16个Y分别代表了4个像素,但是他们共用了一组U和V,这种方式减少了数据量,失真比较厉害

还有一些其他变体

UYVY 这种等于YUYV422的变体形式
VYUY 这种等于YUYV422的变体形式
YVYU 这种等于YUYV422的变体形式

在这里YUYV 422,他们实际是用了4字节,每个量1字节,如果隔列获取的话,那么最后拿到的就全是YYYYY,直接把UV都去掉了。

如果全取就是YUYV的字节顺序

如果是RGB565,实际上是指5bitR,6bitG,5bitB,一共还是2字节的数据

同时还会选择average neighbor chroma,会取平均色度

下面代码则是使用YUYV进行输出,并且取平均色度

{0x44 , 0x22}, // output format YUYV

输出分辨率

分辨率控制,主要是通过三个东西控制,window、crop、subsample,都会影响到最终的分辨率

Window

image-20230601103505794

前面是设置行列数据的开始是什么

后面就是摄像头采样的窗口大小,下面代码中设置的大小就是0x1E8,0x288转换过来就是488x648,就是GC0328的像素矩阵大小

这个是由于Timing环节规定的,这个宽度一定是目标宽度+8

Crop

image-20230601103255712

0x50控制的是否对窗口进行剪裁,默认0就是不剪裁,1是剪裁

x1和y1是指像素的剪裁起始点,后面的宽高则是剪裁大小,下面代码中的0x78,0xA0对应的就是120x160刚好是qqvga的大小

subsample

image-20230601103341690

下采样模式,0x59控制下采样率,1/x,这个值越大,采样越少,代码中就是0x44,下采样就是1/4,默认值是1/1就是全采,对应的就是分辨率是最大值的几分之几。qqvga就是最大的1/4,如果是qvga则是1/2

0x5a,这个应该是采样方法,只是不知道具体是指什么

static const uint8_t qqvga_regs[][2] = {
    {0xfe , 0x00}, // page 0
    // window
    //windowing mode
    {0x09 , 0x00}, // Row start high
    {0x0a , 0x00}, // Row start low
    {0x0b , 0x00}, // Col start high
    {0x0c , 0x00}, // Col start low
    {0x0d , 0x01}, // Window height high
    {0x0e , 0xe8}, // Window height low
    {0x0f , 0x02}, // Window width high
    {0x10 , 0x88}, // Window width low
    //crop mode 
    {0x50 , 0x01}, // crop window mode enable
    {0x51 , 0x00}, // Crop _win_y1[9:8]
    {0x52 , 0x00}, // Crop _win_y1[7:0]
    {0x53 , 0x00}, // Crop _win_x1[10:8]
    {0x54 , 0x00}, // Crop _win_x1[7:0]
    {0x55 , 0x00}, // Crop _win_height[8]
    {0x56 , 0x78}, // Crop _win_height[7:0]
    {0x57 , 0x00}, // Crop _win_width[9:8]
    {0x58 , 0xA0}, // Crop _win_width[7:0]
    //subsample 1/4
    {0x59 , 0x44}, // subsample
    {0x5a , 0x03}, // Sub mode
    {0x5b , 0x00}, // Sub_row_N1
    {0x5c , 0x00}, // Sub_row_N2
    {0x5d , 0x00}, // Sub_row_N3
    {0x5e , 0x00}, // Sub_row_N4
    {0x5f , 0x00}, // Sub_col_N1
    {0x60 , 0x00}, // Sub_col_N2
    {0x61 , 0x00}, // Sub_col_N3
    {0x62 , 0x00}, // Sub_col_N4
          
    {0x00 , 0x00}
};

摄像头常用参数

翻转、镜像

image-20230607152511747

画面的调整可以通过这里P0:0x17,既能镜像也能上下翻转

饱和度、对比度

image-20230606160316841

一般来说饱和度通过调整d0、d1、d2

对比度通过d3、d4进行调整,唯一的问题是不知道这里的数值含义是什么

Auto Grey

image-20230606152603304

Auto Grey,自动灰度,不知道具体什么意思,起什么作用

ABS AWB

image-20230606152644283

ABS,不知道

AWB,自动白平衡,简单说就是纠正背景的白光可能偏黄或者偏绿

白平衡的白点设置

image-20230607151543752

如果关闭了白平衡,需要通过下面的设置来控制

image-20230607151813817

image-20230606152820268

AEC,自动曝光控制

image-20230607150856223

可以通过P1的2d-32 修改曝光时间,单位是us

ASDE

ASDE,auto saturation de-noise and edge enhancement,自饱和去噪与边缘增强,

image-20230606155637234

DNDD

不明

Gamma

image-20230612101330670

通过这里设置RGB的Gamma值

    // largest gamma curve
    {0xfe , 0x00},
    {0xBF , 0x14},
    {0xc0 , 0x28},
    {0xc1 , 0x44},
    {0xc2 , 0x5D},
    {0xc3 , 0x72},
    {0xc4 , 0x86},
    {0xc5 , 0x95},
    {0xc6 , 0xB1},
    {0xc7 , 0xC6},
    {0xc8 , 0xD5},
    {0xc9 , 0xE1},
    {0xcA , 0xEA},
    {0xcB , 0xF1},
    {0xcC , 0xF5},
    {0xcD , 0xFB},
    {0xcE , 0xFE},
    {0xcF , 0xFF},

image-20230612101720559

这里影响到亮度Y的Gama曲线

    {0xfe , 0x00},
    {0x63 , 0x00},
    {0x64 , 0x10},
    {0x65 , 0x1c},
    {0x66 , 0x30},
    {0x67 , 0x43},
    {0x68 , 0x54},
    {0x69 , 0x65},
    {0x6a , 0x75},
    {0x6b , 0x93},
    {0x6c , 0xb0},
    {0x6d , 0xcb},
    {0x6e , 0xe6},
    {0x6f , 0xff},

意外bug

K210代码里有这么个结构,然后实际上宏定义不能这样用

enum
{
    GC0328_RGB_Gamma_m0 = 0,
    GC0328_RGB_Gamma_m1,
    GC0328_RGB_Gamma_m2,
    GC0328_RGB_Gamma_m3,
    GC0328_RGB_Gamma_m4,
    GC0328_RGB_Gamma_m5,
    GC0328_RGB_Gamma_m6,
    GC0328_RGB_Gamma_night,
	GC0328_RGB_Gamma_cap,
	GC0328_RGB_Gamma_test
};

#define GC0328_RGB_Gamma GC0328_RGB_Gamma_test

这样定义出来的宏,在后续使用的时候无法确定具体宏的数值,所以宏判等等情况都会失败

#if (GC0328_Y_Gamma == GC0328_Y_Gamma_05)
    //0.5
    {0xfe , 0x00}, //select page0
    {0x63 , 0x00}, // Y Gamma 0
    {0x64 , 0x49}, // Y Gamma 1
    {0x65 , 0x68}, // Y Gamma 2
    {0x66 , 0x80}, // ...
#elif (GC0328_Y_Gamma == GC0328_Y_Gamma_06)
    //0.5
    {0xfe , 0x00}, //select page0
    {0x63 , 0x00}, // Y Gamma 0
    {0x64 , 0x49}, // Y Gamma 1
    {0x65 , 0x68}, // Y Gamma 2
    {0x66 , 0x80}, // ...

Summary

移植驱动主要就注意这几点,剩下大量的寄存器配置都是未知的,只能照搬

Quote

https://club.rt-thread.org/ask/question/7e46e3d50a1b6ab5.html

https://github.com/RT-Thread-Studio/sdk-bsp-stm32h750-realthread-artpi/blob/master/libraries/drivers/include/drv_gc0328c.h

https://github.com/fukuen/Maixduino_GC0328/tree/master

https://github.com/Hengbote/RT-Thread_GC0308

https://blog.csdn.net/rjszcb/article/details/118728264