SVGA Signal 800 x 600 @ 60 Hz timing
Screen refresh rate 60 Hz
Vertical refresh 37.878787878788 kHz
Pixel freq. 40.0 MHz
Horizontal timing (line)
Polarity of horizontal sync pulse is negative.
Scanline part Pixels Time [µs]
Visible area 800 20
Front porch 40 1
Sync pulse 128 3.2
Back porch 88 2.2
Whole line 1056 26.4
Vertical timing (frame)
Polarity of vertical sync pulse is negative.
Frame part Lines Time [ms]
Visible area 600 15.84
Front porch 1 0.0264
Sync pulse 4 0.1056
Back porch 23 0.6072
Whole frame 628 16.5792
Name Type Value, Misc: Hardware Description
HorizVisibleArea uint16 800 true Horizontal Visible Area
HorizFrontPorch uint16 40 true Horizontal Front Porch
HorizSyncPulse uint16 128 true Horizontal Sync Pulse
HorizBackPorch uint16 88 true Horizontal Back Porch
HorizPulsePostive bool true true Horizontal Pulse Positive
VertVisibleArea uint16 600 true Vertical Visible Area
VertFrontPorch uint16 1 true Vertical Front Porch
VertSyncPulse uint16 4 true Vertical Sync Pulse
VertBackPorch uint16 23 true Vertical Back Porch
VertPulsePositive bool true true Vertical Pulse Positive
Do make sure the Misc Hardware value is set to true, the Description is not important but if you want to access these values from Verilog, the Hardware bool set to true is important//`#start header` -- edit after this line, do not edit this line
// ========================================
//
// Copyright YOUR COMPANY, THE YEAR
// All Rights Reserved
// UNPUBLISHED, LICENSED SOFTWARE.
//
// CONFIDENTIAL AND PROPRIETARY INFORMATION
// WHICH IS THE PROPERTY OF your company.
//
// ========================================
`include "cypress.v"
//`#end` -- edit above this line, do not edit this line
// Generated on 12/21/2015 at 01:39
// Component: VideoCtrl_v1_0
module VideoCtrl_v1_0 (
output blank_n,
output hsync,
output [9:0] line_cnt,
output line_dma,
output vsync,
input clock,
input reset
);
parameter HorizBackPorch = 88;
parameter HorizFrontPorch = 40;
parameter HorizPulsePositive = 1;
parameter HorizSyncPulse = 128;
parameter HorizVisibleArea = 800;
parameter VertBackPorch = 23;
parameter VertFrontPorch = 1;
parameter VertPulsePositive = 1;
parameter VertSyncPulse = 4;
parameter VertVisibleArea = 600;
//`#start body` -- edit after this line, do not edit this line
// Your code goes here
//`#end` -- edit above this line, do not edit this line
endmodule
//`#start footer` -- edit after this line, do not edit this line
//`#end` -- edit above this line, do not edit this line
// Horizontal and Vertical states for Finite State Machine (FSM).
localparam STATE_FP = 2'd0;
localparam STATE_SYNC = 2'd1;
localparam STATE_BP = 2'd2;
localparam STATE_VIS = 2'd3;
// Horizontal and Vertical state registers.
reg [3:0] h_state_r;
reg [3:0] v_state_r;
// Current Horizontal and Vertical counters.
// These values count the pixels on each current state and don't carry the overall line or pixel count.
reg [9:0] h_count_r;
reg [9:0] v_count_r;
// Total line count output register to make it accessible to native code, this will only show the last visible line.
reg [9:0] line_cnt_r;
reg newline;
// Horizontal section
always@(posedge clock)
begin
// We need to see how we can force a reset even if the reset pin is wired to a digital constant of value 0
// Maybe a _Start routine via the API could be used to initalize the module as well as the reset.
// Otherwise make sure the state machine will eventually get to the right state no matter what the random initial values are.
if(reset)
begin
// Initialize horizontal registers with initial state set to Front Porch
h_state_r <= STATE_FP;
h_count_r <= 10'd1;
newline <= 1'b0;
end
else
begin
// Horizontal FSM
case (h_state_r)
STATE_FP:
begin
newline <= 1'b0;
// Check if we are still within the Horizontal Front Porch
if (h_count_r == HorizFrontPorch)
begin
// If we reached the end of the Front Porch.
// Reset the counter and jump into the Sync State.
h_count_r <= 10'd1;
h_state_r <= STATE_SYNC;
end
else
begin
// Increment the horizontal pixel count
h_count_r <= h_count_r + 10'd1;
end
end
STATE_SYNC:
begin
newline <= 1'b0;
// DMA signaling only can happen during the Back Porch so set the signal to low
// Check if we are still within the Horizontal Sync Pulse
if (h_count_r == HorizSyncPulse)
begin
// If we reached the end of the Sync Pulse.
// Reset the counter and jump into the Back Porch State.
h_count_r <= 10'd1;
h_state_r <= STATE_BP;
end
else
begin
// Increment the horizontal pixel count
h_count_r <= h_count_r + 10'd1;
end
end
STATE_BP:
begin
newline <= 1'b0;
// Check if we are still within the Horizontal Back Porch
if (h_count_r == HorizBackPorch)
begin
// If we reached the end of the Back Porch.
// Reset the counter and jump into the Visible State.
h_count_r <= 10'd1;
h_state_r <= STATE_VIS;
end
else
begin
// Increment the horizontal pixel count
h_count_r <= h_count_r + 10'd1;
end
end
STATE_VIS:
begin
// Check if we are still within the Horizontal Visible state
if (h_count_r == HorizVisibleArea)
begin
// If we reached the end of the Visible state.
// Reset the counter and jump into the Front Porch State.
h_count_r <= 10'd1;
h_state_r <= STATE_FP;
newline <= 1'b1;
end
else
begin
// Increment the horizontal pixel count
h_count_r <= h_count_r + 10'd1;
newline <= 1'b0;
end
end
default:
begin
// We should never end up here since our state machine is only two bits and we have 4 states covered.
// Set initial state set to Front Porch
h_state_r <= STATE_FP;
end
endcase
end
end
// Vertical section
always@(posedge clock)
begin
if(reset)
begin
// Initialize vertical registers with initial state set to Front Porch
v_state_r <= STATE_FP;
v_count_r <= 10'd1;
end
else
begin
if (newline)
begin
// Deal with the line counter register here, only increment it
// if we are on the vertical visible state, otherwise reset it to zero
if (v_state_r == STATE_VIS)
line_cnt_r <= line_cnt_r+10'd1;
else
line_cnt_r <= 10'd0;
// Vertical FSM
case (v_state_r)
STATE_FP:
begin
// Check if we are still within the Horizontal Front Porch
if (v_count_r == VertFrontPorch)
begin
// If we reached the end of the Front Porch.
// Reset the counter and jump into the Sync State.
v_count_r <= 10'd1;
v_state_r <= STATE_SYNC;
end
else
begin
v_count_r <= v_count_r+10'd1;
end
end
STATE_SYNC:
begin
// Check if we are still within the Vertical Sync Pulse
if (v_count_r == VertSyncPulse)
begin
// If we reached the end of the Sync Pulse.
// Reset the counter and jump into the Back Porch State.
v_count_r <= 10'd1;
v_state_r <= STATE_BP;
end
else
begin
v_count_r <= v_count_r+10'd1;
end
end
STATE_BP:
begin
// Check if we are still within the Vertical Back Porch
if (v_count_r == VertBackPorch)
begin
// If we reached the end of the Back Porch.
// Reset the counter and jump into the Visible State.
v_count_r <= 10'd1;
v_state_r <= STATE_VIS;
end
else
begin
v_count_r <= v_count_r+10'd1;
end
end
STATE_VIS:
begin
// Check if we are still within the Vertical Visible state
if (v_count_r == VertVisibleArea)
begin
// If we reached the end of the Visible state.
// Reset the counter and jump into the Front Porch State.
v_count_r <= 10'd1;
v_state_r <= STATE_FP;
end
else
begin
v_count_r <= v_count_r+10'd1;
end
end
default:
begin
// We should never end up here since our state machine is only two bits and we have 4 states covered.
// Just in case we add more bits to the state, reset the module as if a reset had occurred.
// Initialize vertical registers with initial state set to Front Porch
v_state_r <= STATE_FP;
v_count_r <= 10'd1;
end
endcase
end
end
end
//
// Assign the current registers to the actual outputs
//
// Horizontal and Vertical Blanking are only off in Visible state, blank signal has negative logic (0 blanking, 1 non-blanking)
assign blank_n = (h_state_r == STATE_VIS) & (v_state_r == STATE_VIS);
// hsync will be low or high during the horizontal synch pulse state depending on the HorizPulsePositive value.
// If pulse positive is true the hsync will be low (zero) when not active, otherwise it will be high (one) when not active.
assign hsync = (h_state_r == STATE_SYNC)?HorizPulsePositive: ~HorizPulsePositive;
// vsync will be low or high during the vertical synch pulse state depending on the VertPulsePositive value.
// If pulse positive is true the vsync will be low (zero) when not active, otherwise it will be high (one) when not active.
assign vsync = (v_state_r == STATE_SYNC)?VertPulsePositive: ~VertPulsePositive;
// line_cnt will allow the module to know what current visible line needs to be fetched.
assign line_cnt = line_cnt_r;
// line_dma will go high when we need to fetch another line, vertical blank state will be checked so no dma is requested on non visible lines.
// HorizDMAAdjust should never exceed HorizBackPorch since line_dma would only be triggered during the Horizontal STATE_BP (Back Porch) state.
assign line_dma = (h_state_r == STATE_BP)&(h_count_r+HorizDMAAdjust == HorizBackPorch)&(v_state_r == STATE_VIS);
// Horizontal and Vertical state registers.
reg [1:0] h_state_r;
reg [1:0] v_state_r;
#include <cytypes.h>
#include <cyfitter.h>
#include <CyLib.h>
#if !defined(`$INSTANCE_NAME`_H)
#define `$INSTANCE_NAME`_H
#define `$INSTANCE_NAME`_H_RES `$HorizVisibleArea`
#define `$INSTANCE_NAME`_V_RES `$VertVisibleArea`
// We could also declare these ones if we needed to access them.
// #define `$INSTANCE_NAME`_H_FP `$HorizFrontPorch`
// #define `$INSTANCE_NAME`_H_HP `$HorizSyncPulse`
// #define `$INSTANCE_NAME`_H_BP `$HorizBackPorch`
// #define `$INSTANCE_NAME`_V_FP `$VertFrontPorch`
// #define `$INSTANCE_NAME`_V_HP `$VertSyncPulse`
// #define `$INSTANCE_NAME`_V_BP `$VertBackPorch`
// #define `$INSTANCE_NAME`_H_DMA `$HorizDMAAdjust`
// #define `$INSTANCE_NAME`_H_PP `$HorizPulsePositive`
// #define `$INSTANCE_NAME`_V_PP `$VertPulsePositive`
#endif
`$INSTANCE_NAME` will be substituted with your instance name, so in our case it will be replaced with VideoCtrl_1, so with this our main.c can access VideoCtrl_1_H_RES and VideoCtrl_1_V_RES to obtain the actual needed resolution.#include <project.h>
// Get the resolution from the Video Controller instance.
#define VGA_RES_X VideoCtrl_1_H_RES
#define VGA_RES_Y VideoCtrl_1_V_RES
// Our buffer will be one bit per pixel so we only need 1/8th for our horizontal dimension.
#define VGA_X_FACTOR 8
// We don't have enough memory so we are going to duplicate the vertical lines
// to save on memory requirements.
#define VGA_Y_FACTOR 2
// This is our final dimmensions for our frame buffers.
#define VGA_X_BYTES ((VGA_RES_X)/VGA_X_FACTOR)
#define VGA_Y_BYTES (VGA_RES_Y/VGA_Y_FACTOR)
//
// Define our frame buffers making sure the X dimension is continuous in memory.
//
// CPU frame, by default this will be on 0x1FFF8000 Code SRAM space (i.e. section .ram)
uint8 cframe[VGA_Y_BYTES][VGA_X_BYTES];
// DMA frame, Declare the DMA video frame to go in our new section .ram2 located at 0x2000000
uint8 dframe[VGA_Y_BYTES][VGA_X_BYTES] __attribute__ ((section(".ram2")));
// Declare our DMA channel and our DMA Transaction Descriptor.
uint8 dmaCh, dmaTd;
// Set up a refresh signal so the CPU can refresh the DMA buffer.
volatile int refresh = 1;
// ScanLine Interrupt
//
// This gets called everytime our DMA transfer is done, so we can setup the next line
// or if we are on the last line we will refresh the dma frame with the current cpu frame.
CY_ISR(ScanLine)
{
// Get our line count from both status registers
// LINE_CNT_HI holds the upper 2 bits
// LINE_CNT_LO holds the lower 8 bits
uint16 line = ((LINE_CNT_HI_Status<<8))|LINE_CNT_LO_Status;
// We don't want to change anything unless we are past line 0.
if (line)
{
// Check if we are within the visible area.
if (line < VGA_RES_Y)
{
// Update the next DMA transfer for the next line.
// adusting the line by the Y skip factor.
if ((line % VGA_Y_FACTOR) == 0)
CY_SET_REG16(CY_DMA_TDMEM_STRUCT_PTR[dmaTd].TD1, LO16((uint32) dframe[line / VGA_Y_FACTOR]));
}
else if (line == VGA_RES_Y)
{
// On the last line since we are going to enter vertical sync
// Indicate the CPU that it's ok to refresh the screen.
CY_SET_REG16(CY_DMA_TDMEM_STRUCT_PTR[dmaTd].TD1, LO16((uint32) dframe[0]));
refresh = 1;
}
}
}
int main()
{
CyGlobalIntEnable; /* Enable global interrupts. */
//
// DMA setup
//
// Alocate a transaction descriptor.
dmaTd = CyDmaTdAllocate();
// Initialize the DMA channel to transfer from the dframe base address to the control base address.
// This indicates the high 16 bit address that will apply to the low addresses set on the TD.
dmaCh = DMA_DmaInitialize(1, 0, HI16((uint32) dframe), HI16(CYDEV_PERIPH_BASE));
// Configure the transaction descriptor for the first transfer.
// Transder VGA_X_BYTES with auto increment and signalling the end of the transfer.
// use the single transaction descriptor as our next TD as well.
CyDmaTdSetConfiguration(dmaTd, VGA_X_BYTES, dmaTd, DMA__TD_TERMOUT_EN | TD_INC_SRC_ADR);
// Set the destination address to be our DMA_OUT control register in the schematic.
CyDmaTdSetAddress(dmaTd, LO16((uint32) dframe[0]), LO16((uint32) DMA_OUT_Control_PTR));
// Set the channel transaction descriptor that we just configured.
CyDmaChSetInitialTd(dmaCh, dmaTd);
// Finally enable the DMA channel.
// This will start the first transfer and call the interrupt after every line.
CyDmaChEnable(dmaCh, 1);
//
// Interrup Setup.
//
// Set our interrupt for SCANLINE to the interrupt function declared above.
SCANLINE_StartEx(ScanLine);
//
// Initialize EEPROM
//
// Character set resides here and it is accessible with the following expression:
// CY_GET_REG8(CYDEV_EE_BASE + index + (y%8)*256);
// Where:
// index Is the sprite to be displayed from 0 to 255.
// y Is the current frame buffer line.
EEPROM_Start();
// Lets just setup something to display in here.
// for now just setup a border to see if we get it all in frame.
// lest set it as a define, so we can easily compile out the code
// when we don't need this test.
// The first test takes priority if the rest are defined.
#define TEST_CHAR_SET 1
#define TEST_BORDER 0
#if TEST_CHAR_SET
int x = 0, y = 0;
for (y = 0; y < VGA_Y_BYTES; y++)
{
for (x = 0; x < VGA_X_BYTES; x++)
{
// Leave blanks in between characters to place graphical characters separators
int index = ((y/16)*(VGA_X_BYTES/2)+x/2)%256;
//
// Temporary vertical timing fix.
//
// Apparently the memory copy done by the CPU takes longer than the vertical retrace
// So to fix this we need to add a second DMA
// To be implemented later
//
// Leave the last line blank until we add a 2nd DMA
// Otherwise that last line will appear on the top of the screen
// when the memory copy is done and repeated until we enable the DMA.
//
if (y == (VGA_Y_BYTES-1))
{
index = 0x00;
}
else if ((y%16)/8 == 0)
{
if ((x%2) == 1)
{
// Separator in cross spaces '+'
index = 0xc5;
}
else
{
// Separator between vertical characters '-'
index = 0xc4;
}
}
else if ((x%2) == 1)
{
// Separator between horizontal characters '|'
index = 0xb3;
}
// Fill the current frame buffer with the selected character
// row of pixels.
cframe[y][x] = CY_GET_REG8(CYDEV_EE_BASE + index + (y%8)*256);
}
}
#elif TEST_BORDER
int x = 0, y = 0;
for (y = 0; y < VGA_Y_BYTES; y++)
{
for (x = 0; x < VGA_X_BYTES; x++)
{
// On the first and last line we are setting all the pixels on.
if ((y == 0) || (y == (VGA_Y_BYTES-1)))
{
cframe[y][x] = 0xff;
}
else
{
// On the rest of the lines.
if (x == 0)
{
// Set the highest nibble for the left border.
cframe[y][x] = 0x80;
}
else if (x == (VGA_X_BYTES-1))
{
// Set the lowest nibble for the right border.
cframe[y][x] = 0x01;
}
else
{
// The rest is all blank (or background color.
cframe[y][x] = 0x00;
}
}
}
}
#endif
// We could update the CPU frame buffer (cframe) within the for loop.
// like for example implement a Pong game.
// The DMA interrupt and hardware will take care to update the DMA frame buffer.
for(;;)
{
// Refresh the screen when the interrupt sets the refresh bit on.
if (refresh)
{
//
// Apparently the memory copy takes longer than the vertical retrace
// So to fix this we need to add a second DMA
// To be implemented later
//
// Disable the DMA channel
CyDmaChDisable(dmaCh);
// Copy the CPU frame buffer into the DMA frame buffer
memcpy(dframe, cframe, VGA_Y_BYTES * VGA_X_BYTES);
// Enable the DMA channel
CyDmaChEnable(dmaCh, 1);
// We are done refreshing so reset refresh to 0
refresh = 0;
}
else
{
// Here we can put code that modifies the CPU frame when we are not busy updating
// the DMA buffer.
}
}
}
Resource Type : Used : Free : Max : % Used
============================================================
UDB : : : :
Macrocells : 103 : 89 : 192 : 53.65 %
Unique P-terms : 180 : 204 : 384 : 46.88 %
Total P-terms : 191 : : :
Datapath Cells : 0 : 24 : 24 : 0.00 %
Status Cells : 2 : 22 : 24 : 8.33 %
Status Registers : 2 : : :
Control Cells : 1 : 23 : 24 : 4.17 %
Control Registers : 1 : : :
So we are using 103 Macrocells and only have 89 left over, also the Verilog made usage of 180 P-terms only 12 of them are reused it seems and no Datapaths.Partial code attached in post, no space due to post size limit.
filename PartialVideoCtr_v1_1_v.txt
localparam EXEC_NOP = 3'd0; // Pass
localparam EXEC_LOAD_FP = 3'd1; // Load FP in D0 into A0
localparam EXEC_LOAD_SYNC = 3'd2; // Load Sync in D1 into A1
localparam EXEC_LOAD_BP = 3'd3; // Load BP in F0 into A0
localparam EXEC_LOAD_VIS = 3'd4; // Load Vis in F1 into A1
localparam EXEC_DEC_A0 = 3'd5; // Decrement A0
localparam EXEC_DEC_A1 = 3'd6; // Decrement A1
As shown in this image:UDB : : : :
Macrocells : 68 : 124 : 192 : 35.42 %
Unique P-terms : 134 : 250 : 384 : 34.90 %
Total P-terms : 142 : : :
Datapath Cells : 2 : 22 : 24 : 8.33 %
Status Cells : 3 : 21 : 24 : 12.50 %
Status Registers : 2 : : :
Routed Count7 Load/Enable : 1 : : :
Control Cells : 2 : 22 : 24 : 8.33 %
Control Registers : 1 : : :
Count7 Cells : 1 : : :
vs v1.0 (older one)UDB : : : :
Macrocells : 103 : 89 : 192 : 53.65 %
Unique P-terms : 180 : 204 : 384 : 46.88 %
Total P-terms : 191 : : :
Datapath Cells : 0 : 24 : 24 : 0.00 %
Status Cells : 2 : 22 : 24 : 8.33 %
Status Registers : 2 : : :
Control Cells : 1 : 23 : 24 : 4.17 %
Control Registers : 1 : : :
#include <cytypes.h>
#include <cyfitter.h>
#include <CyLib.h>
#if !defined(`$INSTANCE_NAME`_H)
#define `$INSTANCE_NAME`_H
// Don't adjust the existing resolution parameters definitions
// used in main.c so this updated version is compatible with the previous one.
#define `$INSTANCE_NAME`_H_RES `$HorizVisibleArea`
#define `$INSTANCE_NAME`_V_RES `$VertVisibleArea`
// Instead make a new VIS definition for the UDB configuration
// The API will use these defines internally to set the UDBs
// Use the parameters as unsigned values.
// Adjust the visible parameters by dividing them by 8 minus 1 since it's 0 based
// This is done so we can fit them into the 8 bit single buffer FIFO
#define `$INSTANCE_NAME`_H_VIS ((`$HorizVisibleArea`u>>3u)-1u)
#define `$INSTANCE_NAME`_V_VIS ((`$VertVisibleArea`u>>3u)-1u)
// The rest will fit in the 8 bits registers/FIFOs so just adjust them to be 0 based.
#define `$INSTANCE_NAME`_H_FP (`$HorizFrontPorch`u-1u)
#define `$INSTANCE_NAME`_H_SP (`$HorizSyncPulse`u-1u)
#define `$INSTANCE_NAME`_H_BP (`$HorizBackPorch`u-1u)
#define `$INSTANCE_NAME`_V_FP (`$VertFrontPorch`u-1u)
#define `$INSTANCE_NAME`_V_SP (`$VertSyncPulse`u-1u)
#define `$INSTANCE_NAME`_V_BP (`$VertBackPorch`u-1u)
// We don't need these ones yet.
//#define `$INSTANCE_NAME`_H_DMA `$HorizDMAAdjust`
//#define `$INSTANCE_NAME`_H_PP `$HorizPulsePositive`
//#define `$INSTANCE_NAME`_V_PP `$VertPulsePositive`
// Define the Horizontal and Vertical access to the UDB various registers and FIFOs
// Add defines to access them both directly or as a pointer
// All of these are in cyfitter.h but we want to give them a more comprehensive name.
// Define the access to the UDB Auxiliary Control Register needed to set the FIFOs in single buffer mode
#define `$INSTANCE_NAME`_H_DP_AUX_CTL_REG (*(reg8 *) `$INSTANCE_NAME`_HorizDP_u0__DP_AUX_CTL_REG)
#define `$INSTANCE_NAME`_H_DP_AUX_CTL_PTR ( (reg8 *) `$INSTANCE_NAME`_HorizDP_u0__DP_AUX_CTL_REG)
#define `$INSTANCE_NAME`_V_DP_AUX_CTL_REG (*(reg8 *) `$INSTANCE_NAME`_VertDP_u0__DP_AUX_CTL_REG)
#define `$INSTANCE_NAME`_V_DP_AUX_CTL_PTR ( (reg8 *) `$INSTANCE_NAME`_VertDP_u0__DP_AUX_CTL_REG)
// Define access to the Front Porch, Sync Pulse, Back Porch and Visible.
// So they match where our ALU expects those to be at as stated in our Verilog implementation.
// localparam EXEC_LOAD_FP = 3'd1; // Load FP into D0
// localparam EXEC_LOAD_SYNC = 3'd2; // Load Sync into D1
// localparam EXEC_LOAD_BP = 3'd3; // Load BP into F0
// localparam EXEC_LOAD_VIS = 3'd4; // Load Vis into F1
#define `$INSTANCE_NAME`_H_FP_REG (*(reg8 *) `$INSTANCE_NAME`_HorizDP_u0__D0_REG)
#define `$INSTANCE_NAME`_H_FP_PTR ( (reg8 *) `$INSTANCE_NAME`_HorizDP_u0__D0_REG)
#define `$INSTANCE_NAME`_H_SP_REG (*(reg8 *) `$INSTANCE_NAME`_HorizDP_u0__D1_REG)
#define `$INSTANCE_NAME`_H_SP_PTR ( (reg8 *) `$INSTANCE_NAME`_HorizDP_u0__D1_REG)
#define `$INSTANCE_NAME`_H_BP_REG (*(reg8 *) `$INSTANCE_NAME`_HorizDP_u0__F0_REG)
#define `$INSTANCE_NAME`_H_BP_PTR ( (reg8 *) `$INSTANCE_NAME`_HorizDP_u0__F0_REG)
#define `$INSTANCE_NAME`_H_VIS_REG (*(reg8 *) `$INSTANCE_NAME`_HorizDP_u0__F1_REG)
#define `$INSTANCE_NAME`_H_VIS_PTR ( (reg8 *) `$INSTANCE_NAME`_HorizDP_u0__F1_REG)
#define `$INSTANCE_NAME`_V_FP_REG (*(reg8 *) `$INSTANCE_NAME`_VertDP_u0__D0_REG)
#define `$INSTANCE_NAME`_V_FP_PTR ( (reg8 *) `$INSTANCE_NAME`_VertDP_u0__D0_REG)
#define `$INSTANCE_NAME`_V_SP_REG (*(reg8 *) `$INSTANCE_NAME`_VertDP_u0__D1_REG)
#define `$INSTANCE_NAME`_V_SP_PTR ( (reg8 *) `$INSTANCE_NAME`_VertDP_u0__D1_REG)
#define `$INSTANCE_NAME`_V_BP_REG (*(reg8 *) `$INSTANCE_NAME`_VertDP_u0__F0_REG)
#define `$INSTANCE_NAME`_V_BP_PTR ( (reg8 *) `$INSTANCE_NAME`_VertDP_u0__F0_REG)
#define `$INSTANCE_NAME`_V_VIS_REG (*(reg8 *) `$INSTANCE_NAME`_VertDP_u0__F1_REG)
#define `$INSTANCE_NAME`_V_VIS_PTR ( (reg8 *) `$INSTANCE_NAME`_VertDP_u0__F1_REG)
// Function Prototype to Initialze the UDBs
// We will follow the convention of using _Init as other components do
// And make it PSoC3 compatible (for Keil)
void `$INSTANCE_NAME`_Init(void) `=ReentrantKeil($INSTANCE_NAME . "_Init")`;
#endif
The first set of defines are to get the adjusted values for 0 based counts, also making the visible count fit in the 8 bit register by dividing it by 8 with shift operation. Every shift to the right divides the value by two, so three shifts divides it by 8.// Include the header of our instance, all the needed definitions will be there.
#include "`$INSTANCE_NAME`.h"
// Initialize the component
void `$INSTANCE_NAME`_Init(void) `=ReentrantKeil($INSTANCE_NAME . "_Init")`
{
// Store the current interrupt state here.
uint8 interruptState;
// Set both the Horizontal and Vertical FIFOs (F0 & F1) in single buffer mode.
// Pretty much this just stops the FIFOs from changing to the next entry
// making it act just like a register.
// Enter critical section
interruptState = CyEnterCriticalSection();
// Set the Count Start bit for both FIFOS (lower two bits)
// On both the Horizontal and Vertical DataPaths.
`$INSTANCE_NAME`_H_DP_AUX_CTL_REG |= (0x03);
`$INSTANCE_NAME`_V_DP_AUX_CTL_REG |= (0x03);
// Exit critical section
CyExitCriticalSection(interruptState);
// Setup all the UDB Data registers and FIFOS
// For both the Horizontal and Vertical UDBs
`$INSTANCE_NAME`_H_FP_REG = `$INSTANCE_NAME`_H_FP;
`$INSTANCE_NAME`_H_SP_REG = `$INSTANCE_NAME`_H_SP;
`$INSTANCE_NAME`_H_BP_REG = `$INSTANCE_NAME`_H_BP;
`$INSTANCE_NAME`_H_VIS_REG = `$INSTANCE_NAME`_H_VIS;
`$INSTANCE_NAME`_V_FP_REG = `$INSTANCE_NAME`_V_FP;
`$INSTANCE_NAME`_V_SP_REG = `$INSTANCE_NAME`_V_SP;
`$INSTANCE_NAME`_V_BP_REG = `$INSTANCE_NAME`_V_BP;
`$INSTANCE_NAME`_V_VIS_REG = `$INSTANCE_NAME`_V_VIS;
}
Hi Miguel,
Is it possible to use the project as an OSD....capture composite video signal and add the overlay on it?
Maybe a sync separator like LMH1881 or 1981 has to be used? Any thoughts?
Thanks in advance with best regards
Nick
And No, I don't get a commission from Cypress, not even free kits.
Hi Miguel,
Some misunderstanding.....a typo mistake. I mean to capture just the sync from the video signal by LMH1981, then use the sync by the PSoC for synchronization.
The video signal will be then mixed outside the PSoC.
QuoteAnd No, I don't get a commission from Cypress, not even free kits.Write it up as an appnote and they might...