Jump to content
  • 0
Fnord42

Best practice for implementing timers?

Question

Hi,

I'd like to have some timers for various purposes in my program and I'm wondering what would be the best way to accomplish that.
What I came up with is just using the vsync interrupt to count down my timer variables and set a corresponding bit in another variable when one of them hits zero.
The main program then just has to check the timer_trigger variable at a convenient time and reset the counter if necessary.
The thing is, I'm not sure if I can just assume the vsync frequency to be 60Hz in all situations. If not, is there a better way to do it?

Share this post


Link to post
Share on other sites

10 answers to this question

Recommended Posts

  • 0

Okay, since I cannot select two^H^H^Hthree best answers, I'll quote them here and select this post instead. 🙂

19 hours ago, StinkerB06 said:

The X16 has two MOS 6522 VIA chips in it, both of which contain 2 timers (A and B) for a total of 4 timers. However, these aren't implemented in the emulator yet, I think. Expect them to be not changed when changing VERA output modes.

Also, the YM2151 FM sound chip has 2 extra timers, totaling to 6.

 

19 hours ago, StephenHorn said:

The vsync timer will definitely change if you replace the VERA entirely.

Otherwise, no. The VERA is going to output VGA at 60Hz and NTSC at 60Hz. There is no 50Hz PAL support planned.

Of course, if your interrupt code takes more than 16ms to execute, you're going to miss a VSYNC simply because nothing will check for it.

 

1 hour ago, Ender said:

If you want to use a timer you can set though, you could use the soft timer in the kernel.  It's 24-bit and 60Hz.  You set A to bits 0-7, X to bits 8-15, and Y to bits 16-23 and call $FFDB.  Then you can get the timer with $FFDE, it returns the bits the same way.

Edited by Fnord42

Share this post


Link to post
Share on other sites
  • 0

The X16 has two MOS 6522 VIA chips in it, both of which contain 2 timers (A and B) for a total of 4 timers. However, these aren't implemented in the emulator yet, I think. Expect them to be not changed when changing VERA output modes.

Also, the YM2151 FM sound chip has 2 extra timers, totaling to 6.

  • Like 1

Share this post


Link to post
Share on other sites
  • 0
1 hour ago, Fnord42 said:

Hi,

I'd like to have some timers for various purposes in my program and I'm wondering what would be the best way to accomplish that.
What I came up with is just using the vsync interrupt to count down my timer variables and set a corresponding bit in another variable when one of them hits zero.
The main program then just has to check the timer_trigger variable at a convenient time and reset the counter if necessary.
The thing is, I'm not sure if I can just assume the vsync frequency to be 60Hz in all situations. If not, is there a better way to do it?

The vsync timer will definitely change if you replace the VERA entirely.

Otherwise, no. The VERA is going to output VGA at 60Hz and NTSC at 60Hz. There is no 50Hz PAL support planned.

Of course, if your interrupt code takes more than 16ms to execute, you're going to miss a VSYNC simply because nothing will check for it.

  • Like 1

Share this post


Link to post
Share on other sites
  • 0
1 hour ago, StinkerB06 said:

The X16 has two MOS 6522 VIA chips in it, both of which contain 2 timers (A and B) for a total of 4 timers. However, these aren't implemented in the emulator yet, I think. Expect them to be not changed when changing VERA output modes.

Also, the YM2151 FM sound chip has 2 extra timers, totaling to 6.

Nice, so there won't be a shortage of timers. 🙂
I assume the 6522 timers can be used to trigger an interrupt? I'll have to read up on the 6522 anyway.
 

1 hour ago, StephenHorn said:

Otherwise, no. The VERA is going to output VGA at 60Hz and NTSC at 60Hz. There is no 50Hz PAL support planned.

Of course, if your interrupt code takes more than 16ms to execute, you're going to miss a VSYNC simply because nothing will check for it.

Okay, that sounds good. I don't think I have to worry about the interrupt taking longer than 16ms - it only checks the counter and sets a bit, but the actual work is being done elsewhere.
 

46 minutes ago, Ender said:

There should be a 32-bit cycle counter up to 500 seconds at $9FB8-$9FBB, at least according to https://github.com/commanderx16/x16-emulator/commit/9e271d1513704838e4e37123e46c255e8bb23146

I couldn't find any documentation regarding it though. The reference guide just lists $9FA0-$9FBF as "future expansion."

For now, I'll stick with the vsync interrupt, but the cycle counter could come in handy at some point.

Thank you!

Share this post


Link to post
Share on other sites
  • 0
Posted (edited)
1 hour ago, Ender said:

There should be a 32-bit cycle counter up to 500 seconds at $9FB8-$9FBB, at least according to https://github.com/commanderx16/x16-emulator/commit/9e271d1513704838e4e37123e46c255e8bb23146

I couldn't find any documentation regarding it though. The reference guide just lists $9FA0-$9FBF as "future expansion."

These are variables specific to the emulator and will not work on the final X16, which is probably why they aren't in the official documentation.

For the curious, the emulator-specific variables are:

  • $9FB0: 1 if the built-in debugger is enabled, 0 otherwise.
  • $9FB1: 1 if video logging is enabled ("-log v" command line option), 0 otherwise.
  • $9FB2: 1 if keyboard logging is enabled ("-log k" command line option), 0 otherwise.
  • $9FB3: The emulator's "echo mode" (see also "-echo" command line option)
  • $9FB4: 1 if the emulator should save a dump of the machine's state on exit, 0 otherwise.
  • $9FB5: The gif record mode. If set at runtime, this will begin writing a gif.
  • $9FB6-$9FB7: Unused.
  • $9FB8: Bits 0-7 of clockticks6502 (the cycle counter). (Read-only)
  • $9FB9: Bits 8-15 of clockticks6502 (the cycle counter). (Read-only)
  • $9FBA: Bits 16-23 of clockticks6502 (the cycle counter). (Read-only)
  • $9FBB: Bits 24-31 of clockticks6502 (the cycle counter). (Read-only)
  • $9FBC: Unused.
  • $9FBD: The emulator's keymap (see also: "-keymap" command line option). (Read-only)
  • $9FBE: Always $31 (ASCII code for '1'). Useful for detecting that the emulator is being used. (Read-only)
  • $9FBF: Always $36 (ASCII code for '6'). Useful for detecting that the emulator is being used. (Read-only)

Unused registers are read-only and will always return $FF.

Edited by StephenHorn
  • Like 3

Share this post


Link to post
Share on other sites
  • 0
15 minutes ago, StephenHorn said:

These are variables specific to the emulator and will not work on the final X16, which is probably why they aren't in the official documentation.

For the curious, the emulator-specific variables are:

  • $9FB0: 1 if the built-in debugger is enabled, 0 otherwise.
  • $9FB1: 1 if video logging is enabled ("-log v" command line option), 0 otherwise.
  • $9FB2: 1 if keyboard logging is enabled ("-log k" command line option), 0 otherwise.
  • $9FB3: The emulator's "echo mode" (see also "-echo" command line option)
  • $9FB4: 1 if the emulator should save a dump of the machine's state on exit, 0 otherwise.
  • $9FB5: The gif record mode. If set at runtime, this will begin writing a gif.
  • $9FB6-$9FB7: Unused.
  • $9FB8: Bits 0-7 of clockticks6502 (the cycle counter). (Read-only)
  • $9FB9: Bits 8-15 of clockticks6502 (the cycle counter). (Read-only)
  • $9FBA: Bits 16-23 of clockticks6502 (the cycle counter). (Read-only)
  • $9FBB: Bits 24-31 of clockticks6502 (the cycle counter). (Read-only)
  • $9FBC: Unused.
  • $9FBD: The emulator's keymap (see also: "-keymap" command line option). (Read-only)
  • $9FBE: Always $31 (ASCII code for '1'). Useful for detecting that the emulator is being used. (Read-only)
  • $9FBF: Always $36 (ASCII code for '6'). Useful for detecting that the emulator is being used. (Read-only)

Unused registers are read-only and will always return $FF.

Ah, right. Makes sense then.  I didn't notice it was amongst those other obviously emulator-specific things. 🥴

Share this post


Link to post
Share on other sites
  • 0
These are variables specific to the emulator and will not work on the final X16, which is probably why they aren't in the official documentation.
For the curious, the emulator-specific variables are:
  • $9FB0: 1 if the built-in debugger is enabled, 0 otherwise.
  • $9FB1: 1 if video logging is enabled ("-log v" command line option), 0 otherwise.
  • $9FB2: 1 if keyboard logging is enabled ("-log k" command line option), 0 otherwise.
  • $9FB3: The emulator's "echo mode" (see also "-echo" command line option)
  • $9FB4: 1 if the emulator should save a dump of the machine's state on exit, 0 otherwise.
  • $9FB5: The gif record mode. If set at runtime, this will begin writing a gif.
  • $9FB6-$9FB7: Unused.
  • $9FB8: Bits 0-7 of clockticks6502 (the cycle counter). (Read-only)
  • $9FB9: Bits 8-15 of clockticks6502 (the cycle counter). (Read-only)
  • $9FBA: Bits 16-23 of clockticks6502 (the cycle counter). (Read-only)
  • $9FBB: Bits 24-31 of clockticks6502 (the cycle counter). (Read-only)
  • $9FBC: Unused.
  • $9FBD: The emulator's keymap (see also: "-keymap" command line option). (Read-only)
  • $9FBE: Always $31 (ASCII code for '1'). Useful for detecting that the emulator is being used. (Read-only)
  • $9FBF: Always $36 (ASCII code for '6'). Useful for detecting that the emulator is being used. (Read-only)
Unused registers are read-only and will always return $FF.

Drat. It’s a shame the cycle counter is read only. It’d be a nice convenience to be able to zero it and easily measure how many cycles my game loop is using. Is there some emulator specific reason that it shouldn’t be modifiable from code?


Sent from my iPhone using Tapatalk
  • Like 1

Share this post


Link to post
Share on other sites
  • 0
6 hours ago, izb said:


Drat. It’s a shame the cycle counter is read only. It’d be a nice convenience to be able to zero it and easily measure how many cycles my game loop is using. Is there some emulator specific reason that it shouldn’t be modifiable from code?


Sent from my iPhone using Tapatalk

Only Michael could answer that.  He probably added it for debugging something he was working on.  It's probably just a temporary thing anyway since it won't be in the actual hardware.  If you want to use a timer you can set though, you could use the soft timer in the kernel.  It's 24-bit and 60Hz.  You set A to bits 0-7, X to bits 8-15, and Y to bits 16-23 and call $FFDB.  Then you can get the timer with $FFDE, it returns the bits the same way.

  • Like 1

Share this post


Link to post
Share on other sites
  • 0
8 hours ago, izb said:

Drat. It’s a shame the cycle counter is read only. It’d be a nice convenience to be able to zero it and easily measure how many cycles my game loop is using.

Any read or copy of the 32-bit value can't be done atomically anyways, so I would advise against trying to use this value in a 65C02 program. The odds of a variable rolling over and presenting you with misleading results is pretty high.

I had wondered about the runtime of my own code, myself, and had some modifications to add the cycle counter and a delta to the built-in debugger. I'll look into re-adding that and submitting a PR. Then I would recommend using that, since it can read and compare the cycle counter without altering the state of the CPU.

  • Like 2

Share this post


Link to post
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.

Guest
Answer this question...

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


×
×
  • Create New...

Important Information

Please review our Terms of Use