;################################################################################# ; subroutine Delay - burns CPU cycles to cause a delay. ; This subroutine implements three nested loops that each iterate ; a number of times specified by the constants C1, C2, and C3, which ; must be supplied as arguments in R0, R1, and R2. The ; amount of time expended by these loops is given by the equations below. ; This routine uses registers R16-R18 and restores their values on exit. Delay: .DEF C1 = R0 ; loop counter constants .DEF C2 = R1 .DEF C3 = R2 .DEF counter1 = R16 ; loop counters for delay loops .DEF counter2 = R17 .DEF counter3 = R18 ; save the values in the Registers we're using here. Note we will only read R0, R1, and R2 push counter1 push counter2 push counter3 ; start of delay loop; uses 3 nested loops ; Cycles for initialization: 1 ; Cycles for inner loop: C3*C2*C1*3 - C1*C2 ; Cycles for middle loop: C2*C1*4 - C1 ; Cycles for outer loop: C1*4 - 1 ; Total cycles: 1 + C3*C2*C1*3 - C1*C2 + C2*C1*4 - C1 + C1*4 - 1 ; = C3*C2*C1*3 + C2*C1*3 + C1*3 ; = 3*C1(C3*C2 + C2 + 1) mov counter1, C1 ; init outermost loop counter to C1 loop1: ; this loop executes C1 times mov counter2, C2 ; init middle loop counter to C2 loop2: ; this loop executes C1*C2 times mov counter3, C3 ; init innermost loop counter to C3 loop3: ; this loop executes C1*C2*C3 times dec counter3 brne loop3 ; takes 2 CPU cycles if true; 1 if false dec counter2 brne loop2 dec counter1 brne loop1 ; end of delay loop; takes 60ms at 16MHz for C1=32, C2=99, C3=100 ; restore initial values of Registers we've been using pop counter3 pop counter2 pop counter1 ret ; return to caller ; end subroutine Delay ;################################################################################# ;################################################################################# ; subroutine delay60 ; This subroutine invokes a 60ms delay by setting specific values to ; registers R0, R1, and R2 which are used as arguments to the Delay subroutine ; The particular values used here result in a 60ms delay at 16Mhz delay60: push R0 ;save registers push R1 push R2 push temp ldi temp, 32 mov R0, temp ldi temp, 99 mov R1, temp ldi temp, 100 mov R2, temp rcall delay ; 60ms delay is more than enough to let the LCD initialize pop temp ; restore registers pop R2 pop R1 pop R0 ret ; end subroutine delay60 ;################################################################################# ;################################################################################# ; subroutine delay1000 ; This subroutine invokes a 1000ms delay by setting specific values to ; registers R0, R1, and R2 which are used as arguments to the Delay subroutine ; The particular values used here result in a 1000ms delay at 16Mhz delay1000: push R0 ;save registers push R1 push R2 push temp ldi temp, 200 mov R0, temp ldi temp, 200 mov R1, temp ldi temp, 132 mov R2, temp rcall delay ; delay sub uses R0, R1, and R2 as "arguments" pop temp ;restore registers pop R2 pop R1 pop R0 ret ; end subroutine delay1000 ;#################################################################################