• AVR Freaks

Useful cycle-accurate delay subroutine

Author
mxbond
New Member
  • Total Posts : 3
  • Reward points : 0
  • Joined: 2009/03/11 17:47:44
  • Location: 0
  • Status: offline
2009/03/11 18:40:08 (permalink)
5 (1)

Useful cycle-accurate delay subroutine

  Here's an optimized subroutine to provide cycle-accurate delays from 14-65535 cycles. It takes a 16 bit value ... high byte in the memory location 'DelayH', and low byte in the W reg. Input values from 0 to 13 give a delay of (input val + 65536). I came up with this many years ago for the 16c54 series, and since I've still not seen anything similar, I figured it would be nice to finally post it.
 
Note that due to the 'addwf PCL,1' instruction, attention must be given to issues regarding paging. If you've no idea what the previous sentence means, *RTFM* ;-)
 
Example Usage:
 
;------------------------------------------
DelayH          RES     1               ; declare 'DelayH' byte variable
;------------------------------------------
start           clrf    DelayH          ; 1 cycle
                movlw   #14             ; 1 cycle
                call    vdelay          ; 14 cycles
 
                movlw   #255            ; 1 cycle - DelayH is zero as a result of previous call
                call    vdelay          ; 255 cycles
 
                movlw   #50000/256      ; 1 cycle - calculate high byte of 50k
                movwf   DelayH          ; 1 cycle
                movlw   #50000%256      ; 1 cycle - calculate low byte of 50k ... ie 50k modulo 256
                call    vdelay          ; 50000 cycles
 
                movlw   #0              ; 1 cycle - DelayH is zero as a result of previous call,
                                        ;   16bit val = 0
                call    vdelay          ; 65536 cycles ... for 16 bit values less than 14,
                                        ;   the delay is (value + 65536)
 
                goto    start
;------------------------------------------
; here's the actual subroutine:
 
vdelay          addlw   #-14
                btfsc   STATUS,C
                incf    DelayH,1
 
vdelay_loop     addlw   #-5
                btfss   STATUS,C
                decfsz  DelayH,1
                goto    vdelay_loop
                xorlw   #-1
                addwf   PCL,1
                nop
                nop
                nop
                nop
                retlw   #0
;------------------------------------------
 
Replies of 'thanks' are always appreciated ... I hope some of you find this useful :-)
 
Bond ... *Mike* Bond
 
post edited by mxbond - 2009/03/11 18:45:56
#1

12 Replies Related Threads

    K8LH
    Super Member
    • Total Posts : 1887
    • Reward points : 0
    • Joined: 2004/03/26 05:12:34
    • Location: Michigan, USA
    • Status: offline
    RE: Useful cycle-accurate delay subroutine 2009/03/12 10:07:02 (permalink)
    +2 (1)
    Oh wow! Nicely done Mike.

    That code is much tighter and cleaner than what I came up with long ago (below) and the improvement is so intuitive and obvious that I'm embarrassed that I didn't see it.

    Regards, Mike, K8LH

    DelayCy macro   cycles          ; parameter 18..65535 cycles
             movlw   high cycles     ; 4 instructions, 5 cycles
             movwf   TMRH            ;
             movlw   low cycles      ;
             call    DelayTcy        ; use 16 bit entry point
             endm

    ;                                                                 *
    ;  18 words (14 bit core)                                         *
    ;                                                                 *
    DelayTcy
             comf    TMRH,F          ; compliment delay hi
             addlw   -22             ; subtract "overhead"
             skpc                    ; borrow? no, skip, else
             goto    DelayHi         ;
             nop                     ;
    DelayLo
             addlw   -4              ; subtract 4 cycle loop time
             skpnc                   ;
             goto    DelayLo         ;
             nop                     ;
    DelayHi
             addlw   -4              ; subtract 4 cycle loop time
             incfsz  TMRH,F          ; done?  yes, skip, else
             goto    DelayLo         ; loop again
             sublw   h'FB'           ;
             addwf   PCL,F           ;
             nop                     ;
             nop                     ;
             nop                     ;
             return                  ;
    post edited by K8LH - 2009/03/13 09:48:10
    #2
    K8LH
    Super Member
    • Total Posts : 1887
    • Reward points : 0
    • Joined: 2004/03/26 05:12:34
    • Location: Michigan, USA
    • Status: offline
    RE: Useful cycle-accurate delay subroutine 2009/03/12 10:10:04 (permalink)
    0
    Mike,

    Just a funny note to compliment your last name, Bond.  My Amateur Radio bureau QSL card manager in Ohio is a young lady named Sandy Moneypenny (grin)...

    Regards, Mike, K8LH
    #3
    mxbond
    New Member
    • Total Posts : 3
    • Reward points : 0
    • Joined: 2009/03/11 17:47:44
    • Location: 0
    • Status: offline
    RE: Useful cycle-accurate delay subroutine 2009/03/12 13:11:10 (permalink)
    0
        I haven't heard of another person who was able to figure out how to use a 'nop jump-table' to make a good var-delay function for the PIC until now. Considering that nearly every online PIC code example I've seen that implements some form of variable cycle delay is downright primitive compared to the code you posted ... you have no cause at all to feel 'embarassed'. On the contrary, your code is *very* close to mine ... 15 cycles vs 14 cycles call overhead, and only 4 instructions larger.  It was interesting and informative for me to see an alternate approach. Anyone who has figured out how to do this type of stuff on their own is obviously an 'elite' PIC programmer - so I salute you. I'd love to see someone else come up with a 16 bit delay routine with a smaller overhead (less than 14 cycles minimum without being huge).

    MXBond

    post edited by mxbond - 2009/03/12 13:15:52
    #4
    K8LH
    Super Member
    • Total Posts : 1887
    • Reward points : 0
    • Joined: 2004/03/26 05:12:34
    • Location: Michigan, USA
    • Status: offline
    RE: Useful cycle-accurate delay subroutine 2009/03/12 15:58:48 (permalink)
    0
    I think I've seen the "nop jump" operation on PICLIST and here on Forum.Microchip before.

    I updated my "fixed" delay subsystem with your 4 word 5 cycle 16 bit timing loop and shaved 3 words off my delay subroutine.  Very cool indeed.  Thanks again for sharing a great optimization example.  You're a bloomin' genius.

    Kind regards, Mike

    ;
    ;  example "beep" routine generates a precise 500 Hz tone using
    ;  almost any clock (4, 8, 12, 16, 20 MHz, etc.).
    ;
             bsf     Beep,5          ; do 32 msec switch press beep    |B0
    DoBeep  movf    PORTA,W         ; read port A                     |B0
             xorlw   1<<Spkr         ; toggle speaker bit              |B0
             movwf   PORTA           ; toggle speaker pin              |B0
             DelayCy(1*msecs-6)      ; 1 msec minus 6 cycle loop time  |B0
             decfsz  Beep,F          ; done?  yes, skip, else          |B0
             goto    DoBeep          ; loop (toggle Spkr pin again)    |B0
    ;

    Here's my updated DelayCy() subsystem for "constant" operands;


    ;
    ;  DelayCy() clock equate and macro operand multipliers
    ;
             radix   dec
    clock   equ     8               ; clock frequency in Megahertz
    usecs   equ     clock/4         ; cycles/microsecond multiplier
    msecs   equ     usecs*1000      ; cycles/millisecond multiplier
    ;
    ;  DelayCy() Macro generates four instructions
    ;
    DelayCy macro   delay           ; 11..327690 cycles
             movlw   high((delay-11)/5)+1
             movwf   TMRH
             movlw   low ((delay-11)/5)
             call    DelayLp-((delay-11)%5)
             endm
    ;
    ;  code for simulation testing
    ;
    SimIt   DelayCy(327690)         ; <- put program counter here
             nop                     ; <- simulator break point here
    ;
    ;  Delay(11..327690 Tcy) subroutine   Mike McLaren, K8LH, Mar'09
    ;
    ;  9 words, 1 RAM variable, 14 bit core
    ;
             nop                     ; entry for (delay-11)%5 == 4     |B0
             nop                     ; entry for (delay-11)%5 == 3     |B0
             nop                     ; entry for (delay-11)%5 == 2     |B0
             nop                     ; entry for (delay-11)%5 == 1     |B0
    DelayLp addlw   -1              ; subtract 5 cycle loop time      |B0
             skpc                    ; borrow? no, skip, else          |B0
             decfsz  TMRH,F          ; done?  yes, skip, else          |B0
             goto    DelayLp         ; do another loop                 |B0
             return                  ;                                 |B0
    post edited by K8LH - 2009/03/20 01:35:48
    #5
    mxbond
    New Member
    • Total Posts : 3
    • Reward points : 0
    • Joined: 2009/03/11 17:47:44
    • Location: 0
    • Status: offline
    RE: Useful cycle-accurate delay subroutine 2009/03/12 17:44:10 (permalink)
    0
    Sweeeet!
        I hadn't thought of placing the 'nop table' before the loop for fixed delays ... very impressive!
     
    Mike Bond
     
    #6
    K8LH
    Super Member
    • Total Posts : 1887
    • Reward points : 0
    • Joined: 2004/03/26 05:12:34
    • Location: Michigan, USA
    • Status: offline
    RE: Useful cycle-accurate delay subroutine 2009/03/13 19:06:24 (permalink)
    +2 (1)
    Yeah, some interesting possibilities with those nop instructions too.  How about using some of them to increase the loop time and upper delay limit without increasing the subroutine 'overhead' and lower delay limit?

    Food for thought... Mike

    ;
    ;  DelayCy() clock equate and macro operand multipliers
    ;
             radix   dec
    clock   equ     8               ; clock frequency in Megahertz
    usecs   equ     clock/4         ; cycles/microsecond multiplier
    msecs   equ     usecs*1000      ; cycles/millisecond multiplier
    ;
    ;  5 cycle loop -> delay range 11..327690 cycles
    ;  6 cycle loop -> delay range 11..393226 cycles
    ;  7 cycle loop -> delay range 11..458762 cycles
    ;  8 cycle loop -> delay range 11..524298 cycles
    ;
    loop    equ     8               ; select 5..8 cycle loop
    ;
    ;  DelayCy() macro generates four instructions
    ;
    DelayCy macro   delay           ; minimum 11 cycles
             movlw   high((delay-11)/loop)+1
             movwf   DelayHi
             movlw   low ((delay-11)/loop)
             call    uDelay-((delay-11)%loop)
             endm
    ;
    SimTest DelayCy(1200*usecs)     ; <- simulator PC here
             nop                     ; <- simulator break point here
    ;
    ;  uDelay subroutine with adjustable 5..8 cycle loop time
    ;
    ;  12 words, 1 RAM variable, 14 bit core
    ;
             nop                     ; entry for (delay-11)%loop == 7  |B0
             nop                     ; entry for (delay-11)%loop == 6  |B0
             nop                     ; entry for (delay-11)%loop == 5  |B0
             nop                     ; entry for (delay-11)%loop == 4  |B0
             nop                     ; entry for (delay-11)%loop == 3  |B0
             nop                     ; entry for (delay-11)%loop == 2  |B0
             nop                     ; entry for (delay-11)%loop == 1  |B0
    uDelay  addlw   -1              ; subtract "loop" cycle time      |B0
             skpc                    ; borrow? no, skip, else          |B0
             decfsz  DelayHi,F       ; done?  yes, skip, else          |B0
             goto    uDelay-loop+5   ; do another loop                 |B0
             return                  ;                                 |B0
    post edited by K8LH - 2009/03/21 06:34:26
    #7
    Stefan Uhlemayr
    Super Member
    • Total Posts : 4292
    • Reward points : 0
    • Joined: 2005/05/12 12:25:46
    • Location: Germany
    • Status: offline
    RE: Useful cycle-accurate delay subroutine 2009/03/14 14:01:16 (permalink)
    0
    Very impressive work from both of you! I have the feeling, that assembler is your native language...wink

    Of course, I've added a link to this thread into the "Flying with SoftWare Favorites Gallery List".

    Greetings and thanks for sharing,Smile
    Stefan
    #8
    BitWise
    Super Member
    • Total Posts : 1238
    • Reward points : 0
    • Joined: 2004/11/09 13:24:20
    • Location: UK
    • Status: offline
    RE: Useful cycle-accurate delay subroutine 2009/03/15 02:09:16 (permalink)
    +2 (1)
    When I was writing my video generation code I needed some short delays and opted for a recursive call approach as my 18F target has a deep stack (31 levels) that I'm only using a fraction of. The code assumes a symbol 'FOSC' contains the clock speed after PLL scaling.

    The DELAY macro is defined in a header file ...

    extern Delay4
    extern Delay8
    extern Delay16
    extern Delay32
    extern Delay64

    ;===============================================================================
    ; Macros
    ;-------------------------------------------------------------------------------

    ; The DELAY macro generates a series of CALL, BRA and NOP instructions that will
    ; take USEC to execute (based on the configured oscillator). The DEDUCT argument
    ; allows a number of already used instruction cycles to be excluded from the
    ; delay.

    DELAY macro USEC,DEDUCT
    nolist
    local cycles
    cycles = (USEC * (FOSC / .1000000) / .4) - DEDUCT

    while cycles > .0
    if cycles >= .64
    list
    call Delay64
    nolist
    cycles -= .64
    else
    if cycles >= .32
    list
    call Delay32
    nolist
    cycles -= .32
    else
    if cycles >= .16
    list
    call Delay16
    nolist
    cycles -= .16
    else
    if cycles >= .8
    list
    call Delay8
    nolist
    cycles -= .8
    else
    if cycles >= .4
    list
    call Delay4
    nolist
    cycles -= .4
    else
    if cycles >= .2
    list
    bra $+.2
    nolist
    cycles -= .2
    else
    list
    nop
    nolist
    cycles -= .1
    endif
    endif
    endif
    endif
    endif
    endif
    endw

    list
    endm

    ... and a code module defines the recursive calls used to consume the cycles.

    global Delay4
    global Delay8
    global Delay16
    global Delay32
    global Delay64

    ;===============================================================================
    ; Delay Routines
    ;-------------------------------------------------------------------------------

    code

    ; A nested set of subroutine calls are used to generate delays in the smallest
    ; amount of code space.

    Delay64: rcall Delay32
    Delay32: rcall Delay16
    Delay16: rcall Delay8
    Delay8: rcall Delay4
    Delay4: return

    You could add more levels of call to lengthen the delay and generate less code.

    For a simple delay the DEDUCT argument would be 0. I use it when I need take some additional instructions into account during video pulse generation. For example in the following code its used to take into account the cycles used in the preceding instructions.

    PALScanLine0:
    bcf SYNC_LATCH,SYNC_BIT ; Generate 4uS sync pulse
    movff FSR0L,HI_FSR0L
    movff FSR0H,HI_FSR0H
    movff FSR1L,HI_FSR1L
    movff FSR1H,HI_FSR1H
    movff FSR2L,HI_FSR2L
    movff FSR2H,HI_FSR2H
    DELAY .4,.13
    bsf SYNC_LATCH,SYNC_BIT
    movff ROW_PTR+.0,FSR1L ; Reload start of row pointer
    movff ROW_PTR+.1,FSR1H
    movff ATR_PTR+.0,FSR0L
    movff ATR_PTR+.1,FSR0H
    movlw high (SHAPES0) ; Point FSR2 at shape page
    movwf FSR2H
    DELAY .12,.23 ; Back Porch
    rcall DrawLine
    movff HI_FSR0L,FSR0L
    movff HI_FSR0H,FSR0H
    movff HI_FSR1L,FSR1L
    movff HI_FSR1H,FSR1H
    movff HI_FSR2L,FSR2L
    movff HI_FSR2H,FSR2H
    bcf PIR1,TMR2IF ; Clear interrupt and return
    retfie FAST

    This approach could be used with care on the mid-range processors but the shallower stack (7 levels) means you could accidentally generate a stack wrap around if you generate a delay in a nested subroutine.
    post edited by BitWise - 2009/03/15 02:10:16

    Throughout your life advance daily, becoming more skillful than yesterday, more skillful than today. This is never-ending.

    Yamamoto Tsunetomo (1659-1719)
    #9
    K8LH
    Super Member
    • Total Posts : 1887
    • Reward points : 0
    • Joined: 2004/03/26 05:12:34
    • Location: Michigan, USA
    • Status: offline
    RE: Useful cycle-accurate delay subroutine 2009/03/15 05:53:11 (permalink)
    0
    Very nice Andrew (BitWise).  It supports multiple clocks, allows subtracting instruction cycles for isochronous timing, and doesn't corrupt WREG and STATUS registers.

    If corrupting WREG and STATUS isn't an issue then another approach might be to use a simple in-line delay which doesn't use any subroutines (and stack levels).  The 1..770 Tcy range of the example below would have an upper delay limit of 77 usecs with Fosc == 40 MHz;

    Kind regards, Mike

    ;******************************************************************
    ;                                                                 *
    ;  inDlyCy(), 1..770 Tcy, in-line     Mike McLaren, K8LH, Jun'07  *
    ;                                                                 *
    ;  requires the use of constant operands known at assembly time!  *
    ;                                                                 *
    ;  inDlyCy() macro produces 1, 3, or 4 instructions, 16 bit core  *
    ;                                                    -----------  *
             radix   dec
    clock   equ     20              ; clock, 4, 8, 12, 16, 20, 32, 40
    usecs   equ     clock/4         ; cycles/microsecond multiplier

    inDlyCy macro   delay           ; parameter range 1..770
             local   loop
          if delay > 2
             movlw   delay/3-1
    loop    addlw   -1              ; subtract 3 cycle loop time
             bc      loop            ; borrow? no, branch, else
          endif
          if delay%3 == 2
             bra     $+2             ; 2 cycle delay
          endif
          if delay%3 == 1
             nop                     ; 1 cycle delay
          endif
             endm
    ;                                                                 *
    ;  code for simulation testing;                                   *
    ;                                                                 *
    SimTest
             inDlyCy(4*usecs-13)     ; delay 4 usecs minus 13 cycles
             nop                     ; put simulator breakpoint here
    post edited by K8LH - 2009/03/21 08:10:35
    #10
    1and0
    Access is Denied
    • Total Posts : 12099
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    RE: Useful cycle-accurate delay subroutine 2009/03/15 10:09:39 (permalink)
    +2 (1)
    Very nice, guys!  I am saving these macros into my collection.  Modifying Mike's inDlyCy as below reduces 1 or 2 instruction words for delay = 3, 4 and 5.

    inDlyCy macro   delay           ; parameter range 1..770
          if delay < 8
      
          if delay & 4
             bra     $+2             ; 4 cycle delay
             bra     $+2
          endif
          if delay & 2
             bra     $+2             ; 2 cycle delay
          endif
          if delay & 1
             nop                     ; 1 cycle delay
          endif
       
          else
      
             local   loop
          if delay > 2
             movlw   delay/3-1
    loop    addlw   -1              ; subtract 3 cycle loop time
             bc      loop            ; borrow? no, branch, else
          endif
          if delay%3 == 2
             bra     $+2             ; 2 cycle delay
          endif
          if delay%3 == 1
             nop                     ; 1 cycle delay
          endif
      
          endif
             endm
    #11
    k_kilowatt
    New Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2005/04/27 22:57:08
    • Status: offline
    RE: Useful cycle-accurate delay subroutine 2009/03/24 13:08:06 (permalink)
    0

    Bond ... *Mike* Bond's cycle-accurate delay subroutine is clever for accurate
    short delays with 1usec resolution (4MHz oscillator) when the PIC doesn't
    need to do anything but wait for the passage of some time.
     
    http://www.microchip.com/forums/tm.aspx?m=135820 presents a set of
    subroutines for longer accurate delays, up to 256 minutes with 10usec
    resolution. These subroutines also are for applications where the PIC
    doesn't need to do anything but wait.
     
    Kurt Christner P.E.
    #12
    K8LH
    Super Member
    • Total Posts : 1887
    • Reward points : 0
    • Joined: 2004/03/26 05:12:34
    • Location: Michigan, USA
    • Status: offline
    RE: Useful cycle-accurate delay subroutine 2009/03/28 06:16:05 (permalink)
    0
    Hi guys,

    After checking out the 4 MHz delay subroutines from Kurt's link (previous post) I thought I'd try a 256 minute timer using my fixed delay subsystem just for fun.  Total memory usage including the 12 word DelayCy timing subroutine is a nice respectable 32 words when using a 4 MHz clock climbing to 64 words when using a 20 MHz clock.

    ;******************************************************************
    ;
    ;  appliance timer (isochronous loop) demo requires presetting
    ;  the "minutes" and "seconds" variables with values in the range
    ;  of 0 minutes 1 second to 255 minutes 59 seconds.
    ;
             radix   dec
    timer
             bsf     relaypin        ; turn relay on                   |B0
    sloop   DelayCy(1000*msecs-11)  ; 1 sec minus 11 cycle loop time  |B0
             movlw   59              ; just in case                    |B0
             decf    seconds,F       ; decrement seconds               |B0
             btfsc   seconds,7       ; negative? no, skip, else        |B0
             decf    minutes,F       ; decrement minutes               |B0
             btfsc   seconds,7       ; negative? no, skip, else        |B0
             movwf   seconds         ; update seconds                  |B0
             movf    seconds,W       ;                                 |B0
             iorwf   minutes,W       ; is it timed out?                |B0
             skpz                    ; yes, skip, else                 |B0
             goto    sloop           ; loop again                      |B0
             bcf     relaypin        ; turn relay off                  |B0

    Need more then 256 minutes?  Add five instructions and an "hours" variable for a 256 hour timer.  Memory usage is 37 words with a 4 MHz clock climbing to 69 words with a 20 MHz clock.

    ;******************************************************************
    ;
    ;  appliance timer (isochronous loop) demo requires presetting
    ;  the "hours", "minutes" and "seconds" variables to values in
    ;  the range of 00:00:01 to 23:59:59 or perhaps to 255:59:59
    ;
             radix   dec
    timer
             bsf     relaypin        ; turn relay on                   |B0
    sloop   DelayCy(1000*msecs-16)  ; 1 sec minus 16 cycle loop time  |B0
             movlw   59              ; W = 59 (mins/secs reset value)  |B0
             decf    seconds,F       ; decrement seconds               |B0
             btfsc   seconds,7       ; negative? no, skip, else        |B0
             decf    minutes,F       ; decrement minutes               |B0
             btfsc   seconds,7       ; negative? no, skip, else        |B0
             movwf   seconds         ; reset seconds = 59              |B0
             btfsc   minutes,7       ; negative? no, skip, else        |B0
             decf    hours,F         ; decrement hours                 |B0
             btfsc   minutes,7       ; negative? no, skip, else        |B0
             movwf   minutes         ; reset minutes = 59              |B0
             movf    seconds,W       ;                                 |B0
             iorwf   minutes,W       ;                                 |B0
             iorwf   hours,W         ; timer timed-out?                |B0
             skpz                    ; yes, skip, else                 |B0
             goto    sloop           ; loop again                      |B0
             bcf     relaypin        ; turn relay off                  |B0

    I modified my DelayCy() subsystem macro to provide the 1 second delay required in the programs above.  Basically the macro makes multiple calls (each using 4 words) to the timing subroutine as needed to produce larger delays.  Caveat!  This can eat up a lot of memory.  For example, the DelayCy macro will make 10 calls and generate 40 instructions for a 1 second delay when using a 20 MHz clock.

    ;******************************************************************
    ;
    ;  DelayCy() clock equate and macro operand multipliers
    ;
             radix   dec
    clock   equ     4               ; clock frequency in Megahertz
    usecs   equ     clock/4         ; cycles/microsecond multiplier
    msecs   equ     usecs*1000      ; cycles/millisecond multiplier
    ;
    ;  5 cycle loop delay range 11..327690 cycles
    ;  6 cycle loop delay range 11..393226 cycles
    ;  7 cycle loop delay range 11..458762 cycles
    ;  8 cycle loop delay range 11..524298 cycles
    ;
    loop    equ     8               ; select 5..8 cycle loop
    ;
    ;  DelayCy() macro generates four instructions plus an additional
    ;  four instructions for each loop*65536 cycles in the delay
    ;
    DelayCy macro   delay           ; minimum 11 cycles
             local   cycles
             cycles = delay
       while cycles > (loop*65536+10)
             movlw   high((loop*65536-11)/loop)+1
             movwf   DelayHi
             movlw   low ((loop*65536-11)/loop)
             call    uDelay-((65536-11)%loop)
             cycles -= (loop*65536)
    endw
             movlw   high((cycles-11)/loop)+1
             movwf   DelayHi
             movlw   low ((cycles-11)/loop)
             call    uDelay-((cycles-11)%loop)
             endm
    ;
    ;  example code for simulation testing.
    ;
    SimTest DelayCy(1000*msecs)     ; <- put simulator PC here
            nop                     ; <- put simulator break point here
    ;
    ;  16 bit uDelay subroutine with adjustable 5..8 cycle loop time
    ;
    ;  12 words, 1 RAM variable, 14 bit core   ---  Mike, K8LH
    ;
             nop                     ; entry for (delay-11)%loop == 7  |B0
             nop                     ; entry for (delay-11)%loop == 6  |B0
             nop                     ; entry for (delay-11)%loop == 5  |B0
             nop                     ; entry for (delay-11)%loop == 4  |B0
             nop                     ; entry for (delay-11)%loop == 3  |B0
             nop                     ; entry for (delay-11)%loop == 2  |B0
             nop                     ; entry for (delay-11)%loop == 1  |B0
    uDelay  addlw   -1              ; subtract "loop" cycle time      |B0
             skpc                    ; borrow? no, skip, else          |B0
             decfsz  DelayHi,F       ; done?  yes, skip, else          |B0
             goto    uDelay+5-loop   ; do another loop                 |B0
             return                  ;                                 |B0
    post edited by K8LH - 2009/04/03 03:40:37
    #13
    Jump to:
    © 2021 APG vNext Commercial Version 4.5