	.psect	clock
	.title	vt52 clock display
;
; this program displays a digital clock on the face of a vt52 display
;
; written by:
;	mark johnson, september 22, 1977.
;
	.mcall	ttyout,tinit,enter,leave
	.mcall	qio$s,gtim$s,mrkt$s,wtse$s
	.dsabl	gbl

;
esc=33	;escape code used to signal vt52 command
lf=12	;line feed code
bs=10	;backspace code
cursr=103	;cursor right command
cursl=104	;cursor left command
cursu=101	;cursor up command
cursd=102	;cursor down command
;
digtop=41	;code for top line of digits
diglin=20.	;number of lines in a digit
bits=16.	;number of columns in a digit
;
cohr10=2
cohr1=20.
colcol=40.+40
comn10=44.
comn1=62.
;
	.globl	io.att		;attach command needed for output
io.wvb=410	;need to use write/pass all for cursor control
;
	.macro	fill	addr,char
	mov	addr,r3		;get address
	movb	char,(r3)+
	movb	char,(r3)+
	movb	char,(r3)+
	.endm
;
start:	tinit	5,1
	qio$s	#io.att,#5
;
; initialize storage
;
	mov	#-1,hr10	;force display first time
	mov	#-1,hr1
	mov	#-1,mn10
	mov	#-1,mn1
;
	ttyout	#erase,#erasel	;erase the screen
;
loop:	gtim$s	#tbuf	;get time from system
	mov	tbuf+6,r5	;get hours
	clr	r4		;double precision
	div	#10.,r4		;tens digit in r4, ones in r5
;
	cmp	r4,hr10		;tens digit ok?
	beq	1$		;yes, skip this stuff
	mov	r4,hr10		;update memory
	mov	#cohr10,r2	;set up column number
	jsr	pc,char		;display it
;
1$:	cmp	r5,hr1		;how is the units digit?
	beq	2$		;ok, don't change it
	mov	r5,r4
	mov	r4,hr1		;update memory
	mov	#cohr1,r2	;set up column number
	jsr	pc,char		;show this one
;
2$:	mov	tbuf+10,r5	;get minute
	clr	r4		;double precision
	div	#10.,r4		;tens dig in r4, units in r5
;
	cmp	r4,mn10		;tens digit ok?
	beq	3$		;ok, don't change it
	mov	r4,mn10		;update memory
	mov	#comn10,r2	;set up column number
	jsr	pc,char		;show the digit
;
3$:	cmp	r5,mn1		;minute digit ok?
	beq	4$		;ok, don't change it
	mov	r5,r4		;set up parameter
	mov	r4,mn1		;update memory
	mov	#comn1,r2	;set up column number
	jsr	pc,char		;show this one
;
; update seconds
;
4$:	gtim$s	#tbuf		;fresh time for seconds accuracy
	mov	tbuf+12,r5	;get seconds
	clr	r4		;dubble precise
	div	#10.,r4		;tens in r4, units in r5
	add	#'0,r4		;convert to ascii
	add	#'0,r5		;convert to ascii
;
	fill	#s101,r4
	fill	#s102,r4
	fill	#s103,r4
;
	fill	#s11,r5
	fill	#s12,r5
	fill	#s13,r5
;
	ttyout	#colon,#colen
;
;wait for a while
;
	mrkt$s	#2,#1,#2	;wait one second
	wtse$s	#2		;wait for it
;
	jmp	loop		;then go again
	.page
	.sbttl	char - display one character
;
; char - display one character
;
; inputs:
;	r2 - column number of first column of character
;	r4 - digit to display in range 0-9.
;
; outputs: none
;
char:	enter	r0,r1,r2,r3,r4,r5
	movb	chtb(r4),r1	;set up character to use
	asl	r4		;convert to words
	mov	mptb(r4),r0	;get map address
	
;
; move to upper left corner of character
;
	add	#40,r2		;set column address
	movb	r2,colm		;put into command
	movb	r2,colm2	;and new line command
6$:	movb	#digtop,line	;set up top line address
	ttyout	#movit,#5	;send the command
;
; main character loop
;
	mov	#diglin,r3	;number of lines per character
4$:	mov	(r0),r4		;one row of bits
	com	(r0)+		;prepare for next pass
	mov	#bits,r5	;number of bits per line
	mov	#linbuf+1,r2	;address of output buffer
;
; line loop
;
3$:	rol	r4		;get the next bit
	bcc	1$		;clear => don't write
	movb	r1,(r2)+	;set => insert character
	br	2$		;exit
;
1$:	movb	#esc,(r2)+	;prepare to skip
	movb	#cursr,(r2)+	;skip one position
;
2$:	sob	r5,3$	
;
; line ready to send
;
	sub	#linbuf,r2	;get length of stuff to send
	ttyout	#linbuf,r2	;send one character line
;
; move to next line of character
;
	ttyout	#nxtlin,#nxtlen	;send command
;
	sob	r3,4$		;end of pass
;
	cmpb	r1,#40		;end of second pass?
	beq	5$		;yes, leave
;
; pass 2 replaces all other characters with blanks
;
	mov	#40,r1		;set up blank
	sub	#mapsiz,r0	;restore map pointer
	jmp	6$		;and do it again
;
5$:	leave
	rts	pc
	.page
	.sbttl	buffers, etc.
;
;erase screen by home, erase to end of screen
;
erase:	.byte	esc
	.ascii	/h/		;home
	.byte	esc
	.ascii	/j/		;erase
erasel=.-erase
;
; direct cursor addressing command buffer
;
movit:	.byte	esc
	.ascii	/y/
line:	.byte	40	;40 is top line
colm:	.byte	40	;40 is left column
;
; new line command string
;
nxtlin:	.byte	lf,esc
	.ascii	/y/
	.byte	100		;out of range =>no vert. motion
colm2:	.byte	0		;set up at run time
nxtlen=.-nxtlin
;
; instructions to draw a colon
;
colon:	.byte	esc
	.ascii	/y/
	.byte	digtop+6
	.byte	colcol
s101:	.ascii	/:::/
	.byte	lf,bs,bs,bs
s102:	.ascii	/:::/
	.byte	lf,bs,bs,bs
s103:	.ascii	/:::/
	.byte	lf,lf,lf,bs,bs,bs
s11:	.ascii	/:::/
	.byte	lf,bs,bs,bs
s12:	.ascii	/:::/
	.byte	lf,bs,bs,bs
s13:	.ascii	/:::/
colen=.-colon
;
; output line buffer
;
linbuf:	.byte	0	;null for good measure
	.blkb	bits*4	;could be as many as four bytes per bit
;
	.even
tbuf:	.blkw	8.
;
hr10:	.word	0
hr1:	.word	0
mn10:	.word	0
mn1:	.word	0
;
; tables
;
chtb:	.ascii	/0123456789/
mptb:	.word	map0,map1,map2,map3,map4,map5,map6,map7,map8,map9
;
	.page
	.sbttl	bit maps
	.nlist	bex
	.even
;
; character 0
;
map0:	.word	03760,17774,30006,60003,60003
	.word	60003,60003,60003,60003,60003
	.word	60003,60003,60003,60003,60003
	.word	60003,60003,30006,17774,03760
;
map1:	.word	00300,00700,01700,03700,00300
	.word	00300,00300,00300,00300,00300
	.word	00300,00300,00300,00300,00300
	.word	00300,00300,00300,07776,07776
;
map2:	.word	03760,17774,30006,60003,00003
	.word	00003,00003,00006,00014,00030
	.word	00060,00140,00300,00600,01400
	.word	03000,06000,14000,37777,77777
;
map3:	.word	03760,17774,30006,60003,00003
	.word	00003,00003,00003,00006,00014
	.word	00014,00006,00003,00003,00003
	.word	00003,60003,30006,17774,03760
;
map4:	.word	00030,00070,00170,00330,00630
	.word	01430,03030,06030,14030,30030
	.word	77777,77777,00030,00030,00030
	.word	00030,00030,00030,00030,00030
;
map5:	.word	77777,77777,60000,60000,60000
	.word	60000,60000,77000,37740,00770
	.word	00014,00006,00003,00003,00003
	.word	00003,60003,30006,17774,03760
map6:	.word	03760,17774,30006,60003,60000
	.word	60000,60000,60000,60000,63760
	.word	77774,70006,60003,60003,60003
	.word	60003,60003,30006,17774,03760
map7:	.word	77777,77777,00003,00006,00014
	.word	00030,00030,00060,00140,00140
	.word	00300,00600,01400,03000,06000
	.word	14000,30000,60000,60000,60000
map8:	.word	03760,17774,30006,60003,60003
	.word	60003,60003,60003,30006,17774
	.word	17774,30006,60003,60003,60003
	.word	60003,60003,30006,17774,03760
map9:	.word	03760,17774,30006,60003,60003
	.word	60003,60003,60003,30007,17777
	.word	03763,00003,00003,00003,00003
	.word	00003,60003,30006,17774,03760
;
mapsiz=map1-map0
	.end	start
