mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-04-14 10:07:39 +08:00
libtunes: Changed to a set_control/string and a get_next_tune functions
Now it is possible to set a string and a control. The get_next_tune function use the same return values as the erliaer implemented parse_cmd and parse_string functions.
This commit is contained in:
parent
5214642bc3
commit
b84a97c6d5
@ -52,7 +52,7 @@
|
||||
// initialise default tunes
|
||||
const char *Tunes::_default_tunes[] = {
|
||||
"", // empty to align with the index
|
||||
"MFT240L8 O2aO3dc O2aO3dc O2aO3dc L16dcdcdcdc", // startup tune
|
||||
"MFT240L8 O4aO5dc O4aO5dc O4aO5dc L16dcdcdcdc", // startup tune
|
||||
"MBT200a8a8a8PaaaP", // ERROR tone
|
||||
"MFT200e8a8a", // Notify Positive tone
|
||||
"MFT200e8e", // Notify Neutral tone
|
||||
@ -98,160 +98,66 @@ void Tunes::config_tone()
|
||||
_octave = _default_octave;
|
||||
}
|
||||
|
||||
int Tunes::parse_cmd(const tune_control_s &tune_control, unsigned &frequency, unsigned &duration, unsigned &silence)
|
||||
void Tunes::set_control(const tune_control_s &tune_control)
|
||||
{
|
||||
int continue_sequnece = 0;
|
||||
bool reset_playing_tune = false;
|
||||
|
||||
switch (tune_control.tune_id) {
|
||||
case tune_control_s::STARTUP:
|
||||
case tune_control_s::ERROR:
|
||||
case tune_control_s::NOTIFY_POSITIVE:
|
||||
case tune_control_s::NOTIFY_NEUTRAL:
|
||||
case tune_control_s::NOTIFY_NEGATIVE:
|
||||
case tune_control_s::ARMING_WARNING:
|
||||
case tune_control_s::BATTERY_WARNING_SLOW:
|
||||
case tune_control_s::BATTERY_WARNING_FAST:
|
||||
case tune_control_s::GPS_WARNING:
|
||||
case tune_control_s::PARACHUTE_RELEASE:
|
||||
case tune_control_s::EKF_WARNING:
|
||||
case tune_control_s::BARO_WARNING:
|
||||
case tune_control_s::SINGLE_BEEP:
|
||||
case tune_control_s::HOME_SET:
|
||||
case tune_control_s::TUNE_ID_STARTUP:
|
||||
case tune_control_s::TUNE_ID_ERROR:
|
||||
reset_playing_tune = true;
|
||||
config_tone();
|
||||
|
||||
// set tune string the first time
|
||||
if (_tune == nullptr) {
|
||||
case tune_control_s::TUNE_ID_NOTIFY_POSITIVE:
|
||||
case tune_control_s::TUNE_ID_NOTIFY_NEUTRAL:
|
||||
case tune_control_s::TUNE_ID_NOTIFY_NEGATIVE:
|
||||
case tune_control_s::TUNE_ID_ARMING_WARNING:
|
||||
case tune_control_s::TUNE_ID_BATTERY_WARNING_SLOW:
|
||||
case tune_control_s::TUNE_ID_BATTERY_WARNING_FAST:
|
||||
case tune_control_s::TUNE_ID_GPS_WARNING:
|
||||
case tune_control_s::TUNE_ID_PARACHUTE_RELEASE:
|
||||
case tune_control_s::TUNE_ID_EKF_WARNING:
|
||||
case tune_control_s::TUNE_ID_BARO_WARNING:
|
||||
case tune_control_s::TUNE_ID_SINGLE_BEEP:
|
||||
case tune_control_s::TUNE_ID_HOME_SET:
|
||||
|
||||
// TODO: come up with a better strategy
|
||||
if (_tune == nullptr || reset_playing_tune) {
|
||||
_tune = _default_tunes[tune_control.tune_id];
|
||||
_next = _tune;
|
||||
}
|
||||
|
||||
continue_sequnece = next_note(frequency, duration, silence);
|
||||
break;
|
||||
|
||||
case tune_control_s::CUSTOM:
|
||||
case tune_control_s::TUNE_ID_CUSTOM:
|
||||
default:
|
||||
frequency = (unsigned)tune_control.frequency;
|
||||
duration = (unsigned)tune_control.duration;
|
||||
silence = 0;
|
||||
_frequency = (unsigned)tune_control.frequency;
|
||||
_duration = (unsigned)tune_control.duration;
|
||||
_using_custom_msg = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return continue_sequnece;
|
||||
}
|
||||
|
||||
int Tunes::parse_string(const char *string, unsigned &frequency, unsigned &duration, unsigned &silence)
|
||||
void Tunes::set_string(const char *string)
|
||||
{
|
||||
// set tune string the first time
|
||||
if (_tune == nullptr) {
|
||||
_tune = string;
|
||||
_next = _tune;
|
||||
}
|
||||
|
||||
return next_note(frequency, duration, silence);
|
||||
}
|
||||
|
||||
unsigned Tunes::note_to_frequency(unsigned note)
|
||||
int Tunes::get_next_tune(unsigned &frequency, unsigned &duration, unsigned &silence)
|
||||
{
|
||||
// compute the frequency (Hz)
|
||||
return (unsigned)(880.0f * powf(2.0f, ((int)note - 46) / 12.0f));
|
||||
}
|
||||
|
||||
unsigned Tunes::note_duration(unsigned &silence, unsigned note_length, unsigned dots)
|
||||
{
|
||||
unsigned whole_note_period = BEAT_TIME_CONVERSION / _tempo;
|
||||
|
||||
if (note_length == 0) {
|
||||
note_length = 1;
|
||||
}
|
||||
|
||||
unsigned note_period = whole_note_period / note_length;
|
||||
|
||||
switch (_note_mode) {
|
||||
case NoteMode::NORMAL:
|
||||
silence = note_period / 8;
|
||||
break;
|
||||
|
||||
case NoteMode::STACCATO:
|
||||
silence = note_period / 4;
|
||||
break;
|
||||
|
||||
case NoteMode::LEGATO:
|
||||
default:
|
||||
// Return the vaules for frequency and duration if the custom msg was recieved
|
||||
if (_using_custom_msg) {
|
||||
_using_custom_msg = false;
|
||||
frequency = _frequency;
|
||||
duration = _duration;
|
||||
silence = 0;
|
||||
break;
|
||||
return TUNE_STOP;
|
||||
}
|
||||
|
||||
note_period -= silence;
|
||||
|
||||
unsigned dot_extension = note_period / 2;
|
||||
|
||||
while (dots--) {
|
||||
note_period += dot_extension;
|
||||
dot_extension /= 2;
|
||||
}
|
||||
|
||||
return note_period;
|
||||
}
|
||||
|
||||
unsigned Tunes::rest_duration(unsigned rest_length, unsigned dots)
|
||||
{
|
||||
unsigned whole_note_period = BEAT_TIME_CONVERSION / _tempo;
|
||||
|
||||
if (rest_length == 0) {
|
||||
rest_length = 1;
|
||||
}
|
||||
|
||||
unsigned rest_period = whole_note_period / rest_length;
|
||||
|
||||
unsigned dot_extension = rest_period / 2;
|
||||
|
||||
while (dots--) {
|
||||
rest_period += dot_extension;
|
||||
dot_extension /= 2;
|
||||
}
|
||||
|
||||
return rest_period;
|
||||
}
|
||||
|
||||
int Tunes::next_char()
|
||||
{
|
||||
while (isspace(*_next)) {
|
||||
_next++;
|
||||
}
|
||||
|
||||
return toupper(*_next);
|
||||
}
|
||||
|
||||
unsigned Tunes::next_number()
|
||||
{
|
||||
unsigned number = 0;
|
||||
int c;
|
||||
|
||||
for (;;) {
|
||||
c = next_char();
|
||||
|
||||
if (!isdigit(c)) {
|
||||
return number;
|
||||
}
|
||||
|
||||
_next++;
|
||||
number = (number * 10) + (c - '0');
|
||||
}
|
||||
}
|
||||
|
||||
unsigned Tunes::next_dots()
|
||||
{
|
||||
unsigned dots = 0;
|
||||
|
||||
while (next_char() == '.') {
|
||||
_next++;
|
||||
dots++;
|
||||
}
|
||||
|
||||
return dots;
|
||||
}
|
||||
|
||||
int Tunes::next_note(unsigned &frequency, unsigned &duration, unsigned &silence)
|
||||
{
|
||||
// make sure we still have a tune
|
||||
if ((_next == nullptr) || (_tune == nullptr)) {
|
||||
return TUNE_ERROR;
|
||||
@ -441,3 +347,104 @@ tune_end:
|
||||
return TUNE_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned Tunes::note_to_frequency(unsigned note)
|
||||
{
|
||||
// compute the frequency (Hz)
|
||||
return (unsigned)(880.0f * powf(2.0f, ((int)note - 46) / 12.0f));
|
||||
}
|
||||
|
||||
unsigned Tunes::note_duration(unsigned &silence, unsigned note_length, unsigned dots)
|
||||
{
|
||||
unsigned whole_note_period = BEAT_TIME_CONVERSION / _tempo;
|
||||
|
||||
if (note_length == 0) {
|
||||
note_length = 1;
|
||||
}
|
||||
|
||||
unsigned note_period = whole_note_period / note_length;
|
||||
|
||||
switch (_note_mode) {
|
||||
case NoteMode::NORMAL:
|
||||
silence = note_period / 8;
|
||||
break;
|
||||
|
||||
case NoteMode::STACCATO:
|
||||
silence = note_period / 4;
|
||||
break;
|
||||
|
||||
case NoteMode::LEGATO:
|
||||
default:
|
||||
silence = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
note_period -= silence;
|
||||
|
||||
unsigned dot_extension = note_period / 2;
|
||||
|
||||
while (dots--) {
|
||||
note_period += dot_extension;
|
||||
dot_extension /= 2;
|
||||
}
|
||||
|
||||
return note_period;
|
||||
}
|
||||
|
||||
unsigned Tunes::rest_duration(unsigned rest_length, unsigned dots)
|
||||
{
|
||||
unsigned whole_note_period = BEAT_TIME_CONVERSION / _tempo;
|
||||
|
||||
if (rest_length == 0) {
|
||||
rest_length = 1;
|
||||
}
|
||||
|
||||
unsigned rest_period = whole_note_period / rest_length;
|
||||
|
||||
unsigned dot_extension = rest_period / 2;
|
||||
|
||||
while (dots--) {
|
||||
rest_period += dot_extension;
|
||||
dot_extension /= 2;
|
||||
}
|
||||
|
||||
return rest_period;
|
||||
}
|
||||
|
||||
int Tunes::next_char()
|
||||
{
|
||||
while (isspace(*_next)) {
|
||||
_next++;
|
||||
}
|
||||
|
||||
return toupper(*_next);
|
||||
}
|
||||
|
||||
unsigned Tunes::next_number()
|
||||
{
|
||||
unsigned number = 0;
|
||||
int c;
|
||||
|
||||
for (;;) {
|
||||
c = next_char();
|
||||
|
||||
if (!isdigit(c)) {
|
||||
return number;
|
||||
}
|
||||
|
||||
_next++;
|
||||
number = (number * 10) + (c - '0');
|
||||
}
|
||||
}
|
||||
|
||||
unsigned Tunes::next_dots()
|
||||
{
|
||||
unsigned dots = 0;
|
||||
|
||||
while (next_char() == '.') {
|
||||
_next++;
|
||||
dots++;
|
||||
}
|
||||
|
||||
return dots;
|
||||
}
|
||||
|
||||
@ -64,27 +64,28 @@ public:
|
||||
~Tunes() = default;
|
||||
|
||||
/**
|
||||
* parse a tune_control_s in frequency(Hz), duration(us) and silence(us).
|
||||
* Set tune to be played
|
||||
*
|
||||
* @param tune_control struct containig the uORB message
|
||||
* @param frequency return frequency value (Hz)
|
||||
* @param duration return duration of the tone (us)
|
||||
* @param silence return silance duration (us)
|
||||
* @return -1 for error, 0 for play one tone and 1 for continue a sequence
|
||||
*/
|
||||
int parse_cmd(const tune_control_s &tune_control, unsigned &frequency, unsigned &duration, unsigned &silence);
|
||||
void set_control(const tune_control_s &tune_control);
|
||||
|
||||
/**
|
||||
* parse a tune string, formatted with the syntax of the Microsoft GWBasic/QBasic, in frequency(Hz),
|
||||
* duration(us) and silence(us).
|
||||
*
|
||||
* @param string tune input string
|
||||
*/
|
||||
void set_string(const char *string);
|
||||
|
||||
/**
|
||||
* Get next note in the setted string in set_control or play_string
|
||||
* @param frequency return frequency value (Hz)
|
||||
* @param duration return duration of the tone (us)
|
||||
* @param silence return silance duration (us)
|
||||
* @param silence return silence duration (us)
|
||||
* @return -1 for error, 0 for play one tone and 1 for continue a sequence
|
||||
*/
|
||||
int parse_string(const char *string, unsigned &frequency, unsigned &duration, unsigned &silence);
|
||||
int get_next_tune(unsigned &frequency, unsigned &duration, unsigned &silence);
|
||||
|
||||
private:
|
||||
static const char *_default_tunes[TONE_NUMBER_OF_TUNES];
|
||||
@ -104,6 +105,10 @@ private:
|
||||
NoteMode _default_mode = NoteMode::NORMAL;
|
||||
unsigned _default_octave = 4;
|
||||
|
||||
unsigned _frequency;
|
||||
unsigned _duration;
|
||||
bool _using_custom_msg = false;
|
||||
|
||||
/**
|
||||
* Convert note to frequency
|
||||
*
|
||||
@ -129,10 +134,6 @@ private:
|
||||
//
|
||||
unsigned rest_duration(unsigned rest_length, unsigned dots);
|
||||
|
||||
// Parse the next note out of the string
|
||||
//
|
||||
int next_note(unsigned &frequency, unsigned &duration, unsigned &silence);
|
||||
|
||||
// Find the next character in the string, discard any whitespace and
|
||||
// return the canonical (uppercase) version.
|
||||
//
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user