----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date: 01/08/2022 10:04:42 PM
-- Design Name: 
-- Module Name: pomme - 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;

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 pomme is
    generic ( dataSize : integer);
    Port (
        clk : in std_logic;
        pxl_clk : in std_logic;
        reset : in std_logic;
        
        CE : in std_logic;
        
        X : in unsigned (9 downto 0);
        Y : in unsigned (8 downto 0);
        
        posX : out unsigned(5 downto 0);
        posY : out unsigned(4 downto 0);
        
        colorOut : out color;
        
        address : out unsigned(SNAKE_ADDRESS_SIZE-1 downto 0) := (others => '0');
        data : in std_logic_vector(dataSize-1 downto 0);
        
        matAddress : out unsigned(SNAKE_ADDRESS_SIZE-1 downto 0) := (others => '0');
        matData : in std_logic_vector(SNAKE_ADDRESS_SIZE-1 downto 0) := (others => '0');
        
        ROMAddress : out unsigned(7 downto 0) := (others => '0');
        ROMData : in std_logic_vector(SPRITES_DATA_SIZE-1 downto 0)
    );
end pomme;

architecture Behavioral of pomme is
signal Xpos : unsigned(9 downto 0) := (others => '0');
signal Ypos : unsigned(8 downto 0) := (others => '0');
constant FINISHED : unsigned(3 downto 0) := to_unsigned(15,4);
signal state : unsigned(3 downto 0) := (others => '0');
signal pommeHere : std_logic;
begin
process(clk,reset,CE,state)
variable randInd : unsigned(SNAKE_ADDRESS_SIZE-1 downto 0) := (others => '0');
begin
    if(reset = '0') then
        state <= to_unsigned(0,4);
    elsif(CE = '0') then
        if(state /= FINISHED) then
            state <= to_unsigned(0,4);
        else
            state <= FINISHED;
        end if;
    elsif(rising_edge(clk)) then
        if(state /= FINISHED) then
            state <= state + 1;
        else
            state <= FINISHED;
        end if;
        if(state = 0) then
            randInd := (randInd + 937) rem MAX_SNAKE;
            Xpos <= (randInd(5 downto 0) rem 40) & "1000";
            Ypos <= resize(randInd rem 30,5) & "1000";
        elsif(state = 1) then
            matAddress <= to_unsigned(to_integer(Ypos(Ypos'HIGH downto 4)) * 40 + to_integer(Xpos(Xpos'HIGH downto 4)),SNAKE_ADDRESS_SIZE);
        elsif(state = 3) then
            address <= unsigned(matData);
        elsif(state = 5) then
            if(to_pos(data).isDefined = '1') then
                state <= to_unsigned(0,4);
            else
                state <= FINISHED;
            end if;
        end if;
    end if;
end process;

process(pxl_clk)
variable sX,sY : integer;
begin
    if(rising_edge(pxl_clk)) then
        if(pommeHere = '1') then
            colorOut <= to_color(ROMData);
        else
            colorOut <= (others => (others => '0'));
        end if;
        pommeHere <= '0';
        
        if(to_integer(X)>=TO_INTEGER(Xpos)-8 and to_integer(X)<TO_INTEGER(Xpos)+8 and to_integer(Y)>=TO_INTEGER(Ypos)-8 and to_integer(Y)<TO_INTEGER(Ypos)+8) then
            pommeHere <= '1';
            sX := (to_integer(X) - to_integer(Xpos)) + 8;
            sY := (to_integer(Y) - to_integer(Ypos)) + 8;
            ROMAddress <= to_unsigned(sY*16+sX,8);
        end if;
    end if;
end process;

posX <= Xpos(Xpos'HIGH downto 4);
posY <= Ypos(Ypos'HIGH downto 4);
end Behavioral;
