// Программа, включающая два канала АЦП устройства и отображающая мгновенное амплитудное значение по двум каналам два раза в секунду
// © ЗАО "ЭТМС" 1992-2011. Все права защищены

#include "stdafx.h"
#include <windows.h> 
#include <conio.h>
#include <stdio.h>

#include "zadc_int.h"						// Интерфейс библиотеки Zadc.dll

#define MAX_TYPE_DSP	20					// Максимальное поддерживаемое количество типов устройств
#define MAX_DEVICE_NAME	16					// Максимальное значение длины возвращаемого имени устройства

int main(int argc, char* argv[])
{
	long typeDevice;						// Тип устройства
	long numberDSP = 0;						// Порядковый номер сигнального процессора
	long Err;								// Код ошибки
	long enable;							// Флаг поддерживается / не поддерживается
	long numChannelsADC;					// Количество включенных каналов АЦП
	long numWordsADC;						// Количество слов (по два байта) в одном отсчете АЦП
	short *pBuffer16ADC = NULL;				// Указатель на начало буфера драйвера для АЦП с разрядностью не более 16 бит
	long *pBuffer32ADC = NULL;				// Указатель на начало буфера драйвера для АЦП с разрядностью более 16 бит 
	long sizeBufferADC;						// Размер буфера драйвера в словах
	long pointerADC = 0;					// Указатель на текущий элемент заполнения буфера драйвера (кратен 2)
	long pointerADC_old = 0;				// Предыдущее значение указателя на буфер драйвера
	double amplifyADC0, amplifyADC1;		// Коэффициент усиления по первым двум каналам 
	double resolutionADC0, resolutionADC1;	// Вес младшего разряда АЦП по первым двум каналам
	double volt0, volt1;					// Мгновенное текущее значение АЦП (в вольтах)
	long serial;							// Серийный номер устройства
	char deviceName[MAX_DEVICE_NAME];		// Имя устройства

	// Цикл подключения к первому поддерживаемому устройству
	for(typeDevice = 0; typeDevice < MAX_TYPE_DSP; typeDevice++)
	{
		// Подключение к драйверу устройства
		Err = ZOpen(typeDevice, numberDSP);
		// Если подключение прошло без ошибок
		if(Err == 0)
		{
			// Проверка поддержки устройством АЦП
			Err = ZGetEnableADC(typeDevice, numberDSP, &enable);
			// Если устройство поддерживает АЦП
			if(Err == 0 && enable != 0)
			{
				// Выход из цикла подключения
				break;
			}
			// Если устройство не поддерживает АЦП
			else
			{
				// Вывод информации об ошибке
				printf("ZGetEnableADC() return Error = 0x%X\n\r", Err);
				// Отключение от драйвера устройства
				Err = ZClose(typeDevice, numberDSP);
			}
		}
	}

	// Если не удалось подключиться к драйверу устройства
	if(typeDevice >= MAX_TYPE_DSP)
	{
		// Вывод информации об ошибке
		printf("Device not found! Error = 0x%X\n\r", Err);
		getch();
		return 0;
	}
	// Если удалось подключиться к драйверу устройства
	else
	{
		// Вывод информации о том, что произошло подключение к драйверу устройства
		printf("Device found...\n\r");
	}

	// Опрос имени устройства
	Err = ZGetNameDevice(typeDevice, numberDSP, deviceName, MAX_DEVICE_NAME);
	// Если опрос выполнился с ошибкой
	if(Err != 0)
	{
		// Вывод информации об ошибке
		printf("ZGetNameDevice() return Error = 0x%X\n\r", Err);
		// Отключение от драйвера устройства
		Err = ZClose(typeDevice, numberDSP);
		getch();
		return 0;
	}
	// Если опрос выполнился без ошибок
	else
	{
		// Вывод имени устройства
		printf("Device name: %s\n\r", deviceName);
	}

	// Опрос серийного номера устройства
	Err = ZGetSerialNumberDSP(typeDevice, numberDSP, &serial);
	// Если опрос выполнился с ошибкой
	if(Err != 0)
	{
		// Вывод информации об ошибке
		printf("ZGetNameDevice() return Error = 0x%X\n\r", Err);
		// Отключение от драйвера устройства
		Err = ZClose(typeDevice, numberDSP);
		getch();
		return 0;
	}
	// Если опрос выполнился без ошибок
	else
	{
		// Вывод серийного номера устройства
		printf("Serial number: %ld\n\r", serial);
	}

	// Опрос колличества каналов АЦП устройства
	Err = ZGetQuantityChannelADC(typeDevice, numberDSP, &numChannelsADC);
	// Если опрос выполнился с ошибкой
	if(Err != 0)
	{
		// Вывод информации об ошибке
		printf("ZGetQuantityChannelADC() return Error = 0x%X\n\r", Err);
		// Отключение от драйвера устройства
		Err = ZClose(typeDevice, numberDSP);
		getch();
		return 0;
	}
	// Если опрос выполнился без ошибок
	else
	{
		// Вывод количества каналов АЦП устройства
		printf("Quantity of ADC channel: %ld\n\r", numChannelsADC);
	}

	// Запрос на включение первого канала АЦП устройства
	Err = ZSetInputADC(typeDevice, numberDSP, 0, 1);
	// Если запрос выполнился с ошибкой
	if(Err != 0)
	{
		// Вывод информации об ошибке
		printf("ZSetInputADC() return Error = 0x%X\n\r", Err);
		// Отключение от драйвера устройства
		Err = ZClose(typeDevice, numberDSP);
		getch();
		return 0;
	}
	// Если запрос выполнился без ошибок
	else
	{
		// Вывод информации об успешном включении первого канала АЦП устройства
		printf("First channel activation is successful...\n\r");
	}
	// Если количество каналов устройства больше одного
	if(numChannelsADC > 1)
	{
		// Запрос на включение второго канала АЦП устройства
		Err = ZSetInputADC(typeDevice, numberDSP, 1, 1);
		// Если запрос выполнился с ошибкой
		if(Err != 0)
		{
			// Вывод информации об ошибке
			printf("ZSetInputADC() return Error = 0x%X\n\r", Err);
			// Отключение от драйвера устройства
			Err = ZClose(typeDevice, numberDSP);
			getch();
			return 0;
		}
		// Если запрос выполнился без ошибок
		else
		{
			// Вывод информации об успешном включении первого канала устройства
			printf("Second channel activation is successful...\n\r");
		}
	}

	// Опрос коэффициента усиления по первому каналу АЦП
	Err = ZGetAmplifyADC(typeDevice, numberDSP, 0, &amplifyADC0);
	// Если опрос выполнился с ошибкой
	if(Err != 0)
	{
		// Вывод информации об ошибке
		printf("ZGetAmplifyADC() return Error = 0x%X\n\r", Err);
		// Отключение от драйвера устройства
		Err = ZClose(typeDevice, numberDSP);
		getch();
		return 0;
	}
	// Если опрос выполнился без ошибок
	else
	{
		// Вывод коэффициента усиления по первому каналу АЦП
		printf("First channel amplifier: %f\n\r", amplifyADC0);
	}
	// Если количество каналов устройства больше одного
	if(numChannelsADC > 1)
	{
		// Опрос коэффициента усиления по второму каналу АЦП
		Err = ZGetAmplifyADC(typeDevice, numberDSP, 1, &amplifyADC1);
		// Если опрос выполнился с ошибкой
		if(Err != 0)
		{
			// Вывод информации об ошибке
			printf("ZGetAmplifyADC() return Error = 0x%X\n\r", Err);
			// Отключение от драйвера устройства
			Err = ZClose(typeDevice, numberDSP);
			getch();
			return 0;
		}
		// Если опрос выполнился без ошибок
		else
		{
			// Вывод коэффициента усиления по второму каналу АЦП
			printf("Second channel amplifier: %f\n\r", amplifyADC1);
		}
	}

	// Опрос веса младшего разряда АЦП первого канала устройства
	Err = ZGetDigitalResolChanADC(typeDevice, numberDSP, 0, &resolutionADC0);
	// Если опрос выполнился с ошибкой
	if(Err != 0)
	{
		// Вывод информации об ошибке
		printf("ZGetDigitalResolChanADC() return Error = 0x%X\n\r", Err);
		// Отключение от драйвера устройства
		Err = ZClose(typeDevice, numberDSP);
		getch();
		return 0;
	}
	// Если опрос выполнился без ошибок
	else
	{
		// Вывод веса младшего разряда АЦП первого канала устройства
		printf("First channel digital resolution: %f\n\r", resolutionADC0);
	}
	// Если количество каналов устройства больше одного
	if(numChannelsADC > 1)
	{
		//  Опрос веса младшего разряда АЦП второго канала устройства
		Err = ZGetDigitalResolChanADC(typeDevice, numberDSP, 1, &resolutionADC1);
		// Если опрос выполнился с ошибкой
		if(Err != 0)
		{
			// Вывод информации об ошибке
			printf("ZGetDigitalResolChanADC() return Error = 0x%X\n\r", Err);
			// Отключение от драйвера устройства
			Err = ZClose(typeDevice, numberDSP);
			getch();
			return 0;
		}
		else
		{
			// Вывод веса младшего разряда АЦП второго канала устройства
			printf("Second channel digital resolution: %f\n\r", resolutionADC1);
		}
	}

	// Опрос количества включенных каналов АЦП устройства
	Err = ZGetNumberInputADC(typeDevice, numberDSP, &numChannelsADC);
	// Если опрос выполнился с ошибкой
	if(Err != 0)
	{
		// Вывод информации об ошибке
		printf("Function ZGetNumberInputADC() return Error = 0x%X\n\r", Err);
		// Отключение от драйвера устройства
		Err = ZClose(typeDevice, numberDSP);
		getch();
		return 0;
	}
	// Если опрос выполнился без ошибок
	else
	{
		// Вывод количества включенных каналов АЦП устройства
		printf("Quantity of activated ADC channel: %ld\n\r", numChannelsADC);
	}

	// Опрос количества слов в одном отсчета АЦП устройства
	Err = ZGetWordsADC(typeDevice, numberDSP, &numWordsADC);
	// Если опрос выполнился с ошибкой
	if(Err != 0)
	{
		// Вывод информации об ошибке
		printf("ZGetWordsADC() return Error = 0x%X\n\r", Err);
		// Отключение от драйвера устройства
		Err = ZClose(typeDevice, numberDSP);
		getch();
		return 0;
	}
	// Если опрос выполнился без ошибок
	else
	{
		// Вывод количества слов в одном отсчете АЦП устройства
		printf("Quantity of words: %ld\n\r", numWordsADC);
	}

	// Проверка переменных, чтобы избежать деления на ноль
	if(numWordsADC == 0 || amplifyADC0 == 0 || amplifyADC1 == 0)
	{
		// Вывод информации об ошибке
		printf("Error DAC parameters\n\r");
		// Отключение от драйвера устройства
		Err = ZClose(typeDevice, numberDSP);
		getch();
		return 0;
	}

	// Запрос буфера АЦП
	Err = ZGetBufferADC(typeDevice, numberDSP, (void**) &pBuffer16ADC, &sizeBufferADC);
	// Если запрос выполнился с ошибкой
	if(Err != 0)
	{
		// Вывод информации об ошибке
		printf("Function ZGetBufferADC() return Error = 0x%X\n\r", Err);
		// Отключение от драйвера устройства
		Err = ZClose(typeDevice, numberDSP);
		getch();
		return 0;
	}
	pBuffer32ADC = (long*) pBuffer16ADC;

	// Запрос на останов АЦП
	Err = ZStopADC(typeDevice, numberDSP);
	// Запрос на запуск АЦП
	Err = ZStartADC(typeDevice, numberDSP);

	// Цикл чтения данных АЦП
	while(!kbhit())
	{
		// Задержка обновления данных АЦП для отображения
		Sleep(500);

		// Запрос указателя на текущий элемент буфера
		Err = ZGetPointerADC(typeDevice, numberDSP, &pointerADC);
		// Если запрос выполнился с ошибкой
		if(Err != 0)
		{
			// Вывод информации об ошибке
			printf("Function ZGetPointerADC() return Error = 0x%X\n\r", Err);
			// Выход из цикла
			break;
		}

		// Если новые данные в буфер от АЦП не поступили, то перейти в начало цикла и подождать
		if(pointerADC == pointerADC_old)
			continue;

		// Обновление предыдущего значения указателя
		pointerADC_old = pointerADC;

		// Переход на отсчет первого включенного канала последнего кадра АЦП
		if(pointerADC - numWordsADC * numChannelsADC < 0)
			pointerADC = sizeBufferADC + pointerADC - numWordsADC * numChannelsADC;
		else 
			pointerADC = pointerADC - numWordsADC * numChannelsADC; 

		// Вычисление из целого значения отсчета АЦП вещественного значение отсчета (в вольтах) для первого канала
		if(numWordsADC == 1)
			volt0 = resolutionADC0 * (pBuffer16ADC[pointerADC]) / amplifyADC0;
		else
			volt0 = resolutionADC0 * (pBuffer32ADC[pointerADC / numWordsADC]) / amplifyADC0;

		// Вывод мгновенного значения напряжения для первого канала
		printf("%+8.4f", volt0);

		// Если количество каналов устройства больше одного
		if(numChannelsADC > 1)
		{
			// Переход на следующий отсчет АЦП
			pointerADC += numWordsADC;
			
			// При выходе за границу буфера, осуществляется переход в начало
			if(pointerADC >= sizeBufferADC)
				pointerADC = pointerADC - sizeBufferADC;

			// Вычисление из целого значения отсчета АЦП вещественного значение отсчета (в вольтах) для второго канала
			if(numWordsADC == 1)
				volt1 = resolutionADC1 * (pBuffer16ADC[pointerADC]) / amplifyADC1;
			else
				volt1 = resolutionADC1 * (pBuffer32ADC[pointerADC/numWordsADC]) / amplifyADC1;

			// Вывод мгновенного значения напряжения для второго канала
			printf("\t%+8.4f", volt1);
		}
		printf("\n\r");
	}

	// Запрос на останов АЦП
	Err = ZStopADC(typeDevice, numberDSP);
	// Если запрос выполнился с ошибкой
	if(Err != 0)
	{
		// Вывод информации об ошибке
		printf("Function ZStopADC() return Error = 0x%X\n\r", Err);
	}

	// Запрос на освобождение буфера АЦП
	if(pBuffer16ADC != NULL)
	{
		Err = ZRemBufferADC(typeDevice, numberDSP, (void**) &pBuffer16ADC);
		// Если запрос выполнился с ошибкой
		if(Err != 0)
		{
			// Вывод информации об ошибке
			printf("Function ZRemBufferADC() return Error = 0x%X\n\r", Err);
		}
	}

	// Отключение от драйвера устройства
	Err = ZClose(typeDevice, numberDSP);
	// Если запрос выполнился с ошибкой
	if(Err != 0)
	{
		// Вывод информации об ошибке
		printf("Function ZClose() return Error = 0x%X\n\r", Err);
	}

	if(!kbhit())
		getch();

	printf("Press any key for exit...");
	getch();

 	return 0;
}
