Floating point representation and sharing

Coding and general discussion relating to the compiler

Moderators: David Barker, Jerry Messina

Post Reply
SHughes_Fusion
Posts: 219
Joined: Wed Sep 11, 2013 1:27 pm
Location: Chesterfield

Floating point representation and sharing

Post by SHughes_Fusion » Mon Sep 21, 2015 9:46 am

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.

Jerry Messina
Swordfish Developer
Posts: 1469
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: Floating point representation and sharing

Post by Jerry Messina » Mon Sep 21, 2015 2:48 pm

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:

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)
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.
I only need a quite limited resolution - no better than to hundredths
You could always used a scaled integer representation to handle the decimals (ie 10.00 = 1000), but you still have the data representation issue.
it will be RS485 all the way so I can go to a text-based transmission but that isn't that compatible with SPI.
Could you expand on that? Why can't you transfer ASCII data via SPI?

SHughes_Fusion
Posts: 219
Joined: Wed Sep 11, 2013 1:27 pm
Location: Chesterfield

Re: Floating point representation and sharing

Post by SHughes_Fusion » Mon Sep 21, 2015 3:00 pm

Jerry Messina wrote:
it will be RS485 all the way so I can go to a text-based transmission but that isn't that compatible with SPI.
Could you expand on that? Why can't you transfer ASCII data via SPI?
Thanks, Jerry, I'll give that a go.

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.

Post Reply