
#include "canctrl.h"

#if (COMM_CAN != 0)

#include "trigger.h"
#include "cpuid.h"

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

CanRxCtrl g_canRxCtrl;
CanTxCtrl g_canTxCtrl;

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

void InitCanMsgList(void);
void InitCanFilter(void);

//------------------------------------------------------------------------
// 默认过滤器，接收所有数据包
void DefaultCanFilter(u8 fifo)
{
	HAL_StatusTypeDef halsta;

	CAN_FilterTypeDef hFilterConfig;
	hFilterConfig.FilterBank = 0;								// 待初始化的过滤器为主0--13 , 从14--27
	hFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; 			// 工作在标识符屏蔽位模式
	hFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;			// 过滤器位宽为1个32位。
	hFilterConfig.FilterIdHigh = 0x0000; 						// 设定过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterIdLow = 0x0000;							// 设定过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个）
	hFilterConfig.FilterMaskIdHigh = 0x0000; 					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其高段位，16位位宽时为第一个）
	hFilterConfig.FilterMaskIdLow = 0x0000; 					// 设定过滤器屏蔽标识符或者过滤器标识符（32位位宽时为其低段位，16位位宽时为第二个)
	hFilterConfig.FilterFIFOAssignment = fifo; 					// 过滤器被关联到FIFO
	hFilterConfig.SlaveStartFilterBank = 14;					// 从节点CAN过滤器（对于主CAN无意义）。双CAN的系统必须设置
	hFilterConfig.FilterActivation = CAN_FILTER_ENABLE; 		// 使能过滤器

	halsta = HAL_CAN_ConfigFilter(&HCAN, &hFilterConfig);

	printf("DefaultCanFilter at fifo%d, halsta=%d\r\n", fifo, halsta);
}


void (*SetCanFilter)(u8) = DefaultCanFilter;

void RegistFilter(void*func)
{
	SetCanFilter = (void (*)(u8))func;
}

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

void InitCanCtrl(void)
{
	HAL_StatusTypeDef halsta;	// 状态

	InitCanMsgList();			// 控制数据结构初始化

	if (SetCanFilter != NULL)	// 过滤器初始化
	{
		SetCanFilter(CAN_FILTER_FIFO0);
	}

	halsta = HAL_CAN_ActivateNotification(&HCAN, CAN_IT_RX_FIFO0_MSG_PENDING);		// 打开CAN接收中断
	if (halsta != HAL_OK)
	{
		printf("HAL_CAN_ActivateNotification(&HCAN, CAN_IT_RX_FIFO0_MSG_PENDING) failed\r\n");
	}

	halsta = HAL_CAN_ActivateNotification(&HCAN, CAN_IT_RX_FIFO0_FULL);		// 打开CAN邮箱满中断
	if (halsta != HAL_OK)
	{
		printf("HAL_CAN_ActivateNotification(&HCAN, CAN_IT_RX_FIFO0_FULL) failed\r\n");
	}

	halsta = HAL_CAN_DeactivateNotification(&HCAN, CAN_IT_TX_MAILBOX_EMPTY);		// 关闭发送中断
	if (halsta != HAL_OK)
	{
		printf("HAL_CAN_DeactivateNotification(&HCAN, CAN_IT_TX_MAILBOX_EMPTY) failed\r\n");
	}

	halsta = HAL_CAN_Start(&HCAN);		// 启动CAN模块
	if (halsta != HAL_OK)
	{
		printf("HAL_CAN_Start failed\r\n");
	}
}

// 初始化控制结构
void InitCanMsgList(void)
{
	memset(&g_canTxCtrl, 0, sizeof(CanTxCtrl));
	memset(&g_canRxCtrl, 0, sizeof(CanRxCtrl));

	g_canTxCtrl.pktTxListHead = g_canTxCtrl.pktTxList;	// 头指针
	g_canTxCtrl.pktTxListTail = g_canTxCtrl.pktTxList;	// 尾指针
	g_canTxCtrl.pktTxNumber = 0;						// 有效个数
	g_canTxCtrl.sendingFlag = 0;

	g_canRxCtrl.pktRxListHead = g_canRxCtrl.pktRxList;	// 头指针
	g_canRxCtrl.pktRxListTail = g_canRxCtrl.pktRxList;	// 尾指针
	g_canRxCtrl.pktRxNumber = 0;						// 有效个数
}

//---------------------------------------------------------
/*
  HAL_OK       = 0x00U,
  HAL_ERROR    = 0x01U,
  HAL_BUSY     = 0x02U,
  HAL_TIMEOUT  = 0x03U,
 */
// 发送数据到总线
int TransCanDataToBus(void)
{
	HAL_StatusTypeDef halsta;		// 发送状态
	u32 tsmBox;						// 发送邮箱

//	printf("TransCanDataToBus\r\n");

	// 从队列取一个数据包发送
	if (g_canTxCtrl.pktTxNumber <= 0)
	{
		//printf("pktTxNumber=%d\r\n", g_canTxCtrl.pktTxNumber);
		return 1;
	}

	halsta = HAL_CAN_AddTxMessage(&HCAN, &(g_canTxCtrl.pktTxListTail->canTxhead) , g_canTxCtrl.pktTxListTail->data, &tsmBox);
	//printf("exid=0x%x,tsmBox=%d,halsta=%d\r\n", g_canTxCtrl.pktTxListTail->canTxhead.ExtId, tsmBox,halsta);
	if (halsta == HAL_OK)
	{
		EnterCritical();
		g_canTxCtrl.pktTxNumber--;
		g_canTxCtrl.pktTxListTail++;
		if (g_canTxCtrl.pktTxListTail > &(g_canTxCtrl.pktTxList[TRANS_PKT_LIST_NUM-1]))
		{
			g_canTxCtrl.pktTxListTail = &(g_canTxCtrl.pktTxList[0]);
		}
		ExitCritical();

//		printf("HAL_OK, g_canTxCtrl.pktTxNumber=%d\r\n", num);

		return 0;
	}
	else
	{
		printf("TransCanDataToBus:other sta, halsta=%d\r\n", halsta);
		return 2;
	}
}

// 从总线上接收数据
int ResvCanDataFromBus(void)
{
	HAL_StatusTypeDef halsta;
	CanRxMsg rxMsg;

	halsta = HAL_CAN_GetRxMessage(&HCAN, CAN_RX_FIFO0, &(rxMsg.canRxhead), rxMsg.data);		// 读取数据
	if (halsta == HAL_OK)
	{
		//printf("get a can packet:\r\n");
		//printf("exid=0x%x\r\n", rxMsg.canRxhead.ExtId);
		if (g_canRxCtrl.pktRxNumber < RESV_PKT_LIST_NUM-1)			// 添加到队列中
		{
		//	printf("add to rxlist, add=0x%x\r\n", g_canRxCtrl.pktRxListHead);
			memcpy(g_canRxCtrl.pktRxListHead, &rxMsg, sizeof(CanRxMsg));

			g_canRxCtrl.pktRxNumber++;
			g_canRxCtrl.pktRxListHead++;			
			if (g_canRxCtrl.pktRxListHead > &(g_canRxCtrl.pktRxList[RESV_PKT_LIST_NUM-1]))
			{
				g_canRxCtrl.pktRxListHead = &(g_canRxCtrl.pktRxList[0]);
			}
			//printf("resv RxNum=%d\r\n", g_canRxCtrl.pktRxNumber);
			return 0;
		}
		else
		{
			printf("can receive buff is full\r\n");
		}
	}
	else
	{
		printf("ResvCanDataFromBus:other sta, halsta=%d\r\n", halsta);
	}
	return 1;
}

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

// 添加发送数据到队列
int SendACANDataPacket(CanTxMsg * pMsg)
{
	int rslt;
	if (pMsg == NULL)
	{
		printf("SendACANDataPacket:para error\r\n");
		return -1;
	}

	if (g_canTxCtrl.pktTxNumber < TRANS_PKT_LIST_NUM)
	{
		// 添加一个数据包到发送队列
		memcpy(g_canTxCtrl.pktTxListHead, pMsg, sizeof(CanTxMsg));		// 拷贝数据

		EnterCritical();
		g_canTxCtrl.pktTxNumber++;
		g_canTxCtrl.pktTxListHead++;
		if (g_canTxCtrl.pktTxListHead > &(g_canTxCtrl.pktTxList[TRANS_PKT_LIST_NUM-1]))
		{
			g_canTxCtrl.pktTxListHead = &(g_canTxCtrl.pktTxList[0]);
		}
		ExitCritical();

		if (g_canTxCtrl.sendingFlag == 0)	// 没有发送
		{
			rslt = TransCanDataToBus();		// 启动发送队列中数据到总线

			if (rslt == 0)			// 添加到队列成功，队列中有数据
			{
				//printf("send a can packet in app\r\n");
				g_canTxCtrl.sendingFlag = 1;		// 设置标志
				HAL_CAN_ActivateNotification(&HCAN, CAN_IT_TX_MAILBOX_EMPTY);		// 打开邮箱空中断
			}
			else if (rslt == 1)		// 队列中没有数据要发送
			{
				//printf("send list empty in app\r\n");
				g_canTxCtrl.sendingFlag = 0;
				HAL_CAN_DeactivateNotification(&HCAN, CAN_IT_TX_MAILBOX_EMPTY);		// 没有数据发送，关闭中断
			}
			else	// 没有合适的邮箱
			{
				printf("no mail box in app, start later\r\n");
			}
		}
		else
		{
			//printf("sendingFlag=1\r\n");
			HAL_CAN_ActivateNotification(&HCAN, CAN_IT_TX_MAILBOX_EMPTY);	// 打开邮箱空中断
		}
		rslt = 0;
	}
	else
	{
		printf("can send buff is full\r\n");
		rslt = 1;
	}

	return rslt;
}


// 从队列中读取数据
int GetACanDataPacket(CanRxMsg * pMsg)
{
	int rslt;
	if (pMsg == NULL)
	{
		return -1;
	}

	if (g_canRxCtrl.pktRxNumber > 0)
	{
		memcpy(pMsg, g_canRxCtrl.pktRxListTail, sizeof(CanRxMsg));

		EnterCritical();
		g_canRxCtrl.pktRxNumber--;
		//printf("2.RxNum=%d\r\n", g_canRxCtrl.pktRxNumber);
		g_canRxCtrl.pktRxListTail++;
		if (g_canRxCtrl.pktRxListTail > &(g_canRxCtrl.pktRxList[RESV_PKT_LIST_NUM-1]))
		{
			g_canRxCtrl.pktRxListTail = &(g_canRxCtrl.pktRxList[0]);
		}
		ExitCritical();

		rslt = 0;
	}
	else
	{
		rslt = 1;
	}

	return rslt;
}

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

void CanTransIntProc(void)
{
	int rslt;

	rslt = TransCanDataToBus();

	if (rslt == 0)			// 队列中有数据且发送成功
	{
		//printf("send a can packet in int\r\n");
	}
	else if (rslt == 1)		// 队列中没有数据要发送
	{
	//	printf("send list empty in int, close int\r\n");
		g_canTxCtrl.sendingFlag = 0;
		HAL_CAN_DeactivateNotification(&HCAN, CAN_IT_TX_MAILBOX_EMPTY);		// 没有数据发送，关闭中断
	}
	else	// 没有邮箱
	{
		printf("no mail box in int\r\n");
	}
}

void CanResvIntProc(void)
{
	u32 len;
	len = HAL_CAN_GetRxFifoFillLevel(&HCAN, CAN_RX_FIFO0);	// 个数
	while(len != 0)
	{
		//printf("get a can packet:\r\n");
		ResvCanDataFromBus();		// 读取数据，添加到队列
		len--;
	}
}

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

// CAN邮箱0发送完成中断的回调函数
void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *pcan)
{
//	if (pcan->Instance == CAN1)
	{
		CanTransIntProc();
	}
}

// CAN邮箱1发送完成中断的回调函数
void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *pcan)
{
//	if (pcan->Instance == CAN1)
	{
		CanTransIntProc();
	}
}

// CAN邮箱2发送完成中断的回调函数
void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *pcan)
{
//	if (pcan->Instance == CAN1)
	{
		CanTransIntProc();
	}
}

// CAN邮箱0接收中断回调函数
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *pcan)
{
//	if (pcan->Instance == CAN1)
	{
		//printf("rx fifo 0\r\n");
		CanResvIntProc();
	}
}

void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *pcan)
{
	printf("can rx fifo0 full\r\n");
}

void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan)
{
	printf("can error\r\n");
}
//---------------------------------------------------------
#endif

