/**
 * 东北大学ACTION码盘驱动
 *
 * 本驱动采用ops_9定位系统,负责收发码盘的原始数据,并在任务中解析出相应的位置坐标。
 * 解析后的位置坐标将被交给导航处理模块,生成期望的运动向量。
 *
 * 使用手册:
 * 请参阅相关文档了解如何使用本驱动。
 *
 * 注意:
 * 本驱动仅适用于东北大学ACTION码盘。
 
 *删去Action_HandleOffline错误处理函数中对结构体清0的函数
 
 */

/* Includes ----------------------------------------------------------------- */
#include "tim.h"
#include "Action.h"
#include <string.h>

static osThreadId_t thread_alert;


uint8_t rxbuf[RS232_FRAME_LENGTH];

static void Ops10msTimerCallback(void *arg){
  (void)arg;
  osThreadFlagsSet(thread_alert,SIGNAL_OPSTIMER_REDY);
}

/* Private function  -------------------------------------------------------- */
static void ACTION_IdleCallback(void) {	
	osThreadFlagsSet(thread_alert,SIGNAL_ACTION_RAW_REDY);
}

/* Exported functions ------------------------------------------------------- */
int8_t ACTIONRECV_Init(Action_POS_t *pos){
	if(pos == NULL) return DEVICE_ERR_NULL;
	
	 pos->Action_ready =0;//码盘校准标志位初始化
	
   if((thread_alert = osThreadGetId()) == NULL ) return DEVICE_ERR_NULL;
   pos->action_timer_Id =
      osTimerNew(Ops10msTimerCallback, osTimerPeriodic,NULL,NULL);
	
	osTimerStart(pos->action_timer_Id,10);//此处ticks 理解为1个tick为1ms 此处为每10ms触发一次回调函数   
	
   BSP_UART_RegisterCallback(BSP_UART_ACTION,BSP_UART_IDLE_LINE_CB,
                            ACTION_IdleCallback);
	
   return DEVICE_OK;
}

int8_t ACTION_StartReceiving() {
  if (HAL_UARTEx_ReceiveToIdle_DMA(BSP_UART_GetHandle(BSP_UART_ACTION),
                           (uint8_t *)rxbuf,
                           sizeof(rxbuf)) == HAL_OK)
    return DEVICE_OK;
  return DEVICE_ERR;
}

bool_t ACTION_WaitDmaCplt(void) {
  return(osThreadFlagsWait(SIGNAL_ACTION_RAW_REDY, osFlagsWaitAll,400) ==
          SIGNAL_ACTION_RAW_REDY);   
}


/* *


*/
int8_t ACTION_Parse(Action_POS_t *pos)
{
  if (pos == NULL) return DEVICE_ERR_NULL;
  
  static union
  {
    fp32 pos_data[3];
    char rxbuff[12];
  } pos_rxbuf;

  
  if (rxbuf[0] == 0x0D && rxbuf[1] == 0x0A)
  {
    if (rxbuf[26] == 0x0A && rxbuf[27] == 0x0D)
    {

      pos_rxbuf.rxbuff[0]=rxbuf[2];
      pos_rxbuf.rxbuff[1]=rxbuf[3];
      pos_rxbuf.rxbuff[2]=rxbuf[4];
      pos_rxbuf.rxbuff[3]=rxbuf[5];
	    
	    
      pos_rxbuf.rxbuff[4]=rxbuf[14];
      pos_rxbuf.rxbuff[5]=rxbuf[15];
      pos_rxbuf.rxbuff[6]=rxbuf[16];
      pos_rxbuf.rxbuff[7]=rxbuf[17];
	    
	    
      pos_rxbuf.rxbuff[8]=rxbuf[18];
      pos_rxbuf.rxbuff[9]=rxbuf[19];
      pos_rxbuf.rxbuff[10]=rxbuf[20];
      pos_rxbuf.rxbuff[11]=rxbuf[21];
	    
	    
	    
      // 数据解析
      pos->pos_yaw = pos_rxbuf.pos_data[0];
     // 按照安装方向决定正负号
      pos->pos_x = pos_rxbuf.pos_data[1];
      pos->pos_y = pos_rxbuf.pos_data[2];
    
      pos ->Action_ready =1;//码盘校准完成
    }
  }
  else
  {
    return -1;
  }
  return DEVICE_OK;
}

//该函数用来计算速度(利用获取的位置来计算相应的速度)
//此处获取的是真实的位置(mm)后每10ms做一次微分处理
int8_t ACTION_DataRefresh(Action_POS_t *pos){
	if (pos == NULL) return DEVICE_ERR_NULL;
	
  if (osThreadFlagsGet() & SIGNAL_OPSTIMER_REDY){
	   osThreadFlagsClear(SIGNAL_OPSTIMER_REDY);
	   		//计算每毫秒的速度 该函数每10ms调用
		pos->pos_Vx = (pos->pos_x - pos->pos_lastX) / 10;
		pos->pos_Vy = (pos->pos_y - pos->pos_lastY) / 10;

		pos->pos_lastX = pos->pos_x;
		pos->pos_lastY = pos->pos_y;
  } 
	return DEVICE_OK;
}



int8_t Action_HandleOffline(Action_POS_t *pos) {
  if (pos == NULL) return DEVICE_ERR_NULL;

  (void)pos;
	
//  memset(pos, 0, sizeof(*pos));
  return 0;
}

/* 将字符串拼接 */
void Strcat(char str1[], char str2[], uint8_t num)
{
    int i = 0, j = 0;

    while (str1[i] != '\0')
        i++;
    
    for (j = 0; j < num; j++)
    {
        str1[i++] = str2[j];
    }
}

/* 该部分函数用于码盘的重定位系统 */
/* ----------------------------- */

/* 手动标定,用于校正 */
void ACT_Calibration(void)
{
    HAL_UART_Transmit(&huart1, (uint8_t *)"ACTR", 4, 100);
}

/* 清零 */
/* 将当前位置设置为 (0, 0) */
void ACT_ZeroClear(void)
{
    HAL_UART_Transmit(&huart1, (uint8_t *)"ACT0", 4, 100);
}

/* 更新 XY 坐标 */
/* 将当前位置更新为指定的 X 和 Y */
void ACT_UpdateXY(float pos_x, float pos_y)
{
    char update_xy[12] = "ACTD"; // 命令前缀为 "ACTD"
    static union
    {
        float XY[2];    // 两个浮点数表示 X 和 Y 坐标
        char data[8];   // 将浮点数视为字节数据
    } set;

    set.XY[0] = pos_x;
    set.XY[1] = pos_y;

    Strcat(update_xy, set.data, 8);

    HAL_UART_Transmit(&huart1, (uint8_t *)update_xy, sizeof(update_xy), 100);
}