Recent

Author Topic: [Solved] Bitpacked record help needed  (Read 1643 times)

lainz

  • Hero Member
  • *****
  • Posts: 4468
    • https://lainz.github.io/
[Solved] Bitpacked record help needed
« on: May 10, 2022, 04:03:26 pm »
Hi, I have this bitpacked record structure (2 bytes):

Code: Pascal  [Select][+][-]
  1. TBitsTM900 = bitpacked record
  2.     Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7,
  3.     Bit8, Bit9, Bit10, Bit11, Bit12, Bit13, Bit14, Bit15: Boolean;
  4.   end;

And I need to convert that structure to hexadecimal string.

Say I have a variable of TBitsTM900

Code: Pascal  [Select][+][-]
  1. var
  2. bits: TBitsTM900;
  3.  
  4. bits.bit1 := true;
  5. bits.bit2 := true;
  6. bits.bit3 := true;
  7. bits.bit4 := true;
  8. bits.bit5 := true;
  9. bits.bit6 := true;
  10. bits.bit7 := true;
  11. bits.bit8 := false;
  12. bits.bit9 := false;
  13. bits.bit10 := false;
  14. bits.bit11 := false;
  15. bits.bit12 := false;
  16. bits.bit13 := false;
  17. bits.bit14 := false;
  18. bits.bit15 := false;

So how to convert that to 'FF00' string?
« Last Edit: May 10, 2022, 05:45:30 pm by lainz »

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 1313
Re: Bitpacked record help needed
« Reply #1 on: May 10, 2022, 04:16:03 pm »
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. uses sysutils;
  4.  
  5. type
  6.   TBitsTM900 = bitpacked record
  7.           case Boolean of
  8.           False: (Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7,
  9.                  Bit8, Bit9, Bit10, Bit11, Bit12, Bit13, Bit14, Bit15: Boolean);
  10.           True:  (Value: Word);
  11.   end;
  12.  
  13. var
  14.   MyBits: TBitsTM900;
  15.  
  16. begin
  17.   MyBits.Bit0 := True;
  18.   WriteLn(IntToHex(MyBits.Value));
  19. end.

lainz

  • Hero Member
  • *****
  • Posts: 4468
    • https://lainz.github.io/
Re: Bitpacked record help needed
« Reply #2 on: May 10, 2022, 05:07:32 pm »
Thanks. Another question: it's initialized all with false to start with? Or I must initialize it in some way?

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Bitpacked record help needed
« Reply #3 on: May 10, 2022, 05:39:23 pm »
Hi!

Yes you have to initialize the record. But with the above example this is easy:
Code: Pascal  [Select][+][-]
  1. MyBits.Value := 0;
  2.  
or

Code: Pascal  [Select][+][-]
  1. MyBits.Value := $FFFF;

And simplify the above record with an array of bits:


Code: Pascal  [Select][+][-]
  1. Type
  2. TBit  = 0..1;
  3.  
  4. TBitsTM900 = bitpacked record
  5.           case Boolean of
  6.           False: (Bits: array[0..15] of TBit);
  7.           True:  (Value: Word);
  8.   end;
  9.  
  10.  

Winni


lainz

  • Hero Member
  • *****
  • Posts: 4468
    • https://lainz.github.io/
Re: Bitpacked record help needed
« Reply #4 on: May 10, 2022, 05:44:48 pm »
Thanks

440bx

  • Hero Member
  • *****
  • Posts: 4029
Re: [Solved] Bitpacked record help needed
« Reply #5 on: May 10, 2022, 06:38:55 pm »
just a minor comment...

Initializing variables is definitely a good habit which I certainly don't want to discourage in any way but, FYI, if as shown in your code snippet, the variable is global then the compiler will place it in the initialized data segment and that location will already be all zeroes.

IOW, the time that a variable _really_ needs to be initialized is when it is local to a function/procedure or when it is located in the heap.

All that said, it's a really good habit to initialize variables in code as a matter of course no matter where they reside.

(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

avra

  • Hero Member
  • *****
  • Posts: 2514
    • Additional info
Re: [Solved] Bitpacked record help needed
« Reply #6 on: May 10, 2022, 11:33:25 pm »
With latest trunk this is possible:

Code: Pascal  [Select][+][-]
  1. program Project2;
  2.  
  3. uses sysutils, syshelpers;
  4.  
  5. type
  6.   TMyRecord = record
  7.     MyValue: word;
  8.   end;
  9.  
  10. var
  11.   MyRecord: TMyRecord;
  12.  
  13. begin
  14.   MyRecord.MyValue.Clear;
  15.   MyRecord.MyValue.Bits[0] := true;
  16.   WriteLn(MyRecord.MyValue.ToHexString);
  17. end.

Demonstration of possibilities can be seen at console demo here:
https://gitlab.com/freepascal.org/fpc/source/-/blob/main/packages/rtl-objpas/examples/syshelpersdemo.pas

GUI demo can be found here:
https://gitlab.com/freepascal.org/fpc/source/uploads/cf21e96abdca0a4cfb5e9e3c1c054011/20220120-3-examples.zip
« Last Edit: May 10, 2022, 11:49:23 pm by avra »
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

440bx

  • Hero Member
  • *****
  • Posts: 4029
Re: [Solved] Bitpacked record help needed
« Reply #7 on: May 10, 2022, 11:40:00 pm »
the most succinct way I know of, which is valid since FPC v3.0.4 (and maybe earlier) is:
Code: Pascal  [Select][+][-]
  1. type
  2.   TBitsTM900 = bitpacked record
  3.     Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7,
  4.     Bit8, Bit9, Bit10, Bit11, Bit12, Bit13, Bit14, Bit15: Boolean;
  5.   end;
  6.  
  7. var
  8.   TM900 : TBitsTM900 = ();
  9.  

PS: learned that a while back from @ASerge
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5481
  • Compiler Developer
Re: [Solved] Bitpacked record help needed
« Reply #8 on: May 11, 2022, 09:02:20 am »
the most succinct way I know of, which is valid since FPC v3.0.4 (and maybe earlier) is:
Code: Pascal  [Select][+][-]
  1. type
  2.   TBitsTM900 = bitpacked record
  3.     Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7,
  4.     Bit8, Bit9, Bit10, Bit11, Bit12, Bit13, Bit14, Bit15: Boolean;
  5.   end;
  6.  
  7. var
  8.   TM900 : TBitsTM900 = ();
  9.  

PS: learned that a while back from @ASerge

It might be that this is an an artefact and should not work as such or at least not without some warning about missing fields. So, no guarantee that this keeps working.

440bx

  • Hero Member
  • *****
  • Posts: 4029
Re: [Solved] Bitpacked record help needed
« Reply #9 on: May 11, 2022, 03:17:51 pm »
It might be that this is an an artefact and should not work as such or at least not without some warning about missing fields. So, no guarantee that this keeps working.
I remember having a discussion about this feature when @ASerge showed it was possible.  That feature got "more clearly" documented as a result of that discussion and now it is documented as being a compiler feature (IOW, not an artifact.)

In case you're interested, the link to the discussion is : https://www.freepascal.org/docs-html/current/ref/refse24.html#x55-730004.4

(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5481
  • Compiler Developer
Re: [Solved] Bitpacked record help needed
« Reply #10 on: May 12, 2022, 09:20:24 am »
It might be that this is an an artefact and should not work as such or at least not without some warning about missing fields. So, no guarantee that this keeps working.
I remember having a discussion about this feature when @ASerge showed it was possible.  That feature got "more clearly" documented as a result of that discussion and now it is documented as being a compiler feature (IOW, not an artifact.)

In case you're interested, the link to the discussion is : https://www.freepascal.org/docs-html/current/ref/refse24.html#x55-730004.4

Ah, okay, then all is well. :) (By the way: your link points to the documentation, not the discussion ;) )

ccrause

  • Hero Member
  • *****
  • Posts: 856
Re: [Solved] Bitpacked record help needed
« Reply #11 on: May 12, 2022, 12:26:16 pm »
Allow me to carry on with an already solved topic %)
Using typecast:
Code: Pascal  [Select][+][-]
  1. WriteLn(IntToHex(uint16(MyBits)));
Using absolute:
Code: Pascal  [Select][+][-]
  1. var
  2.   MyBitsWord: word absolute MyBits;
  3.  
  4.   WriteLn(IntToHex(MyBitsWord));

So how to convert that to 'FF00' string?
Do you actually want FF00 as output for your example, i.e. the little endian representation of your bit name convention?  In that case the answers so far is not generating the required output, since the convention for representing human readable numbers(*) is big endian, hence using the built-in conversions to human readable hex strings is not directly applicable.  If this is indeed what the OP wants(**), then one option is to to swap the endianness of the underlying value before converting to hex format, for example using the SwapEndian function:
Code: Pascal  [Select][+][-]
  1. WriteLn(IntToHex(SwapEndian(uint16(MyBits))));

* There are of course other representations, of which left to right big endian is only one, but for the sake of this discussion (Pascal language with English roots) I make this assumption.
** This may not be the first time I completely misread a discussion, especially given that the OP is already satisfied with the previous information in this thread...

Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: [Solved] Bitpacked record help needed
« Reply #12 on: May 12, 2022, 12:38:30 pm »
Why a record? You can use the bithelpers for word from sysutils. Those also contain a hexstring conversion.
Those are in rtl/objpas/sysutils/syshelph.inc, so they are in sysutils. Much cleaner.
extract:
Code: Pascal  [Select][+][-]
  1.   TWordHelper = Type Helper for Word
  2.   const
  3.     MaxValue  = High(word);
  4.     MinValue  = Low(word);
  5.     MaxBit    = High(TWordBitIndex);
  6.     MinBit    = Low(TWordBitIndex);
  7.     MaxNibble = High(TWordNibbleIndex);
  8.     MinNibble = Low(TWordNibbleIndex);
  9.     MaxByte   = High(TWordByteIndex);
  10.     MinByte   = Low(TWordByteIndex);
  11.   public
  12.     Class Function Parse(const AString: string): Word; inline; static;
  13.     Class Function Size: Integer; inline; static;
  14.     Class Function ToString(const AValue: Word): string; overload; inline; static;
  15.     Class Function TryParse(const AString: string; out AValue: Word): Boolean; inline; static;
  16.   protected
  17.     function  GetBit(const aIndex: TWordBitIndex): boolean; inline;
  18.     procedure PutBit(const aIndex: TWordBitIndex; const aNewValue: boolean); inline;
  19.     function  GetNibble(const aIndex: TWordNibbleIndex): nibble; inline;
  20.     procedure PutNibble(const aIndex: TWordNibbleIndex; const aNewValue: nibble); inline;
  21.     function  GetByte(const aIndex: TWordByteIndex): byte;
  22.     procedure PutByte(const aIndex: TWordByteIndex; const aNewValue: byte);
  23.   public
  24.     Function ToBoolean: Boolean; inline;
  25.     Function ToDouble: Double; inline;
  26.     Function ToExtended: Extended; inline;
  27.     Function ToBinString:string; inline;
  28.     Function ToHexString(const AMinDigits: Integer): string; overload; inline;
  29.     Function ToHexString: string; overload; inline;
  30.     Function ToSingle: Single; inline;
  31.     Function ToString: string; overload; inline;
  32.     Function SetBit(const Index: TWordBitIndex) : Word; inline;
  33.     Function ClearBit(const Index: TWordBitIndex) : Word; inline;
  34.     Function ToggleBit(const Index: TWordBitIndex) : Word; inline;
  35.     Function TestBit(const Index:TWordBitIndex):Boolean; inline;  
  36.     procedure Clear; inline;
  37.     function  HighestSetBitPos: int8; inline;
  38.     function  LowestSetBitPos: int8; inline;
  39.     function  SetBitsCount: byte; inline;
  40.     property  Bits [aIndex: TWordBitIndex]: boolean   read GetBit  write PutBit;
  41.     property  Nibbles [aIndex: TWordNibbleIndex]: nibble read GetNibble write PutNibble;
  42.     property  Bytes [aIndex: TWordByteIndex]: byte     read GetByte write PutByte;
  43.   end;

Made by me and Avra extended it.
« Last Edit: May 12, 2022, 12:44:34 pm by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

440bx

  • Hero Member
  • *****
  • Posts: 4029
Re: [Solved] Bitpacked record help needed
« Reply #13 on: May 12, 2022, 07:36:52 pm »
(By the way: your link points to the documentation, not the discussion ;) )
ooops! wrong link... sorry about that... here is the correct link : https://forum.lazarus.freepascal.org/index.php/topic,51461.msg377850.html#msg377850
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5481
  • Compiler Developer
Re: [Solved] Bitpacked record help needed
« Reply #14 on: May 13, 2022, 09:28:26 am »
Thanks, now I remember that discussion  :-[

 

TinyPortal © 2005-2018