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



.equ TCRT1K_INTERVAL          = 7
;.equ TCRT1K_LIMIT             = 170
.equ TCRT1K_LIMIT             = 100

.equ TCRT1K_FLAGS_VALID_BIT   = 7
.equ TCRT1K_FLAGS_VALUE_BIT   = 0


; ***************************************************************************
; data

.dseg

tcrt1kDataBegin:
  tcrt1kTimer:        .byte 1
  tcrt1kFlags:        .byte 1
  tcrt1kLastValue:    .byte 1
tcrt1kDataEnd:




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

.cseg



; ---------------------------------------------------------------------------
; @routine TCRT1K_Init
;
; Init module.
;
; @return CFLAG always set

TCRT1K_Init:
  ; preset SRAM data area
  ldi xh, HIGH(tcrt1kDataBegin)
  ldi xl, LOW(tcrt1kDataBegin)
  clr r16
  ldi r17, (tcrt1kDataEnd-tcrt1kDataBegin)
  rcall Utils_FillSram

  ; setup pins
  sbi TCRT1K_LED_DDR, TCRT1K_LED_PIN                 ; set DATA port as output
  cbi TCRT1K_LED_PORT, TCRT1K_LED_PIN                ; LED off
  cbi TCRT1K_ADC_PORT, TCRT1K_ADC_PIN                ; disable internal pullup for ADC
  cbi TCRT1K_ADC_DDR, TCRT1K_ADC_PIN                 ; set ADC port as input

  ldi r16, TCRT1K_ADC_MUX                            ; select input pin, use Vcc as reference voltage
  out ADMUX, r16
  ldi r16, (1 << ADLAR)
  out ADCSRB, r16
  ldi r16, (1 << ADEN) | (1 << ADPS1) | (1 << ADPS0) ; enable, prescaler 8
  out ADCSRA, r16
  
  ldi r16, TCRT1K_INTERVAL
  sts tcrt1kTimer, r16
  
  sec
  ret



TCRT1K_Fini:
  sec
  ret



; ---------------------------------------------------------------------------
; @routine TCRT1K_Every100ms @global
;

TCRT1K_Every100ms:
  lds r16, tcrt1kTimer
  dec r16
  breq TCRT1K_Every100ms_readValue
  sts tcrt1kTimer, r16
  cpi r16, 1
  breq TCRT1K_Every100ms_startMeasure
  cpi r16, 2
  breq TCRT1K_Every100ms_ledOn
  ret
TCRT1K_Every100ms_ledOn:
  sbi TCRT1K_LED_PORT, TCRT1K_LED_PIN ; LED on
  ret
TCRT1K_Every100ms_startMeasure:
  sbi ADCSRA, ADSC                     ; start conversion
  ret
TCRT1K_Every100ms_readValue:
  sbic ADCSRA, ADSC
    ret ; return if bit still set, leave tcrt1kTimer at "1"
  ; conversion complete, read value
  ldi r16, TCRT1K_INTERVAL             ; restart timer
  sts tcrt1kTimer, r16
  in r16, ADCH                         ; read value from ADC
  sts tcrt1kLastValue, r16
  cbi TCRT1K_LED_PORT, TCRT1K_LED_PIN  ; LED off
  ; convert to 1/0
  lds r17, tcrt1kFlags
  cbr r17, (1<<TCRT1K_FLAGS_VALUE_BIT) ; clear value bit
  cpi r16, TCRT1K_LIMIT                ; ADC value < LIMIT?
  brcs TCRT1K_Every100ms_valueSet      ; yes: keep value bit zero
  sbr r17, (1<<TCRT1K_FLAGS_VALUE_BIT) ; no: set value bit
TCRT1K_Every100ms_valueSet:
  sbr r17, (1<<TCRT1K_FLAGS_VALID_BIT) ; set valid bit
  sts tcrt1kFlags, r17
  ret
; @end



; ---------------------------------------------------------------------------
; @routine TCRT1K_GetValue @global
;
; @return CFLAG set if there is a value, cleared otherwise (standard api)
; @return R16 value (0=door closed, 1=door open)
; @clobbers R16

TCRT1K_GetValue:
  lds r16, tcrt1kFlags
  sbrs r16, TCRT1K_FLAGS_VALID_BIT
    rjmp TCRT1K_GetValue_retNc
  andi r16, (1<<TCRT1K_FLAGS_VALUE_BIT)
  sec
  ret
TCRT1K_GetValue_retNc:
  clc
  ret
; @end



