laoo Posted January 28 Share Posted January 28 (edited) Sorry for the clickbait title, but what I've found is hard to explain in a title. I don't actually know whether it's genuinely unknown feature, but I haven't read about it in the docs and author of Handy haven't read about it too, so I suspect it's something new. tl;dr: When enabling linking of two timers with higher timer triggering an interrupt and with no reloading, after counter underflows the interrupt is being triggered at each borrow. When using timer without reloading, after counter underflows the interrupt is being triggered at each timer cycle (i.e. decrement try, or borrow from linked timer). Long version: I've wrote a VGM player on Lynx that unintentionally worked on real hardware but did not on Handy nor Felix. I've looked at it with @42bs few days back and found that the initial bug causing Handy to hang wasn't really a bug in the player but a bug in Handy. The player is interrupt driven and new interrupt is being issued each time previous interrupt triggered. I just needed initial interrupt to get started so the player just writes a value to INTSET that should manually trigger an interrupt. It just seems to not work in Handy. But the fun part begins later as the player still did not work on any emulator. After further investigation I've discovered a bug that in one specific place the player did not reissue the next interrupt. No interrupt - no playback. Emulators did the right thing. But the hardware played along anyways. I came up with an hypothesis. I've wrote a piece of software to test it and it confirmed. Emulators behave differently than the real hardware. The test program at each VBL is setting timer5 and timer7 as follows: TIMER7_COUNT = 50; TIMER7_CONTROLA = ENABLE_INT|RESET_DONE|ENABLE_COUNT|AUD_LINKING; TIMER5_BACKUP = 158; TIMER5_CONTROLA = ENABLE_RELOAD|ENABLE_COUNT|AUD_1; Timer5 is counting lines. Just like HCOUNT. It's linked to Timer7 that has no reload (so no backup just count) and triggers an interrupt after finish and is initially set to 50 (about half of the screen). I XOR the green0 color with 15 after timer7 interrupt and reset it to zero at VBL. As you may have guessed it does not behave like this: But rather like this: TIMER_DONE does not prevent triggering an interrupt after borrow from previous timer and the interrupt is being triggered each time the previous timer underflows. That's it. That's the mystery. A minor thing, but a thing. I'll just incorporate the fix into the Felix UPDATE After more experiments it turned out that linking is not necessary. Only one timer without reload is enough to observe this phenomenon. @MicheleS found that it's even documented TimerDone.lyx Edited January 29 by laoo 1 1 Quote Link to comment Share on other sites More sharing options...
sage Posted January 28 Share Posted January 28 1 hour ago, laoo said: Sorry for the clickbait title, but what I've found is hard to explain in a title. I don't actually know whether it's genuinely unknown feature, but I haven't read about it in the docs and author of Handy haven't read about it too, so I suspect it's something new. tl;dr: When enabling linking of two timers with higher timer triggering an interrupt and with no reloading, after counter underflows the interrupt is being triggered at each borrow. TIMER_DONE does not prevent triggering an interrupt after borrow from previous timer and the interrupt is being triggered each time the previous timer underflows. That's it. That's the mystery. A minor thing, but a thing. I'll just incorporate the fix into the Felix It is know that Timers are not emulated prefect in Handy, esp audio timers which high frequency are no emulated. But the linking is a nice find. Quote Link to comment Share on other sites More sharing options...
sage Posted January 28 Share Posted January 28 5 hours ago, sage said: It is know that Timers are not emulated prefect in Handy, esp audio timers which high frequency are no emulated. But the linking is a nice find. so, thw fix is to never set DONE if it is linking? or is it altogether a problem with single shot timers? Quote Link to comment Share on other sites More sharing options...
MichelS Posted January 28 Share Posted January 28 (edited) Is it this? Handy Specification, page 34, last paragraph: Quote The interrupt signal comes from the timer when the timer value is zero AND the timer is attempting to perform a ‘borrow’. Based on the control bits, the borrow may not actually occur, but the interrupt signal will. Timer 7 ("clocked" by timer 5) reaches zero and triggers interrupt on next borrow. Since it's not reloaded, it stays at zero. Now, everytime counter 5 reaches zero and clocks timers 7, the interrupt is triggered again. Or did i misinterpret your find? Edited January 28 by MichelS 1 Quote Link to comment Share on other sites More sharing options...
Cyprian Posted January 28 Share Posted January 28 @laoo does it mean that we can expect a new Felix version? Quote Link to comment Share on other sites More sharing options...
sage Posted January 28 Share Posted January 28 1 hour ago, Cyprian said: @laoo does it mean that we can expect a new Felix version? it seems it wasnt even fixed in the repo yet Quote Link to comment Share on other sites More sharing options...
42bs Posted January 29 Share Posted January 29 14 hours ago, MichelS said: Is it this? Handy Specification, page 34, last paragraph: Timer 7 ("clocked" by timer 5) reaches zero and triggers interrupt on next borrow. Since it's not reloaded, it stays at zero. Now, everytime counter 5 reaches zero and clocks timers 7, the interrupt is triggered again. Or did i misinterpret your find? I agree, this seems to be the point. So no bug in the HW, but a misinterpreted behavior. Quote Link to comment Share on other sites More sharing options...
laoo Posted January 29 Author Share Posted January 29 16 hours ago, sage said: so, thw fix is to never set DONE if it is linking? or is it altogether a problem with single shot timers? While preparing a fix in the emulator I was investigating it further it turned out to be not related to linking, but single shot timers, i.e. without reload. So @MichelS is right that IT IS in the docs, and @42bs is right that it's misinterpreted behaviour. RJ Mical did a good job hiding things in the documentation 1 Quote Link to comment Share on other sites More sharing options...
42bs Posted January 29 Share Posted January 29 German saying: one does not see the wood because one only sees the trees. 1 Quote Link to comment Share on other sites More sharing options...
sage Posted January 29 Share Posted January 29 i wonder a bit about the advantage of single shot timers over reloading ones then.... if manually have to disable them on the first interrupt, behaviour is the same 🤔 Quote Link to comment Share on other sites More sharing options...
42bs Posted January 29 Share Posted January 29 sometimes you just need a single shot. For example a timeout. Quote Link to comment Share on other sites More sharing options...
sage Posted January 29 Share Posted January 29 1 hour ago, 42bs said: sometimes you just need a single shot. For example a timeout. ... but as it does not disable it by itself, there is no large difference or do i miss something? with RELOAD 49 int every 50 counts without RELOAD int after 50 counts, then every count. Quote Link to comment Share on other sites More sharing options...
laoo Posted January 29 Author Share Posted January 29 For one-shot timers without reload you just need to remember to set INTRST at the end of the interrupt as it will almost certainly shot another time during interrupt handler. Beside this their the same. Frankly, this "feature" feels buggy to me. Quote Link to comment Share on other sites More sharing options...
laoo Posted January 29 Author Share Posted January 29 (edited) On 1/28/2023 at 5:45 PM, Cyprian said: @laoo does it mean that we can expect a new Felix version? Generally nobody expects when there will be another version of Felix. I have to migrate the renderer to something multiplatform (OpenGL ES? Vulkan?) I have to fix nasty audio/video synchronization issue I have to add memory viewer debug window I had an year long break due to fatigue and lack of inspiration, but who knows... my energy level might be high enough now Edited January 29 by laoo 2 Quote Link to comment Share on other sites More sharing options...
+karri Posted January 29 Share Posted January 29 12 minutes ago, laoo said: Generally nobody expects when there will be another version of Felix. Pretty good link. I love it! PS. I am toying with the idea of trying to improve on the PSP Lynx emulator. The PSP has such a nice display and fits my hands. Perhaps I could port the felix engine to the Plynx application. Quote Link to comment Share on other sites More sharing options...
sage Posted January 29 Share Posted January 29 1 hour ago, laoo said: For one-shot timers without reload you just need to remember to set INTRST at the end of the interrupt as it will almost certainly shot another time during interrupt handler. Beside this their the same. Frankly, this "feature" feels buggy to me. I wonder if the timer done bit is set differently. Quote Link to comment Share on other sites More sharing options...
laoo Posted January 29 Author Share Posted January 29 2 hours ago, sage said: I wonder if the timer done bit is set differently. Have you ever observed TIMER_DONE bit of CONTROLB timer register? I'm actually testing it while investigating this issue, and found that it's always zero, regardless if reload is set or not. Furthermore: LAST_CLOCK seems to be 1 just before the clock when the counter is decremented (so it's observable with prescaler greater than 1) BORROW_IN is 1 even when the timer is not being linked but just in every cycle the timer is decremented. Only BORROW_OUT bit is reasonable and behaves like I expect it to do. 3 hours ago, karri said: Perhaps I could port the felix engine to the Plynx application. The project is cleanly divided into libFelix that is platform agnistic and just does the emulation, and application itself that does I/O and A/V. It might be CPU hungry though (as it ultimately aims to be cycle exact without cheating). Quote Link to comment Share on other sites More sharing options...
sage Posted January 30 Share Posted January 30 (edited) 16 hours ago, laoo said: Have you ever observed TIMER_DONE bit of CONTROLB timer register? I'm actually testing it while investigating this issue, and found that it's always zero, regardless if reload is set or not. Furthermore: LAST_CLOCK seems to be 1 just before the clock when the counter is decremented (so it's observable with prescaler greater than 1) BORROW_IN is 1 even when the timer is not being linked but just in every cycle the timer is decremented. Only BORROW_OUT bit is reasonable and behaves like I expect it to do. unluckily not. but it could explain why comlynx is emulated badly. redeye code uses one shot timers. 16 hours ago, laoo said: The project is cleanly divided into libFelix that is platform agnistic and just does the emulation, and application itself that does I/O and A/V. It might be CPU hungry though (as it ultimately aims to be cycle exact without cheating). yes. but unluckily does not compile under linux yet... will give it a try again after updates. I would happily include it into sdl-handy Edited January 30 by sage Quote Link to comment Share on other sites More sharing options...
obschan Posted January 30 Share Posted January 30 On 1/30/2023 at 4:03 AM, karri said: PS. I am toying with the idea of trying to improve on the PSP Lynx emulator. The PSP has such a nice display and fits my hands. Perhaps I could port the felix engine to the Plynx application. I believe you have libretro and retroarch running on PSP. 1 Quote Link to comment Share on other sites More sharing options...
42bs Posted January 31 Share Posted January 31 On 1/29/2023 at 4:15 PM, sage said: ... but as it does not disable it by itself, there is no large difference or do i miss something? with RELOAD 49 int every 50 counts without RELOAD int after 50 counts, then every count. Right, yes. Likely not what was intended. Quote Link to comment Share on other sites More sharing options...
42bs Posted January 31 Share Posted January 31 20 hours ago, sage said: unluckily not. but it could explain why comlynx is emulated badly. redeye code uses one shot timers. yes. but unluckily does not compile under linux yet... will give it a try again after updates. I would happily include it into sdl-handy I tried to compile files in libFelix on Mac, no chance. <coroutine> is not in Clang (or only experimental). But then, _I_ do not need a native Mac port. Quote Link to comment Share on other sites More sharing options...
laoo Posted January 31 Author Share Posted January 31 1 hour ago, 42bs said: I tried to compile files in libFelix on Mac, no chance. <coroutine> is not in Clang (or only experimental). But then, _I_ do not need a native Mac port. That can be tweaked for time being. But I'm in a process of researching GLFW/Vulkan to get rid of DX11 so I hope that in few months it can be compiled everywhere (with some wrappers on Mac, as it has its own Metal, but Vulkan can be translated to it AFAIK). 1 Quote Link to comment Share on other sites More sharing options...
42bs Posted January 31 Share Posted January 31 Yes, tried it. The came a bunch of new errors. Like not finding "comment". Anyway. I can wait. I'd rather see code/memory breakpoints, register/memory manipulation. Means a Lua-Console Maybe you should set up a Patreon account. Quote Link to comment Share on other sites More sharing options...
laoo Posted January 31 Author Share Posted January 31 30 minutes ago, 42bs said: I'd rather see code/memory breakpoints, register/memory manipulation. Means a Lua-Console We'll talk about it 😎 30 minutes ago, 42bs said: Maybe you should set up a Patreon account. It would became a JOB. Pressure = not fun. I come back to Felix when I feel inspiration to do so. 1 Quote Link to comment Share on other sites More sharing options...
sage Posted January 31 Share Posted January 31 5 hours ago, laoo said: That can be tweaked for time being. But I'm in a process of researching GLFW/Vulkan to get rid of DX11 so I hope that in few months it can be compiled everywhere (with some wrappers on Mac, as it has its own Metal, but Vulkan can be translated to it AFAIK). but thats part of the platform part, not emulator core ... 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.