library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity xy_detector is

port (
	clk50:	in std_logic;
	
	-- Avalon Bus Signals
    signal address : IN STD_LOGIC_VECTOR (4 DOWNTO 0);
    signal chipselect : IN STD_LOGIC;
    signal read : IN STD_LOGIC;
    signal reset_n : IN STD_LOGIC;
    signal write : IN STD_LOGIC;
    signal writedata : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
    signal readdata : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);	
	
	-- Input from the line buffer
	read_data : IN std_logic_vector(29 downto 0);
	v_pos	:	in std_logic_vector(15 downto 0); --unsigned
	h_pos	:	in std_logic_vector(15 downto 0) --unsigned	
);
end xy_detector;

architecture RTL of xy_detector is

			--first we will determine whether or not a given pixel is a laser pixel
			signal Red : unsigned(9 downto 0) := "0000000000";
			signal Green : unsigned(9 downto 0) := "0000000000";
			signal Blue : unsigned(9 downto 0) := "0000000000";
			constant Rmin : integer := 236;
			constant Rmax : integer := 255;
			constant Gmin : integer := 221;
			constant Gmax : integer := 255;
			constant Bmin : integer := 220;
			constant Bmax : integer := 255;
			signal pix_min : integer := 2;--the minimum number of across a dot
			signal pix_max : integer := 30;--the maximum number of across a dot
			signal laser_pixel : boolean := false; --decides if the pixel is a laser pixel
			signal dot1 : unsigned(9 downto 0) := "0000000000";
			signal dot2 : unsigned(9 downto 0) := "0000000000";
			signal dot3 : unsigned(9 downto 0) := "0000000000";
			signal flag1 : boolean := false;
			signal flag2 : boolean := false;
			signal flag3 : boolean := false;
			
			signal x1_coord : std_logic_vector(15 downto 0); --the x values
			signal y1_coord : std_logic_vector(15 downto 0);
			signal x2_coord : std_logic_vector(15 downto 0); --the x values
			signal y2_coord : std_logic_vector(15 downto 0);
			signal x3_coord : std_logic_vector(15 downto 0); --the x values
			signal y3_coord : std_logic_vector(15 downto 0);
			
		begin
			--unsigned can compare to integer
			SetLaser	:	process(clk50)
			begin
				if rising_edge(clk50) then
					Red <= unsigned(read_data(29 downto 20));
					Green <= unsigned(read_data(19 downto 10));
					Blue <= unsigned(read_data(9 downto 0));
						if (Rmin <= Red and Red <= Rmax) then
							if (Gmin <= Green and Green <= Gmax) then
								if (Bmin <= Blue and Blue <= Bmax) then
									laser_pixel <= true;
								
								end if;
							end if;
						end if;
				--will only set flag1 once dot1 has been confirmed, otherwise will reset
				--same is true of dot2 and flag2
				
					if(not laser_pixel and dot1 = 0) then
					--do nothing
					elsif(laser_pixel and not flag1) then --find the first laser pixel
						dot1 <= dot1 + 1;
					elsif(not laser_pixel and dot1 /= 1 and dot1 < pix_min) then-- if found a null dot before minimum dot size met
						dot1 <= "0000000000";
					elsif(not laser_pixel and dot1 > pix_max) then -- first null dot after maximum dot size
						dot1 <= "0000000000";
					elsif(not laser_pixel and dot1 <= pix_max and dot1 >= pix_min) then -- first dot complete
						flag1 <= true;
						x1_coord <=	std_logic_vector(unsigned(v_pos)-(dot1/2)); --the x value
						y1_coord <= std_logic_vector(unsigned(h_pos)+(dot1/2)); --the y value
					
					elsif(flag1 and not(laser_pixel) and dot2 = 0) then
					--do nothing
					elsif(flag1 and laser_pixel and not flag2) then
						dot2 <= dot2 + 1;
					elsif(flag1 and not laser_pixel and dot2 < pix_min) then
						dot2 <= "0000000000";
					elsif(flag1 and not laser_pixel and dot2 > pix_max) then
						dot2 <= "0000000000";
					elsif(flag1 and not laser_pixel and dot2 <= pix_max and dot2 >= pix_min) then
						flag2 <= true;
						x2_coord <=	std_logic_vector(unsigned(v_pos)-(dot2/2)); --the x value
						y2_coord <= std_logic_vector(unsigned(h_pos)+(dot2/2)); --the y value
					end if;
					if(flag2 and not laser_pixel and dot3 = 0) then
					--do nothing
					end if;
					if(flag2 and laser_pixel and not flag3) then
						dot3 <= dot3 + 1;
					end if;
					if(flag2 and not laser_pixel and dot3 < pix_min) then
						dot3 <= "0000000000";
					end if;
					if(flag2 and not laser_pixel and dot3 > pix_max) then
						dot3 <= "0000000000";
					end if;
					if(flag2 and not laser_pixel and dot3 <= pix_max and dot3 >= pix_min) then
						flag3 <= true;
						x3_coord <=	std_logic_vector(unsigned(v_pos)-(dot3/2)); --the x value
						y3_coord <= std_logic_vector(unsigned(h_pos)+(dot3/2)); --the y value							
					end if;
					if(unsigned(v_pos) = 0 and unsigned(h_pos) = 0) then
						dot1 <= "0000000000";
						dot2 <= "0000000000";
						dot3 <= "0000000000";
						flag1 <= false;
						flag2 <= false;
						flag3 <= false;
					end if;
					if chipselect = '1' then
						if address(2 downto 0) = "001" then
							readdata <= h_pos;
						elsif address(2 downto 0) = "010" then
							readdata <= v_pos;
						elsif address(2 downto 0) = "011" then
							readdata <= x2_coord;
						elsif address(2 downto 0) = "100" then
							readdata <= y2_coord;
						elsif address(2 downto 0) = "101" then
							readdata <= x3_coord;
						elsif address(2 downto 0) = "110" then
							readdata <= y3_coord;
						end if;
					end if;
				end if;
				
			end process SetLaser;			

end RTL;