---------------------------------------------------------------------------------
-- ASCAL_TEST
---------------------------------------------------------------------------------

-- A IAUTO
-- B HIMIN
-- C HIMAX
-- D VIMIN
-- E VIMAX
-- F OAUTO
-- G OHMIN
-- H OHMAX
-- I OVMIN
-- J OVMAX
-- K Mire
-- L RESET

-- +/-, O/P
-- ++ / -- , 9/0

--  A,B : IHMIN
--  IHMAX

LIBRARY IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.numeric_std.all;
USE IEEE.std_logic_unsigned.ALL;

LIBRARY work;
USE work.base_pack.ALL;

ENTITY emu IS
  PORT (
    -- Master input clock
    clk_50m          : IN    std_logic;

    -- Async reset from top-level module. Can be used as initial reset.
    reset            : IN    std_logic;

    -- Must be passed to hps_io module
    hps_bus          : INOUT std_logic_vector(44 DOWNTO 0);

    sconf            : OUT   std_logic_vector(4 DOWNTO 0);
    -- Base video clock. Usually equals to CLK_SYS.
    clk_video        : OUT   std_logic;

    -- Multiple resolutions are supported using different CE_PIXEL rates.
    -- Must be based on CLK_VIDEO
    ce_pixel         : OUT   std_logic;

    -- Video aspect ratio for HDMI. Most retro systems have ratio 4:3.
    video_arx        : OUT   std_logic_vector(7 DOWNTO 0);
    video_ary        : OUT   std_logic_vector(7 DOWNTO 0);

    -- VGA
    vga_r            : OUT   std_logic_vector(7 DOWNTO 0);
    vga_g            : OUT   std_logic_vector(7 DOWNTO 0);
    vga_b            : OUT   std_logic_vector(7 DOWNTO 0);
    vga_hs           : OUT   std_logic; -- positive pulse!
    vga_vs           : OUT   std_logic; -- positive pulse!
    vga_fl           : OUT   std_logic;
    vga_de           : OUT   std_logic; -- = not (VBlank or HBlank)

    -- LED
    led_user         : OUT   std_logic; -- 1 - ON, 0 - OFF.

    -- b[1]: 0 - LED status is system status ORed with b[0]
    --       1 - LED status is controled solely by b[0]
    -- hint: supply 2'b00 to let the system control the LED.
    led_power        : OUT   std_logic_vector(1 DOWNTO 0);
    led_disk         : OUT   std_logic_vector(1 DOWNTO 0);
    
    -- AUDIO
    audio_l          : OUT   std_logic_vector(15 DOWNTO 0);
    audio_r          : OUT   std_logic_vector(15 DOWNTO 0);
    audio_s          : OUT   std_logic; -- 1 = signed audio, 0 = unsigned
    -- 0 - no mix, 1 - 25%, 2 - 50%, 3 - 100% (mono)
    audio_mix        : OUT   std_logic_vector(1 DOWNTO 0);
    
    tape_in          : IN    std_logic;
    
    -- SD-SPI
    sd_sck           : OUT   std_logic := 'Z';
    sd_mosi          : OUT   std_logic := 'Z';
    sd_miso          : IN    std_logic;
    sd_cs            : OUT   std_logic := 'Z';
    sd_cd            : IN    std_logic;
    
    ----------------------------------------------
    iauto   : OUT std_logic; -- 1=Autodetect image size 0=Choose window
    himin   : OUT natural RANGE 0 TO 4095;
    himax   : OUT natural RANGE 0 TO 4095;
    vimin   : OUT natural RANGE 0 TO 4095;
    vimax   : OUT natural RANGE 0 TO 4095;
    
    hdisp   : IN  natural RANGE 0 TO 4095;
    hmin    : OUT natural RANGE 0 TO 4095;
    hmax    : OUT natural RANGE 0 TO 4095;
    vdisp   : IN  natural RANGE 0 TO 4095;
    vmin    : OUT natural RANGE 0 TO 4095;
    vmax    : OUT natural RANGE 0 TO 4095;

    ----------------------------------------------
    -- High latency DDR3 RAM interface
    -- Use for non-critical time purposes
    ddram_clk        : OUT   std_logic;
    ddram_busy       : IN    std_logic;
    ddram_burstcnt   : OUT   std_logic_vector(7 DOWNTO 0);
    ddram_addr       : OUT   std_logic_vector(28 DOWNTO 0);
    ddram_dout       : IN    std_logic_vector(63 DOWNTO 0);
    ddram_dout_ready : IN    std_logic;
    ddram_rd         : OUT   std_logic;
    ddram_din        : OUT   std_logic_vector(63 DOWNTO 0);
    ddram_be         : OUT   std_logic_vector(7 DOWNTO 0);
    ddram_we         : OUT   std_logic;

    -- SDRAM interface with lower latency
    sdram_clk        : OUT   std_logic;
    sdram_cke        : OUT   std_logic;
    sdram_a          : OUT   std_logic_vector(12 DOWNTO 0);
    sdram_ba         : OUT   std_logic_vector(1 DOWNTO 0);
    sdram_dq         : INOUT std_logic_vector(15 DOWNTO 0);
    sdram_dqml       : OUT   std_logic;
    sdram_dqmh       : OUT   std_logic;
    sdram_ncs        : OUT   std_logic;
    sdram_ncas       : OUT   std_logic;
    sdram_nras       : OUT   std_logic;
    sdram_nwe        : OUT   std_logic);
END emu;

ARCHITECTURE struct OF emu IS

  COMPONENT pll IS
    PORT (
      refclk   : in  std_logic; -- clk
      rst      : in  std_logic; -- reset
      outclk_0 : out std_logic; -- clk
      outclk_1 : out std_logic; -- clk
      locked   : out std_logic  -- export
      );
  END COMPONENT pll;
  
  CONSTANT CONF_STR : string := 
    "SCALERTEST;;" &
    "O46,Scaler,Nearest,Bilinear,SharpBilinear,Bicubic,Poly 1,Poly 2,Poly 3,TEST;" &
    "O7,Scaler,Direct,TripleBuffer;" &
    "O8,Scaler,Normal,Synchro;" &
    "V1.0";

  FUNCTION to_slv(s: string) return std_logic_vector is 
    CONSTANT ss : string(1 to s'length) := s; 
    VARIABLE rval : std_logic_vector(1 to 8 * s'length); 
    VARIABLE p : integer; 
    VARIABLE c : integer; 
  BEGIN
    FOR i in ss'range LOOP
      p := 8 * i;
      c := character'pos(ss(i));
      rval(p - 7 to p) := std_logic_vector(to_unsigned(c,8)); 
    END LOOP;
    RETURN rval;
  END FUNCTION; 

  COMPONENT hps_io
    GENERIC (
      STRLEN : integer := 0;
      PS2DIV : integer := 1000;
      WIDE   : integer := 0; --  8bits download bus
      VDNUM  : integer := 1;
      PS2WE  : integer := 0);
    PORT (
      clk_sys           : IN  std_logic;
      hps_bus           : INOUT std_logic_vector(44 DOWNTO 0);

      conf_str          : IN  std_logic_vector(8*STRLEN-1 DOWNTO 0);

      buttons           : OUT std_logic_vector(1 DOWNTO 0);
      forced_scandoubler: OUT std_logic;

      joystick_0        : OUT std_logic_vector(15 DOWNTO 0);
      joystick_1        : OUT std_logic_vector(15 DOWNTO 0);
      joystick_analog_0 : OUT std_logic_vector(15 DOWNTO 0);
      joystick_analog_1 : OUT std_logic_vector(15 DOWNTO 0);
      status            : OUT std_logic_vector(31 DOWNTO 0);

      sd_lba            : IN  std_logic_vector(31 DOWNTO 0);
      sd_rd             : IN  std_logic;
      sd_wr             : IN  std_logic;
      sd_ack            : OUT std_logic;
      sd_conf           : IN  std_logic;
      sd_ack_conf       : OUT std_logic;

      sd_buff_addr      : OUT std_logic_vector(8 DOWNTO 0);
      sd_buff_dout      : OUT std_logic_vector(7 DOWNTO 0);
      sd_buff_din       : IN  std_logic_vector(7 DOWNTO 0);
      sd_buff_wr        : OUT std_logic;

      img_mounted       : OUT std_logic;
      img_size          : OUT std_logic_vector(63 DOWNTO 0);
      img_readonly      : OUT std_logic;

      ioctl_download    : OUT std_logic;
      ioctl_index       : OUT std_logic_vector(7 DOWNTO 0);
      ioctl_wr          : OUT std_logic;
      ioctl_addr        : OUT std_logic_vector(24 DOWNTO 0);
      ioctl_dout        : OUT std_logic_vector(7 DOWNTO 0);
      ioctl_wait        : IN  std_logic;
      
      rtc               : OUT std_logic_vector(64 DOWNTO 0);
      timestamp         : OUT std_logic_vector(32 DOWNTO 0);

      ps2_kbd_clk_out   : OUT std_logic;
      ps2_kbd_data_out  : OUT std_logic;
      ps2_kbd_clk_in    : IN  std_logic;
      ps2_kbd_data_in   : IN  std_logic;

      ps2_kbd_led_use   : IN  std_logic_vector(2 DOWNTO 0);
      ps2_kbd_led_status: IN  std_logic_vector(2 DOWNTO 0);

      ps2_mouse_clk_out : OUT std_logic;
      ps2_mouse_data_out: OUT std_logic;
      ps2_mouse_clk_in  : IN  std_logic;
      ps2_mouse_data_in : IN  std_logic;

      ps2_key           : OUT std_logic_vector(10 DOWNTO 0);
      ps2_mouse         : OUT std_logic_vector(24 DOWNTO 0));
  END COMPONENT hps_io;

  SIGNAL buttons          : std_logic_vector(1 DOWNTO 0);
  SIGNAL status           : std_logic_vector(31 DOWNTO 0);
  SIGNAL joystick_0       : std_logic_vector(15 DOWNTO 0);
  SIGNAL joystick_1       : std_logic_vector(15 DOWNTO 0);
  SIGNAL joystick_analog_0 : std_logic_vector(15 DOWNTO 0);
  SIGNAL joystick_analog_1 : std_logic_vector(15 DOWNTO 0);
 
  SIGNAL ioctl_download   : std_logic;
  SIGNAL ioctl_index      : std_logic_vector(7 DOWNTO 0);
  SIGNAL ioctl_wr         : std_logic;
  SIGNAL ioctl_addr       : std_logic_vector(24 DOWNTO 0);
  SIGNAL ioctl_dout       : std_logic_vector(7 DOWNTO 0);
  SIGNAL ioctl_wait       : std_logic :='0';
  
  SIGNAL ps2_key,ps2_key_delay : std_logic_vector(10 DOWNTO 0);
  SIGNAL key_0,key_1,key_2,key_3,key_4,key_5,key_6,key_7,key_8,key_9 : std_logic;
  SIGNAL key_a,key_b,key_c,key_d,key_e,key_f,key_g,key_h,key_i,key_j : std_logic;
  SIGNAL key_k,key_l,key_m,key_n,key_o,key_p,key_q,key_r,key_s,key_t : std_logic;
  SIGNAL key_u,key_v,key_w,key_x,key_y,key_z                         : std_logic;
  SIGNAL key_space,key_return                                        : std_logic;
  
  SIGNAL clksys,clksys2,pll_locked : std_logic;
  
  SIGNAL reset_na : std_logic;
  
  ------------------------------------------------
  SIGNAL sel : natural RANGE 0 TO 10;
  SIGNAL mire : natural RANGE 0 TO 7;
  SIGNAL iauto_i : std_logic :='0';
  SIGNAL oauto_i : std_logic :='0';
  SIGNAL inc,dec : std_logic;
  SIGNAL delta : natural RANGE 1 TO 10;
  
  SIGNAL himin_i,himax_i : natural RANGE 0 TO 4095;
  SIGNAL vimin_i,vimax_i : natural RANGE 0 TO 4095;
  SIGNAL hmin_i,hmax_i   : natural RANGE 0 TO 4095;
  SIGNAL vmin_i,vmax_i   : natural RANGE 0 TO 4095;
  
  ------------------------------------------------
  SIGNAL gde,ghs,gvs : std_logic;
  SIGNAL gfl : std_logic :='0';
  SIGNAL ghcpt,gvcpt : natural RANGE 0 TO 4095;
  SIGNAL ghdisp      : natural range 0 to 4095 := 640; --320; --800;
  SIGNAL ghsyncstart : natural range 0 to 4095 := 840;
  SIGNAL ghsyncend   : natural range 0 to 4095 := 968;
  SIGNAL ghtotal     : natural range 0 to 4095 := 1056;
  SIGNAL gvdisp      : natural range 0 to 4095 := 200; --600;
  SIGNAL gvsyncstart : natural range 0 to 4095 := 601;
  SIGNAL gvsyncend   : natural range 0 to 4095 := 605;
  SIGNAL gvtotal     : natural range 0 to 4095 := 628;
  SIGNAL gr,gg,gb    : uv8;
  
  ------------------------------------------------

  
  -- OVO -----------------------------------------
  FUNCTION CC(i : character) RETURN unsigned IS
  BEGIN
    CASE i IS
      WHEN '0' => RETURN "00000";
      WHEN '1' => RETURN "00001";
      WHEN '2' => RETURN "00010";
      WHEN '3' => RETURN "00011";
      WHEN '4' => RETURN "00100";
      WHEN '5' => RETURN "00101";
      WHEN '6' => RETURN "00110";
      WHEN '7' => RETURN "00111";
      WHEN '8' => RETURN "01000";
      WHEN '9' => RETURN "01001";
      WHEN 'A' => RETURN "01010";
      WHEN 'B' => RETURN "01011";
      WHEN 'C' => RETURN "01100";
      WHEN 'D' => RETURN "01101";
      WHEN 'E' => RETURN "01110";
      WHEN 'F' => RETURN "01111";
      WHEN ' ' => RETURN "10000";
      WHEN '=' => RETURN "10001";
      WHEN '+' => RETURN "10010";
      WHEN '-' => RETURN "10011";
      WHEN '<' => RETURN "10100";
      WHEN '>' => RETURN "10101";
      WHEN '^' => RETURN "10110";
      WHEN 'v' => RETURN "10111";
      WHEN '(' => RETURN "11000";
      WHEN ')' => RETURN "11001";
      WHEN ':' => RETURN "11010";
      WHEN '.' => RETURN "11011";
      WHEN ',' => RETURN "11100";
      WHEN '?' => RETURN "11101";
      WHEN '|' => RETURN "11110";
      WHEN '#' => RETURN "11111";
      WHEN OTHERS => RETURN "10000";
    END CASE;
  END FUNCTION CC;
  FUNCTION CS(s : string) RETURN unsigned IS
    VARIABLE r : unsigned(0 TO s'length*5-1);
    VARIABLE j : natural :=0;
  BEGIN
    FOR i IN s'RANGE LOOP
      r(j TO j+4) :=CC(s(i));
      j:=j+5;
    END LOOP;
    RETURN r;
  END FUNCTION CS;
  FUNCTION CN(v : unsigned) RETURN unsigned IS
    VARIABLE t : unsigned(0 TO v'length-1);
    VARIABLE o : unsigned(0 TO v'length/4*5-1);
  BEGIN
    t:=v;
    FOR i IN 0 TO v'length/4-1 LOOP
      o(i*5 TO i*5+4):='0' & t(i*4 TO i*4+3);
    END LOOP;
    RETURN o;
  END FUNCTION CN;
  
  SIGNAL vga_r_u   : unsigned(7 DOWNTO 0);
  SIGNAL vga_g_u   : unsigned(7 DOWNTO 0);
  SIGNAL vga_b_u   : unsigned(7 DOWNTO 0);
  
  SIGNAL ovo_ena  : std_logic;
  SIGNAL ovo_in0  : unsigned(0 TO 32*5-1) :=(OTHERS =>'0');
  SIGNAL ovo_in1  : unsigned(0 TO 32*5-1) :=(OTHERS =>'0');
  
  -- OVO -----------------------------------------
  
BEGIN

  hps : hps_io
    GENERIC MAP (
      STRLEN => CONF_STR'length)
    PORT MAP (
      clk_sys            => clksys,
      hps_bus            => hps_bus,
      conf_str           => to_slv(CONF_STR),
      buttons            => buttons,
      forced_scandoubler => OPEN,
      joystick_0         => OPEN,
      joystick_1         => OPEN,
      joystick_analog_0  => joystick_analog_0,
      joystick_analog_1  => joystick_analog_1,
      status             => status,
      sd_lba             => std_logic_vector'(x"0000_0000"),
      sd_rd              => '0',
      sd_wr              => '0',
      sd_ack             => OPEN,
      sd_conf            => '0',
      sd_ack_conf        => OPEN,
      sd_buff_addr       => OPEN,
      sd_buff_dout       => OPEN,
      sd_buff_din        => std_logic_vector'(x"00"),
      sd_buff_wr         => OPEN,
      img_mounted        => OPEN,
      img_size           => OPEN,
      img_readonly       => OPEN,
      ioctl_download     => ioctl_download,
      ioctl_index        => ioctl_index,
      ioctl_wr           => ioctl_wr,
      ioctl_addr         => ioctl_addr,
      ioctl_dout         => ioctl_dout,
      ioctl_wait         => ioctl_wait,
      rtc                => OPEN,
      timestamp          => OPEN,
      ps2_kbd_clk_out    => OPEN,
      ps2_kbd_data_out   => OPEN,
      ps2_kbd_clk_in     => '1',
      ps2_kbd_data_in    => '1',
      ps2_kbd_led_use    => std_logic_vector'("000"),
      ps2_kbd_led_status => std_logic_vector'("000"),
      ps2_mouse_clk_out  => OPEN,
      ps2_mouse_data_out => OPEN,
      ps2_mouse_clk_in   => '1',
      ps2_mouse_data_in  => '1',
      ps2_key            => ps2_key,
      ps2_mouse          => OPEN);
  
  sconf<=status(8 DOWNTO 4);
  
  ----------------------------------------------------------
  --ipll : pll
  --  PORT MAP (
  --    refclk   => clk_50m,
  --    rst      => '0',
  --    outclk_0 => clksys,
  --    outclk_1 => clksys2,
  --    locked   => pll_locked
  --    );
  clksys<=clk_50m;
  ----------------------------------------------------------
  VideoGen:PROCESS (clksys) IS
  BEGIN
    IF rising_edge(clksys) THEN
      IF ghcpt<ghtotal THEN
        ghcpt<=ghcpt+1;
      ELSE
        ghcpt<=0;
        IF gvcpt<gvtotal THEN
          gvcpt<=gvcpt+1;
        ELSE
          gvcpt<=0;
          gfl<=NOT gfl;
        END IF;
      END IF;
      
      gde<=to_std_logic(ghcpt<ghdisp AND gvcpt<gvdisp);
      ghs<=to_std_logic(ghcpt>=ghsyncstart AND ghcpt<ghsyncend);
      gvs<=to_std_logic(gvcpt>=gvsyncstart AND gvcpt<gvsyncend);
      
    END IF;
  END PROCESS;
  
  ----------------------------------------------------------
  -- MIRE
  MireZ:PROCESS (clksys) IS
    VARIABLE t : std_logic;
  BEGIN
    IF rising_edge(clksys) THEN
      CASE mire IS
        WHEN 0 =>
          t:=to_std_logic((ghcpt=0 OR ghcpt=ghdisp-1 OR
                           gvcpt=0 OR gvcpt=gvdisp-1) AND
                          ghcpt<ghdisp AND gvcpt<gvdisp);
        WHEN 1 =>
          t:=to_std_logic((ghcpt MOD 16)=0 AND (gvcpt MOD 16)=0);
          
        WHEN 2 =>
          t:=to_std_logic((ghcpt+gvcpt) MOD 16 = 0);
          
        WHEN 3 =>
          t:=to_std_logic(((ghcpt+gvcpt)/16) MOD 2 = 0);
        WHEN 4 =>
          t:=to_std_logic((ghcpt/16) MOD 2 = (gvcpt/16) MOD 2);
        WHEN 5 =>
          t:=to_std_logic((ghcpt MOD 4)=0 AND (gvcpt MOD 4)=0);
        WHEN 6 =>
          t:=to_std_logic(ghcpt MOD 2=0);
        WHEN 7 =>
          t:=to_std_logic(gvcpt MOD 2=0);
      END CASE;
      
      ----------------------------------
      gr<=(OTHERS =>t);
      gg<=(OTHERS =>t);
      gb<=(OTHERS =>t);
    END IF;
  END PROCESS;
  
  ----------------------------------------------------------
  KeyCodes:PROCESS (clksys,reset_na) IS
  BEGIN
    IF reset_na='0' THEN
      NULL;
    ELSIF rising_edge(clksys) THEN
      key_0<='0';      key_1<='0';
      key_2<='0';      key_3<='0';
      key_4<='0';      key_5<='0';
      key_6<='0';      key_7<='0';
      key_8<='0';      key_9<='0';
      key_q<='0';      key_w<='0';
      key_e<='0';      key_r<='0';
      key_t<='0';      key_y<='0';
      key_u<='0';      key_i<='0';
      key_o<='0';      key_p<='0';
      key_a<='0';      key_s<='0';
      key_d<='0';      key_f<='0';
      key_g<='0';      key_h<='0';
      key_j<='0';      key_k<='0';
      key_l<='0';      key_z<='0';
      key_x<='0';      key_c<='0';
      key_v<='0';      key_b<='0';
      key_n<='0';      key_m<='0';
      key_space<='0'; 
      key_return<='0';
      --------------------------
                    
      ps2_key_delay<=ps2_key;
      IF ps2_key_delay(10)/=ps2_key(10) THEN
        CASE ps2_key(7 DOWNTO 0) IS
          WHEN x"45" => key_0<=ps2_key(9);
          WHEN x"16" => key_1<=ps2_key(9);
          WHEN x"1E" => key_2<=ps2_key(9);
          WHEN x"26" => key_3<=ps2_key(9);
          WHEN x"25" => key_4<=ps2_key(9);
          WHEN x"2E" => key_5<=ps2_key(9);
          WHEN x"36" => key_6<=ps2_key(9);
          WHEN x"3D" => key_7<=ps2_key(9);
          WHEN x"3E" => key_8<=ps2_key(9);
          WHEN x"46" => key_9<=ps2_key(9);

          WHEN x"15" => key_q<=ps2_key(9);
          WHEN x"1D" => key_w<=ps2_key(9);
          WHEN x"24" => key_e<=ps2_key(9);
          WHEN x"2D" => key_r<=ps2_key(9);
          WHEN x"2C" => key_t<=ps2_key(9);
          WHEN x"35" => key_y<=ps2_key(9);
          WHEN x"3C" => key_u<=ps2_key(9);
          WHEN x"43" => key_i<=ps2_key(9);
          WHEN x"44" => key_o<=ps2_key(9);
          WHEN x"4D" => key_p<=ps2_key(9);

          WHEN x"1C" => key_a<=ps2_key(9);
          WHEN x"1B" => key_s<=ps2_key(9);
          WHEN x"23" => key_d<=ps2_key(9);
          WHEN x"2B" => key_f<=ps2_key(9);
          WHEN x"34" => key_g<=ps2_key(9);
          WHEN x"33" => key_h<=ps2_key(9);
          WHEN x"3B" => key_j<=ps2_key(9);
          WHEN x"42" => key_k<=ps2_key(9);
          WHEN x"4B" => key_l<=ps2_key(9);
                        
          WHEN x"1A" => key_z<=ps2_key(9);
          WHEN x"22" => key_x<=ps2_key(9);
          WHEN x"21" => key_c<=ps2_key(9);
          WHEN x"2A" => key_v<=ps2_key(9);
          WHEN x"32" => key_b<=ps2_key(9);
          WHEN x"31" => key_n<=ps2_key(9);
          WHEN x"3A" => key_m<=ps2_key(9);
                        
          WHEN x"29" => key_space<=ps2_key(9); -- SPACE
          WHEN x"5A" => key_return<=ps2_key(9); -- RETURN
          WHEN OTHERS => NULL;
        END CASE;
      END IF;
    END IF;
  END PROCESS KeyCodes;

  ----------------------------------------------------------
  Keys:PROCESS(clksys) IS
  BEGIN
    IF rising_edge(clksys) THEN
      IF key_a='1' THEN iauto_i <=NOT iauto_i; END IF;
      IF key_b='1' THEN sel<=0; END IF;
      IF key_c='1' THEN sel<=1; END IF;
      IF key_d='1' THEN sel<=2; END IF;
      IF key_e='1' THEN sel<=3; END IF;
      IF key_f='1' THEN oauto_i <=NOT oauto_i; END IF;
      IF key_g='1' THEN sel<=4; END IF;
      IF key_h='1' THEN sel<=5; END IF;
      IF key_i='1' THEN sel<=6; END IF;
      IF key_j='1' THEN sel<=7; END IF;
      IF key_k='1' THEN mire<=(mire +1) MOD 8; END IF;
      IF key_l='1' THEN
        iauto_i<='0';
        oauto_i<='0';
        himin_i<=0;
        himax_i<=ghdisp-1;
        vimax_i<=0;
        vimax_i<=gvdisp-1;
      END IF;

      inc<='0';
      dec<='0';
      
      IF key_o='1' THEN
        inc<='1';
        delta<=1;
      END IF;
      IF key_p='1' THEN
        dec<='1';
        delta<=1;
      END IF;
      IF key_9='1' THEN
        inc<='1';
        delta<=10;
      END IF;
      IF key_0='1' THEN
        dec<='1';
        delta<=10;
      END IF;
      
      CASE sel IS
        WHEN 0 => IF inc='1' THEN himin_i<=himin_i+delta; ELSIF dec='1' AND himin_i>=delta THEN himin_i<=himin_i-delta;  END IF;
        WHEN 1 => IF inc='1' THEN himax_i<=himax_i+delta; ELSIF dec='1' AND himax_i>=delta THEN himax_i<=himax_i-delta;  END IF;
        WHEN 2 => IF inc='1' THEN vimin_i<=vimin_i+delta; ELSIF dec='1' AND vimin_i>=delta THEN vimin_i<=vimin_i-delta;  END IF;
        WHEN 3 => IF inc='1' THEN vimax_i<=vimax_i+delta; ELSIF dec='1' AND vimax_i>=delta THEN vimax_i<=vimax_i-delta;  END IF;
        WHEN 4 => IF inc='1' THEN hmin_i <=hmin_i+delta;  ELSIF dec='1' AND hmin_i>=delta THEN hmin_i <=hmin_i-delta;  END IF;
        WHEN 5 => IF inc='1' THEN hmax_i <=hmax_i+delta;  ELSIF dec='1' AND hmax_i>=delta THEN hmax_i <=hmax_i-delta;  END IF;
        WHEN 6 => IF inc='1' THEN vmin_i <=vmin_i+delta;  ELSIF dec='1' AND vmin_i>=delta THEN vmin_i <=vmin_i-delta;  END IF;
        WHEN 7 => IF inc='1' THEN vmax_i <=vmax_i+delta;  ELSIF dec='1' AND vmax_i>=delta THEN vmax_i <=vmax_i-delta;  END IF;
        WHEN OTHERS => NULL;
      END CASE;

      IF oauto_i='0' THEN
        hmin_i<=0;
        hmax_i<=hdisp-1;
        vmin_i<=0;
        vmax_i<=vdisp-1;
      END IF;
    END IF;
  END PROCESS Keys;

  himin<=himin_i;
  himax<=himax_i;
  vimin<=vimin_i;
  vimax<=vimax_i;
  hmin<=hmin_i;
  hmax<=hmax_i;
  vmin<=vmin_i;
  vmax<=vmax_i;
  iauto<=NOT iauto_i;
  
  ----------------------------------------------------------
  i_ovo: ENTITY work.ovo
    PORT MAP (
      i_r     => gr,
      i_g     => gg,
      i_b     => gb,
      i_hs    => ghs,
      i_vs    => gvs,
      i_de    => gde,
      i_en    => '1',
      i_clk   => clksys,
      o_r     => vga_r_u,
      o_g     => vga_g_u,
      o_b     => vga_b_u,
      o_hs    => vga_hs,
      o_vs    => vga_vs,
      o_de    => vga_de,
      ena     => ovo_ena,
      in0     => ovo_in0,
      in1     => ovo_in1);

  vga_r<=std_logic_vector(vga_r_u);
  vga_g<=std_logic_vector(vga_g_u);
  vga_b<=std_logic_vector(vga_b_u);

  vga_fl<=gfl;
  
  clk_video<=clksys;
  ce_pixel<='1';
  
  audio_l<=x"0000";
  audio_r<=x"0000";
  audio_s<='1';
  audio_mix<="11";
  
  ovo_in0<=
    CC(' ') & -- 1
    CN(to_unsigned(himin_i,12)) & -- 3
    CC(':') & -- 1
    CN(to_unsigned(himax_i,12)) & -- 3
    CC(' ') & -- 1
    CN(to_unsigned(vimin_i,12)) & -- 3
    CC(':') & -- 1
    CN(to_unsigned(vimax_i,12)) & -- 3
    CC(' ') & -- 1
    CN(to_unsigned(mire,4)) & -- 1
    CC(' ') & -- 1
    "1001" & iauto_i & -- 1
    "1001" & oauto_i & -- 1
    CC(' ') & -- 1
    CS("          ") -- 10 
    ;
    
  ovo_in1<=
    CC(' ') & -- 1
    CN(to_unsigned(hmin_i,12)) & -- 3
    CC(':') & -- 1
    CN(to_unsigned(hmax_i,12)) & -- 3
    CC(' ') & -- 1
    CN(to_unsigned(vmin_i,12)) & -- 3
    CC(':') & -- 1
    CN(to_unsigned(vmax_i,12)) & -- 3
    CC(' ') & -- 1
    CS("               ") -- 15
    ;
  
  ovo_ena<='1'; -- Overlay
  
  ----------------------------------------------------------
  -- ROM / RAM

  reset_na<=NOT reset OR pll_locked;
  
END struct;
