' *** ' *** Delay routines ' *** ' *** written by larry Bradley, January 2004 Sub Pauseus(n As uInteger) ' ' This routine generates much smaller code sequences than do the ' DELAY routines supplied with Basic18, which typically generate in-line code. '

' The delays generated include the calling sequence times as well, ' and are exact for a UINTEGER argument, or a constant greater than 255. ' Using a constant les than 256 will remove 1 instruction cycle from the interval ' (1 usec at 4 mHz, for example) '

' There is a minimum value that be used ' as the argument, because of the overhead of the loops.
' This ranges from 4 for a 40 mHz clock to 27 for a 4 mHz clock '

' Oscillator frequencies supported are: ' 40 mHz, 20 mHz, 16 mHz, 12 mHz, 10 mHz, 8 mHz, and 4 mHz.
' If you need to use a different oscillator freqency, you can use ' the Basic18 DELAY routines. '

' This is the number of microseconds to delay (0 to 65535) ' #If FOSC=40000000 ' Pause for N microseconds (min N is 4) ' 40 mhz clock movf n,w addlw -4 ; 1 Subtract overhead movwf n movlw -1 bra $+2 bra LOOP1A LOOP1: addwf n, F LOOP1A: clrwdt bra $+2 btfss STATUS, C addwf n.Byte1, F btfss STATUS, C bra finished bra LOOP1 finished: bra $+2 bra $+2 bra $+2 '#endif #elseIf FOSC=20000000 ' Pause for N microseconds (min N is 5) ' For a 20 mhz clock (OSC20) (5*n instrutions) ' ' Account for calling and setup overhead by taking 5 ' off the low-order byte ' n.lowbyte - n,lowbyte - 5 movf n,w addlw -5 ' adding -5 is same as subtracting 5 movwf n ' Complement the high order byte ' n.highbyte = - (n.highbyte+1) comf n.Byte1, F ' If the lowbyte conputation resulted in a 0 or -ve results, ' skip the inner loop (this effectively handles the "borrow" from ' the high-order byte) btfss STATUS, C bra LOOP2A ' Loop1 is high-order-byte counter, which counts up to zero from a -ve start LOOP1: movlw -1 ' This is what we subtract from n each pass thru loop2 ' Loop2 is low-order byte counter, which counts down to zero stepping by 1 LOOP2: nop addwf n, F btfsc STATUS, C ' If count reaches 0, exit the loop bra LOOP2 ' End of inner Loop. Set up inner loop counter again by subtracting 1 addwf n, F LOOP2A: clrwdt ' Clear WDT incfsz n.Byte1, F ' Incr. high byte, if zero, we are done. bra LOOP1 ' End of outer loop; extra cycles nop nop '#endif #elseIf FOSC=16000000 ' Pause for N microseconds (min N is 6) ' For a 16 mhz clock ' ' Account for calling and setup overhead by taking 5 ' off the low-order byte ' n.lowbyte - n,lowbyte - 5 movf n,w addlw -6 'adding -6 is same as subtracting 5 movwf n ' Complement the high order byte ' n.highbyte = - (n.highbyte+1) comf n.Byte1, F movlw -1 btfss STATUS, C bra loop2 loop1: addwf n, F btfsc STATUS, C bra loop1 loop2: addwf n, F clrwdt incfsz n.Byte1, F bra loop1 nop nop '#endif #elseIf FOSC=12000000 ' Pause for N microseconds (min N is 10) ' For a 12 mhz clock movf n,w addlw -10 movwf n comf n.Byte1, F btfss STATUS, C bra loop3 loop1: movlw -2 loop2: bra $+2 addwf n, F btfsc STATUS, C bra loop2 addwf n, F loop3: clrwdt nop incfsz n.Byte1, F bra loop1 bra $+2 btfss n, 0 bra finished bra $+2 bra $+2 finished: '#endif #elseIf FOSC=10000000 ' Pause for N microseconds (min N is 12) ' For a 10 mhz clock movf n,w addlw -12 ' Subtract overhead movwf n comf n.Byte1, F ' If the lowbyte conputation resulted in a 0 or -ve results, ' skip the inner loop (this effectively handles the "borrow" from ' the high-order byte) btfss STATUS, C bra LOOP2A ' Loop1 is high-order-byte counter, which counts up to zero from a -ve start LOOP1: movlw -2 ' This is what we subtract from n each pass thru loop2 ' Loop2 is low-order byte counter, which counts down to zero stepping by 2 LOOP2: nop addwf n, F LOOP2A: btfsc STATUS, C bra LOOP2 ' End of inner Loop. Set up inner loop counter again by subtracting 2 addwf n, F clrwdt incfsz n.Byte1, F bra LOOP1 ' End of outer loop ; add in extra cycles nop btfsc n, 0 bra $+2 btfsc n, 0 bra $+2 nop nop '#endif #elseIf FOSC=8000000 ' Pause for N microseconds (min N is 14) ' 8 mhz clock movf n,w addlw -14 movwf n comf n.Byte1, F movlw -2 btfss STATUS, C bra loop2 loop1: addwf n, F btfsc STATUS, C bra loop1 loop2: addwf n,F clrwdt incfsz n.Byte1, F bra loop1 nop nop btfsc n,0 bra $+2 btfsc n,0 bra $+2 '#endif #elseIf FOSC=4000000 ' Pause for N microseconds (min N is 27) ' 4 mhz clock movf n,w addlw -27 'Subtract overhead movwf n comf n.Byte1, F movlw -4 'Inner loop step is -4 btfss STATUS, C bra LOOP1A ' Loop1 is high-order-byte counter, which counts up to zero from a -ve start LOOP1: addwf n, F btfsc STATUS, C bra LOOP1 ' End of inner Loop. Set up inner loop counter again by subtracting 1 LOOP1A: addwf n, F ' 1 Do an extra countdown clrwdt incfsz n.Byte1, F bra LOOP1 ' End of outer loop ; add in extra cycles btfsc n, 0 bra $+2 btfss n,1 bra finished nop bra finished finished: #else ' Uncomment this when the preprocessor bug gets fixed "*** ERROR *** Clock frequency FOSC not supported by PauseuS. Use DelayuS" #endif '#ifndefOSC__OK ' "*** ERROR *** Clock frequency FOSC not supported by PauseuS. Use DelayuS" '#endif ' End Sub Sub PauseMS(n As uInteger) ' ' This routine generates much smaller code sequences than do the ' DELAY routines supplied with Basic18, which typically generate in-line code. '

' The delays generated include the calling sequence times as well, ' and are exact for a UINTEGER argument, or a constant greater than 255. ' Using a constant les than 256 will remove 1 instruction cycle from the interval ' (1 usec at 4 mHz, for example) '

' Oscillator frequencies supported are: ' 40 mHz, 20 mHz, 16 mHz, 12 mHz, 10 mHz, 8 mHz, and 4 mHz.
' If you need to use a different oscillator freqency, you can use ' the Basic18 DELAY routines. '

The PauseMS routine calls the PauseUs routine '

'The number of milliseconds to pause, from 1 to 65535 ' Pause for n milliseconds #If FOSC=40000000 'const pause__delay = 1000-(10*4/40) 'const pause__delay2 = 1000-(17*4/40) Const pause__delay = 999 Const pause__delay2 = 998 '#endif #elseIf FOSC=20000000 'const pause__delay = 1000-(10*4/20) 'const pause__delay2 = 1000-(17*4/20) Const pause__delay = 998 Const pause__delay2 = 996 '#endif #elseIf FOSC=16000000 'const pause__delay = 1000-(10*4/16) 'const pause__delay2 = 1000-(17*4/16) Const pause__delay = 997 Const pause__delay2 = 995 '#endif #elseIf FOSC=12000000 'const pause__delay = 1000-(10*4/12) 'const pause__delay2 = 1000-(17*4/12) Const pause__delay = 996 Const pause__delay2 = 994 '#endif #elseIf FOSC=10000000 'const pause__delay = 1000-(10*4/10) 'const pause__delay2 = 1000-(17*4/10) Const pause__delay = 996 Const pause__delay2 = 993 '#endif #elseIf FOSC=8000000 'const pause__delay = 1000-(10*4/8) 'const pause__delay2 = 1000-(17*4/8) Const pause__delay = 995 Const pause__delay2 = 991 '#endif #elseIf FOSC=4000000 'const pause__delay = 1000-(10*4/4) 'const pause__delay2 = 1000-(17*4/4) Const pause__delay = 990 Const pause__delay2 = 983 #else 'Uncomment this when the preprocessor bug gets Fixed Const pause__delay = 0 Const pause__delay2 = 0 "*** ERROR *** Clock frequency FOSC not supported by PauseMS. Use DelaymS" #endif '#ifndef OSC__OK 'Const pause__delay = 0 'Const pause__delay2 = 0 ' "*** ERROR *** Clock frequency FOSC not supported by PauseMS. Use DelaymS" '#endif ' Note the use of two calls in order to get the lowest possible error by accounting ' for the overhead of the routine ' The loop uses 10 instructions, thus delay needs to be 1000-(10*4/fosc) ' This is not exact, so we compensate by using some additional insructions 'n = n - 1 decf n,F movlw 0 subwfb n+1,F ' While n <> 0 ' Using a WHILE loop results in instr count being different for n < 255 and ' n > 255, so we hand code the equivalent, but add an instruction at label ' "pause2" to equalize. This now is 5 instructions loop: tstfsz n+1 ' Hi byte > 0? bra pause2 ' yes tstfsz n ' No. Low byte > 0 bra pause3 ' yes bra loopend ' No, loop is done pause2: bra $+2 ' To make instr count the same for < 256 and > 256 pause3: Call pauseus(pause__delay) #If FOSC = 16000000 ' Add 2 instr cycles bra $+2 #endif #If FOSC = 12000000 ' Add 3 instr cycles bra $+2 #endif 'n = n - 1 decf n,F movlw 0 subwfb n+1,F bra loop loopend: ' End While ' This call handles the overall overhead, which is 17 instructions ' this is delay2=1000-(17*4/fosc) Call pauseus(pause__delay2) #If FOSC=40000000 ' Additional instructions bra $+2 nop #endif #If FOSC=20000000 ' Additional instructions bra $+2 nop #endif #If FOSC=16000000 ' Additional instructions bra $+2 nop #endif #If FOSC=12000000 ' Additional instructions nop #endif #If FOSC=10000000 ' Additional instructions nop #endif #If FOSC=8000000 ' Additional instructions nop #endif End Sub