Here is an elegant way to convert a BCD byte value in 'b0' into its decimal equivalent in 'b0', or into another variable if the original value of 'b0' has to be retained ...
b0 = b0 / 16 * MINUS_6 + b0
This uses less code space, is faster, and requires no additional variable as the more commonly used conversion code does ...
b1 = b0 / 16 * 10
b0 = b0 & 15 | b1
Demo code which runs in the simulator and real chip to show that it works follows ...
The trick behind the conversion is thinking in a different way to trying to create the decimal value from the two BCD nibbles individually; how would one need to adjust the decimal value of the BCD number ( as it is ) to get what one actually wants ... ?
$10 = 16, should be 10, so need to subtract 6
$20 = 32, should be 20, so need to subtract 12
$30 = 48, should be 30, so need to subtract 18
$40 = 64, should be 40, so need to subtract 24
$50 = 80, should be 50, so need to subtract 30
etc
There is a very obvious and convenient pattern; the number we need to subtract is the most significant BCD nibble multiplied by six. What we would like to use as a conversion expression is ...
b0 = b0 - ( (b0/16) * 6 )
That however will not pass syntax check so we need to rearrange it to something which does.
First -(a*b) can equally be represented as a*(-b) so ...
b0 = b0 - ( (b0/16) * 6 )
becomes
b0 = b0 + ( (b0/16) * -6 )
Addition is commutative, a+b is the same as b+a, so ...
b0 = b0 + ( (b0/16) * -6 )
becomes
b0 = ( (b0/16) * -6 ) + b0
And now the precedence of operation there matches the left to right nature of PICAXE maths, so we can simply take out the parenthesis ( round brackets ) ...
b0 = b0 / 16 * -6 + b0
Unfortunately it is not possible to just place "-6" in the middle of an assignment expression on a PICAXE without a syntax error but that "-6" can be replaced by something defined by a SYMBOL statement so we end up with ...
b0 = b0 / 16 * MINUS_6 + b0
Defining MINUS_6 in a SYMBOL statement is a bit of a challenge if one wants to do it in a single line. First "-6" is not acceptable syntax by itself, and while "0-6" is valid and creates the desired value, that generates a 32-bit number so needs to be masked with $FFFF to limit it to 16-bits for use with PICAXE maths. Unfortunately the SYMBOL only allows one operator per SYMBOL so this would have to be done in two steps with two SYMBOL statements.
One pragmatic solution is to calculate -6 by hand ($FFFA) and just drop that into the single SYMBOL statement ...
Symbol MINUS_6 = $FFFA ; -6 = 0 - 6 & $FFFF
Another is to force 16-bit compliance not by subtracting 6 from 0 but from $10000 ...
Symbol MINUS_6 = $10000 - 6
However the MINUS_6 constant is created it has no impact on the expression code size or execution speed; both create a value of $FFFA or -6 for 16-bit maths use.
b0 = b0 / 16 * MINUS_6 + b0
This uses less code space, is faster, and requires no additional variable as the more commonly used conversion code does ...
b1 = b0 / 16 * 10
b0 = b0 & 15 | b1
Demo code which runs in the simulator and real chip to show that it works follows ...
Code:
b0 = $09 : Gosub Convert
b0 = $18 : Gosub Convert
b0 = $27 : Gosub Convert
b0 = $36 : Gosub Convert
b0 = $45 : Gosub Convert
b0 = $54 : Gosub Convert
b0 = $63 : Gosub Convert
b0 = $72 : Gosub Convert
b0 = $81 : Gosub Convert
b0 = $90 : Gosub Convert
End
Symbol MINUS_6 = $10000 - 6
Convert:
b0 = b0 / 16 * MINUS_6 + b0
SerTxd( #b0, " " )
Return
Code:
For b1 = $00 to $90 Step $10
For b2 = $0 To $9
b0 = b1 | b2 : Gosub Convert
Next
Next
End
Symbol MINUS_6 = $10000 - 6
Convert:
b0 = b0 / 16 * MINUS_6 + b0
SerTxd( #b0, " " )
Return
$10 = 16, should be 10, so need to subtract 6
$20 = 32, should be 20, so need to subtract 12
$30 = 48, should be 30, so need to subtract 18
$40 = 64, should be 40, so need to subtract 24
$50 = 80, should be 50, so need to subtract 30
etc
There is a very obvious and convenient pattern; the number we need to subtract is the most significant BCD nibble multiplied by six. What we would like to use as a conversion expression is ...
b0 = b0 - ( (b0/16) * 6 )
That however will not pass syntax check so we need to rearrange it to something which does.
First -(a*b) can equally be represented as a*(-b) so ...
b0 = b0 - ( (b0/16) * 6 )
becomes
b0 = b0 + ( (b0/16) * -6 )
Addition is commutative, a+b is the same as b+a, so ...
b0 = b0 + ( (b0/16) * -6 )
becomes
b0 = ( (b0/16) * -6 ) + b0
And now the precedence of operation there matches the left to right nature of PICAXE maths, so we can simply take out the parenthesis ( round brackets ) ...
b0 = b0 / 16 * -6 + b0
Unfortunately it is not possible to just place "-6" in the middle of an assignment expression on a PICAXE without a syntax error but that "-6" can be replaced by something defined by a SYMBOL statement so we end up with ...
b0 = b0 / 16 * MINUS_6 + b0
Defining MINUS_6 in a SYMBOL statement is a bit of a challenge if one wants to do it in a single line. First "-6" is not acceptable syntax by itself, and while "0-6" is valid and creates the desired value, that generates a 32-bit number so needs to be masked with $FFFF to limit it to 16-bits for use with PICAXE maths. Unfortunately the SYMBOL only allows one operator per SYMBOL so this would have to be done in two steps with two SYMBOL statements.
One pragmatic solution is to calculate -6 by hand ($FFFA) and just drop that into the single SYMBOL statement ...
Symbol MINUS_6 = $FFFA ; -6 = 0 - 6 & $FFFF
Another is to force 16-bit compliance not by subtracting 6 from 0 but from $10000 ...
Symbol MINUS_6 = $10000 - 6
However the MINUS_6 constant is created it has no impact on the expression code size or execution speed; both create a value of $FFFA or -6 for 16-bit maths use.