From 4baa949a77c4d1a83bd7646ba86e4e60cbf8a596 Mon Sep 17 00:00:00 2001 From: Martin Preuss Date: Sat, 10 May 2025 15:16:05 +0200 Subject: [PATCH] moved multiplication function to "common" dir, added divide routine. --- avr/common/0BUILD | 2 ++ avr/common/divide.asm | 59 ++++++++++++++++++++++++++++++ avr/common/multiply.asm | 69 ++++++++++++++++++++++++++++++++++++ avr/devices/all/includes.asm | 1 + avr/modules/si7021/main2.asm | 55 ++-------------------------- 5 files changed, 133 insertions(+), 53 deletions(-) create mode 100644 avr/common/divide.asm create mode 100644 avr/common/multiply.asm diff --git a/avr/common/0BUILD b/avr/common/0BUILD index d4e91ba..4d18df1 100644 --- a/avr/common/0BUILD +++ b/avr/common/0BUILD @@ -5,9 +5,11 @@ crc8.asm debug.asm + divide.asm m_fixedbuffers.asm m_ringbuffer.asm m_ringbuffer_y.asm + multiply.asm ringbuffer.asm ringbuffer_y.asm shared.asm diff --git a/avr/common/divide.asm b/avr/common/divide.asm new file mode 100644 index 0000000..c7109e6 --- /dev/null +++ b/avr/common/divide.asm @@ -0,0 +1,59 @@ +; *************************************************************************** +; 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 COMMON_DIVIDE_H +#define COMMON_DIVIDE_H + + +; --------------------------------------------------------------------------- +; @routine Utils_Divu16_16_16 +; +; Divides two unsigned 16 bit values resulting in one 16 bit value. +; This is a rather simple but reasonable fast routine working just like you would +; when doing divisions with pen and paper. +; +; R17:R16 = R21:R20 / R23:R22 +; R19:R18 = R21:R20 mod R23:R22 + +; TODO: adapt for signed values +; +; @param R21:R20 16 bit value A +; @param R23:R22 16 bit value B +; @return R17:R16 16 bit result +; @return R19:R18 16 bit remainder +; @clobbers + +Utils_Divu16_16_16: + mov r16, r20 ; r17:r16=result (intitially: dividend) + mov r17, r21 + clr r18 ; r19:r18=remainder + clr r19 + ldi r26, 16 ; 16 bits to divide +Utils_Divu16_16_16_loop: + lsl r16 ; shift 0 bit into result + rol r17 + rol r18 + rol r19 + + sub r18, r22 ; try to subtract divisor from value + sbc r19, r23 + brcs Utils_Divu16_16_16_nofit ; jmp if dividend < divisor + ori r16, 1 ; otherwise set bit in result + rjmp Utils_Divu16_16_16_loop_end +Utils_Divu16_16_16_nofit: + add r18, r22 ; undo subtraction + adc r19, r23 + ; r17:r16=result +Utils_Divu16_16_16_loop_end: + dec r26 + brne Utils_Divu16_16_16_loop + ret +; @end + + diff --git a/avr/common/multiply.asm b/avr/common/multiply.asm new file mode 100644 index 0000000..61834c2 --- /dev/null +++ b/avr/common/multiply.asm @@ -0,0 +1,69 @@ +; *************************************************************************** +; 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 COMMON_MULTIPLY_H +#define COMMON_MULTIPLY_H + + +; --------------------------------------------------------------------------- +; @routine Utils_Mulu16x16_32 +; +; Multiplies two unsigned 16 bit values resulting in one 32 bit value. +; This is a rather simple but reasonable fast routine working just like you would +; when doing multiplications with pen and paper. +; +; R19:R18:R17:R16 = R21:R20 * R23:R22 +; +; TODO: adapt for signed values +; +; @param R21:R20 16 bit value A +; @param R23:R22 16 bit value B +; @return R19:R18:R17:R16 32 bit result +; @clobbers R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26 + +Utils_Mulu16x16_32: + clr r19 + clr r18 + clr r17 + clr r16 + clr r25 + clr r24 + ldi r26, 16 ; 16 bit multiplicator +Utils_Mulu16x16_32_loop: + lsr r23 + ror r22 + brcc Utils_Mulu16x16_32_noadd ; current digit in B is 0, don't add shifted A to result + add r16, r22 + adc r17, r23 + adc r18, r24 + adc r19, r25 +; brcs Utils_Mulu16x16_32_overflow ; can't happen +Utils_Mulu16x16_32_noadd: + dec r26 + breq Utils_Mulu16x16_32_done + lsl r20 + rol r21 + rol r24 + rol r25 +; brcs Utils_Mulu16x16_32_overflow ; can't happen + rjmp Utils_Mulu16x16_32_loop +Utils_Mulu16x16_32_done: + clc + ret +;Utils_Mulu16x16_32_overflow: ; never reached. Multiplying 2 16 bit values can't overflow 32 bit +; sec +; ret +; @end + + + + + +#endif ; COMMON_MULTIPLY_H + diff --git a/avr/devices/all/includes.asm b/avr/devices/all/includes.asm index 10b5199..9047817 100644 --- a/avr/devices/all/includes.asm +++ b/avr/devices/all/includes.asm @@ -82,6 +82,7 @@ #ifdef MODULES_NETWORK .include "modules/si7021/send.asm" #endif +.include "common/multiply.asm" #endif #ifdef MODULES_OWI_MASTER diff --git a/avr/modules/si7021/main2.asm b/avr/modules/si7021/main2.asm index 4694912..5a3d9ac 100644 --- a/avr/modules/si7021/main2.asm +++ b/avr/modules/si7021/main2.asm @@ -306,7 +306,7 @@ si7021CalcTemp: mov r21, r19 ldi r23, HIGH(17572) ldi r22, LOW(17572) - rcall si7021Mulu16x16_32 ; result is in R19:R18:R17:R16, we only use R19-R18 -> /65536 + rcall Utils_Mulu16x16_32 ; result is in R19:R18:R17:R16, we only use R19-R18 -> /65536 ldi r16, LOW(4685) ldi r17, HIGH(4685) sub r18, r16 @@ -332,7 +332,7 @@ si7021CalcHumidity: mov r21, r19 clr r23 ldi r22, 125 - rcall si7021Mulu16x16_32 ; result is in R19:R18:R17:R16, we only use R19-R18 -> /65536 + rcall Utils_Mulu16x16_32 ; result is in R19:R18:R17:R16, we only use R19-R18 -> /65536 ldi r16, 6 clr r17 sub r18, r16 @@ -341,57 +341,6 @@ si7021CalcHumidity: -; --------------------------------------------------------------------------- -; si7021Mulu16x16_32 -; -; Multiplies two unsigned 16 bit values resulting in one 32 bit value. -; This is a rather simple but reasonable fast routine working just like you would -; when doing multiplications with pen and paper. -; TODO: adapt for signed values -; -; IN: -; - R21:R20: 16 bit value A -; - R23:R22: 16 bit value B -; OUT: -; - R19:R18:R17:R16: 32 bit result -; USED: R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26 -; R19:R18:R17:R16 = R21:R20 * R23:R22 -; R19:R18:R17:R16 = R25:R24:R21:R20 * R23:R22 -si7021Mulu16x16_32: - clr r19 - clr r18 - clr r17 - clr r16 - clr r25 - clr r24 - ldi r26, 16 ; 16 bit multiplicator -si7021Muls16x16_32_loop: - lsr r23 - ror r22 - brcc si7021Muls16x16_32_noadd ; current digit in B is 0, don't add shifted A to result - add r16, r22 - adc r17, r23 - adc r18, r24 - adc r19, r25 -; brcs si7021Muls16x16_32_overflow ; can't happen -si7021Muls16x16_32_noadd: - dec r26 - breq si7021Muls16x16_32_done - lsl r20 - rol r21 - rol r24 - rol r25 -; brcs si7021Muls16x16_32_overflow ; can't happen - rjmp si7021Muls16x16_32_loop -si7021Muls16x16_32_done: - clc - ret -;si7021Muls16x16_32_overflow: ; never reached. Multiplying 2 16 bit values can't overflow 32 bit -; sec -; ret - - - ; --------------------------------------------------------------------------- ; @routine SI7021_GetValue @global ;