m_axis_tuser(0) <= s2mm_fsync_node;
m_axis_tkeep <= (others => '1') when pfifo_empty='0' else (others => '0');
・入力で Video Timing Controller コアを検出モードで使用する。
・Video In to AXI4 Stream コアを使用して入力ビデオ タイミング情報から SOF 信号を生成する。
・AXI VDMA などの該当するコアの SOF on TUSER モードをイネーブルにし、fsync 信号ではなくこれを使用してフレーム同期を行う。コアによって、SOF が自動的にシステム全体に伝搬されます。
・デザインに AXI VDMA が含まれている場合 :
・S2MM 側を外部フレーム同期モードに設定し、SOF on TUSER をイネーブルにする。 S2MM_DMACR レジスタの FsyncSrcSelect ビットを 2'b10 に設定してフレーム同期ソースとして TUSER を選択してください。
・MM2S 側をフリー ランニング モードに設定する。
・fsync 信号を接続する (XPS では接続しなくてもよい)。
・出力で Video Timing Controller コアを生成モードで使用し、ビデオ タイミング情報を再生成する。
・AXI4 Stream to Video Out コアを使用して出力ビデオ データを同期する。
NET "vga_blue[0]" LOC = Y21;
NET "vga_blue[1]" LOC = Y20;
NET "vga_blue[2]" LOC = AB20;
NET "vga_blue[3]" LOC = AB19;
NET "vga_blue[0]" IOSTANDARD = LVCMOS33;
NET "vga_blue[1]" IOSTANDARD = LVCMOS33;
NET "vga_blue[2]" IOSTANDARD = LVCMOS33;
NET "vga_blue[3]" IOSTANDARD = LVCMOS33;
INST "vga_blue_0_OBUF" IOB =FORCE;
INST "vga_blue_1_OBUF" IOB =FORCE;
INST "vga_blue_2_OBUF" IOB =FORCE;
INST "vga_blue_3_OBUF" IOB =FORCE;
NET "vga_green[0]" LOC = AB22;
NET "vga_green[1]" LOC = AA22;
NET "vga_green[2]" LOC = AB21;
NET "vga_green[3]" LOC = AA21;
NET "vga_green[0]" IOSTANDARD = LVCMOS33;
NET "vga_green[1]" IOSTANDARD = LVCMOS33;
NET "vga_green[2]" IOSTANDARD = LVCMOS33;
NET "vga_green[3]" IOSTANDARD = LVCMOS33;
INST "vga_green_0_OBUF" IOB =FORCE;
INST "vga_green_1_OBUF" IOB =FORCE;
INST "vga_green_2_OBUF" IOB =FORCE;
INST "vga_green_3_OBUF" IOB =FORCE;
NET "vga_red[0]" LOC = V20;
NET "vga_red[1]" LOC = U20;
NET "vga_red[2]" LOC = V19;
NET "vga_red[3]" LOC = V18;
NET "vga_red[0]" IOSTANDARD = LVCMOS33;
NET "vga_red[1]" IOSTANDARD = LVCMOS33;
NET "vga_red[2]" IOSTANDARD = LVCMOS33;
NET "vga_red[3]" IOSTANDARD = LVCMOS33;
INST "vga_red_0_OBUF" IOB =FORCE;
INST "vga_red_1_OBUF" IOB =FORCE;
INST "vga_red_2_OBUF" IOB =FORCE;
INST "vga_red_3_OBUF" IOB =FORCE;
NET "vga_hsync" LOC = AA19;
NET "vga_vsync" LOC = Y19;
NET "vga_hsync" IOSTANDARD = LVCMOS33;
NET "vga_vsync" IOSTANDARD = LVCMOS33;
INST "vga_hsync_OBUF" IOB =FORCE;
INST "vga_vsync_OBUF" IOB =FORCE;
INST "hdmi_clk_OBUF" IOB =FORCE;
NET "hdmi_clk" LOC = W18;
NET "hdmi_clk" IOSTANDARD = LVCMOS33;
INST "hdmi_vsync_OBUF" IOB =FORCE;
NET "hdmi_vsync" LOC = W17;
NET "hdmi_vsync" IOSTANDARD = LVCMOS33;
INST "hdmi_hsync_OBUF" IOB =FORCE;
NET "hdmi_hsync" LOC = V17;
NET "hdmi_hsync" IOSTANDARD = LVCMOS33;
INST "hdmi_data_e_OBUF" IOB =FORCE;
NET "hdmi_data_e" LOC = U16;
NET "hdmi_data_e" IOSTANDARD = LVCMOS33;
INST "hdmi_data_0_OBUF" IOB =FORCE;
NET "hdmi_data[0]" LOC = Y13;
NET "hdmi_data[0]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_1_OBUF" IOB =FORCE;
NET "hdmi_data[1]" LOC = AA13;
NET "hdmi_data[1]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_2_OBUF" IOB =FORCE;
NET "hdmi_data[2]" LOC = AA14;
NET "hdmi_data[2]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_3_OBUF" IOB =FORCE;
NET "hdmi_data[3]" LOC = Y14;
NET "hdmi_data[3]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_4_OBUF" IOB =FORCE;
NET "hdmi_data[4]" LOC = AB15;
NET "hdmi_data[4]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_5_OBUF" IOB =FORCE;
NET "hdmi_data[5]" LOC = AB16;
NET "hdmi_data[5]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_6_OBUF" IOB =FORCE;
NET "hdmi_data[6]" LOC = AA16;
NET "hdmi_data[6]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_7_OBUF" IOB =FORCE;
NET "hdmi_data[7]" LOC = AB17;
NET "hdmi_data[7]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_8_OBUF" IOB =FORCE;
NET "hdmi_data[8]" LOC = AA17;
NET "hdmi_data[8]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_9_OBUF" IOB =FORCE;
NET "hdmi_data[9]" LOC = Y15;
NET "hdmi_data[9]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_10_OBUF" IOB =FORCE;
NET "hdmi_data[10]" LOC = W13;
NET "hdmi_data[10]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_11_OBUF" IOB =FORCE;
NET "hdmi_data[11]" LOC = W15;
NET "hdmi_data[11]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_12_OBUF" IOB =FORCE;
NET "hdmi_data[12]" LOC = V15;
NET "hdmi_data[12]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_13_OBUF" IOB =FORCE;
NET "hdmi_data[13]" LOC = U17;
NET "hdmi_data[13]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_14_OBUF" IOB =FORCE;
NET "hdmi_data[14]" LOC = V14;
NET "hdmi_data[14]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_15_OBUF" IOB =FORCE;
NET "hdmi_data[15]" LOC = V13;
NET "hdmi_data[15]" IOSTANDARD = LVCMOS33;
NET "hdmi_iic_Scl" LOC = AA18;
NET "hdmi_iic_Scl" IOSTANDARD = LVCMOS33;
NET "hdmi_iic_Sda" LOC = Y16;
NET "hdmi_iic_Sda" IOSTANDARD = LVCMOS33;
NET "hdmi_data[15]" SLEW = FAST;
NET "hdmi_data[14]" SLEW = FAST;
NET "hdmi_data[13]" SLEW = FAST;
NET "hdmi_data[12]" SLEW = FAST;
NET "hdmi_data[11]" SLEW = FAST;
NET "hdmi_data[10]" SLEW = FAST;
NET "hdmi_data[9]" SLEW = FAST;
NET "hdmi_data[8]" SLEW = FAST;
NET "hdmi_data[7]" SLEW = FAST;
NET "hdmi_data[6]" SLEW = FAST;
NET "hdmi_data[5]" SLEW = FAST;
NET "hdmi_data[4]" SLEW = FAST;
NET "hdmi_data[3]" SLEW = FAST;
NET "hdmi_data[2]" SLEW = FAST;
NET "hdmi_data[1]" SLEW = FAST;
NET "hdmi_data[0]" SLEW = FAST;
NET "vga_blue[3]" SLEW = FAST;
NET "vga_blue[2]" SLEW = FAST;
NET "vga_blue[1]" SLEW = FAST;
NET "vga_blue[0]" SLEW = FAST;
NET "vga_green[3]" SLEW = FAST;
NET "vga_green[2]" SLEW = FAST;
NET "vga_green[1]" SLEW = FAST;
NET "vga_green[0]" SLEW = FAST;
NET "vga_red[3]" SLEW = FAST;
NET "vga_red[2]" SLEW = FAST;
NET "vga_red[1]" SLEW = FAST;
NET "vga_red[0]" SLEW = FAST;
NET "hdmi_clk" SLEW = FAST;
NET "hdmi_data_e" SLEW = FAST;
NET "hdmi_hsync" SLEW = FAST;
NET "hdmi_iic_Scl" SLEW = SLOW;
NET "hdmi_vsync" SLEW = FAST;
NET "vga_hsync" SLEW = FAST;
NET "vga_vsync" SLEW = FAST;
NET "mt9d111_d[7]" LOC = W12;
NET "mt9d111_d[6]" LOC = V12;
NET "mt9d111_d[5]" LOC = W11;
NET "mt9d111_d[4]" LOC = W10;
NET "mt9d111_d[3]" LOC = V10;
NET "mt9d111_d[2]" LOC = V9;
NET "mt9d111_d[1]" LOC = W8;
NET "mt9d111_d[0]" LOC = V8;
NET "mt9d111_d[7]" IOSTANDARD = LVCMOS33;
NET "mt9d111_d[6]" IOSTANDARD = LVCMOS33;
NET "mt9d111_d[5]" IOSTANDARD = LVCMOS33;
NET "mt9d111_d[4]" IOSTANDARD = LVCMOS33;
NET "mt9d111_d[3]" IOSTANDARD = LVCMOS33;
NET "mt9d111_d[2]" IOSTANDARD = LVCMOS33;
NET "mt9d111_d[1]" IOSTANDARD = LVCMOS33;
NET "mt9d111_d[0]" IOSTANDARD = LVCMOS33;
NET "mt9d111_href" LOC = AB10;
NET "mt9d111_pclk" LOC = AA9;
NET "mt9d111_Scl" LOC = Y11;
NET "mt9d111_Sda" LOC = AB11;
NET "mt9d111_standby" LOC = Y10;
NET "mt9d111_vsync" LOC = AA11;
NET "mt9d111_xck" LOC = AA8;
NET "mt9d111_href" IOSTANDARD = LVCMOS33;
NET "mt9d111_pclk" IOSTANDARD = LVCMOS33;
NET "mt9d111_Scl" IOSTANDARD = LVCMOS33;
NET "mt9d111_Sda" IOSTANDARD = LVCMOS33;
NET "mt9d111_standby" IOSTANDARD = LVCMOS33;
NET "mt9d111_vsync" IOSTANDARD = LVCMOS33;
NET "mt9d111_xck" IOSTANDARD = LVTTL;
NET "mt9d111_d[0]" OFFSET = IN 10.8 ns VALID 21.7 ns BEFORE "mt9d111_pclk" RISING;
NET "mt9d111_d[1]" OFFSET = IN 10.8 ns VALID 21.7 ns BEFORE "mt9d111_pclk" RISING;
NET "mt9d111_d[2]" OFFSET = IN 10.8 ns VALID 21.7 ns BEFORE "mt9d111_pclk" RISING;
NET "mt9d111_d[3]" OFFSET = IN 10.8 ns VALID 21.7 ns BEFORE "mt9d111_pclk" RISING;
NET "mt9d111_d[4]" OFFSET = IN 10.8 ns VALID 21.7 ns BEFORE "mt9d111_pclk" RISING;
NET "mt9d111_d[5]" OFFSET = IN 10.8 ns VALID 21.7 ns BEFORE "mt9d111_pclk" RISING;
NET "mt9d111_d[6]" OFFSET = IN 10.8 ns VALID 21.7 ns BEFORE "mt9d111_pclk" RISING;
NET "mt9d111_d[7]" OFFSET = IN 10.8 ns VALID 21.7 ns BEFORE "mt9d111_pclk" RISING;
NET "mt9d111_href" OFFSET = IN 10.8 ns VALID 21.7 ns BEFORE "mt9d111_pclk" RISING;
NET "mt9d111_vsync" OFFSET = IN 10.8 ns VALID 21.7 ns BEFORE "mt9d111_pclk" RISING;
NET "mt9d111_Scl" PULLUP;
NET "mt9d111_Sda" PULLUP;
// laplacian_filter.c
// RGBをYに変換後にラプラシアンフィルタを掛ける。
// ピクセルのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 2013/09/16
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <assert.h>
#include <ctype.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/kernel.h>
#define HORIZONTAL_PIXEL_WIDTH 800
#define VERTICAL_PIXEL_WIDTH 600
#define ALL_PIXEL_VALUE (HORIZONTAL_PIXEL_WIDTH*VERTICAL_PIXEL_WIDTH)
#define PAGE_SIZE (4*1024)
#define BLOCK_SIZE (4*1024)
#define ALLC_SIZE (PAGE_SIZE * 469) // 800*600*4 を超えるPAGE_SIZEの倍数
#define BUFSIZE 1024
int laplacian_fil(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2);
int conv_rgb2y(int rgb);
int chkhex(char *str);
volatile unsigned int *setup_io(off_t mapped_addr, unsigned int *buf_addr);
void Xil_DCacheInvalidateLine(unsigned int adr);
void Xil_DCacheFlushLine(unsigned int adr);
int main()
{
FILE *fd;
int xy[3][3];
char buf[BUFSIZE], *token;
unsigned int read_num;
unsigned int bitmap_dc_reg_addr;
volatile unsigned *bm_disp_cnt_reg;
unsigned int fb_addr, next_frame_addr;
int x, y;
unsigned int val;
int i, j;
int lap_fil_val;
int *r_pixel, *w_pixel;
unsigned int r_addr, w_addr;
unsigned int r_addr_page, w_addr_page;
unsigned int r_addr_page_pre=0, w_addr_page_pre=0;
unsigned int r_addr_offset, w_addr_offset;
unsigned int r_buf, w_buf, bitmap_buf;
// fb_start_addr.txt の内容をパイプに入れる
memset(buf, '\0', sizeof(buf)); // buf すべてに\0 を入れる
// fb_start_addr.txt を開く
fd = popen("cat /Apps/fb_start_addr.txt", "r");
if (fd != NULL){
read_num = fread(buf, sizeof(unsigned char), BUFSIZE, fd);
if (read_num > 0){
sscanf(buf, "%x\n", &fb_addr);
}
}
pclose(fd);
// ラプラシアンフィルタの結果を入れておくフレーム・バッファ
next_frame_addr = ((fb_addr + (ALL_PIXEL_VALUE*4)) & (~(int)(PAGE_SIZE-1))) + PAGE_SIZE;
// RGB値をY(輝度成分)のみに変換し、ラプラシアンフィルタを掛けた。
for (y=0; y<VERTICAL_PIXEL_WIDTH; y++){
for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
if (y==0 || y==VERTICAL_PIXEL_WIDTH-1){ // 縦の境界の時の値は0とする
lap_fil_val = 0;
}else if (x==0 || x==HORIZONTAL_PIXEL_WIDTH-1){ // 横の境界の時も値は0とする
lap_fil_val = 0;
}else{
for (j=-1; j<2; j++){
for (i=-1; i<2; i++){
r_addr = fb_addr+((y+j)*HORIZONTAL_PIXEL_WIDTH+(x+i))*4;
r_addr_page = r_addr & (~(int)(PAGE_SIZE-1));
r_addr_offset = r_addr & ((int)(PAGE_SIZE-1));
r_pixel = setup_io((off_t)r_addr_page, &r_buf);
xy[i+1][j+1] = *(volatile int *)((unsigned int)r_pixel + r_addr_offset);
munmap(r_pixel, BLOCK_SIZE);
free((char *)r_buf);
xy[i+1][j+1] = conv_rgb2y(xy[i+1][j+1]);
}
}
lap_fil_val = laplacian_fil(xy[0][0], xy[1][0], xy[2][0], xy[0][1], xy[1][1], xy[2][1], xy[0][2], xy[1][2], xy[2][2]);
}
w_addr = next_frame_addr+(y*HORIZONTAL_PIXEL_WIDTH + x)*4;
w_addr_page = w_addr & (~(int)(PAGE_SIZE-1));
w_addr_offset = w_addr & ((int)(PAGE_SIZE-1));
w_pixel = setup_io((off_t)w_addr_page, &w_buf);
*(volatile int *)((unsigned int)w_pixel + w_addr_offset) = (lap_fil_val<<16)+(lap_fil_val<<8)+lap_fil_val ;
munmap(w_pixel, BLOCK_SIZE);
free((char *)w_buf);
// printf("x = %d y = %d", x, y);
}
}
// bitmap-disp-cntrler-axi-master のアドレスを取得
memset(buf, '\0', sizeof(buf)); // buf すべてに\0 を入れる
// ls /sys/devices/axi.0 の内容をパイプに入れる
fd = popen("ls /sys/devices/axi.0", "r");
if (fd != NULL){
read_num = fread(buf, sizeof(unsigned char), BUFSIZE, fd);
if (read_num > 0){
token = buf;
if ((token=strtok(token, ".\n")) != NULL){
do {
if (chkhex(token)){ // 16進数
sscanf(token, "%x", &val);
} else {
if (strcmp(token, "bitmap-disp-cntrler-axi-master") == 0)
bitmap_dc_reg_addr = val;
}
}while((token=strtok(NULL, ".\n")) != NULL);
}
}
}
pclose(fd);
// ラプラシアンフィルタの掛かった画像のスタートアドレスを bitmap-disp-cntrler-axi-master にセット
bm_disp_cnt_reg = setup_io((off_t)bitmap_dc_reg_addr, &bitmap_buf);
*bm_disp_cnt_reg = next_frame_addr;
munmap((unsigned int *)bm_disp_cnt_reg, BLOCK_SIZE);
free((char *)bitmap_buf);
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
//
int conv_rgb2y(int rgb){
float r, g, b, y_f;
int y;
b = (float)(rgb & 0xff);
g = (float)((rgb>>8) & 0xff);
r = (float)((rgb>>16) & 0xff);
y_f = 0.299*r + 0.587*g + 0.114*b;
y = (int)y_f;
return(y);
}
// ラプラシアンフィルタ
// x0y0 x1y0 x2y0 -1 -1 -1
// x0y1 x1y1 x2y1 -1 8 -1
// x0y2 x1y2 x2y2 -1 -1 -1
int laplacian_fil(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2)
{
return(abs(-x0y0 -x1y0 -x2y0 -x0y1 +8*x1y1 -x2y1 -x0y2 -x1y2 -x2y2));
}
//
// Set up a memory regions to access GPIO
//
volatile unsigned int *setup_io(off_t mapped_addr, unsigned int *buf_addr)
// void setup_io()
{
int mem_fd;
char *gpio_mem, *gpio_map;
/* open /dev/mem */
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
printf("can't open /dev/mem \n");
printf("mapped_addr = %x\n", (unsigned int)mapped_addr);
exit (-1);
}
/* mmap GPIO */
// Allocate MAP block
if ((gpio_mem = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
printf("allocation error \n");
exit (-1);
}
*buf_addr = (unsigned int)gpio_mem; // mallocしたアドレスをコピー
// Make sure pointer is on 4K boundary
if ((unsigned long)gpio_mem % PAGE_SIZE)
gpio_mem += PAGE_SIZE - ((unsigned long)gpio_mem % PAGE_SIZE);
// Now map it
gpio_map = (unsigned char *)mmap(
(caddr_t)gpio_mem,
BLOCK_SIZE,
PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_FIXED,
mem_fd,
mapped_addr
);
if ((long)gpio_map < 0) {
printf("mmap error %d\n", (int)gpio_map);
printf("mapped_addr = %x\n", (unsigned int)mapped_addr);
exit (-1);
}
close(mem_fd); // /dev/mem のクローズ
// Always use volatile pointer!
// gpio = (volatile unsigned *)gpio_map;
return((volatile unsigned *)gpio_map);
} // setup_io
// 文字列が16進数かを調べる
int chkhex(char *str){
while (*str != '\0'){
if (!isxdigit(*str))
return 0;
str++;
}
return 1;
}
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
- | - | - | - | 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 | - |