Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
adi_console_menu.c
00001 /*! 00002 ***************************************************************************** 00003 @file: adi_console_menu.c 00004 00005 @brief: A simple console menu manager handler 00006 00007 @details: A way to define using arrays of structs a set of menus that can 00008 be displayed to a user, easily, with all user interaction handled 00009 by the library, leaving only the implementation of the menu actions 00010 to be done by the library user. 00011 ----------------------------------------------------------------------------- 00012 Copyright (c) 2019, 2020 Analog Devices, Inc. 00013 All rights reserved. 00014 00015 This software is proprietary to Analog Devices, Inc. and its licensors. 00016 By using this software you agree to the terms of the associated 00017 Analog Devices Software License Agreement. 00018 00019 *****************************************************************************/ 00020 00021 #include <stdio.h> 00022 #include <stdlib.h> 00023 #include <ctype.h> 00024 #include <string.h> 00025 #include <stdbool.h> 00026 #include <assert.h> 00027 00028 #include "adi_console_menu.h" 00029 00030 00031 #define DIV_STRING "\t==================================================" 00032 00033 /*! 00034 * @brief displays the text of a console menu 00035 * 00036 * @details 00037 */ 00038 static void adi_display_console_menu(const console_menu * menu) 00039 { 00040 adi_clear_console(); 00041 00042 // call headerItem to allow display of other content 00043 if (menu->headerItem != NULL) { 00044 menu->headerItem(); 00045 printf(DIV_STRING EOL); 00046 } 00047 00048 /* 00049 * Display the menu title and menuItems 00050 * The shortcutKey is used to display '[A]' before the dispayText 00051 */ 00052 printf("\t%s" EOL "\t", menu->title); 00053 // show an underline to distinguish title from item 00054 for (uint8_t i = 0; i < strlen(menu->title); i++) { 00055 putchar('-'); 00056 } 00057 // Extend underline past end of string, and then new line 00058 printf("--" EOL); 00059 00060 // If the shortcutKey is not unique, first found is used 00061 for (uint8_t i = 0; i < menu->itemCount; i ++) { 00062 if (menu->items[i].shortcutKey == '\00') { 00063 // No shortcut key defined, but display item text if available 00064 printf("\t%s" EOL, menu->items[i].text); 00065 } else { 00066 printf("\t[%c] %s" EOL, toupper(menu->items[i].shortcutKey), 00067 menu->items[i].text); 00068 } 00069 } 00070 if (menu->enableEscapeKey) { 00071 printf(EOL "\t[ESC] Exit Menu" EOL); 00072 } 00073 00074 printf(EOL "\tPlease make a selection." EOL); 00075 00076 // call footerItem to allow display of other content 00077 if (menu->footerItem != NULL) { 00078 printf(DIV_STRING EOL); 00079 menu->footerItem(); 00080 } 00081 } 00082 00083 00084 /*! 00085 * @brief Display a consoleMenu and handle User interaction 00086 * 00087 * @details This displays the menuItems defined by the console menu, and 00088 * handles all user interaction for the menu. 00089 */ 00090 int32_t adi_do_console_menu(const console_menu * menu) 00091 { 00092 int32_t itemSelected = MENU_ESCAPED; 00093 bool enableKeyScan = true; 00094 00095 adi_display_console_menu(menu); 00096 00097 /* 00098 * Loop waiting for valid user input. menuItem index is returned if 00099 * user presses a valid menu option. 00100 */ 00101 do { 00102 char keyPressed = toupper(getchar()); 00103 00104 if (menu->enableEscapeKey) { 00105 if (keyPressed == ESCAPE_KEY_CODE) { 00106 itemSelected = MENU_ESCAPED; 00107 enableKeyScan = false; 00108 break; 00109 } 00110 } 00111 00112 for (uint8_t i = 0; i < menu->itemCount; i ++) { 00113 if (toupper(menu->items[i].shortcutKey) == keyPressed) { 00114 itemSelected = i; 00115 00116 // If the menuAction function pointer is not NULL, call the action 00117 if (menu->items[i].action != NULL) { 00118 switch (menu->items[i].action(menu->items[i].id)) { 00119 case MENU_DONE: { 00120 enableKeyScan = false; 00121 break; 00122 } 00123 case MENU_CONTINUE: 00124 default: { 00125 enableKeyScan = true; 00126 adi_display_console_menu(menu); 00127 break; 00128 } 00129 } 00130 } 00131 break; 00132 } 00133 } 00134 } while (enableKeyScan); 00135 00136 return (itemSelected); 00137 } 00138 00139 /*! 00140 * @brief Reads a decimal string from the user 00141 * 00142 * @param input_len max number of character to accept from the user 00143 * 00144 * @return The integer value entered 00145 * 00146 * @details Allows a user to type in number, echoing back to the user, 00147 * up to input_len chars 00148 * 00149 * @note Only positive integer numbers are supported currently 00150 */ 00151 int32_t adi_get_decimal_int(uint8_t input_len) 00152 { 00153 char buf[20] = {0}; 00154 uint8_t buf_index = 0; 00155 char ch; 00156 bool loop = true; 00157 00158 assert(input_len < 19); 00159 00160 do { 00161 ch = getchar(); 00162 if (isdigit(ch) && buf_index < (input_len)) { 00163 // echo and store it as buf not full 00164 buf[buf_index++] = ch; 00165 putchar(ch); 00166 } 00167 if ((ch == '\x7F') && (buf_index > 0)) { 00168 //backspace and at least 1 char in buffer 00169 buf[buf_index--] = '\x00'; 00170 putchar(ch); 00171 } 00172 if ((ch == '\x0D') || (ch == '\x0A')) { 00173 // return key pressed, all done, null terminate string 00174 buf[buf_index] = '\x00'; 00175 loop = false; 00176 } 00177 } while(loop); 00178 00179 return atoi(buf); 00180 } 00181 00182 /*! 00183 * @brief Reads a hexadecimal number from the user 00184 * 00185 * @param input_len max number of character to accept from the user 00186 * 00187 * @return The integer value entered 00188 * 00189 * @details Allows a user to type in a hexnumber, echoing back to the user, 00190 * up to input_len chars 00191 */ 00192 uint32_t adi_get_hex_integer(uint8_t input_len) 00193 { 00194 char buf[9] = {0}; 00195 uint8_t buf_index = 0; 00196 char ch; 00197 bool loop = true; 00198 00199 assert(input_len < 8); 00200 00201 do { 00202 ch = getchar(); 00203 if (isxdigit(ch) && buf_index < (input_len)) { 00204 // echo and store it as buf not full 00205 buf[buf_index++] = ch; 00206 putchar(ch); 00207 } 00208 if ((ch == '\x7F') && (buf_index > 0)) { 00209 //backspace and at least 1 char in buffer 00210 buf[buf_index--] = '\x00'; 00211 putchar(ch); 00212 } 00213 if ((ch == '\x0D') || (ch == '\x0A')) { 00214 // return key pressed, all done, null terminate string 00215 buf[buf_index] = '\x00'; 00216 loop = false; 00217 } 00218 } while(loop); 00219 00220 return strtol(buf, NULL, 16); 00221 } 00222 00223 00224 /*! 00225 * @brief Reads a floating string from the user 00226 * 00227 * @param input_len max number of character to accept from the user 00228 * 00229 * @return The float value entered 00230 * 00231 * @details Allows a user to type in number, echoing back to the user, 00232 * up to input_len chars 00233 * 00234 * @note Only positive floating point numbers are supported currently 00235 */ 00236 float adi_get_decimal_float(uint8_t input_len) 00237 { 00238 char buf[20] = { 0 }; 00239 uint8_t buf_index = 0; 00240 char ch; 00241 bool loop = true; 00242 00243 assert(input_len < 19); 00244 00245 do { 00246 ch = getchar(); 00247 if ((isdigit(ch) || (ch == '.')) && buf_index < (input_len)) { 00248 // echo and store it as buf not full 00249 buf[buf_index++] = ch; 00250 putchar(ch); 00251 } 00252 if ((ch == '\x7F') && (buf_index > 0)) { 00253 //backspace and at least 1 char in buffer 00254 buf[buf_index--] = '\x00'; 00255 putchar(ch); 00256 } 00257 if ((ch == '\x0D') || (ch == '\x0A')) { 00258 // return key pressed, all done, null terminate string 00259 buf[buf_index] = '\x00'; 00260 loop = false; 00261 } 00262 } while (loop); 00263 00264 return atof(buf); 00265 } 00266 00267 00268 /*! 00269 * @brief Clears the console terminal 00270 * 00271 * @details Clears the console terminal using VT100 escape code, or can be changed to 00272 * output blank lines if serial link doesn't support VT100. 00273 */ 00274 void adi_clear_console(void) 00275 { 00276 /* 00277 * clear console and move cursor to home location, followed by move to home location. 00278 * Dedicated call to move home is because sometimes first move home doesn't work 00279 * \r\n required to flush the uart buffer. 00280 */ 00281 printf("\x1B[2J\x1B[H\r\n"); 00282 00283 /* 00284 * if VT100 is not supported, this can be enabled instead, but menu display may not work well 00285 */ 00286 // for (uint8_t = 0; i < 100; i++) 00287 // printf("\r\n\r"); 00288 } 00289 00290 00291 /*! 00292 * @brief waits for any key to be pressed, and displays a prompt to the user 00293 * 00294 * @details 00295 */ 00296 void adi_press_any_key_to_continue(void) 00297 { 00298 printf("\r\nPress any key to continue...\r\n"); 00299 getchar(); 00300 }
Generated on Wed Jul 20 2022 16:03:27 by
1.7.2