mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-02-21 23:33:57 -04:00
Clean up formatting for AP_Common
This commit is contained in:
parent
82b23f8eb5
commit
77da85648d
@ -2,10 +2,11 @@
|
|||||||
function format {
|
function format {
|
||||||
DIR=$1
|
DIR=$1
|
||||||
find $DIR -regex ".*\.\(h\|cpp\|pde\)" -exec astyle {} \;
|
find $DIR -regex ".*\.\(h\|cpp\|pde\)" -exec astyle {} \;
|
||||||
find $DIR -regex ".*\.\(h\|cpp\|pde\)" -exec rm {}.orig \;
|
find $DIR -regex ".*\.\(h\|cpp\|pde\)" -exec rm -f {}.orig \;
|
||||||
}
|
}
|
||||||
|
|
||||||
format apo
|
format apo
|
||||||
format ArduRover
|
format ArduRover
|
||||||
format ArduBoat
|
format ArduBoat
|
||||||
format libraries/APO
|
format libraries/APO
|
||||||
|
format libraries/AP_Common
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
// auto-detect at compile time if a call to a string function is using
|
// auto-detect at compile time if a call to a string function is using
|
||||||
// a flash-stored string or not
|
// a flash-stored string or not
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char c;
|
char c;
|
||||||
} prog_char_t;
|
} prog_char_t;
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -97,17 +97,17 @@ typedef struct {
|
|||||||
|
|
||||||
static inline int strcasecmp_P(const char *str1, const prog_char_t *pstr)
|
static inline int strcasecmp_P(const char *str1, const prog_char_t *pstr)
|
||||||
{
|
{
|
||||||
return strcasecmp_P(str1, (const prog_char *)pstr);
|
return strcasecmp_P(str1, (const prog_char *)pstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int strcmp_P(const char *str1, const prog_char_t *pstr)
|
static inline int strcmp_P(const char *str1, const prog_char_t *pstr)
|
||||||
{
|
{
|
||||||
return strcmp_P(str1, (const prog_char *)pstr);
|
return strcmp_P(str1, (const prog_char *)pstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline size_t strlcat_P(char *buffer, const prog_char_t *pstr, size_t buffer_size)
|
static inline size_t strlcat_P(char *buffer, const prog_char_t *pstr, size_t buffer_size)
|
||||||
{
|
{
|
||||||
return strlcat_P(buffer, (const prog_char *)pstr, buffer_size);
|
return strlcat_P(buffer, (const prog_char *)pstr, buffer_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
@ -145,12 +145,12 @@ static inline size_t strlcat_P(char *buffer, const prog_char_t *pstr, size_t buf
|
|||||||
//@{
|
//@{
|
||||||
|
|
||||||
struct Location {
|
struct Location {
|
||||||
uint8_t id; ///< command id
|
uint8_t id; ///< command id
|
||||||
uint8_t options; ///< options bitmask (1<<0 = relative altitude)
|
uint8_t options; ///< options bitmask (1<<0 = relative altitude)
|
||||||
uint8_t p1; ///< param 1
|
uint8_t p1; ///< param 1
|
||||||
int32_t alt; ///< param 2 - Altitude in centimeters (meters * 100)
|
int32_t alt; ///< param 2 - Altitude in centimeters (meters * 100)
|
||||||
int32_t lat; ///< param 3 - Lattitude * 10**7
|
int32_t lat; ///< param 3 - Lattitude * 10**7
|
||||||
int32_t lng; ///< param 4 - Longitude * 10**7
|
int32_t lng; ///< param 4 - Longitude * 10**7
|
||||||
};
|
};
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
@ -68,8 +68,8 @@ private:
|
|||||||
/// Constructor
|
/// Constructor
|
||||||
///
|
///
|
||||||
Test::Test(const char *name) :
|
Test::Test(const char *name) :
|
||||||
_name(name),
|
_name(name),
|
||||||
_fail(false)
|
_fail(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,10 +40,10 @@ uint16_t AP_Var::_bytes_in_use;
|
|||||||
// Constructor for standalone variables
|
// Constructor for standalone variables
|
||||||
//
|
//
|
||||||
AP_Var::AP_Var(Key p_key, const prog_char_t *name, Flags flags) :
|
AP_Var::AP_Var(Key p_key, const prog_char_t *name, Flags flags) :
|
||||||
_group(NULL),
|
_group(NULL),
|
||||||
_key(p_key | k_key_not_located),
|
_key(p_key | k_key_not_located),
|
||||||
_name(name),
|
_name(name),
|
||||||
_flags(flags)
|
_flags(flags)
|
||||||
{
|
{
|
||||||
// Insert the variable or group into the list of known variables, unless
|
// Insert the variable or group into the list of known variables, unless
|
||||||
// it wants to be unlisted.
|
// it wants to be unlisted.
|
||||||
@ -57,10 +57,10 @@ AP_Var::AP_Var(Key p_key, const prog_char_t *name, Flags flags) :
|
|||||||
// Constructor for variables in a group
|
// Constructor for variables in a group
|
||||||
//
|
//
|
||||||
AP_Var::AP_Var(AP_Var_group *pGroup, Key index, const prog_char_t *name, Flags flags) :
|
AP_Var::AP_Var(AP_Var_group *pGroup, Key index, const prog_char_t *name, Flags flags) :
|
||||||
_group(pGroup),
|
_group(pGroup),
|
||||||
_key(index),
|
_key(index),
|
||||||
_name(name),
|
_name(name),
|
||||||
_flags(flags)
|
_flags(flags)
|
||||||
{
|
{
|
||||||
AP_Var **vp;
|
AP_Var **vp;
|
||||||
|
|
||||||
@ -76,10 +76,10 @@ AP_Var::AP_Var(AP_Var_group *pGroup, Key index, const prog_char_t *name, Flags f
|
|||||||
size_t loopCount = 0;
|
size_t loopCount = 0;
|
||||||
while (*vp != NULL) {
|
while (*vp != NULL) {
|
||||||
|
|
||||||
if (loopCount++>k_num_max) return;
|
if (loopCount++>k_num_max) return;
|
||||||
|
|
||||||
if ((*vp)->_key >= _key) {
|
if ((*vp)->_key >= _key) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
vp = &((*vp)->_link);
|
vp = &((*vp)->_link);
|
||||||
}
|
}
|
||||||
@ -106,17 +106,17 @@ AP_Var::~AP_Var(void)
|
|||||||
// Scan the list and remove this if we find it
|
// Scan the list and remove this if we find it
|
||||||
|
|
||||||
{
|
{
|
||||||
size_t loopCount = 0;
|
size_t loopCount = 0;
|
||||||
while (*vp) {
|
while (*vp) {
|
||||||
|
|
||||||
if (loopCount++>k_num_max) return;
|
if (loopCount++>k_num_max) return;
|
||||||
|
|
||||||
if (*vp == this) {
|
if (*vp == this) {
|
||||||
*vp = _link;
|
*vp = _link;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
vp = &((*vp)->_link);
|
vp = &((*vp)->_link);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are destroying a group, remove all its variables from the list
|
// If we are destroying a group, remove all its variables from the list
|
||||||
@ -129,7 +129,7 @@ AP_Var::~AP_Var(void)
|
|||||||
|
|
||||||
while (*vp) {
|
while (*vp) {
|
||||||
|
|
||||||
if (loopCount++>k_num_max) return;
|
if (loopCount++>k_num_max) return;
|
||||||
|
|
||||||
// Does the variable claim us as its group?
|
// Does the variable claim us as its group?
|
||||||
if ((*vp)->_group == this) {
|
if ((*vp)->_group == this) {
|
||||||
@ -166,7 +166,7 @@ AP_Var::find(const char *name)
|
|||||||
|
|
||||||
for (vp = first(); vp; vp = vp->next()) {
|
for (vp = first(); vp; vp = vp->next()) {
|
||||||
|
|
||||||
if (loopCount++>k_num_max) return NULL;
|
if (loopCount++>k_num_max) return NULL;
|
||||||
|
|
||||||
char name_buffer[32];
|
char name_buffer[32];
|
||||||
|
|
||||||
@ -189,7 +189,7 @@ AP_Var::find(Key key)
|
|||||||
AP_Var *vp;
|
AP_Var *vp;
|
||||||
size_t loopCount = 0;
|
size_t loopCount = 0;
|
||||||
for (vp = first(); vp; vp = vp->next()) {
|
for (vp = first(); vp; vp = vp->next()) {
|
||||||
if (loopCount++>k_num_max) return NULL;
|
if (loopCount++>k_num_max) return NULL;
|
||||||
if (key == vp->key()) {
|
if (key == vp->key()) {
|
||||||
return vp;
|
return vp;
|
||||||
}
|
}
|
||||||
@ -242,7 +242,7 @@ bool AP_Var::save(void)
|
|||||||
newv = eeprom_read_byte(ep);
|
newv = eeprom_read_byte(ep);
|
||||||
if (newv != vbuf[i]) {
|
if (newv != vbuf[i]) {
|
||||||
serialDebug("readback failed at offset %p: got %u, expected %u",
|
serialDebug("readback failed at offset %p: got %u, expected %u",
|
||||||
ep, newv, vbuf[i]);
|
ep, newv, vbuf[i]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -304,10 +304,10 @@ bool AP_Var::save_all(void)
|
|||||||
|
|
||||||
while (vp) {
|
while (vp) {
|
||||||
|
|
||||||
if (loopCount++>k_num_max) return false;
|
if (loopCount++>k_num_max) return false;
|
||||||
|
|
||||||
if (!vp->has_flags(k_flag_no_auto_load) && // not opted out of autosave
|
if (!vp->has_flags(k_flag_no_auto_load) && // not opted out of autosave
|
||||||
(vp->_key != k_key_none)) { // has a key
|
(vp->_key != k_key_none)) { // has a key
|
||||||
|
|
||||||
if (!vp->save()) {
|
if (!vp->save()) {
|
||||||
result = false;
|
result = false;
|
||||||
@ -329,10 +329,10 @@ bool AP_Var::load_all(void)
|
|||||||
|
|
||||||
while (vp) {
|
while (vp) {
|
||||||
|
|
||||||
if (loopCount++>k_num_max) return false;
|
if (loopCount++>k_num_max) return false;
|
||||||
|
|
||||||
if (!vp->has_flags(k_flag_no_auto_load) && // not opted out of autoload
|
if (!vp->has_flags(k_flag_no_auto_load) && // not opted out of autoload
|
||||||
(vp->_key != k_key_none)) { // has a key
|
(vp->_key != k_key_none)) { // has a key
|
||||||
|
|
||||||
if (!vp->load()) {
|
if (!vp->load()) {
|
||||||
result = false;
|
result = false;
|
||||||
@ -365,7 +365,7 @@ AP_Var::erase_all()
|
|||||||
|
|
||||||
while (vp) {
|
while (vp) {
|
||||||
|
|
||||||
if (loopCount++>k_num_max) return;
|
if (loopCount++>k_num_max) return;
|
||||||
|
|
||||||
vp->_key = vp->key() | k_key_not_located;
|
vp->_key = vp->key() | k_key_not_located;
|
||||||
vp = vp->_link;
|
vp = vp->_link;
|
||||||
@ -449,7 +449,7 @@ AP_Var::first_member(AP_Var_group *group)
|
|||||||
|
|
||||||
while (*vp) {
|
while (*vp) {
|
||||||
|
|
||||||
if (loopCount++>k_num_max) return NULL;
|
if (loopCount++>k_num_max) return NULL;
|
||||||
|
|
||||||
serialDebug("consider %p with %p", *vp, (*vp)->_group);
|
serialDebug("consider %p with %p", *vp, (*vp)->_group);
|
||||||
if ((*vp)->_group == group) {
|
if ((*vp)->_group == group) {
|
||||||
@ -471,7 +471,7 @@ AP_Var::next_member()
|
|||||||
|
|
||||||
while (vp) {
|
while (vp) {
|
||||||
|
|
||||||
if (loopCount++>k_num_max) return NULL;
|
if (loopCount++>k_num_max) return NULL;
|
||||||
|
|
||||||
if (vp->_group == _group) {
|
if (vp->_group == _group) {
|
||||||
return vp;
|
return vp;
|
||||||
@ -498,7 +498,7 @@ bool AP_Var::_EEPROM_scan(void)
|
|||||||
eeprom_address = 0;
|
eeprom_address = 0;
|
||||||
eeprom_read_block(&ee_header, (void *)eeprom_address, sizeof(ee_header));
|
eeprom_read_block(&ee_header, (void *)eeprom_address, sizeof(ee_header));
|
||||||
if ((ee_header.magic != k_EEPROM_magic) ||
|
if ((ee_header.magic != k_EEPROM_magic) ||
|
||||||
(ee_header.revision != k_EEPROM_revision)) {
|
(ee_header.revision != k_EEPROM_revision)) {
|
||||||
|
|
||||||
serialDebug("no header, magic 0x%x revision %u", ee_header.magic, ee_header.revision);
|
serialDebug("no header, magic 0x%x revision %u", ee_header.magic, ee_header.revision);
|
||||||
return false;
|
return false;
|
||||||
@ -514,7 +514,7 @@ bool AP_Var::_EEPROM_scan(void)
|
|||||||
|
|
||||||
while (eeprom_address < (k_EEPROM_size - sizeof(var_header) - 1)) {
|
while (eeprom_address < (k_EEPROM_size - sizeof(var_header) - 1)) {
|
||||||
|
|
||||||
if (loopCount++>k_num_max) return NULL;
|
if (loopCount++>k_num_max) return NULL;
|
||||||
|
|
||||||
// Read a variable header
|
// Read a variable header
|
||||||
//
|
//
|
||||||
@ -531,10 +531,10 @@ bool AP_Var::_EEPROM_scan(void)
|
|||||||
// Sanity-check the variable header and abort if it looks bad
|
// Sanity-check the variable header and abort if it looks bad
|
||||||
//
|
//
|
||||||
if (k_EEPROM_size <= (
|
if (k_EEPROM_size <= (
|
||||||
eeprom_address + // current position
|
eeprom_address + // current position
|
||||||
sizeof(var_header) + // header for this variable
|
sizeof(var_header) + // header for this variable
|
||||||
var_header.size + 1 + // data for this variable
|
var_header.size + 1 + // data for this variable
|
||||||
sizeof(var_header))) { // header for sentinel
|
sizeof(var_header))) { // header for sentinel
|
||||||
|
|
||||||
serialDebug("header overruns EEPROM");
|
serialDebug("header overruns EEPROM");
|
||||||
return false;
|
return false;
|
||||||
@ -544,7 +544,7 @@ bool AP_Var::_EEPROM_scan(void)
|
|||||||
vp = _variables;
|
vp = _variables;
|
||||||
size_t loopCount2 = 0;
|
size_t loopCount2 = 0;
|
||||||
while(vp) {
|
while(vp) {
|
||||||
if (loopCount2++>k_num_max) return false;
|
if (loopCount2++>k_num_max) return false;
|
||||||
if (vp->key() == var_header.key) {
|
if (vp->key() == var_header.key) {
|
||||||
// adjust the variable's key to point to this entry
|
// adjust the variable's key to point to this entry
|
||||||
vp->_key = eeprom_address + sizeof(var_header);
|
vp->_key = eeprom_address + sizeof(var_header);
|
||||||
@ -572,7 +572,7 @@ bool AP_Var::_EEPROM_scan(void)
|
|||||||
vp = _variables;
|
vp = _variables;
|
||||||
size_t loopCount3 = 0;
|
size_t loopCount3 = 0;
|
||||||
while(vp) {
|
while(vp) {
|
||||||
if (loopCount3++>k_num_max) return false;
|
if (loopCount3++>k_num_max) return false;
|
||||||
if (vp->_key & k_key_not_located) {
|
if (vp->_key & k_key_not_located) {
|
||||||
vp->_key |= k_key_not_allocated;
|
vp->_key |= k_key_not_allocated;
|
||||||
serialDebug("key %u not allocated", vp->key());
|
serialDebug("key %u not allocated", vp->key());
|
||||||
@ -737,7 +737,7 @@ AP_Var_group::_serialize_unserialize(void *buf, size_t buf_size, bool do_seriali
|
|||||||
|
|
||||||
while (vp) {
|
while (vp) {
|
||||||
|
|
||||||
if (loopCount++>k_num_max) return false;
|
if (loopCount++>k_num_max) return false;
|
||||||
|
|
||||||
// (un)serialise the group member
|
// (un)serialise the group member
|
||||||
if (do_serialize) {
|
if (do_serialize) {
|
||||||
|
@ -302,14 +302,18 @@ public:
|
|||||||
///
|
///
|
||||||
/// @return The parent group, or NULL if the variable is not grouped.
|
/// @return The parent group, or NULL if the variable is not grouped.
|
||||||
///
|
///
|
||||||
AP_Var_group *group(void) { return _group; }
|
AP_Var_group *group(void) {
|
||||||
|
return _group;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the first variable in the global list.
|
/// Returns the first variable in the global list.
|
||||||
///
|
///
|
||||||
/// @return The first variable in the global list, or NULL if
|
/// @return The first variable in the global list, or NULL if
|
||||||
/// there are none.
|
/// there are none.
|
||||||
///
|
///
|
||||||
static AP_Var *first(void) { return _variables; }
|
static AP_Var *first(void) {
|
||||||
|
return _variables;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the next variable in the global list.
|
/// Returns the next variable in the global list.
|
||||||
///
|
///
|
||||||
@ -367,7 +371,9 @@ public:
|
|||||||
///
|
///
|
||||||
/// @return The sum of sizeof(*this) for all constructed AP_Var subclass instances.
|
/// @return The sum of sizeof(*this) for all constructed AP_Var subclass instances.
|
||||||
///
|
///
|
||||||
static uint16_t get_memory_use() { return _bytes_in_use; }
|
static uint16_t get_memory_use() {
|
||||||
|
return _bytes_in_use;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Memory statistics
|
// Memory statistics
|
||||||
|
@ -14,29 +14,29 @@
|
|||||||
void * operator new(size_t size)
|
void * operator new(size_t size)
|
||||||
{
|
{
|
||||||
#ifdef AP_DISPLAYMEM
|
#ifdef AP_DISPLAYMEM
|
||||||
displayMemory();
|
displayMemory();
|
||||||
#endif
|
#endif
|
||||||
return(calloc(size, 1));
|
return(calloc(size, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete(void *p)
|
void operator delete(void *p)
|
||||||
{
|
{
|
||||||
if (p) free(p);
|
if (p) free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void __cxa_pure_virtual()
|
extern "C" void __cxa_pure_virtual()
|
||||||
{
|
{
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
Serial.println("Error: pure virtual call");
|
Serial.println("Error: pure virtual call");
|
||||||
delay(1000);
|
delay(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void * operator new[](size_t size)
|
void * operator new[](size_t size)
|
||||||
{
|
{
|
||||||
#ifdef AP_DISPLAYMEM
|
#ifdef AP_DISPLAYMEM
|
||||||
displayMemory();
|
displayMemory();
|
||||||
#endif
|
#endif
|
||||||
return(calloc(size, 1));
|
return(calloc(size, 1));
|
||||||
}
|
}
|
||||||
@ -50,12 +50,12 @@ __extension__ typedef int __guard __attribute__((mode (__DI__)));
|
|||||||
|
|
||||||
int __cxa_guard_acquire(__guard *g)
|
int __cxa_guard_acquire(__guard *g)
|
||||||
{
|
{
|
||||||
return !*(char *)(g);
|
return !*(char *)(g);
|
||||||
};
|
};
|
||||||
|
|
||||||
void __cxa_guard_release (__guard *g)
|
void __cxa_guard_release (__guard *g)
|
||||||
{
|
{
|
||||||
*(char *)g = 1;
|
*(char *)g = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
void __cxa_guard_abort (__guard *) {};
|
void __cxa_guard_abort (__guard *) {};
|
||||||
|
@ -7,24 +7,24 @@ FastSerialPort0(Serial);
|
|||||||
int8_t
|
int8_t
|
||||||
menu_test(uint8_t argc, const Menu::arg *argv)
|
menu_test(uint8_t argc, const Menu::arg *argv)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
Serial.printf("This is a test with %d arguments\n", argc);
|
Serial.printf("This is a test with %d arguments\n", argc);
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
Serial.printf("%d: int %ld float ", i, argv[i].i);
|
Serial.printf("%d: int %ld float ", i, argv[i].i);
|
||||||
Serial.println(argv[i].f, 6); // gross
|
Serial.println(argv[i].f, 6); // gross
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t
|
int8_t
|
||||||
menu_auto(uint8_t argc, const Menu::arg *argv)
|
menu_auto(uint8_t argc, const Menu::arg *argv)
|
||||||
{
|
{
|
||||||
Serial.println("auto text");
|
Serial.println("auto text");
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct Menu::command top_menu_commands[] PROGMEM = {
|
const struct Menu::command top_menu_commands[] PROGMEM = {
|
||||||
{"*", menu_auto},
|
{"*", menu_auto},
|
||||||
{"test", menu_test},
|
{"test", menu_test},
|
||||||
};
|
};
|
||||||
|
|
||||||
MENU(top, "menu", top_menu_commands);
|
MENU(top, "menu", top_menu_commands);
|
||||||
@ -32,8 +32,8 @@ MENU(top, "menu", top_menu_commands);
|
|||||||
void
|
void
|
||||||
setup(void)
|
setup(void)
|
||||||
{
|
{
|
||||||
Serial.begin(38400);
|
Serial.begin(38400);
|
||||||
top.run();
|
top.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -23,101 +23,101 @@
|
|||||||
/// Class defining and handling one menu tree
|
/// Class defining and handling one menu tree
|
||||||
class Menu {
|
class Menu {
|
||||||
public:
|
public:
|
||||||
/// argument passed to a menu function
|
/// argument passed to a menu function
|
||||||
///
|
///
|
||||||
/// Space-delimited arguments are parsed from the commandline and
|
/// Space-delimited arguments are parsed from the commandline and
|
||||||
/// separated into these structures.
|
/// separated into these structures.
|
||||||
///
|
///
|
||||||
/// If the argument cannot be parsed as a float or a long, the value
|
/// 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
|
/// of f or i respectively is undefined. You should range-check
|
||||||
/// the inputs to your function.
|
/// the inputs to your function.
|
||||||
///
|
///
|
||||||
struct arg {
|
struct arg {
|
||||||
const char *str; ///< string form of the argument
|
const char *str; ///< string form of the argument
|
||||||
long i; ///< integer form of the argument (if a number)
|
long i; ///< integer form of the argument (if a number)
|
||||||
float f; ///< floating point form of the argument (if a number)
|
float f; ///< floating point form of the argument (if a number)
|
||||||
};
|
};
|
||||||
|
|
||||||
/// menu command function
|
/// menu command function
|
||||||
///
|
///
|
||||||
/// Functions called by menu array entries are expected to be of this
|
/// Functions called by menu array entries are expected to be of this
|
||||||
/// type.
|
/// type.
|
||||||
///
|
///
|
||||||
/// @param argc The number of valid arguments, including the
|
/// @param argc The number of valid arguments, including the
|
||||||
/// name of the command in argv[0]. Will never be
|
/// name of the command in argv[0]. Will never be
|
||||||
/// more than MENU_ARGS_MAX.
|
/// more than MENU_ARGS_MAX.
|
||||||
/// @param argv Pointer to an array of Menu::arg structures
|
/// @param argv Pointer to an array of Menu::arg structures
|
||||||
/// detailing any optional arguments given to the
|
/// detailing any optional arguments given to the
|
||||||
/// command. argv[0] is always the name of the
|
/// command. argv[0] is always the name of the
|
||||||
/// command, so that the same function can be used
|
/// command, so that the same function can be used
|
||||||
/// to handle more than one command.
|
/// to handle more than one command.
|
||||||
///
|
///
|
||||||
typedef int8_t (*func)(uint8_t argc, const struct arg *argv);
|
typedef int8_t (*func)(uint8_t argc, const struct arg *argv);
|
||||||
|
|
||||||
/// menu pre-prompt function
|
/// menu pre-prompt function
|
||||||
///
|
///
|
||||||
/// Called immediately before waiting for the user to type a command; can be
|
/// Called immediately before waiting for the user to type a command; can be
|
||||||
/// used to display help text or status, for example.
|
/// used to display help text or status, for example.
|
||||||
///
|
///
|
||||||
/// If this function returns false, the menu exits.
|
/// If this function returns false, the menu exits.
|
||||||
///
|
///
|
||||||
typedef bool (*preprompt)(void);
|
typedef bool (*preprompt)(void);
|
||||||
|
|
||||||
/// menu command description
|
/// menu command description
|
||||||
///
|
///
|
||||||
struct command {
|
struct command {
|
||||||
/// Name of the command, as typed or received.
|
/// Name of the command, as typed or received.
|
||||||
/// Command names are limited in size to keep this structure compact.
|
/// Command names are limited in size to keep this structure compact.
|
||||||
///
|
///
|
||||||
const char command[MENU_COMMAND_MAX];
|
const char command[MENU_COMMAND_MAX];
|
||||||
|
|
||||||
/// The function to call when the command is received.
|
/// The function to call when the command is received.
|
||||||
///
|
///
|
||||||
/// The argc argument will be at least 1, and no more than
|
/// The argc argument will be at least 1, and no more than
|
||||||
/// MENU_ARGS_MAX. The argv array will be populated with
|
/// MENU_ARGS_MAX. The argv array will be populated with
|
||||||
/// arguments typed/received up to MENU_ARGS_MAX. The command
|
/// arguments typed/received up to MENU_ARGS_MAX. The command
|
||||||
/// name will always be in argv[0].
|
/// name will always be in argv[0].
|
||||||
///
|
///
|
||||||
/// Commands may return -2 to cause the menu itself to exit.
|
/// Commands may return -2 to cause the menu itself to exit.
|
||||||
/// The "?", "help" and "exit" commands are always defined, but
|
/// The "?", "help" and "exit" commands are always defined, but
|
||||||
/// can be overridden by explicit entries in the command array.
|
/// can be overridden by explicit entries in the command array.
|
||||||
///
|
///
|
||||||
int8_t (*func)(uint8_t argc, const struct arg *argv); ///< callback function
|
int8_t (*func)(uint8_t argc, const struct arg *argv); ///< callback function
|
||||||
};
|
};
|
||||||
|
|
||||||
/// constructor
|
/// constructor
|
||||||
///
|
///
|
||||||
/// Note that you should normally not call the constructor directly. Use
|
/// Note that you should normally not call the constructor directly. Use
|
||||||
/// the MENU and MENU2 macros defined below.
|
/// the MENU and MENU2 macros defined below.
|
||||||
///
|
///
|
||||||
/// @param prompt The prompt to be displayed with this menu.
|
/// @param prompt The prompt to be displayed with this menu.
|
||||||
/// @param commands An array of ::command structures in program memory (PROGMEM).
|
/// @param commands An array of ::command structures in program memory (PROGMEM).
|
||||||
/// @param entries The number of entries in the menu.
|
/// @param entries The number of entries in the menu.
|
||||||
///
|
///
|
||||||
Menu(const char *prompt, const struct command *commands, uint8_t entries, preprompt ppfunc = 0);
|
Menu(const char *prompt, const struct command *commands, uint8_t entries, preprompt ppfunc = 0);
|
||||||
|
|
||||||
/// menu runner
|
/// menu runner
|
||||||
void run(void);
|
void run(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Implements the default 'help' command.
|
/// Implements the default 'help' command.
|
||||||
///
|
///
|
||||||
void _help(void); ///< implements the 'help' command
|
void _help(void); ///< implements the 'help' command
|
||||||
|
|
||||||
/// calls the function for the n'th menu item
|
/// calls the function for the n'th menu item
|
||||||
///
|
///
|
||||||
/// @param n Index for the menu item to call
|
/// @param n Index for the menu item to call
|
||||||
/// @param argc Number of arguments prepared for the menu item
|
/// @param argc Number of arguments prepared for the menu item
|
||||||
///
|
///
|
||||||
int8_t _call(uint8_t n, uint8_t argc);
|
int8_t _call(uint8_t n, uint8_t argc);
|
||||||
|
|
||||||
const char *_prompt; ///< prompt to display
|
const char *_prompt; ///< prompt to display
|
||||||
const command *_commands; ///< array of commands
|
const command *_commands; ///< array of commands
|
||||||
const uint8_t _entries; ///< size of the menu
|
const uint8_t _entries; ///< size of the menu
|
||||||
const preprompt _ppfunc; ///< optional pre-prompt action
|
const preprompt _ppfunc; ///< optional pre-prompt action
|
||||||
|
|
||||||
static char _inbuf[MENU_COMMANDLINE_MAX]; ///< input buffer
|
static char _inbuf[MENU_COMMANDLINE_MAX]; ///< input buffer
|
||||||
static arg _argv[MENU_ARGS_MAX + 1]; ///< arguments
|
static arg _argv[MENU_ARGS_MAX + 1]; ///< arguments
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Macros used to define a menu.
|
/// Macros used to define a menu.
|
||||||
|
@ -19,10 +19,10 @@ Menu::arg Menu::_argv[MENU_ARGS_MAX + 1];
|
|||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
Menu::Menu(const prog_char *prompt, const Menu::command *commands, uint8_t entries, preprompt ppfunc) :
|
Menu::Menu(const prog_char *prompt, const Menu::command *commands, uint8_t entries, preprompt ppfunc) :
|
||||||
_prompt(prompt),
|
_prompt(prompt),
|
||||||
_commands(commands),
|
_commands(commands),
|
||||||
_entries(entries),
|
_entries(entries),
|
||||||
_ppfunc(ppfunc)
|
_ppfunc(ppfunc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,112 +30,112 @@ Menu::Menu(const prog_char *prompt, const Menu::command *commands, uint8_t entri
|
|||||||
void
|
void
|
||||||
Menu::run(void)
|
Menu::run(void)
|
||||||
{
|
{
|
||||||
uint8_t len, i, ret;
|
uint8_t len, i, ret;
|
||||||
uint8_t argc;
|
uint8_t argc;
|
||||||
int c;
|
int c;
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
// loop performing commands
|
// loop performing commands
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
// run the pre-prompt function, if one is defined
|
// run the pre-prompt function, if one is defined
|
||||||
if ((NULL != _ppfunc) && !_ppfunc())
|
if ((NULL != _ppfunc) && !_ppfunc())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// loop reading characters from the input
|
// loop reading characters from the input
|
||||||
len = 0;
|
len = 0;
|
||||||
Serial.printf("%S] ", FPSTR(_prompt));
|
Serial.printf("%S] ", FPSTR(_prompt));
|
||||||
for (;;) {
|
for (;;) {
|
||||||
c = Serial.read();
|
c = Serial.read();
|
||||||
if (-1 == c)
|
if (-1 == c)
|
||||||
continue;
|
continue;
|
||||||
// carriage return -> process command
|
// carriage return -> process command
|
||||||
if ('\r' == c) {
|
if ('\r' == c) {
|
||||||
_inbuf[len] = '\0';
|
_inbuf[len] = '\0';
|
||||||
Serial.write('\r');
|
Serial.write('\r');
|
||||||
Serial.write('\n');
|
Serial.write('\n');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// backspace
|
// backspace
|
||||||
if ('\b' == c) {
|
if ('\b' == c) {
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
len--;
|
len--;
|
||||||
Serial.write('\b');
|
Serial.write('\b');
|
||||||
Serial.write(' ');
|
Serial.write(' ');
|
||||||
Serial.write('\b');
|
Serial.write('\b');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// printable character
|
// printable character
|
||||||
if (isprint(c) && (len < (MENU_COMMANDLINE_MAX - 1))) {
|
if (isprint(c) && (len < (MENU_COMMANDLINE_MAX - 1))) {
|
||||||
_inbuf[len++] = c;
|
_inbuf[len++] = c;
|
||||||
Serial.write((char)c);
|
Serial.write((char)c);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// split the input line into tokens
|
// split the input line into tokens
|
||||||
argc = 0;
|
argc = 0;
|
||||||
_argv[argc++].str = strtok_r(_inbuf, " ", &s);
|
_argv[argc++].str = strtok_r(_inbuf, " ", &s);
|
||||||
// XXX should an empty line by itself back out of the current menu?
|
// XXX should an empty line by itself back out of the current menu?
|
||||||
while (argc <= MENU_ARGS_MAX) {
|
while (argc <= MENU_ARGS_MAX) {
|
||||||
_argv[argc].str = strtok_r(NULL, " ", &s);
|
_argv[argc].str = strtok_r(NULL, " ", &s);
|
||||||
if ('\0' == _argv[argc].str)
|
if ('\0' == _argv[argc].str)
|
||||||
break;
|
break;
|
||||||
_argv[argc].i = atol(_argv[argc].str);
|
_argv[argc].i = atol(_argv[argc].str);
|
||||||
_argv[argc].f = atof(_argv[argc].str); // calls strtod, > 700B !
|
_argv[argc].f = atof(_argv[argc].str); // calls strtod, > 700B !
|
||||||
argc++;
|
argc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// populate arguments that have not been specified with "" and 0
|
// populate arguments that have not been specified with "" and 0
|
||||||
// this is safer than NULL in the case where commands may look
|
// this is safer than NULL in the case where commands may look
|
||||||
// without testing argc
|
// without testing argc
|
||||||
i = argc;
|
i = argc;
|
||||||
while (i <= MENU_ARGS_MAX) {
|
while (i <= MENU_ARGS_MAX) {
|
||||||
_argv[i].str = "";
|
_argv[i].str = "";
|
||||||
_argv[i].i = 0;
|
_argv[i].i = 0;
|
||||||
_argv[i].f = 0;
|
_argv[i].f = 0;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// look for a command matching the first word (note that it may be empty)
|
// look for a command matching the first word (note that it may be empty)
|
||||||
for (i = 0; i < _entries; i++) {
|
for (i = 0; i < _entries; i++) {
|
||||||
if (!strcasecmp_P(_argv[0].str, _commands[i].command)) {
|
if (!strcasecmp_P(_argv[0].str, _commands[i].command)) {
|
||||||
ret = _call(i, argc);
|
ret = _call(i, argc);
|
||||||
if (-2 == ret)
|
if (-2 == ret)
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// implicit commands
|
// implicit commands
|
||||||
if (i == _entries) {
|
if (i == _entries) {
|
||||||
if (!strcmp(_argv[0].str, "?") || (!strcasecmp_P(_argv[0].str, PSTR("help")))) {
|
if (!strcmp(_argv[0].str, "?") || (!strcasecmp_P(_argv[0].str, PSTR("help")))) {
|
||||||
_help();
|
_help();
|
||||||
} else if (!strcasecmp_P(_argv[0].str, PSTR("exit"))) {
|
} else if (!strcasecmp_P(_argv[0].str, PSTR("exit"))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// display the list of commands in response to the 'help' command
|
// display the list of commands in response to the 'help' command
|
||||||
void
|
void
|
||||||
Menu::_help(void)
|
Menu::_help(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
Serial.println("Commands:");
|
Serial.println("Commands:");
|
||||||
for (i = 0; i < _entries; i++)
|
for (i = 0; i < _entries; i++)
|
||||||
Serial.printf(" %S\n", FPSTR(_commands[i].command));
|
Serial.printf(" %S\n", FPSTR(_commands[i].command));
|
||||||
}
|
}
|
||||||
|
|
||||||
// run the n'th command in the menu
|
// run the n'th command in the menu
|
||||||
int8_t
|
int8_t
|
||||||
Menu::_call(uint8_t n, uint8_t argc)
|
Menu::_call(uint8_t n, uint8_t argc)
|
||||||
{
|
{
|
||||||
func fn;
|
func fn;
|
||||||
|
|
||||||
fn = (func)pgm_read_word(&_commands[n].func);
|
fn = (func)pgm_read_word(&_commands[n].func);
|
||||||
return(fn(argc, &_argv[0]));
|
return(fn(argc, &_argv[0]));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user