#ifndef ODRIVE_CAN_H
#define ODRIVE_CAN_H

#ifdef __cplusplus
extern "C"{
#endif

#include "struct_typedef.h"
#include "device.h"
	
/**
请在此处更改你设置的节点id,六位,最大0x3f
*/
typedef enum
{
    AXIS0_NODE = 0x010,
    AXIS1_NODE = 0x20
}node_id_e;


/**
*下面的内容中**为CANopen内容,odrive不用
*若标为***,可发送至任意地址
*若标为*,则为客户端服务器模型,发送时使用RTR,然后接收相同id的信息,对应CANopen SDO
*若什么都没有标,则为生产者消费者模型,只需发送,对应CANopen PDO
*大部分cmd_id仅仅是列出,推荐使用odrivetool和gui更改,更加方便快速
*/
typedef enum
{
    //**//NMT消息
    ODRIVE_NMT = 0x000,
    //心跳消息,前四位错误信息,后四位当前状态
    ODRIVE_HEART = 0x001,
    //急停消息
    ODRIVE_STOP = 0x002,
    //*//获取电机错误,前四位为错误信息
    ODRIVE_ERROR_MOTOR = 0x003,
    //*//获取编码器错误,前四位为错误信息
    ODRIVE_ERROR_ENCODER = 0x004,
    //*//获取无传感器错误,前四位为错误信息
    ODRIVE_SENSORLESS_ERROR = 0x005,
    //设置节点id,前四位
    ODRIVE_AXIS_NODE = 0x006,
    //设置请求状态,前四位
    ODRIVE_STATUS = 0x007,
    //设置启动配置
    ODRIVE_AXIS_START = 0x008,
    //*//获取编码器估算值,前四位位置,后四位速度
    ODRIVE_ENCODER_VALUE = 0x009,
    //*//编码器计数值,前四位为shadow,后四位为cpr值
    ODRIVE_ENCODER_COUNT = 0x00A,
    //设置控制模式,前四位控制模式,后四位输入模式
    ODRIVE_CONTROL_MODE = 0x00B,
    //设置目标位置,前四位位置,中两位vel ff,后两位Torque FF,速度限制和力矩限制,若上位机配好了可以给0
    ODRIVE_POS_SET = 0x00C,
    //设置目标速度,前四位速度,后四位torque ff
    ODRIVE_SPEED_SET = 0x00D,
    //设置力矩,前四位力矩
    ODRIVE_TORQUE = 0x00E,
    //设置极限速度,前四位速度
    ODRIVE_SPEED_LIM = 0x00F,
    //开启防嵌齿
    ODRIVE_PREVENT = 0x010,
    //设置梯形模式速度极限,前四位速度
    ODRIVE_TRAJ_SPEED_LIM = 0x011,
    //设置梯形模式加减速极限,前四位加速,后四位减速
    ODRIVE_TRAJ_ACC_LIM = 0x012,
    //设置梯形模式惯性,前四位
    ODRIVE_TRAJ_INERTIA = 0x013,
    //*//获取iq信号
    ODRIVE_IQ = 0x014,
    //*//无传感器估算值,前四位位置,后四位速度
    ODRIVE_SENSORLESS_VALUE = 0x015,
    //***//重启
    ODRIVE_RESATRT = 0x016,
    //***//获取vbus电压
    ODRIVE_VOL = 0x017,
    //清除错误信息
    ODRIVE_CLEARN_ERROR = 0x018

}odrive_cmd_e;

typedef struct
{
    fp32 pos;
    fp32 speed;
}odrive_msg_t;


/**
 * @brief  获取编码器估算值
 * @param  node_id 节点id,AXIS0_NODE或者AXIS0_NODE
 * @return  device_status_e,若值为0,则为成功
 */
device_status_e odrive_get_encode(node_id_e node_id);

/**
 * @brief  odrive初始化
 * @param  none
 * @return  device_status_e,若值为0,则为成功
 */
device_status_e Odrive_Can_Init(void);

/**
 * @brief  速度模式控制电机
 * @param  node_id 节点id,AXIS0_NODE或者AXIS0_NODE
 * @param  speed 目标速度
 * @return  device_status_e,若值为0,则为成功
 */
device_status_e odrive_speed_cmd(node_id_e node_id, fp32 speed);

/**
 * @brief  位置模式控制电机
 * @param  node_id 节点id,AXIS0_NODE或者AXIS1_NODE
 * @param  pos 目标位置
 * @param  accel 加速度限制
 * @param  decel 减速度限制
 * @return  device_status_e,若值为0,则为成功
 */
device_status_e odrive_accel_cmd(node_id_e node_id, fp32 accel , fp32 decel);

/**
 * @brief  位置模式控制电机
 * @param  node_id 节点id,AXIS0_NODE或者AXIS1_NODE
 * @param  pos 目标位置
 * @param  accel 加速度限制
 * @param  decel 减速度限制
 * @return  device_status_e,若值为0,则为成功
 */
device_status_e odrive_pos_cmd(node_id_e node_id, fp32 pos);

/**
 * @brief  获取odrive结构体指针
 * @param  none
 * @return  信息结构体指针
 */
 odrive_msg_t* Get_Odrive_Point(void);

void User_Odrive_Can1_CB(void);
void User_Odrive_Can2_CB(void);

#ifdef __cplusplus
}
#endif

#endif