----------------------------------------------------------------------------------------------------
-- 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_lcd is
	port (
	pixel_column:	in std_logic_vector (8 downto 0);
	pixel_line:	in std_logic_vector (7 downto 0);
    clk: in  std_logic;
    checker_grid: in  std_logic;
    pixel_clk: in  std_logic;
	grid_X: in std_logic_vector (7 downto 0);
	grid_Y: in std_logic_vector (7 downto 0);
	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);
	pixel_addr:	out std_logic_vector (15 downto 0);
    grid:	out  std_logic;
    plotsync:	out  std_logic;	-- '1' innerhalb vertikaler Grafik-Frame-Grenzen für Plot-Routinen etc.
	frame:	out std_logic
    );
end framer_lcd;

architecture behave of framer_lcd is
  signal pixel_x  : std_logic_vector (9 downto 0);
  signal pixel_y  : std_logic_vector (8 downto 0);
  signal xvalid : std_logic;
  signal yvalid : std_logic;
  signal frame_int : std_logic;
  signal checker : std_logic;	-- feines Muster
  
  
  signal hgridcount  : integer range 255 downto 0;
  signal vgridcount  : integer range 255 downto 0;
  signal hgrid : std_logic;
  signal vgrid : std_logic;
  
begin


-- Frame-Koordinaten je nach Fenstergröße (und Pixeltakt) berechnen
checker <= pixel_column(0) xor pixel_line(0) when (checker_grid='1') else '1';
pixel_addr <= pixel_y(7 downto 0) & pixel_x(7 downto 0);
grid <= (hgrid or vgrid) and frame_int and checker;
frame_int <= '1' when (xvalid = '1' and yvalid = '1') else '0';
frame <= frame_int;
plotsync <= yvalid;

process (pixel_clk)	-- über Register wg. Glitches der Counter
begin
	if rising_edge(pixel_clk) then
		pixel_x <= '0' & pixel_column - start_X;
		pixel_y <= '0' & pixel_line - start_Y;
		if pixel_x < x"100"  then
			xvalid <= '1';
		else
			xvalid <= '0';
		end if;
		if pixel_y < x"0C0"  then
			yvalid <= '1';
		else
			yvalid <= '0';
		end if;
	end if;
end process;


process (pixel_clk, xvalid)	-- horizontales X-Grid hochzählen
begin
	if xvalid = '0' then
		hgridcount<=1;
		hgrid<='1';
	elsif rising_edge(pixel_clk) then 
		hgridcount <= hgridcount+1;
		if (hgridcount=grid_X) or (pixel_x=x"FF") then
			hgridcount<=1;
			hgrid<='1';
		else
			hgrid<='0';
		end if;
	end if;
end process;

process (xvalid, yvalid)	-- vertikales Y-Grid hochzählen
begin
	if yvalid = '0' then
		vgridcount<=1;
		vgrid<='1';
	elsif falling_edge(xvalid) then 
		vgridcount <= vgridcount+1;
		if (vgridcount=grid_Y) or (pixel_y=x"BE") then	-- $BF für nächste Zeile
			vgridcount<=1;
			vgrid<='1';
		else
			vgrid<='0';
		end if;
		
	end if;
end process;

end behave;
