Skip to content

Commit bbe8484

Browse files
refactor(esp-hal-buzzer): Enable playing tones from slices instead of fixed-size arrays (#39)
* refactor(esp-hal-buzzer)!: Enable playing tones from slices instead of fixed-size arrays - Add new `Buzzer::play_tones_from_slice(&mut self, sequence: &[u32], timings: &[u32])` to play tones from slices. BREAKING CHANGE: `Buzzer::play_song()` now takes a slice instead of a fixed-size array * Add CHANGELOG.md entry
1 parent 444bd6b commit bbe8484

5 files changed

Lines changed: 89 additions & 30 deletions

File tree

.cargo/config.toml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
[alias]
2-
esp32 = "run --release --features=esp32 --target=xtensa-esp32-none-elf"
3-
esp32c2 = "run --release --features=esp32c2 --target=riscv32imc-unknown-none-elf"
4-
esp32c3 = "run --release --features=esp32c3 --target=riscv32imc-unknown-none-elf"
5-
esp32c6 = "run --release --features=esp32c6 --target=riscv32imac-unknown-none-elf"
6-
esp32h2 = "run --release --features=esp32h2 --target=riscv32imac-unknown-none-elf"
7-
esp32s2 = "run --release --features=esp32s2 --target=xtensa-esp32s2-none-elf"
8-
esp32s3 = "run --release --features=esp32s3 --target=xtensa-esp32s3-none-elf"
2+
esp32 = "run --release --features=esp32,esp-hal/unstable --target=xtensa-esp32-none-elf"
3+
esp32c2 = "run --release --features=esp32c2,esp-hal/unstable --target=riscv32imc-unknown-none-elf"
4+
esp32c3 = "run --release --features=esp32c3,esp-hal/unstable --target=riscv32imc-unknown-none-elf"
5+
esp32c6 = "run --release --features=esp32c6,esp-hal/unstable --target=riscv32imac-unknown-none-elf"
6+
esp32h2 = "run --release --features=esp32h2,esp-hal/unstable --target=riscv32imac-unknown-none-elf"
7+
esp32s2 = "run --release --features=esp32s2,esp-hal/unstable --target=xtensa-esp32s2-none-elf"
8+
esp32s3 = "run --release --features=esp32s3,esp-hal/unstable --target=xtensa-esp32s3-none-elf"
99

1010
[build]
1111
target = "riscv32imac-unknown-none-elf"

esp-hal-buzzer/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12+
- Added `Buzzer::play_tones_from_slice(&self, sequence: &[u32], timings: &[u32])` to allow tone playback using slices (#39)
13+
1214
### Changed
1315
- **Breaking Change:** `Buzzer::mute()` is now infallible (#38)
16+
- **Breaking Change:** `Buzzer::play_song()` now takes a `&[ToneValue]` slice instead of a fixed-size `[ToneValue; N]` array (#39)
1417

1518
### Fixed
1619
- Upgrade esp-hal to 1.0.0-beta.1 (#31)

esp-hal-buzzer/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ targets = ["riscv32imc-unknown-none-elf"]
1414
[dependencies]
1515
defmt = { version = "1.0.1", optional = true }
1616
document-features = "0.2.11"
17-
esp-hal = { version = "1.0.0-rc.0"}
17+
# Unstable required for:
18+
# - ledc
19+
# - delay
20+
esp-hal = { version = "1.0.0-rc.0", features = ["requires-unstable"] }
1821

1922
[dev-dependencies]
2023
esp-backtrace = { version = "0.17.0", features = [

esp-hal-buzzer/examples/buzzer.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,20 @@ fn main() -> ! {
2828
peripherals.GPIO6,
2929
);
3030

31-
buzzer.play_song(DOOM).unwrap();
32-
buzzer.play_song(FURELISE).unwrap();
33-
buzzer.play_song(MERRY_CHRISTMAS).unwrap();
34-
buzzer.play_song(MII_CHANNEL).unwrap();
35-
buzzer.play_song(NEVER_GONNA_GIVE_YOU_UP).unwrap();
36-
buzzer.play_song(ODE_TO_JOY).unwrap();
37-
buzzer.play_song(PACMAN).unwrap();
38-
buzzer.play_song(STAR_WARS).unwrap();
39-
buzzer.play_song(SUPER_MARIO_BROS).unwrap();
40-
buzzer.play_song(TAKE_ON_ME).unwrap();
41-
buzzer.play_song(TETRIS).unwrap();
42-
buzzer.play_song(THE_LION_SLEEPS_TONIGHT).unwrap();
43-
buzzer.play_song(ZELDA_LULLABY).unwrap();
44-
buzzer.play_song(ZELDA_THEME).unwrap();
31+
buzzer.play_song(&DOOM).unwrap();
32+
buzzer.play_song(&FURELISE).unwrap();
33+
buzzer.play_song(&MERRY_CHRISTMAS).unwrap();
34+
buzzer.play_song(&MII_CHANNEL).unwrap();
35+
buzzer.play_song(&NEVER_GONNA_GIVE_YOU_UP).unwrap();
36+
buzzer.play_song(&ODE_TO_JOY).unwrap();
37+
buzzer.play_song(&PACMAN).unwrap();
38+
buzzer.play_song(&STAR_WARS).unwrap();
39+
buzzer.play_song(&SUPER_MARIO_BROS).unwrap();
40+
buzzer.play_song(&TAKE_ON_ME).unwrap();
41+
buzzer.play_song(&TETRIS).unwrap();
42+
buzzer.play_song(&THE_LION_SLEEPS_TONIGHT).unwrap();
43+
buzzer.play_song(&ZELDA_LULLABY).unwrap();
44+
buzzer.play_song(&ZELDA_THEME).unwrap();
4545

4646
println!("Done");
4747

esp-hal-buzzer/src/lib.rs

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ pub enum Error {
6161

6262
/// When the volume level is out of range. Either too low or too high.
6363
VolumeOutOfRange,
64+
65+
/// Sequence and timings slice aren't of the same length
66+
LengthMismatch,
6467
}
6568

6669
/// Converts [channel::Error] into [self::Error]
@@ -325,6 +328,55 @@ impl<'a> Buzzer<'a> {
325328
Ok(())
326329
}
327330

331+
/// Play a sound sequence through the buzzer
332+
///
333+
/// Uses a pair of frequency and duration slices to play a sound sequence.
334+
/// Both slices must be of the same length, where each pair of `(frequency, duration)` defines one tone.
335+
///
336+
/// # Arguments
337+
/// * `sequence` - A slice of frequencies to play through the buzzer
338+
/// * `timings` - A slice of durations in milliseconds for each frequency
339+
///
340+
/// # Examples
341+
/// Play a single beep at 300Hz for 1 second
342+
/// ```
343+
/// buzzer.play_tones_from_slice(&[300], &[1000]);
344+
/// ```
345+
///
346+
/// Play a sequence of 3 beeps with a break in between
347+
/// ```
348+
/// buzzer.play_tones_from_slice(&[200, 0, 200, 0, 200], &[200, 50, 200, 50, 200]);
349+
/// ```
350+
///
351+
/// Play a sequence of 3 beeps with the same duration
352+
/// ```
353+
/// buzzer.play_tones_from_slice(&[100, 200, 300], &[100; 3]);
354+
/// ```
355+
///
356+
/// # Errors
357+
/// This function returns an [Error] in the following cases:
358+
/// - If the `sequence` and `timings` slices have different lengths ([Error::LengthMismatch])
359+
/// - If playing a frequency results in an error
360+
pub fn play_tones_from_slice(
361+
&mut self,
362+
sequence: &[u32],
363+
timings: &[u32],
364+
) -> Result<(), Error> {
365+
if sequence.len() != timings.len() {
366+
return Err(Error::LengthMismatch);
367+
}
368+
369+
// Iterate for each frequency / timing pair
370+
for (frequency, timing) in sequence.iter().zip(timings.iter()) {
371+
self.play(*frequency)?;
372+
self.delay.delay_millis(*timing);
373+
self.mute();
374+
}
375+
// Mute at the end of the sequence
376+
self.mute();
377+
Ok(())
378+
}
379+
328380
/// Play a tone sequence through the buzzer
329381
///
330382
/// Uses a pair of frequencies and timings to play a sound sequence.
@@ -349,19 +401,20 @@ impl<'a> Buzzer<'a> {
349401
/// duration: 100,
350402
/// },
351403
/// ];
352-
/// buzzer.play_song(song);
404+
/// buzzer.play_song(&song);
353405
/// ```
354406
///
355407
/// # Errors
356408
/// This function returns an [Error] in case of an error.
357409
/// An error can occur when an invalid value is used as a tone
358-
pub fn play_song<const T: usize>(&mut self, tones: [ToneValue; T]) -> Result<(), Error> {
359-
let mut sequence: [u32; T] = [0; T];
360-
let mut timings: [u32; T] = [0; T];
361-
for (index, tone) in tones.iter().enumerate() {
362-
sequence[index] = tone.frequency;
363-
timings[index] = tone.duration;
410+
pub fn play_song(&mut self, tones: &[ToneValue]) -> Result<(), Error> {
411+
for tone in tones {
412+
self.play(tone.frequency)?;
413+
self.delay.delay_millis(tone.duration);
414+
self.mute();
364415
}
365-
self.play_tones(sequence, timings)
416+
// Mute at the end of the sequence
417+
self.mute();
418+
Ok(())
366419
}
367420
}

0 commit comments

Comments
 (0)