----------------------------------------------------------------------------
--	RGB_controller.vhd -- Nexys4 RGB LED controller
----------------------------------------------------------------------------
-- Author:  Marshall Wingerson 
--          Copyright 2013 Digilent, Inc.
----------------------------------------------------------------------------
--
----------------------------------------------------------------------------
-- Revision History:
--  08/08/2013(MarshallW): Created 
--  08/30/2013(SamB): Modified RGB pattern
--                    Added comments
----------------------------------------------------------------------------

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE IEEE.NUMERIC_STD.ALL;

entity RGB_controller is
	port(
	GCLK 	: in std_logic;	
	BTN     : in  std_logic_vector(3 downto 0);
	LED0_O	: out std_logic_vector(2 downto 0);
	LED1_O	: out std_logic_vector(2 downto 0);
	LED2_O	: out std_logic_vector(2 downto 0);
	LED3_O	: out std_logic_vector(2 downto 0)
	);
end RGB_controller;

architecture Behavioral of RGB_controller is
--counter signals
	constant window   : std_logic_vector(7 downto 0) := "11111111";
	constant windowMin: std_logic_vector(7 downto 0) := "00100000";
	signal windowcount : std_logic_vector(7 downto 0) := (others => '0');

    constant deltacountMax : std_logic_vector(19 downto 0) := std_logic_vector(to_unsigned(1000000, 20));
	signal deltacount : std_logic_vector(19 downto 0) := (others => '0');
		
    constant valcountMax : std_logic_vector(8 downto 0) := "101111111";
    signal valcount   : std_logic_vector(8 downto 0) := (others => '0');

--color intensity signals
    signal incVal     : std_logic_vector(7 downto 0);
    signal decVal     : std_logic_vector(7 downto 0);
    signal halfIncVal : std_logic_vector(7 downto 0);
    signal halfDecVal : std_logic_vector(7 downto 0);

	signal pat0       : std_logic_vector(7 downto 0);
	signal pat1       : std_logic_vector(7 downto 0);
	signal pat2       : std_logic_vector(7 downto 0);
	signal pat3       : std_logic_vector(7 downto 0);
	signal pat4       : std_logic_vector(7 downto 0);
	signal pat5       : std_logic_vector(7 downto 0);
	
--PWM registers
    signal btn_reg    : std_logic_vector(3 downto 0);
    signal rgbLedReg0 : std_logic_vector(2 downto 0);
	signal rgbLedReg1 : std_logic_vector(2 downto 0);
    signal rgbLedReg2 : std_logic_vector(2 downto 0);
    signal rgbLedReg3 : std_logic_vector(2 downto 0);
    signal rgbLed0    : std_logic_vector(2 downto 0);
    signal rgbLed1    : std_logic_vector(2 downto 0);
    signal rgbLed2    : std_logic_vector(2 downto 0);
    signal rgbLed3    : std_logic_vector(2 downto 0);
    signal LED0_reg   : std_logic_vector(2 downto 0);
    signal LED1_reg   : std_logic_vector(2 downto 0);
    signal LED2_reg   : std_logic_vector(2 downto 0);
    signal LED3_reg   : std_logic_vector(2 downto 0);

begin

btn_proc:process(GCLK)
begin
	if(rising_edge(GCLK)) then
		btn_reg <= BTN;
	end if;
end process;

window_counter:process(GCLK)
begin
	if(rising_edge(GCLK)) then
		if windowcount < (window) then
			windowcount <= windowcount + 1;
		else
			windowcount <= windowMin;
		end if;
	end if;
end process;

color_change_counter:process(GCLK)
begin
    if(rising_edge(GCLK)) then
		if(deltacount < deltacountMax) then
			deltacount <= deltacount + 1;
		else
			deltacount <= (others => '0');
		end if;
	end if;
end process;

color_intensity_counter:process(GCLK)
begin
	if(rising_edge(GCLK)) then
	if(deltacount = 0) then
		if(valcount < valcountMax) then
			valcount <= valcount + 1;
		else
			valcount <= (others => '0');
		end if;
    end if;
	end if;
end process;

incVal <= "0" & valcount(6 downto 0);

--The folowing code sets decVal to (128 - incVal)
decVal(7) <= '0';
decVal(6) <= not(valcount(6));
decVal(5) <= not(valcount(5));
decVal(4) <= not(valcount(4));
decVal(3) <= not(valcount(3));
decVal(2) <= not(valcount(2));
decVal(1) <= not(valcount(1));
decVal(0) <= not(valcount(0));
 
halfIncVal <= "0" & incVal(6 downto 0);
halfDecVal <= "0" & decVal(6 downto 0);

pat0    <= incVal when (valcount(8 downto 7) = "00") else
           decVal when (valcount(8 downto 7) = "01") else
           (others => '0');       
pat1    <= decVal when (valcount(8 downto 7) = "00") else
           (others => '0') when (valcount(8 downto 7) = "01") else
           incVal;
pat2    <= (others => '0') when (valcount(8 downto 7) = "00") else
           incVal when (valcount(8 downto 7) = "01") else
           decVal;        
pat3    <= halfIncVal when (valcount(8 downto 7) = "00") else
           "00111111" when (valcount(8 downto 7) = "01") else
           halfDecVal;
pat4    <= "00111111" when (valcount(8 downto 7) = "00") else
           halfDecVal when (valcount(8 downto 7) = "01") else
           halfIncVal;
pat5    <= halfDecVal when (valcount(8 downto 7) = "00") else
           halfIncVal when (valcount(8 downto 7) = "01") else
           "00111111";       

--RGB0 processes
--red processes
red0_comp:process(GCLK)
begin
	if(rising_edge(GCLK)) then
		if((pat0) > windowcount) then
			rgbLedReg0(2) <= '1';
		else
			rgbLedReg0(2) <= '0';
		end if;
	end if;
end process;

--green processes
green0_comp:process(GCLK)
begin
	if(rising_edge(GCLK)) then
		if((pat1) > windowcount) then
			rgbLedReg0(1) <= '1';
		else
			rgbLedReg0(1) <= '0';
		end if;
	end if;
end process;

			
--blue processes
blue0_comp:process(GCLK)
begin
	if(rising_edge(GCLK)) then
		if((pat2) > windowcount) then
			rgbLedReg0(0) <= '1';
		else
			rgbLedReg0(0) <= '0';
		end if;
	end if;
end process;
	
--RGB1 processes---	
--red1 processes
red1_comp:process(GCLK)
begin
	if(rising_edge(GCLK)) then
		if((pat1) > windowcount) then
			rgbLedReg1(2) <= '1';
		else
			rgbLedReg1(2) <= '0';
		end if;
	end if;
end process;

--green1 processes
green1_comp:process(GCLK)
begin
	if(rising_edge(GCLK)) then
		if((pat2) > windowcount) then
			rgbLedReg1(1) <= '1';
		else
			rgbLedReg1(1) <= '0';
		end if;
	end if;
end process;
	
--blue1 processes
blue1_comp:process(GCLK)
begin
	if(rising_edge(GCLK)) then
		if((pat0) > windowcount) then
			rgbLedReg1(0) <= '1';
		else
			rgbLedReg1(0) <= '0';
		end if;
	end if;
end process;

--RGB2 processes---	
--red2 processes
red2_comp:process(GCLK)
begin
	if(rising_edge(GCLK)) then
		if((pat2) > windowcount) then
			rgbLedReg2(2) <= '1';
		else
			rgbLedReg2(2) <= '0';
		end if;
	end if;
end process;

--green2 processes
green2_comp:process(GCLK)
begin
	if(rising_edge(GCLK)) then
		if((pat3) > windowcount) then
			rgbLedReg2(1) <= '1';
		else
			rgbLedReg2(1) <= '0';
		end if;
	end if;
end process;

--blue2 processes
blue2_comp:process(GCLK)
begin
	if(rising_edge(GCLK)) then
		if((pat1) > windowcount) then
			rgbLedReg2(0) <= '1';
		else
			rgbLedReg2(0) <= '0';
		end if;
	end if;
end process;
	
--RGB3 processes---	
--red3 processes
red3_comp:process(GCLK)
begin
	if(rising_edge(GCLK)) then
		if((pat3) > windowcount) then
			rgbLedReg3(2) <= '1';
		else
			rgbLedReg3(2) <= '0';
		end if;
	end if;
end process;

--green3 processes
green3_comp:process(GCLK)
begin
	if(rising_edge(GCLK)) then
		if((pat0) > windowcount) then
			rgbLedReg3(1) <= '1';
		else
			rgbLedReg3(1) <= '0';
		end if;
	end if;
end process;

			
--blue3 processes
blue3_comp:process(GCLK)
begin
	if(rising_edge(GCLK)) then
		if((pat5) > windowcount) then
			rgbLedReg3(0) <= '1';
		else
			rgbLedReg3(0) <= '0';
		end if;
	end if;
end process;

--button controll processes
rgbLed0 <= rgbLedReg0 when btn_reg(0)='0' else "000";	
rgbLed1 <= rgbLedReg1 when btn_reg(1)='0' else "000";	
rgbLed2 <= rgbLedReg2 when btn_reg(2)='0' else "000";	
rgbLed3 <= rgbLedReg3 when btn_reg(3)='0' else "000";	

--output register processes
output_comp:process(GCLK)
begin
	if(rising_edge(GCLK)) then
        LED0_reg <= rgbLed0;
        LED1_reg <= rgbLed1;
        LED2_reg <= rgbLed2;
        LED3_reg <= rgbLed3;	
	end if;
end process;

--output port
LED0_O <= LED0_reg;
LED1_O <= LED1_reg;
LED2_O <= LED2_reg;
LED3_O <= LED3_reg;

end Behavioral;

