; ***************************************************************************
; 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_IRQ_H
#define AVR_MODULES_COM2W_COM2WN_IRQ_H


.cseg



; ---------------------------------------------------------------------------
; @routine com2wnSetupIrq
;

com2wnSetupIrq:
  ; setup pin-change interrupt for CLK
  rcall com2wnEnableClkIrq

  ; enable PCIEn irq
  inr r16, COM_IRQ_ADDR_M_CLK          ; enable pin change irq PCIEn
  sbr r16, (1<<COM_IRQ_BIT_M_CLK)
  outr COM_IRQ_ADDR_M_CLK, r16

  ; clear PCIEn interrupt flag
  inr r16, COM_IRQ_ADDR_F_CLK          ; enable pin change irq PCIEn
  sbr r16, (1<<COM_IRQ_BIT_F_CLK)
  outr COM_IRQ_ADDR_F_CLK, r16
  
  ret
; @end



; ---------------------------------------------------------------------------
; @routine com2wnEnableClkIrq
;
; @clobbers 

com2wnEnableClkIrq:
  push r16
    push r17
      ; clear this interfaces CLK bit in com2wnIoDisabledClockMask
      ldd r16, Y+COM2W_IFACE_OFFS_PINMASK_CLK
      com r16
      lds r17, com2wnIoDisabledClockMask
      and r17, r16
      sts com2wnIoDisabledClockMask, r17
      ; enable pin change irq
      ldd r16, Y+COM2W_IFACE_OFFS_PINMASK_IRQ
      inr r17, COM_IRQ_ADDR_CLK
      or r17, r16
      outr COM_IRQ_ADDR_CLK, r17
    pop r17
  pop r16
  ret
; @end



; ---------------------------------------------------------------------------
; @routine com2wnDisableClkIrq
;
; @clobbers none

com2wnDisableClkIrq:
  push r16
    push r17
      ldd r16, Y+COM2W_IFACE_OFFS_PINMASK_IRQ
      com r16
      inr r17, COM_IRQ_ADDR_CLK
      and r17, r16                             ; clear bit for clock line
      outr COM_IRQ_ADDR_CLK, r17
      
      ; set this interfaces CLK bit in com2wnIoDisabledClockMask
      ldd r16, Y+COM2W_IFACE_OFFS_PINMASK_CLK
      lds r17, com2wnIoDisabledClockMask
      or r17, r16
      sts com2wnIoDisabledClockMask, r17
      
    pop r17
  pop r16
  ret
; @end



; ---------------------------------------------------------------------------
; @routine COM2WN_ClkChangeIsr @global @isr
;
; Interrupt service routine for dual or single port (i.e. one port contains all 
; CLOCK and DATA bits like in node R05 and R06).
;
; @clobbers none

COM2WN_ClkChangeIsr:
.if COM_DATA_INPUT == COM_CLK_INPUT
  ; routine for single port
  push r15
    in r15, SREG
    push r16
      inr r16, COM_CLK_INPUT                    ; read clk state early
      push r17
        lds r17, com2wnIoDisabledClockMask      ; mask disabled interfaces
        or r16, r17
        push r18
          push xl
            push xh
              push yl
                push yh
                  ldi yl, LOW(com2wnIoRingBuffer)
                  ldi yh, HIGH(com2wnIoRingBuffer)
                  rcall RingBufferY_WriteByte       ; (R17, R18, X)
                  brcs COM2WN_ClkChangeIsr_popRet
                  lds r16, com2wnIoFlags
                  ori r16, (1<<COM2W_IO_FLAGS_BIT_OVR)
                  sts com2wnIoFlags, r16
COM2WN_ClkChangeIsr_popRet:
                pop yh
              pop yl
            pop xh
          pop xl
        pop r18
      pop r17
    pop r16
    out SREG, r15
  pop r15
  reti
.else
  ; routine for two port
  push r15
    in r15, SREG
    push r16
      push r17
        inr r16, COM_CLK_INPUT                        ; read clk state early
        inr r17, COM_DATA_INPUT                       ; read data state early
        push r18
          lds r18, com2wnIoDisabledClockMask          ; mask disabled interfaces
          or r16, r18
          push xl
            push xh
              push yl
                push yh
                  ldi yl, LOW(com2wnIoRingBuffer)
                  ldi yh, HIGH(com2wnIoRingBuffer)
                  push r17
                    rcall RingBufferY_WriteByte       ; push clk state (R17, R18, X)
                  pop r16                             ; pop DATA input into r16 (from r17)
                  brcc COM2WN_ClkChangeIsr_ovr
                  rcall RingBufferY_WriteByte         ; push data state (R17, R18, X)
                  brcs COM2WN_ClkChangeIsr_popRet
COM2WN_ClkChangeIsr_ovr:
                  lds r16, com2wnIoFlags
                  ori r16, (1<<COM2W_IO_FLAGS_BIT_OVR)
                  sts com2wnIoFlags, r16
COM2WN_ClkChangeIsr_popRet:
                pop yh
              pop yl
            pop xh
          pop xl
        pop r18
      pop r17
    pop r16
    out SREG, r15
  pop r15
  reti
  
.endif
; @end



#endif ; AVR_MODULES_COM2W_COM2WN_IRQ_H

