In SX Microcontrollers, SX/B Compiler and SX-Key Tool, mrchadwickusa wrote: Hi Hans, Things have finally settled down enough that I could get back to this. I found a better 16 bit to BCD conversion routine, it is much faster and works very well as an SXB subroutine. The word to be converted is a two byte array, the output is a 5 byte array. The input is least significant byte first, the output is most significant digit first. The output is ASCII and is not zero terminated by the subroutine, but that would be trivial to add. I have tested it with SXSIM to verify it works with the SX28 and the SX52. It works very nicely and requires no temporary space other than the __PARAM variables used in SXB. [code] ' ========================================================================= ' ' File...... BCD_QUICK.SXB ' Purpose... Test a Binary to BCD conversion routine in SXB ' Author.... Mike Chadwick ' E-mail.... ' Started... 2006/03/30 ' Updated... ' ' ========================================================================= ' ------------------------------------------------------------------------- ' Program Description ' ------------------------------------------------------------------------- ' Test code for an SXB compatible 16 bit Binary to BCD conversion subroutine ' ------------------------------------------------------------------------- ' Device Settings ' ------------------------------------------------------------------------- ' uncomment one DEVICE line to test with SX29 v 52/48 DEVICE SX28, OSC4MHZ, TURBO, STACKX, OPTIONX 'DEVICE SX52, OSC4MHZ FREQ 4_000_000 ' ------------------------------------------------------------------------- ' IO Pins ' ------------------------------------------------------------------------- ' ------------------------------------------------------------------------- ' Constants ' ------------------------------------------------------------------------- ' Test values, uncomment one pair only TESTVALUEL CON 12345//256 TESTVALUEH CON 12345/256 'TESTVALUEL CON 65535//256 'TESTVALUEH CON 65535/256 'TESTVALUEL CON 0//256 'TESTVALUEH CON 0/256 ' ------------------------------------------------------------------------- ' Variables ' ------------------------------------------------------------------------- 'variables to use while we test the routines TestInput VAR Byte(2) 'Our test word to be output low byte then high byte 'Subroutine wrapper may be changed for high then low TestOutput VAR Byte(5) 'Our test output string, will be most significant 'digit first so we can output the string to a serial 'device in the correct order ' ------------------------------------------------------------------------- INTERRUPT ' ------------------------------------------------------------------------- ISR_Start: ' ISR code here ISR_Exit: RETURNINT ' {cycles} ' ========================================================================= PROGRAM Start ' ========================================================================= Pgm_ID: DATA "Binary to BCD Test", 0 ' ------------------------------------------------------------------------- ' Subroutines / Jump Table ' ------------------------------------------------------------------------- ' 'Use: BIN2BCD input, output ' where input is the starting address of a two byte array to be converted to ASCII bcd ' into output which is the address of a 5 byte array, the output is just the 5 ASCII digits ' the routine does not zero terminate them. ' input is least significant byte then most significant byte ' output is most significant digit first. BIN2BCD SUB 1,2 ' ------------------------------------------------------------------------- ' Program Code ' ------------------------------------------------------------------------- Start: ' initialization code here Main: ' main code here TestInput(0) = TESTVALUEL TestInput(1) = TESTVALUEH '-- Try each number in turn TestAnother: BIN2BCD TestInput, TestOutput 'this works because the base address of the array is passed TestInput(0) = TestInput(0)+1 TestInput(1) = TestInput(1) + C GOTO TestAnother ' ------------------------------------------------------------------------- ' Page 1 Code ' ------------------------------------------------------------------------- Page_1: ADDRESS $200 P1_Start: GOTO P1_Start ' error if Pg0 overruns Pg1 ' ------------------------------------------------------------------------- ' Page 2 Code ' ------------------------------------------------------------------------- Page_2: ADDRESS $400 P2_Start: GOTO P2_Start ' error if Pg1 overruns Pg2 ' ------------------------------------------------------------------------- ' Page 3 Code ' ------------------------------------------------------------------------- Page_3: ADDRESS $600 ' ------------------------------------------------------------------------- 'Use: BIN2BCD input, output ' where input is the starting address of a two byte array to be converted to ASCII bcd ' into output which is the address of a 5 byte array, the output is just the 5 ASCII digits ' the routine does not zero terminate them. ' input is least significant byte then most significant byte ' output is most significant digit first. BIN2BCD: ASM ' Original code by Nikolai Golovchenko found on SXLIST.COM ' Original Total execution time: ' worst case: 59 + 80 + 66 + 46 = 251 cycles ' Modified for SXB by Michael Chadwick ' Time from call through return using SXSIM ' Brief testing shows 300 cycles worst case at input 63990d $F9F6 ' Best time 133 Cycles at 12220d $2FBC ' Works properly for SX28 and SX 48/52 ' And doesn't care where the variables are located mov FSR,__PARAM1 'source address mov __PARAM3,IND 'least significant byte inc FSR mov __PARAM4,IND 'most significant byte mov FSR,__PARAM2 ' pointer to most significant digit of output clr IND ' clear result :sub30k mov W, #3 add IND, W mov W, #30000 & $FF sub __PARAM3, W mov W, #30000 >> 8 sb C mov W, #(30000 >> 8) + 1 sub __PARAM4, W snb C jmp :sub30k :add10k dec IND mov W, #10000 & $FF add __PARAM3, W mov W, #(10000 >> 8) snb C mov W, #(10000 >> 8) + 1 add __PARAM4, W sb C jmp :add10k add IND,#$30 ; convert to ASCII ;worst case: 12 * 3 + 11 * 3 - 1 = 59 inc FSR ' point to next most significant digit out clr IND :sub3k mov W, #3 add IND, W mov W, #3000 & $FF sub __PARAM3, W mov W, #3000 >> 8 sb C mov W, #(3000 >> 8) + 1 sub __PARAM4, W snb C jmp :sub3k :add1k dec IND mov W, #1000 & $FF add __PARAM3, W mov W, #(1000 >> 8) snb C mov W, #(1000 >> 8) + 1 add __PARAM4, W sb C jmp :add1k add IND,#$30 ; convert to ASCII ;worst case: 12 * 4 + 11 * 3 - 1 = 80 inc FSR ' point to next most significant digit out clr IND :sub300 mov W, #3 add IND, W mov W, #300 & $FF sub __PARAM3, W mov W, #300 >> 8 sb C mov W, #(300 >> 8) + 1 sub __PARAM4, W snb C jmp :sub300 :add100 dec IND mov W, #100 & $FF add __PARAM3, W mov W, #(100 >> 8) snb C mov W, #(100 >> 8) + 1 add __PARAM4, W sb C jmp :add100 add IND,#$30 ; convert to ASCII ;worst case: 11 * 4 + 6 * 3 + 3 = 66 inc FSR ' point to next most significant digit out clr IND mov w,#30 :sub30 inc IND sub __PARAM3, W snb C jmp :sub30 mov W, IND rl IND add IND, W mov W, #10 :add10 dec IND add __PARAM3, W sb C jmp :add10 add IND,#$30 inc FSR add __PARAM3,#$30 mov IND,__PARAM3 'least significant digit ;worst case: 6 * 4 + 6 * 3 + 4 = 46 ENDASM RETURN P3_Start: GOTO P3_Start ' error if Pg3 overruns Pg4 [/code] ---------- End of Message ---------- You can view the post on-line at: http://forums.parallax.com/forums/default.aspx?f=7&p=1&m=112538#m118027 Need assistance? Send an email to the Forum Administrator at forumadmin@parallax.com The Parallax Forums are powered by dotNetBB Forums, copyright 2002-2006 (http://www.dotNetBB.com)