----------------------------------------------------------------------------------------------------
-- Pixel Counter for 256 x 192 Pixel Display
-- by C.Meyer & c't magazin 4/2009
-- frame should be high during 256 clock cycles horizontal, 192 lines vertical
----------------------------------------------------------------------------------------------------
library ieee;
  use ieee.std_logic_1164.all;
  use ieee.std_logic_unsigned.all;
  use ieee.numeric_std.all;

entity framer is
  port (
    vsync: in  std_logic;		-- asyncronous
    hsync: in  std_logic;		-- asyncronous
    clk12: in  std_logic;
    clk25: in  std_logic;
	 grid_X: in std_logic_vector (7 downto 0);
	 grid_Y: in std_logic_vector (7 downto 0);
	 smallw: in  std_logic;
	 start_X: 	in std_logic_vector (7 downto 0);
	 start_Y:	in std_logic_vector (7 downto 0);
	 size_X:	in std_logic_vector (7 downto 0);
	 size_Y:	in std_logic_vector (7 downto 0);
	 trig_X:	in std_logic_vector (7 downto 0);
	 trig_Y:	in std_logic_vector (7 downto 0);
    grid:	out  std_logic;
    trig_vert:	out  std_logic;
    trig_hor:	out  std_logic;
	 frame:	out std_logic;
	 framedone:	out std_logic;
    adr: 	out std_logic_vector (15 downto 0)
    );
end framer;

architecture behave of framer is
  signal frame_x : std_logic_vector (7 downto 0);
  signal frame_y : std_logic_vector (8 downto 0);
  signal frame_y_adr : std_logic_vector (7 downto 0);
  signal grid_Y_int : std_logic_vector (7 downto 0);
  signal hctr  : integer range 793 downto 0;
  signal vctr  : integer range 524 downto 0;
  signal hgridcount  : integer range 255 downto 0;
  signal vgridcount  : integer range 255 downto 0;
  signal clk : std_logic;
  signal xvalid : std_logic;
  signal yvalid : std_logic;
  signal framevalid : std_logic;
  signal vborder : std_logic;
  signal hborder : std_logic;
  signal hgrid : std_logic;
  signal vgrid : std_logic;
  
  signal hwinstart  : std_logic_vector (9 downto 0);
  signal vwinstart  : std_logic_vector (9 downto 0);
  signal hwinend  : std_logic_vector (9 downto 0);
  signal vwinend  : std_logic_vector (9 downto 0);
  signal hstart9  : std_logic_vector (8 downto 0);
  signal hsize9  : std_logic_vector (8 downto 0);
  signal vstart9  : std_logic_vector (8 downto 0);
  signal vsize9  : std_logic_vector (8 downto 0);
  
begin

adr(7 downto 0) <= frame_x;
frame_y_adr <= frame_y(7 downto 0) when (smallw='1') else frame_y(8 downto 1);
adr(15 downto 8) <= frame_y_adr;

clk <= clk25 when (smallw='1') else clk12;
-- Frame-Koordinaten je nach Fenstergröße (und Pixeltakt) berechnen
hstart9 <= start_X & '0';
hsize9 <= size_X & '0';
vstart9 <= start_Y & '0';
vsize9 <= size_Y & '0';
hwinstart <= '0' & hstart9 when (smallw='1') else "00" & start_X;
vwinstart <= '0' & vstart9;
hwinend <= hstart9 + hsize9 when (smallw='1') else start_X + hsize9;
vwinend <= vstart9 + vsize9 when (smallw='1') else vstart9 + (size_Y & "00");
grid_Y_int <= grid_Y when (smallw='1') else grid_Y(6 downto 0) & '0';
framevalid	<=	xvalid and yvalid;
grid <= vborder or hborder or ((hgrid or vgrid) and framevalid);

framedone <= not yvalid;

trig_hor <= '1' when ((frame_y_adr = trig_Y) and (framevalid = '1')) else '0';
trig_vert <= '1' when ((frame_x = trig_X) and (framevalid = '1')) else '0';

process (vsync, hsync, clk, xvalid)	-- horizontale X-Position innerhalb Frame hochzählen
begin
	if xvalid = '0' then
		frame_x <= (others =>'0');
		hgridcount<=1;
		hgrid<='0';
	elsif rising_edge(clk) then 
		if (frame_x < 255) then
			frame_x <= frame_x+1;
			hgridcount <= hgridcount+1;
			if hgridcount=grid_X then
				hgridcount<=1;
				hgrid<='1';
			else
				hgrid<='0';
			end if;
		end if;
	end if;
end process;

process (vsync, xvalid, yvalid)	-- vertikale Y-Position innerhalb Frame hochzählen
begin
	if yvalid = '0' then
		frame_y <= (others =>'0');
		vgridcount<=1;
		vgrid<='0';
	elsif falling_edge(xvalid) then 
		frame_y <= frame_y+1;
		vgridcount <= vgridcount+1;
		if vgridcount=grid_Y_int then
			vgridcount<=1;
			vgrid<='1';
		else
			vgrid<='0';
		end if;
	end if;
end process;

xpos:process (clk)
begin
	if rising_edge(clk) then
		vborder<='0';
		frame <= framevalid; -- UM 1 CLK VERZÖGERT
		if (hsync='0') or (vsync='0')  then
			hctr<=0;
			xvalid<='0';
		else
			hctr<=hctr+1;
		end if;
		if hctr=hwinstart then
			xvalid<='1';
			vborder<=yvalid;
			if (vctr=vwinstart) or (vctr=vwinend) then
				hborder<='1';
			end if;
		elsif hctr=hwinend then
			hborder<='0';
			xvalid<='0';
			vborder<=yvalid;
		end if;		
	end if;
end process;

ypos:process (hsync)
begin
	if rising_edge(hsync) then
		if vsync='0' then
			yvalid<='0';
			vctr<=0;
		else
			vctr<=vctr+1;
		end if;
		if vctr=vwinstart then
			yvalid<='1';
		elsif vctr=vwinend then
			yvalid<='0';
		end if;
	end if;
end process;

end behave;
