PS: I like the wall of text
Me, too ... I certainly write enough of them!
I can't define the tempo. Tempo is how fast the song plays (not how fast the irq tick is). If a song is at 120 BPM ( a popular tempo), that means it plays 120 whole notes in 1 minute. Or 20 in 1 second.
See my message above on the basic theory.
I -can- define how many down counts are used before the psg player is called. So yes, in 1 second I can get as many calls as
needed. But I still only get 1 call per group of counts.
In order to change the *tempo*, I have to change the counter limit, which the psg player does, by changing the timer interval.
See my message above on the basic theory.
Your "problem" as-such is that you're hard-coding the note-length in Squirrel, either as "Direct" mode or as "Tempo" mode (which are basically, from a programming POV, the same thing).
By doing that, then "yes" you need to change the timer interval in order to change the tempo.
That's a design-choice that you guys made with Squirrel ... it's not a limitation of the System Card Player, or a basic limitation of other music-drivers.
So, in "practical" terms, I do see where you're coming from.
How would you deal with interrupts in such a situation? (Remember we are getting 6991 of them every second) There's no guarantee that
an irq won't occur while the player is updating. Do those interrupts count towards the next psg call?
And at 6991 timer irqs / sec, do we even have enough time to handle this? And run a game? At 60 fps?
Those are the things I don't understand about how this would work. (And keep in mind, irq problems are a real thing, as rovers problem shows)
The whole point of any
well-designed interrupt scheme is to keep the interrupt handling predicatable and usually short and fast.
Handling interrupts from within other interrupts just requires a careful design.
Bonknuts gave the basic code for a timer interrupt for handling the 6991Hz sample playback and music-driver calling.
Yes, interrupts need to be counted if you were to run a sound driver from a timer IRQ at the same time as you were outputting samples with the same IRQ.
For example ... take your 120 BPM.
120 BPM, with a beat being 1/4 note, and using the PSG Player's convention of 48 calls per 1/4 note, means that you'd want to call it 96 times per second.
With a 6991Hz timer interrupt, that means that you'd call the PSG Player once every 6991/96 = 73 timer interrupts ... which would give you an actual rate of 119.7 BPM.
*IF* you are limited to -only- vsync, 1/32nd notes are impossible. They require a fraction of a frame. But, if you use the timer irq, you can update at less than 1 frame. That was the point.
So the timer -is- needed. And without using the timer, There's no way to get 1/32 notes.
You can do then in the System Card Player by using the Direct length mode of encoding the data stream, and setting the time to 3 or 4 ticks at 1/60th and 128 BPM.
But then you lose the ability to change the Tempo, and you'd have to worry keeping track of the overall time.
That's a limitation of the operation of the System Card Player, deflemask is quite happy to do them, taking either 3 or 4 ticks at 128 BPM using a 60Hz update.
(And. as an aside, 1/32 notes are possible to play in the player. They just take 1 tick, instead of the 1.5 they should be,
causing them to de-sync. Which is probably why they aren't supported. And how we found the trick below, thanks to a bug in squirrel during development.)
Sure, call the System Card Player at 120Hz, and suddenly you have a 7/120ths instead of 3.5/60ths.
Computers like integers!
How would you deal with interrupts in such a situation? (Remember we are getting 6991 of them every second) There's no guarantee that an irq won't occur while the player is updating. Do those interrupts count towards the next psg call?
And at 6991 timer irqs / sec, do we even have enough time to handle this? And run a game? At 60 fps?
Of course another interrupt would occur while the sound driver was doing it's slow processing.
That's fairly easy to handle, and "yes", of course you have to keep counting the timer interrupts while the sound driver is processing.
As for whether there would be enough time, Bonknuts has already said that single-channel 7KHz sample playback takes approx 11% of the CPU cycles.
So there's time ... it's just that even trying to do a countdown like that wastes 928 cycles per frame for the dec-zero-page+branch instructions.
Which is part of the reason I was asking about running it from HSync.
*IF* it can run off of hsync...
1) you could do a quick sample update (lda [samples],x / sta )
2) it would be at a decent rate (15 Khz, right?)
3) It could be hooked in via the user hsync hook.
You
could do that, but you've just doubled the CPU cost for those samples, and the hsync processing is slower anyway, which costs even more cycles.
The question is ... is the System Card Player, and the IRQ handling in both the System Card and HuC smart enough to handle not only timer-followed-by-vblank, but also vblank-follow-by-timer???
For the player, it is. Once the player starts processing, it locks itself out from further calls until it is done.
Yes, but that's not the problem that I'm worried about. The problem is "what happens if the vsync interrupt triggers, and then the timer interrupt triggers one scanline later on".
Is the entire vblank interrupt processed with interrupts disabled?
If so, then you're delaying interrupts for a long time, and introducing a delay/error in the sample playback.
If not, then a timer interrupt can occur with a complete call to the sound driver, which would delay the time-critical processing that's going on in the vblank.
It all depends upon just how much stuff is being processed in the vblank interrupt.