次は、今のガボールフィルタのままだと、右白線、左白線とCPUで設定する必要があるから、CPUで左右を設定してから、ガボール・フィルタ処理結果を取得する必要がある。これはフレームレートが遅くなってしまう。
そこで、左右白線の2フレーム1セットでガボールフィルタ処理を行うことにする。左右は当然異なるフレームバッファにDMAする。その為にVDMAを4フレーム対応にして左右左右のフレームバッファにライトする。
これで左右白線用ガボールフィルタはカメラのフレームレートが15 fps だから、半分の 7.5 fps でデータが取得できる。
このエッジをとりあえずはCPUで探索して、どの位置にいるかを確認することにしよう。
// Gabor_filter_lh_2.h
// 2016/07/24
// 2016/07/25 : 右白線検出用のGabor Filterの重みを追加
// 2016/07/27 : 右白線検出用配列と左白線検出用配列を統合
// 2016/08/29 : 1回目左白線検出、2回目右白線検出のモードを追加
//
#ifndef __Gabor_filter_lh_H__
#define __Gabor_filter_lh_H__
#define HORIZONTAL_PIXEL_WIDTH 800
#define VERTICAL_PIXEL_WIDTH 600
//#define HORIZONTAL_PIXEL_WIDTH 640 // for Simulation
//#define VERTICAL_PIXEL_WIDTH 480
//#define HORIZONTAL_PIXEL_WIDTH 64
//#define VERTICAL_PIXEL_WIDTH 48
#define ALL_PIXEL_VALUE (HORIZONTAL_PIXEL_WIDTH*VERTICAL_PIXEL_WIDTH)
#define ARRAY_SIZE 9
#define RIGHT_WEIGHT 1
#define LEFT_WEIGHT 0
#define L_R_WEIGHT 2
const int gabor_weight[2][ARRAY_SIZE][ARRAY_SIZE] = { // 左白線検出用+右白線検出用
{
{0,-3,-10,-16,-7,7,10,5,1},
{-3,-15,-27,-11,32,50,29,5,-2},
{-11,-24,-5,73,135,95,16,-17,-10},
{-11,4,85,187,160,14,-72,-52,-14},
{4,51,135,137,-18,-159,-136,-45,-2},
{16,50,59,-39,-179,-185,-73,3,13},
{10,12,-25,-104,-131,-60,15,27,11},
{1,-7,-31,-48,-24,18,29,14,3},
{-1,-5,-9,-4,10,16,10,2,-1}
},
{
{1,5,7,1,-12,-17,-10,-3,0},
{1,11,33,45,21,-16,-27,-15,-4},
{-8,-5,35,107,131,69,-2,-21,-11},
{-17,-47,-51,40,169,187,93,13,-7},
{-8,-54,-134,-147,-18,123,130,58,11},
{9,-6,-82,-185,-187,-65,36,44,17},
{11,24,12,-55,-125,-112,-43,1,7},
{3,14,30,23,-13,-41,-33,-12,-1},
{0,2,9,17,14,1,-6,-5,-2}
}
};
const float gabor_fweight[2][ARRAY_SIZE][ARRAY_SIZE] = { // 左白線検出用+右白線検出用(float)
{
{0.001282,-0.009914,-0.04062,-0.060586,-0.027574,0.026072,0.038427,0.018191,0.003056},
{-0.012155,-0.057448,-0.104645,-0.042953,0.123263,0.197238,0.114451,0.020448,-0.007239},
{-0.042252,-0.093065,-0.018911,0.285374,0.525746,0.372687,0.060734,-0.064748,-0.040465},
{-0.042261,0.015673,0.332798,0.728763,0.625046,0.053591,-0.283076,-0.203293,-0.05608},
{0.017342,0.198305,0.52554,0.535526,-0.069756,-0.622839,-0.531089,-0.177366,-0.006367},
{0.060866,0.19708,0.231032,-0.154219,-0.699885,-0.721808,-0.286707,0.013004,0.049249},
{0.038379,0.04877,-0.098477,-0.404993,-0.510165,-0.233566,0.057894,0.104366,0.041887},
{0.0047,-0.0278,-0.121277,-0.187262,-0.093276,0.070512,0.113857,0.055799,0.009976},
{-0.003798,-0.01885,-0.035607,-0.01709,0.037692,0.064268,0.038606,0.007536,-0.002133}
},
{
{0.005562,0.018882,0.028293,0.004499,-0.044995,-0.064838,-0.039469,-0.009822,0.000815},
{0.002294,0.04108,0.127023,0.175094,0.083025,-0.063755,-0.106402,-0.057798,-0.01406},
{-0.031269,-0.021096,0.135641,0.417286,0.512467,0.269946,-0.008354,-0.082091,-0.041357},
{-0.066348,-0.184919,-0.197802,0.15614,0.65976,0.728616,0.361674,0.052074,-0.027152},
{-0.031146,-0.211178,-0.523777,-0.573856,-0.069756,0.480311,0.506451,0.225223,0.041031},
{0.035552,-0.023892,-0.320104,-0.723563,-0.728735,-0.253689,0.1391,0.170625,0.067723},
{0.04216,0.094939,0.047511,-0.216623,-0.488075,-0.437898,-0.168739,0.003336,0.027009},
{0.012112,0.056596,0.115239,0.090332,-0.05076,-0.158403,-0.127847,-0.046375,-0.004918},
{-0.00168,0.007437,0.036985,0.067021,0.053689,0.004977,-0.02365,-0.018248,-0.005928}
}
};
#endif
// Gabor_fiter_lh_2.cpp
// 2016/07/23 by marsee
// 2016/07/25 : 右白線検出用のGabor Filterを追加して、右左の白線を指定するRorL 引数を追加
// 2016/07/27 : 右白線検出用配列と左白線検出用配列を統合
// 2016/08/29 : 1回目左白線検出、2回目右白線検出のモードを追加
//
#include <stdio.h>
#include <string.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>
#include <hls_video.h>
#include "Gabor_filter_lh_2.h"
int conv_rgb2y(int rgb);
int Gabor_filter_lh_2(hls::stream<ap_axis<32,1,1,1> >& ins,
hls::stream<ap_axis<32,1,1,1> >& outs, ap_uint<2> & RorL){
#pragma HLS INTERFACE s_axilite port=RorL
#pragma HLS INTERFACE axis port=ins
#pragma HLS INTERFACE axis port=outs
#pragma HLS INTERFACE s_axilite port=return
ap_axis<32,1,1,1> pix;
ap_axis<32,1,1,1> gabor;
hls::LineBuffer<ARRAY_SIZE-1, HORIZONTAL_PIXEL_WIDTH, int> linebuf;
hls::Window<ARRAY_SIZE, ARRAY_SIZE, int> mbuf;
int gray_pix, val, i, j, x, y;
do { // user が 1になった時にフレームがスタートする
ins >> pix;
} while(pix.user == 0);
for (int k=0; k<2; k++){
for (y=0; y<VERTICAL_PIXEL_WIDTH; y++){
for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
#pragma HLS PIPELINE II=1
if (!(x==0 && y==0)) // 最初の入力はすでに入力されている
ins >> pix; // AXI4-Stream からの入力
mbuf.shift_left(); // mbuf の列を1ビット左シフト
for(i=ARRAY_SIZE-2; i>=0; --i){
mbuf.insert(linebuf(i,x), i+1, ARRAY_SIZE-1);
}
gray_pix = conv_rgb2y(pix.data);
mbuf.insert(gray_pix, 0, ARRAY_SIZE-1);
// LineBuffer の更新
linebuf.shift_down(x);
linebuf.insert_bottom(gray_pix, x);
// 使用する配列を決定する
int ano;
switch (RorL){
case LEFT_WEIGHT :
ano = LEFT_WEIGHT;
break;
case RIGHT_WEIGHT :
ano = RIGHT_WEIGHT;
break;
case L_R_WEIGHT :
if (k == 0)
ano = LEFT_WEIGHT;
else
ano = RIGHT_WEIGHT;
break;
default :
ano = LEFT_WEIGHT;
break;
}
// Gabor filter の演算
for (j=0, val=0; j<ARRAY_SIZE-1; j++){
for (i=0; i<ARRAY_SIZE-1; i++){
val += gabor_weight[ano][j][i] * mbuf(ARRAY_SIZE-1-j,i);
}
}
val = val/256; // 256倍してあるので、1/256して戻す
if (val<0)
//val = -val; // 絶対値
val = 0; // マイナスの値を0に丸める
else if (val>255)
val = 255;
// Gabor filter・データの書き込み
gabor.data = (val<<16)+(val<<8)+val;
// 最初のARRAY_SIZE-1行とその他の行の最初のARRAY_SIZE-1列は無効データなので0とする
if (x<(ARRAY_SIZE-1) || y<(ARRAY_SIZE-1))
gabor.data = 0;
if (x==0 && y==0) // 最初のデータでは、TUSERをアサートする
gabor.user = 1;
else
gabor.user = 0;
if (x == (HORIZONTAL_PIXEL_WIDTH-1)) // 行の最後で TLAST をアサートする
gabor.last = 1;
else
gabor.last = 0;
outs << gabor; // AXI4-Stream へ出力
}
}
}
return(0);
}
// 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 にした
int conv_rgb2y(int rgb){
int r, g, b, y_f;
int y;
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で割る
return(y);
}
// Gabor_filter_lh_2_tb.cpp
// 2016/07/24 by marsee
// 2016/07/25 : 右白線検出用のGabor Filterを追加して、右左の白線を指定するRorL 引数を追加
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <iostream>
#include <fstream>
#include <math.h>
#include <ap_axi_sdata.h>
#include <hls_video.h>
#include "Gabor_filter_lh_2.h"
#include "bmp_header.h"
int Gabor_filter_lh_2(hls::stream<ap_axis<32,1,1,1> >& ins, hls::stream<ap_axis<32,1,1,1> >& outs, ap_uint<2> & RorL);
int conv_rgb2y_soft(int rgb);
int Gabor_filter_lh_2_soft(hls::stream<ap_axis<32,1,1,1> >& ins, hls::stream<ap_axis<32,1,1,1> >& outs, ap_uint<2> & RorL);
#define CLOCK_PERIOD 10
#define RIGHT_OR_LEFT L_R_WEIGHT
#define BMP_FILE_NAME "road_1.bmp"
int main()
{
using namespace std;
hls::stream<ap_axis<32,1,1,1> > ins;
hls::stream<ap_axis<32,1,1,1> > ins_soft;
hls::stream<ap_axis<32,1,1,1> > outs;
hls::stream<ap_axis<32,1,1,1> > outs_soft;
ap_axis<32,1,1,1> pix;
ap_axis<32,1,1,1> vals;
ap_axis<32,1,1,1> vals_soft;
int m_seq = 1; // M系列の値
int i, k;
int xor_shift;
BITMAPFILEHEADER bmpfhr; // BMPファイルのファイルヘッダ(for Read)
BITMAPINFOHEADER bmpihr; // BMPファイルのINFOヘッダ(for Read)
FILE *fbmpr, *fbmpw, *fbmpwf;
int *rd_bmp, *hw_gabor, *sw_gabor;
int blue, green, red;
ap_uint<2> r_l;
char fhname[100];
char fsname[100];
if ((fbmpr = fopen(BMP_FILE_NAME, "rb")) == NULL){ // test.bmp をオープン
fprintf(stderr, "Can't open test.bmp by binary read mode\n");
exit(1);
}
// bmpヘッダの読み出し
fread(&bmpfhr.bfType, sizeof(char), 2, fbmpr);
fread(&bmpfhr.bfSize, sizeof(long), 1, fbmpr);
fread(&bmpfhr.bfReserved1, sizeof(short), 1, fbmpr);
fread(&bmpfhr.bfReserved2, sizeof(short), 1, fbmpr);
fread(&bmpfhr.bfOffBits, sizeof(long), 1, fbmpr);
fread(&bmpihr, sizeof(BITMAPINFOHEADER), 1, fbmpr);
// ピクセルを入れるメモリをアロケートする
if ((rd_bmp =(int *)malloc(sizeof(int) * (bmpihr.biWidth * bmpihr.biHeight))) == NULL){
fprintf(stderr, "Can't allocate rd_bmp memory\n");
exit(1);
}
if ((hw_gabor =(int *)malloc(2 * sizeof(int) * (bmpihr.biWidth * bmpihr.biHeight))) == NULL){
fprintf(stderr, "Can't allocate hw_gabor memory\n");
exit(1);
}
if ((sw_gabor =(int *)malloc(2 * sizeof(int) * (bmpihr.biWidth * bmpihr.biHeight))) == NULL){
fprintf(stderr, "Can't allocate hw_gabor memory\n");
exit(1);
}
// rd_bmp にBMPのピクセルを代入。その際に、行を逆転する必要がある
for (int y=0; y<bmpihr.biHeight; y++){
for (int x=0; x<bmpihr.biWidth; x++){
blue = fgetc(fbmpr);
green = fgetc(fbmpr);
red = fgetc(fbmpr);
rd_bmp[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] = (blue & 0xff) | ((green & 0xff)<<8) | ((red & 0xff)<<16);
}
}
fclose(fbmpr);
// ins に入力データを用意する
for(int i=0; i<5; i++){ // dummy data
pix.user = 0;
pix.data = i;
ins << pix;
}
// 2画面分を入力する
for(int k=0; k<2; k++){
for(int j=0; j < bmpihr.biHeight; j++){
for(i=0; i < bmpihr.biWidth; i++){
pix.data = (ap_int<32>)rd_bmp[(j*bmpihr.biWidth)+i];
if (j==0 && i==0) // 最初のデータの時に TUSER を 1 にする
pix.user = 1;
else
pix.user = 0;
if (i == bmpihr.biWidth-1) // 行の最後でTLASTをアサートする
pix.last = 1;
else
pix.last = 0;
ins << pix;
ins_soft << pix;
}
}
}
r_l = (ap_uint<2>)RIGHT_OR_LEFT;
Gabor_filter_lh_2(ins, outs, r_l);
Gabor_filter_lh_2_soft(ins_soft, outs_soft, r_l);
// ハードウェアとソフトウェアのラプラシアン・フィルタの値のチェック
cout << endl;
cout << "outs" << endl;
for(k=0; k<2; k++){
for(int j=0; j < bmpihr.biHeight; j++){
for(i=0; i < bmpihr.biWidth; i++){
outs >> vals;
outs_soft >> vals_soft;
ap_int<32> val = vals.data;
ap_int<32> val_soft = vals_soft.data;
hw_gabor[bmpihr.biWidth*bmpihr.biHeight*k+(j*bmpihr.biWidth)+i] = (int)val;
sw_gabor[bmpihr.biWidth*bmpihr.biHeight*k+(j*bmpihr.biWidth)+i] = (int)val_soft;
//printf("k=%d, j=%d, i=%d\n",k,j,i);
if ((double)pow((double)(val&0xff)-(val_soft&0xff),(double)2) > 4){ // 2乗誤差が4よりも大きい
printf("ERROR HW and SW results mismatch i = %ld, j = %ld, HW = %08x, SW = %08x\n", i, j, (int)val, (int)val_soft);
//return(1);
}
//if (vals.last)
//cout << "AXI-Stream is end" << endl;
}
}
}
cout << "Success HW and SW results match" << endl;
cout << endl;
// ハードウェアのラプラシアンフィルタの結果を temp_gabor0.bmp, temp_gabor1.bmp へ出力する
for(k=0; k<2; k++){
if(k == 0){
if ((fbmpw=fopen("temp_gabor0.bmp", "wb")) == NULL){
fprintf(stderr, "Can't open temp_gabor0.bmp by binary write mode\n");
exit(1);
}
} else {
if ((fbmpw=fopen("temp_gabor1.bmp", "wb")) == NULL){
fprintf(stderr, "Can't open temp_gabor1.bmp by binary write mode\n");
exit(1);
}
}
// BMPファイルヘッダの書き込み
fwrite(&bmpfhr.bfType, sizeof(char), 2, fbmpw);
fwrite(&bmpfhr.bfSize, sizeof(long), 1, fbmpw);
fwrite(&bmpfhr.bfReserved1, sizeof(short), 1, fbmpw);
fwrite(&bmpfhr.bfReserved2, sizeof(short), 1, fbmpw);
fwrite(&bmpfhr.bfOffBits, sizeof(long), 1, fbmpw);
fwrite(&bmpihr, sizeof(BITMAPINFOHEADER), 1, fbmpw);
// RGB データの書き込み、逆順にする
for (int y=0; y<bmpihr.biHeight; y++){
for (int x=0; x<bmpihr.biWidth; x++){
blue = hw_gabor[bmpihr.biWidth*bmpihr.biHeight*k+((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] & 0xff;
green = (hw_gabor[bmpihr.biWidth*bmpihr.biHeight*k+((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] >> 8) & 0xff;
red = (hw_gabor[bmpihr.biWidth*bmpihr.biHeight*k+((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x]>>16) & 0xff;
fputc(blue, fbmpw);
fputc(green, fbmpw);
fputc(red, fbmpw);
}
}
fclose(fbmpw);
}
// ソフトウェアのラプラシアンフィルタの結果を temp_gabor_float0.bmp, temp_gabor_float1.bmp へ出力する
for(k=0; k<2; k++){
if (k == 0){
if ((fbmpwf=fopen("temp_gabor_float0.bmp", "wb")) == NULL){
fprintf(stderr, "Can't open temp_gabor_float0.bmp by binary write mode\n");
exit(1);
}
} else {
if ((fbmpwf=fopen("temp_gabor_float1.bmp", "wb")) == NULL){
fprintf(stderr, "Can't open temp_gabor_float1.bmp by binary write mode\n");
exit(1);
}
}
// BMPファイルヘッダの書き込み
fwrite(&bmpfhr.bfType, sizeof(char), 2, fbmpwf);
fwrite(&bmpfhr.bfSize, sizeof(long), 1, fbmpwf);
fwrite(&bmpfhr.bfReserved1, sizeof(short), 1, fbmpwf);
fwrite(&bmpfhr.bfReserved2, sizeof(short), 1, fbmpwf);
fwrite(&bmpfhr.bfOffBits, sizeof(long), 1, fbmpwf);
fwrite(&bmpihr, sizeof(BITMAPINFOHEADER), 1, fbmpwf);
// RGB データの書き込み、逆順にする
for (int y=0; y<bmpihr.biHeight; y++){
for (int x=0; x<bmpihr.biWidth; x++){
blue = sw_gabor[bmpihr.biWidth*bmpihr.biHeight*k+((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] & 0xff;
green = (sw_gabor[bmpihr.biWidth*bmpihr.biHeight*k+((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] >> 8) & 0xff;
red = (sw_gabor[bmpihr.biWidth*bmpihr.biHeight*k+((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x]>>16) & 0xff;
fputc(blue, fbmpwf);
fputc(green, fbmpwf);
fputc(red, fbmpwf);
}
}
fclose(fbmpwf);
}
free(rd_bmp);
free(hw_gabor);
return 0;
}
int Gabor_filter_lh_2_soft(hls::stream<ap_axis<32,1,1,1> >& ins, hls::stream<ap_axis<32,1,1,1> >& outs, ap_uint<2> & RorL){
ap_axis<32,1,1,1> pix;
ap_axis<32,1,1,1> gabor;
hls::LineBuffer<ARRAY_SIZE-1, HORIZONTAL_PIXEL_WIDTH, int> linebuf;
hls::Window<ARRAY_SIZE, ARRAY_SIZE, int> mbuf;
int gray_pix, val, i, j, x, y;
float valf;
do { // user が 1になった時にフレームがスタートする
ins >> pix;
} while(pix.user == 0);
for (int k=0; k<2; k++){
for (y=0; y<VERTICAL_PIXEL_WIDTH; y++){
for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
if (!(x==0 && y==0)) // 最初の入力はすでに入力されている
ins >> pix; // AXI4-Stream からの入力
mbuf.shift_left(); // mbuf の列を1ビット左シフト
for(i=ARRAY_SIZE-2; i>=0; --i){
mbuf.insert(linebuf(i,x), i+1, ARRAY_SIZE-1);
}
gray_pix = conv_rgb2y_soft(pix.data);
mbuf.insert(gray_pix, 0, ARRAY_SIZE-1);
// LineBuffer の更新
linebuf.shift_down(x);
linebuf.insert_bottom(gray_pix, x);
// 使用する配列を決定する
int ano;
switch (RorL){
case LEFT_WEIGHT :
ano = LEFT_WEIGHT;
break;
case RIGHT_WEIGHT :
ano = RIGHT_WEIGHT;
break;
case L_R_WEIGHT :
if (k == 0)
ano = LEFT_WEIGHT;
else
ano = RIGHT_WEIGHT;
break;
default :
ano = LEFT_WEIGHT;
break;
}
// Gabor filter の演算
for (j=0, valf=0; j<ARRAY_SIZE-1; j++){
for (i=0; i<ARRAY_SIZE-1; i++){
valf += gabor_fweight[ano][j][i] * (float)mbuf(ARRAY_SIZE-1-j,i);
}
}
val = (int)valf;
if (val<0)
//val = -val; // 絶対値
val = 0; // マイナスの値を0に丸める
else if (val>255)
val = 255;
// Gabor filter・データの書き込み
gabor.data = (val<<16)+(val<<8)+val;
// 最初のARRAY_SIZE-1行とその他の行の最初のARRAY_SIZE-1列は無効データなので0とする
if (x<(ARRAY_SIZE-1) || y<(ARRAY_SIZE-1))
gabor.data = 0;
if (x==0 && y==0) // 最初のデータでは、TUSERをアサートする
gabor.user = 1;
else
gabor.user = 0;
if (x == (HORIZONTAL_PIXEL_WIDTH-1)) // 行の最後で TLAST をアサートする
gabor.last = 1;
else
gabor.last = 0;
outs << gabor; // AXI4-Stream へ出力
}
}
}
return(0);
}
// 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 にした
int conv_rgb2y_soft(int rgb){
int r, g, b, y_f;
int y;
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で割る
return(y);
}
---◆◇構成内容◆◇-------------------------------------------------
【 リサイクル 】個人向け ( リサイクル料金が含まれます。回収時に費用は発生しません。 )
【 OS 】★\5,800(税別)★Windows 10 Pro 64ビット
【 オフィスソフト 】・・・ オフィスソフト無し ( KINGSOFT Office 60日間トライアル版付属キャンペーン中 )
【 ウイルス対策・セキュリティソフト 】マカフィー リブセーフ ( 60日体験版 )
【 パソコン下取りサービス 】・・・ 下取りサービスなし
【 J-Moss 】J-Mossマーク 非含有マーク(グリーンマーク・緑色)
【 CPU 】★\2,800(税別)★インテル(R) Core(TM) i5-6500 プロセッサー ( 4コア / 4スレッド / 3.20GHz / TB時最大3.60GHz / 6MBキャッシュ )
【 CPUファン 】標準CPUクーラー
【 CPUグリス 】標準CPUグリス
【 メモリ 】8GB メモリ [ 8GB×1 ( PC4-17000 / DDR4-2133 ) ]
【 SSD 】・・・ SSD無し
【 SSD/HDD 】1TB ( 7200rpm / 6Gbps 対応 )
【 外付けストレージ 】・・・ 外付けストレージなし
【 グラフィックス 】インテル(R) HD グラフィックス 530
【 光学ドライブ 】★\2,800(税別)★DVDスーパーマルチドライブ ( DVD±R DL 読み書き対応 )
【 カードリーダー 】・・・ カードリーダー無し
【 マザーボード 】インテル(R) H110 Expressチップセット ( Micro ATX / DDR4 / SATA 6Gbps 対応ポート×4 )
【 ケース 】■ ミニタワーケース ( フロントUSB 2.0×2 / 9cmリア排気ファン搭載 )
【 ケースFAN 】【リアファン】9cmケースファン標準付属
【 電源 】★\3,800(税別)★500W 電源 ( 80PLUS(R) GOLD ) ⇒ 優れた電力変換効率で無駄な発熱を低減!
【 地デジ対応TVチューナー 】・・・ 地デジTVチューナーなし
【 LAN 】[ オンボード ] 10/100/1000BASE-T GigaBit-Ethernet LAN
【 無線LAN 】・・・ 無線LAN無し
【 サウンド 】ハイデフィニション・オーディオ
【 キーボード 】・・・ キーボードなし
【 マウス 】・・・ マウスなし
【 マウスパッド 】・・・ マウスパッドなし
【 スピーカー 】・・・ スピーカーなし ( 音声出力にはスピーカーが別途必要です )
【 ヘッドフォン 】・・・ ヘッドフォンなし
【 WEBカメラ(オプション) 】・・・ 外付けWebカメラなし
【 オプションサービス 】・・・オプションサービス無し
---◆◇周辺機器◆◇---------------------------------------------
【 モニタ 】・・・ モニタなし
【 プリンタ 】・・・ プリンタなし
【 ブロードバンドルーター 】・・・ ブロードバンドルーターなし
【 LANケーブル 】・・・ LANケーブルなし
【 HUB 】・・・ HUBなし
---◆◇サービス◆◇---------------------------------------------
【 サポート 】[1年間 標準保証] 初期不良対応1ヵ月+センドバック修理保証
【 各種出張サービス 】・・・ 出張セットアップサービスなし
【 電話サポート 】[ 24時間365日電話サポート ] 困った時はいつでもお電話いただけます ※弊社指定日を除く
……………………………………………………………………………………
小計(税込): \81,000
送料(税込): \3,240
合計(税込): \84,240
// Gabor_filter_lh.h
// 2016/07/24
// 2016/07/25 : 右白線検出用のGabor Filterの重みを追加
// 2016/07/27 : 右白線検出用配列と左白線検出用配列を統合
//
#ifndef __Gabor_filter_lh_H__
#define __Gabor_filter_lh_H__
//#define HORIZONTAL_PIXEL_WIDTH 800
//#define VERTICAL_PIXEL_WIDTH 600
#define HORIZONTAL_PIXEL_WIDTH 640 // for Simulation
#define VERTICAL_PIXEL_WIDTH 480
//#define HORIZONTAL_PIXEL_WIDTH 64
//#define VERTICAL_PIXEL_WIDTH 48
#define ALL_PIXEL_VALUE (HORIZONTAL_PIXEL_WIDTH*VERTICAL_PIXEL_WIDTH)
#define ARRAY_SIZE 9
#define RIGHT_WEIGHT 1
#define LEFT_WEIGHT 0
const int gabor_weight[2][ARRAY_SIZE][ARRAY_SIZE] = { // 左白線検出用+右白線検出用
{
{0,-3,-10,-16,-7,7,10,5,1},
{-3,-15,-27,-11,32,50,29,5,-2},
{-11,-24,-5,73,135,95,16,-17,-10},
{-11,4,85,187,160,14,-72,-52,-14},
{4,51,135,137,-18,-159,-136,-45,-2},
{16,50,59,-39,-179,-185,-73,3,13},
{10,12,-25,-104,-131,-60,15,27,11},
{1,-7,-31,-48,-24,18,29,14,3},
{-1,-5,-9,-4,10,16,10,2,-1}
},
{
{1,5,7,1,-12,-17,-10,-3,0},
{1,11,33,45,21,-16,-27,-15,-4},
{-8,-5,35,107,131,69,-2,-21,-11},
{-17,-47,-51,40,169,187,93,13,-7},
{-8,-54,-134,-147,-18,123,130,58,11},
{9,-6,-82,-185,-187,-65,36,44,17},
{11,24,12,-55,-125,-112,-43,1,7},
{3,14,30,23,-13,-41,-33,-12,-1},
{0,2,9,17,14,1,-6,-5,-2}
}
};
const float gabor_fweight[2][ARRAY_SIZE][ARRAY_SIZE] = { // 左白線検出用+右白線検出用(float)
{
{0.001282,-0.009914,-0.04062,-0.060586,-0.027574,0.026072,0.038427,0.018191,0.003056},
{-0.012155,-0.057448,-0.104645,-0.042953,0.123263,0.197238,0.114451,0.020448,-0.007239},
{-0.042252,-0.093065,-0.018911,0.285374,0.525746,0.372687,0.060734,-0.064748,-0.040465},
{-0.042261,0.015673,0.332798,0.728763,0.625046,0.053591,-0.283076,-0.203293,-0.05608},
{0.017342,0.198305,0.52554,0.535526,-0.069756,-0.622839,-0.531089,-0.177366,-0.006367},
{0.060866,0.19708,0.231032,-0.154219,-0.699885,-0.721808,-0.286707,0.013004,0.049249},
{0.038379,0.04877,-0.098477,-0.404993,-0.510165,-0.233566,0.057894,0.104366,0.041887},
{0.0047,-0.0278,-0.121277,-0.187262,-0.093276,0.070512,0.113857,0.055799,0.009976},
{-0.003798,-0.01885,-0.035607,-0.01709,0.037692,0.064268,0.038606,0.007536,-0.002133}
},
{
{0.005562,0.018882,0.028293,0.004499,-0.044995,-0.064838,-0.039469,-0.009822,0.000815},
{0.002294,0.04108,0.127023,0.175094,0.083025,-0.063755,-0.106402,-0.057798,-0.01406},
{-0.031269,-0.021096,0.135641,0.417286,0.512467,0.269946,-0.008354,-0.082091,-0.041357},
{-0.066348,-0.184919,-0.197802,0.15614,0.65976,0.728616,0.361674,0.052074,-0.027152},
{-0.031146,-0.211178,-0.523777,-0.573856,-0.069756,0.480311,0.506451,0.225223,0.041031},
{0.035552,-0.023892,-0.320104,-0.723563,-0.728735,-0.253689,0.1391,0.170625,0.067723},
{0.04216,0.094939,0.047511,-0.216623,-0.488075,-0.437898,-0.168739,0.003336,0.027009},
{0.012112,0.056596,0.115239,0.090332,-0.05076,-0.158403,-0.127847,-0.046375,-0.004918},
{-0.00168,0.007437,0.036985,0.067021,0.053689,0.004977,-0.02365,-0.018248,-0.005928}
}
};
#endif
ERROR HW and SW results mismatch i = 556, j = 73, HW = 00171717, SW = 00141414
ERROR HW and SW results mismatch i = 418, j = 88, HW = 00171717, SW = 00141414
ERROR HW and SW results mismatch i = 418, j = 92, HW = 00131313, SW = 00101010
ERROR HW and SW results mismatch i = 404, j = 100, HW = 003e3e3e, SW = 003b3b3b
ERROR HW and SW results mismatch i = 425, j = 106, HW = 00121212, SW = 000f0f0f
左白線用Gabor Filterパラメータ sigma = 4, Lambda = 85, Psi = 94, Theta = 50
0.001282,-0.009914,-0.040620,-0.060586,-0.027574,0.026072,0.038427,0.018191,0.003056
-0.012155,-0.057448,-0.104645,-0.042953,0.123263,0.197238,0.114451,0.020448,-0.007239
-0.042252,-0.093065,-0.018911,0.285374,0.525746,0.372687,0.060734,-0.064748,-0.040465
-0.042261,0.015673,0.332798,0.728763,0.625046,0.053591,-0.283076,-0.203293,-0.056080
0.017342,0.198305,0.525540,0.535526,-0.069756,-0.622839,-0.531089,-0.177366,-0.006367
0.060866,0.197080,0.231032,-0.154219,-0.699885,-0.721808,-0.286707,0.013004,0.049249
0.038379,0.048770,-0.098477,-0.404993,-0.510165,-0.233566,0.057894,0.104366,0.041887
0.004700,-0.027800,-0.121277,-0.187262,-0.093276,0.070512,0.113857,0.055799,0.009976
-0.003798,-0.018850,-0.035607,-0.017090,0.037692,0.064268,0.038606,0.007536,-0.002133
右白線用Gabor Filterパラメータ sigma = 4, Lambda = 85, Psi = 94, Theta = 125
0.005562,0.018882,0.028293,0.004499,-0.044995,-0.064838,-0.039469,-0.009822,0.000815
0.002294,0.041080,0.127023,0.175094,0.083025,-0.063755,-0.106402,-0.057798,-0.014060
-0.031269,-0.021096,0.135641,0.417286,0.512467,0.269946,-0.008354,-0.082091,-0.041357
-0.066348,-0.184919,-0.197802,0.156140,0.659760,0.728616,0.361674,0.052074,-0.027152
-0.031146,-0.211178,-0.523777,-0.573856,-0.069756,0.480311,0.506451,0.225223,0.041031
0.035552,-0.023892,-0.320104,-0.723563,-0.728735,-0.253689,0.139100,0.170625,0.067723
0.042160,0.094939,0.047511,-0.216623,-0.488075,-0.437898,-0.168739,0.003336,0.027009
0.012112,0.056596,0.115239,0.090332,-0.050760,-0.158403,-0.127847,-0.046375,-0.004918
-0.001680,0.007437,0.036985,0.067021,0.053689,0.004977,-0.023650,-0.018248,-0.005928
/* * cam_disp_hls.c * * Created on: 2016/08/21 * Author: Masaaki */
#include <stdio.h>
#include <stdlib.h>
#include "xil_io.h"
#include "xdma_read_addr.h"
#include "xdma_write.h"
#include "sleep.h"
#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
#define FRAME_BUFFER_ADDRESS 0x10000000
void cam_i2c_init(volatile unsigned *mt9d111_i2c_axi_lites) {
mt9d111_i2c_axi_lites[64] = 0x2; // reset tx fifo ,address is 0x100, i2c_control_reg
mt9d111_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 *mt9d111_i2c_axi_lites, unsigned int device_addr, unsigned int write_addr, unsigned int write_data){
mt9d111_i2c_axi_lites[66] = 0x100 | (device_addr & 0xfe); // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
mt9d111_i2c_axi_lites[66] = write_addr;
mt9d111_i2c_axi_lites[66] = (write_data >> 8)|0xff; // first data
mt9d111_i2c_axi_lites[66] = 0x200 | (write_data & 0xff); // second data
cam_i2x_write_sync();
}
int main(){
XDma_read_addr dmar, *dmarp;
XDma_write dmaw, *dmawp;
dmarp = &dmar;
dmawp = &dmaw;
// Initialization of DMA Read
if (XDma_read_addr_Initialize(dmarp, 0) != XST_SUCCESS){
fprintf(stderr,"DMA Read open error\n");
exit(-1);
}
// Initialization of DMA Write
if (XDma_write_Initialize(dmawp, 0) != XST_SUCCESS){
fprintf(stderr,"DMA Write open error\n");
exit(-1);
}
// frame buffer settings
XDma_read_addr_Set_frame_buffer0(&dmar, FRAME_BUFFER_ADDRESS);
XDma_read_addr_Set_frame_buffer1(&dmar, FRAME_BUFFER_ADDRESS+HORIZONTAL_PIXELS*VERTICAL_LINES*PIXEL_NUM_OF_BYTES);
XDma_read_addr_Set_frame_buffer2(&dmar, FRAME_BUFFER_ADDRESS+2*HORIZONTAL_PIXELS*VERTICAL_LINES*PIXEL_NUM_OF_BYTES);
XDma_write_Set_frame_buffer0(&dmaw, FRAME_BUFFER_ADDRESS);
XDma_write_Set_frame_buffer1(&dmaw, FRAME_BUFFER_ADDRESS+HORIZONTAL_PIXELS*VERTICAL_LINES*PIXEL_NUM_OF_BYTES);
XDma_write_Set_frame_buffer2(&dmaw, FRAME_BUFFER_ADDRESS+2*HORIZONTAL_PIXELS*VERTICAL_LINES*PIXEL_NUM_OF_BYTES);
// mt9d111_inf_axis_0, axi_iic_0, bitmap_disp_cont_axis_0
volatile unsigned int *mt9d111_axiL;
volatile unsigned int *cam_iic_axiL;
volatile unsigned int *bmdc_axiL;
mt9d111_axiL = (volatile unsigned int *)XPAR_MT9D111_INF_AXIS_0_BASEADDR;
cam_iic_axiL = (volatile unsigned int *)XPAR_AXI_IIC_0_BASEADDR;
bmdc_axiL = (volatile unsigned int *)XPAR_BITMAP_DISP_CONT_AXIS_0_BASEADDR;
// DMA Start
XDma_read_addr_Set_mode_V(&dmar, 0);
while(!XDma_read_addr_IsIdle(&dmar)) ;
XDma_read_addr_Start(&dmar);
XDma_read_addr_EnableAutoRestart(&dmar);
while(!XDma_write_IsIdle(&dmaw)) ;
XDma_write_Start(&dmaw);
XDma_write_EnableAutoRestart(&dmaw);
// mt9d111_inf_axis_0 and bitmap_disp_cont_axis_0 is started
mt9d111_axiL[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Camera Interface start (Address is dummy)
bmdc_axiL[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Camera Interface start (Address is dummy)
// CMOS Camera initialize, MT9D111
cam_i2c_init(cam_iic_axiL);
cam_i2c_write(cam_iic_axiL, 0xba, 0xf0, 0x1); // Changed regster map to IFP page 1
cam_i2c_write(cam_iic_axiL, 0xba, 0x97, 0x20); // RGB Mode, RGB565
mt9d111_axiL[1] = 0; // One_shot_mode is disabled
return(0);
}
set_property IOSTANDARD LVCMOS33 [get_ports {vga_blue[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_blue[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_blue[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_blue[0]}]
set_property PACKAGE_PIN J18 [get_ports {vga_blue[3]}]
set_property PACKAGE_PIN K19 [get_ports {vga_blue[2]}]
set_property PACKAGE_PIN M20 [get_ports {vga_blue[1]}]
set_property PACKAGE_PIN P20 [get_ports {vga_blue[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_blue[4]}]
set_property PACKAGE_PIN G19 [get_ports {vga_blue[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_green[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_green[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_green[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_green[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_green[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_green[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_red[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_red[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_red[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_red[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_red[0]}]
set_property PACKAGE_PIN F20 [get_ports {vga_green[5]}]
set_property PACKAGE_PIN H20 [get_ports {vga_green[4]}]
set_property PACKAGE_PIN J19 [get_ports {vga_green[3]}]
set_property PACKAGE_PIN L19 [get_ports {vga_green[2]}]
set_property PACKAGE_PIN N20 [get_ports {vga_green[1]}]
set_property PACKAGE_PIN H18 [get_ports {vga_green[0]}]
set_property PACKAGE_PIN F19 [get_ports {vga_red[4]}]
set_property PACKAGE_PIN G20 [get_ports {vga_red[3]}]
set_property PACKAGE_PIN J20 [get_ports {vga_red[2]}]
set_property PACKAGE_PIN L20 [get_ports {vga_red[1]}]
set_property PACKAGE_PIN M19 [get_ports {vga_red[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports vga_hsync]
set_property IOSTANDARD LVCMOS33 [get_ports vga_vsync]
set_property PACKAGE_PIN P19 [get_ports vga_hsync]
set_property PACKAGE_PIN R19 [get_ports vga_vsync]
set_property PACKAGE_PIN T14 [get_ports {cam_data[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[0]}]
set_property PACKAGE_PIN U14 [get_ports {cam_data[6]}]
set_property PACKAGE_PIN T15 [get_ports {cam_data[5]}]
set_property PACKAGE_PIN U15 [get_ports {cam_data[4]}]
set_property PACKAGE_PIN P14 [get_ports {cam_data[3]}]
set_property PACKAGE_PIN V17 [get_ports {cam_data[2]}]
set_property PACKAGE_PIN R14 [get_ports {cam_data[1]}]
set_property PACKAGE_PIN V18 [get_ports {cam_data[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports mt9d111_iic_scl_io]
set_property IOSTANDARD LVCMOS33 [get_ports mt9d111_iic_sda_io]
set_property IOSTANDARD LVCMOS33 [get_ports href]
set_property IOSTANDARD LVCMOS33 [get_ports pclk]
set_property IOSTANDARD LVCMOS33 [get_ports standby]
set_property IOSTANDARD LVCMOS33 [get_ports vsync]
set_property IOSTANDARD LVCMOS33 [get_ports xck]
set_property PACKAGE_PIN V15 [get_ports mt9d111_iic_scl_io]
set_property PACKAGE_PIN W14 [get_ports mt9d111_iic_sda_io]
set_property PACKAGE_PIN W15 [get_ports vsync]
set_property PACKAGE_PIN Y14 [get_ports href]
set_property PACKAGE_PIN T11 [get_ports standby]
set_property PACKAGE_PIN T10 [get_ports pclk]
set_property PACKAGE_PIN U12 [get_ports xck]
set_property IOSTANDARD LVCMOS33 [get_ports {hdmi_out_en[0]}]
set_property PACKAGE_PIN F17 [get_ports {hdmi_out_en[0]}]
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets pclk_IBUF]
//
// cam_capture_bmp.cpp
// 2016/08/19 by marsee
//
// This software converts the left and right of the camera image to BMP file.
// -b : bmp file name
// -n : Start File Number
// -h : help
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>
#include "bmp_header.h"
#define PIXEL_NUM_OF_BYTES 4
#define SVGA_HORIZONTAL_PIXELS 800
#define SVGA_VERTICAL_LINES 600
#define SVGA_ALL_DISP_ADDRESS (SVGA_HORIZONTAL_PIXELS * SVGA_VERTICAL_LINES * PIXEL_NUM_OF_BYTES)
#define SVGA_3_PICTURES (SVGA_ALL_DISP_ADDRESS * NUMBER_OF_WRITE_FRAMES)
int WriteBMPfile(FILE *fbmp, volatile unsigned int *frame_buffer, BMP24FORMAT **bmp_data);
int main(int argc, char *argv[]){
int opt;
int c, help_flag=0;
char bmp_fn[256] = "bmp_file";
unsigned char attr[1024];
unsigned long phys_addr;
int i, j;
int file_no = 0;
FILE *fbmp;
BMP24FORMAT **bmp_data; // 24 bits Date of BMP files (SVGA_HORIZONTAL_PIXELS * SVGA_VERTICAL_LINES)
while ((opt=getopt(argc, argv, "b:n:h")) != -1){
switch (opt){
case 'b':
strcpy(bmp_fn, optarg);
break;
case 'n':
file_no = atoi(optarg);
break;
case 'h':
help_flag = 1;
break;
}
}
if (help_flag == 1){ // help
printf("Usage : cam_capture_bmp [-b <bmp file name>] [-n <Start File Number>] [-h]\n");
}
// udmabuf0
int fdf = open("/dev/udmabuf0", O_RDWR | O_SYNC); // frame_buffer, The cache is disabled.
if (fdf == -1){
fprintf(stderr, "/dev/udmabuf0 open error\n");
exit(-1);
}
volatile unsigned *frame_buffer = (volatile unsigned *)mmap(NULL, SVGA_ALL_DISP_ADDRESS, PROT_READ|PROT_WRITE, MAP_SHARED, fdf, 0);
if (!frame_buffer){
fprintf(stderr, "frame_buffer mmap error\n");
exit(-1);
}
// phys_addr of udmabuf0
int fdp = open("/sys/devices/virtual/udmabuf/udmabuf0/phys_addr", O_RDONLY);
if (fdp == -1){
fprintf(stderr, "/sys/devices/virtual/udmabuf/udmabuf0/phys_addr open error\n");
exit(-1);
}
read(fdp, attr, 1024);
sscanf((const char *)attr, "%lx", &phys_addr);
close(fdp);
printf("phys_addr = %x\n", (unsigned int)phys_addr);
// allocated the memory for bmp file
if ((bmp_data=(BMP24FORMAT **)malloc(sizeof(BMP24FORMAT *)*SVGA_VERTICAL_LINES)) == NULL){
fprintf(stderr, "Can not allocate memory of the first dimension of SVGA_VERTICAL_LINES of bmp_data\n");
exit(1);
}
for (i=0; i<SVGA_VERTICAL_LINES; i++){
if ((bmp_data[i]=(BMP24FORMAT *)malloc(sizeof(BMP24FORMAT) * SVGA_HORIZONTAL_PIXELS)) == NULL){
fprintf(stderr, "Can not allocate %d th memory of the first dimension of bmp_data\n", i);
exit(1);
}
}
char bmp_file[256];
// w - writed the left and right eye's bmp files. q - exit.
c = getc(stdin);
while(c != 'q'){
switch ((char)c) {
case 'w' : // w - writed the left and right eye's bmp files.
// writed the left and right eys's frame buffer
sprintf(bmp_file, "%s%d.bmp", bmp_fn, file_no);
if ((fbmp=fopen(bmp_file, "wb")) == NULL){
fprintf(stderr, "Cannot open %s in binary mode\n", bmp_file);
exit(1);
}
WriteBMPfile(fbmp, frame_buffer, bmp_data);
fclose(fbmp);
printf("file No. = %d\n", file_no);
file_no++;
break;
}
c = getc(stdin);
}
for(i=0; i<SVGA_VERTICAL_LINES; i++){
free(bmp_data[i]);
}
free(bmp_data);
munmap((void *)frame_buffer, (SVGA_ALL_DISP_ADDRESS));
close(fdf);
return(0);
}
int WriteBMPfile(FILE *fbmp, volatile unsigned *frame_buffer, BMP24FORMAT **bmp_data){
BITMAPFILEHEADER bmpfh; // file header for a bmp file
BITMAPINFOHEADER bmpih; // INFO header for BMP file
// Copy the camera color data of the bmp_data (data of BMP when its starts from lower left)
for (int i=0; i<SVGA_VERTICAL_LINES; i++){
for (int j=0; j<SVGA_HORIZONTAL_PIXELS; j++){
bmp_data[(SVGA_VERTICAL_LINES-1)-i][j].red = (frame_buffer[i*SVGA_HORIZONTAL_PIXELS+j]>>16)&0xff;
bmp_data[(SVGA_VERTICAL_LINES-1)-i][j].green = (frame_buffer[i*SVGA_HORIZONTAL_PIXELS+j]>>8)&0xff;
bmp_data[(SVGA_VERTICAL_LINES-1)-i][j].blue = (frame_buffer[i*SVGA_HORIZONTAL_PIXELS+j])&0xff;
}
}
// Assign a value to the file header of the BMP file
bmpfh.bfType = 0x4d42;
bmpfh.bfSize = SVGA_HORIZONTAL_PIXELS*SVGA_VERTICAL_LINES*3+54;
bmpfh.bfReserved1 = 0;
bmpfh.bfReserved2 = 0;
bmpfh.bfOffBits = 0x36;
// Assign a value to the INFO header of the BMP file
bmpih.biSize = 0x28;
bmpih.biWidth = SVGA_HORIZONTAL_PIXELS;
bmpih.biHeight = SVGA_VERTICAL_LINES;
bmpih.biPlanes = 0x1;
bmpih.biBitCount = 24;
bmpih.biCompression = 0;
bmpih.biSizeImage = 0;
bmpih.biXPixPerMeter = 3779;
bmpih.biYPixPerMeter = 3779;
bmpih.biClrUsed = 0;
bmpih.biClrImporant = 0;
// Writing of BMP file header
fwrite(&bmpfh.bfType, sizeof(char), 2, fbmp);
fwrite(&bmpfh.bfSize, sizeof(long), 1, fbmp);
fwrite(&bmpfh.bfReserved1, sizeof(short), 1, fbmp);
fwrite(&bmpfh.bfReserved2, sizeof(short), 1, fbmp);
fwrite(&bmpfh.bfOffBits, sizeof(long), 1, fbmp);
// Writing of BMP INFO header
fwrite(&bmpih, sizeof(BITMAPINFOHEADER), 1, fbmp);
// Writing of bmp_data
for (int i=0; i<SVGA_VERTICAL_LINES; i++) {
for (int j=0; j<SVGA_HORIZONTAL_PIXELS; j++) {
fputc((int)bmp_data[i][j].blue, fbmp);
fputc((int)bmp_data[i][j].green, fbmp);
fputc((int)bmp_data[i][j].red, fbmp);
}
}
}
// bitmap_disp_cont_axis.v
//
// by marsee
//
// Read Only IP, 64 bit bus
//
// 2012/06/28
// 2012/11/22 : HDMI出力を追加
// 2014/07/23 : ZYBO 用に変更
// 2014/09/18 : Frame Buffer のスタートアドレスを設定するためにAXI4 Lite Slave インターフェースを追加
// 2016/08/08 : AXI4 Master から AXI4-Stream インターフェースに変更、AXI4 Lite Slave インターフェースはダミーライトに変更
// ダミーライトするとディスプレイ・コントローラがスタートする
//
`default_nettype none
module bitmap_disp_cont_axis #
(
// AXI4 Lite Slave Interface
parameter integer C_S_AXI_LITE_ADDR_WIDTH = 9,
parameter integer C_S_AXI_LITE_DATA_WIDTH = 32,
// AXI4-Stream Interface
parameter integer C_M_AXIS_DATA_WIDTH = 32,
parameter [31:0] C_DISPLAY_START_ADDRESS = 32'h17800000, // フレームバッファのスタートアドレス
// video resolution : "VGA", "SVGA", "XGA", "SXGA", "HD"
parameter [80*8:1] RESOLUTION ="SVGA" // SVGA
)
(
// Clocks and Reset
input wire s_axi_lite_aclk,
input wire AXIS_ACLK,
input wire ARESETN,
///////////////////////////////
// AXI4 Lite Slave Interface //
///////////////////////////////
// AXI Lite Write Address Channel
input wire s_axi_lite_awvalid,
output wire s_axi_lite_awready,
input wire [C_S_AXI_LITE_ADDR_WIDTH-1:0] s_axi_lite_awaddr,
// AXI Lite Write Data Channel
input wire s_axi_lite_wvalid,
output wire s_axi_lite_wready,
input wire [C_S_AXI_LITE_DATA_WIDTH-1:0] s_axi_lite_wdata,
// AXI Lite Write Response Channel
output wire [1:0] s_axi_lite_bresp,
output wire s_axi_lite_bvalid,
input wire s_axi_lite_bready,
// AXI Lite Read Address Channel
input wire s_axi_lite_arvalid,
output wire s_axi_lite_arready,
input wire [C_S_AXI_LITE_ADDR_WIDTH-1:0] s_axi_lite_araddr,
// AXI Lite Read Data Channel
output wire s_axi_lite_rvalid,
input wire s_axi_lite_rready,
output wire [C_S_AXI_LITE_DATA_WIDTH-1:0] s_axi_lite_rdata,
output wire [1:0] s_axi_lite_rresp,
/////////////////////////////////
// AXI4-Stream Slave Interface //
/////////////////////////////////
input wire [C_M_AXIS_DATA_WIDTH-1:0] s_axis_tdata,
input wire [(C_M_AXIS_DATA_WIDTH/8)-1:0] s_axis_tstrb,
input wire s_axis_tvalid,
output wire s_axis_tready,
input wire s_axis_tlast,
input wire s_axis_tuser,
// User Ports
input wire pixclk,
(* IOB = "FORCE" *) output reg [4:0] vga_red,
(* IOB = "FORCE" *) output reg [5:0] vga_green,
(* IOB = "FORCE" *) output reg [4:0] vga_blue,
(* IOB = "FORCE" *) output reg vga_hsync,
(* IOB = "FORCE" *) output reg vga_vsync,
output wire [23:0] vid_pData,
output wire vid_pVDE,
output wire vid_pHSync,
output wire vid_pVSync
);
wire [7:0] red, green, blue;
wire hsyncx, vsyncx;
wire display_enable;
reg reset_disp_2b = 1'b1, reset_disp_1b = 1'b1;
wire reset_disp;
wire afifo_overflow, afifo_underflow;
wire reset_out;
wire init_done;
bm_disp_cntrler_axi_lite_slave #(
.C_S_AXI_LITE_ADDR_WIDTH(C_S_AXI_LITE_ADDR_WIDTH),
.C_S_AXI_LITE_DATA_WIDTH(C_S_AXI_LITE_DATA_WIDTH),
.C_DISPLAY_START_ADDRESS(C_DISPLAY_START_ADDRESS)
) bm_disp_cntrler_axi_lite_slave_i
(
.s_axi_lite_aclk(s_axi_lite_aclk),
.axi_resetn(ARESETN),
.s_axi_lite_awvalid(s_axi_lite_awvalid),
.s_axi_lite_awready(s_axi_lite_awready),
.s_axi_lite_awaddr(s_axi_lite_awaddr),
.s_axi_lite_wvalid(s_axi_lite_wvalid),
.s_axi_lite_wready(s_axi_lite_wready),
.s_axi_lite_wdata(s_axi_lite_wdata),
.s_axi_lite_bresp(s_axi_lite_bresp),
.s_axi_lite_bvalid(s_axi_lite_bvalid),
.s_axi_lite_bready(s_axi_lite_bready),
.s_axi_lite_arvalid(s_axi_lite_arvalid),
.s_axi_lite_arready(s_axi_lite_arready),
.s_axi_lite_araddr(s_axi_lite_araddr),
.s_axi_lite_rvalid(s_axi_lite_rvalid),
.s_axi_lite_rready(s_axi_lite_rready),
.s_axi_lite_rdata(s_axi_lite_rdata),
.s_axi_lite_rresp(s_axi_lite_rresp),
.fb_start_address(),
.init_done(init_done)
);
bitmap_disp_engine #(
.RESOLUTION(RESOLUTION)
) bitmap_disp_eng_inst (
.clk_disp(pixclk),
.clk_axi(AXIS_ACLK),
.reset_disp(reset_disp),
.reset_axi(~ARESETN),
.s_axis_tdata(s_axis_tdata),
.s_axis_tstrb(s_axis_tstrb),
.s_axis_tvalid(s_axis_tvalid),
.s_axis_tready(s_axis_tready),
.s_axis_tlast(s_axis_tlast),
.s_axis_tuser(s_axis_tuser),
.red_out(red),
.green_out(green),
.blue_out(blue),
.hsyncx(hsyncx),
.vsyncx(vsyncx),
.display_enable(display_enable),
.ddr_cont_init_done(init_done),
.afifo_overflow(afifo_overflow),
.afifo_underflow(afifo_underflow)
);
always @(posedge pixclk) begin
if (reset_disp) begin
vga_red <= 5'd0;
vga_green <= 6'd0;
vga_blue <= 5'd0;
vga_hsync <= 1'b1;
vga_vsync <= 1'b1;
end else begin
vga_red <= red[7:3];
vga_green <= green[7:2];
vga_blue <= blue[7:3];
vga_hsync <= hsyncx;
vga_vsync <= vsyncx;
end
end
always @(posedge pixclk) begin
reset_disp_2b <= ~ARESETN;
reset_disp_1b <= reset_disp_2b;
end
assign reset_disp = reset_disp_1b;
assign vid_pData = {red, blue, green};
assign vid_pVDE = display_enable;
assign vid_pHSync = hsyncx;
assign vid_pVSync = vsyncx;
endmodule
`default_nettype wire
// BitMap Display Controller
// bitmap_disp_engine.v
// AXI4バス用 by marsee
//
// 2014/07/26 : video_timing_param.vh を使用
// 2014/09/18 : フレームバッファのスタートアドレス入力を追加
// 2016/03/04 : display_enable の出力期間のバグをフィックスした
// 2016/08/08 : AXI4 Master から AXI4-Stream インターフェースに変更
//
`default_nettype none
// synthesis translate_off
// `include "std_ovl_defines.h"
// synthesis translate_on
module bitmap_disp_engine #(
// AXI4-Stream Interface
parameter integer C_M_AXIS_DATA_WIDTH = 32,
// video resolution : "VGA", "SVGA", "XGA", "SXGA", "HD"
parameter [80*8:1] RESOLUTION ="SVGA" // SVGA
) (
input wire clk_disp, // ディスプレイ表示用クロック
input wire clk_axi, // AXI4バスクロック
input wire reset_disp, // clk_disp 用リセット
input wire reset_axi, // clk_axi 用リセット
input wire [C_M_AXIS_DATA_WIDTH-1:0] s_axis_tdata,
input wire [(C_M_AXIS_DATA_WIDTH/8)-1:0] s_axis_tstrb,
input wire s_axis_tvalid,
output wire s_axis_tready,
input wire s_axis_tlast,
input wire s_axis_tuser,
output reg [7:0] red_out,
output reg [7:0] green_out,
output reg [7:0] blue_out,
(*S="TRUE"*) output reg hsyncx,
(*S="TRUE"*) output reg vsyncx,
output wire display_enable,
input wire ddr_cont_init_done, // DDR2 SDRAMコントローラの初期化終了
output wire afifo_overflow, // 非同期FIFO のオーバーフロー・エラー
output wire afifo_underflow // 非同期FIFO のアンダーフロー・エラー
);
`include "./video_timing_param.vh"
parameter [2:0] idle_rdg= 3'b001,
wait_half_full= 3'b010,
display_mode= 3'b100;
reg [2:0] cs_rdg;
reg afifo_rd_en;
wire afifo_wr_en;
wire [31:0] afifo_dout;
wire afifo_full;
wire afifo_empty;
wire [9:0] wr_data_count;
reg [15:0] h_count;
reg [15:0] v_count;
reg [7:0] red_node, green_node, blue_node;
reg hsyncx_node, vsyncx_node;
reg vsync_axi, vsync_axi_b1;
reg vsync_axi_1d;
reg vsyncx_rise_pulse;
reg de, de_b1, de_b2;
wire disp_mode_ena;
reg disp_mode_ena_d0, disp_mode_ena_d1;
reg init_done_d0 = 1'b0;
reg init_done_d1 = 1'b0;
// synthesis translate_off
// wire [`OVL_FIRE_WIDTH-1:0] fire_overflow, fire_underflow;
// synthesis translate_on
// RGB保存用非同期FIFO, FWFT Wirte側64ビット幅512深度、Read側32ビット512深度とする
bitmap_afifo bitmap_afifo_inst (
.wr_rst(reset_axi),
.wr_clk(clk_axi),
.rd_clk(clk_disp),
.rd_rst(reset_disp),
//.din(data_in), // Bus [63 : 0]
.din(s_axis_tdata), // Bus [31 : 0]
.wr_en(afifo_wr_en),
.rd_en(afifo_rd_en),
.dout(afifo_dout), // Bus [31 : 0]
.full(afifo_full),
.overflow(afifo_overflow),
.empty(afifo_empty),
.underflow(afifo_underflow),
.wr_data_count(wr_data_count) // [9 : 0] wr_data_count
);
assign afifo_wr_en = s_axis_tvalid & ~afifo_full;
// afifo_wr_en が 1 になるときは、tuserが1の時か、cs_rdgがidle_rdgでなく、tvalidが1で、FIFOがFULLでない時
assign s_axis_tready = ~afifo_full;
// ddr_cont_init_done を clk_axi で同期化する
always @(posedge clk_axi) begin
init_done_d0 <= ddr_cont_init_done;
init_done_d1 <= init_done_d0;
end
// Readデータ処理モジュール用ステートマシン
always @(posedge clk_axi) begin
if (reset_axi | ~init_done_d1)
cs_rdg <= idle_rdg;
else begin
case (cs_rdg)
idle_rdg :
if (s_axis_tuser & afifo_wr_en)
cs_rdg <= wait_half_full;
wait_half_full : // 最初にFIFO が half_full になるのを待ってスタートする
if (wr_data_count[8])
cs_rdg <= display_mode;
display_mode : // 画面表示モード
;
endcase
end
end
assign disp_mode_ena = (cs_rdg==display_mode) ? 1'b1 : 1'b0;
// ビットマップVGAコントローラのclk_disp 動作部
// h_count、v_count用にclk_axi 動作のcs_rdg の値を使用するので2回clk_disp 動作のFFでラッチする
always @(posedge clk_disp) begin
if (reset_disp) begin
disp_mode_ena_d0 <= 0;
end else begin
disp_mode_ena_d0 <= disp_mode_ena;
disp_mode_ena_d1 <= disp_mode_ena_d0;
end
end
// h_countの実装(水平カウンタ)
always @(posedge clk_disp) begin
if (reset_disp==1'b1 || disp_mode_ena_d1==1'b0)
h_count <= 0;
else if (h_count>=(H_SUM-1)) // h_count がH_SUM-1よりも大きければ0に戻す(mod H_SUM)
h_count <= 0;
else
h_count <= h_count + 1;
end
// v_countの実装(垂直カウンタ)
always @(posedge clk_disp) begin
if (reset_disp==1'b1 || disp_mode_ena_d1==1'b0)
v_count <= 0;
else if (h_count>=(H_SUM-1)) begin // 水平カウンタがクリアされるとき
if (v_count>=(V_SUM-1)) // v_count がV_SUM-1よりも大きければ0に戻す(mode V_SUM)
v_count <= 0;
else
v_count <= v_count + 1;
end
end
// Red, Green, Blue出力
always @(posedge clk_disp) begin
if (reset_disp) begin
red_node <= 0;
green_node <= 0;
blue_node <= 0;
end else begin
if (disp_mode_ena_d1==1'b0) begin // 最初にpixel_async_fifo がフルになるまで画像データを出力しない。
red_node <= 0;
green_node <= 0;
blue_node <= 0;
end else if (h_count<=H_ACTIVE_VIDEO && v_count<V_ACTIVE_VIDEO) begin
red_node <= afifo_dout[23:16];
green_node <= afifo_dout[15:8];
blue_node <= afifo_dout[7:0];
end else begin
red_node <= 0;
green_node <= 0;
blue_node <= 0;
end
end
end
always @(posedge clk_disp) begin
if (reset_disp) begin
red_out <= 0;
green_out <= 0;
blue_out <= 0;
end else begin
red_out <= red_node;
green_out <= green_node;
blue_out <= blue_node;
end
end
// hsyncx 出力(水平同期信号)
always @(posedge clk_disp) begin
if (reset_disp | ~disp_mode_ena_d1)
hsyncx_node <= 1'b1;
else
if (h_count>(H_ACTIVE_VIDEO + H_FRONT_PORCH-1) && h_count<=(H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE-1)) // 水平同期期間
hsyncx_node <= 1'b0;
else
hsyncx_node <= 1'b1;
end
always @(posedge clk_disp) begin
if (reset_disp)
hsyncx <= 1'b1;
else
hsyncx <= hsyncx_node;
end
// vsyncx 出力(水平同期信号)
always @(posedge clk_disp) begin
if (reset_disp | ~disp_mode_ena_d1)
vsyncx_node <= 1'b1;
else
if (v_count>(V_ACTIVE_VIDEO + V_FRONT_PORCH-1) && v_count<=(V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE-1)) // 垂直同期期間
vsyncx_node <= 1'b0;
else
vsyncx_node <= 1'b1;
end
always @(posedge clk_disp) begin
if (reset_disp)
vsyncx <= 1'b1;
else
vsyncx <= vsyncx_node;
end
// vsync をclk_axi で同期化
always @(posedge clk_axi) begin
if (reset_axi) begin
vsync_axi <= 1'b0;
vsync_axi_b1 <= 1'b0;
vsync_axi_1d <= 1'b0;
end else begin
vsync_axi_b1 <= ~vsyncx_node;
vsync_axi <= vsync_axi_b1;
vsync_axi_1d <= vsync_axi;
end
end
// vsyncx_rise_pulse の処理。vsyncx の立ち上がり時に1パルス出力する
always @(posedge clk_axi) begin
if (reset_axi)
vsyncx_rise_pulse <= 1'b0;
else begin
if (vsync_axi==1'b0 && vsync_axi_1d==1'b1)
vsyncx_rise_pulse <= 1'b1;
else
vsyncx_rise_pulse <= 1'b0;
end
end
// display_enable 出力
always @(posedge clk_disp) begin
if (reset_disp | ~disp_mode_ena_d1)
de <= 1'b0;
else begin
if (h_count<H_ACTIVE_VIDEO && v_count<V_ACTIVE_VIDEO)
de <= 1'b1;
else
de <= 1'b0;
end
end
always @(posedge clk_disp) begin
if(reset_disp | ~disp_mode_ena_d1) begin
de_b1 <= 1'b0;
de_b2 <= 1'b0;
end else begin
de_b1 <= de;
de_b2 <= de_b1;
end
end
assign display_enable = de_b2;
// afifo_rd_en の処理
always @(posedge clk_disp) begin
if (reset_disp)
afifo_rd_en <= 1'b0;
else begin
if (~disp_mode_ena_d1) // 初期化中
afifo_rd_en <= 1'b0;
else if (h_count<H_ACTIVE_VIDEO && v_count<V_ACTIVE_VIDEO) // 表示期間
afifo_rd_en <= 1'b1;
else
afifo_rd_en <= 1'b0;
end
end
endmodule
`default_nettype wire
// bm_disp_cntrler_axi_lite_slave.v
// bitmap_disp_cntrler_axi_master のAXI Lite Slave モジュール。Frame Buffer のスタートアドレス・レジスタを持つ。
//
// Addr 0x0 - frame buffer start address
//
`default_nettype none
module bm_disp_cntrler_axi_lite_slave # (
parameter integer C_S_AXI_LITE_ADDR_WIDTH = 9, // Address width of the AXI Lite Interface
parameter integer C_S_AXI_LITE_DATA_WIDTH = 32, // Data width of the AXI Lite Interface
parameter [31:0] C_DISPLAY_START_ADDRESS = 32'h1A00_0000
)(
input wire s_axi_lite_aclk,
input wire axi_resetn,
// AXI Lite Write Address Channel
input wire s_axi_lite_awvalid,
output wire s_axi_lite_awready,
input wire [C_S_AXI_LITE_ADDR_WIDTH-1: 0] s_axi_lite_awaddr,
// AXI Lite Write Data Channel
input wire s_axi_lite_wvalid,
output wire s_axi_lite_wready,
input wire [C_S_AXI_LITE_DATA_WIDTH-1: 0] s_axi_lite_wdata,
// AXI Lite Write Response Channel
output wire [1:0] s_axi_lite_bresp,
output wire s_axi_lite_bvalid,
input wire s_axi_lite_bready,
// AXI Lite Read Address Channel
input wire s_axi_lite_arvalid,
output wire s_axi_lite_arready,
input wire [C_S_AXI_LITE_ADDR_WIDTH-1: 0] s_axi_lite_araddr,
// AXI Lite Read Data Channel
output wire s_axi_lite_rvalid,
input wire s_axi_lite_rready,
output wire [C_S_AXI_LITE_DATA_WIDTH-1: 0] s_axi_lite_rdata,
output wire [1:0] s_axi_lite_rresp,
output wire [31:0] fb_start_address, // Frame Buffer のスタートアドレス
output reg init_done // PS部の初期化終了
);
// RESP の値の定義
parameter RESP_OKAY = 2'b00;
parameter RESP_EXOKAY = 2'b01;
parameter RESP_SLVERR = 2'b10;
parameter RESP_DECERR = 2'b11;
parameter IDLE_WR = 2'b00, // for wrt_cs
DATA_WRITE_HOLD = 2'b01,
BREADY_ASSERT = 2'b11;
parameter IDLE_RD = 1'b0, // for rdt_cs
AR_DATA_WAIT = 1'b1;
reg [1:0] wrt_cs = IDLE_WR;
reg [31:0] fb_start_addr_reg = C_DISPLAY_START_ADDRESS;
reg rdt_cs = IDLE_RD;
reg reset_1d = 1'b0;
reg reset = 1'b0;
reg awready = 1'b1;
reg bvalid = 1'b0;
reg arready = 1'b1;
reg rvalid = 1'b0;
wire aclk;
assign aclk = s_axi_lite_aclk;
// Synchronization of axi_resetn
always @(posedge aclk) begin
reset_1d <= ~axi_resetn;
reset <= reset_1d;
end
// AXI4 Lite Slave Write Transaction State Machine
always @(posedge aclk) begin
if (reset) begin
wrt_cs <= IDLE_WR;
awready <= 1'b1;
bvalid <= 1'b0;
end else begin
case (wrt_cs)
IDLE_WR :
if (s_axi_lite_awvalid & ~s_axi_lite_wvalid) begin // Write Transaction Start
wrt_cs <= DATA_WRITE_HOLD;
awready <= 1'b0;
end else if (s_axi_lite_awvalid & s_axi_lite_wvalid) begin // Write Transaction Start with data
wrt_cs <= BREADY_ASSERT;
awready <= 1'b0;
bvalid <= 1'b1;
end
DATA_WRITE_HOLD :
if (s_axi_lite_wvalid) begin // Write data just valid
wrt_cs <= BREADY_ASSERT;
bvalid <= 1'b1;
end
BREADY_ASSERT :
if (s_axi_lite_bready) begin // The write transaction was terminated.
wrt_cs <= IDLE_WR;
bvalid <= 1'b0;
awready <= 1'b1;
end
endcase
end
end
assign s_axi_lite_awready = awready;
assign s_axi_lite_bvalid = bvalid;
assign s_axi_lite_wready = 1'b1;
assign s_axi_lite_bresp = RESP_OKAY;
// AXI4 Lite Slave Read Transaction State Machine
always @(posedge aclk) begin
if (reset) begin
rdt_cs <= IDLE_RD;
arready <= 1'b1;
rvalid <= 1'b0;
end else begin
case (rdt_cs)
IDLE_RD :
if (s_axi_lite_arvalid) begin
rdt_cs <= AR_DATA_WAIT;
arready <= 1'b0;
rvalid <= 1'b1;
end
AR_DATA_WAIT :
if (s_axi_lite_rready) begin
rdt_cs <= IDLE_RD;
arready <= 1'b1;
rvalid <= 1'b0;
end
endcase
end
end
assign s_axi_lite_arready = arready;
assign s_axi_lite_rvalid = rvalid;
assign s_axi_lite_rresp = RESP_OKAY;
// fb_start_addr_reg
always @(posedge aclk) begin
if (reset)
fb_start_addr_reg <= C_DISPLAY_START_ADDRESS;
else
if (s_axi_lite_wvalid)
fb_start_addr_reg <= s_axi_lite_wdata;
end
assign fb_start_address = fb_start_addr_reg;
assign s_axi_lite_rdata = fb_start_addr_reg;
// generated init_done
always @(posedge aclk) begin
if(reset) begin
init_done <= 1'b0;
end else if(wrt_cs==BREADY_ASSERT) begin
init_done <= 1'b1;
end
end
endmodule
`default_nettype wire
`default_nettype none
`timescale 100ps / 1ps
// bitmap_disp_cont_axis_tb.v
// 2012/07/03
// 2014/09/19 : for ZYBO
// 2016/08/14 : for AXI4-Stream
module bitmap_disp_cntrler_axi_master_tb;
parameter integer C_S_AXI_LITE_ADDR_WIDTH = 9; // Address width of the AXI Lite Interface
parameter integer C_S_AXI_LITE_DATA_WIDTH = 32; // Data width of the AXI Lite Interface
parameter integer C_M_AXIS_DATA_WIDTH= 32; // AXI4-Stream Interface
parameter DELAY = 1;
wire ACLK;
wire ARESETN;
wire [C_M_AXIS_DATA_WIDTH-1:0] s_axis_tdata;
wire [(C_M_AXIS_DATA_WIDTH/8)-1:0] s_axis_tstrb;
wire s_axis_tvalid;
wire s_axis_tready;
wire s_axis_tlast;
wire s_axis_tuser;
reg ap_start;
wire ap_done;
wire ap_idle;
wire ap_ready;
wire pixclk;
wire [4:0] vga_red;
wire [5:0] vga_green;
wire [4:0] vga_blue;
wire vga_hsync;
wire vga_vsync;
wire [23:0] vid_pData;
wire vid_pVDE;
wire vid_pHSync;
wire vid_pVSync;
reg [7:0] red;
reg [7:0] blue;
reg [7:0] green;
wire [32:0] rbg_data;
// AXI Lite Write Address Channel
reg s_axi_lite_awvalid = 1'b0;
wire s_axi_lite_awready;
reg [C_S_AXI_LITE_ADDR_WIDTH-1: 0] s_axi_lite_awaddr = 0;
//reg [3-1:0] s_axi_lite_awport = 1'b0;
// AXI Lite Write Data Channel
reg s_axi_lite_wvalid =1'b0;
wire s_axi_lite_wready;
reg [C_S_AXI_LITE_DATA_WIDTH-1: 0] s_axi_lite_wdata = 0;
// AXI Lite Write Response Channel
wire [1:0] s_axi_lite_bresp;
wire s_axi_lite_bvalid;
reg s_axi_lite_bready = 1'b0;
// AXI Lite Read Address Channel
reg s_axi_lite_arvalid = 1'b0;
wire s_axi_lite_arready;
reg [C_S_AXI_LITE_ADDR_WIDTH-1: 0] s_axi_lite_araddr = 1'b0;
//reg [3-1:0] s_axi_lite_arport = 0;
// AXI Lite Read Data Channel
wire s_axi_lite_rvalid;
reg s_axi_lite_rready = 1'b0;
wire [C_S_AXI_LITE_DATA_WIDTH-1: 0] s_axi_lite_rdata;
wire [1:0] s_axi_lite_rresp;
integer i;
// Instantiate the Unit Under Test (uut_bdc_axis)
bitmap_disp_cont_axis #(
.C_S_AXI_LITE_ADDR_WIDTH(C_S_AXI_LITE_ADDR_WIDTH),
.C_S_AXI_LITE_DATA_WIDTH(C_S_AXI_LITE_DATA_WIDTH),
.C_M_AXIS_DATA_WIDTH(C_M_AXIS_DATA_WIDTH),
.RESOLUTION("SVGA")
) uut_bdc_axis (
.s_axi_lite_aclk(ACLK),
.AXIS_ACLK(ACLK),
.ARESETN(ARESETN),
.s_axi_lite_awvalid(s_axi_lite_awvalid),
.s_axi_lite_awready(s_axi_lite_awready),
.s_axi_lite_awaddr(s_axi_lite_awaddr),
.s_axi_lite_wvalid(s_axi_lite_wvalid),
.s_axi_lite_wready(s_axi_lite_wready),
.s_axi_lite_wdata(s_axi_lite_wdata),
.s_axi_lite_bresp(s_axi_lite_bresp),
.s_axi_lite_bvalid(s_axi_lite_bvalid),
.s_axi_lite_bready(s_axi_lite_bready),
.s_axi_lite_arvalid(s_axi_lite_arvalid),
.s_axi_lite_arready(s_axi_lite_arready),
.s_axi_lite_araddr(s_axi_lite_araddr),
.s_axi_lite_rvalid(s_axi_lite_rvalid),
.s_axi_lite_rready(s_axi_lite_rready),
.s_axi_lite_rdata(s_axi_lite_rdata),
.s_axi_lite_rresp(s_axi_lite_rresp),
.s_axis_tdata(s_axis_tdata),
.s_axis_tstrb(s_axis_tstrb),
.s_axis_tvalid(s_axis_tvalid),
.s_axis_tready(s_axis_tready),
.s_axis_tlast(s_axis_tlast),
.s_axis_tuser(s_axis_tuser),
.pixclk(pixclk),
.vga_red(vga_red),
.vga_green(vga_green),
.vga_blue(vga_blue),
.vga_hsync(vga_hsync),
.vga_vsync(vga_vsync),
.vid_pData(vid_pData),
.vid_pVDE(vid_pVDE),
.vid_pHSync(vid_pHSync),
.vid_pVSync(vid_pVSync)
);
//defparam uut_master.bitmap_disp_eng_inst.INIT_COUNT_VAL = 20; // 初期化時のWaitタイマー
// clk_gen のインスタンス(ACLK)
clk_gen #(
.CLK_PERIOD(100), // 10nsec, 100MHz
.CLK_DUTY_CYCLE(0.5),
.CLK_OFFSET(0),
.START_STATE(1'b0)
) ACLKi (
.clk_out(ACLK)
);
// clk_gen のインスタンス(pixclk)
clk_gen #(
//.CLK_PERIOD(154), // 15.4 nsec, 64.9 MHz
.CLK_PERIOD(250), // 25 nsec, 40 MHz
.CLK_DUTY_CYCLE(0.5),
.CLK_OFFSET(0),
.START_STATE(1'b0)
) pixclk_i (
.clk_out(pixclk)
);
// reset_gen のインスタンス
reset_gen #(
.RESET_STATE(1'b0),
.RESET_TIME(1000) // 100nsec
) RESET_ARESETN (
.reset_out(ARESETN),
.init_done()
);
// Instantiate the AXI4-Stream Master Model (uut_axi4sm)
axi4_stream_master uut_axi4sm (
.ap_clk(ACLK),
.ap_rst_n(ARESETN),
.ap_start(ap_start),
.ap_done(ap_done),
.ap_idle(ap_idle),
.ap_ready(ap_ready),
.outs_TDATA(s_axis_tdata),
.outs_TVALID(s_axis_tvalid),
.outs_TREADY(s_axis_tready),
.outs_TKEEP(),
.outs_TSTRB(s_axis_tstrb),
.outs_TUSER(s_axis_tuser),
.outs_TLAST(s_axis_tlast),
.outs_TID(),
.outs_TDEST()
);
initial begin
// Initialize Inputs
ap_start = 1'b0;
s_axi_lite_awaddr = 0;
//s_axi_lite_awport = 0;
s_axi_lite_wvalid = 0;
s_axi_lite_wdata = 0;
s_axi_lite_wvalid = 0;
s_axi_lite_bready = 0;
s_axi_lite_araddr = 0;
//s_axi_lite_arport = 0;
s_axi_lite_arvalid = 0;
s_axi_lite_rready = 0;
// Wait Reset rising edge
@(posedge ARESETN);
#10000; // 1us wait
for (i=0; i<10; i=i+1) begin
@(posedge ACLK); // 次のクロックへ
#DELAY;
end
// Add stimulus here
@(posedge ACLK); // 次のクロックへ
#DELAY;
AXI_MASTER_WADC1(32'h0000_0100, 32'h55AA_55AA);
@(posedge ACLK); // 次のクロックへ
#DELAY;
AXI_MASTER_RADC1(32'h0000_0100);
#DELAY;
ap_start = 1'b1;
@(posedge ACLK); // 次のクロックへ
#DELAY;
AXI_MASTER_WADC2(32'h0000_0100, 32'h17800000);
@(posedge ACLK); // 次のクロックへ
#DELAY;
AXI_MASTER_RADC2(32'h0000_0600);
end
// Write Transcation 1
task AXI_MASTER_WADC1;
input [C_S_AXI_LITE_ADDR_WIDTH-1:0] awaddr;
input [C_S_AXI_LITE_DATA_WIDTH-1:0] wdata;
begin
s_axi_lite_awaddr = awaddr;
s_axi_lite_awvalid = 1'b1;
@(posedge ACLK); // 次のクロックへ
#DELAY;
s_axi_lite_awvalid = 1'b0;
s_axi_lite_wdata = wdata;
s_axi_lite_wvalid = 1'b1;
@(posedge ACLK); // 次のクロックへ, s_axi_lite_wready は常に 1
#DELAY;
s_axi_lite_wvalid = 1'b0;
s_axi_lite_bready = 1'b1;
@(posedge ACLK); // 次のクロックへ
#DELAY;
s_axi_lite_bready = 1'b0;
end
endtask
// Write Transcation 2
task AXI_MASTER_WADC2;
input [C_S_AXI_LITE_ADDR_WIDTH-1:0] awaddr;
input [C_S_AXI_LITE_DATA_WIDTH-1:0] wdata;
begin
s_axi_lite_awaddr = awaddr;
s_axi_lite_awvalid = 1'b1;
@(posedge ACLK); // 次のクロックへ
#DELAY;
s_axi_lite_awvalid = 1'b0;
s_axi_lite_wdata = wdata;
s_axi_lite_wvalid = 1'b1;
@(posedge ACLK); // 次のクロックへ, s_axi_lite_wready は常に 1
#DELAY;
s_axi_lite_wvalid = 1'b0;
@(posedge ACLK); // 次のクロックへ
#DELAY;
s_axi_lite_bready = 1'b1;
@(posedge ACLK); // 次のクロックへ
#DELAY;
s_axi_lite_bready = 1'b0;
end
endtask
// Read Transcation 1
task AXI_MASTER_RADC1;
input [31:0] araddr;
begin
s_axi_lite_araddr = araddr;
s_axi_lite_arvalid = 1'b1;
@(posedge ACLK); // 次のクロックへ
#DELAY;
s_axi_lite_araddr = 0;
s_axi_lite_arvalid = 1'b0;
s_axi_lite_rready = 1'b1;
@(posedge ACLK); // 次のクロックへ
#DELAY;
s_axi_lite_rready = 1'b0;
end
endtask
// Read Transcation 2
task AXI_MASTER_RADC2;
input [31:0] araddr;
begin
s_axi_lite_araddr = araddr;
s_axi_lite_arvalid = 1'b1;
@(posedge ACLK); // 次のクロックへ
#DELAY;
s_axi_lite_araddr = 0;
s_axi_lite_arvalid = 1'b0;
@(posedge ACLK); // 次のクロックへ
#DELAY;
s_axi_lite_rready = 1'b1;
@(posedge ACLK); // 次のクロックへ
#DELAY;
s_axi_lite_rready = 1'b0;
end
endtask
// assertion
always @(posedge pixclk or negedge ARESETN) begin
if (~ARESETN) begin
red <= 8'd0;
end else if (vid_pVDE) begin
red <= red + 8'd1;
end
end
always @(posedge pixclk or negedge ARESETN) begin
if (~ARESETN) begin
green <= 8'd0;
end else if (vid_pVDE) begin
green <= green + 8'd2;
end
end
always @(posedge pixclk or negedge ARESETN) begin
if (~ARESETN) begin
blue <= 8'd0;
end else if (vid_pVDE) begin
blue <= blue + 8'd3;
end
end
assign rbg_data = {8'd0, red, blue, green};
always @(posedge pixclk or negedge ARESETN) begin
if (~ARESETN) begin
;
end else if (vid_pVDE==1'b1 && {8'd0, vid_pData} != rbg_data) begin
$display("%t Data Error : rbg_data = %h, vid_pData = %h", $realtime, rbg_data, vid_pData);
end
end
endmodule
module clk_gen #(
parameter CLK_PERIOD = 100,
parameter real CLK_DUTY_CYCLE = 0.5,
parameter CLK_OFFSET = 0,
parameter START_STATE = 1'b0 )
(
output reg clk_out
);
begin
initial begin
#CLK_OFFSET;
forever
begin
clk_out = START_STATE;
#(CLK_PERIOD-(CLK_PERIOD*CLK_DUTY_CYCLE)) clk_out = ~START_STATE;
#(CLK_PERIOD*CLK_DUTY_CYCLE);
end
end
end
endmodule
module reset_gen #(
parameter RESET_STATE = 1'b1,
parameter RESET_TIME = 100 )
(
output reg reset_out,
output reg init_done
);
begin
initial begin
reset_out = RESET_STATE;
init_done = 1'b0;
#RESET_TIME;
reset_out = ~RESET_STATE;
init_done = 1'b1;
end
end
endmodule
`default_nettype wire
// axi4_stream_master.h
// 2016/08/15 by marsee
//
#ifndef __AXI4_STREAM_MASTER_H__
#define __AXI4_STREAM_MASTER_H__
#define HORIZONTAL_PIXELS 800
#define VERTICAL_LINES 600
#endif
// axi4_stream_master.cpp
// 2016/08/15 by marsee
//
// AXI4-Stream Master Model
//
#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>
#include "axi4_stream_master.h"
void axi4_stream_master(hls::stream<ap_axis<32,1,1,1> >& outs){
#pragma HLS INTERFACE axis port=outs
#pragma HLS INTERFACE ap_ctrl_hs port=return
ap_uint<8> red = 0;
ap_uint<8> blue = 0;
ap_uint<8> green = 0;
ap_axis<32,1,1,1> pix;
for (int y=0; y<VERTICAL_LINES; y++){
for (int x=0; x<HORIZONTAL_PIXELS; x++){
#pragma HLS PIPELINE II=1
pix.data = red*65536 + green*256 + blue;
red++;
green += 2;
blue += 3;
if (x==0 && y==0) // 最初のデータでは、TUSERをアサートする
pix.user = 1;
else
pix.user = 0;
if (x==(HORIZONTAL_PIXELS-1)) // 行の最後で TLAST をアサートする
pix.last = 1;
else
pix.last = 0;
outs << pix;
}
}
}
// axi4_stream_master.tb.cpp
// 2016/08/15 by marsee
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <iostream>
#include <fstream>
#include <ap_axi_sdata.h>
#include "axi4_stream_master.h"
void axi4_stream_master(hls::stream<ap_axis<32,1,1,1> >& outs);
int main(){
using namespace std;
hls::stream<ap_axis<32,1,1,1> > outs;
ap_axis<32,1,1,1> pix;
ap_uint<8> red = 0;
ap_uint<8> blue = 0;
ap_uint<8> green = 0;
ap_int<32> pix_data;
axi4_stream_master(outs);
for (int y=0; y<VERTICAL_LINES; y++){
for (int x=0; x<HORIZONTAL_PIXELS; x++){
outs >> pix;
pix_data = red*65536 + green*256 + blue;
//printf("red=%x, green=%x, blue=%x, pix_data=%x\n", (int)red, (int)green, (int)blue, (int)pix_data);
if (pix.data != pix_data){
printf("ERROR HW and SW results mismatch x = %d, y = %d, HW = %x, SW = %x\n", x, y, (int)pix.data, (int)pix_data);
return(1);
}
red++;
green += 2;
blue += 3;
}
}
cout << "Success HW and SW results match" << endl;
cout << endl;
return(0);
}
ENTITY bitmap_afifo IS
PORT (
wr_clk : IN STD_LOGIC;
wr_rst : IN STD_LOGIC;
rd_clk : IN STD_LOGIC;
rd_rst : IN STD_LOGIC;
din : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
wr_en : IN STD_LOGIC;
rd_en : IN STD_LOGIC;
dout : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
full : OUT STD_LOGIC;
overflow : OUT STD_LOGIC;
empty : OUT STD_LOGIC;
underflow : OUT STD_LOGIC;
wr_data_count : OUT STD_LOGIC_VECTOR(9 DOWNTO 0)
);
END bitmap_afifo;
//
// lap_fil_on.c
// Created on: 2015/12/04
// Author: marsee
//
// Refered to http://japan.xilinx.com/support/documentation/sw_manuals_j/xilinx2014_4/ug902-vivado-high-level-synthesis.pdf
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>
#define CMA_START_ADDRESS 0x17800000
#define VIDEO_BUFFER_START_ADDRESS 0x18000000 // Limit 0x18800000, 800*600*4 = 2MBytes * 2
int main(){
int fd2, fd3, fd4;
volatile unsigned *axis_switch_0, *axis_switch_1;
volatile unsigned *lap_filter_axis_0;
int laps_cntrl;
// axis_switch_0 (UIO2)
fd2 = open("/dev/uio2", O_RDWR); // axis_switch_0 interface AXI4 Lite Slave
if (fd2 < 1){
fprintf(stderr, "/dev/uio2 (axis_switch_0) open error\n");
exit(-1);
}
axis_switch_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd2, 0);
if (!axis_switch_0){
fprintf(stderr, "axis_switch_0 mmap error\n");
exit(-1);
}
// axis_switch_1 (UIO3)
fd3 = open("/dev/uio3", O_RDWR); // axis_switch_1 interface AXI4 Lite Slave
if (fd3 < 1){
fprintf(stderr, "/dev/uio3 (axis_switch_1) open error\n");
exit(-1);
}
axis_switch_1 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd3, 0);
if (!axis_switch_1){
fprintf(stderr, "axis_switch_1 mmap error\n");
exit(-1);
}
// lap_filter_axis_0 (UIO4)
fd4 = open("/dev/uio4", O_RDWR); // lap_filter_axis_0 interface AXI4 Lite Slave
if (fd4 < 1){
fprintf(stderr, "/dev/uio4 (lap_filter_axis_0) open error\n");
exit(-1);
}
lap_filter_axis_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd4, 0);
if (!lap_filter_axis_0){
fprintf(stderr, "lap_filter_axis_0 mmap error\n");
exit(-1);
}
// axis_switch_1, 1to2 ,Select M01_AXIS
// Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
axis_switch_1[16] = 0x80000000; // 0x40 = 0x80000000; disable
axis_switch_1[17] = 0; // 0x44 = 0;
axis_switch_1[18] = 0x80000000; // 0x48 = 0x80000000, disable
axis_switch_1[0] = 0x2; // 0x0 = 2; Commit registers
// laplacian filter AXIS Start
laps_cntrl = lap_filter_axis_0[0] & 0x80; // Auto Restart bit
lap_filter_axis_0[0] = laps_cntrl | 0x01; // Start bit set
lap_filter_axis_0[0] = 0x80; // Auto Restart bit set
// axis_switch_0, 2to1, Select S01_AXIS
// Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
axis_switch_0[16] = 0x1; // 0x40 = 0x1;
axis_switch_0[0] = 0x2; // 0x0 = 2; Commit registers
munmap((void *)axis_switch_0, 0x10000);
munmap((void *)axis_switch_1, 0x10000);
munmap((void *)lap_filter_axis_0, 0x10000);
return(0);
}
//
// gabor_fil_left.c
// Created on: 2016/08/09
// Author: marsee
//
// Refered to http://japan.xilinx.com/support/documentation/sw_manuals_j/xilinx2014_4/ug902-vivado-high-level-synthesis.pdf
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>
#define CMA_START_ADDRESS 0x17800000
#define VIDEO_BUFFER_START_ADDRESS 0x18000000 // Limit 0x18800000, 800*600*4 = 2MBytes * 2
int main(){
int fd2, fd3, fd4;
volatile unsigned *axis_switch_0, *axis_switch_1;
volatile unsigned *gabor_filter_lh_0;
int gabor_cntrl;
// axis_switch_0 (UIO2)
fd2 = open("/dev/uio2", O_RDWR); // axis_switch_0 interface AXI4 Lite Slave
if (fd2 < 1){
fprintf(stderr, "/dev/uio2 (axis_switch_0) open error\n");
exit(-1);
}
axis_switch_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd2, 0);
if (!axis_switch_0){
fprintf(stderr, "axis_switch_0 mmap error\n");
exit(-1);
}
// axis_switch_1 (UIO3)
fd3 = open("/dev/uio3", O_RDWR); // axis_switch_1 interface AXI4 Lite Slave
if (fd3 < 1){
fprintf(stderr, "/dev/uio3 (axis_switch_1) open error\n");
exit(-1);
}
axis_switch_1 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd3, 0);
if (!axis_switch_1){
fprintf(stderr, "axis_switch_1 mmap error\n");
exit(-1);
}
// gabor_filter_lh_0 (UIo14)
fd4 = open("/dev/uio14", O_RDWR); // gabor_filter_lh_0 interface AXI4 Lite Slave
if (fd4 < 1){
fprintf(stderr, "/dev/uio14 (gabor_filter_lh_0) open error\n");
exit(-1);
}
gabor_filter_lh_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd4, 0);
if (!gabor_filter_lh_0){
fprintf(stderr, "lap_filter_axis_0 mmap error\n");
exit(-1);
}
// axis_switch_1, 1to2 ,Select M01_AXIS
// Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
axis_switch_1[16] = 0x80000000; // 0x40 = 0x80000000; disable
axis_switch_1[17] = 0x80000000; // 0x44 = 0x80000000; disable
axis_switch_1[18] = 0; // 0x48 = 0;
axis_switch_1[0] = 0x2; // 0x0 = 2; Commit registers
// gabor filter AXIS Start
gabor_filter_lh_0[6] = 0; // left parameter
gabor_cntrl = gabor_filter_lh_0[0] & 0x80; // Auto Restart bit
gabor_filter_lh_0[0] = gabor_cntrl | 0x01; // Start bit set
gabor_filter_lh_0[0] = 0x80; // Auto Restart bit set
// axis_switch_0, 2to1, Select S01_AXIS
// Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
axis_switch_0[16] = 0x2; // 0x40 = 0x2;
axis_switch_0[0] = 0x2; // 0x0 = 2; Commit registers
munmap((void *)axis_switch_0, 0x10000);
munmap((void *)axis_switch_1, 0x10000);
munmap((void *)gabor_filter_lh_0, 0x10000);
return(0);
}
//
// gabor_fil_right.c
// Created on: 2016/08/09
// Author: marsee
//
// Refered to http://japan.xilinx.com/support/documentation/sw_manuals_j/xilinx2014_4/ug902-vivado-high-level-synthesis.pdf
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>
#define CMA_START_ADDRESS 0x17800000
#define VIDEO_BUFFER_START_ADDRESS 0x18000000 // Limit 0x18800000, 800*600*4 = 2MBytes * 2
int main(){
int fd2, fd3, fd4;
volatile unsigned *axis_switch_0, *axis_switch_1;
volatile unsigned *gabor_filter_lh_0;
int gabor_cntrl;
// axis_switch_0 (UIO2)
fd2 = open("/dev/uio2", O_RDWR); // axis_switch_0 interface AXI4 Lite Slave
if (fd2 < 1){
fprintf(stderr, "/dev/uio2 (axis_switch_0) open error\n");
exit(-1);
}
axis_switch_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd2, 0);
if (!axis_switch_0){
fprintf(stderr, "axis_switch_0 mmap error\n");
exit(-1);
}
// axis_switch_1 (UIO3)
fd3 = open("/dev/uio3", O_RDWR); // axis_switch_1 interface AXI4 Lite Slave
if (fd3 < 1){
fprintf(stderr, "/dev/uio3 (axis_switch_1) open error\n");
exit(-1);
}
axis_switch_1 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd3, 0);
if (!axis_switch_1){
fprintf(stderr, "axis_switch_1 mmap error\n");
exit(-1);
}
// gabor_filter_lh_0 (UIo14)
fd4 = open("/dev/uio14", O_RDWR); // gabor_filter_lh_0 interface AXI4 Lite Slave
if (fd4 < 1){
fprintf(stderr, "/dev/uio14 (gabor_filter_lh_0) open error\n");
exit(-1);
}
gabor_filter_lh_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd4, 0);
if (!gabor_filter_lh_0){
fprintf(stderr, "lap_filter_axis_0 mmap error\n");
exit(-1);
}
// axis_switch_1, 1to2 ,Select M01_AXIS
// Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
axis_switch_1[16] = 0x80000000; // 0x40 = 0x80000000; disable
axis_switch_1[17] = 0x80000000; // 0x44 = 0x80000000; disable
axis_switch_1[18] = 0; // 0x48 = 0;
axis_switch_1[0] = 0x2; // 0x0 = 2; Commit registers
// gabor filter AXIS Start
gabor_filter_lh_0[6] = 1; // right parameter
gabor_cntrl = gabor_filter_lh_0[0] & 0x80; // Auto Restart bit
gabor_filter_lh_0[0] = gabor_cntrl | 0x01; // Start bit set
gabor_filter_lh_0[0] = 0x80; // Auto Restart bit set
// axis_switch_0, 2to1, Select S01_AXIS
// Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
axis_switch_0[16] = 0x2; // 0x40 = 0x2;
axis_switch_0[0] = 0x2; // 0x0 = 2; Commit registers
munmap((void *)axis_switch_0, 0x10000);
munmap((void *)axis_switch_1, 0x10000);
munmap((void *)gabor_filter_lh_0, 0x10000);
return(0);
}
//
// cam_return_axis.c
// Created on: 2014/11/22
// Author: Masaaki
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>
int main(){
int fd2, fd3, fd4;
volatile unsigned *axis_switch_0, *axis_switch_1;
volatile unsigned *lap_filter_axis_0;
// axis_switch_0 (UIO2)
fd2 = open("/dev/uio2", O_RDWR); // axis_switch_0 interface AXI4 Lite Slave
if (fd2 < 1){
fprintf(stderr, "/dev/uio2 (axis_switch_0) open error\n");
exit(-1);
}
axis_switch_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd2, 0);
if (!axis_switch_0){
fprintf(stderr, "axis_switch_0 mmap error\n");
exit(-1);
}
// axis_switch_1 (UIO3)
fd3 = open("/dev/uio3", O_RDWR); // axis_switch_1 interface AXI4 Lite Slave
if (fd3 < 1){
fprintf(stderr, "/dev/uio3 (axis_switch_1) open error\n");
exit(-1);
}
axis_switch_1 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd3, 0);
if (!axis_switch_1){
fprintf(stderr, "axis_switch_1 mmap error\n");
exit(-1);
}
// lap_filter_axis_0 (UIO4)
fd4 = open("/dev/uio4", O_RDWR); // lap_filter_axis_0 interface AXI4 Lite Slave
if (fd4 < 1){
fprintf(stderr, "/dev/uio4 (lap_filter_axis_0) open error\n");
exit(-1);
}
lap_filter_axis_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd4, 0);
if (!lap_filter_axis_0){
fprintf(stderr, "lap_filter_axis_0 mmap error\n");
exit(-1);
}
// axis_switch_1, 1to2 ,Select M01_AXIS
// Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
axis_switch_1[16] = 0; // 0x44 = 0;
axis_switch_1[17] = 0x80000000; // 0x40 = 0x80000000; disable
axis_switch_1[0] = 0x2; // 0x0 = 2; Commit registers
// laplacian filter AXIS Start
lap_filter_axis_0[0] = 0x00; // Auto Restart Disable
// axis_switch_0, 2to1, Select S01_AXIS
// Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
axis_switch_0[16] = 0x0; // 0x40 = 0x0;
axis_switch_0[0] = 0x2; // 0x0 = 2; Commit registers
munmap((void *)axis_switch_0, 0x10000);
munmap((void *)axis_switch_1, 0x10000);
munmap((void *)lap_filter_axis_0, 0x10000);
}
//
// cam_disp_vdma.c
// Created on: 2015/12/03
// Author: marsee
// 2016/01/23 : udmabuf version
// 2016/08/09 : Gabor Filter version
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>
#define CMA_START_ADDRESS 0x17800000
#define VIDEO_BUFFER_START_ADDRESS 0x18000000 // Limit 0x18800000, 800*600*4 = 2MBytes * 2
#define NUMBER_OF_WRITE_FRAMES 3 // Note: If not at least 3 or more, the image is not displayed in succession.
#define HORIZONTAL_PIXEL 800
#define ALL_CHAR_OF_1LINE (HORIZONTAL_PIXEL/8)
#define VERTICAL_PIXEL 600
#define ALL_CHAR_OF_ROW (VERTICAL_PIXEL/8)
#define ALL_DISP_ADDRESS (HORIZONTAL_PIXEL*VERTICAL_PIXEL*4)
#define ALL_DISP_CHARACTOR HORIZONTAL_PIXEL*VERTICAL_PIXEL
void cam_i2c_init(volatile unsigned *mt9d111_axi_iic) {
mt9d111_axi_iic[64] = 0x2; // reset tx fifo ,address is 0x100, i2c_control_reg
mt9d111_axi_iic[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 *mt9d111_axi_iic, unsigned int device_addr, unsigned int write_addr, unsigned int write_data){
mt9d111_axi_iic[66] = 0x100 | (device_addr & 0xfe); // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
mt9d111_axi_iic[66] = write_addr;
mt9d111_axi_iic[66] = (write_data >> 8)|0xff; // first data
mt9d111_axi_iic[66] = 0x200 | (write_data & 0xff); // second data
cam_i2x_write_sync();
}
int main()
{
int fd0, fd1, fd2, fd3, fd4, fd5, fd6, fd7, fd8, fd9, fd10;
volatile unsigned *bmdc_axi_lites0, *bmdc_axi_lites1;
volatile unsigned *axi_vdma_0;
volatile unsigned *axis_switch_0, *axis_switch_1;
volatile unsigned *mt9d111_inf_axis_0;
volatile unsigned *mt9d111_axi_iic;
volatile unsigned *axi_gpio_0;
volatile unsigned *frame_buffer_bmdc;
unsigned char attr[1024];
unsigned long phys_addr;
int i;
// Bitmap Display Controller 0 AXI4 Lite Slave (UIO6)
fd6 = open("/dev/uio6", O_RDWR); // bitmap_display_controller 0 axi4 lite
if (fd6 < 1){
fprintf(stderr, "/dev/uio6 (bitmap_disp_cntrler_axi_master_0) open error\n");
exit(-1);
}
bmdc_axi_lites0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd6, 0);
if (!bmdc_axi_lites0){
fprintf(stderr, "bmdc_axi_lites0 mmap error\n");
exit(-1);
}
bmdc_axi_lites0[0] = VIDEO_BUFFER_START_ADDRESS; // Bitmap Display 1 Controller start
// Bitmap Display Controller 1 AXI4 Lite Slave (UIO7)
fd7 = open("/dev/uio7", O_RDWR); // bitmap_display_controller axi4 lite
if (fd7 < 1){
fprintf(stderr, "/dev/uio7 (bitmap_disp_cntrler_axi_master_0) open error\n");
exit(-1);
}
bmdc_axi_lites1 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd7, 0);
if (!bmdc_axi_lites1){
fprintf(stderr, "bmdc_axi_lites1 mmap error\n");
exit(-1);
}
bmdc_axi_lites1[0] = VIDEO_BUFFER_START_ADDRESS; // Bitmap Display Controller start
// axi_vdma_0 (UIO1)
fd1 = open("/dev/uio1", O_RDWR); // axi_vdma_0 interface AXI4 Lite Slave
if (fd1 < 1){
fprintf(stderr, "/dev/uio1 (axi_vdma_0) open error\n");
exit(-1);
}
axi_vdma_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd1, 0);
if (!axi_vdma_0){
fprintf(stderr, "axi_vdma_0 mmap error\n");
exit(-1);
}
// mt9d111 i2c AXI4 Lite Slave (UIO0)
fd0 = open("/dev/uio0", O_RDWR); // mt9d111 i2c AXI4 Lite Slave
if (fd0 < 1){
fprintf(stderr, "/dev/uio0 (mt9d111_axi_iic) open error\n");
exit(-1);
}
mt9d111_axi_iic = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd0, 0);
if (!mt9d111_axi_iic){
fprintf(stderr, "mt9d111_axi_iic mmap error\n");
exit(-1);
}
// mt9d111 inf axis AXI4 Lite Slave (UIO5)
fd5 = open("/dev/uio5", O_RDWR); // mt9d111 inf axis AXI4 Lite Slave
if (fd5 < 1){
fprintf(stderr, "/dev/uio5 (mt9d111_inf_axis_0) open error\n");
exit(-1);
}
mt9d111_inf_axis_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd5, 0);
if (!mt9d111_inf_axis_0){
fprintf(stderr, "mt9d111_inf_axis_0 mmap error\n");
exit(-1);
}
// axis_switch_0 (UIO2)
fd2 = open("/dev/uio2", O_RDWR); // axis_switch_0 interface AXI4 Lite Slave
if (fd2 < 1){
fprintf(stderr, "/dev/uio2 (axis_switch_0) open error\n");
exit(-1);
}
axis_switch_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd2, 0);
if (!axis_switch_0){
fprintf(stderr, "axis_switch_0 mmap error\n");
exit(-1);
}
// axis_switch_1 (UIO3)
fd3 = open("/dev/uio3", O_RDWR); // axis_switch_1 interface AXI4 Lite Slave
if (fd3 < 1){
fprintf(stderr, "/dev/uio3 (axis_switch_1) open error\n");
exit(-1);
}
axis_switch_1 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd3, 0);
if (!axis_switch_1){
fprintf(stderr, "axis_switch_1 mmap error\n");
exit(-1);
}
// axi_gpio_0 (UIO8)
fd8 = open("/dev/uio8", O_RDWR); // axi_gpio_0 interface AXI4 Lite Slave
if (fd8 < 1){
fprintf(stderr, "/dev/uio8 (axi_gpio_0) open error\n");
exit(-1);
}
axi_gpio_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd8, 0);
if (!axi_gpio_0){
fprintf(stderr, "axi_gpio_8 mmap error\n");
exit(-1);
}
// udmabuf0
fd9 = open("/dev/udmabuf0", O_RDWR | O_SYNC); // frame_buffer, The chache is disabled.
if (fd9 == -1){
fprintf(stderr, "/dev/udmabuf0 open error\n");
exit(-1);
}
frame_buffer_bmdc = (volatile unsigned *)mmap(NULL, 5760000, PROT_READ|PROT_WRITE, MAP_SHARED, fd9, 0);
if (!frame_buffer_bmdc){
fprintf(stderr, "frame_buffer_bmdc mmap error\n");
exit(-1);
}
// axis_switch_1, 1to2 ,Select M00_AXIS
// Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
axis_switch_1[16] = 0x0; // 0x40 = 0
axis_switch_1[17] = 0x80000000; // 0x44 = 0x80000000, disable
axis_switch_1[18] = 0x80000000; // 0x48 = 0x80000000, disable
axis_switch_1[0] = 0x2; // Comit registers
// axis_switch_0, 2to1, Select S00_AXIS
// Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
axis_switch_0[16] = 0x0; // 0x40 = 0;
axis_switch_0[0] = 0x2; // Comit registers
// phys_addr of udmabuf0
fd10 = open("/sys/devices/virtual/udmabuf/udmabuf0/phys_addr", O_RDONLY);
if (fd10 == -1){
fprintf(stderr, "/sys/devices/virtual/udmabuf/udmabuf0/phys_addr open error\n");
exit(-1);
}
read(fd10, attr, 1024);
sscanf(attr, "%lx", &phys_addr);
close(fd10);
printf("phys_addr = %x\n", (int)phys_addr);
// AXI VDMA Initialization sequence
axi_vdma_0[12] = 0x4; // S2MM_VDMACR (S2MM VDMA Control Register Offset 30h) is 0x4
while ((axi_vdma_0[12] & 0x4) == 0x4) ; // Reset is progress
axi_vdma_0[12] = 0x4; // S2MM_VDMACR (S2MM VDMA Control Register Offset 30h) is 0x4
while ((axi_vdma_0[12] & 0x4) == 0x4) ; // Reset is progress
axi_vdma_0[18] = 0x3; // S2MM_FRMSTORE (0x48) register
axi_vdma_0[12] = 0x00010002; // S2MM_VDMACR(IRQFrameCount = 0x1, Circular_Park = 1)
axi_vdma_0[41] = 0xc80; // S2MM Horizontal Size Register(S2MM_HSIZE)0xc80 = 3200dec = 800 x 4
axi_vdma_0[42] = 0xc80; // S2MM Frame Delay and Stride Register(S2MM_FRMDLY_STRIDE)0xc80 = 3200dec = 800 x 4
axi_vdma_0[43] = (int)phys_addr; // S2MM Start Address (1 to 16) Start Address 1
axi_vdma_0[44] = (int)phys_addr; // S2MM Start Address (1 to 16) Start Address 2
axi_vdma_0[45] = (int)phys_addr; // S2MM Start Address (1 to 16) Start Address 3
axi_vdma_0[12] = 0x00010003; // S2MM_VDMACR(IRQFrameCount = 0x1, Circular_Park = 1, Run/stop = 1)
while((axi_vdma_0[13] & 0x1) == 0x1) ; // Halt? (S2MM_VDMASR 0x34)
axi_vdma_0[40] = 0x258; // S2MM Vertical Size (S2MM_VSIZE Offset 0xA0) 0x258 = 600dec
// bitmap display controller settings
bmdc_axi_lites0[0] = (int)phys_addr; // Bitmap Display Controller 0 start
bmdc_axi_lites1[0] = (int)phys_addr; // Bitmap Display Controller 1 start
mt9d111_inf_axis_0[0] = (int)phys_addr; // Camera Interface start (Address is dummy)
// CMOS Camera initialize, MT9D111
cam_i2c_init(mt9d111_axi_iic);
for (i=0; i<100; i++){
cam_i2c_write(mt9d111_axi_iic, 0xba, 0xf0, 0x1); // Changed regster map to IFP page 1
cam_i2c_write(mt9d111_axi_iic, 0xba, 0x97, 0x20); // RGB Mode, RGB565
}
mt9d111_inf_axis_0[1] = 0;
munmap((void *)bmdc_axi_lites0, 0x10000);
munmap((void *)bmdc_axi_lites1, 0x10000);
munmap((void *)axi_vdma_0, 0x10000);
munmap((void *)mt9d111_inf_axis_0, 0x10000);
munmap((void *)mt9d111_axi_iic, 0x10000);
munmap((void *)axis_switch_0, 0x10000);
munmap((void *)axis_switch_1, 0x10000);
munmap((void *)axi_gpio_0, 0x10000);
munmap((void *)frame_buffer_bmdc, 576000);
close(fd0);
close(fd1);
close(fd2);
close(fd3);
close(fd4);
close(fd5);
close(fd6);
close(fd7);
close(fd8);
close(fd9);
return(0);
}
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
- | 1 | 2 | 3 | 4 | 5 | 6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 31 | - | - | - |