Jump to content
IGNORED

Atari 5200 Real Time Clock


Recommended Posts

Does anyone know what the ticks are for the Real-time Clock Lo of the Atari 5200?  I am using @Ryan Witmer's "hardware.s" which has the RCLKHI ($01) and RCLKLO ($02) - thank you, by the way!  I timed the RCLKHI at about 8 second to cycle.  But I the RCLKLO runs too quick for me to figure out.  I was thinking of reading RCLKLO and then adding a number, say $10, to it and then when it reaches that number, change the background color or something to figure out how many ticks happen to time a second out of the RCLKLO.  But I am not successful yet.  Thank you!

Link to comment
Share on other sites

It's based on the TV frame rate.  Low byte incremented about every 60th of a second.  High incremented once the low ticks over (about 4.25 seconds)

The frame rate for NTSC from Antic is actually 59.9227 FPS so a simulated RTC will run a bit slower than reality but for most purposes should be OK.

 

Link to comment
Share on other sites

If you want a little more detail, RCLKLO is incremented in the immediate vertical blank interrupt that lives in the BIOS, so it gets updated during every VBLANK period, and RCLKHI is updated when RCLKLO rolls over.  If you write a custom immediate VBI (which is rare in my experience) you'll need to update the clock yourself.  Also, if you disable VBI, the clock will stop since nothing will be tending to it.

Link to comment
Share on other sites

17 hours ago, Rybags said:

It's based on the TV frame rate.  Low byte incremented about every 60th of a second.  High incremented once the low ticks over (about 4.25 seconds)

The frame rate for NTSC from Antic is actually 59.9227 FPS so a simulated RTC will run a bit slower than reality but for most purposes should be OK.

 

not actually, the NTSC standard of old is not exactly 60 Hz. Pictures of the Broadcast test patterns showing frequency were also posted on the forums adding a little verification to that as well.

I have had long winded discussions about this so just for clarity, because video devices are always made doing this and SHOULD not! It causes timing and alignment issues causing undesired interference issues...

The NTSC rate was reduced a fraction of a percent depending on era for tolerance as well as compatibility and is well known documented fact. This causes video overlay devices operating as 60 hz to periodically miss align and not be smooth. The accepted value rounded to 59.94 these days. 60 is short hand for 59.94. Please be precise in this area because people make awesome video cards for our old machines and that little ghost causes imperfections to be found after production, sometimes right away and sometimes lurking to emerge years later. So .999 does matter!

The Atari's rate is very close to 59.94 and was reduced further, as a number of consumer televisions worked better at the slightly lower frequency tolerance of old. splitting the difference was the correct path. There is mention of this discussion in Atari so that even Samsung TV's of the time would work with the Atari home computers.

Engineers know that 59.94 fields per second is legacy for the NTSC color system as prior to 1954 the black and white monochrome video was locked to at 60Hz frequency standard alternating current in the United States. A 29.97 Hz frame scan rate was designed for color TV's to be backwards compatible with black and white monochrome televisions when the color sets were introduced. A frequency offset of 0.03Hz was utilized to make space for the color sub-carrier.

This discussion came into play again with Bryan during the development of the UAV. It also helped him understand the added artifact color that the UAV correctly produces. I do not know if the timebase was eventually made correct or if some other method was employed for the end products. I just know he was very interested and soon after the discussion progress was right where it needed to be.

Edited by _The Doctor__
  • Like 2
Link to comment
Share on other sites

Must be early in the day, double checking I see some other discussions about this sort of thing.

 

https://www.nvidia.com/en-us/geforce/forums/shield-tv/9/247789/why-is-59940-hz-recommended-over-60hz/

 

modern day no frame and drop frame discussions are something to check on as well

 

Edited by _The Doctor__
Link to comment
Share on other sites

NTSC broadcast standard timings and timecodes aren't really relevant here except to note that the Atari deviates from them. The rate at which RCLKLO/HI count is based on the rate at which the VBI occurs, which is solely based on the rate that the master clock is divided down by the clock generator and the horizontal/vertical counters within ANTIC. NTSC machine master clock of 14.31818MHz divided by 8 gives machine/bus clock of 1.7897725MHz. ANTIC counts 114 cycles per scan line for a horizontal rate of 15.700KHz and 262 scan lines per frame for a vertical rate of 59.9227Hz, as Rybags noted above.

 

Using an approximation of 60 ticks/second instead of 59.9227 ticks/second gives an error of about 0.13%. After a full day, this results in timing being off by 1 minute 51 seconds. Not ideal if you're running a clock for a 24/7 BBS that's on for weeks, perfectly fine for shorter time measuring uses, and cheaper to compute.

 

Trying to correct for this in hardware to achieve more standard display timing is a different issue. Changing the horizontal and vertical counts is impractical as it would require modifying ANTIC internals, and where that's feasible, would break software relying on precise cycle timings. Speeding up the entire system clock is safer, at the cost of slightly speeding up the output and raising the pitch of the POKEY a tiny bit. This is what you'd expect to see from most emulation devices that output standard video timings, because otherwise trying to run at true rate would result in periodic jank. But video mods for the original computers are the opposite and run non-standard video timings, because they want to stay locked to GTIA without the cost and downsides of trying to buffer entire scanlines or frames.

 

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

We're doing a non interlaced display so the timing will be off regardless vs broadcast.

I'm not even sure though if the scanline durations are the same, isn't there some slight difference there?

 

What we need to do is deduce an easy algorithm for  PAL and NTSC where we could add "leap ticks" to keep a software RTC more accurate than by the 50/60 method alone.

Link to comment
Share on other sites

On 2/27/2024 at 10:25 AM, Rybags said:

What we need to do is deduce an easy algorithm for  PAL and NTSC where we could add "leap ticks" to keep a software RTC more accurate than by the 50/60 method alone.

I tried to do that once and arrived at a quite accurate correction. My son used to run a 130XE with that routine for months on end as an alarm clock. I did not use the built-in timers at all, however, but implemented my own in a VBI routine.

 

IIRC I calculated how much correction was required per day and calculated after how many jiffies there should be a "leap jiffy" to distribute clock correction evenly over the course of a day. There's counters for jiffies, seconds, minutes, etc. plus a separate counter that is decreased and causes a "leap jiffy" or so every time it hits zero. 

 

I found some assembly code but that's most probably work in progress for an improved version never that never got finished. (There's some code in there to display the time, the actual timing code isn't that long.) We should have an Action! version somewhere (with a VBI programmed in Action!).

 

 

;ATARI VBLANK CLOCK
;BLUESTONEMC & SLX
;2015-2020
;
;version 1.8
;
;most subroutines replaced with inline code
;reset performed using Y register instead of table (saving a whopping byte!)
;correction initializiation routine prepared for PAL/NTSC aware version
;
;System Reset Proof code added
;
;PAL/NTSC detection added
;
;daily correction added
;

TESTING SET 1
;
;System Equates
;
VCOUNT = $D40B
SYSVBV = $E45F
SETVBV = $E45C
XITVBV = $E462
DOSINI = $0C


 ORG $600

; IN CASE DOS INITS AT FIRST
; BYTE, JUST RTS BACK
;
			
RETURN	RTS 
;
TIMEDATA
TENTH 	.BYTE $00
SECOND 	.BYTE 55
MINUTE 	.BYTE 59
HOUR 	.BYTE 23
DAY 	.BYTE 28
MONTH 	.BYTE $02
YEAR 	.BYTE 20
CENTURY .BYTE 20
OLDYEAR .BYTE $00
COUNTER .BYTE $05
CORRECT .BYTE 103,2
;
; INIT MONLEN TO ONE LONGER THAN
; LENGTH OF MONTH because it compares after incrementing
;
MONLEN 		.BYTE 32,29,32,31,32,31
 			.BYTE 32,32,31,32,31,32

RESETVALUE	.BYTE 10, 60, 60, 24, 00, 13, 100, 100

; POP USR ARGUMENT COUNT FROM
; STACK. WILL NOT WORK IF USR()
; IS CALLED WITH PARAMETERS
;
BASICSTART	PLA 
; 
; RELOC ROUTINE - JSR to Printer routine acc AA and then examine stack for own address
; 
; RELOC via table in located where storage will go later? 
; multisegment load tempting (RELOC first, rest at MEMLO? but fails on some DOSes
;

;old initialization code obviated by loading initalized values

START		LDA DOSINI			;save old DOSINI to JSR in our code
			STA OLDDOSINI+1
			LDA DOSINI+1
			STA OLDDOSINI+2
OLDDOSINI	JSR DOSINI			;and jump there
			LDA <OLDDOSINI		;patch own initialization address into DOSINI
			STA DOSINI
			LDA >OLDDOSINI
			STA DOSINI+1
;
; INSTALL MAIN CLOCK COUNTER LOOP IN IMM VBLANK
;			
			LDX # >PALNTSC
			LDY # <PALNTSC
			LDA #6
			JSR SETVBV 

	.IF TESTING=1
SCREEN = $BC90


;display routine for testing
SCREENDISPLAY	LDA SECOND
				JSR BYTETODEC
				ORA #$10
				STA SCREEN+20
				TXA
				ORA #$10
				STA SCREEN+19
				
				LDA MINUTE
				JSR BYTETODEC
				ORA #$10
				STA SCREEN+17
				TXA
				ORA #$10
				STA SCREEN+16
				
				LDA HOUR
				JSR BYTETODEC
				ORA #$10
				STA SCREEN+14
				TXA
				ORA #$10
				STA SCREEN+13
				
				LDA YEAR
				JSR BYTETODEC
				ORA #$10
				STA SCREEN+10
				TXA
				ORA #$10
				STA SCREEN+9
				
				LDA CENTURY
				JSR BYTETODEC
				ORA #$10
				STA SCREEN+8
				TXA
				ORA #$10
				STA SCREEN+7
				
				LDA MONTH
				JSR BYTETODEC
				ORA #$10
				STA SCREEN+5
				TXA
				ORA #$10
				STA SCREEN+4
				
				LDA DAY
				JSR BYTETODEC
				ORA #$10
				STA SCREEN+2
				TXA
				ORA #$10
				STA SCREEN+1
				
				JMP SCREENDISPLAY

BYTETODEC 						;REQUIRES BYTE TO BE CONVERTED IN ACC
 				LDX #$FF        ; WILL RETURN TENS DIGIT IN X
 				SEC             ; AND LOWEST DIGIT IN ACC
LOOP.1 			INX       		; Count Tens up by one
 				SBC #10         ; deduct 10
 				BPL LOOP.1      ; if still above zero, the last value was above 10, so continue
 				ADC #10         ; if not, put 10 back
 				RTS
	.ENDIF

			RTS
 
;
; AFTER SETVBV WILL RTS TO BASIC (or DOS if called from DOS)
;
;
; DURING EVERY VBLANK CORRECTION
; COUNTER IS REDUCED BY ONE
;
;
;MAINFIRST	JSR PALNTSC 		

MAIN		DEC CORRECT
 			BNE DECJIFFY
;
; WHEN REACHING ZERO, MSB CORR.
; COUNTER IS REDUCED BY ONE
;
 			DEC CORRECT+1
 			BNE DECJIFFY
;
; WHEN MSB REACHES ZERO,
; CORRECTION COUNTER IS RESET
; TO START VALUE 358
;
CORRECTLOW	LDA #103
 			STA CORRECT
CORRECTHIGH	LDA #$02
 			STA CORRECT+1
;
; THEREAFTER CORRECTION COUNTER
; COUNTER IS REDUCED BY ONE.
;
 			DEC COUNTER
 			BNE EXIT
 			JSR INCTIME
;
; DURING EVERY VBLANK JIFFY
; COUNTER IS REDUCED BY 1
;			
DECJIFFY	DEC COUNTER
			BNE EXIT
			JSR INCTIME

EXIT		JMP SYSVBV
;
; IF COUNTER REACHES ZERO, TIME
; INCREASE is performed
;
INCTIME 	LDX #5			;reset counter to 5 for next 1/10th of a second
 			STX COUNTER

 			LDY #0			;default reset value for time values
;
 			LDX #0
NEXTVALUE	INC TIMEDATA,X
			CPX #$04		;check if increasing day
			BNE CONTCHECK	;if not, continue with standard routine	
;
; the following routine checks whether the year has changed since the day was changed the last time 
; and performs a check whether the year is a leap year
; this is done here because the day is likely to be adjusted to the actual data after program
; initialisation and the correct length of the month is required now to check whether the month needs 
; to be rolled over
;
			LDA #$07		;every full day a correction by 35 7/10th of a second is required
			STA TIMEDATA	;this could be distributed more evenly during the day at the cost 
							;of more memory usage for the program by alternating a COUNTER
							;increase of 1 and 2 for every full hour except midnight
							;NTSC value TBD
			
			LDA YEAR		;load current year
 			CMP OLDYEAR     ;check if year has changed since last cycle (e.g. changed by user)
 			BEQ DOCHECK		;if not, continue normally
 			STA OLDYEAR     ;if it has changed, reset OLDYEAR to new value and check for leap year

			LDY #29			;set non-leap-year check value for February days

 			AND #$03 		;check if divisible by 4
 			BNE SAVEMONLEN	;if it isn't, then it is not a leap year and 29 can be saved
 			LDA CENTURY		;it's not a leap year unless the century is divisibly by zero         
 			AND #$03
 			BNE SAVEMONLEN	;if it isn't save 29 as check value for February
 			INY             ;if it is, increase to 30

SAVEMONLEN 	STY MONLEN+1 	;and store directly in table for February

DOCHECK		LDY MONTH		;load actual month
			LDA MONLEN-1,Y	;load reset value for actual month
			CMP TIMEDATA,X	;check if this has been reached
			BNE EXITINC		;if not, exit
			LDY #1			;otherwise load 1 to be stored during reset
			BNE RESET		;and proceed to reset routine

;
;REMINDER
;
;old algorithm used a 2 counter-decrement every hour for extra correction
;check if still required
;

CONTCHECK	CPX #6			;check if year has been reached
			BNE CONTCHECK1	;if not, continue
			DEY				;if yes, change reset value to 0
CONTCHECK1	LDA TIMEDATA,X	
			CMP RESETVALUE,X ;check if value has reached value that requires reset
 			BNE EXITINC 

RESET	 	TYA				;load resetvalue from Y
			STA TIMEDATA,X	;store to variable
			INX				;increase loop counter to next time value
			CPX #$08		;check if beyond end of table
			BNE	NEXTVALUE	;if not, continue
EXITINC		RTS
			

;
;correction counter is initialized to 358, as counter needs to be corrected every 358 jiffies
;to maintain correct time (as system frequency is not exactly 50 Hz on PAL systems)
;
;for some reason I noted 358 but the actual value is 615, needs to be investigated
;

PALNTSC		BIT VCOUNT
  		  	BPL PALNTSC
WAIT1 		LDA VCOUNT
  			BPL VBOVER
  			TAX
  			BMI WAIT1
VBOVER 		CPX #$90
 			LDA #0
 			ADC #0
			BNE DONE		

			LDA #$ED
 			STA CORRECTLOW+1		;patch correction factor for NTSC into 
 			LDA #2					;correction routine
			STA CORRECTHIGH+1
			LDA #$06				;in NTSC 1/10th of a second takes 6 VBLANKS
			STA INCTIME +1			;so patch counter reset routine accordingly
			;
; INSTALL MAIN CLOCK COUNTER LOOP IN IMM VBLANK 
;			
DONE		LDX # >MAIN
			LDY # <MAIN
			LDA #6
			JSR SETVBV
			JMP SYSVBV		;exit VBLANK
;		
; ADD INIT ADDRESS SEGMENT FOR
; BINARY LOAD
;
 			ORG $02E2
 			.BYTE  <START
 			.BYTE  >START

 

  • Like 4
Link to comment
Share on other sites

How often do RTC devices with their drivers check the time from the devices when leaving the computer run all day/all month?

Not sure how long before the drivers for those are reporting incorrect times unless they are called at regular intervals or just before saves / writes to other devices...

 

Edited by _The Doctor__
Link to comment
Share on other sites

20 hours ago, _The Doctor__ said:

How often do RTC devices with their drivers check the time from the devices when leaving the computer run all day/all month?

Not sure how long before the drivers for those are reporting incorrect times unless they are called at regular intervals or just before saves / writes to other devices...

 

Not sure if I really understand your concern. Doesn‘t R-TIME8 provide the time at some dedicated memory locations more or less continuously and leaves it to programs using the time how often to read it? As there is no dedicated system clock on the Atari it would seem to make sense to just access those memory locations whenever you need the time rather than updating a separate clock. 

Link to comment
Share on other sites

23 hours ago, slx said:
;
 			ORG $02E2
 			.BYTE  <START
 			.BYTE  >START

 

I'm curious, from what source did you learn 6502 assembly language ? In almost 50 years, I have -never- seen that construct for an init/run vector.

Edited by Alfred
Link to comment
Share on other sites

On 3/2/2024 at 10:44 PM, Alfred said:

I'm curious, from what source did you learn 6502 assembly language ? In almost 50 years, I have -never- seen that construct for an init/run vector.

I learned it from Rodney Zaks’ book combined with Antic articles and De Re Atari. I am pretty sure I wasn’t clever enough to come up with that myself but copied the idea from some code I saw but don’t have the faintest idea where that might have been.

 

Google shows it mentioned here and a similar construct is in the SpeedScript source code.

 

May I ask if it’s the low/high byte notation you found strange or anything else? Come to think of it, if it’s the former it is probably due to my not checking that a pseudo-opcode to store a 2-byte value would work as well (like .WORD START or .DB START).

 

 

  • Like 1
Link to comment
Share on other sites

18 hours ago, slx said:

I learned it from Rodney Zaks’ book combined with Antic articles and De Re Atari. I am pretty sure I wasn’t clever enough to come up with that myself but copied the idea from some code I saw but don’t have the faintest idea where that might have been.

 

Google shows it mentioned here and a similar construct is in the SpeedScript source code.

 

May I ask if it’s the low/high byte notation you found strange or anything else? Come to think of it, if it’s the former it is probably due to my not checking that a pseudo-opcode to store a 2-byte value would work as well (like .WORD START or .DB START).

 

 

It was the low/high byte separation. Normally all you see is a .WORD address. to see low/high there was surprising.

  • Like 1
Link to comment
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.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

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

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...