@@ -61,6 +61,8 @@ def __init__(self, buzzer_pin: int|str = None):
6161 # State variables for non-blocking playback
6262 self ._note_end_time = 0
6363 self ._tempo = 120 # Default BPM
64+ self ._in_gap = False
65+ self ._gap_end_time = 0
6466
6567 # Song playback state
6668 self ._song = []
@@ -124,15 +126,14 @@ def _parse_note(self, note_str: str):
124126 if note_letter in "ABCDEFG" :
125127 # Check for sharp (#) or flat (b) modifier
126128 note_with_modifier = note_letter
129+ octave_pos = 1
127130 if len (note_str ) > 1 :
128131 if note_str [1 ] == "#" :
129132 note_with_modifier = note_letter + "#"
130133 octave_pos = 2
131134 elif note_str [1 ] == "B" :
132135 note_with_modifier = note_letter + "B"
133136 octave_pos = 2
134- else :
135- octave_pos = 1
136137
137138 try :
138139 if octave_pos < len (note_str ):
@@ -150,24 +151,25 @@ def _update(self, timer):
150151 Internal callback for non-blocking playback.
151152 Called by the timer when running in non-blocking mode.
152153 """
153-
154- # Check if current note is done
155- if time .ticks_diff (self ._note_end_time , time .ticks_ms ()) <= 0 :
156- # Note done - stop the tone
154+ now = time .ticks_ms ()
155+
156+ if self ._in_gap :
157+ # Waiting for the inter-note silence to pass before advancing
158+ if time .ticks_diff (self ._gap_end_time , now ) <= 0 :
159+ self ._in_gap = False
160+ self ._song_index += 1
161+ if self ._song_index < len (self ._song ):
162+ note , duration = self ._song [self ._song_index ]
163+ self ._start_note (note , duration , self ._song_tempo )
164+ else :
165+ # Song finished
166+ self ._timer .deinit ()
167+ self ._timer_in_use = False
168+ elif time .ticks_diff (self ._note_end_time , now ) <= 0 :
169+ # Note done - silence and schedule a short gap before next note
157170 self ._pwm .duty_u16 (0 )
158-
159- # Small gap between notes
160- time .sleep_ms (20 )
161-
162- # Play next note in song
163- self ._song_index += 1
164- if self ._song_index < len (self ._song ):
165- note , duration = self ._song [self ._song_index ]
166- self ._start_note (note , duration , self ._song_tempo )
167- else :
168- # Song finished
169- self ._timer .deinit ()
170- self ._timer_in_use = False
171+ self ._in_gap = True
172+ self ._gap_end_time = time .ticks_add (now , 20 )
171173
172174 def _start_note (self , note : str , duration : str = "quarter" , tempo : int = None ):
173175 """Start playing a note (non-blocking helper)."""
@@ -231,14 +233,17 @@ def play_note(self, note: str, duration: str = "quarter", blocking: bool = True,
231233 if blocking :
232234 self ._play_tone_blocking (frequency , duration_ms )
233235 else :
234- # Non-blocking - start the note and set up timer if needed
236+ # Non-blocking - clear any active song so _update won't advance it
237+ self ._song = []
238+ self ._song_index = 0
239+ self ._in_gap = False
240+
235241 if frequency > 0 :
236242 self ._pwm .freq (frequency )
237243 self ._pwm .duty_u16 (32768 )
238-
244+
239245 self ._note_end_time = time .ticks_add (time .ticks_ms (), duration_ms )
240-
241- # Start timer if not already running
246+
242247 if not self ._timer_in_use :
243248 self ._timer .init (freq = 100 , callback = lambda t : self ._update (t ))
244249 self ._timer_in_use = True
@@ -284,17 +289,21 @@ def play_song(self, song: list, tempo: int = None, blocking: bool = True):
284289 duration_ms = self ._duration_to_ms (duration , tempo )
285290 self ._play_tone_blocking (frequency , duration_ms )
286291 else :
287- # Non-blocking - store song and start playing with timer
292+ # Non-blocking - stop any existing playback before starting new song
293+ if self ._timer_in_use :
294+ self ._timer .deinit ()
295+ self ._timer_in_use = False
296+ self ._in_gap = False
297+
288298 self ._song = song
289299 self ._song_index = 0
290300 self ._song_tempo = tempo
291- self ._timer_in_use = False
292-
301+
293302 # Start playing first note
294303 note , duration = song [0 ]
295304 self ._start_note (note , duration , tempo )
296305 self ._song_index = 1
297-
306+
298307 # Start the timer for non-blocking playback
299308 self ._timer .init (freq = 100 , callback = lambda t : self ._update (t ))
300309 self ._timer_in_use = True
@@ -315,6 +324,7 @@ def reset_buzzer(self):
315324 # Reset song state
316325 self ._song = []
317326 self ._song_index = 0
327+ self ._in_gap = False
318328
319329 def play_move_it (self , blocking : bool = True ):
320330 """
0 commit comments