// Пример, демонстрирующий работу 
// модуля цифрового вывода QMS90 в статическом и в динамическом режимах,
// а также считывание цифровых входов
// В статическом режиме на выходы выводятся числа 0х5555 и 0хАААА.
// В динамическом режиме с заданной частотой выводится натуральный ряд


#include "../../dll/qmx.h"
#include <shellapi.h>
#include <stdio.h>
#include <conio.h> 
#include <math.h>


HANDLE SD;                              // Дескриптор системы
QMX_CONFIG CFG;                         // Конфигурация системы


static unsigned int out_cntr=0;
static unsigned short int *out_buf[2];
static unsigned short int DataOut = 15;

void CheckErr(void);
void quit(void);
void FillBuf(WORD *buf, DWORD len);




//void main(void)
void main(int argc, char* argv[])
{
	char s_wrk[64];
	double CRate;
	WORD Inputs;

	printf("Please wait....\r");
	
	// Запустим сервер
	ShellExecuteW(NULL, TEXT("open"), TEXT("qmbox_ds.exe"), TEXT("-p3"), NULL, SW_SHOWNORMAL);
	Sleep(500);

	// Получим дискриптор системы
	SD = 0;
	SD=QMX_CircBufAttach(0);
	if (SD == NULL) {
		printf("ERROR: No QMBox found.");
		quit(); 
	}

	// Проинициализуем систему
	QMX_InitModules(SD, QMX_LOG_NONE, NULL);
	CheckErr();

	// Фиктивный вызов QMX_Prepare - выясним конфигурацию устройства
	// т.е. из каких модулей оно состоит
	QMX_MOD_SetActive(SD, 0, QMX_ON);
	QMX_Prepare(SD, 100, &CFG);
	CheckErr();
	QMX_MOD_SetActive(SD, 0, QMX_OFF);

	
	// Убедимся, что первый модуль системы - QMS90
	strncpy_s (s_wrk, CFG.ModName[0], 5); s_wrk[5] = 0;
	if (!_stricmp(s_wrk, "QMS90"))	printf("Module name OK\n");
	else{ printf("Module Name error\n");	quit();	}


	// Разрешим цифровые выходы (выведем их из третьего состояния)
	QMX_QMS90_QMS92_OutputEnable(SD, 0, QMX_ON);


	// Запишем в цифровые выходы число 0х5555
	QMX_QMS90_QMS92_SetOutputs(SD, 0, 0x5555);

	// Считаем состояние цифровых входов и отобразим
	QMX_QMS90_QMS92_GetInputs(SD, 0, &Inputs);
	printf("Data: 0x%X%\n", Inputs);

	// Запишем в цифровые выходы число 0хАААА	
	QMX_QMS90_QMS92_SetOutputs(SD, 0, 0xAAAA);

	// Считаем состояние цифровых входов и отобразим
	QMX_QMS90_QMS92_GetInputs(SD, 0, &Inputs);
	printf("Data: 0x%X%\n", Inputs);



	// Определим нужные указатели для динамического вывода
	out_buf[0]=(WORD *)CFG.CBOutput.buf_start;								// указатель на первую половину буфера вывода
	out_buf[1]=(WORD *)(CFG.CBOutput.buf_start+(*CFG.CBOutput.buf_size>>1));	// указатель на вторую половину буфера вывода


	// Установим частоту работы QMS90, в Гц
	QMX_QMS90_QMS92_SetRate(SD, 0, 6000000.0, &CRate);
	printf("Output Rate = %8.2f Hz \n", CRate);
	

	// Теперь осуществим предварительную заливку буфера модуля
	// для того, чтобы к моменту "Старта" в его локальном буфере уже были наготове нужные данные
	QMX_MOD_SetActive(SD, 0, QMX_ON);	// Для этого он объявляется активным
	QMX_Prepare(SD, 0, &CFG);			// После этого обязательно вызвать QMX_Prepare
	CheckErr();							// Проверка, что всё ОК
	FillBuf(out_buf[0], *CFG.CBOutput.buf_size);		// Заполняем весь буфер вывода (обе половины) нужными данными
	QMX_MOD_OutputPrestage(SD, 0);						// Заливаем этот буфер в модуль


//	QMX_MOD_SetStartMode(SD, 0xFF, QMX_START_MODE_EXTERNAL);
	
	// Запустим сеанс сбора данных - дадим "Старт"
	QMX_Start(SD);
	CheckErr();


	while(!_kbhit()){													// Бесконечный цикл (до нажатия кнопки)				
	  if(out_cntr<*CFG.CBOutput.buf_ptr) {								// Если в сервере есть свободный буфер для отправки						
		   FillBuf(out_buf[out_cntr++&1], (*CFG.CBOutput.buf_size)>>1); // Заполним его очередной порцией данных
		   QMX_CircBufOutputUpdate(SD);									// И дадим команду серверу на отправку
		   printf("Write Counter: %3u\r", out_cntr);	// Отобразим счетчик отправленных половинок буферов
	  }
	  Sleep(10);
	}


	QMX_Stop(SD, QMX_STOP_ALL);			// Остановим систему

	// Переведем цифровые выходы в третье состояние
	QMX_QMS90_QMS92_OutputEnable(SD, 0, QMX_OFF);

	quit();											// выход из программы
}


// Выход из программы
void quit(void){
	
	printf("\n\n Please wait....\r");
	QMX_Stop(SD, QMX_STOP_ALL);			// Остановим систему
	QMX_MOD_SetStartMode(SD, 0xFF, QMX_START_MODE_MANUAL); 									
	
	QMX_CircBufDetach(SD);              // Освободим виртуальный слот USB
										// Остановим сервер
	ShellExecute(NULL, TEXT("open"), TEXT("qmbox_ds.exe"), TEXT("-s0"), NULL, SW_SHOWNORMAL);
	printf("\n\n");
	ExitProcess(0);
}


// Проверка на ошибки
void CheckErr(void) {
char tmp_str[1024];

if (QMX_GetLastError(SD, tmp_str, sizeof(tmp_str))==QMX_OK){ return;}
else  {	printf("%s\n", tmp_str);	quit();}
}



// Заполнение очередной порции данных для динамического вывода
void FillBuf(WORD *buf, DWORD len) {

DWORD i;
 
  for(i=0; i<len; i++) *buf++=(WORD)(DataOut++);
}




