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.
Revision 0:694155408133, committed 2020-03-29
- Comitter:
- skyscraper
- Date:
- Sun Mar 29 16:00:36 2020 +0000
- Commit message:
- Initial commit
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Sun Mar 29 16:00:36 2020 +0000
@@ -0,0 +1,42 @@
+
+
+#include "userMenu.h"
+#include <iostream>
+
+template <int N>
+int8_t
+menu(uint8_t argc, const Menu::arg *argv)
+{
+ std::cout << " This is menu " << N << "\n";
+ if ( argc > 1) {
+ std::cout << "args = " ;
+ for ( uint8_t i = 1U; i < argc; ++i){
+ if ( i > 1){
+ std::cout << ", ";
+ }
+ std::cout << argv[i].str ;
+ }
+ std::cout << '\n';
+ }
+ return 1;
+}
+
+constexpr struct Menu::command mainMenuCommands[] = {
+ {"menu1", menu<1>},
+ {"menu2", menu<2>},
+ {"menu3", menu<3>}
+};
+
+MENU(main_menu, "User_menu", mainMenuCommands);
+
+void user_menu()
+{
+ main_menu.run();
+}
+
+
+int main()
+{
+
+ user_menu();
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-os.lib Sun Mar 29 16:00:36 2020 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/mbed-os.git/#83926138aae9cd77e8c74ec8678b38417bebaa3d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/userMenu.cpp Sun Mar 29 16:00:36 2020 +0000
@@ -0,0 +1,168 @@
+
+
+//
+/// Simple commandline menu system.
+/// Originally from https://code.google.com/archive/p/ardu-imu/downloads
+
+
+#include <ctype.h>
+#include <string.h>
+
+#include <iostream>
+
+#include "userMenu.h"
+
+// statics
+char Menu::_inbuf[commandlineLenMax];
+Menu::arg Menu::_argv[argsLenMax+ 1];
+
+// constructor
+Menu::Menu(const char*prompt, const Menu::command *commands, uint8_t entries, preprompt ppfunc) :
+ _prompt(prompt),
+ _commands(commands),
+ _entries(entries),
+ _ppfunc(ppfunc)
+{
+}
+namespace {
+ // could be a eeprom option
+ // If terminal at PC end already echoes then don't echo here
+ static constexpr bool serial_echo = false;
+}
+
+// run the menu
+void
+Menu::run(void)
+{
+ for (;;) {
+ if(_ppfunc != nullptr){
+ // run the included pre-prompt function
+ if ( !_ppfunc()){
+ return;
+ }
+ }
+ // Serial.print(_prompt);
+ // Serial.print(']');
+ std::cout << _prompt << ']';
+ for (uint8_t len = 0,done = false; done == false;) {
+ // int c = -1;// = Serial.read();
+ int c = std::cin.get();
+ switch(c) {
+ case -1:
+ //eof
+ break;
+ case '\r':
+ // carriage return -> process command
+ _inbuf[len] = '\0';
+ if ( serial_echo){
+ // Serial.write('\r');
+ // Serial.write('\n');
+ std::cout << '\r';
+ }
+ std::cout << '\n';
+ done = true;
+ break;
+ case '\b':
+ // backspace
+ if (len > 0) {
+ len--;
+ if ( serial_echo){
+ // Serial.write('\b');
+ std::cout << '\b';
+ }
+ // Serial.write(' ');
+ // Serial.write('\b');
+ std::cout << " \b";
+ }
+ break;
+ default:
+ // printable character
+ if (isprint(c) && (len < (commandlineLenMax - 1))) {
+ _inbuf[len++] = c;
+ if(serial_echo){
+ // Serial.write((char)c);
+ std::cout << static_cast<char>(c);
+ }
+ }
+ break;
+ }
+ }
+ // split the input line into tokens
+ uint8_t argc = 0;
+ char *s = nullptr;
+ _argv[argc++].str = strtok_r(_inbuf, " ", &s);
+ // XXX should an empty line by itself back out of the current menu?
+ for ( ;argc <= argsLenMax; ++argc) {
+ _argv[argc].str = strtok_r(nullptr, " ", &s);
+ if (_argv[argc].str != nullptr){
+ _argv[argc].i = atol(_argv[argc].str);
+ _argv[argc].f = atof(_argv[argc].str); // calls strtod, > 700B !
+ }else{
+ break;
+ }
+ }
+
+ if (_argv[0].str == nullptr) {
+ continue;
+ }
+
+ // populate arguments that have not been specified with "" and 0
+ // this is safer than NULL in the case where commands may look
+ // without testing argc
+ for(int i = argc; i <= argsLenMax;++i){
+ _argv[i].str = nullptr;
+ _argv[i].i = 0;
+ _argv[i].f = 0;
+ }
+
+ bool cmd_found = false;
+ // look for a command matching the first word (note that it may be empty)
+ int i = 0;
+ for (; i < _entries; ++i) {
+ if (!strcmp(_argv[0].str, _commands[i].command)) {
+ int8_t ret = _call(i, argc);
+ cmd_found=true;
+ if (-2 == ret){
+ return;
+ }
+ break;
+ }
+ }
+
+ // implicit commands
+ if (i == _entries) {
+ if (!strcmp(_argv[0].str, "?") || (!strcmp(_argv[0].str, "help"))) {
+ _help();
+ cmd_found=true;
+ } else if (!strcmp(_argv[0].str, "exit")) {
+ return;
+ }
+ }
+
+ if (cmd_found == false){
+ //Serial.println("Invalid command, type 'help'");
+ std::cout << "Invalid command, type 'help'\n" ;
+ }
+ }
+}
+
+// display the list of commands in response to the 'help' command
+void
+Menu::_help(void)
+{
+ // Serial.println("Commands:");
+ std::cout << "Commands:\n";
+ for (int i = 0; i < _entries; i++){
+ std::cout << " " << _commands[i].command << '\n';
+ // Serial.print(" ");
+ // Serial.print(_commands[i].command);
+ // Serial.print('\n');
+ }
+}
+
+// run the n'th command in the menu
+int8_t
+Menu::_call(uint8_t n, uint8_t argc)
+{
+ return _commands[n].func(argc, &_argv[0]);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/userMenu.h Sun Mar 29 16:00:36 2020 +0000
@@ -0,0 +1,151 @@
+///
+/// @file userMenu.h
+/// @brief Simple commandline menu subsystem.
+/// @discussion
+/// Menu derived from old version of ArduPilot, used in ArduIMU.V3
+/// Originally from https://code.google.com/archive/p/ardu-imu/downloads
+///
+/// The Menu class implements a simple CLI that accepts commands typed by
+/// the user, and passes the arguments to those commands to a function
+/// defined as handing the command.
+///
+/// Commands are defined in an array of Menu::command structures passed
+/// to the constructor. Each entry in the array defines one command.
+///
+/// Arguments passed to the handler function are pre-converted to both
+/// long and float for convenience.
+
+#ifndef SKYSCRAPER_MBED_USER_MENU_H_INCLUDED
+#define SKYSCRAPER_MBED_USER_MENU_H_INCLUDED
+
+#include <inttypes.h>
+
+//#define MENU_COMMANDLINE_MAX 32
+//#define MENU_ARGS_MAX 4
+//#define MENU_COMMAND_MAX 14
+
+/// Class defining and handling one menu tree
+class Menu {
+public:
+
+
+ static constexpr uint8_t commandlineLenMax = 32U; ///< maximum input line length
+ static constexpr uint8_t argsLenMax = 4U; ///< maximum number of arguments
+ static constexpr uint8_t commandNameLenMax = 14; ///< maximum length of a command name
+ /// argument passed to a menu function
+ ///
+ /// Space-delimited arguments are parsed from the commandline and
+ /// separated into these structures.
+ ///
+ /// If the argument cannot be parsed as a float or a long, the value
+ /// of f or i respectively is undefined. You should range-check
+ /// the inputs to your function.
+ ///
+ struct arg {
+ arg(): str{nullptr}, i{0},f{0.0}{}
+ const char *str; ///< string form of the argument
+ long i; ///< integer form of the argument (if a number)
+ float f; ///< floating point form of the argument (if a number)
+ };
+
+ /// menu command function
+ ///
+ /// Functions called by menu array entries are expected to be of this
+ /// type.
+ ///
+ /// @param argc The number of valid arguments, including the
+ /// name of the command in argv[0]. Will never be
+ /// more than argsLenMax.
+ /// @param argv Pointer to an array of Menu::arg structures
+ /// detailing any optional arguments given to the
+ /// command. argv[0] is always the name of the
+ /// command, so that the same function can be used
+ /// to handle more than one command.
+ ///
+ typedef int8_t (*func)(uint8_t argc, const struct arg *argv);
+
+ /// menu pre-prompt function
+ ///
+ /// Called immediately before waiting for the user to type a command; can be
+ /// used to display help text or status, for example.
+ ///
+ /// If this function returns false, the menu exits.
+ ///
+ typedef bool (*preprompt)(void);
+
+ /// menu command description
+ ///
+ struct command {
+ /// Name of the command, as typed or received.
+ /// Command names are limited in size to keep this structure compact.
+ ///
+ const char command[commandNameLenMax];
+
+ /// The function to call when the command is received.
+ ///
+ /// The argc argument will be at least 1, and no more than
+ /// argsLenMax. The argv array will be populated with
+ /// arguments typed/received up to argsLenMax. The command
+ /// name will always be in argv[0].
+ ///
+ /// Commands may return -2 to cause the menu itself to exit.
+ /// The "?", "help" and "exit" commands are always defined, but
+ /// can be overridden by explicit entries in the command array.
+ ///
+ int8_t (*func)(uint8_t argc, const struct arg *argv); ///< callback function
+ };
+
+ /// constructor
+ ///
+ /// Note that you should normally not call the constructor directly. Use
+ /// the MENU and MENU2 macros defined below.
+ ///
+ /// @param prompt The prompt to be displayed with this menu.
+ /// @param commands An array of ::command structures in program memory (PROGMEM).
+ /// @param entries The number of entries in the menu.
+ ///
+ Menu(const char *prompt, const struct command *commands, uint8_t entries, preprompt ppfunc = 0);
+
+ /// menu runner
+ void run(void);
+
+private:
+ /// Implements the default 'help' command.
+ ///
+ void _help(void); ///< implements the 'help' command
+
+ /// calls the function for the n'th menu item
+ ///
+ /// @param n Index for the menu item to call
+ /// @param argc Number of arguments prepared for the menu item
+ ///
+ int8_t _call(uint8_t n, uint8_t argc);
+
+ const char *_prompt; ///< prompt to display
+ const command *_commands; ///< array of commands
+ const uint8_t _entries; ///< size of the menu
+ const preprompt _ppfunc; ///< optional pre-prompt action
+
+ static char _inbuf[commandlineLenMax]; ///< input buffer
+ static arg _argv[argsLenMax+ 1]; ///< arguments
+};
+
+/// Macros used to define a menu.
+///
+/// The commands argument should be an arary of Menu::command structures, one
+/// per command name. The array does not need to be terminated with any special
+/// record.
+///
+/// Use name.run() to run the menu.
+///
+/// The MENU2 macro supports the optional pre-prompt printing function.
+///
+#define MENU(name, prompt, commands) \
+ static constexpr char __menu_name__ ##name[] = prompt; \
+ static Menu name(__menu_name__ ##name, commands, sizeof(commands) / sizeof(commands[0]))
+
+#define MENU2(name, prompt, commands, preprompt) \
+ static constexpr char __menu_name__ ##name[] = prompt; \
+ static Menu name(__menu_name__ ##name, commands, sizeof(commands) / sizeof(commands[0]), preprompt)
+
+#endif