Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions src/kaleidoscope/driver/speaker/Base.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#pragma once
#include <Arduino.h>
#include <initializer_list>

namespace kaleidoscope {
namespace driver {
Expand All @@ -36,27 +37,32 @@ class Base {
public:
Base() {}

void setup() {}
void playTone(unsigned int frequency, uint32_t duration) {}
void playTone(unsigned int frequency) {
virtual void setup() {}
virtual void playTone(unsigned int frequency, uint32_t duration) {}
virtual void playTone(unsigned int frequency) {
playTone(frequency, 0); // 0 duration means play until stopped
}
void stopTone() {}
bool isPlaying() { return false; }
virtual void stopTone() {}
virtual bool isPlaying() { return false; }

void playTune(const uint16_t *notes, const uint16_t *durations, uint8_t length);
void stopTune();
void update();
void playTune(std::initializer_list<uint16_t> notes, std::initializer_list<uint16_t> durations) {
playTune(notes.begin(), durations.begin(), min(notes.size(), durations.size()));
}
virtual void stopTune();
virtual void update();

// Prepare speaker for sleep - noop in base implementation
void prepareForSleep() {}
virtual void prepareForSleep() {}

protected:
virtual void playNextTone();

uint16_t current_notes_[_SpeakerProps::kMaxTuneLength];
uint16_t current_durations_[_SpeakerProps::kMaxTuneLength];
uint8_t current_length_;
uint8_t current_index_;
uint32_t next_note_time_;
uint8_t current_length_ {0};
uint8_t current_index_ {0};
uint32_t next_note_time_ {0};
};

} // namespace speaker
Expand Down
32 changes: 16 additions & 16 deletions src/kaleidoscope/driver/speaker/Base_Impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ void Base<_SpeakerProps>::playTune(const uint16_t *notes, const uint16_t *durati
memcpy(current_notes_, notes, length * sizeof(uint16_t));
memcpy(current_durations_, durations, length * sizeof(uint16_t));
current_length_ = length;
current_index_ = 0;
next_note_time_ = 0;
current_index_ = 0;

playNextTone();
}

template<typename _SpeakerProps>
Expand All @@ -51,27 +52,26 @@ void Base<_SpeakerProps>::stopTune() {

template<typename _SpeakerProps>
void Base<_SpeakerProps>::update() {
if (current_length_ == 0 || current_index_ >= current_length_)
if (current_length_ == 0)
return;

uint32_t now = millis();
if (now < next_note_time_)
return;

if (next_note_time_ == 0) {
// Start playing the first note
playTone(current_notes_[current_index_], current_durations_[current_index_]);
next_note_time_ = now + current_durations_[current_index_];
} else {
// Move to next note
current_index_++;
if (current_index_ < current_length_) {
playTone(current_notes_[current_index_], current_durations_[current_index_]);
next_note_time_ = now + current_durations_[current_index_];
} else {
stopTune();
}
if (current_index_ >= current_length_) {
stopTune();
return;
}

playNextTone();
}

template<typename _SpeakerProps>
void Base<_SpeakerProps>::playNextTone() {
playTone(current_notes_[current_index_], current_durations_[current_index_]);
next_note_time_ = millis() + current_durations_[current_index_];
current_index_++;
}

template class Base<BaseProps>;
Expand Down
2 changes: 1 addition & 1 deletion src/kaleidoscope/driver/speaker/None.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace speaker {

class None : public kaleidoscope::driver::speaker::Base<BaseProps> {
public:
void update() {} // no speaker. no updates.
virtual void update() override {} // no speaker. no updates.
};

} // namespace speaker
Expand Down
12 changes: 6 additions & 6 deletions src/kaleidoscope/driver/speaker/Piezo.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,37 +41,37 @@ class Piezo : public Base<_SpeakerProps> {
Piezo()
: Base<_SpeakerProps>() {}

void setup() {
virtual void setup() override {
if (_SpeakerProps::pin != -1) {
pinMode(_SpeakerProps::pin, OUTPUT);
}
}

void playTone(unsigned int frequency, uint32_t duration) {
virtual void playTone(unsigned int frequency, uint32_t duration) override {
if (_SpeakerProps::pin != -1) {
::tone(_SpeakerProps::pin, frequency, duration);
}
}

void playTone(unsigned int frequency) {
virtual void playTone(unsigned int frequency) override {
if (_SpeakerProps::pin != -1) {
::tone(_SpeakerProps::pin, frequency); // Arduino's tone() without duration plays until noTone()
}
}

void stopTone() {
virtual void stopTone() override {
if (_SpeakerProps::pin != -1) {
::noTone(_SpeakerProps::pin);
}
}

bool isPlaying() {
virtual bool isPlaying() override {
// This is a simplification, as Arduino's tone() function is blocking
// In a real implementation, we'd need to track the playing state
return false;
}

void prepareForSleep() {
virtual void prepareForSleep() override {
// Make sure to stop any active tones and shut down the speaker peripheral
if (_SpeakerProps::pin != -1) {
::noTone(_SpeakerProps::pin);
Expand Down