PWM Melodies¶
A landed rocket needs a way to communicate its position to the searching squad. One simple way of making it easier to find is to play loud buzzer sounds in an endless loop until the recovery team finds it.
But only playing loud noises is boring and annoying in testing. Instead, use the PWM Melody API to play music of your liking:
/ {
buzzer0: buzzer_0 {
compatible = "auxspaceev,pwm-buzzer";
pwms = <&ledc0 0 PWM_MSEC(200) PWM_POLARITY_NORMAL>;
};
};
#include <aurora/lib/pwm_melody.h>
// dt node that contains a "pwms" child node
static const struct pwm_dt_spec buzzer =
PWM_DT_SPEC_GET(DT_NODELABEL(buzzer0));
// play astronomia from aurora/lib/pwm_melody.h
PWM_MELODY_CTX_DEFINE(melody_ctx, &buzzer, astronomia, 1024);
int main()
{
pwm_melody_start(&melody_ctx);
// --snip--
// play as long as needed
// --snip
pwm_melody_stop(&melody_ctx);
}
Several Tunes, One Buzzer¶
A board has one buzzer, so two playback threads would fight over the
same PWM output. Melodies therefore share a single context and are
switched with pwm_melody_play(), which stops the current tune,
waits for its thread to be gone, and starts the new one:
// while the post-flight log conversion runs
pwm_melody_play(&melody_ctx, mii_channel, ARRAY_SIZE(mii_channel));
// ... and back to the recovery beacon when it is done
pwm_melody_play(&melody_ctx, astronomia, ARRAY_SIZE(astronomia));
The melodies shipped in aurora/lib/pwm_melody.h:
Melody |
Used for |
|---|---|
|
Post-landing recovery beacon. |
|
Post-flight log conversion in progress (arming is held off meanwhile). |
Playback loops until stopped, with a 500 ms gap between repeats.
Note
A melody has to survive a single square-wave channel with no dynamics, so
pick tunes that are carried by their melody line. mii_channel is the
tune usually meant by “the Wii menu music”; the actual Wii System Menu
music is carried by its harmony and reduces to something unrecognisable
on one buzzer.
API Reference¶
-
static const struct pwm_melody_note astronomia[] = {{466, 4}, {466, 4}, {466, 4}, {466, 4}, {466, 4}, {466, 4}, {466, 4}, {466, 4}, {466, 4}, {466, 4}, {466, 4}, {466, 4}, {466, 4}, {466, 4}, {466, 4}, {466, 4}, {466, 4}, {466, 4}, {466, 4}, {466, 4}, {587, 4}, {587, 4}, {587, 4}, {587, 4}, {523, 4}, {523, 4}, {523, 4}, {523, 4}, {698, 4}, {698, 4}, {698, 4}, {698, 4}, {784, 4}, {784, 4}, {784, 4}, {784, 4}, {784, 4}, {784, 4}, {784, 4}, {784, 4}, {784, 4}, {784, 4}, {784, 4}, {784, 4}, {523, 4}, {466, 4}, {440, 4}, {349, 4}, {392, 4}, {0, 4}, {392, 4}, {587, 4}, {523, 4}, {0, 4}, {466, 4}, {0, 4}, {440, 4}, {0, 4}, {440, 4}, {440, 4}, {523, 4}, {0, 4}, {466, 4}, {440, 4}, {392, 4}, {0, 4}, {392, 4}, {932, 4}, {880, 4}, {932, 4}, {880, 4}, {932, 4}, {392, 4}, {0, 4}, {392, 4}, {932, 4}, {880, 4}, {932, 4}, {880, 4}, {932, 4}, {392, 4}, {0, 4}, {392, 4}, {587, 4}, {523, 4}, {0, 4}, {466, 4}, {0, 4}, {440, 4}, {0, 4}, {440, 4}, {440, 4}, {523, 4}, {0, 4}, {466, 4}, {440, 4}, {392, 4}, {0, 4}, {392, 4}, {932, 4}, {880, 4}, {932, 4}, {880, 4}, {932, 4}, {392, 4}, {0, 4}, {392, 4}, {932, 4}, {880, 4}, {932, 4}, {880, 4}, {932, 4},}¶
Astronomia (Coffin Dance) melody. Ideal for post-flight celebration.
-
static const struct pwm_melody_note mii_channel[] = {{370, 4}, {0, 4}, {440, 4}, {554, 4}, {0, 4}, {440, 4}, {0, 4}, {370, 4}, {294, 4}, {294, 4}, {294, 4}, {0, 4}, {0, 2}, {0, 2}, {277, 4}, {0, 4}, {294, 4}, {0, 4}, {370, 4}, {0, 4}, {440, 4}, {0, 4}, {554, 4}, {0, 4}, {440, 4}, {0, 4}, {740, 4}, {659, 4}, {698, 4}, {0, 4}, {740, 4}, {0, 4}, {698, 4}, {740, 4}, {880, 4}, {0, 4}, {554, 4}, {0, 4}, {587, 4}, {554, 4}, {523, 4}, {0, 4}, {523, 4}, {440, 4}, {0, 4}, {440, 4}, {587, 4}, {0, 4}, {554, 4}, {0, 4}, {466, 4}, {0, 4}, {466, 4}, {587, 4}, {554, 4}, {0, 4}, {466, 4}, {0, 4}, {440, 2}, {0, 2},}¶
Mii Channel theme.
-
int pwm_melody_start(struct pwm_melody_ctx *ctx)¶
Start playing a melody.
Stops any melody already playing, then spawns a thread that iterates over the notes in
ctxand drives the PWM output accordingly.- Parameters:
ctx – Melody player context (must have been initialised, e.g. via PWM_MELODY_CTX_DEFINE).
- Return values:
-EBUSY – The previous playback thread did not terminate in time, so its context could not be reused. Nothing was started.
- Returns:
0 on success, or a negative error code.
-
int pwm_melody_stop(struct pwm_melody_ctx *ctx)¶
Stop a melody that is currently playing.
Signals the playback thread to stop and waits for it to terminate. The PWM output is turned off before returning.
- Parameters:
ctx – Melody player context.
- Return values:
-EBUSY – The thread did not terminate within the join timeout. The context is still in use and must not be restarted; the PWM output is left untouched.
- Returns:
0 once no playback thread is running (including when none was).
-
int pwm_melody_play(struct pwm_melody_ctx *ctx, const struct pwm_melody_note *notes, size_t num_notes)¶
Play a specific melody on an existing context.
Stops whatever
ctxis currently playing, points it atnotesand starts playback.- Parameters:
ctx – Melody player context (e.g. from PWM_MELODY_CTX_DEFINE).
notes – Array of pwm_melody_note to play.
num_notes – Number of notes in
notes.
- Return values:
-EINVAL –
ctxornotesis NULL, ornum_notesis 0.-EBUSY – The previous playback thread did not terminate in time. Nothing was changed and nothing was started.
- Returns:
0 on success, or a negative error code.
-
PWM_MELODY_CTX_DEFINE(_name, _pwm, _notes, _stack_size)¶
Statically define and initialize a melody player context.
This macro allocates the thread stack and initialises the context struct.
- Parameters:
_name – Variable name for the context.
_pwm – Pointer to a
pwm_dt_specfor the buzzer output._notes – Array of pwm_melody_note to play.
_stack_size – Stack size in bytes for the playback thread.
-
struct pwm_melody_note¶
- #include <pwm_melody.h>
A single note in a melody.
-
struct pwm_melody_ctx¶
- #include <pwm_melody.h>
Runtime context for a melody player instance.