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