unit UNiiefa;

interface

uses

	Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
	StdCtrls, Buttons, RXSpin, ExtCtrls, rxPlacemnt, OoMisc, AdStatLt, Mask, OleCtrls,IniFiles,Registry,
	chartfx3, TeEngine, Series, TeeProcs, Chart, Menus,  ToolsRS,   ToolsCan,
	AdPort,  RxHook, RXCtrls, ToolWin, ComCtrls,
	RXSwitch, rxToolEdit, Grids, ValEdit, DBGrids;

type

 	TGridCracker = class(TStringGrid);


	TMessag = record
		Mask: Byte;
		Addr: Word;
		Leng: integer;
		Data: array[0..3] of SmallInt;
		Surs: integer;
	end;

	TUnit = record
		Data: integer;
		Age: integer;
		Surs: integer;
	end;

	TModbusForm = class(TForm)
		Memo1: TMemo;
		FormStorage2: TFormStorage;
		myTimer: TTimer;
		GroupBox: TGroupBox;
		GroupBox2: TGroupBox;
		DiggAddrEdit: TRxSpinEdit;
		SetButton: TButton;
		GroupBox1: TGroupBox;
		DecLab: TRadioButton;
		HexLab: TRadioButton;
    AdreLaba: TLabel;
    dataLaba: TLabel;
		GroupBox3: TGroupBox;
    AnaStartLaba: TLabel;
		AnaStart: TRxSpinEdit;
    DigiStartLaba: TLabel;
		DigiStart: TRxSpinEdit;
    AnaLenLaba: TLabel;
		AnaLen: TRxSpinEdit;
    DigiLenLaba: TLabel;
		DigiLen: TRxSpinEdit;
    FadeBox: TCheckBox;
		Label9: TLabel;
    FadeSpin: TRxSpinEdit;
		AnaStart24: TButton;
		AnaStart64: TButton;
		AnaLen64: TButton;
		DigiStart0: TButton;
		DigiLen32: TButton;
		DigiLen24: TButton;
    ColorBox: TCheckBox;
    DataGrid: TStringGrid;
    DataLenEdit: TRxSpinEdit;
		Label1: TLabel;
    BitGroup: TPanel;
    Panel1: TPanel;
    RadioUp: TRadioButton;
    RadioDn: TRadioButton;
    AutoBox: TCheckBox;
    AutoTimeEdit: TRxSpinEdit;


		procedure FormClose(Sender: TObject; var Action: TCloseAction);
		procedure Memo1DblClick(Sender: TObject);
		procedure Memo1Change(Sender: TObject);
//		procedure btnAnalogClick(Sender: TObject);
		procedure ColorBoxClick(Sender: TObject);
		procedure FadeBoxClick(Sender: TObject);
		procedure FormCreate(Sender: TObject);
		procedure myTimerTimer(Sender: TObject);
		procedure FormShow(Sender: TObject);
		procedure ReadAnalog;
		procedure AnaLenChange(Sender: TObject);
		procedure DigiLenChange(Sender: TObject);
		procedure FadeSpinChange(Sender: TObject);
		procedure SetButtonClick(Sender: TObject);
		procedure SetButtonDo(Sender: TObject);
		procedure CommButtClick(Sender: TObject);
		procedure CommButtDo(Sender: TObject);
		procedure DigiClick(Sender: TObject);
		procedure AnaStartChange(Sender: TObject);
		procedure AnaValue(Sender: TObject);
		procedure DigValue(Sender: TObject);
		procedure DigiStartChange(Sender: TObject);
		procedure DigiLabWrite;
		procedure AnaLabWrite;
		procedure DecLabClick(Sender: TObject);
		procedure HexLabClick(Sender: TObject);
		procedure AnaStart24Click(Sender: TObject);
		procedure AnaStart64Click(Sender: TObject);
		procedure AnaLen64Click(Sender: TObject);
		procedure DigiStart0Click(Sender: TObject);
		procedure DigiLen24Click(Sender: TObject);
		procedure DigiLen32Click(Sender: TObject);

		procedure BitButClick(Sender: TObject);

		procedure HexaDec;

		procedure AnaRewrite;
		procedure DigiRewrite;
		procedure DigiColWrite(Byte: word; Column: integer; Age: integer; Surs: integer);

		procedure DigiBoxWrite(Surs: integer);

		procedure DoNothing(Sender: TObject);
		procedure HagaNada(Sender: TObject; ACol, ARow: Integer; var CanSelect: Boolean);

		procedure RenameButton(Sender: TObject; MousePos: TPoint;
	var Handled: Boolean);

		procedure Renamed(Sender: TObject);
		procedure Renamido(Sender: TObject; var Key: Char);
		procedure SaveProjectComms(ProjID: string);

		procedure DataLenEditChange(Sender: TObject);
		procedure DataGridKeyPress(Sender: TObject; var Key: Char);
		procedure DataGridSetEditText(Sender: TObject; ACol, ARow: Integer;
			const Value: String);
		procedure DataGridDrawCell(Sender: TObject; ACol, ARow: Integer;
			Rect: TRect; State: TGridDrawState);
		procedure DataGridSelectCell(Sender: TObject; ACol, ARow: Integer;
			var CanSelect: Boolean);
		procedure DataGridGetEditText(Sender: TObject; ACol, ARow: Integer;
			var Value: String);
		procedure AutoTimeEditChange(Sender: TObject);

	private
		{ Private declarations }

		Unites : Array[0..127] of TUnit;
		Anapan : Array[0..63] of TPanel;
		Digipan : Array[0..511] of Tpanel;
		Digibox : Array[0..15] of TCheckBox;
		Digibut : Array[0..16] of TButton;

		Bitbut : Array[0..3] of TRadioButton;

		DigiLab: Array[0..31] of TLabel;
		AnaLab: Array[0..7] of TLabel;

		kownt: integer;
		waiste: integer;
		fade: cardinal;
		auto: cardinal;
		reColor: integer;
		doReColor: boolean;

		AnalogStart   : Integer;
		AnalogLength  : Integer;
		DigitalStart  : Integer;
		DigitalLength : Integer;

	rData2, rData3  : double;
	FIniFile        : TRegIniFile;
	FRegFile        : TIniFile;
	Temper1,Temper2          : Array [0..12] of Real;

{	InsideFUst      : boolean = False;
	InsideSet       : boolean = False;
	InsideComm      : boolean = False;
}
	LastSender      : TObject;

	KT1,KT2,KT3     : Array [0..12] of Real;

	UNew            : SmallInt;
	MomentNew       : SmallInt;

	UNewZ           : Integer;

	NameEdit: TEdit;

	ArrNiiefaAnalog       : Array [0..100] of Word;
	ArrNiiefaDigital       : Array [0..100] of Word;

	AutoMoment: cardinal;
	RecolorMoment: cardinal;

	Wordt:  word;

//	ProjectQua : integer = 0;
//	ProjectNum : integer = 0;

	clBlueGradient : array[0..20,0..1] of TColor;
	clRedGradient : array[0..20] of TColor;
	clGreenGradient : array[0..20,0..1] of TColor;

	EmptyCell:TGridRect;

	public

		Numer: integer;
		RSadr: cardinal;
		RXadr: longword;
		TXadr: longword;
		Protokol: integer;

	procedure ReceiveCanData(Mess: TMessag; dev:integer);

	 { Public declarations }
	end;

var

	ModbusForm         : TModbusForm;


const

	clGrad : integer = 20;	//	correct above

	AnalogMaxLength: Integer = 64;
	DigitalMaxLength: Integer = 512;
	MaxAdr: Integer = 127;

	clPink : TColor = $AAAAFF;

	implementation

uses CAN_Terminal;

{$R *.DFM}

procedure TModbusForm.FormClose(Sender: TObject; var Action: TCloseAction);

begin
//   FlagApplication:=True;
	 myTimer.Enabled:=False;

//   CANTerminal.Zakaz.UKSS[Numer].Go.OnClick := CANTerminal.ShoWinClick;

//   (Sender as Tform).Destroy;
//   Oprosc.Checked:=False;
end;

procedure TModbusForm.Memo1DblClick(Sender: TObject);
begin
	 Memo1.Clear;
end;

procedure TModbusForm.Memo1Change(Sender: TObject);
var
	 i : Integer;
begin
	 i:=Memo1.Lines.Count;
	 if i>100 then Memo1.Clear;
end;
{
procedure TModbusForm.btnAnalogClick(Sender: TObject);

begin

		if InsideSet then SetButtonDo(Sender);
		if InsideComm then CommButtDo(LastSender);

		if not InsideFUst then
		begin
			InsideFUst := True;
			try
				ReadAnalog;
			finally
			InsideFUst := False;
			end;
		end;
end;
}
procedure TModbusForm.ColorBoxClick(Sender: TObject);
begin
	if ColorBox.Checked then
	begin
		if not FadeBox.Checked
		then	FadeSpin.Value := 10
	end else FadeSpin.Value := 0;
end;

procedure TModbusForm.FadeBoxClick(Sender: TObject);
begin
	if FadeBox.Checked then
	begin
		ColorBox.Checked := true;
		if (FadeSpin.Value = 10) or (FadeSpin.Value = 0) then FadeSpin.Value := 5
		end	else if ColorBox.Checked then	FadeSpin.Value := 10;
end;

procedure TModbusForm.FormCreate(Sender: TObject);
var i: integer;
		inifile : TIniFile;
		nom,num: string;

begin
	myTimer.Enabled:=True;
	FormStorage2.IniFileName:=PathExe+'Terminal.ini';

	for i:= 0 to clGrad do
	begin

		clRedGradient[clGrad-i] :=
			$0000FF -
			((6300 div clGrad)*i) div 100+
			((((1920 div clGrad)*i) div 10) shl 8) +
			((((1920 div clGrad)*i) div 10) shl 16);

		clGreenGradient[clGrad-i,0] :=
			160 + ((255-160) div clGrad) * i +
			$00FF00 +
			((140 + ((255-140) div clGrad)*i) shl 16);

		clBlueGradient[clGrad-i,0] :=
			180 + ((255-180) div clGrad) * i +
			$00FF00 +
			((160 + ((255-160) div clGrad)*i) shl 16);

		clGreenGradient[clGrad-i,1] :=
			150 + ((255-150) div clGrad) * i +
			((210 + ((255-210) div clGrad)*i) shl 8) +
			$FF0000;

		clBlueGradient[clGrad-i,1] :=
			160 + ((255-160) div clGrad) * i +
			((220 + ((255-220) div clGrad)*i) shl 8) +
			$FF0000;

	end;

	for i:= 0 to 127 do Unites[i].Age :=0;

		for i:= 0 to 31 do
		begin
			DigiLab[i]:=TLabel.Create(self);
			DigiLab[i].ParentFont:=false;
			DigiLab[i].Parent:=GroupBox;
			DigiLab[i].Top:=15;
			DigiLab[i].Left:=10+ i*16 + (i div 4)*3;
			DigiLab[i].Font.Color :=clNavy;
		end;
		DigiLabWrite;

		for i:= 0 to 511 do
		begin
			DigiPan[i]:=TPanel.Create(self);
			DigiPan[i].ParentFont:=false;
			DigiPan[i].Parent:=GroupBox;
			DigiPan[i].Top:=30+(i mod 16)*16 + ((i mod 16)div 8)*3;
			DigiPan[i].Left:=10+(i div 16)*16 + ((i div 16)div 4)*3;
			DigiPan[i].Width:=13;
			DigiPan[i].Height:=13;
			DigiPan[i].OnClick := DigValue;
			DigiPan[i].Tag:=i;
		end;

		for i:= 0 to 7 do
		begin
			AnaLab[i]:=TLabel.Create(self);
			AnaLab[i].ParentFont:=false;
			AnaLab[i].Parent:=GroupBox;
			AnaLab[i].Top:=290;
			AnaLab[i].Left:=10+i *67;
			AnaLab[i].Font.Color :=clNavy;
			AnaLab[i].Alignment := taCenter;
			AnaLab[i].width := 61;
		end;
		AnaLabWrite;

		for i:= 0 to 63 do
		begin
			AnaPan[i]:=TPanel.Create(self);
				AnaPan[i].ParentFont:=false;
				AnaPan[i].Parent:=GroupBox;
				AnaPan[i].Top:=305+(i mod 8)*32;
				AnaPan[i].Left:=10+(i div 8)*67      ;
				AnaPan[i].Width:=61;
				AnaPan[i].Height:=25;
				AnaPan[i].Font.Size:=12;
				AnaPan[i].ShowHint:=true;
				AnaPan[i].Tag :=i;
				AnaPan[i].OnClick := AnaValue;
		end;

		for i:= 0 to 15 do
		begin
			DigiBox[i]:=TCheckBox.Create(self);
			DigiBox[i].Parent:=GroupBox2;
			DigiBox[i].Top:=20+(i mod 4)*20;
			DigiBox[i].Left:=20+(i div 4)*55;
			DigiBox[i].Width:=60;
			DigiBox[i].Height:=20;
			DigiBox[i].ShowHint:=true;
			DigiBox[i].OnClick := DigiClick;
			DigiBox[i].Hint := Project.DigiButNames[i];
		end;

		for i:= 0 to 15 do
		begin
			DigiBut[i]:=TButton.Create(self);
			DigiBut[i].Parent:=GroupBox1;
			DigiBut[i].Top:={20+}20+(i mod 4)*25;
			DigiBut[i].Left:=20+(i div 4)*55;
			DigiBut[i].Width:=50;
			DigiBut[i].Height:=20;
			DigiBut[i].ShowHint:=true;
			DigiBut[i].OnClick := CommButtClick;
			DigiBut[i].Tag := i;
			DigiBut[i].OnContextPopup := RenameButton;
			DigiBut[i].Caption:= Project.DigiButNames[i];

		end;

		DigiBut[16]:=TButton.Create(self);
		DigiBut[16].Parent:=GroupBox1;
		DigiBut[16].Top:={20 + }20 + 4*25;
		DigiBut[16].Left:=20 + 55;
		DigiBut[16].Width:=105;
		DigiBut[16].Height:=20;
		DigiBut[16].ShowHint:=true;
		DigiBut[16].OnClick := CommButtClick;
		DigiBut[16].Tag := 16;
		DigiBut[16].OnContextPopup := RenameButton;
		DigiBut[16].Caption:= Project.DigiButNames[16];

		DigiLabWrite;
		AnaLabWrite;
		HexaDec;

		NameEdit:=TEdit.Create(self);

	for i:= 0 to 3 do
	begin
		DataGrid.Cells[0,i]:='0';
		Bitbut[i]:=TRadioButton.Create(self);
		Bitbut[i].parent:=BitGroup;
		BitBut[i].BringToFront;
		Bitbut[i].Caption:='';
		Bitbut[i].top:=  2+17*i;
		Bitbut[i].left:= 0;
		Bitbut[i].Width := 17;
		Bitbut[i].Height := 17;
		Bitbut[i].TabOrder:=i;
		Bitbut[i].Tag:=i;
		Bitbut[i].OnClick:=BitButClick;
	end;

{	inifile := TIniFile.Create(PathExe+'Terminal.ini');
	ProjectQua := strtoint(Inifile.ReadString('Projects','ProjectQua','0'));
	ProjectNum := strtoint(Inifile.ReadString('Projects','ProjectNum','0'));
	inifile.Free;
}
	FadeSpinChange(Sender);
end;

procedure TModbusForm.myTimerTimer(Sender: TObject);
var	i : integer;
begin

	if(GetTickCount - RecolorMoment)>(Fade * 1000 / (clGrad-1))
	then begin doReColor := true; RecolorMoment:= GetTickCount end;

	if doReColor then
	for i:= 0 to 127 do
	if Unites[i].Age > 0	then
	begin

		dec(Unites[i].Age);
		if Fade = 0 then Unites[i].Age := 0;
		if Fade = 10 then Unites[i].Age := reColor;
		if Unites[i].Age <0 then Unites[i].Age:=0; // бывает

		if (i>= AnalogStart)
		and(i<  AnalogStart + AnalogLength)
		then Anapan[i-AnalogStart].Color := clBlueGradient[Unites[i].Age][Unites[i].Surs];

		if (i>= DigitalStart)
		and(i<  DigitalStart + DigitalLength)
		then	DigiColWrite(Unites[i].Data,i-DigitalStart,Unites[i].Age,Unites[i].Surs);

	end;

	doReColor:=false;

	if(AutoBox.Checked)  then
	if(GetTickCount - AutoMoment)>(myTimer.Interval*Auto)
	then begin
		SetButtonDo(Sender);
		AutoMoment:= GetTickCount;
	end;

end;


procedure TModbusForm.FormShow(Sender: TObject);
var
		i: integer;

begin

	if Protokol=3 then DataLenEdit.MaxValue:=4
	else DataLenEdit.MaxValue :=3;

	myTimer.Enabled:=True;

	AutoMoment:= GetTickCount;
	RecolorMoment:= GetTickCount;

	AnalogStart := trunc(AnaStart.Value);
	DigitalStart:= trunc(DigiStart.Value);
	AnalogLength:= trunc(AnaLen.Value);
	DigitalLength:=trunc(DigiLen.Value);

	for i:=0 to 15 do
		DigiBox[i].Caption:= 'Bit '+inttostr(i);

	AnaLenChange(Sender);
	DigiLenChange(Sender);
	AnaStartChange(Sender);
	DigiStartChange(Sender);
	FadeSpinChange(Sender);
	AutoTimeEditChange(Sender);
	DataLenEditChange(Sender);

	BitBut[0].Checked:=true;
	TGridCracker(DataGrid).SetFocus;

end;

procedure TModbusForm.ReadAnalog;
Var
		i,Bout : Word;
		what:integer;
		Data :  SmallInt;

begin

	Memo1.Lines.Add('Read analog...');

	BufOut[0] := RSadr;
	BufOut[1]:=3;
	BufOut[2]:=HB(AnalogStart);
	BufOut[3]:=LB(AnalogStart);
	BufOut[4]:=HB(AnalogLength);
	BufOut[5]:=LB(AnalogLength);
	Bout := ContrlolSumCRC16(BufOut,6);
	BufOut[6]:=LB(Bout);
	BufOut[7]:=HB(Bout);

	what := RunCmdNew(0,8,AnalogLength*2+5);

	If not((what=0)or(what=2)) then
	begin
		Memo1.Lines.Add('!!! Error !!!');
		exit;
	end;


	If what=0 then
	begin
		for i:=0 to AnalogLength-1 do
		begin
			Data:=Round(BufIn[i*2+1+3] + BufIn[i*2+3]*256);
			Unites[AnalogStart+i].Data := Data;
			Unites[AnalogStart+i].Age := reColor;
		end;
		AnaRewrite;
	end;
end;

procedure TModbusForm.AnaLabWrite;
var i: integer;
begin
	if(Anastart.Value+AnaLen.Value > 128)  then
	AnaLen.Value := 128-Anastart.Value;

		for i:= 0 to 7 do
		if (i*8+trunc(AnaStart.value))<128 then
		begin

			if HexLab.Checked then
				 AnaLab[i].Caption:='0x'+inttohex(i*8+trunc(AnaStart.value),2);
			if DecLab.Checked then
				 AnaLab[i].Caption := inttostr(i*8+trunc(AnaStart.value));

		end
		else AnaLab[i].Caption:='';

end;

procedure TModbusForm.AnaStartChange(Sender: TObject);
var i: integer;
begin
	if(Anastart.Value+AnaLen.Value > 128)	then
		AnaLen.Value := 128-Anastart.Value;
	AnalogStart := trunc(Anastart.Value);
	AnaLabWrite;
	AnaRewrite;
end;

procedure TModbusForm.AnaLenChange(Sender: TObject);
var i: integer;
begin
	if(Anastart.Value+AnaLen.Value > 128)	then
	Anastart.Value := 128-AnaLen.Value;
	AnalogLength:=trunc(AnaLen.Value);
	AnaRewrite;
end;

procedure TModbusForm.DigiLabWrite;
var i: integer;
begin
		for i:= 0 to 31 do
    begin
    if(DecLab.Checked)
    then DigiLab[i].Caption:=inttostr(i+trunc(DigiStart.value));
    if(HexLab.Checked)
    then DigiLab[i].Caption:=inttohex(i+trunc(DigiStart.value),2);
    if(i+trunc(DigiStart.value)>127) then  DigiLab[i].Caption:='';
		end;
end;


procedure TModbusForm.DigiStartChange(Sender: TObject);
var i: integer;
begin
	if(Digistart.Value+DigiLen.Value > 128)	then
		DigiLen.Value := 128-Digistart.Value;
	DigitalStart := trunc(Digistart.Value);
	DigiLabWrite;
	DigiRewrite;
end;

procedure TModbusForm.DigiLenChange(Sender: TObject);
var i: integer;
begin
	if(Digistart.Value+DigiLen.Value > 128)	then
		Digistart.Value := 128-DigiLen.Value;
	DigitalLength:=trunc(DigiLen.Value);
	DigiRewrite;
end;


procedure TModbusForm.SaveProjectComms(ProjID: string);
var i: integer;
		inifile : TIniFile;
		nom: string;
begin
	inifile := TIniFile.Create(PathExe+'Terminal.ini');

	for i:=0 to 16 do
	begin
		nom := 'DigiBut_'+inttostr(i);
		inifile.WriteString(ProjID,nom,DigiBut[i].Caption);
	end;

	inifile.Free;

end;


procedure TModbusForm.FadeSpinChange(Sender: TObject);
begin
	Fade:=trunc(FadeSpin.Value);
	if Fade = 0	then
	begin
		reColor := 0;
		FadeBox.Checked :=false;
		ColorBox.Checked := false;
	end	else
	begin
		reColor := clGrad;
		if Fade = 10	then FadeBox.Checked := false
		else FadeBox.Checked := true;
	end;
	doReColor:=true;
end;

procedure TModbusForm.SetButtonDo(Sender: TObject);
var Bout,what: word;
	 CanStr : String;
	 Mess: Tmessag;
	 i: integer;
	 XXadr: cardinal;
begin

	Memo1.Lines.Add('Setting settings...');

	mess.Leng := trunc(DataLenEdit.Value);

	mess.Mask := 0;

	if mess.Leng = 0 then mess.Mask := 0;
	if mess.Leng = 1 then mess.Mask := 4;
	if mess.Leng = 2 then mess.Mask := 6;
	if mess.Leng = 3 then mess.Mask := 7;
	if mess.Leng = 4 then mess.Mask := $FF;

	mess.Addr := round(DiggAddrEdit.Value);

	for i:=0 to 3 do mess.Data[i] := 	strtoint(DataGrid.Cells[0,i]);

	if RadioUp.Checked
	then begin XXadr:= TXadr; mess.Surs := 0 end
	else begin XXadr:= RXadr; mess.Surs := 1 end;

	if Protokol=3 then
	begin
		ArrCanMessageSend[0].m_dwID := XXadr + mess.Addr;
		ArrCanMessageSend[0].m_bDLC :=  mess.Leng*2;
		ArrCanMessageSend[0].m_bData[1] := HB(mess.Data[0]);
		ArrCanMessageSend[0].m_bData[2] := LB(mess.Data[0]);
		ArrCanMessageSend[0].m_bData[3] := HB(mess.Data[1]);
		ArrCanMessageSend[0].m_bData[4] := LB(mess.Data[1]);
		ArrCanMessageSend[0].m_bData[5] := HB(mess.Data[2]);
		ArrCanMessageSend[0].m_bData[6] := LB(mess.Data[2]);
		ArrCanMessageSend[0].m_bData[7] := HB(mess.Data[3]);
		ArrCanMessageSend[0].m_bData[8] := LB(mess.Data[3]);
	end else begin
		ArrCanMessageSend[0].m_dwID := XXadr;
		ArrCanMessageSend[0].m_bDLC := 8;
		ArrCanMessageSend[0].m_bData[5] := mess.Mask shl 5;
		ArrCanMessageSend[0].m_bData[6] := LB(mess.Addr);
		ArrCanMessageSend[0].m_bData[8] := LB(mess.Data[0]);
		ArrCanMessageSend[0].m_bData[7] := HB(mess.Data[0]);
		ArrCanMessageSend[0].m_bData[2] := LB(mess.Data[1]);
		ArrCanMessageSend[0].m_bData[1] := HB(mess.Data[1]);
		ArrCanMessageSend[0].m_bData[4] := LB(mess.Data[2]);
		ArrCanMessageSend[0].m_bData[3] := HB(mess.Data[2]);
	end;


	WriteMessageCanID(1, CanStr);


	ReceiveCanData(mess,Numer);

end;

procedure TModbusForm.SetButtonClick(Sender: TObject);
var Bout,what: word;
begin
	SetButtonDo(Sender);
end;


procedure TModbusForm.CommButtDo(Sender: TObject);
var Bout,what: word;
	 Mess: Tmessag;
	 CanStr : String;

begin
		Memo1.Lines.Add('Command commands...');

	what := (Sender as TButton).Tag;
	if what <16
	then what := 1 shl what
	else what := 0;

	mess.Mask := 4;
	mess.Addr := 127;
	mess.Data[0] := what;
	mess.Data[1] := 0;
	mess.Data[2] := 0;
	mess.Surs := 1;

	if Protokol=3 then
	begin
		ArrCanMessageSend[0].m_dwID := RXadr + mess.Addr;
		ArrCanMessageSend[0].m_bDLC :=  2;
		ArrCanMessageSend[0].m_bData[1] := HB(mess.Data[0]);
		ArrCanMessageSend[0].m_bData[2] := LB(mess.Data[0]);
	end else begin
		ArrCanMessageSend[0].m_dwID := RXadr;
		ArrCanMessageSend[0].m_bDLC := 8;
		ArrCanMessageSend[0].m_bData[5] := mess.Mask shl 5;
		ArrCanMessageSend[0].m_bData[6] := LB(mess.Addr);
		ArrCanMessageSend[0].m_bData[8] := LB(mess.Data[0]);
		ArrCanMessageSend[0].m_bData[7] := HB(mess.Data[0]);
		ArrCanMessageSend[0].m_bData[2] := LB(mess.Data[1]);
		ArrCanMessageSend[0].m_bData[1] := HB(mess.Data[1]);
		ArrCanMessageSend[0].m_bData[4] := LB(mess.Data[2]);
		ArrCanMessageSend[0].m_bData[3] := HB(mess.Data[2]);
	end;

	WriteMessageCanID(1, CanStr);


	ReceiveCanData(mess,Numer);

end;


procedure TModbusForm.CommButtClick(Sender: TObject);
var Bout,what: word;
begin

	CommButtDo(Sender);
//	if not oprosc.Checked then CommButtDo(Sender)
//  else
//  begin InsideComm := true;
//        LastSender := Sender;
//  end;

end;


procedure TModbusForm.DigiClick(Sender: TObject);
var i,bout: word;
begin
	 bout := 0;
	 for i:=0 to 15 do
	 if digiBox[i].Checked then bout := bout or (1 shl (i));
	 DataGrid.Cells[0, BitGroup.Tag ] := inttostr(bout);

end;

procedure TModbusForm.HexaDec;
var data : array[1..5] of extended;
begin

	data[1]:=DiggAddrEdit.Value;
	data[2]:=AnaStart.Value;
	data[3]:=AnaLen.Value;
	data[4]:=DigiStart.Value;
	data[5]:=DigiLen.Value;

	if	DecLab.Checked then
	begin
		DiggAddrEdit.ValueType:=vtInteger;
		AnaStart.ValueType:=vtInteger;
		AnaLen.ValueType:=vtInteger;
		DigiStart.ValueType:=vtInteger;
		DigiLen.ValueType:=vtInteger;
		AdreLaba.Caption:='Adres.DEC';
		DataLaba.Caption:='Data.DEC';

		AnaStartLaba.Caption:='Начало анал. DEC';
		AnaLenLaba.Caption:='Длина анал. DEC';
		DigiStartLaba.Caption:='Начало дискр. DEC';
		DigiLenLaba.Caption:='Длина дискр. DEC';

		AnaStart24.Caption:='24';
		AnaStart64.Caption:='64';
		AnaLen64.Caption	:='64';
		DigiLen24.Caption	:='24';
		DigiLen32.Caption	:='32';
	end;

	if	HexLab.Checked then
	begin
		DiggAddrEdit.ValueType:=vtHex;
		AnaStart.ValueType:=vtHex;
		AnaLen.ValueType:=vtHex;
		DigiStart.ValueType:=vtHex;
		DigiLen.ValueType:=vtHex;
		AdreLaba.Caption:='Adres.HEX';
		DataLaba.Caption:='Data.DEC';

		AnaStartLaba.Caption:='Начало анал. HEX';
		AnaLenLaba.Caption:='Длина анал. HEX';
		DigiStartLaba.Caption:='Начало дискр. HEX';
		DigiLenLaba.Caption:='Длина дискр. HEX';

		AnaStart24.Caption:='18';
		AnaStart64.Caption:='40';
		AnaLen64.Caption	:='40';
		DigiLen24.Caption	:='18';
		DigiLen32.Caption	:='20';
	end;

	DiggAddrEdit.Value	:=data[1];
	AnaStart.Value			:=data[2];
	AnaLen.Value				:=data[3];
	DigiStart.Value			:=data[4];
	DigiLen.Value				:=data[5];

end;

procedure TModbusForm.DecLabClick(Sender: TObject);
begin
	DigiLabWrite;
	AnaLabWrite;
	HexaDec;
end;

procedure TModbusForm.HexLabClick(Sender: TObject);
begin
	DigiLabWrite;
	AnaLabWrite;
	HexaDec;
end;

procedure TModbusForm.AnaValue(Sender: TObject);
var i, donde, cuanto : integer;
begin
	donde := (Sender as TPanel).Tag;
	donde := donde + AnalogStart;
	DiggAddrEdit.Value :=  donde;

	for i:=0 to 3 do
	begin
		cuanto := Unites[donde+i].Data;
		DataGrid.Cells[0,i]:=inttostr(cuanto);
		if i = BitGroup.Tag then DigiBoxWrite(cuanto);
	end;
end;

procedure TModbusForm.DigValue(Sender: TObject);
var i, tab, one : integer;
wordai: word;
begin
	tab := (Sender as TPanel).Tag;
	tab := tab div 16;
	one := 1;

	DiggAddrEdit.Value := Digistart.value + tab;

	for i:=3 downto 0 do
	begin
		wordai := Unites[DigitalStart + tab+i].Data;
		DataGrid.Cells[0,i]:=inttostr(wordai);
		if i = BitGroup.Tag then DigiBoxWrite(wordai);
	end;
end;

procedure TModbusForm.AnaStart24Click(Sender: TObject);
begin
	AnaStart.Value:=24;
end;

procedure TModbusForm.AnaStart64Click(Sender: TObject);
begin
	AnaStart.Value:=64;
end;

procedure TModbusForm.AnaLen64Click(Sender: TObject);
begin
	AnaLen.Value:=64;
end;

procedure TModbusForm.DigiStart0Click(Sender: TObject);
begin
	DigiStart.Value:=0;
end;

procedure TModbusForm.DigiLen24Click(Sender: TObject);
begin
	DigiLen.Value:=24;
end;

procedure TModbusForm.DigiLen32Click(Sender: TObject);
begin
	DigiLen.Value:=32;
end;

procedure TModbusForm.Renamed(Sender: TObject);
begin
	NameEdit.Hide;
end;

procedure TModbusForm.Renamido(Sender: TObject; var Key: Char);
var num: integer;
begin
	if(Key = chr($D)) then //  Enter
	begin
		num := (Sender as TEdit).Tag;
		DigiBut[num].Caption:=NameEdit.Text;
		DigiBut[num].SetFocus;
		Project.DigiButNames[num]:= NameEdit.Text;
		Project.DigiButNameChange := true;
	end;

	if(Key = chr($1B)) then //  ESC
	begin
		DigiBut[(Sender as TEdit).Tag].SetFocus;
	end;
end;

procedure TModbusForm.RenameButton(Sender: TObject; MousePos: TPoint;
	var Handled: Boolean);
var i: integer;
begin
	NameEdit.show;
	NameEdit.Parent:=GroupBox1;
	NameEdit.BorderStyle:= bsNone;
	NameEdit.Text:= (Sender as TButton).Caption;
	NameEdit.Top:= (Sender as TButton).Top+3;
	NameEdit.Left:=(Sender as TButton).Left+4;
	NameEdit.Width:=(Sender as TButton).Width-6;
	NameEdit.Height:=(Sender as TButton).Height-6;
	NameEdit.Tag := (Sender as TButton).Tag;
	NameEdit.OnExit := Renamed;
	NameEdit.OnKeyPress := Renamido;
	NameEdit.setfocus;
end;

procedure TModbusForm.ReceiveCanData(Mess: TMessag; dev:integer);
var
	Ananum, Diginum, Boxnum: integer;
	i, j, byte: integer;
begin
	kownt:=kownt+1;
	Memo1.Lines[0] := inttohex (mess.addr,2)+' '+
	inttohex (word(mess.data[0]),4)+' '+
	inttohex (word(mess.data[1]),4)+' '+
	inttohex (word(mess.data[2]),4)+' - '+inttostr(kownt);

	Ananum := mess.Addr - AnalogStart;
	Diginum := mess.Addr - DigitalStart;

	for i:= 0 to mess.Leng-1 do
	begin
		if (((mess.Mask and (4 shr i))>0)
		or ( mess.Leng=4))
		and( mess.Addr+i < 128)
		then
		begin
			Unites[mess.Addr+i].Data := mess.Data[i];
			Unites[mess.Addr+i].Age := reColor;
			Unites[mess.Addr+i].Surs := mess.Surs;
			if (Ananum>=0) and (Ananum<AnalogLength)	then
			begin
				Anapan[Ananum].Caption := inttostr(mess.Data[i]);
				Anapan[Ananum].Color := clBlueGradient[reColor,mess.Surs];
			end;
			if (Diginum>=0) and (Diginum<DigitalLength)
			then	DigiColWrite(mess.Data[i],Diginum,reColor,mess.Surs);
		end;
		Ananum := Ananum+1;
		Diginum:=Diginum+1;
	end
end;

procedure TModbusForm.AnaRewrite;
var
	i: integer;
begin
	for i :=0 to 63 do
	begin
		if i < AnalogLength then
		begin
			Anapan[i].Caption := inttostr(Unites[AnalogStart+i].data);
			Anapan[i].Color := clBlueGradient[Unites[AnalogStart+i].Age,Unites[AnalogStart+i].Surs];
		end else
		begin
			Anapan[i].Caption :='';
			Anapan[i].Color := clSilver;
		end;
	end;
end;

procedure TModbusForm.DigiColWrite(Byte: word; Column: integer; Age: integer; Surs: integer);
var
	Box : integer;
begin
	Column := Column * 16;
	for Box := Column to (Column+15) do
	begin
		if (Byte and 1) > 0
			then	digipan[Box].color:= clRedGradient[age]
			else	digipan[Box].color:= clGreenGradient[age][Surs];
		Byte := byte div 2
	end
end;

procedure TModbusForm.DigiRewrite;
var
	i, j: integer;
begin
	for i:= 0 to 31 do
	if i < DigitalLength	then
		DigiColWrite(Unites[DigitalStart+i].Data,i,Unites[DigitalStart+i].Age,Unites[DigitalStart+i].Surs)
	else
		for j:=0 to 15	do	digipan[i*16+j].color := clSilver;
end;

procedure TModbusForm.DataLenEditChange(Sender: TObject);
var NewLen,i: integer;
begin
	NewLen:= Trunc(DataLenEdit.Value);
	EmptyCell:= Datagrid.Selection;
	if EmptyCell.Top > NewLen
	then EmptyCell.Top := NewLen;
	if EmptyCell.Bottom > NewLen
	then EmptyCell.Bottom := NewLen;
	Datagrid.Selection:=EmptyCell;
	DataGrid.RowCount:= Trunc(DataLenEdit.Value);

	if BitGroup.Tag > NewLen-1 then
	BitBut[NewLen-1].Checked:=true;

	for i:=3 downto 0 do
	begin
		BitBut[i].Enabled:= (i <= NewLen-1);
		BitBut[i].Visible:= (i <= NewLen-1);
	end;
end;

procedure TModbusForm.DataGridKeyPress(Sender: TObject; var Key: Char);
begin
case Key of
		chr(3),chr(8),chr(22),'0' .. '9': ; // цифры
	else
		Key := Chr(0); // символ не отображать
	end;
end;

procedure TModbusForm.DataGridSetEditText(Sender: TObject; ACol,
	ARow: Integer; const Value: String);
var str: string;
		num: integer;
begin

	str:= Value;

 if str='' then
 begin
		num:=0; str:='0';
		DataGrid.Cells[ACol,ARow]:=str;
	TGridCracker(DataGrid).InplaceEditor.Deselect;
 end;

 if (length(str)>1) and (copy(str,1,1)='0') then
 begin
	delete(str,1,1);
	DataGrid.Cells[ACol,ARow]:=str;
	TGridCracker(DataGrid).InplaceEditor.Deselect;
 end;

 try num := strtoint(str);
 except
		num:=0; str:='0';
		DataGrid.Cells[ACol,ARow]:=str;
	TGridCracker(DataGrid).InplaceEditor.Deselect;
 end;

 if num > $FFFF then
 begin
	delete(str,length(str),1);
	DataGrid.Cells[ACol,ARow]:=str;
	TGridCracker(DataGrid).InplaceEditor.Deselect;
 end;

 DigiBoxWrite(num);

end;

procedure TModbusForm.DataGridDrawCell(Sender: TObject; ACol,
	ARow: Integer; Rect: TRect; State: TGridDrawState);
begin
	DataGrid.Canvas.Brush.Color:=clWindow;
	DataGrid.Canvas.Font.Color := clWindowText;
	DataGrid.Canvas.FillRect(Rect);
	DataGrid.Canvas.TextOut(Rect.Left+2, Rect.Top+2, DataGrid.Cells[ACol, ARow]);
end;

procedure TModbusForm.BitButClick(Sender: TObject);
var
 i,key,val,sel: integer;
begin

	sel:= (Sender as TRadioButton).Tag;
	if sel <> BitGroup.Tag then
	begin
		BitGroup.Tag:=sel;
		TGridCracker(DataGrid).SelectCell(0,sel);
	end;

	DigiBoxWrite(strtoint(DataGrid.Cells[0,sel]));

end;

procedure TModbusForm.DataGridSelectCell(Sender: TObject; ACol,
	ARow: Integer; var CanSelect: Boolean);
begin
	if BitGroup.Tag<>ARow then
	begin
		BitGroup.Tag:=ARow;
		BitBut[ARow].Checked:=true;
	end;
end;

procedure TModbusForm.DoNothing(Sender: TObject);
begin
//	DOES NOTHING
end;

procedure TModbusForm.HagaNada(Sender: TObject; ACol,
	ARow: Integer; var CanSelect: Boolean);
begin
//	DOES NOTHING
end;

procedure TModbusForm.DataGridGetEditText(Sender: TObject; ACol,
	ARow: Integer; var Value: String);
begin
	if BitGroup.Tag<>ARow then
	begin
		BitGroup.Tag:=ARow;
		BitBut[ARow].Checked:=true;
	end;
end;

procedure TModbusForm.DigiBoxWrite(Surs: integer);
var
  i,key: integer;
begin
	key:=1;
	for i:=0 to 15 do
	begin
		DigiBox[i].OnClick:= DoNothing;
		DigiBox[i].Checked:= (Surs and key) >0;
		DigiBox[i].OnClick:=DigiClick;
		key:=key*2;
	end;
end;

procedure TModbusForm.AutoTimeEditChange(Sender: TObject);
begin
	Auto:=trunc(AutoTimeEdit.Value);
	if Auto = 0
	then AutoBox.Checked:= false;
end;

end.
