Update latency tester

* Enable operation with all sources
* Measure strobe length on low-persistence displays
This commit is contained in:
marqs 2017-10-28 12:10:54 +03:00
parent 4ae3423acb
commit a24d6b0e3a
23 changed files with 1469 additions and 1299 deletions

View File

@ -238,7 +238,7 @@ set_global_assignment -name SIGNALTAP_FILE output_files/ossc_la.stp
set_global_assignment -name FITTER_EFFORT "AUTO FIT"
set_global_assignment -name SEED 6
set_global_assignment -name SEED 2

View File

@ -77,6 +77,9 @@ set_false_path -from [get_registers {scanconverter_inst|H_* scanconverter_inst|V
# Ignore paths from registers which are updated only at leading edge of hsync
set_false_path -from [get_registers {scanconverter:scanconverter_inst|line_idx scanconverter:scanconverter_inst|line_out_idx* scanconverter:scanconverter_inst|hmax*}]
# Ignore paths to latency tester sync regs
set_false_path -to [get_registers {lat_tester:lt0|mode_synced* lat_tester:lt0|VSYNC_in_* lat_tester:lt0|trigger_*}]
### JTAG Signal Constraints ###

View File

@ -17,8 +17,14 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
`define LT_STATE_IDLE 2'h0
`define LT_STATE_LAT_MEAS 2'h1
`define LT_STATE_STB_MEAS 2'h2
`define LT_STATE_FINISHED 2'h3
module lat_tester (
input clk27,
input pclk,
input active,
input armed,
input sensor,
@ -26,47 +32,76 @@ module lat_tester (
input VSYNC_in,
input [1:0] mode_in,
output reg [2:0] mode_synced,
output reg [15:0] result
output reg [15:0] lat_result,
output reg [11:0] stb_result,
output reg finished
);
reg VSYNC_in_L, VSYNC_in_LL, VSYNC_in_LLL;
reg running;
reg VSYNC_in_L, VSYNC_in_LL, trigger_L, trigger_LL;
reg [8:0] clk27_ctr;
reg [1:0] state;
always @(posedge clk27) begin
always @(posedge pclk) begin
VSYNC_in_L <= VSYNC_in;
VSYNC_in_LL <= VSYNC_in_L;
VSYNC_in_LLL <= VSYNC_in_LL;
end
always @(posedge clk27) begin
if (VSYNC_in_LLL && !VSYNC_in_LL)
always @(posedge pclk) begin
if (VSYNC_in_LL && !VSYNC_in_L)
mode_synced <= mode_in;
end
always @(posedge clk27) begin
if (!active) begin
running <= 0;
end else begin
if ((result==0) && (clk27_ctr==0) && armed && trigger) begin
running <= 1;
end else if (running && ((sensor==0) || (result==16'hffff))) begin
running <= 0;
end
end
trigger_L <= trigger;
trigger_LL <= trigger_L;
end
always @(posedge clk27) begin
if (!active || !armed) begin
result <= 0;
clk27_ctr <= 0;
end else if (running) begin
if (clk27_ctr == 270-1) begin
clk27_ctr <= 0;
result <= result + 1'b1;
end else begin
clk27_ctr <= clk27_ctr + 1'b1;
end
if (!active) begin
state <= `LT_STATE_IDLE;
end else begin
case (state)
default: begin //STATE_IDLE
finished <= 1'b0;
lat_result <= 0;
stb_result <= 0;
clk27_ctr <= 0;
if (armed && trigger_LL)
state <= `LT_STATE_LAT_MEAS;
end
`LT_STATE_LAT_MEAS: begin
if (sensor==0) begin
state <= `LT_STATE_STB_MEAS;
clk27_ctr <= 0;
end else if (lat_result==16'hffff) begin
state <= `LT_STATE_FINISHED;
end else begin
if (clk27_ctr == 270-1) begin
clk27_ctr <= 0;
lat_result <= lat_result + 1'b1;
end else begin
clk27_ctr <= clk27_ctr + 1'b1;
end
end
end
`LT_STATE_STB_MEAS: begin
if (((sensor==1) && (stb_result >= 12'd100)) || (stb_result == 12'hfff)) begin
state <= `LT_STATE_FINISHED;
end else begin
if (clk27_ctr == 270-1) begin
clk27_ctr <= 0;
stb_result <= stb_result + 1'b1;
end else begin
clk27_ctr <= clk27_ctr + 1'b1;
end
end
end
`LT_STATE_FINISHED: begin
finished <= 1'b1;
if (!armed)
state <= `LT_STATE_IDLE;
end
endcase
end
end

26
rtl/lat_tester_includes.v Normal file
View File

@ -0,0 +1,26 @@
//
// Copyright (C) 2017 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// This file is part of Open Source Scan Converter project.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
`define LT_POS_NONE 2'b00
`define LT_POS_TOPLEFT 2'b01
`define LT_POS_CENTER 2'b10
`define LT_POS_BOTTOMRIGHT 2'b11
`define LT_WIDTH_DIV 8
`define LT_HEIGHT_DIV 8

View File

@ -54,7 +54,7 @@ module ossc (
inout [3:0] SD_DAT
);
wire [7:0] sys_ctrl;
wire [15:0] sys_ctrl;
wire h_unstable;
wire [1:0] pclk_lock;
wire [1:0] pll_lock_lost;
@ -87,11 +87,13 @@ reg HSYNC_in_L, VSYNC_in_L, FID_in_L;
reg [1:0] btn_L, btn_LL;
reg ir_rx_L, ir_rx_LL, HDMI_TX_INT_N_L, HDMI_TX_INT_N_LL, HDMI_TX_MODE_L, HDMI_TX_MODE_LL;
wire lt_active = extra_info[31];
wire lt_armed = extra_info[30];
wire [1:0] lt_mode = extra_info[29:28];
wire lt_active = sys_ctrl[15];
wire lt_armed = sys_ctrl[14];
wire [1:0] lt_mode = sys_ctrl[13:12];
wire [1:0] lt_mode_synced;
wire [15:0] lt_result;
wire [15:0] lt_lat_result;
wire [11:0] lt_stb_result;
wire lt_finished;
// Latch inputs from TVP7002 (synchronized to PCLK_in)
always @(posedge PCLK_in or negedge reset_n)
@ -200,7 +202,7 @@ sys sys_inst(
.pio_4_h_info2_out_export (h_info2),
.pio_5_v_info_out_export (v_info),
.pio_6_extra_info_out_export (extra_info),
.pio_7_lt_results_in_export ({16'h0000, lt_result})
.pio_7_lt_results_in_export ({lt_finished, 3'h0, lt_stb_result, lt_lat_result})
);
scanconverter scanconverter_inst (
@ -229,7 +231,9 @@ scanconverter scanconverter_inst (
.pclk_lock (pclk_lock),
.pll_lock_lost (pll_lock_lost),
.vmax (vmax),
.vmax_tvp (vmax_tvp)
.vmax_tvp (vmax_tvp),
.lt_active (lt_active),
.lt_mode (lt_mode_synced)
);
ir_rcv ir0 (
@ -243,14 +247,17 @@ ir_rcv ir0 (
lat_tester lt0 (
.clk27 (clk27),
.pclk (HDMI_TX_PCLK),
.active (lt_active),
.armed (lt_armed),
.sensor (btn_LL[1]),
.trigger (HDMI_TX_DE & HDMI_TX_RD[0]),
.trigger (HDMI_TX_DE & HDMI_TX_GD[0]),
.VSYNC_in (HDMI_TX_VS),
.mode_in (extra_info[29:28]),
.mode_in (lt_mode),
.mode_synced (lt_mode_synced),
.result (lt_result)
.lat_result (lt_lat_result),
.stb_result (lt_stb_result),
.finished (lt_finished)
);
`ifdef VIDEOGEN

View File

@ -17,6 +17,8 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
`include "lat_tester_includes.v"
`define TRUE 1'b1
`define FALSE 1'b0
`define HI 1'b1
@ -80,7 +82,9 @@ module scanconverter (
output [1:0] pclk_lock,
output [1:0] pll_lock_lost,
output reg [10:0] vmax,
output reg [10:0] vmax_tvp
output reg [10:0] vmax_tvp,
input lt_active,
input [1:0] lt_mode
);
//clock-related signals
@ -124,7 +128,8 @@ reg line_idx;
reg [1:0] line_out_idx_2x, line_out_idx_3x, line_out_idx_4x;
reg [2:0] line_out_idx_5x;
reg [23:0] warn_h_unstable, warn_pll_lock_lost, warn_pll_lock_lost_3x;
reg mask_enable_pp1, mask_enable_pp2, mask_enable_pp3, mask_enable_pp4, mask_enable_pp5, mask_enable_pp6;
reg border_enable_pp1, border_enable_pp2, border_enable_pp3, border_enable_pp4, border_enable_pp5, border_enable_pp6;
reg lt_box_enable_pp1, lt_box_enable_pp2, lt_box_enable_pp3, lt_box_enable_pp4, lt_box_enable_pp5, lt_box_enable_pp6;
wire rlpf_trigger_act;
reg rlpf_trigger_pp1;
@ -191,19 +196,51 @@ function [7:0] apply_scanlines;
end
endfunction
//Border masking
//LT box / border generation
function [7:0] apply_mask;
input enable;
input lt_active;
input lt_box_enable;
input border_enable;
input [7:0] data;
input [3:0] brightness;
begin
if (enable)
if (lt_active)
apply_mask = lt_box_enable ? 8'hff : 8'h00;
else if (border_enable)
apply_mask = {brightness, 4'h0};
else
apply_mask = data;
end
endfunction
//LT position select
function [7:0] apply_lt_box;
input [1:0] mode;
input [11:0] h_cnt;
input [10:0] v_cnt;
input [9:0] h_start;
input [6:0] v_start;
input [10:0] h_active;
input [10:0] v_active;
begin
case (mode)
default: begin
apply_lt_box = 0;
end
`LT_POS_TOPLEFT: begin
apply_lt_box = ((h_cnt < (h_start+(h_active/`LT_WIDTH_DIV))) && (v_cnt < (v_start+(v_active/`LT_HEIGHT_DIV)))) ? 1 : 0;
end
`LT_POS_CENTER: begin
apply_lt_box = ((h_cnt >= (h_start+(h_active/2)-(h_active/(`LT_WIDTH_DIV*2)))) && (h_cnt < (h_start+(h_active/2)+(h_active/(`LT_WIDTH_DIV*2)))) && (v_cnt >= (v_start+(v_active/2)-(v_active/(`LT_HEIGHT_DIV*2)))) && (v_cnt < (v_start+(v_active/2)+(v_active/(`LT_HEIGHT_DIV*2))))) ? 1 : 0;
end
`LT_POS_BOTTOMRIGHT: begin
apply_lt_box = ((h_cnt >= (h_start+h_active-(h_active/`LT_WIDTH_DIV))) && (v_cnt >= (v_start+v_active-(v_active/`LT_HEIGHT_DIV)))) ? 1 : 0;
end
endcase
end
endfunction
//Reverse LPF
function [7:0] apply_reverse_lpf;
input enable;
input [7:0] data;
@ -402,15 +439,17 @@ always @(posedge pclk_act)
begin
line_id_pp1 <= line_id_act;
col_id_pp1 <= col_id_act;
mask_enable_pp1 <= ((hcnt_act < H_AVIDSTART+H_MASK) | (hcnt_act >= H_AVIDSTART+H_ACTIVE-H_MASK) | (vcnt_act < V_AVIDSTART+V_MASK) | (vcnt_act >= V_AVIDSTART+V_ACTIVE-V_MASK));
border_enable_pp1 <= ((hcnt_act < H_AVIDSTART+H_MASK) | (hcnt_act >= H_AVIDSTART+H_ACTIVE-H_MASK) | (vcnt_act < V_AVIDSTART+V_MASK) | (vcnt_act >= V_AVIDSTART+V_ACTIVE-V_MASK));
rlpf_trigger_pp1 <= rlpf_trigger_act;
lt_box_enable_pp1 <= apply_lt_box(lt_mode, hcnt_act, vcnt_act, H_AVIDSTART, V_AVIDSTART, H_ACTIVE, V_ACTIVE);
HSYNC_pp2 <= HSYNC_act;
VSYNC_pp2 <= VSYNC_act;
DE_pp2 <= DE_act;
line_id_pp2 <= line_id_pp1;
col_id_pp2 <= col_id_pp1;
mask_enable_pp2 <= mask_enable_pp1;
border_enable_pp2 <= border_enable_pp1;
lt_box_enable_pp2 <= lt_box_enable_pp1;
// Optimized modes repeat pixels. Save previous pixel only when linebuffer offset changes.
if (rlpf_trigger_pp1) begin
R_prev_pp2 <= R_act;
@ -418,7 +457,6 @@ begin
B_prev_pp2 <= B_act;
end
R_pp3 <= R_act;
G_pp3 <= G_act;
B_pp3 <= B_act;
@ -427,7 +465,8 @@ begin
DE_pp3 <= DE_pp2;
line_id_pp3 <= line_id_pp2;
col_id_pp3 <= col_id_pp2;
mask_enable_pp3 <= mask_enable_pp2;
border_enable_pp3 <= border_enable_pp2;
lt_box_enable_pp3 <= lt_box_enable_pp2;
R_prev_pp3 <= R_prev_pp2;
G_prev_pp3 <= G_prev_pp2;
B_prev_pp3 <= B_prev_pp2;
@ -444,7 +483,8 @@ begin
DE_pp4 <= DE_pp3;
line_id_pp4 <= line_id_pp3;
col_id_pp4 <= col_id_pp3;
mask_enable_pp4 <= mask_enable_pp3;
border_enable_pp4 <= border_enable_pp3;
lt_box_enable_pp4 <= lt_box_enable_pp3;
R_prev_pp4 <= R_prev_pp3;
G_prev_pp4 <= G_prev_pp3;
B_prev_pp4 <= B_prev_pp3;
@ -461,7 +501,8 @@ begin
DE_pp5 <= DE_pp4;
line_id_pp5 <= line_id_pp4;
col_id_pp5 <= col_id_pp4;
mask_enable_pp5 <= mask_enable_pp4;
border_enable_pp5 <= border_enable_pp4;
lt_box_enable_pp5 <= lt_box_enable_pp4;
R_pp6 <= apply_scanlines(V_SCANLINEMODE, R_pp5, X_SCANLINESTR, V_SCANLINEID, line_id_pp5, col_id_pp5, FID_1x);
G_pp6 <= apply_scanlines(V_SCANLINEMODE, G_pp5, X_SCANLINESTR, V_SCANLINEID, line_id_pp5, col_id_pp5, FID_1x);
@ -469,11 +510,12 @@ begin
HSYNC_pp6 <= HSYNC_pp5;
VSYNC_pp6 <= VSYNC_pp5;
DE_pp6 <= DE_pp5;
mask_enable_pp6 <= mask_enable_pp5;
border_enable_pp6 <= border_enable_pp5;
lt_box_enable_pp6 <= lt_box_enable_pp5;
R_out <= apply_mask(mask_enable_pp6, R_pp6, X_MASK_BR);
G_out <= apply_mask(mask_enable_pp6, G_pp6, X_MASK_BR);
B_out <= apply_mask(mask_enable_pp6, B_pp6, X_MASK_BR);
R_out <= apply_mask(lt_active, lt_box_enable_pp6, border_enable_pp6, R_pp6, X_MASK_BR);
G_out <= apply_mask(lt_active, lt_box_enable_pp6, border_enable_pp6, G_pp6, X_MASK_BR);
B_out <= apply_mask(lt_active, lt_box_enable_pp6, border_enable_pp6, B_pp6, X_MASK_BR);
HSYNC_out <= HSYNC_pp6;
VSYNC_out <= VSYNC_pp6;
DE_out <= DE_pp6;

View File

@ -17,12 +17,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
`define LT_POS_NONE 2'b00
`define LT_POS_TOPLEFT 2'b01
`define LT_POS_CENTER 2'b10
`define LT_POS_BOTTOMRIGHT 2'b11
`define LT_WIDTH 100
`define LT_HEIGHT 100
`include "lat_tester_includes.v"
module videogen (
input clk27,
@ -129,13 +124,13 @@ begin
V_gen <= 8'h00;
end
`LT_POS_TOPLEFT: begin
V_gen <= ((h_cnt < (X_START+`LT_WIDTH)) && (v_cnt < (Y_START+`LT_HEIGHT))) ? 8'hff : 8'h00;
V_gen <= ((h_cnt < (X_START+(H_ACTIVE/`LT_WIDTH_DIV))) && (v_cnt < (Y_START+(V_ACTIVE/`LT_HEIGHT_DIV)))) ? 8'hff : 8'h00;
end
`LT_POS_CENTER: begin
V_gen <= ((h_cnt >= (X_START+(H_ACTIVE/2)-(`LT_WIDTH/2))) && (h_cnt < (X_START+(H_ACTIVE/2)+(`LT_WIDTH/2))) && (v_cnt >= (Y_START+(V_ACTIVE/2)-(`LT_HEIGHT/2))) && (v_cnt < (Y_START+(V_ACTIVE/2)+(`LT_HEIGHT/2)))) ? 8'hff : 8'h00;
V_gen <= ((h_cnt >= (X_START+(H_ACTIVE/2)-(H_ACTIVE/(`LT_WIDTH_DIV*2)))) && (h_cnt < (X_START+(H_ACTIVE/2)+(H_ACTIVE/(`LT_WIDTH_DIV*2)))) && (v_cnt >= (Y_START+(V_ACTIVE/2)-(V_ACTIVE/(`LT_HEIGHT_DIV*2)))) && (v_cnt < (Y_START+(V_ACTIVE/2)+(V_ACTIVE/(`LT_HEIGHT_DIV*2))))) ? 8'hff : 8'h00;
end
`LT_POS_BOTTOMRIGHT: begin
V_gen <= ((h_cnt >= (X_START+H_ACTIVE-`LT_WIDTH)) && (v_cnt >= (Y_START+V_ACTIVE-`LT_HEIGHT))) ? 8'hff : 8'h00;
V_gen <= ((h_cnt >= (X_START+H_ACTIVE-(H_ACTIVE/`LT_WIDTH_DIV))) && (v_cnt >= (Y_START+V_ACTIVE-(V_ACTIVE/`LT_HEIGHT_DIV)))) ? 8'hff : 8'h00;
end
endcase
end else begin

File diff suppressed because it is too large Load Diff

View File

@ -19,12 +19,11 @@
#include <unistd.h>
#include <string.h>
#include "system.h"
#include "flash.h"
#include "lcd.h"
#include "ci_crc.h"
extern alt_epcq_controller_dev epcq_controller_0;
extern char menu_row1[LCD_ROW_LEN+1], menu_row2[LCD_ROW_LEN+1];
alt_epcq_controller_dev *epcq_controller_dev;
@ -34,7 +33,7 @@ int check_flash()
epcq_controller_dev = &epcq_controller_0;
if ((epcq_controller_dev == NULL) || !(epcq_controller_dev->is_epcs && (epcq_controller_dev->page_size == PAGESIZE)))
return -1;
return -FLASH_DETECT_ERROR;
printf("Flash size in bytes: %lu\nSector size: %lu (%lu pages)\nPage size: %lu\n",
epcq_controller_dev->size_in_bytes, epcq_controller_dev->sector_size, epcq_controller_dev->sector_size/epcq_controller_dev->page_size, epcq_controller_dev->page_size);
@ -48,7 +47,7 @@ int read_flash(alt_u32 offset, alt_u32 length, alt_u8 *dstbuf)
retval = alt_epcq_controller_read(&epcq_controller_dev->dev, offset, dstbuf, length);
if (retval != 0)
return -1;
return -FLASH_READ_ERROR;
for (i=0; i<length; i++)
dstbuf[i] = ALT_CI_NIOS_CUSTOM_INSTR_BITSWAP_0(dstbuf[i]) >> 24;
@ -65,11 +64,8 @@ int write_flash_page(alt_u8 *pagedata, alt_u32 length, alt_u32 pagenum)
retval = alt_epcq_controller_erase_block(&epcq_controller_dev->dev, pagenum*PAGESIZE);
if (retval != 0) {
strncpy(menu_row1, "Flash erase", LCD_ROW_LEN+1);
sniprintf(menu_row1, LCD_ROW_LEN+1, "error %d", retval);
menu_row2[0] = '\0';
printf("Flash erase error, sector %u\nRetval %d\n", (unsigned)(pagenum/PAGES_PER_SECTOR), retval);
return -200;
return -FLASH_ERASE_ERROR;
}
}
@ -80,13 +76,11 @@ int write_flash_page(alt_u8 *pagedata, alt_u32 length, alt_u32 pagenum)
retval = alt_epcq_controller_write_block(&epcq_controller_dev->dev, (pagenum/PAGES_PER_SECTOR)*PAGES_PER_SECTOR*PAGESIZE, pagenum*PAGESIZE, pagedata, length);
if (retval != 0) {
strncpy(menu_row1, "Flash write", LCD_ROW_LEN+1);
strncpy(menu_row2, "error", LCD_ROW_LEN+1);
printf("Flash write error, page %u\nRetval %d\n", (unsigned)pagenum, retval);
return -201;
return -FLASH_WRITE_ERROR;
}
return retval;
return 0;
}
int verify_flash(alt_u32 offset, alt_u32 length, alt_u32 golden_crc, alt_u8 *tmpbuf)
@ -99,16 +93,13 @@ int verify_flash(alt_u32 offset, alt_u32 length, alt_u32 golden_crc, alt_u8 *tmp
retval = read_flash(i, bytes_to_read, tmpbuf);
if (retval != 0)
return -202;
return retval;
crcval = crcCI(tmpbuf, bytes_to_read, (i==0));
}
if (crcval != golden_crc) {
sniprintf(menu_row1, LCD_ROW_LEN+1, "Flash verif fail");
menu_row2[0] = '\0';
return -203;
}
if (crcval != golden_crc)
return -FLASH_VERIFY_ERROR;
return 0;
}

View File

@ -32,6 +32,12 @@
#define USERDATA_OFFSET 0x100000
#define MAX_USERDATA_ENTRY 15 // 16 sectors for userdata
#define FLASH_DETECT_ERROR 200
#define FLASH_READ_ERROR 201
#define FLASH_ERASE_ERROR 202
#define FLASH_WRITE_ERROR 203
#define FLASH_VERIFY_ERROR 204
int check_flash();
int read_flash(alt_u32 offset, alt_u32 length, alt_u8 *dstbuf);

View File

@ -31,11 +31,8 @@ int check_sdcard(alt_u8 *databuf)
res = SD_Init(&sdcard_dev);
printf("SD det status: %u\n", res);
if (res) {
sniprintf(menu_row1, LCD_ROW_LEN+1, "No SD card det.");
menu_row2[0] = '\0';
return 1;
}
if (res != SD_OK)
return res;
return SD_Read(&sdcard_dev, databuf, 0, 0, 512);
}

View File

@ -49,7 +49,7 @@
#define SYNC_LOSS_THOLD -5
#define STATUS_TIMEOUT 10000
alt_u8 sys_ctrl;
alt_u16 sys_ctrl;
// Current mode
avmode_t cm;
@ -595,7 +595,7 @@ int init_hw()
// Reset hardware
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, AV_RESET_N|LCD_BL);
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x00);
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x0000);
IOWR_ALTERA_AVALON_PIO_DATA(PIO_3_BASE, 0x00000000);
IOWR_ALTERA_AVALON_PIO_DATA(PIO_5_BASE, 0x00000000);
usleep(10000);
@ -670,15 +670,22 @@ int init_hw()
return 0;
}
#ifdef DEBUG
int latency_test()
{
sniprintf(menu_row2, LCD_ROW_LEN+1, "Unavailable");
lcd_write_menu();
usleep(1000000);
return -1;
}
#else
int latency_test() {
alt_u32 base_val, btn_vec, btn_vec_prev=1;
alt_u32 lt_status, btn_vec, btn_vec_prev=1;
alt_u16 latency_ms_x100, stb_ms_x100;
alt_u8 position = lt_sel+1;
alt_u16 latency_x100ms;
base_val = IORD_ALTERA_AVALON_PIO_DATA(PIO_6_BASE) & 0xff;
base_val |= (1<<31);
IOWR_ALTERA_AVALON_PIO_DATA(PIO_6_BASE, base_val|(position<<28));
sys_ctrl |= LT_ACTIVE|(position<<LT_MODE_OFFS);
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, sys_ctrl);
sniprintf(menu_row2, LCD_ROW_LEN+1, "OK to init");
lcd_write_menu();
@ -687,31 +694,48 @@ int latency_test() {
if ((btn_vec_prev == 0) && (btn_vec != 0)) {
if (btn_vec == rc_keymap[RC_OK]) {
IOWR_ALTERA_AVALON_PIO_DATA(PIO_6_BASE, base_val);
sys_ctrl &= ~(3<<LT_MODE_OFFS);
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, sys_ctrl);
menu_row2[0] = 0;
lcd_write_menu();
usleep(200000);
IOWR_ALTERA_AVALON_PIO_DATA(PIO_6_BASE, base_val|(position<<28)|(1<<30));
while (IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & PB1_BIT) {}
latency_x100ms = IORD_ALTERA_AVALON_PIO_DATA(PIO_7_BASE) & 0xffff;
sniprintf(menu_row2, LCD_ROW_LEN+1, "lat: %u.%.2ums", latency_x100ms/100, latency_x100ms%100);
usleep(400000);
sys_ctrl |= LT_ARMED|(position<<LT_MODE_OFFS);
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, sys_ctrl);
//while (!((lt_status = IORD_ALTERA_AVALON_PIO_DATA(PIO_7_BASE)) & (1<<31))) {} //Hangs if sync is lost
SPI_Timer_On(1000);
while ((SPI_Timer_Status()==TRUE)) {
lt_status = IORD_ALTERA_AVALON_PIO_DATA(PIO_7_BASE);
if (lt_status & (1<<31))
break;
}
SPI_Timer_Off();
latency_ms_x100 = lt_status & 0xffff;
stb_ms_x100 = (lt_status >> 16) & 0xfff;
if ((latency_ms_x100 == 0) || (latency_ms_x100 == 0xffff))
sniprintf(menu_row2, LCD_ROW_LEN+1, "Timeout");
else if (stb_ms_x100 == 0xfff)
sniprintf(menu_row2, LCD_ROW_LEN+1, "%u.%.2ums", latency_ms_x100/100, latency_ms_x100%100);
else
sniprintf(menu_row2, LCD_ROW_LEN+1, "%u.%.2ums/%u.%.2ums", latency_ms_x100/100, latency_ms_x100%100, stb_ms_x100/100, stb_ms_x100%100);
lcd_write_menu();
} else if (btn_vec == rc_keymap[RC_BACK]) {
break;
}
IOWR_ALTERA_AVALON_PIO_DATA(PIO_6_BASE, base_val|(position<<28));
sys_ctrl &= ~LT_ARMED;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, sys_ctrl);
}
btn_vec_prev = btn_vec;
usleep(WAITLOOP_SLEEP_US);
}
base_val &= 0xff;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_6_BASE, base_val);
sys_ctrl &= ~LT_CTRL_MASK;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, sys_ctrl);
return 0;
}
#endif
// Enable chip outputs
void enable_outputs()

View File

@ -24,6 +24,9 @@
#include "sysconfig.h"
// sys_ctrl bits
#define LT_ACTIVE (1<<15)
#define LT_ARMED (1<<14)
#define LT_MODE_OFFS 12
#define SD_SPI_SS_N (1<<7)
#define LCD_CS_N (1<<6)
#define LCD_RS (1<<5)
@ -31,6 +34,8 @@
#define VIDGEN_OFF (1<<1)
#define AV_RESET_N (1<<0)
#define LT_CTRL_MASK 0xf000
// HDMI_TX definitions
#define HDMITX_MODE_MASK 0x00040000

View File

@ -42,7 +42,7 @@ extern avmode_t cm;
extern avconfig_t tc;
extern avinput_t target_mode;
extern alt_u8 menu_active;
extern alt_u8 sys_ctrl;
extern alt_u16 sys_ctrl;
extern alt_u8 profile_sel;
alt_u32 remote_code;

View File

@ -32,18 +32,15 @@
extern char menu_row1[LCD_ROW_LEN+1], menu_row2[LCD_ROW_LEN+1];
extern alt_u16 rc_keymap[REMOTE_MAX_KEYS];
extern SD_DEV sdcard_dev;
extern alt_u8 sys_ctrl;
extern alt_u16 sys_ctrl;
static int check_fw_header(alt_u8 *databuf, fw_hdr *hdr)
{
alt_u32 crcval, tmp;
strncpy(hdr->fw_key, (char*)databuf, 4);
if (strncmp(hdr->fw_key, "OSSC", 4)) {
sniprintf(menu_row1, LCD_ROW_LEN+1, "Invalid image");
menu_row2[0] = '\0';
return 1;
}
if (strncmp(hdr->fw_key, "OSSC", 4))
return FW_IMAGE_ERROR;
hdr->version_major = databuf[4];
hdr->version_minor = databuf[5];
@ -60,19 +57,13 @@ static int check_fw_header(alt_u8 *databuf, fw_hdr *hdr)
memcpy(&tmp, databuf+508, 4);
hdr->hdr_crc = ALT_CI_NIOS_CUSTOM_INSTR_ENDIANCONVERTER_0(tmp);
if (hdr->hdr_len < 26 || hdr->hdr_len > 508) {
sniprintf(menu_row1, LCD_ROW_LEN+1, "Invalid header");
menu_row2[0] = '\0';
return -1;
}
if (hdr->hdr_len < 26 || hdr->hdr_len > 508)
return FW_HDR_ERROR;
crcval = crcCI(databuf, hdr->hdr_len, 1);
if (crcval != hdr->hdr_crc) {
sniprintf(menu_row1, LCD_ROW_LEN+1, "Invalid hdr CRC");
menu_row2[0] = '\0';
return -2;
}
if (crcval != hdr->hdr_crc)
return FW_HDR_CRC_ERROR;
return 0;
}
@ -87,17 +78,14 @@ static int check_fw_image(alt_u32 offset, alt_u32 size, alt_u32 golden_crc, alt_
retval = SD_Read(&sdcard_dev, tmpbuf, (offset+i)/SD_BLK_SIZE, 0, bytes_to_read);
//retval = read_sd_block(offset+i, bytes_to_read, tmpbuf);
if (retval != 0)
return -2;
if (retval != SD_OK)
return retval;
crcval = crcCI(tmpbuf, bytes_to_read, (i==0));
}
if (crcval != golden_crc) {
sniprintf(menu_row1, LCD_ROW_LEN+1, "Invalid data CRC");
menu_row2[0] = '\0';
return -3;
}
if (crcval != golden_crc)
return FW_DATA_CRC_ERROR;
return 0;
}
@ -115,6 +103,7 @@ int fw_update()
{
int retval, i;
int retries = FW_UPDATE_RETRIES;
char *errmsg;
alt_u8 databuf[SD_BLK_SIZE];
alt_u32 btn_vec;
alt_u32 bytes_to_rw;
@ -146,8 +135,7 @@ int fw_update()
if (btn_vec == rc_keymap[RC_BTN1]) {
break;
} else if (btn_vec == rc_keymap[RC_BTN2]) {
retval = 2;
strncpy(menu_row1, "Cancelled", LCD_ROW_LEN+1);
retval = FW_UPD_CANCELLED;
goto failure;
}
@ -168,8 +156,10 @@ update_init:
for (i=0; i<fw_header.data_len; i=i+SD_BLK_SIZE) {
bytes_to_rw = ((fw_header.data_len-i < SD_BLK_SIZE) ? (fw_header.data_len-i) : SD_BLK_SIZE);
retval = SD_Read(&sdcard_dev, databuf, (512+i)/SD_BLK_SIZE, 0, bytes_to_rw);
if (retval != 0)
if (retval != 0) {
retval = -retval; //flag any SD errors critical to trigger update retry
goto failure;
}
retval = write_flash_page(databuf, ((bytes_to_rw < PAGESIZE) ? bytes_to_rw : PAGESIZE), (i/PAGESIZE));
if (retval != 0)
@ -190,15 +180,58 @@ update_init:
goto failure;
SPI_CS_High();
strncpy(menu_row1, "Firmware updated", LCD_ROW_LEN+1);
strncpy(menu_row2, "please restart", LCD_ROW_LEN+1);
lcd_write_menu();
while (1) {}
return 0;
failure:
SPI_CS_High();
switch (retval) {
case SD_NOINIT:
errmsg = "No SD card det.";
break;
case FW_IMAGE_ERROR:
errmsg = "Invalid image";
break;
case FW_HDR_ERROR:
errmsg = "Invalid header";
break;
case FW_HDR_CRC_ERROR:
errmsg = "Invalid hdr CRC";
break;
case FW_DATA_CRC_ERROR:
errmsg = "Invalid data CRC";
break;
case FW_UPD_CANCELLED:
errmsg = "Update cancelled";
break;
case -FLASH_READ_ERROR:
errmsg = "Flash read err";
break;
case -FLASH_ERASE_ERROR:
errmsg = "Flash erase err";
break;
case -FLASH_WRITE_ERROR:
errmsg = "Flash write err";
break;
case -FLASH_VERIFY_ERROR:
errmsg = "Flash verif fail";
break;
default:
errmsg = "Error";
break;
}
strncpy(menu_row2, errmsg, LCD_ROW_LEN+1);
lcd_write_menu();
usleep(1000000);
// Probable rw error, retry update
if ((retval <= -200) && (retries > 0)) {
// Critical error, retry update
if ((retval < 0) && (retries > 0)) {
sniprintf(menu_row1, LCD_ROW_LEN+1, "Retrying update");
retries--;
goto update_init;

View File

@ -40,6 +40,12 @@
#define FW_UPDATE_RETRIES 3
#define FW_IMAGE_ERROR 100
#define FW_HDR_ERROR 101
#define FW_HDR_CRC_ERROR 102
#define FW_DATA_CRC_ERROR 103
#define FW_UPD_CANCELLED 104
typedef struct {
char fw_key[4];
alt_u8 version_major;

View File

@ -31,7 +31,7 @@
#define WRDELAY 20
#define CLEARDELAY 800
extern alt_u8 sys_ctrl;
extern alt_u16 sys_ctrl;
static void lcd_cmd(alt_u8 cmd, alt_u16 postdelay) {
SPI_write(I2CA_BASE, &cmd, 1);

View File

@ -7,7 +7,7 @@
#include "spi_io.h"
#include "av_controller.h"
extern alt_u8 sys_ctrl;
extern alt_u16 sys_ctrl;
alt_u32 sd_timer_ts;

View File

@ -2,8 +2,8 @@
<sch:Settings xmlns:sch="http://www.altera.com/embeddedsw/bsp/schema">
<BspType>hal</BspType>
<BspVersion>default</BspVersion>
<BspGeneratedTimeStamp>Oct 22, 2017 8:54:19 PM</BspGeneratedTimeStamp>
<BspGeneratedUnixTimeStamp>1508694859052</BspGeneratedUnixTimeStamp>
<BspGeneratedTimeStamp>Oct 28, 2017 10:37:24 AM</BspGeneratedTimeStamp>
<BspGeneratedUnixTimeStamp>1509176244401</BspGeneratedUnixTimeStamp>
<BspGeneratedLocation>./</BspGeneratedLocation>
<BspSettingsFile>settings.bsp</BspSettingsFile>
<SopcDesignFile>../../sys.sopcinfo</SopcDesignFile>

View File

@ -4,7 +4,7 @@
* Machine generated for CPU 'nios2_qsys_0' in SOPC Builder design 'sys'
* SOPC Builder design path: ../../sys.sopcinfo
*
* Generated: Sun Oct 22 20:42:22 EEST 2017
* Generated: Thu Oct 26 23:11:44 EEST 2017
*/
/*
@ -330,7 +330,7 @@
#define PIO_0_BIT_CLEARING_EDGE_REGISTER 0
#define PIO_0_BIT_MODIFYING_OUTPUT_REGISTER 0
#define PIO_0_CAPTURE 0
#define PIO_0_DATA_WIDTH 8
#define PIO_0_DATA_WIDTH 16
#define PIO_0_DO_TEST_BENCH_WIRING 0
#define PIO_0_DRIVEN_SIM_VALUE 0
#define PIO_0_EDGE_TYPE "NONE"

View File

@ -664,7 +664,7 @@
<parameter name="resetValue" value="0" />
<parameter name="simDoTestBenchWiring" value="false" />
<parameter name="simDrivenValue" value="0" />
<parameter name="width" value="8" />
<parameter name="width" value="16" />
</module>
<module name="pio_1" kind="altera_avalon_pio" version="17.0" enabled="1">
<parameter name="bitClearingEdgeCapReg" value="false" />

View File

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<EnsembleReport name="sys" kind="sys" version="1.0" fabric="QSYS">
<!-- Format version 17.0 595 (Future versions may contain additional information.) -->
<!-- 2017.10.22.20:50:47 -->
<!-- 2017.10.27.00:12:49 -->
<!-- A collection of modules and connections -->
<parameter name="AUTO_GENERATION_ID">
<type>java.lang.Integer</type>
<value>1508694647</value>
<value>1509052369</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
@ -8456,7 +8456,7 @@ the requested settings for a module instance. -->
</assignment>
<assignment>
<name>embeddedsw.CMacro.DATA_WIDTH</name>
<value>8</value>
<value>16</value>
</assignment>
<assignment>
<name>embeddedsw.CMacro.DO_TEST_BENCH_WIRING</name>
@ -8508,7 +8508,7 @@ the requested settings for a module instance. -->
</assignment>
<assignment>
<name>embeddedsw.dts.params.altr,gpio-bank-width</name>
<value>8</value>
<value>16</value>
</assignment>
<assignment>
<name>embeddedsw.dts.params.resetvalue</name>
@ -8600,7 +8600,7 @@ the requested settings for a module instance. -->
</parameter>
<parameter name="width">
<type>int</type>
<value>8</value>
<value>16</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
@ -9208,7 +9208,7 @@ parameters are a RESULT of the module parameters. -->
<port>
<name>out_port</name>
<direction>Output</direction>
<width>8</width>
<width>16</width>
<role>export</role>
</port>
</interface>