diff --git a/ossc.cof b/ossc.cof new file mode 100644 index 0000000..72b465a --- /dev/null +++ b/ossc.cof @@ -0,0 +1,32 @@ + + + EPCS16 + EP4CE15 + output_files/ossc.jic + 1 + 1 + 7 + + Page_0 + 1 + + output_files/ossc.sof + + + 9 + 0 + 0 + 0 + 0 + + 1 + + + 0 + 2 + 0 + -1 + -1 + 1 + + \ No newline at end of file diff --git a/ossc.workspace b/ossc.workspace new file mode 100644 index 0000000..e9773ea --- /dev/null +++ b/ossc.workspace @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ossc_rtl.project b/ossc_rtl.project new file mode 100644 index 0000000..a064276 --- /dev/null +++ b/ossc_rtl.project @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + make clean + make + + + + None + $(WorkspacePath) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + make clean + make + + + + None + $(WorkspacePath) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ossc_sw_bsp.project b/ossc_sw_bsp.project new file mode 100644 index 0000000..99900a3 --- /dev/null +++ b/ossc_sw_bsp.project @@ -0,0 +1,341 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + make clean + nios2-bsp-generate-files --bsp-dir . --settings settings.bsp + + + + None + $(ProjectPath)/software/sys_controller_bsp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + make clean + nios2-bsp-generate-files --bsp-dir . --settings settings.bsp + + + + None + $(ProjectPath)/software/sys_controller_bsp + + + + + + + + + + + + + + diff --git a/rtl/ir_rcv.v b/rtl/ir_rcv.v index 63ed120..da2a7aa 100644 --- a/rtl/ir_rcv.v +++ b/rtl/ir_rcv.v @@ -1,5 +1,5 @@ // -// Copyright (C) 2015 Markus Hiienkari +// Copyright (C) 2015-2016 Markus Hiienkari // // This file is part of Open Source Scan Converter project. // @@ -17,42 +17,42 @@ // along with this program. If not, see . // -`define STATE_IDLE 2'b00 -`define STATE_LEADVERIFY 2'b01 -`define STATE_DATARCV 2'b10 +`define STATE_IDLE 2'b00 +`define STATE_LEADVERIFY 2'b01 +`define STATE_DATARCV 2'b10 module ir_rcv ( input clk27, input reset_n, input ir_rx, - output reg [15:0] ir_code, - output reg ir_code_ack + output reg [15:0] ir_code, + output reg ir_code_ack ); -// 20ns clock period +// ~37ns clock period -parameter LEADCODE_LO_THOLD = 124200; //4.60ms -parameter LEADCODE_HI_THOLD = 113400; //4.20ms -parameter LEADCODE_HI_RPT_THOLD = 56700; //2.1ms +parameter LEADCODE_LO_THOLD = 226800; //8.4ms +parameter LEADCODE_HI_THOLD = 118800; //4.4ms +parameter LEADCODE_HI_RPT_THOLD = 54000; //2.0ms parameter RPT_RELEASE_THOLD = 3240000; //120ms -parameter BIT_ONE_THOLD = 22410; //0.83ms +parameter BIT_ONE_THOLD = 27000; //1.0ms parameter BIT_DETECT_THOLD = 10800; //0.4ms -parameter IDLE_THOLD = 141557; //5.24ms +parameter IDLE_THOLD = 141480; //5.24ms -reg [1:0] state; // 3 states -reg [31:0] databuf; // temp. buffer +reg [1:0] state; // 3 states +reg [31:0] databuf; // temp. buffer reg [5:0] bits_detected; // max. 63, effectively between 0 and 33 -reg [17:0] act_cnt; // max. 5.2ms -reg [17:0] leadvrf_cnt; // max. 5.2ms -reg [17:0] datarcv_cnt; // max. 5.2ms -reg [22:0] rpt_cnt; // max. 166ms +reg [17:0] act_cnt; // max. 5.2ms +reg [17:0] leadvrf_cnt; // max. 5.2ms +reg [17:0] datarcv_cnt; // max. 5.2ms +reg [22:0] rpt_cnt; // max. 166ms // activity when signal is low always @(posedge clk27 or negedge reset_n) begin if (!reset_n) act_cnt <= 0; - else + else begin if ((state == `STATE_IDLE) & (~ir_rx)) act_cnt <= act_cnt + 1'b1; @@ -66,7 +66,7 @@ always @(posedge clk27 or negedge reset_n) begin if (!reset_n) leadvrf_cnt <= 0; - else + else begin if ((state == `STATE_LEADVERIFY) & ir_rx) leadvrf_cnt <= leadvrf_cnt + 1'b1; @@ -85,7 +85,7 @@ begin bits_detected <= 0; databuf <= 0; end - else + else begin if (state == `STATE_DATARCV) begin @@ -117,7 +117,7 @@ begin ir_code_ack <= 1'b0; ir_code <= 16'h00000000; end - else + else begin if ((bits_detected == 32) & (databuf[31:24] == ~databuf[23:16]) & (databuf[15:8] == ~databuf[7:0])) begin diff --git a/rtl/ossc.v b/rtl/ossc.v index 1c2b055..128c9c0 100644 --- a/rtl/ossc.v +++ b/rtl/ossc.v @@ -1,5 +1,5 @@ // -// Copyright (C) 2015 Markus Hiienkari +// Copyright (C) 2015-2016 Markus Hiienkari // // This file is part of Open Source Scan Converter project. // @@ -21,36 +21,36 @@ `define VIDEOGEN module ossc ( - input clk27, + input clk27, input ir_rx, - inout scl, - inout sda, + inout scl, + inout sda, input [1:0] btn, - input [7:0] R_in, - input [7:0] G_in, - input [7:0] B_in, - input FID_in, - input VSYNC_in, - input HSYNC_in, - input PCLK_in, - output [7:0] HDMI_TX_RD, - output [7:0] HDMI_TX_GD, - output [7:0] HDMI_TX_BD, - output HDMI_TX_DE, - output HDMI_TX_HS, - output HDMI_TX_VS, - output HDMI_TX_PCLK, - input HDMI_TX_INT_N, + input [7:0] R_in, + input [7:0] G_in, + input [7:0] B_in, + input FID_in, + input VSYNC_in, + input HSYNC_in, + input PCLK_in, + output [7:0] HDMI_TX_RD, + output [7:0] HDMI_TX_GD, + output [7:0] HDMI_TX_BD, + output HDMI_TX_DE, + output HDMI_TX_HS, + output HDMI_TX_VS, + output HDMI_TX_PCLK, + input HDMI_TX_INT_N, input HDMI_TX_MODE, - output reset_n, + output reset_n, output LED_G, output LED_R, output LCD_RS, output LCD_CS_N, output LCD_BL, output SD_CLK, - inout SD_CMD, - inout [3:0] SD_DAT + inout SD_CMD, + inout [3:0] SD_DAT ); wire cpu_reset_n; @@ -128,53 +128,54 @@ end assign cpu_reset_n = reset_n_reg; sys sys_inst( - .clk_clk (clk27), - .reset_reset_n (cpu_reset_n), - .pio_0_sys_ctrl_out_export (sys_ctrl), - .pio_1_controls_in_export ({13'b00000000000000, HDMI_TX_MODE, btn, ir_code}), - .pio_2_horizontal_info_out_export (h_info), - .pio_3_vertical_info_out_export (v_info), + .clk_clk (clk27), + .reset_reset_n (cpu_reset_n), + .pio_0_sys_ctrl_out_export (sys_ctrl), + .pio_1_controls_in_export ({13'b00000000000000, HDMI_TX_MODE, btn, ir_code}), + .pio_2_horizontal_info_out_export (h_info), + .pio_3_vertical_info_out_export (v_info), `ifdef DEBUG - .pio_4_linecount_in_export ({8'h00, R_in, G_in, B_in}), + .pio_4_linecount_in_export ({8'h00, R_in, G_in, B_in}), `else - .pio_4_linecount_in_export ({14'h0000, fpga_vsyncgen, 5'h00, lines_out}), + .pio_4_linecount_in_export ({VSYNC_out, 13'h0000, fpga_vsyncgen, 5'h00, lines_out}), `endif .pio_5_lcd_ctrl_out_export (lcd_ctrl), - .i2c_opencores_0_export_scl_pad_io (scl), - .i2c_opencores_0_export_sda_pad_io (sda), + .i2c_opencores_0_export_scl_pad_io (scl), + .i2c_opencores_0_export_sda_pad_io (sda), .sdcard_0_b_SD_cmd (SD_CMD), - .sdcard_0_b_SD_dat (SD_DAT[0]), - .sdcard_0_b_SD_dat3 (SD_DAT[3]), - .sdcard_0_o_SD_clock (SD_CLK) + .sdcard_0_b_SD_dat (SD_DAT[0]), + .sdcard_0_b_SD_dat3 (SD_DAT[3]), + .sdcard_0_o_SD_clock (SD_CLK) ); scanconverter scanconverter_inst ( - .HSYNC_in (HSYNC_in), - .VSYNC_in (VSYNC_in), - .PCLK_in (PCLK_in), - .FID_in (FID_in), - .R_in (R_in), - .G_in (G_in), - .B_in (B_in), - .h_info (h_info), - .v_info (v_info), - .R_out (R_out), - .G_out (G_out), - .B_out (B_out), - .HSYNC_out (HSYNC_out), - .VSYNC_out (VSYNC_out), - .PCLK_out (PCLK_out), - .DATA_enable (DATA_enable), - .h_unstable (h_unstable), - .fpga_vsyncgen (fpga_vsyncgen), - .pclk_lock (pclk_lock), - .pll_lock_lost (pll_lock_lost), - .lines_out (lines_out) + .reset_n (reset_n_reg), + .HSYNC_in (HSYNC_in), + .VSYNC_in (VSYNC_in), + .PCLK_in (PCLK_in), + .FID_in (FID_in), + .R_in (R_in), + .G_in (G_in), + .B_in (B_in), + .h_info (h_info), + .v_info (v_info), + .R_out (R_out), + .G_out (G_out), + .B_out (B_out), + .HSYNC_out (HSYNC_out), + .VSYNC_out (VSYNC_out), + .PCLK_out (PCLK_out), + .DATA_enable (DATA_enable), + .h_unstable (h_unstable), + .fpga_vsyncgen (fpga_vsyncgen), + .pclk_lock (pclk_lock), + .pll_lock_lost (pll_lock_lost), + .lines_out (lines_out) ); ir_rcv ir0 ( - .clk27 (clk27), - .reset_n (reset_n_reg), + .clk27 (clk27), + .reset_n (reset_n_reg), .ir_rx (ir_rx), .ir_code (ir_code), .ir_code_ack () @@ -188,9 +189,9 @@ videogen vg0 ( .G_out (G_out_videogen), .B_out (B_out_videogen), .HSYNC_out (HSYNC_out_videogen), - .VSYNC_out (VSYNC_out_videogen), - .PCLK_out (PCLK_out_videogen), - .ENABLE_out (DATA_enable_videogen) + .VSYNC_out (VSYNC_out_videogen), + .PCLK_out (PCLK_out_videogen), + .ENABLE_out (DATA_enable_videogen) ); `endif diff --git a/rtl/pll_2x.v b/rtl/pll_2x.v index 6c7d33e..4d01f3a 100644 --- a/rtl/pll_2x.v +++ b/rtl/pll_2x.v @@ -9,7 +9,7 @@ // altpll // // Simulation Library Files(s): -// +// altera_mf // ============================================================ // ************************************************************ // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! @@ -103,7 +103,7 @@ module pll_2x ( .vcooverrange (), .vcounderrange ()); defparam - altpll_component.bandwidth_type = "LOW", + altpll_component.bandwidth_type = "HIGH", altpll_component.clk0_divide_by = 1, altpll_component.clk0_duty_cycle = 50, altpll_component.clk0_multiply_by = 2, @@ -169,7 +169,7 @@ endmodule // Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" // Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" // Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" -// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "High" // Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "0" // Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "1" // Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" @@ -246,7 +246,7 @@ endmodule // Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" // Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" // Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all -// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "LOW" +// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "HIGH" // Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1" // Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" // Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "2" @@ -317,4 +317,5 @@ endmodule // Retrieval info: GEN_FILE: TYPE_NORMAL pll_2x.bsf FALSE // Retrieval info: GEN_FILE: TYPE_NORMAL pll_2x_inst.v FALSE // Retrieval info: GEN_FILE: TYPE_NORMAL pll_2x_bb.v TRUE +// Retrieval info: LIB_FILE: altera_mf // Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/rtl/pll_3x.v b/rtl/pll_3x.v index ea4e476..645420b 100644 --- a/rtl/pll_3x.v +++ b/rtl/pll_3x.v @@ -9,7 +9,7 @@ // altpll // // Simulation Library Files(s): -// +// altera_mf // ============================================================ // ************************************************************ // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! @@ -107,7 +107,7 @@ module pll_3x ( .vcooverrange (), .vcounderrange ()); defparam - altpll_component.bandwidth_type = "LOW", + altpll_component.bandwidth_type = "HIGH", altpll_component.clk0_divide_by = 1, altpll_component.clk0_duty_cycle = 50, altpll_component.clk0_multiply_by = 3, @@ -177,7 +177,7 @@ endmodule // Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" // Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" // Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" -// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "High" // Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "0" // Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "1" // Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" @@ -268,7 +268,7 @@ endmodule // Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" // Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" // Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all -// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "LOW" +// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "HIGH" // Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1" // Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" // Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "3" @@ -345,4 +345,5 @@ endmodule // Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x.bsf FALSE // Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_inst.v FALSE // Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf // Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/rtl/pll_3x_lowfreq.v b/rtl/pll_3x_lowfreq.v index 8fc3638..5aac541 100644 --- a/rtl/pll_3x_lowfreq.v +++ b/rtl/pll_3x_lowfreq.v @@ -9,7 +9,7 @@ // altpll // // Simulation Library Files(s): -// +// altera_mf // ============================================================ // ************************************************************ // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! @@ -111,7 +111,7 @@ module pll_3x_lowfreq ( .vcooverrange (), .vcounderrange ()); defparam - altpll_component.bandwidth_type = "LOW", + altpll_component.bandwidth_type = "HIGH", altpll_component.clk0_divide_by = 1, altpll_component.clk0_duty_cycle = 50, altpll_component.clk0_multiply_by = 3, @@ -185,7 +185,7 @@ endmodule // Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" // Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" // Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" -// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "High" // Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "0" // Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "1" // Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" @@ -290,7 +290,7 @@ endmodule // Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" // Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" // Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all -// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "LOW" +// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "HIGH" // Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1" // Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" // Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "3" @@ -373,4 +373,5 @@ endmodule // Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_lowfreq.bsf FALSE // Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_lowfreq_inst.v FALSE // Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_lowfreq_bb.v TRUE +// Retrieval info: LIB_FILE: altera_mf // Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/rtl/scanconverter.v b/rtl/scanconverter.v index 156ea26..49ea667 100644 --- a/rtl/scanconverter.v +++ b/rtl/scanconverter.v @@ -1,5 +1,5 @@ // -// Copyright (C) 2015 Markus Hiienkari +// Copyright (C) 2015-2016 Markus Hiienkari // // This file is part of Open Source Scan Converter project. // @@ -22,14 +22,14 @@ `define HI 1'b1 `define LO 1'b0 -`define LINEMULT_DISABLE 2'h0 -`define LINEMULT_DOUBLE 2'h1 -`define LINEMULT_TRIPLE 2'h2 +`define LINEMULT_DISABLE 2'h0 +`define LINEMULT_DOUBLE 2'h1 +`define LINEMULT_TRIPLE 2'h2 -`define LINETRIPLE_M0 2'h0 -`define LINETRIPLE_M1 2'h1 -`define LINETRIPLE_M2 2'h2 -`define LINETRIPLE_M3 2'h3 +`define LINETRIPLE_M0 2'h0 +`define LINETRIPLE_M1 2'h1 +`define LINETRIPLE_M2 2'h2 +`define LINETRIPLE_M3 2'h3 `define VSYNCGEN_LEN 6 `define VSYNCGEN_GENMID_BIT 0 @@ -48,27 +48,28 @@ `define HSYNC_TRAILING_EDGE ((prev_hs == `LO) & (HSYNC_in == `HI)) module scanconverter ( - input [7:0] R_in, - input [7:0] G_in, - input [7:0] B_in, - input FID_in, - input VSYNC_in, - input HSYNC_in, - input PCLK_in, - input [31:0] h_info, - input [31:0] v_info, - output reg [7:0] R_out, - output reg [7:0] G_out, - output reg [7:0] B_out, - output reg HSYNC_out, - output reg VSYNC_out, - output PCLK_out, - output reg DATA_enable, - output h_unstable, + input reset_n, + input [7:0] R_in, + input [7:0] G_in, + input [7:0] B_in, + input FID_in, + input VSYNC_in, + input HSYNC_in, + input PCLK_in, + input [31:0] h_info, + input [31:0] v_info, + output reg [7:0] R_out, + output reg [7:0] G_out, + output reg [7:0] B_out, + output reg HSYNC_out, + output reg VSYNC_out, + output PCLK_out, + output reg DATA_enable, + output h_unstable, output reg [1:0] fpga_vsyncgen, - output [2:0] pclk_lock, - output [2:0] pll_lock_lost, - output [10:0] lines_out + output [2:0] pclk_lock, + output [2:0] pll_lock_lost, + output [10:0] lines_out ); wire pclk_1x, pclk_2x, pclk_3x, pclk_4x, pclk_3x_h1x, pclk_3x_h4x, pclk_3x_h5x; @@ -96,16 +97,15 @@ wire [11:0] hcnt_act; reg [11:0] hcnt_1x, hcnt_2x, hcnt_3x, hcnt_4x, hcnt_3x_h1x, hcnt_3x_h4x, hcnt_3x_h5x; wire [10:0] vcnt_act; -reg [10:0] vcnt_1x, vcnt_1x_tvp, vcnt_2x, lines_1x, lines_2x; //max. 2047 +reg [10:0] vcnt_1x, vcnt_1x_tvp, vcnt_2x, lines_1x, lines_2x; //max. 2047 reg [9:0] vcnt_3x, vcnt_3x_h1x, lines_3x, lines_3x_h1x; //max. 1023 reg h_enable_3x_prev4x, h_enable_3x_prev3x_h4x, h_enable_3x_prev3x_h5x; reg [1:0] hcnt_3x_h4x_ctr; reg [1:0] hcnt_3x_h5x_ctr; -reg pclk_1x_prev3x, pclk_1x_prev3x_h1x, pclk_1x_prev3x_h4x; +reg pclk_1x_prev3x, pclk_1x_prev3x_h1x; reg [1:0] pclk_3x_cnt, pclk_3x_h1x_cnt; -reg [3:0] pclk_3x_h4x_cnt; // Data enable reg h_enable_1x, v_enable_1x; @@ -118,10 +118,10 @@ reg line_idx; reg [23:0] warn_h_unstable, warn_pll_lock_lost, warn_pll_lock_lost_3x, warn_pll_lock_lost_3x_lowfreq; -reg [10:0] H_ACTIVE; //max. 2047 -reg [7:0] H_BACKPORCH; //max. 255 -reg [10:0] V_ACTIVE; //max. 2047 -reg [5:0] V_BACKPORCH; //max. 63 +reg [10:0] H_ACTIVE; //max. 2047 +reg [7:0] H_BACKPORCH; //max. 255 +reg [10:0] V_ACTIVE; //max. 2047 +reg [5:0] V_BACKPORCH; //max. 63 reg V_SCANLINES; reg V_SCANLINEDIR; reg V_SCANLINEID; @@ -169,14 +169,14 @@ function [8:0] apply_scanlines; //Border masking function [8:0] apply_mask; - input enable; + input enable; input [8:0] data; input [11:0] hoffset; - input [11:0] hstart; - input [11:0] hend; + input [11:0] hstart; + input [11:0] hend; input [10:0] voffset; - input [10:0] vstart; - input [10:0] vend; + input [10:0] vstart; + input [10:0] vend; begin if (enable & ((hoffset < hstart) | (hoffset >= hend) | (voffset < vstart) | (voffset >= vend))) apply_mask = 8'h00; @@ -201,229 +201,275 @@ function [8:0] apply_mask; //Non-critical signals and inactive clock combinations filtered out in SDC always @(*) begin - case (H_LINEMULT) - `LINEMULT_DISABLE: begin - R_act = R_1x; - G_act = G_1x; - B_act = B_1x; - DATA_enable_act = (h_enable_1x & v_enable_1x); - PCLK_out = pclk_out_1x; - HSYNC_act = HSYNC_1x; + case (H_LINEMULT) + `LINEMULT_DISABLE: begin + R_act = R_1x; + G_act = G_1x; + B_act = B_1x; + DATA_enable_act = (h_enable_1x & v_enable_1x); + PCLK_out = pclk_out_1x; + HSYNC_act = HSYNC_1x; VSYNC_act = VSYNC_1x; - lines_out = lines_1x; - linebuf_rdclock = 0; - linebuf_hoffset = 0; - pclk_act = pclk_1x; - slid_act = {1'b0, vcnt_1x[0]}; - hcnt_act = hcnt_1x; - vcnt_act = vcnt_1x; - end - `LINEMULT_DOUBLE: begin - R_act = R_lbuf; - G_act = G_lbuf; - B_act = B_lbuf; - DATA_enable_act = (h_enable_2x & v_enable_2x); - PCLK_out = pclk_out_2x; - HSYNC_act = HSYNC_2x; + lines_out = lines_1x; + linebuf_rdclock = 0; + linebuf_hoffset = 0; + pclk_act = pclk_1x; + slid_act = {1'b0, vcnt_1x[0]}; + hcnt_act = hcnt_1x; + vcnt_act = vcnt_1x; + end + `LINEMULT_DOUBLE: begin + R_act = R_lbuf; + G_act = G_lbuf; + B_act = B_lbuf; + DATA_enable_act = (h_enable_2x & v_enable_2x); + PCLK_out = pclk_out_2x; + HSYNC_act = HSYNC_2x; VSYNC_act = VSYNC_2x; - lines_out = lines_2x; - linebuf_rdclock = pclk_2x; - linebuf_hoffset = hcnt_2x; - pclk_act = pclk_2x; - slid_act = {1'b0, vcnt_2x[0]}; - hcnt_act = hcnt_2x; - vcnt_act = vcnt_2x>>1; - end - `LINEMULT_TRIPLE: begin - R_act = R_lbuf; - G_act = G_lbuf; - B_act = B_lbuf; + lines_out = lines_2x; + linebuf_rdclock = pclk_2x; + linebuf_hoffset = hcnt_2x; + pclk_act = pclk_2x; + slid_act = {1'b0, vcnt_2x[0]}; + hcnt_act = hcnt_2x; + vcnt_act = vcnt_2x>>1; + end + `LINEMULT_TRIPLE: begin + R_act = R_lbuf; + G_act = G_lbuf; + B_act = B_lbuf; VSYNC_act = VSYNC_1x; - case (H_L3MODE) - `LINETRIPLE_M0: begin - DATA_enable_act = (h_enable_3x & v_enable_3x); - PCLK_out = pclk_out_3x; - HSYNC_act = HSYNC_3x; - lines_out = {1'b0, lines_3x}; - linebuf_rdclock = pclk_3x; - linebuf_hoffset = hcnt_3x; - pclk_act = pclk_3x; - hcnt_act = hcnt_3x; - vcnt_act = vcnt_3x/2'h3; //divider generated - slid_act = (vcnt_3x % 2'h3); - end - `LINETRIPLE_M1: begin - DATA_enable_act = (h_enable_3x & v_enable_3x); - PCLK_out = pclk_out_4x; - HSYNC_act = HSYNC_3x; - lines_out = {1'b0, lines_3x}; - linebuf_rdclock = pclk_4x; - linebuf_hoffset = hcnt_4x; - pclk_act = pclk_4x; - hcnt_act = hcnt_4x; - vcnt_act = vcnt_3x/2'h3; //divider generated - slid_act = (vcnt_3x % 2'h3); - end - `LINETRIPLE_M2: begin - DATA_enable_act = (h_enable_3x_h1x & v_enable_3x_h1x); - PCLK_out = pclk_out_3x_h4x; - HSYNC_act = HSYNC_3x_h1x; - lines_out = {1'b0, lines_3x_h1x}; - linebuf_rdclock = pclk_3x_h4x; - linebuf_hoffset = hcnt_3x_h4x; - pclk_act = pclk_3x_h4x; - hcnt_act = hcnt_3x_h4x; - vcnt_act = vcnt_3x_h1x/2'h3; //divider generated - slid_act = (vcnt_3x_h1x % 2'h3); - end - `LINETRIPLE_M3: begin - DATA_enable_act = (h_enable_3x_h1x & v_enable_3x_h1x); - PCLK_out = pclk_out_3x_h5x; - HSYNC_act = HSYNC_3x_h1x; - lines_out = {1'b0, lines_3x_h1x}; - linebuf_rdclock = pclk_3x_h5x; - linebuf_hoffset = hcnt_3x_h5x; - pclk_act = pclk_3x_h5x; - hcnt_act = hcnt_3x_h5x; - vcnt_act = vcnt_3x_h1x/2'h3; //divider generated - slid_act = (vcnt_3x_h1x % 2'h3); - end - endcase - end - default: begin - R_act = 0; - G_act = 0; - B_act = 0; - DATA_enable_act = 0; - PCLK_out = 0; - HSYNC_act = 0; + case (H_L3MODE) + `LINETRIPLE_M0: begin + DATA_enable_act = (h_enable_3x & v_enable_3x); + PCLK_out = pclk_out_3x; + HSYNC_act = HSYNC_3x; + lines_out = {1'b0, lines_3x}; + linebuf_rdclock = pclk_3x; + linebuf_hoffset = hcnt_3x; + pclk_act = pclk_3x; + hcnt_act = hcnt_3x; + vcnt_act = vcnt_3x/2'h3; //divider generated + slid_act = (vcnt_3x % 2'h3); + end + `LINETRIPLE_M1: begin + DATA_enable_act = (h_enable_3x & v_enable_3x); + PCLK_out = pclk_out_4x; + HSYNC_act = HSYNC_3x; + lines_out = {1'b0, lines_3x}; + linebuf_rdclock = pclk_4x; + linebuf_hoffset = hcnt_4x; + pclk_act = pclk_4x; + hcnt_act = hcnt_4x; + vcnt_act = vcnt_3x/2'h3; //divider generated + slid_act = (vcnt_3x % 2'h3); + end + `LINETRIPLE_M2: begin + DATA_enable_act = (h_enable_3x_h1x & v_enable_3x_h1x); + PCLK_out = pclk_out_3x_h4x; + HSYNC_act = HSYNC_3x_h1x; + lines_out = {1'b0, lines_3x_h1x}; + linebuf_rdclock = pclk_3x_h4x; + linebuf_hoffset = hcnt_3x_h4x; + pclk_act = pclk_3x_h4x; + hcnt_act = hcnt_3x_h4x; + vcnt_act = vcnt_3x_h1x/2'h3; //divider generated + slid_act = (vcnt_3x_h1x % 2'h3); + end + `LINETRIPLE_M3: begin + DATA_enable_act = (h_enable_3x_h1x & v_enable_3x_h1x); + PCLK_out = pclk_out_3x_h5x; + HSYNC_act = HSYNC_3x_h1x; + lines_out = {1'b0, lines_3x_h1x}; + linebuf_rdclock = pclk_3x_h5x; + linebuf_hoffset = hcnt_3x_h5x; + pclk_act = pclk_3x_h5x; + hcnt_act = hcnt_3x_h5x; + vcnt_act = vcnt_3x_h1x/2'h3; //divider generated + slid_act = (vcnt_3x_h1x % 2'h3); + end + endcase + end + default: begin + R_act = 0; + G_act = 0; + B_act = 0; + DATA_enable_act = 0; + PCLK_out = 0; + HSYNC_act = 0; VSYNC_act = VSYNC_1x; - lines_out = 0; - linebuf_rdclock = 0; - linebuf_hoffset = 0; - pclk_act = 0; - slid_act = 0; - hcnt_act = 0; - vcnt_act = 0; - end - endcase + lines_out = 0; + linebuf_rdclock = 0; + linebuf_hoffset = 0; + pclk_act = 0; + slid_act = 0; + hcnt_act = 0; + vcnt_act = 0; + end + endcase end pll_2x pll_linedouble ( - .areset ( (H_LINEMULT != `LINEMULT_DOUBLE) ), - .inclk0 ( PCLK_in ), - .c0 ( pclk_2x ), - .locked ( pclk_2x_lock ) + .areset ( (H_LINEMULT != `LINEMULT_DOUBLE) ), + .inclk0 ( PCLK_in ), + .c0 ( pclk_2x ), + .locked ( pclk_2x_lock ) ); pll_3x pll_linetriple ( - .areset ( ((H_LINEMULT != `LINEMULT_TRIPLE) | H_L3MODE[1]) ), - .inclk0 ( PCLK_in ), - .c0 ( pclk_3x ), // sampling clock for 240p: 1280 or 960 samples & MODE0: 1280 output pixels from 1280 input samples (16:9) - .c1 ( pclk_4x ), // MODE1: 1280 output pixels from 960 input samples (960 drawn -> 4:3 aspect) - .locked ( pclk_3x_lock ) + .areset ( ((H_LINEMULT != `LINEMULT_TRIPLE) | H_L3MODE[1]) ), + .inclk0 ( PCLK_in ), + .c0 ( pclk_3x ), // sampling clock for 240p: 1280 or 960 samples & MODE0: 1280 output pixels from 1280 input samples (16:9) + .c1 ( pclk_4x ), // MODE1: 1280 output pixels from 960 input samples (960 drawn -> 4:3 aspect) + .locked ( pclk_3x_lock ) ); pll_3x_lowfreq pll_linetriple_lowfreq ( - .areset ( (H_LINEMULT != `LINEMULT_TRIPLE) | ~H_L3MODE[1]), - .inclk0 ( PCLK_in ), - .c0 ( pclk_3x_h1x ), // sampling clock for 240p: 320 or 256 samples - .c1 ( pclk_3x_h4x ), // MODE2: 1280 output pixels from 320 input samples (960 drawn -> 4:3 aspect) - .c2 ( pclk_3x_h5x ), // MODE3: 1280 output pixels from 256 input samples (1024 drawn -> 5:4 aspect) - .locked ( pclk_3x_lowfreq_lock ) + .areset ( (H_LINEMULT != `LINEMULT_TRIPLE) | ~H_L3MODE[1]), + .inclk0 ( PCLK_in ), + .c0 ( pclk_3x_h1x ), // sampling clock for 240p: 320 or 256 samples + .c1 ( pclk_3x_h4x ), // MODE2: 1280 output pixels from 320 input samples (960 drawn -> 4:3 aspect) + .c2 ( pclk_3x_h5x ), // MODE3: 1280 output pixels from 256 input samples (1024 drawn -> 5:4 aspect) + .locked ( pclk_3x_lowfreq_lock ) ); //TODO: add secondary buffers for interlaced signals with alternative field order -linebuf linebuf_rgb ( - .data ( {R_1x, G_1x, B_1x} ), //or *_in? - .rdaddress ( linebuf_hoffset + (~line_idx << 11) ), - .rdclock ( linebuf_rdclock ), - .wraddress ( hcnt_1x + (line_idx << 11) ), - .wrclock ( pclk_1x ), - .wren ( 1'b1 ), - .q ( {R_lbuf, G_lbuf, B_lbuf} ) +linebuf linebuf_rgb ( + .data ( {R_1x, G_1x, B_1x} ), //or *_in? + .rdaddress ( linebuf_hoffset + (~line_idx << 11) ), + .rdclock ( linebuf_rdclock ), + .wraddress ( hcnt_1x + (line_idx << 11) ), + .wrclock ( pclk_1x ), + .wren ( 1'b1 ), + .q ( {R_lbuf, G_lbuf, B_lbuf} ) ); //Postprocess pipeline -always @(posedge pclk_act /*or negedge reset_n*/) +always @(posedge pclk_act or negedge reset_n) begin - /*if (!reset_n) - begin - end - else*/ - begin - R_pp1 <= apply_mask(1, R_act, hcnt_act, H_BACKPORCH+H_MASK, H_BACKPORCH+H_ACTIVE-H_MASK, vcnt_act, V_BACKPORCH+V_MASK, V_BACKPORCH+V_ACTIVE-V_MASK); - G_pp1 <= apply_mask(1, G_act, hcnt_act, H_BACKPORCH+H_MASK, H_BACKPORCH+H_ACTIVE-H_MASK, vcnt_act, V_BACKPORCH+V_MASK, V_BACKPORCH+V_ACTIVE-V_MASK); - B_pp1 <= apply_mask(1, B_act, hcnt_act, H_BACKPORCH+H_MASK, H_BACKPORCH+H_ACTIVE-H_MASK, vcnt_act, V_BACKPORCH+V_MASK, V_BACKPORCH+V_ACTIVE-V_MASK); - HSYNC_pp1 <= HSYNC_act; - VSYNC_pp1 <= VSYNC_act; - DATA_enable_pp1 <= DATA_enable_act; - - R_out <= apply_scanlines(V_SCANLINES, V_SCANLINEDIR, R_pp1, V_SCANLINESTR, {1'b0, V_SCANLINEID}, slid_act, hcnt_act[0]); - G_out <= apply_scanlines(V_SCANLINES, V_SCANLINEDIR, G_pp1, V_SCANLINESTR, {1'b0, V_SCANLINEID}, slid_act, hcnt_act[0]); - B_out <= apply_scanlines(V_SCANLINES, V_SCANLINEDIR, B_pp1, V_SCANLINESTR, {1'b0, V_SCANLINEID}, slid_act, hcnt_act[0]); - HSYNC_out <= HSYNC_pp1; - VSYNC_out <= VSYNC_pp1; - DATA_enable <= DATA_enable_pp1; - end + if (!reset_n) + begin + R_pp1 <= 8'h00; + G_pp1 <= 8'h00; + G_pp1 <= 8'h00; + HSYNC_pp1 <= 1'b0; + VSYNC_pp1 <= 1'b0; + DATA_enable_pp1 <= 1'b0; + R_out <= 8'h00; + G_out <= 8'h00; + G_out <= 8'h00; + HSYNC_out <= 1'b0; + VSYNC_out <= 1'b0; + DATA_enable <= 1'b0; + end + else + begin + R_pp1 <= apply_mask(1, R_act, hcnt_act, H_BACKPORCH+H_MASK, H_BACKPORCH+H_ACTIVE-H_MASK, vcnt_act, V_BACKPORCH+V_MASK, V_BACKPORCH+V_ACTIVE-V_MASK); + G_pp1 <= apply_mask(1, G_act, hcnt_act, H_BACKPORCH+H_MASK, H_BACKPORCH+H_ACTIVE-H_MASK, vcnt_act, V_BACKPORCH+V_MASK, V_BACKPORCH+V_ACTIVE-V_MASK); + B_pp1 <= apply_mask(1, B_act, hcnt_act, H_BACKPORCH+H_MASK, H_BACKPORCH+H_ACTIVE-H_MASK, vcnt_act, V_BACKPORCH+V_MASK, V_BACKPORCH+V_ACTIVE-V_MASK); + HSYNC_pp1 <= HSYNC_act; + VSYNC_pp1 <= VSYNC_act; + DATA_enable_pp1 <= DATA_enable_act; + + R_out <= apply_scanlines(V_SCANLINES, V_SCANLINEDIR, R_pp1, V_SCANLINESTR, {1'b0, V_SCANLINEID}, slid_act, hcnt_act[0]); + G_out <= apply_scanlines(V_SCANLINES, V_SCANLINEDIR, G_pp1, V_SCANLINESTR, {1'b0, V_SCANLINEID}, slid_act, hcnt_act[0]); + B_out <= apply_scanlines(V_SCANLINES, V_SCANLINEDIR, B_pp1, V_SCANLINESTR, {1'b0, V_SCANLINEID}, slid_act, hcnt_act[0]); + HSYNC_out <= HSYNC_pp1; + VSYNC_out <= VSYNC_pp1; + DATA_enable <= DATA_enable_pp1; + end end //Generate a warning signal from horizontal instability or PLL sync loss -always @(posedge pclk_1x /*or negedge reset_n*/) +always @(posedge pclk_1x or negedge reset_n) begin - /*if (!reset_n) - begin - end - else*/ - begin - if (hmax[0] != hmax[1]) - warn_h_unstable <= 1; - else if (warn_h_unstable != 0) - warn_h_unstable <= warn_h_unstable + 1'b1; - - if ((H_LINEMULT == `LINEMULT_DOUBLE) & ~pclk_2x_lock) - warn_pll_lock_lost <= 1; - else if (warn_pll_lock_lost != 0) - warn_pll_lock_lost <= warn_pll_lock_lost + 1'b1; - - if ((H_LINEMULT == `LINEMULT_TRIPLE) & ~H_L3MODE[1] & ~pclk_3x_lock) - warn_pll_lock_lost_3x <= 1; - else if (warn_pll_lock_lost_3x != 0) - warn_pll_lock_lost_3x <= warn_pll_lock_lost_3x + 1'b1; + if (!reset_n) + begin + warn_h_unstable <= 1'b0; + warn_pll_lock_lost <= 1'b0; + warn_pll_lock_lost_3x <= 1'b0; + warn_pll_lock_lost_3x_lowfreq <= 1'b0; + end + else + begin + if (hmax[0] != hmax[1]) + warn_h_unstable <= 1; + else if (warn_h_unstable != 0) + warn_h_unstable <= warn_h_unstable + 1'b1; + + if ((H_LINEMULT == `LINEMULT_DOUBLE) & ~pclk_2x_lock) + warn_pll_lock_lost <= 1; + else if (warn_pll_lock_lost != 0) + warn_pll_lock_lost <= warn_pll_lock_lost + 1'b1; + + if ((H_LINEMULT == `LINEMULT_TRIPLE) & ~H_L3MODE[1] & ~pclk_3x_lock) + warn_pll_lock_lost_3x <= 1; + else if (warn_pll_lock_lost_3x != 0) + warn_pll_lock_lost_3x <= warn_pll_lock_lost_3x + 1'b1; - if ((H_LINEMULT == `LINEMULT_TRIPLE) & H_L3MODE[1] & ~pclk_3x_lowfreq_lock) - warn_pll_lock_lost_3x_lowfreq <= 1; - else if (warn_pll_lock_lost_3x_lowfreq != 0) - warn_pll_lock_lost_3x_lowfreq <= warn_pll_lock_lost_3x_lowfreq + 1'b1; - end + if ((H_LINEMULT == `LINEMULT_TRIPLE) & H_L3MODE[1] & ~pclk_3x_lowfreq_lock) + warn_pll_lock_lost_3x_lowfreq <= 1; + else if (warn_pll_lock_lost_3x_lowfreq != 0) + warn_pll_lock_lost_3x_lowfreq <= warn_pll_lock_lost_3x_lowfreq + 1'b1; + end end assign h_unstable = (warn_h_unstable != 0); assign pll_lock_lost = {(warn_pll_lock_lost != 0), (warn_pll_lock_lost_3x != 0), (warn_pll_lock_lost_3x_lowfreq != 0)}; //Buffer the inputs using input pixel clock and generate 1x signals -always @(posedge pclk_1x /*or negedge reset_n*/) +always @(posedge pclk_1x or negedge reset_n) begin - /*if (!reset_n) - begin - end - else*/ - begin - if (`HSYNC_TRAILING_EDGE) - begin - hcnt_1x <= 0; - hmax[line_idx] <= hcnt_1x; - line_idx <= line_idx ^ 1'b1; - vcnt_1x <= vcnt_1x + 1'b1; + if (!reset_n) + begin + hcnt_1x <= 0; + hmax[line_idx] <= 0; + line_idx <= 0; + vcnt_1x <= 0; + vcnt_1x_tvp <= 0; + FID_prev <= 0; + fpga_vsyncgen <= 0; + lines_1x <= 0; + H_ACTIVE <= 0; + H_BACKPORCH <= 0; + H_LINEMULT <= 0; + H_L3MODE <= 0; + H_MASK <= 0; + V_ACTIVE <= 0; + V_BACKPORCH <= 0; + V_SCANLINES <= 0; + V_SCANLINEDIR <= 0; + V_SCANLINEID <= 0; + V_SCANLINESTR <= 0; + V_MASK <= 0; + prev_hs <= 0; + prev_vs <= 0; + HSYNC_start <= 0; + R_1x <= 8'h00; + G_1x <= 8'h00; + B_1x <= 8'h00; + HSYNC_1x <= 0; + VSYNC_1x <= 0; + h_enable_1x <= 0; + v_enable_1x <= 0; + end + else + begin + if (`HSYNC_TRAILING_EDGE) + begin + hcnt_1x <= 0; + hmax[line_idx] <= hcnt_1x; + line_idx <= line_idx ^ 1'b1; + vcnt_1x <= vcnt_1x + 1'b1; vcnt_1x_tvp <= vcnt_1x_tvp + 1'b1; - end - else - begin - hcnt_1x <= hcnt_1x + 1'b1; - end + end + else + begin + hcnt_1x <= hcnt_1x + 1'b1; + end - if (`VSYNC_TRAILING_EDGE) //should be checked at every pclk_1x? - begin + if (`VSYNC_TRAILING_EDGE) //should be checked at every pclk_1x? + begin vcnt_1x_tvp <= 0; FID_prev <= FID_in; @@ -439,67 +485,74 @@ begin vcnt_1x <= 0; lines_1x <= vcnt_1x; end - - //Read configuration data from CPU - H_ACTIVE <= h_info[26:16]; // Horizontal active length from by the CPU - 11bits (0...2047) - H_BACKPORCH <= h_info[7:0]; // Horizontal backporch length from by the CPU - 8bits (0...255) - H_LINEMULT <= h_info[31:30]; // Horizontal line multiply mode - H_L3MODE <= h_info[29:28]; // Horizontal line triple mode - H_MASK <= {h_info[11:8], 2'b00}; - V_ACTIVE <= v_info[23:13]; // Vertical active length from by the CPU, 11bits (0...2047) - V_BACKPORCH <= v_info[5:0]; // Vertical backporch length from by the CPU, 6bits (0...64) - V_SCANLINES <= v_info[29]; + + //Read configuration data from CPU + H_ACTIVE <= h_info[26:16]; // Horizontal active length from by the CPU - 11bits (0...2047) + H_BACKPORCH <= h_info[7:0]; // Horizontal backporch length from by the CPU - 8bits (0...255) + H_LINEMULT <= h_info[31:30]; // Horizontal line multiply mode + H_L3MODE <= h_info[29:28]; // Horizontal line triple mode + H_MASK <= {h_info[11:8], 2'b00}; + V_ACTIVE <= v_info[23:13]; // Vertical active length from by the CPU, 11bits (0...2047) + V_BACKPORCH <= v_info[5:0]; // Vertical backporch length from by the CPU, 6bits (0...64) + V_SCANLINES <= v_info[29]; V_SCANLINEDIR <= v_info[28]; V_SCANLINEID <= v_info[27]; - V_SCANLINESTR <= ((v_info[26:24]+8'h01)<<5)-1'b1; - V_MASK <= {v_info[9:6], 2'b00}; - end - - prev_hs <= HSYNC_in; - prev_vs <= VSYNC_in; + V_SCANLINESTR <= ((v_info[26:24]+8'h01)<<5)-1'b1; + V_MASK <= {v_info[9:6], 2'b00}; + end + + prev_hs <= HSYNC_in; + prev_vs <= VSYNC_in; - // record start position of HSYNC - if (`HSYNC_LEADING_EDGE) - HSYNC_start <= hcnt_1x; - - R_1x <= R_in; - G_1x <= G_in; - B_1x <= B_in; - HSYNC_1x <= HSYNC_in; + // record start position of HSYNC + if (`HSYNC_LEADING_EDGE) + HSYNC_start <= hcnt_1x; + + R_1x <= R_in; + G_1x <= G_in; + B_1x <= B_in; + HSYNC_1x <= HSYNC_in; - // Ignore possible invalid vsyncs generated by TVP7002 - if (vcnt_1x > V_ACTIVE) - VSYNC_1x <= VSYNC_in; + // Ignore possible invalid vsyncs generated by TVP7002 + if (vcnt_1x > V_ACTIVE) + VSYNC_1x <= VSYNC_in; // Check if extra vsync needed - fpga_vsyncgen[`VSYNCGEN_GENMID_BIT] <= (lines_1x > ({1'b0, V_ACTIVE} << 1)) ? 1'b1 : 1'b0; - - h_enable_1x <= ((hcnt_1x >= H_BACKPORCH) & (hcnt_1x < H_BACKPORCH + H_ACTIVE)); - v_enable_1x <= ((vcnt_1x >= V_BACKPORCH) & (vcnt_1x < V_BACKPORCH + V_ACTIVE)); //- FID_in ??? - - /*HSYNC_out_debug <= HSYNC_in; - VSYNC_out_debug <= VSYNC_in;*/ - end + fpga_vsyncgen[`VSYNCGEN_GENMID_BIT] <= (lines_1x > ({1'b0, V_ACTIVE} << 1)) ? 1'b1 : 1'b0; + + h_enable_1x <= ((hcnt_1x >= H_BACKPORCH) & (hcnt_1x < H_BACKPORCH + H_ACTIVE)); + v_enable_1x <= ((vcnt_1x >= V_BACKPORCH) & (vcnt_1x < V_BACKPORCH + V_ACTIVE)); //- FID_in ??? + + /*HSYNC_out_debug <= HSYNC_in; + VSYNC_out_debug <= VSYNC_in;*/ + end end //Generate 2x signals for linedouble -always @(posedge pclk_2x /*or negedge reset_n*/) +always @(posedge pclk_2x or negedge reset_n) begin - /*if (!reset_n) - begin - end - else*/ - begin - if ((pclk_1x == 1'b0) & `HSYNC_TRAILING_EDGE) //sync with posedge of pclk_1x - hcnt_2x <= 0; - else if (hcnt_2x == hmax[~line_idx]) //line_idx_prev? - hcnt_2x <= 0; - else - hcnt_2x <= hcnt_2x + 1'b1; + if (!reset_n) + begin + hcnt_2x <= 0; + vcnt_2x <= 0; + lines_2x <= 0; + HSYNC_2x <= 0; + VSYNC_2x <= 0; + h_enable_2x <= 0; + v_enable_2x <= 0; + end + else + begin + if ((pclk_1x == 1'b0) & `HSYNC_TRAILING_EDGE) //sync with posedge of pclk_1x + hcnt_2x <= 0; + else if (hcnt_2x == hmax[~line_idx]) //line_idx_prev? + hcnt_2x <= 0; + else + hcnt_2x <= hcnt_2x + 1'b1; - if (hcnt_2x == 0) - vcnt_2x <= vcnt_2x + 1'b1; - + if (hcnt_2x == 0) + vcnt_2x <= vcnt_2x + 1'b1; + if ((pclk_1x == 1'b0) & (fpga_vsyncgen[`VSYNCGEN_GENMID_BIT] == 1'b1)) begin if (`VSYNC_TRAILING_EDGE) @@ -510,11 +563,11 @@ begin lines_2x <= vcnt_2x; end end - else if ((pclk_1x == 1'b0) & `VSYNC_TRAILING_EDGE & !(`FALSE_FIELD)) //sync with posedge of pclk_1x - begin - vcnt_2x <= 0; - lines_2x <= vcnt_2x; - end + else if ((pclk_1x == 1'b0) & `VSYNC_TRAILING_EDGE & !(`FALSE_FIELD)) //sync with posedge of pclk_1x + begin + vcnt_2x <= 0; + lines_2x <= vcnt_2x; + end if (pclk_1x == 1'b0) begin @@ -524,159 +577,183 @@ begin VSYNC_2x <= VSYNC_in; end - HSYNC_2x <= ~(hcnt_2x >= HSYNC_start); - //TODO: VSYNC_2x - h_enable_2x <= ((hcnt_2x >= H_BACKPORCH) & (hcnt_2x < H_BACKPORCH + H_ACTIVE)); - v_enable_2x <= ((vcnt_2x >= (V_BACKPORCH<<1)) & (vcnt_2x < ((V_BACKPORCH + V_ACTIVE)<<1))); - end + HSYNC_2x <= ~(hcnt_2x >= HSYNC_start); + //TODO: VSYNC_2x + h_enable_2x <= ((hcnt_2x >= H_BACKPORCH) & (hcnt_2x < H_BACKPORCH + H_ACTIVE)); + v_enable_2x <= ((vcnt_2x >= (V_BACKPORCH<<1)) & (vcnt_2x < ((V_BACKPORCH + V_ACTIVE)<<1))); + end end //Generate 3x signals for linetriple M0 -always @(posedge pclk_3x /*or negedge reset_n*/) +always @(posedge pclk_3x or negedge reset_n) begin - /*if (!reset_n) - begin - end - else*/ - begin - if ((pclk_3x_cnt == 0) & `HSYNC_TRAILING_EDGE) //sync with posedge of pclk_1x - hcnt_3x <= 0; - else if (hcnt_3x == hmax[~line_idx]) //line_idx_prev? - hcnt_3x <= 0; - else - hcnt_3x <= hcnt_3x + 1'b1; + if (!reset_n) + begin + hcnt_3x <= 0; + vcnt_3x <= 0; + lines_3x <= 0; + HSYNC_3x <= 0; + h_enable_3x <= 0; + v_enable_3x <= 0; + pclk_3x_cnt <= 0; + pclk_1x_prev3x <= 0; + end + else + begin + if ((pclk_3x_cnt == 0) & `HSYNC_TRAILING_EDGE) //sync with posedge of pclk_1x + hcnt_3x <= 0; + else if (hcnt_3x == hmax[~line_idx]) //line_idx_prev? + hcnt_3x <= 0; + else + hcnt_3x <= hcnt_3x + 1'b1; - if (hcnt_3x == 0) - vcnt_3x <= vcnt_3x + 1'b1; - - if ((pclk_3x_cnt == 0) & `VSYNC_TRAILING_EDGE & !(`FALSE_FIELD)) //sync with posedge of pclk_1x - begin - vcnt_3x <= 0; - lines_3x <= vcnt_3x; - end - - HSYNC_3x <= ~(hcnt_3x >= HSYNC_start); - //TODO: VSYNC_3x - h_enable_3x <= ((hcnt_3x >= H_BACKPORCH) & (hcnt_3x < H_BACKPORCH + H_ACTIVE)); - v_enable_3x <= ((vcnt_3x >= (3*V_BACKPORCH)) & (vcnt_3x < (3*(V_BACKPORCH + V_ACTIVE)))); //multiplier generated!!! - - //read pclk_1x to examine when edges are synced (pclk_1x=1 @ 120deg & pclk_1x=0 @ 240deg) - if (((pclk_1x_prev3x == 1'b1) & (pclk_1x == 1'b0)) | (pclk_3x_cnt == 2'h2)) - pclk_3x_cnt <= 0; - else - pclk_3x_cnt <= pclk_3x_cnt + 1'b1; - - pclk_1x_prev3x <= pclk_1x; - end + if (hcnt_3x == 0) + vcnt_3x <= vcnt_3x + 1'b1; + + if ((pclk_3x_cnt == 0) & `VSYNC_TRAILING_EDGE & !(`FALSE_FIELD)) //sync with posedge of pclk_1x + begin + vcnt_3x <= 0; + lines_3x <= vcnt_3x; + end + + HSYNC_3x <= ~(hcnt_3x >= HSYNC_start); + //TODO: VSYNC_3x + h_enable_3x <= ((hcnt_3x >= H_BACKPORCH) & (hcnt_3x < H_BACKPORCH + H_ACTIVE)); + v_enable_3x <= ((vcnt_3x >= (3*V_BACKPORCH)) & (vcnt_3x < (3*(V_BACKPORCH + V_ACTIVE)))); //multiplier generated!!! + + //read pclk_1x to examine when edges are synced (pclk_1x=1 @ 120deg & pclk_1x=0 @ 240deg) + if (((pclk_1x_prev3x == 1'b1) & (pclk_1x == 1'b0)) | (pclk_3x_cnt == 2'h2)) + pclk_3x_cnt <= 0; + else + pclk_3x_cnt <= pclk_3x_cnt + 1'b1; + + pclk_1x_prev3x <= pclk_1x; + end end //Generate 4x signals for linetriple M1 -always @(posedge pclk_4x /*or negedge reset_n*/) +always @(posedge pclk_4x or negedge reset_n) begin - /*if (!reset_n) - begin - end - else*/ - begin - // Can we sync reliably to h_enable_3x??? - if ((h_enable_3x == 1) & (h_enable_3x_prev4x == 0)) - hcnt_4x <= hcnt_3x - 160; - else - hcnt_4x <= hcnt_4x + 1'b1; - - h_enable_3x_prev4x <= h_enable_3x; - end + if (!reset_n) + begin + hcnt_4x <= 0; + h_enable_3x_prev4x <= 0; + end + else + begin + // Can we sync reliably to h_enable_3x??? + if ((h_enable_3x == 1) & (h_enable_3x_prev4x == 0)) + hcnt_4x <= hcnt_3x - 160; + else + hcnt_4x <= hcnt_4x + 1'b1; + + h_enable_3x_prev4x <= h_enable_3x; + end end //Generate 3x_h1x signals for linetriple M2 and M3 -always @(posedge pclk_3x_h1x /*or negedge reset_n*/) +always @(posedge pclk_3x_h1x or negedge reset_n) begin - /*if (!reset_n) - begin - end - else*/ - begin - if ((pclk_3x_h1x_cnt == 0) & `HSYNC_TRAILING_EDGE) //sync with posedge of pclk_1x - hcnt_3x_h1x <= 0; - else if (hcnt_3x_h1x == hmax[~line_idx]) //line_idx_prev? - hcnt_3x_h1x <= 0; - else - hcnt_3x_h1x <= hcnt_3x_h1x + 1'b1; + if (!reset_n) + begin + hcnt_3x_h1x <= 0; + vcnt_3x_h1x <= 0; + lines_3x_h1x <= 0; + HSYNC_3x_h1x <= 0; + h_enable_3x_h1x <= 0; + v_enable_3x_h1x <= 0; + pclk_3x_h1x_cnt <= 0; + pclk_1x_prev3x_h1x <= 0; + end + else + begin + if ((pclk_3x_h1x_cnt == 0) & `HSYNC_TRAILING_EDGE) //sync with posedge of pclk_1x + hcnt_3x_h1x <= 0; + else if (hcnt_3x_h1x == hmax[~line_idx]) //line_idx_prev? + hcnt_3x_h1x <= 0; + else + hcnt_3x_h1x <= hcnt_3x_h1x + 1'b1; - if (hcnt_3x_h1x == 0) - vcnt_3x_h1x <= vcnt_3x_h1x + 1'b1; - - if ((pclk_3x_h1x_cnt == 0) & `VSYNC_TRAILING_EDGE & !(`FALSE_FIELD)) //sync with posedge of pclk_1x - begin - vcnt_3x_h1x <= 0; - lines_3x_h1x <= vcnt_3x_h1x; - end - - HSYNC_3x_h1x <= ~(hcnt_3x_h1x >= HSYNC_start); - //TODO: VSYNC_3x_h1x - h_enable_3x_h1x <= ((hcnt_3x_h1x >= H_BACKPORCH) & (hcnt_3x_h1x < H_BACKPORCH + H_ACTIVE)); - v_enable_3x_h1x <= ((vcnt_3x_h1x >= (3*V_BACKPORCH)) & (vcnt_3x_h1x < (3*(V_BACKPORCH + V_ACTIVE)))); //multiplier generated!!! - - //read pclk_1x to examine when edges are synced (pclk_1x=1 @ 120deg & pclk_1x=0 @ 240deg) - if (((pclk_1x_prev3x_h1x == 1'b1) & (pclk_1x == 1'b0)) | (pclk_3x_h1x_cnt == 2'h2)) - pclk_3x_h1x_cnt <= 0; - else - pclk_3x_h1x_cnt <= pclk_3x_h1x_cnt + 1'b1; - - pclk_1x_prev3x_h1x <= pclk_1x; - end + if (hcnt_3x_h1x == 0) + vcnt_3x_h1x <= vcnt_3x_h1x + 1'b1; + + if ((pclk_3x_h1x_cnt == 0) & `VSYNC_TRAILING_EDGE & !(`FALSE_FIELD)) //sync with posedge of pclk_1x + begin + vcnt_3x_h1x <= 0; + lines_3x_h1x <= vcnt_3x_h1x; + end + + HSYNC_3x_h1x <= ~(hcnt_3x_h1x >= HSYNC_start); + //TODO: VSYNC_3x_h1x + h_enable_3x_h1x <= ((hcnt_3x_h1x >= H_BACKPORCH) & (hcnt_3x_h1x < H_BACKPORCH + H_ACTIVE)); + v_enable_3x_h1x <= ((vcnt_3x_h1x >= (3*V_BACKPORCH)) & (vcnt_3x_h1x < (3*(V_BACKPORCH + V_ACTIVE)))); //multiplier generated!!! + + //read pclk_1x to examine when edges are synced (pclk_1x=1 @ 120deg & pclk_1x=0 @ 240deg) + if (((pclk_1x_prev3x_h1x == 1'b1) & (pclk_1x == 1'b0)) | (pclk_3x_h1x_cnt == 2'h2)) + pclk_3x_h1x_cnt <= 0; + else + pclk_3x_h1x_cnt <= pclk_3x_h1x_cnt + 1'b1; + + pclk_1x_prev3x_h1x <= pclk_1x; + end end //Generate 3x_h4x signals for for linetriple M2 -always @(posedge pclk_3x_h4x /*or negedge reset_n*/) +always @(posedge pclk_3x_h4x or negedge reset_n) begin - /*if (!reset_n) - begin - end - else*/ - begin - // Can we sync reliably to h_enable_3x??? - if ((h_enable_3x_h1x == 1) & (h_enable_3x_prev3x_h4x == 0)) - hcnt_3x_h4x <= hcnt_3x_h1x - (160/3); - else if (hcnt_3x_h4x_ctr == 2'h0) - hcnt_3x_h4x <= hcnt_3x_h4x + 1'b1; + if (!reset_n) + begin + hcnt_3x_h4x <= 0; + hcnt_3x_h4x_ctr <= 0; + h_enable_3x_prev3x_h4x <= 0; + end + else + begin + // Can we sync reliably to h_enable_3x??? + if ((h_enable_3x_h1x == 1) & (h_enable_3x_prev3x_h4x == 0)) + hcnt_3x_h4x <= hcnt_3x_h1x - (160/3); + else if (hcnt_3x_h4x_ctr == 2'h0) + hcnt_3x_h4x <= hcnt_3x_h4x + 1'b1; - if ((h_enable_3x_h1x == 1) & (h_enable_3x_prev3x_h4x == 0)) - hcnt_3x_h4x_ctr <= 2'h1; - else if (hcnt_3x_h4x_ctr == 2'h2) - hcnt_3x_h4x_ctr <= 2'h0; - else - hcnt_3x_h4x_ctr <= hcnt_3x_h4x_ctr + 1'b1; - - h_enable_3x_prev3x_h4x <= h_enable_3x_h1x; - end + if ((h_enable_3x_h1x == 1) & (h_enable_3x_prev3x_h4x == 0)) + hcnt_3x_h4x_ctr <= 2'h1; + else if (hcnt_3x_h4x_ctr == 2'h2) + hcnt_3x_h4x_ctr <= 2'h0; + else + hcnt_3x_h4x_ctr <= hcnt_3x_h4x_ctr + 1'b1; + + h_enable_3x_prev3x_h4x <= h_enable_3x_h1x; + end end //Generate 3x_h5x signals for for linetriple M3 -always @(posedge pclk_3x_h5x /*or negedge reset_n*/) +always @(posedge pclk_3x_h5x or negedge reset_n) begin - /*if (!reset_n) - begin - end - else*/ - begin - // Can we sync reliably to h_enable_3x??? - if ((h_enable_3x_h1x == 1) & (h_enable_3x_prev3x_h5x == 0)) - hcnt_3x_h5x <= hcnt_3x_h1x - (128/4); - else if (hcnt_3x_h5x_ctr == 2'h0) - hcnt_3x_h5x <= hcnt_3x_h5x + 1'b1; + if (!reset_n) + begin + hcnt_3x_h5x <= 0; + hcnt_3x_h5x_ctr <= 0; + h_enable_3x_prev3x_h5x <= 0; + end + else + begin + // Can we sync reliably to h_enable_3x??? + if ((h_enable_3x_h1x == 1) & (h_enable_3x_prev3x_h5x == 0)) + hcnt_3x_h5x <= hcnt_3x_h1x - (128/4); + else if (hcnt_3x_h5x_ctr == 2'h0) + hcnt_3x_h5x <= hcnt_3x_h5x + 1'b1; - if ((h_enable_3x_h1x == 1) & (h_enable_3x_prev3x_h5x == 0)) - hcnt_3x_h5x_ctr <= 2'h2; - else - hcnt_3x_h5x_ctr <= hcnt_3x_h5x_ctr + 1'b1; - - h_enable_3x_prev3x_h5x <= h_enable_3x_h1x; - end + if ((h_enable_3x_h1x == 1) & (h_enable_3x_prev3x_h5x == 0)) + hcnt_3x_h5x_ctr <= 2'h2; + else + hcnt_3x_h5x_ctr <= hcnt_3x_h5x_ctr + 1'b1; + + h_enable_3x_prev3x_h5x <= h_enable_3x_h1x; + end end endmodule diff --git a/rtl/videogen.v b/rtl/videogen.v index 3e44597..2a275fc 100644 --- a/rtl/videogen.v +++ b/rtl/videogen.v @@ -1,5 +1,5 @@ // -// Copyright (C) 2015 Markus Hiienkari +// Copyright (C) 2015-2016 Markus Hiienkari // // This file is part of Open Source Scan Converter project. // @@ -18,29 +18,29 @@ // module videogen ( - input clk27, - input reset_n, - output [7:0] R_out, - output [7:0] G_out, - output [7:0] B_out, - output reg HSYNC_out, - output reg VSYNC_out, - output PCLK_out, - output reg ENABLE_out + input clk27, + input reset_n, + output [7:0] R_out, + output [7:0] G_out, + output [7:0] B_out, + output reg HSYNC_out, + output reg VSYNC_out, + output PCLK_out, + output reg ENABLE_out ); -//Parameters for 720x480@60Hz (858dots x 525lines), dotclk 27MHz -> 59.94Hz -parameter H_SYNCLEN = 62; -parameter H_BACKPORCH = 60; -parameter H_ACTIVE = 720; -parameter H_FRONTPORCH = 16; -parameter H_TOTAL = 858; +//Parameters for 720x480@59.94Hz (858px x 525lines, pclk 27MHz -> 59.94Hz) +parameter H_SYNCLEN = 62; +parameter H_BACKPORCH = 60; +parameter H_ACTIVE = 720; +parameter H_FRONTPORCH = 16; +parameter H_TOTAL = 858; -parameter V_SYNCLEN = 6; -parameter V_BACKPORCH = 30; -parameter V_ACTIVE = 480; -parameter V_FRONTPORCH = 9; -parameter V_TOTAL = 525; +parameter V_SYNCLEN = 6; +parameter V_BACKPORCH = 30; +parameter V_ACTIVE = 480; +parameter V_FRONTPORCH = 9; +parameter V_TOTAL = 525; parameter H_OVERSCAN = 40; //at both sides parameter V_OVERSCAN = 16; //top and bottom @@ -49,8 +49,8 @@ parameter V_AREA = 448; parameter H_BORDER = (H_AREA-512)/2; parameter V_BORDER = (V_AREA-256)/2; -parameter X_START = H_SYNCLEN + H_BACKPORCH; -parameter Y_START = V_SYNCLEN + V_BACKPORCH; +parameter X_START = H_SYNCLEN + H_BACKPORCH; +parameter Y_START = V_SYNCLEN + V_BACKPORCH; //Counters reg [9:0] h_cnt; //max. 1024 @@ -72,56 +72,56 @@ reg [7:0] V_gen; //HSYNC gen (negative polarity) always @(posedge clk27 or negedge reset_n) begin - if (!reset_n) - begin - h_cnt <= 0; - HSYNC_out <= 0; - end - else - begin - //Hsync counter - if (h_cnt < H_TOTAL-1 ) - h_cnt <= h_cnt + 1; - else - h_cnt <= 0; - - //Hsync signal - HSYNC_out <= (h_cnt < H_SYNCLEN) ? 0 : 1; - end + if (!reset_n) + begin + h_cnt <= 0; + HSYNC_out <= 0; + end + else + begin + //Hsync counter + if (h_cnt < H_TOTAL-1 ) + h_cnt <= h_cnt + 1; + else + h_cnt <= 0; + + //Hsync signal + HSYNC_out <= (h_cnt < H_SYNCLEN) ? 0 : 1; + end end //VSYNC gen (negative polarity) always @(posedge clk27 or negedge reset_n) begin - if (!reset_n) - begin - v_cnt <= 0; - VSYNC_out <= 0; - end - else - begin - if (h_cnt == 0) - begin - //Vsync counter - if (v_cnt < V_TOTAL-1 ) - v_cnt <= v_cnt + 1; - else - v_cnt <= 0; - - //Vsync signal - VSYNC_out <= (v_cnt < V_SYNCLEN) ? 0 : 1; - end - end + if (!reset_n) + begin + v_cnt <= 0; + VSYNC_out <= 0; + end + else + begin + if (h_cnt == 0) + begin + //Vsync counter + if (v_cnt < V_TOTAL-1 ) + v_cnt <= v_cnt + 1; + else + v_cnt <= 0; + + //Vsync signal + VSYNC_out <= (v_cnt < V_SYNCLEN) ? 0 : 1; + end + end end //Data gen always @(posedge clk27 or negedge reset_n) begin - if (!reset_n) - begin - V_gen <= 8'h00; - end - else + if (!reset_n) + begin + V_gen <= 8'h00; + end + else begin if ((h_cnt < X_START+H_OVERSCAN) || (h_cnt >= X_START+H_OVERSCAN+H_AREA) || (v_cnt < Y_START+V_OVERSCAN) || (v_cnt >= Y_START+V_OVERSCAN+V_AREA)) V_gen <= (h_cnt[0] ^ v_cnt[0]) ? 8'hff : 8'h00; @@ -137,11 +137,11 @@ end //Enable gen always @(posedge clk27 or negedge reset_n) begin - if (!reset_n) - begin - ENABLE_out <= 8'h00; - end - else + if (!reset_n) + begin + ENABLE_out <= 8'h00; + end + else begin ENABLE_out <= (h_cnt >= X_START && h_cnt < X_START + H_ACTIVE && v_cnt >= Y_START && v_cnt < Y_START + V_ACTIVE); end diff --git a/software/ossc_sw.project b/software/ossc_sw.project new file mode 100644 index 0000000..8a7ca77 --- /dev/null +++ b/software/ossc_sw.project @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + make clean + make APP_CFLAGS_DEFINED_SYMBOLS="-DDEBUG" + + + + None + $(ProjectPath)/sys_controller + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + make mem_init_generate + + make clean + make + + + + None + $(ProjectPath)/sys_controller + + + + + + + + + + + + + + diff --git a/software/sys_controller/av_controller.c b/software/sys_controller/av_controller.c index 1b5e8d4..fe61229 100644 --- a/software/sys_controller/av_controller.c +++ b/software/sys_controller/av_controller.c @@ -1,5 +1,5 @@ // -// Copyright (C) 2015 Markus Hiienkari +// Copyright (C) 2015-2016 Markus Hiienkari // // This file is part of Open Source Scan Converter project. // @@ -36,7 +36,7 @@ #include "ci_crc.h" alt_u8 fw_ver_major = 0; -alt_u8 fw_ver_minor = 64; +alt_u8 fw_ver_minor = 67; #define FW_UPDATE_RETRIES 3 #define LINECNT_THOLD 1 @@ -46,21 +46,19 @@ alt_u8 fw_ver_minor = 64; #define MAINLOOP_SLEEP_US 10000 -// AV control word: -// [20:17] [16:13] [12:10] [9:8] [7] [6] [5:4] [3] [2] [1] [0] -// | H_MASK[3:0] | V_MASK[3:0] | SCANLINESTR[2:0] | RESERVED[1:0] | TVP_CLKSEL | SLEN | L3MODE[1:0] | L3EN || BTN3 | BTN2 | BTN1 | - -#define SCANLINESTR_MAX 0x07 -#define HV_MASK_MAX 0x0f -#define L3_MODE_MAX 3 -#define S480P_MODE_MAX 2 -#define SL_MODE_MAX 2 -#define SYNC_LPF_MAX 3 +#define SCANLINESTR_MAX 0x07 +#define HV_MASK_MAX 0x0f +#define L3_MODE_MAX 3 +#define S480P_MODE_MAX 2 +#define SL_MODE_MAX 2 +#define SYNC_LPF_MAX 3 #define VIDEO_LPF_MAX 5 -#define SAMPLER_PHASE_MIN -16 -#define SAMPLER_PHASE_MAX 15 +#define SAMPLER_PHASE_MIN -16 +#define SAMPLER_PHASE_MAX 15 +#define SYNC_THOLD_MIN -11 +#define SYNC_THOLD_MAX 20 -//#define TVP_CLKSEL_BIT (1<<7) +//#define TVP_CLKSEL_BIT (1<<7) #define RC_MASK 0x0000ffff #define PB_MASK 0x00030000 @@ -70,10 +68,10 @@ alt_u8 fw_ver_minor = 64; static const char *rc_keydesc[] = { "1", "2", "3", "MENU", "BACK", "UP", "DOWN", "LEFT", "RIGHT", "INFO", "LCD_BACKLIGHT", "HOTKEY1", "HOTKEY2", "HOTKEY3"}; #define REMOTE_MAX_KEYS (sizeof(rc_keydesc)/sizeof(char*)) -alt_u16 rc_keymap[REMOTE_MAX_KEYS] = {0x2088, 0x2048, 0x20c8, 0x2008, 0x20d8, 0x2000, 0x2080, 0x20c0, 0x2040, 0x2058, 0x2010, 0x20e8, 0x2018, 0x2098}; +alt_u16 rc_keymap[REMOTE_MAX_KEYS] = {0x3E29, 0x3EA9, 0x3E69, 0x3E4D, 0x3EED, 0x3E2D, 0x3ECD, 0x3EAD, 0x3E6D, 0x3E65, 0x3E01, 0x3EC1, 0x3E41, 0x3EA1}; typedef enum { - RC_BTN1 = 0, + RC_BTN1 = 0, RC_BTN2, RC_BTN3, RC_MENU, @@ -100,70 +98,74 @@ static const char *sync_lpf_desc[] = { "Off", "33MHz", "10MHz", "2.5MHz" }; static const char *video_lpf_desc[] = { "Auto", "Off", "95MHz (HDTV II)", "35MHz (HDTV I)", "16MHz (EDTV)", "9MHz (SDTV)" }; typedef enum { - AV_KEEP = 0, - AV1_RGBs = 1, - AV1_RGsB = 2, - AV2_YPBPR = 3, - AV2_RGsB = 4, - AV3_RGBHV = 5, - AV3_RGBs = 6, - AV3_RGsB = 7 + AV_KEEP = 0, + AV1_RGBs = 1, + AV1_RGsB = 2, + AV2_YPBPR = 3, + AV2_RGsB = 4, + AV3_RGBHV = 5, + AV3_RGBs = 6, + AV3_RGsB = 7 } avinput_t; // In reverse order of importance typedef enum { - NO_CHANGE = 0, - INFO_CHANGE = 1, - MODE_CHANGE = 2, - TX_MODE_CHANGE = 3, - ACTIVITY_CHANGE = 4 + NO_CHANGE = 0, + INFO_CHANGE = 1, + MODE_CHANGE = 2, + TX_MODE_CHANGE = 3, + ACTIVITY_CHANGE = 4 } status_t; typedef enum { - SCANLINE_MODE, - SCANLINE_STRENGTH, - SCANLINE_ID, - H_MASK, - V_MASK, - SAMPLER_480P, - SAMPLER_PHASE, - YPBPR_COLORSPACE, - SYNC_LPF, - VIDEO_LPF, - LINETRIPLE_ENABLE, - LINETRIPLE_MODE, - TX_MODE, - FW_UPDATE, + SCANLINE_MODE, + SCANLINE_STRENGTH, + SCANLINE_ID, + H_MASK, + V_MASK, + SAMPLER_480P, + SAMPLER_PHASE, + YPBPR_COLORSPACE, + SYNC_THOLD, + SYNC_LPF, + VIDEO_LPF, + LINETRIPLE_ENABLE, + LINETRIPLE_MODE, + TX_MODE, +#ifndef DEBUG + FW_UPDATE, +#endif SAVE_CONFIG } menuitem_id; typedef enum { - NO_ACTION = 0, - NEXT_PAGE = 1, - PREV_PAGE = 2, - VAL_PLUS = 3, - VAL_MINUS = 4, + NO_ACTION = 0, + NEXT_PAGE = 1, + PREV_PAGE = 2, + VAL_PLUS = 3, + VAL_MINUS = 4, } menucode_id; typedef enum { - TX_HDMI = 0, - TX_DVI = 1 + TX_HDMI = 0, + TX_DVI = 1 } tx_mode_t; typedef struct { alt_u8 sl_mode; - alt_u8 sl_str; - alt_u8 sl_id; - alt_u8 linemult_target; - alt_u8 l3_mode; - alt_u8 h_mask; - alt_u8 v_mask; - alt_u8 tx_mode; - alt_u8 s480p_mode; - alt_8 sampler_phase; - alt_u8 ypbpr_cs; - alt_u8 sync_lpf; - alt_u8 video_lpf; + alt_u8 sl_str; + alt_u8 sl_id; + alt_u8 linemult_target; + alt_u8 l3_mode; + alt_u8 h_mask; + alt_u8 v_mask; + alt_u8 tx_mode; + alt_u8 s480p_mode; + alt_8 sampler_phase; + alt_u8 ypbpr_cs; + alt_8 sync_thold; + alt_u8 sync_lpf; + alt_u8 video_lpf; } avconfig_t; // Target configuration @@ -171,7 +173,7 @@ avconfig_t tc; //TODO: transform binary values into flags typedef struct { - alt_u32 totlines; + alt_u32 totlines; alt_u32 clkcnt; alt_u8 progressive; alt_u8 macrovis; @@ -193,23 +195,24 @@ typedef struct { } menuitem_t; const menuitem_t menu[] = { - { SCANLINE_MODE, "Scanlines" }, - { SCANLINE_STRENGTH, "Scanline str." }, - { SCANLINE_ID, "Scanline id" }, - { H_MASK, "Horizontal mask" }, - { V_MASK, "Vertical mask" }, - { SAMPLER_480P, "480p in sampler" }, - { SAMPLER_PHASE, "Sampling phase" }, - { YPBPR_COLORSPACE, "YPbPr in ColSpa" }, - { SYNC_LPF, "Analog sync LPF" }, - { VIDEO_LPF, "Video LPF" }, - { LINETRIPLE_ENABLE, "240p linetriple" }, - { LINETRIPLE_MODE, "Linetriple mode" }, - { TX_MODE, "TX mode" }, -//#ifndef DEBUG - { FW_UPDATE, "Firmware update" }, -//#endif - { SAVE_CONFIG, "Save settings" }, + { SCANLINE_MODE, "Scanlines" }, + { SCANLINE_STRENGTH, "Scanline str." }, + { SCANLINE_ID, "Scanline id" }, + { H_MASK, "Horizontal mask" }, + { V_MASK, "Vertical mask" }, + { SAMPLER_480P, "480p in sampler" }, + { SAMPLER_PHASE, "Sampling phase" }, + { YPBPR_COLORSPACE, "YPbPr in ColSpa" }, + { SYNC_THOLD, "Analog sync thld" }, + { SYNC_LPF, "Analog sync LPF" }, + { VIDEO_LPF, "Video LPF" }, + { LINETRIPLE_ENABLE, "240p/288p lineX3" }, + { LINETRIPLE_MODE, "Linetriple mode" }, + { TX_MODE, "TX mode" }, +#ifndef DEBUG + { FW_UPDATE, "Firmware update" }, +#endif + { SAVE_CONFIG, "Save settings" }, }; #define MENUITEMS (sizeof(menu)/sizeof(menuitem_t)) @@ -225,7 +228,7 @@ typedef struct { alt_u32 hdr_crc; } fw_hdr; -#define USERDATA_HDR_SIZE 11 +#define USERDATA_HDR_SIZE 11 typedef struct { char userdata_key[8]; alt_u8 version_major; @@ -233,15 +236,15 @@ typedef struct { alt_u8 num_entries; } userdata_hdr; -#define USERDATA_ENTRY_HDR_SIZE 2 +#define USERDATA_ENTRY_HDR_SIZE 2 typedef struct { alt_u8 type; alt_u8 entry_len; } userdata_entry; typedef enum { - UDE_REMOTE_MAP = 0, - UDE_AVCONFIG, + UDE_REMOTE_MAP = 0, + UDE_AVCONFIG, } userdata_entry_type; extern mode_data_t video_modes[]; @@ -273,27 +276,22 @@ alt_u8 menu_active, menu_page; alt_u32 remote_code, remote_code_prev; alt_u32 btn_code, btn_code_prev; -/*alt_u8 reverse_bits(alt_u8 b) { - b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; - b = (b & 0xCC) >> 2 | (b & 0x33) << 2; - b = (b & 0xAA) >> 1 | (b & 0x55) << 1; - return b; -}*/ +int check_flash() +{ + epcq_controller_dev = &epcq_controller_0; -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))) + if ((epcq_controller_dev == NULL) || !(epcq_controller_dev->is_epcs && (epcq_controller_dev->page_size == PAGESIZE))) return -1; - //printf("Flash size in bytes: %d\nSector size: %d (%d pages)\nPage size: %d\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); + //printf("Flash size in bytes: %d\nSector size: %d (%d pages)\nPage size: %d\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); - return 0; + return 0; } -int read_flash(alt_u32 offset, alt_u32 length, alt_u8 *dstbuf) { +int read_flash(alt_u32 offset, alt_u32 length, alt_u8 *dstbuf) +{ int retval, i; - + retval = alt_epcq_controller_read(&epcq_controller_dev->dev, offset, dstbuf, length); if (retval != 0) return -1; @@ -304,42 +302,44 @@ int read_flash(alt_u32 offset, alt_u32 length, alt_u8 *dstbuf) { return 0; } -int write_flash_page(alt_u8 *pagedata, alt_u32 length, alt_u32 pagenum) { - int retval, i; +int write_flash_page(alt_u8 *pagedata, alt_u32 length, alt_u32 pagenum) +{ + int retval, i; - if ((pagenum % PAGES_PER_SECTOR) == 0) { - printf("Erasing sector %u\n", (unsigned)(pagenum/PAGES_PER_SECTOR)); - retval = alt_epcq_controller_erase_block(&epcq_controller_dev->dev, pagenum*PAGESIZE); + if ((pagenum % PAGES_PER_SECTOR) == 0) { + printf("Erasing sector %u\n", (unsigned)(pagenum/PAGES_PER_SECTOR)); + 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); + 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; - } - } + printf("Flash erase error, sector %u\nRetval %d\n", (unsigned)(pagenum/PAGES_PER_SECTOR), retval); + return -200; + } + } // Bit-reverse bytes for flash for (i=0; i> 24; - retval = alt_epcq_controller_write_block(&epcq_controller_dev->dev, (pagenum/PAGES_PER_SECTOR)*PAGES_PER_SECTOR*PAGESIZE, pagenum*PAGESIZE, pagedata, length); + 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); + 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 retval; + return retval; } -int verify_flash(alt_u32 offset, alt_u32 length, alt_u32 golden_crc, alt_u8 *tmpbuf) { +int verify_flash(alt_u32 offset, alt_u32 length, alt_u32 golden_crc, alt_u8 *tmpbuf) +{ alt_u32 crcval=0, i, bytes_to_read; int retval; - + for (i=0; ifw_key, (char*)databuf, 4); if (strncmp(hdr->fw_key, "OSSC", 4)) { sniprintf(menu_row1, LCD_ROW_LEN+1, "Invalid image"); @@ -438,10 +441,11 @@ int check_fw_header(alt_u8 *databuf, fw_hdr *hdr) { return 0; } -int check_fw_image(alt_u32 offset, alt_u32 size, alt_u32 golden_crc, alt_u8 *tmpbuf) { +int check_fw_image(alt_u32 offset, alt_u32 size, alt_u32 golden_crc, alt_u8 *tmpbuf) +{ alt_u32 crcval=0, i, bytes_to_read; int retval; - + for (i=0; i 0)) - tc.sl_mode--; - else if ((code == VAL_PLUS) && (tc.sl_mode < SL_MODE_MAX)) - tc.sl_mode++; - strncpy(menu_row2, sl_mode_desc[tc.sl_mode], LCD_ROW_LEN+1); - break; - case SCANLINE_STRENGTH: - if ((code == VAL_MINUS) && (tc.sl_str > 0)) - tc.sl_str--; - else if ((code == VAL_PLUS) && (tc.sl_str < SCANLINESTR_MAX)) - tc.sl_str++; - sniprintf(menu_row2, LCD_ROW_LEN+1, "%u%%", ((tc.sl_str+1)*125)/10); - break; - case SCANLINE_ID: - if ((code == VAL_MINUS) || (code == VAL_PLUS)) - tc.sl_id = !tc.sl_id; - sniprintf(menu_row2, LCD_ROW_LEN+1, tc.sl_id ? "Odd" : "Even"); - break; - case H_MASK: - if ((code == VAL_MINUS) && (tc.h_mask > 0)) - tc.h_mask--; - else if ((code == VAL_PLUS) && (tc.h_mask < HV_MASK_MAX)) - tc.h_mask++; - sniprintf(menu_row2, LCD_ROW_LEN+1, "%u pixels", tc.h_mask<<2); - break; - case V_MASK: - if ((code == VAL_MINUS) && (tc.v_mask > 0)) - tc.v_mask--; - else if ((code == VAL_PLUS) && (tc.v_mask < HV_MASK_MAX)) - tc.v_mask++; - sniprintf(menu_row2, LCD_ROW_LEN+1, "%u pixels", tc.v_mask<<2); - break; - case SAMPLER_480P: - if ((code == VAL_MINUS) && (tc.s480p_mode > 0)) - tc.s480p_mode--; - else if ((code == VAL_PLUS) && (tc.s480p_mode < S480P_MODE_MAX)) - tc.s480p_mode++; - strncpy(menu_row2, s480p_desc[tc.s480p_mode], LCD_ROW_LEN+1); - break; - case SAMPLER_PHASE: - if ((code == VAL_MINUS) && (tc.sampler_phase > SAMPLER_PHASE_MIN)) - tc.sampler_phase--; - else if ((code == VAL_PLUS) && (tc.sampler_phase < SAMPLER_PHASE_MAX)) - tc.sampler_phase++; - sniprintf(menu_row2, LCD_ROW_LEN+1, "%d deg", ((tc.sampler_phase-SAMPLER_PHASE_MIN)*1125)/100); - break; - case YPBPR_COLORSPACE: - if ((code == VAL_MINUS) || (code == VAL_PLUS)) - tc.ypbpr_cs = !tc.ypbpr_cs; - strncpy(menu_row2, csc_coeffs[tc.ypbpr_cs].name, LCD_ROW_LEN+1); - break; - case SYNC_LPF: - if ((code == VAL_MINUS) && (tc.sync_lpf > 0)) - tc.sync_lpf--; - else if ((code == VAL_PLUS) && (tc.sync_lpf < SYNC_LPF_MAX)) - tc.sync_lpf++; - strncpy(menu_row2, sync_lpf_desc[tc.sync_lpf], LCD_ROW_LEN+1); - break; - case VIDEO_LPF: - if ((code == VAL_MINUS) && (tc.video_lpf > 0)) - tc.video_lpf--; - else if ((code == VAL_PLUS) && (tc.video_lpf < VIDEO_LPF_MAX)) - tc.video_lpf++; - strncpy(menu_row2, video_lpf_desc[tc.video_lpf], LCD_ROW_LEN+1); - break; - case LINETRIPLE_ENABLE: - if ((code == VAL_MINUS) || (code == VAL_PLUS)) - tc.linemult_target = !tc.linemult_target; - sniprintf(menu_row2, LCD_ROW_LEN+1, tc.linemult_target ? "On" : "Off"); - break; - case LINETRIPLE_MODE: - if ((code == VAL_MINUS) && (tc.l3_mode > 0)) - tc.l3_mode--; - else if ((code == VAL_PLUS) && (tc.l3_mode < L3_MODE_MAX)) - tc.l3_mode++; - strncpy(menu_row2, l3_mode_desc[tc.l3_mode], LCD_ROW_LEN+1); - break; - case TX_MODE: - if (!(IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & HDMITX_MODE_MASK) && ((code == VAL_MINUS) || (code == VAL_PLUS))) { - tc.tx_mode = !tc.tx_mode; - TX_enable(tc.tx_mode); + switch (menu[menu_page].id) { + case SCANLINE_MODE: + if ((code == VAL_MINUS) && (tc.sl_mode > 0)) + tc.sl_mode--; + else if ((code == VAL_PLUS) && (tc.sl_mode < SL_MODE_MAX)) + tc.sl_mode++; + strncpy(menu_row2, sl_mode_desc[tc.sl_mode], LCD_ROW_LEN+1); + break; + case SCANLINE_STRENGTH: + if ((code == VAL_MINUS) && (tc.sl_str > 0)) + tc.sl_str--; + else if ((code == VAL_PLUS) && (tc.sl_str < SCANLINESTR_MAX)) + tc.sl_str++; + sniprintf(menu_row2, LCD_ROW_LEN+1, "%u%%", ((tc.sl_str+1)*125)/10); + break; + case SCANLINE_ID: + if ((code == VAL_MINUS) || (code == VAL_PLUS)) + tc.sl_id = !tc.sl_id; + sniprintf(menu_row2, LCD_ROW_LEN+1, tc.sl_id ? "Odd" : "Even"); + break; + case H_MASK: + if ((code == VAL_MINUS) && (tc.h_mask > 0)) + tc.h_mask--; + else if ((code == VAL_PLUS) && (tc.h_mask < HV_MASK_MAX)) + tc.h_mask++; + sniprintf(menu_row2, LCD_ROW_LEN+1, "%u pixels", tc.h_mask<<2); + break; + case V_MASK: + if ((code == VAL_MINUS) && (tc.v_mask > 0)) + tc.v_mask--; + else if ((code == VAL_PLUS) && (tc.v_mask < HV_MASK_MAX)) + tc.v_mask++; + sniprintf(menu_row2, LCD_ROW_LEN+1, "%u pixels", tc.v_mask<<2); + break; + case SAMPLER_480P: + if ((code == VAL_MINUS) && (tc.s480p_mode > 0)) + tc.s480p_mode--; + else if ((code == VAL_PLUS) && (tc.s480p_mode < S480P_MODE_MAX)) + tc.s480p_mode++; + strncpy(menu_row2, s480p_desc[tc.s480p_mode], LCD_ROW_LEN+1); + break; + case SAMPLER_PHASE: + if ((code == VAL_MINUS) && (tc.sampler_phase > SAMPLER_PHASE_MIN)) + tc.sampler_phase--; + else if ((code == VAL_PLUS) && (tc.sampler_phase < SAMPLER_PHASE_MAX)) + tc.sampler_phase++; + sniprintf(menu_row2, LCD_ROW_LEN+1, "%d deg", ((tc.sampler_phase-SAMPLER_PHASE_MIN)*1125)/100); + break; + case YPBPR_COLORSPACE: + if ((code == VAL_MINUS) || (code == VAL_PLUS)) + tc.ypbpr_cs = !tc.ypbpr_cs; + strncpy(menu_row2, csc_coeffs[tc.ypbpr_cs].name, LCD_ROW_LEN+1); + break; + case SYNC_THOLD: + if ((code == VAL_MINUS) && (tc.sync_thold > SYNC_THOLD_MIN)) + tc.sync_thold--; + else if ((code == VAL_PLUS) && (tc.sync_thold < SYNC_THOLD_MAX)) + tc.sync_thold++; + sniprintf(menu_row2, LCD_ROW_LEN+1, "%d mV", ((tc.sync_thold-SYNC_THOLD_MIN)*1127)/100); + break; + case SYNC_LPF: + if ((code == VAL_MINUS) && (tc.sync_lpf > 0)) + tc.sync_lpf--; + else if ((code == VAL_PLUS) && (tc.sync_lpf < SYNC_LPF_MAX)) + tc.sync_lpf++; + strncpy(menu_row2, sync_lpf_desc[tc.sync_lpf], LCD_ROW_LEN+1); + break; + case VIDEO_LPF: + if ((code == VAL_MINUS) && (tc.video_lpf > 0)) + tc.video_lpf--; + else if ((code == VAL_PLUS) && (tc.video_lpf < VIDEO_LPF_MAX)) + tc.video_lpf++; + strncpy(menu_row2, video_lpf_desc[tc.video_lpf], LCD_ROW_LEN+1); + break; + case LINETRIPLE_ENABLE: + if ((code == VAL_MINUS) || (code == VAL_PLUS)) + tc.linemult_target = !tc.linemult_target; + sniprintf(menu_row2, LCD_ROW_LEN+1, tc.linemult_target ? "On" : "Off"); + break; + case LINETRIPLE_MODE: + if ((code == VAL_MINUS) && (tc.l3_mode > 0)) + tc.l3_mode--; + else if ((code == VAL_PLUS) && (tc.l3_mode < L3_MODE_MAX)) + tc.l3_mode++; + strncpy(menu_row2, l3_mode_desc[tc.l3_mode], LCD_ROW_LEN+1); + break; + case TX_MODE: + if (!(IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & HDMITX_MODE_MASK) && ((code == VAL_MINUS) || (code == VAL_PLUS))) { + tc.tx_mode = !tc.tx_mode; + TX_enable(tc.tx_mode); + } + sniprintf(menu_row2, LCD_ROW_LEN+1, tc.tx_mode ? "DVI" : "HDMI"); + break; +#ifndef DEBUG + case FW_UPDATE: + if ((code == VAL_MINUS) || (code == VAL_PLUS)) { + retval = fw_update(); + if (retval == 0) { + sniprintf(menu_row1, LCD_ROW_LEN+1, "Fw update OK"); + sniprintf(menu_row2, LCD_ROW_LEN+1, "Please restart"); + } else { + sniprintf(menu_row1, LCD_ROW_LEN+1, "FW not"); + sniprintf(menu_row2, LCD_ROW_LEN+1, "updated"); } - sniprintf(menu_row2, LCD_ROW_LEN+1, tc.tx_mode ? "DVI" : "HDMI"); - break; -//#ifndef DEBUG - case FW_UPDATE: - if ((code == VAL_MINUS) || (code == VAL_PLUS)) { - retval = fw_update(); - if (retval == 0) { - sniprintf(menu_row1, LCD_ROW_LEN+1, "Fw update OK"); - sniprintf(menu_row2, LCD_ROW_LEN+1, "Please restart"); - } else { - sniprintf(menu_row1, LCD_ROW_LEN+1, "FW not"); - sniprintf(menu_row2, LCD_ROW_LEN+1, "updated"); - } - } else { - sniprintf(menu_row2, LCD_ROW_LEN+1, "press <- or ->"); - } - break; -//#endif - case SAVE_CONFIG: - if ((code == VAL_MINUS) || (code == VAL_PLUS)) { - retval = write_userdata(); - if (retval == 0) { - sniprintf(menu_row2, LCD_ROW_LEN+1, "Done"); - } else { - sniprintf(menu_row2, LCD_ROW_LEN+1, "error"); - } - } else { - sniprintf(menu_row2, LCD_ROW_LEN+1, "press <- or ->"); - } - break; - default: - sniprintf(menu_row2, LCD_ROW_LEN+1, "MISSING ITEM"); - break; - } + } else { + sniprintf(menu_row2, LCD_ROW_LEN+1, "press <- or ->"); + } + break; +#endif + case SAVE_CONFIG: + if ((code == VAL_MINUS) || (code == VAL_PLUS)) { + retval = write_userdata(); + if (retval == 0) { + sniprintf(menu_row2, LCD_ROW_LEN+1, "Done"); + } else { + sniprintf(menu_row2, LCD_ROW_LEN+1, "error"); + } + } else { + sniprintf(menu_row2, LCD_ROW_LEN+1, "press <- or ->"); + } + break; + default: + sniprintf(menu_row2, LCD_ROW_LEN+1, "MISSING ITEM"); + break; + } - lcd_write_menu(); + lcd_write_menu(); - return; + return; } -void read_control() { - if (remote_code_prev == 0) { - if (remote_code == rc_keymap[RC_MENU]) { - menu_active = !menu_active; +void read_control() +{ + if (remote_code_prev == 0) { + if (remote_code == rc_keymap[RC_MENU]) { + menu_active = !menu_active; - if (menu_active) { - display_menu(1); - } else { - lcd_write_status(); - } - } else if (remote_code == rc_keymap[RC_BACK]) { + if (menu_active) { + display_menu(1); + } else { + lcd_write_status(); + } + } else if (remote_code == rc_keymap[RC_BACK]) { menu_active = 0; lcd_write_status(); } else if (remote_code == rc_keymap[RC_INFO]) { - sniprintf(menu_row1, LCD_ROW_LEN+1, "VMod: %s", video_modes[cm.id].name); - //sniprintf(menu_row1, LCD_ROW_LEN+1, "0x%x 0x%x 0x%x", ths_readreg(THS_CH1), ths_readreg(THS_CH2), ths_readreg(THS_CH3)); - sniprintf(menu_row2, LCD_ROW_LEN+1, "LO: %u VSM: %u", IORD_ALTERA_AVALON_PIO_DATA(PIO_4_BASE) & 0xffff, IORD_ALTERA_AVALON_PIO_DATA(PIO_4_BASE) >> 16); - lcd_write_menu(); - printf("Mod: %s\n", video_modes[cm.id].name); - printf("Lines: %u M: %u\n", IORD_ALTERA_AVALON_PIO_DATA(PIO_4_BASE) & 0xffff, cm.macrovis); + sniprintf(menu_row1, LCD_ROW_LEN+1, "VMod: %s", video_modes[cm.id].name); + //sniprintf(menu_row1, LCD_ROW_LEN+1, "0x%x 0x%x 0x%x", ths_readreg(THS_CH1), ths_readreg(THS_CH2), ths_readreg(THS_CH3)); + sniprintf(menu_row2, LCD_ROW_LEN+1, "LO: %u VSM: %u", IORD_ALTERA_AVALON_PIO_DATA(PIO_4_BASE) & 0xffff, (IORD_ALTERA_AVALON_PIO_DATA(PIO_4_BASE) >> 16) & 0x3); + lcd_write_menu(); + printf("Mod: %s\n", video_modes[cm.id].name); + printf("Lines: %u M: %u\n", IORD_ALTERA_AVALON_PIO_DATA(PIO_4_BASE) & 0xffff, cm.macrovis); } else if (remote_code == rc_keymap[RC_LCDBL]) { IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, (IORD_ALTERA_AVALON_PIO_DATA(PIO_0_BASE) ^ (1<<1))); } else if (remote_code == rc_keymap[RC_HOTKEY1]) { tc.sl_mode = (tc.sl_mode > 0) ? 0 : 1; } else if (remote_code == rc_keymap[RC_HOTKEY2]) { if (tc.sl_str > 0) - tc.sl_str--; + tc.sl_str--; } else if (remote_code == rc_keymap[RC_HOTKEY3]) { if (tc.sl_str < SCANLINESTR_MAX) - tc.sl_str++; + tc.sl_str++; } - } + } if (btn_code_prev == 0) { if (btn_code & PB1_MASK) tc.sl_mode = (tc.sl_mode > 0) ? 0 : 1; } - if (menu_active) { - display_menu(0); - return; - } + if (menu_active) { + display_menu(0); + return; + } - if (remote_code_prev != 0) - return; + if (remote_code_prev != 0) + return; } -void set_lpf(alt_u8 lpf) { +void set_lpf(alt_u8 lpf) +{ alt_u32 pclk; pclk = (clkrate[cm.refclk]/cm.clkcnt)*video_modes[cm.id].h_total; printf("PCLK: %uHz\n", pclk); - + //Auto if (lpf == 0) { switch (target_type) { case VIDEO_PC: tvp_set_lpf((pclk < 30000000) ? 0x0F : 0); ths_set_lpf(THS_LPF_BYPASS); - break; + break; case VIDEO_HDTV: tvp_set_lpf(0); ths_set_lpf(THS_LPF_BYPASS); - break; + break; case VIDEO_EDTV: tvp_set_lpf(0); ths_set_lpf(1); - break; + break; case VIDEO_SDTV: case VIDEO_LDTV: tvp_set_lpf(0); ths_set_lpf(0); - break; + break; default: - break; + break; } } else { tvp_set_lpf((tc.video_lpf == 2) ? 0x0F : 0); - ths_set_lpf((tc.video_lpf > 2) ? (VIDEO_LPF_MAX-tc.video_lpf) : THS_LPF_BYPASS); + ths_set_lpf((tc.video_lpf > 2) ? (VIDEO_LPF_MAX-tc.video_lpf) : THS_LPF_BYPASS); } } // Check if input video status / target configuration has changed -status_t get_status(tvp_input_t input) { - alt_u32 data1, data2; - alt_u32 totlines, clkcnt; - alt_u8 macrovis, progressive; - alt_u8 refclk; - alt_u8 sync_active; +status_t get_status(tvp_input_t input) +{ + alt_u32 data1, data2; + alt_u32 totlines, clkcnt; + alt_u8 progressive; + //alt_u8 refclk; + alt_u8 sync_active; alt_u8 vsyncmode; alt_u16 fpga_totlines; - status_t status; + status_t status; static alt_u8 act_ctr; + alt_u32 ctr; - status = NO_CHANGE; + status = NO_CHANGE; - sync_active = tvp_check_sync(input); + // Wait until vsync active (avoid noise coupled to I2C bus on earlier prototypes) + for (ctr=0; ctr<25000; ctr++) { + if (!(IORD_ALTERA_AVALON_PIO_DATA(PIO_4_BASE) & (1<<31))) { + //printf("ctrval %u\n", ctr); + break; + } + } + + sync_active = tvp_check_sync(input); vsyncmode = IORD_ALTERA_AVALON_PIO_DATA(PIO_4_BASE) >> 16; // TVP7002 may randomly report "no sync" (especially with arcade boards), // thus disable output only after N consecutive "no sync"-events - if (!cm.sync_active && sync_active) { + if (!cm.sync_active && sync_active) { cm.sync_active = sync_active; - status = ACTIVITY_CHANGE; + status = ACTIVITY_CHANGE; act_ctr = 0; } else if (cm.sync_active && !sync_active) { printf("Sync down in %u...\n", SYNC_LOSS_THOLD-act_ctr); if (act_ctr >= SYNC_LOSS_THOLD) { act_ctr = 0; cm.sync_active = sync_active; - status = ACTIVITY_CHANGE; + status = ACTIVITY_CHANGE; } else { act_ctr++; } } else { act_ctr = 0; } - - data1 = tvp_readreg(TVP_LINECNT1); - data2 = tvp_readreg(TVP_LINECNT2); - totlines = ((data2 & 0x0f) << 8) | data1; - progressive = !!(data2 & (1<<5)); - cm.macrovis = !!(data2 & (1<<6)); + + data1 = tvp_readreg(TVP_LINECNT1); + data2 = tvp_readreg(TVP_LINECNT2); + totlines = ((data2 & 0x0f) << 8) | data1; + progressive = !!(data2 & (1<<5)); + cm.macrovis = !!(data2 & (1<<6)); fpga_totlines = IORD_ALTERA_AVALON_PIO_DATA(PIO_4_BASE) & 0xffff; @@ -979,199 +1019,194 @@ status_t get_status(tvp_input_t input) { totlines = fpga_totlines; //ugly hack } - data1 = tvp_readreg(TVP_CLKCNT1); - data2 = tvp_readreg(TVP_CLKCNT2); - clkcnt = ((data2 & 0x0f) << 8) | data1; + data1 = tvp_readreg(TVP_CLKCNT1); + data2 = tvp_readreg(TVP_CLKCNT2); + clkcnt = ((data2 & 0x0f) << 8) | data1; - //Not fully implemented yet - /*refclk = !!(cword & TVP_CLKSEL_BIT); - refclk = 0; + //Not fully implemented yet + /*refclk = !!(cword & TVP_CLKSEL_BIT); + refclk = 0; - if (refclk != cm.refclk) - status = (status < REFCLK_CHANGE) ? REFCLK_CHANGE : status;*/ + if (refclk != cm.refclk) + status = (status < REFCLK_CHANGE) ? REFCLK_CHANGE : status;*/ - /*if (tc.tx_mode != cm.cc.tx_mode) - status = (status < TX_MODE_CHANGE) ? TX_MODE_CHANGE : status;*/ + /*if (tc.tx_mode != cm.cc.tx_mode) + status = (status < TX_MODE_CHANGE) ? TX_MODE_CHANGE : status;*/ - // TODO: avoid random sync losses? - if ((abs((alt_16)totlines - (alt_16)cm.totlines) > LINECNT_THOLD) || (clkcnt != cm.clkcnt) || (progressive != cm.progressive)) { + // TODO: avoid random sync losses? + if ((abs((alt_16)totlines - (alt_16)cm.totlines) > LINECNT_THOLD) || (clkcnt != cm.clkcnt) || (progressive != cm.progressive)) { printf("totlines: %u (cur) / %u (prev), clkcnt: %u (cur) / %u (prev). Data1: 0x%.2x, Data2: 0x%.2x\n", (unsigned)totlines, (unsigned)cm.totlines, (unsigned)clkcnt, (unsigned)cm.clkcnt, (unsigned)data1, (unsigned)data2); - stable_frames = 0; - } else if (stable_frames != STABLE_THOLD) { - stable_frames++; - if (stable_frames == STABLE_THOLD) - status = (status < MODE_CHANGE) ? MODE_CHANGE : status; - } + stable_frames = 0; + } else if (stable_frames != STABLE_THOLD) { + stable_frames++; + if (stable_frames == STABLE_THOLD) + status = (status < MODE_CHANGE) ? MODE_CHANGE : status; + } - if ((tc.linemult_target != cm.cc.linemult_target) || (tc.l3_mode != cm.cc.l3_mode)) - status = (status < MODE_CHANGE) ? MODE_CHANGE : status; + if ((tc.linemult_target != cm.cc.linemult_target) || (tc.l3_mode != cm.cc.l3_mode)) + status = (status < MODE_CHANGE) ? MODE_CHANGE : status; - if ((tc.s480p_mode != cm.cc.s480p_mode) && (video_modes[cm.id].flags & (MODE_DTV480P|MODE_VGA480P))) - status = (status < MODE_CHANGE) ? MODE_CHANGE : status; + if ((tc.s480p_mode != cm.cc.s480p_mode) && (video_modes[cm.id].flags & (MODE_DTV480P|MODE_VGA480P))) + status = (status < MODE_CHANGE) ? MODE_CHANGE : status; - cm.totlines = totlines; - cm.clkcnt = clkcnt; - cm.progressive = progressive; + cm.totlines = totlines; + cm.clkcnt = clkcnt; + cm.progressive = progressive; - if ((tc.sl_mode != cm.cc.sl_mode) || - (tc.sl_str != cm.cc.sl_str) || - (tc.sl_id != cm.cc.sl_id) || - (tc.h_mask != cm.cc.h_mask) || - (tc.v_mask != cm.cc.v_mask)) - status = (status < INFO_CHANGE) ? INFO_CHANGE : status; + if ((tc.sl_mode != cm.cc.sl_mode) || + (tc.sl_str != cm.cc.sl_str) || + (tc.sl_id != cm.cc.sl_id) || + (tc.h_mask != cm.cc.h_mask) || + (tc.v_mask != cm.cc.v_mask)) + status = (status < INFO_CHANGE) ? INFO_CHANGE : status; - if (tc.sampler_phase != cm.cc.sampler_phase) - tvp_set_hpll_phase(tc.sampler_phase-SAMPLER_PHASE_MIN); + if (tc.sampler_phase != cm.cc.sampler_phase) + tvp_set_hpll_phase(tc.sampler_phase-SAMPLER_PHASE_MIN); - if (tc.ypbpr_cs != cm.cc.ypbpr_cs) - tvp_sel_csc(&csc_coeffs[tc.ypbpr_cs]); + if (tc.sync_thold != cm.cc.sync_thold) + tvp_set_sog_thold(tc.sync_thold-SYNC_THOLD_MIN); - if (tc.video_lpf != cm.cc.video_lpf) - set_lpf(tc.video_lpf); + if (tc.ypbpr_cs != cm.cc.ypbpr_cs) + tvp_sel_csc(&csc_coeffs[tc.ypbpr_cs]); - if (tc.sync_lpf != cm.cc.sync_lpf) - tvp_set_sync_lpf(tc.sync_lpf); + if (tc.video_lpf != cm.cc.video_lpf) + set_lpf(tc.video_lpf); - // use memcpy instead? - cm.cc = tc; + if (tc.sync_lpf != cm.cc.sync_lpf) + tvp_set_sync_lpf(tc.sync_lpf); - return status; + // use memcpy instead? + cm.cc = tc; + + return status; } // h_info: [31:30] [29:28] [27] [26:16] [15:12] [11:8] [7:0] -// | H_LINEMULT[1:0] | H_L3MODE[1:0] | | H_ACTIVE[10:0] | | H_MASK[3:0] | H_BACKPORCH[7:0] | +// | H_LINEMULT[1:0] | H_L3MODE[1:0] | | H_ACTIVE[10:0] | | H_MASK[3:0] | H_BACKPORCH[7:0] | // // v_info: [31:30] [29] [26:24] [23:13] [15:10] [9:6] [5:0] -// | | V_SCANLINES | V_SCANLINEDIR | V_SCANLINEID | V_SCANLINESTR[2:0] | V_ACTIVE[10:0] | | V_MASK[3:0]| V_BACKPORCH[5:0] | -void set_videoinfo() { - alt_u8 slid_target; +// | | V_SCANLINES | V_SCANLINEDIR | V_SCANLINEID | V_SCANLINESTR[2:0] | V_ACTIVE[10:0] | | V_MASK[3:0]| V_BACKPORCH[5:0] | +void set_videoinfo() +{ + alt_u8 slid_target; - if (video_modes[cm.id].flags & MODE_L3ENABLE_MASK) { - cm.linemult = 2; - slid_target = cm.cc.sl_id ? 2 : 0; - } else if (video_modes[cm.id].flags & MODE_L2ENABLE) { - cm.linemult = 1; - slid_target = cm.cc.sl_id; - } else { - cm.linemult = 0; - slid_target = cm.cc.sl_id; - } + if (video_modes[cm.id].flags & MODE_L3ENABLE_MASK) { + cm.linemult = 2; + slid_target = cm.cc.sl_id ? 2 : 0; + } else if (video_modes[cm.id].flags & MODE_L2ENABLE) { + cm.linemult = 1; + slid_target = cm.cc.sl_id; + } else { + cm.linemult = 0; + slid_target = cm.cc.sl_id; + } IOWR_ALTERA_AVALON_PIO_DATA(PIO_2_BASE, (cm.linemult<<30) | (cm.cc.l3_mode<<28) | (video_modes[cm.id].h_active<<16) | (cm.cc.h_mask)<<8 | video_modes[cm.id].h_backporch); - IOWR_ALTERA_AVALON_PIO_DATA(PIO_3_BASE, ((!!cm.cc.sl_mode)<<29) | (cm.cc.sl_mode > 0 ? (cm.cc.sl_mode-1)<<28 : 0) | (slid_target<<27) | (cm.cc.sl_str<<24) | (video_modes[cm.id].v_active<<13) | (cm.cc.v_mask<<6) | video_modes[cm.id].v_backporch); + IOWR_ALTERA_AVALON_PIO_DATA(PIO_3_BASE, ((!!cm.cc.sl_mode)<<29) | (cm.cc.sl_mode > 0 ? (cm.cc.sl_mode-1)<<28 : 0) | (slid_target<<27) | (cm.cc.sl_str<<24) | (video_modes[cm.id].v_active<<13) | (cm.cc.v_mask<<6) | video_modes[cm.id].v_backporch); } // Configure TVP7002 and scan converter logic based on the video mode -void program_mode() { - alt_u32 data1, data2; - alt_u32 h_hz, v_hz_x100; +void program_mode() +{ + alt_u32 data1, data2; + alt_u32 h_hz, v_hz_x100; - // Mark as stable (needed after sync up to avoid unnecessary mode switch) - stable_frames = STABLE_THOLD; + // Mark as stable (needed after sync up to avoid unnecessary mode switch) + stable_frames = STABLE_THOLD; - if ((cm.clkcnt != 0) && (cm.totlines != 0)) { //prevent div by 0 - h_hz = clkrate[cm.refclk]/cm.clkcnt; - v_hz_x100 = cm.progressive ? (100*clkrate[cm.refclk]/cm.clkcnt)/cm.totlines : (2*(100*clkrate[cm.refclk]/cm.clkcnt))/cm.totlines; - } else { - h_hz = 15700; - v_hz_x100 = 6000; - } + if ((cm.clkcnt != 0) && (cm.totlines != 0)) { //prevent div by 0 + h_hz = clkrate[cm.refclk]/cm.clkcnt; + v_hz_x100 = cm.progressive ? (100*clkrate[cm.refclk]/cm.clkcnt)/cm.totlines : (2*(100*clkrate[cm.refclk]/cm.clkcnt))/cm.totlines; + } else { + h_hz = 15700; + v_hz_x100 = 6000; + } - printf("\nLines: %u %c\n", (unsigned)cm.totlines, cm.progressive ? 'p' : 'i'); - printf("Clocks per line: %u : HS %u.%.3u kHz VS %u.%.2u Hz\n", (unsigned)cm.clkcnt, (unsigned)(h_hz/1000), (unsigned)(h_hz%1000), (unsigned)(v_hz_x100/100), (unsigned)(v_hz_x100%100)); + printf("\nLines: %u %c\n", (unsigned)cm.totlines, cm.progressive ? 'p' : 'i'); + printf("Clocks per line: %u : HS %u.%.3u kHz VS %u.%.2u Hz\n", (unsigned)cm.clkcnt, (unsigned)(h_hz/1000), (unsigned)(h_hz%1000), (unsigned)(v_hz_x100/100), (unsigned)(v_hz_x100%100)); - data1 = tvp_readreg(TVP_HSINWIDTH); - data2 = tvp_readreg(TVP_VSINWIDTH); - printf("Hswidth: %u Vswidth: %u Macrovision: %u\n", (unsigned)data1, (unsigned)(data2 & 0x1F), (unsigned)cm.macrovis); + data1 = tvp_readreg(TVP_HSINWIDTH); + data2 = tvp_readreg(TVP_VSINWIDTH); + printf("Hswidth: %u Vswidth: %u Macrovision: %u\n", (unsigned)data1, (unsigned)(data2 & 0x1F), (unsigned)cm.macrovis); - //TODO: rewrite with strncpy to reduce code size - sniprintf(row1, LCD_ROW_LEN+1, "%s %u%c", avinput_str[cm.avinput], (unsigned)cm.totlines, cm.progressive ? 'p' : 'i'); - sniprintf(row2, LCD_ROW_LEN+1, "%u.%.2ukHz %u.%.2uHz", (unsigned)(h_hz/1000), (unsigned)((h_hz%1000)/10), (unsigned)(v_hz_x100/100), (unsigned)(v_hz_x100%100)); - //strncpy(row1, avinput_str[cm.avinput], LCD_ROW_LEN+1); - //strncpy(row2, avinput_str[cm.avinput], LCD_ROW_LEN+1); - if (!menu_active) - lcd_write_status(); + //TODO: rewrite with strncpy to reduce code size + sniprintf(row1, LCD_ROW_LEN+1, "%s %u%c", avinput_str[cm.avinput], (unsigned)cm.totlines, cm.progressive ? 'p' : 'i'); + sniprintf(row2, LCD_ROW_LEN+1, "%u.%.2ukHz %u.%.2uHz", (unsigned)(h_hz/1000), (unsigned)((h_hz%1000)/10), (unsigned)(v_hz_x100/100), (unsigned)(v_hz_x100%100)); + //strncpy(row1, avinput_str[cm.avinput], LCD_ROW_LEN+1); + //strncpy(row2, avinput_str[cm.avinput], LCD_ROW_LEN+1); + if (!menu_active) + lcd_write_status(); - //printf ("Get mode id with %u %u %f\n", totlines, progressive, hz); - cm.id = get_mode_id(cm.totlines, cm.progressive, v_hz_x100/100, target_typemask, cm.cc.linemult_target, cm.cc.l3_mode, cm.cc.s480p_mode); + //printf ("Get mode id with %u %u %f\n", totlines, progressive, hz); + cm.id = get_mode_id(cm.totlines, cm.progressive, v_hz_x100/100, target_typemask, cm.cc.linemult_target, cm.cc.l3_mode, cm.cc.s480p_mode); - if ( cm.id == -1) { - printf ("Error: no suitable mode found, defaulting to 240p\n"); - cm.id = 4; - } + if ( cm.id == -1) { + printf ("Error: no suitable mode found, defaulting to 240p\n"); + cm.id = 4; + } target_type = target_typemask & video_modes[cm.id].type; - printf("Mode %s selected\n", video_modes[cm.id].name); + printf("Mode %s selected\n", video_modes[cm.id].name); - tvp_source_setup(cm.id, target_type, (cm.progressive ? cm.totlines : cm.totlines/2), v_hz_x100/100, cm.refclk); + tvp_source_setup(cm.id, target_type, (cm.progressive ? cm.totlines : cm.totlines/2), v_hz_x100/100, cm.refclk); set_lpf(cm.cc.video_lpf); - set_videoinfo(); -} - -inline void TX_enable(tx_mode_t mode) { - //SetAVMute(TRUE); - if (mode == TX_HDMI) { - EnableVideoOutput(PCLK_MEDIUM, COLOR_RGB444, COLOR_RGB444, 1); - HDMITX_SetAVIInfoFrame(1, F_MODE_RGB444, 0, 0); - } else { - EnableVideoOutput(PCLK_MEDIUM, COLOR_RGB444, COLOR_RGB444, 0); - } - SetAVMute(FALSE); + set_videoinfo(); } // Initialize hardware -int init_hw() { - alt_u32 chiprev; +int init_hw() +{ + alt_u32 chiprev; - // Reset error vector and scan converter - IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x00); - IOWR_ALTERA_AVALON_PIO_DATA(PIO_2_BASE, 0x00000000); - IOWR_ALTERA_AVALON_PIO_DATA(PIO_3_BASE, 0x00000000); - usleep(10000); + // Reset error vector and scan converter + IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x00); + IOWR_ALTERA_AVALON_PIO_DATA(PIO_2_BASE, 0x00000000); + IOWR_ALTERA_AVALON_PIO_DATA(PIO_3_BASE, 0x00000000); + usleep(10000); - // unreset hw - IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x03); + // unreset hw + IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x03); - //wait >500ms for SD card interface to be stable - //over 200ms and LCD may be buggy? - usleep(200000); + //wait >500ms for SD card interface to be stable + //over 200ms and LCD may be buggy? + usleep(200000); - // IT6613 officially supports only 100kHz, but 400kHz seems to work - I2C_init(I2CA_BASE,ALT_CPU_FREQ,400000); + // IT6613 officially supports only 100kHz, but 400kHz seems to work + I2C_init(I2CA_BASE,ALT_CPU_FREQ,400000); - /* Initialize the character display */ - lcd_init(); + /* Initialize the character display */ + lcd_init(); - if (!ths_init()) { + if (!ths_init()) { printf("Error: could not read from THS7353\n"); return -2; - } + } - /* check if TVP is found */ - chiprev = tvp_readreg(TVP_CHIPREV); - //printf("chiprev %d\n", chiprev); + /* check if TVP is found */ + chiprev = tvp_readreg(TVP_CHIPREV); + //printf("chiprev %d\n", chiprev); - if ( chiprev == 0xff) { - printf("Error: could not read from TVP7002\n"); - return -3; - } + if ( chiprev == 0xff) { + printf("Error: could not read from TVP7002\n"); + return -3; + } - tvp_init(); + tvp_init(); - chiprev = HDMITX_ReadI2C_Byte(IT_DEVICEID); + chiprev = HDMITX_ReadI2C_Byte(IT_DEVICEID); - if ( chiprev != 0x13) { - printf("Error: could not read from IT6613\n"); - return -4; - } + if ( chiprev != 0x13) { + printf("Error: could not read from IT6613\n"); + return -4; + } - InitIT6613(); + InitIT6613(); - if (check_flash() != 0) { + if (check_flash() != 0) { printf("Error: incorrect flash type detected\n"); return -1; - } + } // safe? read_userdata(); @@ -1179,215 +1214,217 @@ int init_hw() { // enforce DVI mode on non-DIY boards if ((IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & HDMITX_MODE_MASK)) { cm.cc.tx_mode = TX_DVI; - tc.tx_mode = TX_DVI; + tc.tx_mode = TX_DVI; } if (!(IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & PB1_MASK)) setup_rc(); - //enable TX (videogen) - TX_enable(cm.cc.tx_mode); + //enable TX (videogen) + usleep(200000); + TX_enable(cm.cc.tx_mode); - return 0; + return 0; } // Enable chip outputs -void enable_outputs() { - // program video mode - program_mode(); - // enable TVP output - tvp_enable_output(); +void enable_outputs() +{ + // program video mode + program_mode(); + // enable TVP output + tvp_enable_output(); - // enable and unmute HDMITX - // TODO: check pclk - TX_enable(cm.cc.tx_mode); + // enable and unmute HDMITX + // TODO: check pclk + TX_enable(cm.cc.tx_mode); } int main() { - tvp_input_t target_input; - ths_input_t target_ths; - video_format target_format; - avinput_t target_mode; + tvp_input_t target_input = 0; + ths_input_t target_ths = 0; + video_format target_format = 0; + avinput_t target_mode; - alt_u8 av_init = 0; - status_t status; - alt_u32 test; + alt_u8 av_init = 0; + status_t status; - int init_stat; + int init_stat; - init_stat = init_hw(); + init_stat = init_hw(); - if (init_stat >= 0) { - printf("### DIY VIDEO DIGITIZER / SCANCONVERTER INIT OK ###\n\n"); - sniprintf(row1, LCD_ROW_LEN+1, "OSSC fw. %u.%.2u", fw_ver_major, fw_ver_minor); - strncpy(row2, "2014-2015 marqs", LCD_ROW_LEN+1); - lcd_write_status(); - } else { - sniprintf(row1, LCD_ROW_LEN+1, "Init error %d", init_stat); - strncpy(row2, "", LCD_ROW_LEN+1); - lcd_write_status(); - while (1) {} - } + if (init_stat >= 0) { + printf("### DIY VIDEO DIGITIZER / SCANCONVERTER INIT OK ###\n\n"); + sniprintf(row1, LCD_ROW_LEN+1, "OSSC fw. %u.%.2u", fw_ver_major, fw_ver_minor); + strncpy(row2, "2014-2016 marqs", LCD_ROW_LEN+1); + lcd_write_status(); + } else { + sniprintf(row1, LCD_ROW_LEN+1, "Init error %d", init_stat); + strncpy(row2, "", LCD_ROW_LEN+1); + lcd_write_status(); + while (1) {} + } - while(1) { - // Select target input and mode - remote_code = IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & RC_MASK; + while(1) { + // Select target input and mode + remote_code = IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & RC_MASK; btn_code = ~IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & PB_MASK; - if (remote_code_prev == 0 && remote_code != 0) - printf("RCODE: 0x%.4x\n", remote_code); + if (remote_code_prev == 0 && remote_code != 0) + printf("RCODE: 0x%.4x\n", remote_code); - if (btn_code_prev == 0 && btn_code != 0) - printf("BCODE: 0x%.2x\n", btn_code>>16); + if (btn_code_prev == 0 && btn_code != 0) + printf("BCODE: 0x%.2x\n", btn_code>>16); target_mode = AV_KEEP; - if (remote_code_prev == 0) { - if (remote_code == rc_keymap[RC_BTN1]) { + if (remote_code_prev == 0) { + if (remote_code == rc_keymap[RC_BTN1]) { if (cm.avinput == AV1_RGBs) target_mode = AV1_RGsB; else target_mode = AV1_RGBs; - } else if (remote_code == rc_keymap[RC_BTN2]) { + } else if (remote_code == rc_keymap[RC_BTN2]) { if (cm.avinput == AV2_YPBPR) target_mode = AV2_RGsB; else target_mode = AV2_YPBPR; - } else if (remote_code == rc_keymap[RC_BTN3]) { - if (cm.avinput == AV3_RGBHV) + } else if (remote_code == rc_keymap[RC_BTN3]) { + if (cm.avinput == AV3_RGBHV) target_mode = AV3_RGBs; else if (cm.avinput == AV3_RGBs) target_mode = AV3_RGsB; else target_mode = AV3_RGBHV; - } - } + } + } if ((btn_code_prev == 0) && (btn_code & PB0_MASK)) { target_mode = (cm.avinput == AV3_RGsB) ? AV1_RGBs : (cm.avinput+1); } - if (target_mode == cm.avinput) - target_mode = AV_KEEP; + if (target_mode == cm.avinput) + target_mode = AV_KEEP; - if (target_mode != AV_KEEP) - printf("### SWITCH MODE TO %s ###\n", avinput_str[target_mode]); + if (target_mode != AV_KEEP) + printf("### SWITCH MODE TO %s ###\n", avinput_str[target_mode]); - switch (target_mode) { - case AV1_RGBs: - target_input = TVP_INPUT1; - target_format = FORMAT_RGBS; - target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV; - target_ths = THS_INPUT_B; - break; - case AV1_RGsB: - target_input = TVP_INPUT1; - target_format = FORMAT_RGsB; - target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV; - target_ths = THS_INPUT_B; - break; - case AV2_YPBPR: - target_input = TVP_INPUT1; - target_format = FORMAT_YPbPr; - target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV; - target_ths = THS_INPUT_A; - break; - case AV2_RGsB: - target_input = TVP_INPUT1; - target_format = FORMAT_RGsB; - target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV; - target_ths = THS_INPUT_A; - break; - case AV3_RGBHV: - target_input = TVP_INPUT3; - target_format = FORMAT_RGBHV; - target_typemask = VIDEO_PC; - target_ths = THS_STANDBY; - break; - case AV3_RGBs: - target_input = TVP_INPUT3; - target_format = FORMAT_RGBS; - target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV; - target_ths = THS_STANDBY; - break; - case AV3_RGsB: - target_input = TVP_INPUT3; - target_format = FORMAT_RGsB; - target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV; - target_ths = THS_STANDBY; - break; - default: - break; - } + switch (target_mode) { + case AV1_RGBs: + target_input = TVP_INPUT1; + target_format = FORMAT_RGBS; + target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV; + target_ths = THS_INPUT_B; + break; + case AV1_RGsB: + target_input = TVP_INPUT1; + target_format = FORMAT_RGsB; + target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV; + target_ths = THS_INPUT_B; + break; + case AV2_YPBPR: + target_input = TVP_INPUT1; + target_format = FORMAT_YPbPr; + target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV; + target_ths = THS_INPUT_A; + break; + case AV2_RGsB: + target_input = TVP_INPUT1; + target_format = FORMAT_RGsB; + target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV; + target_ths = THS_INPUT_A; + break; + case AV3_RGBHV: + target_input = TVP_INPUT3; + target_format = FORMAT_RGBHV; + target_typemask = VIDEO_PC; + target_ths = THS_STANDBY; + break; + case AV3_RGBs: + target_input = TVP_INPUT3; + target_format = FORMAT_RGBS; + target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV; + target_ths = THS_STANDBY; + break; + case AV3_RGsB: + target_input = TVP_INPUT3; + target_format = FORMAT_RGsB; + target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV; + target_ths = THS_STANDBY; + break; + default: + break; + } - if (target_mode != AV_KEEP) { - av_init = 1; - cm.avinput = target_mode; - cm.sync_active = 0; - ths_source_sel(target_ths, (cm.cc.video_lpf > 1) ? (VIDEO_LPF_MAX-cm.cc.video_lpf) : THS_LPF_BYPASS); - tvp_disable_output(); - tvp_source_sel(target_input, target_format, cm.refclk); - cm.clkcnt = 0; //TODO: proper invalidate - strncpy(row1, avinput_str[cm.avinput], LCD_ROW_LEN+1); - strncpy(row2, " NO SYNC", LCD_ROW_LEN+1); - if (!menu_active) - lcd_write_status(); - } + if (target_mode != AV_KEEP) { + av_init = 1; + cm.avinput = target_mode; + cm.sync_active = 0; + ths_source_sel(target_ths, (cm.cc.video_lpf > 1) ? (VIDEO_LPF_MAX-cm.cc.video_lpf) : THS_LPF_BYPASS); + tvp_disable_output(); + tvp_source_sel(target_input, target_format, cm.refclk); + cm.clkcnt = 0; //TODO: proper invalidate + strncpy(row1, avinput_str[cm.avinput], LCD_ROW_LEN+1); + strncpy(row2, " NO SYNC", LCD_ROW_LEN+1); + if (!menu_active) + lcd_write_status(); + } - usleep(MAINLOOP_SLEEP_US); - read_control(); + //usleep(MAINLOOP_SLEEP_US); + usleep(300); //avoid triggering multiple times per vsync + read_control(); - if (av_init) { - status = get_status(target_input); + if (av_init) { + status = get_status(target_input); - switch (status) { - case ACTIVITY_CHANGE: - if (cm.sync_active) { - printf("Sync up\n"); - IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, (IORD_ALTERA_AVALON_PIO_DATA(PIO_0_BASE) | (1<<2))); //disable videogen - enable_outputs(); - } else { - printf("Sync lost\n"); - cm.clkcnt = 0; //TODO: proper invalidate - tvp_disable_output(); - //ths_source_sel(THS_STANDBY, 0); - strncpy(row1, avinput_str[cm.avinput], LCD_ROW_LEN+1); - strncpy(row2, " NO SYNC", LCD_ROW_LEN+1); - if (!menu_active) - lcd_write_status(); - } - break; - /*case TX_MODE_CHANGE: - if (cm.sync_active) - TX_enable(cm.cc.tx_mode); - printf("TX mode change\n"); - break;*/ - /*case REFCLK_CHANGE: - if (cm.sync_active) { - printf("Refclk change\n"); - tvp_sel_clk(cm.refclk); - } - break;*/ - case MODE_CHANGE: - if (cm.sync_active && (cm.totlines >= MIN_VALID_LINES)) { - printf("Mode change\n"); - program_mode(); - } - break; - case INFO_CHANGE: - if (cm.sync_active) { - printf("Info change\n"); - set_videoinfo(); - } - break; - default: - break; - } - } + switch (status) { + case ACTIVITY_CHANGE: + if (cm.sync_active) { + printf("Sync up\n"); + IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, (IORD_ALTERA_AVALON_PIO_DATA(PIO_0_BASE) | (1<<2))); //disable videogen + enable_outputs(); + } else { + printf("Sync lost\n"); + cm.clkcnt = 0; //TODO: proper invalidate + tvp_disable_output(); + //ths_source_sel(THS_STANDBY, 0); + strncpy(row1, avinput_str[cm.avinput], LCD_ROW_LEN+1); + strncpy(row2, " NO SYNC", LCD_ROW_LEN+1); + if (!menu_active) + lcd_write_status(); + } + break; + /*case TX_MODE_CHANGE: + if (cm.sync_active) + TX_enable(cm.cc.tx_mode); + printf("TX mode change\n"); + break;*/ + /*case REFCLK_CHANGE: + if (cm.sync_active) { + printf("Refclk change\n"); + tvp_sel_clk(cm.refclk); + } + break;*/ + case MODE_CHANGE: + if (cm.sync_active && (cm.totlines >= MIN_VALID_LINES)) { + printf("Mode change\n"); + program_mode(); + } + break; + case INFO_CHANGE: + if (cm.sync_active) { + printf("Info change\n"); + set_videoinfo(); + } + break; + default: + break; + } + } - remote_code_prev = remote_code; + remote_code_prev = remote_code; btn_code_prev = btn_code; - } + } - return 0; + return 0; } diff --git a/software/sys_controller/it6613/hdmitx_nios2.c b/software/sys_controller/it6613/hdmitx_nios2.c index 4ae9f7f..1d2121c 100644 --- a/software/sys_controller/it6613/hdmitx_nios2.c +++ b/software/sys_controller/it6613/hdmitx_nios2.c @@ -5,78 +5,89 @@ #include "hdmitx.h" #include "it6613.h" -inline alt_u32 read_it2(alt_u32 regaddr) { - I2C_start(I2CA_BASE, IT_BASE, 0); - I2C_write(I2CA_BASE, regaddr, 0); - I2C_start(I2CA_BASE, IT_BASE, 1); - return I2C_read(I2CA_BASE,1); +inline alt_u32 read_it2(alt_u32 regaddr) +{ + I2C_start(I2CA_BASE, IT_BASE, 0); + I2C_write(I2CA_BASE, regaddr, 0); + I2C_start(I2CA_BASE, IT_BASE, 1); + return I2C_read(I2CA_BASE,1); } -inline void write_it2(alt_u32 regaddr, alt_u8 data) { - I2C_start(I2CA_BASE, IT_BASE, 0); - I2C_write(I2CA_BASE, regaddr, 0); - I2C_write(I2CA_BASE, data, 1); +inline void write_it2(alt_u32 regaddr, alt_u8 data) +{ + I2C_start(I2CA_BASE, IT_BASE, 0); + I2C_write(I2CA_BASE, regaddr, 0); + I2C_write(I2CA_BASE, data, 1); } -BYTE I2C_Read_Byte(BYTE Addr,BYTE RegAddr) { - I2C_start(I2CA_BASE, Addr, 0); - I2C_write(I2CA_BASE, RegAddr, 0); - I2C_start(I2CA_BASE, Addr, 1); - return I2C_read(I2CA_BASE,1); +BYTE I2C_Read_Byte(BYTE Addr,BYTE RegAddr) +{ + I2C_start(I2CA_BASE, Addr, 0); + I2C_write(I2CA_BASE, RegAddr, 0); + I2C_start(I2CA_BASE, Addr, 1); + return I2C_read(I2CA_BASE,1); } -SYS_STATUS I2C_Write_Byte(BYTE Addr,BYTE RegAddr,BYTE Data) { - I2C_start(I2CA_BASE, Addr, 0); - I2C_write(I2CA_BASE, RegAddr, 0); - I2C_write(I2CA_BASE, Data, 1); - return 0; +SYS_STATUS I2C_Write_Byte(BYTE Addr,BYTE RegAddr,BYTE Data) +{ + I2C_start(I2CA_BASE, Addr, 0); + I2C_write(I2CA_BASE, RegAddr, 0); + I2C_write(I2CA_BASE, Data, 1); + return 0; } -SYS_STATUS I2C_Read_ByteN(BYTE Addr,BYTE RegAddr,BYTE *pData,int N) { - int i; +SYS_STATUS I2C_Read_ByteN(BYTE Addr,BYTE RegAddr,BYTE *pData,int N) +{ + int i; - for (i=0; i +// Copyright (C) 2015-2016 Markus Hiienkari // // This file is part of Open Source Scan Converter project. // @@ -21,87 +21,89 @@ #include "alt_types.h" #include "altera_avalon_pio_regs.h" -#define LCD_CMD 0x00 -#define LCD_DATA 0x40 +#define LCD_CMD 0x00 +#define LCD_DATA 0x40 -#define WRDELAY 20 -#define CLEARDELAY 800 +#define WRDELAY 20 +#define CLEARDELAY 800 -void lcd_init() { +void lcd_init() +{ alt_u8 lcd_ctrl = 0x00; IOWR_ALTERA_AVALON_PIO_DATA(PIO_5_BASE, lcd_ctrl); usleep(WRDELAY); - SPI_write(I2CA_BASE, 0x38); // function set - usleep(WRDELAY); - SPI_write(I2CA_BASE, 0x39); // function set, select extended table (IS=1) - usleep(WRDELAY); - SPI_write(I2CA_BASE, 0x14); // osc freq - usleep(WRDELAY); - SPI_write(I2CA_BASE, 0x71); // contrast set - usleep(WRDELAY); - SPI_write(I2CA_BASE, 0x5E); // power/icon/cont - usleep(WRDELAY); - SPI_write(I2CA_BASE, 0x6D); // follower control - usleep(WRDELAY); - SPI_write(I2CA_BASE, 0x0C); // display on - usleep(WRDELAY); - SPI_write(I2CA_BASE, 0x01); // clear display - usleep(CLEARDELAY); - SPI_write(I2CA_BASE, 0x06); // entry mode set - usleep(WRDELAY); - SPI_write(I2CA_BASE, 0x02); // return home - usleep(CLEARDELAY); - - lcd_ctrl |= LCD_CS_N; - IOWR_ALTERA_AVALON_PIO_DATA(PIO_5_BASE, lcd_ctrl); -} - -void lcd_write(char *row1, char *row2) { - alt_u8 i, rowlen; - alt_u8 lcd_ctrl = 0x00; - - IOWR_ALTERA_AVALON_PIO_DATA(PIO_5_BASE, lcd_ctrl); - - SPI_write(I2CA_BASE, 0x01); // clear display - usleep(CLEARDELAY); - - // Set RS to enter data write mode - lcd_ctrl |= LCD_RS; - IOWR_ALTERA_AVALON_PIO_DATA(PIO_5_BASE, lcd_ctrl); - - //ensure no empty row - rowlen = strnlen(row1, LCD_ROW_LEN); - if (rowlen == 0) { - strncpy(row1, " ", LCD_ROW_LEN+1); - rowlen++; - } - - for (i=0; i +// Copyright (C) 2015-2016 Markus Hiienkari // // This file is part of Open Source Scan Converter project. // diff --git a/software/sys_controller/sysconfig.h b/software/sys_controller/sysconfig.h index d24dbad..64add6a 100644 --- a/software/sys_controller/sysconfig.h +++ b/software/sys_controller/sysconfig.h @@ -1,5 +1,5 @@ // -// Copyright (C) 2015 Markus Hiienkari +// Copyright (C) 2015-2016 Markus Hiienkari // // This file is part of Open Source Scan Converter project. // diff --git a/software/sys_controller/ths7353/ths7353.c b/software/sys_controller/ths7353/ths7353.c index a2af36b..7d32843 100644 --- a/software/sys_controller/ths7353/ths7353.c +++ b/software/sys_controller/ths7353/ths7353.c @@ -1,5 +1,5 @@ // -// Copyright (C) 2015 Markus Hiienkari +// Copyright (C) 2015-2016 Markus Hiienkari // // This file is part of Open Source Scan Converter project. // @@ -24,7 +24,8 @@ #include "i2c_opencores.h" #include "ths7353.h" -inline alt_u32 ths_readreg(alt_u8 channel) { +inline alt_u32 ths_readreg(alt_u8 channel) +{ //Phase 1 I2C_start(I2CA_BASE, THS_BASE, 0); I2C_write(I2CA_BASE, channel, 1); @@ -34,13 +35,15 @@ inline alt_u32 ths_readreg(alt_u8 channel) { return I2C_read(I2CA_BASE,1); } -inline void ths_writereg(alt_u8 channel, alt_u8 data) { +inline void ths_writereg(alt_u8 channel, alt_u8 data) +{ I2C_start(I2CA_BASE, THS_BASE, 0); I2C_write(I2CA_BASE, channel, 0); I2C_write(I2CA_BASE, data, 1); } -int ths_init() { +int ths_init() +{ //Avoid random FIFO state (see datasheet p.37) I2C_write(I2CA_BASE, 0x00, 0); usleep(10); @@ -53,7 +56,8 @@ int ths_init() { return (ths_readreg(THS_CH1) == (THS_LPF_DEFAULT< +// Copyright (C) 2015-2016 Markus Hiienkari // // This file is part of Open Source Scan Converter project. // diff --git a/software/sys_controller/tvp7002/tvp7002.c b/software/sys_controller/tvp7002/tvp7002.c index 98f0234..107685e 100644 --- a/software/sys_controller/tvp7002/tvp7002.c +++ b/software/sys_controller/tvp7002/tvp7002.c @@ -1,5 +1,5 @@ // -// Copyright (C) 2015 Markus Hiienkari +// Copyright (C) 2015-2016 Markus Hiienkari // // This file is part of Open Source Scan Converter project. // @@ -24,378 +24,407 @@ #include "i2c_opencores.h" #include "tvp7002.h" -//#define SYNCBYPASS // Bypass VGA syncs (for debug - needed for interlace?) -//#define EXTADCCLK // Use external ADC clock (external osc) -//#define ADCPOWERDOWN // Power-down ADCs -//#define PLLPOSTDIV // Double-rate PLL with div-by-2 (decrease jitter?) +//#define SYNCBYPASS // Bypass VGA syncs (for debug - needed for interlace?) +//#define EXTADCCLK // Use external ADC clock (external osc) +//#define ADCPOWERDOWN // Power-down ADCs +//#define PLLPOSTDIV // Double-rate PLL with div-by-2 (decrease jitter?) /* Y'Pb'Pr' to R'G'B' CSC coefficients. * * Coefficients from "Colour Space Conversions" (http://www.poynton.com/PDFs/coloureq.pdf). */ const ypbpr_to_rgb_csc_t csc_coeffs[] = { - { "Rec. 601", 0x2000, 0x0000, 0x2CE5, 0x2000, 0xF4FD, 0xE926, 0x2000, 0x38BC, 0x0000 }, // eq. 101 - { "Rec. 709", 0x2000, 0x0000, 0x323E, 0x2000, 0xFA04, 0xF113, 0x2000, 0x3B61, 0x0000 }, // eq. 105 + { "Rec. 601", 0x2000, 0x0000, 0x2CE5, 0x2000, 0xF4FD, 0xE926, 0x2000, 0x38BC, 0x0000 }, // eq. 101 + { "Rec. 709", 0x2000, 0x0000, 0x323E, 0x2000, 0xFA04, 0xF113, 0x2000, 0x3B61, 0x0000 }, // eq. 105 }; extern mode_data_t video_modes[]; -static inline void tvp_set_hpllcoast(alt_u8 pre, alt_u8 post) { - tvp_writereg(TVP_HPLLPRECOAST, pre); - tvp_writereg(TVP_HPLLPOSTCOAST, post); +static inline void tvp_set_hpllcoast(alt_u8 pre, alt_u8 post) +{ + tvp_writereg(TVP_HPLLPRECOAST, pre); + tvp_writereg(TVP_HPLLPOSTCOAST, post); } -static inline void tvp_set_ssthold(alt_u8 vsdetect_thold) { - tvp_writereg(TVP_SSTHOLD, vsdetect_thold); +static inline void tvp_set_ssthold(alt_u8 vsdetect_thold) +{ + tvp_writereg(TVP_SSTHOLD, vsdetect_thold); } -static void tvp_set_clamp(video_format fmt) { - switch (fmt) { - case FORMAT_RGBS: - case FORMAT_RGBHV: - case FORMAT_RGsB: - //select bottom clamp (RGB) - tvp_writereg(TVP_SOGTHOLD, 0x58); - break; - case FORMAT_YPbPr: - //select mid clamp for Pb & Pr - tvp_writereg(TVP_SOGTHOLD, 0x5D); - break; - default: - break; - } +static void tvp_set_clamp(video_format fmt) +{ + switch (fmt) { + case FORMAT_RGBS: + case FORMAT_RGBHV: + case FORMAT_RGsB: + //select bottom clamp (RGB) + tvp_writereg(TVP_SOGTHOLD, 0x58); + break; + case FORMAT_YPbPr: + //select mid clamp for Pb & Pr + tvp_writereg(TVP_SOGTHOLD, 0x5D); + break; + default: + break; + } } -static void tvp_set_clamp_position(video_type type) { - switch (type) { - case VIDEO_LDTV: - tvp_writereg(TVP_CLAMPSTART, 0x2); - tvp_writereg(TVP_CLAMPWIDTH, 0x6); - break; - case VIDEO_SDTV: - case VIDEO_EDTV: - case VIDEO_PC: - tvp_writereg(TVP_CLAMPSTART, 0x6); - tvp_writereg(TVP_CLAMPWIDTH, 0x10); - break; - case VIDEO_HDTV: - tvp_writereg(TVP_CLAMPSTART, 0x32); - tvp_writereg(TVP_CLAMPWIDTH, 0x20); - break; - default: - break; - } +static void tvp_set_clamp_position(video_type type) +{ + switch (type) { + case VIDEO_LDTV: + tvp_writereg(TVP_CLAMPSTART, 0x2); + tvp_writereg(TVP_CLAMPWIDTH, 0x6); + break; + case VIDEO_SDTV: + case VIDEO_EDTV: + case VIDEO_PC: + tvp_writereg(TVP_CLAMPSTART, 0x6); + tvp_writereg(TVP_CLAMPWIDTH, 0x10); + break; + case VIDEO_HDTV: + tvp_writereg(TVP_CLAMPSTART, 0x32); + tvp_writereg(TVP_CLAMPWIDTH, 0x20); + break; + default: + break; + } } -static void tvp_set_alc(video_type type) { - //disable ALC - //tvp_writereg(TVP_ALCEN, 0x00); - //tvp_writereg(TVP_ALCEN, 0x80); +static void tvp_set_alc(video_type type) +{ + //disable ALC + //tvp_writereg(TVP_ALCEN, 0x00); + //tvp_writereg(TVP_ALCEN, 0x80); - //set analog (coarse) gain to max recommended value (-> 91% of the ADC range with 0.7Vpp input) - tvp_writereg(TVP_BG_CGAIN, 0x88); - tvp_writereg(TVP_R_CGAIN, 0x08); + //set analog (coarse) gain to max recommended value (-> 91% of the ADC range with 0.7Vpp input) + tvp_writereg(TVP_BG_CGAIN, 0x88); + tvp_writereg(TVP_R_CGAIN, 0x08); - //set rest of the gain digitally (fine) to utilize 100% of the range at the output (0.91*(1+(26/256)) = 1) - tvp_writereg(TVP_R_FGAIN, 26); - tvp_writereg(TVP_G_FGAIN, 26); - tvp_writereg(TVP_B_FGAIN, 26); + //set rest of the gain digitally (fine) to utilize 100% of the range at the output (0.91*(1+(26/256)) = 1) + tvp_writereg(TVP_R_FGAIN, 26); + tvp_writereg(TVP_G_FGAIN, 26); + tvp_writereg(TVP_B_FGAIN, 26); - //select ALC placement - switch (type) { - case VIDEO_LDTV: - tvp_writereg(TVP_ALCPLACE, 0x9); - break; - case VIDEO_SDTV: - case VIDEO_EDTV: - case VIDEO_PC: - tvp_writereg(TVP_ALCPLACE, 0x18); - break; - case VIDEO_HDTV: - tvp_writereg(TVP_ALCPLACE, 0x5A); - break; - default: - break; - } + //select ALC placement + switch (type) { + case VIDEO_LDTV: + tvp_writereg(TVP_ALCPLACE, 0x9); + break; + case VIDEO_SDTV: + case VIDEO_EDTV: + case VIDEO_PC: + tvp_writereg(TVP_ALCPLACE, 0x18); + break; + case VIDEO_HDTV: + tvp_writereg(TVP_ALCPLACE, 0x5A); + break; + default: + break; + } } -inline alt_u32 tvp_readreg(alt_u32 regaddr) { - I2C_start(I2CA_BASE, TVP_BASE, 0); - I2C_write(I2CA_BASE, regaddr, 1); //don't use repeated start as it seems unreliable at 400kHz - I2C_start(I2CA_BASE, TVP_BASE, 1); - return I2C_read(I2CA_BASE,1); +inline alt_u32 tvp_readreg(alt_u32 regaddr) +{ + I2C_start(I2CA_BASE, TVP_BASE, 0); + I2C_write(I2CA_BASE, regaddr, 1); //don't use repeated start as it seems unreliable at 400kHz + I2C_start(I2CA_BASE, TVP_BASE, 1); + return I2C_read(I2CA_BASE,1); } -inline void tvp_writereg(alt_u32 regaddr, alt_u8 data) { - I2C_start(I2CA_BASE, TVP_BASE, 0); - I2C_write(I2CA_BASE, regaddr, 0); - I2C_write(I2CA_BASE, data, 1); +inline void tvp_writereg(alt_u32 regaddr, alt_u8 data) +{ + I2C_start(I2CA_BASE, TVP_BASE, 0); + I2C_write(I2CA_BASE, regaddr, 0); + I2C_write(I2CA_BASE, data, 1); } -inline void tvp_reset() { - usleep(10000); - IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x00); - usleep(10000); - IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x01); - usleep(10000); +inline void tvp_reset() +{ + usleep(10000); + IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x00); + usleep(10000); + IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x01); + usleep(10000); } -inline void tvp_disable_output() { - usleep(10000); - tvp_writereg(TVP_MISCCTRL1, 0x13); - usleep(10000); - tvp_writereg(TVP_MISCCTRL2, 0x03); - usleep(10000); +inline void tvp_disable_output() +{ + usleep(10000); + tvp_writereg(TVP_MISCCTRL1, 0x13); + usleep(10000); + tvp_writereg(TVP_MISCCTRL2, 0x03); + usleep(10000); } -inline void tvp_enable_output() { - usleep(10000); - tvp_writereg(TVP_MISCCTRL1, 0x11); - usleep(10000); - tvp_writereg(TVP_MISCCTRL2, 0x02); - usleep(10000); +inline void tvp_enable_output() +{ + usleep(10000); + tvp_writereg(TVP_MISCCTRL1, 0x11); + usleep(10000); + tvp_writereg(TVP_MISCCTRL2, 0x02); + usleep(10000); } -void tvp_init() { - // disable output - tvp_disable_output(); +void tvp_init() +{ + // disable output + tvp_disable_output(); - //Set global defaults + //Set global defaults - // Hsync input->output delay (horizontal shift) - // Default is 13, which maintains alignment of RGB and hsync at output - //tvp_writereg(TVP_HSOUTSTART, 0); + // Hsync input->output delay (horizontal shift) + // Default is 13, which maintains alignment of RGB and hsync at output + //tvp_writereg(TVP_HSOUTSTART, 0); - // Hsync edge->Vsync edge delay - tvp_writereg(TVP_VSOUTALIGN, 0); + // Hsync edge->Vsync edge delay + tvp_writereg(TVP_VSOUTALIGN, 0); - // Set default CSC coeffs. - tvp_sel_csc(&csc_coeffs[0]); + // Set default CSC coeffs. + tvp_sel_csc(&csc_coeffs[0]); - // Set default phase - tvp_set_hpll_phase(0x10); + // Set default phase + tvp_set_hpll_phase(0x10); - // Set min LPF - tvp_set_lpf(0); - tvp_set_sync_lpf(0); + // Set min LPF + tvp_set_lpf(0); + tvp_set_sync_lpf(0); - // Increase line length tolerance - tvp_writereg(TVP_LINELENTOL, 0x06); + // Increase line length tolerance + tvp_writereg(TVP_LINELENTOL, 0x06); - // Common sync separator threshold + // Common sync separator threshold // Some arcade games need more that the default 0x40 - tvp_set_ssthold(0x44); + tvp_set_ssthold(0x44); } // Configure H-PLL (sampling rate, VCO gain and charge pump current) -void tvp_setup_hpll(alt_u16 h_samplerate, alt_u16 v_lines, alt_u8 hz, alt_u8 plldivby2) { - alt_u32 pclk_est; - alt_u8 vco_range; - alt_u8 cp_current; +void tvp_setup_hpll(alt_u16 h_samplerate, alt_u16 v_lines, alt_u8 hz, alt_u8 plldivby2) +{ + alt_u32 pclk_est; + alt_u8 vco_range; + alt_u8 cp_current; - alt_u8 status = tvp_readreg(TVP_HPLLPHASE) & 0xF8; + alt_u8 status = tvp_readreg(TVP_HPLLPHASE) & 0xF8; - // Enable PLL post-div-by-2 with double samplerate - if (plldivby2) { - tvp_writereg(TVP_HPLLPHASE, status|1); - h_samplerate = 2*h_samplerate; - } else { - tvp_writereg(TVP_HPLLPHASE, status); - } + // Enable PLL post-div-by-2 with double samplerate + if (plldivby2) { + tvp_writereg(TVP_HPLLPHASE, status|1); + h_samplerate = 2*h_samplerate; + } else { + tvp_writereg(TVP_HPLLPHASE, status); + } - tvp_writereg(TVP_HPLLDIV_MSB, (h_samplerate >> 4)); - tvp_writereg(TVP_HPLLDIV_LSB, ((h_samplerate & 0xf) << 4)); + tvp_writereg(TVP_HPLLDIV_MSB, (h_samplerate >> 4)); + tvp_writereg(TVP_HPLLDIV_LSB, ((h_samplerate & 0xf) << 4)); - printf("Horizontal samplerate set to %u\n", h_samplerate); + printf("Horizontal samplerate set to %u\n", h_samplerate); - pclk_est = ((alt_u32)h_samplerate * v_lines * hz) / 1000; //in kHz + pclk_est = ((alt_u32)h_samplerate * v_lines * hz) / 1000; //in kHz - printf("Estimated PCLK: %u.%.3u MHz\n", pclk_est/1000, pclk_est%1000); + printf("Estimated PCLK: %u.%.3u MHz\n", pclk_est/1000, pclk_est%1000); - if (pclk_est < 36000) { - vco_range = 0; - } else if (pclk_est < 70000) { - vco_range = 1; - } else if (pclk_est < 135000) { - vco_range = 2; - } else { - vco_range = 3; - } + if (pclk_est < 36000) { + vco_range = 0; + } else if (pclk_est < 70000) { + vco_range = 1; + } else if (pclk_est < 135000) { + vco_range = 2; + } else { + vco_range = 3; + } - cp_current = (40*Kvco[vco_range]+h_samplerate/2) / h_samplerate; //"+h_samplerate/2" for fast rounding + cp_current = (40*Kvco[vco_range]+h_samplerate/2) / h_samplerate; //"+h_samplerate/2" for fast rounding + if (cp_current > 7) + cp_current = 7; - printf("VCO range: %s\nCPC: %u\n", Kvco_str[vco_range], cp_current); - tvp_writereg(TVP_HPLLCTRL, ((vco_range << 6) | (cp_current << 3))); + printf("VCO range: %s\nCPC: %u\n", Kvco_str[vco_range], cp_current); + tvp_writereg(TVP_HPLLCTRL, ((vco_range << 6) | (cp_current << 3))); } -void tvp_sel_clk(alt_u8 refclk) { - alt_u8 status = tvp_readreg(TVP_INPMUX2) & 0xFA; +void tvp_sel_clk(alt_u8 refclk) +{ + alt_u8 status = tvp_readreg(TVP_INPMUX2) & 0xFA; - //TODO: set SOG and CLP LPF based on mode - if (refclk == REFCLK_INTCLK) { - tvp_writereg(TVP_INPMUX2, status|0x2); - } else { + //TODO: set SOG and CLP LPF based on mode + if (refclk == REFCLK_INTCLK) { + tvp_writereg(TVP_INPMUX2, status|0x2); + } else { #ifdef EXTADCCLK - tvp_writereg(TVP_INPMUX2, status|0x8); + tvp_writereg(TVP_INPMUX2, status|0x8); #else - tvp_writereg(TVP_INPMUX2, status|0xA); + tvp_writereg(TVP_INPMUX2, status|0xA); #endif - } + } } -void tvp_sel_csc(ypbpr_to_rgb_csc_t *csc) { - tvp_writereg(TVP_CSC1HI, (csc->G_Y >> 8)); - tvp_writereg(TVP_CSC1LO, (csc->G_Y & 0xff)); - tvp_writereg(TVP_CSC2HI, (csc->G_Pb >> 8)); - tvp_writereg(TVP_CSC2LO, (csc->G_Pb & 0xff)); - tvp_writereg(TVP_CSC3HI, (csc->G_Pr >> 8)); - tvp_writereg(TVP_CSC3LO, (csc->G_Pr & 0xff)); +void tvp_sel_csc(ypbpr_to_rgb_csc_t *csc) +{ + tvp_writereg(TVP_CSC1HI, (csc->G_Y >> 8)); + tvp_writereg(TVP_CSC1LO, (csc->G_Y & 0xff)); + tvp_writereg(TVP_CSC2HI, (csc->G_Pb >> 8)); + tvp_writereg(TVP_CSC2LO, (csc->G_Pb & 0xff)); + tvp_writereg(TVP_CSC3HI, (csc->G_Pr >> 8)); + tvp_writereg(TVP_CSC3LO, (csc->G_Pr & 0xff)); - tvp_writereg(TVP_CSC4HI, (csc->R_Y >> 8)); - tvp_writereg(TVP_CSC4LO, (csc->R_Y & 0xff)); - tvp_writereg(TVP_CSC5HI, (csc->R_Pb >> 8)); - tvp_writereg(TVP_CSC5LO, (csc->R_Pb & 0xff)); - tvp_writereg(TVP_CSC6HI, (csc->R_Pr >> 8)); - tvp_writereg(TVP_CSC6LO, (csc->R_Pr & 0xff)); + tvp_writereg(TVP_CSC4HI, (csc->R_Y >> 8)); + tvp_writereg(TVP_CSC4LO, (csc->R_Y & 0xff)); + tvp_writereg(TVP_CSC5HI, (csc->R_Pb >> 8)); + tvp_writereg(TVP_CSC5LO, (csc->R_Pb & 0xff)); + tvp_writereg(TVP_CSC6HI, (csc->R_Pr >> 8)); + tvp_writereg(TVP_CSC6LO, (csc->R_Pr & 0xff)); - tvp_writereg(TVP_CSC7HI, (csc->B_Y >> 8)); - tvp_writereg(TVP_CSC7LO, (csc->B_Y & 0xff)); - tvp_writereg(TVP_CSC8HI, (csc->B_Pb >> 8)); - tvp_writereg(TVP_CSC8LO, (csc->B_Pb & 0xff)); - tvp_writereg(TVP_CSC9HI, (csc->B_Pr >> 8)); - tvp_writereg(TVP_CSC9LO, (csc->B_Pr & 0xff)); + tvp_writereg(TVP_CSC7HI, (csc->B_Y >> 8)); + tvp_writereg(TVP_CSC7LO, (csc->B_Y & 0xff)); + tvp_writereg(TVP_CSC8HI, (csc->B_Pb >> 8)); + tvp_writereg(TVP_CSC8LO, (csc->B_Pb & 0xff)); + tvp_writereg(TVP_CSC9HI, (csc->B_Pr >> 8)); + tvp_writereg(TVP_CSC9LO, (csc->B_Pr & 0xff)); } -void tvp_set_lpf(alt_u8 val) { - alt_u8 status = tvp_readreg(TVP_VIDEOBWLIM) & 0xF0; - tvp_writereg(TVP_VIDEOBWLIM, status|val); - printf("TVP LPF value set to 0x%x\n", val); +void tvp_set_lpf(alt_u8 val) +{ + alt_u8 status = tvp_readreg(TVP_VIDEOBWLIM) & 0xF0; + tvp_writereg(TVP_VIDEOBWLIM, status|val); + printf("TVP LPF value set to 0x%x\n", val); } -void tvp_set_sync_lpf(alt_u8 val) { - alt_u8 status = tvp_readreg(TVP_INPMUX2) & 0x3F; - tvp_writereg(TVP_INPMUX2, status|((3-val)<<6)); - printf("Sync LPF value set to 0x%x\n", (3-val)); +void tvp_set_sync_lpf(alt_u8 val) +{ + alt_u8 status = tvp_readreg(TVP_INPMUX2) & 0x3F; + tvp_writereg(TVP_INPMUX2, status|((3-val)<<6)); + printf("Sync LPF value set to 0x%x\n", (3-val)); } -void tvp_set_hpll_phase(alt_u8 val) { - alt_u8 status = tvp_readreg(TVP_HPLLPHASE) & 0x07; - tvp_writereg(TVP_HPLLPHASE, (val<<3)|status); - printf("Phase value set to 0x%x\n", val); +void tvp_set_hpll_phase(alt_u8 val) +{ + alt_u8 status = tvp_readreg(TVP_HPLLPHASE) & 0x07; + tvp_writereg(TVP_HPLLPHASE, (val<<3)|status); + printf("Phase value set to 0x%x\n", val); } -void tvp_source_setup(alt_8 modeid, video_type type, alt_u32 vlines, alt_u8 hz, alt_u8 refclk) { - // Configure clock settings - tvp_sel_clk(refclk); - - // Clamp position and ALC - tvp_set_clamp_position(type); - tvp_set_alc(type); - - // Macrovision enable/disable, coast disable for RGBHV. - // Coast needs to be enabled when HSYNC is missing during VSYNC. Valid only for RGBHV? - // Macrovision should be enabled when serration pulses etc. present, so disable only for RGBHV. - switch (type) { - case VIDEO_PC: - //tvp_writereg(TVP_MISCCTRL4, 0x04); - tvp_writereg(TVP_MISCCTRL4, 0x0C); - tvp_writereg(TVP_MVSWIDTH, 0x03); - break; - case VIDEO_HDTV: - tvp_writereg(TVP_MISCCTRL4, 0x08); - tvp_writereg(TVP_MVSWIDTH, 0x0E); - break; - case VIDEO_LDTV: - case VIDEO_SDTV: - case VIDEO_EDTV: - tvp_writereg(TVP_MISCCTRL4, 0x08); - tvp_writereg(TVP_MVSWIDTH, 0x88); // TODO: check mode - break; - default: - break; - } - - tvp_setup_hpll(video_modes[modeid].h_total, vlines, hz, !!(video_modes[modeid].flags & MODE_PLLDIVBY2)); - - //Long coast may lead to PLL frequency drift and sync loss (e.g. SNES) - /*if (video_modes[modeid].v_active < 720) - tvp_set_hpllcoast(3, 3); - else*/ - tvp_set_hpllcoast(1, 0); - - // Hsync output width - tvp_writereg(TVP_HSOUTWIDTH, video_modes[modeid].h_synclen); +void tvp_set_sog_thold(alt_u8 val) +{ + alt_u8 status = tvp_readreg(TVP_SOGTHOLD) & 0x07; + tvp_writereg(TVP_SOGTHOLD, (val<<3)|status); + printf("SOG thold set to 0x%x\n", val); } -void tvp_source_sel(tvp_input_t input, video_format fmt, alt_u8 refclk) { - alt_u8 sync_status; - alt_u8 sog_ch; +void tvp_source_setup(alt_8 modeid, video_type type, alt_u32 vlines, alt_u8 hz, alt_u8 refclk) +{ + // Configure clock settings + tvp_sel_clk(refclk); - if ((fmt == FORMAT_RGsB) || (fmt == FORMAT_YPbPr)) + // Clamp position and ALC + tvp_set_clamp_position(type); + tvp_set_alc(type); + + // Macrovision enable/disable, coast disable for RGBHV. + // Coast needs to be enabled when HSYNC is missing during VSYNC. Valid only for RGBHV? + // Macrovision should be enabled when serration pulses etc. present, so disable only for RGBHV. + switch (type) { + case VIDEO_PC: + //tvp_writereg(TVP_MISCCTRL4, 0x04); + tvp_writereg(TVP_MISCCTRL4, 0x0C); + tvp_writereg(TVP_MVSWIDTH, 0x03); + break; + case VIDEO_HDTV: + tvp_writereg(TVP_MISCCTRL4, 0x08); + tvp_writereg(TVP_MVSWIDTH, 0x0E); + break; + case VIDEO_LDTV: + case VIDEO_SDTV: + case VIDEO_EDTV: + tvp_writereg(TVP_MISCCTRL4, 0x08); + tvp_writereg(TVP_MVSWIDTH, 0x88); // TODO: check mode + break; + default: + break; + } + + tvp_setup_hpll(video_modes[modeid].h_total, vlines, hz, !!(video_modes[modeid].flags & MODE_PLLDIVBY2)); + + //Long coast may lead to PLL frequency drift and sync loss (e.g. SNES) + /*if (video_modes[modeid].v_active < 720) + tvp_set_hpllcoast(3, 3); + else*/ + tvp_set_hpllcoast(1, 0); + + // Hsync output width + tvp_writereg(TVP_HSOUTWIDTH, video_modes[modeid].h_synclen); +} + +void tvp_source_sel(tvp_input_t input, video_format fmt, alt_u8 refclk) +{ + alt_u8 sync_status; + alt_u8 sog_ch; + + if ((fmt == FORMAT_RGsB) || (fmt == FORMAT_YPbPr)) sog_ch = (input == TVP_INPUT3) ? 2 : 0; - else if ((input == TVP_INPUT1) && (fmt == FORMAT_RGBS)) - sog_ch = 1; - else - sog_ch = 2; + else if ((input == TVP_INPUT1) && (fmt == FORMAT_RGBS)) + sog_ch = 1; + else + sog_ch = 2; - // RGB+SOG input select - tvp_writereg(TVP_INPMUX1, (sog_ch<<6) | (input<<4) | (input<<2) | input); + // RGB+SOG input select + tvp_writereg(TVP_INPMUX1, (sog_ch<<6) | (input<<4) | (input<<2) | input); - // Configure clock settings - tvp_sel_clk(refclk); + // Configure clock settings + tvp_sel_clk(refclk); - // Clamp setup - tvp_set_clamp(fmt); + // Clamp setup + tvp_set_clamp(fmt); - // HV/SOG sync select - if ((input == TVP_INPUT3) && (fmt != FORMAT_RGsB)) { - if (fmt == FORMAT_RGBHV) - tvp_writereg(TVP_SYNCCTRL1, 0x52); - else // RGBS - tvp_writereg(TVP_SYNCCTRL1, 0x53); + // HV/SOG sync select + if ((input == TVP_INPUT3) && (fmt != FORMAT_RGsB)) { + if (fmt == FORMAT_RGBHV) + tvp_writereg(TVP_SYNCCTRL1, 0x52); + else // RGBS + tvp_writereg(TVP_SYNCCTRL1, 0x53); - sync_status = tvp_readreg(TVP_SYNCSTAT); - if (sync_status & (1<<7)) - printf("%s detected, %s polarity\n", (sync_status & (1<<3)) ? "Csync" : "Hsync", (sync_status & (1<<5)) ? "pos" : "neg"); - if (sync_status & (1<<4)) - printf("Vsync detected, %s polarity\n", (sync_status & (1<<2)) ? "pos" : "neg"); - } else { - tvp_writereg(TVP_SYNCCTRL1, 0x5B); - sync_status = tvp_readreg(TVP_SYNCSTAT); - if (sync_status & (1<<1)) - printf("SOG detected\n"); - else - printf("SOG not detected\n"); - } + sync_status = tvp_readreg(TVP_SYNCSTAT); + if (sync_status & (1<<7)) + printf("%s detected, %s polarity\n", (sync_status & (1<<3)) ? "Csync" : "Hsync", (sync_status & (1<<5)) ? "pos" : "neg"); + if (sync_status & (1<<4)) + printf("Vsync detected, %s polarity\n", (sync_status & (1<<2)) ? "pos" : "neg"); + } else { + tvp_writereg(TVP_SYNCCTRL1, 0x5B); + sync_status = tvp_readreg(TVP_SYNCSTAT); + if (sync_status & (1<<1)) + printf("SOG detected\n"); + else + printf("SOG not detected\n"); + } - // Enable CSC for YPbPr - if (fmt == FORMAT_YPbPr) - tvp_writereg(TVP_MISCCTRL3, 0x10); - else - tvp_writereg(TVP_MISCCTRL3, 0x00); + // Enable CSC for YPbPr + if (fmt == FORMAT_YPbPr) + tvp_writereg(TVP_MISCCTRL3, 0x10); + else + tvp_writereg(TVP_MISCCTRL3, 0x00); - #ifdef SYNCBYPASS - tvp_writereg(TVP_SYNCBYPASS, 0x03); - #else - tvp_writereg(TVP_SYNCBYPASS, 0x00); - #endif +#ifdef SYNCBYPASS + tvp_writereg(TVP_SYNCBYPASS, 0x03); +#else + tvp_writereg(TVP_SYNCBYPASS, 0x00); +#endif - //TODO: - //clamps - //TVP_ADCSETUP + //TODO: + //clamps + //TVP_ADCSETUP - printf("\n"); + printf("\n"); } -alt_u8 tvp_check_sync(tvp_input_t input) { - alt_u8 sync_status; +alt_u8 tvp_check_sync(tvp_input_t input) +{ + alt_u8 sync_status; - sync_status = tvp_readreg(TVP_SYNCSTAT); + sync_status = tvp_readreg(TVP_SYNCSTAT); - if (input == TVP_INPUT3) - return !!((sync_status & 0x98) > 0x80); - //return !!((sync_status & 0x90) == 0x90); - else - return !!(sync_status & (1<<1)); + if (input == TVP_INPUT3) + return !!((sync_status & 0x98) > 0x80); + //return !!((sync_status & 0x90) == 0x90); + else + return !!(sync_status & (1<<1)); } diff --git a/software/sys_controller/tvp7002/tvp7002.h b/software/sys_controller/tvp7002/tvp7002.h index 1453cd6..405ced6 100644 --- a/software/sys_controller/tvp7002/tvp7002.h +++ b/software/sys_controller/tvp7002/tvp7002.h @@ -1,5 +1,5 @@ // -// Copyright (C) 2015 Markus Hiienkari +// Copyright (C) 2015-2016 Markus Hiienkari // // This file is part of Open Source Scan Converter project. // @@ -28,30 +28,30 @@ #define I2CA_BASE I2C_OPENCORES_0_BASE typedef enum { - TVP_INPUT1 = 0, - TVP_INPUT2 = 1, - TVP_INPUT3 = 2 + TVP_INPUT1 = 0, + TVP_INPUT2 = 1, + TVP_INPUT3 = 2 } tvp_input_t; static const alt_u8 Kvco[] = {75, 85, 150, 200}; static const char *Kvco_str[] = { "Ultra low", "Low", "Medium", "High" }; typedef enum { - REFCLK_EXT27 = 0, - REFCLK_INTCLK = 1 + REFCLK_EXT27 = 0, + REFCLK_INTCLK = 1 } tvp_refclk_t; typedef struct { - const char *name; - alt_u16 R_Y; - alt_u16 R_Pb; - alt_u16 R_Pr; - alt_u16 G_Y; - alt_u16 G_Pb; - alt_u16 G_Pr; - alt_u16 B_Y; - alt_u16 B_Pb; - alt_u16 B_Pr; + const char *name; + alt_u16 R_Y; + alt_u16 R_Pb; + alt_u16 R_Pr; + alt_u16 G_Y; + alt_u16 G_Pb; + alt_u16 G_Pr; + alt_u16 B_Y; + alt_u16 B_Pb; + alt_u16 B_Pr; } ypbpr_to_rgb_csc_t; static const alt_u32 clkrate[] = {27000000, 6500000}; //in MHz @@ -81,6 +81,8 @@ void tvp_set_sync_lpf(alt_u8 val); void tvp_set_hpll_phase(alt_u8 val); +void tvp_set_sog_thold(alt_u8 val); + void tvp_source_setup(alt_8 modeid, video_type type, alt_u32 vlines, alt_u8 hz, alt_u8 refclk); void tvp_source_sel(tvp_input_t input, video_format fmt, alt_u8 refclk); diff --git a/software/sys_controller/tvp7002/tvp7002_regs.h b/software/sys_controller/tvp7002/tvp7002_regs.h index 99b52c3..c66455f 100644 --- a/software/sys_controller/tvp7002/tvp7002_regs.h +++ b/software/sys_controller/tvp7002/tvp7002_regs.h @@ -1,5 +1,5 @@ // -// Copyright (C) 2015 Markus Hiienkari +// Copyright (C) 2015-2016 Markus Hiienkari // // This file is part of Open Source Scan Converter project. // @@ -22,96 +22,96 @@ #define TVP_BASE (0xB8>>1) -#define TVP_CHIPREV 0x00 -#define TVP_HPLLDIV_MSB 0x01 -#define TVP_HPLLDIV_LSB 0x02 -#define TVP_HPLLCTRL 0x03 -#define TVP_HPLLPHASE 0x04 -#define TVP_CLAMPSTART 0x05 -#define TVP_CLAMPWIDTH 0x06 -#define TVP_HSOUTWIDTH 0x07 -#define TVP_B_FGAIN 0x08 -#define TVP_G_FGAIN 0x09 -#define TVP_R_FGAIN 0x0A -#define TVP_B_FOFFSET_MSB 0x0B -#define TVP_G_FOFFSET_MSB 0x0C -#define TVP_R_FOFFSET_MSB 0x0D -#define TVP_SYNCCTRL1 0x0E -#define TVP_HPLLCTRL2 0x0F +#define TVP_CHIPREV 0x00 +#define TVP_HPLLDIV_MSB 0x01 +#define TVP_HPLLDIV_LSB 0x02 +#define TVP_HPLLCTRL 0x03 +#define TVP_HPLLPHASE 0x04 +#define TVP_CLAMPSTART 0x05 +#define TVP_CLAMPWIDTH 0x06 +#define TVP_HSOUTWIDTH 0x07 +#define TVP_B_FGAIN 0x08 +#define TVP_G_FGAIN 0x09 +#define TVP_R_FGAIN 0x0A +#define TVP_B_FOFFSET_MSB 0x0B +#define TVP_G_FOFFSET_MSB 0x0C +#define TVP_R_FOFFSET_MSB 0x0D +#define TVP_SYNCCTRL1 0x0E +#define TVP_HPLLCTRL2 0x0F -#define TVP_SOGTHOLD 0x10 -#define TVP_SSTHOLD 0x11 -#define TVP_HPLLPRECOAST 0x12 -#define TVP_HPLLPOSTCOAST 0x13 -#define TVP_SYNCSTAT 0x14 -#define TVP_OUTFORMAT 0x15 -#define TVP_MISCCTRL1 0x16 -#define TVP_MISCCTRL2 0x17 -#define TVP_MISCCTRL3 0x18 -#define TVP_INPMUX1 0x19 -#define TVP_INPMUX2 0x1A -#define TVP_BG_CGAIN 0x1B -#define TVP_R_CGAIN 0x1C -#define TVP_FOFFSET_LSB 0x1D -#define TVP_B_COFFSET 0x1E -#define TVP_G_COFFSET 0x1F +#define TVP_SOGTHOLD 0x10 +#define TVP_SSTHOLD 0x11 +#define TVP_HPLLPRECOAST 0x12 +#define TVP_HPLLPOSTCOAST 0x13 +#define TVP_SYNCSTAT 0x14 +#define TVP_OUTFORMAT 0x15 +#define TVP_MISCCTRL1 0x16 +#define TVP_MISCCTRL2 0x17 +#define TVP_MISCCTRL3 0x18 +#define TVP_INPMUX1 0x19 +#define TVP_INPMUX2 0x1A +#define TVP_BG_CGAIN 0x1B +#define TVP_R_CGAIN 0x1C +#define TVP_FOFFSET_LSB 0x1D +#define TVP_B_COFFSET 0x1E +#define TVP_G_COFFSET 0x1F -#define TVP_R_COFFSET 0x20 -#define TVP_HSOUTSTART 0x21 -#define TVP_MISCCTRL4 0x22 -#define TVP_B_ALCOUT_LSB 0x23 -#define TVP_G_ALCOUT_LSB 0x24 -#define TVP_R_ALCOUT_LSB 0x25 -#define TVP_ALCEN 0x26 -#define TVP_ALCOUT_MSB 0x27 -#define TVP_ALCFILT 0x28 -#define TVP_FCLAMPCTRL 0x2A -#define TVP_POWERCTRL 0x2B -#define TVP_ADCSETUP 0x2C -#define TVP_CCLAMPCTRL 0x2D -#define TVP_SOGCLAMP 0x2E -#define TVP_RGBCCLAMPCTRL 0x2F +#define TVP_R_COFFSET 0x20 +#define TVP_HSOUTSTART 0x21 +#define TVP_MISCCTRL4 0x22 +#define TVP_B_ALCOUT_LSB 0x23 +#define TVP_G_ALCOUT_LSB 0x24 +#define TVP_R_ALCOUT_LSB 0x25 +#define TVP_ALCEN 0x26 +#define TVP_ALCOUT_MSB 0x27 +#define TVP_ALCFILT 0x28 +#define TVP_FCLAMPCTRL 0x2A +#define TVP_POWERCTRL 0x2B +#define TVP_ADCSETUP 0x2C +#define TVP_CCLAMPCTRL 0x2D +#define TVP_SOGCLAMP 0x2E +#define TVP_RGBCCLAMPCTRL 0x2F -#define TVP_SOGCCLAMPCTRL 0x30 -#define TVP_ALCPLACE 0x31 -#define TVP_MVSWIDTH 0x34 -#define TVP_VSOUTALIGN 0x35 -#define TVP_SYNCBYPASS 0x36 -#define TVP_LINECNT1 0x37 -#define TVP_LINECNT2 0x38 -#define TVP_CLKCNT1 0x39 -#define TVP_CLKCNT2 0x3A -#define TVP_HSINWIDTH 0x3B -#define TVP_VSINWIDTH 0x3C -#define TVP_LINELENTOL 0x3D -#define TVP_VIDEOBWLIM 0x3F +#define TVP_SOGCCLAMPCTRL 0x30 +#define TVP_ALCPLACE 0x31 +#define TVP_MVSWIDTH 0x34 +#define TVP_VSOUTALIGN 0x35 +#define TVP_SYNCBYPASS 0x36 +#define TVP_LINECNT1 0x37 +#define TVP_LINECNT2 0x38 +#define TVP_CLKCNT1 0x39 +#define TVP_CLKCNT2 0x3A +#define TVP_HSINWIDTH 0x3B +#define TVP_VSINWIDTH 0x3C +#define TVP_LINELENTOL 0x3D +#define TVP_VIDEOBWLIM 0x3F -#define TVP_AVIDSTART1 0x40 -#define TVP_AVIDSTART2 0x41 -#define TVP_AVIDSTOP1 0x42 -#define TVP_AVIDSTOP2 0x43 -#define TVP_VB0OFF 0x44 -#define TVP_VB1OFF 0x45 -#define TVP_VB0DUR 0x46 -#define TVP_VB1DUR 0x47 -#define TVP_CSC1LO 0x4A -#define TVP_CSC1HI 0x4B -#define TVP_CSC2LO 0x4C -#define TVP_CSC2HI 0x4D -#define TVP_CSC3LO 0x4E -#define TVP_CSC3HI 0x4F +#define TVP_AVIDSTART1 0x40 +#define TVP_AVIDSTART2 0x41 +#define TVP_AVIDSTOP1 0x42 +#define TVP_AVIDSTOP2 0x43 +#define TVP_VB0OFF 0x44 +#define TVP_VB1OFF 0x45 +#define TVP_VB0DUR 0x46 +#define TVP_VB1DUR 0x47 +#define TVP_CSC1LO 0x4A +#define TVP_CSC1HI 0x4B +#define TVP_CSC2LO 0x4C +#define TVP_CSC2HI 0x4D +#define TVP_CSC3LO 0x4E +#define TVP_CSC3HI 0x4F -#define TVP_CSC4LO 0x50 -#define TVP_CSC4HI 0x51 -#define TVP_CSC5LO 0x52 -#define TVP_CSC5HI 0x53 -#define TVP_CSC6LO 0x54 -#define TVP_CSC6HI 0x55 -#define TVP_CSC7LO 0x56 -#define TVP_CSC7HI 0x57 -#define TVP_CSC8LO 0x58 -#define TVP_CSC8HI 0x59 -#define TVP_CSC9LO 0x5A -#define TVP_CSC9HI 0x5B +#define TVP_CSC4LO 0x50 +#define TVP_CSC4HI 0x51 +#define TVP_CSC5LO 0x52 +#define TVP_CSC5HI 0x53 +#define TVP_CSC6LO 0x54 +#define TVP_CSC6HI 0x55 +#define TVP_CSC7LO 0x56 +#define TVP_CSC7HI 0x57 +#define TVP_CSC8LO 0x58 +#define TVP_CSC8HI 0x59 +#define TVP_CSC9LO 0x5A +#define TVP_CSC9HI 0x5B #endif /* TVP7002_REGS_H_ */ diff --git a/software/sys_controller/tvp7002/video_modes.c b/software/sys_controller/tvp7002/video_modes.c index e2fac1b..c45e050 100644 --- a/software/sys_controller/tvp7002/video_modes.c +++ b/software/sys_controller/tvp7002/video_modes.c @@ -1,5 +1,5 @@ // -// Copyright (C) 2015 Markus Hiienkari +// Copyright (C) 2015-2016 Markus Hiienkari // // This file is part of Open Source Scan Converter project. // @@ -25,61 +25,66 @@ #define LINECNT_MAX_TOLERANCE 30 const mode_data_t video_modes[] = { - { "240p_L3M0", 1280, 240, 6000, 1704, 262, 196, 16, 124, 3, (VIDEO_SDTV|VIDEO_PC), MODE_L3_MODE0 }, - { "240p_L3M1", 960, 240, 6000, 1278, 262, 147, 16, 93, 3, (VIDEO_SDTV|VIDEO_PC), MODE_L3_MODE1 }, - { "240p_L3M2", 320, 240, 6000, 426, 262, 49, 16, 31, 3, (VIDEO_LDTV|VIDEO_PC), (MODE_L3_MODE2|MODE_PLLDIVBY2) }, - { "240p_L3M3", 256, 240, 6000, 341, 262, 39, 16, 25, 3, (VIDEO_LDTV|VIDEO_PC), (MODE_L3_MODE3|MODE_PLLDIVBY2) }, - { "240p", 720, 240, 6000, 858, 262, 65, 16, 60, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L2ENABLE) }, - { "288p", 720, 288, 5000, 864, 312, 65, 16, 60, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L2ENABLE) }, - { "384p", 496, 384, 5766, 640, 423, 50, 29, 62, 3, VIDEO_EDTV, (MODE_L2ENABLE) }, //Sega Model 2 - { "640x384", 640, 384, 5500, 800, 492, 48, 63, 96, 2, VIDEO_PC, (MODE_L2ENABLE) }, //X68k @ 24kHz - { "480i", 720, 240, 5994, 858, 525, 65, 16, 60, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L2ENABLE|MODE_INTERLACED) }, - { "480p", 720, 480, 5994, 858, 525, 60, 30, 62, 6, (VIDEO_EDTV|VIDEO_PC), (MODE_DTV480P) }, - { "640x480", 640, 480, 6000, 800, 525, 48, 33, 96, 2, (VIDEO_PC|VIDEO_EDTV), (MODE_VGA480P) }, - { "640x512", 640, 512, 6000, 800, 568, 48, 28, 96, 2, VIDEO_PC, 0 }, //X68k @ 31kHz - { "576i", 720, 288, 5000, 864, 625, 65, 16, 60, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L2ENABLE|MODE_INTERLACED) }, - { "576p", 720, 576, 5000, 864, 625, 65, 32, 60, 6, VIDEO_EDTV, 0 }, - { "800x600", 800, 600, 6000, 1056, 628, 88, 23, 128, 4, VIDEO_PC, 0 }, - { "720p", 1280, 720, 5994, 1650, 750, 255, 20, 40, 5, VIDEO_HDTV, 0 }, - { "1280x720", 1280, 720, 6000, 1650, 750, 220, 20, 40, 5, VIDEO_PC, 0 }, - { "1024x768", 1024, 768, 6000, 1344, 806, 160, 29, 136, 6, VIDEO_PC, 0 }, - { "1280x1024", 1280, 1024, 6000, 1688, 1066, 248, 38, 112, 3, VIDEO_PC, 0 }, - { "1080i", 1920, 1080, 5994, 2200, 1125, 148, 16, 44, 5, VIDEO_HDTV, (MODE_L2ENABLE|MODE_INTERLACED) }, //Too high freq for L2 PLL - { "1080p", 1920, 1080, 5994, 2200, 1125, 188, 36, 44, 5, VIDEO_HDTV, 0 }, - { "1920x1080", 1920, 1080, 6000, 2200, 1125, 148, 36, 44, 5, VIDEO_PC, 0 }, + { "240p_L3M0", 1280, 240, 6000, 1704, 262, 196, 16, 124, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L3_MODE0) }, + { "240p_L3M1", 960, 240, 6000, 1278, 262, 147, 16, 93, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L3_MODE1|MODE_PLLDIVBY2) }, + { "240p_L3M2", 320, 240, 6000, 426, 262, 49, 16, 31, 3, (VIDEO_LDTV|VIDEO_PC), (MODE_L3_MODE2|MODE_PLLDIVBY2) }, + { "240p_L3M3", 256, 240, 6000, 341, 262, 39, 16, 25, 3, (VIDEO_LDTV|VIDEO_PC), (MODE_L3_MODE3|MODE_PLLDIVBY2) }, + { "240p", 720, 240, 6000, 858, 262, 65, 16, 60, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L2ENABLE|MODE_PLLDIVBY2) }, + { "288p_L3M0", 1280, 288, 5000, 1704, 312, 196, 16, 124, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L3_MODE0) }, + { "288p_L3M1", 960, 288, 5000, 1278, 312, 147, 16, 93, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L3_MODE1|MODE_PLLDIVBY2) }, + { "288p_L3M2", 320, 240, 5000, 426, 312, 49, 41, 31, 3, (VIDEO_LDTV|VIDEO_PC), (MODE_L3_MODE2|MODE_PLLDIVBY2) }, + { "288p_L3M3", 256, 240, 5000, 341, 312, 39, 41, 25, 3, (VIDEO_LDTV|VIDEO_PC), (MODE_L3_MODE3|MODE_PLLDIVBY2) }, + { "288p", 720, 288, 5000, 864, 312, 65, 16, 60, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L2ENABLE|MODE_PLLDIVBY2) }, + { "384p", 496, 384, 5766, 640, 423, 50, 29, 62, 3, VIDEO_EDTV, (MODE_L2ENABLE|MODE_PLLDIVBY2) }, //Sega Model 2 + { "640x384", 640, 384, 5500, 800, 492, 48, 63, 96, 2, VIDEO_PC, (MODE_L2ENABLE) }, //X68k @ 24kHz + { "480i", 720, 240, 5994, 858, 525, 65, 16, 60, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L2ENABLE|MODE_PLLDIVBY2|MODE_INTERLACED) }, + { "480p", 720, 480, 5994, 858, 525, 60, 30, 62, 6, (VIDEO_EDTV|VIDEO_PC), (MODE_DTV480P) }, + { "640x480", 640, 480, 6000, 800, 525, 48, 33, 96, 2, (VIDEO_PC|VIDEO_EDTV), (MODE_VGA480P) }, + { "640x512", 640, 512, 6000, 800, 568, 48, 28, 96, 2, VIDEO_PC, 0 }, //X68k @ 31kHz + { "576i", 720, 288, 5000, 864, 625, 65, 16, 60, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L2ENABLE|MODE_PLLDIVBY2|MODE_INTERLACED) }, + { "576p", 720, 576, 5000, 864, 625, 65, 32, 60, 6, VIDEO_EDTV, 0 }, + { "800x600", 800, 600, 6000, 1056, 628, 88, 23, 128, 4, VIDEO_PC, 0 }, + { "720p", 1280, 720, 5994, 1650, 750, 255, 20, 40, 5, VIDEO_HDTV, 0 }, + { "1280x720", 1280, 720, 6000, 1650, 750, 220, 20, 40, 5, VIDEO_PC, 0 }, + { "1024x768", 1024, 768, 6000, 1344, 806, 160, 29, 136, 6, VIDEO_PC, 0 }, + { "1280x1024", 1280, 1024, 6000, 1688, 1066, 248, 38, 112, 3, VIDEO_PC, 0 }, + { "1080i", 1920, 1080, 5994, 2200, 1125, 148, 16, 44, 5, VIDEO_HDTV, (MODE_INTERLACED) }, //Too high freq for L2 PLL + { "1080p", 1920, 1080, 5994, 2200, 1125, 188, 36, 44, 5, VIDEO_HDTV, 0 }, + { "1920x1080", 1920, 1080, 6000, 2200, 1125, 148, 36, 44, 5, VIDEO_PC, 0 }, }; /* TODO: rewrite, check hz etc. */ -alt_8 get_mode_id(alt_u32 totlines, alt_u8 progressive, alt_u32 hz, video_type typemask, alt_u8 linemult_target, alt_u8 l3_mode, alt_u8 s480p_mode) { - alt_8 i; - alt_u8 num_modes = sizeof(video_modes)/sizeof(mode_data_t); +alt_8 get_mode_id(alt_u32 totlines, alt_u8 progressive, alt_u32 hz, video_type typemask, alt_u8 linemult_target, alt_u8 l3_mode, alt_u8 s480p_mode) +{ + alt_8 i; + alt_u8 num_modes = sizeof(video_modes)/sizeof(mode_data_t); video_type mode_type; - // TODO: a better check - for (i=0; i +// Copyright (C) 2015-2016 Markus Hiienkari // // This file is part of Open Source Scan Converter project. // @@ -24,18 +24,18 @@ #include "sysconfig.h" typedef enum { - FORMAT_RGBS = 0, - FORMAT_RGBHV = 1, - FORMAT_RGsB = 2, - FORMAT_YPbPr = 3 + FORMAT_RGBS = 0, + FORMAT_RGBHV = 1, + FORMAT_RGsB = 2, + FORMAT_YPbPr = 3 } video_format; typedef enum { - VIDEO_LDTV = (1<<0), - VIDEO_SDTV = (1<<1), + VIDEO_LDTV = (1<<0), + VIDEO_SDTV = (1<<1), VIDEO_EDTV = (1<<2), - VIDEO_HDTV = (1<<3), - VIDEO_PC = (1<<4) + VIDEO_HDTV = (1<<3), + VIDEO_PC = (1<<4) } video_type; #define MODE_L3ENABLE_MASK 0xf @@ -45,11 +45,11 @@ typedef enum { MODE_L3_MODE1 = (1<<1), MODE_L3_MODE2 = (1<<2), MODE_L3_MODE3 = (1<<3), - MODE_L2ENABLE = (1<<4), - MODE_INTERLACED = (1<<5), - MODE_PLLDIVBY2 = (1<<6), - MODE_DTV480P = (1<<7), - MODE_VGA480P = (1<<8) + MODE_L2ENABLE = (1<<4), + MODE_INTERLACED = (1<<5), + MODE_PLLDIVBY2 = (1<<6), + MODE_DTV480P = (1<<7), + MODE_VGA480P = (1<<8) } mode_flags; typedef struct { diff --git a/software/sys_controller_bsp/libhal_bsp.a b/software/sys_controller_bsp/libhal_bsp.a index 5cac88b..d0b2521 100644 Binary files a/software/sys_controller_bsp/libhal_bsp.a and b/software/sys_controller_bsp/libhal_bsp.a differ diff --git a/software/sys_controller_bsp/settings.bsp b/software/sys_controller_bsp/settings.bsp index 3a768c6..db2f133 100644 --- a/software/sys_controller_bsp/settings.bsp +++ b/software/sys_controller_bsp/settings.bsp @@ -2,10 +2,10 @@ hal default - Feb 18, 2016 1:07:07 AM - 1455750427597 - ./ - ../sys_controller_bsp/settings.bsp + Mar 22, 2016 7:43:08 PM + 1458668588222 + /home/markus/Code/ossc/software/sys_controller_bsp + settings.bsp ../../sys.sopcinfo default nios2_qsys_0 diff --git a/sys.sopcinfo b/sys.sopcinfo index 85e1176..0f4d0b0 100644 --- a/sys.sopcinfo +++ b/sys.sopcinfo @@ -1,11 +1,11 @@ - + java.lang.Integer - 1453239707 + 1458667846 false true false diff --git a/tools.project b/tools.project new file mode 100644 index 0000000..ca422ca --- /dev/null +++ b/tools.project @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + make clean + make + + + + None + $(WorkspacePath) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + make clean + make + + + + None + $(ProjectPath) + + + + + + + + + + + + + + diff --git a/tools/create_fw_img.c b/tools/create_fw_img.c index f494371..f081647 100644 --- a/tools/create_fw_img.c +++ b/tools/create_fw_img.c @@ -1,3 +1,22 @@ +// +// Copyright (C) 2015-2016 Markus Hiienkari +// +// 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 . +// + #include #include #include @@ -11,77 +30,76 @@ #define BUF_SIZE 1024 #define MAX_FILENAME 32 -#define FW_KEY_SIZE 4 -#define FW_SUFFIX_MAX_SIZE 8 +#define FW_KEY_SIZE 4 +#define FW_SUFFIX_MAX_SIZE 8 -#define FW_HDR_LEN 26 +#define FW_HDR_LEN 26 static uint32_t crc32_tab[] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; -uint32_t -crc32(uint32_t crc, const void *buf, size_t size) +uint32_t crc32(uint32_t crc, const void *buf, size_t size) { - const uint8_t *p; + const uint8_t *p; - p = buf; - crc = crc ^ ~0U; + p = buf; + crc = crc ^ ~0U; - while (size--) - crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); + while (size--) + crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); - return crc ^ ~0U; + return crc ^ ~0U; } int main(int argc, char **argv) { - unsigned char block; - - int fd_i, fd_o; - struct stat fileinfo; + unsigned char block; + + int fd_i, fd_o; + struct stat fileinfo; char fw_bin_name[MAX_FILENAME]; char hdrbuf[HDR_SIZE]; char rdbuf[BUF_SIZE]; @@ -89,29 +107,29 @@ int main(int argc, char **argv) unsigned fw_version_minor; uint32_t hdr_crc; uint32_t crc = 0; - - unsigned int i, bytes_read, bytes_written, tot_bytes_read = 0; - - if ((argc < 3) || (argc > 4)) { - printf("Usege: %s rbf version [version_suffix]\n", argv[0]); - return -1; - } - - if ((fd_i = open(argv[1], O_RDONLY)) == -1 || fstat(fd_i, &fileinfo) == -1) { - printf("Couldn't open input file\n"); - return -1; - } - + + unsigned int i, bytes_read, bytes_written, tot_bytes_read = 0; + + if ((argc < 3) || (argc > 4)) { + printf("Usege: %s rbf version [version_suffix]\n", argv[0]); + return -1; + } + + if ((fd_i = open(argv[1], O_RDONLY)) == -1 || fstat(fd_i, &fileinfo) == -1) { + printf("Couldn't open input file\n"); + return -1; + } + snprintf(fw_bin_name, MAX_FILENAME-1, "ossc_%s%s%s.bin", argv[2], (argc == 4) ? "-" : "", (argc == 4) ? argv[3] : ""); - - if ((fd_o = open(fw_bin_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR)) == -1) { - printf("Couldn't open output file\n"); - return -1; - } + + if ((fd_o = open(fw_bin_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR)) == -1) { + printf("Couldn't open output file\n"); + return -1; + } if ((sscanf(argv[2], "%u.%u", &fw_version_major, &fw_version_minor) != 2) || (fw_version_major > 255) || (fw_version_minor > 255)) { - printf("Invalid version format specified\n"); - return -1; + printf("Invalid version format specified\n"); + return -1; } //printf("%s, %u.%u\n", argv[2], fw_version_major, (uint8_t)fw_version_minor); @@ -155,7 +173,7 @@ int main(int argc, char **argv) bytes_written = write(fd_o, rdbuf, bytes_read); if (bytes_written != bytes_read) { printf("Couldn't write output file\n"); - return -1; + return -1; } tot_bytes_read += bytes_read; } @@ -166,9 +184,9 @@ int main(int argc, char **argv) } printf("Firmware image written to %s\n", fw_bin_name); - - close(fd_o); - close(fd_i); - - return 0; + + close(fd_o); + close(fd_i); + + return 0; }