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



; ***************************************************************************
; defs

.equ DS1307_FLAGS_PRESENT_BIT = 7
.equ DS1307_FLAGS_VALID_BIT   = 6





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

.dseg

ds1307DataBegin:
  ds1307Flags:      .byte 1
  ds1307RecvBuffer: .byte 7
ds1307DataEnd:




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

.cseg



; ---------------------------------------------------------------------------
; @routine Ds1307_Init @global
;
; @return CFLAG set if okay, cleared on error
; @clobbers

Ds1307_Init:
  ldi xh, HIGH(ds1307DataBegin)
  ldi xl, LOW(ds1307DataBegin)
  clr r16
  ldi r17, (ds1307DataEnd-ds1307DataBegin)
  rcall Utils_FillSram

  rcall ds1307CheckPresence
  brcc Ds1307_Init_ret
  ldi r16, (1<<DS1307_FLAGS_PRESENT_BIT)
  sts ds1307Flags, r16
  sec
Ds1307_Init_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Ds1307_Fini @global
;
; @return CFLAG set if okay, cleared on error
; @clobbers none

Ds1307_Fini:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Ds1307_Fini @global
;
; @return CFLAG set if okay, cleared on error
; @clobbers

Ds1307_OnEveryMinute:
  push r15
    in r15, SREG
    cli

    lds r16, ds1307Flags
    sbrs r16, DS1307_FLAGS_PRESENT_BIT
      rjmp Ds1307_OnEveryMinute_ret
    ; clear valid bit
    cbr r16, (1<<DS1307_FLAGS_VALID_BIT)
    sts ds1307Flags, r16
    ; read time from clock
    ldi xl, LOW(ds1307RecvBuffer)
    ldi xh, HIGH(ds1307RecvBuffer)
    clr r16
    ldi r17, 7
    rcall ds1307ReadData
    brcc Ds1307_OnEveryMinute_ret
    ; set valid bit
    lds r16, ds1307Flags
    sbr r16, (1<<DS1307_FLAGS_VALID_BIT)
    sts ds1307Flags, r16
#ifdef MODULES_NETWORK
;    rcall ds1307SendDebug
    rcall Ds1307_AnnounceTime
#endif  
Ds1307_OnEveryMinute_ret:
    out SREG, r15
  pop r15

  ret
; @end



; ---------------------------------------------------------------------------
; @routine ds1307CheckPresence
;
; Expects interrupts being disabled!
;
; @return CFLAG set if okay, clear on error
; @clobbers R16 (R17, R18, R22)

ds1307CheckPresence:
  ldi r16, (DS1307_ADDR*2)   ; write access
  rjmp twiCheckPresence      ; (R16, R17, R18, R22)
; @end



; ---------------------------------------------------------------------------
; @routine ds1307ReadData
;
; @param r16 start address
; @param r17 number of bytes to read
; @param X pointer to buffer to receive data
; @return CFLAG set if okay, cleared on error
; @return r16 number of bytes received if CFLAG set
; @clobbers r16, r17, r18, r19, r20, r22, X

ds1307ReadData:
  mov r20, r16
  mov r19, r17
  rcall twiStart                         ; (R22)
  ldi r16, (DS1307_ADDR*2)               ; write access
  rcall twiSendByteExpectAck             ; (R16, R17, R18, R22)
  brcc ds1307ReadData_error
  mov r16, r20
  rcall twiSendByteExpectAck
  brcc ds1307ReadData_error
  rcall twiRestart                       ; (R22)
  ldi r16, (DS1307_ADDR*2)+1             ; read access
  rcall twiSendByteExpectAck
  brcc ds1307ReadData_error

  clr r20
ds1307ReadData_loop1:
    cpi r19, 1
    breq ds1307ReadData_recvLast
    rcall twiReceiveByteSendAck            ; (R16, R17, R18, R22)
    rjmp ds1307ReadData_recvd
ds1307ReadData_recvLast:
    rcall twiReceiveByte                   ; don't send ACK (R16, R17, R18, R22)
ds1307ReadData_recvd:
    brcc ds1307ReadData_error
    st X+, r16
    inc r20
    dec r19
  brne ds1307ReadData_loop1
  rcall twiStop                          ; (R22)
  mov r16, r20
  sec
  ret
ds1307ReadData_error:
  rcall twiStop                          ; (R22)
  clc
  ret
; @end



; ---------------------------------------------------------------------------
; @routine ds1307SendData
;
; @param r16 start address
; @param r17 number of bytes to read
; @param Z   pointer to buffer to send
; @return    CFLAG set if okay, cleared on error
; @return    r16 number of bytes received if CFLAG set
; @clobbers r16, r17, r18, r19, r20, r22, Z

ds1307SendData:
  mov r20, r16
  mov r19, r17
  rcall twiStart                         ; (R22)
  ldi r16, (DS1307_ADDR*2)               ; write access
  rcall twiSendByteExpectAck             ; (R16, R17, R18, R22)
  brcc ds1307SendData_error

  mov r16, r20                           ; address
  rcall twiSendByteExpectAck             ; (R16, R17, R18, R22)
  brcc ds1307SendData_error

  clr r20
ds1307SendData_loop1:
    ld r16, Z+
    rcall twiSendByteExpectAck             ; (R16, R17, R18, R22)
    brcc ds1307SendData_error
    inc r20
    dec r19
  brne ds1307SendData_loop1
  rcall twiStop                          ; (R22)
  mov r16, r20
  sec
  ret
ds1307SendData_error:
  rcall twiStop                          ; (R22)
  clc
  ret
; @end



