diff --git a/Debug/.clangd/compile_commands.json b/Debug/.clangd/compile_commands.json index b23d093..89e676d 100644 --- a/Debug/.clangd/compile_commands.json +++ b/Debug/.clangd/compile_commands.json @@ -94,11 +94,6 @@ "command" : "clang++ -I\"/home/frederik/.ti/ccs2010/ccs/ccs_base/msp430/include\" -I\"/home/frederik/workspace_ccstheia/ESR-11\" -I\"/home/frederik/workspace_ccstheia/ESR-11/jsmn\" -I\"/home/frederik/workspace_ccstheia/ESR-11/driverlib/MSP430FR2xx_4xx\" -I\"/home/frederik/.ti/ccs2010/ccs/tools/compiler/ti-cgt-msp430_21.6.1.LTS/include\" -D__MSP430FR2355__ -D_FRWP_ENABLE -D_INFO_FRWP_ENABLE -xc", "file" : "/home/frederik/workspace_ccstheia/ESR-11/driverlib/MSP430FR2xx_4xx/tia.c" }, - { - "directory" : "/home/frederik/workspace_ccstheia/ESR-11/Debug", - "command" : "clang++ -I\"/home/frederik/.ti/ccs2010/ccs/ccs_base/msp430/include\" -I\"/home/frederik/workspace_ccstheia/ESR-11\" -I\"/home/frederik/workspace_ccstheia/ESR-11/jsmn\" -I\"/home/frederik/workspace_ccstheia/ESR-11/driverlib/MSP430FR2xx_4xx\" -I\"/home/frederik/.ti/ccs2010/ccs/tools/compiler/ti-cgt-msp430_21.6.1.LTS/include\" -D__MSP430FR2355__ -D_FRWP_ENABLE -D_INFO_FRWP_ENABLE -xc", - "file" : "/home/frederik/workspace_ccstheia/ESR-11/driverlib/MSP430FR2xx_4xx/timer_a.c" - }, { "directory" : "/home/frederik/workspace_ccstheia/ESR-11/Debug", "command" : "clang++ -I\"/home/frederik/.ti/ccs2010/ccs/ccs_base/msp430/include\" -I\"/home/frederik/workspace_ccstheia/ESR-11\" -I\"/home/frederik/workspace_ccstheia/ESR-11/jsmn\" -I\"/home/frederik/workspace_ccstheia/ESR-11/driverlib/MSP430FR2xx_4xx\" -I\"/home/frederik/.ti/ccs2010/ccs/tools/compiler/ti-cgt-msp430_21.6.1.LTS/include\" -D__MSP430FR2355__ -D_FRWP_ENABLE -D_INFO_FRWP_ENABLE -xc", diff --git a/driverlib/MSP430FR2xx_4xx/timer_a.c b/driverlib/MSP430FR2xx_4xx/timer_a.c deleted file mode 100755 index 06eb6c1..0000000 --- a/driverlib/MSP430FR2xx_4xx/timer_a.c +++ /dev/null @@ -1,381 +0,0 @@ -/* --COPYRIGHT--,BSD - * Copyright (c) 2016, Texas Instruments Incorporated - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * --/COPYRIGHT--*/ -//***************************************************************************** -// -// timer_a.c - Driver for the timer_a Module. -// -//***************************************************************************** - -//***************************************************************************** -// -//! \addtogroup timer_a_api timer_a -//! @{ -// -//***************************************************************************** - -#include "inc/hw_memmap.h" - -#ifdef __MSP430_HAS_TxA7__ -#include "timer_a.h" - -#include - -void Timer_A_startCounter(uint16_t baseAddress, - uint16_t timerMode) -{ - HWREG16(baseAddress + OFS_TAxCTL) |= timerMode; -} - -void Timer_A_initContinuousMode(uint16_t baseAddress, - Timer_A_initContinuousModeParam *param) -{ - HWREG16(baseAddress + - OFS_TAxCTL) &= ~(TIMER_A_CLOCKSOURCE_INVERTED_EXTERNAL_TXCLK + - TIMER_A_UPDOWN_MODE + - TIMER_A_DO_CLEAR + - TIMER_A_TAIE_INTERRUPT_ENABLE + - ID__8 - ); - HWREG16(baseAddress + OFS_TAxEX0) &= ~TAIDEX_7; - - HWREG16(baseAddress + OFS_TAxEX0) |= param->clockSourceDivider & 0x7; - HWREG16(baseAddress + OFS_TAxCTL) |= (param->clockSource + - param->timerClear + - param->timerInterruptEnable_TAIE + - ((param->clockSourceDivider >> - 3) << 6)); - - if(param->startTimer) - { - HWREG16(baseAddress + OFS_TAxCTL) |= TIMER_A_CONTINUOUS_MODE; - } -} - -void Timer_A_initUpMode(uint16_t baseAddress, - Timer_A_initUpModeParam *param) -{ - HWREG16(baseAddress + OFS_TAxCTL) &= - ~(TIMER_A_CLOCKSOURCE_INVERTED_EXTERNAL_TXCLK + - TIMER_A_UPDOWN_MODE + - TIMER_A_DO_CLEAR + - TIMER_A_TAIE_INTERRUPT_ENABLE + - ID__8 - ); - HWREG16(baseAddress + OFS_TAxEX0) &= ~TAIDEX_7; - - HWREG16(baseAddress + OFS_TAxEX0) |= param->clockSourceDivider & 0x7; - HWREG16(baseAddress + OFS_TAxCTL) |= (param->clockSource + - param->timerClear + - param->timerInterruptEnable_TAIE + - ((param->clockSourceDivider >> - 3) << 6)); - - if(param->startTimer) - { - HWREG16(baseAddress + OFS_TAxCTL) |= TIMER_A_UP_MODE; - } - - if(TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE == - param->captureCompareInterruptEnable_CCR0_CCIE) - { - HWREG16(baseAddress + - OFS_TAxCCTL0) |= TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE; - } - else - { - HWREG16(baseAddress + - OFS_TAxCCTL0) &= ~TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE; - } - - HWREG16(baseAddress + OFS_TAxCCR0) = param->timerPeriod; -} - -void Timer_A_initUpDownMode(uint16_t baseAddress, - Timer_A_initUpDownModeParam *param) -{ - HWREG16(baseAddress + OFS_TAxCTL) &= - ~(TIMER_A_CLOCKSOURCE_INVERTED_EXTERNAL_TXCLK + - TIMER_A_UPDOWN_MODE + - TIMER_A_DO_CLEAR + - TIMER_A_TAIE_INTERRUPT_ENABLE + - ID__8 - ); - HWREG16(baseAddress + OFS_TAxEX0) &= ~TAIDEX_7; - - HWREG16(baseAddress + OFS_TAxEX0) |= param->clockSourceDivider & 0x7; - HWREG16(baseAddress + OFS_TAxCTL) |= (param->clockSource + - param->timerClear + - param->timerInterruptEnable_TAIE + - ((param->clockSourceDivider >> - 3) << 6)); - - if(param->startTimer) - { - HWREG16(baseAddress + OFS_TAxCTL) |= TIMER_A_UPDOWN_MODE; - } - - if(TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE == - param->captureCompareInterruptEnable_CCR0_CCIE) - { - HWREG16(baseAddress + - OFS_TAxCCTL0) |= TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE; - } - else - { - HWREG16(baseAddress + - OFS_TAxCCTL0) &= ~TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE; - } - - HWREG16(baseAddress + OFS_TAxCCR0) = param->timerPeriod; -} - -void Timer_A_initCaptureMode(uint16_t baseAddress, - Timer_A_initCaptureModeParam *param) -{ - HWREG16(baseAddress + param->captureRegister) |= CAP; - - HWREG16(baseAddress + param->captureRegister) &= - ~(TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE + - TIMER_A_CAPTURE_INPUTSELECT_Vcc + - TIMER_A_CAPTURE_SYNCHRONOUS + - TIMER_A_DO_CLEAR + - TIMER_A_TAIE_INTERRUPT_ENABLE + - CM_3 - ); - - HWREG16(baseAddress + param->captureRegister) |= (param->captureMode + - param->captureInputSelect - + - param-> - synchronizeCaptureSource + - param-> - captureInterruptEnable + - param->captureOutputMode - ); -} - -void Timer_A_initCompareMode(uint16_t baseAddress, - Timer_A_initCompareModeParam *param) -{ - HWREG16(baseAddress + param->compareRegister) &= ~CAP; - - HWREG16(baseAddress + param->compareRegister) &= - ~(TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE + - TIMER_A_OUTPUTMODE_RESET_SET - ); - - HWREG16(baseAddress + - param->compareRegister) |= (param->compareInterruptEnable + - param->compareOutputMode - ); - - HWREG16(baseAddress + param->compareRegister + - OFS_TAxR) = param->compareValue; -} - -void Timer_A_enableInterrupt(uint16_t baseAddress) -{ - HWREG16(baseAddress + OFS_TAxCTL) |= TAIE; -} - -void Timer_A_disableInterrupt(uint16_t baseAddress) -{ - HWREG16(baseAddress + OFS_TAxCTL) &= ~TAIE; -} - -uint32_t Timer_A_getInterruptStatus(uint16_t baseAddress) -{ - return (HWREG16(baseAddress + OFS_TAxCTL) & TAIFG); -} - -void Timer_A_enableCaptureCompareInterrupt(uint16_t baseAddress, - uint16_t captureCompareRegister) -{ - HWREG16(baseAddress + captureCompareRegister) |= CCIE; -} - -void Timer_A_disableCaptureCompareInterrupt(uint16_t baseAddress, - uint16_t captureCompareRegister) -{ - HWREG16(baseAddress + captureCompareRegister) &= ~CCIE; -} - -uint32_t Timer_A_getCaptureCompareInterruptStatus(uint16_t baseAddress, - uint16_t captureCompareRegister, - uint16_t mask) -{ - return (HWREG16(baseAddress + captureCompareRegister) & mask); -} - -void Timer_A_clear(uint16_t baseAddress) -{ - HWREG16(baseAddress + OFS_TAxCTL) |= TACLR; -} - -uint8_t Timer_A_getSynchronizedCaptureCompareInput(uint16_t baseAddress, - uint16_t captureCompareRegister, - uint16_t synchronized) -{ - if(HWREG16(baseAddress + captureCompareRegister) & synchronized) - { - return (TIMER_A_CAPTURECOMPARE_INPUT_HIGH); - } - else - { - return (TIMER_A_CAPTURECOMPARE_INPUT_LOW); - } -} - -uint8_t Timer_A_getOutputForOutputModeOutBitValue(uint16_t baseAddress, - uint16_t captureCompareRegister) -{ - if(HWREG16(baseAddress + captureCompareRegister) & OUT) - { - return (TIMER_A_OUTPUTMODE_OUTBITVALUE_HIGH); - } - else - { - return (TIMER_A_OUTPUTMODE_OUTBITVALUE_LOW); - } -} - -uint16_t Timer_A_getCaptureCompareCount(uint16_t baseAddress, - uint16_t captureCompareRegister) -{ - return (HWREG16(baseAddress + OFS_TAxR + captureCompareRegister)); -} - -void Timer_A_setOutputForOutputModeOutBitValue(uint16_t baseAddress, - uint16_t captureCompareRegister, - uint8_t outputModeOutBitValue) -{ - HWREG16(baseAddress + captureCompareRegister) &= ~OUT; - HWREG16(baseAddress + captureCompareRegister) |= outputModeOutBitValue; -} - -void Timer_A_outputPWM(uint16_t baseAddress, - Timer_A_outputPWMParam *param) -{ - HWREG16(baseAddress + OFS_TAxCTL) &= - ~(TIMER_A_CLOCKSOURCE_INVERTED_EXTERNAL_TXCLK + - TIMER_A_UPDOWN_MODE + TIMER_A_DO_CLEAR + - TIMER_A_TAIE_INTERRUPT_ENABLE + - ID__8 - ); - HWREG16(baseAddress + OFS_TAxEX0) &= ~TAIDEX_7; - - HWREG16(baseAddress + OFS_TAxEX0) |= param->clockSourceDivider & 0x7; - HWREG16(baseAddress + OFS_TAxCTL) |= (param->clockSource + - TIMER_A_UP_MODE + - TIMER_A_DO_CLEAR + - ((param->clockSourceDivider >> - 3) << 6)); - - HWREG16(baseAddress + OFS_TAxCCR0) = param->timerPeriod; - - HWREG16(baseAddress + OFS_TAxCCTL0) &= - ~(TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE + - TIMER_A_OUTPUTMODE_RESET_SET); - - HWREG16(baseAddress + param->compareRegister) |= param->compareOutputMode; - - HWREG16(baseAddress + param->compareRegister + OFS_TAxR) = param->dutyCycle; -} - -void Timer_A_stop(uint16_t baseAddress) -{ - HWREG16(baseAddress + OFS_TAxCTL) &= ~MC_3; -} - -void Timer_A_setCompareValue(uint16_t baseAddress, - uint16_t compareRegister, - uint16_t compareValue) -{ - HWREG16(baseAddress + compareRegister + OFS_TAxR) = compareValue; -} - -void Timer_A_setOutputMode(uint16_t baseAddress, - uint16_t compareRegister, - uint16_t compareOutputMode) -{ - uint16_t temp = HWREG16(baseAddress + compareRegister); - HWREG16(baseAddress + - compareRegister) = temp & ~(OUTMOD_7) | compareOutputMode; -} - -void Timer_A_clearTimerInterrupt(uint16_t baseAddress) -{ - HWREG16(baseAddress + OFS_TAxCTL) &= ~TAIFG; -} - -void Timer_A_clearCaptureCompareInterrupt(uint16_t baseAddress, - uint16_t captureCompareRegister) -{ - HWREG16(baseAddress + captureCompareRegister) &= ~CCIFG; -} - -uint16_t Timer_A_getCounterValue(uint16_t baseAddress) -{ - uint16_t voteOne, voteTwo, res; - - voteTwo = HWREG16(baseAddress + OFS_TAxR); - - do - { - voteOne = voteTwo; - voteTwo = HWREG16(baseAddress + OFS_TAxR); - - if(voteTwo > voteOne) - { - res = voteTwo - voteOne; - } - else if(voteOne > voteTwo) - { - res = voteOne - voteTwo; - } - else - { - res = 0; - } - } - while(res > TIMER_A_THRESHOLD); - - return(voteTwo); -} - -#endif -//***************************************************************************** -// -//! Close the doxygen group for timer_a_api -//! @} -// -//***************************************************************************** diff --git a/src/state_machine.c b/src/state_machine.c index 81c1ae3..a4e081c 100644 --- a/src/state_machine.c +++ b/src/state_machine.c @@ -4,7 +4,7 @@ * @brief State machine implementation for the beverage dispenser core program. * * Tracks per‐type stock levels, enforces stock limits on orders, - * and provides an “*” menu in IDLE to edit stock via the keypad. + * and provides an “[A-D]/*” menu in IDLE to edit stock via the keypad. * * @authors * Frederik Beimgraben @@ -24,20 +24,19 @@ #include "state_machine.h" #include "timer.h" -/* ——— Configurable Defaults ———————————————————————————————— */ -#define INITIAL_STOCK_DEFAULT 20U /**< Default stock for each beverage */ -#define MAX_STOCK 255U /**< Maximum stock representable */ - -/* ——— Internal State Variables —————————————————————————————— */ +/** Default initial stock for each beverage. */ +#define INITIAL_STOCK_DEFAULT 20U +/** Maximum stock representable (uint8_t limit). */ +#define MAX_STOCK 255U /** Last key pressed on the keypad. */ -volatile char keypad_last_key = '\0'; +volatile char keypad_last_key = '\0'; /** Flag set when a new key is ready to handle. */ -volatile bool keypad_flag_chg = false; +volatile bool keypad_flag_chg = false; /** True if the door is currently open. */ -volatile bool door_open = false; +volatile bool door_open = false; /** True if the state has just changed and UI needs redrawing. */ -volatile bool state_chg = false; +volatile bool state_chg = false; /** Current UI state. */ volatile State_t current_state = STATE_IDLE; @@ -59,12 +58,14 @@ volatile uint8_t stock_d = INITIAL_STOCK_DEFAULT; /** Temporary buffer for building a new stock value. */ volatile uint8_t new_stock_count = 0; -/** LCD line buffers. */ +/** LCD line buffers (must be at least 17 bytes for 16-char + null). */ char buffer_ab[17]; char buffer_cd[17]; -/* ——— Function Prototypes ———————————————————————————————— */ +/* —— Function Prototypes —— */ + /* Keypad input handlers */ +static void keypad_handler(char key); void handle_input_idle(unsigned char key); void handle_input_sel_count(unsigned char key); void handle_input_confirmed(unsigned char key); @@ -103,24 +104,21 @@ void buzz_invalid_input(void); static void door_opened_handler(void); static void door_closed_handler(void); -/* Keypad Callback */ -static void keypad_handler(char key); - /* General interrupt dispatcher */ void handle_general_interrupt(void); -/* ——— Implementation ————————————————————————————————————— */ /** * @brief Initialize peripherals and draw the initial UI. + * + * Registers keypad and door callbacks, resets counts and stock, + * and displays the idle screen. */ void sm_init(void) { - /* register keypad + door callbacks */ - keypad_init(/* callback = */ keypad_handler); + keypad_init(keypad_handler); door_init(door_opened_handler, door_closed_handler); - /* start in IDLE with default stocks */ reset_amounts(); reset_new_stock(); stock_a = stock_b = stock_c = stock_d = INITIAL_STOCK_DEFAULT; @@ -128,23 +126,25 @@ void sm_init(void) ui_draw_idle(); } + /** - * @brief Main event loop: low‐power + interrupts. + * @brief Main event loop: low‐power mode with interrupts. */ void sm_loop(void) { for (;;) { - __bis_SR_register(LPM0_bits | GIE); /* sleep until interrupt */ + __bis_SR_register(LPM0_bits | GIE); __no_operation(); handle_general_interrupt(); } } + /** * @brief Keypad interrupt handler. * @param key ASCII code of the pressed key. * - * Routes key to the correct state‐specific handler. + * Routes key to the state‐specific handler. */ static void keypad_handler(char key) { @@ -169,7 +169,6 @@ static void keypad_handler(char key) handle_input_edit_stock_set(key); break; case STATE_EDIT_STOCK_CONFIRMED: - /* any key closes confirmation */ transition(STATE_IDLE); break; default: @@ -178,12 +177,12 @@ static void keypad_handler(char key) } } + /** - * @brief Handle keypress when in STATE_IDLE. + * @brief Handle keypress in STATE_IDLE. * @param key ASCII of pressed key. * - * A–D start ordering that beverage. - * ‘*’ enters stock‐editing menu. + * [A-D] to order, [*] to enter stock‐edit menu. */ void handle_input_idle(unsigned char key) { @@ -202,12 +201,13 @@ void handle_input_idle(unsigned char key) } } + /** - * @brief Handle keypress when selecting order quantity. + * @brief Handle keypress in STATE_SEL_COUNT. * @param key ASCII of pressed key. * - * Digits build count (up to stock), ‘#’ confirms, ‘*’ clears, - * anything else falls back to idle‐handler. + * Digits build an order (up to stock), [#] confirms, [*] clears, + * others fall back to idle. */ void handle_input_sel_count(unsigned char key) { @@ -221,7 +221,7 @@ void handle_input_sel_count(unsigned char key) } else if (!any_selected()) { transition(STATE_NONE_SELECTED); } else { - /* deduct stock before confirming */ + /* Deduct stock */ switch (selected_bev) { case BEV_A: stock_a -= count_a; break; case BEV_B: stock_b -= count_b; break; @@ -240,12 +240,12 @@ void handle_input_sel_count(unsigned char key) } } + /** - * @brief Handle keypress in STATE_CONFIRMED (and STATE_OPEN). + * @brief Handle keypress in STATE_CONFIRMED/STATE_OPEN. * @param key ASCII of pressed key. * - * A–D re‐select beverage for new order. - * ‘*’ resets all order counts. + * [A-D] to start new order, [*] to reset all counts. */ void handle_input_confirmed(unsigned char key) { @@ -264,11 +264,12 @@ void handle_input_confirmed(unsigned char key) } } + /** * @brief Handle keypress in STATE_EDIT_STOCK_SELECT. - * @param key ASCII pressed. + * @param key ASCII of pressed key. * - * A–D pick which stock to edit, ‘*’ cancels to IDLE. + * Select which beverage stock to edit [A-D], or [*] to cancel. */ void handle_input_edit_stock_select(unsigned char key) { @@ -287,11 +288,12 @@ void handle_input_edit_stock_select(unsigned char key) } } + /** * @brief Handle keypress in STATE_EDIT_STOCK_SET. - * @param key ASCII pressed. + * @param key ASCII of pressed key. * - * Digits build new stock, ‘#’ confirms update, ‘*’ cancels. + * Digits build new stock, [#] confirms, [*] cancels. */ void handle_input_edit_stock_set(unsigned char key) { @@ -300,7 +302,6 @@ void handle_input_edit_stock_set(unsigned char key) transition(STATE_EDIT_STOCK_SET); } else if (key == '#') { - /* apply new stock */ switch (selected_bev) { case BEV_A: stock_a = new_stock_count; break; case BEV_B: stock_b = new_stock_count; break; @@ -318,11 +319,12 @@ void handle_input_edit_stock_set(unsigned char key) } } + /** - * @brief Update the order count for selected beverage. - * @param digit 0–9 to append. + * @brief Append a digit to the order count for selected beverage. + * @param digit Value 0–9. * - * Ensures you never exceed the stock level. + * Prevents exceeding remaining stock. */ void update_amount(uint8_t digit) { @@ -351,8 +353,9 @@ void update_amount(uint8_t digit) } } + /** - * @brief Reset the order count for the currently selected beverage. + * @brief Reset the current beverage’s order count to zero. */ void reset_amount(void) { @@ -364,6 +367,7 @@ void reset_amount(void) } } + /** * @brief Reset all order counts to zero. */ @@ -372,41 +376,44 @@ void reset_amounts(void) count_a = count_b = count_c = count_d = 0; } + /** - * @brief Build up new stock value from digit. - * @param digit 0–9 to append. + * @brief Append a digit to the new‐stock entry. + * @param digit Value 0–9. * * Caps at MAX_STOCK. */ void update_new_stock(uint8_t digit) { uint16_t tentative = new_stock_count * 10 + digit; - if (tentative <= MAX_STOCK) { + if (tentative <= MAX_STOCK) new_stock_count = (uint8_t)tentative; - } else { + else buzz_invalid_input(); - } } + /** - * @brief Reset the “new stock” entry buffer to zero. + * @brief Reset the new‐stock entry buffer to zero. */ void reset_new_stock(void) { new_stock_count = 0; } + /** - * @brief True if any order count > 0. - * @return bool + * @brief Check if any order count is nonzero. + * @return true if at least one beverage has a count. */ bool any_selected(void) { return (count_a + count_b + count_c + count_d) > 0; } + /** - * @brief Perform the visual update when state changes. + * @brief Redraw the UI if the state has changed. */ void handle_general_interrupt(void) { @@ -428,9 +435,10 @@ void handle_general_interrupt(void) state_chg = false; } + /** - * @brief Transition to a new state (requests a redraw). - * @param next Next state. + * @brief Transition to a new state and request redrawing. + * @param next The next state to enter. */ void transition(State_t next) { @@ -438,10 +446,11 @@ void transition(State_t next) state_chg = true; } -/* ——— Door Callbacks —————————————————————————————————————— */ /** - * @brief Called when door opens. + * @brief Called when the door is opened. + * + * If not in CONFIRMED state, shows UNAUTHORIZED; otherwise OPEN. */ static void door_opened_handler(void) { @@ -453,8 +462,11 @@ static void door_opened_handler(void) door_open = true; } + /** - * @brief Called when door closes. + * @brief Called when the door is closed. + * + * Resets orders and returns to IDLE. */ static void door_closed_handler(void) { @@ -463,105 +475,130 @@ static void door_closed_handler(void) door_open = false; } -/* ——— UI Drawing Functions —————————————————————————————— */ /** * @brief Draw the IDLE screen. + * + * Line 1: “Ready!” centered. + * Line 2: “[A-D]/*” menu hint. */ void ui_draw_idle(void) { lcd_clear(); - lcd_set_cursor(0,5); lcd_print("Ready!"); - lcd_set_cursor(1,0); lcd_print("A-D to order * to edit"); + lcd_set_cursor(0,5); lcd_print("Ready!"); + lcd_set_cursor(1,4); lcd_print("[A-D]/*"); } + /** - * @brief Draw the quantity‐selection screen. + * @brief Draw the order‐quantity selection screen. + * + * Shows A/B on line 1, C/D on line 2 with “*” marking the selected. */ void ui_draw_sel_count(void) { snprintf(buffer_ab, 17, "A:%c%3u B:%c%3u", - (selected_bev==BEV_A?'*':' '), count_a, - (selected_bev==BEV_B?'*':' '), count_b); + (selected_bev==BEV_A?'*':' '), count_a, + (selected_bev==BEV_B?'*':' '), count_b); snprintf(buffer_cd, 17, "C:%c%3u D:%c%3u", - (selected_bev==BEV_C?'*':' '), count_c, - (selected_bev==BEV_D?'*':' '), count_d); + (selected_bev==BEV_C?'*':' '), count_c, + (selected_bev==BEV_D?'*':' '), count_d); lcd_clear(); - lcd_set_cursor(0,0); lcd_print(buffer_ab); - lcd_set_cursor(1,0); lcd_print(buffer_cd); + lcd_set_cursor(0,0); lcd_print(buffer_ab); + lcd_set_cursor(1,0); lcd_print(buffer_cd); } + /** * @brief Draw the “order confirmed” screen. + * + * Line 1: “Confirmed!” centered. + * Line 2: “Press [A-D]/*” for next action. */ void ui_draw_confirmed(void) { lcd_clear(); - lcd_set_cursor(0,3); lcd_print("Confirmed!"); - lcd_set_cursor(1,1); lcd_print("Press A-D or *"); + lcd_set_cursor(0,3); lcd_print("Confirmed!"); + lcd_set_cursor(1,2); lcd_print("OPEN/[A-D]/*"); } + /** * @brief Draw the unauthorized‐open error. */ void ui_draw_error(void) { lcd_clear(); - lcd_set_cursor(0,2); lcd_print("UNAUTHORIZED"); - lcd_set_cursor(1,1); lcd_print("DOOR OPENED!"); + lcd_set_cursor(0,2); lcd_print("UNAUTHORIZED"); + lcd_set_cursor(1,3); lcd_print("DOOR OPENED"); } + /** * @brief Draw the “door is open” screen. */ void ui_draw_open(void) { lcd_clear(); - lcd_set_cursor(0,2); lcd_print("DOOR OPEN"); - lcd_set_cursor(1,0); lcd_print("Close then *"); + lcd_set_cursor(0,4); lcd_print("DOOR OPEN"); + lcd_set_cursor(1,2); lcd_print("[*] to reset"); } + /** * @brief Draw when no beverage was selected at “#”. */ void ui_draw_none_selected(void) { lcd_clear(); - lcd_set_cursor(0,4); lcd_print("SELECT!"); - lcd_set_cursor(1,1); lcd_print("Choose A-D"); + lcd_set_cursor(0,4); lcd_print("SELECT!"); + lcd_set_cursor(1,1); lcd_print("Choose [A-D]"); sleep(1000); transition(STATE_SEL_COUNT); ui_draw_sel_count(); } + /** - * @brief Transient “amounts reset” screen. + * @brief Transient “all reset” screen. */ void ui_draw_reset(void) { lcd_clear(); - lcd_set_cursor(0,2); lcd_print("All Reset"); - lcd_set_cursor(1,1); lcd_print("Ready"); + lcd_set_cursor(0,3); lcd_print("All Reset"); + lcd_set_cursor(1,5); lcd_print("Ready"); sleep(1000); - transition(STATE_IDLE); - ui_draw_idle(); + if (door_open) { + transition(STATE_OPEN); + ui_draw_open(); + } else { + transition(STATE_IDLE); + ui_draw_idle(); + } } + /** * @brief Draw the stock‐selection screen. + * + * [A-D] picks beverage, [*] cancels. */ void ui_draw_stock_select(void) { lcd_clear(); - lcd_set_cursor(0,3); lcd_print("Edit Stock"); - lcd_set_cursor(1,1); lcd_print("A-D:*cancel"); + lcd_set_cursor(0,3); lcd_print("Edit Stock"); + lcd_set_cursor(1,4); lcd_print("[A-D]/*"); } + /** * @brief Draw the “enter new stock” screen. + * + * Line 1: “X stock:YYY” current level. + * Line 2: “New:ZZZ /*” entry buffer and cancel. */ void ui_draw_stock_set(void) { @@ -574,28 +611,28 @@ void ui_draw_stock_set(void) } lcd_clear(); snprintf(buffer_ab,17,"%c stock:%3u", 'A'+selected_bev, cur); - lcd_set_cursor(0,0); lcd_print(buffer_ab); + lcd_set_cursor(0,0); lcd_print(buffer_ab); - snprintf(buffer_cd,17,"New:%3u *cancel", new_stock_count); - lcd_set_cursor(1,0); lcd_print(buffer_cd); + snprintf(buffer_cd,17,"New:%3u /*", new_stock_count); + lcd_set_cursor(1,0); lcd_print(buffer_cd); } + /** * @brief Draw the “stock updated” confirmation. */ void ui_draw_stock_confirmed(void) { lcd_clear(); - lcd_set_cursor(0,1); lcd_print("Stock Updated!"); - lcd_set_cursor(1,1); lcd_print("Press any key"); + lcd_set_cursor(0,2); lcd_print("Stock Updated"); + lcd_set_cursor(1,1); lcd_print("Press any key"); } -/* ——— Feedback ——————————————————————————————————————————— */ /** - * @brief Short buzzer tone for invalid input. + * @brief Short buzzer tone or LED flash for invalid input. */ void buzz_invalid_input(void) { - /* stub: beep or flash LED */ + /* stub: implement buzzer or LED indication */ }