#include "bsp_can.h"
#include "bsp_queue.h"

#include "kit_time.h"
#include "kit_math.h"
#include "kit_debug.h"

/***********************************************同步接口*********************************************/
KitResult bsp_can_sync_send(CanDev dev, uint32_t id, uint8_t *buf, uint8_t len, CanIde ide, CanRtr rtr)
{
    CanMsg msg;
    uint32_t dly = 0;
    KitResult res = kKitResult_Ok;
    
    KIT_ASSERT_PARAM(dev <= kCanDev_End);
    KIT_ASSERT_PARAM(((buf != NULL) && (len > 0) && (len < 9)) || ((buf == NULL) && (len == 0)));
    
    msg.ide = ide;
    msg.rtr = rtr;
    msg.len = len;
    msg.id.value = id;
    kit_copy_buf(msg.data.byte, buf, len); 
    
    while(drv_can_send(dev, &msg) != kKitResult_Ok)
    {
        kit_time_dly_ms(1);
        if(++dly > 5)
        {
            res = kKitResult_TimeOut;
            break;
        }
    }
    
    KIT_ASSERT_RES(dev, res);
    return res;
}

KitResult bsp_can_ext_data_sync_send(CanDev dev, uint32_t id, uint8_t *buf, uint8_t len)
{
    KIT_ASSERT_PARAM(((buf != NULL) && (len > 0) && (len < 9)) || ((buf == NULL) && (len == 0)));
    
    return bsp_can_sync_send(dev, id, buf, len, kCanIde_Ext, kCanRtr_Data);
}

KitResult bsp_can_std_data_sync_send(CanDev dev, uint32_t id, uint8_t *buf, uint8_t len)
{
    KIT_ASSERT_PARAM(((buf != NULL) && (len > 0) && (len < 9)) || ((buf == NULL) && (len == 0)));
    
    return bsp_can_sync_send(dev, id, buf, len, kCanIde_Std, kCanRtr_Data);
}

KitResult bsp_can_ext_data_series_sync_send(CanDev dev, uint32_t id, uint32_t add_value, uint8_t *buf, uint16_t len)
{
    uint16_t  remainder, quotient;
    KitResult res = kKitResult_Ok;    
    
    KIT_ASSERT_PARAM((len > 0) && (buf != NULL));
    
    quotient = len >> 3;
    remainder = len % 8;
    for(len = 0; len < quotient; len++)
    {
        res |= bsp_can_ext_data_sync_send(dev, id, (uint8_t *)(buf + (len << 3)), 8);
        id += add_value;        
    }
    
    if(0 != remainder)
    {
        res |= bsp_can_ext_data_sync_send(dev, id, (uint8_t *)(buf + (len << 3)), remainder);
    }
    
    return res;     
}

/***********************************************异步接口*********************************************/
#if STM32F40_41xxx
    bool is_can_it_start[kCanDev_End] = {false, false};
    QUEUE_STATIC_INIT_CCM(can0_tx_queue, 300, sizeof(CanMsg));
    QUEUE_STATIC_INIT_CCM(can1_tx_queue, 300, sizeof(CanMsg));
    QueueItem * const can_tx_queue[kCanDev_End] = {&can0_tx_queue, &can1_tx_queue};
#else
    QUEUE_STATIC_INIT(can0_tx_queue, 200, sizeof(CanMsg));
    #if STM32F10X_CL
        bool is_can_it_start[kCanDev_End] = {false, false};
        QUEUE_STATIC_INIT(can1_tx_queue, 200, sizeof(CanMsg));
        QueueItem * const can_tx_queue[kCanDev_End] = {&can0_tx_queue, &can1_tx_queue};
    #else
        bool is_can_it_start[kCanDev_End] = {false};
        QueueItem * const can_tx_queue[kCanDev_End] = {&can0_tx_queue};
    #endif
#endif


KitResult bsp_can_async_send(CanDev dev, uint32_t id, uint8_t *buf, uint8_t len, CanIde ide, CanRtr rtr)
{
    CanMsg *msg;
    uint32_t cnt = 0;
    KitResult res = kKitResult_Error;
    
    KIT_ASSERT_PARAM((dev <= kCanDev_End) && (msg != NULL));
    //当mailbox空闲时，优先使用mailbox发送
    //一但开启中断发送，始终都用中断直至队列为空
    if((drv_can_get_mailbox(dev) < 3) && (is_can_it_start[dev] == false))
    {  
        res = bsp_can_sync_send(dev, id, buf, len, ide, rtr);
    }
    else
    {       
        while(((bsp_queue_push_pointer(can_tx_queue[dev], (void** )&msg)) != kKitResult_Ok) && (cnt++ < 5))
        {
            kit_time_dly_ms(1);
        }
        if(cnt < 5)
        {
            msg->len = len;
            msg->id.value = id;
            msg->ide = ide;
            msg->rtr = rtr;    
            kit_copy_buf(msg->data.byte, buf, len);
            is_can_it_start[dev] = true;
            drv_can_ctrl_interrupt(dev, kCanInterrupt_Tx, true);
            res = kKitResult_Ok;
        }
    }
    
    return res;
}

KitResult bsp_can_ext_data_async_send(CanDev dev, uint32_t id, uint8_t *buf, uint8_t len)
{
    KIT_ASSERT_PARAM(((buf != NULL) && (len > 0) && (len < 9)) || ((buf == NULL) && (len == 0)));
    
    return bsp_can_async_send(dev, id, buf, len, kCanIde_Ext, kCanRtr_Data);
}

KitResult bsp_can_std_data_async_send(CanDev dev, uint32_t id, uint8_t *buf, uint8_t len)
{
    KIT_ASSERT_PARAM(((buf != NULL) && (len > 0) && (len < 9)) || ((buf == NULL) && (len == 0)));
    
    return bsp_can_async_send(dev, id, buf, len, kCanIde_Std, kCanRtr_Data);
}

KitResult bsp_can_ext_data_series_async_send(CanDev dev, uint32_t id, uint32_t add_value, uint8_t *buf, uint16_t len)
{
    uint16_t  remainder, quotient;
    KitResult res = kKitResult_Ok;
    
    KIT_ASSERT_PARAM(len > 0);
    KIT_ASSERT_PARAM(buf != NULL);
    
    quotient = len >> 3;
    remainder = len % 8;
    for(len = 0; len < quotient; len++)
    {
        res |= bsp_can_ext_data_async_send(dev, id, (uint8_t *)(buf + (len << 3)), 8);            
        id += add_value;
    }
    
    if(0 != remainder)
    {
        res |= bsp_can_ext_data_async_send(dev, id, (uint8_t *)(buf + (len << 3)), remainder);
    }
    
    return res;    
}



void bsp_can_async_poll(CanDev dev)
{  
    CanMsg *msg;
    
    while(drv_can_get_mailbox(dev) < 3)
    {        
        if(bsp_queue_pop_pointer(can_tx_queue[dev], (void **)&msg) == kKitResult_Ok)
        {
            drv_can_send(dev, msg);
        }   
        else
        {
            is_can_it_start[dev] = false;
            drv_can_ctrl_interrupt(dev, kCanInterrupt_Tx, false);
            break;
        }
    }
}


