Jump to content
IGNORED

Unknown timer behaviour CONFIRMED


laoo

Recommended Posts

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:

Felix.png.598fc5fec03f9852d127f9f078a673ca.pngHandy.png.8642d0e18b634b2cedf664e4521aeab2.png

 

But rather like this:

Lynx.jpg.a6d3418237403084035a70a08a720cd4.jpg

 

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 by laoo
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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 by MichelS
  • Like 1
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 ;)

 

  • Haha 1
Link to comment
Share on other sites

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.

 

Link to comment
Share on other sites

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.

 

 

Link to comment
Share on other sites

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 by laoo
  • Like 2
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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).

Link to comment
Share on other sites

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 by sage
Link to comment
Share on other sites

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.

  • Like 1
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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).

  • Like 1
Link to comment
Share on other sites

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.

  • Like 1
Link to comment
Share on other sites

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 ...

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...