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


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

.cseg


; ---------------------------------------------------------------------------
; Utils_WriteEepromIncr
;
; Write a byte to EEPROM (see example in ATtiny24/44/84 manual p.18).
;
; @param R16 byte to write
; @param X   EEPROM Address to write to
; @return CFLAG set if data written, cleared on error
; @clobbers R17

Eeprom_WriteByte:
  mov r17, r16
    rcall Eeprom_CheckAddr          ; (r16)
  mov r16, r17
  brcs Eeprom_WriteByte_addrOk
  ret
Eeprom_WriteByte_addrOk:
  ; call routine with IRQs disabled
  push r15
    inr r15, SREG
    cli
    rcall Eeprom_WriteByte_noirq
    outr SREG, r15
  pop r15
  sec
  ret
Eeprom_WriteByte_noirq:
  ; wait for EEPROM to be ready
Eeprom_WriteByte_waitLoop:
.ifdef EEPE
    sbic EECR, EEPE                 ; wait for previous write to complete (if any)
.else
    sbic EECR, EEWE                 ; wait for previous write to complete (if any)
.endif
  rjmp Eeprom_WriteByte_waitLoop
  ; write data
.ifdef EEPM1
  ldi r17, (0<<EEPM1) | (0<<EEPM0) ; set programming mode
.else
  clr r17
.endif
  out EECR, r17
  out EEARH, xh                    ; set EEPROM address
  out EEARL, xl
  out EEDR,  r16                   ; write data to data register
.ifdef EEMPE
  sbi EECR, EEMPE                  ; write logical one to EEMPE
.else
  sbi EECR, EEMWE                  ; write logical one to EEMWE
.endif
.ifdef EEPE
  sbi EECR, EEPE                   ; start EEPROM write by setting EEPE
.else
  sbi EECR, EEWE                   ; start EEPROM write by setting EEWE
.endif
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Eeprom_WriteByteIfChanged @global
;
; Only write EEPROM byte if changed from current value (save on write cycles)
;
; @param r16 byte to write
; @param X   eeprom address to write to
; @clobbers r17

Eeprom_WriteByteIfChanged:
  mov r17, r16  
  rcall Eeprom_ReadByte
  brcc Eeprom_WriteByteIfChanged_end
  cp r16, r17
  sec
  breq Eeprom_WriteByteIfChanged_end
  mov r16, r17
  rcall Eeprom_WriteByte              ; (R17)
Eeprom_WriteByteIfChanged_end:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Eeprom_WriteBytes @global
;
; Write bytes into EEPROM (if changed, thus saving on write cycles)
;
; @param X    eeprom address to write to
; @param Y    address in SDRAM to read from
; @param R17  number of bytes to copy
; @clobbers r16, r17, r18, X, Y

Eeprom_WriteBytes:
  mov r18, r17
Eeprom_WriteBytes_loop:
    ld r16, Y+
    rcall Eeprom_WriteByteIfChanged  ; (r17)
    brcc Eeprom_WriteBytes_ret
    adiw xh:xl, 1
    dec r18
  brne Eeprom_WriteBytes_loop
  sec
Eeprom_WriteBytes_ret:
  ret
; @end




#endif ; AQH_AVR_COMMON_EEPROM_W_H


