2024-08-06 17:33:19 +02:00
|
|
|
hardware updates
|
|
|
|
|
2024-08-08 01:58:22 +02:00
|
|
|
* problems
|
|
|
|
** 32 bit timestamps (cycle counts)
|
|
|
|
- we use unsigned 32 bit ints for timestamps.
|
|
|
|
- "timestamps" are misnomers, they're cycle counts.
|
|
|
|
- a 32 bit int has a max value of 4,294,967,295 cycles.
|
|
|
|
at 8 Mhz, this is equivalent to 536.87 seconds, or just under 9 minutes.
|
|
|
|
- a 64 bit unsigned int has a max value of 18,446,744,073,709,551,615
|
|
|
|
at 8 Mhz, this is equivalent to 2305843009213.69 seconds, which we'll never see.
|
|
|
|
** E_UPDATE(v) -> EMUL_hardwareUpdate(v) is confusing
|
|
|
|
- dispatch::doUpdate() calls EMUL_hardwareUpdate() based on cpu_update_period.
|
|
|
|
- cpu_update_period is a number of cycles, and roughly gives us our update resolution.
|
|
|
|
- since instructions take anywhere from 2-8 cycles, this can be slightly off.
|
|
|
|
** Need to handle timing, i.e. lock to 8 Mhz.
|
|
|
|
- VICE updates timing every video frame (60 hz.)
|
|
|
|
- We need to update our per-cycle loop based on
|
|
|
|
* possible changes
|
|
|
|
- change the naming of 'timestamp' to 'cyclecount'.
|
|
|
|
- move to 'uint64_t' instead of 'word32' for timestamp/cyclecount
|
|
|
|
-> will want to hunt down all uses of word32 to make sure of what we have.
|
|
|
|
- get rid of E_UPDATE macro. Consider renaming EMUL_hardwareUpdate to just hardwareUpdate.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
* ---- old notes ----
|
|
|
|
|
2024-08-06 17:33:19 +02:00
|
|
|
* hardware updates take place at regular intervals:
|
|
|
|
- screen refresh (60 hz)
|
|
|
|
- system timer (100 hz)
|
|
|
|
|
|
|
|
* emulator itself has to process SDL events at around 60 hz.
|
|
|
|
- this could be handled separately from the cpu loop.
|
|
|
|
|
|
|
|
* the way this often is handled
|
|
|
|
- we know our clock speed, 8 Mhz.
|
|
|
|
- something synchronizes the emulated clock speed to keep it at 8 Mhz.
|
|
|
|
- all events happen at certain clock intervals
|
|
|
|
- each clock cycle is 125 ns.
|
|
|
|
** example: screen refresh
|
|
|
|
- 100 hz timer with 1 msec resolution.
|
|
|
|
- need to update the timer value every 1 msec
|
|
|
|
1 msec = 1,000,000 ns
|
|
|
|
1 msec = 1,000,000 ns / 125 ns per cycle = 8000 cycles
|
|
|
|
- after 100,000 updates, the timer fires an IRQ
|
|
|
|
*** problems
|
|
|
|
- instructions take varying numbers of cycles
|
|
|
|
- updates could be delayed or slightly irregular
|
|
|
|
|
|
|
|
hardware update (event) table. gets updated as events occur.
|
|
|
|
|
|
|
|
| event | freq | last update | next update | notes |
|
|
|
|
| ------------ | ------ | ----------- | ----------- | ----------------- |
|
|
|
|
| 100 hz timer | 8000 | 0 | 8000 | 1 msec resolution |
|
|
|
|
| 60 hz timer | 133333 | 0 | 133333 | 60 hz resolution |
|
|
|
|
| | | | | |
|
|
|
|
|
|
|
|
60 hz timer, assuming all 2 cycle instructions, will update
|
|
|
|
|
|
|
|
* alternate approach: alter system clock so 60 hz divides cleanly
|
|
|
|
*idea* Could get around this by altering the system clock enough to at least
|
|
|
|
make the 60 hz timer work correctly. i.e. so that we have an exact number of
|
|
|
|
clock cycles.
|
|
|
|
|
|
|
|
* alternate approach: accept that any event might be a bit off and pick better divisors
|
|
|
|
*idea* make the timer 60 hz timer 50 hz instead. in that case,
|
|
|
|
50 hz = 20,000,000 ns / 125 ns = 160000 cycles.
|
|
|
|
|
|
|
|
compare to 60 hz = 16,666,666.66 ns / 125 ns = 133333.33 cycles.
|
|
|
|
|
|
|
|
^-- sticks with the cycle-timed approach, but gets us better accuracy.
|
|
|
|
that kind of means that anything that doesn't fit the cycle time is
|
|
|
|
going to be a bit off, but that might be true anyway.
|
|
|
|
|
|
|
|
* other thoughts
|
|
|
|
- smallest instruction is 2 cycles, or 300 ns.
|
|
|
|
- largest instruction is 8 cycles, or 1000 ns.
|
|
|
|
-> effectively, our resolution can only be as good as 1000 ns.
|
|
|
|
- 60 hz is 16.66 msec, or 133333.33 cycles
|