/**
 * @file CanBus.h
 * @brief CAN总线通信接口封装
 * 
 * 使用MCP2515 CAN控制器实现ESP32与上位机(ROS2)的通信
 * 引用库文件 autowp/autowp-mcp2515@^1.3.1
 * CAN通信帧格式：
 * - 标准帧(11位ID)，扩展帧(29位ID)
 * - 每帧最大8字节数据
 * - 波特率: 500Kbps
 * 
 * CAN ID分配：
 *   上行(ESP32→上位机):
 *     0x101 - 姿态数据(电压/角度/线速度)
 *     0x102 - 电机转速(RPM 1-3)
 *     0x103 - 编码器累计值(1-2)
 *     0x104 - 编码器累计值(3-4)
 *   下行(上位机→ESP32):
 *     0x201 - PWM模式控制
 *     0x202 - ROS速度模式控制
 * 
 * 硬件接线(MCP2515模块):
 *   ESP32 GPIO10 → CS
 *   ESP32 GPIO4  → INT
 *   ESP32 GPIO23 → SI (MOSI)
 *   ESP32 GPIO19 → SO (MISO)
 *   ESP32 GPIO18 → SCK
 *   3.3V         → VCC
 *   GND          → GND
 */

#ifndef _CanBus_H
#define _CanBus_H

#include <Arduino.h>
#include <mcp2515.h>

// MCP2515模块引脚定义
#define CAN_CS_PIN    15    // SPI片选引脚
#define CAN_INT_PIN   16    // 中断引脚(暂未使用,采用轮询)

// ============ CAN ID 定义 ============
// 上行: ESP32 → 上位机 (基础ID)
#define CAN_UPLINK_BASE   0x101
// 下行: 上位机 → ESP32
#define CAN_DOWNLINK_PWM  0x201   // PWM模式控制命令(-100~100)
#define CAN_DOWNLINK_ROS  0x202   // ROS速度模式控制命令(mm/s)

// ============ 数据包格式说明 ============
// 
// 【上行 0x101】姿态数据 - 8字节
//   Byte[0-1]: uint16 - 电压值(单位: 0.01V, 如 241 表示 24.1V)
//   Byte[2-3]: int16  - 航向角Z(单位: 度, -32768~32767)
//   Byte[4-5]: int16  - X轴线速度(单位: mm/s)
//   Byte[6-7]: int16  - Y轴线速度(单位: mm/s)
// 
// 【上行 0x102】电机转速 - 6字节
//   Byte[0-1]: int16 - 电机1转速(RPM)
//   Byte[2-3]: int16 - 电机2转速(RPM)
//   Byte[4-5]: int16 - 电机3转速(RPM)
// 
// 【上行 0x103】编码器累计值 - 8字节
//   Byte[0-3]: int32 - 编码器1累计值
//   Byte[4-7]: int32 - 编码器2累计值
// 
// 【上行 0x104】编码器累计值 - 8字节
//   Byte[0-3]: int32 - 编码器3累计值
//   Byte[4-7]: int32 - 编码器4累计值
// 
// 【下行 0x201】PWM控制 - 6字节
//   Byte[0-1]: int16 - X轴速度(-100~100, 百分比)
//   Byte[2-3]: int16 - Y轴速度(-100~100, 百分比)
//   Byte[4-5]: int16 - Z轴角速度(-100~100, 百分比)
// 
// 【下行 0x202】ROS控制 - 6字节
//   Byte[0-1]: int16 - X轴线速度(单位: mm/s)
//   Byte[2-3]: int16 - Y轴线速度(单位: mm/s)
//   Byte[4-5]: int16 - Z轴角速度(单位: deg/s)
//

/**
 * @brief CAN接收回调函数类型
 * @param canId CAN帧ID
 * @param data 数据缓冲区
 * @param len 数据长度(1-8字节)
 */
typedef void (*CanRxCallback)(uint16_t canId, const uint8_t* data, uint8_t len);

class CanBus
{
private:
    MCP2515* mcp2515;           // MCP2515 CAN控制器指针
    CanRxCallback _callback;    // 接收回调函数
    bool initialized = false;  // 初始化状态标志
    
public:
    CanBus();
    
    /**
     * @brief 初始化CAN总线
     * @param callback 接收到CAN帧时的回调函数
     * @return 初始化是否成功
     */
    bool begin(CanRxCallback callback);
    
    /**
     * @brief 更新CAN总线状态(轮询接收)
     * @note 应在loop()中周期性调用
     */
    void update();
    
    /**
     * @brief 发送原始CAN帧
     * @param canId CAN帧ID
     * @param data 数据指针
     * @param len 数据长度(最大8字节)
     * @return 发送是否成功
     */
    bool sendFrame(uint16_t canId, const uint8_t* data, uint8_t len);
    
    /**
     * @brief 发送姿态数据(上行0x101)
     * @param voltage 电池电压(V)
     * @param angleZ 航向角Z(度)
     * @param linearX X轴线速度(mm/s)
     * @param linearY Y轴线速度(mm/s)
     * @param angularZ 角速度(deg/s)
     */
    bool sendPoseData(float voltage, int16_t angleZ, int16_t linearX, int16_t linearY, int16_t angularZ);
    
    /**
     * @brief 发送电机转速数据(上行0x102)
     * @param rpm1 电机1转速(RPM)
     * @param rpm2 电机2转速(RPM)
     * @param rpm3 电机3转速(RPM)
     */
    bool sendMotorRpm(int16_t rpm1, int16_t rpm2, int16_t rpm3);
    
    /**
     * @brief 发送编码器累计值(上行0x103, 0x104)
     * @param tick1~tick4 4个编码器的累计脉冲数
     * @note int32类型,支持负数表示反转方向
     */
    bool sendEncoderTicks(int32_t tick1, int32_t tick2, int32_t tick3, int32_t tick4);
};

#endif