; ***************************************************************************
; 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.   *
; ***************************************************************************


; ***************************************************************************
; code


.cseg


; ---------------------------------------------------------------------------
; @routine ioWaitForAttnState100ms
;
; @param r16 expected state (0x00 or 0xff)
; @param r17 time to wait for expected state (in 100 ms units)
; @clobbers R17 (R22, R24)

ioWaitForAttnState100ms:
  cbi COM_ATTN_DDR, COM_ATTN_PIN          ; set ATTN port as input
  cbi COM_ATTN_OUTPUT, COM_ATTN_PIN       ; disable internal pullup for ATTN
  nop
ioWaitForAttnState100ms_loop:
#ifdef LED_SIMPLE_PINNUM
    sbi LED_SIMPLE_PORTIN, LED_SIMPLE_PINNUM  ; toggle LED
#endif
    push r17
      ldi r17, 100
      rcall ioWaitForAttnStateMilliSeconds          ; (R22, R24)
    pop r17
    brcs ioWaitForAttnState100ms_stateReached
    dec r17
  brne ioWaitForAttnState100ms_loop
  clc
ioWaitForAttnState100ms_stateReached:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine ioWaitForAttnStateMilliSeconds
;
; @param r16 expected state (0x00 or 0xff)
; @param r17 time to wait for expected state (in milliseconds)
; @clobbers R17 (R22, R24)

ioWaitForAttnStateMilliSeconds:
ioWaitForAttnStateMilliSeconds_loop:
    rcall ioWaitForAttnState1ms             ; (R22, R24)
    brcs ioWaitForAttnStateMilliSeconds_stateReached
    dec r17
  brne ioWaitForAttnStateMilliSeconds_loop
  clc
ioWaitForAttnStateMilliSeconds_stateReached:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine ioWaitForAttnState1ms
;
; Wait for up to 1ms for ATTN line to reach the given state
;
; @return CFLAG set if state reached, cleared otherwise
; @param  R16 expected state (0xff for high, 0 for low)
; @clobbers R24 (R22)

ioWaitForAttnState1ms:
  ldi r24, 100
ioWaitForAttnState1ms_loop:
    push r17
      in r17, COM_ATTN_INPUT
      eor r17, r16
      andi r17, (1<<COM_ATTN_PIN)
    pop r17
    breq ioWaitForAttnState1ms_stateReached
    rcall Utils_WaitFor10MicroSecs                ; wait for 10us (R22)
    dec r24
  brne ioWaitForAttnState1ms_loop
  clc
  ret
ioWaitForAttnState1ms_stateReached:
  sec
  ret
; @end



; ---------------------------------------------------------------------------
; @routine ioRawWaitForOneBitLength
;
; wait for one bit length (minus cycles for call and ret).
;
; @clobbers r22

ioRawWaitForOneBitLength:
  Utils_WaitNanoSecs COM_BIT_LENGTH, 7, r22       ; wait for one bit duration (minus RCALL/RET)
  ret
; @end



; ---------------------------------------------------------------------------
; @routine ioRawAcquireBus
;
; Reserve bus if free (otherwise return error)
; Expects interrupts to be disabled.
;
; @return CFLAG set if okay (bus acquired), cleared on error
; @clobbers: none

ioRawAcquireBus:
  ; check for ATTN line: busy?
  cbi COM_ATTN_DDR, COM_ATTN_PIN                 ; set ATTN as input
  cbi COM_ATTN_OUTPUT, COM_ATTN_PIN              ; disable pullup on ATTN
  nop                                            ; needed to sample current input
  sbis COM_ATTN_INPUT, COM_ATTN_PIN              ; ATTN low?
    rjmp ioRawAcquireBus_busy                    ; jump if it is
  sbi COM_ATTN_DDR, COM_ATTN_PIN                 ; set ATTN as output
  cbi COM_ATTN_OUTPUT, COM_ATTN_PIN              ; set ATTN low
  sec
  ret
ioRawAcquireBus_busy:
  clc
  ret
; @end




