I also wrote this god-awful macro for the Parallax SX key assembler that may be of use to someone: It produces the smallest possible (I think) and/or tightest loop delays inline when you call it with the value and units of time you wish to delay for; calculating the number of cycles based on the processor speed. The CpuMhz equate must be adjusted to what ever is right for your chip. It should probably be called CpuMips vice CpuMhz. The only redeeming virtue is that it does not use anything other than w (on the SX you can decrement W); no stack use, no register use. I'd love to see a translation into an MPLAB macro (using a file register I guess): device pins28, pages1, banks8, turbo, stackx, optionx, carryx reset reset_entry CpuMhz = 50 temp ds 1 usec EQU -6 msec EQU -3 sec EQU 1 cycles EQU 0 mynop MACRO noexpand page $>>8 ENDM cyclefor MACRO 1 _cycles = \1 IF _cycles > 0 _temp = $//4 IF _temp = 2 IF _cycles < 5 REPT _cycles expand mynop noexpand ENDR _cycles = 0 ELSE expand mynop noexpand _cycles = _cycles -1 ENDIF ENDIF IF _temp = 1 IF _cycles < 6 REPT _cycles expand mynop noexpand ENDR _cycles = 0 ELSE expand mynop mynop noexpand _cycles = _cycles -2 ENDIF ENDIF IF _cycles > 3 expand mov w, #_cycles / 3 decsz 1 ;dec w clrb 2.1 ;modify PC to jump back noexpand _cycles = _cycles // 3 ;cycles left over ENDIF IF _cycles > 0 REPT _cycles expand mynop noexpand ENDR ENDIF ENDIF ENDM reset_entry mov w,#$7F mov !OPTION,w delayhelp MACRO ERROR 'USAGE: delay value, [usec,msec,sec,cycles]' ENDM delay MACRO 2 noexpand IF (\2=usec OR \2=msec OR \2=sec) AND (\1<1000 AND \1>0) IF \2=sec _cycles = (\1 * 1000000 / (1000/CpuMhz)) ENDIF IF \2=msec _cycles = (\1 * 1000 / (1000/CpuMhz)) ENDIF IF \2=usec _cycles = (\1 / (1000/CpuMhz)) ENDIF IF \2=cycles _cycles = \2 ENDIF IF _cycles = 0 expand ;delay less than one cycle at this processor speed' noexpand ELSE IF _cycles > 255 REPT (_cycles / 256) cyclefor 256 _cycles = _cycles - 256 ENDR ENDIF cyclefor _cycles ENDIF ELSE delayhelp ENDIF ENDM delay 999, usec delay 200, usec delay 250, usec delay 10, usec delay 20, usec delay 100, msec James Newton mailto:jamesnewton@geocities.com phone:1-619-652-0593 http://techref.homepage.com NOW OPEN (R/O) TO NON-MEMBERS! Members can add private/public comments/pages ($0 TANSTAAFL web hosting) PIC/PICList FAQ: http://www.piclist.com -----Original Message----- From: pic microcontroller discussion list [mailto:PICLIST@MITVMA.MIT.EDU]On Behalf Of Morgan Olsson Sent: Tuesday, November 23, 1999 3:23 PM To: PICLIST@MITVMA.MIT.EDU Subject: 1cyc resolution variable delay idea :2 A try to minimize the overhead in a byte controlled 1cyc resolution delay routine I4ve seen a similar solution to this presented on this list before... don4t know exactly. (Untested) This delay routine has a 1 cycle resolution variable controlled delay. Input value in counter, range 4-255 (0=256, 1=257, 2=258, 3=259) cycles. Technique: let the 2 lsb control wasting of cycles using bittest, skip and goto, at the same time as counter is divided by four, then controls number of 4cyc loops. DELAY BCF S,C ; New MSB=0! RRF COUNTER,1 ; Bit 0 to carry, shall control 1 cyc difference BTFSC S,C ; if set, GOTO $+1 ; waste 2 cyc using GOTO next instr, else 1 cycle skipping. BCF S,C ; New MSB=0! RRF COUNTER,1 ; Bit 1 to carry shall control 2 cyc difference BTFSS S,C ; if set: use double goto (4cyc); else skip+nop (2cyc) GOTO DELAY2 ; (cycles until DECFSZ instr) ; For the remainding bits use this 4*n cycle delay loop: DELAYL NOP ;NOP or other 1cyc instr. This will be executed at least once. DELAY3 DECFSZ COUNTER GOTO DELAYL RETURN DELAY2 GOTO DELAY3 Minimum time: call with counter = 4 Cycles: Task: 2 call this 11 1cyc instr/skips 2 return == 15 total minimum ( @ counter = 4 ) /Morgan