; macro_wait.inc ; 25.11.2021 ; Idee: https://www.mikrocontroller.net/articles/AVR_Assembler_Makros ; Verzogerung um X Nanosekunden von Klaus2m5 #ifndef _MACRO_WAIT_ #define _MACRO_WAIT_ .include "macro_defs.inc" ;=== hier F_CPU eingeben ====================================================== ;.set Osc_Hz = 7372800 ;7,3728 MHz (Baudrate xtal) ;.set Osc_Hz = 8000000 ;8,0000 MHz .set Osc_Hz = 16000000 ;16,0000 MHz ;==================================================================v ;=== Funktionen mit gesicherten Register und SREG ============================= ;============================================================================== ; wait_ns @0 Verzogerungszeit in Nanosekunden ; @1 bereits verbrauchte Takte, 2-50b ; ; wait_us @0 Verzogerungszeit in Mikrosekunden, 2-50b ; ; wait_ms @0 Verzogerungszeit in Millisekunden, 2-50b ; ;============================================================================== ;=== Funktionen, die templ, temph, temp1_l, temp1_h benutzen ================== ;============================================================================== ; delay_ns @0 Verzogerungszeit in Nanosekunden ; @1 bereits verbrauchte Takte, 2-24b ; ; delay_us @0 Verzogerungszeit in Mikrosekunden, 2-24b ; ; delay_ms @0 Verzogerungszeit in Millisekunden, 2-24b ; ;============================================================================== ;=== Funktionen mit variabler Verzoegerung ==================================== ;============================================================================== ; delayloop1 temp = cycle*3 Verzoegerung, 6b ; ; delayloop2 templ,temph = cycle*4+1 Verzoegerung, 10b ; ; delayloop3 templ,temph,temp1_l = cycle*5+2 Verzoegerung, 14b ; ; delayloop4 templ,temph,temp1_l,temp1_h = cycle*6+3 Verzoegerung, 18b ; ;============================================================================== ;============================================================================== .set cycle_time_ns = (2000000000 / Osc_Hz) ;clock Laenge ;============================================================================== ;=== Sehr genaue Verzoegerungen =============================================== ;============================================================================== .macro wait_ns ; @0 Verzogerungszeit in Nanosekunden ; @1 bereits verbrauchte Takte, 2-50b .set cycles = (((@0 + cycle_time_ns - 1) / cycle_time_ns - @1)*2) wait_wait cycles .endm .macro wait_us ; @0 Verzogerungszeit in Mikrosekunden, 2-50b .set cycles = ((((@0 * 1000) + cycle_time_ns - 1) / cycle_time_ns)*2) wait_wait cycles .endm .macro wait_ms ; @0 Verzogerungszeit in Millisekunden, 2-50b .set cycles = ((((@0 * 1000000) + cycle_time_ns - 1) / cycle_time_ns)*2) wait_wait cycles .endm ; Uebergang zu waitloop4: ; F_CPU = 20 MHz: 4194305400 ns, 4194305 us, 4194 ms x ; F_CPU = 18,432 MHz: 4529849832 ns, 4529849 us, 4529 ms x ; F_CPU = 16,384 MHz: 5117052588 ns, 5117052 us, 5117 ms x ; F_CPU = 16 MHz: 5242881750 ns, 5242881 us, 5242 ms x 134217 ms ; F_CPU = 14,7456 MHz: 5662312290 ns, 5662312 us, 5662 ms x ; F_CPU = 12,288 MHz: 6794774748 ns, 6794774 us, 6794 ms x ; F_CPU = 12 MHz: 6962546964 ns, 6962546 us, 6962 ms x ; F_CPU = 11,0592 MHz: 7549749720 ns, 7549749 us, 7549 ms x ; F_CPU = 10,24 MHz: 8178895530 ns, 8178895 us, 8178 ms x ; F_CPU = 10 MHz: 8388610800 ns, 8388610 us, 8388 ms x ; F_CPU = 9,216 MHz: 9101642718 ns, 9101642 us, 9101 ms x ; F_CPU = 8,192 MHz: 10234105176 ns, 10234105 us, 10234 ms x ; F_CPU = 8 MHz: 10485763500 ns, 10485763 us, 10485 ms x 268435 ms ; F_CPU = 7,3728 MHz: 11366567634 ns, 11366567 us, 11366 ms x ; F_CPU = 4,096 MHz: 20468210352 ns, 20468210 us, 20468 ms x ; F_CPU = 4 MHz: 20971527000 ns, 20971527 us, 20971 ms x ; F_CPU = 3,6864 MHz: 22733135268 ns, 22733135 us, 22733 ms x ; F_CPU = 3,2768 MHz: 25585262940 ns, 25585262 us, 25585 ms x ; F_CPU = 2 MHz: 41943054000 ns, 41943054 us, 41943 ms x ; F_CPU = 1,8432 MHz: 45508213590 ns, 45508213 us, 45508 ms x ; F_CPU = 1,024 MHz: 81914784462 ns, 81914784 us, 81914 ms x ; F_CPU = 1 MHz: 83886108000 ns, 83886108 us, 83886 ms x ;=== Hauptschleife ============================================================ .macro wait_wait ; @0 wait_cycles, max. 83886109 cycles 2-50b .set wait_cycles = @0 .if (wait_cycles > 83886109) .set loop_cycles = (((wait_cycles - 25) / 6) - 1) waitloop4 loop_cycles .set wait_cycles = (wait_cycles - (((loop_cycles + 1) * 6)+19)) .elif (wait_cycles > (65536 * 4 + 18)) .set loop_cycles = (((wait_cycles - 20) / 5) - 1) waitloop3 loop_cycles .set wait_cycles = (wait_cycles - (((loop_cycles + 1) * 5)+15)) .elif (wait_cycles > (255 * 3 + 2)) .set loop_cycles = (((wait_cycles - 15) / 4) - 1) waitloop2 loop_cycles .set wait_cycles = (wait_cycles - (((loop_cycles + 1) * 4)+11)) .elif (wait_cycles > 12) .set loop_cycles = ((wait_cycles - 10) / 3) waitloop1 loop_cycles .set wait_cycles = (wait_cycles - ((loop_cycles * 3) + 10)) .endif .if (wait_cycles > 0) waitloop0 wait_cycles .endif .endm .macro waitloop0 ; @0 cycle, 0-15c, 0-16b .if (@0 & 8) rjmp pc+1 rjmp pc+1 rjmp pc+1 rjmp pc+1 .endif .if (@0 & 4) rjmp pc+1 rjmp pc+1 .endif .if (@0 & 2) rjmp pc+1 .endif .if (@0 & 1) nop .endif .endm .macro waitloop1 ; @0 cycle, 13-778 c 18b push r16 ; @*3+10 c in r16, sreg push r16 ldi r16, @0 dec r16 brne PC-1 pop r16 out sreg, r16 pop r16 .endm .macro waitloop2 ; @0 cycle, push r16 ; @0*4+15 c 26b in r16, sreg push r16 push r17 ldi r16, low(@0) ldi r17, high(@0) subi r16, 1 sbci r17, 0 brne PC-2 pop r17 pop r16 out sreg, r16 pop r16 .endm .macro waitloop3 ; @0 cycle, push r16 ; @0*5+20 c 34b in r16, sreg push r16 push r17 push r18 ldi r16, low(@0) ldi r17, high(@0) ldi r18, byte3(@0) subi r16, 1 sbci r17, 0 sbci r18, 0 brne PC-3 pop r18 pop r17 pop r16 out sreg, r16 pop r16 .endm .macro waitloop4 ; @0 cycle, push r16 ; @0*6+25 c 42b in r16, sreg push r16 push r17 push r18 push r19 ldi r16, low(@0) ldi r17, high(@0) ldi r18, byte3(@0) ldi r19, byte4(@0) subi r16, 1 sbci r17, 0 sbci r18, 0 sbci r19, 0 brne PC-4 pop r19 pop r18 pop r17 pop r16 out sreg, r16 pop r16 .endm ;============================================================================== ;=== Verzoegerungen ohne push-Reg ============================================= ;============================================================================== .macro delay_ns ; @0 Verzogerungszeit in Nanosekunden ; @1 bereits verbrauchte Takte, 2-24b .set cycles = (((@0 + cycle_time_ns - 1) / cycle_time_ns - @1)*2) delay_delay cycles .endm .macro delay_us ; @0 Verzogerungszeit in Mikrosekunden, 2-24b .set cycles = ((((@0 * 1000) + cycle_time_ns - 1) / cycle_time_ns)*2) delay_delay cycles .endm .macro delay_ms ; @0 Verzogerungszeit in Millisekunden, 2-24b .set cycles = ((((@0 * 1000000) + cycle_time_ns - 1) / cycle_time_ns)*2) delay_delay cycles .endm ;=== Hauptschleife ============================================================ .macro delay_delay ; @0 wait_cycles, max. 83886109 cycles, 2-24b .set wait_cycles = @0 .if (wait_cycles > 83886086) .set loop_cycles = ((wait_cycles - 3) / 6) delayloop4 loop_cycles .set wait_cycles = (wait_cycles - ((loop_cycles * 6)+3)) .elif (wait_cycles > (65536 * 4 + 3)) .set loop_cycles = ((wait_cycles - 2) / 5) delayloop3 loop_cycles .set wait_cycles = (wait_cycles - ((loop_cycles * 5)+2)) .elif (wait_cycles > (255 * 3 + 2)) .set loop_cycles = ((wait_cycles - 1) / 4) delayloop2 loop_cycles .set wait_cycles = (wait_cycles - ((loop_cycles * 4)+1)) .elif (wait_cycles > 5) .set loop_cycles = (wait_cycles / 3) delayloop1 loop_cycles .set wait_cycles = (wait_cycles - (loop_cycles * 3)) .endif .if (wait_cycles > 0) delayloop0 wait_cycles .endif .endm .macro delayloop0 ; @0 cycle, 0-15c, 0-16b .if (@0 & 8) rjmp pc+1 rjmp pc+1 rjmp pc+1 rjmp pc+1 .endif .if (@0 & 4) rjmp pc+1 rjmp pc+1 .endif .if (@0 & 2) rjmp pc+1 .endif .if (@0 & 1) nop .endif .endm .macro delayloop1 ; @0 cycle, 3-768 c 6b ; @*3 c ldi temp, @0 dec temp brne PC-1 .endm .macro delayloop2 ; @0 cycle, ; @0*4+1 c 10b ldi templ, low(@0) ldi temph, high(@0) subi templ, 1 sbci temph, 0 brne PC-2 .endm .macro delayloop3 ; @0 cycle, ; @0*5+2 c 14b ldi temp0, low(@0) ldi temp1, high(@0) ldi temp2, byte3(@0) subi temp0, 1 sbci temp1, 0 sbci temp2, 0 brne PC-3 .endm .macro delayloop4 ; @0 cycle, ; @0*6+3 c 18b ldi temp0, low(@0) ldi temp1, high(@0) ldi temp2, byte3(@0) ldi temp3, byte4(@0) subi temp0, 1 sbci temp1, 0 sbci temp2, 0 sbci temp3, 0 brne PC-4 .endm #endif /* _MACRO_WAIT_*/