unit MainUnit;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Menus, ToolWin, ComCtrls, ProcSettings, ExtCtrls, StdCtrls,
  LibV, In_Drv, FrameBuf, SpanBuf;

type
  TMainForm = class(TForm)
    ToolBar: TToolBar;
    MeasureButton: TToolButton;
    ToolImages: TImageList;
    LeftPanel: TPanel;
    RightPanel: TPanel;
    LC1Panel: TPanel;
    RC1Panel: TPanel;
    LeftSigPanel: TPanel;
    LC2Panel: TPanel;
    LeftSpecPanel: TPanel;
    LC3Panel: TPanel;
    RightSigPanel: TPanel;
    RC2Panel: TPanel;
    RightSpecPanel: TPanel;
    RC3Panel: TPanel;
    LeftSplitter: TSplitter;
    RightSplitter: TSplitter;
    VertSplitter: TSplitter;
    MainMenu: TMainMenu;
    N1: TMenuItem;
    MeasureItem: TMenuItem;
    ExitItem: TMenuItem;
    N3: TMenuItem;
    LSPaintBox: TPaintBox;
    RSPaintBox: TPaintBox;
    LSpecPaintBox: TPaintBox;
    RSpecPaintBox: TPaintBox;
    Label1: TLabel;
    ToolButton1: TToolButton;
    Label2: TLabel;
    Label3: TLabel;
    TBSignalPower: TTrackBar;
    Label4: TLabel;
    ScaleLabel: TLabel;
    procedure ExitItemClick(Sender: TObject);
    procedure MeasureItemClick(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure TBSignalPowerChange(Sender: TObject);
  private
    NumChannels : integer;
    BlockSize   : integer;
    SpecSize    : integer;
    Frequency   : integer;
    Processing  : Boolean;
    procedure FillMinMax(var mmi:minmaxinfo_t);
    procedure OnIdle(Sender : TObject;var Done : Boolean);
  public
  end;

var
  MainForm : TMainForm;

implementation

{$R *.DFM}

const
  X_BORDER = 5;
  Y_BORDER = 5;
  FRAME_X_SUBDIV  = 8;
  FRAME_Y_SUBDIV  = 4;
  FRAME_COLOR = 200;
  DATA_COLOR = 255;
  SPECTRUM_COLOR = 240;

procedure PlotFrame;
var
  left,top,right,bottom : integer;
  x,y,dx,dy,lim : integer;
begin
  left:=X_BORDER;
  top:=Y_BORDER;
  right:=FB_GetMaxX() - X_BORDER;
  bottom:=FB_GetMaxY() - Y_BORDER;
  FB_DrawHLine(left,top,right,FRAME_COLOR);
  FB_DrawHLine(left,bottom,right,FRAME_COLOR);
  FB_DrawVLine(left,top,bottom,FRAME_COLOR);
  FB_DrawVLine(right,top,bottom,FRAME_COLOR);
  dx:=round((right-left) / FRAME_X_SUBDIV);
  x:=left+dx;
  lim:=right-(dx shr 1);
  while x < lim do
  begin
    FB_DrawVLine(x,top,bottom,FRAME_COLOR);
    x := x + dx;
  end;
  dy:=round((bottom-top) / FRAME_Y_SUBDIV);
  y:=top+dy;
  lim:=bottom-(dy shr 1);
  while y < lim do
  begin
    FB_DrawHLine(left,y,right,FRAME_COLOR);
    y := y + dy;
  end;
end;

procedure PlotData(DC : HDC;data : vec_t_array_p;numpts : integer);
begin
  FB_Clear;
  PlotFrame();
  FB_DrawPixels1fv(X_BORDER,FB_GetMaxX()-X_BORDER,data,numpts,DATA_COLOR);
  FB_BlitTo(DC,0,0,FB_GetMaxX(),FB_GetMaxY());
end;

procedure PlotSpectrum(DC : HDC;data : vec_t_array_p;numpts : integer;
  viewport : vec2_t);
var
  i, max : integer;
  x, dx : vec_t;
begin
  FB_Clear;
  PlotFrame();
  SP_Setup(0,FB_GetMaxY(),FB_GetMaxX());
  i:=numpts-1;
  if i<1 then
    exit;
  x:=FB_GetMaxX() - X_BORDER;
  dx:=(x - X_BORDER) / i;
  max:=round(viewport[1]);
  while i>=0 do
  begin
    SP_AddSpan(round(x),round(data^[i]),max);
    i:=i-1;
    x:=x-dx;
  end;
  SP_DrawVerticalSpans(SPECTRUM_COLOR);
  FB_BlitTo(DC,0,0,FB_GetMaxX(),FB_GetMaxY());
end;

procedure TMainForm.FillMinMax(var mmi:minmaxinfo_t);
var
  border : vec2_t;
begin
  vec2Set(border,Y_BORDER,-Y_BORDER);
  vec2Set(mmi.ld_minmax,0,LeftSigPanel.Height);
  vec2Add(mmi.ld_minmax,mmi.ld_minmax,border);
  vec2Set(mmi.ls_minmax,0,LeftSpecPanel.Height);
  vec2Add(mmi.ls_minmax,mmi.ls_minmax,border);
  if NumChannels = 2 then
  begin
    vec2Set(mmi.rd_minmax,0,RightSigPanel.Height);
    vec2Add(mmi.rd_minmax,mmi.rd_minmax,border);
    vec2Set(mmi.rs_minmax,0,RightSpecPanel.Height);
    vec2Add(mmi.rs_minmax,mmi.rs_minmax,border);
  end;
end;

procedure TMainForm.OnIdle(Sender : TObject;var Done : Boolean);
var
  data : databuf_p;
  mmi  : minmaxinfo_t;
begin
  FillMinMax(mmi);
  data := drvGetData(mmi);
  if data = nil then
  begin
    Sleep(10);
    Done := False;
    exit;
  end;
  FB_SetMaxX(LeftSigPanel.Width-1);
  FB_SetMaxY(LeftSigPanel.Height-1);
  PlotData(LSPaintBox.Canvas.Handle,data^.ld,BlockSize);
  FB_SetMaxX(LeftSpecPanel.Width-1);
  FB_SetMaxY(LeftSpecPanel.Height-1);
  PlotSpectrum(LSpecPaintBox.Canvas.Handle,data^.ls,SpecSize,mmi.ls_minmax);
  if NumChannels = 2 then
  begin
    FB_SetMaxX(RightSigPanel.Width-1);
    FB_SetMaxY(RightSigPanel.Height-1);
    PlotData(RSPaintBox.Canvas.Handle,data^.rd,BlockSize);
    FB_SetMaxX(RightSpecPanel.Width-1);
    FB_SetMaxY(RightSpecPanel.Height-1);
    PlotSpectrum(RSpecPaintBox.Canvas.Handle,data^.rs,SpecSize,mmi.rs_minmax);
  end;
  Done := False;
end;

procedure TMainForm.ExitItemClick(Sender: TObject);
begin
  drvEndProcessing();
  Close;
end;

procedure TMainForm.MeasureItemClick(Sender: TObject);
begin
  if Processing then
  begin
    Application.OnIdle := nil;
    drvEndProcessing();
    Processing := False;
  end
  else
  begin
    if PSettingsForm.ShowModal = mrOk then
    begin
      BlockSize := StrToInt(PSettingsForm.BlockSizeCombo.Items[PSettingsForm.BlockSizeCombo.ItemIndex]);
      SpecSize := BlockSize shr (1+PSettingsForm.SpectrumDivisorCombo.ItemIndex);
      Frequency := StrToInt(PSettingsForm.FreqCombo.Items[PSettingsForm.FreqCombo.ItemIndex]);
      NumChannels := StrToInt(PSettingsForm.NCCombo.Items[PSettingsForm.NCCombo.ItemIndex]);
      Processing := drvBeginProcessing(BlockSize,NumChannels,Frequency,nil,nil);
    end;
  end;
  if Processing then
  begin
    MeasureItem.Caption := 'Остановить отображение';
    MeasureButton.ImageIndex := 1;
    LeftPanel.Visible := True;
    if NumChannels = 2 then
    begin
      VertSplitter.Visible := True;
      RightPanel.Visible := True;
    end;
    FormResize(Self);
    Application.OnIdle := OnIdle;
  end
  else
  begin
    RightPanel.Visible := False;
    VertSplitter.Visible := False;
    LeftPanel.Visible := False;
    MeasureItem.Caption := 'Начать отображение';
    MeasureButton.ImageIndex := 0;
  end;
  MeasureButton.Hint := MeasureItem.Caption;
end;

procedure TMainForm.FormResize(Sender: TObject);
var
  WTotal, HTotal : integer;
begin
  if LeftPanel.Visible and RightPanel.Visible then
  begin
    WTotal := ClientWidth - VertSplitter.Width;
    LeftPanel.Width := WTotal div 2;
    RightPanel.Width := WTotal - LeftPanel.Width;
  end
  else
  begin
    if LeftPanel.Visible then
      LeftPanel.Width := ClientWidth;
    if RightPanel.Visible then
      RightPanel.Width := ClientWidth;
  end;
  HTotal := ClientHeight - LC1Panel.Height - LC2Panel.Height
    - LC3Panel.Height - LeftSplitter.Height;
  if HTotal < 20 then
    HTotal := 20;
  LeftSigPanel.Height := HTotal div 2;
  RightSigPanel.Height := LeftSigPanel.Height;
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
  RightPanel.Visible := False;
  VertSplitter.Visible := False;
  LeftPanel.Visible := False;
  MeasureItem.Caption := 'Начать отображение';
  MeasureButton.ImageIndex := 0;
  MeasureButton.Hint := MeasureItem.Caption;
end;

procedure TMainForm.TBSignalPowerChange(Sender: TObject);
begin
  ScaleLabel.Caption := IntToStr(1 shl TBSignalPower.Position);
  if Processing then
     drvCommand(PChar('set_sigscale '+ScaleLabel.Caption));
end;

end.

