

// adapted from lab3 vga_ball
module viewtube(input logic        clk,
	input logic 	   reset,
	input logic [31:0]  writedata,
    output logic [31:0]  readdata,
	input logic 	   write,
    input logic 	   read,
	input 		   chipselect,
	input logic [3:0]  address,
	output logic [7:0] VGA_R, VGA_G, VGA_B,
	output logic 	   VGA_CLK, VGA_HS, VGA_VS,
		               VGA_BLANK_n,
	output logic 	   VGA_SYNC_n);

   logic [10:0]	   hcount;
   logic [9:0]     vcount;


   logic [7:0]  sprite_table_VGA_R, sprite_table_VGA_G, sprite_table_VGA_B;
   logic [7:0]  sprite_index;
   logic 		sprite_increment_x; 
   logic [4:0]  sprite_row_offset;
   logic [4:0]  sprite_col_offset;
   logic [11:0] sprite_cur_x_pos;
   logic [11:0] sprite_cur_y_pos;
   logic [11:0] sprite_start_x_pos;
   logic [11:0] sprite_start_y_pos;
   logic [9:0]  sprite_width;
   logic [9:0]  sprite_height;
   logic        sprite_ready;
   logic        sprite_active;
   logic [23:0] sprite_writedata;
   logic [7:0]  sprite_io_sprite_index;
   logic [1:0]  sprite_io_address;
   logic		sprite_io_write;
   logic [7:0]  sprite_display_buffer_index;

   logic background_ready_to_read;
   logic background_seek_to_x_pos;
   logic background_active;
   logic [7:0] 	   background_r, background_g, background_b;
   logic [7:0] 	   line_buffer_r, line_buffer_g, line_buffer_b;
   logic [11:0] background_x_index;
   logic [11:0] background_y_index;
   logic [11:0] background_x_start;
   logic [11:0] background_y_start;
   logic 		background_window;

   logic [9:0] background_width;
   logic [9:0] background_height;

   logic background_ready;

   logic shift_current_sprite;
   logic [1:0] sprite_index_delay;

   logic background_write;
   logic sync_movement;
   logic go_to_beginning;
   logic [31:0] background_writedata;
   logic [1:0]  background_address;

   initial background_width = 500;
   initial background_height = 425;
   initial background_write = 0;
   initial sync_movement = 0;
   initial go_to_beginning = 0;
   initial sprite_io_write = 0;
   initial sprite_index_delay = 2'b0;

	

   viewtube_background_layer background_layer(
	   .VGA_R(background_r), 
	   .VGA_G(background_g), 
	   .VGA_B(background_b), 
	   .active(background_active), 
	   .x_pos(background_x_index), 
	   .y_pos(background_y_index),
	   .window_x(background_x_start),
	   .window_y(background_y_start),
	   .ready_to_read(background_ready_to_read),
	   .seek_to_x_pos(background_seek_to_x_pos),
	   .ready(background_ready),
	   .write(background_write),
	   .writedata(background_writedata),
	   .address(background_address),
	   .*);

	viewtube_line_buffer line_buffer(
		.background_VGA_R(background_r), 
		.background_VGA_G(background_g), 
		.background_VGA_B(background_b),
		.out_VGA_R(line_buffer_r), 
		.out_VGA_G(line_buffer_g), 
		.out_VGA_B(line_buffer_b),
		.sprite_index(sprite_display_buffer_index),
		.*
	);

	viewtube_sprite_table sprite_table(
		.out_VGA_R(sprite_table_VGA_R), 
		.out_VGA_G(sprite_table_VGA_G), 
		.out_VGA_B(sprite_table_VGA_B),
		.*
	);


   vga_counters counters(.clk50(clk), .*);


   always_ff @(posedge clk) begin
	   if (reset) begin
		   background_write <= 0;
		   background_address <= 2'b0;
		   background_writedata <= 32'b0;
		   sprite_writedata <= 24'b0;
   		   sprite_io_address <= 2'b0;
		   sprite_io_sprite_index <= 8'b0;
		   sync_movement <= 0;
		   sprite_io_write <= 0;
		   sprite_index_delay <= 0;
	   end else if (chipselect && write) begin
		   case (address)
				4'h0 : begin //scroll display
						background_write <= 1;
						background_address <= 2'd0;
						background_writedata <= writedata;
				end
				4'h1 : begin // update sprite 
   						sprite_writedata <= writedata[23:0];
   						sprite_io_sprite_index <= writedata[31:24];
   						sprite_io_address <= 2'b0;
   						sprite_io_write <= 0;
						sprite_index_delay <= 2'd3;
				end
				4'h2 : begin // move sprite
   						sprite_writedata <= writedata[23:0];
   						sprite_io_sprite_index <= writedata[31:24];
   						sprite_io_address <= 2'd1;
   						sprite_io_write <= 0;
						sprite_index_delay <= 2'd3;
				end
				4'h3 : background_width <=  500;
				4'h4 : background_width <=  500;
				4'h5 : background_width <=  500;
				4'h6 : background_width <=  500;
				4'h7 : background_width <=  500;
				4'h8 : background_width <=  500;
				4'h9 : background_width <=  500;
				4'ha : background_width <=  500;
				4'hb : background_width <=  500;
				4'hc : background_width <=  500;
				4'hd : background_width <=  500;
				4'he : background_width <=  500;
				4'hf : background_width <=  500;
				default: background_width <=  500;
		   endcase
	   end else if (chipselect && read ) begin
		   case (address)
				4'h0 : readdata <= {4'b0, background_x_start, 4'b0, background_y_start};
				4'h1 : readdata <= writedata;
				4'h2 : readdata <= writedata;
				4'h3 : readdata <= writedata;
				4'h4 : readdata <= writedata;
				4'h5 : readdata <= writedata;
				4'h6 : readdata <= writedata;
				4'h7 : readdata <= writedata;
				4'h8 : readdata <= writedata;
				4'h9 : readdata <= writedata;
				4'ha : readdata <= writedata;
				4'hb : readdata <= writedata;
				4'hc : readdata <= writedata;
				4'hd : readdata <= writedata;
				4'he : readdata <= writedata;
				4'hf : readdata <= writedata;
				default: readdata <= writedata;
		   endcase
		   	if(sprite_index_delay == 2'd3) begin
			   sprite_io_write <= 1;
		   end else if (sprite_io_write) begin
			   sprite_io_write <= 0;
		   end
		   if(sprite_index_delay != 0) begin
		       sprite_index_delay <= sprite_index_delay -1;
		   end
		   
		   background_write <=0;
	   end else begin
		   	if(sprite_index_delay == 2'd3) begin
			   sprite_io_write <= 1;
		   end else if (sprite_io_write) begin
			   sprite_io_write <= 0;
		   end
		   if(sprite_index_delay != 0) begin
		       sprite_index_delay <= sprite_index_delay -1;
		   end
		   
		   background_write <=0;

		   if (vcount == 479 && hcount == 1280) begin
			   sync_movement <= 1;
		   end else begin
			   sync_movement <= 0;
		   end

		   if (vcount == 480 && hcount == 1280) begin
			   go_to_beginning <= 1;
		   end else begin
			   go_to_beginning <= 0;
		   end

	   end

	
	

   end


   always_comb begin
	if (sprite_io_write || sprite_index_delay != 2'b0) begin
		   sprite_index = sprite_io_sprite_index;
	   end else begin
		   sprite_index = sprite_display_buffer_index;
	   end
      {VGA_R, VGA_G, VGA_B} = {8'h0, 8'h0, 8'h0};
      if (VGA_BLANK_n ) begin
		//if( (hcount > 500) && (hcount < 600) && (vcount > 200 && vcount < 250)) begin
			//{VGA_R, VGA_G, VGA_B} = {8'h0,8'h0,8'hff};
		//	{VGA_R, VGA_G, VGA_B} = {line_buffer_r, line_buffer_g, line_buffer_b};
		//end else begin
	 	//{VGA_R, VGA_G, VGA_B} = {background_r, background_g, background_b};
			{VGA_R, VGA_G, VGA_B} = {line_buffer_r, line_buffer_g, line_buffer_b};
		//end
	  end
   end
	       
endmodule




