Help - Floating point, Microchip-> IEEE 754

General discussion on mikroPascal.
Post Reply
Author
Message
FRM
Posts: 381
Joined: 20 May 2005 18:58
Location: UK

Help - Floating point, Microchip-> IEEE 754

#1 Post by FRM » 18 Jan 2007 10:30

Hi,
I some help in handling mP-Microchip float hex values sent to PC via RS232 at the PC side.

I think the mE team should know this one as they have Delphi code that does what I need in the mP IDE Convertor tool.

I'm using Delphi7 at the PC side, but seem to be having difficulties in finding a 3rd party component specifically to deal with Microchip format numbers...
I need to convert the Microchip float value to IEEE754 on the PC.

Does anyone have any experiences of this? I don't want to convert to string prior to sending out rs232, as I cannot afford any more processing time. I am sending the bytes efficiently as absolute addressed bytes of a real-type variable.

Wish-list:
Maybe a useful option in the IDE would be the option of choosing between Microchip/IEEE754 format for floating-point numbers.

Thanks in advance.

FRM
Posts: 381
Joined: 20 May 2005 18:58
Location: UK

#2 Post by FRM » 18 Jan 2007 13:46

Solved!
After delving deeper into the internet, I found the PIC format explained.
Comparing the differences, I realised the difference in the exponent <> Sign bit relationship and wrote some logic to process the incoming bytes and viola!...it works.

In delhi I wrote:

Code: Select all

tr1_IEEE[0] := Rx_Buff[0];
tr1_IEEE[1] := Rx_Buff[1];
tr1_IEEE[2] := (Rx_Buff[2] and (255 - 128)) or (Rx_Buff[3] and 1) shl 7;
tr1_IEEE[3] := (Rx_Buff[3] shr 1) or (Rx_Buff[2] and 128);
where Rx_buff[x] contains the Microchip format single precision lo-highest bytes. Tr1 is single precision in Delphi, with tr1_IEEE[x] referencing as absolute Tr1.

I couldn't find the Microchip format explained anywhere in the mP documentation, but maybe I missed it.

Hope it helps anyone as much as it helped me!

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

Re: Help - Floating point, Microchip-> IEEE 754

#3 Post by janni » 18 Jan 2007 13:51

FRM wrote:Hi,
I some help in handling mP-Microchip float hex values sent to PC via RS232 at the PC side.

I think the mE team should know this one as they have Delphi code that does what I need in the mP IDE Convertor tool.
I'm sure they do :) , but may not have the time to help you immediately.

There are two ways to do it - manipulate the bits of 32-bit Microchip number to get a number of type single in Delphi, or work on bytes without worring about details (like difference in ranges). Although I lately use the first approach (but mostly on PIC side), the latter is more popular and more convenient for you. Here's an example:

Code: Select all

type 
     picbuf = array [1..4] of byte;

Function pic2float(RxBuf:picbuf):double;
 var i,e,sgn: integer;
     hib: byte;
     ex,res: double;
     ress: array [1..3] of double;
 begin
  e:=RxBuf[1];
  for i:=1 to 3 do begin ress[i]:=RxBuf[i+1]; e:=e+RxBuf[i+1] end;
  if e<>0 then
   begin
    e:=RxBuf[1]-127;
    if ress[1]>127 then sgn:=-1 else begin sgn:=1; ress[1]:=ress[1]+128 end;
    res:=sgn*(ress[1]/128.0+ress[2]/32768.0+ress[3]/8388608.0);
    if e<0 then hib:=-e else hib:=e;
    ex:=1;
    if hib>0 then for i:=1 to hib do ex:=ex*2;
    if e<0 then res:=res/ex else res:=ex*res;
   end else res:=0;
  pic2float:=res;
 END;{pic2float}
Take into account that the RxBuf array contains the four bytes of Microchip floating-point format in original order. mP uses reversed order in PIC memory (LSB first).

FRM
Posts: 381
Joined: 20 May 2005 18:58
Location: UK

#4 Post by FRM » 18 Jan 2007 14:43

janni - Many thanks for your reply and useful code. I think we must have crossed posts!
:wink:

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

#5 Post by janni » 18 Jan 2007 15:11

FRM wrote:janni - Many thanks for your reply and useful code. I think we must have crossed posts!
:wink:
Yea, that we did :D .

In your bit-manipulating method you have to take into account some more subtle differences between both formats. For example, exponent of value FF in Delphi type single means either infinity or NAN (not a number), while it's still within normal range in Microchip format. And there are other differences in notation. Compare AN575 and Delphi help on real types.

FRM
Posts: 381
Joined: 20 May 2005 18:58
Location: UK

#6 Post by FRM » 18 Jan 2007 15:30

Yes, good points. I will study the differences further.
Thanks again.

Andreas
Posts: 139
Joined: 05 Feb 2005 12:43
Location: Germany

Re: Help - Floating point, Microchip-> IEEE 754

#7 Post by Andreas » 25 Dec 2015 23:00

Many thanks for the Delphi code. Do you also have the reverse function "float2pic" ?

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

Re: Help - Floating point, Microchip-> IEEE 754

#8 Post by janni » 26 Dec 2015 17:36

Yes. It's somewhat expensive computationally, but it may be used with any real type, regardless of internal format. As with the reverse function, result is formed in original Microchip format (big endian), unlike in mP.

Code: Select all

type picbuf = array [1..4] of byte;

Function float2pic(arg:double):picbuf;
 var i,e,sgn:integer;
     hib:byte;
     ex:double;

 begin
  for i:=1 to 4 do result[i]:=0;
  if arg<>0 then begin
   if arg<0 then sgn:=-1 else sgn:=1;
   arg:=abs(arg);
   e:=trunc(ln(arg)/ln(2));
   hib:=abs(e);
   ex:=1;
   if hib>0 then for i:=1 to hib do ex:=ex*2;
   if e<0 then arg:=arg*ex else arg:=arg/ex;
   if arg<1 then begin arg:=2*arg; e:=e-1; end;
   result[1]:=e+127;
   i:=trunc(arg*128);
   arg:=arg-i/128;
   e:=trunc(arg*32768);
   if 8388608*(arg-e/32768)>=255.5 then
    if e<255 then inc(e)
     else if i<255 then begin inc(i); e:=0; arg:=0; end;
   if sgn>0 then result[2]:=i-128 else result[2]:=i;
   result[3]:=e;
   result[4]:=trunc(8388608*(arg-e/32768));
  end;
 END;{float2pic}
Last edited by janni on 26 Dec 2015 22:05, edited 1 time in total.

Andreas
Posts: 139
Joined: 05 Feb 2005 12:43
Location: Germany

Re: Help - Floating point, Microchip-> IEEE 754

#9 Post by Andreas » 26 Dec 2015 19:39

Thanks, Janni, you are a real life saver.

For all that want examples of the PIC side:

Code: Select all

//PIC to PC

//mP
VAR r : REAL;
  UART1_Write(Highest(r));
  UART1_Write(Higher(r));
  UART1_Write(HI(r));
  UART1_Write(LO(r));
//Delphi
VAR buf : picbuf;
VAR d : double;
  buf[1] := ReceiveByte;
  buf[2] := ReceiveByte;
  buf[3] := ReceiveByte;
  buf[4] := ReceiveByte;
  d := pic2float(buf);

Code: Select all

//PC to PIC
//Delphi
buf := float2pic(d);
  SendByte(buf[1]);
  SendByte(buf[2]);
  SendByte(buf[3]);
  SendByte(buf[4]);
//mP
  Highest(r) := UART1_Read;
  Higher(r) := UART1_Read;
  HI(r) := UART1_Read;
  LO(r) := UART1_Read;
SendByte and ReceiveByte are just example names for whatever you use in Delphi to send/receive via RS232.

BTW: This line
str:robol;
in the second example is not needed.

Thanks again!

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

Re: Help - Floating point, Microchip-> IEEE 754

#10 Post by janni » 26 Dec 2015 22:14

Andreas wrote:BTW: This line
str:robol;
in the second example is not needed.
Right. It was a leftover from code cut from some old program that i modified in the forum editor :) .

Post Reply

Return to “mikroPascal General”