
#include "extendboards.h"
#include "delay.h"
#include "crc16.h"
#include "filetrans.h"


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


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


#if (MAX_SUPPORT_CORE > 0)

CoreControl g_extendCtrlList[MAX_SUPPORT_CORE];

#define	EXID_CORE_STA1			MAKE_EXID(BN_PROTOCOL_MVCTRL, BN_ID_CORE_1, 0, BN_CMD_REGVAL)	// 第一块的状态变化 ID
#define	EXID_CORE_STA2			MAKE_EXID(BN_PROTOCOL_MVCTRL, BN_ID_CORE_2, 0, BN_CMD_REGVAL)	// 第二块的状态变化 ID
#define	EXID_CORE_STA3			MAKE_EXID(BN_PROTOCOL_MVCTRL, BN_ID_CORE_3, 0, BN_CMD_REGVAL)	// 第三块的状态变化 ID

#define	CUR_BOARD_INSTA_EXID	MAKE_EXID(BN_PROTOCOL_MVCTRL, CUR_COREBOARD_ID, 0, BN_CMD_REGVAL)

#define	EXID_CORE_CTRL1			MAKE_EXID(BN_PROTOCOL_MVCTRL, BN_ID_CORE_1, 0, BN_CMD_WTREG)	// 第一块的控制数据 ID
#define	EXID_CORE_CTRL2			MAKE_EXID(BN_PROTOCOL_MVCTRL, BN_ID_CORE_2, 0, BN_CMD_WTREG)	// 第二块的控制数据 ID
#define	EXID_CORE_CTRL3			MAKE_EXID(BN_PROTOCOL_MVCTRL, BN_ID_CORE_3, 0, BN_CMD_WTREG)	// 第三块的控制数据 ID

#define	CUR_BOARD_OUTCTRL_EXID	MAKE_EXID(BN_PROTOCOL_MVCTRL, CUR_COREBOARD_ID, 0, BN_CMD_WTREG)


const u32 g_coreInExid[MAX_SUPPORT_CORE] =
{
	EXID_CORE_STA1,
#if (MAX_SUPPORT_CORE > 1)
	EXID_CORE_STA2,
#endif
#if (MAX_SUPPORT_CORE > 2)
	EXID_CORE_STA3,
#endif
};

const u32 g_coreOutExid[MAX_SUPPORT_CORE] =
{
	EXID_CORE_CTRL1,
#if (MAX_SUPPORT_CORE > 1)
	EXID_CORE_CTRL2,
#endif
#if (MAX_SUPPORT_CORE > 2)
	EXID_CORE_CTRL3,
#endif
};

#endif


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

int g_curBoardIdx = -1;					// 当前板卡在列表中的下角标
int g_curBoardID = -1;					// 当前板卡的节点ID
int g_curBoardInstaExid = -1;
int g_curBoardOutCtrlExid = -1;

int g_wrcmdtoogle = 0;
int g_rdcmdtoogle = 0;
u32 g_rdcmdbitmap = 0;

int g_wrstatoogle = 0;
int g_rdstatoogle = 0;
u32 g_rdstabitmap = 0;

#if (RD_HEAD_PARA_NUM > 0)
u8 g_exbNvPara[RD_HEAD_PARA_NUM][BOARD_PARA_SIZE];	// 外围板非易失性参数
u8 g_receiveEn[RD_HEAD_PARA_NUM] = {0};				// 接收允许
u8 g_receivenum[RD_HEAD_PARA_NUM] = {0};			// 接收计数
u8 g_framenum[RD_HEAD_PARA_NUM] = {0};				// 数据包帧数
u16 g_datacrc[RD_HEAD_PARA_NUM] = {0};				// 数据crc校验值
#endif

s32 headparaval = 0;

#define	TOOGLE_ADD	0x00010000

#define	PORT_ADDR_MOD	0x0000FFFF
#define	PORT_TOOG_MOD	0xFFFF0000

#define	CMDSTA_BMP_FULL	0x000000FF

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

static const u32 IDX_TO_BIT[32] = 
{
	0x00000001,
	0x00000002,
	0x00000004,
	0x00000008,
	0x00000010,
	0x00000020,
	0x00000040,
	0x00000080,
	0x00000100,
	0x00000200,
	0x00000400,
	0x00000800,
	0x00001000,
	0x00002000,
	0x00004000,
	0x00008000,
	0x00010000,
	0x00020000,
	0x00040000,
	0x00080000,
	0x00100000,
	0x00200000,
	0x00400000,
	0x00800000,
	0x01000000,
	0x02000000,
	0x04000000,
	0x08000000,
	0x10000000,
	0x20000000,
	0x40000000,
	0x80000000,
};

#if (MAX_SUPPORT_HEAD > 0)

HeadControl g_headList[MAX_SUPPORT_HEAD+1];

#endif

#if (MAX_SUPPORT_COLOR > 0)

ColorControl g_colorList[MAX_SUPPORT_COLOR+1];

#endif

#if (MAX_SUPPORT_EXTIO > 0)

ExtIOControl g_extioList[MAX_SUPPORT_EXTIO+1];

#endif

#if (MAX_SUPPORT_SEWHD > 0)

SewHeadControl g_sewHeadList[MAX_SUPPORT_SEWHD+1];

#endif
//-------------------------------------------------------------------------

void InitBoardsList(void)
{
	int i;
	int id;

// 核心主板
	g_curBoardIdx = CUR_CORE_IDX;
	g_curBoardID = -1;
	g_curBoardInstaExid = -1;
	g_curBoardOutCtrlExid = -1;

#if (MAX_SUPPORT_CORE > 0)
	for (i = 0; i < MAX_SUPPORT_CORE; i++)
	{
		InitCoreControl(&(g_extendCtrlList[i]));
		id = i+1;
		g_extendCtrlList[i].staexid = MAKE_EXID(BN_PROTOCOL_MVCTRL, id, 0, BN_CMD_REGVAL);
		g_extendCtrlList[i].cmdexid = MAKE_EXID(BN_PROTOCOL_MVCTRL, id, 0, BN_CMD_WTREG);

		if (g_curBoardIdx == i)
		{
			g_curBoardID = id;
			g_curBoardInstaExid = g_extendCtrlList[i].staexid;
			g_curBoardOutCtrlExid = g_extendCtrlList[i].cmdexid;
		}

	}
#endif

	if (g_curBoardIdx >= 0)
	{
		printf("cur board idx = %d\r\n", g_curBoardIdx);
	}
	else
	{
		printf("init extendCtrlList error\r\n");
	}

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

// 机头板
#if (MAX_SUPPORT_HEAD > 0)
	for (i = 0; i < MAX_SUPPORT_HEAD+1; i++)		// 0为广播命令 故MAX_SUPPORT_HEAD+1
	{
		InitHeadControl(&(g_headList[i]));

		if (i == 0)
		{
			g_headList[i].nodeId = BN_ID_BROADCAST;
		}
		else
		{
			id = i + HEAD_NODEID_BASE - 1;
			g_headList[i].nodeId = id;
		}
	}
#endif	// (MAX_SUPPORT_HEAD > 0)

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

// 换色板
#if (MAX_SUPPORT_COLOR > 0)
	for (i = 0; i < MAX_SUPPORT_COLOR+1; i++)
	{
		InitColorControl(&(g_colorList[i]));
		if (i == 0)
		{
			g_colorList[i].nodeId = BN_ID_BROADCAST;
		}
		else
		{
			id = i + COLOR_NODEID_BASE - 1;
			g_colorList[i].nodeId = id;
		}
	}
#endif

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

// IO扩展板
#if (MAX_SUPPORT_EXTIO > 0)
	for (i = 0; i < MAX_SUPPORT_EXTIO+1; i++)
	{
		InitExtIOControl(&(g_extioList[i]));
		if (i == 0)
		{
			g_extioList[i].nodeId = BN_ID_BROADCAST;
		}
		else
		{
			id = i + EXTIO_NODEID_BASE - 1;
			g_extioList[i].nodeId = id;
		}
	}
#endif
//-------------------------------------------------------------------------

// 缝纫机头板
#if (MAX_SUPPORT_SEWHD > 0)
	for (i = 0; i < MAX_SUPPORT_SEWHD+1; i++)
	{
		InitSewHeadControl(&(g_sewHeadList[i]));
		if (i == 0)
		{
			g_sewHeadList[i].nodeId = BN_ID_BROADCAST;
		}
		else
		{
			id = i + SEWHD_NODEID_BASE - 1;
			g_sewHeadList[i].nodeId = id;
		}
	}
#endif
}

//---------------------------------------------------
// 设置过滤器
void CoreCanFilter(u8 fifo)
{
	int filteridx = 0;
	CAN_FilterTypeDef hFilterConfig;

	if (1)
	{// 防止报警
		filteridx = filteridx;
		hFilterConfig.FilterBank = 1;
		hFilterConfig.FilterBank = hFilterConfig.FilterBank;
	}


#if (MAX_SUPPORT_CORE > 1)
	// 请求本节点输入变化的远程帧和控制本节点输出的数据帧
	hFilterConfig.FilterBank = filteridx;												// 设置过滤器组，范围为0~13
	hFilterConfig.FilterMode = CAN_FILTERMODE_IDLIST;								// 过滤器组为标识符列表模式
	hFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;							// 过滤器组位宽为32位
	hFilterConfig.FilterIdHigh = HIWORD(MAKE_FILTER(g_curBoardInstaExid, CAN_RTR_REMOTE));		// 设定第一个过滤器高16位
	hFilterConfig.FilterIdLow = LOWORD(MAKE_FILTER(g_curBoardInstaExid, CAN_RTR_REMOTE));		// 设定第一个过滤器低16位
	hFilterConfig.FilterMaskIdHigh = HIWORD(MAKE_FILTER(g_curBoardOutCtrlExid, CAN_RTR_DATA));	// 设定第二个过滤器高16位
	hFilterConfig.FilterMaskIdLow = LOWORD(MAKE_FILTER(g_curBoardOutCtrlExid, CAN_RTR_DATA));	// 设定第二个过滤器低16位
	hFilterConfig.FilterFIFOAssignment = fifo;							// 关联到接收FIFO0
	hFilterConfig.SlaveStartFilterBank = 14;
	hFilterConfig.FilterActivation = ENABLE;								// 使能过滤器
	HAL_CAN_ConfigFilter(&HCAN, &hFilterConfig);											// 写入设置
	filteridx++;

	// 针对本类设备的所有ID的广播的远程帧和数据帧
	hFilterConfig.FilterBank = filteridx;							// 设置过滤器组，范围为0~13
	hFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;			// 过滤器组为标识符屏蔽位模式
	hFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;		// 过滤器位宽为1个32位过滤器
	hFilterConfig.FilterIdHigh = HIWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_MVCTRL, BN_ID_BROADCAST, 0, 0), 0));		// 设定过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterIdLow = LOWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_MVCTRL, BN_ID_BROADCAST, 0, 0), 0));		// 设定过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个）
	hFilterConfig.FilterMaskIdHigh = HIWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_TID, 0));	// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterMaskIdLow = LOWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_TID, 0));	// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个)
	hFilterConfig.FilterFIFOAssignment = fifo;				// 关联到接收FIFO0
	hFilterConfig.SlaveStartFilterBank = 14;
	hFilterConfig.FilterActivation = ENABLE;					// 使能过滤器
	HAL_CAN_ConfigFilter(&HCAN, &hFilterConfig);				// 写入设置
	filteridx++;

	// 针对其他N1的寄存器变化数据帧
	hFilterConfig.FilterBank = filteridx;							// 设置过滤器组，范围为0~13
	hFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;			// 过滤器组为标识符屏蔽位模式
	hFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;		// 过滤器位宽为1个32位过滤器
	hFilterConfig.FilterIdHigh = HIWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_MVCTRL, 0, 0, BN_CMD_WTREG), CAN_RTR_DATA));	// 设定过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterIdLow = LOWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_MVCTRL, 0, 0, BN_CMD_WTREG), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个）
	hFilterConfig.FilterMaskIdHigh = HIWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_REMOTE));				// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterMaskIdLow = LOWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_REMOTE));				// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个)
	hFilterConfig.FilterFIFOAssignment = fifo;				// 关联到接收FIFO0
	hFilterConfig.SlaveStartFilterBank = 14;
	hFilterConfig.FilterActivation = ENABLE;					// 使能过滤器
	HAL_CAN_ConfigFilter(&HCAN, &hFilterConfig);
	filteridx++;

	// 针对其他N1的寄存器变化数据帧
	hFilterConfig.FilterBank = filteridx;							// 设置过滤器组，范围为0~13
	hFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;			// 过滤器组为标识符屏蔽位模式
	hFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;		// 过滤器位宽为1个32位过滤器
	hFilterConfig.FilterIdHigh = HIWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_MVCTRL, 0, 0, BN_CMD_REGVAL), CAN_RTR_DATA));	// 设定过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterIdLow = LOWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_MVCTRL, 0, 0, BN_CMD_REGVAL), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个）
	hFilterConfig.FilterMaskIdHigh = HIWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_REMOTE));				// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterMaskIdLow = LOWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_REMOTE));				// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个)
	hFilterConfig.FilterFIFOAssignment = fifo;				// 关联到接收FIFO0
	hFilterConfig.SlaveStartFilterBank = 14;
	hFilterConfig.FilterActivation = ENABLE;					// 使能过滤器
	HAL_CAN_ConfigFilter(&HCAN, &hFilterConfig);				// 写入设置
	filteridx++;
#endif

#if (MAX_SUPPORT_HEAD > 0)
	// 针对机头板的状态变化数据帧
	hFilterConfig.FilterBank = filteridx;							// 设置过滤器组，范围为0~13
	hFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;			// 过滤器组为标识符屏蔽位模式
	hFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;		// 过滤器位宽为1个32位过滤器
	hFilterConfig.FilterIdHigh = HIWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_HEAD, 0, 0, BN_CMD_EXSTA), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterIdLow = LOWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_HEAD, 0, 0, BN_CMD_EXSTA), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个）
	hFilterConfig.FilterMaskIdHigh = HIWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterMaskIdLow = LOWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个)
	hFilterConfig.FilterFIFOAssignment = fifo;				// 关联到接收FIFO0
	hFilterConfig.SlaveStartFilterBank = 14;
	hFilterConfig.FilterActivation = ENABLE;					// 使能过滤器
	HAL_CAN_ConfigFilter(&HCAN, &hFilterConfig);				// 写入设置
	filteridx++;

	// 针对机头板的总线状态命令的数据帧
	hFilterConfig.FilterBank = filteridx;							// 设置过滤器组，范围为0~13
	hFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;			// 过滤器组为标识符屏蔽位模式
	hFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;		// 过滤器位宽为1个32位过滤器
	hFilterConfig.FilterIdHigh = HIWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_HEAD, 0, 0, BN_CMD_BUSSTA), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterIdLow = LOWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_HEAD, 0, 0, BN_CMD_BUSSTA), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个）
	hFilterConfig.FilterMaskIdHigh = HIWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterMaskIdLow = LOWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个)
	hFilterConfig.FilterFIFOAssignment = fifo;				// 关联到接收FIFO0
	hFilterConfig.SlaveStartFilterBank = 14;
	hFilterConfig.FilterActivation = ENABLE;					// 使能过滤器
	HAL_CAN_ConfigFilter(&HCAN, &hFilterConfig);				// 写入设置
	filteridx++;

	// 针对机头板的读取寄存器命令的数据帧
	hFilterConfig.FilterBank = filteridx;							// 设置过滤器组，范围为0~13
	hFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;			// 过滤器组为标识符屏蔽位模式
	hFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;		// 过滤器位宽为1个32位过滤器
	hFilterConfig.FilterIdHigh = HIWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_HEAD, 0, 0, BN_CMD_REGVAL), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterIdLow = LOWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_HEAD, 0, 0, BN_CMD_REGVAL), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个）
	hFilterConfig.FilterMaskIdHigh = HIWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterMaskIdLow = LOWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个)
	hFilterConfig.FilterFIFOAssignment = fifo;				// 关联到接收FIFO0
	hFilterConfig.SlaveStartFilterBank = 14;
	hFilterConfig.FilterActivation = ENABLE;					// 使能过滤器
	HAL_CAN_ConfigFilter(&HCAN, &hFilterConfig);				// 写入设置
	filteridx++;

	// 针对机头板的读写参数命令的数据帧
	hFilterConfig.FilterBank = filteridx;							// 设置过滤器组，范围为0~13
	hFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;			// 过滤器组为标识符屏蔽位模式
	hFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;		// 过滤器位宽为1个32位过滤器
	hFilterConfig.FilterIdHigh = HIWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_HEAD, 0, 0, BN_CMD_NVPARA), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterIdLow = LOWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_HEAD, 0, 0, BN_CMD_NVPARA), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个）
	hFilterConfig.FilterMaskIdHigh = HIWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterMaskIdLow = LOWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个)
	hFilterConfig.FilterFIFOAssignment = fifo;				// 关联到接收FIFO0
	hFilterConfig.SlaveStartFilterBank = 14;
	hFilterConfig.FilterActivation = ENABLE;					// 使能过滤器
	HAL_CAN_ConfigFilter(&HCAN, &hFilterConfig);				// 写入设置
	filteridx++;

#endif

#if (MAX_SUPPORT_COLOR > 0)
	// 针对换色板的状态变化数据帧
	hFilterConfig.FilterBank = filteridx;							// 设置过滤器组，范围为0~13
	hFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;			// 过滤器组为标识符屏蔽位模式
	hFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;		// 过滤器位宽为1个32位过滤器
	hFilterConfig.FilterIdHigh = HIWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_COLOR, 0, 0, BN_CMD_EXSTA), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterIdLow = LOWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_COLOR, 0, 0, BN_CMD_EXSTA), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个）
	hFilterConfig.FilterMaskIdHigh = HIWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterMaskIdLow = LOWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个)
	hFilterConfig.FilterFIFOAssignment = fifo;				// 关联到接收FIFO0
	hFilterConfig.SlaveStartFilterBank = 14;
	hFilterConfig.FilterActivation = ENABLE;					// 使能过滤器
	HAL_CAN_ConfigFilter(&HCAN, &hFilterConfig);				// 写入设置
	filteridx++;
 

	// 针对换色板的读取寄存器命令的数据帧
	hFilterConfig.FilterBank = filteridx;							// 设置过滤器组，范围为0~13
	hFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;			// 过滤器组为标识符屏蔽位模式
	hFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;		// 过滤器位宽为1个32位过滤器
	hFilterConfig.FilterIdHigh = HIWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_COLOR, 0, 0, BN_CMD_REGVAL), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterIdLow = LOWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_COLOR, 0, 0, BN_CMD_REGVAL), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个）
	hFilterConfig.FilterMaskIdHigh = HIWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterMaskIdLow = LOWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个)
	hFilterConfig.FilterFIFOAssignment = fifo;				// 关联到接收FIFO0
	hFilterConfig.SlaveStartFilterBank = 14;
	hFilterConfig.FilterActivation = ENABLE;					// 使能过滤器
	HAL_CAN_ConfigFilter(&HCAN, &hFilterConfig);				// 写入设置
	filteridx++;

	// 针对换色板的读写参数命令的数据帧
	hFilterConfig.FilterBank = filteridx;							// 设置过滤器组，范围为0~13
	hFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;			// 过滤器组为标识符屏蔽位模式
	hFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;		// 过滤器位宽为1个32位过滤器
	hFilterConfig.FilterIdHigh = HIWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_COLOR, 0, 0, BN_CMD_NVPARA), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterIdLow = LOWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_COLOR, 0, 0, BN_CMD_NVPARA), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个）
	hFilterConfig.FilterMaskIdHigh = HIWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterMaskIdLow = LOWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个)
	hFilterConfig.FilterFIFOAssignment = fifo;				// 关联到接收FIFO0
	hFilterConfig.SlaveStartFilterBank = 14;
	hFilterConfig.FilterActivation = ENABLE;					// 使能过滤器
	HAL_CAN_ConfigFilter(&HCAN, &hFilterConfig);				// 写入设置
	filteridx++;
#endif

#if (MAX_SUPPORT_EXTIO > 0)
	// 针对IO扩展板的状态变化数据帧
	hFilterConfig.FilterBank = filteridx;							// 设置过滤器组，范围为0~13
	hFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;			// 过滤器组为标识符屏蔽位模式
	hFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;		// 过滤器位宽为1个32位过滤器
	hFilterConfig.FilterIdHigh = HIWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_EXTIO, 0, 0, BN_CMD_EXSTA), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterIdLow = LOWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_EXTIO, 0, 0, BN_CMD_EXSTA), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个）
	hFilterConfig.FilterMaskIdHigh = HIWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterMaskIdLow = LOWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个)
	hFilterConfig.FilterFIFOAssignment = fifo;				// 关联到接收FIFO0
	hFilterConfig.SlaveStartFilterBank = 14;
	hFilterConfig.FilterActivation = ENABLE;					// 使能过滤器
	HAL_CAN_ConfigFilter(&HCAN, &hFilterConfig);				// 写入设置
	filteridx++;

	// 针对IO扩展板的读取寄存器命令的数据帧
	hFilterConfig.FilterBank = filteridx;							// 设置过滤器组，范围为0~13
	hFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;			// 过滤器组为标识符屏蔽位模式
	hFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;		// 过滤器位宽为1个32位过滤器
	hFilterConfig.FilterIdHigh = HIWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_EXTIO, 0, 0, BN_CMD_REGVAL), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterIdLow = LOWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_EXTIO, 0, 0, BN_CMD_REGVAL), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个）
	hFilterConfig.FilterMaskIdHigh = HIWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterMaskIdLow = LOWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个)
	hFilterConfig.FilterFIFOAssignment = fifo;				// 关联到接收FIFO0
	hFilterConfig.SlaveStartFilterBank = 14;
	hFilterConfig.FilterActivation = ENABLE;					// 使能过滤器
	HAL_CAN_ConfigFilter(&HCAN, &hFilterConfig);				// 写入设置
	filteridx++;
#endif

#if (MAX_SUPPORT_SEWHD > 0)
	// 针对缝纫机头板的状态变化数据帧
	hFilterConfig.FilterBank = filteridx;							// 设置过滤器组，范围为0~13
	hFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;			// 过滤器组为标识符屏蔽位模式
	hFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;		// 过滤器位宽为1个32位过滤器
	hFilterConfig.FilterIdHigh = HIWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_SEWHD, 0, 0, BN_CMD_EXSTA), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterIdLow = LOWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_SEWHD, 0, 0, BN_CMD_EXSTA), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个）
	hFilterConfig.FilterMaskIdHigh = HIWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterMaskIdLow = LOWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个)
	hFilterConfig.FilterFIFOAssignment = fifo;				// 关联到接收FIFO0
	hFilterConfig.SlaveStartFilterBank = 14;
	hFilterConfig.FilterActivation = ENABLE;					// 使能过滤器
	HAL_CAN_ConfigFilter(&HCAN, &hFilterConfig);				// 写入设置
	filteridx++;

	// 针对缝纫机头板的总线状态命令的数据帧
	hFilterConfig.FilterBank = filteridx;							// 设置过滤器组，范围为0~13
	hFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;			// 过滤器组为标识符屏蔽位模式
	hFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;		// 过滤器位宽为1个32位过滤器
	hFilterConfig.FilterIdHigh = HIWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_SEWHD, 0, 0, BN_CMD_BUSSTA), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterIdLow = LOWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_SEWHD, 0, 0, BN_CMD_BUSSTA), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个）
	hFilterConfig.FilterMaskIdHigh = HIWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterMaskIdLow = LOWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个)
	hFilterConfig.FilterFIFOAssignment = fifo;				// 关联到接收FIFO0
	hFilterConfig.SlaveStartFilterBank = 14;
	hFilterConfig.FilterActivation = ENABLE;					// 使能过滤器
	HAL_CAN_ConfigFilter(&HCAN, &hFilterConfig);				// 写入设置
	filteridx++;

	// 针对缝纫机头板的读取寄存器命令的数据帧
	hFilterConfig.FilterBank = filteridx;							// 设置过滤器组，范围为0~13
	hFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;			// 过滤器组为标识符屏蔽位模式
	hFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;		// 过滤器位宽为1个32位过滤器
	hFilterConfig.FilterIdHigh = HIWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_SEWHD, 0, 0, BN_CMD_REGVAL), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterIdLow = LOWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_SEWHD, 0, 0, BN_CMD_REGVAL), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个）
	hFilterConfig.FilterMaskIdHigh = HIWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterMaskIdLow = LOWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个)
	hFilterConfig.FilterFIFOAssignment = fifo;				// 关联到接收FIFO0
	hFilterConfig.SlaveStartFilterBank = 14;
	hFilterConfig.FilterActivation = ENABLE;					// 使能过滤器
	HAL_CAN_ConfigFilter(&HCAN, &hFilterConfig);				// 写入设置
	filteridx++;

	// 针对缝纫机头板的读写参数命令的数据帧
	hFilterConfig.FilterBank = filteridx;							// 设置过滤器组，范围为0~13
	hFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;			// 过滤器组为标识符屏蔽位模式
	hFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;		// 过滤器位宽为1个32位过滤器
	hFilterConfig.FilterIdHigh = HIWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_SEWHD, 0, 0, BN_CMD_NVPARA), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterIdLow = LOWORD(MAKE_FILTER(MAKE_EXID(BN_PROTOCOL_SEWHD, 0, 0, BN_CMD_NVPARA), CAN_RTR_DATA));		// 设定过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个）
	hFilterConfig.FilterMaskIdHigh = HIWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterMaskIdLow = LOWORD(MAKE_FILTER(BNMASK_PRT|BNMASK_CMD, CAN_RTR_DATA));					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个)
	hFilterConfig.FilterFIFOAssignment = fifo;				// 关联到接收FIFO0
	hFilterConfig.SlaveStartFilterBank = 14;
	hFilterConfig.FilterActivation = ENABLE;					// 使能过滤器
	HAL_CAN_ConfigFilter(&HCAN, &hFilterConfig);				// 写入设置
	filteridx++;
#endif

}

void InitExtendBoards()
{
	InitBoardsList();

	RegistFilter(CoreCanFilter);

	InitCanCtrl();
}

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


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

void InputsTask()
{
	int rslt;
	CanRxMsg rxMsg;
	u32 tid, sid, cmd, dev, toogle;
	int i, count, idx;
	CtrlBusPacket pkt;

	count = 0;
	// CAN输入
	do
	{
		rslt = GetACanDataPacket(&rxMsg);
		if (rslt == 0)
		{
			dev = GET_PRT_FROM_EXID(rxMsg.canRxhead.ExtId);
			tid = GET_TID_FROM_EXID(rxMsg.canRxhead.ExtId);
			sid = GET_SID_FROM_EXID(rxMsg.canRxhead.ExtId);
			cmd = GET_CMD_FROM_EXID(rxMsg.canRxhead.ExtId);
			sid = sid;
			if (rxMsg.canRxhead.RTR == CAN_RTR_REMOTE)			// 远程帧
			{
				if ((dev == BN_PROTOCOL_ALL || dev == BN_PROTOCOL_MVCTRL) && 	// 全部设备或N1
					(tid == BN_ID_BROADCAST || tid == g_curBoardID)	)	// 全部ID或本板
				{
					if (cmd == BN_CMD_REGVAL)		// 请求本节点发送寄存器
					{
//						printf("receive sta request packet\r\n");
						if (g_curBoardIdx >= 0)
						{
							g_extendCtrlList[g_curBoardIdx].refreshflag = 1;		// 设置本板状态刷新标志，重新发送
						}
						else
						{
							printf("error: g_curBoardIdx not init\r\n");
						}
					}
					else
					{
						printf("other Remote cmd, cmd=0x%x\r\n", cmd);
					}
				}
				else
				{
					printf("other Remote packet, exid=0x%x\r\n", rxMsg.canRxhead.ExtId);
				}
			}
			else if (rxMsg.canRxhead.RTR == CAN_RTR_DATA && rxMsg.canRxhead.DLC == CAN_DATA_LEN) 		// 数据帧，数据长度为8
			{
#if (MAX_SUPPORT_CORE > 0)
				if (dev == BN_PROTOCOL_MVCTRL)
				{
					if (tid == BN_ID_BROADCAST || tid == g_curBoardID)	// 全部ID或本板
					{
						if (cmd == BN_CMD_WTREG)	// 写入命令或数据
						{
							// 写入命令到本节点
							if (g_curBoardIdx >= 0)
							{
								memcpy(pkt.cancomm.data.buff, rxMsg.data, CAN_DATA_LEN);

								toogle = pkt.cancomm.data.wrport.portaddr & PORT_TOOG_MOD;
								idx = pkt.cancomm.data.wrport.portaddr & PORT_ADDR_MOD;

							//	printf("refresh this cmd, toogle=0x%x, idx=%d, cmd=0x%x\r\n", toogle, idx, pkt.cancomm.data.wrport.wrdata);
								if (toogle != g_rdcmdtoogle)	// 新命令
								{
									// 清空状态buff
									g_rdcmdtoogle = toogle;
									g_rdcmdbitmap = 0;
									g_extendCtrlList[g_curBoardIdx].newcmdflag = 0;
									memset(g_extendCtrlList[g_curBoardIdx].cmdbuff, 0, sizeof(CORE_CHG_BUF_LEN));
								//	printf("get new cmd begin\r\n");
								}
								if (idx < CORE_CHG_BUF_LEN)
								{
									g_extendCtrlList[g_curBoardIdx].cmdbuff[idx] = pkt.cancomm.data.wrport.wrdata;

									g_rdcmdbitmap |= IDX_TO_BIT[idx];
									if (g_rdcmdbitmap == CMDSTA_BMP_FULL)
									{
										g_extendCtrlList[g_curBoardIdx].newcmdflag = 1;		// 设置收到新命令状态
									//	printf("get new cmd end\r\n");
									}
								}
							//	printf("refresh this cmd, toogle=0x%x, idx=%d, cmd=0x%x\r\n", toogle, idx, pkt.cancomm.data.wrport.wrdata);
							}
							else
							{
								printf("error: g_curBoardIdx not init\r\n");
							}
						}
						else
						{
							//printf("get other core data for this, cmd=%d, sid=%d\r\n", cmd, sid);
						}
					}
					else	// 其他节点ID
					{
						if (cmd == BN_CMD_REGVAL)		// 寄存器变化命令
						{
							for (i = 0; i < MAX_SUPPORT_CORE ; i++)
							{
								if (g_extendCtrlList[i].staexid == rxMsg.canRxhead.ExtId)	// 找到其他节点ID相符的缓冲区
								{
									// 刷新状态到缓冲区
									memcpy(pkt.cancomm.data.buff, rxMsg.data, CAN_DATA_LEN);

									toogle = pkt.cancomm.data.wrport.portaddr & PORT_TOOG_MOD;
									idx = pkt.cancomm.data.wrport.portaddr & PORT_ADDR_MOD;

									if (toogle != g_rdstatoogle)	// 新状态
									{
										// 清空状态buff
										memset(g_extendCtrlList[i].stabuff, 0, sizeof(CORE_CHG_BUF_LEN));
										g_rdstatoogle = toogle;
										g_rdstabitmap = 0;
										g_extendCtrlList[i].stachangeflag = 0;
									//	printf("get new status begin, toogle=0x%x, idx=%d\r\n", toogle, idx);
									}

									if (idx < CORE_CHG_BUF_LEN)
									{
										g_extendCtrlList[i].stabuff[idx] = pkt.cancomm.data.wrport.wrdata;

										g_rdstabitmap |= IDX_TO_BIT[idx];
										if (g_rdstabitmap == CMDSTA_BMP_FULL)
										{
											g_extendCtrlList[i].stachangeflag = 1;		// 设置收到新命令状态
										//	printf("get new status ok\r\n");
										}
									}
								//	printf("refresh core %d status, toogle=0x%x, idx=%d, val=0x%x\r\n", i+1, toogle, idx, pkt.cancomm.data.wrport.wrdata);
									break;
								}
							}
						}
						else
						{
							//printf("get other core data, exid=0x%x\r\n", rxMsg.canRxhead.ExtId);
						}
					}
				}
#endif

#if (MAX_SUPPORT_HEAD > 0)
				else if (dev == BN_PROTOCOL_HEAD)		// 机头板
				{
					if (cmd == BN_CMD_EXSTA)
					{
						//printf("get head sta packet, sid=%d\r\n", sid);
						if (tid == g_curBoardID)
						{
							for (i = 0; i < MAX_SUPPORT_HEAD+1; i++)
							{
								if (sid == g_headList[i].nodeId)
								{
									g_headList[i].exbSta.cancomm.exId.id = rxMsg.canRxhead.ExtId;
									memcpy(g_headList[i].exbSta.cancomm.data.buff, rxMsg.data, CAN_DATA_LEN);
									g_headList[i].staFlag = 1;
									break;
								}
							}
						}
					}
					else if (cmd == BN_CMD_BUSSTA)	// 总线状态命令
					{
						printf("get head bus sta packet, sid=%d\r\n", sid);
						if (tid == g_curBoardID)
						{
							for (i = 0; i < MAX_SUPPORT_HEAD+1; i++)
							{
								if (sid == g_headList[i].nodeId)
								{
									g_headList[i].busSta.cancomm.exId.id = rxMsg.canRxhead.ExtId;
									memcpy(g_headList[i].busSta.cancomm.data.buff, rxMsg.data, CAN_DATA_LEN);
									g_headList[i].busFlag = 1;
									break;
								}
							}
						}
					}
					else if (cmd == BN_CMD_REGVAL)	// 读取寄存器命令
					{
						//printf("get head reg val packet, sid=%d, tid=%d\r\n", sid, tid);
						if (tid == g_curBoardID)
						{
							for (i = 0; i < MAX_SUPPORT_HEAD+1; i++)
							{
								if (sid == g_headList[i].nodeId)
								{
									memcpy(pkt.cancomm.data.buff, rxMsg.data, CAN_DATA_LEN);
									u32 highaddr, lowaddr;
									highaddr = pkt.cancomm.data.rdport.portaddr & PORT_ADDR_HIGH;
									lowaddr = pkt.cancomm.data.rdport.portaddr & PORT_ADDR_LOW;
									if (highaddr == BOARD_VERSION)
									{
										if (g_headList[i].regVal.rdnewbverflag == 1)		// 新程序版本
										{
											g_headList[i].regVal.rdbverbitmap = 0;
											g_headList[i].regVal.rdnewbverflag = 0;		// 清空
											g_headList[i].verFlag = 0;
											memset(g_headList[i].regVal.exbVer, 0, BOARD_VER_LEN*sizeof(u32));
										}
										if (lowaddr < BOARD_VER_LEN)
										{
											g_headList[i].regVal.exbVer[lowaddr] = pkt.cancomm.data.rdport.status;
											g_headList[i].regVal.rdbverbitmap |= IDX_TO_BIT[lowaddr];
											if (g_headList[i].regVal.rdbverbitmap == CMDSTA_BMP_FULL)
											{
												g_headList[i].verFlag = 1;
											}
										}
									}
									else if (highaddr == GET_NV_PARA)		// 读取参数
									{
										g_headList[i].headParaFlag = 1;
										headparaval = pkt.cancomm.data.rdport.status;
									}
									break;
								}
							}
						}
					}
#if (RD_HEAD_PARA_NUM > 0)
					else if (cmd == BN_CMD_NVPARA)		// 读取非易失性参数
					{
						if (tid == g_curBoardID)
						{
							for (i = 0; i < MAX_SUPPORT_HEAD+1; i++)
							{
								if (sid == g_headList[i].nodeId)
								{
									int id = 0;
									if (g_headList[i].nodeTye == FLAT_EMB_HEAD)
									{
										id = 1;
									}
									else if (g_headList[i].nodeTye == CHENILLE_HEAD)
									{
										id = 2;
									}
									else if (g_headList[i].nodeTye == COIL_HEAD)
									{
										id = 3;
									}
									int rslt = ReceiveBoardNvParaProc(rxMsg, id, g_headList[i].nodeTye);
									if (rslt == 0)
									{
										g_headList[i].nvParaFlag = 1;
									}
									break;
								}
							}
						}
					}
#endif
					else
					{
						printf("get other head data packet, exid=0x%x\r\n", rxMsg.canRxhead.ExtId);
					}
				}
#endif
#if (MAX_SUPPORT_COLOR > 0)
				else if (dev == BN_PROTOCOL_COLOR)
				{
					if (cmd == BN_CMD_EXSTA)
					{
						//printf("get color sta packet, sid=0x%x, tid=0x%x\r\n", sid, tid);
						if (tid == g_curBoardID)
						{
							for (i = 0; i < MAX_SUPPORT_COLOR+1; i++)
							{
								if (sid == g_colorList[i].nodeId)
								{
									g_colorList[i].exbSta.cancomm.exId.id = rxMsg.canRxhead.ExtId;
									memcpy(g_colorList[i].exbSta.cancomm.data.buff, rxMsg.data, CAN_DATA_LEN);
									g_colorList[i].staFlag = 1;
									break;
								}
							}
						}
					}
					else if (cmd == BN_CMD_REGVAL)	// 读取寄存器命令
					{
						//printf("get color reg val packet, sid=%d, tid=%d\r\n", sid, tid);
						if (tid == g_curBoardID)
						{
							for (i = 0; i < MAX_SUPPORT_COLOR+1; i++)
							{
								if (sid == g_colorList[i].nodeId)
								{
									memcpy(pkt.cancomm.data.buff, rxMsg.data, CAN_DATA_LEN);
									u32 highaddr, lowaddr;
									highaddr = pkt.cancomm.data.rdport.portaddr & PORT_ADDR_HIGH;
									lowaddr = pkt.cancomm.data.rdport.portaddr & PORT_ADDR_LOW;
									if (highaddr == BOARD_VERSION)
									{
										if (g_colorList[i].regVal.rdnewbverflag == 1)		// 新程序版本
										{
											g_colorList[i].regVal.rdbverbitmap = 0;
											g_colorList[i].regVal.rdnewbverflag = 0;		// 清空
											g_colorList[i].verFlag = 0;
											memset(g_colorList[i].regVal.exbVer, 0, BOARD_VER_LEN*sizeof(u32));
										}
										if (lowaddr < BOARD_VER_LEN)
										{
											g_colorList[i].regVal.exbVer[lowaddr] = pkt.cancomm.data.rdport.status;
											g_colorList[i].regVal.rdbverbitmap |= IDX_TO_BIT[lowaddr];
											if (g_colorList[i].regVal.rdbverbitmap == CMDSTA_BMP_FULL)
											{
												g_colorList[i].verFlag = 1;
											}
										}
									}
									break;
								}
							}
						}
					}
#if (RD_HEAD_PARA_NUM > 0)
					else if (cmd == BN_CMD_NVPARA)		// 读取非易失性参数
					{
						if (tid == g_curBoardID)
						{
							for (i = 0; i < MAX_SUPPORT_COLOR+1; i++)
							{
								if (sid == g_colorList[i].nodeId)
								{
									int id = 0;
									if (i == 2)	// 毛巾换色板
									{
										id = 4;
									}
									int rslt = ReceiveBoardNvParaProc(rxMsg, id, 0);
									if (rslt == 0)
									{
										g_colorList[i].nvParaFlag = 1;
									}
									break;
								}
							}
						}
					}
#endif
					else
					{
						printf("get other color data packet, exid=0x%x\r\n", rxMsg.canRxhead.ExtId);
					}
				}
#endif	// (MAX_SUPPORT_COLOR > 0)

#if (MAX_SUPPORT_EXTIO > 0)
				else if (dev == BN_PROTOCOL_EXTIO)
				{
					if (cmd == BN_CMD_EXSTA)
					{
						//printf("get extio sta packet, sid=0x%x, tid=0x%x\r\n", sid, tid);
						if (tid == g_curBoardID)
						{
							for (i = 0; i < MAX_SUPPORT_EXTIO+1; i++)
							{
								if (sid == g_extioList[i].nodeId)
								{
									g_extioList[i].exbSta.cancomm.exId.id = rxMsg.canRxhead.ExtId;
									memcpy(g_extioList[i].exbSta.cancomm.data.buff, rxMsg.data, CAN_DATA_LEN);
									g_extioList[i].staFlag = 1;
									break;
								}
							}
						}
					}
					else if (cmd == BN_CMD_REGVAL)	// 读取寄存器命令
					{
						//printf("get extio reg val packet, sid=%d, tid=%d\r\n", sid, tid);
						if (tid == g_curBoardID)
						{
							for (i = 0; i < MAX_SUPPORT_EXTIO+1; i++)
							{
								if (sid == g_extioList[i].nodeId)
								{
									memcpy(pkt.cancomm.data.buff, rxMsg.data, CAN_DATA_LEN);
									u32 highaddr, lowaddr;
									highaddr = pkt.cancomm.data.rdport.portaddr & PORT_ADDR_HIGH;
									lowaddr = pkt.cancomm.data.rdport.portaddr & PORT_ADDR_LOW;
									if (highaddr == BOARD_VERSION)
									{
										if (g_extioList[i].regVal.rdnewbverflag == 1)		// 新程序版本
										{
											g_extioList[i].regVal.rdbverbitmap = 0;
											g_extioList[i].regVal.rdnewbverflag = 0;		// 清空
											g_extioList[i].verFlag = 0;
											memset(g_extioList[i].regVal.exbVer, 0, BOARD_VER_LEN*sizeof(u32));
										}
										if (lowaddr < BOARD_VER_LEN)
										{
											g_extioList[i].regVal.exbVer[lowaddr] = pkt.cancomm.data.rdport.status;
											g_extioList[i].regVal.rdbverbitmap |= IDX_TO_BIT[lowaddr];
											if (g_extioList[i].regVal.rdbverbitmap == CMDSTA_BMP_FULL)
											{
												g_extioList[i].verFlag = 1;
											}
										}
									}
									break;
								}
							}
						}
					}
					else
					{
						printf("get other extio data packet, exid=0x%x\r\n", rxMsg.canRxhead.ExtId);
					}
				}
#endif	// (MAX_SUPPORT_EXTIO > 0)

#if (MAX_SUPPORT_SEWHD > 0)
				else if (dev == BN_PROTOCOL_SEWHD)
				{
					if (cmd == BN_CMD_EXSTA)
					{
						//printf("get color sta packet, sid=0x%x, tid=0x%x\r\n", sid, tid);
						if (tid == g_curBoardID)
						{
							for (i = 0; i < MAX_SUPPORT_SEWHD+1; i++)
							{
								if (sid == g_sewHeadList[i].nodeId)
								{
									g_sewHeadList[i].exbSta.cancomm.exId.id = rxMsg.canRxhead.ExtId;
									memcpy(g_sewHeadList[i].exbSta.cancomm.data.buff, rxMsg.data, CAN_DATA_LEN);
									g_sewHeadList[i].staFlag = 1;
									break;
								}
							}
						}
					}
					else if (cmd == BN_CMD_REGVAL)	// 读取寄存器命令
					{
						//printf("get color reg val packet, sid=%d, tid=%d\r\n", sid, tid);
						if (tid == g_curBoardID)
						{
							for (i = 0; i < MAX_SUPPORT_SEWHD+1; i++)
							{
								if (sid == g_sewHeadList[i].nodeId)
								{
									memcpy(pkt.cancomm.data.buff, rxMsg.data, CAN_DATA_LEN);
									u32 highaddr, lowaddr;
									highaddr = pkt.cancomm.data.rdport.portaddr & PORT_ADDR_HIGH;
									lowaddr = pkt.cancomm.data.rdport.portaddr & PORT_ADDR_LOW;
									if (highaddr == BOARD_VERSION)
									{
										if (g_sewHeadList[i].regVal.rdnewbverflag == 1)		// 新程序版本
										{
											g_sewHeadList[i].regVal.rdbverbitmap = 0;
											g_sewHeadList[i].regVal.rdnewbverflag = 0;		// 清空
											g_sewHeadList[i].verFlag = 0;
											memset(g_sewHeadList[i].regVal.exbVer, 0, BOARD_VER_LEN*sizeof(u32));
										}
										if (lowaddr < BOARD_VER_LEN)
										{
											g_sewHeadList[i].regVal.exbVer[lowaddr] = pkt.cancomm.data.rdport.status;
											g_sewHeadList[i].regVal.rdbverbitmap |= IDX_TO_BIT[lowaddr];
											if (g_sewHeadList[i].regVal.rdbverbitmap == CMDSTA_BMP_FULL)
											{
												g_sewHeadList[i].verFlag = 1;
											}
										}
									}
									break;
								}
							}
						}
					}
					else
					{
						printf("get other sew head data packet, exid=0x%x\r\n", rxMsg.canRxhead.ExtId);
					}
				}
#endif	// (MAX_SUPPORT_SEWHD > 0)

				else
				{
					printf("get other data packet, exid=0x%x\r\n", rxMsg.canRxhead.ExtId);
				}
			}
			else
			{
				printf("other packet,RTR=%d,ID=%x,DLC=%d\r\n", rxMsg.canRxhead.RTR, rxMsg.canRxhead.ExtId, rxMsg.canRxhead.DLC);
			}
		}
		else
		{
//			printf("no data");
			break;
		}
		count++;
		if (count > 10)
		{
			break;
		}
	}while(1);
}

void OutputsTask()
{
	CanTxMsg txMsg;
	int i, j;
	CtrlBusPacket pkt;

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

#if (MAX_SUPPORT_CORE > 0)
	// 发给其他核心主板的控制命令和本节点的状态命令
	for (i = 0; i < MAX_SUPPORT_CORE; i++)
	{
		if (g_curBoardIdx == i)		// 本节点的状态发送
		{
			if (g_extendCtrlList[i].refreshflag != 0)
			{
				if (g_extendCtrlList[i].ReSendStatus != NULL)
				{
					g_extendCtrlList[i].ReSendStatus(1);
				}

				g_extendCtrlList[i].refreshflag = 0;
				g_extendCtrlList[i].stachangeflag = 1;
			}
			if (g_extendCtrlList[i].stachangeflag != 0)
			{
				txMsg.canTxhead.ExtId = g_extendCtrlList[i].staexid;
				txMsg.canTxhead.RTR = CAN_RTR_DATA;			// 数据帧
				txMsg.canTxhead.IDE = CAN_ID_EXT;			// 扩展帧
				txMsg.canTxhead.DLC = CAN_DATA_LEN;			// 数据场长度

				for (j = 0; j < CORE_CHG_BUF_LEN; j++)
				{
					pkt.cancomm.data.wrport.portaddr = j | g_wrstatoogle;				// 地址
					pkt.cancomm.data.wrport.wrdata = g_extendCtrlList[i].stabuff[j];	// 数据
					memcpy(txMsg.data, pkt.cancomm.data.buff, CAN_DATA_LEN);			// 填充数据场
					SendACANDataPacket(&txMsg);
//					printf("send sta change, toogle=0x%x, idx=%d, sta=0x%x\r\n", g_wrstatoogle, j, pkt.cancomm.data.wrport.wrdata);
				}

				g_extendCtrlList[i].stachangeflag = 0;
				g_wrstatoogle += TOOGLE_ADD;
			}
		}
		else	// 其他节点的命令发送
		{
			if (g_extendCtrlList[i].newcmdflag != 0)
			{
				txMsg.canTxhead.ExtId = g_extendCtrlList[i].cmdexid;
				txMsg.canTxhead.RTR = CAN_RTR_DATA;			// 数据帧
				txMsg.canTxhead.IDE = CAN_ID_EXT;				// 扩展帧
				txMsg.canTxhead.DLC = CAN_DATA_LEN;			// 数据场长度

				for (j = 0; j < CORE_CHG_BUF_LEN; j++)
				{
					pkt.cancomm.data.wrport.portaddr = j | g_wrcmdtoogle;				// 地址
					pkt.cancomm.data.wrport.wrdata = g_extendCtrlList[i].cmdbuff[j];	// 数据
					memcpy(txMsg.data, pkt.cancomm.data.buff, CAN_DATA_LEN);			// 填充数据场
					SendACANDataPacket(&txMsg);
//					printf("send cmd, toogle=0x%x, idx=%d, sta=0x%x\r\n", g_wrcmdtoogle, j, pkt.cancomm.data.wrport.wrdata);
				}

				g_extendCtrlList[i].newcmdflag = 0;
				g_wrcmdtoogle += TOOGLE_ADD;
			}
		}
	}
#endif

#if (MAX_SUPPORT_HEAD > 0)
	for (i = 0; i < MAX_SUPPORT_HEAD+1; i++)
	{
		if (g_headList[i].cmdFlag != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_HEAD, g_headList[i].nodeId, g_curBoardID, BN_CMD_EXCTRL);
			txMsg.canTxhead.RTR = CAN_RTR_DATA;			// 数据帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;				// 扩展帧
			txMsg.canTxhead.DLC = CAN_DATA_LEN;			// 数据场长度
			memcpy(txMsg.data, g_headList[i].ctrlCmd.cancomm.data.buff, CAN_DATA_LEN);	// 填充数据场
			SendACANDataPacket(&txMsg);
			g_headList[i].cmdFlag = 0;
		}

		if (g_headList[i].refSta != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_HEAD, g_headList[i].nodeId, g_curBoardID, BN_CMD_EXSTA);
			txMsg.canTxhead.RTR = CAN_RTR_REMOTE;				// 远程帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;					// 扩展帧
			txMsg.canTxhead.DLC = 0;							// 数据场长度
			memset(txMsg.data, 0, CAN_DATA_LEN);	// 填充数据场
			SendACANDataPacket(&txMsg);				// 发送远程帧
			g_headList[i].refSta = 0;
		}

		if (g_headList[i].refVer != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_HEAD, g_headList[i].nodeId, g_curBoardID, BN_CMD_REGVAL);
			txMsg.canTxhead.RTR = CAN_RTR_DATA;				// 数据帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;					// 扩展帧
			txMsg.canTxhead.DLC = CAN_DATA_LEN;				// 数据场长度
			memset(&g_headList[i].rdReg.cancomm.data.buff, 0, CAN_DATA_LEN);
			g_headList[i].rdReg.cancomm.data.rdport.portaddr = BOARD_VERSION;
			memcpy(txMsg.data, g_headList[i].rdReg.cancomm.data.buff, CAN_DATA_LEN);	// 填充数据场
			SendACANDataPacket(&txMsg);				// 发送
			g_headList[i].refVer = 0;
		}

		if (g_headList[i].traFlag != 0)		// 遍历命令
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_HEAD, g_headList[i].nodeId, g_curBoardID, BN_CMD_TRAVERSE);
			txMsg.canTxhead.RTR = CAN_RTR_DATA;			// 数据帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;				// 扩展帧
			txMsg.canTxhead.DLC = CAN_DATA_LEN;			// 数据场长度
			memcpy(txMsg.data, g_headList[i].traCmd.cancomm.data.buff, CAN_DATA_LEN);	// 填充数据场
			SendACANDataPacket(&txMsg);
			g_headList[i].traFlag = 0;
		}

		if (g_headList[i].transFlag != 0)	// 数据传输命令
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_HEAD, g_headList[i].nodeId, g_curBoardID, BN_CMD_TRANS_DATA);
			ExboardDataTrans(txMsg.canTxhead.ExtId);
			g_headList[i].transFlag = 0;
		}

		if (g_headList[i].exbupdateFlag != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_HEAD, g_headList[i].nodeId, g_curBoardID, BN_CMD_REGVAL);
			txMsg.canTxhead.RTR = CAN_RTR_DATA;					// 数据帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;					// 扩展帧
			txMsg.canTxhead.DLC = CAN_DATA_LEN;					// 数据场长度
			memcpy(txMsg.data, g_headList[i].rdReg.cancomm.data.buff, CAN_DATA_LEN);	// 填充数据场
			SendACANDataPacket(&txMsg);				// 发送远程帧
			g_headList[i].exbupdateFlag = 0;
		}

		if (g_headList[i].refNvPara != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_HEAD, g_headList[i].nodeId, g_curBoardID, BN_CMD_NVPARA);
			txMsg.canTxhead.RTR = CAN_RTR_REMOTE;				// 远程帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;					// 扩展帧
			txMsg.canTxhead.DLC = 0;							// 数据场长度
			memset(txMsg.data, 0, CAN_DATA_LEN);	// 填充数据场
			SendACANDataPacket(&txMsg);				// 发送远程帧
			g_headList[i].refNvPara = 0;
		}

		if (g_headList[i].refHeadPara != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_HEAD, g_headList[i].nodeId, g_curBoardID, BN_CMD_REGVAL);
			txMsg.canTxhead.RTR = CAN_RTR_DATA;				// 远程帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;					// 扩展帧
			txMsg.canTxhead.DLC = CAN_DATA_LEN;							// 数据场长度
			memcpy(txMsg.data, g_headList[i].rdReg.cancomm.data.buff, CAN_DATA_LEN);	// 填充数据场
			SendACANDataPacket(&txMsg);				// 发送远程帧
			g_headList[i].refHeadPara = 0;
		}

	}
#endif
	
#if (MAX_SUPPORT_COLOR > 0)
	for (i = 0; i < MAX_SUPPORT_COLOR+1; i++)
	{
		if (g_colorList[i].cmdFlag != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_COLOR, g_colorList[i].nodeId, g_curBoardID, BN_CMD_EXCTRL);
			txMsg.canTxhead.RTR = CAN_RTR_DATA;			// 数据帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;				// 扩展帧
			txMsg.canTxhead.DLC = CAN_DATA_LEN;			// 数据场长度
			memcpy(txMsg.data, g_colorList[i].ctrlCmd.cancomm.data.buff, CAN_DATA_LEN);	// 填充数据场
			SendACANDataPacket(&txMsg);
			g_colorList[i].cmdFlag = 0;
		}

		if (g_colorList[i].refSta != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_COLOR, g_colorList[i].nodeId, g_curBoardID, BN_CMD_EXSTA);
			txMsg.canTxhead.RTR = CAN_RTR_REMOTE;				// 远程帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;					// 扩展帧
			txMsg.canTxhead.DLC = 0;							// 数据场长度
			memset(txMsg.data, 0, CAN_DATA_LEN);	// 填充数据场
			SendACANDataPacket(&txMsg);				// 发送远程帧
			g_colorList[i].refSta = 0;
		}

		if (g_colorList[i].refVer != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_COLOR, g_colorList[i].nodeId, g_curBoardID, BN_CMD_REGVAL);
			txMsg.canTxhead.RTR = CAN_RTR_DATA;				// 数据帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;					// 扩展帧
			txMsg.canTxhead.DLC = CAN_DATA_LEN;				// 数据场长度
			memset(&g_colorList[i].rdReg.cancomm.data.buff, 0, CAN_DATA_LEN);
			g_colorList[i].rdReg.cancomm.data.rdport.portaddr = BOARD_VERSION;
			memcpy(txMsg.data, g_colorList[i].rdReg.cancomm.data.buff, CAN_DATA_LEN);	// 填充数据场
			SendACANDataPacket(&txMsg);				// 发送
			g_colorList[i].refVer = 0;
		}

		if (g_colorList[i].transFlag != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_COLOR, g_colorList[i].nodeId, g_curBoardID, BN_CMD_TRANS_DATA);
			ExboardDataTrans(txMsg.canTxhead.ExtId);
			g_colorList[i].transFlag = 0;
		}

		if (g_colorList[i].exbupdateFlag != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_COLOR, g_colorList[i].nodeId, g_curBoardID, BN_CMD_REGVAL);
			txMsg.canTxhead.RTR = CAN_RTR_DATA;				// 远程帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;				// 扩展帧
			txMsg.canTxhead.DLC = CAN_DATA_LEN;				// 数据场长度
			memcpy(txMsg.data, g_colorList[i].rdReg.cancomm.data.buff, CAN_DATA_LEN);	// 填充数据场
			SendACANDataPacket(&txMsg);				// 发送远程帧
			g_colorList[i].exbupdateFlag = 0;
		}

		if (g_colorList[i].refNvPara != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_COLOR, g_colorList[i].nodeId, g_curBoardID, BN_CMD_NVPARA);
			txMsg.canTxhead.RTR = CAN_RTR_REMOTE;				// 远程帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;					// 扩展帧
			txMsg.canTxhead.DLC = 0;							// 数据场长度
			memset(txMsg.data, 0, CAN_DATA_LEN);	// 填充数据场
			SendACANDataPacket(&txMsg);				// 发送远程帧
			g_colorList[i].refNvPara = 0;
		}
	}
#endif
	
#if (MAX_SUPPORT_EXTIO > 0)
	for (i = 0; i < MAX_SUPPORT_EXTIO+1; i++)
	{
		if (g_extioList[i].cmdFlag != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_EXTIO, g_extioList[i].nodeId, g_curBoardID, BN_CMD_EXCTRL);
			txMsg.canTxhead.RTR = CAN_RTR_DATA;			// 数据帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;				// 扩展帧
			txMsg.canTxhead.DLC = CAN_DATA_LEN;			// 数据场长度
			memcpy(txMsg.data, g_extioList[i].ctrlCmd.cancomm.data.buff, CAN_DATA_LEN);	// 填充数据场
			SendACANDataPacket(&txMsg);
			g_extioList[i].cmdFlag = 0;
		}

		if (g_extioList[i].refSta != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_EXTIO, g_extioList[i].nodeId, g_curBoardID, BN_CMD_EXSTA);
			txMsg.canTxhead.RTR = CAN_RTR_REMOTE;				// 远程帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;					// 扩展帧
			txMsg.canTxhead.DLC = 0;							// 数据场长度
			memset(txMsg.data, 0, CAN_DATA_LEN);	// 填充数据场
			SendACANDataPacket(&txMsg);				// 发送远程帧
			g_extioList[i].refSta = 0;
		}

		if (g_extioList[i].refVer != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_EXTIO, g_extioList[i].nodeId, g_curBoardID, BN_CMD_REGVAL);
			txMsg.canTxhead.RTR = CAN_RTR_DATA;				// 数据帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;					// 扩展帧
			txMsg.canTxhead.DLC = CAN_DATA_LEN;				// 数据场长度
			memset(&g_extioList[i].rdReg.cancomm.data.buff, 0, CAN_DATA_LEN);
			g_extioList[i].rdReg.cancomm.data.rdport.portaddr = BOARD_VERSION;
			memcpy(txMsg.data, g_extioList[i].rdReg.cancomm.data.buff, CAN_DATA_LEN);	// 填充数据场
			SendACANDataPacket(&txMsg);				// 发送
			g_extioList[i].refVer = 0;
		}

		if (g_extioList[i].transFlag != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_EXTIO, g_extioList[i].nodeId, g_curBoardID, BN_CMD_TRANS_DATA);
			ExboardDataTrans(txMsg.canTxhead.ExtId);
			g_extioList[i].transFlag = 0;
		}

		if (g_extioList[i].exbupdateFlag != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_EXTIO, g_extioList[i].nodeId, g_curBoardID, BN_CMD_REGVAL);
			txMsg.canTxhead.RTR = CAN_RTR_DATA;				// 远程帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;				// 扩展帧
			txMsg.canTxhead.DLC = CAN_DATA_LEN;				// 数据场长度
			memcpy(txMsg.data, g_extioList[i].rdReg.cancomm.data.buff, CAN_DATA_LEN);	// 填充数据场
			SendACANDataPacket(&txMsg);				// 发送远程帧
			g_extioList[i].exbupdateFlag = 0;
		}
	}
#endif

#if (MAX_SUPPORT_SEWHD > 0)
	for (i = 0; i < MAX_SUPPORT_SEWHD+1; i++)
	{
		if (g_sewHeadList[i].cmdFlag != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_SEWHD, g_sewHeadList[i].nodeId, g_curBoardID, BN_CMD_EXCTRL);
			txMsg.canTxhead.RTR = CAN_RTR_DATA;			// 数据帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;				// 扩展帧
			txMsg.canTxhead.DLC = CAN_DATA_LEN;			// 数据场长度
			memcpy(txMsg.data, g_sewHeadList[i].ctrlCmd.cancomm.data.buff, CAN_DATA_LEN);	// 填充数据场
			SendACANDataPacket(&txMsg);
			g_sewHeadList[i].cmdFlag = 0;
		}

		if (g_sewHeadList[i].refSta != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_SEWHD, g_sewHeadList[i].nodeId, g_curBoardID, BN_CMD_EXSTA);
			txMsg.canTxhead.RTR = CAN_RTR_REMOTE;				// 远程帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;					// 扩展帧
			txMsg.canTxhead.DLC = 0;							// 数据场长度
			memset(txMsg.data, 0, CAN_DATA_LEN);	// 填充数据场
			SendACANDataPacket(&txMsg);				// 发送远程帧
			g_sewHeadList[i].refSta = 0;
		}

		if (g_sewHeadList[i].refVer != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_SEWHD, g_sewHeadList[i].nodeId, g_curBoardID, BN_CMD_REGVAL);
			txMsg.canTxhead.RTR = CAN_RTR_DATA;				// 数据帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;					// 扩展帧
			txMsg.canTxhead.DLC = CAN_DATA_LEN;				// 数据场长度
			memset(&g_sewHeadList[i].rdReg.cancomm.data.buff, 0, CAN_DATA_LEN);
			g_sewHeadList[i].rdReg.cancomm.data.rdport.portaddr = BOARD_VERSION;
			memcpy(txMsg.data, g_sewHeadList[i].rdReg.cancomm.data.buff, CAN_DATA_LEN);	// 填充数据场
			SendACANDataPacket(&txMsg);				// 发送
			g_sewHeadList[i].refVer = 0;
		}

		if (g_sewHeadList[i].transFlag != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_SEWHD, g_sewHeadList[i].nodeId, g_curBoardID, BN_CMD_TRANS_DATA);
			ExboardDataTrans(txMsg.canTxhead.ExtId);
			g_sewHeadList[i].transFlag = 0;
		}

		if (g_sewHeadList[i].exbupdateFlag != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_SEWHD, g_sewHeadList[i].nodeId, g_curBoardID, BN_CMD_REGVAL);
			txMsg.canTxhead.RTR = CAN_RTR_DATA;				// 远程帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;				// 扩展帧
			txMsg.canTxhead.DLC = CAN_DATA_LEN;				// 数据场长度
			memcpy(txMsg.data, g_sewHeadList[i].rdReg.cancomm.data.buff, CAN_DATA_LEN);	// 填充数据场
			SendACANDataPacket(&txMsg);				// 发送远程帧
			g_sewHeadList[i].exbupdateFlag = 0;
		}

		if (g_sewHeadList[i].refNvPara != 0)
		{
			txMsg.canTxhead.ExtId = MAKE_EXID(BN_PROTOCOL_SEWHD, g_sewHeadList[i].nodeId, g_curBoardID, BN_CMD_NVPARA);
			txMsg.canTxhead.RTR = CAN_RTR_REMOTE;				// 远程帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;					// 扩展帧
			txMsg.canTxhead.DLC = 0;							// 数据场长度
			memset(txMsg.data, 0, CAN_DATA_LEN);	// 填充数据场
			SendACANDataPacket(&txMsg);				// 发送远程帧
			g_sewHeadList[i].refNvPara = 0;
		}
	}
#endif

}

void ExtendBoardTask(void)
{
	InputsTask();
	OutputsTask();
}

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

CoreControl * GetCoreFromList(u8 id)
{
#if (MAX_SUPPORT_CORE > 0)
	if (id > 0 && id <= MAX_SUPPORT_CORE)
	{
		return &(g_extendCtrlList[id-1]);
	}
	else
#endif
	{
		return NULL;
	}
}

HeadControl * GetHeadFromList(u8 id)
{
#if (MAX_SUPPORT_HEAD > 0)
	if (id > 0 && id <= MAX_SUPPORT_HEAD+1)
	{
		return &(g_headList[id-1]);
	}
	else
#endif
	{
		return NULL;
	}
}

ColorControl * GetColorFromList(u8 id)
{
#if (MAX_SUPPORT_COLOR > 0)
	if (id > 0 && id <= MAX_SUPPORT_COLOR+1)
	{
		return &(g_colorList[id-1]);
	}
	else
#endif
	{
		return NULL;
	}
}

ExtIOControl * GetExtIOFromList(u8 id)
{
#if (MAX_SUPPORT_EXTIO > 0)
	if (id > 0 && id <= MAX_SUPPORT_EXTIO+1)
	{
		return &(g_extioList[id-1]);
	}
	else
#endif
	{
		return NULL;
	}
}

int GetCurBoardID(void)
{
	return g_curBoardID;
}

//------------------------------------------------------------------------
#if (MAX_SUPPORT_CORE > 0)

int IsNewControlCommand(void)
{
	if (g_extendCtrlList[g_curBoardIdx].newcmdflag != 0)
	{
		printf("can data inter\r\n");
		return TRUE;
	}
	return FALSE;
}

// 请求其他板子发送状态
void RequestExStatus(void)
{
	CanTxMsg txMsg;
	int i;
	for (i = 0; i < MAX_SUPPORT_CORE; i++)
	{
		if (g_curBoardIdx != i)		// 其他点的状态请求
		{
			txMsg.canTxhead.ExtId = g_extendCtrlList[i].staexid;
			txMsg.canTxhead.RTR = CAN_RTR_REMOTE;					// 远程帧
			txMsg.canTxhead.IDE = CAN_ID_EXT;						// 扩展帧
			txMsg.canTxhead.DLC = 0;								// 数据场长度
			memset(txMsg.data, 0, CAN_DATA_LEN);		// 填充数据场
			SendACANDataPacket(&txMsg);					// 发送远程帧
		}
	}
}
#endif

//-------------------------------------------------------------------------
// 机头板协议,上位机不需要知道对应的节点ID,只需告知节点类型和机头号即可
// 换色板协议 需告知第几块板卡
// IO扩展板协议 需告知第几块板卡
void StartBoardUpdate(u8 protocol, u8 nodetype, u8 nodeid)
{
#if (MAX_SUPPORT_HEAD > 0)
	if (protocol == BN_PROTOCOL_HEAD)
	{
		HeadControl * head = GetHeadFromList(1);		// 默认广播发送
		HeadControl * temp = NULL;					// 临时存储
		if (nodeid != 0)
		{
			for(int i = 1; i < MAX_SUPPORT_HEAD+1; i++)
			{
				temp = GetHeadFromList(i+1);
				if (temp->nodeTye == nodetype)
				{
					if (nodeid <= 1)
					{
						head = temp;
						break;
					}
					else
					{
						nodeid--;
					}
				}
			}
		}
		head->rdReg.cancomm.data.rdport.portaddr = EXBOARD_UPDATE;
		head->rdReg.cancomm.data.rdport.status = nodetype;
		head->exbupdateFlag = 1;
	}
	else
#endif
#if (MAX_SUPPORT_COLOR > 0)
	if (protocol == BN_PROTOCOL_COLOR)
	{
		ColorControl * color = GetColorFromList(nodeid+1);
		color->exbupdateFlag = 1;
	}
	else
#endif
#if (MAX_SUPPORT_EXTIO > 0)
	if (protocol == BN_PROTOCOL_EXTIO)
	{
		ExtIOControl * extio = GetExtIOFromList(nodeid+1);
		extio->exbupdateFlag = 1;
	}
	else
#endif
	{
	}
}

// 设置外围板非易失性参数
void SetBoardNvPara(int protocolType, int nodetype, int nodeId, u8 parablockID, u8 paraID, s32 paraVal)
{
#if (MAX_SUPPORT_HEAD > 0)
	if (protocolType == BN_PROTOCOL_HEAD)
	{
		SetHeadNvParaCmd(nodetype, nodeId, parablockID, paraID, paraVal);
	}
	else
#endif
#if (MAX_SUPPORT_COLOR > 0)
	if (protocolType == BN_PROTOCOL_COLOR)
	{
		if (nodeId != 0)	// 20220628 不支持广播设置,因为界面存在乱发命令的情况
		{
			SetColorNvParaCmd(nodeId, parablockID, paraID, paraVal);
		}
	}
	else
#endif
	{
	}
}

//-------------------------------------------------------------------------
#if (MAX_SUPPORT_HEAD > 0)

// 进入遍历状态
void EnterTraverse(void)
{
	memset(&g_headList[0].traCmd.cancomm.data, 0, CAN_DATA_LEN);

	g_headList[0].traCmd.cancomm.data.traverse.tracmd = TRA_CMD_ENTER_TRA;

	g_headList[0].traFlag = 1;

	OutputsTask();
}

/* function:总线遍历
 * return:	0:
 * 			-1: 参数错误
*/
int TraverseSingleNode(u8 traNodeType, u8 traNodeId)
{
	printf("traverse nodeid=%d, nodetype=%d\r\n", traNodeId, traNodeType);

	memset(&g_headList[0].traCmd.cancomm.data, 0, CAN_DATA_LEN);

	g_headList[0].traCmd.cancomm.data.traverse.tracmd = TRA_CMD_NODE_TRA_BEG;
	g_headList[0].traCmd.cancomm.data.traverse.nodetype = traNodeType;
	g_headList[0].traCmd.cancomm.data.traverse.nodeid = traNodeId;

	g_headList[0].traFlag = 1;

	OutputsTask();

	return 0;
}

/* function:当前节点已遍历,返回确认数据包
 * return:	0:
*/
int CurNodeTraverseAlready(u32 nodeid)
{
	printf("nodeid %d already set\r\n", nodeid);

	for(int i = 1; i < MAX_SUPPORT_HEAD+1; i++)
	{
		if(g_headList[i].nodeId == nodeid)
		{
			memset(&g_headList[i].traCmd.cancomm.data, 0, CAN_DATA_LEN);
			g_headList[i].traCmd.cancomm.data.traverse.tracmd = TRA_CMD_NODE_TRA_END;
			g_headList[i].traCmd.cancomm.data.traverse.nodeid = nodeid;
			g_headList[i].traFlag = 1;
			break;
		}
	}
	OutputsTask();
	return 0;
}


void ExitTravers()						// 退出遍历
{
	memset(&g_headList[0].traCmd.cancomm.data, 0, CAN_DATA_LEN);

	g_headList[0].traCmd.cancomm.data.traverse.tracmd = TRA_CMD_EXIT_TRA;
	g_headList[0].traFlag = 1;

	OutputsTask();

	printf("exit traverse\r\n");
}

//---------------------------------------------------
// 请求总线状态
void InquireBusSta(int idx)
{
	memset(&g_headList[idx].traCmd.cancomm.data, 0, CAN_DATA_LEN);

	g_headList[idx].traCmd.cancomm.data.traverse.tracmd = TRA_CMD_ASK_TRA_STA;

	g_headList[idx].traFlag = 1;

	OutputsTask();

	printf("inquire bus sta, idx=%d\r\n", idx);
}

u32 GetHeadStatus(int idx)
{
	u32 sta;

	HeadCommand * pSta;
	if (idx > 0 && idx <= MAX_SUPPORT_HEAD)
	{
		pSta = (HeadCommand *)( &(g_headList[idx].exbSta.cancomm.data.buff));
		sta = pSta->headSta.staBits;
	}
	else
	{
		sta = 0;
	}
	return sta;
}

void CleanHeadStatus(int idx)
{
	HeadCommand * pSta;
	if (idx > 0 && idx <= MAX_SUPPORT_HEAD)
	{
		pSta = (HeadCommand *)( &(g_headList[idx].exbSta.cancomm.data.buff));
		pSta->headSta.staBits = 0;
	}
}

void RequestHeadsStatus(void)
{
	RequestHeadStatus(&(g_headList[0]));		// 发送广播命令
	OutputsTask();
}

void RequestHeadsVersion(void)
{
	RequestHeadVersion(&(g_headList[0]));		// 广播询问

	for(int i = 1; i < MAX_SUPPORT_HEAD+1; i++)
	{
		g_headList[i].regVal.rdnewbverflag = 1;
	}
}

void RequestAHeadNvPara(int idx)
{
	if (idx <= 0)
	{
		return;
	}
	RequestHeadNvPara(&(g_headList[idx]));
}

// 设置主轴角度
void SendHeadAngCmd(int idx, u8 para1, u16 para2, u8 para3)
{
	HeadCommand ncmd;
	memset(&ncmd, 0, sizeof(HeadCommand));
	ncmd.setmsang.cmd = CTRL_CMD_HEAD_MSANG;
	ncmd.setmsang.validFlag = para1;
	ncmd.setmsang.msang = para2;
	ncmd.setmsang.nodetype = para3;
	SendHeadCommand(&g_headList[idx], &ncmd);	// 节点命令

	OutputsTask();						// 刷新输入输出
}

// 设置机头板非易失性参数
void SetHeadNvParaCmd(int nodetype, int idx, u8 parablockid, u8 paraid, s32 paraval)
{
	if (idx < 0 || idx > MAX_SUPPORT_HEAD)
	{
		return;
	}
	HeadCommand ncmd;

	memset(&ncmd, 0, sizeof(HeadCommand));
	if (nodetype == FLAT_EMB_HEAD)
	{
		ncmd.headNvPara.cmd = CTRL_CMD_HEAD_NVPARA;
	}
	else if (nodetype == CHENILLE_HEAD)
	{
		ncmd.headNvPara.cmd = CTRL_CMD_CHENILLE_NVPARA;
	}
	else if (nodetype == COIL_HEAD)
	{
		ncmd.headNvPara.cmd = CTRL_CMD_COIL_NVPARA;
	}
	ncmd.headNvPara.parablockID = parablockid;
	ncmd.headNvPara.paraID = paraid;
	ncmd.headNvPara.paraval = paraval;

	SendHeadCommand(&g_headList[idx], &ncmd);	// 节点命令

	OutputsTask();						// 刷新输入输出
}

u16 GetHeadPotValue(int idx)
{
	u32 sta;

	HeadCommand * pSta;
	if (idx > 0 && idx <= MAX_SUPPORT_HEAD)
	{
		pSta = (HeadCommand *)( &(g_headList[idx].exbSta.cancomm.data.buff));
		sta = pSta->headSta.potValue;
	}
	else
	{
		sta = 0;
	}
	return sta;
}

int GetHeadCurrentNeele(int idx)
{
	u32 sta;

	HeadCommand * pSta;
	if (idx > 0 && idx <= MAX_SUPPORT_HEAD)
	{
		pSta = (HeadCommand *)( &(g_headList[idx].exbSta.cancomm.data.buff));
		sta = pSta->headSta.setedNP;
	}
	else
	{
		sta = 0;
	}
	return sta;
}
#endif
//-------------------------------------------------------------------------

#if (MAX_SUPPORT_COLOR > 0)

void RequestColorsVersion(void)
{
	RequestColorVersion(&(g_colorList[0]));
	for(int i = 1; i < MAX_SUPPORT_COLOR+1; i++)
	{
		g_colorList[i].regVal.rdnewbverflag = 1;
	}
}

void RequestAColorNvPara(int idx)
{
	if (idx <= 0)
	{
		return;
	}

	RequestColorNvPara(&(g_colorList[idx]));
}

void SendColorCtrlCmd(int idx, u8 subcmd, u8 para1, u8 para2)
{
	ColorCommand ncmd;

	memset(&ncmd, 0, sizeof(ColorCommand));
	ncmd.colorCtrl.cmd = CTRL_CMD_COLOR_CTRL;
	ncmd.colorCtrl.subcmd = subcmd;
	ncmd.colorCtrl.para[0] = para1;
	ncmd.colorCtrl.para[1] = para2;

	SendColorCommand(&g_colorList[idx], &ncmd);	// 节点命令
	OutputsTask();						// 刷新输入输出
}

// 设置换色板非易失性参数
void SetColorNvParaCmd(int idx, u8 parablockid, u8 paraid, s32 paraval)
{
	if (idx < 0 || idx > MAX_SUPPORT_COLOR)
	{
		return;
	}

	ColorCommand ncmd;

	memset(&ncmd, 0, sizeof(ColorCommand));
	ncmd.colorNvPara.cmd = CTRL_CMD_COLOR_NVPARA;
	ncmd.colorNvPara.parablockID = parablockid;
	ncmd.colorNvPara.paraID = paraid;
	ncmd.colorNvPara.paraval = paraval;

	SendColorCommand(&g_colorList[idx], &ncmd);	// 节点命令
	OutputsTask();						// 刷新输入输出
}

void SendColorParaCmd(int idx, u8 para1)
{
	ColorCommand ncmd;
	memset(&ncmd, 0, sizeof(ColorCommand));
	ncmd.colorPara.cmd = CTRL_CMD_COLOR_PARA;
	ncmd.colorPara.needleNums = para1;
	SendColorCommand(&g_colorList[idx], &ncmd);	// 节点命令
	OutputsTask();						// 刷新输入输出
}

void CleanColorSta(int idx)
{
	memset(&(g_colorList[idx].exbSta.cancomm.data.buff), 0, CAN_DATA_LEN);
}

u16 GetColorStatus(int idx)
{
	u16 sta;
	ColorCommand * pSta;
	pSta = (ColorCommand *)( &(g_colorList[idx].exbSta.cancomm.data.buff));
	sta = pSta->colorSta.staBits;

	return sta;
}

u16 GetColorPotValue(int idx)
{
	u16 sta;
	ColorCommand * pSta;
	pSta = (ColorCommand *)( &(g_colorList[idx].exbSta.cancomm.data.buff));
	sta = pSta->colorSta.potValue;

	return sta;
}

int GetColorCurrentNeele(int idx)
{
	int sta;
	ColorCommand * pSta;
	pSta = (ColorCommand *)( &(g_colorList[idx].exbSta.cancomm.data.buff));
	sta = (int)pSta->colorSta.curNeedle;

	return sta;
}

void RequestColorsStatus(void)
{
	RequestColorStatus(&(g_colorList[0]));		// 发送广播命令
	OutputsTask();
}

#endif

#if (MAX_SUPPORT_EXTIO > 0)

u16 GetExtIOStatus(int idx)
{
	u16 sta;
	ExtIOCommand * pSta;
	if (idx > 0 && idx <= MAX_SUPPORT_EXTIO)
	{
		pSta = (ExtIOCommand *)( &(g_extioList[idx].exbSta.cancomm.data.buff));
		sta = pSta->extIOSta.inputSta;
	}
	else
	{
		sta = 0;
	}
	return sta;
}

void CleanExtIOStatus(int idx)
{
	ExtIOCommand * pSta;
	if (idx > 0 && idx <= MAX_SUPPORT_EXTIO)
	{
		pSta = (ExtIOCommand *)( &(g_extioList[idx].exbSta.cancomm.data.buff));
		pSta->extIOSta.inputSta = 0;
	}
}

void RequestExtIOsStatus(void)
{
	RequestExtIOStatus(&(g_extioList[0]));		// 发送广播命令
	OutputsTask();
}

void RequestExtIOsVersion(void)
{
	RequestExtIOVersion(&(g_extioList[0]));		// 广播询问

	for(int i = 1; i < MAX_SUPPORT_EXTIO+1; i++)
	{
		g_extioList[i].regVal.rdnewbverflag = 1;
	}
}

void SetExtOutputOn(int idx, u16 bit)
{
	ExtIOCommand ncmd;
	memset(&ncmd, 0, sizeof(ExtIOCommand));
	ncmd.extIOCtrl.cmd = CTRL_CMD_EXTIO_CTRL;
	ncmd.extIOCtrl.subcmd = CTRL_SUBCMD_OUT_ON;
	ncmd.extIOCtrl.outctrl = bit;

	SendExtIOCommand(&g_extioList[idx], &ncmd);
	OutputsTask();						// 刷新输入输出
}

void SetExtOutputOff(int idx, u16 bit)
{
	ExtIOCommand ncmd;
	memset(&ncmd, 0, sizeof(ExtIOCommand));
	ncmd.extIOCtrl.cmd = CTRL_CMD_EXTIO_CTRL;
	ncmd.extIOCtrl.subcmd = CTRL_SUBCMD_OUT_OFF;
	ncmd.extIOCtrl.outctrl = bit;

	SendExtIOCommand(&g_extioList[idx], &ncmd);
	OutputsTask();						// 刷新输入输出
}

#endif

#if (MAX_SUPPORT_SEWHD > 0)
void RequestSewHeadsStatus(void)
{
	RequestSewHeadStatus(&(g_sewHeadList[0]));		// 发送广播命令
	OutputsTask();
}

void RequestSewHeadsVersion(void)
{
	RequestSewHeadVersion(&(g_sewHeadList[0]));
	for(int i = 1; i < MAX_SUPPORT_SEWHD+1; i++)
	{
		g_sewHeadList[i].regVal.rdnewbverflag = 1;
	}
}

void CleanSewHeadSta(int idx)
{
	memset(&(g_sewHeadList[idx].exbSta.cancomm.data.buff), 0, CAN_DATA_LEN);
}

u16 GetSewHeadStatus(int idx)
{
	u16 sta;
	SewHeadCommand * pSta;
	pSta = (SewHeadCommand *)( &(g_sewHeadList[idx].exbSta.cancomm.data.buff));
	sta = pSta->headSta.staBits;

	return sta;
}

void SendSewHeadCtrlCmd(int idx, u8 subcmd, u8 para1, u8 para2)
{
	SewHeadCommand ncmd;

	memset(&ncmd, 0, sizeof(SewHeadCommand));
	ncmd.headCtrl.cmd = CTRL_CMD_SEW_HEAD_CTRL;
	ncmd.headCtrl.subcmd = subcmd;
	ncmd.headCtrl.para[0] = para1;
	ncmd.headCtrl.para[1] = para2;

	SendSewHeadCommand(&g_sewHeadList[idx], &ncmd);	// 节点命令
	OutputsTask();						// 刷新输入输出
}
#endif

#if (RD_HEAD_PARA_NUM > 0)
/*
 *  0:接收完成且正确
 * -1:接收未完成
 * -2:CRC校验错误
 * -3:参数错误
 */
int ReceiveBoardNvParaProc(CanRxMsg rxMsg, int id, u8 nodetype)
{
	if (id < 1 || id > RD_HEAD_PARA_NUM)
	{
		return -3;
	}

	BoardFileCanCtrl * rxbuf = (BoardFileCanCtrl*)(&rxMsg.data);
	int rslt = -1;
	if ( rxbuf->head.sync[0] == CDP_SYNC[0] &&
		 rxbuf->head.sync[1] == CDP_SYNC[1] &&
		 rxbuf->head.sync[2] == CDP_SYNC[2] &&
		1 )		// 判断是否为数据包头
	{
		if ((nodetype == FLAT_EMB_HEAD && rxbuf->head.pktId == 0) ||	// 平绣机头板参数
				(nodetype == CHENILLE_HEAD && rxbuf->head.pktId == 1) ||	// 毛巾机头板参数
				(nodetype == COIL_HEAD && rxbuf->head.pktId == 2) ||	// 缠绕机头板参数
				(nodetype == 0 && rxbuf->head.pktId == 3) ||			// 毛巾换色板参数
				0)
		{
			g_receiveEn[id-1] = 0x5A;
			g_receivenum[id-1] = 0;
			g_framenum[id-1] = rxbuf->head.fnum;
			g_datacrc[id-1] = rxbuf->head.crc;
			memset(&g_exbNvPara[id-1][0], 0, BOARD_PARA_SIZE);
		}
	}
	else
	{
		if (g_receiveEn[id-1] == 0x5A)
		{
			// 拷贝数据内容
			memcpy(&g_exbNvPara[id-1][g_receivenum[id-1]*8], &rxbuf->data, CAN_DATA_LEN);
			g_receivenum[id-1]++;

			if (g_receivenum[id-1] == g_framenum[id-1])		// 接收完成
			{
				g_receiveEn[id-1] = 0;
				u16 crc = CalcCrc16((u8*)(&g_exbNvPara[id-1][0]), BOARD_PARA_SIZE);
				if (crc != g_datacrc[id-1])
				{
					rslt = -2;
				}
				else
				{
					rslt = 0;
				}
			}
		}
	}

	return rslt;
}

u8* GetBoardNvPara(int id)
{
	if (id < 1)
	{
		return NULL;
	}
	return (u8*)(&g_exbNvPara[id-1][0]);
}
#endif

void ParaDataFromOperToCan(u8 protocol, OperPacket * pPkt, BoardFilePacketCtrl * pBoard)
{
	u32 exid = 0;
#if (MAX_SUPPORT_HEAD > 0 || MAX_SUPPORT_COLOR > 0)
	int i = 0;
	u8 nodeId = 0;		// 0为广播
#endif

	memset(pBoard, 0, sizeof(BoardFilePacketCtrl));

#if (MAX_SUPPORT_HEAD > 0)
	if (protocol == BN_PROTOCOL_HEAD)
	{	// 机头板协议,只需告知节点类型和相应的机头号即可,不需关心具体的节点ID
		if (pPkt->boardPara.nodeId != 0)
		{
			int hdnm = pPkt->boardPara.nodeId;	// 对应机头号
			for (i = 1; i < MAX_SUPPORT_HEAD+1; i++)
			{
				if (g_headList[i].nodeTye == pPkt->boardPara.nodeType)
				{
					if (hdnm <= 1)
					{
						nodeId = g_headList[i].nodeId;
						break;
					}
					else
					{
						hdnm--;
					}
				}
			}
		}

		if (pPkt->boardPara.nodeType == FLAT_EMB_HEAD)
		{
			pBoard->pktHead.head.pktId = 0;		// 平绣机头板参数
		}
		else if (pPkt->boardPara.nodeType == CHENILLE_HEAD)
		{
			pBoard->pktHead.head.pktId = 1;		// 毛巾机头板参数
		}
		else if (pPkt->boardPara.nodeType == COIL_HEAD)
		{
			pBoard->pktHead.head.pktId = 2;		// 缠绕机头板参数
		}
		else
		{
			printf("set head para, nodeType unknown\r\n");		// 20230807新增,防止界面节点类型发送错误
			return;
		}
	}
	else
#endif
#if (MAX_SUPPORT_COLOR > 0)
	if (protocol == BN_PROTOCOL_COLOR)
	{
		u8 boardnum = pPkt->boardPara.nodeId;
		if (boardnum == 0 || boardnum > MAX_SUPPORT_COLOR)
		{
			return;		// 20220628 不再支持广播设置,防止界面乱发命令
		}
		nodeId = g_colorList[boardnum].nodeId;
		if (boardnum == 2)
		{
			pBoard->pktHead.head.pktId = 3;		// 毛巾换色板参数
		}
	}
	else
#endif
	{
		printf("not support protocol\r\n");
		return;
	}

	memcpy(pBoard->pktHead.head.sync, CDP_SYNC, CDPSYNC_LEN);

	pBoard->pktHead.head.fnum = BOARD_PARA_SIZE/CAN_DATA_LEN;

	for (int j = 0; j < pBoard->pktHead.head.fnum; j++)
	{
		memcpy(&pBoard->pktData[j].data, &pPkt->boardPara.exData[j*CAN_DATA_LEN], CAN_DATA_LEN);
	}

	pBoard->pktHead.head.crc = CalcCrc16((u8*)pBoard->pktData, BOARD_PARA_SIZE);

#if (MAX_SUPPORT_HEAD > 0)
	if (protocol == BN_PROTOCOL_HEAD)
	{
		if (i <= MAX_SUPPORT_HEAD)		// 找到对应的节点或广播
		{
			exid = MAKE_EXID(BN_PROTOCOL_HEAD, nodeId, g_curBoardID, BN_CMD_NVPARA);
		}
	}
	else
#endif
#if (MAX_SUPPORT_COLOR > 0)
	if (protocol == BN_PROTOCOL_COLOR)
	{
		exid = MAKE_EXID(BN_PROTOCOL_COLOR, nodeId, g_curBoardID, BN_CMD_NVPARA);
	}
	else
#endif
	{
	}

	if (exid != 0)
	{
		SendPacketDataWithCanFrame(exid, pBoard);
	}
}

// 用CAN数据帧的格式发送数据包
void SendPacketDataWithCanFrame(u32 exid, BoardFilePacketCtrl * pBoard)
{
	CanTxMsg txMsg;
	txMsg.canTxhead.ExtId = exid;
	txMsg.canTxhead.RTR = CAN_RTR_DATA;			// 数据帧
	txMsg.canTxhead.IDE = CAN_ID_EXT;			// 扩展帧
	txMsg.canTxhead.DLC = CAN_DATA_LEN;			// 数据场长度

	for (int idx = 0; idx < pBoard->pktHead.head.fnum+1; idx++)
	{
		memcpy(&txMsg.data, ((u8*)&pBoard->pktHead)+idx*CAN_DATA_LEN, CAN_DATA_LEN);	// 填充数据场
		SendACANDataPacket(&txMsg);
		DelayMs(1);
	}
}

s32 GetHeadPara(void)
{
	return headparaval;
}

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


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


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


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