/*********************************************************************
*
* ANSI C Example program:
*    ContAcq-IntClk.c
*
* Example Category:
*    AI
*
* Description:
*    This example demonstrates how to acquire a continuous amount of
*    data using the DAQ device's internal clock.
*
* Instructions for Running:
*    1. Select the physical channel to correspond to where your
*       signal is input on the DAQ device.
*    2. Enter the minimum and maximum voltage range.
*    Note: For better accuracy try to match the input range to the
*          expected voltage level of the measured signal.
*    3. Set the rate of the acquisition. Also set the Samples per
*       Channel control. This will determine how many samples are
*       read at a time. This also determines how many points are
*       plotted on the graph each time.
*    Note: The rate should be at least twice as fast as the maximum
*          frequency component of the signal being acquired.
*
* Steps:
*    1. Create a task.
*    2. Create an analog input voltage channel.
*    3. Set the rate for the sample clock. Additionally, define the
*       sample mode to be continuous.
*    4. Call the Start function to start the acquistion.
*    5. Read the data in the EveryNCallback function until the stop
*       button is pressed or an error occurs.
*    6. Call the Clear Task function to clear the task.
*    7. Display an error if any.
*
* I/O Connections Overview:
*    Make sure your signal input terminal matches the Physical
*    Channel I/O control. For further connection information, refer
*    to your hardware reference manual.
*
*********************************************************************/


//#include <NIDAQmx.h>
#define DAQmxErrChk(functionCall) if( DAQmxFailed(error=(functionCall)) ) goto Error; else

int32 CVICALLBACK EveryNCallback_AIO(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData);




int ni_routine(void)
{
	int32       error=0;
	
	char        errBuff[2048]={'\0'};

	/*********************************************/
	// DAQmx Configure Code
	/*********************************************/
	DAQmxErrChk (DAQmxCreateTask("",&taskHandle));
	
	
	DAQmxErrChk (DAQmxCreateAIVoltageChan(taskHandle,"Dev1/ai0:15","",DAQmx_Val_RSE,-3.0,5.0,DAQmx_Val_Volts,NULL));
	DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandle,"",ni_sampling_frequency,DAQmx_Val_Rising,DAQmx_Val_ContSamps,1));
	DAQmxErrChk (DAQmxRegisterEveryNSamplesEvent(taskHandle,DAQmx_Val_Acquired_Into_Buffer,1,0,EveryNCallback_AIO,NULL));
	/*********************************************/
	// DAQmx Start Code
	/*********************************************/
	DAQmxErrChk (DAQmxStartTask(taskHandle));



Error:
	if( DAQmxFailed(error) )
		DAQmxGetExtendedErrorInfo(errBuff,2048);
	/*
	if( taskHandle!=0 ) {
		/--------------------------
		// DAQmx Stop Code
		/--------------------------
		DAQmxStopTask(taskHandle);
		DAQmxClearTask(taskHandle);
	}*/
	if( DAQmxFailed(error) )
		printf("DAQmx Error: %s\n",errBuff);
	printf("NI Initilization done\n");
	//getchar();
	return 0;
}

int32 CVICALLBACK EveryNCallback_AIO(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData)
{
	int32       error=0;
	char        errBuff[2048]={'\0'};
	static int  totalRead=0;
	int32       read=0;

	/*********************************************/
	// DAQmx Read Code
	/*********************************************/
	DAQmxErrChk (DAQmxReadAnalogF64(taskHandle,1,10.0,DAQmx_Val_GroupByScanNumber,dataAI,128/*16*/,&read,NULL));
	if( read>0 ) {

			//Software timer code
			QueryPerformanceCounter(&t2);
			elapsedTime = (t2.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart;
			QueryPerformanceCounter(&t1);
			QueryPerformanceCounter(&t3);
			
			elapsedTimeBeg = (t3.QuadPart - tstart.QuadPart) * 1000.0 / frequency.QuadPart;
			//printf ("Beginning: %f msec\n",elapsedTimeBeg);
			
			time ( &rawtime );
			timeinfo = localtime ( &rawtime );
			
			//Update variables
			front_left_rpm=front_left_ticks*fl_ticks_to_rpm;
			front_right_rpm=front_right_ticks*fr_ticks_to_rpm;
			rear_left_rpm=rear_left_ticks*rl_ticks_to_rpm;
			rear_right_rpm=rear_right_ticks*rr_ticks_to_rpm;
			engine_rpm=(engine_ticks*rpm_ticks_to_rpm)/engine_ignitions_per_rpm;

			car_speed=(front_left_rpm+front_right_rpm+rear_left_rpm+rear_right_rpm)*(2*PI*wheel_radius/100)*(0.06/*60/1000*//4);	//car_speed in km/h

			#include	"code/update_adc.cpp"
			sprintf (log_buffer_1,"Sample:\t%d\tFL:\t%d\tFR:\t%d\tRL:\t%d\tRR:\t%d\tEngine:\t%d\tIg_RPM:\t%d\tWR:\t%1.2f\t",sample_number,front_left_rpm,front_right_rpm,rear_left_rpm,rear_right_rpm,engine_rpm,engine_ignitions_per_rpm,wheel_radius/100);			
			sprintf (log_buffer_2,"acc_fx:\t%2.4f\tacc_fy:\t%2.4f\tacc_fz:\t%2.4f\tacc_mx:\t%2.4f\tacc_my:\t%2.4f\tacc_mz:\t%2.4f\tx_rate:\t%3.1f\ty_rate:\t%3.1f\tacc_rx:\t%2.4f\t",acc_fx,acc_fy,acc_fz,acc_mx,acc_my,acc_mz,x_rate,y_rate,acc_rx);
			sprintf (log_buffer_3,"acc_ry:\t%2.4f\tacc_rz:\t%2.4f\tsteering_torque:\t%2.4f\thandbrake_position:\t%2.4f\tsteering_angle:\t%2.4f\tfront_brake:\t%2.4f\trear_brake:\t%2.4f\tT:\t%5.2f\tms\tTBeg:\t%8.2f\tms\tTall:\t%s",acc_ry,acc_rz,steering_torque,handbrake_position,steering_angle,front_brake,rear_brake,elapsedTime,elapsedTimeBeg,asctime(timeinfo));
			
			
			//double mpelas=elapsedTime*0.001; //time in ms
			x_angle=x_rate*0.01+x_angle;
			//x_angle=(float)((float)mpelas+(float)x_angle);

			static int print_counter=0;
			print_counter++;
			if(print_counter>20){
				//printf("\nYaw:%f acc_fx:%2.2f acc_fy:%2.2f torque:%1.4f\n\n ", x_angle, dataAI[acc_fx_con],dataAI[acc_fy_con],dataAI[steering_torque_con]);
				//printf("handbrake_position=%f\n",handbrake_position);
				print_counter=0;
			}


			switch((char)state){
				case 'i' :
					//printf("%s",log_buffer);
				break; 
				case 'n':
					if (log_File!=NULL){
						if(log_event==FALSE){
							sample_number++;
							fputs (log_buffer_1,log_File);
							fputs (log_buffer_2,log_File);
							fputs (log_buffer_3,log_File);
						}
					}
				break;
				case 'p':
					
				break;
				case 's':
				break;
				case 'r':
					if (log_File!=NULL){
						if(log_event==FALSE){
							sample_number++;
							fputs (log_buffer_1,log_File);
							fputs (log_buffer_2,log_File);
							fputs (log_buffer_3,log_File);
						}
					}
					state='n';
				break;

			}


	}

Error:
	if( DAQmxFailed(error) ) {
		DAQmxGetExtendedErrorInfo(errBuff,2048);
		/*********************************************/
		// DAQmx Stop Code
		/*********************************************/
		DAQmxStopTask(taskHandle);
		DAQmxClearTask(taskHandle);
		printf("DAQmx Error: %s\n",errBuff);
	}
	return 0;
}
