Recent

Author Topic: Pascal-ish Syntax for bit access.  (Read 32660 times)

Edson

  • Hero Member
  • *****
  • Posts: 1325
Re: Pascal-ish Syntax for bit access.
« Reply #30 on: April 01, 2017, 03:26:28 am »
Quote
2. FAIK, when using sets, you can only work with fileds of one bit length. What about if I want a two-bits field?
Indexed properties can do that, see the wiki link I gave you before. There's even an example. Sets can do that too (include, exclude).

I saw the wiki. But I think you should remember, the objective of this. This is a small compiler for small devices.
I'm not going to implement in this compiler, support to:
* Properties in records.
* Indexes on porperties.
* Advanced records or "Delphi mode".
Just for setting a pair of bits. Something that is very common in the embedded world.

In others word, you are telling me, that I implement the support for some code like this (and define it for all the 1000 registers, and execute):

Code: Pascal  [Select][+][-]
  1.   TSomeBitStructure = record
  2.   private
  3.     RawData: Word;
  4.     function GetBits(const AIndex: Integer): Integer; inline;
  5.     procedure SetBits(const AIndex: Integer; const AValue: Integer); inline;
  6.   public
  7.     // High byte of index offset, low byte of index is bit count
  8.     property OneBit: Integer index $0001 read GetBits write SetBits;
  9.     property TwoBits: Integer index $0102 read GetBits write SetBits;
  10.     property FourBits: Integer index $0304 read GetBits write SetBits;
  11.     property EightBits: Integer index $0708 read GetBits write SetBits;
  12.   end;
  13.  
  14. {$OPTIMIZATION ON}
  15. {$OVERFLOWCHECKS OFF}
  16. function TSomeBitStructure.GetBits(const AIndex: Integer): Integer;
  17. var
  18.   Offset: Integer;
  19.   BitCount: Integer;
  20.   Mask: Integer;
  21. begin
  22.   BitCount := AIndex and $FF;
  23.   Offset := AIndex shr 8;
  24.   Mask := ((1 shl BitCount) - 1);
  25.   Result := (RawData shr Offset) and Mask;
  26. end;
  27.  
  28. procedure TSomeBitStructure.SetBits(const AIndex: Integer; const AValue: Integer);
  29. var
  30.   Offset: Integer;
  31.   BitCount: Integer;
  32.   Mask: Integer;
  33. begin
  34.   BitCount := AIndex and $FF;
  35.   Offset := AIndex shr 8;
  36.   Mask := ((1 shl BitCount) - 1);
  37.   Assert(aValue <= Mask);
  38.   RawData := (RawData and (not (Mask shl Offset))) or (AValue shl Offset);
  39. end;
  40.  


Just, for a task that can be done with a pair of machine instructions?

I still think, the best way would be some intrinsic feature of the compiler, to do this, just defining something like:

Code: Pascal  [Select][+][-]
  1. VAR
  2.   STATUS: byte ABSOLUTE $03  RECORD C , DC, Z, PD, _TO : Bit; RP : 0..3; END;
  3.  
« Last Edit: April 01, 2017, 03:28:37 am by Edson »
Lazarus 2.2.6 - FPC 3.2.2 - x86_64-win64 on Windows 10

Edson

  • Hero Member
  • *****
  • Posts: 1325
Re: Pascal-ish Syntax for bit access.
« Reply #31 on: April 01, 2017, 03:45:33 am »
Quote
3. When using sets, the syntax, to set or clear a bit, is complicated, in comparison with just: "STATUS.C := 1"
It may look complicated, but sets are very powerful afterwards. Set/reset a number of pins in one go. Examine which bits are set in one go, Have pins depend on each other etc, etc.
That's why I use sets for pins when I work with hardware.

OK. Maybe I can also, implement something with sets like  %):

Code: Pascal  [Select][+][-]
  1. VAR
  2.   STATUS: byte ABSOLUTE $03  BITSET OF (C=0 , DC, Z, PD, _TO , RP0, RP1);
  3.  

But I still see problems working with fields of more than one bit. Maybe, defining a new syntax features for sets.  :-[
Lazarus 2.2.6 - FPC 3.2.2 - x86_64-win64 on Windows 10

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Pascal-ish Syntax for bit access.
« Reply #32 on: April 01, 2017, 03:47:21 am »
Quote
In others word, you are telling me, that I implement the support for some code like this (and define it for all the 1000 registers, and execute):
You are the one that wants to have individual flag names for each register, and which differ for each register. You do not have to do that and could choose for a more generic approach.

Every register could be typed as TSomeBitStructure and you're done with it.

Quote
Just, for a task that can be done with a pair of machine instructions?
Indeed. real programmers write up an asm routine to manipulate bits and be done with it, or use the and, or, xor, etc operators manually.

You wish to add more convenience and usually that is done by adding syntax sugar to the compiler. Typehelpers, advanced records etc are all that: simple syntax sugar, just as you wish to declare individual flagnames for each register.

With each additional syntax sugar you add complexity to your compiler/parser.

Quote
I still think, the best way would be some intrinsic feature of the compiler, to do this, just defining something like:
uhm, i really did not get that part. You mean you would like to add a new type of size bit and follow the usual parsing of a record structure ?

That could perhaps proof to be the most simplest solution (e.g. least intrusive) for your case.

Edson

  • Hero Member
  • *****
  • Posts: 1325
Re: Pascal-ish Syntax for bit access.
« Reply #33 on: April 01, 2017, 04:16:58 am »
Quote
I still think, the best way would be some intrinsic feature of the compiler, to do this, just defining something like:
uhm, i really did not get that part. You mean you would like to add a new type of size bit and follow the usual parsing of a record structure ?
It's very common to have the type "bit" for small devices compilers.
If fact, I have already, created this type in my compiler.  :D

Code: Pascal  [Select][+][-]
  1. var
  2.   x: bit;
  3. begin
  4.   x := 0;
  5. end.

Now I'm implementing the operations with this strange type.
« Last Edit: April 01, 2017, 04:22:07 am by Edson »
Lazarus 2.2.6 - FPC 3.2.2 - x86_64-win64 on Windows 10

mse

  • Sr. Member
  • ****
  • Posts: 286
Re: Pascal-ish Syntax for bit access.
« Reply #34 on: April 01, 2017, 09:12:22 am »
MSElang treats sets as an array of boolean1 (1 bit size).
Code: Pascal  [Select][+][-]
  1. type
  2.  flag = (a,b,c,d);
  3.  flags = set of flag;
  4. var
  5.  f1: flags;
  6. [...]
  7.  
  8.  f1[a]:= true; //-> include(f1,a)
  9.  if f1[a] then //-> if a in f1
  10.   [...]
  11.  end;
  12.  

Thaddy

  • Hero Member
  • *****
  • Posts: 17413
  • Ceterum censeo Trumpum esse delendum (Tnx Charlie)
Re: Pascal-ish Syntax for bit access.
« Reply #35 on: April 01, 2017, 01:17:17 pm »
I still think, the best way would be some intrinsic feature of the compiler, to do this, just defining something like:
Code: Pascal  [Select][+][-]
  1. VAR
  2.   STATUS: byte ABSOLUTE $03  RECORD C , DC, Z, PD, _TO : Bit; RP : 0..3; END;
  3.  

But then follow existing syntax:
Code: Pascal  [Select][+][-]
  1. program testbits;
  2. {$mode objfpc}{$packenum 1}{$packset 1}
  3. type
  4.   TByteBits = set of (Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7);
  5.  
  6. var
  7.   a:byte;
  8.   b:TBytebits absolute a;  //  can also point to a hardware address
  9. begin
  10.  a := 0;
  11.  writeln(a);
  12.  include (b, bit0);// turn bit0 on
  13.  writeln(a);
  14.  include(b,bit7); // turn bit7 on
  15.  writeln(a);
  16.  exclude(b, bit0); // turn bit0 off
  17.  writeln(a);
  18.  b := [bit3,bit5];// toggles pin 3 and 5 and clears the rest
  19.  writeln(a);
  20.  readln;
  21. end.

This is how I use it on the Raspberry pi, only for the range of all GPIO pins using banks of byte, with pins named after specific functionality if applicable.
That's why I wrote I like bitsets .... :D 8-) I got the idea and the specs from here http://www.pieter-jan.com/node/15 and my code looks much nicer  :D
« Last Edit: April 01, 2017, 05:26:12 pm by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12314
  • FPC developer.
Re: Pascal-ish Syntax for bit access.
« Reply #36 on: April 01, 2017, 06:26:16 pm »
This is how I use it on the Raspberry pi, only for the range of all GPIO pins using banks of byte, with pins named after specific functionality if applicable.
That's why I wrote I like bitsets .... :D 8-) I got the idea and the specs from here http://www.pieter-jan.com/node/15 and my code looks much nicer  :D

This jogged some other things that might be related:

- bit addressing is generally  read-modify-write safe. One should use it if possible.
- Otherwise one needs to use the XOR trick (see the microchip forum link above)

On Microchip, depending on which exact chip, pins can change register.

E.g. T8IF  (the interrupt flag of timer 8) might be in various registers bundled with other interrupt flags depending on how many of each peripheral with interrupt flags a chip has.

In C they solve it by defining a macro, so when generating the headers, for such known pins they generate e.g.

#define _T8IF  INTR1bits.T8IF

This will be harder with FPC. (though I assume since it is parameterless, $macro might be enough, I don't like macros)



« Last Edit: April 01, 2017, 06:37:00 pm by marcov »

Edson

  • Hero Member
  • *****
  • Posts: 1325
Re: Pascal-ish Syntax for bit access.
« Reply #37 on: April 01, 2017, 09:39:48 pm »
MSElang treats sets as an array of boolean1 (1 bit size).
Code: Pascal  [Select][+][-]
  1. type
  2.  flag = (a,b,c,d);
  3.  flags = set of flag;
  4. var
  5.  f1: flags;
  6. [...]
  7.  
  8.  f1[a]:= true; //-> include(f1,a)
  9.  if f1[a] then //-> if a in f1
  10.   [...]
  11.  end;
  12.  

Excelent.  :D I think they must be treated as records too:

Code: Pascal  [Select][+][-]
  1. var
  2.  f1: set of (a,b,c,d);
  3. [...]
  4.  
  5.  f1.a := 1; //-> include(f1,a)
  6.  f1.b := 0; //-> exclude(f1,b)
  7.  if f1.a = 1 then //-> if a in f1
  8.   [...]
  9.  end;
  10.  

And I like the MODULA 2 syntax, too. Probably I will be including this syntax.
« Last Edit: April 01, 2017, 09:52:51 pm by Edson »
Lazarus 2.2.6 - FPC 3.2.2 - x86_64-win64 on Windows 10

Edson

  • Hero Member
  • *****
  • Posts: 1325
Re: Pascal-ish Syntax for bit access.
« Reply #38 on: April 01, 2017, 10:51:14 pm »
But then follow existing syntax:

OK. I will try to implement support for sets, in the formal way.  Then I will add features of records for sets.

Currently, I can work with bit variables:

Code: Pascal  [Select][+][-]
  1. var
  2.   PORTB : byte absolute $06;
  3.   pin   : bit absolute PORTB.7;
  4. begin                          
  5.   pin := 1;
  6. end.
Lazarus 2.2.6 - FPC 3.2.2 - x86_64-win64 on Windows 10

sam707

  • Guest
Re: Pascal-ish Syntax for bit access.
« Reply #39 on: April 02, 2017, 01:25:44 am »
LoOoL
how comes 3 pages comenting on bits ops hahahahahaha?

just use boolean operators, and all will be fine

and, or, not, ror, rol, shl, shr etc etc and other new intrinsics

http://wiki.freepascal.org/FPC_New_Features_2.6.0#ROL.2FROR_intrinsics

come on! 3 pages trolling on BASIC ops  :D  :D  :D

there are some recordmen downthere LOL
« Last Edit: April 02, 2017, 01:29:06 am by sam707 »

Thaddy

  • Hero Member
  • *****
  • Posts: 17413
  • Ceterum censeo Trumpum esse delendum (Tnx Charlie)
Re: Pascal-ish Syntax for bit access.
« Reply #40 on: April 02, 2017, 06:46:24 am »
You missed some points;
- He is writing a cross-compiler for very light devices
- Bit-twiddling like you propose is on a much lower level
- What this discussion is about is high-level pin access using bitfields.
- That means trying to map bits to pins in a direct way.
- Object Pascal already has different options for such high-level interfacing for bit access
Hence the discussion is about high level access to bitfields and how to implement it.
It has merit because such syntax makes the relation between a pin and a bit immediately obvious.
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

Edson

  • Hero Member
  • *****
  • Posts: 1325
Re: Pascal-ish Syntax for bit access.
« Reply #41 on: April 02, 2017, 06:29:26 pm »
Just to clarify  ;). This compiler is intended to target devices as small as PIC16F83, with 512 words of FLASH memory, and 36 bytes of RAM, and probably running at 1MHz or less.

So please, don't pretend I include OOP, generics, or complex features of the language.   >:D This devices works at the level of bits.

That's why it's so important to have integrated features in the language, for manipulate directly bits.

To compile this:

Code: Pascal  [Select][+][-]
  1. procedure TSomeBitStructure.SetBits(const AIndex: Integer; const AValue: Integer);
  2. var
  3.   Offset: Integer;
  4.   BitCount: Integer;
  5.   Mask: Integer;
  6. begin
  7.   BitCount := AIndex and $FF;
  8.   Offset := AIndex shr 8;
  9.   Mask := ((1 shl BitCount) - 1);
  10.   Assert(aValue <= Mask);
  11.   RawData := (RawData and (not (Mask shl Offset))) or (AValue shl Offset);
  12. end;

to modify just a bit, is inacceptable, considering that:

1. It could use 10% or more of the Flash Memory.  :o
2. There are instructions to manipulate bits in this kind of devices. Just one instruction.
 
« Last Edit: April 02, 2017, 06:48:34 pm by Edson »
Lazarus 2.2.6 - FPC 3.2.2 - x86_64-win64 on Windows 10

kupferstecher

  • Hero Member
  • *****
  • Posts: 604
Re: Pascal-ish Syntax for bit access.
« Reply #42 on: April 03, 2017, 04:44:08 pm »
Its an interesting question I think, also in regard to the FPC with target embedded (AVR/ARM).

Providing a special type for easier bit-access has a negative (side-) effect: Assigning an integer value is getting more troublesome, as an explicit type conversion has to be done. Is there any possibility to allow implicit type conversion e.g. from "byte" to "bitpacked array [0..7] of TBit" and vise versa?

Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3. Type
  4.   TBit = 0..1;
  5.   TBitByte = bitpacked array [0..7] of TBit;
  6. var
  7.   // USART
  8.   UDR : TBitByte;   //absolute $00+$2C; // USART I/O Data Register
  9.   UCSRA : TBitByte; //absolute $00+$2B; // USART Control and Status Register A
  10.   UCSRB : TBitByte; //absolute $00+$2A; // USART Control and Status Register B
  11.   UCSRC : TBitByte; //absolute $00+$40; // USART Control and Status Register C
  12.   UBRRH : TBitByte; //absolute $00+$40; // USART Baud Rate Register Hight Byte
  13.   UBRRL : TBitByte; //absolute $00+$29; // USART Baud Rate Register Low Byte
  14.  
  15. Const
  16.   // UCSRB
  17.   RXCIE = 7; // RX Complete Interrupt Enable
  18.   TXCIE = 6; // TX Complete Interrupt Enable
  19.   UDRIE = 5; // USART Data register Empty Interrupt Enable
  20.   RXEN = 4; // Receiver Enable
  21.   TXEN = 3; // Transmitter Enable
  22.   UCSZ2 = 2; // Character Size
  23.   RXB8 = 1; // Receive Data Bit 8
  24.   TXB8 = 0; // Transmit Data Bit 8
  25.  
  26. var
  27.   aByte: Byte;
  28.  
  29. begin
  30.  
  31.   UCSRA[5]:= 1;
  32.   UCSRA[RXEN]:= 1;     //Bit of UCSRB used in UCSRA, no warning here.
  33.  
  34.   aByte:= UDR; // <- Error message here: incompatible types
  35.  
  36. end.  

Thaddy

  • Hero Member
  • *****
  • Posts: 17413
  • Ceterum censeo Trumpum esse delendum (Tnx Charlie)
Re: Pascal-ish Syntax for bit access.
« Reply #43 on: April 03, 2017, 04:58:02 pm »
Its an interesting question I think, also in regard to the FPC with target embedded (AVR/ARM).

Providing a special type for easier bit-access has a negative (side-) effect: Assigning an integer value is getting more troublesome, as an explicit type conversion has to be done. Is there any possibility to allow implicit type conversion e.g. from "byte" to "bitpacked array [0..7] of TBit" and vise versa?

Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3. Type
  4.   TBit = 0..1;
  5.   TBitByte = bitpacked array [0..7] of TBit;
  6. var
  7.   // USART
  8.   UDR : TBitByte;   //absolute $00+$2C; // USART I/O Data Register
  9.   UCSRA : TBitByte; //absolute $00+$2B; // USART Control and Status Register A
  10.   UCSRB : TBitByte; //absolute $00+$2A; // USART Control and Status Register B
  11.   UCSRC : TBitByte; //absolute $00+$40; // USART Control and Status Register C
  12.   UBRRH : TBitByte; //absolute $00+$40; // USART Baud Rate Register Hight Byte
  13.   UBRRL : TBitByte; //absolute $00+$29; // USART Baud Rate Register Low Byte
  14.  
  15. Const
  16.   // UCSRB
  17.   RXCIE = 7; // RX Complete Interrupt Enable
  18.   TXCIE = 6; // TX Complete Interrupt Enable
  19.   UDRIE = 5; // USART Data register Empty Interrupt Enable
  20.   RXEN = 4; // Receiver Enable
  21.   TXEN = 3; // Transmitter Enable
  22.   UCSZ2 = 2; // Character Size
  23.   RXB8 = 1; // Receive Data Bit 8
  24.   TXB8 = 0; // Transmit Data Bit 8
  25.  
  26. var
  27.   aByte: Byte;
  28.  
  29. begin
  30.  
  31.   UCSRA[5]:= 1;
  32.   UCSRA[RXEN]:= 1;     //Bit of UCSRB used in UCSRA, no warning here.
  33.  
  34.   aByte:= UDR; // <- Error message here: incompatible types
  35.  
  36. end.  

You didn't look or understood my example, did you?
The set elements are bits.... So there is a one to one mapping to pins.
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Pascal-ish Syntax for bit access.
« Reply #44 on: April 03, 2017, 05:01:46 pm »
Providing a special type for easier bit-access has a negative (side-) effect: Assigning an integer value is getting more troublesome, as an explicit type conversion has to be done. Is there any possibility to allow implicit type conversion e.g. from "byte" to "bitpacked array [0..7] of TBit" and vise versa?
use absolute keyword, all or not combined with a type helper. that way you are able to assign both bits as well as integer values (well, byte values would be more accurate).

Also possible to use would be a variant record, holding both types (overlap)

edit: And to satisfy the curiosity, here your code with using operators.
Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3. Type
  4.   TBit = 0..1;
  5.   TBitByte = bitpacked array [0..7] of TBit;
  6.  
  7. var
  8.   // USART
  9.   UDR   : TBitByte; //absolute $00+$2C; // USART I/O Data Register
  10.   UCSRA : TBitByte; //absolute $00+$2B; // USART Control and Status Register A
  11.   UCSRB : TBitByte; //absolute $00+$2A; // USART Control and Status Register B
  12.   UCSRC : TBitByte; //absolute $00+$40; // USART Control and Status Register C
  13.   UBRRH : TBitByte; //absolute $00+$40; // USART Baud Rate Register Hight Byte
  14.   UBRRL : TBitByte; //absolute $00+$29; // USART Baud Rate Register Low Byte
  15.  
  16. Const
  17.   // UCSRB
  18.   RXCIE = 7; // RX Complete Interrupt Enable
  19.   TXCIE = 6; // TX Complete Interrupt Enable
  20.   UDRIE = 5; // USART Data register Empty Interrupt Enable
  21.   RXEN  = 4; // Receiver Enable
  22.   TXEN  = 3; // Transmitter Enable
  23.   UCSZ2 = 2; // Character Size
  24.   RXB8  = 1; // Receive Data Bit 8
  25.   TXB8  = 0; // Transmit Data Bit 8
  26.  
  27. operator := (x: byte) Result : TBitByte;
  28. var
  29.   retval: Byte absolute Result;
  30. begin
  31.   retval := x;
  32. end;
  33.  
  34. operator := (x: TBitByte) Result : Byte;
  35. var
  36.   inval: byte absolute x;
  37. begin
  38.   Result := inval;
  39. end;
  40.  
  41. operator :=(x: TBitByte) Result : LongInt;
  42. var
  43.   inval: byte absolute x;
  44. begin
  45.   Result := inval;
  46. end;
  47.  
  48. var
  49.   aByte: Byte;
  50.   bByte: TBitByte absolute aByte;
  51. begin
  52.   UCSRA[5]:= 1;
  53.   UCSRA[RXEN]:= 1;     //Bit of UCSRB used in UCSRA, no warning here.
  54.  
  55.   UDR[2] := 1;
  56.   bByte:= UDR;  // this is assignment compatible using absolute modifier
  57.   aByte:= UDR;  // this is assignment compatible because of TBitByte->Byte operator
  58.   UDR := aByte; // this is assignment compatible because of Byte->TBitByte operator
  59.  
  60.   WriteLn('UDR = ', BinStr(UDR, 8)); // this is working because of TBitByte->LongInt operator
  61. end.
  62.  
« Last Edit: April 03, 2017, 06:43:10 pm by molly »

 

TinyPortal © 2005-2018