Full Version : Delays Macros (ASM)
avr >>ASSMBLER ROUTINES >>Delays Macros (ASM)


AVR_Admin- 04-16-2006
_Delays.

INCLUDE "_Delays.asm" enables you to use the following macro in your code

_Waiste_us n (with n = 1 to 25.769.803.779)

This macro will generate a wait loop from 1 µs to 25.769.803.779 µs.

_Waiste_us is actually limited to minimum (1.000.000/F_CPU) us because we can not loop for less then 1 instruction cycle. If you request a delay below this limit _Waiste_us will insert no instruction in your code.

_Waiste_us is absolutely exact down to (1/Your_CPU_frequency_in_MHz) µs

_Waiste_us will pick the smallest code for your delay (1 to 13 words).
Well that is not 100% true. It will pick the shortest usable loop 8-,16-,24- or 32-bit and add a 2nd 8-bit loop and maybe 2 NOP's to match exactly the delay you requested. In some cases that results in code that is 1 word longer than the minimum code that would have generated the requested delay. (Fixing that would make the macro really complex and I decided the benefit was not worth the effort)

A-men

;******************************************************************************
;_Delays.asm Version 0.0a
;******************************************************************************
;
;Written for : Atmel "AVR Assembler" and "AVR Assembler 2"
; when : 2005 November 20
; where: BRUSSELS - BELGIUM - EUROPE
; who : Jan Huygh
; E-mail: jan.huygh@skynet.be

;******************************************************************************
;A WORD FROM THE AUTHOR :
;
;I would find it motivating to find out that people use this code.
;
;On regular base (every 10 to 12 weeks) I gather the comments on the code I
;posted and use the comments to improve my code. If you have constructive
;comment then let me know.
; * Give me an evaluation.
; * Send me a mail (jan.huygh@skynet.be) subject "I use your _Delays.asm".
; * Send me a mail (jan.huygh@skynet.be) subject "Comment on your _Delays.asm"

;******************************************************************************
;ABOUT VERSION 0.0a
;
;This is the first posted version.
;
; KNOWN BUGS :
; * None so far
; OPPORTUNITIES FOR IMPROVEMENT :
; * a version that can be used as a subroutine taking in to acount the time
; for the call and for the return.
; * a version that takes the input from the stack so it can take a variable
; for the input.
; * a version that is less precise but takes less bytes of program memory
;

;******************************************************************************
;.INCLUDE "_Delays.asm" enables you to use the following macro in your code
;
; _Waiste_us n
; With (1.000.000/F_CPU) <= n <= 25769803779/Your_CPU_frequency_in_MHz
;
; This macro will generate a wait loop from 1 µs to 25.769.803.779 µs
; Depending on the CPU-speed set in F_CPU here below you will need to
; respect a minimum value for n. (n_minimum) = 1.000.000/F_CPU).
; This is needed because we can not loop for less then 1
; instruction cycle.
; 25.769.803.779 µs, that's over 3h30 when you use a CPU running at 20 MHz.
; _Waiste_us is absolutely exact down to (1/Your_CPU_frequency_in_MHz) µs
; _Waiste_us will pick the smallest code for your delay (Maximum 13 words)

;******************************************************************************
;How to use this in your code :
;
; A) Pick the correct ".equ F_CPU = x" statement
; AND
; save this file to your disk
;
; B) Make sure it is in the same folder as the other files of your current project
; OR
; Make sure the folder where you saved this file is referenced in the
; assembler options (Project=>Assembler Options=>Additional include path)
;
; C) Include the statement .INCLUDE "_Delays.asm" at the top of your program
;
; D) Use the statement _Waiste_us n, in your code
;
;Here is a code example :
;
; .INCLUDE "_Waiste.asm" ;Make the macro _Waiste_us n available in your code
; _Waiste_us 100 ;loop for 100 µs (that's 0,1 ms)
; _Waiste_us 16000 ;loop for 16.000 µs (that's 16 ms)
; _Waiste_us 7000000 ;loop for 7.000.000 µs (that's 7 s )
;

;******************************************************************************
;The CPU-speed needs to be set before you can use _Waiste_us.
;Find your CPU-speed in the list here below and uncomment it (remove the ";")
;then press Ctrl^S to save to disk otherwise the include file used by AVR studio
;will be the unchanged version on your disk.
;
;
; .equ F_CPU = 1000000 ;Hz
; .equ F_CPU = 2000000 ;Hz
.equ F_CPU = 3579545 ;Hz
; .equ F_CPU = 3686400 ;Hz
; .equ F_CPU = 4000000 ;Hz
; .equ F_CPU = 4032000 ;Hz
; .equ F_CPU = 4096000 ;Hz
; .equ F_CPU = 4194304 ;Hz
; .equ F_CPU = 4433619 ;Hz
; .equ F_CPU = 4915200 ;Hz
; .equ F_CPU = 5000000 ;Hz
; .equ F_CPU = 5068800 ;Hz
; .equ F_CPU = 5990400 ;Hz
; .equ F_CPU = 6000000 ;Hz
; .equ F_CPU = 6144000 ;Hz
; .equ F_CPU = 6500000 ;Hz
; .equ F_CPU = 7372800 ;Hz
; .equ F_CPU = 7680000 ;Hz
; .equ F_CPU = 8000000 ;Hz
; .equ F_CPU = 9000000 ;Hz
; .equ F_CPU = 9216000 ;Hz
; .equ F_CPU = 9830400 ;Hz
; .equ F_CPU = 10000000 ;Hz
; .equ F_CPU = 10240000 ;Hz
; .equ F_CPU = 11000000 ;Hz
; .equ F_CPU = 11059200 ;Hz
; .equ F_CPU = 11520000 ;Hz
; .equ F_CPU = 12000000 ;Hz
; .equ F_CPU = 12000393 ;Hz
; .equ F_CPU = 12288000 ;Hz
; .equ F_CPU = 13500000 ;Hz
; .equ F_CPU = 14318180 ;Hz
; .equ F_CPU = 14745600 ;Hz
; .equ F_CPU = 15000000 ;Hz
; .equ F_CPU = 15360000 ;Hz
; .equ F_CPU = 16000000 ;Hz
; .equ F_CPU = 16000312 ;Hz
; .equ F_CPU = 16257000 ;Hz
; .equ F_CPU = 16384000 ;Hz
; .equ F_CPU = 17734475 ;Hz
; .equ F_CPU = 18000000 ;Hz
; .equ F_CPU = 18432000 ;Hz
; .equ F_CPU = 19660800 ;Hz
; .equ F_CPU = 20000000 ;Hz


.Macro _Waiste_us ;n
; Calculate the number of CPU-cycles needed to generate the requested delay
; taking in to account the frequency you are using for your CPU.
; You can simplify the next 9 lines of code before "_Cycle_Waister Cycles_Needed"
; to "Cycles_Needed = @0 * F_CPU / 1000000". If you do so _Waist_us will
; generate the exact delay you requested or the delay obtained by executing the
; number of cpu-cycles that brings just less then the delay you requested.
; This might be a good option if you need a certain delay but need to be sure
; you never have a delay that is even a fraction of a CPU-cycle longer than the
; delay you requested.
; The 9 lines of code here below do NOT use any space in the actual program
; memory of your AVR.
; The code here below will actually pick the number of CPU-cycles needed to
; generate EXACTLY the delay you requested and when that can not be achieved
; it will select the number of cycles that generate the delay that is the best
; approximation for the delay you requested even if that is just above the
; delay you requested.
.set Fraction = @0*F_CPU/1000000 ;
.set Fraction = Fraction * 100
.set Fraction = @0*F_CPU/10000 - Fraction
.if Fraction >= 50
.equ Cycles_Needed = (@0 * F_CPU /1000000)+1
.endif
.if Fraction < 50
.equ Cycles_Needed = (@0 * F_CPU /1000000)
.endif
_Cycle_Waister Cycles_Needed
.endmacro

.macro _Cycle_Waister
.If @0 == 1
nop
.EndIf
.If @0 == 2
nop
nop
.EndIf
.If ((@0 > 2) && (@0 < 769))
;C=3n
;769=(3 * (2^8)) + 1
.set Loops_Needed = @0/3
ldi R16,Low(Loops_Needed)
Loop:
dec R16
brne Loop
.set Cycles_Left_To_Do = @0 - (3*Loops_Needed)
_Cycle_Waister Cycles_Left_To_Do
.EndIf
.If (@0 > 768) && (@0 < 262146)
;C=1+4n
;262146 = 1 + (4 * 2^16) + 1
.set Loops_Needed = (@0 - 1)/4
ldi ZL,Low(Loops_Needed)
ldi ZH,High(Loops_Needed)
Loop:
sbiw ZL,1
brne Loop
.set Cycles_Left_To_Do = (@0 - (4*Loops_Needed))-1
_Cycle_Waister Cycles_Left_To_Do
.EndIf
.If (@0 > 262145) && (@0 < 83886083)
;C=2+5n
;83.886.083 = 2 + (5 * 2^24) +1
.set Loops_Needed = (@0 - 2)/5
ldi R16,Low(Loops_Needed)
ldi ZL,Byte2(Loops_Needed)
ldi ZH,Byte3(Loops_Needed)
Loop:
subi R16,1
sbci ZL,0
sbci ZH,0
brne Loop
.set Cycles_Left_To_Do = (@0 - (5*Loops_Needed))-2
_Cycle_Waister Cycles_Left_To_Do
.EndIf
.If (@0 > 83886082) && (@0 < 25769803780)
;C=3+6n
;25769803780 = 3 + (6 * 2^32) +1
.set Loops_Needed = (@0 - 3)6
ldi XL,Low(Loops_Needed)
ldi XH,Byte2(Loops_Needed)
ldi ZL,Byte3(Loops_Needed)
ldi ZH,Byte4(Loops_Needed)
Loop:
sbiw Xl
sbci ZL,0
sbci ZH,0
brne Loop
.set Cycles_Left_To_Do = (@0 - (6*Loops_Needed)) - 3
_Cycle_Waister Cycles_Left_To_Do
.endif
.endmacro




Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.