program Test_Zadc;
{$APPTYPE CONSOLE}

uses
  SysUtils,
  Windows,
  Zadc_int;

const
  MAX_TYPE_DSP = 20;                                  // Максимальное поддерживаемое кол-во типов устройств
  MAX_DEVICE_NAME	= 16;				                      	// Максимальное значение длины возвращаемого имени устройства

var
  Err: Longint;                                       // Код ошибки
  typeDevice: Longint;                                // Тип устройства
  numberDSP: Longint = 0;                             // Порядковый номер устройства
  enable: Longint;                                    // Флаг поддерживается / не поддерживается
  deviceName: array [0..MAX_DEVICE_NAME] of Char;     // Имя устройства
  serial: Longint;                                    // Серийный номер устройства
  numChannelsADC: Longint;					                  // Количество включенных каналов АЦП
  amplifyADC: array [0..1] of Double;                 // Коэффициенты усиления по первым двум каналам
  resolutionADC: array [0..1] of Double;              // Вес младшего разряда АЦП по первым двум каналам
  numWordsADC: Longint;                               // Количество слов (по два байта) в одном отсчете АЦП
  sizeBufferADC: Longint;		                          // Размер буфера драйвера в словах
  pointerADC: Longint = 0;			                      // Указатель на текущий элемент заполнения буфера драйвера
  pointerADC_old: Longint = 0;	                      // Предыдущее значение указателя заполнения буфера драйвера
  pBuffer: Pointer = 0;				                        // Указатель на начало буфера драйвера для АЦП
  pBuffer16ADC: ^Smallint = 0;                        // Указатель на начало буфера драйвера для АЦП с разрядностью не более 16 бит
  pBuffer32ADC: ^Longint = 0;		                      // Указатель на начало буфера драйвера для АЦП с разрядностью более 16 бит
  volt: array [0..1] of Double;					              // Мгновенное текущее значение АЦП (в вольтах)
  sampleADC: array [0..1] of Longint;                 // Мгновенное текущее значение отсчета АЦП (оцифрованное значение)
  sample16ADC: array [0..1] of Smallint;              // Мгновенное текущее значение отсчета АЦП с разрядностью не более 16 бит(оцифрованное значение)
  sample32ADC: array [0..1] of Longint;               // Мгновенное текущее значение отсчета АЦП с разрядностью более 16 бит(оцифрованное значение)
  proc: Boolean = True;

begin
  // Цикл подключения к первому поддерживаемому устройству
  for typeDevice := 0 to MAX_TYPE_DSP - 1 do
  begin
    // Подключение к драйверу устройства
    Err := ZOpen(typeDevice, numberDSP);
    // Если подключение прошло без ошибок
    if Err = 0 then
    begin
      // Проверка поддержки устройством АЦП
      Err := ZGetEnableADC(typeDevice, numberDSP, enable);
      // Если устройство поддерживает АЦП
      if (Err = 0) and (enable <> 0) then
        // Выход из цикла подключения
        break
      // Если устройство не поддерживает АЦП
      else
      begin
        // Вывод информации об ошибке
        WriteLn('ZGetEnableADC() return Error = 0x', IntToHex(Err, 2));
        // Отключение от драйвера устройства
        Err := ZClose(typeDevice, numberDSP);
      end;
    end
  end;

  // Если не удалось подключиться к драйверу устройства
	if typeDevice >= MAX_TYPE_DSP then
	begin
		// Вывод информации об ошибке
    WriteLn('Device not found! Error = 0x', IntToHex(Err, 2));
		ReadLn;
		Exit;
	end
	// Если удалось подключиться к драйверу устройства
	else
    // Вывод информации о том, что произошло подключение к драйверу устройства
    WriteLn('Device found...');

  // Опрос имени устройства
  Err := ZGetNameDevice(typeDevice, numberDSP, deviceName, MAX_DEVICE_NAME);
  // Если опрос выполнился с ошибкой
	if Err <> 0 then
	begin
		// Вывод информации об ошибке
    WriteLn('ZGetNameDevice() return Error = 0x', IntToHex(Err, 2));
		// Отключение от драйвера устройства
		Err := ZClose(typeDevice, numberDSP);
    ReadLn;
		Exit;
	end
	// Если опрос выполнился без ошибок
	else
  	// Вывод имени устройства
    WriteLn('Device name: ', deviceName);

  // Опрос серийного номера устройства
	Err := ZGetSerialNumberDSP(typeDevice, numberDSP, serial);
	// Если опрос выполнился с ошибкой
	if Err <> 0 then
	begin
		// Вывод информации об ошибке
    WriteLn('ZGetNameDevice() return Error = 0x', IntToHex(Err, 2));
		// Отключение от драйвера устройства
		Err := ZClose(typeDevice, numberDSP);
	  ReadLn;
		Exit;
	end
	// Если опрос выполнился без ошибок
	else
		// Вывод серийного номера устройства
    WriteLn('Serial number: ', serial);

  // Опрос колличества каналов АЦП устройства
	Err := ZGetQuantityChannelADC(typeDevice, numberDSP, numChannelsADC);
	// Если опрос выполнился с ошибкой
	if Err <> 0 then
	begin
		// Вывод информации об ошибке
    WriteLn('ZGetQuantityChannelADC() return Error = 0x', IntToHex(Err, 2));
		// Отключение от драйвера устройства
		Err := ZClose(typeDevice, numberDSP);
	  ReadLn;
	  Exit;
  end
	// Если опрос выполнился без ошибок
	else
		// Вывод количества каналов АЦП устройства
    WriteLn('Quantity of ADC channel: ', numChannelsADC);

	// Запрос на включение первого канала АЦП устройства
	Err := ZSetInputADC(typeDevice, numberDSP, 0, 1);
	// Если запрос выполнился с ошибкой
	if Err <> 0 then
  begin
		// Вывод информации об ошибке
    WriteLn('ZSetInputADC() return Error = 0x', IntToHex(Err, 2));
		// Отключение от драйвера устройства
		Err := ZClose(typeDevice, numberDSP);
		ReadLn;
	  Exit;
	end
	// Если запрос выполнился без ошибок
	else
		// Вывод информации об успешном включении первого канала АЦП устройства
    Writeln('First channel activation is successful...');

	// Если количество каналов устройства больше одного
	if numChannelsADC > 1 then
	begin
		// Запрос на включение второго канала АЦП устройства
		Err := ZSetInputADC(typeDevice, numberDSP, 1, 1);
		// Если запрос выполнился с ошибкой
		if Err <> 0 then
		begin
			// Вывод информации об ошибке
      WriteLn('ZSetInputADC() return Error = 0x', IntToHex(Err, 2));
			// Отключение от драйвера устройства
			Err := ZClose(typeDevice, numberDSP);
			ReadLn;
	    Exit;
		end
		// Если запрос выполнился без ошибок
		else
			// Вывод информации об успешном включении первого канала устройства
      Writeln('Second channel activation is successful...');
	end;

	// Опрос коэффициента усиления по первому каналу АЦП
	Err := ZGetAmplifyADC(typeDevice, numberDSP, 0, amplifyADC[0]);
	// Если опрос выполнился с ошибкой
	if Err <> 0 then
	begin
		// Вывод информации об ошибке
    WriteLn('ZGetAmplifyADC() return Error = 0x', IntToHex(Err, 2));
		// Отключение от драйвера устройства
		Err := ZClose(typeDevice, numberDSP);
		ReadLn;
    Exit;
	end
	// Если опрос выполнился без ошибок
	else
		// Вывод коэффициента усиления по первому каналу АЦП
    WriteLn('First channel amplifier: ', amplifyADC[0]:12:6);

	// Если количество каналов устройства больше одного
	if numChannelsADC > 1 then
	begin
		// Опрос коэффициента усиления по второму каналу АЦП
		Err := ZGetAmplifyADC(typeDevice, numberDSP, 1, amplifyADC[1]);
		// Если опрос выполнился с ошибкой
		if Err <> 0 then
		begin
			// Вывод информации об ошибке
      WriteLn('ZGetAmplifyADC() return Error = 0x', IntToHex(Err, 2));
			// Отключение от драйвера устройства
			Err := ZClose(typeDevice, numberDSP);
			ReadLn;
      Exit;
		end
		// Если опрос выполнился без ошибок
		else
			// Вывод коэффициента усиления по второму каналу АЦП
      WriteLn('Second channel amplifier: ', amplifyADC[1]:12:6);
	end;

	// Опрос веса младшего разряда АЦП первого канала устройства
	Err := ZGetDigitalResolChanADC(typeDevice, numberDSP, 0, resolutionADC[0]);
	// Если опрос выполнился с ошибкой
	if Err <> 0 then
	begin
		// Вывод информации об ошибке
    WriteLn('ZGetDigitalResolChanADC() return Error = 0x', IntToHex(Err, 2));
		// Отключение от драйвера устройства
		Err := ZClose(typeDevice, numberDSP);
		ReadLn;
    Exit;
	end
	// Если опрос выполнился без ошибок
	else
		// Вывод веса младшего разряда АЦП первого канала устройства
    WriteLn('First channel digital resolution: ', resolutionADC[0]:12:6);

	// Если количество каналов устройства больше одного
	if numChannelsADC > 1 then
	begin
		// Опрос веса младшего разряда АЦП второго канала устройства
		Err := ZGetDigitalResolChanADC(typeDevice, numberDSP, 1, resolutionADC[1]);
		// Если опрос выполнился с ошибкой
		if Err <> 0 then
    begin
			// Вывод информации об ошибке
      WriteLn('ZGetDigitalResolChanADC() return Error = 0x', IntToHex(Err, 2));
			// Отключение от драйвера устройства
			Err := ZClose(typeDevice, numberDSP);
			ReadLn;
      Exit;
		end
		else
		  // Вывод веса младшего разряда АЦП второго канала устройства
      WriteLn('Second channel digital resolution: ', resolutionADC[1]:12:6);
	end;

	// Опрос количества включенных каналов АЦП устройства
	Err := ZGetNumberInputADC(typeDevice, numberDSP, numChannelsADC);
	// Если опрос выполнился с ошибкой
	if Err <> 0 then
	begin
		// Вывод информации об ошибке
    WriteLn('ZGetNumberInputADC() return Error = 0x', IntToHex(Err, 2));
		// Отключение от драйвера устройства
		Err := ZClose(typeDevice, numberDSP);
		ReadLn;
    Exit;
	end
	// Если опрос выполнился без ошибок
	else
		// Вывод количества включенных каналов АЦП устройства
    WriteLn('Quantity of activated ADC channel: ', numChannelsADC);

	// Опрос количества слов в одном отсчета АЦП устройства
	Err := ZGetWordsADC(typeDevice, numberDSP, numWordsADC);
	// Если опрос выполнился с ошибкой
	if Err <> 0 then
	begin
		// Вывод информации об ошибке
    WriteLn('ZGetWordsADC() return Error = 0x', IntToHex(Err, 2));
		// Отключение от драйвера устройства
		Err := ZClose(typeDevice, numberDSP);
		ReadLn;
    Exit;
	end
	// Если опрос выполнился без ошибок
	else
		// Вывод количества слов в одном отсчете АЦП устройства
    WriteLn('Quantity of words: ', numWordsADC);

	// Проверка переменных, чтобы избежать деления на ноль
	if(numWordsADC = 0) and (amplifyADC[0] = 0) or (amplifyADC[1] = 0) then
	begin
		// Вывод информации об ошибке
    WriteLn('Error ADC parameters');
		// Отключение от драйвера устройства
		Err := ZClose(typeDevice, numberDSP);
		ReadLn;
    Exit;
	end;

  // Запрос буфера АЦП
	Err := ZGetBufferADC(typeDevice, numberDSP, pBuffer, sizeBufferADC);
	// Если запрос выполнился с ошибкой
	if Err <> 0 then
	begin
		// Вывод информации об ошибке
    WriteLn('ZGetBufferADC() return Error = 0x', IntToHex(Err, 2));
		// Отключение от драйвера устройства
		Err := ZClose(typeDevice, numberDSP);
		ReadLn;
    Exit;
	end;

  // Запрос на останов АЦП
	Err := ZStopADC(typeDevice, numberDSP);
	// Запрос на запуск АЦП
	Err := ZStartADC(typeDevice, numberDSP);

  // Цикл чтения данных АЦП
	while proc do
  begin
    // Задержка обновления данных АЦП для отображения
		Sleep(500);

    // Запрос указателя на текущий элемент буфера
		Err := ZGetPointerADC(typeDevice, numberDSP, pointerADC);
		// Если запрос выполнился с ошибкой
		if Err <> 0 then
		begin
			// Вывод информации об ошибке
      WriteLn('ZGetPointerADC() return Error = 0x', IntToHex(Err, 2));
			// Выход из цикла
			break;
		end;

		// Если новые данные в буфер от АЦП не поступили, то перейти в начало цикла и подождать
		if pointerADC = pointerADC_old then
			continue;

		// Обновление предыдущего значения указателя
		pointerADC_old := pointerADC;

		// Переход на отсчет первого включенного канала последнего кадра АЦП
		if pointerADC - numWordsADC * numChannelsADC < 0 then
			pointerADC := sizeBufferADC + pointerADC - numWordsADC * numChannelsADC
		else
			pointerADC := pointerADC - numWordsADC * numChannelsADC;

		// Вычисление из целого значения отсчета АЦП вещественного значение отсчета (в вольтах) для первого канала
		if numWordsADC = 1 then
    begin
      pBuffer16ADC := pBuffer;
      Inc(pBuffer16ADC, pointerADC);
      CopyMemory(@sample16ADC[0], pBuffer16ADC, 2);
      sampleADC[0] := sample16ADC[0];
    end
		else
    begin
      pBuffer32ADC := pBuffer;
      Inc(pBuffer32ADC, (pointerADC div numWordsADC));
      CopyMemory(@sample32ADC[0], pBuffer32ADC, 4);
      sampleADC[0] := sample32ADC[0];
    end;
    volt[0] := resolutionADC[0] * (sampleADC[0] / amplifyADC[0]);

		// Вывод мгновенного значения напряжения для первого канала
    if numChannelsADC = 1 then
      WriteLn(volt[0]:12:6);

		// Если количество каналов устройства больше одного
		if numChannelsADC > 1 then
		begin
			// Переход на следующий отсчет АЦП
			pointerADC := pointerADC + numWordsADC;

			// При выходе за границу буфера, осуществляется переход в начало
			if pointerADC >= sizeBufferADC then
				pointerADC := pointerADC - sizeBufferADC;

			// Вычисление из целого значения отсчета АЦП вещественного значение отсчета (в вольтах) для второго канала
			if numWordsADC = 1 then
      begin
        pBuffer16ADC := pBuffer;
        Inc(pBuffer16ADC, pointerADC);
        CopyMemory(@sample16ADC[1], pBuffer16ADC, 2);
        sampleADC[1] := sample16ADC[1];
      end
	  	else
      begin
        pBuffer32ADC := pBuffer;
        Inc(pBuffer32ADC, (pointerADC div numWordsADC));
        CopyMemory(@sample32ADC[1], pBuffer32ADC, 4);
        sampleADC[1] := sample32ADC[1];
      end;
	  	volt[1] := resolutionADC[1] * (sampleADC[1] / amplifyADC[1]);

			// Вывод мгновенного значения напряжения для двух каналов
      WriteLn(volt[0]:12:6, '   ', volt[1]:12:6);
		end;
	end;

	// Запрос на останов АЦП
	Err := ZStopADC(typeDevice, numberDSP);
	// Если запрос выполнился с ошибкой
	if Err <> 0 then
  	// Вывод информации об ошибке
    WriteLn('ZStopADC() return Error = 0x', IntToHex(Err, 2));

	// Запрос на освобождение буфера АЦП
	Err := ZRemBufferADC(typeDevice, numberDSP, pBuffer);
 	// Если запрос выполнился с ошибкой
	if Err <> 0 then
	  // Вывод информации об ошибке
    WriteLn('ZRemBufferADC() return Error = 0x', IntToHex(Err, 2));

	// Отключение от драйвера устройства
	Err := ZClose(typeDevice, numberDSP);
	// Если запрос выполнился с ошибкой
	if Err <> 0 then
		// Вывод информации об ошибке
    WriteLn('ZClose() return Error = 0x', IntToHex(Err, 2));

  WriteLn('Press any key for exit...');
  ReadLn;
end.
