base:initialize_tod_clock_on_all_platforms
no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
— | base:initialize_tod_clock_on_all_platforms [2015-04-17 04:32] (current) – created - external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Initializing TOD clock on all platforms ====== | ||
+ | |||
+ | Before using the TOD Clock, you need to tell it if it's clocked at 50Hz or 60Hz, in order for it to measure time correctly. | ||
+ | The TOD is clocked from the A/C Power frequency on C64 and C128. On the SX-64 however, the TOD clock comes from a 60Hz crystal in both the NTSC and PAL machines. This means that figuring out if the machine is NTSC or PAL is not enough to determine if the TOD is clocked at 50Hz or 60Hz. | ||
+ | |||
+ | It is however possible to initialize the TOD correctly on both PAL and NTSC machines regardless if their TOD is clocked at 50Hz or 60Hz by using a single piece of code. And you don't even need to figure out if the machine is PAL or NTSC. There' | ||
+ | |||
+ | ===== Theory of Operation ===== | ||
+ | |||
+ | - Gain max control by setting a dummy NMI and disabling the display | ||
+ | - Set TOD Clock Frequency to 60Hz | ||
+ | - Sync raster to real TOD Clock Frequency | ||
+ | - Count number of CPU cycles it takes for TOD to count 1 decisecond | ||
+ | - If number of cycles counted is less than 118230, TOD Clock Frequency is set to 60Hz, otherwise 50Hz. | ||
+ | |||
+ | |||
+ | Alternatively the same result can be achieved by clocking TOD at 50Hz and | ||
+ | then just counting 98525, but then the margin for error increases slightly. | ||
+ | |||
+ | ===== The code ===== | ||
+ | |||
+ | |||
+ | < | ||
+ | ;Initialize TOD Clock by correctly determining the actual frequency | ||
+ | ;by which the TOD is clocked. | ||
+ | ;Supports PAL/NTSC with 50/60Hz TOD-Clock in ANY combination. | ||
+ | ;by Devia/ | ||
+ | |||
+ | TODInit2: | ||
+ | sei | ||
+ | lda #< | ||
+ | sta $fffa ; | ||
+ | lda #> | ||
+ | sta $fffb ; | ||
+ | lda # | ||
+ | sta $01 ; so new NMI vector is active | ||
+ | |||
+ | lda #0 | ||
+ | sta $d011 ; | ||
+ | sta $dc0e ; | ||
+ | sta $dc0f ; | ||
+ | sta $dc0b ; | ||
+ | sta $dc0a ; | ||
+ | sta $dc09 ; | ||
+ | sta $dc08 ; | ||
+ | |||
+ | lda $dc08 ; | ||
+ | : | ||
+ | beq :- ; | ||
+ | |||
+ | ldx # | ||
+ | ldy #0 ; counter operation | ||
+ | lda $dc08 ; | ||
+ | : | ||
+ | bne : | ||
+ | iny ; | ||
+ | jmp : | ||
+ | : | ||
+ | nop ; | ||
+ | : | ||
+ | beq : | ||
+ | ;Each loop = 16 cycles | ||
+ | ;If less than 118230 cycles passed, TOD is | ||
+ | ; | ||
+ | ; | ||
+ | ;It might be a good idea to account for a bit | ||
+ | ;of slack and since every loop is 16 cycles, | ||
+ | ;28*256 loops = 114688 cycles, which seems to be | ||
+ | ; | ||
+ | ;a Y value of 28. | ||
+ | |||
+ | cpy # | ||
+ | bcc :+ ;- Then we already have correct 60Hz $dc0e value | ||
+ | lda # | ||
+ | sta $dc0e | ||
+ | : | ||
+ | lda # | ||
+ | sta $d011 | ||
+ | rts | ||
+ | |||
+ | INT_NMI: | ||
+ | rti | ||
+ | </ | ||
+ | |||
+ | ===== Example Program ===== | ||
+ | |||
+ | An example program using the above method can be found here: {{: | ||
+ | |||
+ | ===== Footnotes ===== | ||
+ | |||
+ | The sta $dc0b, sta $dc0a and sta $dc09 can be omitted if you don't need to reset the clock to 0:00:00. The sta $dc08 is needed to unlatch the TOD in case it got latched prior to this routine. | ||
+ | When running this in Vice, it will always end up detecting the Vice TOD Clock as 60Hz clocked and it will always be counting correct despite of this. In other words: Vice seems to ignore bit 7 of $dc0e and just always clock correctly. | ||
+ | In CCS64, the reset of the TOD seems to take longer than it should, but the routine still works. | ||
+ | In Hoxs64 the emulation is correct down to the last cycle! | ||
base/initialize_tod_clock_on_all_platforms.txt · Last modified: 2015-04-17 04:32 by 127.0.0.1