558 lines
12 KiB
NASM
558 lines
12 KiB
NASM
; ***************************************************************************
|
|
; copyright : (C) 2023 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. *
|
|
; ***************************************************************************
|
|
|
|
|
|
|
|
|
|
|
|
; ***************************************************************************
|
|
; data
|
|
|
|
|
|
.dseg
|
|
|
|
utilsDataBegin:
|
|
utilsSeed: .byte 2
|
|
utilsDataEnd:
|
|
|
|
|
|
|
|
; ***************************************************************************
|
|
; code
|
|
|
|
|
|
.cseg
|
|
|
|
UTILS_BEGIN:
|
|
|
|
|
|
utilsDateString: .db "%YEAR%-%MONTH%-%DAY%-%HOUR%:%MINUTE%", 0, 0
|
|
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Utils_Init
|
|
;
|
|
; IN:
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear on error
|
|
; USED: R16, R17, R18, R19, X, (R20, R21, R24, R25, X, Z)
|
|
|
|
Utils_Init:
|
|
rcall utilsSetupSeed ; (R16, R18, R19, R20, R21, R24, R25, X, Z)
|
|
|
|
; preset SRAM data area
|
|
ldi xh, HIGH(utilsDataBegin)
|
|
ldi xl, LOW(utilsDataBegin)
|
|
clr r16
|
|
ldi r17, (utilsDataEnd-utilsDataBegin)
|
|
rcall Utils_FillSram ; (r17, x)
|
|
|
|
sts utilsSeed, r18
|
|
sts utilsSeed+1, r19
|
|
|
|
sec
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; setup seed
|
|
;
|
|
; IN:
|
|
; OUT:
|
|
; REGS: R16, R18, R19, R20, R21, R24, R25, X, Z
|
|
|
|
utilsSetupSeed:
|
|
rcall Utils_ReadSeed
|
|
mov r20, r18
|
|
mov r21, r19
|
|
|
|
; default initial seed
|
|
ldi r18, 0xe1
|
|
ldi r19, 0xac
|
|
|
|
; work stored seed into it
|
|
mov r16, r20
|
|
rcall utilsWorkByteIntoSeed
|
|
mov r16, r21
|
|
rcall utilsWorkByteIntoSeed
|
|
|
|
; work date string into seed
|
|
ldi zl, LOW(utilsDateString*2)
|
|
ldi zh, HIGH(utilsDateString*2)
|
|
rcall utilsWorkProgStringIntoSeed ; (R16, Z)
|
|
|
|
; work sram content into seed
|
|
rcall utilsWorkSramContentIntoSeed ; (R16, R24, R25, X)
|
|
|
|
; store seed in EEPROM
|
|
rcall Utils_WriteSeed ; (R16, R17, X)
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; utilsWorkProgStringIntoSeed
|
|
;
|
|
; IN:
|
|
; - Z : pointer to string to work into seed
|
|
; - R18: low byte of current seed
|
|
; - R19: high byte of current seed
|
|
; OUT:
|
|
; - R18: low byte of updated seed
|
|
; - R19: high byte of updated seed
|
|
; USED: R16, Z
|
|
|
|
utilsWorkProgStringIntoSeed:
|
|
lpm r16, Z+
|
|
tst r16
|
|
breq utilsWorkProgStringIntoSeed_done
|
|
rcall utilsWorkByteIntoSeed
|
|
rjmp utilsWorkProgStringIntoSeed
|
|
utilsWorkProgStringIntoSeed_done:
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; utilsWorkSramContentIntoSeed
|
|
; IN:
|
|
; - Z : pointer to string to work into seed
|
|
; - R18: low byte of current seed
|
|
; - R19: high byte of current seed
|
|
; OUT:
|
|
; - R18: low byte of updated seed
|
|
; - R19: high byte of updated seed
|
|
; USED: R16, R24, R25, X
|
|
|
|
utilsWorkSramContentIntoSeed:
|
|
ldi xl, LOW(SRAM_START)
|
|
ldi xh, HIGH(SRAM_START)
|
|
ldi r24, LOW(RAMEND-SRAM_START)
|
|
ldi r25, HIGH(RAMEND-SRAM_START)
|
|
utilsWorkSramContentIntoSeed_loop:
|
|
ld r16, X+
|
|
rcall utilsWorkByteIntoSeed
|
|
sbiw r25:r24, 1
|
|
brne utilsWorkSramContentIntoSeed_loop
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; utilsWorkByteIntoSeed
|
|
;
|
|
; IN:
|
|
; - R16: byte to work into the seed
|
|
; - R18: low byte of current seed
|
|
; - R19: high byte of current seed
|
|
; OUT:
|
|
; - R18: low byte of updated seed
|
|
; - R19: high byte of updated seed
|
|
; USED:
|
|
|
|
utilsWorkByteIntoSeed:
|
|
eor r18, r16
|
|
clc
|
|
sbrc r19, 7
|
|
sec ; only executed if bit 7 is set in r19
|
|
rol r18
|
|
rol r19
|
|
ret
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Utils_Fini
|
|
;
|
|
; IN:
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear on error
|
|
; USED: R16, R17, R18, X, Y
|
|
|
|
|
|
Utils_Fini:
|
|
sec
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Utils_FillSram
|
|
;
|
|
; IN:
|
|
; - x: pointer to SRAM to fill
|
|
; - r16: value to fill the SRAM with
|
|
; - r17: size of area to fill
|
|
; OUT:
|
|
; - nothing
|
|
; MODIFIED REGISTERS: r17, x
|
|
|
|
Utils_FillSram:
|
|
tst r17
|
|
breq Utils_FillSram_end
|
|
|
|
Utils_FillSram_loop:
|
|
st x+, r16
|
|
dec r17
|
|
brne Utils_FillSram_loop
|
|
Utils_FillSram_end:
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Increment a 32 bit counter at the address given by X.
|
|
; IN:
|
|
; - X: Address of the 4 byte counter (1. byte is LSB)
|
|
; OUT:
|
|
; - nothing
|
|
; MODIFIED REGISTERS: r18, r19, r20, r21, 22
|
|
|
|
Utils_IncrementCounter32:
|
|
ld r18, x+
|
|
ld r19, x+
|
|
ld r20, x+
|
|
ld r21, x
|
|
ldi r22, 1
|
|
add r18, r22
|
|
clr r22 ; doesn't affect carry flag
|
|
adc r19, r22
|
|
adc r20, r22
|
|
adc r21, r22
|
|
st x, r21
|
|
st -x, r20
|
|
st -x, r19
|
|
st -x, r18
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Increment a 16 bit counter at the address given by X.
|
|
; IN:
|
|
; - X: Address of the 2 byte counter (1. byte is LSB)
|
|
; OUT:
|
|
; - nothing
|
|
; MODIFIED REGISTERS: r18, r19, 22
|
|
|
|
Utils_IncrementCounter16:
|
|
ld r18, x+
|
|
ld r19, x
|
|
ldi r22, 1
|
|
add r18, r22
|
|
clr r22 ; doesn't affect carry flag
|
|
adc r19, r22
|
|
st x, r19
|
|
st -x, r18
|
|
ret
|
|
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Utils_ReadEepromIncr
|
|
;
|
|
; Read a byte from EEPROM (see example in ATtiny24/44/84 manual p.19).
|
|
;
|
|
; IN:
|
|
; - X: EEPROM Address to read from
|
|
; OUT:
|
|
; - R16: byte read
|
|
; - X: EEPROM Address incremented
|
|
; MODIFIED REGISTERS: R16
|
|
|
|
Utils_ReadEepromIncr:
|
|
sbic EECR, EEPE ; wait for previous write to complete (if any)
|
|
rjmp Utils_ReadEepromIncr
|
|
out EEARH, xh ; set EEPROM address
|
|
out EEARL, xl
|
|
sbi EECR, EERE ; start EEPROM read by writing EERE
|
|
in r16, EEDR ; read data from data register
|
|
adiw xh:xl, 1
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Utils_WriteEepromIncr
|
|
;
|
|
; Write a byte to EEPROM (see example in ATtiny24/44/84 manual p.18).
|
|
;
|
|
; IN:
|
|
; - R16: byte to write
|
|
; - X: EEPROM Address to write to
|
|
; OUT:
|
|
; - X: EEPROM Address incremented
|
|
; MODIFIED REGISTERS: R17
|
|
|
|
Utils_WriteEepromIncr:
|
|
sbic EECR, EEPE ; wait for previous write to complete (if any)
|
|
rjmp Utils_WriteEepromIncr
|
|
ldi r17, (0<<EEPM1) | (0<<EEPM0) ; set programming mode
|
|
out EECR, r17
|
|
out EEARH, xh ; set EEPROM address
|
|
out EEARL, xl
|
|
out EEDR, r16 ; write data to data register
|
|
sbi EECR, EEMPE ; write logical one to EEMPE
|
|
sbi EECR, EEPE ; start EEPROM write by setting EEPE
|
|
adiw xh:xl, 1
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Utils_PseudoRandom
|
|
;
|
|
; Generate a pseudo random number.
|
|
; (see https://www.avrfreaks.net/s/topic/a5C3l000000URNfEAO/t119045?comment=P-1021038)
|
|
;
|
|
; IN:
|
|
; OUT:
|
|
; - R16: 8 bit pseudo random number
|
|
; REGS: R16, R17, R18, R19
|
|
|
|
Utils_PseudoRandom:
|
|
lds r16, utilsSeed
|
|
lds r17, utilsSeed+1
|
|
ldi r18, 0x9c
|
|
ldi r19, 8
|
|
Utils_PseudoRandom_step:
|
|
lsr r17
|
|
ror r16
|
|
brcc Utils_PseudoRandom_nomask
|
|
eor r17, r18
|
|
Utils_PseudoRandom_nomask:
|
|
dec r19
|
|
brne Utils_PseudoRandom_step
|
|
sts utilsSeed, r16
|
|
sts utilsSeed+1, r17
|
|
ret ; result in r16
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Update seed in EEPROM.
|
|
;
|
|
; IN:
|
|
; OUT:
|
|
; REGS: R18, R19, (R16, R17, X)
|
|
|
|
Utils_UpdateSeedInEeprom:
|
|
lds r18, utilsSeed
|
|
lds r19, utilsSeed+1
|
|
rcall Utils_WriteSeed ; (R16, R17, X)
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Utils_ReadUid
|
|
;
|
|
; Read UID from EEPROM.
|
|
;
|
|
; IN:
|
|
; - nothing
|
|
; OUT:
|
|
; - R18:R19:R20:R21: UID
|
|
; REGS: R16, X
|
|
|
|
Utils_ReadUid:
|
|
push r15
|
|
in r15, SREG
|
|
cli
|
|
ldi xl, LOW(EEPROM_OFFS_UUID)
|
|
ldi xh, HIGH(EEPROM_OFFS_UUID)
|
|
rcall Utils_ReadEepromIncr ; (R16)
|
|
mov r18, r16
|
|
rcall Utils_ReadEepromIncr ; (R16)
|
|
mov r19, r16
|
|
rcall Utils_ReadEepromIncr ; (R16)
|
|
mov r20, r16
|
|
rcall Utils_ReadEepromIncr ; (R16)
|
|
mov r21, r16
|
|
out SREG, r15
|
|
pop r15
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Utils_SetupUid
|
|
;
|
|
; Reads UID from EEPROM. If not set generate a new one and store it in EEPROM.
|
|
;
|
|
; IN:
|
|
; OUT:
|
|
; - CFLAG set if new generated, cleared if there already was one.
|
|
; REGS: R15, R16, R18, R19, R20, R21, X (R17)
|
|
|
|
Utils_SetupUid:
|
|
in r15, SREG
|
|
cli
|
|
rcall Utils_ReadUid ; (R16, X)
|
|
mov r16, r18 ; all 0x00?
|
|
or r16, r19
|
|
or r16, r20
|
|
or r16, r21
|
|
breq Utils_SetupUid_generate ; yep, go generate one
|
|
mov r16, r18 ; all 0xff?
|
|
and r16, r19
|
|
and r16, r20
|
|
and r16, r21
|
|
inc r16
|
|
breq Utils_SetupUid_generate ; yep, go generate one
|
|
out SREG, r15
|
|
clc
|
|
ret
|
|
Utils_SetupUid_generate:
|
|
ldi xl, LOW(EEPROM_OFFS_UUID)
|
|
ldi xh, HIGH(EEPROM_OFFS_UUID)
|
|
rcall Utils_PseudoRandom ; byte 0 (R16, R17, R18, R19)
|
|
inc r16
|
|
rcall Utils_WriteEepromIncr ; (R17)
|
|
rcall Utils_PseudoRandom ; byte 1
|
|
rcall Utils_WriteEepromIncr
|
|
rcall Utils_PseudoRandom ; byte 2
|
|
rcall Utils_WriteEepromIncr
|
|
rcall Utils_PseudoRandom ; byte 3
|
|
rcall Utils_WriteEepromIncr
|
|
|
|
rcall Utils_UpdateSeedInEeprom ; (R16, R17, R18, R19, X)
|
|
|
|
out SREG, r15
|
|
sec
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Utils_ReadSeed
|
|
;
|
|
; Read seed from EEPROM.
|
|
;
|
|
; IN:
|
|
; OUT:
|
|
; - R18:R19: seed read
|
|
; REGS: R16, X
|
|
|
|
Utils_ReadSeed:
|
|
in r15, SREG
|
|
push r15
|
|
cli
|
|
ldi xl, LOW(EEPROM_OFFS_SEED)
|
|
ldi xh, HIGH(EEPROM_OFFS_SEED)
|
|
rcall Utils_ReadEepromIncr ; (R16)
|
|
mov r18, r16
|
|
rcall Utils_ReadEepromIncr ; (R16)
|
|
mov r19, r16
|
|
pop r15
|
|
out SREG, r15
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Utils_WriteSeed
|
|
;
|
|
; Read seed from EEPROM.
|
|
;
|
|
; IN:
|
|
; - R18:R19: seed to write
|
|
; OUT:
|
|
; REGS: R16, X, (R17)
|
|
Utils_WriteSeed:
|
|
in r15, SREG
|
|
push r15
|
|
cli
|
|
ldi xl, LOW(EEPROM_OFFS_SEED)
|
|
ldi xh, HIGH(EEPROM_OFFS_SEED)
|
|
mov r16, r18
|
|
rcall Utils_WriteEepromIncr ; (R17)
|
|
mov r16, r19
|
|
rcall Utils_WriteEepromIncr ; (R17)
|
|
pop r15
|
|
out SREG, r15
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Utils_TableJump
|
|
;
|
|
; Jump to a routine using a jump table.
|
|
; IN:
|
|
; - r16: position to jump to
|
|
; - r17: number of entries in table
|
|
; - Z : pointer to table
|
|
; OUT:
|
|
; - depends on called function
|
|
; REGS: depends on called function
|
|
|
|
Utils_TableJump:
|
|
cp r16, r17
|
|
brcc Utils_TableJump_ret
|
|
clr r17
|
|
add zl, r16
|
|
adc zh, r17
|
|
lsl zl ; shift z left for LPM instruction
|
|
rol zh
|
|
lpm r16, z+ ; read pointer from table
|
|
lpm r17, z
|
|
tst r16
|
|
brne Utils_TableJump_jmp
|
|
tst r17
|
|
brne Utils_TableJump_jmp
|
|
Utils_TableJump_ret:
|
|
ret
|
|
Utils_TableJump_jmp:
|
|
push r16 ; jump via stack
|
|
push r17
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Find position of a given code in a table.
|
|
;
|
|
; IN:
|
|
; - r16: value to translate
|
|
; - r17: number of entries
|
|
; - Z : pointer to table
|
|
; OUT:
|
|
; - CFLAG: set if translation found, cleared otherwise
|
|
; - r16: translated value
|
|
|
|
Utils_FindBytePositionInTable:
|
|
lsl zl ; shift z left for LPM instruction
|
|
rol zh
|
|
clr r19
|
|
Utils_TranslateByTable_loop:
|
|
lpm r18, z+
|
|
cp r18, r16
|
|
breq Utils_TranslateByTable_found
|
|
inc r19
|
|
dec r17
|
|
brne Utils_TranslateByTable_loop
|
|
clc
|
|
ret
|
|
Utils_TranslateByTable_found:
|
|
mov r16, r19
|
|
sec
|
|
ret
|
|
|
|
|
|
|
|
|
|
|
|
UTILS_END:
|
|
.equ MODULE_SIZE_UTILS = UTILS_END-UTILS_BEGIN
|
|
|