Hex to base 10 and divide
![VonSzarvas](https://forums.parallax.com/uploads/userpics/814/n2KKWCY80HQA7.png)
Hello all,
I have a 2 byte hex number, stored as a byte array (I appreciate a Word would also do this with SX/B)
TestInput VAR Byte(2)
TestOutput VAR Byte(5)
And using the ASM version of BIN2BCD by Michael Chadwick http://forums.parallax.com/showthread.php?p=579269
I can convert (for example) 01c2 to 00451.
This represents a temperature reading. I would need to divide the decimal 451 by 16 to get 25.25 degrees, and store the result for later output or math.
I have proven the BIN2BCD works by displaying the decimal result of the subroutine thus:
When TestInput(0) and (1) = 01, c2 ; The output is correctly displayed as 00451.
The 10,000 and 1,000's are not important, as temp will not be above 999 degrees! So I can just consider TestOutput(2), (3) & (4)
In theory, I would like to achieve the result in a Word, with the msb equal to the whole number, and the lsb equal to the decimal places.
So with the example 451 / 16 :
TestResult VAR Word
TestResult = 28, 18
So far I have tried various techniques cobbled out of information on this forum.
I think the issue is getting to do the equations 451 / 16 and 451 // 16 to get the MSB and LSB results.
Each time the non-decimal version of the number seems to get divided, so in essence the issue is my lack of knowledge in how to handle numbers properly!
Maybe if I could convert the original 01c2 hex code into 1 byte as decimal 451 (rather than the 5 byte array that BIN2BCD does), then I could just divide it and split out the MSB and LSB? Of course I can't because of the 255 byte limit, but maybe as a word....
Anyhow, I hope my plight is clear, if anyone has some advice to help me.
Many thanks, Max.
I have a 2 byte hex number, stored as a byte array (I appreciate a Word would also do this with SX/B)
TestInput VAR Byte(2)
TestOutput VAR Byte(5)
And using the ASM version of BIN2BCD by Michael Chadwick http://forums.parallax.com/showthread.php?p=579269
I can convert (for example) 01c2 to 00451.
This represents a temperature reading. I would need to divide the decimal 451 by 16 to get 25.25 degrees, and store the result for later output or math.
I have proven the BIN2BCD works by displaying the decimal result of the subroutine thus:
BIN2BCD TestInput, TestOutput TX_BYTE TestOutput(0) TX_BYTE TestOutput(1) TX_BYTE TestOutput(2) TX_BYTE TestOutput(3) TX_BYTE TestOutput(4)
When TestInput(0) and (1) = 01, c2 ; The output is correctly displayed as 00451.
The 10,000 and 1,000's are not important, as temp will not be above 999 degrees! So I can just consider TestOutput(2), (3) & (4)
In theory, I would like to achieve the result in a Word, with the msb equal to the whole number, and the lsb equal to the decimal places.
So with the example 451 / 16 :
TestResult VAR Word
TestResult = 28, 18
So far I have tried various techniques cobbled out of information on this forum.
I think the issue is getting to do the equations 451 / 16 and 451 // 16 to get the MSB and LSB results.
Each time the non-decimal version of the number seems to get divided, so in essence the issue is my lack of knowledge in how to handle numbers properly!
Maybe if I could convert the original 01c2 hex code into 1 byte as decimal 451 (rather than the 5 byte array that BIN2BCD does), then I could just divide it and split out the MSB and LSB? Of course I can't because of the 255 byte limit, but maybe as a word....
Anyhow, I hope my plight is clear, if anyone has some advice to help me.
Many thanks, Max.
Comments
I switched to using Bin16DEC, courtesy of Bean (Hitt Consulting) & Michael Chadwick & John Couture
I have a Word, tmpW = 01,c2
Bin16DEC tmpW
gives 01, 194
I realised my earlier error, that the MSB 01 is actually binary 0000000100000000 and not just 1, therefore, the value would be 256! Ie. larger than 255 and lost when I was trying to shift the result.
tmpW_MSB >> 8
I will continue to experiment, but it seems I may need to divide the 01c2 by 16 before sending it to Bin16Dec, as then it will not exceed 255 (unless its really hot!)
Quite how I do that in Hex... umm, maybe divide by 10h ? ... lets see.
result >> 4
is the same as:
result / 16
Actually I just figured it may be easier to multiply the decimal result instead.. so 451 * 625 = 281875. (no probs with decimal places then).
(The device resolution is 0.0625 which is where the divide by 16 idea came from originally...)
and finally I can split that result in msb/lsb positions by dividing by 10000 twice (to get whole number and remainder)
That works better....
Now I just need to get the manipulation of the word holding my decimal value 451 sorted out...
testing...trying....learning....!
I will post a full code later once I have cleaned it up... might help someone else later.
I am close to conceding that without an external floating-point helper, this cannot be done.
Let's take 415 / 16 = 25.9375 (degrees C)
Getting the 25 is easy. But the __(W)REMAINDER doesn't work (I assume because) 9375 exceeds 255. So I get 0. (Truncated would be enough if that can be done.. would be happy to get 93?)
-- Actually, after the math (myWordVar / 16) I did try pulling the __WREMAINDER into another Word variable. But could not understand why the msb/lsb's were zero or nonsense.. maybe the WREMAINDER store itself is limited to 255 also?
Or,
Is there a way to IF/THEN on the 1st 2 digits of the decimal places? Ie. IF digits = 93 THEN gottcha. (as that is unique within this range - below)
My thinking is that as the possible range of values (resolution) is incrementing by 0.0625, then there can only be 16 (if you include 0) possible variations of the decimals:
0,0000
0,0625 16
0,1250 32
0,1875 48
0,2500 64
0,3125 80
0,3750 96
0,4375 112
0,5000 128
0,5625 144
0,6250 160
0,6875 176
0,7500 192
0,8125 208
0,8750 224
0,9375 240
1,0000 256
Trying every way I can, I keep hitting something bigger than 255/65535 when doing the math....
Well if it can't be done, I will stick to sending the hex code to the PC, and do the translation there. It would have been nice of the SX to do that for me, but oh well!
-- Actually, this is an SX-28, maybe the SX-48 can handle it?
Good evening all!
Post Edited (Maxwin) : 9/10/2007 12:16:17 AM GMT
result = sensor >> 4
result = result + sensor.3
Yes, that's it, and here's how it works. The first line reduces the raw sensor value to a whole number. Since the lower four bits of the sensor value represent the fractional portion, all you have to do is add bit3 because this bit is set when the fractional portion is 0.5 (decimal) or higher.
If, on the other hand, you're wanting to recover the fractional portion and return it as a byte, you could do this:
frac = sensor_LSB & $0F
frac = frac */ $0640
result = sensor >> 4
The first line saves the fractional bits then multiplies them by 6.25 (using */).
SX/B is no more/less capable on the SX48 as SX28 (outside of supporting specific hardware features).
Post Edited (JonnyMac) : 9/10/2007 1:40:13 AM GMT
Anyhow, I have decided to go with the "send hex to PC, and process there" route for this project, as the inclusion of this extra code also costs me memory space which I need for other functions.
However, I have learnt some valuble maths techniques here, which I am really grateful for and am sure will be useful sometime soon.
Thanks again JonnyMac.
Max.
Check out this page:
www.sxlist.com/cgi-bin/constdivmul.exe?cpu=sx
It generates SX (or PIC) code for multiplying or dividing by a constant. Great stuff.
Thanks,
PeterM