-- See documentation in ray_tracer_avalon_module.vhd

architecture rtl of ray_tracer_avalon_module is
  
	signal camera_x : unsigned (8 downto 0);
	signal camera_y : unsigned (8 downto 0);
	signal camera_z : unsigned (8 downto 0);
	signal camera_x_buffer : unsigned (8 downto 0);
	signal camera_y_buffer : unsigned (8 downto 0);
	signal camera_z_buffer : unsigned (8 downto 0);
	type rectangle_memory_type is array (84 downto 0) of unsigned (8 downto 0);  -- we really only need 13, but then simulation fails because we try to read one past the end.
	signal rectangle_memory : rectangle_memory_type := (others => "000000000");
	signal rectangle_memory_buffer : rectangle_memory_type := (others => "000000000");
	signal buffer_index : unsigned (6 downto 0) := (others => '0');
	-- See ray_control for description:
	signal rect_memory_address : unsigned (7 downto 0);
	signal rect_memory_data : unsigned (8 downto 0);
	
	signal start_screen : std_logic := '0';
begin

	ray_tracer_renderer_instance : entity work.ray_tracer_renderer port map (
		clock => clock,
		reset => reset,

		camera_x => camera_x,
		camera_y => camera_y,
		camera_z => camera_z,
		rect_memory_address => rect_memory_address,
		rect_memory_data => rect_memory_data,

		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,
		
		start_screen_out => start_screen
	);

	BusInterface : process (clock, reset)
	begin
		if reset = '1' then
			camera_x <= "000000000";
			camera_y <= "000000000";
			camera_z <= "000000000";
		elsif rising_edge(clock) then
			if chipselect = '1' and write = '1' then
				if address = 0 then
					camera_x_buffer <= writedata(8 downto 0);
				elsif address = 1 then
					camera_y_buffer <= writedata(8 downto 0);
				elsif address = 2 then
					camera_z_buffer <= writedata(8 downto 0);
				else
					rectangle_memory_buffer(to_integer(address - 3)) <= writedata(8 downto 0);
				end if;
			elsif chipselect = '1' and read = '1' then
				if address = 0 then
					readdata <= "0000000" & camera_x_buffer;
				elsif address = 1 then
					readdata <= "0000000" & camera_y_buffer;
				elsif address = 2 then
					readdata <= "0000000" & camera_z_buffer;
				else
					readdata <= "0000000" & rectangle_memory_buffer(to_integer(address - 3));
				end if;
			end if;
			if start_screen = '1' then
				camera_x <= camera_x_buffer;
				camera_y <= camera_y_buffer;
				camera_z <= camera_z_buffer;
				buffer_index <= "0000000";
			elsif buffer_index /= "1010101" then -- 85
				rectangle_memory(to_integer(buffer_index)) <= rectangle_memory_buffer(to_integer(buffer_index));
				buffer_index <= buffer_index + 1;
			end if;
		end if;
	end process BusInterface;
	
	rectangle_memory_access : process (clock)
	begin
		if rising_edge(clock) then
			rect_memory_data <= rectangle_memory(to_integer(rect_memory_address));
		end if;
	end process rectangle_memory_access;
	
	debugging : process (clock)
	begin
		if rising_edge(clock) then
			if debug_address = 0 then
				debug_data <= camera_x;
			elsif debug_address = 1 then
				debug_data <= camera_y;
			elsif debug_address = 2 then
				debug_data <= camera_z;
			else
				debug_data <= rectangle_memory(to_integer(debug_address - 3));
			end if;
		end if;
	end process debugging;

end rtl;
