-------------------------------------------------------------------------------- -- Control.vhd -- 1998 Nov -- Sydney Tang -- -- top-level control system -- -- 736 (63%), 151.4ns, 6.60MHz (7.21, Julian, noerrchk, fixed, nospace) -- 893 (77%), 156.6ns, 6.38MHz (7.21, Gregorian, errchk, fixed, nospace, norl) -- 924 (80%), (7.21, Julian, new handshaking, errck, fixed, nospace, rl) -- -- 771 (66%), (8.1, Julian, no error check) -- 731 (63%), (8.1, Julian, noerrchk, fixed, nospace) -- 834 (72%), (8.1, Julian, errchk, fixed, nospace) -- 777 (67%), (8.1, Julian, noerck, fixed, lcdrst, nospace) -- -- 895 (77%), 127.6ns, 7.83MHz (8.1, Gregorian, errchk, fixed, nospace, norl) -- 932 (80%), ?????ns, ????MHz (8.1, Gregorian, errchk, fixed, nospace, rl) -- -- Controller for the system. This entity contains the code and sub-entities -- that keep track of time, manage a state machine, and handle the keypad and -- LCD drivers that are attached to it. -- -- See my big comment at the end of this file if you really want all the gory -- and explicit details as to what this entity does. Also see Control_Package. -------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; library work; use work.Constants_Package.all; use work.Time_Package.all; use work.Control_Package.all; use work.BCD_Package.all; entity Control is port( -- basic input clock: in std_logic; reset: in std_logic; oneSecondClock: in std_logic; --diagnostics: out std_logic_vector(DIAGNOSTIC_WIDTH-1 downto 0); -- input from Keypad driver keyData: in std_logic_vector(KEYPAD_DATA_WIDTH-1 downto 0); keyDataAvailable: in std_logic; -- output to keypad driver keyAcknowledged: out std_logic; -- handshaking input from LCD driver LCDready:in std_logic; -- instructions to LCD driver currentState: out std_logic_vector(STATE_WIDTH-1 downto 0); LCDcharacter: out std_logic_vector(CHAR_WIDTH-1 downto 0); LCDinstruction: out std_logic_vector(LCD_INSTRUCTION_WIDTH-1 downto 0); -- general output LEDalarm: out std_logic; speaker: out std_logic ); end Control; -------------------------------------------------------------------------------- architecture controller of Control is ------------------------------------------ -- wires attached to the TimeDate component signal loadNewTimeDate: std_logic; signal currentYear: std_logic_vector(YEAR_WIDTH-1 downto 0); signal currentMonth: std_logic_vector(MONTH_WIDTH-1 downto 0); signal currentDay: std_logic_vector(DAY_WIDTH-1 downto 0); signal currentHour: std_logic_vector(HOUR_WIDTH-1 downto 0); signal currentMinute: std_logic_vector(MINUTE_WIDTH-1 downto 0); signal currentSecond: std_logic_vector(SECOND_WIDTH-1 downto 0); signal currentWeekday: std_logic_vector(WEEKDAY_WIDTH-1 downto 0); signal newYear: std_logic_vector(YEAR_WIDTH-1 downto 0); signal newMonth: std_logic_vector(MONTH_WIDTH-1 downto 0); signal newDay: std_logic_vector(DAY_WIDTH-1 downto 0); signal newHour: std_logic_vector(HOUR_WIDTH-1 downto 0); signal newMinute: std_logic_vector(MINUTE_WIDTH-1 downto 0); signal newSecond: std_logic_vector(SECOND_WIDTH-1 downto 0); signal newWeekday: std_logic_vector(WEEKDAY_WIDTH-1 downto 0); ------------------------------------------ -- wires attached to the EventManager component signal eventID: std_logic_vector(EVENT_ID_WIDTH-1 downto 0); signal saveEvent: std_logic; signal eventOccurred: std_logic; signal eventHour: std_logic_vector(HOUR_WIDTH-1 downto 0); signal eventMinute: std_logic_vector(MINUTE_WIDTH-1 downto 0); signal eventWeekday: std_logic_vector(WEEKDAY_WIDTH-1 downto 0); signal acknowledgeEvent: std_logic; ------------------------------------------ -- interactivity signals signal LatchedKeyData: std_logic_vector(BCD_WIDTH-1 downto 0); signal BCDdigitToConvertToChar: std_logic_vector(BCD_WIDTH-1 downto 0); signal ConvertedBCDdigit: std_logic_vector(CHAR_WIDTH-1 downto 0); signal digitToPrint: std_logic_vector(BCD_WIDTH-1 downto 0); signal TimeDate_index: std_logic_vector(CURSOR_POSITION_WIDTH-1 downto 0); signal AcknowledgeKey: std_logic; ------------------------------------------ -- LCD control signals signal printerState: printer_state_type; signal LCDstate: LCD_state_type; signal LCDresetFinished: std_logic; signal KeypressLCDcmd: std_logic_vector(LCD_INSTRUCTION_WIDTH-1 downto 0); signal LCDstateInstruction: std_logic_vector(LCD_INSTRUCTION_WIDTH-1 downto 0); signal ROMcharacter: std_logic_vector(CHAR_WIDTH-1 downto 0); ------------------------------------------ -- signals governing the usage of the printer entities signal FixedPrinterDone: std_logic; signal SpecialPrinterDone: std_logic; --signal SpaceSkipDone: std_logic; signal character_valid: std_logic; signal FixedPrinterBusy: std_logic; --signal SpecialPrinterBusy, SpaceSkipperBusy: std_logic; signal StartPrintingFixedText: std_logic; signal StartPrintingVariableText: std_logic; signal specialDigit: std_logic_vector(BCD_WIDTH-1 downto 0); signal SpecialLCDinstruction: std_logic_vector(LCD_INSTRUCTION_WIDTH-1 downto 0); --signal SpacesToSkip: std_logic_vector(LCD_POSITION_WIDTH-1 downto 0); --signal SkipSpace: std_logic; --signal SkipDirection: std_logic; ------------------------------------------ -- top-level state machine stuff signal current_state: std_logic_vector(STATE_WIDTH-1 downto 0); signal state: state_type; signal state_changed: std_logic; signal AlarmActive: std_logic; -------------------------------------------------------------------------------- begin ------------------------------------------------------------------------------ -- Time/Date tracking entity; supplies the current system time CurrentTime: JulianTimeDate port map( clock => clock, reset => reset, count_enable => OneSecondClock, year => currentYear, month => currentMonth, day => currentDay, hour => currentHour, minute => currentMinute, second => currentSecond, weekday => currentWeekday, load_enable => loadNewTimeDate, new_year => newYear, new_month => newMonth, new_day => newDay, new_hour => newHour, new_minute => newMinute, new_second => newSecond, new_weekday => newWeekday ); --diagnostics <= currentSecond(DIAGNOSTIC_WIDTH-1 downto 0); -------------------------------------------------------------------------- -- manager for weekly events stored in RAM. WeeklyEventMemoryManager: WeeklyEventManager port map( clock => clock, eventID => eventID, writeEvent => saveEvent, checkForEvent => oneSecondClock, eventMatched => eventOccurred, eventMatchAcknowledged => acknowledgeEvent, hour => eventHour, minute => eventMinute, weekday => eventWeekday, test_hour => currentHour, test_minute => currentMinute, test_weekday => currentWeekday, input_hour => newHour, input_minute => newMinute, input_weekday => newWeekday ); -------------------------------------------------------------------------- -- converter of BCD digits to LCD characters DigitToCharacterConverter: BCDtoLCD port map( BCDin => BCDdigitToConvertToChar, LCDout => ConvertedBCDdigit ); --CursorMover: SpaceSkipper -- port map( -- clock => clock, -- -- ready => LCDready, -- done => SpaceSkipDone, -- busy => SpaceSkipperBusy, -- -- start => StartSkippingSpaces, -- spaces_to_skip => SpacesToSkip, -- -- skip_enable => SkipSpace -- ); -------------------------------------------------------------------------- TopLinePrinter: FixedScreenPrinter port map( clock => clock, start => StartPrintingFixedText, ready => LCDready, currentState => current_state, done => FixedPrinterDone, busy => FixedPrinterBusy, character_valid => character_valid, character => ROMcharacter ); -------------------------------------------------------------------------- PrintingMachine: SpecialScreenPrinter port map( clock => clock, start => StartPrintingVariableText, ready => LCDready, done => SpecialPrinterDone, --busy => SpecialPrinterBusy, digit => digitToPrint, LCDinstruction => SpecialLCDinstruction, currentState => current_state, currentYear => currentYear, currentMonth => currentMonth, currentDay => currentDay, currentHour => currentHour, currentMinute => currentMinute, currentSecond => currentSecond, currentWeekday => currentWeekday, eventHour => eventHour, eventMinute => eventMinute, eventWeekday => eventWeekday ); -------------------------------------------------------------------------- -- key acknowledgement keyAcknowledged <= acknowledgeKey; -------------------------------------------------------------------------- -- alarm system SpeakerDriver: Oscillator port map( clock => clock, enable => AlarmActive, output_signal => speaker ); LEDalarm <= AlarmActive; -------------------------------------------------------------------------- -- state machine currentState <= current_state; current_state <= INITIAL_STATE when state = initial else SET_TIME_STATE when state = set_time else NORMAL_STATE when state = normal else SELECT_WEEKLY_EVENT_STATE when state = select_weekly_event else EDIT_WEEKLY_EVENT_STATE when state = edit_weekly_event else ALARM_STATE when state = alarm ;--else -------------------------------------------------------------------------- -- process for handling events in each state -- (and I don't mean alarm-type events) stateEventHandler: process(clock) is begin if reset = '1' then -------------------------------------------------------------------------- -- handle reset ********************************************************** -------------------------------------------------------------------------- AcknowledgeKey <= '0'; loadNewTimeDate <= '0'; saveEvent <= '0'; acknowledgeEvent <= '1'; -- supress event detection during startup AlarmActive <= '0'; LCDstate <= LCD_RESET_0; LCDresetFinished <= '0'; printerState <= idle; KeypressLCDcmd <= NO_ACTION; StartPrintingFixedText <= '0'; StartPrintingVariableText <= '0'; BCDdigitToConvertToChar <= LatchedKeyData; LCDcharacter <= ConvertedBCDdigit; state <= initial; state_changed <= '0'; elsif clock'event and clock = '1' then -- everything is synchronous LatchedKeyData <= keyData; -- Now we come to the big part. This is where each state looks at -- the input from the keypad (ie., user) and acts accordingly. -- user input may or may not cause a state transition. -- When a state transition occurs, the current state is responsible -- for initializing signals for the new state. case state is when initial => if LCDresetFinished = '1' then LCDresetFinished <= '0'; state <= set_time; state_changed <= '1'; TimeDate_index <= Y3; acknowledgeEvent <= '0'; -- enable events to be reported else state_changed <= '0'; end if; ------------------------------------------------------------------ when set_time => --state_changed <= '0'; if keyDataAvailable = '1' and AcknowledgeKey = '0' then --if keyDataAvailable = '1' then AcknowledgeKey <= '1'; case keyData is when ENT_KEY => loadNewTimeDate <= '1'; state <= normal; state_changed <= '1'; --KeypressLCDcmd <= REFRESH_SCREEN; when ONE_KEY | TWO_KEY | THREE_KEY | FOUR_KEY | FIVE_KEY | SIX_KEY | SEVEN_KEY | EIGHT_KEY | NINE_KEY | ZERO_KEY => -- a digit key was pressed. state_changed <= '0'; -- caused warning if TimeDate_index /= "1111" then -- Tell LCD to print the key. It will auto-advance. ??timing?? KeypressLCDcmd <= PRINT_CHAR; --print_request <= '1'; -- write keyData to TimeDate[TimeDate_index] -- Sad, isn't it? This is what happens when I can't use -- TimeDate_index as a pointer. case TimeDate_index is when Y3 => newYear(4*BCD_WIDTH-1 downto 3*BCD_WIDTH) <= keyData; when Y2 => newYear(3*BCD_WIDTH-1 downto 2*BCD_WIDTH) <= keyData; when Y1 => newYear(2*BCD_WIDTH-1 downto 1*BCD_WIDTH) <= keyData; when Y0 => newYear(1*BCD_WIDTH-1 downto 0*BCD_WIDTH) <= keyData; when MO1 => newMonth(2*BCD_WIDTH-1 downto 1*BCD_WIDTH) <= keyData; when MO0 => newMonth(1*BCD_WIDTH-1 downto 0*BCD_WIDTH) <= keyData; when D1 => newDay(2*BCD_WIDTH-1 downto 1*BCD_WIDTH) <= keyData; when D0 => newDay(1*BCD_WIDTH-1 downto 0*BCD_WIDTH) <= keyData; when H1 => newHour(2*BCD_WIDTH-1 downto 1*BCD_WIDTH) <= keyData; when H0 => newHour(1*BCD_WIDTH-1 downto 0*BCD_WIDTH) <= keyData; when M1 => newMinute(2*BCD_WIDTH-1 downto 1*BCD_WIDTH) <= keyData; when M0 => newMinute(1*BCD_WIDTH-1 downto 0*BCD_WIDTH) <= keyData; when S1 => newSecond(2*BCD_WIDTH-1 downto 1*BCD_WIDTH) <= keyData; when S0 => newSecond(1*BCD_WIDTH-1 downto 0*BCD_WIDTH) <= keyData; when W => newWeekday(1*BCD_WIDTH-1 downto 0*BCD_WIDTH) <= keyData; when others => -- do nothing end case; -- TimeDate_index -- if TimeDate_index = W then --KeypressLCDcmd <= BACKUP_CURSOR; -- need pending skip*** --SpacesToSkip <= ONE_SPACE; --SkipDirection <= SKIP_BACKWARD; --StartSkippingspaces <= '1'; -- else -- increment cursor position after typing a digit TimeDate_index <= TimeDate_index + '1'; -- end if; end if; --last position when LEFT_KEY => state_changed <= '0'; if TimeDate_index /= Y3 then KeypressLCDcmd <= BACKUP_CURSOR; TimeDate_index <= TimeDate_index - '1'; end if; when RIGHT_KEY => state_changed <= '0'; if TimeDate_index /= "1111" then KeypressLCDcmd <= ADVANCE_CURSOR; TimeDate_index <= TimeDate_index + '1'; end if; when others => -- nondigit key was pressed KeypressLCDcmd <= NO_ACTION; state_changed <= '0'; end case; -- set_time: keyData else -- no keypress AcknowledgeKey <= '0'; state_changed <= '0'; loadNewTimeDate <= '0'; end if; -- keypress ------------------------------------------------------------------ when normal => AlarmActive <= '0'; loadNewTimeDate <= '0'; if keyDataAvailable = '1' and AcknowledgeKey = '0' then --if keyDataAvailable = '1' then AcknowledgeKey <= '1'; -- key was pressed in normal state; -- therefore goto select_weekly_event state. state <= select_weekly_event; state_changed <= '1'; else -- no keypress AcknowledgeKey <= '0'; if eventOccurred = '1' then --acknowledgeEvent <= '1'; if currentSecond = "00" or currentSecond = "01" then state <= alarm; state_changed <= '1'; end if; elsif oneSecondClock = '1' then state <= normal; state_changed <= '1'; --if oneSecondClock = '1' then -- state <= normal; -- state_changed <= '1'; -- --elsif eventOccurred = '1' then -- acknowledgeEvent <= '1'; -- if currentSecond = "00" then -- state <= alarm; -- state_changed <= '1'; -- end if; else state_changed <= '0'; end if; end if; -- keypress ------------------------------------------------------------------ when select_weekly_event => saveEvent <= '0'; acknowledgeEvent <= '0'; if keyDataAvailable = '1' and AcknowledgeKey = '0' then --if keyDataAvailable = '1' then AcknowledgeKey <= '1'; case keyData is when ONE_KEY | TWO_KEY | THREE_KEY | FOUR_KEY | FIVE_KEY | SIX_KEY | SEVEN_KEY | ZERO_KEY => eventID <= keyData(EVENT_ID_WIDTH-1 downto 0); state <= edit_weekly_event; state_changed <= '1'; TimeDate_index <= H1; when others => state <= normal; state_changed <= '1'; --showCursor <= '0'; end case; -- select_weekly_event: keyData else AcknowledgeKey <= '0'; state_changed <= '0'; end if; -- keypress ------------------------------------------------------------------ when edit_weekly_event => --state_changed <= '0'; if keyDataAvailable = '1' and AcknowledgeKey = '0' then --if keyDataAvailable = '1' then AcknowledgeKey <= '1'; case keyData is when ENT_KEY => -- write currentTimeDate to RAM -- return to main menu saveEvent <= '1'; state <= select_weekly_event; state_changed <= '1'; when ONE_KEY | TWO_KEY | THREE_KEY | FOUR_KEY | FIVE_KEY | SIX_KEY | SEVEN_KEY | EIGHT_KEY | NINE_KEY | ZERO_KEY => if TimeDate_index /= "1111" then KeypressLCDcmd <= PRINT_CHAR; --print_request <= '1'; state_changed <= '0'; -- write keyData directly to TimeDate_index position of -- currentTimeDate case TimeDate_index is when H1 => newHour(2*BCD_WIDTH-1 downto 1*BCD_WIDTH) <= keyData; when H0 => newHour(1*BCD_WIDTH-1 downto 0*BCD_WIDTH) <= keyData; when M1 => newMinute(2*BCD_WIDTH-1 downto 1*BCD_WIDTH) <= keyData; when M0 => newMinute(1*BCD_WIDTH-1 downto 0*BCD_WIDTH) <= keyData; when W => newWeekday(1*BCD_WIDTH-1 downto 0*BCD_WIDTH) <= keyData; when others => -- do nothing end case; -- TimeDate_index -- increment cursor position after typing a digit if TimeDate_index = M0 then TimeDate_index <= TimeDate_index + "11"; --elsif TimeDate_index = W then --SpacesToSkip <= ONE_SPACE; ******************** --SkipDirection <= SKIP_BACKWARD; --StartSkippingspaces <= '1'; else TimeDate_index <= TimeDate_index + '1'; end if; end if; when LEFT_KEY => state_changed <= '0'; if TimeDate_index /= H1 then KeypressLCDcmd <= BACKUP_CURSOR; if TimeDate_index = W then TimeDate_index <= TimeDate_index - "11"; else TimeDate_index <= TimeDate_index - '1'; end if; end if; when RIGHT_KEY => state_changed <= '0'; if TimeDate_index /= "1111" then KeypressLCDcmd <= ADVANCE_CURSOR; if TimeDate_index = M0 then TimeDate_index <= TimeDate_index + "11"; else TimeDate_index <= TimeDate_index + '1'; end if; end if; when others => -- hit a key other than 0 to 9 or ENT -- while in edit_weekly_event -> backup to select_weekly_event state <= select_weekly_event; state_changed <= '1'; end case; -- edit_weekly_event: keyData else -- no keypress AcknowledgeKey <= '0'; state_changed <= '0'; saveEvent <= '0'; end if; -- keypress ------------------------------------------------------------------ when alarm => --state_changed <= '0'; acknowledgeEvent <= '1'; AlarmActive <= '1'; if keyDataAvailable = '1' then AcknowledgeKey <= '1'; -- added on dec1 state <= normal; state_changed <= '1'; acknowledgeEvent <= '1'; elsif oneSecondClock = '1' and currentSecond = ALARM_DURATION then -- alarm event is triggered on the minute; -- passively lapse back to normal state after ALARM_DURATION. state <= normal; state_changed <= '1'; acknowledgeEvent <= '1'; else state_changed <= '0'; end if; ------------------------------------------------------------------ --when others => ------------------------------------------------------------------ end case; -- state case printerState is when idle => --LCDinstruction <= NO_ACTION; if LCDstateInstruction /= NO_ACTION and LCDready = '1' then --if print_request = '1' and LCDready = '1' then LCDinstruction <= LCDstateInstruction; -- for fast fixed print printerState <= start; else LCDinstruction <= NO_ACTION; end if; when start => LCDinstruction <= LCDstateInstruction; --print_request <= '0'; printerState <= printing; when printing => if LCDready = '0' then -- LCDinstruction <= NO_ACTION; printerState <= done; else LCDinstruction <= LCDstateInstruction; end if; when done => KeypressLCDcmd <= NO_ACTION; printerState <= idle; end case; -- printer state case LCDstate is when USER_INITIATED => LCDstateInstruction <= KeypressLCDcmd; BCDdigitToConvertToChar <= LatchedKeyData; LCDcharacter <= ConvertedBCDdigit; if state_changed = '1' then LCDstate <= CLEAR_SCREEN; StartPrintingFixedText <= '0'; StartPrintingVariableText <= '0'; end if; when CLEAR_SCREEN => LCDstateInstruction <= REFRESH_SCREEN; -- if printerState = done then -- LCDstate <= FIXED_TEXT; -- StartPrintingFixedText <= '1'; -- end if; if printerState = done then LCDstate <= HOME_CURSOR; end if; when HOME_CURSOR => LCDstateInstruction <= CURSOR_HOME; if printerState = done then LCDstate <= FIXED_TEXT; StartPrintingFixedText <= '1'; end if; when FIXED_TEXT => if character_valid = '1' then LCDstateInstruction <= PRINT_CHAR; else LCDstateInstruction <= NO_ACTION; end if; LCDcharacter <= ROMcharacter; StartPrintingFixedText <= '0'; -- if printerState = done then -- LCDstate <= VARIABLE_TEXT; -- StartPrintingVariableText <= '1'; -- LCDcharacter <= ConvertedBCDdigit; -- end if; if FixedPrinterDone = '1' then LCDstate <= LINE2; end if; when LINE2 => LCDstateInstruction <= GOTO_LINE2; if printerState = done then LCDstate <= VARIABLE_TEXT; --print_request <= '1'; StartPrintingVariableText <= '1'; LCDcharacter <= ConvertedBCDdigit; end if; when VARIABLE_TEXT => LCDstateInstruction <= SpecialLCDinstruction; BCDdigitToConvertToChar <= digitToPrint; LCDcharacter <= ConvertedBCDdigit; StartPrintingVariableText <= '0'; if SpecialPrinterDone = '1' then LCDstate <= USER_INITIATED; BCDdigitToConvertToChar <= LatchedKeyData; end if; when LCD_RESET_0 => LCDstateInstruction <= REFRESH_SCREEN; if printerState = done then LCDstate <= LCD_RESET_1; end if; when LCD_RESET_1 => LCDstateInstruction <= CURSOR_HOME; if printerState = done then LCDstate <= LCD_RESET_2; end if; when LCD_RESET_2 => LCDstateInstruction <= LCD_DISPLAY_ON; if printerState = done then LCDstate <= LCD_RESET_3; end if; when LCD_RESET_3 => LCDstateInstruction <= LCD_FUNCTION_SET; if printerState = done then LCDresetFinished <= '1'; elsif state_changed = '1' then LCDstate <= CLEAR_SCREEN; end if; end case; -- LCDstate end if; -- rising clock edge end process stateEventHandler; -------------------------------------------------------------------------- end controller; -------------------------------------------------------------------------------- -- Expected control flow: -------------------------------------------------------------------------------- -- -- power-up -> -- system does nothing, system is uninitialized. -- -- RST key pressed -> -- 1. state <= initial (0), LCD begins reset procedure, -- control outputs initialized -- -------------------------------------------------------------------------------- -- INITIAL_STATE = 0 -- -- oneSecondClock -> -- 1. state <= set_time (1), LCD begins drawing screen, cursor visible -- -------------------------------------------------------------------------------- -- SET_TIME_STATE = 1 -- -- 2. LCD finishes drawing screen -> LCDready <= '1' -- -> start skipping back 32 spaces (spaceSkipActive = 1). -- 3. Done skipping spaces -> ready for user input. -- -- digit key pressed -> -- 1. LCD prints key on screen and advances cursor, TimeDate_index advanced. -- 2) possibly needs to advance another space -> SkipSpaceActive -- 3) done skipping spaces. -- -- some other key pressed -> -- 1. do nothing. -- -- ENT key pressed -> -- 1. state <= normal (2), load new time into TimeDate, LCD begins printing new -- screen, cursor invisible. -- -------------------------------------------------------------------------------- -- NORMAL_STATE = 2 -- -- 2. LCD finishes printing new screen -> Start skipping back 32 spaces -- 3. done skipping back -> start printing "special" screen by sending data -- from TimeDate to LCD. -- 4. done printing special screen, ready for user input -- -- any key pressed -> -- 1. state <= select_weekly_event (3), LCD begins printing new screen, -- cursor invisible -- 2. LCD finished -> start skipping back 32 spaces -- 3 done skipping, ready for user input. -- -------------------------------------------------------------------------------- -- SELECT_WEEKLY_EVENT_STATE = 3 -- -- key other than 0 to 7 pressed -> -- 1. state <= normal (2), LCD begins printing screen -- -- digit 0 to 7 pressed -> -- 1. state <= edit_weekly_event (4), LCD begins printing new screen, -- cursor visible. -- -------------------------------------------------------------------------------- -- EDIT_WEEKLY_EVENT_STATE = 4 -- -- 2. LCD finishes printing screen -> start skipping 32 spaces back to start. -- 3. done skipping spaces -> (maybe do this: start printing special screen, -- sending data for selected event to screen.) -- -- digit key pressed -> -- 1. LCD prints key to screen, cursor advanced, TimeDate_index advanced -- 2. LCD finished -> may need to move another space -> start skipping space -- 3 space skip finished, ready for user input. -- -- ENT key pressed -> -- 1. state <= select_weekly_event, save new event to selected address, -- LCD begins printing new screen. -- --------------------------------------------------------------------------------