; *************************************************************************** ; 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. * ; *************************************************************************** ; *************************************************************************** ; macros ; --------------------------------------------------------------------------- ; Utils_WaitNanoSecs waittime_in_ns , cyles_already_used , waitcount_register ; ; cycles already used will be subtracted from the delay ; the waittime resolution is 1 cycle (delay from exact to +1 cycle) ; the maximum delay at 20MHz (50ns/clock) is 38350ns ; waitcount register must specify an immediate register ; taken from https://www.mikrocontroller.net/articles/AVR_Assembler_Makros#Verz%C3%B6gerung_um_X_Nanosekunden ; .set Osc_Hz = clock ; 1 MHz .set cycle_time_ns = (1000000000 / Osc_Hz) ; clock duration .macro Utils_WaitNanoSecs .set cycles = ((@0 + cycle_time_ns - 1) / cycle_time_ns - @1) .if (cycles > (255 * 3 + 2)) .error "MACRO Utils_WaitNanoSecs - too many cycles to burn" .else .if (cycles > 6) .set loop_cycles = (cycles / 3) ldi @2,loop_cycles dec @2 brne pc-1 .set cycles = (cycles - (loop_cycles * 3)) .endif .if (cycles > 0) .if (cycles & 4) rjmp pc+1 rjmp pc+1 .endif .if (cycles & 2) rjmp pc+1 .endif .if (cycles & 1) nop .endif .endif .endif .endmacro ; *************************************************************************** ; 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 #if 0 ; --------------------------------------------------------------------------- ; 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 #endif ; --------------------------------------------------------------------------- ; 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<