

#include "exio.h"

#if (SHIFT_REG_NUM > 0)

#include "shell.h"
#include "delay.h"
#include "inout.h"
#include "trigger.h"

#define OUT_TM_INFO			0

//------------------------------------------
#ifndef	ExDelay
#define	ExDelay()			DelayUs(1)
#endif

//------------------------------------------

void ReadExInputs(u8 * inputList);
void WriteExOutputs(u8* outputList);
void ExioSwapData(void);

void TestExInout(char * para1, char * para2);

//------------------------------------------

#define MAX_EX_INPUTS_NUM	(SHIFT_REG_NUM*IN_NUM_PER_REG)
#define MAX_EX_OUTPUTS_NUM	(SHIFT_REG_NUM*OUT_NUM_PER_REG)

u8 g_exInputStaList[MAX_EX_INPUTS_NUM];
u8 g_exOutputStaList[MAX_EX_OUTPUTS_NUM];

//------------------------------------------

#ifndef SetOutputEnHigh
#define SetOutputEnHigh		SetOutputNull
#endif

#ifndef SetOutputEnLow
#define SetOutputEnLow		SetOutputNull
#endif

void InitExInOuts(void)
{
	memset(g_exInputStaList, 0, sizeof(u8)*MAX_EX_INPUTS_NUM);
	memset(g_exOutputStaList, 0, sizeof(u8)*MAX_EX_INPUTS_NUM);

	SetOutputEnHigh();
	GetExInputSta(-1);		// 读取输入信号状态
	SetExOutputOff(0);		// 设置所有输出信号为off
	SetOutputEnLow();

//	AddShellCmd("TESTEX", "test Ex inout", TestExInout);
}

// 读取输入信号状态
void ReadExInputs(u8 * inputList)
{
	int i;
	if (inputList == NULL)
	{
		return;
	}

	SetClkHigh();			// 设置为高电平
	SetInputLatchLow();		// 锁存到寄存器
	ExDelay();
	SetInputLatchHigh();	// 锁存结束
	ExDelay();				// 等待数据稳定

	// 读取数据，从低位开始
	for(i = 0; i < MAX_EX_INPUTS_NUM; i++)
	{
		ExDelay();			// 等待数据稳定
		SetClkLow();		// 电平翻转
		*inputList++ = GetDinStatus();	// 读取数据
		ExDelay();
		SetClkHigh();		// 上升沿数据开始移位
	}
}

// 输出数据
void WriteExOutputs(u8* outputList)
{
	int i;

	if (outputList == NULL)
	{
		return;
	}

	SetClkLow();
	SetOutputLatchLow();
	ExDelay();

	// 设置数据，从高位开始设置
	for(i = MAX_EX_OUTPUTS_NUM; i > 0; i--)
	{
		if ((outputList[i-1]) != 0)
		{
			SetDOutLow();
		}
		else
		{
			SetDOutHigh();
		}
		ExDelay();		// 等待数据稳定
		SetClkHigh();	// 上升沿移位输出
		ExDelay();		// 等待数据输出稳定
		SetClkLow();	// 翻转为低电平
	}

	SetOutputLatchHigh();		// 上升沿，移位寄存器输出到锁存寄存器
	ExDelay();
	SetOutputLatchLow();		// 翻转为低电平
}

// 交换数据
void ExioSwapData(void)
{
	int i, j;
	SetClkLow();			// 设置为低电平
	SetOutputLatchLow();	// 设置为低电平
	SetInputLatchLow();		// 锁存到寄存器
	ExDelay();
	SetInputLatchHigh();	// 锁存结束
	ExDelay();				// 等待数据稳定

	for(i = MAX_EX_OUTPUTS_NUM, j = 0; i > 0; i--, j++)
	{
		// 设置输出数据
		if ((g_exInputStaList[i-1]) != 0)
		{
			SetDOutLow();
		}
		else
		{
			SetDOutHigh();
		}
		ExDelay();		// 等待数据稳定
		SetClkHigh();	// 上升沿数据开始移位
		ExDelay();
		g_exInputStaList[j] = GetDinStatus();	// 读取输入数据
		SetClkLow();	// 翻转为低电平
	}

	SetOutputLatchHigh();		// 上升沿，移位寄存器输出到锁存寄存器
	ExDelay();
	SetOutputLatchLow();		// 翻转为低电平
}

#ifndef RD_EXIN_GAP
#define RD_EXIN_GAP		0		// 单位ms
#endif

u8 GetExInputSta(int id)
{
#if (OUT_TM_INFO == 1)
	u32 temp, timer;
	timer = GetUsSoftTimer();
#endif
#if (RD_EXIN_GAP > 0)
	static u32 oldtimer = 0;
	u32 newtimer = GetMsSoftTimer();
	if (newtimer - oldtimer > RD_EXIN_GAP)
	{
		oldtimer = newtimer;
		ReadExInputs(g_exInputStaList);
	}
#else
	ReadExInputs(g_exInputStaList);
#endif
#if (OUT_TM_INFO == 1)
	temp = GetUsSoftTimer();
	printf("GetExInputSta time=%d\r\n", temp-timer);
#endif
	if (id > 0 && id <= MAX_EX_INPUTS_NUM)
	{
		return g_exInputStaList[id-1];
	}

	return 0xff;
}

u8 GetExOutputSta(int id)
{
	if (id > 0 && id <= MAX_EX_OUTPUTS_NUM)
	{
		return g_exOutputStaList[id-1];
	}
	return 0xff;
}

void SetExOutputOn(int id)
{
#if (OUT_TM_INFO == 1)
	u32 temp, timer;
	timer = GetUsSoftTimer();
#endif
	if (id > 0 && id <= MAX_EX_OUTPUTS_NUM)
	{
		g_exOutputStaList[id-1] = 1;
	}
	else if (id == 0)
	{
		memset(g_exOutputStaList, 1, sizeof(u8)*MAX_EX_INPUTS_NUM);		// 全部输出
	}

	WriteExOutputs(g_exOutputStaList);
#if (OUT_TM_INFO == 1)
	temp = GetUsSoftTimer();
	printf("GetExInputSta time=%d\r\n", temp-timer);
#endif
}

void SetExOutputOff(int id)
{
#if (OUT_TM_INFO == 1)
	u32 temp, timer;
	timer = GetUsSoftTimer();
#endif
	if (id > 0 && id <= MAX_EX_OUTPUTS_NUM)
	{
		g_exOutputStaList[id-1] = 0;
	}
	else if (id == 0)
	{
		memset(g_exOutputStaList, 0, sizeof(u8)*MAX_EX_INPUTS_NUM);		// 全部关闭
	}
	WriteExOutputs(g_exOutputStaList);
#if (OUT_TM_INFO == 1)
	temp = GetUsSoftTimer();
	printf("GetExInputSta time=%d\r\n", temp-timer);
#endif
}

void TestExInout(char * para1, char * para2)
{
	int p1, p2;

	p1 = p2 = 0;
	if (para1 != NULL && strcmp(para1, "") != 0)
	{
		p1 = atoi(para1);
	}
	if (para2 != NULL && strcmp(para2, "") != 0)
	{
		p2 = atoi(para2);
	}
	if (p1 == p2)
	{
	}
	//--------------------------------

	if (p1 < 100)
	{// 显示输入状态
		s8 oldinput[MAX_EX_INPUTS_NUM] = {-1};
		do
		{
			GetExInputSta(-1);

			for (int i = 0; i < MAX_EX_INPUTS_NUM; i++)
			{
				if (oldinput[i] != g_exInputStaList[i])
				{
					oldinput[i] = g_exInputStaList[i];
					if (oldinput[i] == 0)
					{
						printf("%d.input is on\r\n", i+1);
					}
					else
					{
						printf("%d.input is off\r\n", i+1);
					}
				}
			}

			if (IsConsoleCancel() != 0 || p1 == 0)		// 终端输入停止
			{
				break;
			}

			DelayMs(50);

		}while(1);
	}
	else
	{// 输出
		p1 -= 100;
		if (p1 == 0)
		{// 显示输出状态
			for (int i = 0; i < MAX_EX_OUTPUTS_NUM; i++)
			{
				if (g_exOutputStaList[i] == 1)
				{
					printf("%d.output is on\r\n", i+1);
				}
				else
				{
					printf("%d.output is off\r\n", i+1);
				}
			}
		}
		else
		{// 设置输出状态
			if (p2 == 0)
			{// off
				if (p1 > 0 && p1 <= MAX_EX_OUTPUTS_NUM)
				{
					g_exOutputStaList[p1-1] = 0;
					WriteExOutputs(g_exOutputStaList);
				}
			}
			else
			{// on
				if (p1 > 0 && p1 <= MAX_EX_OUTPUTS_NUM)
				{
					g_exOutputStaList[p1-1] = 1;
					WriteExOutputs(g_exOutputStaList);
				}
			}
		}
	}
}

#endif
