Files
aqhomecontrol/avr/common/itoa.asm
2026-01-23 20:46:08 +01:00

183 lines
4.0 KiB
NASM

; ***************************************************************************
; 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_COMMON_ITOA_ASM
#define AQH_AVR_COMMON_ITOA_ASM
; ***************************************************************************
; defines
.equ ITOA_BUFFER_SIZE = 8
; ***************************************************************************
; global data
.dseg
itoa_buffer: ; max uint16 65535, 5 digits, plus komma, sign, ZERO
.byte ITOA_BUFFER_SIZE
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; @routine IntToAscii @global
;
; @param R21:R20 value to transform to ascii
; @param R24 number of digits after komma
; @return X pointer to result string (will be overwritten by next call!)
; @clobbers R16, R17, R18, R19, R20, R21, R22, R23
IntToAscii:
ldi xl, LOW(itoa_buffer)
ldi xh, HIGH(itoa_buffer)
adiw xh:xl, ITOA_BUFFER_SIZE
clr r16
st -X, r16
ldi r25, ITOA_BUFFER_SIZE-1 ; byte counter
IntToAscii_loop:
; divide by 10
ldi r22, 10
clr r23
push r25
bigcall Utils_Divu16_16_16 ; R17:R16=result, R19:R18=remainder (R25)
pop r25
; move result for next loop
mov r20, r16
mov r21, r17
; store digit of remainder (can only be 0-9 when dividing by 10)
ldi r19, '0'
add r19, r18
st -X, r19
dec r25
breq IntToAscii_ret
; maybe insert komma
tst r24
breq IntToAscii_next
dec r24
brne IntToAscii_next
ldi r19, ','
st -X, r19
dec r25
breq IntToAscii_ret
IntToAscii_next:
mov r16, r20 ; result == 0?
or r16, r21
breq IntToAscii_ret ; yes, done
rjmp IntToAscii_loop
IntToAscii_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine HexWordToAscii @global
;
; Shares buffer with @ref IntToAscii !
;
; @param R21:R20 value to transform to ascii
; @return X pointer to result string (will be overwritten by next call!)
; @clobbers R16, R17
HexWordToAscii:
ldi xl, LOW(itoa_buffer)
ldi xh, HIGH(itoa_buffer)
mov r16, r21
rcall writeHexByteToBuffer ; write hi byte
mov r16, r20
rcall writeHexByteToBuffer ; write low byte
clr r16
st X+, r16
sbiw xh:xl, 5
ret
; @end
; ---------------------------------------------------------------------------
; @routine HexByteToAscii @global
;
; Shares buffer with @ref IntToAscii !
;
; @param R16 value to transform to ascii
; @return X pointer to result string (will be overwritten by next call!)
; @clobbers R16, R17
HexByteToAscii:
ldi xl, LOW(itoa_buffer)
ldi xh, HIGH(itoa_buffer)
rcall writeHexByteToBuffer
clr r16
st X+, r16
sbiw xh:xl, 3
ret
; @end
; ---------------------------------------------------------------------------
; @routine writeHexByteToBuffer
;
; @param R16 value to transform to ascii
; @param X pointer to current pos in result buffer
; @clobbers R16, R17
writeHexByteToBuffer:
push r16
swap r16
rcall hexNibbleToAscii ; transform high nibble (r16, r17)
st X+, r16
pop r16
rcall hexNibbleToAscii ; transform low nibble (r16, r17)
st X+, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine hexNibbleToAscii
;
; Convert a nibble to an ASCII char.
; @return R16 ASCII representation of that nibble (e.g. '0' for 0)
; @param R16 byte (in bits 0-3)
; @clobbers r16, r17
hexNibbleToAscii:
andi r16, 0xf
cpi r16, 10
brcs hexNibbleToAscii_l1
ldi r17, 7
add r16, r17
hexNibbleToAscii_l1:
ldi r17, '0'
add r16, r17
ret
; @end
#endif