Displays user interactions with menus displayed on a console or a serial terminal.
Dependents: EVAL-AD568x-AD569x EVAL-AD7124 EVAL-AD5592R EVAL-AD717x-AD411x ... more
adi_console_menu.c@7:49c1587ecd29, 2022-02-15 (annotated)
- Committer:
- pmallick
- Date:
- Tue Feb 15 15:45:15 2022 +0530
- Revision:
- 7:49c1587ecd29
- Parent:
- 6:34034065d24b
- Child:
- 8:17fbfba02ff1
* Updated the copyright year.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mahphalke | 1:dcc17e5a913f | 1 | /*! |
mahphalke | 1:dcc17e5a913f | 2 | ***************************************************************************** |
mahphalke | 1:dcc17e5a913f | 3 | @file: adi_console_menu.c |
mahphalke | 1:dcc17e5a913f | 4 | |
mahphalke | 1:dcc17e5a913f | 5 | @brief: A simple console menu manager handler |
mahphalke | 1:dcc17e5a913f | 6 | |
mahphalke | 1:dcc17e5a913f | 7 | @details: A way to define using arrays of structs a set of menus that can |
mahphalke | 1:dcc17e5a913f | 8 | be displayed to a user, easily, with all user interaction handled |
mahphalke | 1:dcc17e5a913f | 9 | by the library, leaving only the implementation of the menu actions |
mahphalke | 1:dcc17e5a913f | 10 | to be done by the library user. |
mahphalke | 1:dcc17e5a913f | 11 | ----------------------------------------------------------------------------- |
pmallick | 7:49c1587ecd29 | 12 | Copyright (c) 2019-2022 Analog Devices, Inc. |
mahphalke | 1:dcc17e5a913f | 13 | All rights reserved. |
mahphalke | 1:dcc17e5a913f | 14 | |
mahphalke | 1:dcc17e5a913f | 15 | This software is proprietary to Analog Devices, Inc. and its licensors. |
mahphalke | 1:dcc17e5a913f | 16 | By using this software you agree to the terms of the associated |
mahphalke | 1:dcc17e5a913f | 17 | Analog Devices Software License Agreement. |
mahphalke | 1:dcc17e5a913f | 18 | |
mahphalke | 1:dcc17e5a913f | 19 | *****************************************************************************/ |
mahphalke | 1:dcc17e5a913f | 20 | |
Kjansen |
5:052b9936f41f | 21 | /****************************************************************************/ |
Kjansen |
5:052b9936f41f | 22 | /***************************** Include Files ********************************/ |
Kjansen |
5:052b9936f41f | 23 | /****************************************************************************/ |
mahphalke | 1:dcc17e5a913f | 24 | #include <stdio.h> |
mahphalke | 1:dcc17e5a913f | 25 | #include <stdlib.h> |
mahphalke | 1:dcc17e5a913f | 26 | #include <ctype.h> |
mahphalke | 1:dcc17e5a913f | 27 | #include <string.h> |
mahphalke | 1:dcc17e5a913f | 28 | #include <stdbool.h> |
mahphalke | 1:dcc17e5a913f | 29 | #include <assert.h> |
mahphalke | 1:dcc17e5a913f | 30 | |
mahphalke | 1:dcc17e5a913f | 31 | #include "adi_console_menu.h" |
Kjansen |
5:052b9936f41f | 32 | #include "error.h" |
mahphalke | 1:dcc17e5a913f | 33 | |
Kjansen |
5:052b9936f41f | 34 | /****************************************************************************/ |
Kjansen |
5:052b9936f41f | 35 | /********************** Macros and Constants Definition *********************/ |
Kjansen |
5:052b9936f41f | 36 | /****************************************************************************/ |
mahphalke | 1:dcc17e5a913f | 37 | #define DIV_STRING "\t==================================================" |
mahphalke | 1:dcc17e5a913f | 38 | |
Kjansen |
5:052b9936f41f | 39 | /******************************************************************************/ |
Kjansen |
5:052b9936f41f | 40 | /*************************** Types Declarations *******************************/ |
Kjansen |
5:052b9936f41f | 41 | /******************************************************************************/ |
Kjansen |
5:052b9936f41f | 42 | // Saves the state of console menu library |
Kjansen |
5:052b9936f41f | 43 | console_menu_state adi_console_menu_state = { |
Kjansen |
5:052b9936f41f | 44 | .last_error_code = SUCCESS |
Kjansen |
5:052b9936f41f | 45 | }; |
Kjansen |
5:052b9936f41f | 46 | |
Kjansen |
5:052b9936f41f | 47 | /****************************************************************************/ |
Kjansen |
5:052b9936f41f | 48 | /***************************** Function Definitions *************************/ |
Kjansen |
5:052b9936f41f | 49 | /****************************************************************************/ |
mahphalke | 1:dcc17e5a913f | 50 | /*! |
mahphalke | 1:dcc17e5a913f | 51 | * @brief displays the text of a console menu |
mahphalke | 1:dcc17e5a913f | 52 | * |
mahphalke | 1:dcc17e5a913f | 53 | * @details |
mahphalke | 1:dcc17e5a913f | 54 | */ |
mahphalke | 1:dcc17e5a913f | 55 | static void adi_display_console_menu(const console_menu * menu) |
mahphalke | 1:dcc17e5a913f | 56 | { |
mahphalke | 1:dcc17e5a913f | 57 | adi_clear_console(); |
mahphalke | 1:dcc17e5a913f | 58 | |
mahphalke | 1:dcc17e5a913f | 59 | // call headerItem to allow display of other content |
mahphalke | 1:dcc17e5a913f | 60 | if (menu->headerItem != NULL) { |
mahphalke | 1:dcc17e5a913f | 61 | menu->headerItem(); |
mahphalke | 1:dcc17e5a913f | 62 | printf(DIV_STRING EOL); |
mahphalke | 1:dcc17e5a913f | 63 | } |
mahphalke | 1:dcc17e5a913f | 64 | |
mahphalke | 1:dcc17e5a913f | 65 | /* |
mahphalke | 1:dcc17e5a913f | 66 | * Display the menu title and menuItems |
mahphalke | 1:dcc17e5a913f | 67 | * The shortcutKey is used to display '[A]' before the dispayText |
mahphalke | 1:dcc17e5a913f | 68 | */ |
mahphalke | 1:dcc17e5a913f | 69 | printf("\t%s" EOL "\t", menu->title); |
mahphalke | 1:dcc17e5a913f | 70 | // show an underline to distinguish title from item |
mahphalke | 1:dcc17e5a913f | 71 | for (uint8_t i = 0; i < strlen(menu->title); i++) { |
mahphalke | 1:dcc17e5a913f | 72 | putchar('-'); |
mahphalke | 1:dcc17e5a913f | 73 | } |
mahphalke | 1:dcc17e5a913f | 74 | // Extend underline past end of string, and then new line |
mahphalke | 1:dcc17e5a913f | 75 | printf("--" EOL); |
mahphalke | 1:dcc17e5a913f | 76 | |
mahphalke | 1:dcc17e5a913f | 77 | // If the shortcutKey is not unique, first found is used |
mahphalke | 1:dcc17e5a913f | 78 | for (uint8_t i = 0; i < menu->itemCount; i ++) { |
mahphalke | 1:dcc17e5a913f | 79 | if (menu->items[i].shortcutKey == '\00') { |
mahphalke | 1:dcc17e5a913f | 80 | // No shortcut key defined, but display item text if available |
mahphalke | 1:dcc17e5a913f | 81 | printf("\t%s" EOL, menu->items[i].text); |
mahphalke | 1:dcc17e5a913f | 82 | } else { |
mahphalke | 1:dcc17e5a913f | 83 | printf("\t[%c] %s" EOL, toupper(menu->items[i].shortcutKey), |
mahphalke | 1:dcc17e5a913f | 84 | menu->items[i].text); |
mahphalke | 1:dcc17e5a913f | 85 | } |
mahphalke | 1:dcc17e5a913f | 86 | } |
mahphalke | 1:dcc17e5a913f | 87 | if (menu->enableEscapeKey) { |
mahphalke | 1:dcc17e5a913f | 88 | printf(EOL "\t[ESC] Exit Menu" EOL); |
mahphalke | 1:dcc17e5a913f | 89 | } |
mahphalke | 1:dcc17e5a913f | 90 | |
mahphalke | 1:dcc17e5a913f | 91 | printf(EOL "\tPlease make a selection." EOL); |
mahphalke | 1:dcc17e5a913f | 92 | |
mahphalke | 1:dcc17e5a913f | 93 | // call footerItem to allow display of other content |
mahphalke | 1:dcc17e5a913f | 94 | if (menu->footerItem != NULL) { |
mahphalke | 1:dcc17e5a913f | 95 | printf(DIV_STRING EOL); |
mahphalke | 1:dcc17e5a913f | 96 | menu->footerItem(); |
mahphalke | 1:dcc17e5a913f | 97 | } |
mahphalke | 1:dcc17e5a913f | 98 | } |
mahphalke | 1:dcc17e5a913f | 99 | |
mahphalke | 1:dcc17e5a913f | 100 | /*! |
mahphalke | 1:dcc17e5a913f | 101 | * @brief Display a consoleMenu and handle User interaction |
mahphalke | 1:dcc17e5a913f | 102 | * |
mahphalke | 1:dcc17e5a913f | 103 | * @details This displays the menuItems defined by the console menu, and |
Kjansen |
5:052b9936f41f | 104 | * handles all user interaction for the menu. |
Kjansen |
5:052b9936f41f | 105 | * |
Kjansen |
5:052b9936f41f | 106 | * @note The function will return either the item selected or error code |
Kjansen |
5:052b9936f41f | 107 | * from the last action. One at a time. Either define the menu action |
Kjansen |
5:052b9936f41f | 108 | * or sub menu. If both are defined the function would return error. |
Kjansen |
5:052b9936f41f | 109 | * If both menu action and sub menu are defined NULL, then the |
Kjansen |
5:052b9936f41f | 110 | * function will return the item selected |
mahphalke | 1:dcc17e5a913f | 111 | */ |
mahphalke | 1:dcc17e5a913f | 112 | int32_t adi_do_console_menu(const console_menu * menu) |
mahphalke | 1:dcc17e5a913f | 113 | { |
mahphalke | 1:dcc17e5a913f | 114 | int32_t itemSelected = MENU_ESCAPED; |
mahphalke | 1:dcc17e5a913f | 115 | bool enableKeyScan = true; |
Kjansen |
5:052b9936f41f | 116 | int32_t ret = MENU_DONE; |
Kjansen |
5:052b9936f41f | 117 | |
mahphalke | 1:dcc17e5a913f | 118 | adi_display_console_menu(menu); |
mahphalke | 1:dcc17e5a913f | 119 | |
mahphalke | 1:dcc17e5a913f | 120 | /* |
mahphalke | 1:dcc17e5a913f | 121 | * Loop waiting for valid user input. menuItem index is returned if |
mahphalke | 1:dcc17e5a913f | 122 | * user presses a valid menu option. |
mahphalke | 1:dcc17e5a913f | 123 | */ |
mahphalke | 1:dcc17e5a913f | 124 | do { |
mahphalke | 1:dcc17e5a913f | 125 | char keyPressed = toupper(getchar()); |
mahphalke | 1:dcc17e5a913f | 126 | |
mahphalke | 1:dcc17e5a913f | 127 | if (menu->enableEscapeKey) { |
mahphalke | 1:dcc17e5a913f | 128 | if (keyPressed == ESCAPE_KEY_CODE) { |
mahphalke | 1:dcc17e5a913f | 129 | itemSelected = MENU_ESCAPED; |
mahphalke | 1:dcc17e5a913f | 130 | enableKeyScan = false; |
mahphalke | 1:dcc17e5a913f | 131 | break; |
mahphalke | 1:dcc17e5a913f | 132 | } |
mahphalke | 1:dcc17e5a913f | 133 | } |
mahphalke | 1:dcc17e5a913f | 134 | |
mahphalke | 1:dcc17e5a913f | 135 | for (uint8_t i = 0; i < menu->itemCount; i ++) { |
mahphalke | 1:dcc17e5a913f | 136 | if (toupper(menu->items[i].shortcutKey) == keyPressed) { |
mahphalke | 1:dcc17e5a913f | 137 | itemSelected = i; |
mahphalke | 1:dcc17e5a913f | 138 | |
Kjansen |
5:052b9936f41f | 139 | // If the menuAction function pointer is NULL and |
Kjansen |
5:052b9936f41f | 140 | // the sub console menu pointer is not NULL, |
Kjansen |
5:052b9936f41f | 141 | // call the sub console menu. |
Kjansen |
5:052b9936f41f | 142 | if (menu->items[i].action == NULL |
Kjansen |
5:052b9936f41f | 143 | && menu->items[i].submenu != NULL) { |
Kjansen |
5:052b9936f41f | 144 | ret = adi_do_console_menu(menu->items[i].submenu); |
Kjansen |
5:052b9936f41f | 145 | } |
Kjansen |
5:052b9936f41f | 146 | // If the menuAction function pointer is not NULL and sub console menu |
Kjansen |
5:052b9936f41f | 147 | // pointer is NULL, call the action. |
Kjansen |
5:052b9936f41f | 148 | else if (menu->items[i].action != NULL && menu->items[i].submenu == NULL) { |
Kjansen |
5:052b9936f41f | 149 | ret = menu->items[i].action(menu->items[i].id); |
Kjansen |
5:052b9936f41f | 150 | } |
Kjansen |
5:052b9936f41f | 151 | // If both are NULL, then return Not Supported action. |
Kjansen |
5:052b9936f41f | 152 | else if (menu->items[i].action != NULL && menu->items[i].submenu != NULL) { |
Kjansen |
5:052b9936f41f | 153 | ret = -ENOTSUP; |
Kjansen |
5:052b9936f41f | 154 | } |
Kjansen |
5:052b9936f41f | 155 | |
Kjansen |
5:052b9936f41f | 156 | // Store the return value if it is negative. |
Kjansen |
5:052b9936f41f | 157 | if (ret < 0) { |
Kjansen |
5:052b9936f41f | 158 | adi_console_menu_state.last_error_code = ret; |
Kjansen |
5:052b9936f41f | 159 | ret = MENU_CONTINUE; |
Kjansen |
5:052b9936f41f | 160 | } |
Kjansen |
5:052b9936f41f | 161 | |
Kjansen |
5:052b9936f41f | 162 | switch (ret) { |
Kjansen |
5:052b9936f41f | 163 | case MENU_DONE : { |
Kjansen |
5:052b9936f41f | 164 | enableKeyScan = false; |
Kjansen |
5:052b9936f41f | 165 | break; |
Kjansen |
5:052b9936f41f | 166 | } |
Kjansen |
5:052b9936f41f | 167 | case MENU_CONTINUE: |
Kjansen |
5:052b9936f41f | 168 | default: { |
Kjansen |
5:052b9936f41f | 169 | enableKeyScan = true; |
Kjansen |
5:052b9936f41f | 170 | adi_display_console_menu(menu); |
Kjansen |
5:052b9936f41f | 171 | break; |
Kjansen |
5:052b9936f41f | 172 | } |
mahphalke | 1:dcc17e5a913f | 173 | } |
mahphalke | 1:dcc17e5a913f | 174 | break; |
mahphalke | 1:dcc17e5a913f | 175 | } |
mahphalke | 1:dcc17e5a913f | 176 | } |
Kjansen |
5:052b9936f41f | 177 | // If both the action and sub menu are defined NULL, and the item selected |
Kjansen |
5:052b9936f41f | 178 | // is not MENU_ESCAPED, then break the loop to return selected item. |
Kjansen |
5:052b9936f41f | 179 | if(itemSelected != MENU_ESCAPED && |
Kjansen |
5:052b9936f41f | 180 | menu->items[itemSelected].action == NULL && |
Kjansen |
5:052b9936f41f | 181 | menu->items[itemSelected].submenu == NULL) { |
Kjansen |
5:052b9936f41f | 182 | break; |
Kjansen |
5:052b9936f41f | 183 | } |
mahphalke | 1:dcc17e5a913f | 184 | } while (enableKeyScan); |
mahphalke | 1:dcc17e5a913f | 185 | |
mahphalke | 1:dcc17e5a913f | 186 | return (itemSelected); |
mahphalke | 1:dcc17e5a913f | 187 | } |
mahphalke | 1:dcc17e5a913f | 188 | |
mahphalke | 1:dcc17e5a913f | 189 | /*! |
mahphalke | 1:dcc17e5a913f | 190 | * @brief Reads a decimal string from the user |
mahphalke | 1:dcc17e5a913f | 191 | * |
mahphalke | 1:dcc17e5a913f | 192 | * @param input_len max number of character to accept from the user |
mahphalke | 1:dcc17e5a913f | 193 | * |
Kjansen |
5:052b9936f41f | 194 | * @return The integer value entered |
mahphalke | 1:dcc17e5a913f | 195 | * |
mahphalke | 1:dcc17e5a913f | 196 | * @details Allows a user to type in number, echoing back to the user, |
mahphalke | 1:dcc17e5a913f | 197 | * up to input_len chars |
mahphalke | 1:dcc17e5a913f | 198 | * |
mahphalke | 1:dcc17e5a913f | 199 | * @note Only positive integer numbers are supported currently |
mahphalke | 1:dcc17e5a913f | 200 | */ |
mahphalke | 1:dcc17e5a913f | 201 | int32_t adi_get_decimal_int(uint8_t input_len) |
mahphalke | 1:dcc17e5a913f | 202 | { |
mahphalke | 1:dcc17e5a913f | 203 | char buf[20] = {0}; |
mahphalke | 1:dcc17e5a913f | 204 | uint8_t buf_index = 0; |
mahphalke | 1:dcc17e5a913f | 205 | char ch; |
mahphalke | 1:dcc17e5a913f | 206 | bool loop = true; |
mahphalke | 1:dcc17e5a913f | 207 | |
mahphalke | 1:dcc17e5a913f | 208 | assert(input_len < 19); |
mahphalke | 1:dcc17e5a913f | 209 | |
mahphalke | 1:dcc17e5a913f | 210 | do { |
mahphalke | 1:dcc17e5a913f | 211 | ch = getchar(); |
mahphalke | 1:dcc17e5a913f | 212 | if (isdigit(ch) && buf_index < (input_len)) { |
mahphalke | 1:dcc17e5a913f | 213 | // echo and store it as buf not full |
mahphalke | 1:dcc17e5a913f | 214 | buf[buf_index++] = ch; |
mahphalke | 1:dcc17e5a913f | 215 | putchar(ch); |
mahphalke | 1:dcc17e5a913f | 216 | } |
mahphalke | 1:dcc17e5a913f | 217 | if ((ch == '\x7F') && (buf_index > 0)) { |
mahphalke | 1:dcc17e5a913f | 218 | //backspace and at least 1 char in buffer |
mahphalke | 1:dcc17e5a913f | 219 | buf[buf_index--] = '\x00'; |
mahphalke | 1:dcc17e5a913f | 220 | putchar(ch); |
mahphalke | 1:dcc17e5a913f | 221 | } |
mahphalke | 1:dcc17e5a913f | 222 | if ((ch == '\x0D') || (ch == '\x0A')) { |
mahphalke | 1:dcc17e5a913f | 223 | // return key pressed, all done, null terminate string |
mahphalke | 1:dcc17e5a913f | 224 | buf[buf_index] = '\x00'; |
mahphalke | 1:dcc17e5a913f | 225 | loop = false; |
mahphalke | 1:dcc17e5a913f | 226 | } |
mahphalke | 1:dcc17e5a913f | 227 | } while(loop); |
mahphalke | 1:dcc17e5a913f | 228 | |
mahphalke | 1:dcc17e5a913f | 229 | return atoi(buf); |
mahphalke | 1:dcc17e5a913f | 230 | } |
mahphalke | 1:dcc17e5a913f | 231 | |
mahphalke | 1:dcc17e5a913f | 232 | /*! |
mahphalke | 1:dcc17e5a913f | 233 | * @brief Reads a hexadecimal number from the user |
mahphalke | 1:dcc17e5a913f | 234 | * |
mahphalke | 1:dcc17e5a913f | 235 | * @param input_len max number of character to accept from the user |
mahphalke | 1:dcc17e5a913f | 236 | * |
mahphalke | 1:dcc17e5a913f | 237 | * @return The integer value entered |
mahphalke | 1:dcc17e5a913f | 238 | * |
mahphalke | 1:dcc17e5a913f | 239 | * @details Allows a user to type in a hexnumber, echoing back to the user, |
mahphalke | 1:dcc17e5a913f | 240 | * up to input_len chars |
mahphalke | 1:dcc17e5a913f | 241 | */ |
mahphalke | 1:dcc17e5a913f | 242 | uint32_t adi_get_hex_integer(uint8_t input_len) |
mahphalke | 1:dcc17e5a913f | 243 | { |
mahphalke | 1:dcc17e5a913f | 244 | char buf[9] = {0}; |
mahphalke | 1:dcc17e5a913f | 245 | uint8_t buf_index = 0; |
mahphalke | 1:dcc17e5a913f | 246 | char ch; |
mahphalke | 1:dcc17e5a913f | 247 | bool loop = true; |
mahphalke | 1:dcc17e5a913f | 248 | |
mahphalke | 1:dcc17e5a913f | 249 | assert(input_len < 8); |
mahphalke | 1:dcc17e5a913f | 250 | |
mahphalke | 1:dcc17e5a913f | 251 | do { |
mahphalke | 1:dcc17e5a913f | 252 | ch = getchar(); |
mahphalke | 1:dcc17e5a913f | 253 | if (isxdigit(ch) && buf_index < (input_len)) { |
mahphalke | 1:dcc17e5a913f | 254 | // echo and store it as buf not full |
mahphalke | 1:dcc17e5a913f | 255 | buf[buf_index++] = ch; |
mahphalke | 1:dcc17e5a913f | 256 | putchar(ch); |
mahphalke | 1:dcc17e5a913f | 257 | } |
mahphalke | 1:dcc17e5a913f | 258 | if ((ch == '\x7F') && (buf_index > 0)) { |
mahphalke | 1:dcc17e5a913f | 259 | //backspace and at least 1 char in buffer |
mahphalke | 1:dcc17e5a913f | 260 | buf[buf_index--] = '\x00'; |
mahphalke | 1:dcc17e5a913f | 261 | putchar(ch); |
mahphalke | 1:dcc17e5a913f | 262 | } |
mahphalke | 1:dcc17e5a913f | 263 | if ((ch == '\x0D') || (ch == '\x0A')) { |
mahphalke | 1:dcc17e5a913f | 264 | // return key pressed, all done, null terminate string |
mahphalke | 1:dcc17e5a913f | 265 | buf[buf_index] = '\x00'; |
mahphalke | 1:dcc17e5a913f | 266 | loop = false; |
mahphalke | 1:dcc17e5a913f | 267 | } |
mahphalke | 1:dcc17e5a913f | 268 | } while(loop); |
mahphalke | 1:dcc17e5a913f | 269 | |
mahphalke | 1:dcc17e5a913f | 270 | return strtol(buf, NULL, 16); |
mahphalke | 1:dcc17e5a913f | 271 | } |
mahphalke | 1:dcc17e5a913f | 272 | |
mahphalke | 1:dcc17e5a913f | 273 | /*! |
mahphalke | 1:dcc17e5a913f | 274 | * @brief Reads a floating string from the user |
mahphalke | 1:dcc17e5a913f | 275 | * |
mahphalke | 1:dcc17e5a913f | 276 | * @param input_len max number of character to accept from the user |
mahphalke | 1:dcc17e5a913f | 277 | * |
Kjansen |
5:052b9936f41f | 278 | * @return The float value entered |
mahphalke | 1:dcc17e5a913f | 279 | * |
mahphalke | 1:dcc17e5a913f | 280 | * @details Allows a user to type in number, echoing back to the user, |
mahphalke | 1:dcc17e5a913f | 281 | * up to input_len chars |
mahphalke | 1:dcc17e5a913f | 282 | * |
mahphalke | 1:dcc17e5a913f | 283 | * @note Only positive floating point numbers are supported currently |
mahphalke | 1:dcc17e5a913f | 284 | */ |
mahphalke | 1:dcc17e5a913f | 285 | float adi_get_decimal_float(uint8_t input_len) |
mahphalke | 1:dcc17e5a913f | 286 | { |
mahphalke | 1:dcc17e5a913f | 287 | char buf[20] = { 0 }; |
mahphalke | 1:dcc17e5a913f | 288 | uint8_t buf_index = 0; |
mahphalke | 1:dcc17e5a913f | 289 | char ch; |
mahphalke | 1:dcc17e5a913f | 290 | bool loop = true; |
mahphalke | 1:dcc17e5a913f | 291 | |
mahphalke | 1:dcc17e5a913f | 292 | assert(input_len < 19); |
mahphalke | 1:dcc17e5a913f | 293 | |
mahphalke | 1:dcc17e5a913f | 294 | do { |
mahphalke | 1:dcc17e5a913f | 295 | ch = getchar(); |
mahphalke | 1:dcc17e5a913f | 296 | if ((isdigit(ch) || (ch == '.')) && buf_index < (input_len)) { |
mahphalke | 1:dcc17e5a913f | 297 | // echo and store it as buf not full |
mahphalke | 1:dcc17e5a913f | 298 | buf[buf_index++] = ch; |
mahphalke | 1:dcc17e5a913f | 299 | putchar(ch); |
mahphalke | 1:dcc17e5a913f | 300 | } |
mahphalke | 1:dcc17e5a913f | 301 | if ((ch == '\x7F') && (buf_index > 0)) { |
mahphalke | 1:dcc17e5a913f | 302 | //backspace and at least 1 char in buffer |
mahphalke | 1:dcc17e5a913f | 303 | buf[buf_index--] = '\x00'; |
mahphalke | 1:dcc17e5a913f | 304 | putchar(ch); |
mahphalke | 1:dcc17e5a913f | 305 | } |
mahphalke | 1:dcc17e5a913f | 306 | if ((ch == '\x0D') || (ch == '\x0A')) { |
mahphalke | 1:dcc17e5a913f | 307 | // return key pressed, all done, null terminate string |
mahphalke | 1:dcc17e5a913f | 308 | buf[buf_index] = '\x00'; |
mahphalke | 1:dcc17e5a913f | 309 | loop = false; |
mahphalke | 1:dcc17e5a913f | 310 | } |
mahphalke | 1:dcc17e5a913f | 311 | } while (loop); |
mahphalke | 1:dcc17e5a913f | 312 | |
mahphalke | 1:dcc17e5a913f | 313 | return atof(buf); |
mahphalke | 1:dcc17e5a913f | 314 | } |
mahphalke | 1:dcc17e5a913f | 315 | |
Kjansen |
5:052b9936f41f | 316 | /** |
pmallick | 6:34034065d24b | 317 | * @brief Handles the integer type input from the user by displaying |
Kjansen |
5:052b9936f41f | 318 | * the menu message and provides a set number of |
Kjansen |
5:052b9936f41f | 319 | * input attempts for the user. |
Kjansen |
5:052b9936f41f | 320 | * @param menu_prompt[in] - User specified prompt. |
Kjansen |
5:052b9936f41f | 321 | * @param min_val[in] - minimum input value. |
Kjansen |
5:052b9936f41f | 322 | * @param max_val[in] - maximum input value. |
Kjansen |
5:052b9936f41f | 323 | * @param input_val[in, out] - User provided input value. |
pmallick | 6:34034065d24b | 324 | * @param input_len[in] - User provided input length. |
pmallick | 6:34034065d24b | 325 | * @param max_attempts[in] - Maximum number of input attempts. |
Kjansen |
5:052b9936f41f | 326 | * @param clear_lines[in] - lines to clear in case of |
Kjansen |
5:052b9936f41f | 327 | invalid input. |
Kjansen |
5:052b9936f41f | 328 | * @return SUCCESS in case success. otherwise FAILURE |
Kjansen |
5:052b9936f41f | 329 | */ |
pmallick | 6:34034065d24b | 330 | int32_t adi_handle_user_input_integer(const char* menu_prompt, |
Kjansen |
5:052b9936f41f | 331 | uint16_t min_val, |
Kjansen |
5:052b9936f41f | 332 | uint16_t max_val, |
Kjansen |
5:052b9936f41f | 333 | uint16_t *input_val, |
pmallick | 6:34034065d24b | 334 | uint8_t input_len, |
Kjansen |
5:052b9936f41f | 335 | uint8_t max_attempts, |
Kjansen |
5:052b9936f41f | 336 | uint8_t clear_lines) |
Kjansen |
5:052b9936f41f | 337 | { |
Kjansen |
5:052b9936f41f | 338 | uint8_t count = 0; |
Kjansen |
5:052b9936f41f | 339 | |
Kjansen |
5:052b9936f41f | 340 | if (menu_prompt == NULL || input_val == NULL) { |
Kjansen |
5:052b9936f41f | 341 | return FAILURE; |
Kjansen |
5:052b9936f41f | 342 | } |
Kjansen |
5:052b9936f41f | 343 | |
Kjansen |
5:052b9936f41f | 344 | do { |
Kjansen |
5:052b9936f41f | 345 | /* Gets the input from the user and allows |
Kjansen |
5:052b9936f41f | 346 | * reattempts in-case of incorrect input */ |
Kjansen |
5:052b9936f41f | 347 | printf("%s (%d - %d): ", menu_prompt, min_val, max_val); |
pmallick | 6:34034065d24b | 348 | *input_val = (uint16_t)adi_get_decimal_int(input_len); |
Kjansen |
5:052b9936f41f | 349 | |
Kjansen |
5:052b9936f41f | 350 | if ((*input_val >= min_val) && (*input_val <= max_val)) { |
Kjansen |
5:052b9936f41f | 351 | // break out of the loop in-case of a correct input |
Kjansen |
5:052b9936f41f | 352 | break; |
Kjansen |
5:052b9936f41f | 353 | } else { |
Kjansen |
5:052b9936f41f | 354 | if (count == max_attempts) { |
Kjansen |
5:052b9936f41f | 355 | printf(EOL "Maximum try limit exceeded" EOL); |
Kjansen |
5:052b9936f41f | 356 | adi_press_any_key_to_continue(); |
Kjansen |
5:052b9936f41f | 357 | return FAILURE; |
Kjansen |
5:052b9936f41f | 358 | } |
Kjansen |
5:052b9936f41f | 359 | |
Kjansen |
5:052b9936f41f | 360 | printf(EOL "Please enter a valid selection" EOL); |
Kjansen |
5:052b9936f41f | 361 | adi_press_any_key_to_continue(); |
Kjansen |
5:052b9936f41f | 362 | /* Moves up the cursor by specified lines and |
Kjansen |
5:052b9936f41f | 363 | * clears the lines below it */ |
Kjansen |
5:052b9936f41f | 364 | for (uint8_t i = 0; i < clear_lines; i++) { |
Kjansen |
5:052b9936f41f | 365 | printf(VT100_CLEAR_CURRENT_LINE); |
Kjansen |
5:052b9936f41f | 366 | printf(VT100_MOVE_UP_N_LINES, 1); |
Kjansen |
5:052b9936f41f | 367 | } |
Kjansen |
5:052b9936f41f | 368 | } |
Kjansen |
5:052b9936f41f | 369 | } while (++count <= max_attempts); |
Kjansen |
5:052b9936f41f | 370 | |
Kjansen |
5:052b9936f41f | 371 | return SUCCESS; |
Kjansen |
5:052b9936f41f | 372 | } |
mahphalke | 1:dcc17e5a913f | 373 | |
pmallick | 6:34034065d24b | 374 | /** |
pmallick | 6:34034065d24b | 375 | * @brief Handles the float type input from the user by displaying |
pmallick | 6:34034065d24b | 376 | * the menu message and provides a set number of |
pmallick | 6:34034065d24b | 377 | * input attempts for the user. |
pmallick | 6:34034065d24b | 378 | * @param menu_prompt[in] - User specified prompt. |
pmallick | 6:34034065d24b | 379 | * @param min_val[in] - minimum input value. |
pmallick | 6:34034065d24b | 380 | * @param max_val[in] - maximum input value. |
pmallick | 6:34034065d24b | 381 | * @param input_val[in, out] - User provided input value. |
pmallick | 6:34034065d24b | 382 | * @param input_len[in] - User provided input length. |
pmallick | 6:34034065d24b | 383 | * @param max_attempts[in] - Maximum number of input attempts. |
pmallick | 6:34034065d24b | 384 | * @param clear_lines[in] - lines to clear in case of |
pmallick | 6:34034065d24b | 385 | invalid input. |
pmallick | 6:34034065d24b | 386 | * @return SUCCESS in case success. otherwise FAILURE |
pmallick | 6:34034065d24b | 387 | */ |
pmallick | 6:34034065d24b | 388 | int32_t adi_handle_user_input_float(const char* menu_prompt, |
pmallick | 6:34034065d24b | 389 | float min_val, |
pmallick | 6:34034065d24b | 390 | float max_val, |
pmallick | 6:34034065d24b | 391 | float *input_val, |
pmallick | 6:34034065d24b | 392 | uint8_t input_len, |
pmallick | 6:34034065d24b | 393 | uint8_t max_attempts, |
pmallick | 6:34034065d24b | 394 | uint8_t clear_lines) |
pmallick | 6:34034065d24b | 395 | { |
pmallick | 6:34034065d24b | 396 | uint8_t count = 0; |
pmallick | 6:34034065d24b | 397 | |
pmallick | 6:34034065d24b | 398 | if (menu_prompt == NULL || input_val == NULL) { |
pmallick | 6:34034065d24b | 399 | return FAILURE; |
pmallick | 6:34034065d24b | 400 | } |
pmallick | 6:34034065d24b | 401 | |
pmallick | 6:34034065d24b | 402 | do { |
pmallick | 6:34034065d24b | 403 | /* Gets the input from the user and allows |
pmallick | 6:34034065d24b | 404 | * reattempts in-case of incorrect input */ |
pmallick | 6:34034065d24b | 405 | printf("%s (%0.3f - %0.3f): ", menu_prompt, min_val, max_val); |
pmallick | 6:34034065d24b | 406 | *input_val = adi_get_decimal_float(input_len); |
pmallick | 6:34034065d24b | 407 | |
pmallick | 6:34034065d24b | 408 | if ((*input_val >= min_val) && (*input_val <= max_val)) { |
pmallick | 6:34034065d24b | 409 | // break out of the loop in-case of a correct input |
pmallick | 6:34034065d24b | 410 | break; |
pmallick | 6:34034065d24b | 411 | } |
pmallick | 6:34034065d24b | 412 | else { |
pmallick | 6:34034065d24b | 413 | if (count == max_attempts) { |
pmallick | 6:34034065d24b | 414 | printf(EOL "Maximum try limit exceeded" EOL); |
pmallick | 6:34034065d24b | 415 | adi_press_any_key_to_continue(); |
pmallick | 6:34034065d24b | 416 | return FAILURE; |
pmallick | 6:34034065d24b | 417 | } |
pmallick | 6:34034065d24b | 418 | |
pmallick | 6:34034065d24b | 419 | printf(EOL "Please enter a valid selection" EOL); |
pmallick | 6:34034065d24b | 420 | adi_press_any_key_to_continue(); |
pmallick | 6:34034065d24b | 421 | /* Moves up the cursor by specified lines and |
pmallick | 6:34034065d24b | 422 | * clears the lines below it */ |
pmallick | 6:34034065d24b | 423 | for (uint8_t i = 0; i < clear_lines; i++) { |
pmallick | 6:34034065d24b | 424 | printf(VT100_CLEAR_CURRENT_LINE); |
pmallick | 6:34034065d24b | 425 | printf(VT100_MOVE_UP_N_LINES, 1); |
pmallick | 6:34034065d24b | 426 | } |
pmallick | 6:34034065d24b | 427 | } |
pmallick | 6:34034065d24b | 428 | } while (++count <= max_attempts); |
pmallick | 6:34034065d24b | 429 | |
pmallick | 6:34034065d24b | 430 | return SUCCESS; |
pmallick | 6:34034065d24b | 431 | } |
pmallick | 6:34034065d24b | 432 | |
mahphalke | 1:dcc17e5a913f | 433 | /*! |
mahphalke | 1:dcc17e5a913f | 434 | * @brief Clears the console terminal |
mahphalke | 1:dcc17e5a913f | 435 | * |
mahphalke | 1:dcc17e5a913f | 436 | * @details Clears the console terminal using VT100 escape code, or can be changed to |
mahphalke | 1:dcc17e5a913f | 437 | * output blank lines if serial link doesn't support VT100. |
mahphalke | 1:dcc17e5a913f | 438 | */ |
mahphalke | 1:dcc17e5a913f | 439 | void adi_clear_console(void) |
mahphalke | 1:dcc17e5a913f | 440 | { |
mahphalke | 1:dcc17e5a913f | 441 | /* |
mahphalke | 1:dcc17e5a913f | 442 | * clear console and move cursor to home location, followed by move to home location. |
mahphalke | 1:dcc17e5a913f | 443 | * Dedicated call to move home is because sometimes first move home doesn't work |
mahphalke | 1:dcc17e5a913f | 444 | * \r\n required to flush the uart buffer. |
mahphalke | 1:dcc17e5a913f | 445 | */ |
mahphalke |
4:ced4fa6875ed | 446 | printf(VT100_CLEAR_CONSOLE VT100_MOVE_TO_HOME EOL); |
mahphalke | 1:dcc17e5a913f | 447 | |
mahphalke | 1:dcc17e5a913f | 448 | /* |
mahphalke | 1:dcc17e5a913f | 449 | * if VT100 is not supported, this can be enabled instead, but menu display may not work well |
mahphalke | 1:dcc17e5a913f | 450 | */ |
mahphalke | 1:dcc17e5a913f | 451 | // for (uint8_t = 0; i < 100; i++) |
mahphalke | 1:dcc17e5a913f | 452 | // printf("\r\n\r"); |
mahphalke | 1:dcc17e5a913f | 453 | } |
mahphalke | 1:dcc17e5a913f | 454 | |
Kjansen |
5:052b9936f41f | 455 | /*! |
Kjansen |
5:052b9936f41f | 456 | * @brief Clears the error code from the last menu |
Kjansen |
5:052b9936f41f | 457 | * |
Kjansen |
5:052b9936f41f | 458 | * @details |
Kjansen |
5:052b9936f41f | 459 | */ |
Kjansen |
5:052b9936f41f | 460 | void adi_clear_last_menu_error(void) |
Kjansen |
5:052b9936f41f | 461 | { |
Kjansen |
5:052b9936f41f | 462 | adi_console_menu_state.last_error_code = SUCCESS; |
Kjansen |
5:052b9936f41f | 463 | } |
Kjansen |
5:052b9936f41f | 464 | |
Kjansen |
5:052b9936f41f | 465 | /*! |
Kjansen |
5:052b9936f41f | 466 | * @brief Returns the error code from the last menu |
Kjansen |
5:052b9936f41f | 467 | * |
Kjansen |
5:052b9936f41f | 468 | * @return The error code value |
Kjansen |
5:052b9936f41f | 469 | */ |
Kjansen |
5:052b9936f41f | 470 | int32_t adi_get_last_menu_error(void) |
Kjansen |
5:052b9936f41f | 471 | { |
Kjansen |
5:052b9936f41f | 472 | return adi_console_menu_state.last_error_code; |
Kjansen |
5:052b9936f41f | 473 | } |
mahphalke | 1:dcc17e5a913f | 474 | |
mahphalke | 1:dcc17e5a913f | 475 | /*! |
mahphalke | 1:dcc17e5a913f | 476 | * @brief waits for any key to be pressed, and displays a prompt to the user |
mahphalke | 1:dcc17e5a913f | 477 | * |
mahphalke | 1:dcc17e5a913f | 478 | * @details |
mahphalke | 1:dcc17e5a913f | 479 | */ |
mahphalke | 1:dcc17e5a913f | 480 | void adi_press_any_key_to_continue(void) |
mahphalke | 1:dcc17e5a913f | 481 | { |
mahphalke | 1:dcc17e5a913f | 482 | printf("\r\nPress any key to continue...\r\n"); |
mahphalke | 1:dcc17e5a913f | 483 | getchar(); |
mahphalke | 1:dcc17e5a913f | 484 | } |