library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity regioner is
    Port (  inck                                    : in  STD_LOGIC := '0';
            valid                                   : out STD_LOGIC := '0';
            last                                    : out STD_LOGIC := '0';
            first_row                               : in  STD_LOGIC_VECTOR(11 downto 0)  := (others => '0');
            last_row                                : in  STD_LOGIC_VECTOR(11 downto 0)  := (others => '0');
            first_column                            : in  STD_LOGIC_VECTOR(11 downto 0)  := (others => '0');
            last_column                             : in  STD_LOGIC_VECTOR(11 downto 0)  := (others => '0');
            new_row                                 : out STD_LOGIC := '0';
            channel_sel                             : out STD_LOGIC_VECTOR(4 downto 0)   := (others => '0');
            data_in_vector                          : in  STD_LOGIC_VECTOR(191 downto 0) := (others => '0');
            image_data_valid_from_signal            : out STD_LOGIC := '0';
            selected_image_data_valid_from_signal   : out STD_LOGIC := '0';
            image_data_with_sync_valid_from_signal  : out STD_LOGIC := '0'
    );
end regioner;

architecture Behavioral of regioner is

  begin

  process(inck)
    
    variable inck_counter     : integer := 0;
    variable row_counter      : integer := 0;
    variable column_counter   : integer := 0;
    variable byl_SAV          : integer := 0;
    variable byl_EAV          : integer := 0;
    variable byl_SAV_invalid  : integer := 0;
    variable channel_sel_sig  : std_logic_vector(4 downto 0) := (0 => '1',others => '0');

    
     --SYNC CODE
    type sync_code is (
      idle,            
      prvni,  
      druhy,             
      treti,      
      ctvrty   
    ); 
    variable SAV          : sync_code;
    variable SAV_invalid  : sync_code;
    variable EAV          : sync_code;
    
  begin
    if(rising_edge(inck)) then
        case SAV_invalid is
            when idle => 
                          if(data_in_vector(11 downto 0) = "111111111111") then
                            SAV_invalid := prvni;
                          end if;
            
            when prvni =>
                          if(data_in_vector(11 downto 0) = "000000000000") then
                            SAV_invalid := druhy;
                          else
                            SAV_invalid := idle;
                          end if;
            
            when druhy =>
                          if(data_in_vector(11 downto 0) = "000000000000") then
                            SAV_invalid := treti;
                          else
                            SAV_invalid := idle;
                          end if;
            
            when treti =>
                          if(data_in_vector(11 downto 0) = "101010110000") then
                            SAV_invalid := ctvrty;
                          else 
                            SAV_invalid := idle;
                          end if;
            when ctvrty =>
                          byl_SAV_invalid := 1;
                          SAV_invalid := idle;
          end case;
    
      case SAV is
        when idle => 
                      if(data_in_vector(11 downto 0) = "111111111111") then
                        SAV := prvni;
                      end if;
        
        when prvni =>
                      if(data_in_vector(11 downto 0) = "000000000000") then
                        SAV := druhy;
                      else
                        SAV := idle;
                      end if;
        
        when druhy =>
                      if(data_in_vector(11 downto 0) = "000000000000") then
                        SAV := treti;
                      else
                        SAV := idle;
                      end if;
        
        when treti =>
                      if(data_in_vector(11 downto 0) = "100000000000") then
                        SAV := ctvrty;
                      else 
                        SAV := idle;
                      end if;
        when ctvrty =>
                      byl_SAV := 1;
                      byl_SAV_invalid := 0;
                      SAV := idle;
      end case;
      
      case EAV is
        when idle => 
                      if(data_in_vector(11 downto 0) = "111111111111") then
                        EAV := prvni;
                      end if;
        
        when prvni =>
                      if(data_in_vector(11 downto 0) = "000000000000") then
                        EAV := druhy;
                      else
                        EAV := idle;
                      end if;
        
        when druhy =>
                      if(data_in_vector(11 downto 0) = "000000000000") then
                        EAV := treti;
                      else
                        EAV := idle;
                      end if;
        
        when treti =>
                      if(data_in_vector(11 downto 0) = "100111010000") then
                        EAV := ctvrty;
                      else 
                        EAV := idle;
                      end if;
        when ctvrty =>
                      byl_EAV := 1;
                      byl_SAV := 0;
                      EAV := idle;
      end case;
      if(byl_EAV = 1)then --end of line was recognized - selects next DMA channel, increments line counter and resets pixel counter
        byl_EAV       := 0;
        row_counter   := row_counter + 1;
        inck_counter  := 0;
        if(channel_sel_sig(0) = '1')then
          channel_sel_sig := (1 => '1', others => '0');
        else
          channel_sel_sig := (0 => '1', others => '0');
        end if;
      end if;
    
      if(byl_SAV = 1 and inck_counter < 4112)then --Is in between SAV and EAV
        
  
        --is in defined area
        if(inck_counter >= unsigned(first_column) and inck_counter <= unsigned(last_column) and row_counter >= unsigned(first_row) and row_counter <= unsigned(last_row))then
          valid <= '1';
          selected_image_data_valid_from_signal <= '1';
        else
          valid <= '0';
          selected_image_data_valid_from_signal <= '0';
        end if;
        --last pixel of defined area
        if(inck_counter = unsigned(last_column) and row_counter = unsigned(last_row))then
          last <= '1';
        else
          last <= '0';
        end if;
        
        image_data_valid_from_signal <= '1';
        inck_counter := inck_counter + 1; --next pixel
        
      else --is not valid image - is somewhere between expositions
        
      end if;
      if(byl_SAV_invalid = 1)then
        image_data_valid_from_signal <= '0';
        byl_SAV := 0;
        inck_counter := 0;
        row_counter := 0;
      end if;
        channel_sel <= channel_sel_sig;
    end if;
  end process;
end Behavioral;
