FC2カウンター FPGAの部屋 2022年09月
fc2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

kv260_median_platform のメディアン・フィルタを KV260 の Petalinux から動作させる17

kv260_median_platform のメディアン・フィルタを KV260 の Petalinux から動作させる16”の続き。

前回は、異常終了する原因を探ってみた。file コマンドで vadd を見たところ、x86 バイナリだったので、これが原因だった。今回は、再度、Vitis 2022.1 で vadd アクセラレーション・アプリケーション・プロジェクトを削除して、再度 vadd を作り直したところ、ARM aarch64 バイナリになった。vadd.bit.bin を作成し、vadd.bit.bin, vadd, binary_container_1.xclbin を KV260 の Petalinux に転送して、vadd を動作せたところ、”/lib/libc.so.6: version `GLIBC_2.34' not found (required by ./vadd)”エラーになってしまった。

Vitis 2022.1 で vadd_system を Explorer から完全削除して、もう一度 vadd を作り直した。
Active build configuration を Hardware に変更した。
Explorer の vadd_system を選択し、トンカチボタンをクリックしてビルドし、成功した。
KV260_custom_platform_94_220930.png

kv260_median_platform/kv260_median_pkg/vadd/Hardware/vadd を file コマンドで確認したところ、ARM aarch64 バイナリだった。前回は、何をミスってしまったのだろうか?
KV260_custom_platform_92_220928.png

vadd: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=ac4ef1c5805207baa9ef89b464a93f96451e85d9, for GNU/Linux 3.14.0, with debug_info, not stripped



これで、正常と思われる vadd が生成できたので、関連するファイルを生成し、KV260 の Petalinux に転送する。

system.bit から vadd.bit.bin を作成した。
cd /media/masaaki/Ubuntu_Disk/KRIA_KV260/2022.1/kv260_median_platform/kv260_median_pkg/vadd_system/Hardware/package.build/package
echo 'all:{system.bit}'>bootgen.bif
bootgen -w -arch zynqmp -process_bitstream bin -image bootgen.bif
mv system.bit.bin vadd.bit.bin


KV260 にファイルを転送した。
以下のファイルをPYNQ を実行していた KV260 の ubuntu のホーム・ディレクトリに FileZilla で転送した。

kv260_median_platform/kv260_median_pkg/vadd_system/Hardware/package.build/package/vadd.bit.bin
kv260_median_platform/kv260_median_pkg/vadd/Hardware/vadd
kv260_median_platform/kv260_median_pkg/vadd_system/Hardware/binary_container_1.xclbin



ここからは KV260 の Petalinux での作業となる。

vadd.bit.bin を /lib/firmware/xilinx/vadd に転送した。
sudo mv vadd.bit.bin /lib/firmware/xilinx/vadd

すでにロードされているハードウェアをアンロードして、vadd をロードした。
sudo xmutil unloadapp
sudo xmutil loadapp vadd


vadd を走らせたがエラーになってしまった。
./vadd binary_container_1.xclbin
KV260_custom_platform_95_220930.png

エラーは以下の内容だった。

./vadd: /lib/libc.so.6: version `GLIBC_2.34' not found (required by ./vadd)


Petalinux が 2021.1 用だったのがまずかったのかも知れないので、2022.1 の Petalinux を次回作成することにする。
  1. 2022年09月30日 05:05 |
  2. Vitis
  3. | トラックバック:0
  4. | コメント:0

KV260 のブートファームウェアを更新した

KV260 で動作する Petalinux のバージョンを 2022.1 にするに当たって、ブートファームウェアを更新する必要があるそうだ。
”KV260向けにVitisプラットフォームを作成してDPUを動かす その1 (Vitis 2022.1 + Vitis-AI v2.5)”の”ビルド+SDイメージの作成、ブート確認”を参照した。

Xilinx Wiki の Kria K26 SOM の Boot Firmware UpdatesXilinx download - 2022.1_update3_BOOT.BIN を適用するようだ。
Xilinx download - 2022.1_update3_BOOT.BIN をダウンロードすると、BOOT_xilinx-k26-starterkit-v2022.1-09152304_update3.BIN をダウンロードすることができた。

ブートファームウェアの更新は ikwzm さんの”KV260 の ブートファームウェアを更新”を参照して進めた。また、同じく ikwzm さんの”KV260 の QSPI フラッシュメモリをのぞいてみる”も参照した。

まずは、2021.1 の Petalinux が動作する KV260 に FileZilla で BOOT_xilinx-k26-starterkit-v2022.1-09152304_update3.BIN を転送した。
KV260_custom_platform_89_220927.png

image_update コマンドの -p オプションで現在の状況を確認した。
sudo image_update -p
Requested Boot Image と Last Boot Image が Image A になっていた。

Image A の内容をファイル(boot_ok.bin)にバックアップした。
sudo dd if=/dev/mtd5 of=boot_ok.bin bs=1024
KV260_custom_platform_90_220927.png

sudo image_update -i コマンドで BOOT_xilinx-k26-starterkit-v2022.1-09152304_update3.BIN をブートファームウェアとして書き込んだ。
sudo image_update -i BOOT_xilinx-k26-starterkit-v2022.1-09152304_update3.BIN

sudo halt で KV260 をシャットダウンして、電源を OFF した。
もう一度、電源を ON して、KV260 で Petalinux 2021.1 を起動した。

image_update コマンドの -p オプションで現在の状況を確認した。
Image B は Non Bootable だったが、Requested Boot Image と Last Boot Image が Image B になっていた。
sudo image_update -p

image_update コマンドの -v オプションを使って、Last Booted Image(今回の場合は Image B) を Bootable に変更した。
sudo image_update -v

sudo image_update -p で確認すると、Image B がBootable に変更された。
KV260_custom_platform_91_220927.png

Petalinux 2021.1 の起動メッセージを見ると、

Xilinx Zynq MP First Stage Boot Loader
Release 2022.1 Sep 16 2022 - 04:56:15


だった。ブートファームウェアの更新に成功したようだ。
KV260_custom_platform_93_220929.png
  1. 2022年09月29日 04:57 |
  2. KRIA KV260 Vision AI Starter Kit
  3. | トラックバック:0
  4. | コメント:0

kv260_median_platform のメディアン・フィルタを KV260 の Petalinux から動作させる16

kv260_median_platform のメディアン・フィルタを KV260 の Petalinux から動作させる15”の続き。

前回は、すでにロードされているハードウェアをアンロードして、vadd をロードし、vadd を走らせたが、”./vadd: cannot execute binary file: Exec format error”で異常終了した。今回は、異常終了する原因を探ってみた。file コマンドで vadd を見たところ、x86 バイナリだった。これが原因だ。。。

KV260 の Petalinux に転送した vadd ファイルを file コマンドで見たところ、x86-64 バイナリだった。これが原因だ。。。

vadd: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=ef287cc15a43c960562e7767ee120e1e0009b57c, with debug_info, not stripped


以前、Vitis 2021.1 で作成した vadd は ARM aarch64 バイナリだった。

vadd: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=66e998c92ae7d805781bb737a0fb487ff518f2fe, for GNU/Linux 3.14.0, with debug_info, not stripped


KV260_custom_platform_92_220928.png

しかし、同じ手順でやってきたはずなんだが、何処でミスったのだろうか?
原因を探ってみる。
  1. 2022年09月28日 04:56 |
  2. Vitis
  3. | トラックバック:0
  4. | コメント:0

kv260_median_platform のメディアン・フィルタを KV260 の Petalinux から動作させる15

kv260_median_platform のメディアン・フィルタを KV260 の Petalinux から動作させる14”の続き。

前回は、system.bit から vadd.bit.bin を作成し、vadd.dtbo ファイルを用意した。更に、pl.dtsi を vadd.bit.bin を使用するように変更し、再度コンパイルして、pl.dtbo を作成し、名前を vadd.dtbo に変更した。shell.json ファイルを作成した。最後に、5 つのファイルを KV260 で動作する Petalinux に SFTP で送った。今回は、すでにロードされているハードウェアをアンロードして、vadd をロードし、vadd を走らせたが、”./vadd: cannot execute binary file: Exec format error”で異常終了した。

すでにロードされているハードウェアをアンロードして、vadd をロードする。
sudo xmutil listapps
sudo xmutil unloadapp
sudo xmutil loadapp vadd

KV260_custom_platform_79_220926.png
KV260_custom_platform_80_220926.png

vadd を走らせたがエラーになってしまった。
./vadd binary_container_1.xclbin
KV260_custom_platform_81_220926.png

エラーは以下の内容だった。

-sh: ./vadd: cannot execute binary file: Exec format error


KV260 で動作する Petalinux はバージョン 2021.1 で、現在使用してるのが 2022.1 なので、その違いかも知れない?

Petalinux 2022.1 でビルドした KV260 用の Petalinux を使うにはどうしたら良いのかを調べたところ、”KV260向けにVitisプラットフォームを作成してDPUを動かす その1 (Vitis 2022.1 + Vitis-AI v2.5)”の”ビルド+SDイメージの作成、ブート確認”が参考になりそうだった。
それは、petalinux-package を使用して、イメージをwic ファイルに出力する。

petalinux-package --boot --u-boot --force
petalinux-package --wic --images-dir images/linux/ --bootfiles "ramdisk.cpio.gz.u-boot,boot.scr,Image,system.dtb,system-zynqmp-sck-kv-g-revB.dtb" --disk-name "mmcblk1"

  1. 2022年09月27日 04:13 |
  2. Vitis
  3. | トラックバック:0
  4. | コメント:0

kv260_median_platform のメディアン・フィルタを KV260 の Petalinux から動作させる14

kv260_median_platform のメディアン・フィルタを KV260 の Petalinux から動作させる13”の続き。

前回は、作成した kv260_median アクセラレーション・プラットフォームを使用して、vadd アプリケーション・プロジェクトを作成し、ビルドして成功した。そして、Vitis HLS 2022.1 のプロジェクトと Vivado 2022.1 のプロジェクトを見た。今回は、system.bit から vadd.bit.bin を作成し、vadd.dtbo ファイルを用意した。更に、pl.dtsi を vadd.bit.bin を使用するように変更し、再度コンパイルして、pl.dtbo を作成し、名前を vadd.dtbo に変更した。shell.json ファイルを作成した。最後に、5 つのファイルを KV260 で動作する Petalinux に SFTP で送った。

KV260 に転送するファイルを準備する
bin ファイルを用意する
system.bit は kv260_median_platform/kv260_median_pkg/vadd_system/Hardware/package.build/package にある。
KV260_custom_platform_68_220926.png

system.bit から vadd.bit.bin を作成する。
cd /media/masaaki/Ubuntu_Disk/KRIA_KV260/2022.1/kv260_median_platform/kv260_median_pkg/vadd_system/Hardware/package.build/package
echo 'all:{system.bit}'>bootgen.bif
bootgen -w -arch zynqmp -process_bitstream bin -image bootgen.bif
mv system.bit.bin vadd.bit.bin

KV260_custom_platform_69_220926.png

KV260_custom_platform_70_220926.png

vadd.dtbo ファイルを用意する
pl.dtsi ファイルを編集して、pl.dtbo ファイルを再度作成する。
pl.dtsi ファイルは kv260_median_platform/device-tree-xlnx ディレクトリにある。
KV260_custom_platform_71_220926.png

pl.dtsi を開いて 16 行目の kv260_custom_platform.bit.bin を vadd.bit.bin に変更する。
KV260_custom_platform_72_220926.png

pl.dtsi を再度コンパイルして、pl.dtbo を作成し、名前を vadd.dtbo に変更した。
cd /media/masaaki/Ubuntu_Disk/KRIA_KV260/2022.1/kv260_median_platform/device-tree-xlnx
dtc -@ -O dtb -o pl.dtbo pl.dtsi
mv pl.dtbo vadd.dtbo

KV260_custom_platform_73_220926.png

shell.json ファイルを作成する
kv260_median_platform/kv260_median_pkg/pfm/shell.json を作成した。

{
  "shell_type" : "XRT_FLAT",
  "num_slots": "1"
}


KV260_custom_platform_74_220926.png

KV260_custom_platform_75_220926.png

KV260 にファイルを転送する
以下のファイルをPYNQ を実行していた KV260 の ubuntu のホーム・ディレクトリに FileZilla で転送した。

kv260_median_platform/device-tree-xlnx/vadd.dtbo
kv260_median_platform/kv260_median_pkg/vadd_system/Hardware/package.build/package/vadd.bit.bin
kv260_median_platform/kv260_median_pkg/pfm/shell.json
kv260_median_platform/kv260_median_pkg/vadd/Hardware/vadd
kv260_median_platform/kv260_median_pkg/vadd_system/Hardware/binary_container_1.xclbin


KV260_custom_platform_77_220926.png

ここからは KV260 の Petalinux にログインしての作業となる。
久しぶりに KV260 の電源を入れると Petalinux が起動した。
KV260_custom_platform_76_220926.png

ssh 192.168.3.29 -X -l petalinux
でログインして、/lib/firmware/xilinx/vadd ディレクトリを作成しようとしたところ、前のディレクトリが残っていたので、vadd211 に改名して、もう一度、/lib/firmware/xilinx/vadd ディレクトリを作成した。そして、vadd.dtbo vadd.bit.bin shell.json を /lib/firmware/xilinx/vadd に転送した。
sudo mkdir /lib/firmware/xilinx/vadd
sudo mv /lib/firmware/xilinx/vadd /lib/firmware/xilinx/vadd211
sudo mkdir /lib/firmware/xilinx/vadd
sudo mv vadd.dtbo vadd.bit.bin shell.json /lib/firmware/xilinx/vadd
ls -l /lib/firmware/xilinx/vadd

KV260_custom_platform_78_220926.png
  1. 2022年09月26日 16:27 |
  2. Vitis
  3. | トラックバック:0
  4. | コメント:0

kv260_median_platform のメディアン・フィルタを KV260 の Petalinux から動作させる13

kv260_median_platform のメディアン・フィルタを KV260 の Petalinux から動作させる12”の続き。

前回は、、Vitis 2022.1 で kv260_median アクセラレーション・プラットフォームを作成した。今回は、作成した kv260_median アクセラレーション・プラットフォームを使用して、vadd アプリケーション・プロジェクトを作成し、ビルドして成功した。そして、Vitis HLS 2022.1 のプロジェクトと Vivado 2022.1 のプロジェクトを見ていこう。

現在の Vitis 2022.1 の様子を示す。
KV260_custom_platform_52_220924.png

vadd アプリケーション・プロジェクトの作成
Vitis 2021.1 で File メニューから New -> Application Project... を選択する。
New Application Project ダイアログの Create a New Application Project 画面が開く。
Next > ボタンをクリックする。

Platform 画面
kv260_median プラットフォームを選択する。
KV260_custom_platform_54_220924.png

Application Project Detail 画面
Application project name に vadd と入力する。
KV260_custom_platform_55_220924.png

Domain 画面
sysroot path: に kv260_median_platform/kv260_median_pkg/sysroots/cortexa72-cortexa53-xilinx-linux を指定した。
Root FS: に kv260_median_platform/kv260_median_plnx/images/linux/rootfs.ext4 を指定した。
Kernel Image: に kv260_median_platform/kv260_median_plnx/images/linux/Image を指定した。
KV260_custom_platform_56_220924.png

Templates 画面
Simple Vector Addition を選択した。
Finish ボタンをクリックした。
KV260_custom_platform_57_220924.png

vadd プロジェクトが生成された。
最初に Emulation-SW でビルドしてみよう。
Active build configuration を Emulation-SW のままとする。
Explorer から vadd_system を選択する。
トンカチ・ボタンをクリックして、ビルドを行う。
KV260_custom_platform_58_220924.png

ビルドが成功した。
KV260_custom_platform_59_220924.png

Run ボタンをクリックした。
Error Launching Program ダイアログが表示された。
エラーのようだ。
KV260_custom_platform_60_220924.png

次に Hardware でビルドしてみよう。
Active build configuration を Hardware に変更する。
Explorer から vadd_system を選択する。
トンカチ・ボタンをクリックして、ビルドを行う。
KV260_custom_platform_61_220924.png

ビルドが成功した。
KV260_custom_platform_62_220924.png

Vitis HLS 2022.1 の krnl_vadd プロジェクトを見てみよう。
krnl_vadd プロジェクトは、kv260_median_platform/kv260_median_pkg/vadd_kernels/Hardware/build/krnl_vadd/krnl_vadd/krnl_vadd にあった。
C コードの合成結果を示す。
KV260_custom_platform_63_220924.png

次に、Vivado 2022.1 のプロジェクトは、kv260_median_platform/kv260_median_pkg/vadd_system_hw_link/Hardware/binary_container_1.build/link/vivado/vpl/prj にあった。
KV260_custom_platform_64_220924.png

system ブロック・デザインを示す。
KV260_custom_platform_65_220924.png

Address Editor 画面を示す。
KV260_custom_platform_66_220924.png

Project Summary を示す。
KV260_custom_platform_67_220924.png
  1. 2022年09月25日 04:22 |
  2. Vitis
  3. | トラックバック:0
  4. | コメント:0

kv260_median_platform のメディアン・フィルタを KV260 の Petalinux から動作させる12

kv260_median_platform のメディアン・フィルタを KV260 の Petalinux から動作させる11”の続き。

前回は、sysroot をインストールし、 boot ディレクトリと sd_dir ディレクトリを用意した。今回は、Vitis 2022.1 で kv260_median アクセラレーション・プラットフォームを作成する。

Vitis 2022.1 を起動した。
vitis &

Vitis IDE Launcher ダイアログが開いた。
Workspace に kv260_median_platform/kv260_median_pkg を指定して、Launch ボタンをクリックする。
KV260_custom_platform_46_220924.png

Vitis IDE が起動した。
File -> New -> Platform Project... を選択する。
New Platform Project ダイアログが開いた。
Create new platform project 画面
Platform project name に kv260_median と入力した。
KV260_custom_platform_47_220924.png

platform 画面
XSA file に kv260_median_platform/kv260_median_platform/kv260_median_platform.xsa を指定した。
Operation system に Linux を指定した。
Processor に psu_cortexa53 を指定した。
Architecture に 64-bit を指定した。
Boot Components の Generate boot components のチェックボックスのチェックを外した。
Finish ボタンをクリックした。
KV260_custom_platform_48_220924.png

kv260_median プラットフォーム・プロジェクトが生成された。
KV260_custom_platform_49_220924.png

kv260_median プラットフォームの psu_cortexa53 → Linux on psu_cortexa53 をクリックする。
以下のように設定する。
Bif Files: Brows... の右横の下向き三角をクリックするとドロップダウンメニューが表示されるので、Generate BIF を選択する。
Boot Components Directory: Brows... ボタンをクリックして、kv260_median_pkg/pfm/boot ディレクトリを選択する。
FAT32 Partition Directory: Brows... ボタンをクリックして、kv260_median_pkg/pfm/sd_dir を選択する。
KV260_custom_platform_50_220924.png

トンカチ・ボタンをクリックしてビルドを行った。
KV260_custom_platform_51_220924.png

ビルドが終了した。
KV260_custom_platform_52_220924.png

kv260_median プラットフォームは export ディレクトリ以下に生成されていた。
KV260_custom_platform_53_220924.png
  1. 2022年09月24日 05:16 |
  2. Vitis
  3. | トラックバック:0
  4. | コメント:0

kv260_median_platform のメディアン・フィルタを KV260 の Petalinux から動作させる11

kv260_median_platform のメディアン・フィルタを KV260 の Petalinux から動作させる10”の続き。

前回は、デバイス・ツリー・オーバーレイを生成した。今回は、sysroot をインストールし、 boot ディレクトリと sd_dir ディレクトリを用意する。

kv260_median_platform ディレクトリの下に kv_median_pkg ディレクトリを新規作成し、その下に pfm ディレクトリを新規作成した。
cd ..
mkdir kv260_median_pkg
cd kv260_median_pkg
mkdir pfm

KV260_custom_platform_38_220923.png

sysroot をインストールする。
cd ../kv260_median_plnx/images/linux
./sdk.sh -d /media/masaaki/Ubuntu_Disk/KRIA_KV260/2022.1/kv260_median_platform/kv260_median_pkg

KV260_custom_platform_39_220923.png
KV260_custom_platform_40_220923.png

kv260_median_platform/kv260_median_pkg/sysroots ディレクトリが生成され、その下に cortexa72-cortexa53-xilinx-linux ディレクトリと x86_64-petalinux-linux ディレクトリが生成された。
KV260_custom_platform_41_220923.png

kv260_median_pkg/pfm ディレクトリに boot ディレクトリと sd_dir ディレクトリを新規作成する。
cd ../../../kv260_median_pkg/pfm
mkdir boot
mkdir sd_dir

KV260_custom_platform_42_220923.png

kv260_median_plnx/imges/linux ディレクトリの以下のファイルを kv260_median_pkg/pfm/boot ディレクトリにコピーする。

zynqmp_fsbl.elf
pmufw.elf
bl31.elf
u-boot-dtb.elf (名前をu-boot.elfに変更する)
system-zynqmp-sck-kv-g-revB.dtb (名前を system.dtb に変更する)


KV260_custom_platform_43_220923.png

KV260_custom_platform_44_220923.png

kv260_median_plnx/imges/linux ディレクトリの以下のファイルを kv260_median_pkg/pfm/sd_dir ディレクトリにコピーする。

boot.scr (u-boot初期化用のスクリプト)
system-zynqmp-sck-kv-g-revB.dtb (Linuxがシステム・セットアップを理解するために起動中に読み取るデバイス・ツリー・ブロブ)(名前を system.dtb に変更する)


KV260_custom_platform_45_220923.png
  1. 2022年09月23日 06:01 |
  2. Vitis
  3. | トラックバック:0
  4. | コメント:0

kv260_median_platform のメディアン・フィルタを KV260 の Petalinux から動作させる10

kv260_median_platform のメディアン・フィルタを KV260 の Petalinux から動作させる9”の続き。

前回は、ハードウエアをエクスポートした。そして、Petalinux 2022.1 で kv260_median_plnx プロジェクトを作成し、petalinux-config で設定を行って、petalinux-build すると成功した。また、petalinux-build --sdk も成功した。今回は、デバイス・ツリー・オーバーレイを生成する。

DTG をインストールする。
cd ..
git clone https://github.com/Xilinx/device-tree-xlnx
cd device-tree-xlnx

KV260_custom_platform_31_220921.png

DTG のバージョン 2022.1 をチェックアウトして、xsct を起動する。なお、Vitis の setting64.sh は起動してある。
git checkout xlnx_rel_v2022.1
xsct

KV260_custom_platform_32_220921.png

XSA ファイルを読み取って、DTS を生成する。
hsi open_hw_design /media/masaaki/Ubuntu_Disk/KRIA_KV260/2022.1/kv260_median_platform/kv260_median_platform/kv260_median_platform.xsa
hsi set_repo_path /media/masaaki/Ubuntu_Disk/KRIA_KV260/2022.1/kv260_median_platform/device-tree-xlnx
hsi create_sw_design device-tree -os device_tree -proc psu_cortexa53_0
hsi set_property CONFIG.dt_overlay true [hsi::get_os]
hsi set_property CONFIG.dt_zocl true [hsi::get_os]
hsi generate_target -dir /media/masaaki/Ubuntu_Disk/KRIA_KV260/2022.1/kv260_median_platform/device-tree-xlnx
hsi close_hw_design [hsi current_hw_design]
exit

KV260_custom_platform_33_220921.png
KV260_custom_platform_34_220921.png

ログを示す。

(base) masaaki@masaaki-H110M4-M01:/media/masaaki/Ubuntu_Disk/KRIA_KV260/2022.1/kv260_median_platform/device-tree-xlnx$ xsct
rlwrap: warning: your $TERM is 'xterm-256color' but rlwrap couldn't find it in the terminfo database. Expect some problems.
                                                                                
****** Xilinx Software Commandline Tool (XSCT) v2022.1.0
  **** SW Build 3524075 on 2022-04-13-17:42:45
    ** Copyright 1986-2022 Xilinx, Inc. All Rights Reserved.


xsct% hsi open_hw_design /media/masaaki/Ubuntu_Disk/KRIA_KV260/2022.1/kv260_median_platform/kv260_median_platform/kv260_median_platform.xsa
INFO: [Hsi 55-2053] elapsed time for repository (/media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis/2022.1/data/embeddedsw) loading 12 seconds
hsi::open_hw_design: Time (s): cpu = 00:00:08 ; elapsed = 00:00:21 . Memory (MB): peak = 2348.008 ; gain = 0.000 ; free physical = 1330 ; free virtual = 37790
system_wrapper
xsct% hsi set_repo_path /media/masaaki/Ubuntu_Disk/KRIA_KV260/2022.1/kv260_median_platform/device-tree-xlnx
xsct% hsi create_sw_design device-tree -os device_tree -proc psu_cortexa53_0    
device-tree                                                                     
xsct% hsi set_property CONFIG.dt_overlay true [hsi::get_os]                     
true
xsct% hsi set_property CONFIG.dt_zocl true [hsi::get_os]                        
true
xsct% hsi generate_target -dir /media/masaaki/Ubuntu_Disk/KRIA_KV260/2022.1/kv260_median_platform/device-tree-xlnx
WARNING: Interrupt pin "mm2s_introut" of IP block: "axi_dma_0" is not connected to any interrupt controller

WARNING: Interrupt pin "s2mm_introut" of IP block: "axi_dma_0" is not connected to any interrupt controller

WARNING: no s_axi_aclk for clockwizard IP block: " clk_wiz_0"

WARNING: Clock pin "s_axi_lite_aclk" of IP block "axi_dma_0" is not connected to any of the pl_clk"

WARNING: no s_axi_aclk for clockwizard IP block: " clk_wiz_0"

WARNING: Clock pin "m_axi_mm2s_aclk" of IP block "axi_dma_0" is not connected to any of the pl_clk"

WARNING: no s_axi_aclk for clockwizard IP block: " clk_wiz_0"

WARNING: Clock pin "m_axi_s2mm_aclk" of IP block "axi_dma_0" is not connected to any of the pl_clk"

WARNING: no s_axi_aclk for clockwizard IP block: " clk_wiz_0"                   

WARNING: Clock pin "s_axi_aclk" of IP block "axi_intc_0" is not connected to any of the pl_clk"

WARNING: Interrupt pin "interrupt" of IP block: "median_axis_RGB24_0" is not connected to any interrupt controller

WARNING: no s_axi_aclk for clockwizard IP block: " clk_wiz_0"

WARNING: Clock pin "ap_clk" of IP block "median_axis_RGB24_0" is not connected to any of the pl_clk"

WARNING: Interrupt pin "interrupt" of IP block: "multi_axi4ls_0" is not connected to any interrupt controller

WARNING: no s_axi_aclk for clockwizard IP block: " clk_wiz_0"

WARNING: Clock pin "ap_clk" of IP block "multi_axi4ls_0" is not connected to any of the pl_clk"

zocl:true                                                                       
ext_platform:
intr_ctrl_len:1
WARNING: ERROR: axi_dma_0: mm2s_introut port is not connected                   
WARNING: ERROR: axi_dma_0: s2mm_introut port is not connected
hsi::generate_target: Time (s): cpu = 00:00:26 ; elapsed = 00:00:29 . Memory (MB): peak = 2348.008 ; gain = 0.000 ; free physical = 1251 ; free virtual = 37735
xsct% hsi close_hw_design [hsi current_hw_design]                               
xsct% exit                                                                      
exit


pl.dtsi が生成された。
KV260_custom_platform_35_220921.png

pl.dtsi を示す。axi_dma_0 , median_axis_RGB24_0, multi_axi4ls_0 の項目も見えた。
KV260_custom_platform_36_220921.png

pl.dtbi をコンパイルして pl.dtbo を生成する。
dtc -@ -O dtb -o pl.dtbo pl.dtsi
pl.dtbo が生成された。
KV260_custom_platform_37_220921.png
  1. 2022年09月22日 04:02 |
  2. Vitis
  3. | トラックバック:0
  4. | コメント:0

kv260_median_platform のメディアン・フィルタを KV260 の Petalinux から動作させる9

kv260_median_platform のメディアン・フィルタを KV260 の Petalinux から動作させる8”の続き。

前回は、2022.1 バージョンのツールを使用して、Vitis アクセラレーション・プラットフォームを作成して行こうと思うが、色を RBG に修正して、また、multi_axi4ls IP を追加して、ハードウエア・プラットフォームを作成する。ということで、Vivado 2021.1 の kv260_custom_platform プロジェクトをコピーして、Vivado 2022.1 で読み込んでアップグレードした。そして、ブロック・デザインに multi_axi4ls IP と AXI4-Stream Subset Converter を追加して配線して、論理合成、インプリメンテーション、ビットストリームの生成を行った。今回は、ハードウエアをエクスポートする。そして、Petalinux 2022.1 で kv260_median_plnx プロジェクトを作成し、petalinux-config で設定を行って、petalinux-build すると成功した。また、petalinux-build --sdk も成功した。
なお、使用しているパソコンの OS は Ubuntu 18.04 LTS だ。

File -> Export -> Export Platform を選択した。
Export Hardware Platform ダイアログが開く。
Next > ボタンをクリックする。

Platform Type 画面
Hardware and Hardware Emulation ラジオボタンをクリックした。
Next > ボタンをクリックする。

Platform State 画面
Pre-synthesis ラジオボタンをクリックする。(デフォルト)
Include bitstream チェックボックスにチェックを入れた。
Next > ボタンをクリックする。

Platform Properties 画面
Name に kv260_median_platform を入力した。
後はデフォルトのままとする。
Next > ボタンをクリックする。

Output File 画面
XSA file name に kv260_median_platform と入力した。
Next > ボタンをクリックする。

Exporting Hardware Platform 画面
Finish ボタンをクリックした。

kv260_median_platform.xsa が出力された。
KV260_custom_platform_17_220920.png

Petalinux 2022.1 の環境を設定した。
source /media/masaaki/Ubuntu_Disk/tools/Xilinx/PetaLinux/2022.1/settings.sh

KRIA_KV260/2022.1/kv260_median_platform ディレクトリに行って、petalinux-upgrade を行う。なお、”XILINX KIRA K26(KV260) Petalinux2022.1用起動用SDカードイメージの作り方”によると、KRIA カードでは、petalinux-upgrade を行わないと動作しないそうだ。
その後、BSP を元に kv260_median_plnx プロジェクトを作成し、kv260_median_plnx に入る。
cd /media/masaaki/Ubuntu_Disk/KRIA_KV260/2022.1/kv260_median_platform
petalinux-upgrade -u http://petalinux.xilinx.com/sswreleases/rel-v2022/sdkupdate/2022.1_update2/ -p "aarch64" --wget-args "--wait 1 -nH --cut-dirs=4"
petalinux-create --type project -s /media/masaaki/Ubuntu_Disk/Archives/Xilinx_tools/xilinx-kv260-starterkit-v2022.1-05140151.bsp -n kv260_median_plnx
cd kv260_median_plnx

KV260_custom_platform_18_220920.png

XSA ファイルを使用して petalinux-config する
petalinux-config --get-hw-description=/media/masaaki/Ubuntu_Disk/KRIA_KV260/2022.1/kv260_median_platform/kv260_median_platform
なお、キャプチャ図は echo コマンドを実行しているが、今回は実行していない。
KV260_custom_platform_19_220920.png

petalinux-config 画面
→キーを押して、< Exit > を選択して、Enter キーを押す。
KV260_custom_platform_20_220920.png

セーブ画面になるので、< Yes > を選択して Enter キーを押す。

ターミナルに戻った。
KV260_custom_platform_21_220920.png

rootfs の xrt を有効にする。
petalinux-config -c rootfs

Filesystem packages -> libs -> xrt を有効にする。(スペースキー)
KV260_custom_platform_22_220920.png

→キーを押して、< Exit > を選択して、Enter キーを何回か実行し、セーブ画面で< Yes > を選択して Enter キーを押してターミナルに戻った。
KV260_custom_platform_23_220920.png

ビルド
petalinux-build
成功した。
KV260_custom_platform_24_220920.png
KV260_custom_platform_25_220920.png

petalinux-build --sdk
KV260_custom_platform_26_220921.png
KV260_custom_platform_27_220921.png

kv260_median_platform/kv260_median_plnx/images/linux ディレクトリの内容を示す。
KV260_custom_platform_30_220921.png
  1. 2022年09月21日 04:59 |
  2. Vitis
  3. | トラックバック:0
  4. | コメント:0

kv260_median_platform のメディアン・フィルタを KV260 の Petalinux から動作させる8

kv260_median_platform のメディアン・フィルタを KV260 の Petalinux から動作させる7”の続き。

2021.1 バージョンのツールで、メディアン・フィルタ入りのハードウエア・プラットフォームを作成し、Petalinux でソフトウェア・プラットフォームを作成して、Vitis アクセラレーション・プラットフォームの kv260_median_platform を作成した。プラットフォームのメディアン・フィルタを使おうと /dev/mem を使用して、メディアン・フィルタを使用したが、RGB のはずが RBG で色がおかしくなっていた。今回は、2022.1 バージョンのツールを使用して、Vitis アクセラレーション・プラットフォームを作成して行こうと思うが、色を RBG に修正して、また、multi_axi4ls IP を追加して、ハードウエア・プラットフォームを作成していこう。

/media/masaaki/Ubuntu_Disk/KRIA_KV260/2021.1/kv260_median_platform/kv260_median_platform ディレクトリを/media/masaaki/Ubuntu_Disk/KRIA_KV260/2022.1/kv260_median_platform/kv260_median_platform にコピーした。

Vivado 2022.1 を起動して、/media/masaaki/Ubuntu_Disk/KRIA_KV260/2022.1/kv260_median_platform/kv260_median_platform/kv260_median_platform.xpr を読み込ませた。
2022.1 への変換プロセスが走って、ダイアログが表示された。
変換プロセスが走って、2022.1 に変換してくれたが、問題が生じた。
AXI SmartConnet がアップグレードできないと言ってきたので、一度消去してから、再度 Add IP したところ、問題が解決した。

なお、Vivado 2021.1 での、ハードウエア・プラットフォームの作成方法は、
メディアン・フィルタを含んだ Vitis アクセラレーション・プラットフォームを作成する1(Vivado で kv260_median_platform プロジェクトを作成1)
メディアン・フィルタを含んだ Vitis アクセラレーション・プラットフォームを作成する2(Vivado で kv260_median_platform プロジェクトを作成2)
メディアン・フィルタを含んだ Vitis アクセラレーション・プラットフォームを作成する3(Vivado で kv260_median_platform プロジェクトを作成3)
だった。

Project device を変更したので、示す。
Vivado の Tools メニューから Settings... を選択する。
Settings ダイアログが表示された。
Project device の ... ボタンをクリックする。
Select Device ダイアログが表示された。
Kria KV260 Vision AI Starter Kit を選択して、Connections をクリックする。
KV260_custom_platform_7_220920.png

Manage Board Connection ダイアログが表示された。
Connector 1 on kv260 の右脇の下向き三角をクリックして、Vision AI Starter Kit carrier card を選択する。
KV260_custom_platform_8_220920.png

Project device が設定され、Kria KV260 Vision AI Starter Kit に設定された。
KV260_custom_platform_9_220920.png

kv260_median_platform ディレクトリに multi_axi4ls ディレクトリを新規作成した。
multi_axi4ls ディレクトリに”Vitis HLS 2022.1 で multi_axi4ls IP を作成する”で作成した IP をコピー&ペーストした。
具体的には、multi_axi4ls/solution1/impl/export.zip を展開して、multi_axi4ls ディレクトリにコピーした。
KV260_custom_platform_12_220920.png

IP Catalog に、multi_axi4ls IP を追加した。
KV260_custom_platform_13_220920.png

ブロック・デザインに multi_axi4ls IP と AXI4-Stream Subset Converter を追加して配線した。
KV260_custom_platform_10_220920.png

AXI4-Stream Subset Converter の設定を示す。
tdata[23:0] を tdata[23:16],tdata[7:0],tdata[15:8] に変更した。つまり、RGB を RBG に変更した。
KV260_custom_platform_11_220920.png

Address Editor 画面を示す。
KV260_custom_platform_14_220920.png

ブロック・デザインが完成したら、Flow Navigator から Generate Block Design を選択すると、Generate Output Products ダイアログを表示された。
Synthesis Options のラジオボタンを Global に変更した。
Generate ボタンをクリックした。
KV260_custom_platform_15_220920.png

Flow Navigator から Generate Bitstream をクリックして、論理合成、インプリメンテーション、ビットストリームの生成を行って、成功した。
Project Summary を示す。
KV260_custom_platform_16_220920.png
  1. 2022年09月20日 04:38 |
  2. Vitis
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2022.1 で multi_axi4ls IP を作成する

Vitis アクセラレーション・プラットフォーム上に予め回路を埋め込んでおいて、その回路を XRT 経由で操作するというお題は以前やってみたのだが、失敗した。それなら、Vitis とは別のソフトウェアで動かせば良いのでは?というアドバイスを AMD XILINX TECH DAY TOKYO 2022 の後のタリーズコーヒーでいただいたので、やってみることにした。

今回は、”自作回路を cocotb でシミュレーションする1(Vitis HLS で multiplier を作成1)”と”自作回路を cocotb でシミュレーションする2(Vitis HLS で multiplier を作成2)”で作成した multiplier を multi_axi4ls として、 AXI4 Lite インターフェース対応にする。
multi_axi4ls IP を Vitis アクセラレーション・プラットフォームのハードウエア・プラットフォーム上に実装する。

ソースコードの multi_axi4ls.cpp を示す。

// multi_axi4ls.cpp
// 2022/09/18 by marsee
//

#include <stdint.h>

int multi_axi4ls(int16_t a, int16_t b, int32_t *c){
#pragma HLS INTERFACE mode=s_axilite port=c
#pragma HLS INTERFACE mode=s_axilite port=b
#pragma HLS INTERFACE mode=s_axilite port=a
#pragma HLS INTERFACE mode=s_axilite port=return

    *c = a * b;

    return(0);
}


テストベンチの multi_axi4ls_tb.cpp を示す。

// multi_axi4ls_tb.cpp
// 2022/09/18 by marsee
//

#include <stdio.h>
#include <stdint.h>

int multi_axi4ls(int16_t a, int16_t b, int32_t *c);

int main(){
    int16_t a, b;
    int32_t c;

    a = 3;
    b = 4;

    multi_axi4ls(a, b, &c);
    printf("a = %d, b = %d, c = (a*b) = %d\n", a, b, c);

    return(0);
}


Vitis HLS 2022.1 の multi_axi4ls プロジェクトを示す。KV260 用だ。Part は xck26-sfvc784-2LV-c だ。
KV260_custom_platform_1_220918.jpg

C シミュレーションの結果を示す。
KV260_custom_platform_2_220918.jpg

C コードの合成を行った。結果を示す。
なお、200 MHz で動かす予定なので、クロック周期は 5 ns に設定してある。
KV260_custom_platform_3_220919.png

C/RTL 協調シミュレーションを行った。結果を示す。
レイテンシは 3 クロックだった。
KV260_custom_platform_4_220919.png

C/RTL 協調シミュレーションの波形を示す。
KV260_custom_platform_5_220919.png

Export RTL を行った。

Implementation の結果を示す。
問題ないようだ。
KV260_custom_platform_6_220919.png
  1. 2022年09月19日 06:48 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

Kria KR260 ロボティクス スターター キットが届いた

AMD XILINX TECH DAY TOKYO 2022 から家に帰ってきたら、Kria KR260 ロボティクス スターター キットが届いていた。

KR260 は Mouser に発注していたのだが、最終用途証明書を出していなかったので、時間がかかってしまった。9/7 に発注して 9/18 に届いた。
KR260_1_220918.jpg

Mouser 経由なので、電源も入っています。PSE マークは無かったです。
SD カードも入っていたので、すぐに試せそうです。中身確認していないけど、書いてありますよね?

KR260 の表面を示す。
KR260_2_220918.jpg

PMOD が 4 個あるのが嬉しい。これでパラレルポート出力カメラが接続できそうだ。

裏面を示す。
KR260_3_220918.jpg

マイクロ SD カードスロットなどがある。
  1. 2022年09月18日 05:32 |
  2. KR260
  3. | トラックバック:0
  4. | コメント:0

AMD XILINX TECH DAY TOKYO 2022 に行ってきます

今日は、2年ぶり以上のオンサイトのセミナ”AMD XILINX TECH DAY TOKYO 2022”に行ってきます。
とっても楽しみです。
皆様にお会い出来るのもとっても楽しみです。

そろそろ KR260 も届くと思うので、”Kria SOM 最新情報 (ビジョン AI + ロボティクス)”と”KR260 ロボティクス スターター キット ユーザー セッション”を楽しみにしています。

”ザイリンクスの新しいコスト重視製品ポートフォリオのご紹介​”では、どのような製品がでてくるのでしょうか?
Edge AI Versal の新しい安価なボードが出てくると良いのですが。。。

とにかく、久しぶりのセミナ、展示会を楽しもうと思います。

(2022/09/18 :追記)
とても有意義なセミナでした。皆様ありがとうございました。
そして、いろいろと懐かしい方々にもお会い出来ました。ありがとうございました。
また、よろしくお願いいたします。
  1. 2022年09月16日 04:42 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:0

cocotb 実行時の python, make, iverilog のバージョン

職場の Ubuntu 18.04 のパソコンだと cocotb が make できないのだが、自宅のパソコンの python, make, iverilog のバージョンを書いておく。

python --version
Python 3.8.10

make --version
GNU Make 4.1
このプログラムは x86_64-pc-linux-gnu 用にビルドされました
Copyright (C) 1988-2014 Free Software Foundation, Inc.
ライセンス GPLv3+: GNU GPL バージョン 3 以降
これはフリーソフトウェアです: 自由に変更および配布できます.
法律の許す限り、 無保証 です.

iverilog -v
Icarus Verilog version 10.1 (stable) ()

Copyright 1998-2015 Stephen Williams
  1. 2022年09月16日 04:26 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

自作回路を cocotb でシミュレーションする3(cocotb でシミュレーション)

自作回路を cocotb でシミュレーションする2(Vitis HLS で multiplier を作成2)”の続き。

cocotb でサンプルをやってきたが、自作回路を cocotb でシミュレーションしてみようということで、前回は、multiplier プロジェクトの C シミュレーション、C コードの合成、C/RTL 協調シミュレーションを行った。今回は、ファイルを用意して、make を行ったら PASS した。gtkwave で波形を表示した。

Cocotb ディレクトリの下に multiplier ディレクトリを新規作成した。
multiplier ディレクトリに multiplier.v と multiplier_mul_mul_16s_16s_32_4_1.v をコピーした。
multiplier.v と multiplier_mul_mul_16s_16s_32_4_1.v の Verilog HDL コードは”自作回路を cocotb でシミュレーションする2(Vitis HLS で multiplier を作成2)”に貼ってある。
ただし、mltiplier.v には、VCD ファイルを生成するために、コードを追加した。
cocotb_32_220915.png

// the "macro" to dump signals
`ifdef COCOTB_SIM
initial begin
  $dumpfile ("multiplier.vcd");
  $dumpvars (0, multiplier);
  #1;
end
`endif


multiplier ディレクトリに test_multiplier.py ファイルを新規作成した。
test_multiplier.py ファイルを示す。

# test_multiplier.py
# 2022/09/13 by marsee

import random
import cocotb
from cocotb.clock import Clock
from cocotb.triggers import Timer, RisingEdge

@cocotb.test()
async def test_multiplier(dut):
    dut.ap_rst = 1 # Reset
    
    clock = Clock(dut.ap_clk, 10, units="ns")  # Create a 10ns period clock on port clk
    cocotb.start_soon(clock.start())  # Start the clock
    
    await Timer(10, units='ns')
    
    dut.ap_start = 1
    dut.ap_rst = 0 # Normal Operation
    for i in range(5):
        dut.a.value = i
        dut.b.value = i+1
        for j in range(3):
            await RisingEdge(dut.ap_clk)
        await Timer(1, units='ns')
        assert dut.c.value == i*(i+1), "Invalid value for multiplication {}".format(i*(i+1))
    
    await Timer(9, units='ns')


Makefile を新規作成した。
Makefile を示す。

# Makefile
# 2022/09/13 by marsee

SIM ?= icarus

VERILOG_SOURCES = $(shell pwd)/multiplier.v
VERILOG_SOURCES += $(shell pwd)/multiplier_mul_mul_16s_16s_32_4_1.v
TOPLEVEL = multiplier
MODULE = test_multiplier

include $(shell cocotb-config --makefiles)/Makefile.sim


これで cocotb のシミュレーションに必要なファイルが用意できた。

次に
make
を行った。
cocotb_28_220915.png

cocotb_29_220915.png

PASS した成功だ。

make 後の mulitplier ディレクトリを示す。
cocotb_31_220915.png

multiplier.vcd ファイルを gtkwave で表示する。
gtkwave multiplier.vcd &
波形が表示された。
cocotb_30_220915.png

make の時のログを貼っておく。

(base) masaaki@masaaki-H110M4-M01:/media/masaaki/Ubuntu_Disk/Cocotb/multiplier$ make
rm -f results.xml
make -f Makefile results.xml
make[1]: ディレクトリ '/media/masaaki/Ubuntu_Disk/Cocotb/multiplier' に入ります
rm -f results.xml
MODULE=test_multiplier TESTCASE= TOPLEVEL=multiplier TOPLEVEL_LANG=verilog \
         /usr/bin/vvp -M /home/masaaki/anaconda3/lib/python3.8/site-packages/cocotb/libs -m libcocotbvpi_icarus   sim_build/sim.vvp 
     -.--ns INFO     gpi                                ..mbed/gpi_embed.cpp:76   in set_program_name_in_venv        Did not detect Python virtual environment. Using system-wide Python interpreter
     -.--ns INFO     gpi                                ../gpi/GpiCommon.cpp:101  in gpi_print_registered_impl       VPI registered
     0.00ns INFO     cocotb                             Running on Icarus Verilog version 10.1 (stable)
     0.00ns INFO     cocotb                             Running tests with cocotb v1.7.0 from /home/masaaki/anaconda3/lib/python3.8/site-packages/cocotb
     0.00ns INFO     cocotb                             Seeding Python random module with 1663099051
     0.00ns INFO     cocotb.regression                  Found test test_multiplier.test_multiplier
     0.00ns INFO     cocotb.regression                  running test_multiplier (1/1)
/media/masaaki/Ubuntu_Disk/Cocotb/multiplier/test_multiplier.py:11: DeprecationWarning: Setting values on handles using the ``dut.handle = value`` syntax is deprecated. Instead use the ``handle.value = value`` syntax
  dut.ap_rst = 1 # Reset
VCD info: dumpfile multiplier.vcd opened for output.
/media/masaaki/Ubuntu_Disk/Cocotb/multiplier/test_multiplier.py:19: DeprecationWarning: Setting values on handles using the ``dut.handle = value`` syntax is deprecated. Instead use the ``handle.value = value`` syntax
  dut.ap_start = 1
/media/masaaki/Ubuntu_Disk/Cocotb/multiplier/test_multiplier.py:20: DeprecationWarning: Setting values on handles using the ``dut.handle = value`` syntax is deprecated. Instead use the ``handle.value = value`` syntax
  dut.ap_rst = 0 # Normal Operation
   160.00ns INFO     cocotb.regression                  test_multiplier passed
   160.00ns INFO     cocotb.regression                  *****************************************************************************************
                                                        ** TEST                             STATUS  SIM TIME (ns)  REAL TIME (s)  RATIO (ns/s) **
                                                        *****************************************************************************************
                                                        ** test_multiplier.test_multiplier   PASS         160.00           0.00      40576.39  **
                                                        *****************************************************************************************
                                                        ** TESTS=1 PASS=1 FAIL=0 SKIP=0                   160.00           0.21        754.96  **
                                                        *****************************************************************************************
                                                        
make[1]: ディレクトリ '/media/masaaki/Ubuntu_Disk/Cocotb/multiplier' から出ます

  1. 2022年09月15日 04:54 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

自作回路を cocotb でシミュレーションする2(Vitis HLS で multiplier を作成2)

自作回路を cocotb でシミュレーションする1(Vitis HLS で multiplier を作成1)”の続き。

cocotb でサンプルをやってきたが、自作回路を cocotb でシミュレーションしてみようということで、前回は、乗算器(mulitplier)のソースコードとテストベンチを貼って、Vitis HLS 2022.1 の multiplier プロジェクトを作成した。今回は、multiplier プロジェクトの C シミュレーション、C コードの合成、C/RTL 協調シミュレーションを行った。

C シミュレーションを行った。結果を示す。
cocotb_23_220913.png

C コードの合成を行った。
Latency は 3 クロックだった。
cocotb_24_220913.png

合成された Verilog HDL ファイルだが、multiplier.v と multiplier_mul_mul_16s_16s_32_4_1.v が生成された。
今回は、2 つの Verilog HDL コードのみを使用する。
multiplier.v のポート宣言部分を確認した。ブロック・レベルのインターフェースは ap_ctrl_hs で入力は ap_none, 出力は、ap_vld だった。
cocotb_25_220913.png

C/RTL 協調シミュレーションを行った。
レイテンシは 3 クロックだった。
cocotb_26_220913.png

C/RTL 協調シミュレーションの波形を示す。
cocotb_27_220913.png

multiplier.v を貼っておく。

// ==============================================================
// RTL generated by Vitis HLS - High-Level Synthesis from C, C++ and OpenCL v2022.1 (64-bit)
// Version: 2022.1
// Copyright (C) Copyright 1986-2022 Xilinx, Inc. All Rights Reserved.
// 
// ===========================================================

`timescale 1 ns / 1 ps 

(* CORE_GENERATION_INFO="multiplier_multiplier,hls_ip_2022_1,{HLS_INPUT_TYPE=cxx,HLS_INPUT_FLOAT=0,HLS_INPUT_FIXED=0,HLS_INPUT_PART=xc7z020-clg400-1,HLS_INPUT_CLOCK=10.000000,HLS_INPUT_ARCH=others,HLS_SYN_CLOCK=2.150000,HLS_SYN_LAT=3,HLS_SYN_TPT=none,HLS_SYN_MEM=0,HLS_SYN_DSP=0,HLS_SYN_FF=4,HLS_SYN_LUT=25,HLS_VERSION=2022_1}" *)

module multiplier (
        ap_clk,
        ap_rst,
        ap_start,
        ap_done,
        ap_idle,
        ap_ready,
        a,
        b,
        c,
        c_ap_vld,
        ap_return
);

parameter    ap_ST_fsm_state1 = 4'd1;
parameter    ap_ST_fsm_state2 = 4'd2;
parameter    ap_ST_fsm_state3 = 4'd4;
parameter    ap_ST_fsm_state4 = 4'd8;

input   ap_clk;
input   ap_rst;
input   ap_start;
output   ap_done;
output   ap_idle;
output   ap_ready;
input  [15:0] a;
input  [15:0] b;
output  [31:0] c;
output   c_ap_vld;
output  [31:0] ap_return;

reg ap_done;
reg ap_idle;
reg ap_ready;
reg c_ap_vld;

(* fsm_encoding = "none" *) reg   [3:0] ap_CS_fsm;
wire    ap_CS_fsm_state1;
wire  signed [31:0] grp_fu_53_p2;
wire    ap_CS_fsm_state4;
reg   [3:0] ap_NS_fsm;
reg    ap_ST_fsm_state1_blk;
wire    ap_ST_fsm_state2_blk;
wire    ap_ST_fsm_state3_blk;
wire    ap_ST_fsm_state4_blk;
wire    ap_ce_reg;

// power-on initialization
initial begin
#0 ap_CS_fsm = 4'd1;
end

multiplier_mul_mul_16s_16s_32_4_1 #(
    .ID( 1 ),
    .NUM_STAGE( 4 ),
    .din0_WIDTH( 16 ),
    .din1_WIDTH( 16 ),
    .dout_WIDTH( 32 ))
mul_mul_16s_16s_32_4_1_U1(
    .clk(ap_clk),
    .reset(ap_rst),
    .din0(b),
    .din1(a),
    .ce(1'b1),
    .dout(grp_fu_53_p2)
);

always @ (posedge ap_clk) begin
    if (ap_rst == 1'b1) begin
        ap_CS_fsm <= ap_ST_fsm_state1;
    end else begin
        ap_CS_fsm <= ap_NS_fsm;
    end
end

always @ (*) begin
    if ((ap_start == 1'b0)) begin
        ap_ST_fsm_state1_blk = 1'b1;
    end else begin
        ap_ST_fsm_state1_blk = 1'b0;
    end
end

assign ap_ST_fsm_state2_blk = 1'b0;

assign ap_ST_fsm_state3_blk = 1'b0;

assign ap_ST_fsm_state4_blk = 1'b0;

always @ (*) begin
    if ((1'b1 == ap_CS_fsm_state4)) begin
        ap_done = 1'b1;
    end else begin
        ap_done = 1'b0;
    end
end

always @ (*) begin
    if (((ap_start == 1'b0) & (1'b1 == ap_CS_fsm_state1))) begin
        ap_idle = 1'b1;
    end else begin
        ap_idle = 1'b0;
    end
end

always @ (*) begin
    if ((1'b1 == ap_CS_fsm_state4)) begin
        ap_ready = 1'b1;
    end else begin
        ap_ready = 1'b0;
    end
end

always @ (*) begin
    if ((1'b1 == ap_CS_fsm_state4)) begin
        c_ap_vld = 1'b1;
    end else begin
        c_ap_vld = 1'b0;
    end
end

always @ (*) begin
    case (ap_CS_fsm)
        ap_ST_fsm_state1 : begin
            if (((ap_start == 1'b1) & (1'b1 == ap_CS_fsm_state1))) begin
                ap_NS_fsm = ap_ST_fsm_state2;
            end else begin
                ap_NS_fsm = ap_ST_fsm_state1;
            end
        end
        ap_ST_fsm_state2 : begin
            ap_NS_fsm = ap_ST_fsm_state3;
        end
        ap_ST_fsm_state3 : begin
            ap_NS_fsm = ap_ST_fsm_state4;
        end
        ap_ST_fsm_state4 : begin
            ap_NS_fsm = ap_ST_fsm_state1;
        end
        default : begin
            ap_NS_fsm = 'bx;
        end
    endcase
end

assign ap_CS_fsm_state1 = ap_CS_fsm[32'd0];

assign ap_CS_fsm_state4 = ap_CS_fsm[32'd3];

assign ap_return = 32'd0;

assign c = grp_fu_53_p2;

endmodule //multiplier


multiplier_mul_mul_16s_16s_32_4_1.v を貼っておく。

`timescale 1 ns / 1 ps

  module multiplier_mul_mul_16s_16s_32_4_1_DSP48_0(clk, rst, ce, a, b, p);
input clk;
input rst;
input ce;
input signed [16 - 1 : 0] a;
input signed [16 - 1 : 0] b;
output signed [32 - 1 : 0] p;

reg signed [32 - 1 : 0] p_reg; 

reg signed [16 - 1 : 0] a_reg; 
reg signed [16 - 1 : 0] b_reg; 

reg signed [32 - 1 : 0] p_reg_tmp; 

always @ (posedge clk) begin
    if (ce) begin
        a_reg <= a;
        b_reg <= b;
        p_reg_tmp <= a_reg * b_reg;
        p_reg <= p_reg_tmp;
    end
end

assign p = p_reg;

endmodule
`timescale 1 ns / 1 ps
module multiplier_mul_mul_16s_16s_32_4_1(
    clk,
    reset,
    ce,
    din0,
    din1,
    dout);

parameter ID = 32'd1;
parameter NUM_STAGE = 32'd1;
parameter din0_WIDTH = 32'd1;
parameter din1_WIDTH = 32'd1;
parameter dout_WIDTH = 32'd1;
input clk;
input reset;
input ce;
input[din0_WIDTH - 1:0] din0;
input[din1_WIDTH - 1:0] din1;
output[dout_WIDTH - 1:0] dout;



multiplier_mul_mul_16s_16s_32_4_1_DSP48_0 multiplier_mul_mul_16s_16s_32_4_1_DSP48_0_U(
    .clk( clk ),
    .rst( reset ),
    .ce( ce ),
    .a( din0 ),
    .b( din1 ),
    .p( dout ));

endmodule

  1. 2022年09月14日 04:23 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

自作回路を cocotb でシミュレーションする1(Vitis HLS で multiplier を作成1)

cocotb でサンプルをやってきたが、自作回路を cocotb でシミュレーションしてみようと思う。
AXI4 インターフェースの回路をシミュレーションしてみたいと思って、検索してみたところ、”AXI interface modules for Cocotb”を見つけた。これを使用すれば、AXI4 インターフェースのシミュレーションができそうだ。AXI4 Slave Bus Functional Model も作ってあるので、スレーブも問題ない。
AXI4 インターフェースの cocotb を使ったシミュレーションをしたいのだが、何分にも Makefile の書き方がよく分かっていないので、簡単な回路から cocotb でシミュレーションをしてみよう。
今回は、Vitis HLS 2022.1 で乗算器(mulitplier)を作成する。なお、ZYBO Z7-20 用とした。この乗算器を cocotb でシミュレーションしてみたい。

multiplier のソースコードとテストベンチを示す。
ソースコードの multiplier.cpp を示す。

// multiplier.cpp
// 2022/09/13 by marsee
//

#include <stdint.h>

int multiplier(int16_t a, int16_t b, int32_t *c){

    *c = a * b;

    return(0);
}


テストベンチの multiplier_tb.cpp を示す。

// multiplier_tb.cpp
// 2022/09/13 by marsee
//

#include <stdio.h>
#include <stdint.h>

int multiplier(int16_t a, int16_t b, int32_t *c);

int main(){
    int16_t a, b;
    int32_t c;

    a = 3;
    b = 4;

    multiplier(a, b, &c);
    printf("a = %d, b = %d, c = (a*b) = %d\n", a, b, c);

    return(0);
}


ZYBO Z7-20 用の Vitis HLS 2022.1 プロジェクトの multiplier を示す。
cocotb_22_220913.png
  1. 2022年09月13日 04:48 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

FPGAの部屋のまとめサイトの更新(2022年9月12日)

FPGAの部屋のまとめサイトを更新しました。
TVM_VTA”カテゴリを追加して、記事へのリンクをFPGAの部屋のまとめサイトにまとめました。
  1. 2022年09月12日 05:00 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:0

cocotb を試してみる3(examples/adder)

cocotb を試してみる2(シミュレーション波形を表示)”の続き。

Python で書いたコードをテストベンチとして使用できるテストベンチ環境の cocotb を使ってみたいということで、前回は、”cocotb を試してみる1”で実行したサンプルの波形を gtkwave で表示した。今回は cocotb を git clone して、examples の adder をやってみよう。

cocotb を git clone した。
git clone https://github.com/cocotb/cocotb.git
cocotb_12_220911.png

cocotb/examples/adder に移動した。
cd cocotb/examples/adder/
tree .

cocotb_13_220911.png

hdl/adder.sv から見ていく。
4 ビット長の加算で、dump.vcd に波形を出力する。
cocotb_17_220911.png

model/adder_model.py を見た。
Python で書かれた加算だった。
cocotb_18_220911.png

tests/test_adder.py を見た。
adder_basic_test() と adder_randomised_test() の 2 つの関数(テスト)があった。
adder_basic_test() は 5 と 10 を加算して、dut の X の値を adder_model() の結果と比較する。
adder_randomised_test() はランダムな値の加算を 10 回行う。こちらも dut の X の値を adder_model() の結果と比較する。
2 つのテスト関数の時間を進めるのは、

await Timer(2, units="ns")

のようだ。つまり、1 つのテストあたり 2 ns 時間が進むようだ。
cocotb_19_220911.png

tests/Makefile を見た。
icarus verilog が指定されていないので、make 時に指定する必要があるようだ。
cocotb_20_220911.png

tests ディレクトリに行って make を行った。
cd tests
make SIM=icarus

cocotb_14_220911.png

cocotb_15_220911.png

adder_basic_test() と adder_randomised_test() の 2 つの関数(テスト)共に PASS した。

シミュレーション実行後のファイルを見ると dump.vcd があったので、gtkwave で波形を確認する。
gtkwave dump.vcd
cocotb_16_220911.png

gtkwave の波形を示す。
なお、表示は Data Format を Decimal に変更してある。
cocotb_21_220911.png

最初の結果が adder_basic_test() の 5 + 10 で、その後は adder_randomised_test() の 10 個の加算が続くようだ。
全ての加算は 2 ns の間隔になっていた。

最後に make の結果を貼っておく。

(base) masaaki@masaaki-H110M4-M01:/media/masaaki/Ubuntu_Disk/Cocotb/cocotb/examples/adder/tests$ make SIM=icarus
rm -f results.xml
make -f Makefile results.xml
make[1]: ディレクトリ '/media/masaaki/Ubuntu_Disk/Cocotb/cocotb/examples/adder/tests' に入ります
mkdir -p sim_build
/usr/bin/iverilog -o sim_build/sim.vvp -D COCOTB_SIM=1 -s adder -f sim_build/cmds.f -g2012   /media/masaaki/Ubuntu_Disk/Cocotb/cocotb/examples/adder/tests/../hdl/adder.sv
rm -f results.xml
MODULE=test_adder TESTCASE= TOPLEVEL=adder TOPLEVEL_LANG=verilog \
         /usr/bin/vvp -M /home/masaaki/anaconda3/lib/python3.8/site-packages/cocotb/libs -m libcocotbvpi_icarus   sim_build/sim.vvp 
     -.--ns INFO     gpi                                ..mbed/gpi_embed.cpp:76   in set_program_name_in_venv        Did not detect Python virtual environment. Using system-wide Python interpreter
     -.--ns INFO     gpi                                ../gpi/GpiCommon.cpp:101  in gpi_print_registered_impl       VPI registered
     0.00ns INFO     cocotb                             Running on Icarus Verilog version 10.1 (stable)
     0.00ns INFO     cocotb                             Running tests with cocotb v1.7.0 from /home/masaaki/anaconda3/lib/python3.8/site-packages/cocotb
     0.00ns INFO     cocotb                             Seeding Python random module with 1662838789
     0.00ns INFO     cocotb.regression                  Found test test_adder.adder_basic_test
     0.00ns INFO     cocotb.regression                  Found test test_adder.adder_randomised_test
     0.00ns INFO     cocotb.regression                  running adder_basic_test (1/2)
                                                          Test for 5 + 10
VCD info: dumpfile dump.vcd opened for output.
     2.00ns INFO     cocotb.regression                  adder_basic_test passed
     2.00ns INFO     cocotb.regression                  running adder_randomised_test (2/2)
                                                          Test for adding 2 random numbers multiple times
    22.00ns INFO     cocotb.regression                  adder_randomised_test passed
    22.00ns INFO     cocotb.regression                  ******************************************************************************************
                                                        ** TEST                              STATUS  SIM TIME (ns)  REAL TIME (s)  RATIO (ns/s) **
                                                        ******************************************************************************************
                                                        ** test_adder.adder_basic_test        PASS           2.00           0.00       2616.21  **
                                                        ** test_adder.adder_randomised_test   PASS          20.00           0.00      19518.44  **
                                                        ******************************************************************************************
                                                        ** TESTS=2 PASS=2 FAIL=0 SKIP=0                     22.00           0.29         76.33  **
                                                        ******************************************************************************************
                                                        
make[1]: ディレクトリ '/media/masaaki/Ubuntu_Disk/Cocotb/cocotb/examples/adder/tests' から出ます

  1. 2022年09月11日 05:19 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

cocotb を試してみる2(シミュレーション波形を表示)

cocotb を試してみる1”の続き。

Python で書いたコードをテストベンチとして使用できるテストベンチ環境の cocotb を使ってみたいということで、前回は、cocotb のインストールと最初のサンプルをやってみて成功した。今回は、前回実行したサンプルの波形を gtkwave で表示した。

シミュレータには Icarus Verilog を使用しているので、VCD ファイルを出力させたい。
”cocotb’s documentation”の”Icarus Verilog/Waveforms”にやり方が書いてあった。
そうだ、Icarus Verilog は Verilog HDL コードに VCD コードに出力するように書くんだった。
”cocotb’s documentation”の”Icarus Verilog/Waveforms”のコードの一部を引用する。

// the "macro" to dump signals
`ifdef COCOTB_SIM
initial begin
  $dumpfile ("button_deb.vcd");
  $dumpvars (0, button_deb);
  #1;
end
`endif


これを dff.sv に追加する。
cocotb/cocotb”の README の dff.sv を引用して、VCD ファイルに波形を出力するコードを追加した dff.sv を貼る。
cocotb_9_220908.png

// dff.sv

`timescale 1us/1ns

module dff (
    output logic q,
    input logic clk, d
);

always @(posedge clk) begin
    q <= d;
end

`ifdef COCOTB_SIM
initial begin
  $dumpfile ("dff.vcd");
  $dumpvars (0, dff);
  #1;
end
`endif

endmodule


Makefile にも、シミュレータを指定する行を追加した。

SIM ?= icarus


cocotb/cocotb”の README の Makefile を引用して、現在の Makefile を貼った。
cocotb_8_220908.png

# Makefile

SIM ?= icarus

TOPLEVEL_LANG = verilog
VERILOG_SOURCES = $(shell pwd)/dff.sv
TOPLEVEL = dff
MODULE = test_dff

include $(shell cocotb-config --makefiles)/Makefile.sim


更にテストベンチの説明をする。
cocotb/cocotb”の README の test_dff.py を引用する。
cocotb_4_220908.png

”cocotb’s documentation”の”Creating a Test”によると、
”@cocotb.test() ”でテストする関数を指定しているようだ。
”.value = value”で信号に値を割り当てる。
”.value”で信号の値を取得できる。

これで VCD ファイルを出力する設定が終了したので、make を実行した。
make

実行後に dff_example ディレクトリを見ると dff.vcd が生成されていた。
cocotb_10_220908.png

gtkwave を起動して、dff.vcd を読み込ませる。
gtkwave dff.vcd
波形を表示するとクロックの立ち下がりで q が d をキャプチャしているのが分かる。
cocotb_11_220908.png
  1. 2022年09月10日 05:00 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

cocotb を試してみる1

テストベンチが Python で書かれた cocotb を試してみようと思う。
cocotb を知ったのは Adam Talyor さんの記事” MicroZed Chronicles: Getting Started with Cocotb”を読んだからだった。この記事を試してみようと思ったのだが、シミュレータに ModelSim を使っていた。ModelSim は持っていないので、そこで本家?の”cocotb/cocotb”の README のコードを試してみることにした。

cocotb のドキュメントは”docs.cocotb.org”にある。その翻訳の一部を引用する。

cocotbは、Pythonを使用してVHDL および SystemVerilog RTLを検証するためのCOroutineベースのCOsimulation TestBench環境です。


今回のシミュレータは icarus verilog を使用する。
まずは、icarus verilog をインストールするのだが、すでに gtkwave も含めてインストール済みだった。
cocotb_1_220908.png

インストールしていない場合は、”Icarus Verilogの導入とAND回路のシミュレーション”が参考になる。

さて、”cocotb/cocotb”の README を参照して、cocotb を Ubuntu 18.04 にインストールする。
pip install cocotb
cocotb_2_220908.png

インストール成功した。

cocotb/cocotb”の README のコードをコピー & ペーストして、/media/masaaki/Ubuntu_Disk/Cocotb/dff_example ディレクトリの下に dff.sv, test_dff.py, Makefile を作成した。
cocotb_3_220908.png

cocotb_4_220908.png

cocotb_5_220908.png

cocotb_6_220908.png

make をしてみよう。
make SIM=icarus
を実行した。
PASS した。
cocotb_7_220908.png

make 時のログを示す。

(base) masaaki@masaaki-H110M4-M01:/media/masaaki/Ubuntu_Disk/Cocotb/dff_example$ make SIM=icarus
rm -f results.xml
make -f Makefile results.xml
make[1]: ディレクトリ '/media/masaaki/Ubuntu_Disk/Cocotb/dff_example' に入ります
mkdir -p sim_build
/usr/bin/iverilog -o sim_build/sim.vvp -D COCOTB_SIM=1 -s dff -f sim_build/cmds.f -g2012   /media/masaaki/Ubuntu_Disk/Cocotb/dff_example/dff.sv
rm -f results.xml
MODULE=test_dff TESTCASE= TOPLEVEL=dff TOPLEVEL_LANG=verilog \
         /usr/bin/vvp -M /home/masaaki/anaconda3/lib/python3.8/site-packages/cocotb/libs -m libcocotbvpi_icarus   sim_build/sim.vvp 
     -.--ns INFO     gpi                                ..mbed/gpi_embed.cpp:76   in set_program_name_in_venv        Did not detect Python virtual environment. Using system-wide Python interpreter
     -.--ns INFO     gpi                                ../gpi/GpiCommon.cpp:101  in gpi_print_registered_impl       VPI registered
     0.00ns INFO     cocotb                             Running on Icarus Verilog version 10.1 (stable)
     0.00ns INFO     cocotb                             Running tests with cocotb v1.7.0 from /home/masaaki/anaconda3/lib/python3.8/site-packages/cocotb
     0.00ns INFO     cocotb                             Seeding Python random module with 1662639569
     0.00ns INFO     cocotb.regression                  Found test test_dff.test_dff_simple
     0.00ns INFO     cocotb.regression                  running test_dff_simple (1/1)
                                                          Test that d propagates to q
 95001.00ns INFO     cocotb.regression                  test_dff_simple passed
 95001.00ns INFO     cocotb.regression                  **************************************************************************************
                                                        ** TEST                          STATUS  SIM TIME (ns)  REAL TIME (s)  RATIO (ns/s) **
                                                        **************************************************************************************
                                                        ** test_dff.test_dff_simple       PASS       95001.00           0.00   33260690.68  **
                                                        **************************************************************************************
                                                        ** TESTS=1 PASS=1 FAIL=0 SKIP=0              95001.00           2.71      35015.19  **
                                                        **************************************************************************************
                                                        
make[1]: ディレクトリ '/media/masaaki/Ubuntu_Disk/Cocotb/dff_example' から出ます

  1. 2022年09月09日 03:58 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

Xilinx 社の Video IP を使ってブロック・デザインを作る4

Xilinx 社の Video IP を使ってブロック・デザインを作る3”の続き。

自分で作った IP を使用して画像を表示しているが、それを Xilinx 社の IP を使用して画像を表示してみたいということで、前回は、Jupyter Notebook の cam_disp2.ipynb を作成して実行したが、ディスプレイに表示される色が間違っていた。たぶん RGB のところ RBG になっていると思われる。今回は、ディスプレイに表示するソーベル・フィルタの後に AXI4-Stream Subset Converter を挿入して RGB を RBG に変換したところ、色が正常になった。

cam_disp2 ディレクトリの Vivado 2022.1 の cam_disp プロジェクトの cam_disp_bd ブロック・デザインに AXI4-Stream Subset Converter を挿入した。sobel_axis_RGB24_0 と v_axi4s_vid_out_0 の AXI4-Stream インターフェースの間に挿入した。
X_video_IP_14_220907.png

axis_subset_converter_1 の設定を示す。
X_video_IP_15_220907.png

TDATA Remap String に tdata[23:16],tdata[7:0],tdata[15:8] を入力して、RGB を RBG に入れ替えた。

これで論理合成、インプリメンテーション、ビットストリームの生成を行った。
Project Summary を示す。
X_video_IP_16_220907.png

ZYBO Z7-20 の PYNQ Linux を起動した。
Jupyter Notebook にアクセスするために Chrome ブラウザで

http://192.168.3.17:9090/tree/my_project/cam_disp2

にアクセスした。

cam_disp.bit と cam_disp.hwh を削除した。

cam_disp2/cam_disp.runs/impl_1/cam_disp_bd_wrapper.bit と cam_disp2/cam_disp.gen/sources_1/bd/cam_disp_bd/hw_handoff/cam_disp_bd.hwh をアップロードした。

cam_disp_bd_wrapper.bit と cam_disp_bd.hwh の名前を cam_disp.bit と cam_disp.hwh に変更した。

cam_disp2.ipynb を起動して実行していくと、カメラ画像がディスプレイに表示された。
X_video_IP_17_220908.png

今度は色が正常になった。。。
  1. 2022年09月08日 05:07 |
  2. IP
  3. | トラックバック:0
  4. | コメント:0

Xilinx 社の Video IP を使ってブロック・デザインを作る3

Xilinx 社の Video IP を使ってブロック・デザインを作る2”の続き。

自分で作った IP を使用して画像を表示しているが、それを Xilinx 社の IP を使用して画像を表示してみたいということで、前回は、実際に v_axi4s_vid_out と v_tc を配線して、論理合成、インプリメンテーション、ビットストリームの生成を行った。今回は、Jupyter Notebook の cam_disp2.ipynb を作成して実行したが、ディスプレイに表示される色が間違っていた。たぶん RGB のところ RBG になっていると思われる。

ZYBO Z7-20 の PYNQ Linux で起動される Jupyter Notebook で cam_disp2 フォルダを新規作成した。

cam_disp2 フォルダに Jupyter Notebook の cam_disp2.ipynb ファイルを作成した。これは、以前から使用してる cam_disp.ipynb の bitmap_disp_cont_axis の処理コードを抜いて、VTC の処理コードを追加したものだ。
Video Timing Controller v6.2 LogiCORE IP Product Guide PG016 February 26, 2021”や”PYNQ-Z1 > HDMI > TMDSを使ったHDMI出力 (Tutorialの実行) > カラーパターンの表示”によると、VTC に起動用コマンドを入れる必要があるようだ。

Video Timing Controller v6.2 LogiCORE IP Product Guide PG016 February 26, 2021”の”Table 2-4: Control Register (Address Offset 0x0000) (Cont’d)”を引用する。
X_video_IP_12_220907.png

Table 2-4 によると、少なくとも、bit2 の GEN_ENABLE を 1 にする必要がある。
よって、Jupyter Notebook に VTC の 0 番地に 4 を書くコードを追加した。

# VTC enable
vtc.write(0x0, 0x04) # Generation Enable


cam_disp2.ipynb の一部を示す。

vtc = cam_disp.v_tc_0

を追加してある。
X_video_IP_10_220907.png

cam_disp2/cam_disp.runs/impl_1/cam_disp_bd_wrapper.bit と cam_disp2/cam_disp.gen/sources_1/bd/cam_disp_bd/hw_handoff/cam_disp_bd.hwh をアップロードした。

cam_disp_bd_wrapper.bit と cam_disp_bd.hwh の名前を cam_disp.bit と cam_disp.hwh に変更した。

cam_disp2.ipynb ファイルを実行していくと、Jupyter Notebook にキャプチャするカメラ画像は問題なかった。
X_video_IP_11_220907.png

ただし、ディスプレイに表示されるカメラ画像の色がおかしかった。
画面で青いはずの椅子の背もたれが緑になっている。どうやら、Green と Blue が反転しているようだ。つまり、RGB でなく RBG になっているようだ。
X_video_IP_13_220907.jpg

次回は、色を修正する。

最後に cam_disp2.ipynb の Python コード部分を貼っておく。

#!/usr/bin/env python
# coding: utf-8

# cam_disp2<br>
# 2022/09/06 by marsee

# In[1]:
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
get_ipython().run_line_magic('matplotlib', 'inline')
from pynq import allocate, Overlay
import time
import cv2

# In[2]:
# Download bitstream
cam_disp = Overlay("./cam_disp.bit")

# In[3]:
# Generate an instance for each IP
vflip_dmaw = cam_disp.vflip_dma_write_0
paracam_inf = cam_disp.paracam_inf_axis_0
vtc = cam_disp.v_tc_0
cam_iic = cam_disp.axi_iic_0
sobel0 = cam_disp.sobel_axis_RGB24_0
sobel1 = cam_disp.sobel_axis_RGB24_1
dma2axis30 = cam_disp.DMA2axis_3buf_0
dma2axis31 = cam_disp.DMA2axis_3buf_1
axis2dma = cam_disp.axis2DMA4dwc_0

# In[4]:
def cam_i2c_init(cam_iic):
    cam_iic.write(0x100, 0x2)   # reset tx fifo ,address is 0x100, i2c_control_reg
    cam_iic.write(0x100, 0x1)   # enable i2c

# In[5]:
def cam_i2x_write_sync():
    time.sleep(0.001) # 1ms wait

# In[6]:
def cam_i2c_write(cam_iic, device_addr, write_addr, write_data):
    cam_iic.write(0x108, 0x100 | (device_addr & 0xfe))   # Slave IIC Write Address, address is 0x108, i2c_tx_fifo
    cam_iic.write(0x108, (write_addr >> 8) & 0xff)      # address upper byte
    cam_iic.write(0x108, write_addr & 0xff) # address lower byte
    cam_iic.write(0x108, 0x200 | (write_data & 0xff))   # data
    cam_i2x_write_sync()

# In[7]:
def cam_reg_set(cam_iic, device_addr):
    cam_i2c_write(cam_iic, device_addr, 0x3103, 0x93)
    cam_i2c_write(cam_iic, device_addr, 0x3008, 0x82)
    cam_i2c_write(cam_iic, device_addr, 0x3017, 0x7f)
    cam_i2c_write(cam_iic, device_addr, 0x3018, 0xfc)
    cam_i2c_write(cam_iic, device_addr, 0x3810, 0xc2)
    cam_i2c_write(cam_iic, device_addr, 0x3615, 0xf0)
    cam_i2c_write(cam_iic, device_addr, 0x3000, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3001, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3002, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3003, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3000, 0xf8)
    cam_i2c_write(cam_iic, device_addr, 0x3001, 0x48)
    cam_i2c_write(cam_iic, device_addr, 0x3002, 0x5c)
    cam_i2c_write(cam_iic, device_addr, 0x3003, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x3004, 0x07)
    cam_i2c_write(cam_iic, device_addr, 0x3005, 0xb7)
    cam_i2c_write(cam_iic, device_addr, 0x3006, 0x43)
    cam_i2c_write(cam_iic, device_addr, 0x3007, 0x37)
    cam_i2c_write(cam_iic, device_addr, 0x3011, 0x08) # 0x08 - 15fps, 0x10 - 30fps
    cam_i2c_write(cam_iic, device_addr, 0x3010, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x460c, 0x22)
    cam_i2c_write(cam_iic, device_addr, 0x3815, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x370d, 0x06)
    cam_i2c_write(cam_iic, device_addr, 0x370c, 0xa0)
    cam_i2c_write(cam_iic, device_addr, 0x3602, 0xfc)
    cam_i2c_write(cam_iic, device_addr, 0x3612, 0xff)
    cam_i2c_write(cam_iic, device_addr, 0x3634, 0xc0)
    cam_i2c_write(cam_iic, device_addr, 0x3613, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3605, 0x7c)
    cam_i2c_write(cam_iic, device_addr, 0x3621, 0x09)
    cam_i2c_write(cam_iic, device_addr, 0x3622, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3604, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x3603, 0xa7)
    cam_i2c_write(cam_iic, device_addr, 0x3603, 0x27)
    cam_i2c_write(cam_iic, device_addr, 0x4000, 0x21)
    cam_i2c_write(cam_iic, device_addr, 0x401d, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x3600, 0x54)
    cam_i2c_write(cam_iic, device_addr, 0x3605, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x3606, 0x3f)
    cam_i2c_write(cam_iic, device_addr, 0x3c01, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5000, 0x4f)
    cam_i2c_write(cam_iic, device_addr, 0x5020, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x5181, 0x79)
    cam_i2c_write(cam_iic, device_addr, 0x5182, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5185, 0x22)
    cam_i2c_write(cam_iic, device_addr, 0x5197, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x5001, 0xff)
    cam_i2c_write(cam_iic, device_addr, 0x5500, 0x0a)
    cam_i2c_write(cam_iic, device_addr, 0x5504, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5505, 0x7f)
    cam_i2c_write(cam_iic, device_addr, 0x5080, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x300e, 0x18)
    cam_i2c_write(cam_iic, device_addr, 0x4610, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x471d, 0x05)
    cam_i2c_write(cam_iic, device_addr, 0x4708, 0x06)
    cam_i2c_write(cam_iic, device_addr, 0x3710, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x3632, 0x41)
    cam_i2c_write(cam_iic, device_addr, 0x3702, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x3620, 0x37)
    cam_i2c_write(cam_iic, device_addr, 0x3631, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x3808, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x3809, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x380a, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x380b, 0xe0)
    cam_i2c_write(cam_iic, device_addr, 0x380e, 0x07)
    cam_i2c_write(cam_iic, device_addr, 0x380f, 0xd0)
    cam_i2c_write(cam_iic, device_addr, 0x501f, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5000, 0x4f)
    cam_i2c_write(cam_iic, device_addr, 0x4300, 0x61) # RGB565
    cam_i2c_write(cam_iic, device_addr, 0x3503, 0x07)
    cam_i2c_write(cam_iic, device_addr, 0x3501, 0x73)
    cam_i2c_write(cam_iic, device_addr, 0x3502, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x350b, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3503, 0x07)
    cam_i2c_write(cam_iic, device_addr, 0x3824, 0x11)
    cam_i2c_write(cam_iic, device_addr, 0x3501, 0x1e)
    cam_i2c_write(cam_iic, device_addr, 0x3502, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x350b, 0x7f)
    cam_i2c_write(cam_iic, device_addr, 0x380c, 0x0c)
    cam_i2c_write(cam_iic, device_addr, 0x380d, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x380e, 0x03)
    cam_i2c_write(cam_iic, device_addr, 0x380f, 0xe8)
    cam_i2c_write(cam_iic, device_addr, 0x3a0d, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x3a0e, 0x03)
    cam_i2c_write(cam_iic, device_addr, 0x3818, 0xc1)
    cam_i2c_write(cam_iic, device_addr, 0x3705, 0xdb)
    cam_i2c_write(cam_iic, device_addr, 0x370a, 0x81)
    cam_i2c_write(cam_iic, device_addr, 0x3801, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x3621, 0xc7)
    cam_i2c_write(cam_iic, device_addr, 0x3801, 0x50)
    cam_i2c_write(cam_iic, device_addr, 0x3803, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x3827, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x3810, 0xc0)
    cam_i2c_write(cam_iic, device_addr, 0x3804, 0x05)
    cam_i2c_write(cam_iic, device_addr, 0x3805, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5682, 0x05)
    cam_i2c_write(cam_iic, device_addr, 0x5683, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3806, 0x03)
    cam_i2c_write(cam_iic, device_addr, 0x3807, 0xc0)
    cam_i2c_write(cam_iic, device_addr, 0x5686, 0x03)
    cam_i2c_write(cam_iic, device_addr, 0x5687, 0xc0)
    cam_i2c_write(cam_iic, device_addr, 0x3a00, 0x78)
    cam_i2c_write(cam_iic, device_addr, 0x3a1a, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x3a13, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x3a18, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3a19, 0x7c)
    cam_i2c_write(cam_iic, device_addr, 0x3a08, 0x12)
    cam_i2c_write(cam_iic, device_addr, 0x3a09, 0xc0)
    cam_i2c_write(cam_iic, device_addr, 0x3a0a, 0x0f)
    cam_i2c_write(cam_iic, device_addr, 0x3a0b, 0xa0)
    cam_i2c_write(cam_iic, device_addr, 0x3004, 0xff)
    cam_i2c_write(cam_iic, device_addr, 0x350c, 0x07)
    cam_i2c_write(cam_iic, device_addr, 0x350d, 0xd0)
    cam_i2c_write(cam_iic, device_addr, 0x3500, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3501, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3502, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x350a, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x350b, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3503, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x528a, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x528b, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x528c, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x528d, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x528e, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x528f, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5290, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5292, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5293, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x5294, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5295, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x5296, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5297, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x5298, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5299, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x529a, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x529b, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x529c, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x529d, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x529e, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x529f, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x3a0f, 0x3c)
    cam_i2c_write(cam_iic, device_addr, 0x3a10, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x3a1b, 0x3c)
    cam_i2c_write(cam_iic, device_addr, 0x3a1e, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x3a11, 0x70)
    cam_i2c_write(cam_iic, device_addr, 0x3a1f, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x3030, 0x0b)
    cam_i2c_write(cam_iic, device_addr, 0x3a02, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3a03, 0x7d)
    cam_i2c_write(cam_iic, device_addr, 0x3a04, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3a14, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3a15, 0x7d)
    cam_i2c_write(cam_iic, device_addr, 0x3a16, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3a00, 0x78)
    cam_i2c_write(cam_iic, device_addr, 0x3a08, 0x09)
    cam_i2c_write(cam_iic, device_addr, 0x3a09, 0x60)
    cam_i2c_write(cam_iic, device_addr, 0x3a0a, 0x07)
    cam_i2c_write(cam_iic, device_addr, 0x3a0b, 0xd0)
    cam_i2c_write(cam_iic, device_addr, 0x3a0d, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x3a0e, 0x06)
    cam_i2c_write(cam_iic, device_addr, 0x5193, 0x70)
    cam_i2c_write(cam_iic, device_addr, 0x3620, 0x57)
    cam_i2c_write(cam_iic, device_addr, 0x3703, 0x98)
    cam_i2c_write(cam_iic, device_addr, 0x3704, 0x1c)
    cam_i2c_write(cam_iic, device_addr, 0x589b, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x589a, 0xc5)
    cam_i2c_write(cam_iic, device_addr, 0x528a, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x528b, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x528c, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x528d, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x528e, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x528f, 0x28)
    cam_i2c_write(cam_iic, device_addr, 0x5290, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x5292, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5293, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5294, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5295, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x5296, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5297, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x5298, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5299, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x529a, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x529b, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x529c, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x529d, 0x28)
    cam_i2c_write(cam_iic, device_addr, 0x529e, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x529f, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x5282, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5300, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5301, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5302, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5303, 0x7c)
    cam_i2c_write(cam_iic, device_addr, 0x530c, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x530d, 0x0c)
    cam_i2c_write(cam_iic, device_addr, 0x530e, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x530f, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5310, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5311, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5308, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5309, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x5304, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5305, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x5306, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5307, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5314, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x5315, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5319, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x5316, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5317, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x5318, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x5380, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x5381, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5382, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5383, 0x4e)
    cam_i2c_write(cam_iic, device_addr, 0x5384, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5385, 0x0f)
    cam_i2c_write(cam_iic, device_addr, 0x5386, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5387, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5388, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x5389, 0x15)
    cam_i2c_write(cam_iic, device_addr, 0x538a, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x538b, 0x31)
    cam_i2c_write(cam_iic, device_addr, 0x538c, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x538d, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x538e, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x538f, 0x0f)
    cam_i2c_write(cam_iic, device_addr, 0x5390, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5391, 0xab)
    cam_i2c_write(cam_iic, device_addr, 0x5392, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5393, 0xa2)
    cam_i2c_write(cam_iic, device_addr, 0x5394, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x5480, 0x14)
    cam_i2c_write(cam_iic, device_addr, 0x5481, 0x21)
    cam_i2c_write(cam_iic, device_addr, 0x5482, 0x36)
    cam_i2c_write(cam_iic, device_addr, 0x5483, 0x57)
    cam_i2c_write(cam_iic, device_addr, 0x5484, 0x65)
    cam_i2c_write(cam_iic, device_addr, 0x5485, 0x71)
    cam_i2c_write(cam_iic, device_addr, 0x5486, 0x7d)
    cam_i2c_write(cam_iic, device_addr, 0x5487, 0x87)
    cam_i2c_write(cam_iic, device_addr, 0x5488, 0x91)
    cam_i2c_write(cam_iic, device_addr, 0x5489, 0x9a)
    cam_i2c_write(cam_iic, device_addr, 0x548a, 0xaa)
    cam_i2c_write(cam_iic, device_addr, 0x548b, 0xb8)
    cam_i2c_write(cam_iic, device_addr, 0x548c, 0xcd)
    cam_i2c_write(cam_iic, device_addr, 0x548d, 0xdd)
    cam_i2c_write(cam_iic, device_addr, 0x548e, 0xea)
    cam_i2c_write(cam_iic, device_addr, 0x548f, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5490, 0x05)
    cam_i2c_write(cam_iic, device_addr, 0x5491, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5492, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x5493, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5494, 0x03)
    cam_i2c_write(cam_iic, device_addr, 0x5495, 0x60)
    cam_i2c_write(cam_iic, device_addr, 0x5496, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x5497, 0xb8)
    cam_i2c_write(cam_iic, device_addr, 0x5498, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x5499, 0x86)
    cam_i2c_write(cam_iic, device_addr, 0x549a, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x549b, 0x5b)
    cam_i2c_write(cam_iic, device_addr, 0x549c, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x549d, 0x3b)
    cam_i2c_write(cam_iic, device_addr, 0x549e, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x549f, 0x1c)
    cam_i2c_write(cam_iic, device_addr, 0x54a0, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x54a1, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x54a2, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x54a3, 0xed)
    cam_i2c_write(cam_iic, device_addr, 0x54a4, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x54a5, 0xc5)
    cam_i2c_write(cam_iic, device_addr, 0x54a6, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x54a7, 0xa5)
    cam_i2c_write(cam_iic, device_addr, 0x54a8, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x54a9, 0x6c)
    cam_i2c_write(cam_iic, device_addr, 0x54aa, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x54ab, 0x41)
    cam_i2c_write(cam_iic, device_addr, 0x54ac, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x54ad, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x54ae, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x54af, 0x16)
    cam_i2c_write(cam_iic, device_addr, 0x3406, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5192, 0x04) # 0x04
    cam_i2c_write(cam_iic, device_addr, 0x5191, 0xf8) # 0xf8
    cam_i2c_write(cam_iic, device_addr, 0x5193, 0x70)
    cam_i2c_write(cam_iic, device_addr, 0x5194, 0xf0)
    cam_i2c_write(cam_iic, device_addr, 0x5195, 0xf0)
    cam_i2c_write(cam_iic, device_addr, 0x518d, 0x3d)
    cam_i2c_write(cam_iic, device_addr, 0x518f, 0x54)
    cam_i2c_write(cam_iic, device_addr, 0x518e, 0x3d)
    cam_i2c_write(cam_iic, device_addr, 0x5190, 0x54)
    cam_i2c_write(cam_iic, device_addr, 0x518b, 0xc0)
    cam_i2c_write(cam_iic, device_addr, 0x518c, 0xbd)
    cam_i2c_write(cam_iic, device_addr, 0x5187, 0x18)
    cam_i2c_write(cam_iic, device_addr, 0x5188, 0x18)
    cam_i2c_write(cam_iic, device_addr, 0x5189, 0x6e)
    cam_i2c_write(cam_iic, device_addr, 0x518a, 0x68)
    cam_i2c_write(cam_iic, device_addr, 0x5186, 0x1c)
    cam_i2c_write(cam_iic, device_addr, 0x5181, 0x50)
    cam_i2c_write(cam_iic, device_addr, 0x5184, 0x25)
    cam_i2c_write(cam_iic, device_addr, 0x5182, 0x11)
    cam_i2c_write(cam_iic, device_addr, 0x5183, 0x14)
    cam_i2c_write(cam_iic, device_addr, 0x5184, 0x25)
    cam_i2c_write(cam_iic, device_addr, 0x5185, 0x24)
    cam_i2c_write(cam_iic, device_addr, 0x5025, 0x82)
    cam_i2c_write(cam_iic, device_addr, 0x5583, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x5584, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x5580, 0x02) # 0x02
    cam_i2c_write(cam_iic, device_addr, 0x3633, 0x07)
    cam_i2c_write(cam_iic, device_addr, 0x3702, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x3703, 0xb2)
    cam_i2c_write(cam_iic, device_addr, 0x3704, 0x18)
    cam_i2c_write(cam_iic, device_addr, 0x370b, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x370d, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x3620, 0x52)
    cam_i2c_write(cam_iic, device_addr, 0x3c00, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x5001, 0xFF)
    cam_i2c_write(cam_iic, device_addr, 0x5282, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5300, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5301, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5302, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5303, 0x7c)
    cam_i2c_write(cam_iic, device_addr, 0x530c, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x530d, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x530e, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x530f, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5310, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5311, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5308, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5309, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x5304, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5305, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x5306, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5307, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5314, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x5315, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5319, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x5316, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5317, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5318, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x5500, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5502, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5503, 0x06)
    cam_i2c_write(cam_iic, device_addr, 0x5504, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5505, 0x7f)
    cam_i2c_write(cam_iic, device_addr, 0x5025, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5300, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5301, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5302, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5303, 0x7c)
    cam_i2c_write(cam_iic, device_addr, 0x530c, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x530d, 0x0c)
    cam_i2c_write(cam_iic, device_addr, 0x530e, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x530f, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5310, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5311, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5308, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5309, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x5304, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5305, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x5306, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5307, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5314, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x5315, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5319, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x5316, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5317, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x5318, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x5380, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x5381, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5382, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5383, 0x1f)
    cam_i2c_write(cam_iic, device_addr, 0x5384, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5385, 0x06)
    cam_i2c_write(cam_iic, device_addr, 0x5386, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5387, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5388, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5389, 0xE1)
    cam_i2c_write(cam_iic, device_addr, 0x538A, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x538B, 0x2B)
    cam_i2c_write(cam_iic, device_addr, 0x538C, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x538D, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x538E, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x538F, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5390, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5391, 0xB3)
    cam_i2c_write(cam_iic, device_addr, 0x5392, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5393, 0xA6)
    cam_i2c_write(cam_iic, device_addr, 0x5394, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x5480, 0xd)
    cam_i2c_write(cam_iic, device_addr, 0x5481, 0x18)
    cam_i2c_write(cam_iic, device_addr, 0x5482, 0x2a)
    cam_i2c_write(cam_iic, device_addr, 0x5483, 0x49)
    cam_i2c_write(cam_iic, device_addr, 0x5484, 0x56)
    cam_i2c_write(cam_iic, device_addr, 0x5485, 0x62)
    cam_i2c_write(cam_iic, device_addr, 0x5486, 0x6c)
    cam_i2c_write(cam_iic, device_addr, 0x5487, 0x76)
    cam_i2c_write(cam_iic, device_addr, 0x5488, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5489, 0x88)
    cam_i2c_write(cam_iic, device_addr, 0x548a, 0x96)
    cam_i2c_write(cam_iic, device_addr, 0x548b, 0xa2)
    cam_i2c_write(cam_iic, device_addr, 0x548c, 0xb8)
    cam_i2c_write(cam_iic, device_addr, 0x548d, 0xcc)
    cam_i2c_write(cam_iic, device_addr, 0x548e, 0xe0)
    cam_i2c_write(cam_iic, device_addr, 0x548f, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5490, 0x3)
    cam_i2c_write(cam_iic, device_addr, 0x5491, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x5492, 0x3)
    cam_i2c_write(cam_iic, device_addr, 0x5493, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x5494, 0x2)
    cam_i2c_write(cam_iic, device_addr, 0x5495, 0xa0)
    cam_i2c_write(cam_iic, device_addr, 0x5496, 0x2)
    cam_i2c_write(cam_iic, device_addr, 0x5497, 0x48)
    cam_i2c_write(cam_iic, device_addr, 0x5498, 0x2)
    cam_i2c_write(cam_iic, device_addr, 0x5499, 0x26)
    cam_i2c_write(cam_iic, device_addr, 0x549a, 0x2)
    cam_i2c_write(cam_iic, device_addr, 0x549b, 0xb)
    cam_i2c_write(cam_iic, device_addr, 0x549c, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x549d, 0xee)
    cam_i2c_write(cam_iic, device_addr, 0x549e, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x549f, 0xd8)
    cam_i2c_write(cam_iic, device_addr, 0x54a0, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x54a1, 0xc7)
    cam_i2c_write(cam_iic, device_addr, 0x54a2, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x54a3, 0xb3)
    cam_i2c_write(cam_iic, device_addr, 0x54a4, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x54a5, 0x90)
    cam_i2c_write(cam_iic, device_addr, 0x54a6, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x54a7, 0x62)
    cam_i2c_write(cam_iic, device_addr, 0x54a8, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x54a9, 0x27)
    cam_i2c_write(cam_iic, device_addr, 0x54aa, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x54ab, 0x09)
    cam_i2c_write(cam_iic, device_addr, 0x54ac, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x54ad, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x54ae, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x54af, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x54b0, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x54b1, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x54b2, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x54b3, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x54b4, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x54b5, 0xf0)
    cam_i2c_write(cam_iic, device_addr, 0x54b6, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x54b7, 0xdf)
    cam_i2c_write(cam_iic, device_addr, 0x5583, 0x5d)
    cam_i2c_write(cam_iic, device_addr, 0x5584, 0x5d)
    cam_i2c_write(cam_iic, device_addr, 0x5580, 0x06)
    cam_i2c_write(cam_iic, device_addr, 0x5587, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5588, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x558a, 0x09)
    cam_i2c_write(cam_iic, device_addr, 0x5589, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5000, 0xcf)
    cam_i2c_write(cam_iic, device_addr, 0x5800, 0x48)
    cam_i2c_write(cam_iic, device_addr, 0x5801, 0x31)
    cam_i2c_write(cam_iic, device_addr, 0x5802, 0x21)
    cam_i2c_write(cam_iic, device_addr, 0x5803, 0x1b)
    cam_i2c_write(cam_iic, device_addr, 0x5804, 0x1a)
    cam_i2c_write(cam_iic, device_addr, 0x5805, 0x1e)
    cam_i2c_write(cam_iic, device_addr, 0x5806, 0x29)
    cam_i2c_write(cam_iic, device_addr, 0x5807, 0x38)
    cam_i2c_write(cam_iic, device_addr, 0x5808, 0x26)
    cam_i2c_write(cam_iic, device_addr, 0x5809, 0x17)
    cam_i2c_write(cam_iic, device_addr, 0x580a, 0x11)
    cam_i2c_write(cam_iic, device_addr, 0x580b, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x580c, 0xd)
    cam_i2c_write(cam_iic, device_addr, 0x580d, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x580e, 0x13)
    cam_i2c_write(cam_iic, device_addr, 0x580f, 0x1a)
    cam_i2c_write(cam_iic, device_addr, 0x5810, 0x15)
    cam_i2c_write(cam_iic, device_addr, 0x5811, 0xd)
    cam_i2c_write(cam_iic, device_addr, 0x5812, 0x8)
    cam_i2c_write(cam_iic, device_addr, 0x5813, 0x5)
    cam_i2c_write(cam_iic, device_addr, 0x5814, 0x4)
    cam_i2c_write(cam_iic, device_addr, 0x5815, 0x5)
    cam_i2c_write(cam_iic, device_addr, 0x5816, 0x9)
    cam_i2c_write(cam_iic, device_addr, 0x5817, 0xd)
    cam_i2c_write(cam_iic, device_addr, 0x5818, 0x11)
    cam_i2c_write(cam_iic, device_addr, 0x5819, 0xa)
    cam_i2c_write(cam_iic, device_addr, 0x581a, 0x4)
    cam_i2c_write(cam_iic, device_addr, 0x581b, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x581c, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x581d, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x581e, 0x6)
    cam_i2c_write(cam_iic, device_addr, 0x581f, 0x9)
    cam_i2c_write(cam_iic, device_addr, 0x5820, 0x12)
    cam_i2c_write(cam_iic, device_addr, 0x5821, 0xb)
    cam_i2c_write(cam_iic, device_addr, 0x5822, 0x4)
    cam_i2c_write(cam_iic, device_addr, 0x5823, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x5824, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x5825, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x5826, 0x6)
    cam_i2c_write(cam_iic, device_addr, 0x5827, 0xa)
    cam_i2c_write(cam_iic, device_addr, 0x5828, 0x17)
    cam_i2c_write(cam_iic, device_addr, 0x5829, 0xf)
    cam_i2c_write(cam_iic, device_addr, 0x582a, 0x9)
    cam_i2c_write(cam_iic, device_addr, 0x582b, 0x6)
    cam_i2c_write(cam_iic, device_addr, 0x582c, 0x5)
    cam_i2c_write(cam_iic, device_addr, 0x582d, 0x6)
    cam_i2c_write(cam_iic, device_addr, 0x582e, 0xa)
    cam_i2c_write(cam_iic, device_addr, 0x582f, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x5830, 0x28)
    cam_i2c_write(cam_iic, device_addr, 0x5831, 0x1a)
    cam_i2c_write(cam_iic, device_addr, 0x5832, 0x11)
    cam_i2c_write(cam_iic, device_addr, 0x5833, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x5834, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x5835, 0xf)
    cam_i2c_write(cam_iic, device_addr, 0x5836, 0x15)
    cam_i2c_write(cam_iic, device_addr, 0x5837, 0x1d)
    cam_i2c_write(cam_iic, device_addr, 0x5838, 0x6e)
    cam_i2c_write(cam_iic, device_addr, 0x5839, 0x39)
    cam_i2c_write(cam_iic, device_addr, 0x583a, 0x27)
    cam_i2c_write(cam_iic, device_addr, 0x583b, 0x1f)
    cam_i2c_write(cam_iic, device_addr, 0x583c, 0x1e)
    cam_i2c_write(cam_iic, device_addr, 0x583d, 0x23)
    cam_i2c_write(cam_iic, device_addr, 0x583e, 0x2f)
    cam_i2c_write(cam_iic, device_addr, 0x583f, 0x41)
    cam_i2c_write(cam_iic, device_addr, 0x5840, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x5841, 0xc)
    cam_i2c_write(cam_iic, device_addr, 0x5842, 0xd)
    cam_i2c_write(cam_iic, device_addr, 0x5843, 0xc)
    cam_i2c_write(cam_iic, device_addr, 0x5844, 0xc)
    cam_i2c_write(cam_iic, device_addr, 0x5845, 0xc)
    cam_i2c_write(cam_iic, device_addr, 0x5846, 0xc)
    cam_i2c_write(cam_iic, device_addr, 0x5847, 0xc)
    cam_i2c_write(cam_iic, device_addr, 0x5848, 0xd)
    cam_i2c_write(cam_iic, device_addr, 0x5849, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x584a, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x584b, 0xa)
    cam_i2c_write(cam_iic, device_addr, 0x584c, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x584d, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x584e, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x584f, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5850, 0x11)
    cam_i2c_write(cam_iic, device_addr, 0x5851, 0xa)
    cam_i2c_write(cam_iic, device_addr, 0x5852, 0xf)
    cam_i2c_write(cam_iic, device_addr, 0x5853, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x5854, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5855, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5856, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5857, 0xa)
    cam_i2c_write(cam_iic, device_addr, 0x5858, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x5859, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x585a, 0xf)
    cam_i2c_write(cam_iic, device_addr, 0x585b, 0xf)
    cam_i2c_write(cam_iic, device_addr, 0x585c, 0xf)
    cam_i2c_write(cam_iic, device_addr, 0x585d, 0xa)
    cam_i2c_write(cam_iic, device_addr, 0x585e, 0x9)
    cam_i2c_write(cam_iic, device_addr, 0x585f, 0xd)
    cam_i2c_write(cam_iic, device_addr, 0x5860, 0xc)
    cam_i2c_write(cam_iic, device_addr, 0x5861, 0xb)
    cam_i2c_write(cam_iic, device_addr, 0x5862, 0xd)
    cam_i2c_write(cam_iic, device_addr, 0x5863, 0x7)
    cam_i2c_write(cam_iic, device_addr, 0x5864, 0x17)
    cam_i2c_write(cam_iic, device_addr, 0x5865, 0x14)
    cam_i2c_write(cam_iic, device_addr, 0x5866, 0x18)
    cam_i2c_write(cam_iic, device_addr, 0x5867, 0x18)
    cam_i2c_write(cam_iic, device_addr, 0x5868, 0x16)
    cam_i2c_write(cam_iic, device_addr, 0x5869, 0x12)
    cam_i2c_write(cam_iic, device_addr, 0x586a, 0x1b)
    cam_i2c_write(cam_iic, device_addr, 0x586b, 0x1a)
    cam_i2c_write(cam_iic, device_addr, 0x586c, 0x16)
    cam_i2c_write(cam_iic, device_addr, 0x586d, 0x16)
    cam_i2c_write(cam_iic, device_addr, 0x586e, 0x18)
    cam_i2c_write(cam_iic, device_addr, 0x586f, 0x1f)
    cam_i2c_write(cam_iic, device_addr, 0x5870, 0x1c)
    cam_i2c_write(cam_iic, device_addr, 0x5871, 0x16)
    cam_i2c_write(cam_iic, device_addr, 0x5872, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5873, 0xf)
    cam_i2c_write(cam_iic, device_addr, 0x5874, 0x13)
    cam_i2c_write(cam_iic, device_addr, 0x5875, 0x1c)
    cam_i2c_write(cam_iic, device_addr, 0x5876, 0x1e)
    cam_i2c_write(cam_iic, device_addr, 0x5877, 0x17)
    cam_i2c_write(cam_iic, device_addr, 0x5878, 0x11)
    cam_i2c_write(cam_iic, device_addr, 0x5879, 0x11)
    cam_i2c_write(cam_iic, device_addr, 0x587a, 0x14)
    cam_i2c_write(cam_iic, device_addr, 0x587b, 0x1e)
    cam_i2c_write(cam_iic, device_addr, 0x587c, 0x1c)
    cam_i2c_write(cam_iic, device_addr, 0x587d, 0x1c)
    cam_i2c_write(cam_iic, device_addr, 0x587e, 0x1a)
    cam_i2c_write(cam_iic, device_addr, 0x587f, 0x1a)
    cam_i2c_write(cam_iic, device_addr, 0x5880, 0x1b)
    cam_i2c_write(cam_iic, device_addr, 0x5881, 0x1f)
    cam_i2c_write(cam_iic, device_addr, 0x5882, 0x14)
    cam_i2c_write(cam_iic, device_addr, 0x5883, 0x1a)
    cam_i2c_write(cam_iic, device_addr, 0x5884, 0x1d)
    cam_i2c_write(cam_iic, device_addr, 0x5885, 0x1e)
    cam_i2c_write(cam_iic, device_addr, 0x5886, 0x1a)
    cam_i2c_write(cam_iic, device_addr, 0x5887, 0x1a)
    cam_i2c_write(cam_iic, device_addr, 0x528a, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x528b, 0x06)
    cam_i2c_write(cam_iic, device_addr, 0x528c, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x528d, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x528e, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x528f, 0x50)
    cam_i2c_write(cam_iic, device_addr, 0x5290, 0x60)
    cam_i2c_write(cam_iic, device_addr, 0x5292, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5293, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x5294, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5295, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x5296, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5297, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x5298, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5299, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x529a, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x529b, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x529c, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x529d, 0x28)
    cam_i2c_write(cam_iic, device_addr, 0x529e, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x529f, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x5282, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5680, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5681, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5682, 0x05)
    cam_i2c_write(cam_iic, device_addr, 0x5683, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5684, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5685, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5686, 0x03)
    cam_i2c_write(cam_iic, device_addr, 0x5687, 0xc0)
    cam_i2c_write(cam_iic, device_addr, 0x5180, 0xff)
    cam_i2c_write(cam_iic, device_addr, 0x5181, 0x52)
    cam_i2c_write(cam_iic, device_addr, 0x5182, 0x11)
    cam_i2c_write(cam_iic, device_addr, 0x5183, 0x14)
    cam_i2c_write(cam_iic, device_addr, 0x5184, 0x25)
    cam_i2c_write(cam_iic, device_addr, 0x5185, 0x24)
    cam_i2c_write(cam_iic, device_addr, 0x5186, 0x14)
    cam_i2c_write(cam_iic, device_addr, 0x5187, 0x14)
    cam_i2c_write(cam_iic, device_addr, 0x5188, 0x14)
    cam_i2c_write(cam_iic, device_addr, 0x5189, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x518a, 0x60)
    cam_i2c_write(cam_iic, device_addr, 0x518b, 0xa2)
    cam_i2c_write(cam_iic, device_addr, 0x518c, 0x9c)
    cam_i2c_write(cam_iic, device_addr, 0x518d, 0x36)
    cam_i2c_write(cam_iic, device_addr, 0x518e, 0x34)
    cam_i2c_write(cam_iic, device_addr, 0x518f, 0x54)
    cam_i2c_write(cam_iic, device_addr, 0x5190, 0x4c)
    cam_i2c_write(cam_iic, device_addr, 0x5191, 0xf8)
    cam_i2c_write(cam_iic, device_addr, 0x5192, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x5193, 0x70)
    cam_i2c_write(cam_iic, device_addr, 0x5194, 0xf0)
    cam_i2c_write(cam_iic, device_addr, 0x5195, 0xf0)
    cam_i2c_write(cam_iic, device_addr, 0x5196, 0x03)
    cam_i2c_write(cam_iic, device_addr, 0x5197, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x5198, 0x05)
    cam_i2c_write(cam_iic, device_addr, 0x5199, 0x2f)
    cam_i2c_write(cam_iic, device_addr, 0x519a, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x519b, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x519c, 0x06)
    cam_i2c_write(cam_iic, device_addr, 0x519d, 0xa0)
    cam_i2c_write(cam_iic, device_addr, 0x519e, 0xa0)
    cam_i2c_write(cam_iic, device_addr, 0x3a0f, 0x3c)
    cam_i2c_write(cam_iic, device_addr, 0x3a10, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x3a1b, 0x3c)
    cam_i2c_write(cam_iic, device_addr, 0x3a1e, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x3a11, 0x70)
    cam_i2c_write(cam_iic, device_addr, 0x3a1f, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x3800, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x3801, 0x50)
    cam_i2c_write(cam_iic, device_addr, 0x3802, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x3803, 0x8)
    cam_i2c_write(cam_iic, device_addr, 0x3804, 0x5)
    cam_i2c_write(cam_iic, device_addr, 0x3805, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x3806, 0x3)
    cam_i2c_write(cam_iic, device_addr, 0x3807, 0xc0)
    cam_i2c_write(cam_iic, device_addr, 0x3808, 0x3)
    cam_i2c_write(cam_iic, device_addr, 0x3809, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x380a, 0x2)
    cam_i2c_write(cam_iic, device_addr, 0x380b, 0x58)
    cam_i2c_write(cam_iic, device_addr, 0x380c, 0xc)
    cam_i2c_write(cam_iic, device_addr, 0x380d, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x380e, 0x3)
    cam_i2c_write(cam_iic, device_addr, 0x380f, 0xe8)
    cam_i2c_write(cam_iic, device_addr, 0x5001, 0x7f)
    cam_i2c_write(cam_iic, device_addr, 0x5680, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x5681, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x5682, 0x5)
    cam_i2c_write(cam_iic, device_addr, 0x5683, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x5684, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x5685, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x5686, 0x3)
    cam_i2c_write(cam_iic, device_addr, 0x5687, 0xc0)
    cam_i2c_write(cam_iic, device_addr, 0x5687, 0xc0)
    cam_i2c_write(cam_iic, device_addr, 0x3815, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x3503, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3818, 0x81) # No Mirror
    cam_i2c_write(cam_iic, device_addr, 0x3621, 0xa7)

    cam_i2c_write(cam_iic, device_addr, 0x4740, 0x21)

    cam_i2c_write(cam_iic, device_addr, 0x501e, 0x2a)
    cam_i2c_write(cam_iic, device_addr, 0x5002, 0x78)
    cam_i2c_write(cam_iic, device_addr, 0x501f, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x4300, 0x61)

# In[8]:
# frame buffer alocate
height = 600
width = 800
buffer0 = allocate(shape=(height, width, 1), dtype=np.uint32, cacheable=1)
buffer1 = allocate(shape=(height, width, 1), dtype=np.uint32, cacheable=1)
buffer2 = allocate(shape=(height, width, 1), dtype=np.uint32, cacheable=1)
buffer3 = allocate(shape=(height, width, 3), dtype=np.uint8, cacheable=1)

# In[9]:
# frame buffer resister set
vflip_dmaw.register_map.fb0_1 = buffer0.physical_address
vflip_dmaw.register_map.fb0_2 = 0
vflip_dmaw.register_map.fb1_1 = buffer1.physical_address
vflip_dmaw.register_map.fb1_2 = 0
vflip_dmaw.register_map.fb2_1 = buffer2.physical_address
vflip_dmaw.register_map.fb2_2 = 0

# In[10]:
dma2axis30.register_map.fb0 = buffer0.physical_address
dma2axis30.register_map.fb1 = buffer1.physical_address
dma2axis30.register_map.fb2 = buffer2.physical_address
dma2axis30.register_map.mode = 0 # DMA_WRITE_MODE

# In[11]:
dma2axis31.register_map.fb0 = buffer0.physical_address
dma2axis31.register_map.fb1 = buffer1.physical_address
dma2axis31.register_map.fb2 = buffer2.physical_address
dma2axis31.register_map.mode = 0 # DMA_WRITE_MODE

# In[12]:
sobel0.register_map.row_size = height
sobel0.register_map.col_size = width
sobel0.register_map.function_r = 0 # ORG_IMGwAxiVdma

# In[13]:
sobel1.register_map.row_size = height
sobel1.register_map.col_size = width
sobel1.register_map.function_r = 0 # ORG_IMGwAxiVdma

# In[14]:
axis2dma.register_map.out_r = buffer3.physical_address
axis2dma.register_map.row_size = height
axis2dma.register_map.col_size = width


# In[15]:
# vflip_dma_write start and auto repeat
vflip_dmaw.register_map.CTRL = 0x81

# In[16]:
# Camera Initialization
cam_i2c_init(cam_iic)
cam_reg_set(cam_iic, 0x78)

# In[17]:
# paracam_inf_axi start
paracam_inf.write(0x0, 0x0)
paracam_inf.write(0x4, 0x0)

# In[18]:
# VTC enable
vtc.write(0x0, 0x04) # Generation Enable

# In[19]:
# sobel_axis_RGB24 start
sobel0.register_map.CTRL = 0x81

# In[20]:
# dma2axis_3buf start and auto repeat
dma2axis30.register_map.CTRL = 0x81

# In[21]:
# image capture
axis2dma.register_map.CTRL = 0x1

# In[22]:
print(axis2dma.register_map.CTRL)


# In[23]:
sobel1.register_map.CTRL = 0x1

# In[24]:
print(sobel1.register_map.CTRL)

# In[25]:
dma2axis31.register_map.CTRL = 0x1

# In[26]:
print(dma2axis31.register_map.CTRL)

# In[27]:
print(axis2dma.register_map.CTRL)
print(sobel1.register_map.CTRL)
print(dma2axis31.register_map.CTRL)

# In[28]:
cam_image = Image.fromarray(buffer3)

# In[29]:
print("Image size: {}x{} pixels.".format(width, height))
plt.figure(figsize=(12, 10));
_ = plt.imshow(cam_image)

# In[30]:
cam_image.save('temp.jpg')

# In[31]:
#sobel filter on for camera image
sobel0.register_map.function_r = 1 # SOBELwAxiVdma

# In[32]:
# sobel filter off for camera image
sobel0.register_map.function_r = 0 # ORG_IMGwAxiVdma

# In[27]:
#sobel fliter on for image capture
sobel1.register_map.function_r = 1 # SOBELwAxiVdma
#axis2dma.register_map.CTRL = 0x1
#sobel1.register_map.CTRL = 0x1
#dma2axis31.register_map.CTRL = 0x1

# In[ ]:
#sobel fliter off for image capture
sobel1.register_map.function_r = 0 # ORG_IMGwAxiVdma
#axis2dma.register_map.CTRL = 0x1
#sobel1.register_map.CTRL = 0x1
#dma2axis31.register_map.CTRL = 0x1

  1. 2022年09月07日 04:43 |
  2. IP
  3. | トラックバック:0
  4. | コメント:0

Xilinx 社の Video IP を使ってブロック・デザインを作る2

自分で作った IP を使用して画像を表示しているが、それを Xilinx 社の IP を使用して画像を表示してみたいということで、前回は bitmap_disp_cont_axis IP を AXI4-Stream to Video Out(v_axi4s_vid_out) IP と Video TIming Controller (v_tc) IP で置き換えた。今回は、実際に v_axi4s_vid_out と v_tc を配線して、論理合成、インプリメンテーション、ビットストリームの生成を行った。

v_axi4s_vid_out と v_tc を配線して、ブロック・デザインを完成させた。
X_video_IP_2_220906.png

v_tc_0 の設定を示す。
なお設定方法は、”Video Beginner Series 16: Understanding Video Timing with the VTC IP”を参照。
Detection/Generation タブ。
X_video_IP_3_220906.png

Default/Constant タブ。
X_video_IP_4_220906.png

Frame Sync Positon タブ。
X_video_IP_5_220906.png

v_axi4s_vid_out_0 の設定を示す。
X_video_IP_6_220906.png

Address Editor を示す。
X_video_IP_7_220906.png

論理合成、インプリメンテーション、ビットストリームの生成を行った。
Project Summary を示す。
X_video_IP_8_220906.png
  1. 2022年09月06日 04:48 |
  2. IP
  3. | トラックバック:0
  4. | コメント:0

Xilinx 社の Video IP を使ってブロック・デザインを作る1

自分で作った IP を使用して画像を表示しているが、それを Xilinx 社の IP を使用して画像を表示してみたい。
具体的には bitmap_disp_cont_axis IP を AXI4-Stream to Video Out(v_axi4s_vid_out) IP と Video TIming Controller (v_tc) IP で置き換えたい。

AXI4-Stream to Video Out(v_axi4s_vid_out) IP と Video TIming Controller (v_tc) IP は””MicroZed Chronicles: Kria & Raspberry Pi Camera”をやってみる”という記事で使用している(””MicroZed Chronicles: Kria & Raspberry Pi Camera”をやってみる6”参照)

現状は、AXI4-Stream to Video Out(v_axi4s_vid_out) IP と Video TIming Controller (v_tc) IP を入れたところだ。
X_video_IP_1_220905.png
  1. 2022年09月05日 05:07 |
  2. IP
  3. | トラックバック:0
  4. | コメント:0

”MicroZed Chronicles: PYNQ Interrupts”をやってみる2

”MicroZed Chronicles: PYNQ Interrupts”をやってみる1”の続き。

PYNQ での割り込みを学習するために、Adam Taylor さんの”MicroZed Chronicles: Memory Scrubbing”を ZYBO Z7-20 の PYNQ でやってみることにしたということで、前回は、Vivado 2022.1 で pynq_int プロジェクトを作成してブロック・デザインを作成し、論理合成、インプリメンテーション、ビットストリームの生成を行った。今回は、ZYBO Z7-20 上の PYNQ Linux にビットストリームと hwh ファイルをアップロードし、pynq_int.ipynb ファイルを生成して、割り込み動作を確認した。

ZYBO Z7-20 の Jupyter Notebook の my_project の下に pinq_int ディレクトリを生成した。

Vivado 2022.1 で作った pynq_int プロジェクトの pynq_int/pynq_int.runs/impl_1 から pynq_int_wrapper.bit を pynq_int ディレクトリにアップロードし、名前を pynq_int.bit に変更した。

Vivado 2022.1 で作った pynq_int プロジェクトの pynq_int/pynq_int.gen/sources_1/bd/pynq_int/hw_handoff から pynq_int.hwh ファイルを pynq_int ディレクトリにアップロードした。

pynq_int.ipynb ファイルを新規作成した。
MicroZed Chronicles: Memory Scrubbing”のコードを引用した。変数名を多少いじってあるが、ほとんどコードを引用してある。
ZYBO_Z7_PYNQ_248_220904.png

ZYBO Z7-20 の PYNQ Linux にログインして、cat /proc/interrupts を行った。
ZYBO_Z7_PYNQ_249_220904.png

たぶん fabric が PL からの割り込みを表すと思う。
現在、CPU0 のカウントは 0 になっている。

pynq_int.ipynb ファイルを全部実行した。
最後の

asyncio.get_event_loop().run_until_complete(handler_task)

で実行待ちになっている。
ZYBO_Z7_PYNQ_250_220904.png

ZYBO Z7-20 の押ボタン・スイッチのどれかを押すと、最後の行を実行できた。
LED が全て点灯した。
ZYBO_Z7_PYNQ_251_220904.png

handle() 関数を割り込みで実行できているようだ。

cat /proc/interrupts を行うと fabric の CPU0 のカウントが +1 されていた。
ZYBO_Z7_PYNQ_252_220904.png

MicroZed Chronicles: Memory Scrubbing”を引用した Python コードを貼っておく。

#!/usr/bin/env python
# coding: utf-8

# ## PYNQ Interrupt

# In[1]:

from pynq import Overlay, Interrupt, GPIO
import asyncio

# In[2]:

# Download bitstream
pi = Overlay("./pynq_int.bit")

# In[3]:

pi.interrupt_pins

# In[4]:

intc = pi.axi_intc_0
intr_inst = Interrupt('axi_gpio_0/ip2intc_irpt')

# In[5]:

from pynq.lib import AxiGPIO

# In[6]:

gpio0 = pi.ip_dict['axi_gpio_0']
gpio1 = pi.ip_dict['axi_gpio_1']

# In[7]:

leds = AxiGPIO(gpio1).channel1
sw = AxiGPIO(gpio0).channel1

# In[8]:

async def handle():
    await sw.wait_for_interrupt_async()
    leds[0:4].toggle()

# In[9]:

handler_task = asyncio.ensure_future(handle())

# In[10]:

asyncio.get_event_loop().run_until_complete(handler_task)

  1. 2022年09月04日 04:44 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0

ZYBO Z7-20 の PYNQ 2.7 上で Jupyter Notebook に画像を表示する10

ZYBO Z7-20 の PYNQ 2.7 上で Jupyter Notebook に画像を表示する9”の続き。

Jupyter Notebook にカメラ画像を表示しようということで、前回は、色の違いを修正するために、Red と Blue を入れ替えたところ、正常な色になった。今回は、1 つやるのを忘れていたことがあった。それは、カメラ画像をファイルにすることだ。結論を言うとカメラ画像を JPEG ファイルにすることができた。

まずは、NumPy配列ndarrayを画像ファイルとして保存するために、”Python, NumPyで画像処理(読み込み、演算、保存)”の”NumPy配列ndarrayを画像ファイルとして保存する方法”を参考にさせていただいた。
Python, NumPyで画像処理(読み込み、演算、保存)”によると、

cam_image = Image.fromarray(buffer3)

の cam_image の save メソッドを呼び出せば良いようだ。

cam_image.save('temp.jpg')


実行した。
ZYBO_Z7_PYNQ_245_220902.png

test.jpg が生成された。
ZYBO_Z7_PYNQ_246_220902.png

test.jpg を確認したが、正常だった。
ZYBO_Z7_PYNQ_247_220902.png

これで画像をファイルにする方法が分かった。

現在の Jupyter Notebook の Python コードを貼っておく。

# cam_disp.py
# 2022/08/05 by marsee
# 2022/08/14 : Added Sobel filter.

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from pynq import allocate, Overlay
import time

# Download bitstream
cam_disp = Overlay("./cam_disp.bit")

# Generate an instance for each IP
vflip_dmaw = cam_disp.vflip_dma_write_0
paracam_inf = cam_disp.paracam_inf_axis_0
bmpd_cont = cam_disp.bitmap_disp_cont_axis_0
cam_iic = cam_disp.axi_iic_0
sobel0 = cam_disp.sobel_axis_RGB24_0
sobel1 = cam_disp.sobel_axis_RGB24_1
dma2axis30 = cam_disp.DMA2axis_3buf_0
dma2axis31 = cam_disp.DMA2axis_3buf_1
axis2dma = cam_disp.axis2DMA_0

def cam_i2c_init(cam_iic):
    cam_iic.write(0x100, 0x2)   # reset tx fifo ,address is 0x100, i2c_control_reg
    cam_iic.write(0x100, 0x1)   # enable i2c

def cam_i2x_write_sync():
    time.sleep(0.001) # 1ms wait

def cam_i2c_write(cam_iic, device_addr, write_addr, write_data):
    cam_iic.write(0x108, bin(0x100 | (device_addr & 0xfe)))   # Slave IIC Write Address, address is 0x108, i2c_tx_fifo
    cam_iic.write(0x108, bin((write_addr >> 8) & 0xff))      # address upper byte
    cam_iic.write(0x108, bin(write_addr & 0xff)) # address lower byte
    cam_iic.write(0x108, bin(0x200 | (write_data & 0xff)))   # data
    cam_i2x_write_sync()

def cam_reg_set(cam_iic, device_addr):
    cam_i2c_write(cam_iic, device_addr, 0x3103, 0x93)
    cam_i2c_write(cam_iic, device_addr, 0x3008, 0x82)
    cam_i2c_write(cam_iic, device_addr, 0x3017, 0x7f)
    cam_i2c_write(cam_iic, device_addr, 0x3018, 0xfc)
    cam_i2c_write(cam_iic, device_addr, 0x3810, 0xc2)
    cam_i2c_write(cam_iic, device_addr, 0x3615, 0xf0)
    cam_i2c_write(cam_iic, device_addr, 0x3000, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3001, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3002, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3003, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3000, 0xf8)
    cam_i2c_write(cam_iic, device_addr, 0x3001, 0x48)
    cam_i2c_write(cam_iic, device_addr, 0x3002, 0x5c)
    cam_i2c_write(cam_iic, device_addr, 0x3003, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x3004, 0x07)
    cam_i2c_write(cam_iic, device_addr, 0x3005, 0xb7)
    cam_i2c_write(cam_iic, device_addr, 0x3006, 0x43)
    cam_i2c_write(cam_iic, device_addr, 0x3007, 0x37)
    cam_i2c_write(cam_iic, device_addr, 0x3011, 0x08) # 0x08 - 15fps, 0x10 - 30fps
    cam_i2c_write(cam_iic, device_addr, 0x3010, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x460c, 0x22)
    cam_i2c_write(cam_iic, device_addr, 0x3815, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x370d, 0x06)
    cam_i2c_write(cam_iic, device_addr, 0x370c, 0xa0)
    cam_i2c_write(cam_iic, device_addr, 0x3602, 0xfc)
    cam_i2c_write(cam_iic, device_addr, 0x3612, 0xff)
    cam_i2c_write(cam_iic, device_addr, 0x3634, 0xc0)
    cam_i2c_write(cam_iic, device_addr, 0x3613, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3605, 0x7c)
    cam_i2c_write(cam_iic, device_addr, 0x3621, 0x09)
    cam_i2c_write(cam_iic, device_addr, 0x3622, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3604, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x3603, 0xa7)
    cam_i2c_write(cam_iic, device_addr, 0x3603, 0x27)
    cam_i2c_write(cam_iic, device_addr, 0x4000, 0x21)
    cam_i2c_write(cam_iic, device_addr, 0x401d, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x3600, 0x54)
    cam_i2c_write(cam_iic, device_addr, 0x3605, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x3606, 0x3f)
    cam_i2c_write(cam_iic, device_addr, 0x3c01, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5000, 0x4f)
    cam_i2c_write(cam_iic, device_addr, 0x5020, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x5181, 0x79)
    cam_i2c_write(cam_iic, device_addr, 0x5182, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5185, 0x22)
    cam_i2c_write(cam_iic, device_addr, 0x5197, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x5001, 0xff)
    cam_i2c_write(cam_iic, device_addr, 0x5500, 0x0a)
    cam_i2c_write(cam_iic, device_addr, 0x5504, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5505, 0x7f)
    cam_i2c_write(cam_iic, device_addr, 0x5080, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x300e, 0x18)
    cam_i2c_write(cam_iic, device_addr, 0x4610, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x471d, 0x05)
    cam_i2c_write(cam_iic, device_addr, 0x4708, 0x06)
    cam_i2c_write(cam_iic, device_addr, 0x3710, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x3632, 0x41)
    cam_i2c_write(cam_iic, device_addr, 0x3702, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x3620, 0x37)
    cam_i2c_write(cam_iic, device_addr, 0x3631, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x3808, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x3809, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x380a, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x380b, 0xe0)
    cam_i2c_write(cam_iic, device_addr, 0x380e, 0x07)
    cam_i2c_write(cam_iic, device_addr, 0x380f, 0xd0)
    cam_i2c_write(cam_iic, device_addr, 0x501f, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5000, 0x4f)
    cam_i2c_write(cam_iic, device_addr, 0x4300, 0x61) # RGB565
    cam_i2c_write(cam_iic, device_addr, 0x3503, 0x07)
    cam_i2c_write(cam_iic, device_addr, 0x3501, 0x73)
    cam_i2c_write(cam_iic, device_addr, 0x3502, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x350b, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3503, 0x07)
    cam_i2c_write(cam_iic, device_addr, 0x3824, 0x11)
    cam_i2c_write(cam_iic, device_addr, 0x3501, 0x1e)
    cam_i2c_write(cam_iic, device_addr, 0x3502, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x350b, 0x7f)
    cam_i2c_write(cam_iic, device_addr, 0x380c, 0x0c)
    cam_i2c_write(cam_iic, device_addr, 0x380d, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x380e, 0x03)
    cam_i2c_write(cam_iic, device_addr, 0x380f, 0xe8)
    cam_i2c_write(cam_iic, device_addr, 0x3a0d, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x3a0e, 0x03)
    cam_i2c_write(cam_iic, device_addr, 0x3818, 0xc1)
    cam_i2c_write(cam_iic, device_addr, 0x3705, 0xdb)
    cam_i2c_write(cam_iic, device_addr, 0x370a, 0x81)
    cam_i2c_write(cam_iic, device_addr, 0x3801, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x3621, 0xc7)
    cam_i2c_write(cam_iic, device_addr, 0x3801, 0x50)
    cam_i2c_write(cam_iic, device_addr, 0x3803, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x3827, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x3810, 0xc0)
    cam_i2c_write(cam_iic, device_addr, 0x3804, 0x05)
    cam_i2c_write(cam_iic, device_addr, 0x3805, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5682, 0x05)
    cam_i2c_write(cam_iic, device_addr, 0x5683, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3806, 0x03)
    cam_i2c_write(cam_iic, device_addr, 0x3807, 0xc0)
    cam_i2c_write(cam_iic, device_addr, 0x5686, 0x03)
    cam_i2c_write(cam_iic, device_addr, 0x5687, 0xc0)
    cam_i2c_write(cam_iic, device_addr, 0x3a00, 0x78)
    cam_i2c_write(cam_iic, device_addr, 0x3a1a, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x3a13, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x3a18, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3a19, 0x7c)
    cam_i2c_write(cam_iic, device_addr, 0x3a08, 0x12)
    cam_i2c_write(cam_iic, device_addr, 0x3a09, 0xc0)
    cam_i2c_write(cam_iic, device_addr, 0x3a0a, 0x0f)
    cam_i2c_write(cam_iic, device_addr, 0x3a0b, 0xa0)
    cam_i2c_write(cam_iic, device_addr, 0x3004, 0xff)
    cam_i2c_write(cam_iic, device_addr, 0x350c, 0x07)
    cam_i2c_write(cam_iic, device_addr, 0x350d, 0xd0)
    cam_i2c_write(cam_iic, device_addr, 0x3500, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3501, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3502, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x350a, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x350b, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3503, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x528a, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x528b, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x528c, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x528d, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x528e, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x528f, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5290, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5292, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5293, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x5294, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5295, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x5296, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5297, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x5298, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5299, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x529a, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x529b, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x529c, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x529d, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x529e, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x529f, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x3a0f, 0x3c)
    cam_i2c_write(cam_iic, device_addr, 0x3a10, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x3a1b, 0x3c)
    cam_i2c_write(cam_iic, device_addr, 0x3a1e, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x3a11, 0x70)
    cam_i2c_write(cam_iic, device_addr, 0x3a1f, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x3030, 0x0b)
    cam_i2c_write(cam_iic, device_addr, 0x3a02, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3a03, 0x7d)
    cam_i2c_write(cam_iic, device_addr, 0x3a04, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3a14, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3a15, 0x7d)
    cam_i2c_write(cam_iic, device_addr, 0x3a16, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3a00, 0x78)
    cam_i2c_write(cam_iic, device_addr, 0x3a08, 0x09)
    cam_i2c_write(cam_iic, device_addr, 0x3a09, 0x60)
    cam_i2c_write(cam_iic, device_addr, 0x3a0a, 0x07)
    cam_i2c_write(cam_iic, device_addr, 0x3a0b, 0xd0)
    cam_i2c_write(cam_iic, device_addr, 0x3a0d, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x3a0e, 0x06)
    cam_i2c_write(cam_iic, device_addr, 0x5193, 0x70)
    cam_i2c_write(cam_iic, device_addr, 0x3620, 0x57)
    cam_i2c_write(cam_iic, device_addr, 0x3703, 0x98)
    cam_i2c_write(cam_iic, device_addr, 0x3704, 0x1c)
    cam_i2c_write(cam_iic, device_addr, 0x589b, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x589a, 0xc5)
    cam_i2c_write(cam_iic, device_addr, 0x528a, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x528b, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x528c, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x528d, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x528e, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x528f, 0x28)
    cam_i2c_write(cam_iic, device_addr, 0x5290, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x5292, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5293, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5294, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5295, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x5296, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5297, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x5298, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5299, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x529a, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x529b, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x529c, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x529d, 0x28)
    cam_i2c_write(cam_iic, device_addr, 0x529e, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x529f, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x5282, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5300, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5301, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5302, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5303, 0x7c)
    cam_i2c_write(cam_iic, device_addr, 0x530c, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x530d, 0x0c)
    cam_i2c_write(cam_iic, device_addr, 0x530e, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x530f, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5310, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5311, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5308, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5309, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x5304, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5305, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x5306, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5307, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5314, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x5315, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5319, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x5316, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5317, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x5318, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x5380, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x5381, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5382, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5383, 0x4e)
    cam_i2c_write(cam_iic, device_addr, 0x5384, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5385, 0x0f)
    cam_i2c_write(cam_iic, device_addr, 0x5386, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5387, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5388, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x5389, 0x15)
    cam_i2c_write(cam_iic, device_addr, 0x538a, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x538b, 0x31)
    cam_i2c_write(cam_iic, device_addr, 0x538c, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x538d, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x538e, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x538f, 0x0f)
    cam_i2c_write(cam_iic, device_addr, 0x5390, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5391, 0xab)
    cam_i2c_write(cam_iic, device_addr, 0x5392, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5393, 0xa2)
    cam_i2c_write(cam_iic, device_addr, 0x5394, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x5480, 0x14)
    cam_i2c_write(cam_iic, device_addr, 0x5481, 0x21)
    cam_i2c_write(cam_iic, device_addr, 0x5482, 0x36)
    cam_i2c_write(cam_iic, device_addr, 0x5483, 0x57)
    cam_i2c_write(cam_iic, device_addr, 0x5484, 0x65)
    cam_i2c_write(cam_iic, device_addr, 0x5485, 0x71)
    cam_i2c_write(cam_iic, device_addr, 0x5486, 0x7d)
    cam_i2c_write(cam_iic, device_addr, 0x5487, 0x87)
    cam_i2c_write(cam_iic, device_addr, 0x5488, 0x91)
    cam_i2c_write(cam_iic, device_addr, 0x5489, 0x9a)
    cam_i2c_write(cam_iic, device_addr, 0x548a, 0xaa)
    cam_i2c_write(cam_iic, device_addr, 0x548b, 0xb8)
    cam_i2c_write(cam_iic, device_addr, 0x548c, 0xcd)
    cam_i2c_write(cam_iic, device_addr, 0x548d, 0xdd)
    cam_i2c_write(cam_iic, device_addr, 0x548e, 0xea)
    cam_i2c_write(cam_iic, device_addr, 0x548f, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5490, 0x05)
    cam_i2c_write(cam_iic, device_addr, 0x5491, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5492, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x5493, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5494, 0x03)
    cam_i2c_write(cam_iic, device_addr, 0x5495, 0x60)
    cam_i2c_write(cam_iic, device_addr, 0x5496, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x5497, 0xb8)
    cam_i2c_write(cam_iic, device_addr, 0x5498, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x5499, 0x86)
    cam_i2c_write(cam_iic, device_addr, 0x549a, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x549b, 0x5b)
    cam_i2c_write(cam_iic, device_addr, 0x549c, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x549d, 0x3b)
    cam_i2c_write(cam_iic, device_addr, 0x549e, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x549f, 0x1c)
    cam_i2c_write(cam_iic, device_addr, 0x54a0, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x54a1, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x54a2, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x54a3, 0xed)
    cam_i2c_write(cam_iic, device_addr, 0x54a4, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x54a5, 0xc5)
    cam_i2c_write(cam_iic, device_addr, 0x54a6, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x54a7, 0xa5)
    cam_i2c_write(cam_iic, device_addr, 0x54a8, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x54a9, 0x6c)
    cam_i2c_write(cam_iic, device_addr, 0x54aa, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x54ab, 0x41)
    cam_i2c_write(cam_iic, device_addr, 0x54ac, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x54ad, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x54ae, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x54af, 0x16)
    cam_i2c_write(cam_iic, device_addr, 0x3406, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5192, 0x04) # 0x04
    cam_i2c_write(cam_iic, device_addr, 0x5191, 0xf8) # 0xf8
    cam_i2c_write(cam_iic, device_addr, 0x5193, 0x70)
    cam_i2c_write(cam_iic, device_addr, 0x5194, 0xf0)
    cam_i2c_write(cam_iic, device_addr, 0x5195, 0xf0)
    cam_i2c_write(cam_iic, device_addr, 0x518d, 0x3d)
    cam_i2c_write(cam_iic, device_addr, 0x518f, 0x54)
    cam_i2c_write(cam_iic, device_addr, 0x518e, 0x3d)
    cam_i2c_write(cam_iic, device_addr, 0x5190, 0x54)
    cam_i2c_write(cam_iic, device_addr, 0x518b, 0xc0)
    cam_i2c_write(cam_iic, device_addr, 0x518c, 0xbd)
    cam_i2c_write(cam_iic, device_addr, 0x5187, 0x18)
    cam_i2c_write(cam_iic, device_addr, 0x5188, 0x18)
    cam_i2c_write(cam_iic, device_addr, 0x5189, 0x6e)
    cam_i2c_write(cam_iic, device_addr, 0x518a, 0x68)
    cam_i2c_write(cam_iic, device_addr, 0x5186, 0x1c)
    cam_i2c_write(cam_iic, device_addr, 0x5181, 0x50)
    cam_i2c_write(cam_iic, device_addr, 0x5184, 0x25)
    cam_i2c_write(cam_iic, device_addr, 0x5182, 0x11)
    cam_i2c_write(cam_iic, device_addr, 0x5183, 0x14)
    cam_i2c_write(cam_iic, device_addr, 0x5184, 0x25)
    cam_i2c_write(cam_iic, device_addr, 0x5185, 0x24)
    cam_i2c_write(cam_iic, device_addr, 0x5025, 0x82)
    cam_i2c_write(cam_iic, device_addr, 0x5583, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x5584, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x5580, 0x02) # 0x02
    cam_i2c_write(cam_iic, device_addr, 0x3633, 0x07)
    cam_i2c_write(cam_iic, device_addr, 0x3702, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x3703, 0xb2)
    cam_i2c_write(cam_iic, device_addr, 0x3704, 0x18)
    cam_i2c_write(cam_iic, device_addr, 0x370b, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x370d, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x3620, 0x52)
    cam_i2c_write(cam_iic, device_addr, 0x3c00, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x5001, 0xFF)
    cam_i2c_write(cam_iic, device_addr, 0x5282, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5300, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5301, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5302, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5303, 0x7c)
    cam_i2c_write(cam_iic, device_addr, 0x530c, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x530d, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x530e, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x530f, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5310, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5311, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5308, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5309, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x5304, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5305, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x5306, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5307, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5314, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x5315, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5319, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x5316, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5317, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5318, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x5500, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5502, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5503, 0x06)
    cam_i2c_write(cam_iic, device_addr, 0x5504, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5505, 0x7f)
    cam_i2c_write(cam_iic, device_addr, 0x5025, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5300, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5301, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5302, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5303, 0x7c)
    cam_i2c_write(cam_iic, device_addr, 0x530c, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x530d, 0x0c)
    cam_i2c_write(cam_iic, device_addr, 0x530e, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x530f, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5310, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5311, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5308, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5309, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x5304, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5305, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x5306, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5307, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5314, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x5315, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x5319, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x5316, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5317, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x5318, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x5380, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x5381, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5382, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5383, 0x1f)
    cam_i2c_write(cam_iic, device_addr, 0x5384, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5385, 0x06)
    cam_i2c_write(cam_iic, device_addr, 0x5386, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5387, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5388, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5389, 0xE1)
    cam_i2c_write(cam_iic, device_addr, 0x538A, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x538B, 0x2B)
    cam_i2c_write(cam_iic, device_addr, 0x538C, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x538D, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x538E, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x538F, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5390, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5391, 0xB3)
    cam_i2c_write(cam_iic, device_addr, 0x5392, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5393, 0xA6)
    cam_i2c_write(cam_iic, device_addr, 0x5394, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x5480, 0xd)
    cam_i2c_write(cam_iic, device_addr, 0x5481, 0x18)
    cam_i2c_write(cam_iic, device_addr, 0x5482, 0x2a)
    cam_i2c_write(cam_iic, device_addr, 0x5483, 0x49)
    cam_i2c_write(cam_iic, device_addr, 0x5484, 0x56)
    cam_i2c_write(cam_iic, device_addr, 0x5485, 0x62)
    cam_i2c_write(cam_iic, device_addr, 0x5486, 0x6c)
    cam_i2c_write(cam_iic, device_addr, 0x5487, 0x76)
    cam_i2c_write(cam_iic, device_addr, 0x5488, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x5489, 0x88)
    cam_i2c_write(cam_iic, device_addr, 0x548a, 0x96)
    cam_i2c_write(cam_iic, device_addr, 0x548b, 0xa2)
    cam_i2c_write(cam_iic, device_addr, 0x548c, 0xb8)
    cam_i2c_write(cam_iic, device_addr, 0x548d, 0xcc)
    cam_i2c_write(cam_iic, device_addr, 0x548e, 0xe0)
    cam_i2c_write(cam_iic, device_addr, 0x548f, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5490, 0x3)
    cam_i2c_write(cam_iic, device_addr, 0x5491, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x5492, 0x3)
    cam_i2c_write(cam_iic, device_addr, 0x5493, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x5494, 0x2)
    cam_i2c_write(cam_iic, device_addr, 0x5495, 0xa0)
    cam_i2c_write(cam_iic, device_addr, 0x5496, 0x2)
    cam_i2c_write(cam_iic, device_addr, 0x5497, 0x48)
    cam_i2c_write(cam_iic, device_addr, 0x5498, 0x2)
    cam_i2c_write(cam_iic, device_addr, 0x5499, 0x26)
    cam_i2c_write(cam_iic, device_addr, 0x549a, 0x2)
    cam_i2c_write(cam_iic, device_addr, 0x549b, 0xb)
    cam_i2c_write(cam_iic, device_addr, 0x549c, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x549d, 0xee)
    cam_i2c_write(cam_iic, device_addr, 0x549e, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x549f, 0xd8)
    cam_i2c_write(cam_iic, device_addr, 0x54a0, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x54a1, 0xc7)
    cam_i2c_write(cam_iic, device_addr, 0x54a2, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x54a3, 0xb3)
    cam_i2c_write(cam_iic, device_addr, 0x54a4, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x54a5, 0x90)
    cam_i2c_write(cam_iic, device_addr, 0x54a6, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x54a7, 0x62)
    cam_i2c_write(cam_iic, device_addr, 0x54a8, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x54a9, 0x27)
    cam_i2c_write(cam_iic, device_addr, 0x54aa, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x54ab, 0x09)
    cam_i2c_write(cam_iic, device_addr, 0x54ac, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x54ad, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x54ae, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x54af, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x54b0, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x54b1, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x54b2, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x54b3, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x54b4, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x54b5, 0xf0)
    cam_i2c_write(cam_iic, device_addr, 0x54b6, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x54b7, 0xdf)
    cam_i2c_write(cam_iic, device_addr, 0x5583, 0x5d)
    cam_i2c_write(cam_iic, device_addr, 0x5584, 0x5d)
    cam_i2c_write(cam_iic, device_addr, 0x5580, 0x06)
    cam_i2c_write(cam_iic, device_addr, 0x5587, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5588, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x558a, 0x09)
    cam_i2c_write(cam_iic, device_addr, 0x5589, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5000, 0xcf)
    cam_i2c_write(cam_iic, device_addr, 0x5800, 0x48)
    cam_i2c_write(cam_iic, device_addr, 0x5801, 0x31)
    cam_i2c_write(cam_iic, device_addr, 0x5802, 0x21)
    cam_i2c_write(cam_iic, device_addr, 0x5803, 0x1b)
    cam_i2c_write(cam_iic, device_addr, 0x5804, 0x1a)
    cam_i2c_write(cam_iic, device_addr, 0x5805, 0x1e)
    cam_i2c_write(cam_iic, device_addr, 0x5806, 0x29)
    cam_i2c_write(cam_iic, device_addr, 0x5807, 0x38)
    cam_i2c_write(cam_iic, device_addr, 0x5808, 0x26)
    cam_i2c_write(cam_iic, device_addr, 0x5809, 0x17)
    cam_i2c_write(cam_iic, device_addr, 0x580a, 0x11)
    cam_i2c_write(cam_iic, device_addr, 0x580b, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x580c, 0xd)
    cam_i2c_write(cam_iic, device_addr, 0x580d, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x580e, 0x13)
    cam_i2c_write(cam_iic, device_addr, 0x580f, 0x1a)
    cam_i2c_write(cam_iic, device_addr, 0x5810, 0x15)
    cam_i2c_write(cam_iic, device_addr, 0x5811, 0xd)
    cam_i2c_write(cam_iic, device_addr, 0x5812, 0x8)
    cam_i2c_write(cam_iic, device_addr, 0x5813, 0x5)
    cam_i2c_write(cam_iic, device_addr, 0x5814, 0x4)
    cam_i2c_write(cam_iic, device_addr, 0x5815, 0x5)
    cam_i2c_write(cam_iic, device_addr, 0x5816, 0x9)
    cam_i2c_write(cam_iic, device_addr, 0x5817, 0xd)
    cam_i2c_write(cam_iic, device_addr, 0x5818, 0x11)
    cam_i2c_write(cam_iic, device_addr, 0x5819, 0xa)
    cam_i2c_write(cam_iic, device_addr, 0x581a, 0x4)
    cam_i2c_write(cam_iic, device_addr, 0x581b, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x581c, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x581d, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x581e, 0x6)
    cam_i2c_write(cam_iic, device_addr, 0x581f, 0x9)
    cam_i2c_write(cam_iic, device_addr, 0x5820, 0x12)
    cam_i2c_write(cam_iic, device_addr, 0x5821, 0xb)
    cam_i2c_write(cam_iic, device_addr, 0x5822, 0x4)
    cam_i2c_write(cam_iic, device_addr, 0x5823, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x5824, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x5825, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x5826, 0x6)
    cam_i2c_write(cam_iic, device_addr, 0x5827, 0xa)
    cam_i2c_write(cam_iic, device_addr, 0x5828, 0x17)
    cam_i2c_write(cam_iic, device_addr, 0x5829, 0xf)
    cam_i2c_write(cam_iic, device_addr, 0x582a, 0x9)
    cam_i2c_write(cam_iic, device_addr, 0x582b, 0x6)
    cam_i2c_write(cam_iic, device_addr, 0x582c, 0x5)
    cam_i2c_write(cam_iic, device_addr, 0x582d, 0x6)
    cam_i2c_write(cam_iic, device_addr, 0x582e, 0xa)
    cam_i2c_write(cam_iic, device_addr, 0x582f, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x5830, 0x28)
    cam_i2c_write(cam_iic, device_addr, 0x5831, 0x1a)
    cam_i2c_write(cam_iic, device_addr, 0x5832, 0x11)
    cam_i2c_write(cam_iic, device_addr, 0x5833, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x5834, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x5835, 0xf)
    cam_i2c_write(cam_iic, device_addr, 0x5836, 0x15)
    cam_i2c_write(cam_iic, device_addr, 0x5837, 0x1d)
    cam_i2c_write(cam_iic, device_addr, 0x5838, 0x6e)
    cam_i2c_write(cam_iic, device_addr, 0x5839, 0x39)
    cam_i2c_write(cam_iic, device_addr, 0x583a, 0x27)
    cam_i2c_write(cam_iic, device_addr, 0x583b, 0x1f)
    cam_i2c_write(cam_iic, device_addr, 0x583c, 0x1e)
    cam_i2c_write(cam_iic, device_addr, 0x583d, 0x23)
    cam_i2c_write(cam_iic, device_addr, 0x583e, 0x2f)
    cam_i2c_write(cam_iic, device_addr, 0x583f, 0x41)
    cam_i2c_write(cam_iic, device_addr, 0x5840, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x5841, 0xc)
    cam_i2c_write(cam_iic, device_addr, 0x5842, 0xd)
    cam_i2c_write(cam_iic, device_addr, 0x5843, 0xc)
    cam_i2c_write(cam_iic, device_addr, 0x5844, 0xc)
    cam_i2c_write(cam_iic, device_addr, 0x5845, 0xc)
    cam_i2c_write(cam_iic, device_addr, 0x5846, 0xc)
    cam_i2c_write(cam_iic, device_addr, 0x5847, 0xc)
    cam_i2c_write(cam_iic, device_addr, 0x5848, 0xd)
    cam_i2c_write(cam_iic, device_addr, 0x5849, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x584a, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x584b, 0xa)
    cam_i2c_write(cam_iic, device_addr, 0x584c, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x584d, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x584e, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x584f, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5850, 0x11)
    cam_i2c_write(cam_iic, device_addr, 0x5851, 0xa)
    cam_i2c_write(cam_iic, device_addr, 0x5852, 0xf)
    cam_i2c_write(cam_iic, device_addr, 0x5853, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x5854, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5855, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5856, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5857, 0xa)
    cam_i2c_write(cam_iic, device_addr, 0x5858, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x5859, 0xe)
    cam_i2c_write(cam_iic, device_addr, 0x585a, 0xf)
    cam_i2c_write(cam_iic, device_addr, 0x585b, 0xf)
    cam_i2c_write(cam_iic, device_addr, 0x585c, 0xf)
    cam_i2c_write(cam_iic, device_addr, 0x585d, 0xa)
    cam_i2c_write(cam_iic, device_addr, 0x585e, 0x9)
    cam_i2c_write(cam_iic, device_addr, 0x585f, 0xd)
    cam_i2c_write(cam_iic, device_addr, 0x5860, 0xc)
    cam_i2c_write(cam_iic, device_addr, 0x5861, 0xb)
    cam_i2c_write(cam_iic, device_addr, 0x5862, 0xd)
    cam_i2c_write(cam_iic, device_addr, 0x5863, 0x7)
    cam_i2c_write(cam_iic, device_addr, 0x5864, 0x17)
    cam_i2c_write(cam_iic, device_addr, 0x5865, 0x14)
    cam_i2c_write(cam_iic, device_addr, 0x5866, 0x18)
    cam_i2c_write(cam_iic, device_addr, 0x5867, 0x18)
    cam_i2c_write(cam_iic, device_addr, 0x5868, 0x16)
    cam_i2c_write(cam_iic, device_addr, 0x5869, 0x12)
    cam_i2c_write(cam_iic, device_addr, 0x586a, 0x1b)
    cam_i2c_write(cam_iic, device_addr, 0x586b, 0x1a)
    cam_i2c_write(cam_iic, device_addr, 0x586c, 0x16)
    cam_i2c_write(cam_iic, device_addr, 0x586d, 0x16)
    cam_i2c_write(cam_iic, device_addr, 0x586e, 0x18)
    cam_i2c_write(cam_iic, device_addr, 0x586f, 0x1f)
    cam_i2c_write(cam_iic, device_addr, 0x5870, 0x1c)
    cam_i2c_write(cam_iic, device_addr, 0x5871, 0x16)
    cam_i2c_write(cam_iic, device_addr, 0x5872, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x5873, 0xf)
    cam_i2c_write(cam_iic, device_addr, 0x5874, 0x13)
    cam_i2c_write(cam_iic, device_addr, 0x5875, 0x1c)
    cam_i2c_write(cam_iic, device_addr, 0x5876, 0x1e)
    cam_i2c_write(cam_iic, device_addr, 0x5877, 0x17)
    cam_i2c_write(cam_iic, device_addr, 0x5878, 0x11)
    cam_i2c_write(cam_iic, device_addr, 0x5879, 0x11)
    cam_i2c_write(cam_iic, device_addr, 0x587a, 0x14)
    cam_i2c_write(cam_iic, device_addr, 0x587b, 0x1e)
    cam_i2c_write(cam_iic, device_addr, 0x587c, 0x1c)
    cam_i2c_write(cam_iic, device_addr, 0x587d, 0x1c)
    cam_i2c_write(cam_iic, device_addr, 0x587e, 0x1a)
    cam_i2c_write(cam_iic, device_addr, 0x587f, 0x1a)
    cam_i2c_write(cam_iic, device_addr, 0x5880, 0x1b)
    cam_i2c_write(cam_iic, device_addr, 0x5881, 0x1f)
    cam_i2c_write(cam_iic, device_addr, 0x5882, 0x14)
    cam_i2c_write(cam_iic, device_addr, 0x5883, 0x1a)
    cam_i2c_write(cam_iic, device_addr, 0x5884, 0x1d)
    cam_i2c_write(cam_iic, device_addr, 0x5885, 0x1e)
    cam_i2c_write(cam_iic, device_addr, 0x5886, 0x1a)
    cam_i2c_write(cam_iic, device_addr, 0x5887, 0x1a)
    cam_i2c_write(cam_iic, device_addr, 0x528a, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x528b, 0x06)
    cam_i2c_write(cam_iic, device_addr, 0x528c, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x528d, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x528e, 0x40)
    cam_i2c_write(cam_iic, device_addr, 0x528f, 0x50)
    cam_i2c_write(cam_iic, device_addr, 0x5290, 0x60)
    cam_i2c_write(cam_iic, device_addr, 0x5292, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5293, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x5294, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5295, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x5296, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5297, 0x08)
    cam_i2c_write(cam_iic, device_addr, 0x5298, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5299, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x529a, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x529b, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x529c, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x529d, 0x28)
    cam_i2c_write(cam_iic, device_addr, 0x529e, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x529f, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x5282, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5680, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5681, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5682, 0x05)
    cam_i2c_write(cam_iic, device_addr, 0x5683, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5684, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5685, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x5686, 0x03)
    cam_i2c_write(cam_iic, device_addr, 0x5687, 0xc0)
    cam_i2c_write(cam_iic, device_addr, 0x5180, 0xff)
    cam_i2c_write(cam_iic, device_addr, 0x5181, 0x52)
    cam_i2c_write(cam_iic, device_addr, 0x5182, 0x11)
    cam_i2c_write(cam_iic, device_addr, 0x5183, 0x14)
    cam_i2c_write(cam_iic, device_addr, 0x5184, 0x25)
    cam_i2c_write(cam_iic, device_addr, 0x5185, 0x24)
    cam_i2c_write(cam_iic, device_addr, 0x5186, 0x14)
    cam_i2c_write(cam_iic, device_addr, 0x5187, 0x14)
    cam_i2c_write(cam_iic, device_addr, 0x5188, 0x14)
    cam_i2c_write(cam_iic, device_addr, 0x5189, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x518a, 0x60)
    cam_i2c_write(cam_iic, device_addr, 0x518b, 0xa2)
    cam_i2c_write(cam_iic, device_addr, 0x518c, 0x9c)
    cam_i2c_write(cam_iic, device_addr, 0x518d, 0x36)
    cam_i2c_write(cam_iic, device_addr, 0x518e, 0x34)
    cam_i2c_write(cam_iic, device_addr, 0x518f, 0x54)
    cam_i2c_write(cam_iic, device_addr, 0x5190, 0x4c)
    cam_i2c_write(cam_iic, device_addr, 0x5191, 0xf8)
    cam_i2c_write(cam_iic, device_addr, 0x5192, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x5193, 0x70)
    cam_i2c_write(cam_iic, device_addr, 0x5194, 0xf0)
    cam_i2c_write(cam_iic, device_addr, 0x5195, 0xf0)
    cam_i2c_write(cam_iic, device_addr, 0x5196, 0x03)
    cam_i2c_write(cam_iic, device_addr, 0x5197, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x5198, 0x05)
    cam_i2c_write(cam_iic, device_addr, 0x5199, 0x2f)
    cam_i2c_write(cam_iic, device_addr, 0x519a, 0x04)
    cam_i2c_write(cam_iic, device_addr, 0x519b, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x519c, 0x06)
    cam_i2c_write(cam_iic, device_addr, 0x519d, 0xa0)
    cam_i2c_write(cam_iic, device_addr, 0x519e, 0xa0)
    cam_i2c_write(cam_iic, device_addr, 0x3a0f, 0x3c)
    cam_i2c_write(cam_iic, device_addr, 0x3a10, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x3a1b, 0x3c)
    cam_i2c_write(cam_iic, device_addr, 0x3a1e, 0x30)
    cam_i2c_write(cam_iic, device_addr, 0x3a11, 0x70)
    cam_i2c_write(cam_iic, device_addr, 0x3a1f, 0x10)
    cam_i2c_write(cam_iic, device_addr, 0x3800, 0x1)
    cam_i2c_write(cam_iic, device_addr, 0x3801, 0x50)
    cam_i2c_write(cam_iic, device_addr, 0x3802, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x3803, 0x8)
    cam_i2c_write(cam_iic, device_addr, 0x3804, 0x5)
    cam_i2c_write(cam_iic, device_addr, 0x3805, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x3806, 0x3)
    cam_i2c_write(cam_iic, device_addr, 0x3807, 0xc0)
    cam_i2c_write(cam_iic, device_addr, 0x3808, 0x3)
    cam_i2c_write(cam_iic, device_addr, 0x3809, 0x20)
    cam_i2c_write(cam_iic, device_addr, 0x380a, 0x2)
    cam_i2c_write(cam_iic, device_addr, 0x380b, 0x58)
    cam_i2c_write(cam_iic, device_addr, 0x380c, 0xc)
    cam_i2c_write(cam_iic, device_addr, 0x380d, 0x80)
    cam_i2c_write(cam_iic, device_addr, 0x380e, 0x3)
    cam_i2c_write(cam_iic, device_addr, 0x380f, 0xe8)
    cam_i2c_write(cam_iic, device_addr, 0x5001, 0x7f)
    cam_i2c_write(cam_iic, device_addr, 0x5680, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x5681, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x5682, 0x5)
    cam_i2c_write(cam_iic, device_addr, 0x5683, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x5684, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x5685, 0x0)
    cam_i2c_write(cam_iic, device_addr, 0x5686, 0x3)
    cam_i2c_write(cam_iic, device_addr, 0x5687, 0xc0)
    cam_i2c_write(cam_iic, device_addr, 0x5687, 0xc0)
    cam_i2c_write(cam_iic, device_addr, 0x3815, 0x02)
    cam_i2c_write(cam_iic, device_addr, 0x3503, 0x00)
    cam_i2c_write(cam_iic, device_addr, 0x3818, 0x81) # No Mirror
    cam_i2c_write(cam_iic, device_addr, 0x3621, 0xa7)

    cam_i2c_write(cam_iic, device_addr, 0x4740, 0x21)

    cam_i2c_write(cam_iic, device_addr, 0x501e, 0x2a)
    cam_i2c_write(cam_iic, device_addr, 0x5002, 0x78)
    cam_i2c_write(cam_iic, device_addr, 0x501f, 0x01)
    cam_i2c_write(cam_iic, device_addr, 0x4300, 0x61)

# frame buffer alocate
height = 600
width = 800
buffer0 = allocate(shape=(height, width, 1), dtype=np.uint32, cacheable=1)
buffer1 = allocate(shape=(height, width, 1), dtype=np.uint32, cacheable=1)
buffer2 = allocate(shape=(height, width, 1), dtype=np.uint32, cacheable=1)
buffer3 = allocate(shape=(height, width, 3), dtype=np.uint8, cacheable=1)

# frame buffer resister set
vflip_dmaw.register_map.fb0_1 = buffer0.physical_address
vflip_dmaw.register_map.fb0_2 = 0
vflip_dmaw.register_map.fb1_1 = buffer1.physical_address
vflip_dmaw.register_map.fb1_2 = 0
vflip_dmaw.register_map.fb2_1 = buffer2.physical_address
vflip_dmaw.register_map.fb2_2 = 0

dma2axis30.register_map.fb0 = buffer0.physical_address
dma2axis30.register_map.fb1 = buffer1.physical_address
dma2axis30.register_map.fb2 = buffer2.physical_address
dma2axis30.register_map.mode = 0 # DMA_WRITE_MODE

dma2axis31.register_map.fb0 = buffer0.physical_address
dma2axis31.register_map.fb1 = buffer1.physical_address
dma2axis31.register_map.fb2 = buffer2.physical_address
dma2axis31.register_map.mode = 0 # DMA_WRITE_MODE

sobel0.register_map.row_size = height
sobel0.register_map.col_size = width
sobel0.register_map.function_r = 0 # ORG_IMGwAxiVdma

sobel1.register_map.row_size = height
sobel1.register_map.col_size = width
sobel1.register_map.function_r = 0 # ORG_IMGwAxiVdma

axis2dma.register_map.out_r = buffer3.physical_address
axis2dma.register_map.row_size = height
axis2dma.register_map.col_size = width

# vflip_dma_write start and auto repeat
vflip_dmaw.register_map.CTRL = 0x81

# Camera Initialization
cam_i2c_init(cam_iic)
cam_reg_set(cam_iic, 0x78)

# paracam_inf_axi start
paracam_inf.write(0x0, 0x0)
paracam_inf.write(0x4, 0x0)

# bitmap_disp_cont start
bmpd_cont.write(0x0, 0x0)

# sobel_axis_RGB24 start
sobel0.register_map.CTRL = 0x81

# dma2axis_3buf start and auto repeat
dma2axis30.register_map.CTRL = 0x81

# image capture
axis2dma.register_map.CTRL = 0x1

print(axis2dma.register_map.CTRL)

sobel1.register_map.CTRL = 0x1

print(sobel1.register_map.CTRL)

dma2axis31.register_map.CTRL = 0x1

print(dma2axis31.register_map.CTRL)

print(axis2dma.register_map.CTRL)
print(sobel1.register_map.CTRL)
print(dma2axis31.register_map.CTRL)

cam_image = Image.fromarray(buffer3)
print("Image size: {}x{} pixels.".format(width, height))
plt.figure(figsize=(12, 10));
_ = plt.imshow(cam_image)

cam_image.save('temp.jpg')

#sobel filter on for camera image
sobel0.register_map.function_r = 1 # SOBELwAxiVdma

# sobel filter off for camera image
sobel0.register_map.function_r = 0 # ORG_IMGwAxiVdma

#sobel fliter on for image capture
sobel1.register_map.function_r = 1 # SOBELwAxiVdma
#axis2dma.register_map.CTRL = 0x1
#sobel1.register_map.CTRL = 0x1
#dma2axis31.register_map.CTRL = 0x1

#sobel fliter off for image capture
sobel1.register_map.function_r = 0 # ORG_IMGwAxiVdma
#axis2dma.register_map.CTRL = 0x1
#sobel1.register_map.CTRL = 0x1
#dma2axis31.register_map.CTRL = 0x1

  1. 2022年09月02日 05:07 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0

”MicroZed Chronicles: PYNQ Interrupts”をやってみる1

PYNQ での割り込みを学習するために、Adam Taylor さんの”MicroZed Chronicles: Memory Scrubbing”を ZYBO Z7-20 の PYNQ でやってみることにした。今回は、Vivado 2022.1 で pynq_int プロジェクトを作成してブロック・デザインを作成し、論理合成、インプリメンテーション、ビットストリームの生成を行った。

Vivado 2022.1 で pynq_int プロジェクトを作成した。
pynq_int_1_220901.png

pynq_int ブロック・デザインを作成した。
pynq_int_2_220901.png

axi_intc_0 の設定を示す。
デフォルトのままだ。
pynq_int_3_220901.png

axi_gpio_0 の設定を示す。
GPIO 、 GPIO2 共に 4 ビット幅の入力モードに設定されている。
Enable Interrupt にチェックを入れた。
pynq_int_4_220901.png

axi_gpio_1 の設定を示す。
GPIO のみで、4 ビット幅の出力モードに設定されている。
pynq_int_5_220901.png

なお、axi_gpio_0 と axi_gpio_1 の入出力先だが、ZYBO Z7-20 のLED やボタンスイッチ、スライド・スイッチが予めボードの定義として定義されているので、自動配線の時に選択することができる。
pynq_int_6_220901.png

Address Editor を示す。
pynq_int_7_220901.png

HDL Wrapper を作成し、論理合成、インプリメンテーション、ビットストリームの生成を行った。
Project Summary を示す。
pynq_int_8_220901.png
  1. 2022年09月01日 04:55 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0