作者:鄒南,華清遠見嵌入式學院講師。
CAMERA SENSOR
OV9650/9655是CMOS接口的圖像傳感器芯片,可以感知外部的視覺信號並將其轉換為數字信號並輸出。通過下面的框圖可以清晰的看到它的工作原理:
我們需要通過XVCLK1給攝像頭提供時鍾,RESET是復位線,PWDN在攝像頭工作時應該始終為低。HREF是行參考信號,PCLK是像素時鍾,VSYNC是場同步信號。一旦給攝像頭提供了時鍾,並且復位攝像頭,攝像頭就開始工作了,通過HREF,PCLK和VSYNC同步傳輸數字圖像信號。數據是通過D0~D7這八根數據線並行送出的。
OV9650向外傳輸的圖像格式是YUV的格式 ,YUV是一種壓縮后的圖像數據格式,它里面還包含很多具體的格式類型,我們的攝像頭對應的是YCbCr(8 bits, 4:2:2, Interpolated color).一定要搞清楚格式,后面的驅動里面設置的格式一定要和這個格式一致。
OV9650里面有很多寄存器需要配置,配置這些寄存器就需要通過芯片里面的SCCB總線去配置。SCCB其實是一種弱化的I2C總線。我們可以直接把攝像頭接在S5PC100的I2C控制器上,利用I2C總線去讀寫寄存器,當然直接使用GPIO模擬I2C也可以實現讀寫。
從OV9650采集過來的數據沒法直接交給CPU處理。S5PC100芯片里面集成了Camera控制器,叫FIMC(Fully Interactive Mobile Camera)。攝像頭需要先把圖像數據傳給控制器,經過控制器處理(裁剪拉升后直接預覽或者編碼)之后交給CPU處理。
實際上攝像頭工作需要的時鍾也是FIMC給它提供的。
Sccb協議簡介
SCCB(Serial Camera Control Bus)是和I2C類似的一個協議。 SIO_C和SIO_D分別為SCCB總線的時鍾線和數據線。
從設備地址(ID Address,8bit),分為讀地址和寫地址,高7位用於選中芯片, 第0位是讀/寫控制位(R/W),決定是對該芯片進行讀或寫操作;
內部寄存器單元地址(Sub_ Address,8bit),用於決定對內部的哪個寄存器單元進行操作,通常還支持地址單元連續的多字節順序讀寫操作。SCCB控制總線功能的實現完全是依靠SIO_C、SIO_D兩條總線上電平的狀態以及兩者之間的相互配合實現的。SCCB總線傳輸的啟動和停止條件如圖
過程:采用簡單的三相(Phase)寫數據的方式,即在寫寄存器的過程中先發送OV7650的ID地址(ID Address),然后發送寫數據的目地寄存器地址(Sub_address),最后發送要寫入的數據(Write Data)。如果給連續的寄存器寫數據,寫完一個寄存器后,OV7650會自動把寄存器地址加1,程序可繼續向下寫,而不需要再次輸入ID地址,從而三相寫數據變為了兩相寫數據,由於本系統只需對有限個不連續寄存器進行配置,如果采用對全部寄存器都加以配置這一方法的話,會浪費很多時間和資源,所以我們只對需要更改數據的寄存器進行寫數據。對於每一個需更改的寄存器,都采用三相寫數據的方法。
OV9650是OmniVision公司的COMS攝像頭,130萬像素,支持SXVGA、VGA、QVGA、CIF等圖像輸出格式。 最大速率在SXVGA時為15fps,在VGA時為30fps。
OV9650攝像頭時序如下圖:
在獲得攝像頭ID號后說明sccb通信方式已經正常運行,就可以對內部的控制寄存器進行配置,主要的內部控制其有:
時鍾預分頻寄存器:
圖像緩沖區格式設置寄存器:
增益控制寄存器:
輸出模式設置寄存器
配置完成后,在camera模塊數據線上就應該有數據傳輸出來。然后配置主機中camera控制器進行數據的接收和轉換。
CAMIF
該套架構專為攝像頭而設計,如下羅列相應的功能以及接口。分析FIMC需要從兩方面出發,第一是CAMIF端,第二是傳感器端,下面逐一分析。
CAMERA DISCRIBE:
● Camera interface
Mutiple input support
● ITU-R BT 601/656 mode
◆ DMA(axi 64bits interface) mode
◆ MIPI(CSI) mode
Mutiple output support
● DMA(axi 64bits interface)
● Direct FIFIO mode
● Digital Zoom in capability
● 可編程視屏同步信號極性
● 支持最大64M像素輸入
● 圖像鏡像以及旋轉支持
● 多樣式圖像的處理
● 捕捉圖像以及通用處理能力
CRAMERA ARCHITECTURAL
1、可同時支持兩個攝像頭傳感器
2、且3路CRAMIF 可同時操作兩個攝像頭傳感器
3、CRAMIFn有自己的本地管道通向FIMD
4、CRAMIFn有私屬的AXI總線讀寫通道
下圖給出了各個camif 的屬性。
下面來看看如何配置時鍾:
圖一
圖二
圖三
簡單分析下,FIMC由4路時鍾構成,CAM_SCLK如圖二所示,xci_pclk由攝像頭傳感器內部分頻后得到,輸出返回至CAMIF。
BUS_CLOCK&CORE_CLOCK可選擇APLL,MPLL,HPLL,EPLL輸入。注意core clock 最大值是133Mhz , CAM_MCLK最大是83Mhz,XciPCLK最大值也是83Mhz 。
在測試中,筆者選擇了MPLL這一路,最后經過分頻后得到16.7Mhz的BUS/CORE_CLOCK。
知道時鍾后,我們可以看看camif的時序部分:
從s5pc100的用戶手冊中看到這兩幅圖,清楚的表現了camif timing 。一個垂直同步信號下,會引發一個HREF信號,它是一個水平相關信號,在一個HREF周期中,會發生一次數據傳輸。這一點基本和lcd的控制器時序是類似的。
program flow
(1,Reg .register)
配置camera source format Reg 需要填寫采集的數據圖像的大小。這里我們采用的是800x480,其中800是srcHsize ,480是srcVsize。
● 配置 camera window offset Reg 該寄存器主要指定了需要對采集到的源圖像的剪裁所需的各個偏移值。
● 配置全局控制寄存器 camera control Reg 該寄存器有很重要的兩個bits,一個是控制器的復位,一個是攝像頭傳感器chip的復位。並且還需要填寫掃描方式1,隔行掃描或者逐行掃描。
● 配置Output DMA 的 start address Reg 注意,一共有4個frame,全配上的話會使得圖像輸刷新更快,圖像顯示更流暢。
● 配置Target Format Reg , 該寄存器主要是對圖像的旋轉以及目標尺寸的設置。
● 對Pre-Scaler control Reg 1的配置主要是設置scaler。具體需要看公式:
if(SrcXSize>=64*DstXSize)
error;
else if(SrcXSize>=32*DstXSize) {
X_ratio=32;
X_shift=5;
}
else if(SrcXSize>=16*DstXSize) {
X_ratio=16;
X_shift=4;
}
else if(SrcXSize>=8*DstXSize) {
X_ratio=8;
X_shift=3;
}
else if(SrcXSize>=4*DstXSize) {
X_ratio=4;
X_shift=2;
}
else if(SrcXSize>=2*DstXSize) {
X_ratio=2;
X_shift=1;
}
else {
X_ratio=1;
X_shift=0;
}
PreDstXsize = SRC_Xsize / PreXRatio ;
MainXratio = (SRC_Xsize<<8)/(DST_Xsize<<X_Shift)
SHfactor = 10-(H_Shift + X_Shift);
X={v,h}; v=vertical h=height;
● 對main-scaler control Reg的配置。需要選擇LCD的輸入路徑。並且還有scaler的起始位。
● 配置output DMA offset Reg的設置,它決定了你輸出圖像的整體偏移量
● 使能 capture enable Reg ,使能捕捉。
按照以上步驟,就可以簡單的輸出圖像了。注意測試的方案為:camif的數據讀取地址與lcd的framebuffer一致,這樣攝像頭采集到的圖像可以第一時間被lcd捕獲並顯示。注意攝像頭采集不能通過local fifo給顯示設備。
問題與總結:
1、在整個移植過程中會遇到各種各樣的未知問題。通過不斷地測試與推敲后,最終成功。下面是一些遇到的問題和解決方案:
2、如果無法讀取到傳感器的product id 以及manufacture id ,則可能是sccb的限時不夠或者達不到要求。也有可能是沒有進行軟復位,這一點要非常注意,在模擬i2c協議時,這一點尤為重要。
3、如果傳感器不輸出數據,則代表camif的配置還有問題,主要要看時序是否正確,還有是否使能了capture 信號角,main-scaler start bit;
4、如果有數據了,但是顯示出來的卻不清楚,或者花瓶的話,那恭喜你,你離成功快近了,但是要做好連續奮戰幾天的准備。因為這個問題就是一個字,實驗。最后的問題就是輸入的圖像像素以及scaler公式配置不正確,導致輸出的像素不正確。這樣就不會輸出正確的圖像。
(筆者的實驗數據是src/800*480 target/640*320)
內核相關的一些總結
由於在整個移植過程中,我們都參考的是Android 2.6.29內核,現在講下一些移植的經驗。
在linux下,相關的目錄
FIMC: ~\drivers\media\video\samsung\fimc
FIMD: ~\drivers\video\samsung
這兩個是核心目錄,包含了所有FIMC/D體系的代碼,只是與內核關聯的部分涉及到了I2C子系統,平台設備驅動,以及v4l2視頻編程接口,推薦看資料《FS_S5PC100平台上Linux Camera驅動開發詳解》。