 title  "asmDlay - Create a Universal Delay Macro"
;
;  The "Dlay" macro in this routine will provide delays ranging 
;   from 1 to 1,000,000 cycles.  
;
;  Hardware Notes:
;   PIC16F684 running at 4 MHz in Simulator
;   Reset is tied directly to Vcc via Pullup/Programming Hardware
;
;
;  Myke Predko
;  04.09.22
;
  LIST R=DEC
 INCLUDE "p16f684.inc"

 __CONFIG _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTOSCIO

 CBLOCK 0x020                ;  Variable Declaration
DlayValue:2                  ;  Requires 24 Bit Counter (w/ WREG)
 ENDC

Dlay Macro Cycles
 variable CyclesLeft            ;  Keep Track of Remaining Cycles
 variable LargeNum
CyclesLeft = Cycles
 local LongLoop
 if Cycles > 0x04FFFF00         ;  Can't Handle the Anything > 83 Seconds (@ 4 MHz)
 error "Required Delay is longer than 'Dlay' Macro can support"
 endif
 if Cycles > 327681             ;  Need Large Loop?  
LargeNum = CyclesLeft / 327681
  movlw   LargeNum
  movwf   DlayValue + 2         ;  Calculate Number of Loops
LongLoop:                       ;  Repeat for Each Loop
  clrf    DlayValue + 1         ;  Do Maximum Possible Loop Count
  clrf    DlayValue
  decf    DlayValue, f
  btfsc   STATUS, Z
   decfsz DlayValue + 1, f
    goto  $ - 3
  decfsz  DlayValue + 2, f      ;  Repeat Loop
   goto   LongLoop
CyclesLeft = CyclesLeft - ((LargeNum * 327681) + 1 + (LargeNum * 3))
 endif  ;  Need Large Loop
 if Cycles > 14                 ;  Will a Loop be required?  
  movlw   high (((CyclesLeft - 3) / 5) + 256)
  movwf   DlayValue + 1
  movlw   low (((CyclesLeft - 3)/ 5) + 256)
  movwf   DlayValue
  decf    DlayValue, f          ;  5 Cycle Constant Delay Loop
  btfsc   STATUS, Z
   decfsz DlayValue + 1, f
    goto  $ - 3
CyclesLeft = CyclesLeft - (3 + (5 * ((CyclesLeft - 3)/ 5)))
 endif                          ;  Finished with Loop Code
 while CyclesLeft >= 2          ;  Put in 2 Instruction Cycle Delays
  goto    $ + 1
CyclesLeft = CyclesLeft - 2
 endw
 if CyclesLeft == 1             ;  Put in the Last Required Cycle
  nop
 endif
 endm

  PAGE

 org      0
  nop                        ;  Required for MPLAB ICD2

 Dlay 3                      ;  Should be goto & nop
  nop

 Dlay 44                     ;  Delay 44 Cycles
  nop

 Dlay 1000                   ;  1 ms Delay
  nop

 Dlay 100000                 ;  Delay 0.1s
  nop

 Dlay 5000000                ;  Delay 5s
  nop

 Dlay 60000000               ;  Delay 60s

  goto    $                  ;  Finished, Everything Okay

  end                           
