20-bit BIN2BCD (Assembly) - Page 1
Forum section: electronics / general

author: jpanhalt
author_rank: Super Contributor
timestamp: November 28, 2023, 02:50:15 pm
content: Just FYIAttached is the code I have been working on for converting 20-bit binary to BCD. More discussion of that is here:https://www.eevblog.com/forum/microcontrollers/converting-bcd(mm)-to-bcd(inch)/It is based on a polynomial approach developed by Payson and posted on PICList many years ago. Related links:Link and explanation to 16-bit BIN2BCD by Payson w/ explanation by Dattalo:https://pic.hallikainen.org/techref/microchip/math/radix/b2bu-16b5d.htmLink to 17-bit BIN2BCD:https://pic.hallikainen.org/techref/microchip/math/radix/b2bu-17b5d.htm

author: DavidAlfa
author_rank: Super Contributor
timestamp: November 28, 2023, 03:13:29 pm
content: I think you'd better post your code in github, much easier to find by anyone if described with the proper tags (PIC, pic16, assembler, binary to bcd, bin2bcd ...).Here it'll get lost in no time unless someone specifically searches for "bin2cbd".

author: Sacodepatatas
author_rank: Regular Contributor
timestamp: November 28, 2023, 03:22:53 pm
content: Quote from: DavidAlfaSomebody searching for a "binary to cannabidiol" converter will not have much luck at eevblog.... 🤣

author: jpanhalt
author_rank: Super Contributor
timestamp: November 28, 2023, 03:33:37 pm
content: Thank you for adding marijuana to what Google will index for that code.They deserve it.As an aside, I was in grad school when a 1-step synthesis for THC was published. It got a huge response, and the starting material soon disappeared from every chemical catalog.

author: DavidAlfa
author_rank: Super Contributor
timestamp: November 28, 2023, 03:40:38 pm
content: now that's a hard conversion...

author: macboy
author_rank: Super Contributor
timestamp: December 02, 2023, 05:01:19 am
content: Thank you for posting.I had a look, hoping to further adapt to my 40 bit use case. Unfortunately, the original code posted to piclist is very cleverly optimised to the specific 16 bit conversion, and is not easily extended beyond the 20 bits that you took it to.I was however very intrigued by this method of BCD conversion, using accumulated powers of ten derived from each hex digit. So I wrote up the equations for the 40 bit (10 hex digits, 13 decimal digits) case, and wrote entirely new code to implement them. Those equations are vastly bigger and more complex than the relatively simple 16 bit conversion. My code is written in assembly for baseline PIC (12 bit instruction set). The code is rather big at around 550 instructions. Worst case run time I've seen is 900 cycles. That's about three to four times as fast as my double-dabble implementation, which is astounding. It is also no bigger than that slower implementation due to a big look up table I used in that one. Critically it also fits within the ~ 1900 cycle budget that I can afford within the main periodic loop of my target project. There is definitely room to reduce the code size while increasing execution time; I did lots of stuff inline instead of with loops or subroutines, to avoid lots of expensive branching. Using a mid-range (14 bit instruction) PIC could save a few dozen instructions and cycles too. I can clean up the code and post it for anyone interested.

author: jpanhalt
author_rank: Super Contributor
timestamp: December 02, 2023, 07:08:07 am
content: The approach I used based on PICList and the 17-bit version is limited to 20 bits. At least, that seems to be the case with the band aid addition. Starting anew, one could probably extend it, and with the enhanced mid-range instructions, there is less justification for keeping every equation negative. I tried some versions without offsets. The code was longer, but they still worked. That was several years ago. The 12-bit core devices do have limitations, and as I recall, Microchip has abandoned the 12F label for its newer 8-pin chips.I would be very interested in seeing your approach and how you extended it.John

author: macboy
author_rank: Super Contributor
timestamp: December 04, 2023, 05:17:00 pm
content: I've attached some PIC asm code to implement a 40-bit binary to 13-digit decimal (BCD) conversion.My approach is based upon Scott Dattalo's analysis of John Payson's code found in the piclist archive pointed to by jpanhalt in an earlier posthttps://www.eevblog.com/forum/microcontrollers/20-bit-bin2bcd-(assembly)/msg5193069/#msg5193069Some of the following is paraphrasing Scott's notes based on my own understanding. I tend to be verbose, so bear with me.We understand that a decimal number such as 3478 can be broken down as a power-of-10 weighted sum of the digits:3478 = 3*1000 + 4*100 * 7*10 + 8*1Generally:N = b3*1000 + b2*100 + b1*10 + b0= b3*103+ b2*102+ b1*101+ b0*100where bn, n=[0..3] are the decimal digitsEqually, a hexadecimal (hex) number can be written as a power-of-16 (0x10) weighted sum of its digits. For a 16-bit hex number:N = a3*16^3 + a2*16^2 + a1*16^1 + a0*16^0where an, n=[0..3] are the hexadecimal digits (16 is a decimal number for brevity).Then, expanding each 16xN = a3*4096 + a2*256 + a1*16 + a0If we desire to convert the hexadecimal number with digits aninto a decimal number with digits bn, we can re-write the equations to help. As Scott said, there are infinitely many ways to do this, since we can manipulate the equations in any valid algebraic way. We start with:N = a3*4096 + a2*256 + a1*16 + a0N = (4a3)*1000 + (0a3+2a2)*100 + (9a3+5a2+1a1)*10 + (6a3+6a2+6a1+1a0)This gives us a sum of powers-of-ten, which is what we need to represent a decimal number. It looks a lot like the first equation above:N = b3*1000 + b2*100 + b1*10 + b0Then, equations for the decimal digits b0..b4(5 digits for a general 16-bit case) can be extracted from the above:b3= 4a3b2= 2a2b1= 9a3+ 5a2+ a1b0= 6a3+ 6a2+ 6a1+ a0One may notice that there is no b4, the most significant digit, and that all of those equations can result in a number greater than 9. To extract the actual decimal digits, we need to normalize each to limit it to 0..9, just like you would "carry" when adding numbers in grade school. After that, we will have the set of decimal digits b0..b4representing the same number as the hexadecimal number with digits a0..a3Scott's description of John's highly optimized code goes on to describe various manipulations of the above equations which can reduce the work involved in the calculations (e.g. fewer multiplies) and normalizations. These are interesting, and if you are as fascinated by optimization as I am, it is worth a read.I needed to convert a 40 bit number to decimal. That is 10 hexadecimal digits, so we'll end up with a rather larger set of equations.N = a9*169+ a8*168+ a7*167+ a6*166+ a5*165+ a4*164+ a3*163+ a2*162+ a1*16 + a0N = a9*68719476736 + a8*4294967296 + a7*268435456 + a6*16777216 + a5*1048576 + a4*65536 + a3*4086 + a3*256 + a1*16 + a0We can now create the trivial set of equations for the powers-of-ten b0..b12.Let's rearrange it as a visual aid to make the job of extracting powers-of-ten easierN = a9* 6 8 7 1 9 4 7 6 7 3 6+ a8* 4 2 9 4 9 6 7 2 9 6+ a7* 2 6 8 4 3 5 4 5 6+ a6* 1 6 7 7 7 2 1 6+ a5* 1 0 4 8 5 7 6+ a4* 6 5 5 3 6+ a3* 4 0 9 6+ a2* 2 5 6+ a1* 1 6+ a0* 1Each column represents a bn.b10= 6a9b9= 8a9+ 4a8b8= 7a9+ 2a8+ 2a7b7= 1a9+ 9a8+ 6a7+ 1a6b6= 9a9+ 4a8+ 8a7+ 6a6+ 1a5b5= 4a9+ 9a8+ 4a7+ 7a6+ 0a5b4= 7a9+ 6a8+ 3a7+ 7a6+ 4a5+ 6a4b3= 6a9+ 7a8+ 5a7+ 7a6+ 8a5+ 5a4+ 4a3b2= 7a9+ 2a8+ 4a7+ 2a6+ 5a5+ 5a4+ 0a3+ 2a2b1= 3a9+ 9a8+ 5a7+ 1a6+ 7a5+ 3a4+ 9a3+ 5a2+ 1a1b0= 6a9+ 6a8+ 6a7+ 6a6+ 6a5+ 6a4+ 6a3+ 6a2+ 6a1+ 1a0You can see right away that this set of equations is far more complex than the 16-bit case described above. In addition, after doing those calculations, the bnwill be much larger than in the 16-bit case, so there is more work to normalize them, and we have many more digits to normalize.I'm using a lowly PIC with no multiply instruction, and that is a lot of multiplies! Recognize that most anare used multiple times at various multiples from 1 to 9. For example, we use multiples 1,3,4,6,7,8,9 of a9. So we can simply add a9to itself multiple times, using the intermediate result to accumulate a partial result of each bnwhich uses it. Repeat for each an. This avoids using any multiply operations.One gotcha, also not present in the 16-bit case, is that the accumulated bncan overflow. We need to detect that and account for it. Checking for overflow is easy, just check the carry bit of STATUS after adding. One effective way to account for overflow is to subtract 200 from the number, then add 2 to bn+2. In my code, I check for carry only after at least 17*anare accumulated into any bn, since 17*0xF = 255. After this point, carry must always be checked for that bn.After finishing these calculations, we still need to normalize all bninto the range 0..9 so that they represent decimal digits. The trivial way is to repeatedly subtract 10 from bnthen add 1 to bn+1, until bnis less than 10. Due to the potentially large size of each bn, this may take many iterations. The number of iterations can be reduced by first using a larger number, such as 100.The code here is considerably larger than John's original 16-bit code or the adapted 20-bit code posted in this thread, but given the scale of the work for a 40-bit number, it is reasonable. Execution time is also reasonable given that no special optimizations were made to the equations. Code size is approx 430 instructions, and execution time for worst case 0xFFFFFFFFFF is 998 instruction cycles.(edit: attached code removed due to bug, see revised code below)

author: jpanhalt
author_rank: Super Contributor
timestamp: December 04, 2023, 08:58:18 pm
content: 1000 Tcy is still a lot less than the time for Hemsley and other methods on PICList for just 32-bit. Good work.Thanks for posting. I will play later. The idea of avoiding negatives had occurred to me as a necessity as the bits increased past 20 or so, unless you wanted to go double precision. ( I haven't looked at your code yet.) However, "normalization" with newer enhanced PICs becomes easier using subtraction with positive values.Thanks again.John

author: macboy
author_rank: Super Contributor
timestamp: December 05, 2023, 10:36:19 pm
content: What good piece of software has no bugs? First, I'm not setting the digit 13 (only 0 or 1) properly. Probably introduced that when cleaning up the code. Easy to fix. But I also ran a test vector of 10000 random numbers through it and 5 had the wrong result. I'll search for that issue as time allows.

author: macboy
author_rank: Super Contributor
timestamp: December 06, 2023, 01:51:28 pm
content: The bug was a simple typo preventing one digit from being processed, causing it to later overflow only under very specific conditions.I attached fixed code here, including some added code to read test numbers from the UART, and output the result on UART. This is meant to be run in MPLAB SIM with a prepared file as input. The output file is then compared to a prepared expected output file, which should be identical. The input and expected output can be prepared by a script or with help of a spreadsheet, etc. The attached files contain almost 10000 randomly generated numbers to convert to BCD. MPLAB SIM takes only a few seconds to run the test.Good testing makes good software.

author: jpanhalt
author_rank: Super Contributor
timestamp: December 06, 2023, 06:48:39 pm
content: Thank you.I find it very difficult to proofread anything I write, including code. That is particularly true when it is fresh in my mind. I see what I wanted to say, not what is actually on paper. Reviewing something a week or so later always helps.

author: SiliconWizard
author_rank: Super Contributor
timestamp: December 06, 2023, 11:20:58 pm
content: Definitely, and that's also why having stuff reviewed by others can help as well.

author: jpanhalt
author_rank: Super Contributor
timestamp: January 03, 2024, 03:32:16 pm
content: Encouraged by macboy and not really comfortable with a band aid solution, I decided to work on a full 24-bit Binary to BCD conversion using a polynomial approach (attached) to fill the holiday week.1) It seems to work in simulation.2) I decided to post a development version with all the variations I tried to get normalization to run a little faster. I have not carefully gone over the comments.3) I have tested a variety of values to check for potential overflow problems. The attached Test Problems does not include all of them. It is simply 0x000000 to 0xFFFFFF in which each nibble (ai) is duplicated.4) Statistics:a) Average Tcy to the fill the basic equations was 88 (range 78 to 100)b) Average Tcy for each of the normalization protocols was: 263 (-10 only),243 (-20 + -10), 220 (-30 + -10), 210 (-40 +-10) and 217 (-50 + -10). That's a pretty small savings. I will use either -10 alone or -10 and -40. The macros can becleaned up, if one is only going to use one.c) Adding the averages, it's about 300 to 350 Tcy total, depending on which normalization one uses.EDIT:There is an error in the Assembly code. I forgot to add b3 (thousands). That has been corrected. The corrected average times are: 204 for -20, 199 for -30, 238 for -40, and 202 for -50, which gives a total of about 300 Tcy., with -20, -30, and -50 being about the same. I will probably use -30. The revised current code has been uploaded. As there is no way to edit attachments, i deleted the code with the error.

author: themadhippy
author_rank: Super Contributor
timestamp: January 03, 2024, 03:46:58 pm
content: jeez so much hard graft,but i suppose thats the advancement of technology ,to think a few years ago it was as hard as just chucking a 74185 or 2 into the circuit

author: macboy
author_rank: Super Contributor
timestamp: January 03, 2024, 04:38:30 pm
content: Quote from: themadhippy on January 03, 2024, 03:46:58 pmA 74185 or 2 ... or 27.Yes, 27 of those ICs for 20-bit binary to BCD conversion. Of course, you got the result in circa microsecond time scale, orders of magnitude faster than the microcontroller. I can't imagine the 40-bit hardware version. If you have a binary number on a bus, and need a BCD number on a bus, very quickly, then a hardware solution might be the one. If you have a 40 bit number in microcontroller memory, and need to consume the result in the microcontroller, then a software solution is called for. Horses for Courses or whatever.The conversion between number bases (the fundamental problem being solved here) is non-trivial especially for large numbers. For some, creating and optimizing the algorithm is fun and rewarding because of the challenge.

author: jpanhalt
author_rank: Super Contributor
timestamp: January 03, 2024, 04:50:35 pm
content: This ultimately is for my project to reuse the linear scales from my Mitutoyo DRO on my Bridgeport-type mill on my lathe. At 16 MHz, 1000 Tcy to go from BCD mm to BCD inch won't be a noticeable delay. Of course, that DRO could be used directly, but not for controlling any of the lathe functions, such as controlling threading. The slowest part will be the scales, which can only be read about every 30 to 50 ms or so.

author: PCB.Wiz
author_rank: Super Contributor
timestamp: January 03, 2024, 10:12:24 pm
content: Quote from: jpanhalt on January 03, 2024, 04:50:35 pmI looked at my notes for 8051, and found a Bin32ToBCD10R, that does 32bit BIN to 10 BCD digits, in 77 bytes and 70~85us on an older 1T 8051 @ 24MHz sysclk.

author: jpanhalt
author_rank: Super Contributor
timestamp: January 03, 2024, 10:22:27 pm
content: Sure, but that MCU is not a PIC. Please convert it to the PIC RISC so we can compare. The midrange PIC's have very limited math capability and lots of peripherals.

author: jpanhalt
author_rank: Super Contributor
timestamp: January 04, 2024, 04:10:06 pm
content: There was an error in the code attached to post #14. That has been corrected. See edit there.