Recent

Author Topic: 24 bit signed numbers in 32 bit environment  (Read 5034 times)

docwat

  • New Member
  • *
  • Posts: 40
24 bit signed numbers in 32 bit environment
« on: May 22, 2015, 03:57:18 pm »
Hi,

I am communicating with a 24 bit ADC using 3 bytes.  Under 2s compliment +1 is Hex 00 00 01 and -1 is Hex FF FF FF .

But using LongIntToStr(24 bit) does not see the 32 bit MS Byte so string displays fail to detect the data sign. I could easily write a function to detect values > 7F FF FF as -ve to display the correct -ve number. Oddly this requirement did not appear to arise in the Delphi 7 LongIntToStr  version of my application which would seem to indicate that the Delphi Function auto detected the data length.

I would be interested to know if anyone knows of a 24 bit To String Lazarus Pascal function  or if there is a preferred way in Lazarus to deal with 24 bit numbers ?

Very many thanks.




marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: 24 bit signed numbers in 32 bit environment
« Reply #1 on: May 22, 2015, 04:16:55 pm »
Well, then that is a bug. Could you demonstrate a small working program where the size is autodetected with Delphi? Then we can check that and see what goes wrong.

My guess however is that the value is converted to 32-bit before that (long?)inttostr function, and somehow the code travels a different path in Lazarus so it doesn't get converted. (a signed vs unsigned issue somewhere, or different methods of acquisition)


docwat

  • New Member
  • *
  • Posts: 40
Re: 24 bit signed numbers in 32 bit environment
« Reply #2 on: May 22, 2015, 06:49:39 pm »
Hi MARCOV,

On checking back to my Delphi code I find I did not convert to string from 32 bit but sent the raw input string so used:

Off3_Edit.Text:=TrimLeft(nrComm1.ReadString);

So apologies !  The Delphi reference was rubbish.

In the Lazarus code  only the 24 bit data is recovered from EEPROM and sent as a Hex string.(FD AF 08 = -151.800}

MicroPascal Code

  LS:= Read_Offsets_Long(3); {FD AF 08 in ROM  Retrieved from PIC}
                                          LongIntToStr(LS,Uart_Send_String);
                                           LTrim(Uart_Send_String);
                                          Len:=Length(UART_Send_String);
                                         
                                          For i:=0 to Len+1 do
                                          RxTx_Data:=0;
                                         
                                          for i:=0 to Len-1 do
                                          RxTx_Data:=ord(Uart_Send_String);
                                          CanspiWrite(1552,RxTx_Data,8,Can_Send_Flags);{Sent to CANBUS}

This is received by Lazarus CODE

                                            TS:='';
     Application.ProcessMessages;
     GLForm.CANCOM(113,1536,1);
     TS:=GLForm.CANCOM(113,1536,1);  {Data received as 3 byte Hex String  - no 32 bit MSB FFFF to provide Sign bit}}
   
     SPAN_ME3.Text:='';
     SPAN_ME3.Text:=GLForm.CAN_DISPLAY(TS); 

GLForm.CAN_DISLPAY is:

     Function TGLForm.Can_Display(Instring:String):AnsiString;

Var i,j:Integer;
    o:Integer;
    Len:Integer;
    S:String[3];
    M:String[35];  {20}
    C:String[35];  {20}
begin
    Result:='';
    M:='';
    Len:=Length(Instring);
    o:=Len-12;    {12}
    M:=MidStr(Instring,8,o);
    j:=1; c:='';
    S:='';
    For i:=1 to Length(M) Div 2 do
        begin
             S:='$'+M[j] + M[j+1];
             j:=j+2;
             C:=Chr(StrToInt(S));
             S:='';
        end;
    M:='';
    For i:=1 to o do
    M:=M+C;
    Instring:='';
    Result:=M;
   
end; 

Which breaks down the 3 'instring' Hex bytes into the value to be displayed in a text box                   

So the problem remains as only the 24 bit data.The value displayed is the text value of my transmitted hex data FD AF 08 =166254167 and not -151800 which would be displayed if the hex data was FF FD AF 08.

My initial analysis involving LongIintToStr was careless. No bug in Lazarus - however I still have the problem as to how to get the required -151800 display. I think I must add the MSB byte after detecting the 3 byte data going negative in 24 bit terms ?

Sorry for my hasty first analysis.

Many thanks,


Docwat

Laksen

  • Hero Member
  • *****
  • Posts: 724
    • J-Software
Re: 24 bit signed numbers in 32 bit environment
« Reply #3 on: May 22, 2015, 07:39:39 pm »
Sounds like you simply need to sign extend the 24-bit value to 32-bit. Can be done like this:

Code: [Select]
Value:=SarLongint(Value shl 8, 8);

docwat

  • New Member
  • *
  • Posts: 40
Re: 24 bit signed numbers in 32 bit environment
« Reply #4 on: May 23, 2015, 06:31:27 pm »
Thanks Laksen - that looks like a good solution.

docwat

docwat

  • New Member
  • *
  • Posts: 40
Re: 24 bit signed numbers in 32 bit environment
« Reply #5 on: May 25, 2015, 12:31:43 am »
Hi,

I eventually selected the following code to deal with my 3 bye 24bit ADC/EEPROM/and CANBUS 3 byte message. I effectively extended the 24 bit data to 32 bit wherever the 24 biit $7FFFFF value was exceeded. The code illustrates the use of the function MidStr

Many thanks for forum help.

Docwat


Function TGLForm.Can_Display2(Instring:String):AnsiString;

Var i,j:Integer;
    o:Integer;
    Len:Integer;
    M:String[35];
    C:String[35];{20}
    Value:LongInt;
begin
    Result:='';
    M:='';
    Len:=Length(Instring);  {Instring is CANBUS Message}
    o:=Len-12;
    M:=MidStr(Instring,8,o); {M contains CANBUS data bytes}
    C:='$'+'FF'+M;           {Stores 32Bit -ve string with added FF byte to display -ve in the 32 bit environment}
    M:='$' +M;               {Stores 32Bit +ve string}
    Value:=StrToInt(M);      {Calculates value of CANBUS data}
    if Value>$7FFFFF  then   {Tests if 24Bit +ve}
                         Begin
                              Value:=StrToInt(C); {Selects +ve string}
                         end;
 
    M:=IntToStr(Value);
    Result:=M;
end;                                               

 

TinyPortal © 2005-2018