16bit SX-28 BIN2BCD routine
Hi,
Does anybody out there have a working 16bit Binary to BCD routine in SX assembler?
Any help would be much appreciated.
Best regards
Frasse
Does anybody out there have a working 16bit Binary to BCD routine in SX assembler?
Any help would be much appreciated.
Best regards
Frasse

Comments
bin2bcd bank SCRATCH mov W, <>NumH ;w = A2*16+A3 or W, #$F0 ;w = A3-16 mov Thou, W ;B3 = A3-16 add Thou, W ;B3 = 2*(A3-16) = 2A3 - 32 mov Hund, W mov W, #$E2 add Hund, W ;B2 = A3-16 - 30 = A3-46 mov W, #$32 add W, Hund mov Ones, W ;B0 = A3-46 + 50 = A3+4mov W, NumH ;w = A3*16+A2 and W, #$0F ;w = A2 add Hund, W ;B2 = A3-46 + A2 = A3+A2-46 add Hund, W ;B2 = A3+A2-46 + A2 = A3+2A2-46 add Ones, W ;B0 = A3+4 + A2 = A3+A2+4mov Tens, W mov W, #$E9 add Tens, W ;B1 = A2-23 mov W, Tens add Tens, W ;B1 = 2*(A2-23) add Tens, W ;B1 = 3*(A2-23) = 3A2-69 (Doh! thanks NG)mov W, <>NumL ;w = A0*16+A1 and W, #$0F ;w = A1 add Tens, W ;B1 = 3A2-69 + A1 = 3A2+A1-69 range -69...-9 add Ones, W ;B0 = A3+A2+4 + A1 = A3+A2+A1+4 and Carry = 0 (thanks NG)rl Tens ;B1 = 2*(3A2+A1-69) + C = 6A2+2A1-138 and Carry is now 1 as tens register had to be negitive rl Ones ;B0 = 2*(A3+A2+A1+4) + C = 2A3+2A2+2A1+9 (+9 not +8 due to the carry from prev line, Thanks NG) not Ones ;B0 = ~(2A3+2A2+2A1+9) = -2A3-2A2-2A1-10 (ones complement plus 1 is twos complement. Thanks SD) ;;Nikolai Golovchenko [noparse][[/noparse]golovchenko at MAIL.RU] says: complement [noparse][[/noparse]not Ones] can be regarded like: ;; not Ones ;; inc Ones ;; dec Ones ;;First two instructions make up negation. So, ;;Ones = -Ones - 1 ;; = - 2 * (A3 + A2 + A1) - 9 - 1 ;; = - 2 * (A3 + A2 + A1) - 10 rl Ones ;B0 = 2*(-2A3-2A2-2A1-10) = -4A3-4A2-4A1-20mov W, NumL ;w = A1*16+A0 and W, #$0F ;w = A0 add Ones, W ;B0 = -4A3-4A2-4A1-20 + A0 = A0-4(A3+A2+A1)-20 range -215...-5 Carry=0 rl Thou ;B3 = 2*(2A3 - 32) = 4A3 - 64mov W, #$07 ;w = 7 mov TenK, W ;B4 = 7mov W, #$0A ;w = 10 Lb1: ;do add Ones, W ; B0 += 10 dec Tens ; B1 -= 1 sb 3.0 ;skip no carry jmp Lb1 ; while B0 < 0 ;jmp carry Lb2: ;do add Tens, W ; B1 += 10 dec Hund ; B2 -= 1 sb 3.0 jmp Lb2 ; while B1 < 0 Lb3: ;do add Hund, W ; B2 += 10 dec Thou ; B3 -= 1 sb 3.0 jmp Lb3 ; while B2 < 0 Lb4: ;do add Thou, W ; B3 += 10 dec TenK ; B4 -= 1 sb 3.0 jmp Lb4 ; while B3 < 0mov w,#$30 ; convert to ASCII add TenK,w add Thou,w add Hund,w add Tens,w add Ones,w retp▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
MRC
Thanks ever so much for your posted routine for conversion - works like a dream!
That is when I'm singlestepping it in the debugger. However I am planning to use it as a subroutine within a SXB program and have not been able to get it working in that environment.
I think I know how to pass the parameters to the subroutine, however I think I'm messing things up when putting the routine in another memory bank.
I equated the start of the subroutine way out of the way of the "basic code" according to the device listing, but trying to singlestep a SXB program I·get totally·lost among all the embedded bank statements.
Do you happen to have any example of how to call the (a) subroutine from within an SXB program? I would be very greatful.
Best regards and many thanks
Hans alias Frasse
I have only used bin2bcd with assembly language. I have not used it with SXB as I only·use SXB to do quick test programs.
I will look into how to make the bin2bcd work as an SXB subroutine using the parameter variables to pass in the 16 bit value. It would be a valuable exercise for me.
It will take me a day or two before I can get to it.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
MRC
Very kind of you, it will be very much appreciated.
I am eagerly waiting.
Regards
Hans
It is going to be a bit longer than I anticipated, we have had a death in the family. [noparse]:([/noparse]
My father in law, who I loved very much, has passed on.
Later this week, when things settle out some I'll get back to work.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
MRC
Sorry to hear about your great loss.
Take all the time you need! After all it's only a hobby ours. Some things are more important than others and your family is by far the most important.
Regards
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.
' ========================================================================= ' ' 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▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
MRC