日曜技術者のメモ

趣味でやった事のメモ書きです。

Zynqのベアメタルアプリケーションで画像をメモリに書き込む

Zynqでベアメタルアプリケーション(OSなし)を走らせる際
テスト入力として画像データをメモリ上に展開したくなる時がある。
その際GIMPを使えば簡単に画像データをソースコードに変換できるので
blogに書いておく。

GIMP

まず、GIMPをインストール&起動する。
そしてメモリに展開したい画像を開く

開いた後、ファイル→名前をつけてエクスポートを選ぶ、
そして、右下のエクスポートされた全ての画像から
「Cソースコードヘッダ」を選んで適当に名前をつけてエクスポートする。
f:id:ginnyu-tei:20170709005400j:plain

(かなり大きなヘッダファイルが出力されるので開く時は注意!)

出力されたファイルを確認すると以下の様なコードが出力される。

static unsigned int width = 1024;
static unsigned int height = 768;

/*  Call this macro repeatedly.  After each use, the pixel data can be extracted  */

#define HEADER_PIXEL(data,pixel) {\
pixel[0] = (((data[0] - 33) << 2) | ((data[1] - 33) >> 4)); \
pixel[1] = ((((data[1] - 33) & 0xF) << 4) | ((data[2] - 33) >> 2)); \
pixel[2] = ((((data[2] - 33) & 0x3) << 6) | ((data[3] - 33))); \
data += 4; \
}
static char *header_data =
    "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
    "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
    "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
    "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
~以下画像データが続く~

SDK

ヘッダファイルができたらXilinx SDKでヘッダファイルをincludeする。
HEADER_PIXELを呼び出す毎にラスタースキャンでRGB色が取得できるので
それを直接メモリに書き込む。

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"

#include "test.h" //GIMPでエクスポートしたヘッダファイル


int main()
{
    int i,j;
    char pixel[3]; //RGB格納配列
    unsigned int R,G,B;

    volatile unsigned int *Addr;
    volatile unsigned int *reg_base;

    Addr = (unsigned int*)0x10000000;

    init_platform();

    Xil_DCacheDisable();


    print("Hello World\n\r");

    for (j = 0 ; j < 768;j++){
        for (i = 0 ; i < 1024;i++){
            HEADER_PIXEL(header_data,pixel); //1pix読み込む
            R = pixel[0] & 0xFF;
            G = pixel[1] & 0xFF;
            B = pixel[2] & 0xFF;
            Addr[j*1024+i]= (R << 16) | (G << 8) | (B); //メモリへ書き込み
            //Addr[j*1024+i]=j*1024+i;
        }
    }
~以下省略~

この手法はjtagで画像をFPGAに転送するので大きな画像の場合
少し時間がかかるのが難点だが手軽に使えるのが利点。