LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; ENTITY LCD IS PORT ( clock_400hz_en : IN STD_ULOGIC; --400Hz Taktsignal reset : IN STD_ULOGIC; --Reset-Signal data_input : IN STD_ULOGIC_VECTOR (13 DOWNTO 0); --Token-Signal des Decoders / Morse data_keyboard : IN STD_ULOGIC_VECTOR (7 DOWNTO 0); --Keyboard-Daten nach Betätigung einer Taste data_cntr : OUT STD_ULOGIC_VECTOR (3 DOWNTO 0); --Steuersignale des LCD, wie z.B. LCD_EN, LCD_RW etc. data_out : OUT STD_ULOGIC_VECTOR (7 DOWNTO 0); --Datensignale für das LCD (sowohl druckbare-, als auch Steuerzeichen) enable_char : IN STD_ULOGIC; --Pausen-Signal der Morse-Entity zur Überprüfung ob ein Token-Signal "fertig" ist enable : IN STD_ULOGIC; --Switch Signal zum Umschalten zwischen dem Decoder und Encoder done_pressing : IN STD_ULOGIC --gibt an ob die Tastaturtaste losgelassen wurde und die Datenübertragung beendet wurde ); END LCD; ARCHITECTURE structure of LCD IS SIGNAL LCD_ON, LCD_EN, LCD_RS, LCD_RW: STD_ULOGIC; --Stuersignale für das LCD SIGNAL LCD_DATA : STD_ULOGIC_VECTOR (7 DOWNTO 0); --Datensignal für das LCD SIGNAL sig_old : STD_ULOGIC; SIGNAL sig_rise: STD_ULOGIC; SIGNAL sig_old2: STD_ULOGIC; SIGNAL sig_rise2: STD_ULOGIC; SIGNAL sig_fall2: STD_ULOGIC; SIGNAL sig_old3: STD_ULOGIC; SIGNAL sig_rise3: STD_ULOGIC; BEGIN -------------------------------------------------------------- --Ansteuerung des LCD mit Initialisierung und Zeichenausgabe-- -------------------------------------------------------------- LCD_Initialising: PROCESS (clock_400hz_en, reset, data_input, enable_char, enable, data_keyboard, done_pressing) VARIABLE ini : NATURAL RANGE 0 TO 9 := 0; VARIABLE next_command : NATURAL RANGE 0 TO 9 := 0; VARIABLE char_cnt : NATURAL RANGE 0 TO 34 := 0; BEGIN --LCD neu initialisieren IF reset = '0' THEN LCD_ON <= '1'; --LCD_ON LCD_EN <= '1'; --LCD_EN LCD_RW <= '0'; --LCD_RW LCD_RS <= '0'; --LCD_RS LCD_DATA <= x"38"; --x"38" = Display OFF, 2-lines of Display in use ( = reset) ini := 0; next_command := 0; char_cnt := 0; ELSIF Clock_400hz_en'EVENT AND Clock_400hz_en = '1' THEN CASE ini IS --LCD Initialisierung WHEN 0 => LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '0'; LCD_DATA <= x"38"; --x"38" = Display OFF, 2-lines of Display in use next_command := next_command+1; ini := 8; WHEN 1 => LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '0'; LCD_DATA <= x"38"; --x"38" = Display OFF, 2-lines of Display in use next_command := next_command+1; ini := 8; WHEN 2 => LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '0'; LCD_DATA <= x"38"; --x"38" = Display OFF, 2-line mode next_command := next_command+1; ini := 8; WHEN 3 => LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '0'; LCD_DATA <= x"38"; --x"38" = Display OFF, 2-lines of Display in use (4-mal zum initialisieren!) next_command := next_command+1; ini := 8; WHEN 4 => LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '0'; LCD_DATA <= x"08"; --x"08" = Display OFF, Cursor OFF, Blinking Cursor Position OFF (0F = Display --ON and Cursor ON, Blinking cursor position ON) next_command := next_command+1; ini := 8; WHEN 5 => LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '0'; LCD_DATA <= x"01"; --x"01" = Clear Display next_command := next_command+1; ini := 8; WHEN 6 => LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '0'; LCD_DATA <= x"0C"; --x"0C" = Display ON (0E = Display ON, Cursor ON and Blinking cursor OFF) next_command := next_command+1; ini := 8; WHEN 7 => LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '0'; LCD_DATA <= x"06"; --x"06" = Auto increment address and move cursor to the right next_command := 9; ini := 8; -- Initialisierung ist ab hier abgeschlossen!!! WHEN 8 => --Dieser Zyklus dient dazu das Enable-Signal in LCD_EN auch auf '0' zu setzen. --Ansonsten können die Daten nicht an den Bildschirm übertragen werden!!! LCD_ON <= '1'; LCD_EN <= '0'; ini := next_command; WHEN 9 => IF char_cnt = 16 THEN LCD_RS <= '0'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_ON <= '1'; LCD_DATA <= x"C0"; --Setze Cursor an den Anfang der zweiten Zeile des Displays char_cnt := char_cnt + 1; ini := 8; ELSIF char_cnt = 34 THEN LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '0'; LCD_DATA <= x"01"; --x"01" = clear Display char_cnt := 0; ini := 8; ELSE -- defaults sig_rise <= '0'; --setzt das Signal "sig_rise" standardmäßig auf ein LOW, da das --enable_char-Signal NICHT immer eine steigende Flanke hat sig_rise2 <= '0'; sig_rise3 <= '0'; sig_fall2 <= '0'; -- shift value in sig_old <= enable_char; --als altes Signal wird "sig_old" das aktuelle --standard_char-Signal zugewiesen sig_old2 <= enable; sig_old3 <= done_pressing; -- do some real action IF sig_old = '0' AND enable_char = '1' AND enable = '0' THEN --es wird geprüft ob sich das alte Signal zum neuen Signal unterscheidet. Ist dies der Fall, gab es eine positive Flanke, da die Zuweisung erst im NÄCHSTEN --Taktzyklus erfolgt, prüft man somit IMMER die vorherige Zuweisung!!! --(Quelle: https://www.uni-ulm.de/fileadmin/website_uni_ulm/iui.inst.050/vorlesungen/sose09/lrob/Crashkurs_VHDL.pdf Kap. 4.2.3) sig_rise <= '1'; END IF; IF sig_old2 = '0' AND enable = '1' THEN sig_rise2 <= '1'; ELSIF sig_old2 = '1' AND enable = '0' THEN sig_fall2 <= '1'; END IF; IF sig_old3 = '0' AND done_pressing = '1' AND enable = '1' THEN sig_rise3 <= '1'; END IF; ---------------------------------------- --Ansteuerung des LCD im Decoder-Modus-- ---------------------------------------- If sig_rise = '1' THEN LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '1'; CASE data_input IS --Buchstaben WHEN "00000000000111" => LCD_DATA <=x"41"; -- A WHEN "00000011010101" => LCD_DATA <=x"42"; -- B WHEN "00000011011101" => LCD_DATA <=x"43"; -- C WHEN "00000000110101" => LCD_DATA <=x"44"; -- D WHEN "00000000000001" => LCD_DATA <=x"45"; -- E WHEN "00000001011101" => LCD_DATA <=x"46"; -- F WHEN "00000000111101" => LCD_DATA <=x"47"; -- G WHEN "00000001010101" => LCD_DATA <=x"48"; -- H WHEN "00000000000101" => LCD_DATA <=x"49"; -- I WHEN "00000001111111" => LCD_DATA <=x"4A"; -- J WHEN "00000000110111" => LCD_DATA <=x"4B"; -- K WHEN "00000001110101" => LCD_DATA <=x"4C"; -- L WHEN "00000000001111" => LCD_DATA <=x"4D"; -- M WHEN "00000000001101" => LCD_DATA <=x"4E"; -- N WHEN "00000000111111" => LCD_DATA <=x"4F"; -- O WHEN "00000001111101" => LCD_DATA <=x"50"; -- P WHEN "00000011110111" => LCD_DATA <=x"51"; -- Q WHEN "00000000011101" => LCD_DATA <=x"52"; -- R WHEN "00000000010101" => LCD_DATA <=x"53"; -- S WHEN "00000000000011" => LCD_DATA <=x"54"; -- T WHEN "00000000010111" => LCD_DATA <=x"55"; -- U WHEN "00000001010111" => LCD_DATA <=x"56"; -- V WHEN "00000000011111" => LCD_DATA <=x"57"; -- W WHEN "00000011010111" => LCD_DATA <=x"58"; -- X WHEN "00000011011111" => LCD_DATA <=x"59"; -- Y WHEN "00000011110101" => LCD_DATA <=x"5A"; -- Z --Zahlen WHEN "00001111111111" => LCD_DATA <=x"30"; -- 0 WHEN "00000111111111" => LCD_DATA <=x"31"; -- 1 WHEN "00000101111111" => LCD_DATA <=x"32"; -- 2 WHEN "00000101011111" => LCD_DATA <=x"33"; -- 3 WHEN "00000101010111" => LCD_DATA <=x"34"; -- 4 WHEN "00000101010101" => LCD_DATA <=x"35"; -- 5 WHEN "00001101010101" => LCD_DATA <=x"36"; -- 6 WHEN "00001111010101" => LCD_DATA <=x"37"; -- 7 WHEN "00001111110101" => LCD_DATA <=x"38"; -- 8 WHEN "00001111111101" => LCD_DATA <=x"39"; -- 9 --Sonderzeichen -- WHEN "00000111110111" => LCD_DATA <=x"8F"; -- Å WHEN "00000001110111" => LCD_DATA <=x"E1"; -- Ä -- WHEN "00000111010111" => LCD_DATA <=x"8A"; -- È -- WHEN "00000101110101" => LCD_DATA <=x"90"; -- É WHEN "00000011111101" => LCD_DATA <=x"EF"; -- Ö WHEN "00000001011111" => LCD_DATA <=x"F5"; -- Ü WHEN "01010111110101" => LCD_DATA <=x"E2"; -- ß WHEN "00110111011101" => LCD_DATA <=x"3B"; -- ; WHEN "00010111110101" => LCD_DATA <=x"3F"; -- ? WHEN "00110101010111" => LCD_DATA <=x"2D"; -- - WHEN "00010111110111" => LCD_DATA <=x"5F"; -- _ -- WHEN "00001111011111" => LCD_DATA <=x"A5"; -- Ñ WHEN "00011101110111" => LCD_DATA <=x"2E"; -- . WHEN "00111101011111" => LCD_DATA <=x"2C"; -- , WHEN "00111111010101" => LCD_DATA <=x"3A"; -- : WHEN "00001101111101" => LCD_DATA <=x"28"; -- ( WHEN "00110111110111" => LCD_DATA <=x"29"; -- ) WHEN "00011111111101" => LCD_DATA <=x"27"; -- ' WHEN "00001101010111" => LCD_DATA <=x"3D"; -- = WHEN "00000111011101" => LCD_DATA <=x"2B"; -- + WHEN "00001101011101" => LCD_DATA <=x"2F"; -- / WHEN "00011111011101" => LCD_DATA <=x"40"; -- @ WHEN OTHERS => LCD_DATA <= x"00"; END CASE; char_cnt := char_cnt + 1; ini := 8; ------------------------------------------- --Umschalten zwischen Decoder und Encoder-- ------------------------------------------- --Prüfen ob gerade erst zwischen Encoder und Decoder umgestellt wurde ELSIF sig_rise2 = '1' OR sig_fall2 = '1' THEN LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '0'; LCD_DATA <= x"01"; --x"01" = clear Display ini := 8; char_cnt := 0; ---------------------------------------- --Ansteuerung des LCD im Encoder-Modus-- ---------------------------------------- --Prüfen ob eine Tastureingabe gerade beendet wurde ELSIF sig_rise3 = '1' THEN LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '1'; CASE data_keyboard IS --Buchstaben WHEN x"1C" => LCD_DATA <=x"41"; -- A WHEN x"32" => LCD_DATA <=x"42"; -- B WHEN x"21" => LCD_DATA <=x"43"; -- C WHEN x"23" => LCD_DATA <=x"44"; -- D WHEN x"24" => LCD_DATA <=x"45"; -- E WHEN x"2B" => LCD_DATA <=x"46"; -- F WHEN x"34" => LCD_DATA <=x"47"; -- G WHEN x"33" => LCD_DATA <=x"48"; -- H WHEN x"43" => LCD_DATA <=x"49"; -- I WHEN x"3B" => LCD_DATA <=x"4A"; -- J WHEN x"42" => LCD_DATA <=x"4B"; -- K WHEN x"4B" => LCD_DATA <=x"4C"; -- L WHEN x"3A" => LCD_DATA <=x"4D"; -- M WHEN x"31" => LCD_DATA <=x"4E"; -- N WHEN x"44" => LCD_DATA <=x"4F"; -- O WHEN x"4D" => LCD_DATA <=x"50"; -- P WHEN x"15" => LCD_DATA <=x"51"; -- Q WHEN x"2D" => LCD_DATA <=x"52"; -- R WHEN x"1B" => LCD_DATA <=x"53"; -- S WHEN x"2C" => LCD_DATA <=x"54"; -- T WHEN x"3C" => LCD_DATA <=x"55"; -- U WHEN x"2A" => LCD_DATA <=x"56"; -- V WHEN x"1D" => LCD_DATA <=x"57"; -- W WHEN x"22" => LCD_DATA <=x"58"; -- X WHEN x"1A" => LCD_DATA <=x"59"; -- Y WHEN x"35" => LCD_DATA <=x"5A"; -- Z --Zahlen WHEN x"45" => LCD_DATA <=x"30"; -- 0 WHEN x"16" => LCD_DATA <=x"31"; -- 1 WHEN x"1E" => LCD_DATA <=x"32"; -- 2 WHEN x"26" => LCD_DATA <=x"33"; -- 3 WHEN x"25" => LCD_DATA <=x"34"; -- 4 WHEN x"2E" => LCD_DATA <=x"35"; -- 5 WHEN x"36" => LCD_DATA <=x"36"; -- 6 WHEN x"3D" => LCD_DATA <=x"37"; -- 7 WHEN x"3E" => LCD_DATA <=x"38"; -- 8 WHEN x"46" => LCD_DATA <=x"39"; -- 9 --Sonderzeichen -- WHEN x"" => LCD_DATA <=x"8F"; -- Å WHEN x"52" => LCD_DATA <=x"E1"; -- Ä -- WHEN x"" => LCD_DATA <=x"8A"; -- È -- WHEN x"" => LCD_DATA <=x"90"; -- É WHEN x"4C" => LCD_DATA <=x"EF"; -- Ö WHEN x"54" => LCD_DATA <=x"F5"; -- Ü WHEN x"4E" => LCD_DATA <=x"E2"; -- ß -- WHEN x"" => LCD_DATA <=x"3B"; -- ; -- WHEN x"" => LCD_DATA <=x"3F"; -- ? WHEN x"4A" => LCD_DATA <=x"2D"; -- - -- WHEN x"" => LCD_DATA <=x"5F"; -- _ -- WHEN x"" => LCD_DATA <=x"A5"; -- Ñ WHEN x"49" => LCD_DATA <=x"2E"; -- . WHEN x"41" => LCD_DATA <=x"2C"; -- , -- WHEN x"" => LCD_DATA <=x"3A"; -- : -- WHEN x"" => LCD_DATA <=x"28"; -- ( -- WHEN x"" => LCD_DATA <=x"29"; -- ) -- WHEN x"" => LCD_DATA <=x"27"; -- ' -- WHEN x"" => LCD_DATA <=x"3D"; -- = WHEN x"5B" => LCD_DATA <=x"2B"; -- + -- WHEN x"" => LCD_DATA <=x"2F"; -- / -- WHEN x"" => LCD_DATA <=x"40"; -- @ WHEN x"29" => LCD_DATA <=x"20"; -- " " WHEN OTHERS => LCD_DATA <= x"00"; END CASE; char_cnt := char_cnt + 1; ini := 8; END IF; END IF; END CASE; --Übertragung der Steuersignale und Datenbits an das LCD data_cntr(3) <= LCD_ON; data_cntr(0) <= LCD_EN; data_cntr(1) <= LCD_RW; data_cntr(2) <= LCD_RS; data_out <= LCD_DATA; END IF; END PROCESS; END structure;