*************************************
* HC11_DRIFT
* Version 1.0
* Copyright Gert Gottschalk (drgert1@yahoo.com)
* Algorithm by Paul Mortfield (paul@BackyardAstronomer.com)
* You may copy this software for non commercial use, 
* as long as you mention the original developer's copyright
*************************************


* Instructions:
*   1  running Buffalo
*   2  "load t" (enter)
*   3  send the file
*	HyperTerminal (transfer, send text file, all files)
*   4  wait for completion of file send
*   5  "md 2000" (enter) will display the memory containing the program
*   6  "go 2000" (enter) to run the program

*************************************
* Major switches for assembly control
*************************************

DEBUG		EQU	0
ST4_90		EQU	0
GGMODE		EQU	0

*************************************
* Fatal Error Codes
*************************************

*	01	rd_stat checksum error (10x)
*	02	ST4 fails to respond to reset
*	03	wr_stat $06 response failure
*	04	rd_xref checksum error (10x)
*	05	rd_yref checksum error (10x)
*	06	wr_xref $06 response failure
*	07	wr_yref $06 response failure
*	10	rd_stat response timeout error
*	11	wr_stat response timeout error
*	12	rd_xref response timeout error
*	13	rd_yref response timeout error	
*	14	wr_xref response timeout error
*	15	wr_yref response timeout error	
			
************************************************************************
* REGISTER (define registers within the CPU)
************************************************************************

PORTA		EQU	$00		; PORT A
DDRA		EQU	$01		; PORT A DDR
PORTG		EQU	$02		; PORT G
DDRG		EQU	$03		; PORT G DDR
PORTB		EQU	$04		; PORT B
PORTCL		EQU	$05		; PROT C LATCHED DATA REG.
DDRC		EQU	$07		; DATA DIRECTION REGISTER C
PORTD		EQU	$08		; PORT D
DDRD		EQU	$09		; DATA DIRECTION REGISTER D
PORTE		EQU	$0A		; PORT E
CFORC		EQU	$0B		; TIMER COMPARE FORCE REG.
OC1M		EQU	$0C		; O/P COMPARE 1 MASK REG.
OC1D		EQU	$0D		; O/P COMPARE 1 DATA REG
TCNT		EQU	$0E		; TIMER COUNT H
TCNTL		EQU	$0F		;             L
TIC1		EQU	$10		; TIMER O/P COMPARE 1 H
TIC1L		EQU	$11		;                   1 L
TIC2		EQU	$12		;                   2 H
TIC2L		EQU	$13		;                   2 L
TIC3		EQU	$14		;                   3 H
TIC3L		EQU	$15		;                   3 L
TOC1		EQU	$16		; TIMER O/P COMPARE	1 H
TOC1L		EQU	$17		;			1 L
TOC2		EQU	$18		;			2 H
TOC2L		EQU	$19		;			2 L
TOC3		EQU	$1A		;			3 H
TOC3L		EQU	$1B		;			3 L
TOC4		EQU	$1C		;			4 H
TOC4L		EQU	$1D		;			4 L
TOC5		EQU	$1E		;			5 H
TOC5L		EQU	$1F		;			5 L
TCTL1		EQU	$20		; TIMER CONTROL REG 1
TCTL2		EQU	$21		; TIMER CONTROL REG 2
TMSK1		EQU	$22		; TIMER MASK 1
TFLG1		EQU	$23		; TIMER FLAG 1
TMSK2		EQU	$24		; TIMER MASK 2
TFLG2		EQU	$25		; TIMER FLAG 2
PACTL		EQU	$26		; PULSE ACCUMULATOR CONT. REG.
PACNT		EQU	$27		; PULSE ACCUMULATOR COUNT REG.
SPCR		EQU	$28		;
SPSR		EQU	$29		;
SPDR		EQU	$2A		;
BAUD		EQU	$2B		; SCI BAUD REG
SCCR1		EQU	$2C		; SCI CONTROL 1 REG
SCCR2		EQU	$2D		; SCI CONTROL 2 REG
SCSR		EQU	$2E		; SCI STATUS REG
SCDR		EQU	$2F		; SCI DATA REG
ADCTL		EQU	$30		;
ADR1		EQU	$31		;
ADR2		EQU	$32		;
ADR3		EQU	$33		;
ADR4		EQU	$34		;
BPROT		EQU	$35		;
OPTION		EQU	$39		; OPTION REG
COPRST		EQU	$3A		; COP RESET REG
PPROG		EQU	REGBS+$3B	; EEPROM PROG REG
HPRIO		EQU	$3C		; HPRIO REG
INIT		EQU	$3D		; INIT
CONFIG		EQU	$3F		; CONFIG REG
CSSTRH		EQU	$5C		; CS CYCLE STRETCH
CSCTL		EQU	$5D		; CS CONTROL
CSGADR		EQU	$5E		; GENERAL PURPOSE CS (RAM)
CSGSIZ		EQU	$5F		; GENERAL PURPOSE CS SIZE

************************************************************************
* Constants (define references that do not change)
************************************************************************
RAM_SIO	EQU	$00C5		; Buffalo sio IRQ jmp address
RAM_RTI	EQU	$00EC		; Buffalo timer IRQ jmp address
REGBS	EQU	$1000		; start of CPU register block
LED	EQU	%10000000	; led output bit mask
DATA	EQU	%00000001	; LED port data mask
CLK	EQU	%00000010	; LED port clk mask
LOAD	EQU	%00000100	; LED port load mask
DRFDG0	EQU	$01
DRFDG1	EQU	$02
DRFDG2	EQU	$03
DRFRMP	EQU	$04
ANGDG0	EQU	$05	
ANGDG1	EQU	$06
ANGDG2	EQU	$07
ANGRMP	EQU	$08

ALLKEY	EQU	%00111100	; Mask for keys
ANGKEY	EQU	%00001100
ANGPL	EQU	%00001000
ANGMI	EQU	%00000100
DRFKEY	EQU	%00110000
DRFPL	EQU	%00100000
DRFMI	EQU	%00010000
ENTKEY	EQU	%00001000

XCSTHI	equ	$0000
XCSTMD	equ	$0296		; 180*3600*60*0.01375*255/PI
XCSTLO	equ	$1FBE		;	= 43392959 = $0000 0296 1FBE

YCSTHI	equ	$0000
YCSTMD	equ	$0302		; 180*3600*60*0.01600*255/PI
YCSTLO	equ	$78B9		;	= 50493625 = $0000 0302 78B9

ST4ST	equ	$002f
ST4XRF	equ	$7E7C
ST4YRF	equ	$7E7D

ST4XMAX	equ	192
ST4YMAX	equ	165

	ORG	$0800		; variable area
pdmir	rmb	1		; mirror of portd keys
pamir	rmb	1		; mirror of porta keys
angl	rmb	2		; angle
angmod	rmb	1		; angle mod 90
quadr	rmb	1		; quadrant
drift	rmb	2		; dirft
flen	rmb	2		; focal length
xrmplod	rmb	2		; led ramp counter load value x
xrmpcnt	rmb	2		; led ramp counter x
xrmpld	rmb	1		; led for x ramp
yrmplod	rmb	2		; led ramp counter load value y
yrmpcnt	rmb	2		; led ramp coutner y
yrmpld	rmb	1		; led for y ramp
rgled	rmb	1		; mirror red/green LED
entflg	rmb	1		; enter key pressed
cor_mod	rmb	1		; correction active mode flag
timout	rmb	1		; time out counter
sec_cnt	rmb	1		; seconds counter for timer irq 1/122
sec_flg	rmb	1		; 1 second toggle flag (chg each 1/2 sec)
lst_sec	rmb	1		; previous value of 1 sec flag
key_cnt	rmb	1		; 1/5 sec counter for key query
angdsp0	rmb	1		; mirror angle digit 0
angdsp1	rmb	1		; mirror angle digit 1
angdsp2	rmb	1		; mirror angle digit 2
drfdsp0	rmb	1		; mirror drift digit 0
drfdsp1	rmb	1		; mirror drift digit 1
drfdsp2	rmb	1		; mirror dirft digit 2
tmp	rmb	2		; temp storage
sendbuf	rmb	16		; send buffer for irq serial io
sendrd	rmb	2		; send buffer write ptr
sendwr	rmb	2		; send buffer read ptr
recvbuf	rmb	16		; receive buffer for irq serial io
recvrd	rmb	2		; receive buffer write ptr
recvwr	rmb	2		; receive buffer read ptr
scsr_mr	rmb	1		; SIO status reg mirror
rtiv_mr	rmb	2		; orig rti vector
siov_mr	rmb	2		; orig sio vector
st4refx	rmb	1		; reference x-coord from ST4
st4refy	rmb	1		; reference y-coord from ST4
st4buf	rmb	8		; receive buffer from st4
errcnt	rmb	1		; error counter for ST4 communication
errcnt1	rmb	1		; 2nd levl errcount
countx	rmb	2		; 1sec down x-counter for next ST4 ref x-coord modify
county	rmb	2		; 1sec down y-counter for next ST4 ref y-coord modify
cntxld	rmb	2		; 1sec down x-counter load value
cntyld	rmb	2		; 1sec down y-counter load value
xvalid	rmb	1		; flag if x corrections are enabled
yvalid	rmb	1		; flag if y corrections are enabled

*******************************************
*************     Stuff for multiply divide
*******************************************

CNTR     RMB 1  ; Counter for mul/div
DIVPTR   RMB 2  ; Ptr to MS byte of divisor
DIVCNT   RMB 1  ; Number of bytes in the divisor
DVDCNT   RMB 1  ; Number of bytes in the dividend
QPTR     RMB 2  ; Ptr to current byte of quotient
QCNT     RMB 1  ; Number of bytes remaining to be found in quotient
TRIALQ   RMB 1  ; Current quotient trial value

	        ; Temp storage for multiply
A24      RMB 3  ; Argument for multiple precision mul
B24      RMB 3  ; Argument for multiple precision mul
A48      RMB 6  ; Product from multiple precision mul

	        ; Temp storage for  divide
D24      RMB 3  ; Divisor
Q24      RMB 3  ; Quotient - Must immediately precede dividend
D48      RMB 6  ; Dividend

	        ; Temp storage for  divide
TEMP     RMB 2  ; Work space for divide

************************************************************************
************************************************************************
************; P R O G R A M   S T A R T S   H E R E ********************
************************************************************************
************************************************************************
$IF DEBUG = 0
	ORG	$C000		; location in FLASH RAM
$ELSE
	ORG	$2000
$ENDIF

*************

start	sei			; disable irq to set real time irq routine
$IF DEBUG = 0
	lds	#$07FF
$ENDIF
	ldx	#REGBS		; register base address
	ldaa	DDRA,x
	anda	#%11110111	; make 'ent' key -> input
	ora	#%10000111	; make LED interface -> output
	staa	DDRA,x
	ldaa	DDRD,x
	anda	#%11000011	; make pd2-pd5 'keys' -> input
	staa	DDRD,x
	ldaa	#%00000001
	staa	PACTL,X
	bset	TMSK2,X,%01000000	; allow real time irq to cause int
	ldaa	#%00110000		; first prescaler/13 sec ps/1 => 9600bd@8MHz 
	staa	BAUD,x
	
$IF DEBUG = 1
	ldd	RAM_RTI		; in Debug mode use buffalo jump vectors
	std	rtiv_mr
	ldd	#isr_RTI
	std	RAM_RTI		; replace with ROM irq later
	
	ldd	RAM_SIO
	std	siov_mr
	ldd	#isr_SCI
	std	RAM_SIO		; replace with ROM irq later
	ldaa	#%00000000
$ELSE
	ldaa	#%00010000		; bit8+7 are recv bit8 and send bit8
$ENDIF
	staa	SCCR1,x
	ldaa	#%00101100		; enable transmitter and receiver of SCI
	staa 	SCCR2,x 

	ldd	#sendbuf	;  init sio queues prior to first possible irq
	std	sendrd
	std	sendwr
	ldd	#recvbuf
	std	recvrd
	std	recvwr
	
$IF GGMODE = 1
	ldd	#180		; maps to 1800mm Focal Length in GGs setup
	std	drift
$ENDIF
	
	ldd	#0
	std	angl
	
$IF GGMODE = 0
	std	drift
$ENDIF
	
	std	xrmplod
	std	xrmpcnt
	std	yrmplod
	std	yrmpcnt
	staa	entflg
	staa	xrmpld
	staa	yrmpld
	staa	rgled
	staa	cor_mod
	staa	timout
	staa	sec_cnt
	staa	sec_flg
	staa	lst_sec
	staa	key_cnt
	staa	xvalid
	staa	yvalid
$IF DEBUG = 0
	staa	st4refx
	staa	st4refy
$ELSE
	ldaa	#80
	staa	st4refx
	ldaa	#70
	staa	st4refy
$ENDIF

	ldx	#REGBS		; Eat up any trash in serial input data reg
start10	ldaa	SCSR,x
	anda	#%00100000
	beq	start20
	ldaa	SCDR,x		; count shows -> one read is enough to clr bit
	bra	start10

start20	cli

	jsr	ang2rmp
	jsr	drf2rmp
	jsr	ang2dsp
	jsr	dft2dsp
	jsr	dispang
	jsr	dispdrf
	jsr	initled		; show 'FL ' on left display
	jsr	ldgren

$IF DEBUG = 1
	ldaa	#'I'
	jsr	sendv24
	jsr	crlf
	
$ELSE
start21	jsr	rd_stat		; retrieve status
	ora	#$20		; set bit 5 -> call for interrupt ST4
	jsr	wr_stat

	ldaa	#10
	staa	errcnt1		; initialize error counter
start22	jsr	rd_stat
	anda	#$20		; wait for status to clear
	beq	start23		; done
	dec	errcnt1
	bne	start22
	ldd	#02		; if 10 errors encountered -> goto fatal halt
	jmp	fatal
$ENDIF

$IF DEBUG = 1
	jsr	ldorng
	ldaa	#$ff
	staa	timout
startxx	tst	timout
	bne	startxx
$ENDIF
	
start23	ldaa	#$09		; hi	decode mode
	ldab	#%00000111	; lo	left BIN right BCD
	jsr	disp
	ldaa	#ANGDG2	
	ldab	#%01000111	; 'F'
	jsr	disp
	ldaa	#ANGDG1
	ldab	#%00001110	; 'L'
	jsr	disp
	ldaa	#ANGDG0
	ldab	#%00000000	; ' '
	jsr	disp
	jsr	ldred

start30	jsr	dft2dsp		; wait for enter focal length
	jsr	dispfl
	jsr	ang2rmp
	jsr	drf2rmp
	tst	entflg
	beq	start30

	ldd	drift
	std	flen		; store focal length
	ldd	#0
	std	drift
	jsr	initled		; overwrite 'FL' back to numeric

start40	tst	entflg
	bne	start40

$IF DEBUG = 1
	ldd	flen		; print focal length for debug
	jsr	out_dec
	jsr	crlf
$ENDIF
	
main	tst	cor_mod		; 0= pre correction. 1= correction mode
	bne	main_a0
	jmp	main00		;  skip if not yet in correction mode
	
main_a0	jsr	ldgren		; in corr mode led = green
	tst	sec_flg		; count down x y correction 1sec timers
	bne	main_a2		; go there if sec flag == 1
	jmp	main00a		; nothing to do
	
main_a2	tst	lst_sec		; if secflg == 1 and lastsec == 0 -> we just have pos edge
	beq	main_a4		; we have found the edge -> go there
	jmp	main00a		; otherwise goto end of main loop
	
main_a4	inc	lst_sec		; we just have a positive edge on secflag -> do the stuff
	
$IF DEBUG = 1
	ldd	countx
	jsr	out_dec
	ldaa	#' '
	jsr	sendv24
	ldd	county
	jsr	out_dec
	jsr	crlf
$ENDIF

	tst	xvalid		; test if we have excluded X
	beq	main0b		; don't consider x

	ldx	xrmpcnt		; dec ramp x counter
	dex
	stx	xrmpcnt
	bne	main_a6		; if not zero -> no ramp step needed
	
	ldx	xrmplod		; reset ramp x counter
	stx	xrmpcnt
	dec	xrmpld		; dec x led ramp value
		
main_a6	ldx	countx
	dex
	stx	countx
	bne	main0b		; countx > 0
	
	ldx	cntxld		; reset x-counter + apply x correction
	stx	countx
	ldx	xrmplod
	stx	xrmpcnt
	ldaa	#5
	staa	xrmpld
	jsr	ang2rmp

$IF DEBUG =  1
	ldaa	#'X'
	jsr	sendv24
	jsr	crlf
$ENDIF

	ldaa	quadr

$IF ST4_90 = 0 
	;; This table for straight through guide scope
	beq	main0c0		; quadr=0 -> increment xref
	cmpa	#1
	beq	main0d0		; quadr=1 -> decrement xref
	cmpa	#2
	beq	main0d0		; quadr=2 -> decrement xref
	cmpa	#3
	beq	main0c0		; quadr=3 -> increment xref
	bra	main0b
$ELSE
	;; This table for guide scope with 90deg prism
	beq	main0d0		; quadr=0 -> decrement xref
	cmpa	#1
	beq	main0c0		; quadr=1 -> increment xref
	cmpa	#2
	beq	main0c0		; quadr=2 -> increment xref
	cmpa	#3
	beq	main0d0		; quadr=3 -> decrement xref
	bra	main0b	
$ENDIF
		
main0c0	ldaa	st4refx		; get xref
	cmpa	#ST4XMAX
	beq	main0b		; see if we would go beyond max x -> yes, do nothing
	inca			; increment xref
	bra	main0d2

main0d0	ldaa	st4refx		; get xref
	beq	main0b		; see if we would go below 0 -> yes, do nothing
	deca			; decrement xref
main0d2	staa	st4refx
main0d3	jsr	wr_xref		; write to ST4
	jsr	rd_xref
	cmpa	st4refx
	beq	main0b
	ldaa	st4refx
	bra	main0d3
	
main0b	tst	yvalid
	beq	main0d		; don't consider y

	ldx	yrmpcnt		; dec ramp x counter
	dex
	stx	yrmpcnt
	bne	main0bx		; if not zero -> no ramp step needed
	
	ldx	yrmplod		; reset ramp x counter
	stx	yrmpcnt
	dec	yrmpld		; dec x led ramp value
	
main0bx	ldx	county
	dex
	stx	county
	bne	main0d		; county > 0 -> nothing to do
	
	ldx	cntyld		; reset y-counter + apply y correction
	stx	county
	ldx	yrmplod
	stx	yrmpcnt
	ldaa	#5
	staa	yrmpld
	jsr	drf2rmp

$IF DEBUG = 1
	ldaa	#'Y'
	jsr	sendv24
	jsr	crlf
$ENDIF
	
	ldaa	quadr
	beq	main0f0		; quadr=0 -> increment yref
	cmpa	#1
	beq	main0f0		; quadr=1 -> increment yref
	cmpa	#2
	beq	main0g0		; quadr=2 -> decrement yref
	cmpa	#3
	beq	main0g0		; quadr=3 -> decrement yref
	bra	main0d		; illegal quadrant value. should be 0...3

main0f0	ldaa	st4refy		; get yref
	cmpa	#ST4YMAX
	beq	main0d		; see if we would go beyond max y -> yes, do nothing
	inca			; increment yref
	bra	main0g2

main0g0	ldaa	st4refy		; get xref
	beq	main0d		; see if we would go below 0 -> yes, do nothing
	deca			; decrement yref
main0g2	staa	st4refy
main0g3	jsr	wr_yref		; write to ST4
	jsr	rd_yref
	cmpa	st4refy
	beq	main0d
	ldaa	st4refy
	bra	main0g3
	
main0d	bra	main01
	
main00	jsr	ldorng
main00a	tst	sec_flg		; see if sec flag still ==1
	bne	main01		; wait as long as secflag ==1
	clr	lst_sec		; reset lastflag so that we can find next edge
main01	jsr	ang2dsp		; do all the display stuff
	jsr	dft2dsp
	jsr	dispang
	jsr	dispdrf
	jsr	ang2rmp
	jsr	drf2rmp

	
main08	tst	entflg		; see if we have enter key pressed
	bne	main08a		; if enter key pressed 
				; -> have to do the x y calc and reset counters
main081	jmp	main		; if no enter key go back to main loop start

main08a	ldx	drift
	beq	main081		; No drift => dont enter corrections mode + go to main
	ldaa	#1
	staa	cor_mod

	jsr	rd_xref		; retrieve current ref position on ST4
	staa	st4refx
	jsr	rd_yref
	staa	st4refy
				; calc x y down counter values 

	ldd	angl		; get angle to calc modulus 90deg and quadrant
	ldx	#0		; x will become quadrant
main09	cmpd	#89		; see if we can subtract 90deg (once again)
	ble	main10		; no. =>  0<=D<=90
	subd	#90		; yes. subtract
	inx			; increment quadrant counter
	bra	main09		; loop around

main10	stab	angmod
	xgdx
	stab	quadr


xcalc	ldd	angl
	cmpd	#90		; if angle = 90 or 270 -> disable x-calc + x-corr
	beq	xcalc10
	cmpd	#270
	beq	xcalc10
	
	ldaa	#1
	staa	xvalid
	bra	xcalc20
xcalc10	clr	xvalid		;  disable x-calc + x-corr
	clr	xrmpld
	jsr	ang2rmp
	bra	ycalc		;  jmp to y-calc. no x-calc required.
	
xcalc20	ldd	flen		; do x calculation
	std	A24+1
	clr	A24		; A24= Flen / 10
	ldd	drift
	std	B24+1		; B24= Drift * 10
	clr	B24
	jsr	mul24		; A48= Flen * Drift 

	ldd	A48+3
	std	D24
	ldaa	A48+5
	staa	D24+2		; D24= A48= Flen * Drift

	ldd	#XCSTHI
	std	D48
	ldd	#XCSTMD
	std	D48+2
	ldd	#XCSTLO
	std	D48+4		; D48= X_CONST

	jsr	DIV24		; Q24= X_CONST / ( Flen * Drift )
	ldaa	angmod
	jsr	cos_x
	staa	D24+2
	clr	D24+1
	clr	D24		; D24= cos(angle) * 255

	clr	D48
	clr	D48+1
	clr	D48+2
	ldd	Q24
	std	D48+3
	ldaa	Q24+2
	staa	D48+5		; D48= X_CONST / ( Flen * Drift )

	jsr	div24		; Q24= X_CONST / ( Flen * Drift * cos(angle) )

	ldd	Q24+1
	std	cntxld
	std	countx		; x counter value done
	ldx	#05
	idiv
	stx	xrmplod
	stx	xrmpcnt
	ldaa	#5
	staa	xrmpld

ycalc	ldd	angl
	beq	ycalc10		; if angle=0 or 180 disable y-calc + y-corr
	cmpd	#180
	beq	ycalc10
	ldaa	#1
	staa	yvalid
	bra	ycalc20
ycalc10	clr	yvalid
	clr	yrmpld
	jsr	drf2rmp
	bra	main25		;  skip y-calc
	
ycalc20	ldd	flen		; do y calculation
	std	A24+1
	clr	A24		; A24= Flen / 10
	ldd	drift
	std	B24+1		; B24= Drift * 10
	clr	B24
	jsr	mul24		; A48= Flen * Drift 

	ldd	A48+3
	std	D24
	ldaa	A48+5
	staa	D24+2		; D24= A48= Flen * Drift

	ldd	#YCSTHI
	std	D48
	ldd	#YCSTMD
	std	D48+2
	ldd	#YCSTLO
	std	D48+4		; D48= X_CONST

	jsr	DIV24		; Q24= X_CONST / ( Flen * Drift )
	ldaa	angmod
	jsr	sin_x
	staa	D24+2
	clr	D24+1
	clr	D24		; D24= sin(angle) * 255

	clr	D48
	clr	D48+1
	clr	D48+2
	ldd	Q24
	std	D48+3
	ldaa	Q24+2
	staa	D48+5		; D48= X_CONST / ( Flen * Drift )

	jsr	div24		; Q24= X_CONST / ( Flen * Drift * sin(angle) )

	ldd	Q24+1
	std	cntyld
	std	county
	ldx	#05
	idiv
	stx	yrmplod
	stx	yrmpcnt
	ldaa	#5
	staa	yrmpld

main25:
$IF DEBUG = 1
	ldd	angl
	jsr	out_dec
	ldaa	#' '
	jsr	sendv24
	ldd	drift
	jsr	out_dec
	ldaa	#' '
	jsr	sendv24
	ldab	angmod
	clra
	jsr	out_dec
	ldaa	#' '
	jsr	sendv24
	ldaa	quadr
	adda	#'0'
	jsr	sendv24
	ldaa	#' '
	jsr	sendv24
	ldd	cntxld
	jsr	out_dec
	ldaa	#' '
	jsr	sendv24
	ldd	cntyld
	jsr	out_dec
	jsr	crlf
$ENDIF	
main26	tst	entflg
	bne	main26
	jmp	main


initled	ldaa	#$0f		; hi	test register
	ldab	#%00000000	; lo	0 = normal ops
	jsr	disp

	ldaa	#$0c		; hi	shut down reg
	ldab	#%00000001	; lo	1 = normal ops
	jsr	disp
	
	ldaa	#$0b		; hi	scan limit reg
	ldab	#%00000111	; lo	%0111 display all digits
	jsr	disp
	
	ldaa	#$0a		; hi	intensity reg
	ldab	#%00001000	; lo	1/2 intensity
	jsr	disp
	
	ldaa	#$09		; hi	decode mode
	ldab	#%01110111	; lo	left BCD right BCD
	jsr	disp
	rts

	
ang2rmp	ldab	xrmpld
	clra
	addd	#ledtab
	xgdx
	ldab	0,x
	ldaa	#ANGRMP
	jsr	disp
	rts

drf2rmp	ldab	yrmpld
	clra
	addd	#ledtab
	xgdx
	ldab	0,x
	orab	rgled
	ldaa	#DRFRMP
	jsr	disp
	rts

dgreen	ldaa	rgled
	anda	#%11111100
	ora	#%00000001
	bra	dled
dred	ldaa	rgled
	anda	#%11111100
	ora	#%00000010
	bra	dled
dorng	ldaa	rgled
	anda	#%11111100
	ora	#%00000011
	bra	dled
dblak	ldaa	rgled
	anda	#%11111100
	bra	dled

dled	staa	rgled
	rts

ldgren	bsr	dgreen
	bsr	drf2rmp
	rts

ldred	bsr	dred
	bsr	drf2rmp
	rts
	
ldorng	bsr	dorng
	bsr	drf2rmp
	rts
	
ldblak	bsr	dblak
	bsr	drf2rmp
	rts
	
ang2dsp	ldd	angl
	ldx	#10
	idiv
	stab	angdsp0
	xgdx
	ldx	#10
	idiv
	stab	angdsp1
	xgdx
	stab	angdsp2
	rts

dft2dsp	ldd	drift
	ldx	#10
	idiv
	stab	drfdsp0
	xgdx
	ldx	#10
	idiv
	stab	drfdsp1
	xgdx
	stab	drfdsp2
	rts
			
dispang	ldaa	#ANGDG0
	ldab	angdsp0
	jsr	disp
	ldaa	#ANGDG1
	ldab	angdsp1
	jsr	disp
	ldaa	#ANGDG2
	ldab	angdsp2
	jsr	disp
	rts
		
dispdrf	ldaa	#DRFDG0
	ldab	drfdsp0
	jsr	disp
	ldaa	#DRFDG1
	ldab	drfdsp1
	orb	#%10000000
	jsr	disp
	ldaa	#DRFDG2
	ldab	drfdsp2
	jsr	disp
	rts

dispfl	ldaa	#DRFDG0
	ldab	drfdsp0
	jsr	disp
	ldaa	#DRFDG1
	ldab	drfdsp1
	jsr	disp
	ldaa	#DRFDG2
	ldab	drfdsp2
	jsr	disp
	rts

dispdec	clra			; accu b into angle disp as dec
	ldx	#10
	idiv
	pshb
	xgdx
	ldx	#10
	idiv
	pshb
	xgdx
	ldaa	#ANGDG2
	jsr	disp
	pulb
	ldaa	#ANGDG1
	jsr	disp
	pulb
	ldaa	#ANGDG0
	jsr	disp
	rts
	
	
disp	psha
	pshb
	pshx
	pshy
	ldx	#REGBS
	bclr	PORTA,x,CLK
	bclr	PORTA,x,LOAD
	bclr	PORTA,x,DATA
	ldy	#16
disp05	lsld
	bcc	disp10
	bset	PORTA,x,DATA
	bra	disp15
disp10	bclr	PORTA,x,DATA
disp15	bset	PORTA,x,CLK
	bclr	PORTA,x,CLK
	dey
	bne	disp05
	bset	PORTA,x,LOAD
	puly
	pulx
	pulb
	pula
	rts

fatal	std	angl
	ldd	#00
	std	drift
	jsr	ang2dsp
	jsr	dft2dsp
	jsr	dispang
	jsr	dispdrf
	jsr	ldred
fatal1	bra	fatal1

$IF DEBUG = 1
rd_stat	ldaa	#00
	rts

wr_stat rts

rd_xref	ldaa	st4refx
	rts

rd_yref	ldaa	st4refy
	rts

wr_xref	psha
	ldaa	#'X'
	jsr	sendv24
	pula
	tab
	clra
	jsr	out_dec
	jsr	crlf
	rts
	
wr_yref	psha
	ldaa	#'Y'
	jsr	sendv24
	pula
	tab
	clra
	jsr	out_dec
	jsr	crlf
	rts

		
$ELSE	
rd_stat ldaa	#10
	staa	errcnt		; init error counter
rd_st02	ldaa	#$02		; read RAM cmd. and reetry point for error recovery
	jsr	sendv24
	ldaa	#$01		; number of bytes
	jsr	sendv24
	ldaa	#$01		; 0=ext, 1=int ram
	jsr	sendv24
	ldaa	#[ST4ST		; LSB of Status address
	jsr	sendv24
	ldaa	#]ST4ST		; MSB of status address
	jsr	sendv24
	ldaa	#$33		; checksum=$02+$01+$01+$2f+$00
	jsr	sendv24

	
	;; response :	 02 01 ST CS


	ldx	#st4buf		; pointer to read buffer
rd_st05	ldaa	#$ff		; init value for timeout
	staa	timout
	ldy	recvrd
rd_st10	cpy	recvwr		; check if we have received something
	bne	rd_st15		; we have received something
	tst	timout		; wait a while to receive data
	bne	rd_st10		; lop around to try wait more
	dec	errcnt		; time out! count down error
	bne	rd_st02		; loop back to send command
	ldd	#10		; had 10 failures -> fatal error
	jmp	fatal		; go fatal
	
rd_st15	ldaa	0,y
	staa	0,x		; copy v24 receive data to st4 receive buffer
	inx
	cpy	#recvbuf+15
	bne	rd_st20
	ldy	#recvbuf-1
rd_st20	iny
	sty	recvrd
	cpx	#st4buf+4
	bne	rd_st05		; go back for next char. incl re-init of timeout

	ldaa	st4buf		; all received. now check
	cmpa	#$02		; $02
	bne	rd_st95
	ldaa	st4buf+1
	cmpa	#$01		; $01
	bne	rd_st95

	clra
	ldx	#st4buf
rd_st30	adda	0,x		; add up checksum
	inx
	cpx	#st4buf+3
	bne	rd_st30
	cmpa	0,x		; compare with received checksum value
	bne	rd_st95		; goto error handler if wrong checksum
	ldaa	st4buf+2	; retrieve status byte and return it
	rts

rd_st95	dec	errcnt		; count down for error
	beq	rd_st97
	jmp	rd_stat		; if received data are bad goto re issue command

rd_st97	ldd	#01		; if 10 errors encountered -> goto fatal halt
	jmp	fatal

wr_stat	staa	tmp
	ldaa	#10
	staa	errcnt
wr_st02	ldaa	#$01		; write RAM cmd
	jsr	sendv24
	ldaa	#$04		; number of bytes
	jsr	sendv24
	ldaa	#$01		; 0=ext, 1=int ram
	jsr	sendv24
	ldaa	#[ST4ST		; LSB of Status address
	jsr	sendv24
	ldaa	#]ST4ST		; MSB of status address
	jsr	sendv24
	ldaa	tmp		; status byte
	jsr	sendv24
	ldaa	tmp
	adda	#$35		;checksum $35=$01+$04+$01+$2f+$00
	jsr	sendv24

	;; response :	 06

wr_st05	ldy	recvrd
	ldaa	#$ff
	staa	timout
wr_st10	cpy	recvwr
	bne	wr_st15		; wait till we have received something
	tst	timout
	bne	wr_st10
	dec	errcnt
	bne	wr_st02
	ldd	#11
	jmp	fatal
	
wr_st15	ldaa	0,y
	cpy	#recvbuf+15
	bne	wr_st20
	ldy	#recvbuf-1
wr_st20	iny
	sty	recvrd
	cmpa	#$06
	beq	wr_st25
	dec	errcnt
	bne	wr_st02
	ldd	#$03
	jmp	fatal
wr_st25	rts

	;; x ref addr $7e7c

rd_xref	ldaa	#10
	staa	errcnt
rd_xr02	ldaa	#$02		; read RAM cmd
	jsr	sendv24
	ldaa	#$01		; number of bytes
	jsr	sendv24
	ldaa	#$00		; 0=ext, 1=int ram
	jsr	sendv24
	ldaa	#[ST4XRF	; LSB of x ref coordinate address
	jsr	sendv24
	ldaa	#]ST4XRF	; MSB of x ref coordinate address
	jsr	sendv24
	ldaa	#$FD		; checksum $FD=$02+$01+$00+$7c+$7e
	jsr	sendv24

	;; response $02 $01 xref CS
	
	ldx	#st4buf
rd_xr05	ldaa	#$ff
	staa	timout
	ldy	recvrd
rd_xr10	cpy	recvwr
	bne	rd_xr15		; wait till we have received something
	tst	timout
	bne	rd_xr10
	dec	errcnt
	bne	rd_xr02
	ldd	#12
	jmp	fatal
	
rd_xr15	ldaa	0,y
	staa	0,x		; copy v24 receive data to st4 receive buffer
	inx
	cpy	#recvbuf+15
	bne	rd_xr20
	ldy	#recvbuf-1
rd_xr20	iny
	sty	recvrd
	cpx	#st4buf+4
	bne	rd_xr05

	ldaa	st4buf		; all received. now check
	cmpa	#$02		; $02
	bne	rd_xr95
	ldaa	st4buf+1
	cmpa	#$01		; $01
	bne	rd_xr95

	clra
	ldx	#st4buf
rd_xr30	adda	0,x		; add up checksum
	inx
	cpx	#st4buf+3
	bne	rd_xr30
	cmpa	0,x		; compare with received checksum value
	bne	rd_xr95		; goto error handler if wrong checksum
	ldaa	st4buf+2	; retrieve x ref byte and return it
	rts

rd_xr95	dec	errcnt		; count down for error
	beq	rd_xr97
	jmp	rd_xref

rd_xr97	ldd	#04		; if 10 errors encountered -> goto fatal halt
	jmp	fatal
	
	;; y ref addr $7e7d

rd_yref	ldaa	#10
	staa	errcnt
rd_yr02	ldaa	#$02		; read RAM cmd
	jsr	sendv24
	ldaa	#$01		; number of bytes
	jsr	sendv24
	ldaa	#$00		; 0=ext, 1=int ram
	jsr	sendv24
	ldaa	#[ST4YRF	; LSB of y ref coordinate address
	jsr	sendv24
	ldaa	#]ST4YRF	; MSB of y ref coordinate address
	jsr	sendv24
	ldaa	#$FE		; checksum $FE=$02+$01+$00+$7d+$7e
	jsr	sendv24

	;; response $02 $01 yref CS
	
	ldx	#st4buf
rd_yr05	ldaa	#$ff
	staa	timout
	ldy	recvrd
rd_yr10	cpy	recvwr
	bne	rd_yr15		; wait till we have received something
	tst	timout
	bne	rd_yr10
	dec	errcnt
	bne	rd_yr02
	ldd	#13
	jmp	fatal
	
rd_yr15	ldaa	0,y
	staa	0,x		; copy v24 receive data to st4 receive buffer
	inx
	cpy	#recvbuf+15
	bne	rd_yr20
	ldy	#recvbuf-1
rd_yr20	iny
	sty	recvrd
	cpx	#st4buf+4
	bne	rd_yr05

	ldaa	st4buf		; all received. now check
	cmpa	#$02		; $02
	bne	rd_yr95
	ldaa	st4buf+1
	cmpa	#$01		; $01
	bne	rd_yr95

	clra
	ldx	#st4buf
rd_yr30	adda	0,x		; add up checksum
	inx
	cpx	#st4buf+3
	bne	rd_yr30
	cmpa	0,x		; compare with received checksum value
	bne	rd_yr95		; goto error handler if wrong checksum
	ldaa	st4buf+2	; retrieve x ref byte and return it
	rts

rd_yr95	dec	errcnt		; count down for error
	beq	rd_yr97
	jmp	rd_yr02

rd_yr97	ldd	#05		; if 10 errors encountered -> goto fatal halt
	jmp	fatal

 
wr_xref	staa	tmp
	ldaa	#10
	staa	errcnt
wr_xr02	ldaa	#$01		; write RAM cmd
	jsr	sendv24
	ldaa	#$04		; number of bytes
	jsr	sendv24
	ldaa	#$00		; 0=ext, 1=int ram
	jsr	sendv24
	ldaa	#[ST4XRF	; LSB of x ref address $7e7c
	jsr	sendv24
	ldaa	#]ST4XRF	; MSB of x ref address
	jsr	sendv24
	ldaa	tmp		; x ref byte
	jsr	sendv24
	ldaa	tmp
	adda	#$ff		;checksum $ff=$01+$04+$00+$7c+$7e
	jsr	sendv24

	;; response :	 06

wr_xr05	ldy	recvrd
	ldaa	#$ff
	staa	timout
wr_xr10	cpy	recvwr
	bne	wr_xr15		; wait till we have received something
	tst	timout
	bne	wr_xr10
	dec	errcnt
	bne	wr_xr02
	ldd	#14
	jmp	fatal
	
wr_xr15	ldaa	0,y
	cpy	#recvbuf+15
	bne	wr_xr20
	ldy	#recvbuf-1
wr_xr20	iny
	sty	recvrd
	cmpa	#$06
	beq	wr_xr25
	dec	errcnt
	bne	wr_xr02
	ldd	#$06
	jmp	fatal
wr_xr25	rts

wr_yref	staa	tmp
	ldaa	#10
	staa	errcnt
wr_yr02	ldaa	#$01		; write RAM cmd
	jsr	sendv24
	ldaa	#$04		; number of bytes
	jsr	sendv24
	ldaa	#$00		; 0=ext, 1=int ram
	jsr	sendv24
	ldaa	#[ST4YRF	; LSB of y ref address $7e7d
	jsr	sendv24
	ldaa	#]ST4YRF	; MSB of y ref address
	jsr	sendv24
	ldaa	tmp		; x ref byte
	jsr	sendv24
	ldaa	tmp
	adda	#$00		;checksum $00=$01+$04+$00+$7d+$7e
	jsr	sendv24

	;; response :	 06

wr_yr05	ldy	recvrd
	ldaa	#$ff
	staa	timout
wr_yr10	cpy	recvwr
	bne	wr_yr15		; wait till we have received something
	tst	timout
	bne	wr_yr10
	dec	errcnt
	bne	wr_yr02
	ldd	#15
	jmp	fatal

wr_yr15	ldaa	0,y
	cpy	#recvbuf+15
	bne	wr_yr20
	ldy	#recvbuf-1
wr_yr20	iny
	sty	recvrd
	cmpa	#$06
	beq	wr_yr25
	dec	errcnt
	bne	wr_yr02
	ldd	#$07
	jmp	fatal
wr_yr25	rts
$ENDIF
	
out_dec	ldy	#5
out_d10	ldx	#10
	idiv
	pshb
	xgdx
	dey
	bne	out_d10

	ldy	#5
out_d20	pula
	adda	#'0'
	bsr	sendv24
	dey
	bne	out_d20
	rts
		
outbyte	psha			* output accu a 1 byte as 2 hex digits
	anda	#$F0
	lsra
	lsra
	lsra
	lsra
	jsr	outbyt1
	pula
	anda	#$0F
	
outbyt1	adda	#'0'		* output 4 bits as 1 hex digit
	cmpa	#'9'
	ble	sendv24
	adda	#7

sendv24 pshy
	ldy	sendwr
	staa	0,y
	cpy	#sendbuf+15
	bne	sendv50
	ldy	#sendbuf-1
sendv50	iny
sendv60	cpy	sendrd
	beq	sendv60
	sty	sendwr
	puly
	rts  

crlf	psha
	ldaa	#13
	bsr	sendv24
	ldaa	#10
	bsr	sendv24
	pula
	rts

*   Calculate the 48 bit unsigned product of two 24 bit unsigned numbers.
*   Place the multiplicand in A24, the multiplier in B24, then JSR MUL24.
*   Result is returned in A48.  Put smaller value in B24 when given a 
*   choice.
*             Note: A48 must immediately follow B24 in memory !!!!
*   B24 may overlap A48 to save space if desired - some changes req'd.
*   The approach used is similar to multiplication with pencil and paper,
*   where bytes are used as if they were digits. It may be extended to
*   any reasonable number of bytes quite easily.

	
MUL24:   PSHB           ; Preserve regs
         PSHA
         PSHX
         LDX    #B24    ; Address of args
         CLR    3,X     ; Clear A48
         CLR    4,X
         CLR    5,X
         CLR    6,X
         CLR    7,X
         CLR    8,X
         LDAA   #3      ; # bytes in multiplier
         STAA   CNTR

MULOOP:  LDAA   2,X
         BEQ    MULUP2  ; Skip if 0 multiplier
         LDAB   A24+2   ; Least signifigant byte of multiplicand
         MUL
         ADDD   7,X
         STD    7,X
         BCC    MUL1
         INC    6,X     ; Propagate the carry
         BNE    MUL1
         INC    5,X
MUL1:    LDAA   2,X
         LDAB   A24+1
         MUL
         ADDD   6,X
         STD    6,X
         BCC    MUL2
         INC    5,X     ; Propagate Carry
MUL2:    LDAA   2,X
         LDAB   A24     ; Most signifigant byte
         MUL
         ADDD   5,X
         STD    5,X     ; No carry possible on hi end
MULUP2:  DEX            ; Move left 1 byte in multiplier & result
         DEC    CNTR
         BNE    MULOOP
         PULX           ; Restore regs
         PULA
         PULB
         RTS


* Calculate the 24 bit unsigned quotient resulting from division of a
* 48 bit dividend by a 24 bit divisor. Place the divisor in D24 and the
* dividend in D48. The result will be returned in Q24.

*   The approach is similar to long division by hand, but here the
* IDIV instruction is used to form the trial quotient. Care is taken
* to ensure that the trial quotient is always <= the required quotient.

* The division routine can be modified to handle any reasonable number
* of bytes, but it is more challenging than extending the multiplication
* routine.

*   Typical operation is two passes through the loop per byte in the
* dividend.


DIV24:   PSHB
         PSHA
         PSHX
	 PSHY
         CLR    Q24     ; Clear quotient to 0
         CLR    Q24+1
         CLR    Q24+2
         LDAB   #6      ; Size of dividend, max
         LDY    #D48    ; Count bytes in the dividend
DIV0:    TST    0,Y
         BNE    DIV1
         DECB
         BEQ    DIVER1  ; Done if dividend = 0, Return 0
         INY
         BRA    DIV0

DIVER1:  JMP    DIVBY0  ; Extend branch range

*  Find size of divisor and dividend & thus the hi byte of quotient.
*  Also do gross checks to avoid dividing by 0, etc.
DIV1:    STAB   DVDCNT  ; Save # bytes in dividend
         LDAA   #$FF
         NEGB
         ADDD   #D48+5  ; + Addr of LS Byte-1 in dividend
         XGDY           ; Y points to MSB of dividend
         LDA    #3      ; Count bytes in the divisor
         LDX    #D24
DIV1CT:  TST    0,X
         BNE    DIV2
         DECA
         BEQ    DIVER1  ; Quit if divide by 0, Return 0
         INX
         BRA    DIV1CT

DIV2:    STX    DIVPTR  ; Ptr to MSB of divisor
         STA    DIVCNT  ; Number of bytes in divisor
         SUBA   DVDCNT
         BGT    DIVER1  ; Quit if divisor > dividend, Return 0
         LDAB   1,Y     ; Get hi byte of dividend
         CMPB   0,X     ; IF hi byte of dividend > hi byte of divisor
         BLO    DIV3    ;  THEN one more byte needed in the quotient
         DECA
         DEY            ;  and in Dividend
DIV3:    TAB
         NEGA           ; Make it positive
         STAA   QCNT    ; # Bytes in quotient
         CMPA   #4      ; ??? MAKE THIS PREVENT OVERFLOW ???
         BGT    DIVER1  ; Quit if quotient too big, return 0
         LDAA   #$FF    ; Make it a negative 16 bit value
         ADDD   #Q24+2  ; Ptr to hi byte of quotient
         STD    QPTR

*  Decide whether to use 1 or 2 bytes as trial divisor
DIVLUP:  LDX    DIVPTR  ; Get ptr to MSB of divisor
         LDAA   DIVCNT  ; Get # bytes in divisor
         DECA
         BEQ    DIV1BY  ; Only 1 byte in divisor
         STA    CNTR    ; Temp, # bytes in divisor -1
         LDD    1,Y     ; Get hi word of dividend in B
         CPD    0,X     ; IF hi word of dividend < hi word of divisor
         BLO    DIVBYB  ;  THEN use only MSB of divisor
         BHI    DIVW2B  ; Divisor < Dividend  & 2+ bytes in divisor
         LDA    CNTR
         DECA
         BEQ    DIVWRD  ; BR if divisor = MSB's of dividend
         LDAB   3,Y     ; Get next byte of dividend in B
         CMPB   2,X     ; IF next byte of dividend < this byte of divisor
         BLO    DIVBYB  ;  THEN use only MSB of divisor, rounded up
         LDAB   #1      ;  ELSE Trial Quotient = 1
         BRA    DIVSTO

DIVBYB:  JMP    DIVBYT  ; Extend branch range
DIV1BY:  JMP    DIV1BYT

*  Trial divisor is 2 bytes. Round up if required.
DIVW2B:  LDA    CNTR
         DECA           ; Make A = 0 if exactly 2 bytes in divisor
DIVWRD:  LDX    0,X     ; Get MSW of divisor
         TSTA
         BEQ    DIVWNR  ; BR if exactly 2 bytes in divisor
         INX            ; Round divisor up
DIVWNR:  LDD    1,Y     ; Get MSW of dividend
         IDIV
         XGDX           ; Get trial quotient into B
*  Multiply divisor by trial quotient and subtract from dividend
DIVSTO:  STAB   TRIALQ  ; Save trial quotient
         LDX    QPTR
         ADDB   0,X     ; Add Trial Q to current Q
         STAB   0,X
         LDAB   DIVCNT
         STAB   CNTR
         LDX    DIVPTR
         LDAA   0,X     ; Get hi byte of divisor
         LDAB   TRIALQ  ; Get trial quotient byte
         MUL
         STD    TEMP    ; Seems crude, but it works...
         LDD    0,Y
         SUBD   TEMP    ; No borrow possible from hi byte
         STD    0,Y
         DEC    CNTR
         BEQ    DIVLND ; BR if divisor is 1 byte
         LDX    DIVPTR
         LDAA   1,X    ; Get next byte of divisor
         LDAB   TRIALQ
         MUL
         STD    TEMP
         LDD    1,Y
         SUBD   TEMP
         STD    1,Y 
         BCC    *+5
         DEC    0,Y     ; Propagate borrow
         DEC    CNTR
         BEQ    DIVLND  ; BR if divisor is 2 bytes
         LDX    DIVPTR
         LDAA   2,X
         LDAB   TRIALQ
         MUL
         STD    TEMP
         LDD    2,Y
         SUBD   TEMP
         STD    2,Y
         BCC    DIVLND
         LDX    0,Y     ; Propagate borrow
         DEX
         STX    0,Y
DIVLND:  LDD    0,Y
         BEQ    DIVDN0
         TSTA
         BEQ    DIVLN2  ; Almost always branches, 4000:1 or so
         LDX    DIVPTR  ; Ptr to MSB of divisor
         BRA    DIVBYR  ; Last divide by byte was too coarse, correct it

DIVDN0:  INY            ; Hi word of dividend=0, move 1 position right
         DEC    QCNT
         BLT    DIVDUN
         INC    QPTR+1
DIVLN2:  JMP    DIVLUP  ; Loop to do next byte

*  Trial divisor is hi byte of divisor.  Always round it up.
DIVBYT:  DEC    QCNT    ; Divisor > dividend, move 1 position right
         BLT    DIVDUN  ; BR if done
         INC    QPTR+1
         INY
DIVBYR:  LDAB   0,X     ; Get MSB of divisor
         CLRA
         XGDX
         INX            ; Round divisor up
         LDD    0,Y     ; Dividend, current hi 16 bits
         BEQ    DIVDN0  ; Shortcut on 0 dividend     ?? Does this help??
         IDIV           ; MSW of dividend / MSB of divisor = Trial Q
         XGDX           ; Get quotient in D
         TSTA
         BEQ    DIVBT2
         LDAB   #$F0    ; Overflow on this trial, force max 
DIVBT2:  JMP    DIVSTO

* Handle single byte divisor specially
DIV1BYT: LDAB   0,X     ; Get divisor, single byte
         CLRA   
         XGDX
DIV1SKP: CPX    0,Y
         BLS    DIV1BGO 
         DEC    QCNT   ; Divisor > Dividend,  move 1 position right
         BLT    DIVDUN  ; BR if done
         INC    QPTR+1
         INY
         BRA    DIV1SKP
DIV1BGO: LDD    0,Y     ; Dividend, current hi 16 bits
         IDIV           ; MSW of dividend / divisor = Trial Q
         XGDX           ; Get quotient in D
         JMP    DIVSTO

DIVDUN:
DIVBY0:  PULY
	 PULX           ; Restore regs
         PULA
         PULB
         RTS


cos_x	ldab	quadr
	beq	cos_x10
	cmpb	#1
	beq	cos_x20
	cmpb	#2
	beq	cos_x10
	cmpb	#3
	beq	cos_x20

cos_x10	staa	tmp
	ldaa	#90
	suba	tmp

cos_x20	tab
	clra
	addd	#sintab
	xgdx
	ldaa	0,x
	rts

		
sin_x	ldab	quadr
	beq	sin_x10
	cmpb	#1
	beq	sin_x20
	cmpb	#2
	beq	sin_x10
	cmpb	#3
	beq	sin_x20

sin_x20	staa	tmp
	ldaa	#90
	suba	tmp

sin_x10	tab
	clra
	addd	#sintab
	xgdx
	ldaa	0,x
	rts
	
	
isr_RTI	ldx	#REGBS
	ldaa	#%01000000
	staa	TFLG2,X

	tst	timout
	beq	key005
	dec	timout
	
key005	inc	sec_cnt
	ldaa	sec_cnt
	cmpa	#62
	bne	key00
	clr	sec_cnt
	ldaa	sec_flg
	eora	#%00000001
	staa	sec_flg	

key00	inc	key_cnt
	ldaa	key_cnt
	cmpa	#12
	beq	key02
	rti			; skip all irq until key_cnt = 12

key02	clr	key_cnt
	ldaa	PORTD,x
	staa	pdmir
	anda	#ALLKEY
	cmpa	#ALLKEY
	beq	key10	
	anda	#ANGKEY
	cmpa	#ANGKEY
	beq	key20		; no ANG key pressed
	cmpa	#ANGPL
	bne	angminu

angplus	ldd	angl
	addd	#1
	cmpd	#360
	bne	angpl10
	ldd	#0
	std	angl
angpl10	std	angl
	bra	key20
	
angminu	ldd	angl
	subd	#1
	bpl	angmi10
	ldd	#359
angmi10	std	angl
	
key20	ldaa	pdmir
	anda	#DRFKEY
	cmpa	#DRFKEY	
	beq	key10
	cmpa	#DRFPL	
	bne	drfminu

drfplus	ldd	drift
	cmpd	#999
	beq	key10
	addd	#1
	std	drift
	bra	key10

drfminu	ldd	drift
	beq	key10
	subd	#1
	std	drift
	bra	key10
	
key10	ldaa	PORTA,x
	anda	#ENTKEY
	bne	key30
	ldaa	#$01
	staa	entflg
	bra	key99

key30	clr	entflg
	
key99	bra	sio_snd		; see if we have to initiate sending


isr_SCI	ldx	#REGBS
	ldaa	SCSR,x
	staa	scsr_mr
	anda	#%00100000
	bne	sio_rcv
	ldaa	scsr_mr
	anda	#%10000000
	bne	sio_snd
	rti			; if not rcv or snd. No other irq served.

sio_rcv	ldaa	SCDR,x		; dont care for overrun error yet
	ldy	recvwr
	staa	0,y
	cpy	#recvbuf+15
	bne	sio_r10
	ldy	#recvbuf-1
sio_r10	iny
	sty	recvwr
	ldaa	scsr_mr
	anda	#%10000000
	bne	sio_snd
	rti

sio_snd	ldy	sendrd
	cpy	sendwr
	beq	sio_s08				; nothing to send
sio_s03	brclr	SCSR,x,%10000000,sio_s03	; wait till send reg empty

	pshx
	ldx	#8
	clrb
	ldaa	0,y
	psha
sio_s0a	lsra
	bcc	sio_s04
	incb
sio_s04	dex
	bne	sio_s0a
	pula
	pulx
	andb	#$01
	bne	sio_s0c
	bclr	SCCR1,x,%01000000
	bra	sio_s0d
sio_s0c	bset	SCCR1,x,%01000000
	
sio_s0d	staa	SCDR,x
	cpy	#sendbuf+15
	bne	sio_s05
	ldy	#sendbuf-1
sio_s05	iny
	sty	sendrd
	cpy	sendwr
	beq	sio_s08			; nothing more to send
	bset	SCCR2,x,%10000000	; if more bytes to send set irq enable bit
	bra	sio_s10
sio_s08	bclr	SCCR2,x,%10000000	; if no more bytes to send clr irq enable
sio_s10	rti

ledtab	fcb	%00000000
	fcb	%00000100
	fcb	%00100100
	fcb	%00110100
	fcb	%00111100
	fcb	%01111100

ledtab1	fcb	%00000000
	fcb	%00000100
	fcb	%00100000
	fcb	%00010000
	fcb	%00001000
	fcb	%01000000

sintab  fcb     000		; 0
        fcb     004
        fcb     009
        fcb     013
        fcb     018
        fcb     022
        fcb     027
        fcb     031
        fcb     035
        fcb     040
        fcb     044		; 10
        fcb     049
        fcb     053
        fcb     057
        fcb     062
        fcb     066
        fcb     070
        fcb     075
        fcb     079
        fcb     083
        fcb     087		; 20
        fcb     091
        fcb     096
        fcb     100
        fcb     104
        fcb     108
        fcb     112
        fcb     116
        fcb     120
        fcb     124
        fcb     127		; 30
        fcb     131
        fcb     135
        fcb     139
        fcb     143
        fcb     146
        fcb     150
        fcb     153
        fcb     157
        fcb     160
        fcb     164		; 40
        fcb     167
        fcb     171
        fcb     174
        fcb     177
        fcb     180
        fcb     183
        fcb     186
        fcb     190
        fcb     192
        fcb     195		; 50
        fcb     198
        fcb     201
        fcb     204
        fcb     206
        fcb     209
        fcb     211
        fcb     214
        fcb     216
        fcb     219
        fcb     221		; 60
        fcb     223
        fcb     225
        fcb     227
        fcb     229
        fcb     231
        fcb     233
        fcb     235
        fcb     236
        fcb     238
        fcb     240		; 70
        fcb     241
        fcb     243
        fcb     244
        fcb     245
        fcb     246
        fcb     247
        fcb     248
        fcb     249
        fcb     250
        fcb     251		; 80
        fcb     252
        fcb     253
        fcb     253
        fcb     254
        fcb     254
        fcb     254
        fcb     255
        fcb     255
        fcb     255
	fcb	255		; 90
	
$IF DEBUG = 0
	ORG	$FF00			; start of EEPROM

* INITIAL THE CPU

RESET	LDS	#$01FF			; put stack in CPU RAM
	LDX	#$1000			; register base address
	LDAA	#%10010001		; adpu, irqe, dly, cop = 65mS
	STAA	OPTION,X
	ldaa	#%00000000
	staa	TMSK2,X
	LDAA	#%00000000
	STAA	BPROT,X			; make CONFIG & EEPROM writable
	LDS	#$03ff
	LDAA	#%00000101
	STAA	CSCTL,X			; enable program CS for 32K
	LDAA	#%00000000
	STAA	CSGADR,X		; RAM starts at address 0000H
	LDAA	#%00000001
	STAA	CSGSIZ,X		; RAM block size is 32K
	LDAA	#%00011111
	STAA	DDRG,X			; bank select bits = outputs
	LDAA	#%00000000
	STAA	PORTG,X			; select 1ST bank
	jmp	start

	
******************************************************************************
*                           Interrupt Service Routinen                       *
******************************************************************************

*	Commented vectors are serviced in the code
	
* isr_SCI
isr_SPI
isr_PAIE
isr_PAO
isr_TIMO
isr_TIC4
isr_TOC4
isr_TOC3
isr_TOC2
isr_TOC1
isr_TIC3
isr_TIC2
isr_TIC1
* isr_RTI
isr_IRQ 
isr_XIRQ
isr_SWI
isr_ILLOP
isr_COPFAIL
isr_CLMONFAIL
	
        rti                   * keine Bearbeitung fuer diese IRQ's
	
***********************************
* VECTOR TABLE
***********************************

        ORG     $FFD6             * Start der Vectortabelle

        fdb     isr_SCI
        fdb     isr_SPI
        fdb     isr_PAIE
        fdb     isr_PAO
        fdb     isr_TIMO
        fdb     isr_TIC4
        fdb     isr_TOC4   
        fdb     isr_TOC3
        fdb     isr_TOC2
        fdb     isr_TOC1
        fdb     isr_TIC3
        fdb     isr_TIC2
        fdb     isr_TIC1
        fdb     isr_RTI
        fdb     isr_IRQ
        fdb     isr_XIRQ
        fdb     isr_SWI
        fdb     isr_ILLOP
        fdb     isr_COPFAIL
        fdb     isr_CLMONFAIL
        fdb     RESET
$ENDIF
		
*************
* END OF FILE

*	END

