-------------------------------------------------------------------------------
-- Title      : 
-- Project    : 
-------------------------------------------------------------------------------
-- File       : lcdtest.vhd
-- Author     :   <Fador@HINATA>
-- Company    : 
-- Created    : 2008-10-07
-- Last update: 2008-10-08
-- Platform   : 
-- Standard   : VHDL'87
-------------------------------------------------------------------------------
-- Description: 
-------------------------------------------------------------------------------
-- Copyright (c) 2008 
-------------------------------------------------------------------------------
-- Revisions  :
-- Date        Version  Author  Description
-- 2008-10-07  1.0      Fador	Created
-------------------------------------------------------------------------------

library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.numeric_bit.all;


entity lcdtest is
  
  generic (
    clk_rate_g : integer := 50000000);

  port (
    data_out_r      : out std_logic_vector(7 downto 0);
    rw_out_r        : out std_logic;
    rs_out_r        : out std_logic;
    dataready_out_r : out std_logic;
    lcdready_in     : in  std_logic;
    clk             : in  std_logic;
    rst_n           : in  std_logic;
    slow_clk_out    : out std_logic
    );

end lcdtest;




architecture rtl of lcdtest is


  signal clk_divine_r : integer;
  signal sec_div_r : integer;
  signal sec_clk_r : integer;
  signal slow_clk_r : integer;
  signal datan_r : integer;
  signal data_len_r : integer;

  signal slow_clk_state : std_logic;

  -- Kellonaika
  signal bighours : integer range 0 to 2;
  signal smallhours :integer range 0 to 9;
  signal bigminutes : integer range 0 to 5;
  signal smallminutes : integer range 0 to 9;
  signal bigseconds : integer range 0 to 5;
  signal smallseconds : integer range 0 to 9;
 
  
begin  -- rtl


  main: process (clk, rst_n)
  begin  -- process main
    if rst_n = '0' then                 -- asynchronous reset (active low)
      datan_r         <= 0;
      slow_clk_r      <= 0;
      dataready_out_r <= '0';
      clk_divine_r    <= clk_rate_g/100;   -- 10 ms
      sec_div_r       <= clk_rate_g;          -- tasan sekunti
      sec_clk_r       <= 0;
      slow_clk_r      <= 0;
      datan_r         <= 0;
      data_len_r      <= 27;
      slow_clk_state  <= '0';      
      -- kello
      bighours        <= 0;
      smallhours      <= 0;
      bigminutes      <= 0;
      smallminutes    <= 0;
      bigseconds      <= 0;
      smallseconds    <= 0;
      
    elsif clk'event and clk = '1' then  -- rising clock edge
      slow_clk_r <= slow_clk_r +1;
      sec_clk_r  <= sec_clk_r+1;

      -- sekunti
      if sec_clk_r = sec_div_r then
        sec_clk_r <= 0;

        -- lasketaan kellonaika
        if smallseconds = 9 then
          if bigseconds = 5 then
            if smallminutes = 9 then
              if bigminutes = 5 then
                if smallhours = 9 then                  
                  bighours     <= bighours+1;
                  smallhours   <= 0;
                  bigminutes   <= 0;
                  smallminutes <= 0;
                  bigseconds   <= 0;
                  smallseconds <= 0;
                elsif smallhours = 3 and bighours = 2 then
                  smallseconds <= 0;
                  bigseconds   <= 0;
                  smallminutes <= 0;
                  bigminutes   <= 0;
                  smallhours   <= 0;
                  bighours     <= 0;
                else                  
                  smallhours   <= smallhours + 1;
                  bigminutes   <= 0;
                  smallminutes <= 0;
                  smallseconds <= 0;
                  bigseconds   <= 0;
                end if;
              else
                bigminutes   <= bigminutes+1;
                smallminutes <= 0;
                bigseconds   <= 0;
                smallseconds <= 0;
              end if;
            else
              smallminutes <= smallminutes +1;
              bigseconds   <= 0;
              smallseconds <= 0;
            end if;
          else
            bigseconds   <= bigseconds+1;
            smallseconds <= 0;
          end if;
        else
          smallseconds <= smallseconds+1;
        end if;
        
      end if;

      -- hidas kello LCD näytön käsittelyyn
      if slow_clk_r = clk_divine_r then
        -- debuggia
        -- slow_clk_state <= not slow_clk_state;        
        -- slow_clk_out   <= slow_clk_state;

        -- voidaan mennä nopeempaa kun LCD:n asetukset tehty
        if datan_r = 8 then
          clk_divine_r <= clk_rate_g/1000;
        end if;        
        slow_clk_r <= 0;        
        if lcdready_in = '1' then
          if datan_r < data_len_r then         
            dataready_out_r <= '1';
            datan_r         <= datan_r+1;
          else
            -- Kellonaikaa
            dataready_out_r <= '1';
            datan_r <= 19;
          end if;
        else
          dataready_out_r <= '0';
        end if;
        
      end if;
      
      case datan_r is
        when 0 => data_out_r <= "00000000";
                  rw_out_r   <= '0';
                  rs_out_r   <= '0';
        when 1 => data_out_r <= "11000000";
        when 2 => data_out_r <= "11000000";
        when 3 => data_out_r <= "11100000";   -- kaksirivinen näyttö
        when 4 => data_out_r <= "00001000";   -- pimeäksi
        when 5 => data_out_r <= "00000001";   -- näyttömuisti pois
        when 6 => data_out_r <= "00000110";   -- osoitinasetukset
        -- when 7 => data_out_r <= "00001111";   -- kursori päälle
        when 7 => data_out_r <= "00001100";   -- kursori ja vilkunta pois
                  
        when 8 => data_out_r  <= "01000110";   -- Merkki 'F'
                  rs_out_r    <= '1';
        when 9 =>  data_out_r <= "01100001";  -- Merkki 'a'
        when 10 => data_out_r <= "01100100";  -- Merkki 'd'
        when 11 => data_out_r <= "01101111";  -- Merkki 'o'
        when 12 => data_out_r <= "01110010";  -- Merkki 'r'
        when 13 => data_out_r <= "00100000";  -- Merkki ' '
        when 14 => data_out_r <= "01110010";  -- Merkki 'r'
        when 15 => data_out_r <= "01110101";  -- Merkki 'u'
        when 16 => data_out_r <= "01101100";  -- Merkki 'l'
        when 17 => data_out_r <= "01100001";  -- Merkki 'a'
        when 18 => data_out_r <= "01100001";  -- Merkki 'a'

        -- kellonaika                   
        when 19 => data_out_r <= "11000000";  -- Tokan rivin alkuun
                   rs_out_r   <= '0';
                   
        when 20 => data_out_r <=
                     std_logic_vector(to_unsigned(bighours+48, 8));
                   rs_out_r   <= '1';
        when 21 => data_out_r <=
                     std_logic_vector(to_unsigned(smallhours+48, 8));
        when 22 => data_out_r <= "00111010";  -- Merkki ':'
        when 23 => data_out_r <=
                     std_logic_vector(to_unsigned(bigminutes+48, 8));
        when 24 => data_out_r <=
                     std_logic_vector(to_unsigned(smallminutes+48, 8));
        when 25 => data_out_r <= "00111010";  -- Merkki ':'        
        when 26 => data_out_r <=
                     std_logic_vector(to_unsigned(bigseconds+48, 8));
        when 27 => data_out_r <=
                     std_logic_vector(to_unsigned(smallseconds+48, 8));
                   
        when others => data_out_r <= "00000000";
                       rs_out_r   <= '0';
                       rw_out_r   <= '0';
      end case;
    end if;
  end process main;

end rtl;
