#include "gps.h"


//#define TEST 					1  //测试使用,去除的时候可以接触代码的调用
#define parse					1 // 测试使用



/**
提示: 虽然 BLE 以及 GPS都是DMA+ UART接收，但是它们都有所不同
BLE --- DMA + IDLE 中断  循环 DMA + 空闲中断触发处理  UART IDLE  
GPS --- DMA +固定长度 + TC中断   设置固定长度 DMA    DMA传输完成中断

**/


//外部引入
extern UART_HandleTypeDef huart2;
extern DMA_HandleTypeDef handle_GPDMA1_Channel3;


//全局数据变量定义
uint8_t GPS_DMA_RX_BUF[GPS_DMA_RX_BUF_LEN];  //用于DMA接收缓冲
_GPSData GPS;

void GPS_Init(void)
{
    HAL_UARTEx_ReceiveToIdle_DMA(&huart2, GPS_DMA_RX_BUF, GPS_DMA_RX_BUF_LEN);
    __HAL_DMA_DISABLE_IT(&handle_GPDMA1_Channel3, DMA_IT_HT);  // 禁用半传输
}

#ifdef parse
// GPS数据解析
void parseGpsBuffer()
{
	char *subString;
	char *subStringNext;
	char i = 0;
	
	if(GPS.isGetData)
	{
		GPS.isGetData = 0; // 把标志位置为1
		
		char usefullBuffer[2] = {0};
		for(i = 0; i <= 6; i++)
		{
			if(i == 0)
			{
				
				subString = strstr(GPS.GPS_Buffer,",");
				if(!subString)return;
			}
			else
			{
				subString++;
				subStringNext = strstr(subString,",");
				if(!subStringNext)return;
				
				switch(i)
				{
					case 1:
						memcpy(GPS.UTCTime,subString,subStringNext - subString);
						break;
					case 2:
						memcpy(usefullBuffer,subString,subStringNext - subString);
						break;
					case 3:
						memcpy(GPS.latitude,subString,subStringNext - subString);
						break;
					case 4:
						memcpy(GPS.N_S,subString,subStringNext - subString);
						break;
					case 5:
						memcpy(GPS.longitude,subString,subStringNext - subString);
						break;
					case 6:
						memcpy(GPS.E_W,subString,subStringNext - subString);
						break;
					default:break;
				}
				
				subString = subStringNext;
			}
			
		}
		GPS.isParseData = 1;
		GPS.isUsefull = (usefullBuffer[0] == 'A') ? 1 : 0;
	}
	
}
#else // 这里是对于改进后的parse 解析 两个都需要进行测试
void parseGpsBuffer()
{
    char *fields[7];
    char *token;
    int fieldIndex = 0;

    if (GPS.isGetData)
    {
        GPS.isGetData = 0; // 把标志位置为0

        token = strtok(GPS.GPS_Buffer, ",");
        while (token != NULL && fieldIndex < 7)
        {
            fields[fieldIndex++] = token;
            token = strtok(NULL, ",");
        }

        if (fieldIndex == 7)
        {
            memcpy(GPS.UTCTime, fields[1], sizeof(GPS.UTCTime) - 1);
            GPS.UTCTime[sizeof(GPS.UTCTime) - 1] = '\0';

            memcpy(GPS.latitude, fields[3], sizeof(GPS.latitude) - 1);
            GPS.latitude[sizeof(GPS.latitude) - 1] = '\0';

            memcpy(GPS.N_S, fields[4], sizeof(GPS.N_S) - 1);
            GPS.N_S[sizeof(GPS.N_S) - 1] = '\0';

            memcpy(GPS.longitude, fields[5], sizeof(GPS.longitude) - 1);
            GPS.longitude[sizeof(GPS.longitude) - 1] = '\0';

            memcpy(GPS.E_W, fields[6], sizeof(GPS.E_W) - 1);
            GPS.E_W[sizeof(GPS.E_W) - 1] = '\0';

            GPS.isParseData = 1;
            GPS.isUsefull = (fields[2][0] == 'A') ? 1 : 0;
        }
    }
}


/*
改进点总结
使用 strtok 进行分隔：
更加简洁地分割字符串。
数组存储字段：
使用数组存储每个字段的指针，减少重复代码。
边界检查：
确保字段数量足够，避免数组越界。
字符串截断：
确保复制的字符串以 null 结尾，避免潜在的字符串处理问题。
*/
#endif

// 转换角度
double Convert_to_degrees(char *data)
{
	double temp = atof(data);
	int deg = (int)(temp / 100);
	double min = temp - deg * 100;
	return deg + (min / 60.0);
}


// 串口数据清除
void GPS_Data_CLR(void)
{
	memset(GPS_DMA_RX_BUF,0,GPS_DMA_RX_BUF_LEN);
	
}



//void GPS_DMA_Start(void)
//{
//	HAL_UART_Receive_DMA(&huart2,GPS_DMA_RX_BUF,GPS_DMA_RX_BUF_LEN);
//	__HAL_DMA_ENABLE_IT(huart2.hdmarx,DMA_IT_HT);  //半传输中断
//	__HAL_DMA_ENABLE_IT(huart2.hdmarx,DMA_IT_TC);  //全传输中断
//}

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if(huart->Instance == USART2)
	{
		// 根据 Size 拷贝接收到的数据
		memcpy(GPS.GPS_Buffer,GPS_DMA_RX_BUF,Size);
		GPS.GPS_Buffer[Size] = '\0';
		GPS.isGetData = 1;  //数据接收标志位置为1
		
		//重新开启接收
		HAL_UARTEx_ReceiveToIdle_DMA(&huart2,GPS_DMA_RX_BUF,GPS_DMA_RX_BUF_LEN);
		__HAL_DMA_DISABLE_IT(&handle_GPDMA1_Channel3,DMA_IT_HT);
	}
	
}


// 如果需要使用到ThreadX 就把gps.h中的 TEST 宏定义加入
#ifdef  TEST


void gps_thread_entry(ULONG thread_input)
{
    GPS_Init();
    static int gps_first_fix_sent = 0;

    while (1)
    {
        ULONG events;
        tx_event_flags_get(&system_events, EVENT_GPS_DATA_READY, TX_OR_CLEAR, &events, TX_WAIT_FOREVER);

        parseGpsBuffer();

        if (GPS.isParseData && GPS.isUsefull)
        {
            current_location.lat = Convert_to_degrees(GPS.latitude);
            current_location.lon = Convert_to_degrees(GPS.longitude);
            tx_event_flags_set(&system_events, EVENT_LOCATION_UPDATED, TX_OR);

            BLE_Message msg;
            msg.msg_type = 1;
            snprintf(msg.data, sizeof(msg.data), "#{\"lat\":%.6f,\"lon\":%.6f,\"angle\":%.2f}\n",
                     current_location.lat,
                     current_location.lon,
                     current_location.angle);
            tx_queue_send(&ble_tx_queue, &msg, TX_WAIT_FOREVER);

            if (!gps_first_fix_sent)
            {
                gps_first_fix_sent = 1;
                BLE_Message fix_msg;
                fix_msg.msg_type = 2;
                snprintf(fix_msg.data, sizeof(fix_msg.data), "#{\"info\":\"GPS fixed and ready\"}\n");
                tx_queue_send(&ble_tx_queue, &fix_msg, TX_WAIT_FOREVER);
            }
        }
    }
}


#endif


