Please note: the loop counter values in all routines are calculated for an E-Clock of 2 MHz.
; ---------------------------------------------------------------------------
; Function delay100us
; Description delay for 100 microseconds (with E-Clk = 2 MHz)
; Last update 2005-10-16
; Stack usage 1 byte
; Cycle count 20 cycles (including 6 cycles from jsr) plus 5 cycles each
; loop.
; Code size 8 bytes
; ---------------------------------------------------------------------------
delay100us: ; 2'000'000Hz * 0.0001s = 200 cycles to eat
psha ; 3c
ldaa #36 ; 2c ... (200-20)/5 = 36
_delay_100us_0:
deca ; 2c
bne _delay_100us_0 ; 3c
pula ; 4c
rts ; 5c plus jsr (6c)
; ---------------------------------------------------------------------------
; Function delay
; Description delay for n milliseconds (give n in register a, n = 1..255
; For n=0, the function will delay 256 ms)
; Last update 2005-10-16
; Notes This works only for an E-Clock of 2 MHz.
; If you don't mind a small timing error of 18 cycles (9 us)
; but rather would like to save 5 bytes, just comment out
; "ldx 328" and "bra _delay_1"
; For 1 ms delay, we still have a timing error of 3 cycles.
; And if an interupt occurs, timing also is not precise.
; Stack usage 2 bytes
; Code size 17 bytes
; ---------------------------------------------------------------------------
delay:
pshx ; 2c?
ldx #328 ; 3c make first inner loop shorter to compensate
bra _delay_1 ; 3c the 24 cycles per function call (incl. jsr)
_delay_0:
ldx #332 ; 3c ... 332*6 = 1992 cycles
_delay_1:
dex ; 3c
bne _delay_1 ; 3c
deca ; 2c
bne _delay_0 ; 3c plus 8 cycles (3+2+3) = 2000 cycles
pulx ; 5c
rts ; 5c plus jsr (6 cycles)
Both routines have the disadvantage of being inaccurate when interrupts occur. If you want to avoid this, you either could disable interrupts within the delay routine, or by using a timer as shown in the following example:
; ---------------------------------------------------------------------------
; Function delay10ms
; Description Delay for 10 milliseconds
; Last update 2005-10-16
; Notes This works only for an E-Clock of 2 MHz.
; Stack usage 4 bytes
; Code size ? bytes
; ---------------------------------------------------------------------------
include "hc11regs.i"
delay10ms: ; 20000 cycles to eat
pshx ; 2c
psha ;
pshb ;
ldx #REGBASE
ldaa #$80
staa TFLG1,X ; 4c clear OC1F if it is allready set
ldaa #$00
staa TMSK2,X ; setup clock divider and interupt
ldd TCNT,X ; read counter value
addd #20000 ;
std TOC1,X ; when TCNT==TOC1, OC1F will be raised
_delay10ms_l0:
brclr TFLG1,X,#$80,_delay10ms_l0
ldaa #$80
staa TFLG1,X ; clear OC1F
;bclr TFLG1,X,#$7f ; clear OC1F
pulb
pula
pulx
rts ; 5c plus jsr (6 cycles)
This still could be inaccurate, especially if the interrupt routine(s)
take too much time (which they shouldn't).
If highest possible timing is important for you, you should disable interrupts
when entering the delay routine (call sei before pshx) and disable them before
rts or before waiting for the counter to overflow.