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,
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? <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> |
Did you find what you needed? |