unit MainForm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, Rtusbapi;

type
  TLoadingForm = class(TForm)
    LoadingButton: TButton;
    BoardPars: TGroupBox;
    StaticText7: TStaticText;
    StaticText3: TStaticText;
    StaticText4: TStaticText;
    StaticText2: TStaticText;
    StaticText6: TStaticText;
    ModuleNameEdit: TEdit;
    SerialNumberEdit: TEdit;
    StaticText5: TStaticText;
    DspTypeEdit: TEdit;
    RevisionEdit: TEdit;
    ClockFrequencyEdit: TEdit;
    IsDacPresentedEdit: TEdit;
    StaticText8: TStaticText;
    ModuleLoadingLed: TShape;
    StaticText13: TStaticText;
    Memo: TMemo;
    GroupBox1: TGroupBox;
    StaticText10: TStaticText;
    AvrVersionEdit: TEdit;
    StaticText11: TStaticText;
    DspVersionEdit: TEdit;
    StaticText1: TStaticText;
    UsbSpeedEdit: TEdit;
    StaticText9: TStaticText;
    procedure LoadingButtonClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
	procedure DoShortCut(var Msg: TWMKey; var Handled: Boolean);
	procedure InitDisplayInfo;
	procedure DisplayInfo(fi : FLASH_USB3000);
  public
    { Public declarations }
  end;

var
	LoadingForm: TLoadingForm;
	pModule : IRTUSB3000;
	DllVersion : DWORD;
	ModuleType : String;
   hModule : THandle;
   DspDriver: String;
	// структура, содержащая информацию о версии драйвера DSP
	DspInfo : DSP_INFO_USB3000;
	// структура информации в ППЗУ модуля
   fi : FLASH_USB3000;
	// структура параметров ввода данных
   ap : INPUT_PARS_USB3000;
	// структура параметров вывода данных
   dp : OUTPUT_PARS_USB3000;
	// название модуля
	ModuleName : array [0..10] of Char;
	// скорость USB
	UsbSpeed : Byte;
	// серийный номер модуля
	ModuleSerialNumber : array [0..8] of Char;
	// версия драйвера AVR
	AvrVersion : array [0..4] of Char;
   Status : boolean;

DllError : array[0..127] of Char;
N : DWord;

	// идентификатор события
	ReadEvent : THANDLE ;
	// OVERLAPPED структура
	ReadOv : OVERLAPPED ;
	BytesTransferred : DWORD;
   DataStep : DWORD;
	Buffer : array[0..35000] of SHORT;
   AdcBuffer : PSHORT;
   TimeOut : DWORD ;

implementation

{$R *.DFM}

//------------------------------------------------------------------------------
// обнаружение и загрузка модуля в нулевои виртуальном слоте
//------------------------------------------------------------------------------
procedure TLoadingForm.LoadingButtonClick(Sender: TObject);
var
	i : BYTE;
   ErrorString : AnsiString;
begin
	LoadingButton.Enabled := false;
	InitDisplayInfo();
   Application.ProcessMessages;

	// проверим версию используемой DLL библиотеки
	DllVersion := RtGetDllVersion;
   if DllVersion <> CURRENT_VERSION_RTUSBAPI then
   	begin
			ErrorString := 'Неверная версия DLL библиотеки Rtusbapi.dll!' + #10#13 +
						'            Текущая: ' + IntToStr(DllVersion shr 16) +  '.' + IntToStr(DllVersion and $FFFF) + '.' +
						' Требуется: ' + IntToStr(CURRENT_VERSION_RTUSBAPI shr 16) + '.' + IntToStr(CURRENT_VERSION_RTUSBAPI and $FFFF) + '.';
      	Application.MessageBox(PChar(ErrorString), 'ОШИБКА!!!', MB_OK + MB_ICONINFORMATION);
	      Close();
         Exit;
      end;

	// попробуем получить указатель на интерфейс для модуля USB3000
	ModuleType := 'usb3000';
	pModule := RtCreateInstance(PChar(ModuleType));
	if pModule = nil then begin Application.MessageBox('Не могу найти интерфейс модуля USB3000!', 'ОШИБКА!!!', MB_OK + MB_ICONINFORMATION); Close(); Exit; end;
	// попробуем обнаружить какой-нибудь модуль в нулевом виртуальном слоте
	if not pModule.OpenDevice(0) then begin Application.MessageBox('Не могу обнаружить модуль ''USB3000'' в нулевом виртуальном слоте!', 'ОШИБКА!!!', MB_OK + MB_ICONINFORMATION); LoadingButton.Enabled := true; pModule.ReleaseInstance(); Exit; end;
	// прочитаем название модуля в нулевом виртуальном слоте
	if not pModule.GetModuleName(@ModuleName) then begin Application.MessageBox('Не могу прочитать название модуля в нулевом виртуальном слоте!', 'ОШИБКА!!!', MB_OK + MB_ICONINFORMATION); pModule.ReleaseInstance(); LoadingButton.Enabled := true; Exit; end;
	// проверим, что это 'USB3000'
	if Boolean(StrComp(@ModuleName, PChar('USB3000'))) then begin Application.MessageBox('В нулевом виртуальном слоте не ''USB3000''!', 'ОШИБКА!!!', MB_OK + MB_ICONINFORMATION); pModule.ReleaseInstance(); LoadingButton.Enabled := true; Exit; end;
	// пролучим текущую скорость работы USB шины
	if not pModule.GetUsbSpeed(@UsbSpeed) then begin Application.MessageBox('Не могу получить скорость работы шины USB!', 'ОШИБКА!!!', MB_OK + MB_ICONINFORMATION); pModule.ReleaseInstance(); LoadingButton.Enabled := true; Exit; end;
	// прочитаем серийный номер модуля
	if not pModule.GetModuleSerialNumber(@ModuleSerialNumber) then begin Application.MessageBox('Не могу прочитать серийный номер модуля!', 'ОШИБКА!!!', MB_OK + MB_ICONINFORMATION); pModule.ReleaseInstance(); LoadingButton.Enabled := true; Exit; end;
	// прочитаем версию драйвера AVR
	if not pModule.GetAvrVersion(@AvrVersion) then begin Application.MessageBox('Не могу прочитать версию драйвера AVR модуля!', 'ОШИБКА!!!', MB_OK + MB_ICONINFORMATION); pModule.ReleaseInstance(); LoadingButton.Enabled := true; Exit; end;

	// теперь можно попробовать загрузить модуль
//	DspDriver := 'usb3000.rtd';
//	if not pModule.LOAD_DSP(PChar(DspDriver)) then begin ModuleLoadingLed.Brush.Color := clRed; Application.MessageBox('Не могу загрузить драйвер DSP в модуль!', 'ОШИБКА!!!', MB_OK + MB_ICONINFORMATION); pModule.ReleaseInstance(); Close(); Exit; end;
	// Код драйвера DSP возьмём из соответствующего ресурса DLL библиотеки
	if not pModule.LOAD_DSP() then begin ModuleLoadingLed.Brush.Color := clRed; Application.MessageBox('Не могу загрузить драйвер DSP в модуль!', 'ОШИБКА!!!', MB_OK + MB_ICONINFORMATION); pModule.ReleaseInstance(); Close(); Exit; end;
	// проверим загрузку модуля
	if not pModule.MODULE_TEST() then begin ModuleLoadingLed.Brush.Color := clRed; Application.MessageBox('Ошибка в работе драйвера DSP!', 'ОШИБКА!!!', MB_OK + MB_ICONINFORMATION); pModule.ReleaseInstance(); Close(); Exit; end;

	// теперь получим номер версии загруженного драйвера DSP
	if not pModule.GET_DSP_INFO(@DspInfo) then begin ModuleLoadingLed.Brush.Color := clRed; Application.MessageBox('Не могу получить версию драйвера DSP!', 'ОШИБКА!!!', MB_OK + MB_ICONINFORMATION); pModule.ReleaseInstance(); Close(); Exit; end;

	// обязательно проинициализируем поле size структуры FLASH_USB3000
	fi.size := sizeof(FLASH_USB3000);
	// получим информацию из ППЗУ модуля
	if not pModule.GET_FLASH(@fi) then begin ModuleLoadingLed.Brush.Color := clRed; Application.MessageBox('Не могу прочитать ППЗУ модуля!', 'ОШИБКА!!!', MB_OK + MB_ICONINFORMATION); pModule.ReleaseInstance(); Close(); Exit; end;

	// Все хорошо! зажгём зеленую лампочку
	ModuleLoadingLed.Brush.Color := clLime;
	// отобразим информацию из ППЗУ модуля
	DisplayInfo(fi);

	// обязательно проинициализируем поле size структуры INPUT_PARS_USB3000
	ap.size := sizeof(INPUT_PARS_USB3000);
	// получим текущие параметры работы АЦП
	if not pModule.GET_INPUT_PARS(@ap) then begin Application.MessageBox('Не могу получить текущие параметры АЦП!', 'ОШИБКА!!!', MB_OK + MB_ICONINFORMATION); pModule.ReleaseInstance(); Close(); Exit; end;

//	N := pModule.GetLastErrorString(@DllError, 128);

	// установим желаемые параметры АЦП
	ap.ChannelsQuantity := 4;
	for i:=0 to (ap.ChannelsQuantity-1) do ap.ControlTable[i] := i;
	ap.InputRate := 1000.;
	ap.InterKadrDelay := 0.0;
	// передадим требуемые параметры работы АЦП в модуль
	if not pModule.SET_INPUT_PARS(@ap) then begin Application.MessageBox('Не могу передать параметры АЦП!', 'ОШИБКА!!!', MB_OK + MB_ICONINFORMATION); pModule.ReleaseInstance(); Close(); Exit; end;

	// обязательно проинициализируем поле size структуры OUTPUT_PARS_USB3000
	dp.size := sizeof(OUTPUT_PARS_USB3000);
	// получим текущие параметры работы ЦАП
	if not pModule.GET_OUTPUT_PARS(@dp) then begin Application.MessageBox('Не могу получить текущие параметры ЦАП!', 'ОШИБКА!!!', MB_OK + MB_ICONINFORMATION); pModule.ReleaseInstance(); Close(); Exit; end;
	// установим желаемые параметры ЦАП
	dp.OutputRate := 100.0;
	if not pModule.SET_OUTPUT_PARS(@dp) then begin Application.MessageBox('Не могу передать параметры ЦАП!', 'ОШИБКА!!!', MB_OK + MB_ICONINFORMATION); pModule.ReleaseInstance(); Close(); Exit; end;
{
	// теперь попробуем организовать сбор данных с АЦП
	ReadEvent := CreateEvent(nil, FALSE , FALSE, nil);
	FillMemory(@ReadOv, sizeof(OVERLAPPED), 0); ReadOv.hEvent := ReadEvent;
	DataStep := 32768;
	TimeOut := Trunc(ap.ChannelsQuantity*DataStep/ap.ChannelRate + 1000.0);

	AdcBuffer := @Buffer;

	// остановим АЦП и очистим канал сбора
	if not pModule.STOP_READ() then begin Application.MessageBox('Не могу остановить АЦП!', 'ОШИБКА!!!', MB_OK); Close(); Exit; end;
	// а теперь можно и запускать АЦП
	if not pModule.START_READ() then begin Application.MessageBox('Не могу запустить АЦП!', 'ОШИБКА!!!', MB_OK); Close(); Exit; end;

	// асинхронный сбор данных в первую половинку AdcBuffer
	BytesTransferred := 0;
	pModule.ReadData(AdcBuffer, @DataStep, @BytesTransferred, @ReadOv);
	// ждем окончания сбора данных
	if WaitForSingleObject(ReadEvent, TimeOut) = WAIT_TIMEOUT then Application.MessageBox('Ошибка ввода данных с АЦП!', 'ОШИБКА!!!', MB_OK);
   // Ураааааа! Теперь в Buffer находятся отсчеты с АЦП.
}
	// освободим интерфейс модуля
	if not pModule.ReleaseInstance() then begin Application.MessageBox('Не могу освободить интерфейс модуля!', 'ОШИБКА!!!', MB_OK + MB_ICONINFORMATION); Close(); end;
	LoadingButton.Enabled := true;

   LoadingButton.SetFocus();
end;

//---------------------------------------------------------------------------
// сброс отображающей информации из ППЗУ модуля
//---------------------------------------------------------------------------
procedure TLoadingForm.InitDisplayInfo;
begin
	UsbSpeedEdit.Text := '???';
	AvrVersionEdit.Text := '????';
	DspVersionEdit.Text := '?????';
	ModuleLoadingLed.Brush.Color := clBtnFace;
	ModuleNameEdit.Text := '???????';
	DspTypeEdit.Text := '??????????';
	SerialNumberEdit.Text := '????????';
	ClockFrequencyEdit.Text := '?????';
	RevisionEdit.Text := '?';
	IsDacPresentedEdit.Text := '????';
end;

//---------------------------------------------------------------------------
// отображение информации из ППЗУ модуля
//---------------------------------------------------------------------------
procedure TLoadingForm.DisplayInfo(fi : FLASH_USB3000);
begin
	if UsbSpeed = USB11_USB2185 then UsbSpeedEdit.Text := ' 12'
   else if UsbSpeed = USB20_USB2185 then UsbSpeedEdit.Text := '480';

	AvrVersionEdit.Text := StrPas(@AvrVersion);
	DspVersionEdit.Text := IntToStr(DspInfo.DspMajor) + '.' + IntToStr(DspInfo.DspMinor);

	fi.Name[10] := Byte(#0);
	ModuleNameEdit.Text := StrPas(@fi.Name);
	fi.DspType[16] := Byte(#0);
	DspTypeEdit.Text := StrPas(@fi.DspType);
	fi.SerialNumber[8] := Byte(#0);
	SerialNumberEdit.Text := StrPas(@fi.SerialNumber);
	ClockFrequencyEdit.Text := FormatFloat('0.', fi.DspClockout/1000.0);
	RevisionEdit.Text := String(fi.Revision);
	if fi.IsDacPresented = 0 then IsDacPresentedEdit.Text := 'Нет'
	else IsDacPresentedEdit.Text := 'Есть';
end;

//---------------------------------------------------------------------------
// отображение информации из ППЗУ модуля
//---------------------------------------------------------------------------
procedure TLoadingForm.FormCreate(Sender: TObject);
begin
   Application.OnShortCut := DoShortCut;
	InitDisplayInfo();
end;

//---------------------------------------------------------------------------
// обработка нажатия клавиши ESCAPE на клавиатуре
//---------------------------------------------------------------------------
procedure TLoadingForm.DoShortCut(var Msg: TWMKey; var Handled: Boolean);
begin
	if Msg.CharCode = VK_ESCAPE then
   begin
   	if Application.MessageBox('Действительно хотите завершить работу?', 'Подтвердите завершение!', MB_YESNO + MB_ICONQUESTION) = IDYES then Application.Terminate();
   end;
end;

end.
