/* CIN source file */

#include "extcode.h"
#include <windows.h>
#include <stdio.h>
#include "..\..\..\Include\wrRtusbapi.h"

/* Typedefs */

typedef struct {
	int32 dimSize;
	int16 BufferEl[1];
	} TD4;
typedef TD4 **TD4Hdl;

typedef struct {
	TD4Hdl Buffer;
	uInt32 ReadOv;
	uInt32 ReadEvent;
	} TD3;

typedef struct {
	int32 dimSize;
	TD3 ReadBufferPars[1];
	} TD2;
typedef TD2 **TD2Hdl;

typedef struct {
	TD4Hdl Buffer;
	uInt32 WriteOv;
	uInt32 WriteEvent;
	} TD6;

typedef struct {
	int32 dimSize;
	TD6 WriteBufferPars[1];
	} TD5;
typedef TD5 **TD5Hdl;

typedef struct {
	uInt32 DllVersion;
	uInt32 InterfaceType;
	uInt32 InterfaceInstance;
	uInt32 ModuleHandle;
	TD2Hdl ReadBuffersParsArray;
	TD5Hdl WriteBuffersParsArray;
	} TD1;

typedef struct {
	int32 dimSize;
	uInt16 LogicalChannel[1];
	} TD8;
typedef TD8 **TD8Hdl;

typedef struct {
	int32 dimSize;
	float64 AdcOffsetCoef[1];
	} TD9;
typedef TD9 **TD9Hdl;

typedef struct {
	int32 dimSize;
	float64 AdcScaleCoef[1];
	} TD10;
typedef TD10 **TD10Hdl;

typedef struct {
	int32 dimSize;
	uInt32 BufferLength[1];
	} TD11;
typedef TD11 **TD11Hdl;

typedef struct {
	uInt16 size;
	LVBoolean InputEnabled;
	LVBoolean CorrectionEnabled;
	uInt16 InputClockSource;
	uInt16 InputType;
	uInt16 SynchroType;
	uInt16 SynchroAdType;
	uInt16 SynchroAdMode;
	uInt16 SynchroAdChannel;
	int16 SynchroAdPorog;
	uInt16 ChannelsQuantity;
	TD8Hdl ControlTable;
	uInt16 InputFifoBaseAddress;
	uInt16 InputFifoLength;
	float64 InputRate;
	float64 InterKadrDelay;
	float64 ChannelRate;
	TD9Hdl AdcOffsetCoefArray;
	TD10Hdl AdcScaleCoefArray;
	TD11Hdl BuffersLengthArray;
	} TD7;

typedef struct {
	LVBoolean Status;
	uInt32 ViErrorNumber;
	LStrHandle ViName;
	LStrHandle ViErrorString;
	LStrHandle CinName;
	LStrHandle CinErrorString;
	} TD12;

#define CONTROL_TABLE_LENGTH			(128)
#define ADC_OFFSET_COEF_QUANTITY		(0x8)
#define ADC_SCALE_COEF_QUANTITY			(0x8)

enum {UNKNOWN_MODULE, USB2185_MODULE, USB3000_MODULE};

// объявления функций
CIN MgErr CINRun(TD1 *InterfaceInfo, TD7 *InputPars, TD12 *ViStatus);
CIN MgErr CINProperties(int32 prop, void *data);

// ---------------------------------------------------------------
// 
// ---------------------------------------------------------------
MgErr CINRun(TD1 *InterfaceInfo, TD7 *InputPars, TD12 *ViStatus)
{
	uInt16 i;
	// структура параметров ввода данных
	INPUT_PARS_USB3000 ip;
	// указатель на интерфейс модуля
	LPVOID pModule;
	// ошибка подпрограмм LabVIEW
	MgErr Error;

	// посмотрим была ли ошибка в предыдущих CIN		
	if(ViStatus->Status == LVFALSE) return noErr;

	// указатель на интерфейс модуля
	pModule = (LPVOID)InterfaceInfo->InterfaceInstance;

	// с каким модулем работаем?
	if(InterfaceInfo->InterfaceType == USB3000_MODULE)
	{
		// существует ли готовый интерфейс с модулем USB3000?
		if(pModule != NULL)
		{
			// уже выделено место под управляющую таблицу модуля?
			if((*InputPars->ControlTable)->dimSize != CONTROL_TABLE_LENGTH)
			{
				Error = NumericArrayResize(uW, 1L, (UHandle*)&InputPars->ControlTable, CONTROL_TABLE_LENGTH);
				if(Error != noErr) { ViStatus->Status= LVFALSE; return Error; }
				(*InputPars->ControlTable)->dimSize = CONTROL_TABLE_LENGTH;
			}
			// уже выделено место под калибровочные коэф. смещения нуля?
			if((*InputPars->AdcOffsetCoefArray)->dimSize != ADC_OFFSET_COEF_QUANTITY)
			{
				Error = NumericArrayResize(fD, 1L, (UHandle*)&InputPars->AdcOffsetCoefArray, ADC_OFFSET_COEF_QUANTITY);
				if(Error != noErr) { ViStatus->Status= LVFALSE; return Error; }
				(*InputPars->AdcOffsetCoefArray)->dimSize = ADC_OFFSET_COEF_QUANTITY;
			}
			// уже выделено место под калибровочные коэф. масштаба?
			if((*InputPars->AdcScaleCoefArray)->dimSize != ADC_SCALE_COEF_QUANTITY)
			{
				Error = NumericArrayResize(fD, 1L, (UHandle*)&InputPars->AdcScaleCoefArray, ADC_SCALE_COEF_QUANTITY);
				if(Error != noErr) { ViStatus->Status= LVFALSE; return Error; }
				(*InputPars->AdcScaleCoefArray)->dimSize = ADC_SCALE_COEF_QUANTITY;
			}


			// обязательно проинициализируем поле size структуры RTUSB3000::INPUT_PARS
			ip.size = sizeof(INPUT_PARS_USB3000);
			// получим текущие параметры работы АЦП
			if(!GET_INPUT_PARS_Usb3000(pModule, &ip))
			{
				ViStatus->Status= LVFALSE; return noErr;
			}

			// размер структуры с параметрами ввода данных
			InputPars->size = sizeof(TD2);
			// флажок разрешение/запрещение ввода данных (только при чтении)
			if(ip.InputEnabled) InputPars->InputEnabled = LVTRUE;
			else InputPars->InputEnabled = LVFALSE;
			// управление корректировкой входных данных (с АЦП)
			if(ip.CorrectionEnabled) InputPars->CorrectionEnabled = LVTRUE;
			else InputPars->CorrectionEnabled = LVFALSE;
			// определимся с источником тактовых испульсов для ввода данных
			InputPars->InputClockSource = ip.InputClockSource;
			// тип вводимых с модуля даных (АЦП или ТТЛ)
			InputPars->InputType = ip.InputType;
			// тип синхронизации вводимых с модуля даных
			InputPars->SynchroType = ip.SynchroType;
			// тип аналоговой синхронизации
			InputPars->SynchroAdType = ip.SynchroAdType;
			// режим аналоговой сихронизации
			InputPars->SynchroAdMode = ip.SynchroAdMode;
			// синхроканал АЦП при аналоговой синхронизации
			InputPars->SynchroAdChannel = ip.SynchroAdChannel;
			// порог срабатывания АЦП при аналоговой синхронизации
			InputPars->SynchroAdPorog = ip.SynchroAdPorog;
			// число активных логических каналов
			InputPars->ChannelsQuantity = ip.ChannelsQuantity;
			// управляющая таблица с активными логическими каналами
			for(i = 0x0; i < InputPars->ChannelsQuantity; i++)
				(*InputPars->ControlTable)->LogicalChannel[i] = ip.ControlTable[i];
			// базовый адрес FIFO буфера ввода в DSP модуля
			InputPars->InputFifoBaseAddress = ip.InputFifoBaseAddress;
			// длина FIFO буфера ввода в DSP модуля
			InputPars->InputFifoLength = ip.InputFifoLength;
			// тактовая частота ввода данных в кГц
			InputPars->InputRate = ip.InputRate;
			// межкадровая задержка в мс
			InputPars->InterKadrDelay = ip.InterKadrDelay;
			// частота ввода фиксированного логического канала
			InputPars->ChannelRate = ip.ChannelRate;
			// корректировочные коэф. смещение нуля для АЦП
			for(i = 0x0; i < ADC_OFFSET_COEF_QUANTITY; i++)
				(*InputPars->AdcOffsetCoefArray)->AdcOffsetCoef[i]= ip.AdcOffsetCoef[i];
			// корректировочные коэф. масштаба для АЦП
			for(i = 0x0; i < ADC_SCALE_COEF_QUANTITY; i++)
				(*InputPars->AdcScaleCoefArray)->AdcScaleCoef[i]= ip.AdcScaleCoef[i];
		}       
		else
		{
			ViStatus->Status= LVFALSE;
		}
	}
	else 
	{ 
		ViStatus->Status= LVFALSE; 
	}

	return noErr;
}

// ---------------------------------------------------------------
// заявляем, что данный CIN - потокобезопасный
// ---------------------------------------------------------------
CIN MgErr CINProperties(int32 prop, void *data)
{
	switch (prop) 
	{
		case kCINIsReentrant:
			*(Bool32 *)data = TRUE;
			return noErr;
	}
	return mgNotSupported;
}
