/*
The I-8014W contains two types of Magic Scan . One is type 1: standard (each sample clock only samples a single. ) 
and Type 2: virtual Sample and hold (each sample clock will to sample all scan channels that have been set. )
Both of two types can set as polling Mode,Internal Hardware trigger Mode and External Hardware trigger Mode
This Demo will show you how to use Magic Scan ,step by step

Step1: 
    ret=i8014W_Init(slot); , this function will check hardware ID, 
	if retrun code ret is -1 means this slot may empty or wrong I/O (not I-8014W) 
	,return 0 this slot is I-8014W 	
	
Step2: 
    i8014W_ConfigMagicScan( slot, chArr, gainArr, scanChCount, sampleRate, scanMode, triggerSource, triggerState , & realsampleRate);
    for Configure Magic Scan Parameters and return real sample rate that used by I-8014 module	

Step3:
	i8014W_StartMagicScan(int slot);
	to start Magic Scan function 
	(If i8014W_ConfigMagicScan use external trigger signal mode , module will not start to save data .
	It will start to scan data when the signal is active) 
	
Step4:
    Send a external trigger signal for I-8014 module to Start magic scan 
    (external trigger signal Mode only)

Step5:
	to read the data from FIFO in main loop
    i8014W_ReadFIFO(int slot, short hexData[], short readCount,short* dataCountFromFIFO);
    
Step6:
	i8014W_StopMagicScan( slot);
	stop Magic Scan function 

Step7:
	to show calibrated analog data.
	When we use Magic scan to read data from FIFO ,the analog data is not calibrated 
	We can use following function to get the calibrated data.
	void i8014W_CalibrateDataHex(int slot, short iGain,short dataFromFIFO, short* calibratedAI);
	void i8014W_CalibrateData(int slot, short iGain,short dataFromFIFO, float* calibratedAI);
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include "msw.h"
#include "i8014W.h"
//#define MAX_FIFO	1024
short jumper;
short TargetCnt=100;
unsigned long T1,T2; 
short rawData[8192];
int slot, chArr[16], gainArr[16], scanChCount=0, runFlag=1, showCnt=0;
int scanMode=0, triggerSource=-1, triggerState;
float realsampleRate, sampleRate=0;
short hexData[8192];
short ret_fifo=0, totalScanned=0;
char GainStr[5][32]={"+/-10V","+/-5V","+/-2.5V","+/-1.25V","+/-20mA"};
char ModeStr[2][32]={"Standard Mode", "Sample and Hold Mode"};
char SourceStr[3][32]={"Software Command", "Internal Interrupt Signal","External Trigger Signal"};
char StateStr[2][32]={"High","Low"};
void ShowAI(void);

int main()
{
	int ret_init, RetValue, ch, maxCh ;
	short i, readFromFIFO=0;
	char sTemp[20],c;               
	long readCnt=0 ;	      
 
	printf("This Demo will show how to use magic scan function to read analog input\n");
	printf("\nWhich slot does I-8014W plut in?...  ");
	scanf("%d", &slot);
	printf("\n");
	if ((slot<0)&&(slot>8)){
		return FAILURE;
	}
		
	RetValue = Open_Slot(slot);
	if (RetValue >0) {
		printf("open Slot %d failed!\n",slot);
		return FAILURE;
	}
	else
	{ 
		if (i8014W_Init(slot) != -1)
			printf("\t There is an I-8014W at slot %d\n",slot);
		else
		{
			printf("Init I-8014W at slot %d failure!\n",slot);
			return FAILURE;
		}
	}
  /**/
	jumper= i8014W_GetSingleEndJumper(slot);
	if(jumper)
	{
		maxCh=16;
		printf("\t I-8014W Input Mode=Single-End and can have maximum 16 analog input\n\r");
	}
	else
	{
    		maxCh=8;
		printf("\t I-8014W Input Mode=Differential and can have maximum 8 analog input\n\r");
	}
    
	// define the sampling channels array chArr[] 
	// Differential Mode: element for chArr[] range from channel 0 ~ 7 ,
	// Single ended Mode: element for chArr[] range from channel 0 ~ 15 
	// max element counts for chArr[] can be 16 
	// define gain type array for each channel		
	// gainArr[] element for gainArr[] range from channel 0 ~ 15
	// Gain value : 0="+/-10V",1="+/-5V",2="+/-2.5V",3="+/-1.25V",4="+/-20mA" 
	// max element counts for gainArr[] can be 16 
start:	
		
	printf ("\n\n Input all i8014W_ConfigMagicScan parameters :\n");
	printf("\n Step 1: Define scaned channel counts for magic scan:");   

	while ((scanChCount <1)||(scanChCount >16))
	{ 
		printf("\n Input scaned channel counts (1~16) :"); 
		scanf("%d",&scanChCount);
	}
  
	printf(" Now we have scaned channel counts = %d\n\n",scanChCount);
	printf(" Gain: 0)+/-10V   1)+/-5V   2)+/-2.5V   3)+/-1.25V   4)+/-20mA\n");
	printf("\n Step 2: Define %d elements for channel and gain array",scanChCount);
	printf("\n The Gain definition of I-8014W");

	for(i=0;i<5;i++)
	{
		printf ("\n\t Select %d :  %s",i,GainStr[i]);
	}
	printf("\n\r");
        
	if(maxCh==8) // Differential Mode 
     		printf("\n Differential Mode range : channel 0 ~ 7\n\r");
	else
		printf("\n Single ended Mode range : channel 0 ~ 15\n\r");

	for(i=0;i<scanChCount;i++)
	{
		printf(" Select which Channel of Arr[%d] (0~%d) :",i,maxCh-1);
		scanf("%d",&chArr[i]);
		printf(" Select which Gain of Arr[%d](0~4):",i);
		scanf("%d",&gainArr[i]);   	
	}

	// Sample channel counts
	// scanChCount can be 1 ~ 16 (max =16 for both Differential and Single Ended)
	printf("\n\n Step 3: Define Sample Rate of I-8014W\n");
	printf(" Note: the real sample rate may not the same as user input");
	printf("\n      the function i8014W_ConfigMagicScan return code is the \n      real sample rate accepted by I-8014W\n");

	while((sampleRate <2)||(sampleRate >250000)) // Sample rate : 2 ~ 250KHz  
	{ 
		printf(" Input Sample rate of 8014W (2~250000) :");
		scanf("%f",&sampleRate);
	} 
	printf(" sampleRate=%f \n", sampleRate);  

	// Scan Mode = 1 M1 standard mode, Each Sample clock only samples a single channel
	// Scan Mode = 2 M2 Sample and hold Mode
	printf("\n\n Step 4:Select Scan Mode of I-8014W:\n");
	printf("\t Scan Mode 1= M1 Standart Mode \n\t Scan Mode 2= M2 Sample and Hold Mode \n\r");

	while((scanMode <1)||(scanMode >2))
	{ 
		printf(" Input Scan Mode of I-8014W (1 or 2) :");
		scanf("%d",&scanMode);
	} 
    
	// trigger source 0, start magic scan via polling Mode, software command can only trigger one slot I-8014
	// trigger source 1, start magic scan via internal interrupt signal Mode, internal interrupt signal can trigger all I-8014Ws on slots at the same time.
	// trigger source 2, start magic scan via external trigger signal Mode, extern trigger can also trigger all I-8014Ws on slots at the same time.

	printf("\n\n Step 5: Select Trigger Source of I-8014W,\n I-8014W can have 3 types of trigger source \n");
	printf("\t trigger source 0= Software Command \n\t trigger source 1= Internal Interrupt Signal \n\t trigger source 2= External Tigger Signal\n\r");

	while((triggerSource <0)||(triggerSource >2))
	{ 
		printf(" Input trigger source of I-8014W (0 to 2) :");
		scanf("%d",&triggerSource);  
	} 

	// triggerState only related with external DI trigger signal.
	// if triggerState 0, external DI trigger signal must be high to start magic scan (default)
	// if triggerState 1, external DI trigger signal must be low to start magic scan

	printf("\n\n Step6: Select Trigger State of I-8014W if select external trigger source.\n");
	if(triggerSource==2)
	{	    
		printf("\t trigger State 0= external trigger singal high to start magic scan \n\t trigger State 1= external trigger signal low to start magic scan\n\r");
		printf(" Input trigger State of I-8014W (0 or 1) :");
		scanf("%d",&triggerState);  
	}
	else
	{
		printf("\t Not external trigger source, trigger state =0 \n");
		triggerState=0;
	}

	// When Configure Sample Rate of Magic Scan, the result sample rate may be different from input sample rate 
	// Note i8014W_ConfigMagicScan only tell I-8014W how to start magic scan,it will not start magic scan
	// We have to call i8014W_StartMagicScan to start up the magic scan.
	
	i8014W_ConfigMagicScan(slot,chArr,gainArr,scanChCount, sampleRate, scanMode,triggerSource,triggerState, &realsampleRate);	

	printf("\n\nThe Magic Scan Configurations of I-8014W are:\n");
	printf("\t Scan channel count = %d\n", scanChCount);

	for(i=0;i<scanChCount;i++)
	{
		printf("\t CH[%d]= %d\t Gain[%d]= %d ( %s )\n",i, chArr[i],i, gainArr[i], GainStr[gainArr[i]]);
	}
	printf("\t Scan Mode = %d ( %s )\n", scanMode, ModeStr[scanMode-1]);
	printf("\t Trigger Source = %d ( %s )\n", triggerSource, SourceStr[triggerSource]);

	if(triggerSource==2)
		printf("\t Trigger State = %d ( %s )\n", triggerState, StateStr[triggerState]);
	else
		printf("\t Trigger State = %d ( No need for External Trigger Signal )\n",triggerState);

	printf("\t Set Sample Rate = %f  Real Sample Rate = %f \n",sampleRate, realsampleRate);
	printf("Start magic scan...\n\r");

	//Send external trigger for I-8014W module
	if(triggerSource==2)
		printf("Wait for external trigger signal source to %s ....\n", StateStr[triggerState]);
	else
		printf("Wait for Magic Scan .....\n");

	//usleep(100);
	i8014W_StartMagicScan(slot);
	totalScanned=0;	  
	runFlag=1;		
	T1=GetTimeTicks_ms();   

	// i8014W_ReadFIFO is a non block API function
	// readFromFIFO means the data count read from FIFO for each i8014W_ReadFIFO read action
	// It is better to run this demo with low frequency(for example 10Hz) then we can know how this function works.
	ret_fifo= i8014W_ReadFIFO_BlockMode(slot,rawData, TargetCnt ,&readCnt);
	i8014W_StopMagicScan(slot); 
	T2 = GetTimeTicks_ms()-T1;
	printf("Magic scan total spend time = %lu ms  \n\n",T2); 

	if(ret_fifo==FIFO_LATCHED )
	{    	    
		printf("Magic Scan FIFO Latched, Sample Rate too high, try to use Lower Sample Rate\n");
		i8014W_UnLockFIFO(slot);
		i8014W_ClearFIFO(slot);
		goto start;
 	}
   	 
	if(readCnt>0)
	{
		if(TargetCnt != readCnt)
		{
			printf("Magic Scan Block Mode Error, TargetCnt %d must be the same as readCnt %ld\n",TargetCnt, readCnt);
			printf("try again \n");
			goto start;
		}
		totalScanned = readCnt;
	}

	printf("\r\nPress 's' or 'S' to Show AI, others to next step\n\r");
	scanf("%s",&c);
	if(c=='s' || c=='S')
		ShowAI();
		
	printf("Press 'q' or 'Q' to exit program, others to Start magic scan again!\n \r");
	scanf("%s",&c);
	if(c!='q' && c!='Q'){
		scanChCount=0;
		sampleRate=0;
		scanMode=0;
		triggerSource=-1;
		goto start;  // continue another test
	}
	Close_Slot(slot);
	return SUCCESS;
}

void ShowAI(void)
{
	int i;
	float calibratedAI=0;
	printf("Start to printf all data:\n\n\r");
	 
	for(i=0;i<totalScanned;i++)
	{ 	
		i8014W_CalibrateData(slot, gainArr[i %scanChCount],rawData[i],&calibratedAI);
		printf("i=%d: Arr[%d]= F[%f]\t",i, i%scanChCount, calibratedAI);
		if(i % 3 == 2)
			printf("\n");
	}
	printf("\n---------\n");
}
