TGB1718 Posted January 14, 2023 Share Posted January 14, 2023 I don't know if it's common knowledge, but I was trying to use one of the above timers and ran into some issues in that the flag for the associated timer which should be $FF until the timer reaches zero, however when I tried using any of the timers, my code couldn't detect the $FF after setting the timer and ran through to process further code which then reset the timer. After a bit of investigation it turns out that the flag for the associated timer is not set to $FF until the first time a vertical blank is processed i.e. the first time the counter is decremented. From then on it's all good and the timer will count down to zero and the flag cleared when that happens. Simple fix is to set the timer in your code and then store $FF in the timer flag, it all then works fine, I just find it strange that the routine in ROM that sets the timer didn't do this. Quote Link to comment Share on other sites More sharing options...
danwinslow Posted January 14, 2023 Share Posted January 14, 2023 Interesting. Are you looking at a shadow reg? They may have just been generally following the 'do all the OS reg/shadow updates during the VBI' philosophy. Copy the OS to ram and patch it to set the reg when you expected it to, see what happens. Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted January 14, 2023 Author Share Posted January 14, 2023 2 hours ago, danwinslow said: Interesting. Are you looking at a shadow reg? No, there are no shadow registers for these timers/flags, it just seems an oversight by whoever wrote the timer routine. I think they may not have included it as the flag registers are not in sequence, so setting them in a short/sharp routine using the X register as the timers values do, would have had some extra coding requirement and maybe there just wasn't enough space left in the OS Quote Link to comment Share on other sites More sharing options...
tebe Posted January 14, 2023 Share Posted January 14, 2023 https://github.com/tebe6502/Mad-Pascal/blob/master/samples/a8/interrupt/irq_timers.pas https://mads.atari8.info/doc/en/interrupts/ Quote Link to comment Share on other sites More sharing options...
thorfdbg Posted January 14, 2023 Share Posted January 14, 2023 6 hours ago, TGB1718 said: From then on it's all good and the timer will count down to zero and the flag cleared when that happens. Simple fix is to set the timer in your code and then store $FF in the timer flag, it all then works fine, I just find it strange that the routine in ROM that sets the timer didn't do this. SetIRQ() cannot do that, it is a fairly generic function that sets all sorts of interrupt related vectors atomically, but it has no knowledge about whether a particular vector pair is a timer or anything else. However, as a matter of advice, I would probably set the flag in advance, and not before setting the timer value, at least if the number of VBIs you wait for is 1. It may happen that the VBI and thus the timer triggers just after SetIRQ returns, but before you install the FF byte, and thus you miss the timer completely. 1 Quote Link to comment Share on other sites More sharing options...
phaeron Posted January 14, 2023 Share Posted January 14, 2023 The documentation for SETVBV in the OS manual actually says that you should set the flag in advance: Quote When working with the System Timers, the vectors for timers 1 and 2 and the flags for timers 3, 4, and 5 should be set while the associated timer is equal to zero, then the timer should be set to its (nonzero) value. As for why SETVBV doesn't do this, as Thor notes it is actually just a generic routine that sets words in the OS database atomically relative to the VBI. It is actually a tricky routine to write as it cannot modify NMIEN (OS-A did, but this was fixed in OS-B). It could have been designed to reset the flag for the timers, but I'm guessing this was either deemed out of scope or just unnecessary. Note that timers 2-5 are serviced in VBI stage 2, so it's possible for the timer update to be skipped for a frame -- including setting the flag to $FF. If you're in a case where the state of the system timer is fully unknown and you need to set it safely, there are three ways to atomically set the flag together with the count. One is to mask interrupts with SEI/CLI around both the write and the call to SETVBV, locking out VBI stage 2 so the timer can't be processed during the update. The second is to write $FF to one of the bytes of CDTMV before then writing CDTMF and calling SETVBV, in that order, thus locking down the timer for >1 frame before setting it. The third way to avoid race conditions with the VBI is to simply set it from the VBI. 3 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.