I'm developing an application, part of which will be a bridge between a PIC which controls a heater and an ARM-based system. I need to pass various data to the ARM-based system which includes floating point numbers.
From what I have found Swordfish uses a proprietary floating-point format. Is there any way to convert this to a more standard format so I can pass this to the ARM? This uses the Keil compiler so I presume will use the IEEE standard format?
Other than that, can anyone think of a better way to do this? I only need a quite limited resolution - no better than to hundredths, we may even be able to get away with tenths. Numbers can be negative but will not go above about 1000. (Or below -1000)
This is an intermediate step, I've got the actual heater controller which feeds in to an RS485 to SPI converter as the existing equipment does not have an RS485 port. The ARM unit will therefore be performing SPI read / write operations to access the data (and to write any settings). Once we go to the new main hardware it will be RS485 all the way so I can go to a text-based transmission but that isn't that compatible with SPI.
Floating point representation and sharing
Moderators: David Barker, Jerry Messina
-
- Posts: 219
- Joined: Wed Sep 11, 2013 1:27 pm
- Location: Chesterfield
-
- Swordfish Developer
- Posts: 1473
- Joined: Fri Jan 30, 2009 6:27 pm
- Location: US
Re: Floating point representation and sharing
Swordfish floats use the Microchip 32-bit low:high representation that was used in old versions of PIC18 (v2.3) and the CCS C compiler.
If you want to swap between the MC 32 bit and IEEE-754 formats:
I'm not a fan of passing binary data between systems since the data representations rarely match, and if anything changes on either end then both sides have to be changed since they're not compatible anymore. I prefer to transfer them as ASCII strings... more bother but it always works.
If you want to swap between the MC 32 bit and IEEE-754 formats:
Code: Select all
// SF floats are in 32-bit Microchip format, low:high
structure sf_float_t
b(4) as byte union
ul as longword union
f as float union
end structure
structure ieee_t
b(4) as byte union
ul as longword union
f as float union
end structure
{
+-----------+-----------+-----------+-----------+
| eb | f0 | f1 | f2 |
+------------------+-----------+-----------+-----------+-----------+
| IEEE754 32-bit | sxxx xxxx | yxxx xxxx | xxxx xxxx | xxxx xxxx |
+------------------+-----------+-----------+-----------+-----------+
| Microchip 32-bit | xxxx xxxx | sxxx xxxx | xxxx xxxx | xxxx xxxx |
+------------------+-----------+-----------+-----------+-----------+
The conversion from MCHP <--> IEEE754 requires the upper two bytes
be rotated to move the sign bit around.
note: there are two Microchip 32-bit formats- high:low and low:high
The above assumes high:low format (NOT the 32-bit low:high format)
}
function mchptoieee (mc_float as sf_float_t) as ieee_t
dim ieee_fmt as ieee_t
dim b as byte
// swap mc low:high format to high:low
b = mc_float.b(0)
mc_float.b(0) = mc_float.b(3)
mc_float.b(3) = b
b = mc_float.b(1)
mc_float.b(1) = mc_float.b(2)
mc_float.b(2) = b
// do the sign bit manipulation
FSR0 = addressof(mc_float) + 2
asm
bcf STATUS, 0, 0
rlcf POSTINC0, 1, 0
rrcf POSTDEC0, 1, 0
rrcf INDF0, 1, 0
end asm
ieee_fmt.ul = mc_float.ul
result = ieee_fmt
end function
function ieeetomchp (ieee_float as ieee_t) as float
dim b as byte
// do the sign bit manipulation
FSR0 = addressof(ieee_float) + 2
asm
bcf STATUS, 0, 0
rlcf POSTINC0, 1, 0
rlcf POSTDEC0, 1, 0
rrcf INDF0, 1, 0
end asm
// swap mc high:low format to low:high
b = ieee_float.b(0)
ieee_float.b(0) = ieee_float.b(3)
ieee_float.b(3) = b
b = ieee_float.b(1)
ieee_float.b(1) = ieee_float.b(2)
ieee_float.b(2) = b
result = ieee_float.f
end function
dim ieeef1 as ieee_t
dim sf1 as sf_float_t
dim sf2 as sf_float_t
sf1.f = 1.23456
ieeef1 = mchptoieee(sf1)
sf2.f = ieeetomchp(ieeef1)
sf1.f = -1.23456
ieeef1 = mchptoieee(sf1)
sf2.f = ieeetomchp(ieeef1)
You could always used a scaled integer representation to handle the decimals (ie 10.00 = 1000), but you still have the data representation issue.I only need a quite limited resolution - no better than to hundredths
Could you expand on that? Why can't you transfer ASCII data via SPI?it will be RS485 all the way so I can go to a text-based transmission but that isn't that compatible with SPI.
-
- Posts: 219
- Joined: Wed Sep 11, 2013 1:27 pm
- Location: Chesterfield
Re: Floating point representation and sharing
Thanks, Jerry, I'll give that a go.Jerry Messina wrote:Could you expand on that? Why can't you transfer ASCII data via SPI?it will be RS485 all the way so I can go to a text-based transmission but that isn't that compatible with SPI.
As for SPI, I should have said that it seems awkward to handle variable length strings across an SPI bus. I was planning something similar to how you'd access a typical SPI chip, the master sends a register ID the the slave clocks out the number of bytes associated with that register.
I guess there is no reason it couldn't keep clocking bytes out until a null is received, or that I couldn't pad the strings to a fixed size. It just seems that typically binary data of a fixed size is the most commonly used type when communicating over SPI.
If everything is a float then I can specify an SPI transaction of 5 bytes, one 'register address' from the master followed by 4 data bytes from the slave.
I have a feeling the SPI bus on this other equipment is clocked quite slowly - I have a feeling it is under 100kHz so again the shorter the data packets can be, the better.
I'm open to suggestions of other ways to do it, this just seemed the obvious way from what I've done with SPI in the past.