unit TestLab1;
// TestLab 5.1, Burkhard Kainka 2026
// https://www.elektronik-labor.de/TLScript/TLScript.html
// Die Software ist frei und darf beliebig verändert werden.
{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, DateUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Menus,
  LCLType, ExtCtrls, synaser; //, RSCOM;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button10: TButton;
    Button11: TButton;
    Button12: TButton;
    Button13: TButton;
    Button14: TButton;
    Button15: TButton;
    Button16: TButton;
    Button17: TButton;
    Button18: TButton;
    Button19: TButton;
    Button2: TButton;
    Button20: TButton;
    Button21: TButton;
    Button22: TButton;
    Button23: TButton;
    Button24: TButton;
    Button25: TButton;
    Button26: TButton;
    Button27: TButton;
    Button28: TButton;
    Button29: TButton;
    Button3: TButton;
    Button30: TButton;
    Button31: TButton;
    Button32: TButton;
    Button33: TButton;
    Button34: TButton;
    Button35: TButton;
    Button36: TButton;
    Button37: TButton;
    Button38: TButton;
    Button39: TButton;
    Button4: TButton;
    Button40: TButton;
    Button41: TButton;
    Button42: TButton;
    Button43: TButton;
    Button44: TButton;
    Button45: TButton;
    Button46: TButton;
    Button47: TButton;
    Button48: TButton;
    Button49: TButton;
    Button5: TButton;
    Button50: TButton;
    Button51: TButton;
    Button52: TButton;
    Button53: TButton;
    Button54: TButton;
    Button55: TButton;
    Button56: TButton;
    Button57: TButton;
    Button58: TButton;
    Button59: TButton;
    Button6: TButton;
    Button60: TButton;
    Button61: TButton;
    Button62: TButton;
    Button63: TButton;
    Button64: TButton;
    Button65: TButton;
    Button66: TButton;
    Button67: TButton;
    Button68: TButton;
    Button69: TButton;
    Button7: TButton;
    Button70: TButton;
    Button71: TButton;
    Button72: TButton;
    Button73: TButton;
    Button74: TButton;
    Button75: TButton;
    Button76: TButton;
    Button77: TButton;
    Button78: TButton;
    Button79: TButton;
    Button8: TButton;
    Button80: TButton;
    Button81: TButton;
    Button82: TButton;
    Button83: TButton;
    Button84: TButton;
    Button85: TButton;
    Button86: TButton;
    Button87: TButton;
    Button88: TButton;
    Button89: TButton;
    Button9: TButton;
    Button90: TButton;
    Button91: TButton;
    Button92: TButton;
    ComboBox1: TComboBox;
    ComboBox2: TComboBox;
    Edit1: TEdit;
    Edit10: TEdit;
    Edit11: TEdit;
    Edit12: TEdit;
    Edit13: TEdit;
    Edit14: TEdit;
    Edit15: TEdit;
    Edit16: TEdit;
    Edit17: TEdit;
    Edit18: TEdit;
    Edit19: TEdit;
    Edit2: TEdit;
    Edit20: TEdit;
    Edit21: TEdit;
    Edit3: TEdit;
    Edit4: TEdit;
    Edit5: TEdit;
    Edit6: TEdit;
    Edit7: TEdit;
    Edit8: TEdit;
    Edit9: TEdit;
    GroupBox1: TGroupBox;
    Image1: TImage;
    Image2: TImage;
    Image3: TImage;
    Image4: TImage;
    Label1: TLabel;
    Label10: TLabel;
    Label11: TLabel;
    Label12: TLabel;
    Label13: TLabel;
    Label14: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    Label7: TLabel;
    Label8: TLabel;
    Label9: TLabel;
    ListBox1: TListBox;
    MainMenu1: TMainMenu;
    MenuItem1: TMenuItem;
    MenuItem2: TMenuItem;
    MenuItem3: TMenuItem;
    OpenDialog1: TOpenDialog;
    Panel1: TPanel;
    SaveDialog1: TSaveDialog;
    ScrollBar1: TScrollBar;
    ScrollBar2: TScrollBar;
    ScrollBar3: TScrollBar;
    ScrollBar4: TScrollBar;
    Shape1: TShape;
    Timer1: TTimer;
    Timer2: TTimer;
    Timer3: TTimer;
    procedure Button61Click(Sender: TObject);
    procedure Button62Click(Sender: TObject);
    procedure Button63Click(Sender: TObject);
    procedure Button64Click(Sender: TObject);
    procedure Button65Click(Sender: TObject);
    procedure Button66Click(Sender: TObject);
    procedure Button67Click(Sender: TObject);
    procedure Button68Click(Sender: TObject);
    procedure Button69Click(Sender: TObject);
    procedure Button70Click(Sender: TObject);
    procedure Button71Click(Sender: TObject);
    procedure Button72Click(Sender: TObject);
    procedure Button73Click(Sender: TObject);
    procedure Button74Click(Sender: TObject);
    procedure Button75Click(Sender: TObject);
    procedure Button76Click(Sender: TObject);
    procedure Button77Click(Sender: TObject);
    procedure Button78Click(Sender: TObject);
    procedure Button79Click(Sender: TObject);
    procedure Button80Click(Sender: TObject);
    procedure Button81Click(Sender: TObject);
    procedure Button82Click(Sender: TObject);
    procedure Button83Click(Sender: TObject);
    procedure Button84Click(Sender: TObject);
    procedure Button85Click(Sender: TObject);
    procedure Button86Click(Sender: TObject);
    procedure Button87Click(Sender: TObject);
    procedure Button88Click(Sender: TObject);
    procedure Button89Click(Sender: TObject);
    procedure Button90Click(Sender: TObject);
    procedure Button91Click(Sender: TObject);
    procedure Button92Click(Sender: TObject);
    procedure ComboBox1Change(Sender: TObject);
    procedure ComboBox2Change(Sender: TObject);
    procedure Edit10Change(Sender: TObject);
    procedure Edit11Change(Sender: TObject);
    procedure Edit9Change(Sender: TObject);
    procedure Edit9KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure Image4Click(Sender: TObject);
    procedure ListBox1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure Button59Click(Sender: TObject);
    procedure Button60Click(Sender: TObject);
    procedure LabelKorrektur();
    procedure Raster();
    function RepeatDelay(): Real;
    function MeasDelay(): Real;
    procedure Devices();
    procedure MenuItem1Click(Sender: TObject);
    procedure MenuItem2Click(Sender: TObject);
    procedure MenuItem3Click(Sender: TObject);
    procedure Panel1Enter(Sender: TObject);
    procedure ScrollBar1Change(Sender: TObject);
    procedure ScrollBar2Change(Sender: TObject);
    procedure ScrollBar3Change(Sender: TObject);
    procedure ScrollBar4Change(Sender: TObject);
    procedure Shape1ChangeBounds(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure Timer2Timer(Sender: TObject);
    procedure Timer3Timer(Sender: TObject);
    procedure ZeileEinfuegen(Zeile: String);
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    Ser: TBlockSerial;
    function GetNr: Integer;  // Methode der Klasse!
  public

  end;

var
  Form1: TForm1;


implementation

{$R *.lfm}

{ TForm1 }
var f: TextFile;
   Zeile, COMnr, OpenString, Device: String;
   r, i, p, d: Integer;
   RunStart: Integer;
   SelectedIndex: Integer;
   FileName: String;
   DatFileName: String;
   Typ_alt: Integer;
   Adresse, LabelNr, n: Integer;
   Labl: Array[0..255] of Byte;
   Ram: Array[0..255] of Byte;
   stop: Boolean;
   COMopen: Boolean;
const
  Commands: array[0..57, 0..2] of string = (
  ('0x09', 'Pdir = ', '1'),
  ('0x0A', 'Pullup = ', '1'),
  ('0x0B', 'Pulldown = ', '1'),
  ('0x08', 'Pout = ', '1'),

  ('0x01', 'A = ', '2'),
  ('0x02', 'B = ', '2'),
  ('0x03', 'C = ', '2'),
  ('0x04', 'D = ', '2'),

  ('0x10', 'PWM1 = ', '3'),
  ('0x11', 'PWM2 = ', '3'),
  ('0x12', 'A = A AND ', '3'),
  ('0x13', 'A = A OR ', '3'),
  
  ('0x18', 'Delay µs = ', '4'),
  ('0x19', 'Delay ms = ', '4'),
  ('0x1A', 'Delay s = ', '4'),
  ('0x1B', 'Delay min = ', '4'),

  ('              ', 'Label L', '5'),
  ('0x20', 'Jmp L', '5'),
  ('0x25', 'C*Jmp L', '5'),
  ('0x26', 'D*Jmp L', '5'),

  ('0x22', 'If A=B Jmp L', '6'),
  ('0x23', 'If A>B Jmp L', '6'),
  ('0x24', 'If A<B Jmp L', '6'),
  ('0x21', 'Call L', '6'),

  ('0x42', 'Print A', '0'),
  ('0x45', 'Pout = A', '0'),
  ('0x41', 'Input A', '0'),
  ('0x43', 'PWM1 = A', '0'),
  ('0x44', 'PWM2 = A', '0'),

  ('0x28', 'A = A + 1', '0'),
  ('0x29', 'A = A - 1', '0'),
  ('0x2A', 'A = A + B', '0'),
  ('0x2B', 'A = A - B', '0'),
  ('0x33', 'A = Not A', '0'),

  ('0x2C', 'A = A * B', '0'),
  ('0x2D', 'A = A / B', '0'),
  ('0x2E', 'A = A And B', '0'),
  ('0x2F', 'A = A Or B', '0'),
  ('0x30', 'A = A Xor B', '0'),

  ('0x35', 'A = B', '0'),
  ('0x37', 'A = C', '0'),
  ('0x39', 'A = D', '0'),
  ('0x31', 'A = A Shl 1', '0'),
  ('0x32', 'A = A Shr 1', '0'),

  ('0x34', 'B = A', '0'),
  ('0x36', 'C = A', '0'),
  ('0x38', 'D = A', '0'),
  ('0x3A', 'A = [B+]', '0'),
  ('0x3B', '[B+] = A', '0'),

  ('0x3C', 'A = AD0', '0'),
  ('0x3D', 'A = AD1', '0'),
  ('0x3E', 'A = AD2', '0'),
  ('0x40', 'A = Pin0', '0'),
  ('0x3F', 'A = Pin', '0'),

  ('0x4A', 'Nop', '0'),
  ('0x48', 'Ret', '0'),
  ('0x49', 'End', '0'),
  ('              ', 'Rem ', '7')
  );

  function BinStrToInt(BinStr: string): Integer;
  var
    i, Value: Integer;
  begin
    Value := 0;
    for i := 1 to Length(BinStr) do
    begin
      Value := Value shl 1;
      if BinStr[i] = '1' then
        Inc(Value);
    end;
    Result := Value;
  end;

function ConvertToInteger(Input: string): Integer;
    begin
      Input := upcase(Input);

      if (Length(Input) > 2) and ((Input[1] = '0') and (Input[2] in ['x', 'X'])) then
        Result := StrToInt('$' + Copy(Input, 3, Length(Input) - 2))
      else if (Length(Input) > 2) and ((Input[1] = '0') and (Input[2] in ['b', 'B'])) then
        Result := StrToInt('$' + IntToHex(BinStrToInt(Copy(Input, 3, Length(Input) - 2)), 8)) // Binär (z.B. 0b1010)
      else
        TryStrToInt(Input, Result); // Dezimal
    end;

function TForm1.GetNr: Integer;
var
  txt: String;
  d: Integer;
  start: TDateTime;
begin
  txt := '';
  if COMopen and not stop then
  begin
    start := Now;
    repeat
      Application.ProcessMessages;
      if stop then Break;

      // Erst prüfen, ob überhaupt ein Byte verfügbar ist
      if Ser.CanReadEx(10) then    // 10 ms warten
      begin
        d := Ser.RecvByte(0);      // jetzt ohne extra Timeout
        if (d > 47) and (d < 58) then
          txt := txt + Chr(d);
      end;

      // Sicherheits-Timeout, z.B. nach 1 s abbrechen
     // if MilliSecondsBetween(Now, start) > 1000 then
     //   Break;
    until (d = 10);
  end;

  if txt = '' then
    txt := '0';
  Result := StrToInt(txt) and 255;
end;

procedure TForm1.LabelKorrektur();
  var
    Ladr, Lnr, n, p: Integer;
    Ganz, Teil: String;
  begin
    Ladr := 0;
    for n := 1 To Form1.ListBox1.Items.Count -2 do begin
      Teil := copy(Form1.ListBox1.Items[n],1,2);
      If copy(Form1.ListBox1.Items[n],1,2) = '0x' then  begin
        Ladr := Ladr + 1;
      end;
      Teil := copy(Form1.ListBox1.Items[n],1,15);
      if copy(Form1.ListBox1.Items[n],1,15) = '              L' then begin
          Teil :=  copy(Form1.ListBox1.Items[n],16,length(Form1.ListBox1.Items[n])-16);
          Lnr := StrToInt (copy(Form1.ListBox1.Items[n],16,length(Form1.ListBox1.Items[n])-16));
          Labl[Lnr] := Ladr;
      end;
    end;

    Ladr := 0;
    for n := 1 To Form1.ListBox1.Items.Count -2 do begin
        if ConvertToInteger(copy(Form1.ListBox1.Items[n],1,4)) in [32..38] Then  begin
          If copy(ListBox1.Items[n],1,5) <> '0x21F' then  begin
            Ganz := Form1.ListBox1.Items[n];
              p := Pos('L', Ganz);
              Teil := copy(Ganz,p+1,length(Ganz)-p-1);
              Lnr := StrToInt(Teil);
              Ladr :=  Labl[Lnr];
              Teil := intToHex(Ladr);
              Zeile := copy (Ganz,1,4) + copy(Teil,length(Teil)-1,2) +  copy(Ganz,7,length(Ganz)-6);
              Form1.ListBox1.Items[n] := Zeile;
          end;
         end;
       end;
    d:=Ladr;
   end;


procedure TForm1.Panel1Enter(Sender: TObject);
begin

end;

procedure TForm1.ScrollBar1Change(Sender: TObject);
var
  d: Integer;
begin
    d := ScrollBar1.Position;
    Label9.Caption := 'PWM1 = ' + intToStr(d);
    Ser.SendString (pchar('O' + IntToStr(d)));
    Ser.SendByte (13);
end;

procedure TForm1.ScrollBar2Change(Sender: TObject);
var
  d: Integer;
begin
    d := ScrollBar2.Position;
    Label10.Caption := 'PWM2 = ' + intToStr(d);
    Ser.SendString (pchar('P' + IntToStr(d)));
    Ser.SendByte (13);
end;

procedure TForm1.ScrollBar3Change(Sender: TObject);
var
  d: Integer;
begin
  d := ScrollBar3.Position;
  if device = 'Tiny' then begin
    Ser.SendString (pchar('W' + IntToStr(d)));
    Ser.SendByte (13);
    If d = 0 Then Label11.Caption := '0,55 V';
    If d = 1 Then Label11.Caption := '1,1 V';
    If d = 2 Then Label11.Caption := '1,5 V';
    If d = 3 Then Label11.Caption := '2,5 V';
    If d = 4 Then Label11.Caption := '4,3 V';
    If d = 5 Then Label11.Caption := 'VDD';
  end;
  if device = 'Nano' then begin
    Ser.SendString (pchar('W' + IntToStr(d)));
    Ser.SendByte (13);
    If d = 0 Then Label11.Caption := '1,1 V';
    If d = 1 Then Label11.Caption := 'Ext';
    If d = 2 Then Label11.Caption := 'VDD';
  end;

end;

procedure TForm1.ScrollBar4Change(Sender: TObject);
var
  d: Integer;
const
  PicoDiv: array[0..10] of Integer = (250, 166, 125, 100, 50, 25, 20, 10, 5, 2, 1);
  CHDiv: array[0..10] of Integer = (187, 125, 93, 75, 38, 18, 15, 7, 3, 2, 1);
begin
  d := ScrollBar4.Position;
  if device = 'Nano' then begin
    Ser.SendString (pchar('V' + IntToStr(d)));
    Ser.SendByte (13);
    If d = 0 Then Label12.Caption := '30 Hz';
    If d = 1 Then Label12.Caption := '120 Hz';
    If d = 2 Then Label12.Caption := '490 Hz';
    If d = 3 Then Label12.Caption := '3,9 kHz';
    If d = 4 Then Label12.Caption := '31 kHz';
  end;
  if device = 'Tiny' then begin
    d := 7 - d;
    Ser.SendString (pchar('V' + IntToStr(d)));
    Ser.SendByte (13);
    If d = 0 Then Label12.Caption := '78.1 kHz';
    If d = 1 Then Label12.Caption := '39.1 kHz';
    If d = 2 Then Label12.Caption := '19.5 kHz';
    If d = 3 Then Label12.Caption := '9.8 kHz';
    If d = 4 Then Label12.Caption := '4.9 kHz';
    If d = 5 Then Label12.Caption := '1.2 kHz';
    If d = 6 Then Label12.Caption := '305 Hz';
    If d = 7 Then Label12.Caption := '76 Hz';
  end;
  if device = 'Pico' then begin
    d := PicoDiv[d];
    Label12.Caption := FloatToStr(round(2500/d)/10) + ' kHz';
    Ser.SendString (pchar('V' + IntToStr(d)));
    Ser.SendByte (13);
  end;
  if device = 'CH32' then begin
    d := CHDiv[d];
    Label12.Caption := FloatToStr(round(480000/256/d)/10) + ' kHz';
    Ser.SendString (pchar('V' + IntToStr(d)));
    Ser.SendByte (13);
  end;




end;

procedure TForm1.Shape1ChangeBounds(Sender: TObject);
begin

end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  n: Integer;
begin
  if RunStart = 1 then
  begin
    Ser.Purge;
    Edit8.Text := '';
    RunStart := 0;
    Exit;
  end;

  // maximal 4 Bytes pro Tick, aber nur, wenn verfügbar
  for n := 1 to 4 do
  begin
    if Ser.CanReadEx(0) then
    begin
      d := Ser.RecvByte(0);  // oder kleiner Timeout
      if d = 13 then
        Edit8.Text := Edit8.Text + ' '
      else if d > 47 then
      begin
        Edit8.Text := Edit8.Text + Chr(d);
        Edit8.SelStart := Length(Edit8.Text);
      end;
    end
    else
      Break;  // nichts zu lesen → Schleife abbrechen
  end;
end;

procedure TForm1.Timer2Timer(Sender: TObject);
begin
  if ComOpen then begin
    Ser.Purge;
    Ser.SendString ('A');    Label1.Caption := 'A=' + IntToStr(GetNr());
    Ser.SendString ('B');    Label2.Caption := 'B=' + IntToStr(GetNr());
    Ser.SendString ('C');    Label3.Caption := 'C=' + IntToStr(GetNr());
    Ser.SendString ('D');    Label4.Caption := 'D=' + IntToStr(GetNr());
    Ser.SendString ('E');    Label6.Caption := 'AD0=' + IntToStr(GetNr());
    Ser.SendString ('F');    Label7.Caption := 'AD1=' + IntToStr(GetNr());
    Ser.SendString ('G');    Label8.Caption := 'AD2=' + IntToStr(GetNr());
    Ser.SendString ('H');    Label5.Caption := 'Pin=' + IntToStr(GetNr());
  end;
end;

procedure TForm1.Timer3Timer(Sender: TObject);
begin
  if (not Timer2.enabled) and Stop then begin
    Ser.Purge();
  end;
end;

procedure  TForm1.ZeileEinfuegen(Zeile: String);
var
  SelectedIndex: Integer;
  LastIndex: Integer;
begin
  SelectedIndex := ListBox1.ItemIndex;
  LastIndex := ListBox1.Items.Count;
  if (SelectedIndex > 0) And ((SelectedIndex) < LastIndex) then
  begin
   SelectedIndex := Form1.ListBox1.ItemIndex;
   ListBox1.Items.Insert(SelectedIndex, Zeile);
   ListBox1.TopIndex := Form1.ListBox1.Items.Count - 1;
   ListBox1.ItemIndex := SelectedIndex+1;
  end;
  Adresse := Adresse + 1;
  LabelKorrektur();
end;

procedure TForm1.ListBox1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
var
  SelectedIndex: Integer;
  LastIndex: Integer;
begin
  SelectedIndex := ListBox1.ItemIndex;
  LastIndex := ListBox1.Items.Count;
  if Key = VK_DELETE then
  begin
    if (SelectedIndex > 0) And ((SelectedIndex+1) < LastIndex) then
    begin
      ListBox1.Items.Delete(ListBox1.ItemIndex);
      ListBox1.ItemIndex := SelectedIndex;
      LabelKorrektur();
    end;
  end;
end;

procedure TForm1.Button61Click(Sender: TObject);
begin
   ListBox1.Clear;
   ListBox1.Items.Insert(0, '        <<<');
   ListBox1.Items.Insert(1, '        >>>');
   ListBox1.ItemIndex := 1;
   Adresse := 0;
   LabelNr := 0;
   Edit5.Text := '0';
   Edit6.Text := '1';
end;

procedure TForm1.Button62Click(Sender: TObject); //Run
var
  Teil: String;
begin
  if not Ser.InstanceActive then Edit8.text := 'COM error'
  else begin
    COMopen:= true;
    //If Device = 'Pico' then Ser.DTR := True Else Ser.DTR := False;
    //Ser.RTS := False;
    Timer1.enabled := false;
    Ser.SendString (pchar('I'));   //Stop
    Sleep(200);
    p := 0;
    for n:=1 to ListBox1.Items.Count -2 do begin
     Zeile := ListBox1.Items[n];
     if (copy(Zeile,1,2))> '  ' then p := p + 1;
    end;
    Edit8.text := 'p'+ IntToStr(p) + '  ';
    Ser.SendString (pchar('p'+ (IntToStr(p))+chr(13)));
    Sleep(1);
    for n:=1 to ListBox1.Items.Count -2 do begin
      Zeile := ListBox1.Items[n];
      Teil :=(copy(Zeile,1,6));
      if Teil > '      ' then begin
        d := ConvertToInteger(Teil);
        Edit8.text := Edit8.text + IntToStr(d) + ' ';
        Sleep(1);
        Ser.SendString (pchar(IntToStr(d)+chr(13)));
        Application.Processmessages;
        Sleep(1);
      end;
    end;
  end;
  RunStart := 1;
  Timer1.enabled := true;
end;

procedure TForm1.Button63Click(Sender: TObject);  //EEprom
 var
   Teil: String;
   begin
     if not Ser.InstanceActive then Edit8.text := 'COM error'
     else begin
       COMopen:= true;
       //If Device = 'Pico' then Ser.DTR := True Else Ser.DTR := False;
       //Ser.RTS := False;
       Timer1.enabled := false;
       Ser.SendString (pchar('I'));   //Stop
       Sleep(200);;
       p := 0;
       for n:=1 to ListBox1.Items.Count -2 do begin
        Zeile := ListBox1.Items[n];
        if (copy(Zeile,1,2))> '  ' then p := p + 1;
       end;
       Edit8.text := 'e'+ IntToStr(p) + '  ';
       Ser.SendString (pchar('e'+ (IntToStr(p))+chr(13)));
       Sleep(20);
       for n:=1 to ListBox1.Items.Count -2 do begin
         Zeile := ListBox1.Items[n];
         Teil :=(copy(Zeile,1,6));
         if Teil > '      ' then begin
           d := ConvertToInteger(Teil);
           Edit8.text := Edit8.text + IntToStr(d) + ' ';
           Ser.SendString (pchar(IntToStr(d)+chr(13)));
           Application.Processmessages;
           Sleep(10);
         end;
       end;
     end;
     RunStart := 1;
     Timer1.enabled := true;
   end;

procedure TForm1.Button64Click(Sender: TObject);    //Stop
begin
    Ser.SendString (pchar('I'));
    //Timer1.enabled := false;
end;

procedure TForm1.Button65Click(Sender: TObject);    //Go
begin
         Ser.SendString (pchar('J'));
         Timer1.enabled := true;
end;

const
  ScaleFactorX = 800 / 500; // Umrechnungsfaktor für die Breite

procedure DrawScaledDiagram(Canvas: TCanvas);
var
  i: Integer;
begin
  Canvas.Brush.Color := clWhite;
  Canvas.FillRect(Rect(0, 0, 800, 600));
  Canvas.Pen.Color := clBlack;
  for i := 0 to 500 do
  begin
    Canvas.MoveTo(Round(i * 1.5), 100);
    Canvas.LineTo(Round(i * 1.5), 200);
  end;
end;

procedure TForm1.Raster();   //Raster
var
  n: Integer;
begin
  Panel1.Canvas.Pen.Width:=1;
  Panel1.Canvas.Brush.Color:= clWhite;
  Panel1.Canvas.Pen.Color:= clBlack;
  Panel1.Canvas.Rectangle (8, 8,714,296);
  Panel1.Canvas.Pen.Color:= clGreen;
  for n:= 1 to 9 do begin
     Panel1.Canvas.Line(10+round(n*70.025), 10, 10+ round(n*70.025), 296);
     Panel1.Canvas.Line(10, 293-round(n*25*1.11), 715 ,293-round(n*25*1.11));
  end;
end;

function TForm1.RepeatDelay(): Real;
var
  n: integer;
  Eingabe: String;
  c: Char;
begin
  Eingabe := Edit21.Text;
  for n:= 1 to length(Eingabe) do begin
    if Eingabe[n] = '.' then Eingabe[n] := ',';
  end;
  Result := StrToFloatDef(Eingabe, 0) *1000;
end;

function TForm1.MeasDelay(): Real;
var
  n: integer;
  Eingabe: String;
  c: Char;
begin
  Eingabe := Edit10.Text;
  for n:= 1 to length(Eingabe) do begin
    if Eingabe[n] = '.' then Eingabe[n] := ',';
  end;
  Result := StrToFloatDef(Eingabe, 0) *20;
end;


procedure TForm1.Button66Click(Sender: TObject);       //Plotter
var
  n: Integer;
  d: Real;
  t, tt, warten: Real;
  Eingabe: String;
begin
  stop := false;
  repeat
    Raster;
    Timer1.enabled := false;
    Timer2.enabled := false;
    Ser.Purge;
    Panel1.Canvas.Pen.Color:= clBlack;
    Panel1.Canvas.Pen.Width:=3;
    if ComOpen then begin
    d := GetNr();
    end;
    Ram[0] := Trunc(d) and 255;
    Panel1.Canvas.MoveTo(9,293-round(d*1.11));
    Application.Processmessages;
    n:=1;
    repeat
      if ComOpen then begin
      d := GetNr();
      end;
      if stop then break;
      Ram[n] := Trunc(d) and 255;
      if (n<250) then begin Panel1.Canvas.LineTo (9+round(2*n*1.405), 293-round(d*1.11)); end;
      n := n+1;
    until (n = 256) Or stop;
    warten := RepeatDelay();
    tt := GetTickCount64() + warten;
    while tt > GetTickCount64() do Application.Processmessages;
  until stop or (warten = 0);
  stop := true;
end;

procedure TForm1.Button67Click(Sender: TObject);   //Plotter2
var
  n: Integer;
  d1, d2, e1, e2: Real;
  t, tt, warten: Real;
  Eingabe: String;
begin
  stop := false;
  repeat
    Raster;
    Timer1.enabled := false;
    Timer2.enabled := false;
    Ser.Purge;
    Panel1.Canvas.Pen.Color:= clBlack;
    Panel1.Canvas.Pen.Width:=3;
    if ComOpen then begin
    d1 := GetNr();
    e1 := GetNr();
    end;
    n:=1;
    repeat
      if stop then break;
      if ComOpen then begin
      d2 := GetNr();
      e2 := GetNr();
      end;
      Panel1.Canvas.MoveTo (9+round((n-1)*2*1.405), 293-round(d1*1.11));
      Panel1.Canvas.LineTo (9+round(n*2*1.405), 293-round(d2*1.11));
      Panel1.Canvas.MoveTo (9+round((n-1)*2*1.405), 293-round(e1*1.11));
      Panel1.Canvas.LineTo (9+round(n*2*1.405), 293-round(e2*1.11));
      n := n+1;
      d1 := d2;
      e1 := e2;
    until (n = 250) Or stop;
    warten := RepeatDelay();
    tt := GetTickCount64 +  warten;
    while tt > GetTickCount64 do Application.Processmessages;
  until stop or (warten = 0);
  stop := true;
end;

procedure TForm1.Button68Click(Sender: TObject);    //XY
var
  n: Integer;
  d1, d2, e1, e2: Real;
  t, tt, warten: Real;
  Eingabe: String;
begin
  stop := false;
  repeat
    Raster;
    Timer1.enabled := false;
    Timer2.enabled := false;
    if ComOpen then begin
    Ser.Purge;
    Panel1.Canvas.Pen.Color:= clBlack;
    Panel1.Canvas.Pen.Width:=3;
    d1 := GetNr();
    e1 := GetNr();
    end;
    Panel1.Canvas.MoveTo((9+round(d1*2 * 1.376)),293-round(e1*1.11));
    n:=0;
    repeat
      if stop then break;
      if ComOpen then begin
      d2 := GetNr();
      e2 := GetNr();
      end;
      if not stop then Panel1.Canvas.LineTo((9+round(d2*2 * 1.376)),293-round(e2*1.11));
      n := n+1;
    until (n = 512) Or stop;
    warten := RepeatDelay();
    tt := GetTickCount64 +  warten;
    while tt > GetTickCount64 do Application.Processmessages;
  until stop or (warten = 0);
  stop := true;
end;


procedure TForm1.Button69Click(Sender: TObject);   //Bit 0...7
var
  n: Integer;
  d, d_alt: Integer;
  t, tt, warten: Real;
  Eingabe: String;
begin
  stop := false;
  repeat
    Raster;
    Timer1.enabled := false;
    Timer2.enabled := false;
    if ComOpen then begin
    Ser.Purge;
   // if ComOpen then while INBUFFER() = 0 do Application.Processmessages;
    Panel1.Canvas.Pen.Color:= clBlack;
    Panel1.Canvas.Pen.Width:=1;
    d_alt := round(GetNr());
    end;
    n:=0;
    repeat
      if stop then break;
      if ComOpen then begin
      d := round (GetNr());
      end;
      Panel1.Canvas.MoveTo (9+round(n*2*1.405),289-round((d_alt And 1)*16*1.11));
      Panel1.Canvas.LineTo (9+round((n*2+2)*1.405), 289-round((d_alt And 1)* 16*1.11));
      Panel1.Canvas.LineTo (9+round((n*2+2)*1.405), 289-round((d And 1)*16*1.11));

      Panel1.Canvas.MoveTo (9+round(n*2*1.405),259-round((d_alt And 2)*8*1.11));
      Panel1.Canvas.LineTo (9+round((n*2+2)*1.408), 259-round((d_alt And 2)* 8*1.11));
      Panel1.Canvas.LineTo (9+round((n*2+2)*1.408), 259-round((d And 2)*8*1.11));

      Panel1.Canvas.MoveTo (9+round(n*2*1.405),232-round((d_alt And 4)*4*1.11));
      Panel1.Canvas.LineTo (9+round((n*2+2)*1.405), 232-round((d_alt And 4)* 4*1.11));
      Panel1.Canvas.LineTo (9+round((n*2+2)*1.405), 232-round((d And 4)*4*1.11));

      Panel1.Canvas.MoveTo (9+round(n*2*1.405),205-round((d_alt And 8)*2*1.11));
      Panel1.Canvas.LineTo (9+round((n*2+2)*1.405), 205-round((d_alt And 8)* 2*1.11));
      Panel1.Canvas.LineTo (9+round((n*2+2)*1.405), 205-round((d And 8)*2*1.11));

      Panel1.Canvas.MoveTo (9+round(n*2*1.405),176-round((d_alt And 16)*1*1.11));
      Panel1.Canvas.LineTo (9+round((n*2+2)*1.405), 176-round((d_alt And 16)* 1*1.11));
      Panel1.Canvas.LineTo (9+round((n*2+2)*1.405), 176-round((d And 16)*1*1.11));

      Panel1.Canvas.MoveTo (9+round(n*2*1.405),148-round((d_alt And 32)/2*1.11));
      Panel1.Canvas.LineTo (9+round((n*2+2)*1.405), 148-round((d_alt And 32)/2*1.11));
      Panel1.Canvas.LineTo (9+round((n*2+2)*1.405), 148-round((d And 32)/2*1.11));

      Panel1.Canvas.MoveTo (9+round(n*2*1.405),120-round((d_alt And 64)/4*1.11));
      Panel1.Canvas.LineTo (9+round((n*2+2)*1.405), 120-round((d_alt And 64)/4*1.11));
      Panel1.Canvas.LineTo (9+round((n*2+2)*1.405), 120-round((d And 64)/4*1.11));

      Panel1.Canvas.MoveTo (9+round(n*2*1.405),93-round((d_alt And 128)/8*1.11));
      Panel1.Canvas.LineTo (9+round((n*2+2)*1.405), 93-round((d_alt And 128)/8*1.11));
      Panel1.Canvas.LineTo (9+round((n*2+2)*1.405), 93-round((d And 128)/8*1.11));
      n := n+1;
      d_alt := d;
    until (n = 249) Or stop;
    warten := RepeatDelay();
    tt := GetTickCount64() + warten;
    while tt > GetTickCount64() do Application.Processmessages;
  until stop or (warten = 0);
  stop := true;
end;



procedure TForm1.Button70Click(Sender: TObject);    //AD0
var
  n: Integer;
  d: Real;
  t, tt, warten: Real;
begin
  stop := false;
  repeat
    Raster;
    Timer1.enabled := false;
    Timer2.enabled := false;
    Panel1.Canvas.Pen.Color:= clBlack;
    Panel1.Canvas.Pen.Width:=2;
    Stop := true;
    Application.Processmessages;
    Sleep (250);
    Application.Processmessages;
    stop := false;
    t := MeasDelay();
    tt := GetTickCount64() + t;
    if ComOpen then begin
    Ser.Purge;
    Ser.SendByte(69);
    d := GetNr();
    end;
    Panel1.Canvas.MoveTo(9,293-round(d*1.11));
    n:=1;
    repeat
      while tt > GetTickCount64() do Application.Processmessages;
      tt := tt + t;
      if stop then break;
      if ComOpen then begin
      Ser.SendByte(69);
      d := GetNr();
      end;
      Panel1.Canvas.LineTo (9+round(n*1.405), 293-round(d*1.11));
      n := n+1;
    until (n = 500) or stop;
    warten := RepeatDelay();
    tt := GetTickCount() + warten;
    while tt > GetTickCount() do Application.Processmessages;
  until stop or (warten = 0);
  stop := true;
end;


procedure TForm1.Button71Click(Sender: TObject);  //AD1
var
  n: Integer;
  d: Real;
  t, tt, warten: Real;
begin
  repeat
    Raster;
    Timer1.enabled := false;
    Timer2.enabled := false;
    Panel1.Canvas.Pen.Color:= clBlack;
    Panel1.Canvas.Pen.Width:=2;
    Stop := true;
    Application.Processmessages;
    Sleep (250);
    Application.Processmessages;
    stop := false;
    t := MeasDelay();
    tt := GetTickCount64() + t;
    if ComOpen then begin
    Ser.Purge;
    if ComOpen then Ser.SendByte(70);
    d := GetNr();
    end;
     Panel1.Canvas.MoveTo(9,293-round(d*1.11));
    n:=1;
    repeat
      if stop then break;
      while tt > GetTickCount64() do Application.Processmessages;
      tt := tt + t;
      if ComOpen then begin
      if ComOpen then Ser.SendByte(70);
      d := GetNr();
      end;
      Panel1.Canvas.LineTo (9+round(n*1.405), 293-round(d*1.11));
      n := n+1;
    until (n = 500) or stop;
    warten := RepeatDelay();
    tt := GetTickCount64() + warten;
    while tt > GetTickCount64() do Application.Processmessages;
  until stop or (warten = 0);
  stop := true;
end;

procedure TForm1.Button72Click(Sender: TObject);   //AD0/1
var
  n: Integer;
  d1, d2, e1, e2: Real;
  t, tt, warten: Real;
  Eingabe: String;
begin
  repeat
    Raster;
    Timer1.enabled := false;
    Timer2.enabled := false;
    Panel1.Canvas.Pen.Color:= clBlack;
    Panel1.Canvas.Pen.Width:=2;
    Stop := true;
    Application.Processmessages;
    Sleep (250);
    Application.Processmessages;
    stop := false;
    Application.Processmessages;
    Sleep (250);
    Application.Processmessages;
    stop := false;
    Timer1.enabled := false;
    t := MeasDelay();
    tt := GetTickCount64() + t;
    if ComOpen then begin
    Ser.Purge;
    if ComOpen then Ser.SendByte(69);
    d1 := GetNr();
    if ComOpen then Ser.SendByte(70);
    e1 := GetNr();
    end;
    n:=1;
    repeat
      if stop then break;
      while tt > GetTickCount64() do Application.Processmessages;
      tt := tt + t;
      if ComOpen then begin
      if ComOpen then Ser.SendByte(69);
      d2 := GetNr();
      if ComOpen then Ser.SendByte(70);
      e2 := GetNr();
      end;
      Panel1.Canvas.Pen.Color:= clBlack;
      Panel1.Canvas.MoveTo (9+round(n*1.405), 293-round(d1*1.11));
      Panel1.Canvas.LineTo (9+round(n*1.405), 293-round(d2*1.11));
      Panel1.Canvas.Pen.Color:= clRed;
      Panel1.Canvas.MoveTo (9+round(n*1.405), 293-round(e1*1.11));
      Panel1.Canvas.LineTo (9+round(n*1.405), 293-round(e2*1.11));
      n := n+1;
      d1 := d2;
      e1 := e2;
    until (n = 500) Or stop;
    Panel1.Canvas.Pen.Color:= clBlack;
    warten := RepeatDelay();
    tt := GetTickCount64() +  warten;
    while tt > GetTickCount64() do Application.Processmessages;
  until stop or (warten = 0);
  stop := true;

end;

procedure TForm1.Button73Click(Sender: TObject);   //AD0/1/2
var
  n: Integer;
  d1, d2, e1, e2, f1, f2: Real;
  t, tt, warten: Real;
  Eingabe: String;
begin
  stop := false;
  repeat
    if stop then break;
    Raster;
    Timer1.enabled := false;
    Timer2.enabled := false;
    Panel1.Canvas.Pen.Color:= clBlack;
    Panel1.Canvas.Pen.Width:=2;
    Stop := true;
    Application.Processmessages;
    Sleep (250);
    Application.Processmessages;
    stop := false;
    Ser.Purge;
    t := MeasDelay();
    tt := GetTickCount64() + t;
    Sleep(20);
    Ser.Purge;
    Panel1.Canvas.Pen.Color:= clBlack;
    Panel1.Canvas.Pen.Width:=2;
    if ComOpen then begin
    if ComOpen then Ser.SendByte(69);
    d1 := GetNr();
    if ComOpen then Ser.SendByte(70);
    e1 := GetNr();
    if ComOpen then Ser.SendByte(71);
    f1 := GetNr();
    end;
    n:=1;
    repeat
      while tt > GetTickCount64() do Application.Processmessages;
      tt := tt + t;
      if ComOpen then begin
      if ComOpen then Ser.SendByte(69);
      d2 := GetNr();
      if ComOpen then Ser.SendByte(70);
      e2 := GetNr();
      if ComOpen then Ser.SendByte(71);
      f2 := GetNr();
      end;
      Panel1.Canvas.Pen.Color:= clBlack;
      Panel1.Canvas.MoveTo (9+round(n*1.405), 293-round(d1*1.11));
      Panel1.Canvas.LineTo (9+round(n*1.405), 293-round(d2*1.11));
      Panel1.Canvas.Pen.Color:= clRed;
      Panel1.Canvas.MoveTo (9+round(n*1.405), 293-round(e1*1.11));
      Panel1.Canvas.LineTo (9+round(n*1.405), 293-round(e2*1.11));
      Panel1.Canvas.Pen.Color:= clGreen;
      Panel1.Canvas.MoveTo (9+round(n*1.405), 293-round(f1*1.11));
      Panel1.Canvas.LineTo (9+round(n*1.405), 293-round(f2*1.11));
      n := n+1;
      d1 := d2;
      e1 := e2;
      f1 := f2;
    until (n = 500) Or stop;
    Panel1.Canvas.Pen.Color:= clBlack;
    warten := RepeatDelay();
    tt := GetTickCount() +  warten;
    while tt > GetTickCount() do Application.Processmessages;
  until stop or (warten = 0);
  stop := true;
end;

procedure TForm1.Button74Click(Sender: TObject);    //Port 0...7
var
  n: Integer;
  d, d_alt: Integer;
  t, tt, warten: Real;
begin
  stop := false;
  repeat
    Raster;
    Timer1.enabled := false;
    Timer2.enabled := false;
    Panel1.Canvas.Pen.Color:= clBlack;
    Panel1.Canvas.Pen.Width:=2;
    Stop := true;
    Application.Processmessages;
    Sleep (250);
    Application.Processmessages;
    stop := false;
    if ComOpen then begin
    Ser.Purge;
    Panel1.Canvas.Pen.Color:= clBlack;
    Panel1.Canvas.Pen.Width:=1;
    t := MeasDelay();
    tt := GetTickCount64() + t;
    if ComOpen then Ser.SendByte(72);
    d_alt := GetNr();
    end;
    Panel1.Canvas.MoveTo(12,368-round(d_alt*1.4));
    n:=0;
    repeat
      while tt > GetTickCount64() do Application.Processmessages;
      tt := tt + t;
      if stop then break;
      if ComOpen then begin
      if ComOpen then Ser.SendString('H');
      d := GetNr();
      end;
      Panel1.Canvas.MoveTo (9+round(n*1.405),289-round((d_alt And 1)*16*1.11));
      Panel1.Canvas.LineTo (9+round((n+1)*1.405), 289-round((d_alt And 1)* 16*1.11));
      Panel1.Canvas.LineTo (9+round((n+1)*1.405), 289-round((d And 1)*16*1.11));

      Panel1.Canvas.MoveTo (9+round(n*1.405),259-round((d_alt And 2)*8*1.11));
      Panel1.Canvas.LineTo (9+round((n+1)*1.408), 259-round((d_alt And 2)* 8*1.11));
      Panel1.Canvas.LineTo (9+round((n+1)*1.408), 259-round((d And 2)*8*1.11));

      Panel1.Canvas.MoveTo (9+round(n*1.405),232-round((d_alt And 4)*4*1.11));
      Panel1.Canvas.LineTo (9+round((n+1)*1.405), 232-round((d_alt And 4)* 4*1.11));
      Panel1.Canvas.LineTo (9+round((n+1)*1.405), 232-round((d And 4)*4*1.11));

      Panel1.Canvas.MoveTo (9+round(n*1.405),205-round((d_alt And 8)*2*1.11));
      Panel1.Canvas.LineTo (9+round((n+1)*1.405), 205-round((d_alt And 8)* 2*1.11));
      Panel1.Canvas.LineTo (9+round((n+1)*1.405), 205-round((d And 8)*2*1.11));

      Panel1.Canvas.MoveTo (9+round(n*1.405),176-round((d_alt And 16)*1*1.11));
      Panel1.Canvas.LineTo (9+round((n+1)*1.405), 176-round((d_alt And 16)* 1*1.11));
      Panel1.Canvas.LineTo (9+round((n+1)*1.405), 176-round((d And 16)*1*1.11));

      Panel1.Canvas.MoveTo (9+round(n*1.405),148-round((d_alt And 32)/2*1.11));
      Panel1.Canvas.LineTo (9+round((n+1)*1.405), 148-round((d_alt And 32)/2*1.11));
      Panel1.Canvas.LineTo (9+round((n+1)*1.405), 148-round((d And 32)/2*1.11));

      Panel1.Canvas.MoveTo (9+round(n*1.405),120-round((d_alt And 64)/4*1.11));
      Panel1.Canvas.LineTo (9+round((n+1)*1.405), 120-round((d_alt And 64)/4*1.11));
      Panel1.Canvas.LineTo (9+round((n+1)*1.405), 120-round((d And 64)/4*1.11));

      Panel1.Canvas.MoveTo (9+round(n*1.405),93-round((d_alt And 128)/8*1.11));
      Panel1.Canvas.LineTo (9+round((n+1)*1.405), 93-round((d_alt And 128)/8*1.11));
      Panel1.Canvas.LineTo (9+round((n+1)*1.405), 93-round((d And 128)/8*1.11));
      n := n+1;
      d_alt := d;
    until (n = 500) or stop;
    warten := RepeatDelay();
    tt := GetTickCount() + warten;
    while tt > GetTickCount() do Application.Processmessages;
  until stop or (warten = 0);
  stop := true;
end;

procedure TForm1.Button75Click(Sender: TObject);     //On
begin
  Timer2.enabled := True;
  Stop := false;
end;

procedure TForm1.Button76Click(Sender: TObject);
begin
   Timer2.enabled := False;
end;

procedure TForm1.Button77Click(Sender: TObject);
begin
  d := ConvertToInteger(Edit11.Text);
  Ser.SendString (pchar('R' + IntToStr(d)));
  Ser.SendByte (13);
end;

procedure TForm1.Button78Click(Sender: TObject);
begin
  d := ConvertToInteger(Edit12.Text);
  Ser.SendString (pchar('S' + IntToStr(d)));
  Ser.SendByte (13);
end;

procedure TForm1.Button79Click(Sender: TObject);
begin
  d := ConvertToInteger(Edit13.Text);
  Ser.SendString (pchar('T' + IntToStr(d)));
  Ser.SendByte (13);
end;

procedure TForm1.Button80Click(Sender: TObject);
begin
  d := ConvertToInteger(Edit14.Text);
  Ser.SendString (pchar('U' + IntToStr(d)));
  Ser.SendByte (13);
end;

procedure TForm1.Button81Click(Sender: TObject);
begin
   Ser.SendString (pchar('I'));
end;

procedure TForm1.Button82Click(Sender: TObject);
begin
    Ser.SendString (pchar('J'));
end;

procedure TForm1.Button83Click(Sender: TObject);    //Sinus
var
  n,d: Integer;
begin
  Timer2.Enabled := False;
  Ser.SendString (pchar('Q'));
  For n := 0 To 256 do begin
    d := round(127 + 127 * Sin(n * 2 * 3.1415 / 256));
    Ser.SendString (pchar(IntToStr(d)));
    Ser.SendByte (13);
    //
  end;
end;

procedure TForm1.Button84Click(Sender: TObject);   //Rechteck
var
  n,d: Integer;
begin
  Timer2.Enabled := False;
  Ser.SendString (pchar('Q'));
  For n := 0 To 256 do begin
    if n < 128 Then d := 0 Else d := 255;
    Ser.SendString (pchar(IntToStr(d)));
    Ser.SendByte (13);
  end;
end;

procedure TForm1.Button85Click(Sender: TObject);   //Dreieck
var
  n,d: Integer;
begin
  Timer2.Enabled := False;
  Ser.SendString (pchar('Q'));      //RAM füllen
  For n := 0 To 256 do begin
    d := round(127 + 127 * Sin(n * 2 * 3.1415 / 256));
    If n < 128 Then d := n * 2 Else d := 511 - n * 2;
    Ser.SendString (pchar(IntToStr(d)));
    Ser.SendByte (13);
  end;
end;

procedure TForm1.Button86Click(Sender: TObject);
begin
  d := ConvertToInteger(Edit15.Text);
  Ser.SendString (pchar('L' + IntToStr(d)));
  Ser.SendByte (13);
end;

procedure TForm1.Button87Click(Sender: TObject);
begin
  d := ConvertToInteger(Edit16.Text);
  Ser.SendString (pchar('K' + IntToStr(d)));
  Ser.SendByte (13);
end;

procedure TForm1.Button88Click(Sender: TObject);
begin
  d := ConvertToInteger(Edit17.Text);
  Ser.SendString (pchar('M' + IntToStr(d)));
  Ser.SendByte (13);
end;

procedure TForm1.Button89Click(Sender: TObject);
begin
  d := ConvertToInteger(Edit18.Text);
  Ser.SendString (pchar('N' + IntToStr(d)));
  Ser.SendByte (13);
end;

procedure TForm1.Button90Click(Sender: TObject);
begin
  d := ConvertToInteger(Edit19.Text);
  Ser.SendString (pchar('O' + IntToStr(d)));
  Ser.SendByte (13);
end;

procedure TForm1.Button91Click(Sender: TObject);
begin
  d := ConvertToInteger(Edit20.Text);
  Ser.SendString (pchar('P' + IntToStr(d)));
  Ser.SendByte (13);
end;

procedure TForm1.Button92Click(Sender: TObject); //RAM löschen
var
  n,d: Integer;
begin
  Timer2.Enabled := False;
  Ser.SendString (pchar('Q'));
  For n := 0 To 256 do begin
    d := Ram[n];
    Ser.SendString (pchar(IntToStr(d)));
    Ser.SendByte (13);
  end;
end;

procedure TForm1.ComboBox1Change(Sender: TObject);
begin
  COMnr :=  ComboBox2.text;
  Device := ComboBox1.text;
  Ser.Free;
  Ser := TBlockSerial.Create;
  Ser.Connect(COMnr);
  Ser.Config(1000000, 8, 'N', SB1, False, False);
  if not Ser.InstanceActive then Edit8.text := 'COM error' else begin
    Edit8.text := 'COM open';
    COMopen:= true;
    Ser.DTR := True;
  end;
  Devices();
end;

procedure TForm1.Devices();
begin
  device := ComboBox1.text;
  if device = 'Pico' then begin
     Scrollbar4.Max := 10;
     Scrollbar4.Position := 0;
     Label12.Caption := '1 kHz';
     Scrollbar3.Enabled := false;
     Label11.Caption := '3,3 V';

  end;
  if device = 'Nano' then begin
     Scrollbar4.Max := 4;
     Scrollbar4.Position := 2;
     Label12.Caption := '490 Hz';
     Scrollbar3.Enabled := true;
     Scrollbar3.Max := 2;
     Scrollbar3.Position := 2;
     Label11.Caption := 'VDD';
  end;
  if device = 'Tiny' then begin
     Scrollbar4.Max := 7;
     Scrollbar4.Position := 2;
     Label12.Caption := '1,2 kHz';
     Scrollbar3.Enabled := true;
     Scrollbar3.Max := 5;
     Scrollbar3.Position := 3;
     Label11.Caption := '2,5 V';
  end;
    if device = 'CH32' then begin
     Scrollbar4.Max := 10;
     Scrollbar4.Position := 10;
     Label12.Caption := '187,5 kHz';
     Scrollbar3.Enabled := false;
     Label11.Caption := 'VDD';
    end;
end;

procedure TForm1.ComboBox2Change(Sender: TObject);
begin
  COMnr :=  ComboBox2.text;
  Device := ComboBox1.text;
  Openstring := ComNr + '1000000,N,8,1';
  COMopen:= false;
  Ser.Free;
  Ser := TBlockSerial.Create;
  Ser.Connect(COMnr);
  Ser.Config(1000000, 8, 'N', SB1, False, False);
  if not Ser.InstanceActive then Edit8.text := 'COM error' else begin
    Edit8.text := 'COM open';
    COMopen:= true;
    Ser.DTR := True
  end;
  Devices();
end;

procedure TForm1.Edit10Change(Sender: TObject);
begin

end;

procedure TForm1.Edit11Change(Sender: TObject);
begin

end;


procedure TForm1.Edit9Change(Sender: TObject);
var
c: String;
begin
  c := Edit9.text;
  if copy(c, length(c),1)= chr(13) then Edit8.text := c;
end;

procedure TForm1.Edit9KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState
  );
var
  InputNumber: Integer;
begin
  if Key = VK_RETURN then
  begin
    try
      InputNumber := ConvertToInteger((Sender as TEdit).Text);
      Ser.SendString(Pchar(IntToStr(InputNumber)+ Chr(13)));
    except
      on E: EConvertError do;
    end;
  end;
end;





procedure TForm1.Button60Click(Sender: TObject);   //Save
var
  MyFile: TextFile;
  Zeile2: String;
  n : Integer;
begin
  SaveDialog1.Filter := '*.tls|*.tls|*.pbas|*.pbas|*.dat|*.dat';
  if (SaveDialog1.FilterIndex = 1) and (FileName > '') then  SaveDialog1.FileName := Filename;
  if (SaveDialog1.FilterIndex = 2) and (FileName > '') then  SaveDialog1.FileName := Filename;
  if (SaveDialog1.FilterIndex = 3) and (DatFileName > '') then  SaveDialog1.FileName := DatFilename;
  SaveDiaLog1.Execute;
  if SaveDialog1.FilterIndex <3 then begin
     FileName := SaveDialog1.FileName;
     if Filename.EndsWith('.dat') then FileName := '';
     if FileName > '' then begin
        AssignFile(MyFile,FileName);
        {$I-} Rewrite(MyFile); {$I+}
        r:=IOResult;
        if r = 0 then begin
           for n:=1 to ListBox1.Items.Count -2 do begin
            Zeile2 := ListBox1.Items[n];
            //if (copy(Zeile2,1,2))='  ' then Zeile2 :='      '+ Zeile2;
            writeln (MyFile,Zeile2);
           end;
        end;
        CloseFile(MyFile);
     end;
  end;
  if SaveDialog1.FilterIndex = 3 then begin
     DatFileName := SaveDialog1.FileName;
     if DatFilename.EndsWith('.pbas') then DatFileName := '';
     if DatFileName > '' then begin
        AssignFile(MyFile,DatFileName);
        {$I-} Rewrite(MyFile); {$I+}
        r:=IOResult;
        if r = 0 then begin
           for n:=0 to 255 do begin
             writeln (MyFile,Ram[n]);
           end;
        end;
        CloseFile(MyFile);
     end;
  end;
end;

procedure TForm1.Button59Click(Sender: TObject);    //Open
var
   n: Word;
begin
 // OpenDialog1.Filter :=  '(*,tls)|*.tls|(*.pbas)|*.pbas|(*.dat)|*.dat';
  OpenDialog1.Filter := '(*.tls)|*.tls|(*.pbas)|*.pbas|(*.dat)|*.dat';
  OpenDiaLog1.Execute;
  if OpenDialog1.FilterIndex = 1 then begin
      FileName := OpenDialog1.Filename;
      if Filename.EndsWith('.dat') then FileName := '';
      if FileName > '' then begin
        AssignFile(f,Filename);
         {$I-} Reset(f); {$I+}
        r:=IOResult;
        if r = 0 then begin
          ListBox1.Clear;
          ListBox1.Items.Insert(0, '        <<<');
          ListBox1.Items.Insert(1, '        >>>');
          ListBox1.ItemIndex := 1;
          Adresse := 0;
          LabelNr := 0;
          repeat
            Readln(f,Zeile);
            if length(Zeile) > 1 then begin
              SelectedIndex := ListBox1.ItemIndex;
              ListBox1.Items.Insert(SelectedIndex, Zeile);
            end
          until (EOF(f));
          CloseFile(f);
          LabelKorrektur();
       end;
     end;
  end;



  if OpenDialog1.FilterIndex = 2 then begin
    if Filename.EndsWith('.dat') then FileName := '';
    FileName := OpenDialog1.Filename;
    if FileName > '' then begin
      AssignFile(f,Filename);
       {$I-} Reset(f); {$I+}
      r:=IOResult;
      if r = 0 then begin
        ListBox1.Clear;
        ListBox1.Items.Insert(0, '        <<<');
        ListBox1.Items.Insert(1, '        >>>');
        ListBox1.ItemIndex := 1;
        Adresse := 0;
        LabelNr := 0;
        repeat
          Readln(f,Zeile);
          if length(Zeile) > 1 then begin
          //  Zeile := StringReplace(Zeile, 'Goto', 'Jmp', [rfReplaceAll, rfIgnoreCase]);
          //  Zeile := StringReplace(Zeile, 'Gosub', 'Call', [rfReplaceAll, rfIgnoreCase]);
          //  Zeile := StringReplace(Zeile, 'Return', 'Ret', [rfReplaceAll, rfIgnoreCase]);
            SelectedIndex := ListBox1.ItemIndex;
            ListBox1.Items.Insert(SelectedIndex, Zeile);
          end
        until (EOF(f));
        CloseFile(f);
        LabelKorrektur();

   //     FileName :=  StringReplace(FileName, 'pbas', 'tls', [rfReplaceAll, rfIgnoreCase]);
   //     AssignFile(f,FileName);
   //    {$I-} Rewrite(f); {$I+}
   //     r:=IOResult;
   //     if r = 0 then begin
   //        for n:=1 to ListBox1.Items.Count -2 do begin
   //         Zeile := ListBox1.Items[n];
   //         writeln (f,Zeile);
   //       end;
   //     end;
   //     CloseFile(f);

      end;
    end;
   end;

   if OpenDialog1.FilterIndex = 3 then begin
      DatFileName := OpenDialog1.Filename;
      if DatFilename.EndsWith('.pbas') then DatFileName := '';
      if DatFilename.EndsWith('.tls') then DatFileName := '';
      if DatFileName > '' then begin
        AssignFile(f,DatFileName);
        {$I-} Reset(f); {$I+}
        r:=IOResult;
        n :=0;
        if r = 0 then begin
          repeat
            Readln(f,Zeile);
            if n<256 then begin
              Ram[n] := ConvertToInteger(Zeile);
            end;
            n := n+1;
          until (EOF(f));
          CloseFile(f);
       end;
     end;
   end;
end;


procedure TForm1.Button1Click(Sender: TObject); //Befehl einsetzen
var
   Nr, EditNr, Zahl, n: Word;
   HexStr: String;
begin
 Nr := (Sender as TButton).Tag;
 if Nr = 16 then begin
   n := ConvertToInteger(Edit5.text);
   LabelNr := n + 1;
   Edit5.Text := intToStr (LabelNr);
   Edit6.Text := intToStr (LabelNr);
   Zeile := '              L' + Edit5.Text + ':';
   ZeileEinfuegen(Zeile);
   Adresse := Adresse - 1;
   Labl[LabelNr] := Adresse;
 end
 else begin
  if Nr = 57 then begin

      Zeile := Commands[Nr,0];
      Zeile := Zeile + Commands[Nr,1];
      Zeile := Zeile + Edit7.text;
      ZeileEinfuegen(Zeile);
      Adresse := Adresse - 1;
  end
  else begin
      Zeile := Commands[Nr,0];
      EditNr := StrToInt (Commands[Nr,2]);
      if Commands[Nr,2] = '0' then begin
        Zeile := Zeile + '00  ';
      end
      else begin
        if EditNr = 1 then Zahl :=  ConvertToInteger(Edit1.text);
        if EditNr = 2 then Zahl :=  ConvertToInteger(Edit2.text);
        if EditNr = 3 then Zahl :=  ConvertToInteger(Edit3.text);
        if EditNr = 4 then Zahl :=  ConvertToInteger(Edit4.text);
        if EditNr = 5 then Zahl :=  Labl[ConvertToInteger(Edit5.text)];
        if EditNr = 6 then Zahl :=  Labl[ConvertToInteger(Edit6.text)];
        HexStr := intToHex(Zahl);
        if EditNr in [1..6] then  HexStr := copy (HexStr,length(HexStr)-1,2);
        Zeile := Zeile +  HexStr+ '  ';
      end;
      Zeile := Zeile + Commands[Nr,1];
      if EditNr = 1 then Zeile := Zeile + Edit1.text;
      if EditNr = 2 then Zeile := Zeile + Edit2.text;
      if EditNr = 3 then Zeile := Zeile + Edit3.text;
      if EditNr = 4 then Zeile := Zeile + Edit4.text;
      if EditNr = 5 then Zeile := Zeile + Edit5.text + ':';
      if EditNr = 6 then Zeile := Zeile + Edit6.text + ':';
      if EditNr = 7 then Zeile := Zeile + Edit7.text;
      ZeileEinfuegen(Zeile);
  end;
 end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  MyFile: TextFile;
begin
  Ser := TBlockSerial.Create;
  AssignFile(MyFile,'TestLab.ini');
  {$I-} Reset(MyFile); {$I+}
  r:=IOResult;
  if r = 0 then begin
    Readln(MyFile,COMnr);
    Readln(MyFile,Device);
    CloseFile(MyFile);
  end;
  ComboBox2.text := COMnr;
  Combobox1.text := Device;
  ListBox1.Clear;
  ListBox1.Items.Insert(0, '        <<<');
  ListBox1.Items.Insert(1, '        >>>');
  ListBox1.ItemIndex := 1;
  Typ_alt := 1;
  For n := 240 To 255 do Labl[n] := n;
  Adresse := 0;
  LabelNr := 0;
  Device := ComboBox1.text;
  if not Ser.InstanceActive then
  begin
    Ser.Connect(COMnr);
    Ser.Config(1000000, 8, 'N', 0, False, False);
  end;
   if not Ser.InstanceActive then Edit8.text := 'COM error'
  else begin
    Edit8.text := 'COM open';
    COMopen:= true;
    Ser.DTR := True
  end;
  Devices();
end;

procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
var
  MyFile: TextFile;
  i: Integer;
begin
  MenuItem1Click(nil);
  Edit21.Text := '0';
  Sleep(100);
  Timer1.enabled := false;
  Timer2.enabled := false;
  Timer3.enabled := false;
  Stop := true;
  Sleep(10);
  ComOpen := False;
  COMnr := ComboBox2.text;
  Device := Combobox1.text;
  AssignFile(MyFile,'TestLab.ini');
  {$I-} Rewrite(MyFile); {$I+}
  writeln (MyFile,COMnr);
  writeln (MyFile,Device);
  CloseFile(MyFile);
  Sleep(500);
  Panel1.Visible := false;
//  if Assigned(Ser) then
//  begin
//    Ser.Purge;
//    Ser.Free;
//    Ser := nil;
//  end;
  //for n:=1 to 255 do begin
  //Ser.SendString ('H');
  //end;
end;

procedure TForm1.Image4Click(Sender: TObject);
begin

end;



procedure TForm1.MenuItem1Click(Sender: TObject);   //PicoBasic
begin
  Timer2.Enabled:=false;
  stop := true;
  sleep(100);
  Ser.Purge;
  Panel1.Visible := false;
  Timer1.Enabled:=true;
  stop := true;
  RunStart := 1;
end;

procedure TForm1.MenuItem2Click(Sender: TObject);
begin
  MenuItem1Click(nil);
  stop := false;
  Timer1.Enabled := false;
  Image1.visible := false;
  Image2.visible := false;
  Image3.visible := false;
  Image4.visible := false;
  Panel1.Visible := true;
 // Ser.Purge;
  Raster;
  Devices;
  if ComOpen then Timer2.Enabled := true;
 // If Device = 'Pico' then Ser.DTR := True Else Ser.DTR := False;
 // Ser.DTR := True;
end;

procedure TForm1.MenuItem3Click(Sender: TObject);
begin
   MenuItem1Click(nil);
   MenuItem2Click(nil);
   device := ComboBox1.text;
  if device = 'Pico' then Image1.visible := true;
  if device = 'Nano' then Image2.visible := true;
  if device = 'Tiny' then Image3.visible := true;
  if device = 'CH32' then Image4.visible := true;

end;

end.

