Pascal intelligente Sprache, dank bitpacked und absolute

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Pascal intelligente Sprache, dank bitpacked und absolute

Beitrag von Mathias »

Ich habe hier 2 mal die gleiche procedure die erste klassische Varinate, ist sehr unübersichtlich.
Löst man das ganze mit bitpacket und absolute, kann man es sehr elegant und übersichtlich lösen.
Das ganze Gewurschtelt mit if , or und and not entfällt.

Infos zu der Bitfolge

Code: Alles auswählen

    // bit 0-11 Analog Value
    // bit 15                              0 = DAC_A                 1 = DAC_B
    // bit 14 Vref input buffer control    0 = unbuffered(default)   1 = buffered
    // bit 13 Output Gain selection        0 = 2x                    1 = 1x
    // bit 12 Output shutdown control bit  0 = Shutdown the device   1 = Active mode operation

Klassisch;

Code: Alles auswählen

  procedure TMCP4922.sendValue(Value: UInt16);
  begin
    if fDAC then begin
      Value := Value or (UInt16(1) shl 15);
    end else begin
      Value := Value and not (UInt16(1) shl 15);
    end;
    Value := Value and not (UInt16(1) shl 14);
    if fGain then begin
      Value := Value or (UInt16(1) shl 13);
    end else begin
      Value := Value and not (UInt16(1) shl 13);
    end;
    Value := Value or (UInt16(1) shl 12);
 
    SPI_Write(@Value, 2);
  end;


Optimiert:

Code: Alles auswählen

  procedure TMCP4922.sendValue(Value: UInt16);
  var
    Data: bitpacked array[0..15] of boolean absolute Value;
  begin
    Data[12] := True;
    Data[13] := fGain;
    Data[14] := False;
    Data[15] := fDAC;
 
    SPI_Write(@Data, 2);
  end;

Macht mal sowas mit C++. :mrgreen:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Pascal intelligente Sprache, dank bitpacked und absolute

Beitrag von Warf »

Mathias hat geschrieben:Macht mal sowas mit C++. :mrgreen:

 
Sowas ähnliches wie absolute gibts auch in C++, nur etwas generischer und mit mehr einsatzmöglichkeiten:

Code: Alles auswählen

int val1;
char val2[4];
&val2 = (char*)&val1;
val2[0] = 5;

 
Aber ich finde weder die Pascal noch die C++ variante (pointer setzen bei stackobjekten) wirklich gut und übersichtlich, da es verschiedene Variablen sind. Dafür gibt es in C++ Unions und in Pascal Variante records:

Code: Alles auswählen

union {
  int val1;
  char val2[4];
} Test;
test.val2[0] = 5;

Code: Alles auswählen

var Test: record
case (Boolean) of
True: (val1: Integer);
False: (val2: array[0..4] of Byte);
end;
Test.val2[0] := 5

Somit gibt es eine separate variable zum Converten, somit fragt man sich nicht warum Var1 sich verändert obwohl man grade an val2 rumdocktort
 
Was solche memory spielchen angeht können C++ und Pascal praktisch das selbe.
 
Was denkst du wie ich zwischen RGB und TColor convertiere?

Code: Alles auswählen

Col = record
case (Boolean) of
True: (col: Integer);
False: (R,G,B: Byte);
 
col.R := 255;
col.G := 0;
col.B := 0;
Color := col.col;

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Pascal intelligente Sprache, dank bitpacked und absolute

Beitrag von Mathias »

Bei deinem Boolean muss noch die () weg, ansonsten gibt es einen Syntax-fehler.

Das mit case und record kenne ich auch. Aber für die Übergabe in die procedure wollte ich einen Integer verwenden und nicht Record.
Ansonten hätte ich diesen Umweg machen müssen:

Code: Alles auswählen

type
  TValue = record
    case byte of
      0: (i: UInt16);
      1: (Bit: bitpacked array[0..15] of boolean);
  end;


Das Beispiel für absolute in C++ sieht wieder mal typisch C++ chaotisch aus.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Pascal intelligente Sprache, dank bitpacked und absolute

Beitrag von Warf »

Mathias hat geschrieben:Bei deinem Boolean muss noch die () weg, ansonsten gibt es einen Syntax-fehler.

Das mit case und record kenne ich auch. Aber für die Übergabe in die procedure wollte ich einen Integer verwenden und nicht Record.
Ansonten hätte ich diesen Umweg machen müssen


Ja für das kleine Beispiel reicht es aus, da die Funktion sonst nix macht. Das problem ist, wenn man etwas größere Funktionen hat ist es manchmal recht undurchsichtig was was macht. Bei einem record sind alle daten in einer Variable erreichbar, viel übersichtlicher

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Pascal intelligente Sprache, dank bitpacked und absolute

Beitrag von Mathias »

Es kommt immer auf den Anwendungsfall an.
Mein Code wird für einen AVR gebraucht. Da ist Bitsparen eher angesagt, als sauberen Code.
Ich will nur einen Int übergeben un nicht eine Zeiger auf diesen.

Sowas geht mit dem Record auch nicht, da muss man einem Umweg über eine Typisierte Variable machen.

Code: Alles auswählen

TMCP4922.sendValue(123);
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Pascal intelligente Sprache, dank bitpacked und absolute

Beitrag von Timm Thaler »

Mathias hat geschrieben:Mein Code wird für einen AVR gebraucht. Da ist Bitsparen eher angesagt, als sauberen Code.
Ich will nur einen Int übergeben un nicht eine Zeiger auf diesen.


Ja und, genau dafür sind die Records da.

Code: Alles auswählen

  tSadc = bitpacked record  // Statusflags ADC
    case byte of
      0 : (bit0, bit1, bit2, bit3,
           gnd,    // Flag Sensor GND
           open,   // Flag Sensor offen
           noack,  // Flag Eingang kein Ack
           err : boolean)// Flag Fehler Input, gesamt
      1 : (all : uint8);
  end;


Geht auf dem AR wunderbar und der Compiler optimiert das so gut, das bekomme ich in Assembler nicht besser hin. Zudem ist der Zugriff sehr übersichtlich.

BeniBela
Beiträge: 308
Registriert: Sa 21. Mär 2009, 17:31
OS, Lazarus, FPC: Linux (Lazarus SVN, FPC 2.4)
CPU-Target: 64 Bit

Re: Pascal intelligente Sprache, dank bitpacked und absolute

Beitrag von BeniBela »

Ist bitpacked record dann big oder low endian?

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Pascal intelligente Sprache, dank bitpacked und absolute

Beitrag von Mathias »

Wen du diesen kleinen Code laufen lässt, dann weist du es. :wink:

Code: Alles auswählen

  procedure Ausgabe(Value: byte);
  var
    bit: bitpacked array[0..7] of boolean absolute Value;
    i: integer;
  begin
    for i := 7 downto 0 do begin
      Write(bit[i]: 6);
    end;
    WriteLn;
  end;
 
begin
  Ausgabe(4);
end
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

BeniBela
Beiträge: 308
Registriert: Sa 21. Mär 2009, 17:31
OS, Lazarus, FPC: Linux (Lazarus SVN, FPC 2.4)
CPU-Target: 64 Bit

Re: Pascal intelligente Sprache, dank bitpacked und absolute

Beitrag von BeniBela »

Dann weiß ich wie es auf meinem Intel-Computer ist? Aber ist das immer gleich?

Vor allem, hat shr/shl immer dieselbe Auswirkung aufs Array?

siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Pascal intelligente Sprache, dank bitpacked und absolute

Beitrag von siro »

In "C" würde ich das wohl so schreiben:

Code: Alles auswählen

 
 
#define GAIN_2X 0
#define GAIN_1X 1
 
#define VREF_unbuffered 0
#define VREF_buffered   1
 
#define DAC_A 0
#define DAC_B 1
 
typedef struct  {
    unsigned short AdcValue : 12;   // Bit 0..11
    unsigned short ShutDown : 1;    // Bit 12
    unsigned short Gain     : 1;    // Bit 13
    unsigned short VRef     : 1;    // Bit 14
    unsigned short Dac      : 1;    // Bit 15
} TMy_TypeDef;
 
void TMCP4922_sendValue(unsigned short Value)
{ TMy_TypeDef *p = &Value;
 
  p->ShutDown = TRUE;
  p->Gain     = GAIN_2X;
  p->VRef     = VREF_unbuffered;
  p->Dac      = DAC_A;
  SPI_Write(Value, 2);
}
 


Siro
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Pascal intelligente Sprache, dank bitpacked und absolute

Beitrag von siro »

in FPC kann man doch auch diese Variation verwenden : glaube ich ....

Code: Alles auswählen

type tSadc = bitpacked record  // Statusflags ADC
  AdcValue : 0..4095;   // Bit 0..11
  ShutDown : 0..1;    // Bit 12
  Gain     : 0..1;    // Bit 13
  VRef     : 0..1;    // Bit 14
  Dac      : 0..1;    // Bit 15
end;

Code: Alles auswählen

 
const GAIN_2X = 0;
const GAIN_1X = 1;
 
const VREF_unbuffered = 0;
const VREF_buffered   = 1;
 
const DAC_A = 0;
const DAC_B = 1;
 
type tSadc = bitpacked record  // Statusflags ADC
  AdcValue : 0..2047;   // Bit 0..11
  ShutDown : FALSE..TRUE;    // Bit 12
  Gain     : 0..1;    // Bit 13
  VRef     : 0..1;    // Bit 14
  Dac      : 0..1;    // Bit 15
end;
 
procedure Send(value:Uint16);
begin
  tSadc(value).ShutDown:=TRUE;
  tSadc(value).Vref:=VREF_unbuffered;
 
  // oder so:
  with tSadc(value) do begin
    ShutDown:=TRUE;
    Dac:=DAC_B;
  end;
 
end;
 
// zum testen ....
procedure TForm1.FormCreate(Sender: TObject);
var v : tSadc;
begin
  v.AdcValue:=100;
  v.ShutDown:=TRUE;
  v.Dac:=DAC_A;
  Send(Uint16(v));
  caption:=IntToStr(v.AdcValue);
end;
 
Zuletzt geändert von siro am Mo 13. Aug 2018, 16:20, insgesamt 2-mal geändert.
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Pascal intelligente Sprache, dank bitpacked und absolute

Beitrag von Timm Thaler »

siro hat geschrieben:In "C" würde ich das wohl so schreiben:

Code: Alles auswählen

void TMCP4922_sendValue(unsigned short Value)
{ TMy_TypeDef *p = &Value;
 
  p->ShutDown = TRUE;
  p->Gain     = GAIN_2X;
  p->VRef     = VREF_unbuffered;
  p->Dac      = DAC_A;
  SPI_Write(Value, 2);
}
 


Und eben dieses Rumgepointere kannst Du Dir in Pascal sparen. In Pascal kannst Du das direkt zuweisen.

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Pascal intelligente Sprache, dank bitpacked und absolute

Beitrag von Mathias »

in FPC kann man doch auch diese Variation verwenden : glaube ich ....

Bei SizeOf kommt 2 Byte raus, somit müsste es gehen.
Da wäre ein Wiki-Beitrag wert.

Es ist schon erstaunlich, was Pascal alle für Möglichkeiten zu Verfügung stellt. :shock:

Sieht auch recht Elegant aus, egal mit oder ohne with.

Code: Alles auswählen

  with tSadc(value) do begin
    ShutDown:=TRUE;
    Dac:=DAC_B;
  end;



Das kannte ich nicht von C++.
So wie es scheint, ist die Zahl hinter dem : massgebend.

Code: Alles auswählen

typedef struct  {
    unsigned short AdcValue : 12;   // Bit 0..11
    unsigned short ShutDown : 1;    // Bit 12
    unsigned short Gain     : 1;    // Bit 13
    unsigned short VRef     : 1;    // Bit 14
    unsigned short Dac      : 1;    // Bit 15
} TMy_TypeDef;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Pascal intelligente Sprache, dank bitpacked und absolute

Beitrag von Warf »

Mathias hat geschrieben:Das kannte ich nicht von C++.
So wie es scheint, ist die Zahl hinter dem : massgebend.

Code: Alles auswählen

typedef struct  {
    unsigned short AdcValue : 12;   // Bit 0..11
    unsigned short ShutDown : 1;    // Bit 12
    unsigned short Gain     : 1;    // Bit 13
    unsigned short VRef     : 1;    // Bit 14
    unsigned short Dac      : 1;    // Bit 15
} TMy_TypeDef;

geht sogar kürzer:

Code: Alles auswählen

typedef struct  {
    unsigned AdcValue : 12;   // Bit 0..11
    unsigned ShutDown : 1;    // Bit 12
    unsigned Gain     : 1;    // Bit 13
    unsigned VRef     : 1;    // Bit 14
    unsigned Dac      : 1;    // Bit 15
} TMy_TypeDef;


Aber wie gesagt, bei dem ganzen Low-Level kram geben sich Pascal und C nicht so viel, immerhin haben sich die Sprachen gegenseitig über Jahrzehnte hinweg gegenseitig beeinflusst. Ich hab bisher noch keinen C Code gefunden den ich nicht 1 zu 1 nach Pascal übersetzen konnte. Für mich ist Pascal eigentlich das bessere C, man kann genauso gut low level arbeiten wie mit C, kann aber dazu noch High Level features wie OOP verwenden und ist nicht so überladen wie C++

Timm Thaler hat geschrieben:Und eben dieses Rumgepointere kannst Du Dir in Pascal sparen. In Pascal kannst Du das direkt zuweisen.


Fairerweise muss man sagen das es auch schöne C++ Lösungen gibt die es in C so nicht gibt:

Code: Alles auswählen

void TMCP4922_sendValue(unsigned short Value)
{
  *(TMy_TypeDef*)&Value  = {
    .ShutDown = TRUE,
    .Gain     = GAIN_2X,
    .VRef     = VREF_unbuffered,
    .Dac      = DAC_A
  }
  SPI_Write(Value, 2);
}

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Pascal intelligente Sprache, dank bitpacked und absolute

Beitrag von Mathias »

Fairerweise muss man sagen das es auch schöne C++ Lösungen gibt die es in C so nicht gibt:

Habe ich das richtig gesehen, in C++ gibt es auch eine Art with ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten