----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    13:25:59 05/11/2013 
-- Design Name: 
-- Module Name:    main - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
use work.MEMORY.all;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity main is
Port ( clk,en,reset : in  STD_LOGIC;
       srclk0,srclk1,srclk2: out  STD_LOGIC;
		 rclk0,rclk1,rclk2: out  STD_LOGIC;
		 clk_out0,clk_out1,clk_out2: out  STD_LOGIC;
		 ser_row0,ser_row1,ser_row2,ser_row3,ser_row4,ser_row5,ser_row6,ser_row7: out STD_LOGIC;
		 srclk_level,rclk_level,ser_level: out STD_LOGIC;
		 
		 rx : in  STD_LOGIC;
		 
		 an: out std_logic_vector(3 downto 0)
		 );
end main;

architecture Behavioral of main is

signal d1_srclk0,d1_srclk1,d1_srclk2:  STD_LOGIC;
signal d1_rclk0,d1_rclk1,d1_rclk2:  STD_LOGIC;
signal d1_clk_out0,d1_clk_out1,d1_clk_out2:  STD_LOGIC;
signal d1_ser_row0,d1_ser_row1,d1_ser_row2,d1_ser_row3,d1_ser_row4,d1_ser_row5,d1_ser_row6,d1_ser_row7: STD_LOGIC;
signal d1_srclk_level,d1_rclk_level,d1_ser_level: STD_LOGIC;

signal d2_srclk0,d2_srclk1,d2_srclk2:  STD_LOGIC;
signal d2_rclk0,d2_rclk1,d2_rclk2:  STD_LOGIC;
signal d2_clk_out0,d2_clk_out1,d2_clk_out2:  STD_LOGIC;
signal d2_ser_row0,d2_ser_row1,d2_ser_row2,d2_ser_row3,d2_ser_row4,d2_ser_row5,d2_ser_row6,d2_ser_row7: STD_LOGIC;
signal d2_srclk_level,d2_rclk_level,d2_ser_level: STD_LOGIC;

component dispcon_letters is
Port ( clk: in  STD_LOGIC;
		 letter: in unsigned (7 downto 0);
		 color: in unsigned (0 to 17);
       srclk0,srclk1,srclk2: out  STD_LOGIC;
		 rclk0,rclk1,rclk2: out  STD_LOGIC;
		 clk_out0,clk_out1,clk_out2: out  STD_LOGIC;
		 ser_row0,ser_row1,ser_row2,ser_row3,ser_row4,ser_row5,ser_row6,ser_row7: out STD_LOGIC;
		 srclk_level,rclk_level,ser_level: out STD_LOGIC
		 );
end component;

signal frame_clk_counter: unsigned (25 downto 0) := (others => '0');

signal frame_counter : unsigned (9 downto 0) := (others => '0');

component dispcon_animations is
Port ( clk: in  STD_LOGIC;
		 animation: in unsigned (5 downto 0);
		 frame: in unsigned (9 downto 0); 
       srclk0,srclk1,srclk2: out  STD_LOGIC;
		 rclk0,rclk1,rclk2: out  STD_LOGIC;
		 clk_out0,clk_out1,clk_out2: out  STD_LOGIC;
		 ser_row0,ser_row1,ser_row2,ser_row3,ser_row4,ser_row5,ser_row6,ser_row7: out STD_LOGIC;
		 srclk_level,rclk_level,ser_level: out STD_LOGIC
		 );
end component;

signal dispen: unsigned (0 to 1);
signal select_disp: std_logic := '1';

component uart_rx is
    Port (            serial_in : in std_logic;
                       data_out : out std_logic_vector(7 downto 0);
                    read_buffer : in std_logic;
                   reset_buffer : in std_logic;
                   en_16_x_baud : in std_logic;
            buffer_data_present : out std_logic;
                    buffer_full : out std_logic;
               buffer_half_full : out std_logic;
                            clk : in std_logic);
    end component;


signal dout : STD_LOGIC_VECTOR (7 downto 0);
signal data_present : STD_LOGIC;
signal letters_count,current_letter : unsigned (7 downto 0) := (others => '0');
signal letters_clk_counter : unsigned (26 downto 0) := (others => '0');
type t_letters is array (0 to 512) of std_logic_vector (7 downto 0);
signal letters: t_letters;
signal letter: unsigned (7 downto 0);
signal letter_color: unsigned (17 downto 0) := (others => '0');
signal letter_color_counter: unsigned (1 downto 0) := (others => '0');
signal if_showing:std_logic:='0';
signal animation: unsigned (5 downto 0);

type statetype is (wait_for_communication,select_communication,save_color,save_word,show_word,select_animation,show_animation);
signal state_reg: statetype := wait_for_communication;

begin
	--turn off 7seg display
	an <= "1111";
	
	
	process (clk,if_showing)
	begin
		if (clk'event and clk='1') then
			if if_showing='1' then
				frame_clk_counter <= frame_clk_counter + 1; 
				if frame_clk_counter = 25000000 then
					frame_clk_counter <= (others => '0');
					frame_counter <= frame_counter + 1;
					if frame_counter = to_integer(animation) then
						frame_counter <= (others => '0');
					end if;
				end if;
			else
				frame_clk_counter <= (others => '0');
				frame_counter <= (others => '0');
			end if;
		end if;
	end process;

	disp_letters : dispcon_letters port map (clk => clk, letter => letter, 
		color => letter_color, 
		srclk0 => d1_srclk0, srclk1 => d1_srclk1, srclk2 => d1_srclk2,
		rclk0 => d1_rclk0, rclk1 => d1_rclk1, rclk2 => d1_rclk2, clk_out0 => d1_clk_out0, clk_out1 => d1_clk_out1,
		clk_out2 => d1_clk_out2, ser_row0 => d1_ser_row0, ser_row1 => d1_ser_row1, ser_row2 => d1_ser_row2,
		ser_row3 => d1_ser_row3, ser_row4 => d1_ser_row4, ser_row5 => d1_ser_row5, ser_row6 => d1_ser_row6,
		ser_row7 => d1_ser_row7, srclk_level => d1_srclk_level, rclk_level => d1_rclk_level, ser_level => d1_ser_level);

	disp_animations : dispcon_animations port map (clk => clk, 
		animation => unsigned(animation), 
		frame => frame_counter,
		srclk0 => d2_srclk0, srclk1 => d2_srclk1, srclk2 => d2_srclk2,
		rclk0 => d2_rclk0, rclk1 => d2_rclk1, rclk2 => d2_rclk2, clk_out0 => d2_clk_out0, clk_out1 => d2_clk_out1,
		clk_out2 => d2_clk_out2, ser_row0 => d2_ser_row0, ser_row1 => d2_ser_row1, ser_row2 => d2_ser_row2,
		ser_row3 => d2_ser_row3, ser_row4 => d2_ser_row4, ser_row5 => d2_ser_row5, ser_row6 => d2_ser_row6,
		ser_row7 => d2_ser_row7, srclk_level => d2_srclk_level, rclk_level => d2_rclk_level, ser_level => d2_ser_level);
  
  INST_UART_RX : uart_rx port map (
		serial_in => rx,
		read_buffer => '1',
		reset_buffer => '0',
		en_16_x_baud => '1',
		clk => clk,
		data_out => dout,
		buffer_data_present => data_present,
		buffer_half_full => open,
		buffer_full => open
	);

	process (clk,data_present,reset)
	begin
		if reset='1' then
			state_reg <= wait_for_communication;
			if_showing <= '0';
		elsif clk'event and clk='1' then
			if data_present = '1' then
				case state_reg is
					when wait_for_communication =>
						if dout="11000000" then
							state_reg <= select_communication;
							if_showing <= '0';
						end if;
						
					when select_communication =>
						if dout="11010000" then
							state_reg <= save_color;
							
							select_disp <= '1';
							letters_count <= (others => '0');
						end if;
						if dout="11100000" then
							state_reg <= select_animation;
							
							select_disp<= '0';
						end if;
						
					when save_color =>
						if dout="11010001" then
							state_reg <= save_word;
						else
							letter_color_counter <= letter_color_counter + 1;
							if letter_color_counter = 2 then
								letter_color_counter <= (others => '0');
							end if;
							case letter_color_counter is
								when "00" =>
									letter_color(17 downto 12) <= unsigned(dout(5 downto 0)); --RED
								when "01" =>
									letter_color(11 downto 6) <= unsigned(dout(5 downto 0)); --BLUE
								when "10" =>
									letter_color(5 downto 0) <= unsigned(dout(5 downto 0)); --GREEN
								when others =>
								letter_color <= (others => '0');
							end case;
						end if;
						
					when save_word =>
						if dout="11010010" then
							state_reg <= show_word;
						else
							letters(to_integer(letters_count)) <= dout;
							letters_count <= letters_count + 1;
						end if;
						
					when show_word =>
						if dout="11111111" then
							state_reg <= wait_for_communication;
							if_showing <= '1';
						end if;
						
					when select_animation =>
						if dout="11100001" then
							state_reg <= show_animation;
						else
							animation <= unsigned(dout(5 downto 0));
						end if;
						
					when show_animation =>
						if dout="11111111" then
							state_reg <= wait_for_communication;
							if_showing <= '1';
						end if;
						
				end case;
			end if;
		end if;
	end process;

	process (clk,if_showing)
	begin
		if clk'event and clk='1' then
			if if_showing='1' then
				letters_clk_counter <= letters_clk_counter + 1;
				if letters_clk_counter = 12500000 then
					current_letter <= current_letter + 1;
					if current_letter = letters_count-1 then
						current_letter <= (others => '0');
					end if;
					letters_clk_counter <= (others => '0');
				end if;
			else
				current_letter <= (others => '0');
				letters_clk_counter <= (others => '0');
			end if;
		end if;
	end process;
	letter <= unsigned(letters(to_integer(current_letter)));
	
	dispen <= select_disp & en;

	with dispen select
		ser_level <= d1_ser_level when "11",
						 d2_ser_level when "01",
							'0' when others;
							
							
	srclk0 <= d1_srclk0 when select_disp='1' else d2_srclk0;
	srclk1 <= d1_srclk1 when select_disp='1' else d2_srclk1;
	srclk2 <= d1_srclk2 when select_disp='1' else d2_srclk2;
	
	rclk0 <= d1_rclk0 when select_disp='1' else d2_rclk0;
	rclk1 <= d1_rclk1 when select_disp='1' else d2_rclk1;
	rclk2 <= d1_rclk2 when select_disp='1' else d2_rclk2;
	
	clk_out0 <= d1_clk_out0 when select_disp='1' else d2_clk_out0;
	clk_out1 <= d1_clk_out1 when select_disp='1' else d2_clk_out1;
	clk_out2 <= d1_clk_out2 when select_disp='1' else d2_clk_out2;
	
	ser_row0 <= d1_ser_row0 when select_disp='1' else d2_ser_row0;
	ser_row1 <= d1_ser_row1 when select_disp='1' else d2_ser_row1;
	ser_row2 <= d1_ser_row2 when select_disp='1' else d2_ser_row2;
	ser_row3 <= d1_ser_row3 when select_disp='1' else d2_ser_row3;
	ser_row4 <= d1_ser_row4 when select_disp='1' else d2_ser_row4;
	ser_row5 <= d1_ser_row5 when select_disp='1' else d2_ser_row5;
	ser_row6 <= d1_ser_row6 when select_disp='1' else d2_ser_row6;
	ser_row7 <= d1_ser_row7 when select_disp='1' else d2_ser_row7;
	
	srclk_level <= d1_srclk_level when select_disp='1' else d2_srclk_level;
	rclk_level <= d1_rclk_level when select_disp='1' else d2_rclk_level;
	
	
end Behavioral;

