Timer interrupts originate from a host thread that periodically sets an emulator pending flag. The repository's timer callback sleeps according to the selected configuration, then records a request:
usleep(Emu_TimConfigMap[Emu_TimConfig]);
Emu_MutexLock(); INT[INT_TIMER] = 1; Emu_MutexUnlock();
The first excerpt is the valid-configuration sleep branch; an invalid configuration has a fallback delay. The mutex protects setting the shared pending flag.
Start the device with ./emulator -timer program.hex. The program must install a handler and leave the timer and global masks clear. Delivery writes cause two and sets the global hardware-interrupt mask while the handler runs.
The default configuration requests a 500-millisecond interval. Timer configuration changes the interval through a memory-mapped register. These are host-time delays, not a promise of a fixed number of simulated instructions between interrupts. Because requests use one pending bit, several ticks can coalesce while a request remains pending or masked.
Source: emulator.c.