// Test_Zadc.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h> 
#include <conio.h>
#include <stdio.h>
#include "zadc_int.h" // Интерфейс библиотеки Zadc.dll


// Программа включающая два канала АЦП и отображающая мгновенное амплитудное значение
// по двум каналам 2 раза в секунду

int main(int argc, char* argv[])
{
	HINSTANCE dllHandle = NULL;
	long typeDevice;					// Тип устройства
	long numberDSP;						// Порядковый номер устройства
	long err;							// Код ошибки
	long numChannelsADC;				// Кол-во включенных каналов АЦП
	long numWordsADC;					// Кол-во слов (по два байта) в одном отсчете АЦП
	void *pBuffer;						// Указатель на начало буфера драйвера типа void
	short *pBuffer16ADC;				// Указатель на начало буфера драйвера для АЦП с разрядностью не более 16 бит
	long *pBuffer32ADC;					// Указатель на начало буфера драйвера для АЦП с разрядностью более 16 бит 
	long sizeBufferADC;					// Размер буфера драйвера в словах
	long pointerADC;					// Указатель на текущий элемент заполнения буфера драйвера (кратен 2)
	long pointerADC_old;				// Предыдущее значение указателя на буфер драйвера
	double amplifyADC0, amplifyADC1;	// Коэф. усиления по первым двум каналам 
	double resolutionADC;				// Вес младшего разряда АЦП
	double volt0, volt1;				// Мгновенное текущее значение АЦП (в Вольтах)
	
	typeDevice = KDU1616;		// Здесь для примера выбрано устройство ADC 1616 Sigma USB
	numberDSP = 0;				// Порядковый номер DSP


	// Подключиться к библиотеке для работы с АЦП/ЦАП
	dllHandle = LoadLibrary("zadc.dll");

	// Если подключиться не удалось - выйти
	if (dllHandle == NULL) 
	{ 
		printf(" Not find zadc.dll!/n/r");
		getch();
		return 0;
	}

	// подключиться к драйверу (обязательно)
	err = ZOpen(typeDevice, numberDSP);
	if(err != 0)
	{
		printf("Device not found! Error = 0x%X\n\r", err);
		getch();
		return 0;
	}
	else
		printf("Device found...\n\r");

	// включить первый канал АЦП
	err = ZSetInputADC(typeDevice, numberDSP, 0, 1);
	if(err != 0)
	{
		printf("ZSetInputADC() return Error = 0x%X\n\r", err);
		getch();
		return 0;
	}

	// включить второй канал АЦП
	err = ZSetInputADC(typeDevice, numberDSP, 1, 1);
	if(err != 0)
	{
		printf("ZSetInputADC() return Error = 0x%X\n\r", err);
		getch();
		return 0;
	}

	// опросить коэф. усиления по первому каналу АЦП
	err = ZGetAmplifyADC(typeDevice, numberDSP, 0, &amplifyADC0);
	if(err != 0)
	{
		printf("ZGetAmplifyADC() return Error = 0x%X\n\r", err);
		getch();
		return 0;
	}

	// опросить коэф. усиления по второму каналу АЦП
	err = ZGetAmplifyADC(typeDevice, numberDSP, 1, &amplifyADC1);
	if(err != 0)
	{
		printf("ZGetAmplifyADC() return Error = 0x%X\n\r", err);
		getch();
		return 0;
	}

	// опросить вес младшего разряда АЦП
	err = ZGetDigitalResolutionADC(typeDevice, 0, &resolutionADC);
	if(err != 0)
	{
		printf("ZGetDigitalResolutionADC() return Error = 0x%X\n\r", err);
		getch();
		return 0;
	}

	// опросить кол-во включенных каналов АЦП
	err = ZGetNumberInputADC(typeDevice, numberDSP, &numChannelsADC);
	if(err != 0)
	{
		printf("Function ZGetNumberInputADC() return Error = 0x%X\n\r", err);
		getch();
		return 0;
	}

	// опросить кол-во слов в одном отсчете АЦП
	err = ZGetWordsADC(typeDevice, 0, &numWordsADC);
	if(err != 0)
	{
		printf("ZGetWordsADC() return Error = 0x%X\n\r", err);
		getch();
		return 0;
	}

	// Проверка переменных, чтобы избежать деления на 0
	if(numWordsADC == 0 || amplifyADC0 == 0 || amplifyADC1 == 0)
	{
		printf("Ошибочные значения параметров АЦП\n\r");
		getch();
		return 0;
	}

	// запросить буфер АЦП
	err = ZGetBufferADC(typeDevice, numberDSP, &pBuffer, &sizeBufferADC);
	if(err != 0)
	{
		printf("Function ZGetBufferADC() return Error = 0x%X\n\r", err);
		getch();
		return 0;
	}

	// Проинициализировать локальные указатели для конкретных типов данных
	pBuffer16ADC = (short*) pBuffer;
	pBuffer32ADC = (long*) pBuffer;

	// запуск АЦП
	err = ZStartADC(typeDevice, numberDSP);
	if(err != 0)
		printf("Function ZStartADC() return Error = 0x%X\n\r", err);


	//ожидание накопления 100 000 точек
	pointerADC_old = 0;
	int i;
	short dataADC0[10000];//первый канал
	short dataADC1[10000];//второй канал
	short dataADC2[10000];//третий канал
	while(1)
	{
		err = ZGetPointerADC(typeDevice, numberDSP, &pointerADC);
		if((pointerADC-pointerADC_old)>100000*numChannelsADC)
		{
			err = ZStopADC(typeDevice, numberDSP);
			if(err != 0)
				printf("Function ZStopADC() return Error = 0x%X\n\r", err);
			for(i = 0; i < 10000; i++)
			{
				dataADC0[i] = pBuffer16ADC[i*numChannelsADC+0];// для  канала
				dataADC1[i] = pBuffer16ADC[i*numChannelsADC+1];// для второго канала
				dataADC2[i] = pBuffer16ADC[i*numChannelsADC+2];// для третьего канала
			}
			break;
		}

	}

	err = ZStartADC(typeDevice, numberDSP);
	if(err != 0)
		printf("Function ZStartADC() return Error = 0x%X\n\r", err);

	// Цикл чтения данных АЦП
	pointerADC_old = 0;
	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 = resolutionADC * (pBuffer16ADC[pointerADC]) / amplifyADC0;
		else
			volt0 = resolutionADC * (pBuffer32ADC[pointerADC/numWordsADC]) / amplifyADC0;

		// отобразить мгновенное значение напряжения для первого канала
		printf("%+8.4f", volt0);

		// если включено более одного канала АЦП, то сделать то же самое для второго канала
		if(numChannelsADC > 1)
		{
			// перейти на следующий отсчет АЦП
			pointerADC += numWordsADC;
			
			// если вышли за границу буфера, то перейти в начало
			if(pointerADC >= sizeBufferADC)
				pointerADC = pointerADC - sizeBufferADC;

			if(numWordsADC == 1)
				volt1 = resolutionADC * (pBuffer16ADC[pointerADC]) / amplifyADC1;
			else
				volt1 = resolutionADC * (pBuffer32ADC[pointerADC/numWordsADC]) / amplifyADC1;

			// отобразить мгновенное значение напряжения для второго канала
			printf("	%+8.4f", volt1);
		}
		printf("\n\r");
	}

	// останов АЦП
	err = ZStopADC(typeDevice, numberDSP);
	if(err != 0)
		printf("Function ZStopADC() return Error = 0x%X\n\r", err);

	// освободить буфер АЦП
	err = ZRemBufferADC(typeDevice, numberDSP, &pBuffer);
	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);


	// Отключиться от библиотеки для работы с АЦП/ЦАП
	FreeLibrary(dllHandle);
	
	if(!kbhit())
		getch();
	printf("Press any key for exit...");
	getch();

 	return 0;
}
