; *************************************************************************** ; 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_TLV_H #define AQH_AVR_COMMON_EEPROM_TLV_H ; *************************************************************************** ; code .cseg ; --------------------------------------------------------------------------- ; @routine EepromTlv_AddTlv @global ; ; @param r16 type (must not be 0xff!) ; @param r17 length ; @return CFLAG set if free bytes found, cleared on error ; @return X EEPROM address of data for TLV (behind TLV header) ; @clobbers R16, R20, R21, X (R18) EepromTlv_AddTlv: mov r20, r16 mov r21, r17 ldi r16, 0xff rcall EepromTlv_FindFirst ; (r16, r17, r18) brcc EepromTlv_AddTlv_end cpi r17, 0xff brne EepromTlv_AddTlv_clcEnd add xl, r21 ; wanted size adc xh, r21 sub xh, r21 rcall Eeprom_CheckAddr ; check end address (R16) brcc EepromTlv_AddTlv_end sub xl, r21 sbc xh, r21 add xh, r21 sbiw xh:xl, 2 ; go back to begin of TLV mov r16, r20 ; type rcall Eeprom_WriteByte ; (R17) adiw xh:xl, 1 mov r16, r21 ; length rcall Eeprom_WriteByte ; (R17) adiw xh:xl, 1 sec rjmp EepromTlv_AddTlv_end EepromTlv_AddTlv_clcEnd: clc EepromTlv_AddTlv_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine EepromTlv_FindFirst @global ; ; Find first matching TLV ; ; @param r16 TLV type to find ; @return CFLAG set if TLV found, cleared otherwise ; @return r16 type ; @return r17 length ; @return X points to begin of TLV data ; @clobbers r16, r17, r18 EepromTlv_FindFirst: ldi xl, LOW(EEPROM_OFFS_TLV) ldi xh, HIGH(EEPROM_OFFS_TLV) rjmp eepromTlvFind ; (R18) ; @end ; --------------------------------------------------------------------------- ; @routine EepromTlv_FindNext @global ; ; Find next matching TLV ; ; @param r16 TLV type to find ; @param X points to current TLV data (will be skipped when searching) ; @return CFLAG set if TLV found, cleared otherwise ; @return r16 type ; @return r17 length ; @return X points to begin of TLV data ; @clobbers r16, r17, r18 EepromTlv_FindNext: ; skip current TLV rcall EepromTlv_ReadHeader ; r16=type, r17=len (none), X=data brcc EepromTlv_FindNext_ret add xl, r17 ; skip TLV data adc xh, r17 sub xh, r17 ; begin search with next tlv rcall eepromTlvFind ; (R18) EepromTlv_FindNext_ret: ret ; @end ; --------------------------------------------------------------------------- ; @routine eepromTlvFind @global ; ; @param r16 TLV type to find ; @param X EEPROM address to start search ; @return CFLAG set if TLV found, cleared otherwise ; @return r16 type ; @return r17 length ; @return X points to begin of TLV data ; @clobbers r16, r17, r18 eepromTlvFind: mov r18, r16 eepromTlvFind_loop: rcall EepromTlv_ReadHeader ; r16=type, r17=len (none), X=data brcc eepromTlvFind_notFound cp r16, r18 ; the one we wanted? breq eepromTlvFind_found add xl, r17 ; skip TLV data adc xh, r17 sub xh, r17 rjmp eepromTlvFind_loop eepromTlvFind_notFound: clc rjmp eepromTlvFind_end eepromTlvFind_found: sec eepromTlvFind_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine EepromTlv_ReadHeader ; ; @param X EEPROM address ; @return CFLAG set if address okay, cleared if out of range ; @return r16 type ; @return r17 length (only data length, can be 0) ; @return X EEPROM address behind TLV header ; @clobbers none EepromTlv_ReadHeader: rcall Eeprom_ReadByte ; read type brcc EepromTlv_ReadHeader_ret adiw xh:xl, 1 push r16 rcall Eeprom_ReadByte ; read length mov r17, r16 pop r16 brcc EepromTlv_ReadHeader_ret adiw xh:xl, 1 sec EepromTlv_ReadHeader_ret: ret ; @end #endif