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

entity ray_tracer_renderer is
port(
	clock : in std_logic;
	reset : in std_logic;

	camera_x,
	camera_y,
	camera_z : in unsigned (8 downto 0);
	
	-- Allow this module to request rect data from whatever contains it. See 
	-- ray_control for more info.
	rect_memory_address : out unsigned (7 downto 0);
	rect_memory_data : in unsigned (8 downto 0);
	
	vga_clock,
	vga_h_sync,
	vga_v_sync,
	vga_blank,
	vga_sync : out std_logic;
	vga_r,
	vga_g,
	vga_b : out unsigned(9 downto 0);
	
	start_screen_out : out std_logic := '0'
);
end ray_tracer_renderer ;

architecture tracer of ray_tracer_renderer is
	constant INITIAL_ROW : signed(8 downto 0) := "010111101"; -- 189
	constant LAST_ROW : signed(8 downto 0) := "111001110"; -- - 50
	
	signal screen_column : unsigned (8 downto 0); -- column video generator wants to read
	signal screen_color : std_logic_vector (17 downto 0); -- color of pixel at said column
	signal start_screen : std_logic;
	signal start_row : std_logic;
	signal last_start_row : std_logic;

	signal ray_casting_row_counter : signed (8 downto 0);
	signal row_minus_1 : signed (8 downto 0);
begin
	start_screen_out <= start_screen;
	
	video_generator : entity work.video_generator port map (
		clock => clock,
		reset => reset,
		
		col_to_read => screen_column,
		color => screen_color,
		start_screen => start_screen,
		start_row => start_row,

		vga_clock => vga_clock,
		vga_h_sync => vga_h_sync,
		vga_v_sync => vga_v_sync,
		vga_blank => vga_blank,
		vga_sync => vga_sync,
		vga_r => vga_r,
		vga_g => vga_g,
		vga_b => vga_b
	);
	
	row_counter : process(clock)
		variable row : signed (8 downto 0) := (others => '0');
	begin
		if rising_edge(clock) then
			row := ray_casting_row_counter;
			if start_screen = '1' or reset = '1' then -- reset
				row := INITIAL_ROW;
			elsif start_row = '1' and last_start_row = '0' then -- enable
				-- start_row is based on the 25 mhz clock, so over here it looks
				-- like it's high for 2 cycles. last_start_row prevents us from
				-- incrementing the counter twice.
				row := row - 1;
				last_start_row <= '1';
			else
				last_start_row <= '0';
			end if;
			ray_casting_row_counter <= row;
			if row = LAST_ROW then
				row_minus_1 <= INITIAL_ROW;
			else
				row_minus_1 <= row - 1;
			end if;
		end if;
	end process;
	
	buffered_line_generator : entity work.buffered_line_generator port map (
		clock => clock,
		
		row => row_minus_1,
		
		camera_x => camera_x,
		camera_y => camera_y,
		camera_z => camera_z,
		
		rect_memory_address => rect_memory_address,
		rect_memory_data => rect_memory_data(7 downto 0),
		
		screen_col => screen_column,
		screen_col_color => screen_color
	);
end tracer;