#ifndef BSP_CAN_H
#define BSP_CAN_H

#include "general_def.h"
#include "main.h"
#include "fdcan.h"

// ֵܹ֧CAN豸
#define FDCAN_MX_REGISTER_CNT 6 // ȡCANߵĸ
#define DEVICE_CAN_CNT 1        // ݰ趨

typedef struct fdcaninstance
{
  FDCAN_HandleTypeDef *fdcan_handle; // can
  FDCAN_TxHeaderTypeDef txconf;      // CANķ
  uint32_t tx_id;                    // id
  uint32_t tx_mailbox;               // CANϢ
  uint8_t tx_buff[8];                // ͻ,ϢȿͨCANSetDLC()趨,Ϊ8
  uint8_t rx_buff[8];                // ջ,ϢΪ8
  uint32_t rx_id;                    // id
  uint8_t rx_len;                    // ճ,Ϊ0-8
  // յĻص,ڽյ
  void (*fdcan_module_callback)(struct fdcaninstance *); // callback needs an instance to tell among registered ones
  void *id;                                              // ʹcanģָ(idָģӵдcanʵ,Ǹӹϵ)
} FDCANInstance;

/* CANʵʼṹ,˽ṹָ봫עắ */
typedef struct
{
  FDCAN_HandleTypeDef *fdcan_handle;              // can
  uint32_t tx_id;                                 // id
  uint32_t rx_id;                                 // id
  void (*fdcan_module_callback)(FDCANInstance *); // ݵĻص
  void *id;                                       // ӵcanʵģַ,ֲͬģ(ҪĻ),ҪԲ
} FDCAN_Init_Config_s;

/**
 * @brief Register a module to CAN service,remember to call this before using a CAN device
 *        ע(ʼ)һcanʵ,Ҫʼõָ.
 * @param config init config
 * @return CANInstance* can instance owned by module
 */
FDCANInstance *FDCANRegister(FDCAN_Init_Config_s *config);

/**
 * @brief ޸CANͱĵ֡;ע󳤶Ϊ8,ûн޸ĵʱ,ĬϳΪ8
 *
 * @param _instance Ҫ޸ĳȵcanʵ
 * @param length    趨
 */
void FDCANSetDLC(FDCANInstance *_instance, uint8_t length);

/**
 * @brief transmit mesg through CAN device,ͨcanʵϢ
 *        ǰҪCANʵtx_buffд뷢
 *
 * @attention ʱʱ䲻Ӧóô˺,ᵼ
 *
 * @param timeout ʱʱ,λΪms;Ϊus,øȷĿ
 * @param _instance* can instance owned by module
 */
uint8_t FDCANTransmit(FDCANInstance *_instance, float timeout);

#endif
