// serial_master.cpp : Defines the entry point for the console application.
///*  Copyright (C) MOXA Inc. All rights reserved.

    This software is distributed under the terms of the
    MOXA License.  See the file COPYING-MOXA for details.
*/
/*
    digital_input_output.cpp

    Routines to test the digital io.

	2011-01-23  Epson Chiang
		New Release

*/

#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "digital_input_output.h"

#ifdef	_MFC_VER
#include "LogFile.h"
#include "DVTToolDoc.h"
#include "DVTToolView.h"
#endif

#ifdef	_MFC_VER
/*Global variables */
extern		CLogFile	m_log;
extern		CString		log_event;
#endif

int init_dgio_data(HANDLE hDIO, int dout_len, int dout_start, int init_value)
{
	int				output_port_num;

	for(output_port_num = dout_start; output_port_num < dout_start+dout_len; output_port_num++){
			
		if(init_value==0){
			/*Set output signal low*/
			mxdgio_set_output_signal_low(hDIO,output_port_num);
		}
		else{
			/*Set output signal high*/
			mxdgio_set_output_signal_high(hDIO,output_port_num);
		}

	}
	return 0;
}

/*		verify_digit_data
*		
*		dout_len	: digital output length
*		dout_start	: digital output start address
*		dim_len		: digital input length
*		din_start	: digital input start address
*/

int verify_dgio_data(HANDLE hDIO, int dout_len, int dout_start, int din_len, int din_start, int compare_data)
{
	int				input_port_num;
	int				output_port_num;
	int				input_result;
	int				output_result;
	unsigned int	error_detect=0;

	/*Compare the data length of input and output*/

	/*Check the output signal*/
	for(output_port_num = dout_start; output_port_num < dout_start+dout_len; output_port_num++)
	{
		output_result = mxdgio_get_output_signal(hDIO,output_port_num);
	#if _DEBUG_MSG
		printf("output_result DOUT%d = %d\r\n", output_port_num, output_result);
	#endif
		
		/*Check if the output is low  */
		if(compare_data==DGIO_SIGNAL_LOW){
			if(output_result!=DGIO_SIGNAL_LOW){
				error_detect++;
			}
		}
		else{/*Check if the output high */
			if(output_result!=DGIO_SIGNAL_HIGH){
				error_detect++;
			}
		}
	}

	/*Check the input signal*/
	for(input_port_num=din_start; input_port_num<din_start+din_len; input_port_num++){
		input_result=mxdgio_get_input_signal(hDIO,input_port_num);
#if _DEBUG_MSG
		printf("input_result : DIN%d  = %d\r\n", input_port_num,input_result);
#endif

		/*Check if the input is low  */
		if(compare_data==DGIO_SIGNAL_LOW){
			if(input_result!=DGIO_SIGNAL_LOW)
			{
				error_detect = DGIO_DIN_LOW_ERROR;
			}
		}
		else{/*Check if the input is high  */
			if(input_result!=DGIO_SIGNAL_HIGH)
			{
				error_detect = DGIO_DIN_HIGH_ERROR;
			}
		}
	}
		
	if(error_detect==0){
		return 0;
	}
	else
		return error_detect;
	
}

DWORD thread_dgio(LPVOID pdgio)
{

#if _MFC_VER 
	PTHREAD_DATA pData = (PTHREAD_DATA)pdgio;
	DGIO_PRM	*dgio_param=&pData->dgio_prm;
#else
	DGIO_PRM	*dgio_param=(DGIO_PRM *)pdgio;
#endif

	HANDLE			hDIO;
	int				output_port_num;
	unsigned int	error_detect = 0;
	int				error_code = 0;
	unsigned int	ok_count=0;
	unsigned int	error_count=0;

	int		dout_len;
	int		dout_start;
	int		din_len;
	int		din_start;
	int		compare_data;

	/*open dio handle*/
	hDIO=mxdgio_open();
	while(1)
	{
		/*Reset the error detect*/
		error_detect = 0;

		dout_len = dgio_param->dout_port_num;
		din_len  = dgio_param->din_port_num;
		dout_start=0;

		/*Set default value to 0*/
		init_dgio_data(hDIO, dout_len, dout_start,0);

		/*Check the  value*/
		for(int i=0; i<2; i++){ /*Switch the dgio value*/
			for(output_port_num=0; output_port_num < dout_len; output_port_num++){ /*Switch the port number*/
				/*Set output signal*/
				if(i==0){
					mxdgio_set_output_signal_low(hDIO,output_port_num);
				}
				else{
					mxdgio_set_output_signal_high(hDIO,output_port_num);
				}

				dout_len =dout_len/2; //1;
				dout_start =output_port_num * dout_len/2; //0;
				din_len = din_len/2; //3;
				din_start =output_port_num * din_len/2;//0;
				compare_data = (i==0) ? DGIO_SIGNAL_LOW : DGIO_SIGNAL_HIGH;
				/*Check the low signal */
				//Sleep(100);
				Sleep(dgio_param->read_interval);
				error_code = verify_dgio_data(hDIO, dout_len, dout_start, din_len, din_start, compare_data);
				error_detect += error_code;

				/* Log first error*/
				if(error_count != 0)
				{
#ifdef	_MFC_VER
					log_event.Format("thread_dgio : verify_dgio_data fail");
					m_log.LogEvent(log_event);
#endif
					switch(error_code)
					{
					case DGIO_DIN_LOW_ERROR:
#ifdef	_MFC_VER
						log_event.Format("verify_dgio_data : input_result!=DGIO_SIGNAL_LOW");
						m_log.LogEvent(log_event);
						Sleep(1000);
#endif
						break;

					case DGIO_DIN_HIGH_ERROR:
#ifdef	_MFC_VER
						log_event.Format("verify_dgio_data : input_result!=DGIO_SIGNAL_HIGH");
						m_log.LogEvent(log_event);
						Sleep(1000);
#endif
						break;

					default:
						break;
					}
				}
			}
		}

		if(error_detect==0)
		{
			ok_count++;
		}
		else
		{
			error_count++;
			
		}

#if _DEBUG_MSG
		printf("\r ok_count=%d, error_count=%d",ok_count, error_count);
#endif
		dgio_param->ok_count=ok_count;
		dgio_param->error_count=error_count;

		/* wait interval*/
		Sleep(dgio_param->write_interval);

#if _MFC_VER 
		if(pData->thread_stop == 1){
			break;
		}
#else
		if(dgio_param->thread_stop == 1){
			break;
		}
#endif
	
	}

	/*close dio handle*/
	mxdgio_close(hDIO);

	return 0;
}