Timers and timing: Difference between revisions

From MAMEDEV Wiki
(New page: '''Timers''' in MAME are objects which can call you back after a very precise amount of emulated time has passed. You can use them in your drivers and devices to emulate hardware timers o...)
 
mNo edit summary
 
(4 intermediate revisions by 2 users not shown)
Line 13: Line 13:
  my_timer = timer_alloc(machine, callback, reference_pointer);
  my_timer = timer_alloc(machine, callback, reference_pointer);


'''machine''' is the current machine pointer - you should be calling timer_alloc in either your MACHINE_INIT(), DRIVER_INIT(), or DEVICE_INIT()/CPU_INIT() functions, all of which have the current machine pointer available.
'''machine''' is the current machine pointer.  You generally should be calling timer_alloc in either your MACHINE_INIT(), DRIVER_INIT(), or DEVICE_INIT()/CPU_INIT() functions, all of which have the current machine pointer available.


'''callback''' is your function that is called when the timer expires.  It's of this form:
'''callback''' is your function that is called when the timer expires.  It's of this form:


  TIMER_CALLBACK( my_timer_callback )
  TIMER_CALLBACK( my_timer_callback )
{
}


'''reference_pointer''' is any value you want that you can fit into a pointer (beware of 32/64 bit issues here!).  It is passed to your callback as a void * named '''ptr'''.
'''reference_pointer''' is any value you want that you can fit into a pointer (beware of 32/64 bit issues here!).  It is passed to your callback as a void * named '''ptr'''.
Line 55: Line 57:
  ATTOTIME_IN_SEC(x)
  ATTOTIME_IN_SEC(x)


This creates an attotime for a timer which first every x seconds.
This creates an attotime for a timer which fires every x seconds.
   
   
  ATTOTIME_IN_MSEC(x)
  ATTOTIME_IN_MSEC(x)
Line 63: Line 65:
These work similarly to ATTOTIME_IN_SEC but work in terms of milliseconds, microseconds, and nanoseconds.  They are rarely used, obviously.
These work similarly to ATTOTIME_IN_SEC but work in terms of milliseconds, microseconds, and nanoseconds.  They are rarely used, obviously.


Math operations on attotime values are available; refer to the [http://mamedev.org/source/src/emu/attotime.h.html attotime.h] file for more information.
Math operations on attotime values are available; refer to the [http://github.com/mamedev/mame/blob/master/src/emu/attotime.h attotime.h] file for more information.

Latest revision as of 03:25, 25 November 2014

Timers in MAME are objects which can call you back after a very precise amount of emulated time has passed. You can use them in your drivers and devices to emulate hardware timers or do other kinds of periodic tasks.

The basics

Creating a timer

Each timer is an object which you refer to by an opaque pointer, like many other things in MAME. For timers, they are of type "emu_timer", like this:

emu_timer *my_timer;

To instantiate a timer, you call timer_alloc().

my_timer = timer_alloc(machine, callback, reference_pointer);

machine is the current machine pointer. You generally should be calling timer_alloc in either your MACHINE_INIT(), DRIVER_INIT(), or DEVICE_INIT()/CPU_INIT() functions, all of which have the current machine pointer available.

callback is your function that is called when the timer expires. It's of this form:

TIMER_CALLBACK( my_timer_callback )
{
}

reference_pointer is any value you want that you can fit into a pointer (beware of 32/64 bit issues here!). It is passed to your callback as a void * named ptr.

Your callback also gets a pointer to the current machine named machine and one more parameter we will discuss a little later.

Arming a timer

Timers can either be one-shot or periodic. One-shot timers fire once and then never again. Periodic timers automatically start over again after they fire and will keep going off until you stop them. You can change a timer's "mode" on the fly if you wish - each new arm call makes the timer mode behave as specified.

This is how you arm a timer for one-shot operation:

timer_adjust_oneshot(my_timer, time_to_fire, reference_integer);

my_timer is the emu_timer object pointer you allocated, time_to_fire is the amount of time from the current point in the emulation when the timer should fire, and reference_integer is a number for your own use which is passed to your callback as an int named param.

Here's the equivalent for periodic:

timer_adjust_periodic(my_timer, time_to_delay, reference_integer, time_to_fire);

This is quite similar, but it has two time parameters. The first (time_to_delay) is an optional amount of time to wait before beginning our periodic operation. The time_to_fire parameter gives the period of the timer.

About those time parameters

Time in MAME is in terms of "attotime", a high-precision 96 bit fixed point representation accurate to 1 attosecond. Fortunately a variety of helpers are provided in case you don't speak attoseconds:

attotime_never is a constant for infinity, or as close to it as MAME can get. If you use it as a timer's time value the timer will never go off. This is useful for when you're emulating a hardware timer and it's disabled.

attotime_zero is a constant for zero time. If you use this as a timer value the callback will occur immediately.

The following conversion macros are also available:

ATTOTIME_IN_HZ(x)

This creates an attotime for a timer which fires x number of times per second.

ATTOTIME_IN_SEC(x)

This creates an attotime for a timer which fires every x seconds.

ATTOTIME_IN_MSEC(x)
ATTOTIME_IN_USEC(x)
ATTOTIME_IN_NSEC(x)

These work similarly to ATTOTIME_IN_SEC but work in terms of milliseconds, microseconds, and nanoseconds. They are rarely used, obviously.

Math operations on attotime values are available; refer to the attotime.h file for more information.