-- Colin O'Flynn's video utilities
-- coflynn@newae.com or www.newae.com
--


library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.all;

package video_utils is
component location_counter is
	Port	(
		VSYNC_in		: in std_logic;
		HSYNC_in		: in std_logic;
		FID_in		: in std_logic;
		PCLK_in		: in std_logic;

		pixel_out		: out unsigned (9 downto 0);
		line_out		: out unsigned (9 downto 0)
		);
end component location_counter;

   --where is the current active video??
   --outside: outside the tracking box
   --quad1: upper left quadrent
   --quad2: upper right quadrent
   --quad3: lower left quadrent
   --quad4: lower right quadrent
   type video_location_type is (outside, quad1, quad2, quad3, quad4);

component quadrent_location is
	Port (
		PCLK_in		: in std_logic;

		pixel_in		: in unsigned (9 downto 0);
		line_in		: in unsigned (9 downto 0);

		quadrentsize_in: in unsigned (7 downto 0);

		x_cursor_in	: in unsigned (9 downto 0);
		y_cursor_in	: in unsigned (9 downto 0);

		video_loc_out  : out video_location_type
		);
end component quadrent_location;

end video_utils;


------------------------------------------------------------------------------------------------------------------------
-- Based on the line and pixel number figures out what "quadrent" of the trackign window the current video pixel is in
------------------------------------------------------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use work.video_utils.all;

entity quadrent_location is
	Port (
		PCLK_in		: in std_logic;

		pixel_in		: in unsigned (9 downto 0);
		line_in		: in unsigned (9 downto 0);

		quadrentsize_in: in unsigned (7 downto 0);

		x_cursor_in	: in unsigned (9 downto 0);
		y_cursor_in	: in unsigned (9 downto 0);

		video_loc_out  : out video_location_type
		);
end quadrent_location;

architecture behavioural of quadrent_location is

begin


   --find what quadrent we are in currently in
   process(PCLK_in)
   begin
   if falling_edge(PCLK_in) then
   --if any counter is outside of the box, then
   --the video location is 'outside'
   if (pixel_in > (x_cursor_in + quadrentsize_in)) OR
      (pixel_in < (x_cursor_in - quadrentsize_in)) OR
	 (line_in	> (y_cursor_in + quadrentsize_in)) OR
	 (line_in < (y_cursor_in - quadrentsize_in)) then
		video_loc_out <= outside;

   --otherwise see if it is on left or right
   --side of crosshair
   elsif (pixel_in < x_cursor_in) then
   	 	--its on left side, see if it is
		--on top or bottom
   		if (line_in < y_cursor_in) then
			--top
			video_loc_out <= quad1;
		else
			--bottom
			video_loc_out <= quad3;
		end if;
   else
   		--its on right side, see if its on
		--top or bottom
   		if (line_in < y_cursor_in) then
			--top
			video_loc_out <= quad2;
		else
			--bottom
			video_loc_out <= quad4;
		end if;
   end if;
   end if;

   end process;

end behavioural;



------------------------------------------------------------------------------------------------------------------------
-- Location Counter, designed to take as input several signals from the TVP5145 and outputs the current location in
-- Line number and pixel number on that line
------------------------------------------------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity location_counter is
	Port	(
		VSYNC_in		: in std_logic;
		HSYNC_in		: in std_logic;
		FID_in		: in std_logic;
		PCLK_in		: in std_logic;

		pixel_out		: out unsigned (9 downto 0);
		line_out		: out unsigned (9 downto 0)
		);
end location_counter;

architecture behavioural of location_counter is

  signal pixel_counter	: unsigned (9 downto 0);
  signal line_counter	: unsigned (9 downto 0);

  signal FID_sync		: std_logic;

begin

  pixel_out <= pixel_counter;
  line_out <= line_counter;


  --Syncnoizes the even/odd to the VSYNC pulse, otherwise race conditions occur
   syncfid: process (VSYNC_in)
      begin
      if Rising_Edge(VSYNC_in) then
         FID_sync <= not FID_in;
      --else
      --   FID_sync <= FID_sync;
      end if;
   end process syncfid;

   --Horizontal Stuff
   horiz: process (HSYNC_in, PCLK_in)
      begin

      --horiz sync pulse
      if (HSYNC_in = '1') then
         pixel_counter <= CONV_UNSIGNED(0, 10);

      --if we are going to next pixel...
      elsif Rising_Edge(PCLK_in) then
         pixel_counter <= pixel_counter + CONV_UNSIGNED(1, 10);
      end if;
   end process horiz;

   --Vertical Stuff
   vert: process (VSYNC_in, HSYNC_in, FID_Sync)
      begin

      --vert sync pulse
      if (VSYNC_in= '1') then
         if (FID_sync = '1') then
            --if we are on even lines...
            line_counter <= CONV_UNSIGNED(0, 10);
         else
            --if we are on odd lines...
            line_counter <= CONV_UNSIGNED(1, 10);
         end if;

 
       --horiz sync pulse
      elsif Rising_Edge(HSYNC_in) then
         line_counter <= line_counter + CONV_UNSIGNED(2, 10);
      end if;
   end process vert;

end behavioural;

