Add a function to AP_Var for finding a variable by name. It is not efficient, but convenient for e.g. interactive use.
Add pseudo-constant copies of the AP_Meta_calss::Type_id for the standard AP_VarT subclasses. This makes checking the type of a possible AP_Var much cheaper than calling ::meta_cast, as there is no object con/destruction involved. Add some helper functions for manipulating AP_Vars from Menu interfaces. git-svn-id: https://arducopter.googlecode.com/svn/trunk@1541 f9c3cf11-9bcb-44bc-f272-b75c42450872
This commit is contained in:
parent
7f5b882e1a
commit
27c36583d0
@ -5,9 +5,9 @@
|
||||
// Free Software Foundation; either version 2.1 of the License, or (at
|
||||
// your option) any later version.
|
||||
//
|
||||
/// The AP variable interface. This allows different types
|
||||
/// of variables to be passed to blocks for floating point
|
||||
/// math, memory management, etc.
|
||||
|
||||
/// @file AP_Var.cpp
|
||||
/// @brief The AP variable store.
|
||||
|
||||
#if 0
|
||||
# include <FastSerial.h>
|
||||
@ -17,7 +17,9 @@ extern "C" { extern void delay(unsigned long); }
|
||||
# define log(fmt, args...)
|
||||
#endif
|
||||
|
||||
#include "AP_Var.h"
|
||||
#include <AP_Common.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
// Global constants exported for general use.
|
||||
//
|
||||
@ -133,6 +135,28 @@ void AP_Var::copy_name(char *buffer, size_t buffer_size) const
|
||||
strlcat_P(buffer, _name, buffer_size);
|
||||
}
|
||||
|
||||
// Find a variable by name.
|
||||
//
|
||||
AP_Var *
|
||||
AP_Var::find(const char *name)
|
||||
{
|
||||
AP_Var *vp;
|
||||
|
||||
for (vp = first(); vp; vp = vp->next()) {
|
||||
char name_buffer[32];
|
||||
|
||||
// copy the variable's name into our scratch buffer
|
||||
vp->copy_name(name_buffer, sizeof(name_buffer));
|
||||
|
||||
// compare with the user-supplied name
|
||||
if (!strcmp(name, name_buffer)) {
|
||||
return vp;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// Save the variable to EEPROM, if supported
|
||||
//
|
||||
bool AP_Var::save(void)
|
||||
@ -611,3 +635,42 @@ AP_Var_group::_serialize_unserialize(void *buf, size_t buf_size, bool do_seriali
|
||||
}
|
||||
return total_size;
|
||||
}
|
||||
|
||||
// Static pseudo-constant type IDs for known AP_VarT subclasses.
|
||||
//
|
||||
AP_Meta_class::Type_id AP_Var::k_typeid_float; ///< meta_type_id() value for AP_Float
|
||||
AP_Meta_class::Type_id AP_Var::k_typeid_float16; ///< meta_type_id() value for AP_Float16
|
||||
AP_Meta_class::Type_id AP_Var::k_typeid_int32; ///< meta_type_id() value for AP_Int32
|
||||
AP_Meta_class::Type_id AP_Var::k_typeid_int16; ///< meta_type_id() value for AP_Int16
|
||||
AP_Meta_class::Type_id AP_Var::k_typeid_int8; ///< meta_type_id() value for AP_Int8
|
||||
|
||||
/// A special class used to initialise the k_typeid_* values that AP_Var exports.
|
||||
///
|
||||
class AP_Var_typesetup
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
///
|
||||
/// This constructor should be run just once by creating a static instance
|
||||
/// of the class. It will initialise the k_typeid_* values for the well-known
|
||||
/// AP_VarT subclasses.
|
||||
///
|
||||
/// When a new subclass is created, a new k_typeid_* constant should also be
|
||||
/// created and the list below should likewise be expanded.
|
||||
///
|
||||
AP_Var_typesetup(void);
|
||||
};
|
||||
|
||||
/// Initialise AP_Var's k_typeid_* values
|
||||
AP_Var_typesetup::AP_Var_typesetup(void)
|
||||
{
|
||||
AP_Var::k_typeid_float = AP_Meta_class::meta_type_id<AP_Float>();
|
||||
AP_Var::k_typeid_float16 = AP_Meta_class::meta_type_id<AP_Float16>();
|
||||
AP_Var::k_typeid_int32 = AP_Meta_class::meta_type_id<AP_Int32>();
|
||||
AP_Var::k_typeid_int16 = AP_Meta_class::meta_type_id<AP_Int16>();
|
||||
AP_Var::k_typeid_int8 = AP_Meta_class::meta_type_id<AP_Int8>();
|
||||
}
|
||||
|
||||
/// Cause the AP_Var_typesetup constructor to be run.
|
||||
///
|
||||
static AP_Var_typesetup _typesetup __attribute__((used));
|
||||
|
@ -9,12 +9,6 @@
|
||||
/// @file AP_Var.h
|
||||
/// @brief A system for managing and storing variables that are of
|
||||
/// general interest to the system.
|
||||
///
|
||||
///
|
||||
|
||||
/// The AP variable interface. This allows different types
|
||||
/// of variables to be passed to blocks for floating point
|
||||
/// math, memory management, etc.
|
||||
|
||||
#ifndef AP_VAR_H
|
||||
#define AP_VAR_H
|
||||
@ -152,6 +146,12 @@ public:
|
||||
///
|
||||
static const Flags k_flag_unlisted = (1 << 3);
|
||||
|
||||
static AP_Meta_class::Type_id k_typeid_float; ///< meta_type_id() value for AP_Float
|
||||
static AP_Meta_class::Type_id k_typeid_float16; ///< meta_type_id() value for AP_Float16
|
||||
static AP_Meta_class::Type_id k_typeid_int32; ///< meta_type_id() value for AP_Int32
|
||||
static AP_Meta_class::Type_id k_typeid_int16; ///< meta_type_id() value for AP_Int16
|
||||
static AP_Meta_class::Type_id k_typeid_int8; ///< meta_type_id() value for AP_Int8
|
||||
|
||||
/// Constructor for a freestanding variable
|
||||
///
|
||||
/// @param key The storage key to be associated with this variable.
|
||||
@ -201,6 +201,16 @@ public:
|
||||
///
|
||||
void copy_name(char *buffer, size_t bufferSize) const;
|
||||
|
||||
/// Find a variable by name.
|
||||
///
|
||||
/// If the variable has no name, it cannot be found by this interface.
|
||||
///
|
||||
/// @param name The full name of the variable to be found.
|
||||
/// @return A pointer to the variable, or NULL if
|
||||
/// it does not exist.
|
||||
///
|
||||
static AP_Var *find(const char *name);
|
||||
|
||||
/// Save the current value of the variable to EEPROM.
|
||||
///
|
||||
/// This interface works for any subclass that implements
|
||||
@ -622,4 +632,47 @@ extern AP_Float AP_Float_unity;
|
||||
extern AP_Float AP_Float_negative_unity;
|
||||
extern AP_Float AP_Float_zero;
|
||||
|
||||
|
||||
/// Print the value of an AP_Var
|
||||
///
|
||||
/// This function knows about the types listed in the AP_Var::k_typeid_* constants,
|
||||
/// and it will print their value using Serial, which is assumed to be a BetterStream
|
||||
/// serial port (e.g. FastSerial).
|
||||
///
|
||||
/// @param vp The variable to print.
|
||||
///
|
||||
extern void AP_Var_print(AP_Var *vp);
|
||||
|
||||
#ifndef __AP_COMMON_MENU_H
|
||||
# error Must include menu.h
|
||||
#endif
|
||||
|
||||
/// Menu function for setting an AP_Var.
|
||||
///
|
||||
/// This function can be directly called from a Menu. It expects two args, the
|
||||
/// first is the full name of a variable, the second is the value to set the variable
|
||||
/// to.
|
||||
///
|
||||
/// This function knows about the types listed in the AP_Var::k_typeid_* constants.
|
||||
///
|
||||
/// @param argc The number of arguments; must be 3.
|
||||
/// @param argv Arguments. argv[1] must contain a variable name, argv[2].f and .i
|
||||
/// are consulted when setting the value.
|
||||
/// @return Zero if the variable was set successfully, -1 if it could not be set.
|
||||
///
|
||||
extern int8_t AP_Var_menu_set(uint8_t argc, const Menu::arg *argv);
|
||||
|
||||
/// Menu function for displaying AP_Vars.
|
||||
///
|
||||
/// This function can be directly called from a Menu. It expects zero or one argument.
|
||||
/// If no arguments are supplied, all known variables are printed. If an argument is
|
||||
/// supplied, it is expected to be the name of a variable and that variable will be
|
||||
/// printed.
|
||||
///
|
||||
/// @param argc The number of arguments, must be 1 or 2.
|
||||
/// @param argv Argument array; argv[1] may be set to the name of a variable to show.
|
||||
///
|
||||
extern int8_t AP_Var_menu_show(uint8_t argc, const Menu::arg *argv);
|
||||
|
||||
|
||||
#endif // AP_VAR_H
|
||||
|
139
libraries/AP_Common/AP_Var_menufuncs.cpp
Normal file
139
libraries/AP_Common/AP_Var_menufuncs.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||
//
|
||||
// This is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License as published by the
|
||||
// Free Software Foundation; either version 2.1 of the License, or (at
|
||||
// your option) any later version.
|
||||
//
|
||||
|
||||
/// @file AP_Var_menufuncs.cpp
|
||||
/// @brief Useful functions compatible with the menu system for
|
||||
/// managing AP_Var variables.
|
||||
|
||||
#include <FastSerial.h>
|
||||
#include <AP_Common.h>
|
||||
|
||||
void
|
||||
AP_Var_print(AP_Var *vp)
|
||||
{
|
||||
// try to print from variable types that we know
|
||||
if (vp->meta_type_id() == AP_Var::k_typeid_float) {
|
||||
|
||||
AP_Float *v = (AP_Float *)vp;
|
||||
Serial.printf_P(PSTR("%f"), v->get());
|
||||
|
||||
} else if (vp->meta_type_id() == AP_Var::k_typeid_float16) {
|
||||
|
||||
AP_Float16 *v = (AP_Float16 *)vp;
|
||||
Serial.printf_P(PSTR("%f"), v->get());
|
||||
|
||||
} else if (vp->meta_type_id() == AP_Var::k_typeid_int32) {
|
||||
|
||||
AP_Int32 *v = (AP_Int32 *)vp;
|
||||
Serial.printf_P(PSTR("%ld"), v->get());
|
||||
|
||||
} else if (vp->meta_type_id() == AP_Var::k_typeid_int16) {
|
||||
|
||||
AP_Int16 *v = (AP_Int16 *)vp;
|
||||
Serial.printf_P(PSTR("%d"), v->get());
|
||||
|
||||
} else if (vp->meta_type_id() == AP_Var::k_typeid_int8) {
|
||||
|
||||
AP_Int8 *v = (AP_Int8 *)vp;
|
||||
Serial.printf_P(PSTR("%d"), v->get());
|
||||
|
||||
} else {
|
||||
Serial.print_P(PSTR("??"));
|
||||
}
|
||||
}
|
||||
|
||||
int8_t
|
||||
AP_Var_menu_set(uint8_t argc, const Menu::arg *argv)
|
||||
{
|
||||
AP_Var *vp;
|
||||
|
||||
// check argument count
|
||||
if (argc != 3) {
|
||||
Serial.println_P(PSTR("missing name or value"));
|
||||
return -1;
|
||||
}
|
||||
Serial.printf_P(PSTR("%s: "), argv[1].str);
|
||||
|
||||
// search for the variable
|
||||
vp = AP_Var::find(argv[1].str);
|
||||
if (NULL == vp) {
|
||||
Serial.println_P(PSTR("not found"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
// try to assign to variable types that we know
|
||||
if (vp->meta_type_id() == AP_Var::k_typeid_float) {
|
||||
|
||||
AP_Float *v = (AP_Float *)vp;
|
||||
v->set(argv[2].f);
|
||||
|
||||
} else if (vp->meta_type_id() == AP_Var::k_typeid_float16) {
|
||||
|
||||
AP_Float16 *v = (AP_Float16 *)vp;
|
||||
v->set(argv[2].f);
|
||||
|
||||
} else if (vp->meta_type_id() == AP_Var::k_typeid_int32) {
|
||||
|
||||
AP_Int32 *v = (AP_Int32 *)vp;
|
||||
v->set(argv[2].i);
|
||||
|
||||
} else if (vp->meta_type_id() == AP_Var::k_typeid_int16) {
|
||||
|
||||
AP_Int16 *v = (AP_Int16 *)vp;
|
||||
v->set(argv[2].i);
|
||||
|
||||
} else if (vp->meta_type_id() == AP_Var::k_typeid_int8) {
|
||||
|
||||
AP_Int8 *v = (AP_Int8 *)vp;
|
||||
v->set(argv[2].i);
|
||||
|
||||
} else {
|
||||
Serial.println_P(PSTR("unknown type"));
|
||||
return -1;
|
||||
}
|
||||
AP_Var_print(vp);
|
||||
Serial.println();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t
|
||||
AP_Var_menu_show(uint8_t argc, const Menu::arg *argv)
|
||||
{
|
||||
AP_Var *vp;
|
||||
|
||||
// if no arguments, show all variables
|
||||
if (argc == 1) {
|
||||
for (vp = AP_Var::first(); vp; vp = vp->next()) {
|
||||
char name_buffer[32];
|
||||
|
||||
// get a displayable name for the variable
|
||||
vp->copy_name(name_buffer, sizeof(name_buffer));
|
||||
if (name_buffer[0] == 0) {
|
||||
strcpy_P(name_buffer, PSTR("??"));
|
||||
}
|
||||
|
||||
// print name and value
|
||||
Serial.printf_P(PSTR("%-32.32s: "), name_buffer);
|
||||
AP_Var_print(vp);
|
||||
Serial.println();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// show variable by name
|
||||
Serial.printf_P(PSTR("%s: "), argv[1].str);
|
||||
vp = AP_Var::find(argv[1].str);
|
||||
if (NULL == vp) {
|
||||
Serial.println_P(PSTR("not found"));
|
||||
return -1;
|
||||
}
|
||||
AP_Var_print(vp);
|
||||
Serial.println();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user