----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date: 30.11.2021 10:35:30
-- Design Name: 
-- Module Name: Gene_Snake - Behavioral
-- Project Name: 
-- Target Devices: 
-- Tool Versions: 
-- Description: 
-- 
-- Dependencies: 
-- 
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
-- 
----------------------------------------------------------------------------------
-- a faire:
--  - faire bouger le snake
--  - ajouter une clk

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;

library ourTypes;
use ourTypes.types.all;

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

entity Gene_Snake is
Port ( X : in unsigned (9 downto 0);
       Y : in unsigned (8 downto 0);
       clk_rapide: in std_logic;
       clk_lente : in std_logic;
       reset: in std_logic;
       snakePresent : out std_logic);
end Gene_Snake;

architecture Behavioral of Gene_Snake is

component updateSnake
Port ( inSnake : in pos;
       outSnake : out pos;
       inIndex : in unsigned(10 downto 0);
       outIndex : out unsigned(10 downto 0));
end component updateSnake;

-- D???claration des signaux
signal mat: coord;
signal snake: listSnake;
signal snakeHere: std_logic;
signal update: std_logic;
signal current_index: unsigned(10 downto 0);
signal updatedIndex: unsigned(10 downto 0);
signal currentSnake: pos;
signal updatedSnake: pos;
begin

U0 : updateSnake
port map(
    inSnake => currentSnake,
    outSnake => updatedSnake,
    inIndex => current_index,
    outIndex => updatedIndex
);

-- Process d'initialisation
process(mat,snake,reset,clk_rapide,current_index,clk_lente)
variable current_dir : direction;
begin
    if(reset='0')
    then
        update <= '0';
        current_index <= to_unsigned(0,11);
        for x in 0 to 39 loop
            for y in 0 to 29 loop
                mat(x,y) <= to_unsigned(snake'length-1,11);
            end loop;
        end loop;
        
        mat(0,0) <= to_unsigned(0,11);
        mat(1,0) <= to_unsigned(1,11);
        
        snake(0).X <= to_unsigned(8,10);
        snake(0).Y <= to_unsigned(8,9);
        snake(0).dir <= droite;
        snake(0).isDefined <= '1';
        
        snake(1).X <= to_unsigned(24,10);
        snake(1).Y <= to_unsigned(8,9);
        snake(1).dir <= droite;
        snake(1).isDefined <= '1';
        
        for i in 2 to snake'length-1 loop
            snake(i).X <= to_unsigned(0,10);
            snake(i).Y <= to_unsigned(0,9);
            snake(i).dir <= gauche;
            snake(i).isDefined <= '0';
        end loop;
    elsif(clk_rapide'event and clk_rapide = '1')
    then
        snake(to_integer(current_index)) <= updatedSnake;
        current_index <= updatedIndex;
    end if;
    
    if (to_integer(current_index) = snake'length) then
        update <= '0';
        current_index <= to_unsigned(0,11);
    end if;
    
    if(clk_lente'event and clk_lente = '1')
    then
        update <= '1';
    end if;
    
end process;

-- Process de calcul d'affichage
process(X,Y,mat, snake)
variable ref : unsigned(10 downto 0);
variable position : pos;
begin
    snakeHere <= '0';
    for dx in -1 to 1 loop
        for dy in -1 to 1 loop
            ref := mat(to_integer(X/16)+dx,to_integer(Y/16)+dy);
            position := snake(to_integer(ref));
            if(position.isDefined= '1') then
                if(X>=position.X-8 and X<=position.X+8 and Y>=position.Y-8 and Y<=position.Y+8) then
                    snakeHere <= '1';
                end if;
            end if;
         end loop;
     end loop;
end process;

currentSnake <= snake(to_integer(current_index));
snakePresent <= snakeHere;
end Behavioral;
