from Tony Kübek tony.kubek at flintab.com
...it's for 24 bit signed variable, then I cannot output a variable at a time ( supposed to go inside an int handler ), therefore I'm using a 9 byte string to store the result, furthermore for the decimal point and supressing of leading zeroes I needed 1 byte and 2 bit variables. ... Its a bit of 'bloatware', requires about 290 ! instructions but thats efficient enough for me, I might get back to hammer on it when I've finished off the other bits I'm starting with now. I think it goes around 480 instruction executed worst case, and all the way down to 250 something for best case. Also I added a minor conditional that makes execution a tad faster for 20 bit numbers ( as my app will have about 99 % in this range ) to the expence of more code and additional execution for larger numbers.
Translated and optimized for the Scenix SX by Nikolai Golovchenko
;**********************************************************************
; *
; Filename: MathTest.asm 24bit signed binary->ASCII w. dp *
; Date: 2000-03-31 *
; File Version: 0.1B *
; *
; Author: Tony Kübek *
; Company: *
; *
; *
;**********************************************************************
; *
; Notes: Tests of binary to ASCII coversion *
; Routines from techref.massmind.org *
; Originators(16bit): Scott Dattalo and Nikolai Golovchenko*
; Routine takes 24 bit signed binary number and coverts to *
; 8/9 byte ASCII(true!) decimal string with decimal point *
; and minus sign as the first byte ( if negative ). *
; 24 bit variabel is stored in last three string bytes *
; These are 'destroyed' during processing *
; Leading zeroes are surpressed (conv. to space) *
; Resources needed: *
; DpPlacement 1 byte + 1 bit *
; PrevIsChar 1 bit ,prev. zero was surpressed *
; ASCII string of 9 bytes *
;**********************************************************************
DEVICE SX28
RESET Start
TEST_SMALL_NUMBER EQU 1 ; if defined then tests are performed
; to see number is less than +/-1048575 ( 20 bit )
; makes routine a little faster for thoose numbers
; to the expence of more code
; and adds some cycles to all numbers above if used
; but can deduct upto 62 cycles on smaller numbers
DECIMAL_POINT EQU 0x2E ; '.'
BYTE_OFFSET EQU 0x30 ; start decimal ASCII numbers
SIGN_NEGATIVE EQU 0x2D ; '-'
ORG $10 ; start userram bank 0
BitVars DS 1 ; used for dp-bit variable
OutPut DS 9 ; 8 used if no dp, else 9
DpPlacement DS 1 ; where to put dp, counted from start, min=1
; note an added bonus here ! as this var is
; located directly after the string and will
; 'always' be = 0x00(after conversion),
; you have an 'free' null terminator
_DpUsed EQU BitVars.0 ; decimal point has been placed
_PrevIsSpace EQU BitVars.1 ; previous byte/digit is 'converted' to space
Sample EQU OutPut+6 ; Note !! to save ram, 24 bit variable is stored
; in highest three byte in 9 byte string
; define constants to add/sub to the input number
; low/mid/high byte is relative to a 24 bit number
;LOW4M EQU 4000000 & $FF is zero!
MID4M EQU (4000000 >> 8) & $FF
HIGH4M EQU $3D ;(4000000 >> 16) & $FF
LOW1M EQU 1000000 & $FF
MID1M EQU (1000000 >> 8) & $FF
HIGH1M EQU $0F ;(1000000 >> 16) & $FF
LOW300K EQU 300000 & $FF
MID300K EQU (300000 >> 8) & $FF
HIGH300K EQU $04 ;(300000 >> 16) & $FF
LOW100K EQU 100000 & $FF
MID100K EQU (100000 >> 8) & $FF
HIGH100K EQU $01 ;(100000 >> 16) & $FF
LOW30K EQU 30000 & $FF
MID30K EQU (30000 >> 8) & $FF
LOW10K EQU 10000 & $FF
MID10K EQU (10000 >> 8) & $FF
LOW3K EQU 3000 & $FF
MID3K EQU (3000 >> 8) & $FF
LOW1K EQU 1000 & $FF
MID1K EQU (1000 >> 8) & $FF
LOW300 EQU 300 & $FF
MID300 EQU (300 >> 8) & $FF
ORG $0
Start
;************************ Tony test 24 bit->8/9 digit ASCII with decimal point
; code with TEST_SMALL_NUMBER: (about)290 instructions ( excluding variable setup code )
;
; True ASCII conversion, variable decimalpoint, surpress leading zeroes
; 24 bit variable is handled as SIGNED!
;************************************
clr BitVars
; dp=1->dp=7(no dp), adds approx 50 cycles, i.e. dp=1 least cycles
mov W, #1 ; note dp = 1 = between first and second digit
; dp = 7 between the last and second last digit
; if dp >= 7, dp = 0 then last digit is = 0x00
mov DpPlacement, W
mov W, #BYTE_OFFSET ; preset with ASCII offset
mov OutPut, W
mov OutPut+1, W
mov OutPut+2, W
mov OutPut+3, W
mov OutPut+4, W
mov OutPut+5, W
clrb OutPut.4 ; clear bit, makes first char 'space'
; OutPut+6 - OutPut+8 will contain 24 bit sample, LSB in OutPut+8
; ** NOTE ** Sample = OutPut+6, Sample+1 = OutPut+7, Sample+2 = OutPut+8
; Sample is defined as a separate name as it makes the code easier to read
; test number : 1235783 = 0x12DB47 - ok ! cycles approx: 301 -350 depending on dp placment
; Note ! This with TEST_SMALL_NUMBER, without deduct 10 cycles
; mov W, #$47
; mov Sample+2, W
; mov W, #$DB
; mov Sample+1, W
; mov W, #$12
; mov Sample, W
; test number : -1235783 = 0xED24B9 - ok ! cycles approx: 311 -360 depending on dp placment
; Note ! This with TEST_SMALL_NUMBER, without deduct 10 cycles
; mov W, #$B9
; mov Sample+2, W
; mov W, #$24
; mov Sample+1, W
; mov W, #$ED
; mov Sample, W
; test number : 60900 = 0x00EDE4 - ok ! cycles approx: 315 -371 depending on dp placment
; Note ! This with TEST_SMALL_NUMBER, without add 63 cycles
; mov W, #$E4
; mov Sample+2, W
; mov W, #$ED
; mov Sample+1, W
; mov W, #$00
; mov Sample, W
; test number : -60900 = 0xFF121C - ok ! cycles approx: 325 -381 depending on dp placment
; Note ! This with TEST_SMALL_NUMBER, without add 56 cycles
; mov W, #$1C
; mov Sample+2, W
; mov W, #$12
; mov Sample+1, W
; mov W, #$FF
; mov Sample, W
; test number : 231 = 0xE7 - ok !, cycles approx 244-302 depending on dp placement
; NOTE ! With TEST_SMALL_NUMBER, without add 62 cycles
; mov W, #$E7
; mov Sample+2, W
; mov W, #$00
; mov Sample+1, W
; mov W, #$00
; mov Sample, W
; test number : -1 = 0xFFFFFF - ok !, cycles approx:262-326 depending on dp placement
; This with TEST_SMALL_NUMBER, without add 62 cycles
;
; mov W, #$FF
; mov Sample+2, W
; mov W, #$FF
; mov Sample+1, W
; mov W, #$FF
; mov Sample, W
; test number : 1048575 = 0x0FFFFF - ok !, cycles approx: 297-348 depending on dp placement
; this with TEST_SMALL_NUMBER, without add 8 cycles
; mov W, #$FF
; mov Sample+2, W
; mov W, #$FF
; mov Sample+1, W
; mov W, #$0F
; mov Sample, W
; test number : 1000000 = 0x0F4240 - ok !, cycles approx: 291-350 depending on dp placement
; this with TEST_SMALL_NUMBER, without add 8 cycles
; mov W, #$40
; mov Sample+2, W
; mov W, #$42
; mov Sample+1, W
; mov W, #$0F
; mov Sample, W
; test number : 8388607 = 0x7FFFFF - ok !, cycles approx: 394-445 depending on dp placement
; this with TEST_SMALL_NUMBER, without add 8 cycles
; mov W, #$FF
; mov Sample+2, W
; mov W, #$FF
; mov Sample+1, W
; mov W, #$7F
; mov Sample, W
; test number : -7099999 = 0x93A9A1 - ok !, cycles approx:429-480 depending on dp placement
; this with TEST_SMALL_NUMBER, without add 8 cycles
mov W, #$A1
mov Sample+2, W
mov W, #$A9
mov Sample+1, W
mov W, #$93
mov Sample, W
TEST_NEGATIVE
sb Sample.7 ; test if negative
IF TEST_SMALL_NUMBER == 1
jmp TEST_TOPNIBBLE ; nope
ELSE
jmp SUB4M ; nope
ENDIF
; sample is negative
; make two's complement
not Sample+2
not Sample+1
not Sample
mov W, #1
add Sample+2, W
snb C
add Sample+1, W
snb C
add Sample, W
mov W, #SIGN_NEGATIVE
mov OutPut, W ; first digit minus sign
IF TEST_SMALL_NUMBER == 1 ; test for small numbers and skips some loops
; use if number is often in 0-1048575 range ( negative or not)
; i.e. 0x000000 - 0x0FFFFF ( 2.5 bytes 20 bits )
TEST_TOPNIBBLE
; test if top nibble is zero, i.e. number less than 1048576 ( decimal )
; if so we can skip to sub300k routine
mov W, Sample
and W, #$F0 ; Mask out top four bits
sb Z
jmp SUB4M ; nope do full conversion
; this digit is zero, and dp is not yet set
; then downshift to space
setb _PrevIsSpace
clrb OutPut+1.4
jmp SUB300k ; continue
ENDIF ; TEST_SMALL_NUMBER
SUB4M:
; subtract 4 million from sample
mov W, #4
add OutPut+1, W
mov W, #MID4M
sb C
mov W, #MID4M + 1
sub Sample+1, W
mov W, #HIGH4M
sb C
mov W, #HIGH4M + 1
sub Sample, W
snb C ; overflow, i.e. negative
jmp SUB4M
ADD1M:
; add 1 million to sample
dec OutPut+1
mov W, #LOW1M
add Sample+2, W
mov W, #MID1M
snb C
mov W, #MID1M + 1
add Sample+1, W
mov W, #HIGH1M
snb C
mov W, #HIGH1M + 1
add Sample, W
sb C ; done ?
jmp ADD1M
; test for leading zeroes
mov W, #BYTE_OFFSET
mov W, OutPut+1-w
sb Z
jmp SUB300k
; this digit is zero, and dp is not yet set
; then downshift to space
setb _PrevIsSpace
clrb OutPut+1.4
SUB300k:
; substract 300 thousand from sample
mov W, #3
add OutPut+3, W
mov W, #LOW300K
sub Sample+2, W
mov W, #MID300K
sb C
mov W, #MID300K + 1
sub Sample+1, W
mov W, #HIGH300K
sb C
mov W, #HIGH300K + 1
sub Sample, W
snb C
jmp SUB300k
ADD100k
; add 100 thousand to sample
dec OutPut+3
mov W, #LOW100K
add Sample+2, W
mov W, #MID100K
snb C
mov W, #MID100K + 1
add Sample+1, W
mov W, #HIGH100K
snb C
mov W, #HIGH100K + 1
add Sample, W
sb C ; done
jmp ADD100k
IF TEST_SMALL_NUMBER == 1 ; if this test enabled it is possible
; to have an overflow here
; test for overflow ( Output+3 = 10 )
mov W, #BYTE_OFFSET+$0A
mov W, OutPut+3-w
sb Z ; test if non zero
jmp ADD100k_TstDp
; over flow, result is = 10, second digit = 1, third = 0
mov W, #BYTE_OFFSET
mov OutPut+3, W
sb _DpUsed ; test if dp already used
setb OutPut+1.0 ; if no dp used set this digit to one
setb OutPut+2.0 ; set also third digit to 1 ( in case dp is used )
; restore previous digit
sb _PrevIsSpace
jmp ADD100k_TstDp
setb OutPut+1.4
clrb _PrevIsSpace
ENDIF
ADD100k_TstDp:
; test for dp
decsz DpPlacement ; test for dp placement
jmp ADD100k_NoDp ; no dp yet
; place dp
setb _DpUsed ; dp is used
mov W, #DECIMAL_POINT ;
mov OutPut+2, W ; dp is third digit
; restore zero before dp
snb _PrevIsSpace
setb OutPut+1.4
jmp SUB30k ; continue
ADD100k_NoDp:
; no dp copy back number
mov W, OutPut+3
mov OutPut+2, W
; test for leading zeroes
mov W, #BYTE_OFFSET
mov W, OutPut+2-w
sb Z
clrb _PrevIsSpace
sb Z
jmp SUB30k
sb _PrevIsSpace
jmp SUB30k
; this digit is zero, and dp is not yet set
; then downshift to space
setb _PrevIsSpace
clrb OutPut+2.4
SUB30k:
; subtract 30'000 from sample
mov W, #3
add OutPut+4, W
mov W, #LOW30K
sub Sample+2, W
mov W, #MID30K
sb C
mov W, #MID30K + 1
sub Sample+1, W
sb C
dec Sample
sb Sample.7 ; negative ?
jmp SUB30k
ADD10k:
; add 10'000 to sample
dec OutPut+4
mov W, #LOW10K
add Sample+2, W
mov W, #MID10K
snb C
mov W, #MID10K + 1
add Sample+1, W
snb C
inc Sample
snb Sample.7 ; done ?
jmp ADD10k
snb _DpUsed
jmp SUB3k ; dp is already used continue
; test for dp
decsz DpPlacement ; test for dp placement
jmp ADD10k_NoDp ; no dp yet
; place dp
setb _DpUsed ; dp is used
mov W, #DECIMAL_POINT
mov OutPut+3, W ; dp is fourth digit
; restore zero before dp
sb _PrevIsSpace
setb OutPut+2.4
jmp SUB3k ; continue
ADD10k_NoDp:
; no dp copy back number
mov W, OutPut+4
mov OutPut+3, W
; test for leading zeroes
mov W, #BYTE_OFFSET
mov W, OutPut+3-w
sb Z
clrb _PrevIsSpace
sb Z
jmp SUB3k
sb _PrevIsSpace
jmp SUB3k
; this digit is zero, and dp is not yet set
; then downshift to space
setb _PrevIsSpace
clrb OutPut+3.4
SUB3k:
; subtract 3000 from sample
mov W, #3
add OutPut+5, W
mov W, #LOW3K
sub Sample+2, W
mov W, #MID3K
sb C
mov W, #MID3K + 1
sub Sample+1, W
snb C ; negative ?
jmp SUB3k
ADD1k:
; add 1000 to sample
dec OutPut+5
mov W, #LOW1K
add Sample+2, W
mov W, #MID1K
snb C
mov W, #MID1K + 1
add Sample+1, W
sb C
jmp ADD1k
snb _DpUsed
jmp SUB300_PreLoad ; dp is already used continue
; test for dp
decsz DpPlacement ; test for dp placement
jmp ADD1k_NoDp ; no dp yet
; place dp
setb _DpUsed ; dp is used
mov W, #DECIMAL_POINT
mov OutPut+4, W ; dp is fifth digit
; restore zero before dp
snb _PrevIsSpace
setb OutPut+3.4
jmp SUB300_PreLoad ; continue
ADD1k_NoDp:
; no dp copy back number
mov W, OutPut+5
mov OutPut+4, W
; test for leading zeroes
mov W, #BYTE_OFFSET
mov W, OutPut+4-w
sb Z
clrb _PrevIsSpace
sb Z
jmp SUB300_PreLoad
sb _PrevIsSpace
jmp SUB300_PreLoad
; this digit is zero, and dp is not yet set
; then downshift to space
setb _PrevIsSpace
clrb OutPut+4.4
SUB300_PreLoad
mov W, #BYTE_OFFSET
mov OutPut+6, W
SUB300:
; subtract 300 from sample
mov W, #3
add OutPut+6, W
mov W, #LOW300
sub Sample+2, W
mov W, #MID300
sb C
mov W, #MID300 + 1
sub Sample+1, W
snb C ; negative ?
jmp SUB300
mov W, #100
ADD100:
; add 100 to sample
dec OutPut+6
add Sample+2, W
sb C
jmp ADD100
inc Sample+1
snb Sample+1.7
jmp ADD100
snb _DpUsed
jmp SUB30_PreLoad ; dp is already used continue
; test for dp
decsz DpPlacement ; test for dp placement
jmp ADD100_NoDp ; no dp yet
; place dp
setb _DpUsed ; dp is used
mov W, #DECIMAL_POINT ;
mov OutPut+5, W ; dp is sixth digit
; restore zero before dp
snb _PrevIsSpace
setb OutPut+4.4
jmp SUB30_PreLoad ; continue
ADD100_NoDp:
; no dp copy back number
mov W, OutPut+6
mov OutPut+5, W
; test for leading zeroes
mov W, #BYTE_OFFSET
mov W, OutPut+5-w
sb Z
clrb _PrevIsSpace
sb Z
jmp SUB30_PreLoad
sb _PrevIsSpace
jmp SUB30_PreLoad
; this digit is zero, and dp is not yet set
; then downshift to space
setb _PrevIsSpace
clrb OutPut+5.4
SUB30_PreLoad:
mov W, #30
SUB30:
; subtract 30 from sample
inc OutPut+7
sub Sample+2, W
snb C
jmp SUB30
mov W, OutPut+7
rl OutPut+7
add OutPut+7, W
mov W, #10
ADD10:
; add 10 to sample
dec OutPut+7
add Sample+2, W
sb C
jmp ADD10
mov W, #BYTE_OFFSET
add OutPut+7, W
snb _DpUsed
jmp LAST_DIGIT ; dp is already used continue
; test for dp
decsz DpPlacement ; test for dp placement
jmp ADD10_NoDp ; no dp yet
; place dp
setb _DpUsed ; dp is used
mov W, #DECIMAL_POINT
mov OutPut+6, W ; dp is seventh digit
; restore zero before dp
snb _PrevIsSpace
setb OutPut+5.4
jmp LAST_DIGIT ; continue
ADD10_NoDp
; no dp copy back number
mov W, OutPut+7
mov OutPut+6, W
; test for leading zeroes
mov W, #BYTE_OFFSET
mov W, OutPut+6-w
sb Z
jmp LAST_DIGIT
sb _PrevIsSpace
jmp LAST_DIGIT
; this digit is zero, and dp is not yet set
; then downshift to space
setb _PrevIsSpace
clrb OutPut+6.4
LAST_DIGIT:
mov W, #BYTE_OFFSET
add W, Sample+2
mov Sample+2, W
sb _DpUsed
mov OutPut+7, W ; save in previous byte
snb _DpUsed
jmp END_CONV
decsz DpPlacement ; test for dp placement
jmp CLEAR_LAST ; no dp used at all ??
mov W, #DECIMAL_POINT ;
mov OutPut+7, W ; dp is eigth digit
; restore zero before dp
snb _PrevIsSpace
setb OutPut+6.4
jmp END_CONV
CLEAR_LAST:
; no dp used copy back number, and clear last digit
sb _DpUsed
clr OutPut+8 ; clear last digit no dp used
END_CONV
nop ; done :-)
jmp Start
| file: /Techref/scenix/lib/math/radix/b2a-24b9d-lzmsdp-tk_sx.htm, 22KB, , updated: 2004/6/10 14:40, local time: 2025/10/24 13:00,
216.73.216.22,10-3-83-201:LOG IN
|
| ©2025 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://www.piclist.com/techref/scenix/lib/math/radix/b2a-24b9d-lzmsdp-tk_sx.htm"> SX Microcontroller Radix Math Method - Binary to BCD packed and ASCII, 24 bit to 8 or 9 digits with sign, and decimal point</A> |
| Did you find what you needed? |
|
o List host: MIT, Site host massmind.org, Top posters @none found - Page Editors: James Newton, David Cary, and YOU! * Roman Black of Black Robotics donates from sales of Linistep stepper controller kits. * Ashley Roll of Digital Nemesis donates from sales of RCL-1 RS232 to TTL converters. * Monthly Subscribers: Gregg Rew. on-going support is MOST appreciated! * Contributors: Richard Seriani, Sr. |
Welcome to www.piclist.com! |
.