summaryrefslogtreecommitdiff
path: root/frontends/calculator/CEdev/lib/shared/delay.src
blob: affa948a27f7ecc43a601ee9fd270592d9b2fb2c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
; ---
; void delay(uint16_t millis)
; ---

	.def	_delay
	.assume	adl=1

mpTmrRange		equ 0F20000h

tmr2Counter		equ 10h
tmr2Load		equ 14h
tmr2Match1		equ 18h
tmr2Match2		equ 1Ch

tmrCtrl			equ 30h

bTmr2Enable		equ 3
bTmr2Crystal		equ 4
bTmr2Overflow		equ 5
bTmr2CountUp		equ 10

_delay:
; Read argument.
	pop	de
	ex	(sp),hl			; 0hl = millis
	push	de
; Abort ASAP if millis == 0.
	ld	a,h
	or	a,l
	ret	z
; Convert millis to CPU cycles by multiplying by 48000.
; Subtract 2 to offset overhead and the unknown counter low byte.
	ld	b,h
	ld	c,l			; 0bc = millis
	dec.s	bc			; bc = millis-1; need to set bcu = 0
	srl	b
	rr	c			; bc = (millis-1)>>1
					;    = millis*(48000&0FFh)>>8,
					;      off by -1 or -0.5
	ld	e,l
	ld	d,187			; 48000/256 == 187.5
	ld	l,d
	mlt	de			; de = (millis&0FFh)*(48000>>8)
	mlt	hl			; hl = (millis>>8)*(48000>>8)
	dec	hl
	push	hl
	dec	sp
	pop	hl
	inc	sp
	ld	l,-2			; hl = (millis&0FF00h)*(48000>>8)-2
	add	hl,de			; hl = millis*(48000>>8)-2
	add	hl,bc			; hl ~ (millis*48000>>8)-3
; Set up timer 2 control bits: disabled, CPU clock, no interrupt, count down.
	ex	de,hl			; de ~ (millis*48000>>8)-3
	ld	hl,mpTmrRange+tmrCtrl
	res	bTmr2Enable,(hl)
	res	bTmr2Crystal,(hl)
	res	bTmr2Overflow,(hl)
	inc	hl
	res	bTmr2CountUp-8,(hl)
; Set up timer 2 counter, match, and reload values.
	ld	l,tmr2Counter+1
	ld	(hl),de			; counter = millis*48000-768+0xxh
	ld	l,tmr2Match1+3
	ld	(hl),0FFh		; match1 = 0FFxxxxxxh
	ld	l,tmr2Match2+3
	ld	(hl),0FFh		; match2 = 0FFxxxxxxh
	ld	l,tmr2Load+3
	ld	(hl),0FEh		; reload = 0FExxxxxxh
; Enable timer 2.
	ld	l,tmrCtrl
	set	bTmr2Enable,(hl)
; Wait until timer 2 expires (underflows).
; Will catch the underflow if not interrupted for a continuous period of
; ((254-188)<<24)/48000000 ~ 23.1s.
	ld	l,tmr2Counter+3
	ld	a,188			; = 1+((0FFFFh*24000 shl 1)-12 shr 24)
; 380 cc up to this point
_delay_wait:
	cp	a,(hl)
	jr	nc,_delay_wait
; 12-29 cc to exit waitloop
; Done.
	ret
; ~421 cc up to this point
; caller overhead:
;	ld	bc,millis
;	push	bc
;	call	_delay
;	pop	bc
; ~485 cc total