/* The I-9014 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=i9014_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-9014) 
	,return 0 this slot is I-9014 	
	
Step2: 
    i9014_ConfigMagicScan( slot, chArr, gainArr, scanChCount, sampleRate, scanMode, triggerSource, triggerState , & realsampleRate);
    for Configure Magic Scan Parameters and return real sample rate that used by I-9014 module	

Step3:
	i9014_StartMagicScan(int slot);
	to start Magic Scan function 
	(If i9014_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-9014 module to Start magic scan 
    (external trigger signal Mode only)

Step5:
	to read the data from FIFO in main loop
    i9014_ReadFIFO(int slot, short hexData[], short readCount,short* dataCountFromFIFO);
    
Step6:
	i9014_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 i9014_CalibrateDataHex(int slot, short iGain,short dataFromFIFO, short* calibratedAI);
	void i9014_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"*/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.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, 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", "Virtual Sample and Hold Mode"};
char SourceStr[3][36]={"Software Command", "Internal Hardware Trigger Signal","External Hardware Trigger Signal"};
char StateStr[2][32]={"High","Low"};
void ShowAI(void);

int main()
{
	int ret_init, RetValue, ch, maxCh ;
	short i, readFromFIFO=0;
	char 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-9014 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 (i9014_Init(slot) != -1)
			printf("\t There is an I-9014 at slot %d\n",slot);
		else {
			printf("Init I-9014 at slot %d failure!\n",slot);
			return FAILURE;
		}
	}
  
	jumper= i9014_GetSingleEndJumper(slot);
	if(jumper)
	{
		maxCh=16;
		printf("\t I-9014 Input Mode=Single-End and can have maximum 16 analog input\n\r");
	}
	else
	{
		maxCh=8;
		printf("\t I-9014 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 Input all i9014_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 to %d) :",maxCh); 
		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-9014");
	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 Step 3: Define Sample Rate of I-9014\n");
	printf(" Note: the real sample rate may not the same as user input");
	printf("\n      the function i9014_ConfigMagicScan return code is the \n      real sample rate accepted by I-9014\n");
	while ((sampleRate <2)||(sampleRate >2500000)) // Sample rate : 2 ~ 250KHz  
	{ 
		printf (" Input Sample rate of 9014 (2~2500000) :");
		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 Virtual Sample and hold Mode
	printf ("\n Step 4:Select Scan Mode of I-9014:\n");
	printf ("\t Scan Mode 1= M1 Standart Mode \n\t Scan Mode 2= M2 Virtual Sample and Hold Mode \n\r");
	while ((scanMode <1)||(scanMode >2))
	{ 
		printf (" Input Scan Mode of I-9014 (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 hardware trigger signal Mode, internal interrupt signal can trigger all I-9014s on slots at the same time.
	// trigger source 2, start magic scan via external hardware trigger signal Mode, extern trigger can also trigger all I-9014s on slots at the same time.
	printf ("\n Step 5: Select Trigger Source of I-9014,\n I-9014 can have 3 types of trigger source \n");
	printf ("\t trigger source 0= Software Command \n\t trigger source 1= Internal Hardware Signal \n\t trigger source 2= External Hardware Tigger Signal\n\r");
	while ((triggerSource <0)||(triggerSource >2))
	{ 
		printf (" Input trigger source of I-9014 (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 Step6: Select Trigger State of I-9014 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-9014 (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 i9014_ConfigMagicScan only tell I-9014 how to start magic scan,it will not start magic scan
	// We have to call i9014_StartMagicScan to start up the magic scan.

	i9014_ConfigMagicScan(slot,chArr,gainArr,scanChCount, sampleRate, scanMode,triggerSource,triggerState, &realsampleRate);	

	printf("\nThe Magic Scan Configurations of I-9014 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-9014 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);
	i9014_StartMagicScan(slot);
 	
	totalScanned=0;	  
 
	T1=GetTimeTicks_ms();   
	// i9014_ReadFIFO is a non block API function
	// readFromFIFO means the data count read from FIFO for each i9014_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= i9014_ReadFIFO_BlockMode(slot,rawData, TargetCnt ,&readCnt);
	i9014_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");
		i9014_UnLockFIFO(slot);
		i9014_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");
	printf("Start to save all data in .scv file:\n\n\r");
	FILE *output;
	output=fopen("/boot/uboot/9014.csv", "w");
	if (output==NULL){
		printf("Open file fail! \n");
		exit(0);			
	} 
	 
	for(i=0;i<totalScanned;i++)
	{ 	
		i9014_CalibrateData(slot, gainArr[i %scanChCount],rawData[i],&calibratedAI);
		//fprintf(output, "%d,0x%04X,%5.4f\n",i ,rawData[i] ,calibratedAI);		
		printf("i=%d: Arr[%d]= F[%f]\t",i, i%scanChCount, calibratedAI);				
	}
	printf("\n---------\n");
}
