[comp.sys.nsc.32k] No-Slot Clock code

culberts@hplwbc.hpl.hp.com (Bruce Culbertson) (07/14/90)

Here's some code to set and get the time and date from the No-Slot
clock on the PC532.  There is some test code in a comment.  The
user interface for the test code is about as bad as you can get.
I link this into Minix now and only used the test code to be sure
the rest of the code worked.  Maybe Jordan Hubbard will want to
add this to his stand-alone library.

Bruce Culbertson
================================================================

;----------------------------------------------------------------
; Routines to set and get date/time using the PC532 No-Slot clock.
;
; Time is set and returned via an eight byte buffer.  Each byte of
; the buffer stores a BCD number.  Out-of-range values for hours
; and day-of-week will switch the clock to other modes -- see
; manual.
;
;	buf[0]	1/100's of seconds
;	buf[1]	seconds
;	buf[2]	minutes
;	buf[3]	hours
;	buf[4]	day of week
;	buf[5]	day of month
;	buf[6]	month
;	buf[7]	year (I use 90 for 1990)
;----------------------------------------------------------------
eprom_base:	.equ	h'10000000
;reset address does not seem to work -- use a read instead
;rtcadr_reset:	.equ	0+eprom_base
rtcadr_reset:	.equ	rtcadr_rd
rtcadr_wr0:	.equ	h'4000+eprom_base
rtcadr_wr1:	.equ	h'4001+eprom_base
rtcadr_rd:	.equ	h'4004+eprom_base
cfg_dc:		.equ	9	;data cache bit of cfg reg

;----------------------------------------------------------------
;; Test Code
;;
;; 1) Uncomment and assemble (the code is relocatable so you
;;    really do not even have to link it)
;; 2) Load into RAM
;; 3) To set the clock, first put the date and time into the
;;    buffer at address h'3000.  Then run _tst_set from the
;;    monitor.
;; 4) To read the clock, run _tst_get from the monitor.  Then
;;    read the time and date from the buffer at h'3000.
;
;	.text
;tst_buf:	.equ	h'3000
;
;
;_tst_set::
;	movd	tst_buf,tos
;	bsr	_rtc_set
;	adjspb	-4
;	bpt
;
;_tst_get::
;	movd	tst_buf,tos
;	bsr	_rtc_get
;	adjspb	-4
;	bpt
;----------------------------------------------------------------

; Magic code to switch from EPROM to clock.
rtc_code:
	.byte	h'c5,h'3a,h'a3,h'5c
	.byte	h'c5,h'3a,h'a3,h'5c

;----------------------------------------------------------------
; Set the real-time-clock.
; C calling sequence:   rtc_set(buf);
;			char *buf;
;----------------------------------------------------------------
_rtc_set::
	enter	[r3],0
	sprd	cfg,r3
	movd	r3,r0
	cbitb	cfg_dc,r0
	lprd	cfg,r0
	movb	@rtcadr_reset,r0
	movb	@rtcadr_reset,r0
	movb	@rtcadr_reset,r0
	addr	rtc_code(pc),tos
	bsr	rtc_wr64
	movd	8(fp),tos
	bsr	rtc_wr64
	adjspb	-8
	lprd	cfg,r3
	exit	[r3]
	ret	0

;----------------------------------------------------------------
; Set the real-time-clock.
; C calling sequence:   rtc_get(buf);
;			char *buf;
;----------------------------------------------------------------
_rtc_get::
	enter	[r3],0
	sprd	cfg,r3
	movd	r3,r0
	cbitb	cfg_dc,r0
	lprd	cfg,r0
	movb	@rtcadr_reset,r0
	movb	@rtcadr_reset,r0
	movb	@rtcadr_reset,r0
	addr	rtc_code(pc),tos
	bsr	rtc_wr64
	movd	8(fp),tos
	bsr	rtc_rd64
	adjspb	-8
	lprd	cfg,r3
	exit	[r3]
	ret	0

	; rtc_wr64(buf)
	; char *buf;
	;
	; Write 64 bits from buf to real time clock.
	;
	; r0 = data pointer
	; r1 = counter
	; r2 = tmp
rtc_wr64:
	enter	[],0
	movd	8(fp),r0
	movqb	0,r1
wr1:	tbitb	r1,0(r0)
	bfs	wr2
	movb	@rtcadr_wr0,r2
	br	wr3
wr2:	movb	@rtcadr_wr1,r2
wr3:	addqb	1,r1
	cmpb	64,r1
	bne	wr1
	exit	[]
	ret	0

	; rtc_rd64(buf)
	; char *buf;
	;
	; Read 64 bits from real time clock to buf.
	;
	; r0 = data pointer
	; r1 = counter
	; r2 = tmp
rtc_rd64:
	enter	[],0
	movd	8(fp),r0
	movqb	0,r1
rd1:	movb	@rtcadr_rd,r2
	tbitb	0,r2
	bfs	rd2
	cbitb	r1,0(r0)
	br	rd3
rd2:	sbitb	r1,0(r0)
rd3:	addqb	1,r1
	cmpb	64,r1
	bne	rd1
	exit	[]
	ret	0