; ***************************************************************************
; copyright   : (C) 2023 by Martin Preuss
; email       : martin@libchipcard.de
;
; ***************************************************************************
; * This file is part of the project "AqHome".                              *
; * Please see toplevel file COPYING of that project for license details.   *
; ***************************************************************************





; ***************************************************************************
; macros



; ---------------------------------------------------------------------------
; Utils_WaitNanoSecs  waittime_in_ns , cyles_already_used , waitcount_register 
;
; Please note: times smaller than 5000 are unreliable on 1MHZ AtTiny84 (takes much longer
; than requested, probably due to the fact that one cpu instrction already takes 1us to 2us).
;
;     cycles already used will be subtracted from the delay
;     the waittime resolution is 1 cycle (delay from exact to +1 cycle)
;     the maximum delay at 20MHz (50ns/clock) is 38350ns
;     waitcount register must specify an immediate register
; taken from https://www.mikrocontroller.net/articles/AVR_Assembler_Makros#Verz%C3%B6gerung_um_X_Nanosekunden
;
.set     Osc_Hz         = clock                    ; 1 MHz
.set     cycle_time_ns  = (1000000000 / Osc_Hz)      ; clock duration
.macro   Utils_WaitNanoSecs
  .set cycles = ((@0 + cycle_time_ns - 1) / cycle_time_ns - @1)
  .if (cycles > (255 * 3 + 2))
    .error "MACRO Utils_WaitNanoSecs - too many cycles to burn"
  .else
    .if (cycles > 6)
      .set  loop_cycles = (cycles / 3)      
      ldi   @2,loop_cycles
      dec   @2
      brne  pc-1
      .set  cycles = (cycles - (loop_cycles * 3))
    .endif
    .if (cycles > 0)
      .if   (cycles & 4)
        rjmp  pc+1
        rjmp  pc+1
      .endif
      .if   (cycles & 2)
        rjmp  pc+1
      .endif
      .if   (cycles & 1)
        nop
      .endif
    .endif
  .endif
.endmacro



