mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-06-06 06:43:21 +08:00
Factory method for a simple mixer that converts PWM/PPM values to the standard internal format.
This commit is contained in:
@@ -335,7 +335,7 @@ public:
|
|||||||
~SimpleMixer();
|
~SimpleMixer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method.
|
* Factory method with full external configuration.
|
||||||
*
|
*
|
||||||
* Given a pointer to a buffer containing a text description of the mixer,
|
* Given a pointer to a buffer containing a text description of the mixer,
|
||||||
* returns a pointer to a new instance of the mixer.
|
* returns a pointer to a new instance of the mixer.
|
||||||
@@ -351,9 +351,29 @@ public:
|
|||||||
* if the text format is bad.
|
* if the text format is bad.
|
||||||
*/
|
*/
|
||||||
static SimpleMixer *from_text(Mixer::ControlCallback control_cb,
|
static SimpleMixer *from_text(Mixer::ControlCallback control_cb,
|
||||||
uintptr_t cb_handle,
|
uintptr_t cb_handle,
|
||||||
const char *buf,
|
const char *buf,
|
||||||
unsigned &buflen);
|
unsigned &buflen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method for PWM/PPM input to internal float representation.
|
||||||
|
*
|
||||||
|
* @param control_cb The callback to invoke when fetching a
|
||||||
|
* control value.
|
||||||
|
* @param cb_handle Handle passed to the control callback.
|
||||||
|
* @param input The control index used when fetching the input.
|
||||||
|
* @param min The PWM/PPM value considered to be "minimum" (gives -1.0 out)
|
||||||
|
* @param mid The PWM/PPM value considered to be the midpoint (gives 0.0 out)
|
||||||
|
* @param max The PWM/PPM value considered to be "maximum" (gives 1.0 out)
|
||||||
|
* @return A new SimpleMixer instance, or nullptr if one could not be
|
||||||
|
* allocated.
|
||||||
|
*/
|
||||||
|
static SimpleMixer *pwm_input(Mixer::ControlCallback *control_cb,
|
||||||
|
uintptr_t cb_handle,
|
||||||
|
unsigned input,
|
||||||
|
uint16_t min,
|
||||||
|
uint16_t mid,
|
||||||
|
uint16_t max);
|
||||||
|
|
||||||
virtual unsigned mix(float *outputs, unsigned space);
|
virtual unsigned mix(float *outputs, unsigned space);
|
||||||
virtual void groups_required(uint32_t &groups);
|
virtual void groups_required(uint32_t &groups);
|
||||||
@@ -375,10 +395,10 @@ private:
|
|||||||
|
|
||||||
static int parse_output_scaler(const char *buf, unsigned &buflen, mixer_scaler_s &scaler);
|
static int parse_output_scaler(const char *buf, unsigned &buflen, mixer_scaler_s &scaler);
|
||||||
static int parse_control_scaler(const char *buf,
|
static int parse_control_scaler(const char *buf,
|
||||||
unsigned &buflen,
|
unsigned &buflen,
|
||||||
mixer_scaler_s &scaler,
|
mixer_scaler_s &scaler,
|
||||||
uint8_t &control_group,
|
uint8_t &control_group,
|
||||||
uint8_t &control_index);
|
uint8_t &control_index);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -457,9 +477,9 @@ public:
|
|||||||
* if the text format is bad.
|
* if the text format is bad.
|
||||||
*/
|
*/
|
||||||
static MultirotorMixer *from_text(Mixer::ControlCallback control_cb,
|
static MultirotorMixer *from_text(Mixer::ControlCallback control_cb,
|
||||||
uintptr_t cb_handle,
|
uintptr_t cb_handle,
|
||||||
const char *buf,
|
const char *buf,
|
||||||
unsigned &buflen);
|
unsigned &buflen);
|
||||||
|
|
||||||
virtual unsigned mix(float *outputs, unsigned space);
|
virtual unsigned mix(float *outputs, unsigned space);
|
||||||
virtual void groups_required(uint32_t &groups);
|
virtual void groups_required(uint32_t &groups);
|
||||||
|
|||||||
@@ -77,9 +77,11 @@ skipspace(const char *p, unsigned &len)
|
|||||||
while (isspace(*p)) {
|
while (isspace(*p)) {
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
len--;
|
len--;
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,14 +93,16 @@ SimpleMixer::parse_output_scaler(const char *buf, unsigned &buflen, mixer_scaler
|
|||||||
int used;
|
int used;
|
||||||
|
|
||||||
buf = skipspace(buf, buflen);
|
buf = skipspace(buf, buflen);
|
||||||
|
|
||||||
if (buflen < 16)
|
if (buflen < 16)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if ((ret = sscanf(buf, "O: %d %d %d %d %d%n",
|
if ((ret = sscanf(buf, "O: %d %d %d %d %d%n",
|
||||||
&s[0], &s[1], &s[2], &s[3], &s[4], &used)) != 5) {
|
&s[0], &s[1], &s[2], &s[3], &s[4], &used)) != 5) {
|
||||||
debug("scaler parse failed on '%s' (got %d)", buf, ret);
|
debug("scaler parse failed on '%s' (got %d)", buf, ret);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
buflen -= used;
|
buflen -= used;
|
||||||
|
|
||||||
scaler.negative_scale = s[0] / 10000.0f;
|
scaler.negative_scale = s[0] / 10000.0f;
|
||||||
@@ -118,6 +122,7 @@ SimpleMixer::parse_control_scaler(const char *buf, unsigned &buflen, mixer_scale
|
|||||||
int used;
|
int used;
|
||||||
|
|
||||||
buf = skipspace(buf, buflen);
|
buf = skipspace(buf, buflen);
|
||||||
|
|
||||||
if (buflen < 16)
|
if (buflen < 16)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -126,6 +131,7 @@ SimpleMixer::parse_control_scaler(const char *buf, unsigned &buflen, mixer_scale
|
|||||||
debug("control parse failed on '%s'", buf);
|
debug("control parse failed on '%s'", buf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
buflen -= used;
|
buflen -= used;
|
||||||
|
|
||||||
control_group = u[0];
|
control_group = u[0];
|
||||||
@@ -153,13 +159,16 @@ SimpleMixer::from_text(Mixer::ControlCallback control_cb, uintptr_t cb_handle, c
|
|||||||
debug("simple parse failed on '%s'", buf);
|
debug("simple parse failed on '%s'", buf);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
buflen -= used;
|
buflen -= used;
|
||||||
|
|
||||||
mixinfo = (mixer_simple_s *)malloc(MIXER_SIMPLE_SIZE(inputs));
|
mixinfo = (mixer_simple_s *)malloc(MIXER_SIMPLE_SIZE(inputs));
|
||||||
|
|
||||||
if (mixinfo == nullptr) {
|
if (mixinfo == nullptr) {
|
||||||
debug("could not allocate memory for mixer info");
|
debug("could not allocate memory for mixer info");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
mixinfo->control_count = inputs;
|
mixinfo->control_count = inputs;
|
||||||
|
|
||||||
if (parse_output_scaler(end - buflen, buflen, mixinfo->output_scaler))
|
if (parse_output_scaler(end - buflen, buflen, mixinfo->output_scaler))
|
||||||
@@ -167,21 +176,84 @@ SimpleMixer::from_text(Mixer::ControlCallback control_cb, uintptr_t cb_handle, c
|
|||||||
|
|
||||||
for (unsigned i = 0; i < inputs; i++) {
|
for (unsigned i = 0; i < inputs; i++) {
|
||||||
if (parse_control_scaler(end - buflen, buflen,
|
if (parse_control_scaler(end - buflen, buflen,
|
||||||
mixinfo->controls[i].scaler,
|
mixinfo->controls[i].scaler,
|
||||||
mixinfo->controls[i].control_group,
|
mixinfo->controls[i].control_group,
|
||||||
mixinfo->controls[i].control_index))
|
mixinfo->controls[i].control_index))
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
sm = new SimpleMixer(control_cb, cb_handle, mixinfo);
|
sm = new SimpleMixer(control_cb, cb_handle, mixinfo);
|
||||||
|
|
||||||
if (sm != nullptr) {
|
if (sm != nullptr) {
|
||||||
mixinfo = nullptr;
|
mixinfo = nullptr;
|
||||||
debug("loaded mixer with %d inputs", inputs);
|
debug("loaded mixer with %d inputs", inputs);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
debug("could not allocate memory for mixer");
|
debug("could not allocate memory for mixer");
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
||||||
|
if (mixinfo != nullptr)
|
||||||
|
free(mixinfo);
|
||||||
|
|
||||||
|
return sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleMixer *
|
||||||
|
SimpleMixer::pwm_input(Mixer::ControlCallback *control_cb, uintptr_t cb_handle, unsigned input, uint16_t min, uint16_t mid, uint16_t max)
|
||||||
|
{
|
||||||
|
SimpleMixer *sm = nullptr;
|
||||||
|
mixer_simple_s *mixinfo = nullptr;
|
||||||
|
|
||||||
|
mixinfo = (mixer_simple_s *)malloc(MIXER_SIMPLE_SIZE(1));
|
||||||
|
|
||||||
|
if (mixinfo == nullptr) {
|
||||||
|
debug("could not allocate memory for mixer info");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
mixinfo->control_count = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Always pull from group 0, with the input value giving the channel.
|
||||||
|
*/
|
||||||
|
mixinfo->controls[0].control_group = 0;
|
||||||
|
mixinfo->controls[0].control_index = input;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Conversion uses both the input and output side of the mixer.
|
||||||
|
*
|
||||||
|
* The input side is used to slide the control value such that the min argument
|
||||||
|
* results in a value of zero.
|
||||||
|
*
|
||||||
|
* The output side is used to apply the scaling for the min/max values so that
|
||||||
|
* the resulting output is a -1.0 ... 1.0 value for the min...max range.
|
||||||
|
*/
|
||||||
|
mixinfo->controls[0].scaler.negative_scale = 1.0f;
|
||||||
|
mixinfo->controls[0].scaler.positive_scale = 1.0f;
|
||||||
|
mixinfo->controls[0].scaler.offset = -mid;
|
||||||
|
mixinfo->controls[0].scaler.lower_limit = -(mid - min);
|
||||||
|
mixinfo->controls[0].scaler.upper_limit = (max - mid);
|
||||||
|
|
||||||
|
mixinfo->output_scaler.negative_scale = 500.0f / (mid - min);
|
||||||
|
mixinfo->output_scaler.positive_scale = 500.0f / (max - mid);
|
||||||
|
mixinfo->output_scaler.offset = 0.0f;
|
||||||
|
mixinfo->output_scaler.min_output = -1.0f;
|
||||||
|
mixinfo->output_scaler.max_output = 1.0f;
|
||||||
|
|
||||||
|
sm = new SimpleMixer(control_cb, cb_handle, mixinfo);
|
||||||
|
|
||||||
|
if (sm != nullptr) {
|
||||||
|
mixinfo = nullptr;
|
||||||
|
debug("PWM input mixer for %d", input);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
debug("could not allocate memory for PWM input mixer");
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
|
||||||
if (mixinfo != nullptr)
|
if (mixinfo != nullptr)
|
||||||
free(mixinfo);
|
free(mixinfo);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user