FC2カウンター FPGAの部屋 ZYBO Z7
FC2ブログ

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

FPGAの部屋

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

ZYBO Z7-20でのMNISTの実装にOV5642を使用する3

ZYBO Z7-20でのMNISTの実装にOV5642を使用する2”の続き。

前回は、OV5642 カメラ画像を垂直方向にフリップした画像で、ディスプレイに表示することができた。その後、垂直方向にフリップするDMA の vflip_dma_write もできたので、これを使用してMNIST 手書き数字判定システムを修正して行こう。

Vivado 2018.3 で MNIST_CNN_Z7_OV5642 プロジェクトを MNIST_CNN_Z7_OV5642vfd_183 ディレクトリに作成した。
MNIST_CNN_Z7_OV5642_1_190105.png

MNIST_CNN_Z7 ブロック・デザインを示す。
MNIST_CNN_Z7_OV5642_2_190105.png

FCLK_CLK2 は 24 MHz に設定した。

次に、camera_interface モジュールを示す。
MNIST_CNN_Z7_OV5642_3_190105.png

AXI_VDMA を vflip_dma_write IP に変更してある。

Address Editor を示す。
MNIST_CNN_Z7_OV5642_8_190105.png

論理合成、インプリメンテーション、ビットストリームの生成を行った。結果を示す。
MNIST_CNN_Z7_OV5642_4_190105.png

タイミングも満足している。成功だ。
ハードウェアをエクスポートして、SDK を立ち上げた。
mnist_cnn_soft_vflip プロジェクトを作成して、mnist_cnn_soft_vflip.c アプリケーション・ソフトを作成した。
MNIST_CNN_Z7_OV5642_5_190105.png

FPGA にビット・ファイルをダウンロードして、mnist_cnn_soft_vflip.elf を起動した。
OV5642のカメラ画像が表示された。
MNIST_CNN_Z7_OV5642_7_190105.jpg

gtk_term を立ち上げて、キーでピンクの四角を数字の 3 に合わせて、r コマンドでmnist_cnn の結果を表示させた。
MNIST_CNN_Z7_OV5642_6_190105.png

ハードウェア、ソフトウェアともに 3 と判定している。成功だ。

最後に、mnist_cnn_soft_vflip.c を載せておく。

/*
 * mnist_conv_soft_vflip.c (for ZYBO Z7-20, for OV5642)
 *
 *  Created on: 2019/01/03
 *      Author: marsee
 */

#include <stdio.h>
#include <stdlib.h>
#include "xil_io.h"
#include "xparameters.h"
#include "sleep.h"
#include "xtime_l.h"

#include "xvflip_dma_write.h"
#include "xmnist_conv_nn.h"
#include "xsquare_frame_gen.h"
#include "af1_bias_float.h"
#include "af1_weight_float.h"
#include "af2_bias_float.h"
#include "af2_weight_float.h"
#include "conv1_bias_float.h"
#include "conv1_weight_float.h"

#define FRAME_BUFFER_ADDRESS 0x10000000
#define NUMBER_OF_WRITE_FRAMES  3 // Note: If not at least 3 or more, the image is not displayed in succession.

#define HORIZONTAL_PIXELS   800
#define VERTICAL_LINES      600
#define PIXEL_NUM_OF_BYTES  4

int max_int(int out[10]);
int max_float(float out[10]);
int mnist_conv_nn_float(int in[22400], int addr_offset, float out[10]);
float conv_rgb2y_soft(int rgb);

float buf[28][28];
float conv_out[10][24][24];
float pool_out[10][12][12];
float dot1[100];
float dot2[10];

void cam_i2c_init(volatile unsigned *ov5642_i2c_axi_lites) {
    ov5642_i2c_axi_lites[64] = 0x2; // reset tx fifo ,address is 0x100, i2c_control_reg
    ov5642_i2c_axi_lites[64] = 0x1; // enable i2c
}

void cam_i2x_write_sync(void) {
    // unsigned c;

    // c = *cam_i2c_rx_fifo;
    // while ((c & 0x84) != 0x80)
        // c = *cam_i2c_rx_fifo; // No Bus Busy and TX_FIFO_Empty = 1
    usleep(1000);
}

void cam_i2c_write(volatile unsigned *ov5642_axi_iic, unsigned int device_addr, unsigned int write_addr, unsigned int write_data){
    ov5642_axi_iic[66] = 0x100 | (device_addr & 0xfe); // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
    ov5642_axi_iic[66] = (write_addr >> 8) & 0xff;  // address upper byte
    ov5642_axi_iic[66] = write_addr & 0xff;           // address lower byte
    ov5642_axi_iic[66] = 0x200 | (write_data & 0xff);      // data
    cam_i2x_write_sync();
}


int cam_reg_set(volatile unsigned *axi_iic, unsigned int device_addr);

int main(){
    XMnist_conv_nn mcnn;
    XSquare_frame_gen sf_gen;
    XVflip_dma_write vfdma;
    int inbyte_in;
    int xval, yval;
    int i, res;
    int result[10];
    float result_float[10];
    int max_id;
    int result_disp = 0;
    int conv_addr;
    int max_id_float;
    XTime start_time, end_time;

    // vflip_dma_write Initialization sequence
    XVflip_dma_write_Initialize(&vfdma, 0);

    // Frame buffer address set
    XVflip_dma_write_Set_fb0_V(&vfdma, FRAME_BUFFER_ADDRESS);
    XVflip_dma_write_Set_fb1_V(&vfdma, FRAME_BUFFER_ADDRESS);
    XVflip_dma_write_Set_fb2_V(&vfdma, FRAME_BUFFER_ADDRESS);
    
    // Mnist_conv_nn, Square_frame_gen Initialize
    XMnist_conv_nn_Initialize(&mcnn, 0);
    XSquare_frame_gen_Initialize(&sf_gen, 0);

    // square_frame_gen initialize
    XSquare_frame_gen_Set_x_pos(&sf_gen, HORIZONTAL_PIXELS/2);
    xval = HORIZONTAL_PIXELS/2;
    XSquare_frame_gen_Set_y_pos(&sf_gen, VERTICAL_LINES/2);
    yval = VERTICAL_LINES/2;
    XSquare_frame_gen_Set_width(&sf_gen, 28);
    XSquare_frame_gen_Set_height(&sf_gen, 28);
    XSquare_frame_gen_Set_off_on(&sf_gen, 1); // on

    // XSquare_frame_gen start
    XSquare_frame_gen_DisableAutoRestart(&sf_gen);
    while(!XSquare_frame_gen_IsIdle(&sf_gen)) ;
    XSquare_frame_gen_Start(&sf_gen);
    XSquare_frame_gen_EnableAutoRestart(&sf_gen);

    // mnist_conv_nn initialize
    XMnist_conv_nn_Set_addr_offset(&mcnn, HORIZONTAL_PIXELS/2);
    XMnist_conv_nn_Set_in_r(&mcnn, FRAME_BUFFER_ADDRESS+HORIZONTAL_PIXELS*(VERTICAL_LINES/2)*sizeof(int));

    // axis_switch_1, 1to2 ,Select M00_AXIS
    // Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR+0x40), 0x80000000); // disable
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR+0x44), 0x0); // square_frame_gen enable
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR), 0x2); // Commit registers

    // axis_switch_0, 2to1, Select S00_AXIS
    // Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_0_BASEADDR+0x40), 0x1);
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_0_BASEADDR), 0x2); // Commit registers

    // vflip_dma_write start
    XVflip_dma_write_Start(&vfdma);
    XVflip_dma_write_EnableAutoRestart(&vfdma);
    
    // ov5642_inf_axis_0, axi_iic_0, bitmap_disp_cntrler_axi_master_0
    volatile unsigned int *bmdc_axi_lites;
    volatile unsigned int *ov5642_axi_lites;
    volatile unsigned int *ov5642_i2c_axi_lites;

    bmdc_axi_lites = (volatile unsigned *)XPAR_BMD_CONTROLLER_AXIM_0_BASEADDR;
    ov5642_axi_lites = (volatile unsigned *)XPAR_CAMERA_INTERFACE_MT9D111_INF_AXIS_0_BASEADDR;
    ov5642_i2c_axi_lites = (volatile unsigned *)XPAR_CAMERA_INTERFACE_AXI_IIC_0_BASEADDR;

    bmdc_axi_lites[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Bitmap Display Controller start
    //ov5642_axi_lites[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Camera Interface start (Address is dummy)

    // CMOS Camera initialize, MT9D111
    cam_i2c_init(ov5642_i2c_axi_lites);

    cam_reg_set(ov5642_i2c_axi_lites, 0x78); // OV5642 register set

    ov5642_axi_lites[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Camera Interface start (Address is dummy)
    ov5642_axi_lites[1] = 0; // One_shot_mode is disabled

    while(1){
        printf("mnist_conv_nn_test, <h> : left, <k> : up, <j> : down, <l> : right, <q> : exit\n");
        inbyte_in = inbyte();
        switch(inbyte_in) {
            case 'h' : // left
            case 'H' : // left -5
                if(inbyte_in == 'h' && xval > 0)
                    --xval;
                else if(inbyte_in == 'H' && xval >= 5)
                    xval -= 5;
                XSquare_frame_gen_Set_x_pos(&sf_gen, xval);
                XMnist_conv_nn_Set_addr_offset(&mcnn, xval);
                printf("X_POS = %d, Y_POS = %d\n", xval, yval);
                break;
            case 'l' : // right
            case 'L' : // right +5
                if(inbyte_in == 'l' && xval < HORIZONTAL_PIXELS-28)
                    xval++;
                else if(inbyte_in == 'L' && xval <= HORIZONTAL_PIXELS-28-5)
                    xval += 5;
                XSquare_frame_gen_Set_x_pos(&sf_gen, xval);
                XMnist_conv_nn_Set_addr_offset(&mcnn, xval);
                printf("X_POS = %d, Y_POS = %d\n", xval, yval);
                break;
            case 'k' : // up
            case 'K' : // up +5 (vflip)
                if(inbyte_in == 'k' && yval > 0)
                    yval++;
                else if(inbyte_in == 'K' && yval >= 5)
                    yval += 5;
                XSquare_frame_gen_Set_y_pos(&sf_gen, yval);
                XMnist_conv_nn_Set_in_r(&mcnn, FRAME_BUFFER_ADDRESS+HORIZONTAL_PIXELS*(VERTICAL_LINES-1-yval-28)*sizeof(int));
                printf("X_POS = %d, Y_POS = %d\n", xval, yval);
                break;
            case 'j' : // down
            case 'J' : // down -5 (vflip)
                if(inbyte_in == 'j' && yval < VERTICAL_LINES-28)
                    --yval;
                else if(inbyte_in == 'J' && yval <= VERTICAL_LINES-28-5)
                    yval -= 5;
                XSquare_frame_gen_Set_y_pos(&sf_gen, yval);
                XMnist_conv_nn_Set_in_r(&mcnn, FRAME_BUFFER_ADDRESS+HORIZONTAL_PIXELS*(VERTICAL_LINES-1-yval-28)*sizeof(int));
                printf("X_POS = %d, Y_POS = %d\n", xval, yval);
                break;
            case 'r' : // result check
                result_disp = 1;
                break;
            case 'q' : // exit
                return(0);
        }

        if(result_disp){
            printf("\nHardware\n");
            // XMnist_conv_nn start
            XMnist_conv_nn_DisableAutoRestart(&mcnn);
            while(!XMnist_conv_nn_IsIdle(&mcnn));
            XTime_GetTime(&start_time);
            XMnist_conv_nn_Start(&mcnn);
            while(!XMnist_conv_nn_IsIdle(&mcnn));
            XTime_GetTime(&end_time);
            printf("conv_time = %f ms\n", (float)((long)end_time-(long)start_time)/325000.0);

            // mnist cnn result check
            for(i=0; i<5; i++){
                XMnist_conv_nn_Read_out_V_Words(&mcnn, i, &res, 1);
                result[i*2] = res & 0x0fff;
                if(result[i*2] & 0x800) // minus
                    result[i*2] = 0xfffff000 | result[i*2]; // Sign extension

                result[i*2+1] = (res & 0x0fff0000) >> 16;
                if(result[i*2+1] & 0x800) // minus
                    result[i*2+1] = 0xfffff000 | result[i*2+1]; // Sign extension
            }

            max_id = max_int(result);

            for(i=0; i<10; i++){
                printf("result[%d] = %x\n", i, result[i]);
            }
            printf("max_id = %d\n", max_id);

            printf("\nSoftware\n");
            conv_addr = FRAME_BUFFER_ADDRESS+HORIZONTAL_PIXELS*(VERTICAL_LINES-1-yval-28)*sizeof(int);
            XTime_GetTime(&start_time);
            mnist_conv_nn_float((int *)conv_addr, xval, result_float);
            XTime_GetTime(&end_time);
            max_id_float = max_float(result_float);
            printf("conv_time = %f ms\n", (float)((long)end_time-(long)start_time)/325000.0);
            for(i=0; i<10; i++){
                printf("result_float[%d] = %f\n", i, result_float[i]);
            }
            printf("max_id_float = %d\n", max_id_float);

            result_disp = 0;
        }
    }
}

int max_int(int out[10]){
    int max_id;
    int max, i;

    for(i=0; i<10; i++){
        if(i == 0){
            max = out[0];
            max_id = 0;
        }else if(out[i]>max){
            max = out[i];
            max_id = i;
        }
    }
    return(max_id);
}

int mnist_conv_nn_float(int in[22400], int addr_offset, float out[10]){

    // 手書き数字の値を表示
    /*for (int i=0; i<28; i++){
        for (int j=0; j<800; j++){
            if (j>=addr_offset && j<addr_offset+28)
                printf("%2x, ", (int)(conv_rgb2y_soft(in[i*800+j])*256.0));
        }
        printf("\n");
    } */

    buf_copy1: for(int i=0; i<28; i++){
        buf_copy2: for(int j=0; j<800; j++){
            if (j>=addr_offset && j<addr_offset+28)
                buf[i][j-addr_offset] = (float)0.99609375 - (float)conv_rgb2y_soft(in[i*800+j]);
        }
    }

    // Convolutional Neural Network 5x5 kernel, Stride = 1, Padding = 0
    // + ReLU
    CONV1: for(int i=0; i<10; i++){ // カーネルの個数
        CONV2: for(int j=0; j<24; j++){
            CONV3: for(int k=0; k<24; k++){
                conv_out[i][j][k] = 0;
                CONV4: for(int m=0; m<5; m++){
                    CONV5: for(int n=0; n<5; n++){
                        conv_out[i][j][k] += buf[j+m][k+n] * conv1_fweight[i][0][m][n];
                    }
                }
                conv_out[i][j][k] += conv1_fbias[i];

                if(conv_out[i][j][k]<0) // ReLU
                    conv_out[i][j][k] = 0;
            }
        }
    }

    // Pooling Kernel = 2 x 2, Stride = 2
    POOL1: for(int i=0; i<10; i++){
        POOL2: for(int j=0; j<24; j += 2){
            POOL3: for(int k=0; k<24; k += 2){
                POOL4: for(int m=0; m<2; m++){
                    POOL5: for(int n=0; n<2; n++){
                        if(m==0 && n==0){
                            pool_out[i][j/2][k/2] = conv_out[i][j][k];
                        } else if(pool_out[i][j/2][k/2] < conv_out[i][j+m][k+n]){
                            pool_out[i][j/2][k/2] = conv_out[i][j+m][k+n];
                        }
                    }
                }
            }
        }
    }

    af1_dot1: for(int col=0; col<100; col++){
        dot1[col] = 0;
        af1_dot2: for(int i=0; i<10; i++){
            af1_dot3: for(int j=0; j<12; j++){
                af1_dot4: for(int k=0; k<12; k++){
                    dot1[col] += pool_out[i][j][k]*af1_fweight[i*12*12+j*12+k][col];
                }
            }
        }
        dot1[col] += af1_fbias[col];

        if(dot1[col] < 0)   // ReLU
            dot1[col] = 0;
    }

    af2_dot1: for(int col=0; col<10; col++){
        dot2[col] = 0;
        af2_dot2: for(int row=0; row<100; row++){
            dot2[col] += dot1[row]*af2_fweight[row][col];
        }
        dot2[col] += af2_fbias[col];

        out[col] = dot2[col];
    }

    return(0);
}

int max_float(float out[10]){
    int max_id;
    float max;

    for(int i=0; i<10; i++){
        if(i == 0){
            max = out[0];
            max_id = 0;
        }else if(out[i]>max){
            max = out[i];
            max_id = i;
        }
    }
    return(max_id);
}


// RGBからYへの変換
// RGBのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 輝度信号Yのみに変換する。変換式は、Y =  0.299R + 0.587G + 0.114B
// "YUVフォーマット及び YUV<->RGB変換"を参考にした。http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
// 2013/09/27 : float を止めて、すべてint にした
// 2017/06/30 : retval を float にした
float conv_rgb2y_soft(int rgb){
    int r, g, b, y_f;
    int y;
    float y_float;

    b = rgb & 0xff;
    g = (rgb>>8) & 0xff;
    r = (rgb>>16) & 0xff;

    y_f = 77*r + 150*g + 29*b; //y_f = 0.299*r + 0.587*g + 0.114*b;の係数に256倍した
    y = y_f >> 8; // 256で割る

    if (y >= 256)
        y = 255;

    y_float = (float)y/256.0;

    return(y_float);
}

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

    cam_i2c_write(axi_iic, device_addr, 0x4740, 0x21);

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

    return(0);
}

  1. 2019年01月05日 08:23 |
  2. ZYBO Z7
  3. | トラックバック:0
  4. | コメント:0

ZYBO Z7-20でのMNISTの実装にOV5642を使用する2

ZYBO Z7-20でのMNISTの実装にOV5642を使用する1”の続き。

前回は、ZYBO Z7-20 のMNIST の実装で、OV5642 を使用してみたいということで、やってみたところ、うまく行かない。mt9d111_inf_axis_0 のAXI4-Stream のトランザクションもないので、mt9d111_inf_axis_0 がおかしいようだということが分かった。今回は、Vivado Analyzer を入れて2日ほど調査したが、原因が分からなかった。やっと今日、その原因が分かったのだった。原因は、アプリケーション・ソフトでのコマンド順によるものだった。

さて、2日間、Vivado Analyzer を入れたり削除したり、いろいろな配線を観察したりしていたのだが、1回だけカメラ画像を表示することができた。だが、その1回だけで、もう何度やってもカメラ画像は表示することができなかった。1回うまく表示できたときのVivado Analyzer の波形を示す。
最初は、AXI-Stream 波形だ。これは、camera-interface 内のカメラ画像のAXI4-Stream 波形をキャプチャしたものだ。 Slot_0 が mt9d111_inf_axis_0 のAXI4-Stream 波形だ。うまく行っているのが分かる。
ZYBO_Z7_OV5642_10_181229.png

うまく行っている時の mt9d111_inf_axis_0 の波形を示す。
ZYBO_Z7_OV5642_11_181229.png

HREF と VSYNC の波形を示す。
ZYBO_Z7_OV5642_12_181230.jpg

カメラ画像を示す。なお、上下は逆になっているが、レジスタでこれしか設定できなかったためで、これで正しい。
ZYBO_Z7_OV5642_13_181230.jpg

しかし、Ultra96 はほぼ同じ回路でカメラ画像を表示できているし、なぜカメラ画像が表示できないか悩んでいた。今朝、私の好きなテレビ東京の路線バスの旅を見終わったら、ひらめいた。アプリケーション・ソフトがまずいのでは?ということだった。
もしかして、MT9D111 よりも大幅に長くなったレジスタ設定ルーチンがだめなのでは?と思い、よく見直してみた。

//ov5642_axi_lites[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Camera Interface start (Address is dummy)

// CMOS Camera initialize, MT9D111
cam_i2c_init(ov5642_i2c_axi_lites);

cam_reg_set(ov5642_i2c_axi_lites, 0x78); // OV5642 register set

ov5642_axi_lites[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Camera Interface start (Address is dummy)
ov5642_axi_lites[1] = 0; // One_shot_mode is disabled


ov5642_axi_lites[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; を実行すると、mt9d111_inf_axis のリセットが外れて動作するようになるのだが、最初のリセット解除は上に示す最初の行のコメントアウトされている部分にあった。ここで、リセットが外れて、カメラ画像のキャプチャが開始されるのだが、OV5642では、レジスタ設定を行わないとPCLK も出力されていない状況になっている。なので、非同期FIFO がおかしくなってしまっているのではないか?という仮定をした。そして、上のコードに差し替えるとカメラ画像が毎回表示されるようになった。やはり、クロックが出力されていない状態のため非同期FIFO が狂ってしまったようだ。ちなみにMT9D111 は最初からクロックも出力され、SVGA の設定になっているため、問題なかったようだ。
これで不具合は解消されたが、Ultra96 はなぜ大丈夫なのか?という疑問がある。多分今回と同じコードにしておいたほうが良いと思う。
動作も確認したので、”秋月電子カメラモジュールOV5642を使う15(完成)”のcam_cap_ov5642.cpp を修正した。
  1. 2018年12月30日 15:06 |
  2. ZYBO Z7
  3. | トラックバック:0
  4. | コメント:0

ZYBO Z7-20でのMNISTの実装にOV5642を使用する1

Ultra96 のUltra96 用PMOD 拡張ボード経由でOV5642 を使用することができた。
今回は、ZYBO Z7-20 のMNIST の実装で、OV5642 を使用してみたい。

Ultra96 では、MT9D111 のインターフェース用IP をそのまま使用して、OV5642 に行くクロック周波数のXCLK を 24 MHz に下だけだった。ZYBO Z7-20 でもXCLK を 24 MHz にしただけで確かめてみよう。

まずは、MNIST_CNN_Z7 をコピーしてMNIST_Z7_OV5642 ディレクトリとした。
ZYBO_Z7_OV5642_1_181228.png

MNIST_Z7_OV5642 ディレクトリのMNIST_CNN_Z7 プロジェクトを起動して、ZYNQ7 Processing System をダブルクリックして、ダイアログを表示させた。
ダイアログで、Page Navigator の Clock Configuration を選択して、FCLK_CLK2 を 24 MHz に変更した。
ZYBO_Z7_OV5642_2_181228.png

これで、論理合成、インプリメンテーション、ビットストリームの生成を行って、ハードウェアをエクスポートし、SDKを立ち上げてZYBO Z7-20 で確かめてみたが、画面はランダムパターンを表示されていて、カメラ画像を表示していなかった。

そこで、mt9d111_inf_axis_0 の m_axis と axi_vdma_0 の S_AXIS_S2MM 、 axi_vdma_0 の M_AXI_S2MM 、bmd_controller_axim_0 のM_AXI に Debug を指定して、Vivado Analyzer のプローブを仕掛けた。
ZYBO_Z7_OV5642_3_181228.png

ZYBO_Z7_OV5642_4_181228.png

論理合成、インプリメンテーション、ビットストリームの生成を行った。
ZYBO_Z7_OV5642_5_181228.png

タイミングエラーが出ているが、他は問題なさそう。
Implemented Design を開いて、タイミングエラーを見た。
Intra-Clock Paths と Inter-Clock Paths にタイミングエラーが出ていた。
Intra-Clock Paths の方から見ると、clk_fpga_0 の Setup がタイミングエラーだった。
ZYBO_Z7_OV5642_6_181228.png

mnist_conv_nn のところで、-0.177 ns だけタイミングエラーだった。

Inter-Clock Paths のタイミングエラーは、clk_fpga_0 to pclk_buf の間で、 -0.306 ns だった。
ZYBO_Z7_OV5642_7_181228.png

大丈夫そうなので、2つのタイミングエラーは無視して、これでやってみることにした。

まずは、何かアプリケーション・ソフトを起動しないとPL のクロックが出力されないので、SDK を立ち上げてHelloWorld を追加で作成した。アプリ起動時の波形が取りたい場合には、HelloWorld を起動して、PL のクロックを出力させて、Vivado Analyzer を起動してトリガを設定する必要があるためだ。
SDK には、すでにOV5642 用に設定レジスタを設定する cam_reg_set() 関数を追加した mnist_conv_soft_test.cpp が用意されている。
ZYBO_Z7_OV5642_8_181228.png

mnist_conv_soft_test.cpp のバイナリを起動した。

Vivado Analyzer で見ると、bmd_controller_axim_0 のM_AXI はトランザクションが発生しているが、その他はトランザクションが無い。mt9d111_inf_axis_0 のAXI4-Stream のトランザクションもないので、mt9d111_inf_axis_0 がおかしいようだ。最初にOV5642 の波形を調べる必要がありそうだ。
  1. 2018年12月28日 05:33 |
  2. ZYBO Z7
  3. | トラックバック:0
  4. | コメント:0

ZYBO Z7-20でPcam 5Cを使用する8(シリアル・インターフェースで設定変更)

ZYBO Z7-20でPcam 5Cを使用する7(Pcam 5Cの設定を変更)”の続き。

前回は、pcam_vdma_hdmi アプリケーション・プロジェクトの src フォルダの ov5640 フォルダの OV5640.h を変更してカメラの設定を変更した。今回は、pcam_vdma_hdmi アプリケーション・ソフトウェアは、シリアル・インターフェースを使用して設定を変更できる機能があるので、それを使用してみた。

まずは、起動時のTera Term の画面を示す。
MIPI_camera_63_180108.png

Digiletn のZybo Z7 Pcam 5C Demo の”Using the Zybo Z7 Pcam 5C Demo”の”Pcam 5C Image Sensor and Post Processing Options”から引用する。

a - Change Resolution
This option can be used to change the resolution of the video coming from the sensor. Currently 1080p@15Hz is not supported and will cause problems if used.
b - Change Liquid Lens Focus
This option is not compatible with this version of the Pcam 5C and should be ignored
d - Change Image Format
This option was included for debugging purposes and should always be set to RAW mode (option 2)
e - Write a Register inside the Image Sensor
This option allows you to write a value to any register inside the Image sensor over the OmniVision SCCB interface. You will need to refer to the OV5640 datasheet for information on the register map. This option is very useful for exploring the features of the image sensor.
f - Read a Register inside the Image Sensor
This option allows you to read the value of any register inside the Image sensor over the OmniVision SCCB interface.
g - Change Gamma Correction Factor Value
This option allows you to change the amount of gamma correction that is done by the custom AXI stream IP inside the FPGA.
h - Change AWB Settings
This option allows you to adjust how the image sensor is doing auto white balancing. There are 3 modes: Advanced, simple, and disabled. The advanced mode sometimes causes dramatic shifts between “red-ish” and “blue-ish” tints.


最初の”a”とリターンキーをタイプすると、解像度とフレームレートを変更することができる。
MIPI_camera_64_180108.png

2 の 1920 x 1080 15fps はサポートされていないそうなので、やってみると画像が乱れる。3. 1920 x 1080 30fps が標準だ。その時のカメラ画像を示す。
MIPI_camera_70_180110.jpg

1. 1280 x 720 60fps の時の画像を示す。
MIPI_camera_71_180110.jpg
(部屋が散らかっていて申し訳ありません)

b は機能がないそうなので、d とリターンキーをタイプすると、RGB と RAW に変更できるという?
MIPI_camera_65_180108.png

どこを変更しているのか良く分からないが? 1. にしてみた。
MIPI_camera_72_180110.jpg

色がおかしい。。。 2. にすると元に戻った。

f. Read a Register inside the Image Sensor はカメラのレジスタを Read できる機能だ。アドレスを指定するとレジスタの値を表示する。
vfilp の0x3820 のレジスタの値を読んでみよう。
”r”とリターンキーをタイプすると、アドレスを入れるモードになるので、3820 を入力した。
すると、レジスタの値の 40 を表示する。
MIPI_camera_66_180110.png

e. Write a Register inside the Image Sensor はカメラのレジスタを Write できる機能だ。アドレスを指定して、レジスタの値を入力する。 0x3820 に 0x46 を書くと上下反転した。
MIPI_camera_67_180110.png

g. Change Gamma Correction Factor Value は画像のガンマ値を変更することができる。
MIPI_camera_68_180110.png

1. が一番暗くて、5. が一番明るい。

1. の画像を示す。
MIPI_camera_73_180110.jpg

5. の画像を示す。
MIPI_camera_74_180110.jpg

h. Change AWB Settings はホワイト・バランスをアドバンスドとシンプルとオフから選択できる。
MIPI_camera_69_180110.png

1. と 2 . は変化が無かった。
3. のAWB をオフにすると、色が変わってしまった。
MIPI_camera_75_180110.jpg
  1. 2018年01月10日 06:34 |
  2. ZYBO Z7
  3. | トラックバック:0
  4. | コメント:0

ZYBO Z7-20でPcam 5Cを使用する7(Pcam 5Cの設定を変更)

ZYBO Z7-20でPcam 5Cを使用する6(Pcam 5Cのカメラ画像を表示できた)”の続き。

前回は、Digilent 社のデモ・プロジェクトで Pcam 5Cのカメラ画像を表示することができた。今回は、Pcam 5Cのカメラ画像をレジスタを設定することで、画像を変更してみた。

なお、参考にしたのは、Digilent 社のデモ・プロジェクトの OV5640.h と、Linux のドライバーの ov5640.c だ。
後は、Interface 2014年11月号の 「第4章 まずは体験! 最新処理画像機能で OV5642 の機能」を紹介しているエンヤ ヒロカズさんの記事だ( 42 ページ)。

まずは、下の写真の様に、Pcam 5Cのカメラを下に垂らした方が使いやすい。
MIPI_camera_57_180108.jpg

現状では、こうすると、画像は上下が逆になってしまう。
MIPI_camera_60_180108.jpg

ov5640 のデータシートの 39 ページの 4 image sensor core digital functions 、4.1 mirror and flip を引用する。
MIPI_camera_62_180108.png

pcam_vdma_hdmi アプリケーション・プロジェクトの src フォルダの ov5640 フォルダの OV5640.h を見ると、

{0x3820, 0x46}

になっていた。
MIPI_camera_55_180108.png

これは、vfilp がイネーブルになっている。つまり、上下方向で反転されている。Pcam 5C のシルクの向きとは反対なので、搭載方法をミスったのだろうか?

{0x3820, 0x40}

にすれば、上下反転が直るはず。
MIPI_camera_56_180108.png

こう修正すると上下反転したというか、上下反転が直った。
MIPI_camera_61_180108.jpg

次に、少し色が薄い気がするので、Interface 2014年11月号の 「第4章 まずは体験! 最新処理画像機能で OV5642 の機能」の 47 、48 ページの色飽和度を参考にして、0x5001, 0x 5583, 0x5584, 0x5580 のレジスタをいじってみたが、変化は無かった。

Interface 2014年11月号の 「第4章 まずは体験! 最新処理画像機能で OV5642 の機能」の 49、50 ページの「4 - 5 明るさを補正する・・・露出補正」をやってみた。最初、本の通りの値を入れたが、うまく行かない。カメラの型番が違うので、デフォルト値が違うのかも?ということで、レジスタのデフォルト値を読みだして、それを変更したら、露出補正がうまく行った。

まずは、露出補正後のカメラ画像を示す。レースのカーテン越しに外の状況が分かる。室内は暗くなっている。
MIPI_camera_58_180108.jpg

OV5640.h の修正部分のコードを示す。
MIPI_camera_52_180108.png

normal に戻す。
MIPI_camera_53_180108.png

すると、カメラ画像の外は白飛びしてしまう。
MIPI_camera_59_180108.jpg

そのときの OV5640.h の修正部分のコードを貼っておく。

        {0x5001, 0x03},

        // by marsee 2018/01/08
        //EV
        /*{0x3a0f,0x30}, // more dark
        {0x3a10,0x20},
        {0x3a1b,0x30},
        {0x3a1e,0x20},
        {0x3a11,0x88},
        {0x3a1f,0x40}*/
        {0x3a0f,0x78}, // normal
        {0x3a10,0x68},
        {0x3a1b,0x78},
        {0x3a1e,0x68},
        {0x3a11,0xD0},
        {0x3a1f,0x40}

  1. 2018年01月09日 04:22 |
  2. ZYBO Z7
  3. | トラックバック:0
  4. | コメント:0

ZYBO Z7-20でPcam 5Cを使用する6(Pcam 5Cのカメラ画像を表示できた)

ZYBO Z7-20でPcam 5Cを使用する5(SDK1)”の続き。

前回は、SDKのビルドでエラーが出て解消できなかった。今回は、ブロック・デザインで階層を設けないでやってみた。結果的にこれでうまく行ってPcam 5Cのカメラ画像を表示することができた。

ZYBO Z7-20でPcam 5Cを使用する3(インプリメント)”でPcam 5C用の階層とHDMI 出力の階層を分けてしまったので、そのまま分けないでフラットなブロック・デザインとしてやってみた。
MIPI_camera_38_180106.png

MIPI_camera_39_180106.png

拡大した。
MIPI_camera_40_180106.pngMIPI_camera_41_180106.png

Address Editor 画面。
MIPI_camera_42_180106.png

これで、論理合成、インプリメント、ビットストリームの生成を行った。
結果を示す。
MIPI_camera_43_180106.png

同様に sdk フォルダの内容を import すると、今度は、pcam_vdma_hdmi_bsp にBSP Documentation フォルダと ps7_cortexa9_0 フォルダができていた。これでOKそうだ。ビルドも通っている。
MIPI_camera_44_180106.png

Zybo Z7 Pcam 5C Demo”を参考にしながら、Pcam 5Cを接続して、ZYBO Z7の電源をONした。
PROG/UART のMicro USB ポートからパソコンに接続した。
MIPI_camera_45_180107.jpg

FPGAにビット・ファイルをダウンロードして、pcam_vdma_hdmi.elf を起動したところ、HDMI 出力にカメラ画像が表示された。
MIPI_camera_46_180107.jpg

彩度があまりよくないような気がするし、明るくなってくると白飛びしてしまうので、AGCが効いていないのかもしれない?もっと設定を頑張る必要あるとは感じた。

さて、これまではVivado 2016.4でやっていたのだが、Vivado 2017.4 にアップグレードしてみた。
IP をアップグレードしたら、ブロック・デザインも正常になったので、問題ないようだ。
MIPI_camera_47_180107.png

論理合成、インプリメント、ビットストリームの生成を行った。
結果を示す。
MIPI_camera_48_180107.png

critical warnings が増えているが、タイミングエラーの値は同じだ。Vivado 2017.4 になってからクリティカル・ワーニングの数が増えたような気がする。

ハードウエアをエクスポートして、SDK を立ち上げた。
同様に sdk フォルダの内容を import しても、エラーが出てしまう。

pcam_vdma_hdmi アプリケーションソフトをC++ の Empty Application テンプレートで新規作成して、sdk フォルダの hdmi, ov5640, platform フォルダと main.cc ファイルを src フォルダの下にコピーした。
MIPI_camera_51_180107.png

すると、pcam_vdma_hdmi_bsp の ps7_cortexa9_0 -> libsrc -> ddynclk_v1_0 -> ddynclk_g.c がエラーになっていた。
DDynClk_Config DDynClk_ConfigTable の[] の中の文字列の定義(名前を忘れちゃいました。。。)がないということで、エラーになってしまっていた。
よって、xparameters.h を見て、XPAR_AXI_DYNCLK_NUM_INSTANCES と入れ替えた。
MIPI_camera_50_180107.png

MIPI_camera_49_180107.png

こうすると、ビルドできた。
SDK 2016.4 の時と同様にFPGA にビット・ファイルをダウンロードして、pcam_vdma_hdmi.elf を起動したところ、HDMI 出力にカメラ画像が表示された。
  1. 2018年01月07日 15:41 |
  2. ZYBO Z7
  3. | トラックバック:0
  4. | コメント:0

ZYBO Z7-20でPcam 5Cを使用する5(SDK1)

ZYBO Z7-20でPcam 5Cを使用する4(タイミングエラーの検討)”の続き。

前回は、タイミングエラーを検証した。今回は、とりあえず、SDKでアプリケーションソフトを作成してみよう。

Vivado 2016.4 のFile メニューからExport -> Export Hardware... を選択する。

Export Hardware ダイアログで、Include bitstream にチェックを入れてから、OK ボタンをクリックする。

File メニューからLaunch SDK を選択して、SDK を起動した。
MIPI_camera_28_180106.png

Using Digilent Github Demo Projects の4. Import SDK Projects の Launch from Vivado に従って進めていく。

最初にFile メニューから Import... を選択する。
MIPI_camera_29_180106.png

Select ダイアログで、Existing Projects into Workspace を選択する。Next > ボタンをクリックする。
MIPI_camera_30_180106.png

Import Projects ダイアログで、Select root directory のBrowse... ボタンをクリックする。
MIPI_camera_31_180106.png

フォルダーの参照ダイアログで、Zybo-Z7-20-pcam-5c-master フォルダ下の sdk フォルダをクリックして、OK ボタンをクリックする。
MIPI_camera_32_180106.png

Import Projects ダイアログに、情報が入った。
Options の Copy projects into workspace にチェックを入れておく。
MIPI_camera_33_180106.png

pcam_vdma_hdmi アプリケーション・プロジェクトの platform.c がエラーになってしまう。
pcam_vdma_hdmi_bsp にインクルードのフォルダが無いからだ。
MIPI_camera_34_180106.png

それではということでBSP プロジェクトをリジェネレートしてみよう。
pcam_vdma_hdmi_bsp を右クリックして、右クリックメニューからRe-generate BSP Sources を選択した。
MIPI_camera_35_180106.png

Re-generate BSP Sources ダイアログが表示された。OK ボタンをクリックする。
MIPI_camera_36_180106.png

それでも必要なインクルード・フォルダなのどのソースは生成されない。SDK Log を見るとエラーが表示されていた。
MIPI_camera_37_180106.png
  1. 2018年01月07日 05:14 |
  2. ZYBO Z7
  3. | トラックバック:0
  4. | コメント:0
»