31 template<board::Timer NTIMER, board::PWMPin OUTPUT,
typename TONEPLAY>
class AbstractTonePlayer;
44 static constexpr const Tone END = Tone::USER0;
71 static constexpr const Tone TIE = Tone::USER3;
135 return Duration(uint8_t(d) + uint8_t(d) / 2);
143 return Duration(uint8_t(d) * 2 / 3);
196 constexpr TonePlay(
Tone tone, uint8_t value = 0) : tone_{tone}, repeats_{value} {}
205 return tone_ > Tone::SILENCE;
207 bool is_pause()
const
209 return tone_ == Tone::SILENCE;
215 bool is_repeat_start()
const
219 bool is_repeat_end()
const
223 uint8_t repeat_count()
const
231 uint8_t num_ties()
const
236 template<board::Timer NTIMER, board::PWMPin OUTPUT>
237 void generate_tone(ToneGenerator<NTIMER, OUTPUT>& generator)
const
239 generator.start_tone(tone_);
250 template<board::Timer, board::PWMPin,
typename>
friend class AbstractTonePlayer;
268 template<board::Timer NTIMER, board::PWMPin OUTPUT>
class QTonePlay
294 : flags_{flags(tone)}, prescaler_{prescaler(tone)}, counter_{counter(tone)}, duration_{duration} {}
305 : flags_{flags(tone)}, prescaler_{prescaler(tone)}, counter_{counter(tone)}, repeats_{value} {}
319 return flags_ == TONE;
321 bool is_pause()
const
323 return flags_ == NONE;
327 return flags_ == END;
329 bool is_repeat_start()
const
331 return flags_ == REPEAT_START;
333 bool is_repeat_end()
const
335 return flags_ == REPEAT_END;
337 uint8_t repeat_count()
const
343 return flags_ == TIE;
345 uint8_t num_ties()
const
350 void generate_tone(ToneGenerator<NTIMER, OUTPUT>& generator)
const
352 generator.start_tone(prescaler_, counter_);
356 static constexpr uint8_t TONE = 0x00;
357 static constexpr uint8_t NONE = 0x01;
358 static constexpr uint8_t END = 0x02;
359 static constexpr uint8_t REPEAT_START = 0x04;
360 static constexpr uint8_t REPEAT_END = 0x08;
361 static constexpr uint8_t TIE = 0x10;
363 uint8_t flags_ =
END;
364 PRESCALER prescaler_;
373 static constexpr uint32_t period(
Tone tone)
375 return ONE_SECOND / 2 / uint16_t(tone);
377 static constexpr PRESCALER prescaler(
Tone tone)
379 return (tone > Tone::SILENCE ?
CALC::CTC_prescaler(period(tone)) : PRESCALER::NO_PRESCALING);
381 static constexpr COUNTER counter(
Tone tone)
383 return (tone > Tone::SILENCE ?
CALC::CTC_counter(prescaler(tone), period(tone)) : 0);
385 static constexpr uint8_t flags(
Tone tone)
387 if (tone == Tone::SILENCE)
return NONE;
408 explicit constexpr Beat(uint8_t bpm) : duration_{calculate_min_duration(bpm)} {}
410 constexpr uint16_t duration()
const
417 static constexpr uint16_t calculate_min_duration(uint8_t bpm)
421 return (60U * 1000U / 8U) / bpm;
463 template<board::Timer NTIMER, board::PWMPin OUTPUT,
typename TONEPLAY = QTonePlay<NTIMER, OUTPUT>>
492 t32_duration_ms_ = min_duration;
501 return t32_duration_ms_;
511 prepare_(melody, load_sram);
521 prepare_(melody, load_eeprom);
531 prepare_(melody, load_flash);
546 return start_next_();
560 return stop_current_();
568 return (loader_ ==
nullptr);
572 static constexpr const uint16_t INTERTONE_DELAY_MS = 20;
576 void prepare_(
const TONE_PLAY* melody, LOAD_TONE load_tone)
579 current_play_ = melody;
580 repeat_play_ =
nullptr;
588 current_play_ =
nullptr;
589 repeat_play_ =
nullptr;
594 uint16_t start_next_()
596 if (loader_ ==
nullptr)
return 0;
599 const TONE_PLAY* current = loader_(current_play_, holder);
600 if (current->is_end())
607 if (current->is_repeat_start())
609 repeat_play_ = current_play_;
612 else if (current->is_repeat_end())
616 if (repeat_times_ == -1) repeat_times_ = current->repeat_count();
618 current_play_ = repeat_play_;
620 repeat_play_ =
nullptr;
623 else if (current->is_tie())
625 tie_notes_ = current->num_ties();
629 if (current->is_tone()) current->generate_tone(generator_);
634 delay = duration(current->duration());
640 uint16_t stop_current_()
645 return INTERTONE_DELAY_MS;
650 return uint8_t(d) * t32_duration_ms_;
669 LOAD_TONE loader_ =
nullptr;
670 uint16_t t32_duration_ms_ = 0U;
671 const TONE_PLAY* current_play_ =
nullptr;
673 int8_t repeat_times_ = 0;
674 uint8_t tie_notes_ = 0;
675 bool no_delay_ =
false;
711 template<board::Timer NTIMER, board::PWMPin OUTPUT,
typename TONEPLAY = QTonePlay<NTIMER, OUTPUT>>
818 volatile bool stop_ =
true;
855 template<board::Timer NTIMER, board::PWMPin OUTPUT,
typename TONEPLAY = QTonePlay<NTIMER, OUTPUT>>
905 status_ = Status::NOT_STARTED;
909 status_ = Status::STARTED;
928 status_ = Status::NOT_STARTED;
932 status_ = Status::STARTED;
951 status_ = Status::NOT_STARTED;
955 status_ = Status::STARTED;
964 status_ = Status::NOT_STARTED;
973 return status_ != Status::NOT_STARTED;
988 if ((status_ != Status::NOT_STARTED) && (rtt_millis >= next_time_))
992 if (status_ == Status::PLAYING_NOTE)
995 next = Status::PLAYING_INTERNOTE;
1000 next = Status::PLAYING_NOTE;
1004 status_ = Status::NOT_STARTED;
1007 next_time_ = rtt_millis + delay;
1014 enum class Status : uint8_t
1022 Status status_ = Status::NOT_STARTED;
1023 uint32_t next_time_ = 0UL;
This low-level API defines an abstract player of melodies (defined as a sequence of tones and duratio...
uint16_t get_min_duration() const
Get the duration, in milliseconds, of a 32nd note.
void set_min_duration(uint16_t min_duration)
Set the duration, in milliseconds, of a 32nd note.
void prepare_eeprom(const TONE_PLAY *melody)
Prepare playing of melody, which should be stored in EEPROM.
ToneGenerator< NTIMER, OUTPUT > GENERATOR
The type of ToneGenerator to use as constructor's argument.
uint16_t stop_current_note()
Ask this player to stop playing the current note of the melody.
uint16_t start_next_note()
Ask this player to start playing the next note of the melody.
TONEPLAY TONE_PLAY
The type that holds unit of information of a melody.
void prepare_sram(const TONE_PLAY *melody)
Prepare playing of melody, which should be stored in SRAM.
AbstractTonePlayer(GENERATOR &tone_generator)
Create a new tone player, based on an existing ToneGenerator.
bool is_finished() const
Indicate if the currently played melody is finished.
void prepare_flash(const TONE_PLAY *melody)
Prepare playing of melody, which should be stored in Flash.
This API defines a player of melodies, defined as a sequence of tones and durations.
typename BASE::GENERATOR GENERATOR
The type of ToneGenerator to use as constructor's argument.
void update(uint32_t rtt_millis)
Ask this player to update current play if needed, based on current time (as returned by an timer::RTT...
uint16_t get_min_duration() const
Get the duration, in milliseconds, of a 32nd note.
void play_eeprom(const TONE_PLAY *melody, const Beat &beat)
Start playing a melody, defined by a sequence of TONE_PLAYs, stored in EEPROM.
void play_sram(const TONE_PLAY *melody, const Beat &beat)
Start playing a melody, defined by a sequence of TONE_PLAYs, stored in SRAM.
typename BASE::TONE_PLAY TONE_PLAY
The type that holds unit of information of a melody.
bool is_playing() const
Tell if a melody is currently playing.
void stop()
Stop playing current melody (if any).
AsyncTonePlayer(GENERATOR &tone_generator)
Create a new asynchronous tone player, based on an existing ToneGenerator.
void play_flash(const TONE_PLAY *melody, const Beat &beat)
Start playing a melody, defined by a sequence of TONE_PLAYs, stored in Flash.
This embeds minimum duration (duration of a 32nd note), in milliseconds, for a given tempo (beats per...
An optimized surrogate to TonePlay structure.
constexpr QTonePlay(Tone tone, uint8_t value=0)
Construct a "special" optimized tone play with the provided value.
constexpr QTonePlay(Tone tone, Duration duration)
Construct an optimized tone play for the provided tone and duration.
QTonePlay()=default
Default constructor, used only to declare an uninitialized QTonePlay variable.
API class for tone generation to a buzzer (or better an amplifier) connected to pin OUTPUT.
void stop_tone()
Stop the tone being currently generated to the connected buzzer.
This struct is the unit data manipulated by TonePlayer: it describes one Tone along with its duration...
TonePlay()=default
Default constructor, used only to declare an uninitialized TonePlay variable.
constexpr TonePlay(Tone tone, Duration duration)
Construct a tone play with the provided tone and duration.
constexpr TonePlay(Tone tone, uint8_t value=0)
Construct a "special" tone play with the provided value.
This API defines a player of melodies, defined as a sequence of tones and durations.
typename BASE::TONE_PLAY TONE_PLAY
The type that holds unit of information of a melody.
void play_flash(const TONE_PLAY *melody, const Beat &beat)
Play a melody, defined by a sequence of TONE_PLAYs, stored in Flash.
void stop()
Stop playing current melody (if any).
TonePlayer(GENERATOR &tone_generator)
Create a new synchronous tone player, based on an existing ToneGenerator.
bool is_playing() const
Tell if a melody is currently playing.
void play_sram(const TONE_PLAY *melody, const Beat &beat)
Play a melody, defined by a sequence of TONE_PLAYs, stored in SRAM.
void play_eeprom(const TONE_PLAY *melody, const Beat &beat)
Play a melody, defined by a sequence of TONE_PLAYs, stored in EEPROM.
typename BASE::GENERATOR GENERATOR
The type of ToneGenerator to use as constructor's argument.
static bool read(const T *address, T &value)
Read value of type T stored in EEPROM at address.
General API to handle an AVR timer.
typename TRAIT::TYPE TYPE
The type of this timer's counter (either uint8_t or uint16_t).
typename PRESCALERS_TRAIT::TYPE PRESCALER
The enum type listing all available precaler values for this timer.
#define UNUSED
Specific GCC attribute to declare an argument or variable unused, so that the compiler does not emit ...
@ NONE
No interrupt will be generated by the Anolog Comparator.
static constexpr const Tone SLUR
This special tone marks the following notes to be slurred together, ie no intertone delay shall occur...
static constexpr const Tone REPEAT_END
This special tone marks the end of a repeating sequence (started with REPEAT_START).
static constexpr const Tone END
This special tone marks the end of a melody (as a sequence of Tones).
static constexpr const Tone REPEAT_START
This special tone marks the beginning of sequence that shall be repeated later.
static constexpr const Tone TIE
This special tone marks the following notes to be tied together, ie their durations are added with no...
Defines API for audio tones (square waves) generation and simple melodies playing.
static constexpr Duration dotted(Duration d)
Transforms a note duration to its dotted value (1.5 times the given duration).
static constexpr Duration triplet(Duration d)
Transforms a note duration to allow it to use in a triplet.
Duration
Possible duration of a note, following music theory.
@ QUARTER
Duration of a quarter note; this is actually the duration of one beat.
@ SEMI_QUAVER
Other common name for a sixteenth note.
@ SIXTEENTH
Duration of a sixteenth note; a quarter the duration of a quarter!
@ CROTCHET
Other common name for a quarter note.
@ HALF
Duration of a half note; 2 times the duration of a quarter.
@ SEMI_BREVE
Other common name for a whole note.
@ WHOLE
Duration of a whole note; 4 times the duration of a quarter.
@ EIGHTH
Duration of an eighth note; half the duration of a quarter.
@ QUAVER
Other common name for an eighth note.
@ MINIM
Other common name for a half note.
Tone
This enum defines all possible audio tones that can be generated.
T * read_flash(uint16_t address, T *buffer, uint8_t size)
Read flash memory content at given address into buffer.
@ OUTPUT
Notification is dispatched whenever the Future output buffer gets filled, even partly.
void delay_ms(uint16_t ms) INLINE
Delay program execution for the given amount of milliseconds.
DELAY_PTR delay
Delay program execution for the given amount of milliseconds.
Defines a set of calculation methods for the given NTIMER_ The behavior of these methods is specific ...
static constexpr TYPE CTC_counter(PRESCALER prescaler, uint32_t us)
Computes the value of counter to use for this timer, in TimerMode::CTC mode, with prescaler,...
static constexpr PRESCALER CTC_prescaler(uint32_t us)
Computes the ideal prescaler value to use for this timer, in TimerMode::CTC mode, in order to be able...
API to handle tones (simple square waves) generation to a buzzer.