please dont rip this site

SX Microcontroller Radix Math Method

Binary to BCD packed and ASCII, 24 bit to 8 or 9 digits with sign, and decimal point

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 13:40, local time: 2024/12/26 01:48,
TOP NEW HELP FIND: 
13.59.82.60:LOG IN

 ©2024 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?
Please DO link to this page! Digg it! / MAKE!

<A HREF="http://linistepper.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>

After you find an appropriate page, you are invited to your to this massmind site! (posts will be visible only to you before review) Just type a nice message (short messages are blocked as spam) in the box and press the Post button. (HTML welcomed, but not the <A tag: Instead, use the link box to link to another page. A tutorial is available Members can login to post directly, become page editors, and be credited for their posts.


Link? Put it here: 
if you want a response, please enter your email address: 
Attn spammers: All posts are reviewed before being made visible to anyone other than the poster.
Did you find what you needed?