を行うと、プロンプトが出た。キーのエコーが問題無くなった。直りました。sudo apt-get remove --purge xserver-xorg
sudo apt-get install xserver-xorg
sudo dpkg-reconfigure xserver-xorg
に設定してある。operating-points = <666667 1000000 333334 1000000>;
のみにしてみた。operating-points = <650000 1000000 >;
adjtimex -f 667000000 で周波数に667MHzを入れようとしたが、このコマンドを実行して、adjtimex -p で表示した結果は以下の通りだった。linaro@linaro-ubuntu-desktop:~$ sudo adjtimex -p
mode: 0
offset: 0
frequency: 0
maxerror: 1251516
esterror: 16
status: 16385
time_constant: 7
precision: 1
tolerance: 32768000
tick: 10000
raw time: 1417203572s 868504us = 1417203572.868504
linaro@linaro-ubuntu-desktop:~$ sudo adjtimex --help
Usage: adjtimex [OPTION]...
Mandatory or optional arguments to long options are mandatory or optional
for short options too.
Get/Set Kernel Time Parameters:
-p, --print print values of kernel time variables
-t, --tick val set the kernel tick interval in usec
-f, --frequency newfreq set system clock frequency offset
-s, --singleshot adj slew the system clock by adj usec
-S, --status val set kernel clock status
-R, --reset reset status after setting parameters
(needed for early kernels)
-o, --offset adj add a time offset of adj usec
-m, --maxerror val set maximum error (usec)
-e, --esterror val set estimated error (usec)
-T, --timeconstant val set phase locked loop time constant
-a, --adjust[=count] set system clock parameters per CMOS
clock or (with --review) log file
--force-adjust override +-1 percent sanity check
Estimate Systematic Drifts:
-c, --compare[=count] compare system and CMOS clocks
-i, --interval tim set clock comparison interval (sec)
-l, --log[=file] log current times to file
-h, --host timeserver query the timeserver
-w, --watch get current time from user
-r, --review[=file] review clock log file, estimate drifts
-u, --utc the CMOS clock is set to UTC
-d, --directisa access the CMOS clock directly
-n, --nointerrupt bypass the CMOS clock interrupt access method
Informative Output:
--help print this help, then exit
-v, --version print adjtimex program version, then exit
-V, --verbose increase verbosity
)。注記 : アプ リ ケーシ ョ ン プロセッシング ユニッ ト (APU) および PS 全体は、命令 とデータのどち らについて も リ ト ルエンディ アン アーキテ クチャ しかサポー ト していません。
これを次のように修正する// bmp_dataの書き込み
for (i=0; i<VERTICAL_LINES; i++) {
for (j=0; j<HORIZONTAL_PIXEL; 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);
}
}
つまり、1との排他的論理和演算をすることで、LSBを反転させた。これはint 単位(32ビット単位)でアドレスを1つひっくり返すことになる。// bmp_dataの書き込み
for (i=0; i<VERTICAL_LINES; i++) {
for (j=0; j<HORIZONTAL_PIXEL; j++) {
fputc((int)bmp_data[i][j^1].blue, fbmp);
fputc((int)bmp_data[i][j^1].green, fbmp);
fputc((int)bmp_data[i][j^1].red, fbmp);
}
}
* Starting regular background program processing daemon [ OK ]
* Stopping save kernel messages [ OK ]
//
// disp2bmp.c
//
// Created on: 2014/11/24
// Author: Masaaki
// カメラの画像をBMPファイルに変換する
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>
#include "bmpheader.h"
#define HORIZONTAL_PIXEL 800
#define VERTICAL_LINES 600
#define CMA_START_ADDRESS 0x17800000
#define VIDEO_BUFFER_START_ADDRESS 0x18000000 // Limit 0x18800000, 800*600*4 = 2MBytes * 2
int main(int argc, char * argv[])
{
char bmp_file[300];
BITMAPFILEHEADER bmpfh; // BMPファイルのファイルヘッダ
BITMAPINFOHEADER bmpih; // BMPファイルのINFOヘッダ
BMP24FORMAT **bmp_data; // 24ビットのBMPファイルのデータ HORIZONTAL_PIXEL * VERTICAL_LINES
FILE *fbmp;
int i, j;
int fd3;
volatile unsigned int *frame_buffer, *fb_base_addr;
// 引数の処理
if (argc == 1) { // 引数なし
strcpy(bmp_file, "default.bmp");
} else if (argc == 2){ //
strcpy(bmp_file, (const char *)argv[1]);
} else {
fprintf(stderr, "disp2bmp <BMP file name>\n");
exit(1);
}
// メモリをアロケートする
if ((bmp_data=(BMP24FORMAT **)malloc(sizeof(BMP24FORMAT *)*VERTICAL_LINES)) == NULL){
fprintf(stderr, "bmp_dataの1次元目の VERTICAL_LINES のメモリを確保できません\n");
exit(1);
}
for (i=0; i<VERTICAL_LINES; i++){
if ((bmp_data[i]=(BMP24FORMAT *)malloc(sizeof(BMP24FORMAT) * HORIZONTAL_PIXEL)) == NULL){
fprintf(stderr, "bmp_dataの2次元目の%d番目のメモリが確保できません\n", i);
exit(1);
}
}
// Frame Buffer UIO3
fd3 = open("/dev/uio3", O_RDWR); // Frame Buffer
if (fd3 < 1){
fprintf(stderr, "/dev/uio3 open error\n");
exit(-1);
}
frame_buffer = (volatile unsigned int *)mmap(NULL, 0x1000000, PROT_READ|PROT_WRITE, MAP_SHARED, fd3, 0);
if (!frame_buffer){
fprintf(stderr, "frame_buffer mmap error\n");
exit(-1);
}
// キャプチャ画像のベースアドレスを設定する
fb_base_addr = (volatile unsigned int *)((unsigned int)frame_buffer + (VIDEO_BUFFER_START_ADDRESS-CMA_START_ADDRESS));
// カメラのカラーデータをbmp_dataにをコピー(その際にBMPのデータは左下から始まる)
for (i=0; i<VERTICAL_LINES; i++){
for (j=0; j<HORIZONTAL_PIXEL; j++){
bmp_data[(VERTICAL_LINES-1)-i][j].red = (fb_base_addr[i*HORIZONTAL_PIXEL+j]>>16)&0xff;
bmp_data[(VERTICAL_LINES-1)-i][j].green = (fb_base_addr[i*HORIZONTAL_PIXEL+j]>>8)&0xff;
bmp_data[(VERTICAL_LINES-1)-i][j].blue = (fb_base_addr[i*HORIZONTAL_PIXEL+j])&0xff;
}
}
// BMPファイルのファイルヘッダに値を代入
bmpfh.bfType = 0x4d42;
bmpfh.bfSize = HORIZONTAL_PIXEL*VERTICAL_LINES*3+54;
bmpfh.bfReserved1 = 0;
bmpfh.bfReserved2 = 0;
bmpfh.bfOffBits = 0x36;
// BMPファイルのINFOヘッダに値を代入
bmpih.biSize = 0x28;
bmpih.biWidth = HORIZONTAL_PIXEL;
bmpih.biHeight = 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;
// bmpファイルに書き出す
if ((fbmp=fopen(bmp_file, "wb")) == NULL){
fprintf(stderr, "%s がバイナリ・ライトモードで開けません\n", bmp_file);
exit(1);
}
// BMPファイルヘッダの書き込み
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);
// BMPファイルのINFOヘッダの書き込み
fwrite(&bmpih, sizeof(BITMAPINFOHEADER), 1, fbmp);
// bmp_dataの書き込み
for (i=0; i<VERTICAL_LINES; i++) {
for (j=0; j<HORIZONTAL_PIXEL; j++) {
fputc((int)bmp_data[i][j^1].blue, fbmp);
fputc((int)bmp_data[i][j^1].green, fbmp);
fputc((int)bmp_data[i][j^1].red, fbmp);
}
}
fclose(fbmp);
for(i=0; i<VERTICAL_LINES; i++){
free(bmp_data[i]);
}
free(bmp_data);
munmap((void *)frame_buffer, 0x1000000);
return 0;
}
//
// bmpheader.h
// 2014/11/24
//
// reference : http://www.kk.iij4u.or.jp/~kondo/bmp/
//
#include <stdio.h>
// BITMAPFILEHEADER 14bytes
typedef struct tagBITMAPFILEHEADER {
unsigned short bfType;
unsigned long bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned long bfOffBits;
} BITMAPFILEHEADER;
// BITMAPINFOHEADER 40bytes
typedef struct tagBITMAPINFOHEADER{
unsigned long biSize;
long biWidth;
long biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned long biCompression;
unsigned long biSizeImage;
long biXPixPerMeter;
long biYPixPerMeter;
unsigned long biClrUsed;
unsigned long biClrImporant;
} BITMAPINFOHEADER;
typedef struct BMP24bitsFORMAT {
unsigned char blue;
unsigned char green;
unsigned char red;
} BMP24FORMAT;
//
// cam_capture.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 fd1;
volatile unsigned *mt9d111_axi_lites;
// mt9d111 interface AXI4 Lite Slave (UIO1)
fd1 = open("/dev/uio1", O_RDWR); // mt9d111 interface AXI4 Lite Slave
if (fd1 < 1){
fprintf(stderr, "/dev/uio1 open error\n");
exit(-1);
}
mt9d111_axi_lites = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd1, 0);
if (!mt9d111_axi_lites){
fprintf(stderr, "mt9d111_axi_lites mmap error\n");
exit(-1);
}
mt9d111_axi_lites[1] = 3;
munmap((void *)mt9d111_axi_lites, 0x10000);
}
//
// cam_on.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 fd1;
volatile unsigned *mt9d111_axi_lites;
// mt9d111 interface AXI4 Lite Slave (UIO1)
fd1 = open("/dev/uio1", O_RDWR); // mt9d111 interface AXI4 Lite Slave
if (fd1 < 1){
fprintf(stderr, "/dev/uio1 open error\n");
exit(-1);
}
mt9d111_axi_lites = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd1, 0);
if (!mt9d111_axi_lites){
fprintf(stderr, "mt9d111_axi_lites mmap error\n");
exit(-1);
}
mt9d111_axi_lites[1] = 0;
munmap((void *)mt9d111_axi_lites, 0x10000);
}
// mt9d111_axi_lite_slave.v
// mt9d111_inf_axi_master のAXI Lite Slave モジュール。Frame Buffer のスタートアドレス・レジスタを持つ。
//
// 2014/11/08 : one_shot_reg を実装。
// オフセット0番地: フレーム・バッファの先頭アドレス(fb_start_address)
// オフセット4番地: 0 ビット目が 0 の時動画、0 ビット目に 1 の時に、ワンショットで取得した1フレームのカメラ画像を表示(one_shot_reg)
// 1 ビット目に 1 を Write した時に、ワンショットで1フレームの画像をフレーム・バッファに保存
// 2014/11/11 : init_done を追加
//
`default_nettype none
module mt9d111_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,
parameter integer ONE_SHOT_PULSE_LENGTH = 20 // 1ショットパルスの長さのAXI Lite Slave ACLKのクロック数をセット
)(
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 reg [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, // fb_start_address に書き込まれた
output wire one_shot_state, // 1フレーム分取り込んだカメラ画像を保持する
output reg one_shot_trigger // 1フレーム分のカメラ画像取り込みのトリガー、1クロックパルス
);
// RESP の値の定義
parameter RESP_OKAY = 2'b00;
parameter RESP_EXOKAY = 2'b01;
parameter RESP_SLVERR = 2'b10;
parameter RESP_DECERR = 2'b11;
parameter [1:0] 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;
reg [31:0] one_shot_reg;
parameter [1:0] IDLE_TSM = 2'b00, // for one_shot_tsm
WAIT_ONE_SHOT = 2'b01,
ONE_SHOT_TRIG = 2'b11;
reg [1:0] one_shot_tsm;
integer one_shot_counter;
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) begin
init_done <= 1'b0;
fb_start_addr_reg <= C_DISPLAY_START_ADDRESS;
end else begin
if (s_axi_lite_wvalid==1'b1 && s_axi_lite_awaddr[2]==1'b0) begin
init_done <= 1'b1;
fb_start_addr_reg <= s_axi_lite_wdata;
end
end
end
assign fb_start_address = fb_start_addr_reg;
// one_shot_reg
always @(posedge aclk) begin
if (reset)
one_shot_reg <= 32'd0; // default is continuous display mode
else
if (s_axi_lite_wvalid==1'b1 && s_axi_lite_awaddr[2]==1'b1)
one_shot_reg <= s_axi_lite_wdata;
end
assign one_shot_state = one_shot_reg[0];
// one_shot_tsm(State Machine for one_shot_trgger)
always @(posedge aclk) begin
if (reset) begin
one_shot_tsm <= IDLE_TSM;
one_shot_trigger <= 1'b0;
end else begin
case (one_shot_tsm)
IDLE_TSM :
if (s_axi_lite_awvalid & awready & s_axi_lite_awaddr[2]) begin // one_shot_reg address
if (s_axi_lite_wvalid) begin // s_axi_wready is always 1
if (s_axi_lite_wdata[1]) begin // one_shot was triggered
one_shot_tsm <= ONE_SHOT_TRIG;
one_shot_trigger <= 1'b1;
end else begin // is not trigger
one_shot_tsm <= IDLE_TSM;
one_shot_trigger <= 1'b0;
end
end else begin // s_axi_lite_wvalid is not asserted
one_shot_tsm <= WAIT_ONE_SHOT;
one_shot_trigger <= 1'b0;
end
end
WAIT_ONE_SHOT :
if (s_axi_lite_wvalid) begin // s_axi_wready is always 1
if (s_axi_lite_wdata[1]) begin // one_shot was triggered
one_shot_tsm <= ONE_SHOT_TRIG;
one_shot_trigger <= 1'b1;
end else begin // is not trigger
one_shot_tsm <= IDLE_TSM;
one_shot_trigger <= 1'b0;
end
end
ONE_SHOT_TRIG : begin
if (one_shot_counter == 0) begin
one_shot_tsm <= IDLE_TSM;
one_shot_trigger <= 1'b0;
end
end
endcase
end
end
// one shot pulse length counter
always @(posedge aclk) begin
if (reset) begin
one_shot_counter <= ONE_SHOT_PULSE_LENGTH;
end else if (one_shot_tsm == ONE_SHOT_TRIG) begin
one_shot_counter <= one_shot_counter - 1;
end else begin
one_shot_counter <= ONE_SHOT_PULSE_LENGTH;
end
end
// s_axi_lite_rdata
always @(posedge aclk) begin
if (reset) begin
s_axi_lite_rdata <= 0;
end else if (s_axi_lite_arvalid) begin
case (s_axi_lite_araddr[2])
1'b0 : s_axi_lite_rdata <= fb_start_addr_reg;
1'b1 : s_axi_lite_rdata <= one_shot_reg;
endcase
end
end
endmodule
`default_nettype wire
// MT9D111カメラコントローラ
// mt9d111_cam_cont.v
// 2012/12/26
//
// 2014/11/07 : fb_start_address を追加。レジスタに設定された値をスタートアドレスとして参照。
// 2014/11/08 : one_shot_state, one_shot_trigger の入力ポートを追加
`default_nettype none
module mt9d111_cam_cont # (
parameter integer UPSIDE_DOWN = 0 // 1 = 上下反転、0 = 正常
)(
input wire aclk,
input wire areset,
input wire pclk,
input wire preset,
input wire pclk_from_pll,
output wire xclk,
input wire line_valid,
input wire frame_valid,
input wire [7:0] cam_data,
output wire standby,
output wire [31:0] paddr,
input wire pfifo_rd_en,
output wire [63:0] pfifo_dout,
output wire pfifo_empty,
output wire pfifo_almost_empty,
output wire [9:0] pfifo_rd_data_count,
output wire pfifo_overflow,
output wire pfifo_underflow,
input wire [31:0] fb_start_address,
input wire one_shot_state, // 1フレーム分取り込んだカメラ画像を保持する
input wire one_shot_trigger // 1フレーム分のカメラ画像取り込みのトリガー、1クロックパルス
);
`include "./disp_timing_parameters.vh"
// Frame Buffer End Address
reg line_valid_1d;
reg frame_valid_1d;
reg [7:0] cam_data_1d;
reg line_valid_1d_odd;
reg line_v_1d_odd_1d;
reg [63:0] rgb565;
wire pfifo_full, pfifo_almost_full;
reg frame_valid_1d_aclk_1d, frame_valid_1d_aclk_2d;
parameter [1:0] IDLE_ADDR_RST = 2'b00,
ADDR_RST = 2'b01,
ADDR_RST_HOLD = 2'b11;
reg [1:0] addr_rst_cs;
reg [31:0] paddr_reg;
reg rgb565_2nd;
parameter [2:0] IDLE_OS = 3'b000,
WAIT_FRAME_VALID_END = 3'b001,
HOLD_PICTURE = 3'b011,
WAIT_FRAME_VALID_LOW = 3'b010,
WAIT_FRAME_VALID_HIGH = 3'b110;
reg [2:0] one_shot_sm;
reg frame_valid_1d_oh;
reg ost_1d, ost_2d, ost_3d, ost_4d;
reg one_shot_tig_pclk;
assign standby = 1'b0;
// MT9D111 へのクロックを出力 (xclk)
ODDR #(
.DDR_CLK_EDGE("SAME_EDGE"), // "OPPOSITE_EDGE" or "SAME_EDGE"
.INIT(1'b0), // Initial value of Q: 1'b0 or 1'b1
.SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC"
) ODDR_inst (
.Q(xclk), // 1-bit DDR output
.C(pclk_from_pll), // 1-bit clock input
.CE(1'b1), // 1-bit clock enable input
.D1(1'b1), // 1-bit data input (positive edge)
.D2(1'b0), // 1-bit data input (negative edge)
.R(1'b0), // 1-bit reset
.S(1'b0) // 1-bit set
);
// 入力信号を一旦ラッチする
always @(posedge pclk) begin
if (preset) begin
line_valid_1d <= 1'b0;
frame_valid_1d <= 1'b0;
cam_data_1d <= 8'd0;
end else begin
line_valid_1d <= line_valid;
frame_valid_1d <= frame_valid;
cam_data_1d <= cam_data;
end
end
// one_shot_trigger はAXIバスのaclkで生成されているので、pclkで動作するステートマシンでは、本当にone shotでは取れない
// よって、one shotと言ってもある程度の幅を用意してある。pclk の幅のone shot pulse を作る必要がある
always @(posedge pclk) begin // one_shot_trigger を pclk で同期化
if (preset) begin
ost_1d <= 1'b0;
ost_2d <= 1'b0;
ost_3d <= 1'b0;
ost_4d <= 1'b0;
end else begin
ost_1d <= one_shot_trigger;
ost_2d <= ost_1d;
ost_3d <= ost_2d;
ost_4d <= ost_3d;
end
end
// pclk 幅の one shot pulse を生成
always @(posedge pclk) begin
if (preset) begin
one_shot_tig_pclk <= 1'b0;
end else if (ost_3d==1'b1 && ost_4d==1'b0) begin // rising edge
one_shot_tig_pclk <= 1'b1;
end else begin
one_shot_tig_pclk <= 1'b0;
end
end
// one shot state machine
// frame_valid_1d_oh を生成する
always @(posedge pclk) begin
if (preset) begin
one_shot_sm <= IDLE_OS;
frame_valid_1d_oh <= frame_valid_1d;
end else begin
case (one_shot_sm)
IDLE_OS : begin
frame_valid_1d_oh <= frame_valid_1d;
if (one_shot_state) begin
one_shot_sm <= WAIT_FRAME_VALID_END;
end
end
WAIT_FRAME_VALID_END : begin
frame_valid_1d_oh <= frame_valid_1d;
if (!frame_valid_1d) begin
one_shot_sm <= HOLD_PICTURE;
end
end
HOLD_PICTURE : begin
frame_valid_1d_oh <= 1'b0;
if (one_shot_tig_pclk) begin
one_shot_sm <= WAIT_FRAME_VALID_LOW;
end else if (~one_shot_state & ~frame_valid_1d) begin
one_shot_sm <= IDLE_OS;
end
end
WAIT_FRAME_VALID_LOW : begin
frame_valid_1d_oh <= 1'b0;
if (!frame_valid_1d) begin
one_shot_sm <= WAIT_FRAME_VALID_HIGH;
end
end
WAIT_FRAME_VALID_HIGH : begin
frame_valid_1d_oh <= frame_valid_1d;
if (frame_valid_1d) begin
one_shot_sm <= WAIT_FRAME_VALID_END;
end
end
endcase
end
end
// frame_valid_1d_oh をaclk でラッチする
always @(posedge aclk) begin
if (areset) begin
frame_valid_1d_aclk_1d <= 1'b0;
frame_valid_1d_aclk_2d <= 1'b0;
end else begin
frame_valid_1d_aclk_1d <= frame_valid_1d_oh;
frame_valid_1d_aclk_2d <= frame_valid_1d_aclk_1d;
end
end
// line_valid_1d が偶数か奇数かをカウント
always @(posedge pclk) begin
if (preset)
line_valid_1d_odd <= 1'b0;
else begin
if (!frame_valid_1d_oh)
line_valid_1d_odd <= 1'b0;
else if (line_valid_1d)
line_valid_1d_odd <= ~line_valid_1d_odd;
else
line_valid_1d_odd <= 1'b0;
end
end
// rgb565でラッチしているので、line_valid_1d_odd を1クロック遅延する
always @(posedge pclk) begin
if (preset)
line_v_1d_odd_1d <= 1'b0;
else
line_v_1d_odd_1d <= line_valid_1d_odd;
end
// 2番めのRGB565を示す。64ビット長のFIFOに入れるのに2ピクセル集めてから非同期FIFOにWriteする
always @(posedge pclk) begin
if (preset)
rgb565_2nd <= 1'b0;
else begin
if (line_valid_1d_odd)
rgb565_2nd <= ~rgb565_2nd;
end
end
// addressの生成
always @(posedge aclk) begin
if (areset) begin
if (UPSIDE_DOWN==0) // 正常、それ以外は上下反転
paddr_reg <= fb_start_address;
else // 上下反転
paddr_reg <= fb_start_address + (H_ACTIVE_VIDEO * V_ACTIVE_VIDEO)*4 - 8;
end else begin
if (pfifo_rd_en) begin
if (UPSIDE_DOWN==0) // 正常
paddr_reg <= paddr_reg + 32'd8;
else // 上下反転
paddr_reg <= paddr_reg - 32'd8;
end else if (addr_rst_cs==ADDR_RST) begin // frame_valid が0になって、pfifoにデータが無くなった時にアドレスをクリア
if (UPSIDE_DOWN==0) // 正常、それ以外は上下反転
paddr_reg <= fb_start_address;
else // 上下反転
paddr_reg <= fb_start_address + (H_ACTIVE_VIDEO * V_ACTIVE_VIDEO)*4 - 8;
end
end
end
assign paddr = paddr_reg;
// address をリセットするためのステートマシン
always @(posedge aclk) begin
if (areset)
addr_rst_cs <= IDLE_ADDR_RST;
else begin
case (addr_rst_cs)
IDLE_ADDR_RST :
if (~frame_valid_1d_aclk_2d & pfifo_empty)
addr_rst_cs <= ADDR_RST;
ADDR_RST :
addr_rst_cs <= ADDR_RST_HOLD;
ADDR_RST_HOLD :
if (frame_valid_1d_aclk_2d)
addr_rst_cs <= IDLE_ADDR_RST;
endcase
end
end
// RGB565 のデータを保存する。正常と上下反転ではバイト配列が異なる
always @(posedge pclk) begin
if (preset)
rgb565 <= 64'd0;
else begin
if (UPSIDE_DOWN==0) begin // 正常、それ以外は上下反転
case ({rgb565_2nd, line_valid_1d_odd})
2'b00 : // 1番目
rgb565[63:45] <= {8'd0, cam_data_1d[7:3], 3'b000, cam_data_1d[2:0]}; // cam_data_1d = R7 R6 R5 R4 R3 G7 G6 G5
2'b01 : // 2番目
rgb565[44:32] <= {cam_data_1d[7:5], 2'b00, cam_data_1d[4:0], 3'b000}; // cam_data_1d = G4 G3 G2 B7 B6 B5 B4 B3
2'b10 : // 3番目
rgb565[31:13] <= {8'd0, cam_data_1d[7:3], 3'b000, cam_data_1d[2:0]}; // cam_data_1d = R7 R6 R5 R4 R3 G7 G6 G5
2'b11 : // 4番目
rgb565[12:0] <= {cam_data_1d[7:5], 2'b00, cam_data_1d[4:0], 3'b000}; // cam_data_1d = G4 G3 G2 B7 B6 B5 B4 B3
endcase
end else begin // 上下反転
case ({rgb565_2nd, line_valid_1d_odd})
2'b00 : // 1番目
rgb565[31:13] <= {8'd0, cam_data_1d[7:3], 3'b000, cam_data_1d[2:0]}; // cam_data_1d = R7 R6 R5 R4 R3 G7 G6 G5
2'b01 : // 2番目
rgb565[12:0] <= {cam_data_1d[7:5], 2'b00, cam_data_1d[4:0], 3'b000}; // cam_data_1d = G4 G3 G2 B7 B6 B5 B4 B3
2'b10 : // 3番目
rgb565[63:45] <= {8'd0, cam_data_1d[7:3], 3'b000, cam_data_1d[2:0]}; // cam_data_1d = R7 R6 R5 R4 R3 G7 G6 G5
2'b11 : // 4番目
rgb565[44:32] <= {cam_data_1d[7:5], 2'b00, cam_data_1d[4:0], 3'b000}; // cam_data_1d = G4 G3 G2 B7 B6 B5 B4 B3
endcase
end
end
end
// pixel FIFO をインスタンスする
pixel_fifo pfifo (
.rst(areset), // input rst
.wr_clk(pclk), // input wr_clk
.rd_clk(aclk), // input rd_clk
.din(rgb565), // input [63 : 0] din
.wr_en(line_v_1d_odd_1d & ~rgb565_2nd), // input wr_en, 2つのピクセルが揃うには4クロック掛かる
.rd_en(pfifo_rd_en), // input rd_en
.dout(pfifo_dout), // output [63 : 0] dout
.full(pfifo_full), // output full
.almost_full(pfifo_almost_full), // output almost_full
.overflow(pfifo_overflow), // output overflow
.empty(pfifo_empty), // output empty
.almost_empty(pfifo_almost_empty), // output almost_empty
.underflow(pfifo_underflow), // output underflow
.rd_data_count(pfifo_rd_data_count) // output [9 : 0] rd_data_count
);
endmodule
`default_nettype wire
//
// cam_disp_uio.c
// Created on: 2014/11/15
// Author: Masaaki
//
#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 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_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()
{
int i, j, k;
int fd0, fd1, fd2, fd3;
volatile unsigned *bmdc_axi_lites;
volatile unsigned *mt9d111_axi_lites;
volatile unsigned *mt9d111_i2c_axi_lites;
volatile unsigned *frame_buffer;
// Bitmap Display Controller AXI4 Lite Slave (UIO0)
fd0 = open("/dev/uio0", O_RDWR); // bitmap_display_controller axi4 lite
if (fd0 < 1){
fprintf(stderr, "/dev/uio0 open error\n");
exit(-1);
}
bmdc_axi_lites = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd0, 0);
if (!bmdc_axi_lites){
fprintf(stderr, "bmdc_axi_lites mmap error\n");
exit(-1);
}
bmdc_axi_lites[0] = VIDEO_BUFFER_START_ADDRESS; // Bitmap Display Controller start
// mt9d111 interface AXI4 Lite Slave (UIO1)
fd1 = open("/dev/uio1", O_RDWR); // mt9d111 interface AXI4 Lite Slave
if (fd1 < 1){
fprintf(stderr, "/dev/uio1 open error\n");
exit(-1);
}
mt9d111_axi_lites = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd1, 0);
if (!mt9d111_axi_lites){
fprintf(stderr, "mt9d111_axi_lites mmap error\n");
exit(-1);
}
mt9d111_axi_lites[0] = VIDEO_BUFFER_START_ADDRESS; // Bitmap Display Controller start
// mt9d111 i2c AXI4 Lite Slave (UIO2)
fd2 = open("/dev/uio2", O_RDWR); // mt9d111 i2c AXI4 Lite Slave
if (fd2 < 1){
fprintf(stderr, "/dev/uio2 open error\n");
exit(-1);
}
mt9d111_i2c_axi_lites = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd2, 0);
if (!mt9d111_i2c_axi_lites){
fprintf(stderr, "mt9d111_i2c_axi_lites mmap error\n");
exit(-1);
}
// Frame Buffer UIO3
fd3 = open("/dev/uio3", O_RDWR); // Frame Buffer
if (fd3 < 1){
fprintf(stderr, "/dev/uio3 open error\n");
exit(-1);
}
frame_buffer = (volatile unsigned *)mmap(NULL, 0x1000000, PROT_READ|PROT_WRITE, MAP_SHARED, fd3, 0);
if (!frame_buffer){
fprintf(stderr, "frame_buffer mmap error\n");
exit(-1);
}
// CMOS Camera initialize, MT9D111
cam_i2c_init(mt9d111_i2c_axi_lites);
cam_i2c_write(mt9d111_i2c_axi_lites, 0xba, 0xf0, 0x1); // Changed regster map to IFP page 1
cam_i2c_write(mt9d111_i2c_axi_lites, 0xba, 0x97, 0x20); // RGB Mode, RGB565
mt9d111_axi_lites[1] = 0;
munmap((void *)bmdc_axi_lites, 0x10000);
munmap((void *)mt9d111_axi_lites, 0x10000);
munmap((void *)mt9d111_i2c_axi_lites, 0x10000);
munmap((void *)frame_buffer, 0x1000000);
return(0);
}
vim-gtk 2:7.4.052-1ubuntu3
vim-athena 2:7.4.052-1ubuntu3
vim-gnome 2:7.4.052-1ubuntu3
bitmap_display_cntrler_axim@43c00000 {
compatible = "generic-uio";
reg = < 0x43c00000 0x10000 >;
};
mt9d111_inf_axim@0x43c10000 {
compatible = "generic-uio";
reg = < 0x43c10000 0x10000 >;
};
mt9d111_axi_iic@0x41600000 {
compatible = "generic-uio";
reg = < 0x41600000 0x10000>;
};
frame_buffer_bmdc@0x17800000 {
compatible = "generic-uio";
reg = < 0x17800000 0x1000000>;
};
”ZYBO用ビットマップ・ディスプレイ・コントローラの作製1(ブロック・デザイン1)”
”ZYBO用ビットマップ・ディスプレイ・コントローラの作製2(ブロック・デザイン2)”
”ZYBO用ビットマップ・ディスプレイ・コントローラの作製3(ブロック・デザイン3)”
はもう実装されていたので、それを使用した。オフセット0番地: フレーム・バッファの先頭アドレス
を実装した。オフセット4番地: 0 ビット目が 0 の時動画、0 ビット目に 1 の時に、ワンショットで取得した1フレームのカメラ画像を表示
1 ビット目に 1 を Write した時に、ワンショットで1フレームの画像をフレーム・バッファに保存
// one_shot_reg
always @(posedge aclk) begin
if (reset)
one_shot_reg <= 32'd0; // default is continuous display mode
else
if (s_axi_lite_wvalid==1'b1 && s_axi_lite_awaddr[2]==1'b1)
one_shot_reg <= s_axi_lite_wdata;
end
assign one_shot_state = one_shot_reg[0];
// one_shot_tsm(State Machine for one_shot_trgger)
always @(posedge aclk) begin
if (reset) begin
one_shot_tsm <= IDLE_TSM;
one_shot_trigger <= 1'b0;
end else begin
case (one_shot_tsm)
IDLE_TSM :
if (s_axi_lite_awvalid & awready & s_axi_lite_awaddr[2]) begin // one_shot_reg address
if (s_axi_lite_wvalid) begin // s_axi_wready is always 1
if (s_axi_lite_wdata[1]) begin // one_shot was triggered
one_shot_tsm <= ONE_SHOT_TRIG;
one_shot_trigger <= 1'b1;
end else begin // is not trigger
one_shot_tsm <= IDLE_TSM;
one_shot_trigger <= 1'b0;
end
end else begin // s_axi_lite_wvalid is not asserted
one_shot_tsm <= WAIT_ONE_SHOT;
one_shot_trigger <= 1'b0;
end
end
WAIT_ONE_SHOT :
if (s_axi_lite_wvalid) begin // s_axi_wready is always 1
if (s_axi_lite_wdata[1]) begin // one_shot was triggered
one_shot_tsm <= ONE_SHOT_TRIG;
one_shot_trigger <= 1'b1;
end else begin // is not trigger
one_shot_tsm <= IDLE_TSM;
one_shot_trigger <= 1'b0;
end
end
ONE_SHOT_TRIG : begin
one_shot_tsm <= ONE_SHOT_HOLD_OFF;
one_shot_trigger <= 1'b0;
end
ONE_SHOT_HOLD_OFF :
if (!awready) begin
one_shot_tsm <= IDLE_TSM;
one_shot_trigger <= 1'b0;
end
endcase
end
end
(2014/11/12:追記 上の2つの Verilog HDL コードにはバグがありました。詳しくは、”ZYBO用の Linaro Ubuntu のPL部にカメラ・コントローラを搭載する10(デバック2)”を参照して下さい)
// one shot state machine
// frame_valid_1d_oh を生成する
always @(posedge pclk) begin
if (preset) begin
one_shot_sm <= IDLE_OS;
frame_valid_1d_oh <= frame_valid_1d;
end else begin
case (one_shot_sm)
IDLE_OS :
if (one_shot_state) begin
one_shot_sm <= WAIT_FRAME_VALID_END;
frame_valid_1d_oh <= frame_valid_1d;
end
WAIT_FRAME_VALID_END :
if (!frame_valid_1d) begin
one_shot_sm <= HOLD_PICTURE;
frame_valid_1d_oh <= 1'b0;
end
HOLD_PICTURE :
if (one_shot_trigger) begin
one_shot_sm <= WAIT_FRAME_VALID_LOW;
frame_valid_1d_oh <= 1'b0;
end else if (~one_shot_state & ~frame_valid_1d) begin
one_shot_sm <= IDLE_OS;
frame_valid_1d_oh <= frame_valid_1d;
end
WAIT_FRAME_VALID_LOW :
if (!frame_valid_1d) begin
one_shot_sm <= WAIT_FRAME_VALID_HIGH;
frame_valid_1d_oh <= frame_valid_1d;
end
WAIT_FRAME_VALID_HIGH :
if (frame_valid_1d) begin
one_shot_sm <= WAIT_FRAME_VALID_END;
frame_valid_1d_oh <= frame_valid_1d;
end
endcase
end
end
// Add stimulus here
@(posedge ACLK); // 次のクロックへ
#DELAY;
AXI_MASTER_WADC1(32'h0000_0000, 32'h1200_0000);
@(posedge ACLK); // 次のクロックへ
#DELAY;
AXI_MASTER_RADC1(32'h0000_0000);
#DELAY;
@(posedge ACLK); // 次のクロックへ
#DELAY;
AXI_MASTER_WADC2(32'h0000_0004, 32'h0000_0001); // one_shot mode
@(posedge ACLK); // 次のクロックへ
#DELAY;
AXI_MASTER_RADC2(32'h0000_0004);
@(posedge ACLK); // 次のクロックへ
#DELAY;
AXI_MASTER_WADC2(32'h0000_0004, 32'h0000_0003); // one_shot trigger
@(posedge ACLK); // 次のクロックへ
#DELAY;
AXI_MASTER_RADC2(32'h0000_0004);
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
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
- | - | - | - | - | - | 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 | - | - | - | - | - | - |