/******************** Copyright @ SuZhou Inovance CO.,LTD ********************
* File Name          : f_CAN_app.c
* Version            : v0.1
* Date               : 2018/5/6
* Description        : CAN底层驱动
* History            :
   
1. Date: 2018/5/6  Version: v0.1
   Author:        
   ID:
   Modification: 
   
*******************************************************************************/

#include "f_CAN_app.h"
#include "f_CAN_drive.h"
#include "f_user_main.h"


#define CAN_FILTER_NUM 16



CAN_STATE CanState;
CAN_PARAM CanParam = {5,1,1};
Uint16 CanBaudRateSelCur = 5;

//Uint16 TestBB[10];

Uint16 CanTimeOutTicker = 0;

Uint8 CANopenMode = CAN_MODE_DATA;

static void CanFilterConfigDeal(const CAN_FILTER *pCanFilter);
void CANRxdDataDeal(CAN_MSG_STRU *pstrMsg);

extern void InitRecMbox(Uint16 mbox, Uint32 msgid, Uint32 lam, Uint16 fifoNo);


CAN_FILTER CanFilterTable[CAN_FILTER_NUM];
const Uint16 CAN_ID_PDO_SEL_DEFAULT[CAN_FILTER_NUM] = 
{
	0x2021,
	0x2022,
	0x2023,
	0x2024,
	0x3021,
	0x3022,
	0x3023,
	0x3024,
	0x2011,
	0x2012,
	0x2013,
	0x2014,
	0x3011,
	0x3012,
	0x3013,
	0x3014,
};



// 初始化CAN
Uint16 InitCanConfig(const CAN_FILTER *pCanFilter, const Uint16 baud)
{
	Uint16 stat = 0;
	
    //TestBB[0] ++;

    
    stat = InitCanDrive(baud);									// eCAN模块初始化
    
	if (stat != CAN_INIT_SUCC)
	
		return (stat);
		
	CanFilterConfigDeal(pCanFilter);							    // 设定过滤规则
	
	return (CAN_INIT_SUCC);
}


// CAN主调度函数
void CanMainProcess(void)
{

	static Uint16 CanInitalStep = CAN_INIT_STEP_RESET_PARAM;
	Uint16 i = 0;

    if (CanBaudRateSelCur != GetCanBaudRate())
    {
        CanBaudRateSelCur = GetCanBaudRate();
        CanParam.InitCmd = 1;
    }
	
    // 首次初始化
    if (CAN_INIT_STEP_RESET_PARAM  == CanInitalStep)
    {
		for (i=0; i<16; i++)
		{
			CanFilterTable[i].all = CAN_ID_PDO_SEL_DEFAULT[i];
		}
		CanParam.NodeID = 1;
		//CanParam.BauteRate = 5;
	}
	//TestBB[1] ++;
	// 系统初始化是否完成
	if (0 == SystemStatus)
	{
		CanInitalStep = CAN_INIT_STEP_WAIT;
		CanState.InitOk = 0;
		return;
	}
	// 是否存在需要初始化命令
	if (CanParam.InitCmd)
	{
		CanInitalStep = CAN_INIT_STEP_WAIT;
		CanState.InitOk = 0;
		CanParam.InitCmd = 0;
		
		// CAN通讯波特率
		CanParam.BauteRate = CanBaudRateSelCur;
	}
	// 判断是否初始化完成
	if (CanState.InitOk)
	{
		return;
	}
	
	//TestBB[2] ++;
	
	// 判断参数是否正常
	if (CAN_INIT_STEP_WAIT == CanInitalStep)
	{
		if (CanParam.BauteRate > 6)
		{
			return ;
		}
		if ((CanParam.NodeID < 1)||(CanParam.NodeID > 127))
		{
			return;
		}
		CanInitalStep = CAN_INIT_STEP_ING;
	}
	// 初始化 CAN
	if (CAN_INIT_STEP_ING == CanInitalStep)
	{
		if (CAN_INIT_SUCC != InitCanConfig(CanFilterTable, CanParam.BauteRate))
		{
			return;
		}
		else
		{
			CanInitalStep = CAN_INIT_STEP_SUCCESS;  		// 初始化成功
		}
			
	}
	// 初始化完成
	if (CAN_INIT_STEP_SUCCESS == CanInitalStep)
	{
		CanState.InitOk = 1;
	}
	
}

// 接收CAN数据处理
void CANRxdDataDeal(CAN_MSG_STRU *pstrMsg)
{
	Uint16 i = 0;
	Uint16 CobID = 0, Channel = 0;
	
	CanTimeOutTicker = 0;
	
	for (i = 0; i < CAN_FILTER_NUM; i++)
	{
		CobID = CanFilterTable[i].bit.COB_ID;
		Channel = CanFilterTable[i].bit.channel;
		// 参数设置有效
		if ((0 == CobID)
		|| (0 == Channel)
		|| (Channel > 4))
		{
			PdoData.SendBuff[i] = 0;
			continue;
		}
		// 设置的ID合法
		if ((CobID < 0x180) || (CobID > 0x57f))
		{
			PdoData.SendBuff[i] = 0;
			continue;
		}
		// ID匹配
		if ((pstrMsg->id & MASK_ALL) == CobID)
		{
			PdoData.SendBuff[i] = (Uint16)pstrMsg->data[(Channel-1)<<1] + ((Uint16)pstrMsg->data[((Channel-1)<<1)+1] << 8);
		}
	}
}

// 中断中钩子函数 中断中调用
Uint16 CANIntHook(DspCanDataStru *pdata)
{
    Uint16 Ret = 0;

	CANRxdDataDeal((CAN_MSG_STRU *)pdata);
    
    return Ret;
}

// 设定过滤规则
static void CanFilterConfigDeal(const CAN_FILTER *pCanFilter)
{
    Uint32 msgId = 0,MaskType = 0;
	Uint8 i = 0;
	Uint16 RpdoNum = 0;

	
	if (CAN_MODE_DATA == CANopenMode)
	{
		MaskType = MASK_TYPE;
		for(i = 0; i < CAN_FILTER_NUM; i++)
		{
			RpdoNum = pCanFilter[i].bit.COB_ID; 				// 非0就写
			if(RpdoNum !=0)
			{
				msgId = ((Uint32)RpdoNum);						// 生产过滤规则
				InitRecMbox(i, msgId, (Uint32)MaskType, i%2);
			}
		}		
	}
	else if(CAN_MODE_CANID == CANopenMode)
	{
		MaskType = MASK_ADDR;
		RpdoNum = pCanFilter[0].all; 			
		if(RpdoNum != 0)								
		{
			msgId = ((Uint32)RpdoNum);							// 生产过滤规则
			InitRecMbox(i, msgId, (Uint32)MaskType, i%2);
		}
	}
}



