-- The Electronic Gardener -- -- Mark Kudryk, Kim Ellis -- -- Module Name: The Menu State Machine -- Author: Mark Kudryk, Kim Ellis -- Date: November 7, 1998 -- Status: Completed -- -- Size: 480 Logic Cells -- Period: 40.1 ns -- Clock: 24.93 MHz -- -- The purpose of the Menu State Machine is to accept inputs from the user, and to -- output user inputs to the LCD for user feedback, but also to the device controller -- which will control the system according to these inputs. -- -- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.std_logic_arith.all; entity menu_sm is port ( -- interface with the Message Decoder message_address: out std_logic_vector (12 downto 0); variable_data: out std_logic_vector (7 downto 0); decoder_ready: in std_logic; display_message: buffer std_logic; variable_requested: in std_logic; variable_valid: buffer std_logic; -- interface with the Timer set_new_time: out std_logic; set_new_hour: out std_logic_vector (4 downto 0); set_new_minute: out std_logic_vector (5 downto 0); current_hour: in std_logic_vector (4 downto 0); current_minute: in std_logic_vector (5 downto 0); -- interface with the Device Controller user_set_water: out std_logic_vector (7 downto 0); water_option_on: out std_logic; water_start_hr: buffer std_logic_vector (7 downto 0); water_start_m: buffer std_logic_vector (7 downto 0); water_end_hr: buffer std_logic_vector (7 downto 0); water_end_m: buffer std_logic_vector (7 downto 0); -- interface with the buttons push_button_inputs: in std_logic_vector (3 downto 0); --clear_push_buttons: out std_logic_vector (3 downto 0); -- other clock, reset: in std_logic); end entity menu_sm; architecture behaviour of menu_sm is type state_type is (main, show_start, set_start, show_end, set_end, set_level, show_time, set_time); signal state: state_type; signal button: std_logic_vector (3 downto 0); signal internal_reset: std_logic_vector (3 downto 0); signal water_level: std_logic_vector (7 downto 0); signal temp_hour, temp_minute: std_logic_vector (7 downto 0); begin -- The following are bogus values; they have been inputted in order to get the code -- to compile successfully. button <= push_button_inputs; -- menu_sm_sr_latch: component sr_latch -- generic map(WIDTH => 4) -- port map (set => push_buttons_inputs, -- reset => internal_reset, -- value => out_push); state_machine: process (reset, clock, button) variable switch: natural range 0 to (2**2)-1; -- Used for lines displaying two variables. variable toggle: natural range 0 to (2**2)-1; begin if reset = '1' then state <= main; set_new_hour <= "00000"; set_new_minute <= "000000"; set_new_time <= '0'; toggle := 0; elsif rising_edge(clock) then case state is when main => -- Display Screen One set_new_time <= '0'; if toggle = 0 and decoder_ready = '1' then message_address <= "0000000010000"; -- hex 0010 display_message <= '1'; toggle := 1; elsif toggle = 1 then display_message <= '0'; if button(2) = '1' then -- Go to Set Time state <= show_time; toggle := 0; elsif button(3) = '1' then -- Go to Water state <= show_start; toggle := 0; end if; end if; when show_start => -- Display Starting Time for Water if decoder_ready = '1' then message_address <= "0000000100000"; -- hex 0020 display_message <= '1'; switch := 1; elsif display_message = '1' then display_message <= '0'; elsif variable_requested = '1' and switch = 1 then variable_data <= water_start_hr; variable_valid <= '1'; elsif variable_valid = '1' and switch = 1 then variable_valid <= '0'; switch := 2; elsif variable_requested = '1' and switch = 2 then variable_data <= water_start_m; variable_valid <= '1'; elsif variable_valid = '1' and switch = 2 then variable_valid <= '0'; switch := 0; state <= set_start; end if; when set_start => if button(0) = '1' then -- Increment hour water_start_hr <= water_start_hr + 1; if water_start_hr = 24 then water_start_hr <= "00000000"; end if; state <= show_start; elsif button(1) = '1' then -- Increment minute water_start_m <= water_start_m + 1; if water_start_m = 60 then water_start_m <= "00000000"; end if; state <= show_start; elsif button(2) = '1' then -- Go to set End Time state <= show_end; elsif button(3) = '1' then -- Cancel option, go water_option_on <= '0'; -- up one menu. state <= main; end if; when show_end => -- Display Water End time if decoder_ready = '1' then message_address <= "0000001000000"; -- hex 0040 display_message <= '1'; switch := 1; elsif display_message = '1' then display_message <= '0'; elsif variable_requested = '1' and switch = 1 then variable_data <= water_end_hr; variable_valid <= '1'; elsif variable_valid = '1' and switch = 1 then variable_valid <= '0'; switch := 2; elsif variable_requested = '1' and switch = 2 then variable_data <= water_end_m; variable_valid <= '1'; elsif variable_valid = '1' and switch = 2 then variable_valid <= '0'; switch := 0; state <= set_end; end if; when set_end => if button(0) = '1' then -- Increment Hour water_end_hr <= water_end_hr + 1; if water_end_hr = 24 then water_end_hr <= "00000000"; end if; state <= show_end; elsif button(1) = '1' then -- Increment Minute water_end_m <= water_end_m + 1; if water_end_m = 60 then water_end_m <= "00000000"; end if; state <= show_end; elsif button(2) = '1' then -- Save setting, Turn option water_option_on <= '1'; -- on, go to maintain water state <= set_level; elsif button(3) = '1' then -- Turn option off water_option_on <= '0'; -- go to maintain water state <= set_level; end if; when set_level => -- Display Maintain Moisture Levels if toggle = 0 then if decoder_ready = '1' then message_address <= "0000001100000"; -- hex 0060 display_message <= '1'; elsif display_message = '1' then display_message <= '0'; elsif variable_requested = '1' then variable_data <= water_level; variable_valid <= '1'; elsif variable_valid = '1' then variable_valid <= '0'; toggle := 1; end if; else if button(2) = '1' then -- Increment Level water_level <= water_level + 1; if water_level = 10 then water_level <= "00000000"; end if; state <= set_level; toggle := 0; elsif button(3) = '1' then -- Set Level, go to state <= main; -- main menu user_set_water <= water_level; toggle := 0; end if; end if; when show_time => -- Display Current Time and Set if toggle = 0 then temp_hour <= "000" & current_hour; temp_minute <= "00" & current_minute; toggle := 1; end if; if decoder_ready = '1' then message_address <= "0000010000000"; -- hex 0080 display_message <= '1'; switch := 1; elsif display_message = '1' then display_message <= '0'; elsif variable_requested = '1' and switch = 1 then variable_data <= temp_hour; variable_valid <= '1'; elsif variable_valid = '1' and switch = 1 then variable_valid <= '0'; switch := 2; elsif variable_requested = '1' and switch = 2 then variable_data <= temp_minute; variable_valid <= '1'; elsif variable_valid = '1' and switch = 2 then variable_valid <= '0'; switch := 0; state <= set_time; end if; when set_time => if button(0) = '1' then -- Increment Hour temp_hour <= temp_hour + 1; if temp_hour = "00011000" then temp_hour <= "00000000"; end if; state <= show_time; elsif button(1) = '1' then -- Increment Minute temp_minute <= temp_minute + 1; if temp_minute = "00111100" then temp_minute <= "00000000"; end if; state <= show_time; elsif button(2) = '1' then -- Save Time set_new_hour <= temp_hour (4 downto 0); set_new_minute <= temp_minute (5 downto 0); set_new_time <= '1'; state <= main; toggle := 0; elsif button(3) = '1' then -- Don't set new time state <= main; toggle := 0; end if; end case; --internal_reset <= "1111"; end if; end process state_machine; --clear_push_buttons <= "0000"; end architecture behaviour;