; *************************************************************************** ; 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. * ; *************************************************************************** #ifndef AQH_AVR_DEVICES_COMMON_RANDOM_ASM #define AQH_AVR_DEVICES_COMMON_RANDOM_ASM ; *************************************************************************** ; data .dseg randSeed: .byte 2 ; *************************************************************************** ; code .cseg ; --------------------------------------------------------------------------- ; @routine RAND_PseudoRandom ; ; Generate a pseudo random number. ; (see https://www.avrfreaks.net/s/topic/a5C3l000000URNfEAO/t119045?comment=P-1021038) ; ; @return R16 8 bit pseudo random number ; @clobbers R16, R17, R18, R19 RAND_PseudoRandom: lds r16, randSeed lds r17, randSeed+1 ldi r18, 0x9c ldi r19, 8 RAND_PseudoRandom_step: lsr r17 ror r16 brcc RAND_PseudoRandom_nomask eor r17, r18 RAND_PseudoRandom_nomask: dec r19 brne RAND_PseudoRandom_step sts randSeed, r16 sts randSeed+1, r17 ret ; result in r16 ; @end ; --------------------------------------------------------------------------- ; @routine RAND_SetupSeed @global ; ; @clobbers R16, R18, R19, R20, R21, R24, R25, X, Z RAND_SetupSeed: rcall RAND_ReadSeed ; R18:R19=seed (r16, X) mov r20, r18 mov r21, r19 ; default initial seed ldi r18, 0xe1 ldi r19, 0xac ; work stored seed into it mov r16, r20 rcall randWorkByteIntoSeed ; (none) mov r16, r21 rcall randWorkByteIntoSeed ; (none) ; work date string into seed ldi zl, LOW(utilsDateString*2) ldi zh, HIGH(utilsDateString*2) rcall randWorkProgStringIntoSeed ; (R16, Z) ; work sram content into seed rcall randWorkSramContentIntoSeed ; (R16, R24, R25, X) ; store seed in EEPROM rcall RAND_WriteSeed ; (R16, R17, X) ret ; @end ; --------------------------------------------------------------------------- ; @routine RAND_ReadSeed ; ; Read seed from EEPROM. ; ; @return R18:R19 seed read ; @clobbers R16, X RAND_ReadSeed: ldi xl, LOW(EEPROM_OFFS_SEED) ldi xh, HIGH(EEPROM_OFFS_SEED) rcall Eeprom_ReadByte ; (none) brcc RAND_ReadSeed_ret mov r18, r16 adiw xh:xl, 1 rcall Eeprom_ReadByte ; (none) mov r19, r16 RAND_ReadSeed_ret: ret ; @end ; --------------------------------------------------------------------------- ; @routine RAND_WriteSeed ; ; Write seed from EEPROM. ; ; @param R18:R19 seed ; @clobbers R16, R17, X RAND_WriteSeed: ldi xl, LOW(EEPROM_OFFS_SEED) ldi xh, HIGH(EEPROM_OFFS_SEED) mov r16, r18 rcall Eeprom_WriteByteIfChanged ; (r17) brcc RAND_WriteSeed_ret adiw xh:xl, 1 mov r16, r19 rcall Eeprom_WriteByteIfChanged ; (r17) RAND_WriteSeed_ret: ret ; @end ; --------------------------------------------------------------------------- ; @routine RAND_UpdateSeedInEeprom ; ; @clobbers R18, R19, (R16, R17, X) RAND_UpdateSeedInEeprom: lds r18, randSeed lds r19, randSeed+1 rcall RAND_WriteSeed ; (R16, R17, X) ret ; @end ; --------------------------------------------------------------------------- ; @routine randWorkProgStringIntoSeed ; ; @param Z pointer to string to work into seed ; @param R18 low byte of current seed ; @param R19 high byte of current seed ; @return R18 low byte of updated seed ; @return R19 high byte of updated seed ; @clobbers R16, Z randWorkProgStringIntoSeed: lpm r16, Z+ tst r16 breq randWorkProgStringIntoSeed_done rcall randWorkByteIntoSeed rjmp randWorkProgStringIntoSeed randWorkProgStringIntoSeed_done: ret ; @end ; --------------------------------------------------------------------------- ; @routine randWorkSramContentIntoSeed ; IN: ; @param Z pointer to string to work into seed ; @param R18 low byte of current seed ; @param R19 high byte of current seed ; @return R18 low byte of updated seed ; @return R19 high byte of updated seed ; @clobbers R16, R24, R25, X randWorkSramContentIntoSeed: ldi xl, LOW(SRAM_START) ldi xh, HIGH(SRAM_START) ldi r24, LOW(RAMEND-SRAM_START) ldi r25, HIGH(RAMEND-SRAM_START) randWorkSramContentIntoSeed_loop: ld r16, X+ rcall randWorkByteIntoSeed sbiw r25:r24, 1 brne randWorkSramContentIntoSeed_loop ret ; @end ; --------------------------------------------------------------------------- ; @routine randWorkByteIntoSeed ; ; @param R16 byte to work into the seed ; @param R18 low byte of current seed ; @param R19 high byte of current seed ; @return R18 low byte of updated seed ; @return R19 high byte of updated seed randWorkByteIntoSeed: eor r18, r16 clc sbrc r19, 7 sec ; only executed if bit 7 is set in r19 rol r18 rol r19 ret ; @end #endif