OV7670カメラ　資料かき集めとポイント整理。

# OV7670カメラを液晶に動画として表示するための資料とポイント。

OV7670をマイコンで制御して、ちっこいTFT液晶に動画表示させるための資料集めと、ポイントを記録しておきます。2年ぐらいたつとほとんど忘れてしまうので。

:::note
# 概略　随時更新予定。
ざっくりした制御は、**3つの割り込み信号に同期して、垂れ流しにされてくる8ビットパラレルピクセルデータを、1バイトずつ拾って行く作業になります。**　
ピクセルデータが溜まったら、TFT液晶に行または、ページデータを転送します。次のデータが来る前に、データを液晶に、転送させます。RAMが十分大きければ、１画面全体をRAM上に展開できます。

 おおまかな流れは、これだけで、思ったほど複雑なことはしていません。

 繰り返しになりますが、基本動作は、カメラからの３つの割り込みに同期した８ビットパラレルデータを取得するだけです。

 カメラの設定項目がかなりあるので、最初は、ネット上のOV７６７０カメラのコードを参考にするのが、ベストです。

 カメラの設定は、I2C似たSCCBという通信規約で行います。PICマイコンの場合、I2CモジュールのACK確認を素通りさせるだけで、通信できます。
 
 カメラの設定と、液晶の設定を合わせること。ハードの選定と、回路をくみ上げること。地道な作業が、続きますが、一つ一つ丁寧にこなしていくことになります。
 
 ソフト開発を楽にするために、できるだけ高スペックなマイコンを選定、特に、32ビットマイコンがおすすめです。
:::


:::note
# OV7670
アリエクで２０２０年ぐらいに購入。２００円ぐらい。
<img width="350" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/169acc23-5b2e-4e74-3de0-84c7db65fae2.jpeg">
:::

:::note
# トラ技2012年３月号(amazonで新古書として購入)
<img width="200" alt="IMG_5065.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/860a900c-cd27-57e8-d181-99062d7f2e1a.jpeg">
一般に販売された唯一の解説書になるのでしょうか。
:::

:::note
# OV7670のデータシート
![OV7670.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/a048d0cb-a987-9320-9e7b-18e34c00a114.png)
:::

:::note
# **OV7670のレジスタ初期化値で参考にしたもの。**

**１．ネット上のarduinoのソースコード**
        レジスタ名もdefine定義されているので、可読性がよい。
        
**２．トラ技2012年3月号掲載P.65**
        0x01から、0xe9までのレジスタ設定値一覧。

**◆adurinoの初期化値を参考にして、移植するのがベスト。**
**◆画面の大きさは、液晶を使うならQQVGA(120×160)。**
**◆液晶は、ST7735S 1.8inch 120×160ピクセル**
**◆液晶側の初期化と、カメラの初期値を合わせる必要がある。
液晶側の初期化処理もある程度理解しておくこと。色相反転などの設定や、RGB444、RGB565などバイトの色設定もカメラと合わせる。ここがあいまいだと、カメラと液晶側の不具合切り分けができなくなる。
液晶側の設定を、カメラに対応できるよう、液晶ドライバーを先に完成させておくと楽です。**
:::

:::note
# 画面の大きさと色素ピクセル
画面の大きさは、QQVGA(120×160)、カメラのピクセルデータは、RGB565と暫定的に決めておきます。
この前提で、必要部分を探し出しながら資料を読みます。液晶表示ドライバーから先に作っておくと、楽です。
![ST7735S写真.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/efa2e742-0730-9f6a-b6e4-e6c1d6cad8a9.jpeg)

:::

:::note
# マイコンの処理速度と必要メモリ
システムクロックが最低50Mhz、DMAが搭載しているもの。180Mhz以上ならDMAを使わなくても、QQVGAに動画表示可能。
問題なく動作させたいなら、
１．システムクロック 50Mhz以上。
２．できれば、DMA転送　2つ以上搭載したマイコン。
３．28ピン以上のマイコン。もしくは、２８ピン２台で、SCCB担当と、カメラ表示担当に分ける。
４．RAMはQQVGAの場合、行データ160×2byte=320byteをバッファとして使用。一画面キャプチャーだと160×120×2=38kb必要。
動画表示だけなら、一行ずつ、TFT液晶のRAMに転送して、1画面表示できるので、さほど大きなRAMは必要としません。
  先に表示画面の大きさを決めてから、マイコンを選定するといいです。
![IMG_5054.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/13aa7020-ee82-f28b-aa10-968c53be68f3.jpeg)
今回は、PIC32MX370F512 SYSCLK=96MHz RAM=128kBで動かしました。
:::

:::note
# OV7670カメラに供給するクロック
OV7670のXCLK端子に10Mhzから24Mhzを供給します。

**１．マイコンから供給**
　システムクロックを端子から出力できるマイコンがあります。注意点は、高速になるにつれ、出力波形が崩れる可能性があります。PIC32MXには、システムクロックを端子から出力する機能があります。
 
 ※24.11.17 プルダウン抵抗をつけたら、調子が良くなって速度が安定しました。
 ※24.12.11 システムクロックを、内臓RCオシレータから、外付けセラロックにしたら安定しました。

**２．セラロックと、74HC04のクロック回路から供給。**
　この場合、マイコン端子からの供給より確実に２０Mhzくらいのクロックを正確に供給できますが、回路が増えます。28ピンマイコンで制御する場合、この方法がベスト。
 ![IMG_5055.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/93dba038-bbf3-3116-92a8-72308d9c6e12.jpeg)

:::

:::note
# OV7670 PCLKピクセルクロック
**PCLK信号** は、カメラ制御で、もっとも注視すべきクロック。このクロックスピードで、動画のfpsが決まります。
![PCLK手書き計算.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/dcfaf591-c3cd-5d8b-4d36-619946340514.png)

**DBLV(0x6B)レジスタ：PLLの倍率 Bit[7:6]**
00:BypassPLL        
01:Input clock *4
02:Input clock *6   
03:Input clock *8

**CLKRC(0x11)レジスタ:プリスケーラ値 Bit[5:0]**
クロック周波数を減速させます。

計算どうりのクロック設定になっているか、オシロでチェックすると作業が速くなります。
:::



:::note
# OV7670　SCCB通信
上記で触れた、カメラの初期化、レジスタを設定する通信規約です。I2Cとほぼ同じ動作です。

基本的に、選定したマイコンのI2Cモジュールがレジスタベースの制御で通信できているのなら、ACK返信のところをSCCB規約に変更するだけで、使用することができます。

PICマイコンの場合、I2Cモジュールのレジスタを使って、スタート、ACK確認、送信、受信、ストップを制御して通信しているコードの、ACK確認のところだけを改造するだけで、動きます。

具体的には、ACK確認のシーケンスが来たら、ACK,NACKの判定をせず、素通りさせるようにします。
```C:SCCB時のI2CモジュールACK確認
bool I2C2_Wait_Ack(bool _sccb)
{
    signed int i;
    
    if(_sccb)return true;
    
    for(i=0x7FFF; i; i--)
    {
        if(!I2C2STATbits.ACKSTAT)
            return true;
    }
    return false;
}

```



:::

:::note
# OV7670 垂直同期、水平同期、ピクセル同期
OV7670から3つの信号線が出ています。この３つの信号線と、8ビットパラレルラインがあります。

**VSYNC:垂直同期：画面同期。画面表示スタート時、Highになる信号。
HREF:水平同期：1行データ出力時、High。出力終了で、lowになる信号。
PCLK:ピクセル同期：8bitパラレルのピクセルデータがこの信号に同期して出力。**

この３つの信号線を、マイコンの３つの外部入力割り込みで補足し、8ビットデータを受信します。

先に３つの割り込み入力を作成して、物理スイッチのON,OFFでLEDを点滅させるコードを作っておきます。
３つの割り込みが正確に動作できれば、あとは、この3つの割り込みに、水平、垂直、ピクセルの３つの同期信号を割り振るだけで済みます。
![OV7670タイミングチャート.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/55d8d0b6-1d09-f281-17e4-8ed901c26063.png)

:::


:::note
# 液晶表示方法（行単位）
マイコンのシステムクロックが遅く、RAMが小さい場合に有効です。
1画面分(QQVGA120×160)をRAMに確保する場合、RAMは、38kB以上必要になります。32ビットマイコンなら、スペックとしてありますが、16ビット、8ビットマイコンで、画面をすべてを、RAMに確保することは難しいです。
なので、**1行単位で処理することになります。**

QQVGAの場合、1行データ160×2バイト(RGB565)を受信したらすぐに、液晶に行データを送信します。
SPI通信を使用して液晶にデータを送信しますが、ここでDMA転送を使用すれば、圧倒的に転送が速くなり、
次の行データの受信に間に合います。行と行のデータ受信の合間に、液晶に行を表示させるので、転送スピードが必要になってきます。この辺は、実際に回路を組んでみて、動かしながら調整することになります。

![プログラムブロック図.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/b13909d5-31a1-cd1a-058c-34167a7d1303.jpeg)


:::

:::info
# PIC32MX370F512場合の配線
![簡易配線図.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/b34b7f47-bd85-7dd9-b669-e14e7a63ece0.jpeg)
:::