// DEPRECATED !!!

unit VspcCtrl;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, Buttons, ComCtrls, VisVespC;

const
{
0  Reg10
1  Reg14
2  Reg15
3  Reg16
4  Reg19
5  Reg1A
6  Answer
7  ErrorFlag
}
  VspcAlarms: array[0..58] of string = (
    #0+#$00#$03+#$00#$03+'Нулевая скорость',
    #0+#$00#$20+#$00#$00+'Устройство не готово к работе',
    #0+#$00#$40+#$00#$40+'Малая авария',
    #0+#$00#$80+#$00#$80+'Большая авария',

    #1+#$00#$01+#$00#$01+'Плавкий предохранитель',
    #1+#$00#$02+#$00#$02+'Основная цепь под напряжением',
    #1+#$00#$04+#$00#$04+'Энергоуправляющая схема под напряжением',
    #1+#$00#$08+#$00#$08+'Нарушение основной цепи',
    #1+#$00#$10+#$00#$10+'Короткое замыкание',
    #1+#$00#$20+#$00#$20+'Нарушение заземления',
    #1+#$00#$40+#$00#$40+'Перегрузка по току',
    #1+#$00#$80+#$00#$80+'Перегрузка по напряжению',
    #1+#$01#$00+#$01#$00+'Перегрев теплоотвода 1',
    #1+#$02#$00+#$02#$00+'Перегрев теплоотвода 2',
    #1+#$04#$00+#$04#$00+'Перегрузка электродвигателя',
    #1+#$08#$00+#$08#$00+'Перегрузка преобразователя',
    #1+#$10#$00+#$10#$00+'Крутящий момент выше нормы 1',
    #1+#$20#$00+#$20#$00+'Крутящий момент выше нормы 2',
    #1+#$40#$00+#$40#$00+'Неисправность тормозного транзистора',
    #1+#$80#$00+#$80#$00+'Неисправность тормозного резистора',

    #2+#$00#$01+#$00#$01+'Внешняя неисправность 3',
    #2+#$00#$02+#$00#$02+'Внешняя неисправность 4',
    #2+#$00#$04+#$00#$04+'Внешняя неисправность 5',
    #2+#$00#$08+#$00#$08+'Внешняя неисправность 6',
    #2+#$00#$10+#$00#$10+'Внешняя неисправность 7',
    #2+#$00#$20+#$00#$20+'Внешняя неисправность 8',
    #2+#$00#$40+#$00#$40+'Неисправен охлаждающий вентилятор',
    #2+#$00#$80+#$00#$80+'Скорость выше нормы',
    #2+#$01#$00+#$01#$00+'Отклонение скорости выше допустимого',
    #2+#$02#$00+#$02#$00+'Обрыв PG',
    #2+#$04#$00+#$04#$00+'Нехватка входной фазы',
    #2+#$08#$00+#$08#$00+'Нехватка выходной фазы',
    #2+#$20#$00+#$20#$00+'Оператор отключен',
    #2+#$40#$00+#$40#$00+'Ошибка записи в EEPROM',

    #3+#$00#$01+#$00#$01+'Ошибка передачи по MODBUS',
    #3+#$00#$10+#$00#$10+'Сбой управления',
    #3+#$00#$20+#$00#$20+'Ошибка нуля серво-мотора',

    #4+#$00#$01+#$00#$01+'Недостаточное напряжение',
    #4+#$00#$02+#$00#$02+'Перегрузка по напряжению',
    #4+#$00#$04+#$00#$04+'Перегрев преобразователя',
    #4+#$00#$08+#$00#$08+'Предупреждение о перегреве преобразователя',
    #4+#$00#$10+#$00#$10+'Крутящий момент выше нормы 1',
    #4+#$00#$20+#$00#$20+'Крутящий момент выше нормы 2',
    #4+#$00#$40+#$00#$40+'2 wire sequence input fault',
    #4+#$00#$80+#$00#$80+'Заблокирован',
    #4+#$01#$00+#$01#$00+'Внешняя неисправность 3',
    #4+#$02#$00+#$02#$00+'Внешняя неисправность 4',
    #4+#$04#$00+#$04#$00+'Внешняя неисправность 5',
    #4+#$08#$00+#$08#$00+'Внешняя неисправность 6',
    #4+#$10#$00+#$10#$00+'Внешняя неисправность 7',
    #4+#$20#$00+#$20#$00+'Внешняя неисправность 8',
    #4+#$40#$00+#$40#$00+'Неисправен охлаждающий вентилятор',
    #4+#$80#$00+#$80#$00+'Скорость выше нормы',

    #5+#$00#$FF+#$00#$01+'Ошибка кода операции',
    #5+#$00#$FF+#$00#$02+'Ошибка номера регистра',
    #5+#$00#$FF+#$00#$03+'Ошибка размещения данных',
    #5+#$00#$FF+#$00#$21+'Ошибка установки данных',
    #5+#$00#$FF+#$00#$22+'Некорректный режим ввода',
    #5+#$00#$01+#$00#$01+'Нет связи с устройством'
    );

type
  TAlarmFlags = array of byte;

type
  TVspcCtrlFrame = class(TFrame)
    SostPanel: TPanel;
    NamePanel: TPanel;
    ButPanel: TPanel;
    AutoButton: TSpeedButton;
    Label4: TLabel;
    Panel2: TPanel;
    StartButton: TSpeedButton;
    StopButton: TSpeedButton;
    HandLabel: TLabel;
    StatList: TListView;
    Label1: TLabel;
    OpFreqPanel: TPanel;
    Label2: TLabel;
    OutFreqPanel: TPanel;
    Label3: TLabel;
    OutTokPanel: TPanel;
    btFreqStatus: TSpeedButton;
    FreqList: TListView;
    procedure AutoButtonClick(Sender: TObject);
    procedure StartButtonClick(Sender: TObject);
    procedure StopButtonClick(Sender: TObject);
    procedure StatListInfoTip(Sender: TObject; Item: TListItem;
      var InfoTip: String);
    procedure OpFreqPanelClick(Sender: TObject);
    procedure NamePanelClick(Sender: TObject);
    procedure btFreqStatusClick(Sender: TObject);
    procedure FreqListDblClick(Sender: TObject);
  private
    FMessageTag: string;

    FSost: integer;
    FControl: integer;
    FOpFreq: integer;
    FOutFreq: integer;
    FOutTok: integer;

    FTagEnable: integer;
    FTagErrorFlag: integer;
    FTagReg10: integer;
    FTagReg14: integer;
    FTagReg15: integer;
    FTagReg16: integer;
    FTagReg19: integer;
    FTagReg1A: integer;
    FTagReg20: integer;
    FTagReg21: integer;
    FTagReg22: integer;
    FTagAnswer: integer;
    FTagOpFreqDef: integer;

    FAlarms: TAlarmFlags;
  public
    M: TVisVespC;

    procedure Init;
    procedure Process;
  end;

  procedure CheckVspcAlarms(A: TAlarmFlags; num,value: integer);
  procedure UpdateVspcAlarmList(list: TListView; A: TAlarmFlags);

implementation
uses
  MesConst, TagStorage, DevSetPanel, MesLogging, SetChannel, numbers, VspcSetPanel;

{$R *.DFM}

{ TVspcCtrlFrame }

procedure TVspcCtrlFrame.Init;
var
  s: string;
  i,k: integer;
begin
  NamePanel.Caption := M.DeviceName;

  FMessageTag := M.DeviceName;

  s := M.TagPath + '.VSPC_' + M.TagName + '_Enable';
  FTagEnable := GetTagIndex(s);

  s := M.TagPath + '.VSPC_' + M.TagName + '_ErrorFlag';
  FTagErrorFlag := GetTagIndex(s);

  s := M.TagPath + '.VSPC_' + M.TagName + '_Reg10';
  FTagReg10 := GetTagIndex(s);

  s := M.TagPath + '.VSPC_' + M.TagName + '_Reg14';
  FTagReg14 := GetTagIndex(s);

  s := M.TagPath + '.VSPC_' + M.TagName + '_Reg15';
  FTagReg15 := GetTagIndex(s);

  s := M.TagPath + '.VSPC_' + M.TagName + '_Reg16';
  FTagReg16 := GetTagIndex(s);

  s := M.TagPath + '.VSPC_' + M.TagName + '_Reg19';
  FTagReg19 := GetTagIndex(s);

  s := M.TagPath + '.VSPC_' + M.TagName + '_Reg1A';
  FTagReg1A := GetTagIndex(s);

  s := M.TagPath + '.VSPC_' + M.TagName + '_Reg20';
  FTagReg20 := GetTagIndex(s);

  s := M.TagPath + '.VSPC_' + M.TagName + '_Reg21';
  FTagReg21 := GetTagIndex(s);

  s := M.TagPath + '.VSPC_' + M.TagName + '_Reg22';
  FTagReg22 := GetTagIndex(s);

  s := M.TagPath + '.VSPC_' + M.TagName + '_Answer';
  FTagAnswer := GetTagIndex(s);

  s := M.TagPath + '.VSPC_' + M.TagName + '_OpFreqDef';
  FTagOpFreqDef := GetTagIndex(s);

  // Список частот
  btFreqStatus.Caption := 'Обороты';
  FreqList.Left := 400;
  FreqList.Items.Clear;
  for i:=1 to 10 do begin
    s := format('%s.VSPC_%s_OpFreq%.2d', [M.TagPath, M.TagName, i]);
    k := GetTagIndex(s);
    if k>=0 then with FreqList.Items.Add do begin
      Caption := 'Уровень ' + IntToStr(i);
      Subitems.Add('');
      Subitems.Add(s);
      Data := pointer(k);
    end;
  end;
  if FreqList.Items.Count > 1 then begin
    with FreqList.Items[0] do Caption := Caption + ' (внизу)';
    with FreqList.Items[FreqList.Items.Count-1] do Caption := Caption + ' (вверху)';
  end;


  FSost := -1;
  FControl := -1;
  FOpFreq := -1;
  FOutFreq := -1;
  FOutTok := -1;

  StatList.Items.Clear;
  SetLength(FAlarms, length(VspcAlarms));
  for i:=0 to length(FAlarms)-1 do FAlarms[i] := 0;

  Process;
end;

procedure TVspcCtrlFrame.Process;
var
  value, venab, vreg10, vreg20, vreg21, vreg22, i: integer;
  s: string;
begin

  venab   := GetTagValue( FTagEnable );
  vreg10  := GetTagValue( FTagReg10 );
  vreg20  := GetTagValue( FTagReg20 );
  vreg21  := GetTagValue( FTagReg21 );
  vreg22  := GetTagValue( FTagReg22 );


  value := (vreg10 and 5);
  if FSost <> value then begin
    case value of
      0: SostPanel.Caption := 'Отключено';
      1: SostPanel.Caption := 'Работает';
      4: SostPanel.Caption := 'Отключено (реверс)';
      5: SostPanel.Caption := 'Работает (реверс)';
    end;
    FSost := value;
  end;

  value := (venab and 7);
  if FControl <> value then begin
    if (value and 3) = 1 then begin
      AutoButton.Down := true;
      AutoButton.Font.Style := [fsBold];
    end else begin
      AutoButton.Down := false;
      AutoButton.Font.Style := [];
    end;

    if value=7 then begin
      StartButton.Down := true;
      StartButton.Font.Style := [fsBold];
    end else begin
      StartButton.Down := false;
      StartButton.Font.Style := [];
    end;

    if value=3 then begin
      StopButton.Down := true;
      StopButton.Font.Style := [fsBold];
    end else begin
      StopButton.Down := false;
      StopButton.Font.Style := [];
    end;

    FControl := value;
  end;

  value := vreg20;
  if value <> FOpFreq then begin
    OpFreqPanel.Caption := format('%.1f', [value/10]);
    FOpFreq := value;
  end;

  value := vreg21;
  if value <> FOutFreq then begin
    if value > $8000 then
      OutFreqPanel.Caption := format('-%.1f', [($10000 - value)/10])
    else
      OutFreqPanel.Caption := format('%.1f', [value/10]);
    FOutFreq := value;
  end;

  value := vreg22;
  if value <> FOutTok then begin
    OutTokPanel.Caption := '';format('%.1f', [value/10]);
    FOutTok := value;
  end;

{
  value := (vreg28 and $02);
  if (value=0) xor (ButPanel.Enabled) then begin
    ButPanel.Enabled := not ButPanel.Enabled;
    AutoButton.Enabled := ButPanel.Enabled;
    StartButton.Enabled := ButPanel.Enabled;
    StopButton.Enabled := ButPanel.Enabled;
    if ButPanel.Enabled then begin
      HandLabel.Font.Color := clGray;
      HandLabel.Caption := 'Ручное управление';
    end else begin
      HandLabel.Font.Color := clRed;
      HandLabel.Caption := 'Местное управление';
    end;
  end;
}

  if not ButPanel.Enabled then HandLabel.Visible := not HandLabel.Visible;

//  if FreqList.Visible then begin
    for i:=0 to FreqList.Items.Count-1 do begin
      value := GetTagValue(integer(FreqList.Items[i].Data)) div 100;
      s := IntToStr(value);
      if not(s = FreqList.Items[i].SubItems[0]) then
        FreqList.Items[i].SubItems[0] := s;
    end;
//  end else begin

    CheckVspcAlarms(FAlarms, 0, GetTagValue( FTagReg10 ));
    CheckVspcAlarms(FAlarms, 1, GetTagValue( FTagReg14 ));
    CheckVspcAlarms(FAlarms, 2, GetTagValue( FTagReg15 ));
    CheckVspcAlarms(FAlarms, 3, GetTagValue( FTagReg16 ));
    CheckVspcAlarms(FAlarms, 4, GetTagValue( FTagReg19 ));
    CheckVspcAlarms(FAlarms, 5, GetTagValue( FTagAnswer ));
    UpdateVspcAlarmList(StatList, FAlarms);

//  end;


end;

procedure UpdateVspcAlarmList(list: TListView; A: TAlarmFlags);
var
  i, j: integer;
  flag: boolean;
begin
  i := 0;
  while i<list.Items.Count do with list.Items[i] do
    if A[integer(Data)] = 0 then Delete else inc(i);

  for i:=0 to length(A)-1 do
    if A[i]>0 then begin
      flag := true;
      for j:=0 to list.Items.Count-1 do
        if integer(list.Items[j].Data) = i then begin
          flag := false;
          break;
        end;

      if flag then with list.Items.Add do begin
        Caption := copy(VspcAlarms[i], 6, 128);
        Data := pointer(i);
      end;
    end;

end;


procedure CheckVspcAlarms(A: TAlarmFlags; num,value: integer);
var
  i,n,m,v: integer;
  s: string;
begin
  for i:=0 to length(A)-1 do begin
    s := VspcAlarms[i];
    n := ord(s[1]);

    if n = num then begin
      m := ord(s[2])*256 + ord(s[3]);
      v := ord(s[4])*256 + ord(s[5]);
      
      if (value and m) = v then
        A[i] := 1
      else
        A[i] := 0;
    end;
  end;
end;


//============================================================================
// Кнопка авто/руч
//============================================================================
procedure TVspcCtrlFrame.AutoButtonClick(Sender: TObject);
begin
  SaveMessageText(mcMode_text, FMessageTag, 'Автомат', mcMode_bc, mcMode_fc);
  SetTagValue( FTagEnable, (GetTagValue(FTagEnable) or 1) and $FD);
end;

procedure TVspcCtrlFrame.StartButtonClick(Sender: TObject);
begin
  if MessageDlg('ВНИМАНИЕ! Вы подтверждаете запуск машины?',
      mtConfirmation, [mbYes, mbNo], 0) <> mrYes then begin
    FControl := -1;
    exit;
  end;

  SaveMessageText(mcMode_text, FMessageTag, 'Ручное - старт', mcMode_bc, mcMode_fc);
  SetTagValue( FTagEnable, (GetTagValue(FTagEnable) or 6));
end;

procedure TVspcCtrlFrame.StopButtonClick(Sender: TObject);
begin
  SaveMessageText(mcMode_text, FMessageTag, 'Ручное - стоп', mcMode_bc, mcMode_fc);
  SetTagValue( FTagEnable, (GetTagValue(FTagEnable) or 2) and $FB);
end;

procedure TVspcCtrlFrame.StatListInfoTip(Sender: TObject; Item: TListItem;
  var InfoTip: String);
begin
  InfoTip := item.Caption;
end;

procedure TVspcCtrlFrame.OpFreqPanelClick(Sender: TObject);
var
  s: string;
  v,i: integer;
begin
  s := IntToStr(GetTagValue(FTagOpFreqDef) div 100);
  if InputQuery('Установка опорной частоты для режима РУЧ',
      'Введите значение от 0 до ' + IntToStr(M.OpFreqMax)+ ', Гц', s) then begin

    val(s,v,i);
//    if (v>=0) and (v<=M.OpFreqMax) then begin
    SaveMessageText(mcParam_text, FMessageTag, 'F=' + IntToStr(v), mcParam_bc, mcParam_fc);
    SetTagValue( FTagOpFreqDef, v*100);
//    end else
//      MessageDlg('Значение вне допустимых пределов.', mtError, [mbOK], 0);
  end;

end;

procedure TVspcCtrlFrame.NamePanelClick(Sender: TObject);
var
  VspcSetPanelForm: TVspcSetPanelForm;
begin
  VspcSetPanelForm := TVspcSetPanelForm.Create(self);
  VspcSetPanelForm.M := M;
  VspcSetPanelForm.ShowModal;
  VspcSetPanelForm.Free;
end;


procedure TVspcCtrlFrame.btFreqStatusClick(Sender: TObject);
begin
  if btFreqStatus.Caption = 'Статус' then begin
    btFreqStatus.Caption := 'Обороты';
    FreqList.Left := 400
  end else begin
    btFreqStatus.Caption := 'Статус';
    FreqList.Left := 8;
  end;
end;

procedure TVspcCtrlFrame.FreqListDblClick(Sender: TObject);
var
  v,i: integer;
  tname,s: string;
begin
  if FreqList.Selected=nil then exit;

//  CheckEditMode;
//  if not EditMode_On then exit;

  s := FreqList.Selected.SubItems[0];
  tname := FreqList.Selected.SubItems[1];
  if InputQuery('Установка значения', 'Частота для "' +
      FreqList.Selected.Caption + '"', s) then begin

    val(s, v, i);
//    if v > M.OpFreqMax then
//      ShowMessage('Частота не должна превышать ' + inttostr(M.OpFreqMax))
//    else begin
      SaveMessageText(mcParam_text, FMessageTag, 'Fур' +
          inttostr(FreqList.Selected.Index+1) + '=' + IntToStr(v), mcParam_bc, mcParam_fc);
      SetTagValue(integer(FreqList.Selected.Data), v*100);
//    end;
  end;
end;

end.
