Zybo Z7-20 への Raspberry Pi Camera V2(Sony IMX219)の接続を挑戦中なので記録を残しておきます。
最終目標は Zybo での 960fps (640×120) の高速度撮影ですが、今回はとりあえず普通に絵が取れるかどうかのアタリ実験までです。高速撮影時も画素数が減るだけで、物理層の速度は912Mbpsで変わらないので、物理層の実験にはなるはずです。まずはRaspberryPiで動いている手堅いパラメータで動作確認を行いました。
どうやら Zybo Z7 の MIPI CSI-2 のコネクタと、手元にある Raspberry Pi3 のコネクタは、物理形状もピン配置も互換のようですので、基本的にはソフトとRTLを何とかすれば受信できるはずです。
今回は基本的には現物主義のアプローチでRaspberry Pi3 に繋いだときのSCL/SDAのI2Cアクセスをロジアナで読んでコピーするというところと、 Xilinx の標準コアであるMIPI D-PHY コアを使えば、とりあえず何らかの信号が出てくるのでそこから適当に画像らしい部分を拾うというアプローチです。
ただし、調べればいろいろ既に先駆者の情報がいろいろあります。
Raspberry Pi V2 Camera の情報については RaspberryPi のフォーラムから、手繰ると回路解析やデータシートなどの情報があるようです。
MIPI CSI-2関連も正式な仕様書は手に入りませんが、Googleで検索するとドラフト時の資料とか多少出てくるようなので、手がかりにはなりそうです。
以前HDMIのRX作ったときと同様に、今回も規格に準拠したものを作ろうというのではなく、趣味で遊べる程度に映像が取り出せればOKというスタンスで解析していきます。
はじめに Raspberry Pi3 にカメラを繋いでまずは動かします。こちらのサイトを参考にしました。
絵が出たのが確認できたらすかさず、カメラモジュールの端子をロジアナに繋いで解析します。
ここは手抜きで、カプトンテープで軽く保護だけしてコネクタの隙間にピンをねじ込みました(乱暴)。
意外と何とかなるものです。
ZEROPLUSのI2Cプロトコルアナライザが大活躍です。
で、raspstill コマンド実行時のI2Cのアクセス内容が以下の通り。
—————–
r 0000 -> 02 19 ; MODEL_ID r 0002 -> 20 ; ???? r 0003 -> 00 ; ???? w 0102 <- 01 ; ???? (Reserved) w NULL w 0100 <- 00 ; mode_select [4:0] (0: SW standby, 1: Streaming) w 6620 <- 01 01 ; ???? w 6622 <- 01 01 w 30EB <- 0C ; Access command sequence Seq.(データシートと違う?) w 30EB <- 05 w 300A <- FF FF w 30EB <- 05 w 30EB <- 09 w 0114 <- 01 ; CSI_LANE_MODE (03: 4Lane 01: 2Lane) w 0128 <- 00 ; DPHY_CTRL (MIPI Global timing setting 0: auto mode, 1: manual mode) w 012a <- 18 00 ; INCK frequency [MHz] 6,144MHz w 0157 <- 00 ; ANA_GAIN_GLOBAL_A w 015A <- 09 BD ; COARSE_INTEGRATION_TIME_A w 0160 <- 03 72 ; FRM_LENGTH_A w 0162 <- 0D 78 ; LINE_LENGTH_A (line_length_pck Units: Pixels) w 0164 <- 00 00 ; X_ADD_STA_A x_addr_start X-address of the top left corner of the visible pixel data Units: Pixels w 0166 <- 0C CF ; X_ADD_END_A w 0168 <- 00 00 ; Y_ADD_STA_A w 016A <- 09 9F ; Y_ADD_END_A w 016C <- 06 68 ; x_output_size w 016E <- 04 D0 ; y_output_size w 0170 <- 01 01 ; X_ODD_INC_A Increment for odd pixels 1, 3 w 0174 <- 01 01 ; BINNING_MODE_H_A 0: no-binning, 1: x2-binning, 2: x4-binning, 3: x2-analog (special) binning w 018C <- 0A 0A ; CSI_DATA_FORMAT_A CSI-2 data format w 0301 <- 05 ; VTPXCK_DIV Video Timing Pixel Clock Divider Value w 0303 <- 01 03 ; VTSYCK_DIV PREPLLCK_VT_DIV(3: EXCK_FREQ 24 MHz to 27 MHz) w 0305 <- 03 00 ; PREPLLCK_OP_DIV(3: EXCK_FREQ 24 MHz to 27 MHz) / PLL_VT_MPY 区切りがおかしい次に続く w 0307 <- 39 ; PLL_VT_MPY w 0309 <- 0A ; OPPXCK_DIV w 030B <- 01 00 ; OPSYCK_DIV PLL_OP_MPY[10:8] / 区切りがおかしい次に続く w 030D <- 72 ; PLL_OP_MPY[10:8] w 455E <- 00 ; w 471E <- 4B ; w 4767 <- 0F ; w 4750 <- 14 ; w 4540 <- 00 ; w 47B4 <- 14 ; w 4713 <- 30 ; w 478B <- 10 ; w 478F <- 10 ; w 4793 <- 10 ; w 4797 <- 0E ; w 479B <- 0E ; w 0172 <- 03 ; IMG_ORIENTATION_A w 0160 <- 06 E3 ; FRM_LENGTH_A[15:8] w 0162 <- 0D 78 ; LINE_LENGTH_A w 015A <- 04 22 ; COARSE_INTEGRATION_TIME_A w 0157 <- 00 ; ANA_GAIN_GLOBAL_A w 0157 <- 00 ; ANA_GAIN_GLOBAL_A w 0160 <- 06 E3 ; FRM_LENGTH_A w 0162 <- 0D 78 ; LINE_LENGTH_A (line_length_pck Units: Pixels) w 015A <- 04 22 ; COARSE_INTEGRATION_TIME_A w 0100 <- 01 ; mode_select [4:0] 0: SW standby, 1: Streaming w 0157 <- 00 ; ANA_GAIN_GLOBAL_A w 0160 <- 06 E3 ; FRM_LENGTH_A w 0162 <- 0D 78 ; LINE_LENGTH_A w 015A <- 04 21 ; COARSE_INTEGRATION_TIME_A w 0157 <- 00 ; ANA_GAIN_GLOBAL_A w 0160 <- 0D 02 ; FRM_LENGTH_A w 0162 <- 0D 78 ; INE_LENGTH_A (line_length_pck Units: Pixels) w 015A <- 0D 02 ; COARSE_INTEGRATION_TIME_A w 0157 <- E0 ; ANA_GAIN_GLOBAL_A
—————-
Web上の資料や他のオープンソースから情報があったものに関してコメントとつけていますが、不明なものも多いです。
次に、これを Zybo に繋ぎ変えます。
で、PSからI2Cコアを繋いで、他の信号はXILINの D-PHY コアを生成して素直に接続します。
上記のような設定です。
あっさり信号は受信できていました。
ただしこの時一点嵌りまして、ILAで観測するにあたって、rxbyteclkhs クロックが間欠的にしかこないという点があります。まず dbghub にこのクロックがアサインされるとアウトで、ILAの方も、タイミングが悪いとキャプチャボタンを押してもエラーになります(何度か押せば取れるようです)。
また、図の通りレーンごとの信号は稀に前後するケースがあるようなので、rxsynchs でレーン間同期が必要なようです。
で、D-PHYコアから出てくるHSの信号を無信号期間も含めて何も考えずにDDR3-SRAMに記録する回路を書きまして、解析しました。
まずは何も考えずにダンプの一部をラインっぽいデータだけ抜き出して8bitでダンプしたらいきなり絵っぽいもが見えました。
後で分かったのですが、RAW10bitでBeyerデータなのですが、どうも4画素が5バイトにパッキングされているようなのですが、4画素の上位8bitが並んだ後に、下位2bit 4画素分がパッキングされた1バイトが付いているようで、バイナリダンプでもそれなりに絵になるようですね。
ついでなので、この段階で一度まともにデータを切り出して、BAYERを考慮して簡単に色をつけてみます(ホワバラ的に簡単にレベル合わせだけしたので飽和しまくりですが)。まあ、色補正やガンマ処理とかいろいろやることは残っていますが、その辺は最後に回します。
現像をどうするかはこれから考えますが、特許の切れた(20年経ってますよね?)ACPI法あたりの簡易な方法でよい気はしています。ただ解像度が高い近年のイメージセンサだと古典的な方法はあまり効果が無いのと、ピクセルビニング使うとこれまた意味がなくなるのでいろいろ考察は必要になりそうです。
とりあえず、D-PHYの解析結果をまとめると、各レーンのパケットは
- rxactivehs が1の区間だけ立っているところだけ見ればよさそう
- パケットの先頭では rxsynchs が立つのでこれをレーン間で同期
- データはバイトストリームで lane0 -> lane1 -> lane0 -> lane1 で巡回している
というのが見えてきました。
で、パケットには先頭にヘッダがあり
- ID (1byte)
- データ長(2byte)
- ECC (1byte)
- データ (データ長分)
- CRC (2byte)
となっているようです。
1ライン分のデータを示すパケットは ID = 0x2b で始まっているようです。またフレームスタートを示すのに ID=0x00、フレームエンドを示すのに ID = 0x01 というのが来ているようで、これにはデータ部分は無いようです。
またラインの最初に ID = 0x12 というのも1ラインと同じ長さのパケットが2つ来ているようです。
これだけ分かれば、絵を取るには十分なのですが、追加で少し調べた限り、short packet と long packet というのがあるらしく、short packet は ID が 0x00 で frame start、0x01で frame end で他に optional で line start や line end もあるようですね。 0x12 は埋め込みデータ(詳細は未調査)で、0x2bはRAW10bit の画像データを示すようです。
CRCはCRC-16-CCITTという名称のものになるようですが、まあ良く見かけるやつの模様です。ECCの部分は当初良く分からなかったのですがECCだそうです。CRCもECCもエラーが無ければ当面は無視してOKそうですね。
引き続き、受信回路の作成に取り掛かろうと思います。
今回、ここで取ったデータがそのままテストベンチで利用できそうです。
(追記)
実データを使ったテストベンチでRTLが動き始めました。
シミュレーション結果としてAXI4-Stream Video で出力させて、ダンプしたものです。
ちなみにシミュレータには Veritak のシェアウェア版使っています。ビルドがとても早いので、コード弄りと動作確認のTATがとても短くて生産性高いのでお気に入りです。
(さらに追記)
もしかすると Zybo用に Digilent が出している Pcam 5C よりコスパが良いかもしれません。2018/4/29現在の秋月電子の価格でスペックと一緒に比較すると
Pcam 5C : OmniVision OV05640 2592×1944(5M) 15fps 5,130円
RaspPi Cam V2 : Sony IMX219 3280×2464(8M) 21fps 4,300円
のようです。
もちろん輸入費用とか、円ドルのレートとかいろいろあるわけですが、Raspberry Pi の量産の恩恵もありそうに思います。
コメント