; ***************************************************************************
; copyright   : (C) 2025 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.   *
; ***************************************************************************

#ifndef AVR_MODULES_COM2W_COM2WN_WAIT_H
#define AVR_MODULES_COM2W_COM2WN_WAIT_H


; WORK IN PROGRESS



.cseg



; ---------------------------------------------------------------------------
; @routine com2wWaitForClockHighMulti10Us
;
; Wait for high CLK
;
; @param  R20 multiple of 10us to wait (e.g. "2" for "20" us, max: 32)
; @return CFLAG set if okay (state reached), cleared on error
; @clobbers: r16, r20, r22

com2wWaitForClockHighMulti10Us:
.if clock > 1000000
; begin version for > 1000000 Hz
  push r19
    ldi r19, LOW(clock/1000000)
    ldd r22, Y+COM2W_IFACE_OFFS_PINMASK_CLK             ; +2
com2wWaitForClockHighMulti10Us_loop0:
      push r20
com2wWaitForClockHighMulti10Us_loop:                   ; 10 cycles per loop
          inr r16, COM_CLK_INPUT                          ; +1 (if low port, +2 if high port)
          and r16, r22                                    ; +1
          brne com2wWaitForClockHighMulti10Us_stateReached ; +1 if FALSE, +2 if TRUE
      
          inr r16, COM_CLK_INPUT                          ; +1 (if low port, +2 if high port)
          and r16, r22                                    ; +1
          brne com2wWaitForClockHighMulti10Us_stateReached ; +1 if FALSE, +2 if TRUE
      
          nop                                             ; +1
          
          dec r20                                         ; +1
        brne com2wWaitForClockHighMulti10Us_loop           ; +2 if TRUE, +1 if FALSE
      pop r20
      dec r19                                           ; +1
    brne com2wWaitForClockHighMulti10Us_loop0            ; +1 if FALSE, +2 if TRUE
  pop r19
  clc                                                 ; +1
  ret                                                 ; +4
com2wWaitForClockHighMulti10Us_stateReached:
    pop r20
  pop r19
  sec                                                 ; +1
  ret                                                 ; +4
; end version for > 1000000 Hz
.elif clock < 1000000
  .error "Clock speed too low"
.else
; begin version for 1000000 Hz
  ldd r22, Y+COM2W_IFACE_OFFS_PINMASK_CLK             ; +2
com2wWaitForClockHighMulti10Us_loop:                  ; 10 cycles per loop
    inr r16, COM_CLK_INPUT                            ; +1 (if low port, +2 if high port)
    and r16, r22                                      ; +1
    brne com2wWaitForClockHighMulti10Us_stateReached  ; +1 if FALSE, +2 if TRUE

    inr r16, COM_CLK_INPUT                            ; +1 (if low port, +2 if high port)
    and r16, r22                                      ; +1
    brne com2wWaitForClockHighMulti10Us_stateReached   ; +1 if FALSE, +2 if TRUE

    nop                                               ; +1
    
    dec r20                                           ; +1
  brne com2wWaitForClockHighMulti10Us_loop             ; +2 if TRUE, +1 if FALSE
  clc                                                 ; +1
  ret                                                 ; +4
com2wWaitForClockHighMulti10Us_stateReached:
  sec                                                 ; +1
  ret                                                 ; +4
; end version for 1000000 Hz
.endif
; @end



; ---------------------------------------------------------------------------
; @routine com2wWaitForClockLowMulti10Us
;
; Wait for low CLK
;
; @param  R20 multiple of 10us to wait (e.g. "2" for "20" us)
; @return CFLAG set if okay (state reached), cleared on error
; @clobbers: r16, r20, r22

com2wWaitForClockLowMulti10Us:
.if clock > 1000000
; begin version for > 1000000 Hz
  push r19
    ldi r19, LOW(clock/1000000)
    ldd r22, Y+COM2W_IFACE_OFFS_PINMASK_CLK             ; +2
com2wWaitForClockLowMulti10Us_loop0:
      push r20
com2wWaitForClockLowMulti10Us_loop:                   ; 10 cycles per loop
          inr r16, COM_CLK_INPUT                          ; +1 (if low port, +2 if high port)
          and r16, r22                                    ; +1
          breq com2wWaitForClockLowMulti10Us_stateReached ; +1 if FALSE, +2 if TRUE
      
          inr r16, COM_CLK_INPUT                          ; +1 (if low port, +2 if high port)
          and r16, r22                                    ; +1
          breq com2wWaitForClockLowMulti10Us_stateReached ; +1 if FALSE, +2 if TRUE
      
          nop                                             ; +1
          
          dec r20                                         ; +1
        brne com2wWaitForClockLowMulti10Us_loop           ; +2 if TRUE, +1 if FALSE
      pop r20
      dec r19                                           ; +1
    brne com2wWaitForClockLowMulti10Us_loop0            ; +1 if FALSE, +2 if TRUE
  pop r19
  clc                                                 ; +1
  ret                                                 ; +4
com2wWaitForClockLowMulti10Us_stateReached:
    pop r20
  pop r19
  sec                                                 ; +1
  ret                                                 ; +4
; end version for > 1000000 Hz
.elif clock < 1000000
  .error "Clock speed too low"
.else
; begin version for 1000000 Hz
  ldd r22, Y+COM2W_IFACE_OFFS_PINMASK_CLK             ; +2
com2wWaitForClockLowMulti10Us_loop:                   ; 10 cycles per loop
    inr r16, COM_CLK_INPUT                            ; +1 (if low port, +2 if high port)
    and r16, r22                                      ; +1
    breq com2wWaitForClockLowMulti10Us_stateReached   ; +1 if FALSE, +2 if TRUE

    inr r16, COM_CLK_INPUT                            ; +1 (if low port, +2 if high port)
    and r16, r22                                      ; +1
    breq com2wWaitForClockLowMulti10Us_stateReached   ; +1 if FALSE, +2 if TRUE

    nop                                               ; +1
    
    dec r20                                           ; +1
  brne com2wWaitForClockLowMulti10Us_loop             ; +2 if TRUE, +1 if FALSE
  clc                                                 ; +1
  ret                                                 ; +4
com2wWaitForClockLowMulti10Us_stateReached:
  sec                                                 ; +1
  ret                                                 ; +4
; end version for 1000000 Hz
.endif






#endif ; AVR_MODULES_COM2W_COM2WN_WAIT_H


