PDA

View Full Version : Using Floating Point to integer subroutines



Luckyborg
- 4th March 2014, 16:29
I am having trouble using Microchips floating point routines, and I believe I'm just missing or misreading something simple. I don't actually want to do any math, but I am taking a float from a serial stream and want to display the value with 1 decimal point. I am hard coding an easy float into aint. I have used multiple online converters to verify that 50.0 = 0x42480000. I chose it because it is nice and round and does not use the parity bit for any of the bytes when I get to the point of going back to a serial line. I can't seem to get either ftoia or itofb to do what I thought they should do.



include "fp1832l.bas"

aint = $42480000
serout2 portc.6,newbaud,["a hex value = ", hex8 aint]
gosub ftoia
serout2 portc.6,newbaud,["after conversion, a hex value = ", hex8 aint]


bint = 10
serout2 portc.6,newbaud,["b hex value = ", hex8 bint]
gosub itofb 'convert to float
serout2 portc.6,newbaud,["after conversion, b hex value = ", hex8 bint]

For inta the hex value before is displayed correctly, $42480000, however the value after conversion is the exact same
For intb, the hex value is as expected, $0000000A, but after the conversion it is $20000000. the online calculators show $41200000 is what a 10 should look like as a float.

If there is an easier way to get what I need, I would appreciate it or just helping me see what I'm missing. Again, I don't necessarily need math. I just want to convert a single float into a couple of variables for each side of the decimal to display.
Thanks for the clarification
David

HenrikOlsson
- 4th March 2014, 17:12
Hi,
This is new teritory for me but looking at the FPREADME.TXT it seems to me that you're basically using the wrong variables.


itofa Convert integer aint to floating point aarg
itofb Convert integer bint to floating point barg
fpadd Perform floating point addition: aarg + barg
fpsub Perform floating point subtraction: aarg - barg
fpmul Perform floating point multiplication: aarg * barg
fpdiv Perform floating point division: aarg / barg
ftoia Convert floating point aarg to integer aint

The way I interpret this is that use ftoia you should load the floating point number into aarg (not aint, like you're doing) and retrieve the result from aint. For itofb, you should load the integer value to bint and retrieve the result from barg (not bint, like you're doing).

Could that be it?

/Henrik.

Darrel Taylor
- 4th March 2014, 17:37
Along with what Henrik said ...


I have used multiple online converters to verify that 50.0 = 0x42480000.

Most online convertors will use the IEEE floating point format. The format that is used in most PC languages.
But Microchip uses a different format. And 50 in Microchip's format is 0x84480000.

So if you are receiving IEEE formatted floats, you will not be able to convert them with the Microchip Floating Point routines without first converting to Microchip format.

Luckyborg
- 4th March 2014, 17:44
I gave it a try, but aarg and barg are not declared. I loaded up the FP1832L.bas file to take a look and found aint and bint, and the comments say that aint is the Long access to AARG. My understanding is that any call on aint will overwrite itself with the new value and the original value of aint is lost.


I pretty much based my code on the what I found on melabs website http://melabs.com/resources/fp.htm
You had my hopes up though. Thanks for looking
David

Luckyborg
- 4th March 2014, 17:54
Thanks Darrel, I didn't realize microchip had its own format. Any idea on how to convert the IEEE standard?

Luckyborg
- 4th March 2014, 19:06
I found some C code that helped with the transition. When I get everything running I'll post it. I was able to translate the 42480000 to 84480000 but I'm still getting nothing out of the ftoia call. The value of aint is the same before and after. I looked through the include files and the best I can tell is aint should be the variable being changed.



aint = S_RateL 'copy over
serout2 portc.6,newbaud,["hex value = ", hex8 aint]
gosub ftoia
serout2 portc.6,newbaud,["after conversion hex value = ", hex8 aint]

Darrel Taylor
- 4th March 2014, 20:53
C code ???? Yuck!

And you're still missing Henrik's point. The Float goes in AARG (starting at AARGB2) not Aint which starts at AARGB3.


;----[Variables]----------------------------------------------------------------
A VAR LONG
B VAR LONG
A_Float VAR LONG EXT : @A_Float = AARGB2 ;
B_Float VAR LONG EXT : @B_Float = BARGB2 ;

;----[macro Converts IEEE to Microchip FP format]-------------------------------
ASM
IEEEtoMCHIP?NN macro Nin, Nout
MOVE?BB Nin, Nout
MOVE?BB Nin+1, Nout+1
MOVE?BB Nin+2, Nout+2
MOVE?TT Nin+3,7, Nin+2,7
MOVE?BA Nin+3
RLNCF WREG,W
MOVE?AB Nout+3
MOVE?TT Nin+2,7, Nout+3,0
endm
ENDASM

;----[Test IEEE to Microchip conversion]---------------------------------------
A = $42480000 ; 50 - IEEE
GOSUB ShowConversion

A = $C1CCF5C3 ; -25.62 - IEEE
GOSUB ShowConversion

STOP
;----[Show conversion via HSEROUT]---------------------------------------------
ShowConversion:
HSEROUT ["IEEE = ",HEX8 A,13,10]

@ IEEEtoMCHIP?NN _A, _B
HSEROUT ["Mchip= ",HEX8 B,13,10]

A_Float = B
GOSUB FtoIA
HSEROUT ["Aint = ",SDEC Aint,13,10]
A = Aint

A_Float = B ; with 1 decimal place
Bint = 10
GOSUB ItoFB
GOSUB fpmul
GOSUB FtoIA
HSEROUT [" ",SDEC Aint/10,".",DEC1 ABS(Aint),13,10]


A_Float = B ; with 2 decimal places
Bint = 100
GOSUB ItoFB
GOSUB fpmul
GOSUB FtoIA
HSEROUT [" ",SDEC Aint/100,".",DEC2 ABS(Aint),13,10,13,10]
RETURN


7262

Luckyborg
- 4th March 2014, 23:19
Thanks to you both, that was the information I needed. I went through the readme file and the FP1832L.bas file again and I still don't see where it says AARG starts at AARGB2, but you obviously know what your talking about because I have been able to make progress on my project now. Thanks again.

HenrikOlsson
- 5th March 2014, 06:47
Hi,
In this case I certainly won't take any credit because right now I don't understand it either. I'm looking at the README and at the FP1832L.BAS and I don't see it.
I wonder if it's a byte order thing or something like that?

/Henrik.

Darrel Taylor
- 5th March 2014, 07:52
Well, having never used the Floating Point routines before ... you still knew the value went in AARG instead of Aint ... that's worth something.
I guess it's easier when you know how it works.

A floating point value consists of 4 bytes (32-bits).
The highest byte is the exponent.

Looking at the list of variables in FP1832L.bas, the only way to put 4 bytes in a row with the exponent lining up with AEXP is to start at AARGB2 ($1d).


aint var long $1c ' Long access to AARG
AARGB3 var aint.byte0 ' $1c
AARGB2 var aint.byte1 ' $1d
AARGB1 var aint.byte2 ' $1e
AARGB0 var aint.byte3 ' $1f
AEXP var byte $20

Microchip saves RAM space by using the same memory for Floats and Integers.
But when you have an integer value, the LONG variable uses AARGB3-AARGB0 (aint).

I believe the routines were intended to be used by starting with integers, converting to floats, and doing the math from there.
They were never intended to accept previously encoded floating-point values, whether IEEE or Microchip format.
Hence that ability is not documented.

Undocumented features are way more fun than the documented ones. :)