Merge branch 'master' of github.com:PX4/Firmware

This commit is contained in:
Lorenz Meier
2012-08-11 21:19:27 +02:00
55 changed files with 1046 additions and 601 deletions
+5 -5
View File
@@ -81,7 +81,7 @@ struct mixer_scaler_s
};
/** mixer input */
struct mixer_input_s
struct mixer_control_s
{
uint8_t control_group; /**< group from which the input reads */
uint8_t control_index; /**< index within the control group */
@@ -91,12 +91,12 @@ struct mixer_input_s
/** simple mixer */
struct mixer_simple_s
{
uint8_t input_count; /**< number of inputs */
uint8_t control_count; /**< number of inputs */
struct mixer_scaler_s output_scaler; /**< scaling for the output */
struct mixer_input_s inputs[0]; /**< actual size of the array is set by input_count */
struct mixer_control_s controls[0]; /**< actual size of the array is set by control_count */
};
#define MIXER_SIMPLE_SIZE(_icount) (sizeof(struct mixer_simple_s) + (_icount) * sizeof(struct mixer_input_s))
#define MIXER_SIMPLE_SIZE(_icount) (sizeof(struct mixer_simple_s) + (_icount) * sizeof(struct mixer_control_s))
/**
* add a simple mixer in (struct mixer_simple_s *)arg
@@ -114,7 +114,7 @@ struct mixer_rotor_output_s
struct mixer_multirotor_s
{
uint8_t rotor_count;
struct mixer_input_s inputs[4]; /**< inputs are roll, pitch, yaw, thrust */
struct mixer_control_s controls[4]; /**< controls are roll, pitch, yaw, thrust */
struct mixer_rotor_output_s rotors[0]; /**< actual size of the array is set by rotor_count */
};
+19 -10
View File
@@ -371,9 +371,15 @@ o get [-b|-n] [-f <local-path>] -h <ip-address> <remote-path>
Selects either binary ("octect") or test ("netascii") transfer
mode. Default: text.
o help
o help [-v] [<cmd>]
Presents summary information about each command to console.
Presents summary information about NSH commands to console. Options:
-v
Show verbose output will full command usage
<cmd>
Show full command usage only for this command
o ifconfig
@@ -499,14 +505,14 @@ o mkfatfs <path>
Format a fat file system on the block device specified by path.
NSH provides this command to access the mkfatfs() NuttX API.
This block device must reside in the NuttX psuedo filesystem and
This block device must reside in the NuttX pseudo filesystem and
must have been created by some call to register_blockdriver() (see
include/nuttx/fs/fs.h).
o mkfifo <path>
Creates a FIFO character device anywhere in the pseudo file system,
creating whatever psuedo directories that may be needed to complete
creating whatever pseudo directories that may be needed to complete
the full path. By convention, however, device drivers are place in
the standard /dev directory. After it is created, the FIFO device
may be used as any other device driver. NSH provides this command
@@ -578,7 +584,7 @@ o mount [-t <fstype> <block-device> <dir-path>]
If the mount parameters are provied on the command after the 'mount'
command, then the 'mount' command will mount a file system in the
NuttX psuedo-file system. 'mount' performs a three way association,
NuttX pseudo-file system. 'mount' performs a three way association,
binding:
File system. The '-t <fstype>' option identifies the type of
@@ -586,19 +592,19 @@ o mount [-t <fstype> <block-device> <dir-path>]
of this writing, vfat is the only supported value for <fstype>
Block Device. The <block-device> argument is the full or relative
path to a block driver inode in the psuedo filesystem. By convention,
path to a block driver inode in the pseudo filesystem. By convention,
this is a name under the /dev sub-directory. This <block-device>
must have been previously formatted with the same file system
type as specified by <fstype>
Mount Point. The mount point is the location in the psuedo file
Mount Point. The mount point is the location in the pseudo file
system where the mounted volume will appear. This mount point
can only reside in the NuttX psuedo filesystem. By convention, this
can only reside in the NuttX pseudo filesystem. By convention, this
mount point is a subdirectory under /mnt. The mount command will
create whatever psuedo directories that may be needed to complete
create whatever pseudo directories that may be needed to complete
the full path but the full path must not already exist.
After the volume has been mounted in the NuttX psuedo file
After the volume has been mounted in the NuttX pseudo file
system, it may be access in the same way as other objects in the
file system.
@@ -889,6 +895,9 @@ also allow it to squeeze into very small memory footprints.
CONFIG_NSH_DISABLE_UNSET, CONFIG_NSH_DISABLE_USLEEP, CONFIG_NSH_DISABLE_WGET,
CONFIG_NSH_DISABLE_XD
Verbose help output can be suppressed by defining CONFIG_NSH_HELP_TERSE. In that
case, the help command is still available but will be slightly smaller.
NSH-Specific Configuration Settings
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+24 -10
View File
@@ -88,12 +88,12 @@
# define MAX_ARGV_ENTRIES (NSH_MAX_ARGUMENTS+4)
#endif
/* Help layout */
/* Help command summary layout */
#define MAX_CMDLEN 12
#define CMDS_PER_LINE 5
#define CMDS_PER_LINE 6
#define NUM_CMDS (sizeof(g_cmdmap)/sizeof(struct cmdmap_s))
#define NUM_CMDS ((sizeof(g_cmdmap)/sizeof(struct cmdmap_s)) - 1)
#define NUM_CMD_ROWS ((NUM_CMDS + (CMDS_PER_LINE-1)) / CMDS_PER_LINE)
/****************************************************************************
@@ -211,7 +211,11 @@ static const struct cmdmap_s g_cmdmap[] =
#endif
#ifndef CONFIG_NSH_DISABLE_HELP
{ "help", cmd_help, 1, 3, "[-v] [cmd]" },
# ifdef CONFIG_NSH_HELP_TERSE
{ "help", cmd_help, 1, 2, "[<cmd>]" },
#else
{ "help", cmd_help, 1, 3, "[-v] [<cmd>]" },
# endif
#endif
#ifdef CONFIG_NET
@@ -439,7 +443,7 @@ static inline void help_cmdlist(FAR struct nsh_vtbl_s *vtbl)
for (i = 0; i < NUM_CMD_ROWS; i++)
{
nsh_output(vtbl, " ");
for (j = 0, k = i; j < CMDS_PER_LINE && k < NUM_CMDS; j++, k += CMDS_PER_LINE)
for (j = 0, k = i; j < CMDS_PER_LINE && k < NUM_CMDS; j++, k += NUM_CMD_ROWS)
{
nsh_output(vtbl, "%-12s", g_cmdmap[k].cmd);
}
@@ -453,7 +457,7 @@ static inline void help_cmdlist(FAR struct nsh_vtbl_s *vtbl)
* Name: help_usage
****************************************************************************/
#ifndef CONFIG_NSH_DISABLE_HELP
#if !defined(CONFIG_NSH_DISABLE_HELP) && !defined(CONFIG_NSH_HELP_TERSE)
static inline void help_usage(FAR struct nsh_vtbl_s *vtbl)
{
nsh_output(vtbl, "NSH command forms:\n");
@@ -512,6 +516,7 @@ static int help_cmd(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd)
{
/* Yes... show it */
nsh_output(vtbl, "%s usage:", cmd);
help_showcmd(vtbl, cmdmap);
return OK;
}
@@ -526,7 +531,7 @@ static int help_cmd(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd)
* Name: help_allcmds
****************************************************************************/
#ifndef CONFIG_NSH_DISABLE_HELP
#if !defined(CONFIG_NSH_DISABLE_HELP) && !defined(CONFIG_NSH_HELP_TERSE)
static inline void help_allcmds(FAR struct nsh_vtbl_s *vtbl)
{
FAR const struct cmdmap_s *cmdmap;
@@ -569,12 +574,15 @@ static inline void help_builtins(FAR struct nsh_vtbl_s *vtbl)
#ifndef CONFIG_NSH_DISABLE_HELP
static int cmd_help(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
bool verbose = false;
FAR const char *cmd = NULL;
#ifndef CONFIG_NSH_HELP_TERSE
bool verbose = false;
int i;
#endif
/* The command may be followed by a verbose option */
#ifndef CONFIG_NSH_HELP_TERSE
i = 1;
if (argc > i)
{
@@ -598,6 +606,12 @@ static int cmd_help(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
help_usage(vtbl);
}
#else
if (argc > 1)
{
cmd = argv[1];
}
#endif
/* Are we showing help on a single command? */
@@ -605,13 +619,13 @@ static int cmd_help(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
/* Yes.. show the single command */
nsh_output(vtbl, "%s usage:", cmd);
help_cmd(vtbl, cmd);
}
else
{
/* In verbose mode, show detailed help for all commands */
#ifndef CONFIG_NSH_HELP_TERSE
if (verbose)
{
nsh_output(vtbl, "Where <cmd> is one of:\n");
@@ -621,8 +635,8 @@ static int cmd_help(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
/* Otherwise, just show the list of command names */
else
#endif
{
nsh_output(vtbl, "help usage:");
help_cmd(vtbl, "help");
nsh_output(vtbl, "\n");
help_cmdlist(vtbl);
+12 -8
View File
@@ -226,7 +226,7 @@ FMUServo::task_main()
while (!_task_should_exit) {
/* sleep waiting for data, but no more than 100ms */
int ret = ::poll(&fds[0], 2, 100);
int ret = ::poll(&fds[0], 2, 1000);
/* this would be bad... */
if (ret < 0) {
@@ -239,17 +239,21 @@ FMUServo::task_main()
if (fds[0].revents & POLLIN) {
float outputs[num_outputs];
/* get controls */
/* get controls - must always do this to avoid spinning */
orb_copy(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, _t_actuators, &_controls);
/* do mixing */
_mixers->mix(&outputs[0], num_outputs);
/* can we mix? */
if (_mixers != nullptr) {
/* iterate actuators */
for (unsigned i = 0; i < num_outputs; i++) {
/* do mixing */
_mixers->mix(&outputs[0], num_outputs);
/* scale for PWM output 900 - 2100us */
up_pwm_servo_set(i, 1500 + (600 * outputs[i]));
/* iterate actuators */
for (unsigned i = 0; i < num_outputs; i++) {
/* scale for PWM output 900 - 2100us */
up_pwm_servo_set(i, 1500 + (600 * outputs[i]));
}
}
}
+11 -11
View File
@@ -151,15 +151,15 @@ SimpleMixer::mix(float *outputs, unsigned space)
if (space < 1)
return 0;
for (unsigned i = 0; i < _info->input_count; i++) {
for (unsigned i = 0; i < _info->control_count; i++) {
float input;
_control_cb(_cb_handle,
_info->inputs[i].control_group,
_info->inputs[i].control_index,
_info->controls[i].control_group,
_info->controls[i].control_index,
input);
sum += scale(_info->inputs[i].scaler, input);
sum += scale(_info->controls[i].scaler, input);
}
*outputs = scale(_info->output_scaler, sum);
return 1;
@@ -168,8 +168,8 @@ SimpleMixer::mix(float *outputs, unsigned space)
void
SimpleMixer::groups_required(uint32_t &groups)
{
for (unsigned i = 0; i < _info->input_count; i++)
groups |= 1 << _info->inputs[i].control_group;
for (unsigned i = 0; i < _info->control_count; i++)
groups |= 1 << _info->controls[i].control_group;
}
int
@@ -180,7 +180,7 @@ SimpleMixer::check()
/* sanity that presumes that a mixer includes a control no more than once */
/* max of 32 groups due to groups_required API */
if (_info->input_count > 32)
if (_info->control_count > 32)
return -2;
/* validate the output scaler */
@@ -190,18 +190,18 @@ SimpleMixer::check()
return ret;
/* validate input scalers */
for (unsigned i = 0; i < _info->input_count; i++) {
for (unsigned i = 0; i < _info->control_count; i++) {
/* verify that we can fetch the control */
if (_control_cb(_cb_handle,
_info->inputs[i].control_group,
_info->inputs[i].control_index,
_info->controls[i].control_group,
_info->controls[i].control_index,
junk) != 0) {
return -3;
}
/* validate the scaler */
ret = scale_check(_info->inputs[i].scaler);
ret = scale_check(_info->controls[i].scaler);
if (ret != 0)
return (10 * i + ret);
+74 -23
View File
@@ -53,6 +53,9 @@
#include "mixer.h"
#define debug(fmt, args...) do { } while(0)
//#define debug(fmt, args...) do { printf("[mixer] " fmt "\n", ##args); } while(0)
namespace
{
@@ -76,8 +79,10 @@ mixer_getline(int fd, char *line, unsigned maxlen)
ret = read(fd, &c, 1);
/* on error or EOF, return same */
if (ret <= 0)
if (ret <= 0) {
debug("read: EOF");
return ret;
}
/* ignore carriage returns */
if (c == '\r')
@@ -94,6 +99,7 @@ mixer_getline(int fd, char *line, unsigned maxlen)
/* terminate line as string and return */
*p = '\0';
debug("read: '%s'", line);
return 1;
}
@@ -105,17 +111,42 @@ mixer_getline(int fd, char *line, unsigned maxlen)
}
/**
* Parse a scaler from the buffer.
* Parse an output scaler from the buffer.
*/
static int
mixer_parse_scaler(const char *buf, mixer_scaler_s &scaler, uint8_t &control_group, uint8_t &control_index)
mixer_parse_output_scaler(const char *buf, mixer_scaler_s &scaler)
{
int s[5];
if (sscanf(buf, "O: %d %d %d %d %d",
&s[0], &s[1], &s[2], &s[3], &s[4]) != 5) {
debug("scaler parse failed on '%s'", buf);
return -1;
}
scaler.negative_scale = s[0] / 10000.0f;
scaler.positive_scale = s[1] / 10000.0f;
scaler.offset = s[2] / 10000.0f;
scaler.min_output = s[3] / 10000.0f;
scaler.max_output = s[4] / 10000.0f;
return 0;
}
/**
* Parse a control scaler from the buffer.
*/
static int
mixer_parse_control_scaler(const char *buf, mixer_scaler_s &scaler, uint8_t &control_group, uint8_t &control_index)
{
unsigned u[2];
int s[5];
if (sscanf(buf, "S: %u %u %d %d %d %d %d",
&u[0], &u[1], &s[0], &s[1], &s[2], &s[3], &s[4]) != 7)
&u[0], &u[1], &s[0], &s[1], &s[2], &s[3], &s[4]) != 7) {
debug("scaler parse failed on '%s'", buf);
return -1;
}
control_group = u[0];
control_index = u[1];
@@ -133,7 +164,6 @@ mixer_load_simple(Mixer::ControlCallback control_cb, uintptr_t cb_handle, int fd
{
mixer_simple_s *mixinfo = nullptr;
char buf[60];
uint8_t control_group, control_index;
int ret;
/* let's assume we're going to read a simple mixer */
@@ -141,22 +171,30 @@ mixer_load_simple(Mixer::ControlCallback control_cb, uintptr_t cb_handle, int fd
/* first, get the output scaler */
ret = mixer_getline(fd, buf, sizeof(buf));
if (ret < 1)
if (ret < 1) {
debug("failed reading for output scaler");
goto fail;
if (mixer_parse_scaler(buf, mixinfo->output_scaler, control_group, control_index))
}
if (mixer_parse_output_scaler(buf, mixinfo->output_scaler)) {
debug("failed parsing output scaler");
goto fail;
}
/* now get any inputs */
for (unsigned i = 0; i < inputs; i++) {
ret = mixer_getline(fd, buf, sizeof(buf));
if (ret < 1)
goto fail;
if (mixer_parse_scaler(buf,
mixinfo->inputs[i].scaler,
mixinfo->inputs[i].control_group,
mixinfo->inputs[i].control_index)) {
if (ret < 1) {
debug("failed reading for control scaler");
goto fail;
}
if (mixer_parse_control_scaler(buf,
mixinfo->controls[i].scaler,
mixinfo->controls[i].control_group,
mixinfo->controls[i].control_index)) {
debug("failed parsing control scaler");
goto fail;
}
debug("got control %d", i);
}
/* XXX should be a factory that validates the mixinfo ... */
@@ -172,27 +210,32 @@ mixer_load(Mixer::ControlCallback control_cb, uintptr_t cb_handle, int fd, Mixer
{
int ret;
char buf[60];
unsigned scalers;
unsigned inputs;
ret = mixer_getline(fd, buf, sizeof(buf));
/* end of file or error ?*/
if (ret < 1)
if (ret < 1) {
debug("getline %d", ret);
return ret;
}
/* slot is empty - allocate a null mixer */
if (buf[0] == 'Z') {
debug("got null mixer");
mixer = new NullMixer();
return 0;
return 1;
}
/* is it a simple mixer? */
if (sscanf(buf, "M: %u", &scalers) == 1) {
mixer = mixer_load_simple(control_cb, cb_handle, fd, scalers);
return (mixer == nullptr) ? -1 : 0;
if (sscanf(buf, "M: %u", &inputs) == 1) {
debug("got simple mixer with %d inputs", inputs);
mixer = mixer_load_simple(control_cb, cb_handle, fd, inputs);
return (mixer == nullptr) ? -1 : 1;
}
/* we don't recognise the mixer type */
debug("unrecognized mixer type '%c'", buf[0]);
return -1;
}
@@ -260,10 +303,12 @@ MixerGroup::load_from_file(const char *path)
return -1;
int fd = open(path, O_RDONLY);
if (fd < 0)
if (fd < 0) {
debug("failed to open %s", path);
return -1;
}
for (;;) {
for (unsigned count = 0;; count++) {
int result;
Mixer *mixer;
@@ -273,13 +318,19 @@ MixerGroup::load_from_file(const char *path)
mixer);
/* error? */
if (result < 0)
if (result < 0) {
debug("error");
return -1;
}
/* EOF or error */
if (result < 1)
if (result < 1) {
printf("[mixer] loaded %u mixers\n", count);
debug("EOF");
break;
}
debug("loaded mixer %p", mixer);
add_mixer(mixer);
}