#include "drv_clk.h"
#include "drv_can.h"
#include "drv_gpio.h"
#include "drv_misc.h"

#include "kit_debug.h"


#define CAN_INIT_TIMEOUT            (0xFFF0u)

#define CAN_SJW_1tq                 (0u)
#define CAN_BS2_1tq                 (0u)
#define CAN_BS2_2tq                 (1u)
#define CAN_BS1_4tq                 (3u)  
#define CAN_BS1_6tq                 (5u)
#define CAN_BS1_13tq                (12u)
#define CAN_BS1_16tq                (15u)  
#define CAN_RTR_DATA                (0u)


#define GPIO_REMAP1_CAN1            ((uint32_t)0x00004000)
#define GPIO_REMAP2_CAN1            ((uint32_t)0x00006000)
#define GPIO_REMAP_CAN2             ((uint32_t)0x00400000)

typedef struct
{
    uint8_t irq[kcan_interrupt_e_End];
    CAN_TypeDef*  reg;
}Stm32CanProp;

static kit_ret_e drv_can_set_clock_gpio(can_dev_e dev, uint16_t rx_io, uint16_t tx_io);
static KitIrqCall can_irq_call[kcan_dev_e_End][kcan_interrupt_e_End];
static const Stm32CanProp stm32_can[kcan_dev_e_End] =
{
#if defined(STM32F10X_CL) || defined(STM32F40_41xxx) || defined(STM32F429_439xx)
    {{CAN1_RX0_IRQn,    CAN1_TX_IRQn},   CAN1},
    {{CAN2_RX0_IRQn,    CAN2_TX_IRQn},   CAN2},
#else    
    {{USB_LP_CAN1_RX0_IRQn,  USB_HP_CAN1_TX_IRQn},   CAN1},
#endif    
};

const uint8_t can_mailbox_tab[8] = {0xFF, 0, 1, 0, 2, 0, 1, 0};
uint8_t drv_can_get_mailbox(can_dev_e dev)
{
    uint8_t mailbox = 0xFF;
    KIT_ASSERT_PARAM(dev < kcan_dev_e_End);
       
    if(dev < kcan_dev_e_End)
        mailbox = can_mailbox_tab[(stm32_can[dev].reg->TSR >> 26) & 0x07];
    
    return mailbox;
}


kit_ret_e drv_can_send(can_dev_e dev, CanMsg *msg)
{
    uint8_t     id_move = 3, mailbox;
    kit_ret_e   res = kKit_Ret_ParamErr;      
    CAN_TypeDef *can_reg;
    
    KIT_ASSERT_PARAM(msg != NULL); 
    KIT_ASSERT_PARAM(dev < kcan_dev_e_End);

    if((dev < kcan_dev_e_End) && (msg != NULL))
    {
        can_reg = stm32_can[dev].reg;
        mailbox = can_mailbox_tab[(can_reg->TSR >> 26) & 0x07];
        if (mailbox != 0xFF)
        {
            if (msg->ide == kcan_frame_type_e_Std)
            {
                id_move = 21;
            }            
            //write identifier 
            can_reg->sTxMailBox[mailbox].TIR = (msg->id.value << id_move) | (msg->ide << 2) | (msg->rtr << 1);
            //write length
            can_reg->sTxMailBox[mailbox].TDTR = msg->len & 0x0F;
            //write data
            can_reg->sTxMailBox[mailbox].TDLR = msg->data.value[0];
            can_reg->sTxMailBox[mailbox].TDHR = msg->data.value[1];
            //request send
            can_reg->sTxMailBox[mailbox].TIR |= 0x00000001;
            res = kKit_Ret_Ok;
        }
        else
        {
            res = kKit_Ret_OverFlow;
        }
    }
  
    return res;
}


kit_ret_e drv_can_receive(can_dev_e dev, CanMsg* msg)
{
    kit_ret_e   res = kKit_Ret_ParamErr;
    CAN_FIFOMailBox_TypeDef fifo;
    
    KIT_ASSERT_PARAM(msg != NULL); 
    KIT_ASSERT_PARAM(dev < kcan_dev_e_End);
    
    if((dev < kcan_dev_e_End) && (msg != NULL))
    {
        fifo = stm32_can[dev].reg->sFIFOMailBox[0];
        /* Get the Id */
        msg->rtr = (CanRtr)(0x00000001 & fifo.RIR >> 1);
        msg->ide = (can_frame_type_e)(0x00000001 & fifo.RIR >> 2);
        if (msg->ide == kcan_frame_type_e_Std)
            msg->id.value = (uint32_t)0x000007FF & (fifo.RIR >> 21);
        else
            msg->id.value = (uint32_t)0x1FFFFFFF & (fifo.RIR >> 3);

        msg->len = (uint8_t)0x0F & fifo.RDTR;
        msg->data.value[0] = fifo.RDLR;
        msg->data.value[1] = fifo.RDHR;
        
        /* Release the FIFO */
        stm32_can[dev].reg->RF0R |= CAN_RF0R_RFOM0;
        res = kKit_Ret_Ok;
    }
    
    return res;
}
/**********************************************************************************
*  Func   CAN1_REMAP0  CAN1_REMAP1  CAN1_REMAP2       CAN2_REMAP0  CAN2_REMAP1
* CAN_RX     PA11 	     PB8 	      PD0	                PB12 	    PB5
* CAN_TX     PA12 	     PB9 	      PD1	                PB13 	    PB6
**********************************************************************************/

static kit_ret_e drv_can_set_clock_gpio(can_dev_e dev, uint16_t rx_idx, uint16_t tx_idx)
{
    kit_ret_e res = kKit_Ret_Ok;
    uint32_t rx_io = drv_gpio_get_actual_io(rx_idx);
    uint32_t tx_io = drv_gpio_get_actual_io(tx_idx);
    switch (dev)
    {
        case kcan_dev_e_1:
			RCC->APB1ENR |= RCC_APB1Periph_CAN1;

            if((rx_io == GPIO_PORT_PIN(kGpioPort_A, 11)) && (tx_io == GPIO_PORT_PIN(kGpioPort_A, 12))) 
            {
				drv_gpio_set_af(kGpioPort_A, 11, 9);
				drv_gpio_set_af(kGpioPort_A, 12, 9);
			}
            else if((rx_io == GPIO_PORT_PIN(kGpioPort_B, 8)) && (tx_io == GPIO_PORT_PIN(kGpioPort_B, 9))) 
            {
				drv_gpio_set_af(kGpioPort_B, 8, 9);
				drv_gpio_set_af(kGpioPort_B, 9, 9);
			}
            else if((rx_io == GPIO_PORT_PIN(kGpioPort_D, 0)) && (tx_io == GPIO_PORT_PIN(kGpioPort_D, 1))) 
            {
				drv_gpio_set_af(kGpioPort_D, 0, 9);
				drv_gpio_set_af(kGpioPort_D, 1, 9);
			}
            else
                res = kKit_Ret_ParamErr;
            break;
#if defined(STM32F10X_CL) || defined(STM32F40_41xxx) || defined(STM32F429_439xx) 
        //使用CAN2接收需要使能CAN1时钟
        case kcan_dev_e_2:
            RCC->APB1ENR |= RCC_APB1Periph_CAN1;
			RCC->APB1ENR |= RCC_APB1Periph_CAN2;
		
            if((rx_io == GPIO_PORT_PIN(kGpioPort_B, 12)) && (tx_io == GPIO_PORT_PIN(kGpioPort_B, 13))) 
            {
				drv_gpio_set_af(kGpioPort_B, 12, 9);
				drv_gpio_set_af(kGpioPort_B, 13, 9);
			}
            else if((rx_io == GPIO_PORT_PIN(kGpioPort_B, 5)) && (tx_io == GPIO_PORT_PIN(kGpioPort_B, 6))) 
            {
				drv_gpio_set_af(kGpioPort_B, 5, 9);
				drv_gpio_set_af(kGpioPort_B, 6, 9);
			}
            else if((rx_io == GPIO_PORT_PIN(kGpioPort_D, 0)) && (tx_io == GPIO_PORT_PIN(kGpioPort_D, 1))) 
            {
				drv_gpio_set_af(kGpioPort_D, 0, 9);
				drv_gpio_set_af(kGpioPort_D, 1, 9);
			}
            else
                res = kKit_Ret_ParamErr;
            break;
#endif
        default:
            res = kKit_Ret_ParamErr;
            break;
    }
        
    return res;
}


//默认全部关联到FIFO0
void can_set_list_filter(uint8_t channel, can_frame_type_e ide, CanRtr rtr, uint32_t rcv_id1, uint32_t rcv_id2)
{
    uint8_t   id_move = 3;
    uint32_t  bit;
    
    KIT_ASSERT_PARAM(channel < 28);
    KIT_ASSERT_PARAM(ide < kcan_frame_type_e_End);   
    KIT_ASSERT_PARAM(rtr < kCanRtr_End);

	bit = KIT_BIT_MASK_32(channel);
	CAN1->FMR |= CAN_FMR_FINIT;  //进入CAN配置模式
	CAN1->FM1R |= bit; 			 //列表模式
	CAN1->FS1R |= bit;			//32位数据长度
		
	id_move = 3;
	if(ide == kcan_frame_type_e_Std)
	{
		id_move = 21;
	}

	CAN1->sFilterRegister[channel].FR1 = (rcv_id1 << id_move) | (ide << 2) | (rtr << 1);
	CAN1->sFilterRegister[channel].FR2 = (rcv_id2 << id_move) | (ide << 2) | (rtr << 1);

	CAN1->FA1R |= bit;
	CAN1->FMR &= ~CAN_FMR_FINIT;
}

//屏蔽位模式 0不关心 1必须匹配
void can_set_mask_filter(uint8_t channel, can_frame_type_e ide, CanRtr rtr,  uint32_t rcv_id, uint32_t mask_id)
{
    uint8_t   id_move;
    uint32_t  bit;
    
    KIT_ASSERT_PARAM(channel < 28);
    KIT_ASSERT_PARAM(ide < kcan_frame_type_e_End);   
    KIT_ASSERT_PARAM(rtr < kCanRtr_End);

	bit = KIT_BIT_MASK_32(channel);
	CAN1->FMR |= CAN_FMR_FINIT;  //进入CAN配置模式
	CAN1->FM1R &= ~bit;			 //屏蔽模式
	CAN1->FS1R |= bit;			 //32位数据长度
	
	id_move = 3;
	if(ide == kcan_frame_type_e_Std)
	{
		id_move = 21;
	}

	CAN1->sFilterRegister[channel].FR1 = (rcv_id << id_move)  | (ide << 2) | CAN_RTR_DATA;
	CAN1->sFilterRegister[channel].FR2 = (mask_id << id_move) | (ide << 2) | CAN_RTR_DATA;

	CAN1->FA1R |= bit;
	CAN1->FMR &= ~CAN_FMR_FINIT;
}


/*----------------------------------------STM32F10x MCR(master control register)寄存器---------------------------------------------------
|  Bit  |      16     |    15   |         7        |        6        |     5    |    4     |     3      |     2      |    1    |   0  |
-----------------------------------------------------------------------------------------------------------------------------------------
| Item  |      DBF    |  RESET  |      TTCM        |       ABOM      |   AWUM   |   NART   |    RFLM    |   TXFP     |  SLEEP  | INRQ |
-----------------------------------------------------------------------------------------------------------------------------------------
|  DEF  |       1     |    0    |         0        |        0        |     0    |     0    |      0     |     0      |    1    |   0  |
-----------------------------------------------------------------------------------------------------------------------------------------
| Value |1 调试时冻结 |0 不复位 |0 禁用时间触发模式|1 硬件控制Buf off|1 硬件唤醒|0 自动重发|1 满停止接收|1 按顺序发送|         |      |

 
 *软件通过置位SLEEP来请求进入睡眠模式，置位后CAN在当前活动完成后将立即进入睡眠模式，当AWUM置位后，也可以被硬件唤醒清零
 *CAN波特率=APB总线频率/BRP分频器/(1+tBS1+tBS2)  5kbps = 42000/900/(1+6+1)
 *波特率必须是5kbps倍数,小于500，以36M的APB1Periph时钟频率计算，5kbps时在(SJW_1tq, BS1_6tq, BS2_1tq)预分频为900, 其他波特率分频计算 900 / (baud_rate/5)
 *使用CAN2必须使能CAN1时钟
 *CAN初始化同步到总线使用时间根据情况而定，设备较多，有报文需要等待的时间较长
 *本驱动只使用FIFO0，滤波器都关联到FIFO0
 *CAN1过滤器起始地址为0，共有14个，CAN2为14共有14个
 *0表示不过滤，1表示对应位要过滤
 *配置过滤器时必须处于初始化模式
----------------------------------------------------------------------------------------------------------------------------------------*/
kit_ret_e drv_can_init(can_dev_e dev, uint32_t baud_rate, uint16_t rx_io, uint16_t tx_io)
{
    uint32_t    tmp;
    kit_ret_e   res;
    CAN_TypeDef *can_reg;

    KIT_ASSERT_PARAM(dev < kcan_dev_e_End);
    KIT_ASSERT_PARAM(((baud_rate % 5) == 0) && (baud_rate <= 500));
    
    res = drv_can_set_clock_gpio(dev, rx_io, tx_io);
    if(res == kKit_Ret_Ok)
    {
        can_reg = stm32_can[dev].reg;
        // leave sleep mode
        can_reg->MCR &= (~(uint32_t)CAN_MCR_SLEEP);
        // request init mode
        can_reg->MCR |= CAN_MCR_INRQ ;

        // wait init acknowledge 
        res |= kit_wait_flag(&can_reg->MSR, CAN_MSR_INAK, CAN_INIT_TIMEOUT);
        
        //cfg main register 自动退出离线 | 多个报文同时等待发送由请求顺序决定 | 自动重发
        tmp = (CAN_MCR_ABOM | CAN_MCR_TXFP | CAN_MCR_RFLM);

        can_reg->MCR |= tmp;
        //Baud rate prescaler BRP = CLOCK_PCLK1_FREQ / (SJW + BS1 + BS2) / baud_rate - 1
        switch(baud_rate)
        {
            case 125:
            case 250:
                can_reg->BTR = ((uint32_t)CAN_SJW_1tq << 24) | ((uint32_t)CAN_BS1_6tq << 16) | ((uint32_t)CAN_BS2_1tq << 20) | (CLOCK_PCLK1_FREQ / 8000 / baud_rate - 1);
                break;
            
            case 500:
            case 1000:
                can_reg->BTR = ((uint32_t)CAN_SJW_1tq << 24) | ((uint32_t)CAN_BS1_4tq << 16) | ((uint32_t)CAN_BS2_1tq << 20) | (CLOCK_PCLK1_FREQ / 6000 / baud_rate - 1);
                break;
            
            default:
                can_reg->BTR = ((uint32_t)CAN_SJW_1tq << 24) | ((uint32_t)CAN_BS1_6tq << 16) | ((uint32_t)CAN_BS2_1tq << 20) | (CLOCK_PCLK1_FREQ / 8000 / 250 - 1);
                break;
        }

        //leave init mode
        can_reg->MCR &= ~(uint32_t)CAN_MCR_INRQ;

        // Wait the normal acknowledge,当总线有报文时等待时间会较长
        res |= kit_wait_flag(&can_reg->MSR, CAN_MSR_INAK, CAN_INIT_TIMEOUT);
        
        //默认接收任何ID的扩展帧和标准帧
		dev *= 14; 							//通道2起始过滤器为14
		CAN1->FMR |= CAN_FMR_FINIT;  		//进入CAN配置模式
        CAN1->FM1R = 0;                     //所有过滤器组工作在屏蔽位模式
		CAN1->FA1R |= KIT_BIT_MASK_32(dev);
		CAN1->sFilterRegister[dev].FR1 = 0;  //所有位不关心
		CAN1->sFilterRegister[dev].FR2 = 0;
		CAN1->FMR &= ~CAN_FMR_FINIT;
    }

    KIT_ASSERT_RES(dev, res);
    return res;
}

const uint8_t can_interrupt_bit[kcan_interrupt_e_End] = {0x02, 0x01};
kit_ret_e drv_can_set_interrupt(can_dev_e dev, can_interrupt_e it_type, uint16_t priority, KitIrqCall call)
{
    kit_ret_e res;
    
    KIT_ASSERT_PARAM((dev < kcan_dev_e_End) && (it_type < kcan_interrupt_e_End) && (call != NULL));
    
    if((dev < kcan_dev_e_End) && (it_type < kcan_interrupt_e_End) && (call != NULL))
    {
        can_irq_call[dev][it_type] = call;
        drv_misc_set_nvic(stm32_can[dev].irq[it_type], priority);
        stm32_can[dev].reg->IER |= can_interrupt_bit[it_type];
        
        res = kKit_Ret_Ok;
    }
    else
    {
        res = kKit_Ret_ParamErr;
    }
    
    return res;
}

kit_ret_e drv_can_ctrl_interrupt(can_dev_e dev, can_interrupt_e it_type, bool is_enable)
{
    kit_ret_e res;
    
    KIT_ASSERT_PARAM((dev < kcan_dev_e_End) && (it_type < kcan_interrupt_e_End));
    
    if((dev < kcan_dev_e_End) && (it_type < kcan_interrupt_e_End))
    {
        if (is_enable == true)
            stm32_can[dev].reg->IER |= can_interrupt_bit[it_type];
        else
            stm32_can[dev].reg->IER &= ~can_interrupt_bit[it_type];
        
        res = kKit_Ret_Ok;
    }
    else
    {
        res = kKit_Ret_ParamErr;
    }
    
    return res;
}

void drv_can_rx_irq_handler(can_dev_e dev)
{
    CanMsg msg;
    if(can_irq_call[dev][kcan_interrupt_e_Rx] != NULL)
    {
        while((stm32_can[dev].reg->RF0R & 0x03) != 0)
        {
            drv_can_receive(dev, &msg);
            can_irq_call[dev][kcan_interrupt_e_Rx](kKit_Ret_Ok, &msg);
        }
    }
	else
	{
		//清除中断标志，防止一直进中断
        stm32_can[dev].reg->RF0R |= CAN_RF0R_RFOM0;
	}
}

void drv_can_tx_irq_handler(can_dev_e dev)
{
    stm32_can[dev].reg->TSR |= 0x00010101;
    if(can_irq_call[dev][kcan_interrupt_e_Tx] != NULL)
    {       
        can_irq_call[dev][kcan_interrupt_e_Tx](kKit_Ret_Ok, NULL);
    }
}

void CAN1_RX0_IRQHandler(void)
{
    drv_can_rx_irq_handler(kcan_dev_e_1);
}

void CAN1_TX_IRQHandler(void)
{
    drv_can_tx_irq_handler(kcan_dev_e_1);
}

#if defined(STM32F10X_CL) || defined(STM32F40_41xxx) || defined(STM32F429_439xx)  
void CAN2_RX0_IRQHandler(void)
{        
	drv_can_rx_irq_handler(kcan_dev_e_2);
}

void CAN2_TX_IRQHandler(void)
{
    drv_can_tx_irq_handler(kcan_dev_e_2);
}
#endif


