moved multiplication function to "common" dir, added divide routine.

This commit is contained in:
Martin Preuss
2025-05-10 15:16:05 +02:00
parent c7823d3874
commit 4baa949a77
5 changed files with 133 additions and 53 deletions

View File

@@ -5,9 +5,11 @@
<extradist>
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

59
avr/common/divide.asm Normal file
View File

@@ -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

69
avr/common/multiply.asm Normal file
View File

@@ -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

View File

@@ -82,6 +82,7 @@
#ifdef MODULES_NETWORK
.include "modules/si7021/send.asm"
#endif
.include "common/multiply.asm"
#endif
#ifdef MODULES_OWI_MASTER

View File

@@ -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
;