Files
banban/ql-kernel/threadx/quec/quec_hx_gps.c
T

1188 lines
36 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*============================================================================================
Copyright(c) 2018 Quectel Wierless Solution,Co.,Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential.
============================================================================*/
#include "quec_hx_gps.h"
#include "quec_rtos.h"
#include "gps_debug.h"
#include "gps_channel.h"
#include "quec_hx_gps_update.h"
#include "quec_nmea_parse.h"
#include "quec_gps_rom.h"
#include "gps_app.h"
#include "quec_hx_apflash.h"
#include "quec_cust_feature.h"
#include "quec_hx_agps.h"
#include "quec_gps_http.h"
#define QUEC_GNSS_MSG_MAX_ITEM_NBR 50
#define QUEC_GPS_TASK_STACK_SIZE 10*1024
#define APFLASH_DATA_LEN 4*1024
#define HX_GPS_KEEPALIVE_CNT 5*1000 //5S内没有nmea语句将会重启gps模块
QUEC_GPS_DEV_T g_quec_gps_dev;
QUEC_GPS_OPS g_quec_gps_ops;
QUEC_NMEA_CB g_quec_nmea_cb;
hx_locationg_t hx_loactiong_para;/*解析出的位置信息*/
extern int quec_gnss_type_check(void);
static int gnss_rom_type;
//多合一固件当前的gnss类型
hx_gnss_sys_t quec_hxgps_type = GNSS_SYS;
#if 0
hx_locationg_t hx_loactiong_para_back;
#endif
quec_gnss_sate_num_t gnss_sate_num;
#ifdef QUEC_HX_GNSS_SUPPORT
#include "gps_app.h"
//定义全局变量保存HTTP账号和密码,防止在头文件中被开源出去
quec_agps_cfg_t quec_hx_agps_cfg={
.profile_inx=1,\
.agps_url="http://quectel-api1.rx-networks.cn/rxn-api/locationApi/rtcm\0",\
.agpsvendorID="wLgWwv6JQt\0",\
.agpsmodelID="Quectel\0",\
.agpspassWord="aFltUERDZzZxeTY5cEp2eA==\0"\
};
#endif
#define ARRAY_LENGTH(a) (sizeof a / sizeof (a[0]))
extern int nmea_parse_aidinfo( quec_gnss_sate_num_t * gnss_sate_num,char *sentence);
int quec_hx_gnss_sys_set(int sys_type)
{
#if defined (HX_GNSS_CC11_SUPPORT)
if(quec_hxgps_type==BEIDOU_ONLY)
{
return 0;
}
#endif
quec_gps_msg_t cmd_ptr;
memset(&cmd_ptr,0,sizeof(quec_gps_msg_t));
int cfg_sys = 0;
cfg_sys=sys_type;
if((cfg_sys<=8)&&(cfg_sys>=0))
{
char *data=malloc(4);
if(NULL==data)
{
return -1;
}
memcpy(data,&cfg_sys,4);
cmd_ptr.cmd_id = QUEC_GNSS_CFGSYS;
cmd_ptr.data = data;
quec_gnss_cmd_send(&cmd_ptr);
free(data);
}
return 0;
}
/****************************************************
nmea语句 value
禁用 0
GGA 1
RMC 2
GSV 4
GSA 8
VTG 16
GLL 32
全部打开 63
*****************************************************/
int quec_hx_gnss_nmea_set(char value)
{
int i=0;
quec_gps_msg_t cmd_ptr;
memset(&cmd_ptr,0,sizeof(quec_gps_msg_t));
char *data = NULL;
cmd_ptr.cmd_id = QUEC_GNSS_NMEA_TYPE;
uint16 quec_gnss_nmea_type[]={0,4,3,2,5,1};
for(i=0;i<6;i++)
{
data=malloc(4);
if(NULL==data)
{
return -1;
}
else{
memset(data,0,4);
}
data[0] = quec_gnss_nmea_type[i];
data[1] = (value & 0x1);
value = value >>1;
cmd_ptr.data = data;
quec_gnss_cmd_send(&cmd_ptr);
free(data);
}
return 0;
}
/********************************************************************
R3.4.0.0以下版本(国内镜像包)
value:
0 H1: GPS
5 H11: GPS+BDS
7 H10: BDS
R3.4.1.12 适用如下配置 北斗支持B1I
value:
0 H1: GPS
1 H11: GPS+BDS
3 H1101: GPS+GLONASS+GALILEO
4 H101: GPS+ GLONASS
5 H1011: GPS+BDS+GALILEO
6 H1001: GPS+GALILEO
7 H10: BDS
和芯CC1161W支持4个星系随意组合,北斗支持B1I+B1C,QZSS和GPS绑定关系
新增2,8两个组合,后续可以根据客户需求进行扩展
0 H10001: GPS
1 H10091: GPS+BDS
2 H11191: GPS+BDS+GALILEO+GLONASS
3 H11101: GPS+GLONASS+GALILEO
4 H10101: GPS+GLONASS
5 H11091: GPS+BDS+GALILEO
6 H11001: GPS+GALILEO
7 H90: BDS
8 H10191: GPS+BDS+GLONASS
*********************************************************************/
static int quec_gnss_cmd_cfgsys_process(quec_gps_msg_t *cmd_ptr)
{
#if defined (HX_GNSS_CC11_SUPPORT)
uint16 quec_gnss_cfgsys_table_v2[]={10001,10091,11191,11101,10101,11091,11001,90,10191};
#else
uint16 quec_gnss_cfgsys_table_v2[]={1,11,0,1101,101,1011,1001,10,0};
#endif
int data = *(int*)(cmd_ptr->data);
if((data<0)||(data>8))
{
return 0;
}
return quec_gnss_cfgsys_table_v2[data];
}
//修复CC11系列1PPS有380ms的误差,在初始化gnss时发送命令消除
void quec_gnss_cmd_1pps_config(void)
{
int i=0;
quec_gps_msg_t cmd_ptr;
memset(&cmd_ptr,0,sizeof(quec_gps_msg_t));
cmd_ptr.cmd_id = QUEC_GNSS_1PPS_CONFIG;
cmd_ptr.data = NULL;
quec_gnss_cmd_send(&cmd_ptr);
return 0;
}
int quec_gps_reset(int type)
{
quec_gps_msg_t cmd_ptr;
QUEC_GPS_DEV_T *gps_dev=quec_get_gps_dev();
if(!(gps_dev->worke_state & QUEC_NMEA_PASRE_STATE)){//必须时等到gps开始输出nmea语句时才允许发指令
return -3;
}
memset(&cmd_ptr,0,sizeof(quec_gps_msg_t));
if((type<QGPS_START_COLD)||(type>QGPS_START_WARM))
{
return -1;
}
switch(type)
{
case QGPS_START_COLD:
cmd_ptr.cmd_id = QUEC_GNSS_COLD_RESET;
cmd_ptr.data = NULL;
break;
case QGPS_START_WARM:
cmd_ptr.cmd_id = QUEC_GNSS_WARM_RESET;
cmd_ptr.data = NULL;
break;
case QGPS_START_HOT:
cmd_ptr.cmd_id = QUEC_GNSS_HOT_RESET;
cmd_ptr.data = NULL;
break;
default:
return -2;
}
quec_gnss_cmd_send(&cmd_ptr);
gps_dev->worke_state |= QUEC_GPS_RESET_STATE;
return 0;
}
#if 0
void quec_gnss_aidpos_msg_send(void)
{
quec_gps_msg_t cmd_ptr;
memset(&cmd_ptr,0,sizeof(quec_gps_msg_t));
cmd_ptr.cmd_id = QUEC_GNSS_AIDPOS_SET;
cmd_ptr.data = NULL;
quec_gnss_cmd_send(&cmd_ptr);
}
#endif
void quec_gnss_aidtime_msg_send(void)
{
quec_gps_msg_t cmd_ptr;
memset(&cmd_ptr,0,sizeof(quec_gps_msg_t));
cmd_ptr.cmd_id = QUEC_GNSS_AIDTIME_SET;
cmd_ptr.data = NULL;
quec_gnss_cmd_send(&cmd_ptr);
}
int quec_gnss_nmea_cnf(void)
{
QuecOSStatus err = kNoErr;
quec_gps_handle *quec_param_ptr = quec_gnss_config_para_get();
if((quec_param_ptr->nmea_handle_cfg.mdflag&GNSS_SYSCONFGE_ENABLE)==0){
#if defined (HX_GNSS_CC11_SUPPORT)
if(quec_hxgps_type==BEIDOU_ONLY)
{
quec_param_ptr->nmea_handle_cfg.gnss_sys_type = BEIDOU_SYS;
}
else
{
quec_param_ptr->nmea_handle_cfg.gnss_sys_type = GPS_BEIDOU_GALILEO_SYS;
}
#else
quec_param_ptr->nmea_handle_cfg.gnss_sys_type = GPS_BEIDOU_GALILEO_SYS;
#endif
}
/*设置GNSS nmea语句种类 //默认打开GGA/RMC/GSA/GSV/VTG */
if((quec_param_ptr->nmea_handle_cfg.mdflag&GNSS_NMEATYPE_ENABLE)==0){
quec_param_ptr->nmea_handle_cfg.gps_nmea_type =
GGA_EN|RMC_EN|GSV_EN|GSA_EN|VTG_EN;
}
quec_gnss_sys_set(quec_param_ptr->nmea_handle_cfg.gnss_sys_type);
quec_gnss_nmea_set(quec_param_ptr->nmea_handle_cfg.gps_nmea_type & 0x3f);
return 0;
}
void *quec_get_gnss_sate_num(void)
{
return &gnss_sate_num;
}
int quec_gnss_nmea_ret_value_parse(char *sentence, int length)
{
int len = 0;
int ret = 0;
static int appentry = 1;
QUEC_GPS_DEV_T *gps_dev=quec_get_gps_dev();
len = jmin(length,GNSS_CMD_MAX_LENGTH);
if (strncmp(sentence, "$OK", 3) == 0){
GPS_LOGI("ok %d",gps_dev->worke_state);
gps_dev->worke_state &= (~QUEC_GPS_RESET_STATE);
GPS_LOGI("ok %d",gps_dev->worke_state);
}else if(strncmp(sentence, "$FAIL", 5) == 0){
}else if(strncmp(sentence, "$AIDINFO", 8)==0){
GPS_LOGD("%s\r\n",sentence);
nmea_parse_aidinfo(&gnss_sate_num,sentence);
check_aidinfo_and_update_agps();
if(g_quec_gps_dev.nmea_cb->gnss_ephemeris_info_cb){
g_quec_gps_dev.nmea_cb->gnss_ephemeris_info_cb(&gnss_sate_num);
}
}else if(strncmp(sentence, "$CFGGEOID", 9) == 0){
;
}else if (strncmp(sentence, "$PDTINFO", 8)==0){
;
}else{/*非回复数据,走nmea解析器*/
ret = 1;
}
return ret ;
}
static struct tm *gmtime_r(const time_t *tloc, struct tm *result) {
struct tm *tm;
/* Bug Fix.
* Return Value of gmtime() is NULL On CranePlatform.
* SO local_time() is replaced here.By JoshuaWang.@0205/2021.
*/
tm = localtime(tloc);
if(tm)
return memcpy(result, tm, sizeof(struct tm));
return NULL;
}
int quec_gnss_aidtime_process(char *msgbuf)
{
int send_len =0;
struct tm time;
unsigned int now= GPS_GET_RTC_TIME();
gmtime_r(&now, &time);
send_len = snprintf((char *)(msgbuf), sizeof("$AIDTIME"),"$AIDTIME");
send_len += snprintf((char *)(msgbuf+send_len), GNSS_CMD_MAX_LENGTH - send_len,",%d,%d,%d,%d,%d,%d,%d",
time.tm_year+1900,time.tm_mon+1,
time.tm_mday,time.tm_hour,time.tm_min,
time.tm_sec,rand()%1000);
send_len+=snprintf(msgbuf+send_len, GNSS_CMD_MAX_LENGTH - send_len, "\r\n");
GPS_LOGD("%s",msgbuf);
return send_len;
}
#if 0
int quec_gnss_aidpos_process(char *msgbuf,hx_locationg_t *nema_data)
{
char rsp_str[256]= {0};
int len = 0;
int send_len = 0;
memset(rsp_str, 0, 256);
len += (uint16)snprintf((char *)(rsp_str+len), sizeof("$AIDPOS"),"$AIDPOS");
len += (uint16)snprintf((char *)(rsp_str+len), sizeof(rsp_str)-len,",%09.6lf",nema_data->latitude);
len += (uint16)snprintf((char *)(rsp_str+len), sizeof(rsp_str)-len,",%c",nema_data->latitude_cardinal);
len += (uint16)snprintf((char *)(rsp_str+len), sizeof(rsp_str)-len,",%010.6lf",nema_data->longitude);
len += (uint16)snprintf((char *)(rsp_str+len), sizeof(rsp_str)-len,",%c",nema_data->longitude_cardinal);
len += (uint16)snprintf((char *)(rsp_str+len), sizeof(rsp_str)-len,",%.1f",nema_data->altitude);
send_len=snprintf(msgbuf, GNSS_CMD_MAX_LENGTH - 1, "%s",rsp_str);
send_len+=snprintf(msgbuf+send_len, GNSS_CMD_MAX_LENGTH - send_len, "\r\n");
return send_len;
}
#endif
uint8_t one_system_cnr_index = 0;
uint8_t total_cnr_index = 0;
static int quec_gnss_nmea_value_update(struct nmea_s *nmea, hx_locationg_t *gps_data)
{
struct nmea_gprmc_s *rmc = NULL;
struct nmea_gpgsv_s *gsv = NULL;
struct nmea_gpgga_s *gga = NULL;
struct nmea_gpgsa_s *gsa = NULL;
struct nmea_gpvtg_s *vtg = NULL;
unsigned int *temp_cnr = NULL;
uint8_t i = 0;
if(nmea == NULL || gps_data == NULL)
{
GPS_LOGE("param invalid. \r\n");
return -1;
}
if(nmea->type == NMEA_UNKNOWN)
{
GPS_LOGE("gps nmea type is unknown! \r\n");
return -1;
}
switch(nmea->type)
{
case NMEA_RMC:
rmc = (struct nmea_gprmc_s*)nmea->data;
if(rmc)
{
gps_data->valid = rmc->valid;
//经纬??
gps_data->longitude = (rmc->longitude.degrees)*100 + rmc->longitude.minutes;
gps_data->longitude_cardinal = rmc->longitude.cardinal;
gps_data->latitude = (rmc->latitude.degrees)*100 + rmc->latitude.minutes;
gps_data->latitude_cardinal = rmc->latitude.cardinal;
//地面航向
gps_data->heading = rmc->course;
//地面速率
gps_data->gps_speed = rmc->speed;
//UTC
gps_data->time.tm_year = rmc->time.tm_year;
gps_data->time.tm_mon = rmc->time.tm_mon;
gps_data->time.tm_mday = rmc->time.tm_mday;
gps_data->time.tm_hour = rmc->time.tm_hour;
gps_data->time.tm_min = rmc->time.tm_min;
gps_data->time.tm_sec = rmc->time.tm_sec;
}
if(gps_data->gsv_status == SV_UPDATING)
{
gps_data->cnrs_index = total_cnr_index;
gps_data->gsv_status = SV_UPDATED;
}
break;
case NMEA_GGA:
gga = (struct nmea_gpgga_s*)nmea->data;
if(gga)
{
gps_data->altitude = gga->altitude;
gps_data->satellites_num = gga->satellites_tracked;
}
break;
case NMEA_GSA:
gsa = (struct nmea_gpgsa_s*)nmea->data;
if(gsa != NULL)
{
gps_data->hdop = gsa->hdop;
gps_data->pdop = gsa->pdop;
gps_data->fix_mode = gsa->navmode;
}
break;
case NMEA_VTG:
vtg = (struct nmea_gpvtg_s*)nmea->data;
if(vtg != NULL)
{
//地面航向
gps_data->cogt = vtg->cogt;
//地面速率
gps_data->sog = vtg->sog;
gps_data->kph = vtg->kph;
}
break;
case NMEA_GSV:
if(gps_data->gsv_status == SV_NEED_UPDATE)
{
memset(gps_data->cnrs, 0, sizeof(gps_data->cnrs));
one_system_cnr_index = 0;
total_cnr_index = 0;
gps_data->gsv_status = SV_UPDATING;
}
gsv = (struct nmea_gpgsv_s *)nmea->data;
if (gsv != NULL)
{
//每次解析一条GSV,每条最多4个卫星,等到一组NMEA读取完
temp_cnr = &(gps_data->cnrs[total_cnr_index]);
for (i = 0; one_system_cnr_index < gsv->total_sats && i < 4 && total_cnr_index + one_system_cnr_index < HX_GSV_MAX_SATS &&
gsv->sats[i].snr; i++)
{
temp_cnr[one_system_cnr_index] = gsv->sats[i].snr;
GPS_LOGD("sat[%d]:%d total_cnr_index:%d one_system_cnr_index:%d --max%d", i, gsv->sats[i].snr,
total_cnr_index, one_system_cnr_index, HX_GSV_MAX_SATS);
one_system_cnr_index++;
}
if (one_system_cnr_index >= gsv->total_sats)
{
total_cnr_index += one_system_cnr_index;
one_system_cnr_index = 0;
}
}
break;
default:
break;
}
return 0;
}
int quec_gnss_nmea_parse(char* buf,int buf_len)
{
char nmea_buff[256];
char nmea_buff1[256];
unsigned int port_channel;
struct nmea_s *nmea = NULL;
int len = 0;
int ret = 0;
int i = 0;
QUEC_NMEA_CB *nmea_callback = g_quec_gps_dev.nmea_cb;
if(NULL == buf)
return -1;
len = jmin(sizeof(nmea_buff)-1, buf_len);
memset(nmea_buff, 0, sizeof(nmea_buff));
memcpy(nmea_buff, buf, len);
memcpy(nmea_buff1,nmea_buff,len);
GPS_LOGI("%s ,%d\r\n",nmea_buff,len);
if (NULL == memchr(nmea_buff, '$', len)){
return -1;
}
ret = quec_gnss_nmea_ret_value_parse(nmea_buff,len);
if(ret == 0){
return 0;
}
nmea = nmea_parse(nmea_buff, len, 1);
if (nmea){
ret = quec_gnss_nmea_value_update(nmea, &hx_loactiong_para);
if(nmea_callback->loaction_update_cb){
nmea_callback->loaction_update_cb(&hx_loactiong_para); /*定位数据通过回调更新到上层*/
}
if(nmea_callback->nmea_str_cb){
nmea_callback->nmea_str_cb(&hx_loactiong_para.time, nmea_buff1,len); /*实时nmea数据通过回调输出到上层*/
}
//20230616 屏蔽和芯gnss aidpos注入功能,实际测试无效,且概率性会引起串口冲突,产生assert dump
#if 0
if(hx_loactiong_para.valid){
/*非重启快速启动*/
memset(&(hx_loactiong_para_back),0,sizeof(struct quec_gnss_data_struct));
/*缓存重启前的定位数据,在重启后需要使用指令注入*/
memcpy((void*)(&(hx_loactiong_para_back)),(void*)(&hx_loactiong_para),sizeof(struct quec_gnss_data_struct));
}else {
if(hx_loactiong_para_back.valid){
quec_gnss_aidpos_msg_send();
hx_loactiong_para_back.valid = 0;
}
}
#endif
if (ret){
GPS_LOGE("nmea_value_update error. \r\n");
GPS_LOGE(" %s", nmea_buff);
}
if (nmea->data) {
free(nmea->data);
nmea->data = NULL;
}
free(nmea);
nmea = NULL;
}
return 0;
}
hx_locationg_t * hx_location_data_get(void)
{
return &hx_loactiong_para;
}
int quec_gnss_cmd_send(quec_gps_msg_t *rcv)
{
unsigned int send_len = 0;
if(rcv == NULL)
return -1;
char *msgbuf=malloc(GNSS_CMD_MAX_LENGTH);
if(msgbuf == NULL)
ASSERT(0);
memset(msgbuf,0,GNSS_CMD_MAX_LENGTH);
switch(rcv->cmd_id)
{
case QUEC_GNSS_PDTINFO_CMD:
send_len=snprintf(msgbuf, GNSS_CMD_MAX_LENGTH - 1, "$PDTINFO\r\n");
break;
case QUEC_GNSS_HOT_RESET: /*热启动*/
send_len=snprintf(msgbuf, GNSS_CMD_MAX_LENGTH - 1, "$RESET,0,h00\r\n");
break;
case QUEC_GNSS_WARM_RESET:/*温启动*/
send_len=snprintf(msgbuf, GNSS_CMD_MAX_LENGTH - 1, "$RESET,0,h01\r\n");
break;
case QUEC_GNSS_COLD_RESET:/*冷启动*/
#if defined (HX_GNSS_CC11_SUPPORT)
send_len=snprintf(msgbuf, GNSS_CMD_MAX_LENGTH - 1, "$RESET,0,hFF\r\n");
#else
send_len=snprintf(msgbuf, GNSS_CMD_MAX_LENGTH - 1, "$RESET,0,h85\r\n");
#endif
break;
case QUEC_GNSS_AGPS_AIDINFO_REQ:
send_len=snprintf(msgbuf, GNSS_CMD_MAX_LENGTH - 1, "$AIDINFO\r\n");
break;
case QUEC_GNSS_CFG_GEOID_REQ:
send_len=snprintf(msgbuf, GNSS_CMD_MAX_LENGTH - 1, "$CFGGEOID\r\n");
break;
case QUEC_GNSS_CFG_GEOID_SET:
send_len=snprintf(msgbuf, GNSS_CMD_MAX_LENGTH - 1, "$CFGGEOID,1\r\n");
break;
case QUEC_GNSS_CFGSYS:
if(quec_gnss_cmd_cfgsys_process(rcv))
{
send_len=snprintf(msgbuf, GNSS_CMD_MAX_LENGTH - 1, "$CFGSYS,H%d",quec_gnss_cmd_cfgsys_process(rcv));
send_len+=snprintf(msgbuf+send_len, GNSS_CMD_MAX_LENGTH - 1, "\r\n");
}
break;
case QUEC_GNSS_NMEA_TYPE:
#if defined (HX_GNSS_CC11_SUPPORT)
send_len=snprintf(msgbuf, GNSS_CMD_MAX_LENGTH - 1, "$CFGMSG,0,%d,%d,1",rcv->data[0],rcv->data[1]);
#else
send_len=snprintf(msgbuf, GNSS_CMD_MAX_LENGTH - 1, "$CFGMSG,0,%d,%d",rcv->data[0],rcv->data[1]);
#endif
send_len+=snprintf(msgbuf+send_len, GNSS_CMD_MAX_LENGTH - 1, "\r\n");
break;
#if defined (HX_GNSS_CC11_SUPPORT)
case QUEC_GNSS_1PPS_CONFIG:
send_len=snprintf(msgbuf, GNSS_CMD_MAX_LENGTH - 1, "$CFGTP,1000000,500000,1,0,800,-380");
break;
#endif
#if 0
case QUEC_GNSS_AIDPOS_SET:
send_len = quec_gnss_aidpos_process(msgbuf,&(hx_loactiong_para_back));
break;
#endif
case QUEC_GNSS_AIDTIME_SET:
send_len = quec_gnss_aidtime_process(msgbuf);
break;
default:
free(msgbuf);
return -2;
}
if(send_len)
{
GPS_COM_PutByte_Buffer(msgbuf,send_len);
}
free(msgbuf);
return 0;
}
int quec_gps_open(void)
{
QUEC_GPS_DEV_T * quec_gps = &g_quec_gps_dev;
int ret = QUEC_GPS_NO_ERROR;
do{
if(quec_gps->power_state == QUEC_POWER_OFF){
quec_rtos_flag_release(g_quec_gps_dev.gps_event_flag_ref, QUEC_GPS_OPEN_EVENT, QUEC_FLAG_OR);
ret = QUEC_GPS_NO_ERROR;
break;
}
ret = QUEC_GPS_ALREADY_CLOSED_ERROR;
GPS_LOGE("GPS_ALREADY Be CLOSED!!!\n");
}while(0);
return ret;
}
int quec_gps_close(void)
{
QUEC_GPS_DEV_T * quec_gps = &g_quec_gps_dev;
int ret = QUEC_GPS_NO_ERROR;
do{
if(quec_gps->power_state == QUEC_POWER_ON){
quec_rtos_flag_release(g_quec_gps_dev.gps_event_flag_ref, QUEC_GPS_CLOSE_EVENT, QUEC_FLAG_OR);
ret = QUEC_GPS_NO_ERROR;
break;
}
ret = QUEC_GPS_NOT_OPEN_ERROR;
GPS_LOGE("need to OPEN GPS!!!\n");
}while(0);
return ret;
}
void quec_gps_register_nmea_str_cb(nmea_str_put cb)
{
g_quec_nmea_cb.nmea_str_cb = cb;
}
void quec_gps_register_nmea_packet_cb(gps_packet_put cb)
{
g_quec_nmea_cb.nmea_packets_cb = cb;
}
void quec_gps_register_open_success_cb(gps_open_success cb)
{
g_quec_nmea_cb.open_gps_success_cb = cb;
}
void quec_gps_register_location_para_cb(location_update cb)
{
g_quec_nmea_cb.loaction_update_cb = cb;
}
void quec_gps_register_agps_sate_cb(gnss_ephemeris_info cb)
{
g_quec_nmea_cb.gnss_ephemeris_info_cb = cb;
}
void quec_apflash_req_flag_set(void)
{
quec_rtos_flag_release(g_quec_gps_dev.gps_event_flag_ref,QUEC_APFLSH_REQ_EVENT,QUEC_FLAG_OR);
}
void quec_apflsh_req_statue_clear(void)
{
g_quec_gps_dev.worke_state &= ~QUEC_APFLASH_REQED;
}
#ifdef QUEC_HX_AGPS_TIMER
void quec_agps_req_flag_set(void)
{
quec_rtos_flag_release(g_quec_gps_dev.gps_event_flag_ref,QUEC_AGPS_DATA_REQ_EVENT,QUEC_FLAG_OR);
}
#endif
void quec_gps_load_fw_cb(void * para)
{
if(g_quec_gps_dev.power_state != QUEC_POWER_ON)/*若未开机则走下载流程*/
{
quec_rtos_flag_release(g_quec_gps_dev.gps_event_flag_ref,QUEC_GPS_DOWNLOAD_FIRM,QUEC_FLAG_OR);
}
}
/*gps 保活机制如果超过5s没检测到串口回调则会重新开关串口和gps */
void quec_keep_alive_timer(UINT32 argv)
{
quec_rtos_flag_release(g_quec_gps_dev.gps_event_flag_ref,QUEC_GPS_RESTART,QUEC_FLAG_OR);
}
void quec_gps_nmea_data_cb(void * para)
{
quec_gps_handle * gnss_config = quec_gnss_config_para_get();
if((1 == gnss_rom_type) ||(3 == gnss_rom_type))
{
quec_gnss_apflash_struct_t * gnss_apflash = get_hx_apflash_req_status();
if(gnss_apflash->request_flag)/*如果此时发起了apflsh请求*/
{
quec_rtos_flag_release(g_quec_gps_dev.gps_event_flag_ref,QUEC_GPS_APFLASH_EVENT,QUEC_FLAG_OR);
}
else
{
if(g_quec_gps_dev.worke_state & QUEC_NMEA_PASRE_STATE){
quec_rtos_flag_release(g_quec_gps_dev.gps_event_flag_ref, QUEC_GPS_NMEA_PARSE_EVENT, QUEC_FLAG_OR);
}
}
}
else
{
if(g_quec_gps_dev.worke_state & QUEC_NMEA_PASRE_STATE){
quec_rtos_flag_release(g_quec_gps_dev.gps_event_flag_ref, QUEC_GPS_NMEA_PARSE_EVENT, QUEC_FLAG_OR);
}
}
//20230512 修改保活机制处理逻辑,当我们配置nmea语句不输出时,不触发保活机制,以防止gnss反复重启
if((g_quec_gps_dev.worke_state & QUEC_NMEA_PASRE_STATE) && (gnss_config->nmea_handle_cfg.gps_nmea_type != 0)){
quec_rtos_timer_start(g_quec_gps_dev.gps_keep_alive_timer, HX_GPS_KEEPALIVE_CNT, 0, quec_keep_alive_timer, 0);
}
else
{
quec_rtos_timer_stop(g_quec_gps_dev.gps_keep_alive_timer);
}
}
int quec_gps_start_parse(void)
{
QUEC_GPS_DEV_T * quec_gps = &g_quec_gps_dev;
QUEC_GPS_OPS * quec_ops = (QUEC_GPS_OPS *)g_quec_gps_dev.ops;
int ret = QUEC_GPS_ERROR;
if(!(quec_gps->worke_state & QUEC_NMEA_PASRE_STATE )){
GPS_COM_register_cb(quec_gps_nmea_data_cb);
quec_rtos_timer_start(g_quec_gps_dev.gps_keep_alive_timer, HX_GPS_KEEPALIVE_CNT, 0, quec_keep_alive_timer, 0);
quec_gps->worke_state |= QUEC_NMEA_PASRE_STATE;
ret = QUEC_GPS_NO_ERROR;
GPS_LOGI("start nmea parse %d",quec_gps->worke_state);
}
return ret ;
}
int quec_gps_stop_nmea_parse(void)
{
QUEC_GPS_DEV_T * quec_gps = &g_quec_gps_dev;
int ret = QUEC_GPS_ERROR;
if(quec_gps->worke_state & QUEC_NMEA_PASRE_STATE){
GPS_COM_register_cb(NULL);
quec_rtos_timer_stop(g_quec_gps_dev.gps_keep_alive_timer);
ret = QUEC_GPS_NO_ERROR;
quec_gps->worke_state &= ~QUEC_NMEA_PASRE_STATE;
}
return ret ;
}
int gps_open(void)
{
int ret = QUEC_GPS_NO_ERROR;
int i ;
g_quec_gps_dev.power_state = QUEC_POWER_OFF;
GPS_COM_register_cb(quec_gps_load_fw_cb);
for(i=0;i<=3;i++){
ret = hx_gnss_open();
if(ret == HX_L26_INIT_NO_ERROR){
break;
}
else{
GPS_LOGE("GPS UPDATE FAILED: %d",ret);
hx_gnss_close();
ret = QUEC_GPS_NOT_OPEN_ERROR;
}
}
GPS_COM_register_cb(NULL);
g_quec_gps_dev.power_state = QUEC_POWER_ON;
return ret;
}
int gps_close(void)
{
int ret = QUEC_GPS_NO_ERROR;
ret = hx_gnss_close();
g_quec_gps_dev.power_state = QUEC_POWER_OFF;
return ret;
}
extern QUEC_GPS_USER_CALLBACK quec_asr_gps_user_callback_init;
static void quec_gps_process_thread(void* argv)
{
unsigned int gps_flags = 0;
char nmea_r[256] = {0};
char pos = 0;
char aidtimeflag=0;
char agnss_delay=0;
QUEC_GPS_DEV_T * quec_gps = &g_quec_gps_dev;
QUEC_GPS_OPS * quec_ops = (QUEC_GPS_OPS *)g_quec_gps_dev.ops;
unsigned int buffer_len = 0;
char * rx_buf = NULL;
int ret = 0;
unsigned int cnt =0;
int i;
char overflow_flag = 0;
while(1){
quec_rtos_flag_wait(g_quec_gps_dev.gps_event_flag_ref, QUEC_GPS_EVENT_MASK, QUEC_FLAG_OR_CLEAR, &gps_flags,QUEC_WAIT_FOREVER);
if(gps_flags & QUEC_GPS_OPEN_EVENT){ /*gnss打开事件*/
/*step 1:gps 上电*/
ret = gps_open();
if(ret == QUEC_GPS_NO_ERROR){
/*step 2:开启agps定时器*/
quec_hx_agps_init();
/*step 3:初始化gps配置*/
quec_gnss_nmea_cnf();
#if defined (HX_GNSS_CC11_SUPPORT)
//CC11系列1PPS有380ms的误差,需要使用原厂指令进行修正
quec_gnss_cmd_1pps_config();
#endif
/*step 4:初始化gps配置*/
if((1 == gnss_rom_type) ||(3 == gnss_rom_type))
{
/*step 4:初始化gps配置*/
quec_apflash_timer_init();
}
ret = quec_gps_start_parse();
if(quec_asr_gps_user_callback_init!=NULL)
quec_asr_gps_user_callback_init(QUEC_GPS_INITIAL_SUCCESS,NULL,0);
}
else
{
if(quec_asr_gps_user_callback_init!=NULL)
quec_asr_gps_user_callback_init(QUEC_GPS_INITIAL_FAILED,NULL,0);
}
if(ret == QUEC_GPS_NO_ERROR){
if(quec_gps->nmea_cb->open_gps_success_cb)
quec_gps->nmea_cb->open_gps_success_cb();
}
}
else if (gps_flags & QUEC_GPS_CLOSE_EVENT){/*gnss关闭事件*/
/*step 1:关闭nmea解析器*/
quec_gps_stop_nmea_parse();
/*step 2:gps下电*/
gps_close();
/*step 3:关串口,关闭串口操作要在stop_nmea_parse后面,否则可能关机时间和串口接收中断装上导致异常*/
GPS_COM_Deinit();
/*step 4:关闭agps定时器*/
quec_hx_agps_deinit();
if((1 == gnss_rom_type) ||(3 == gnss_rom_type))
{
quec_apflash_timer_deinit();
}
memset(&hx_loactiong_para,0,sizeof(hx_locationg_t));
quec_gps->worke_state = QUEC_GPS_INIT_STATE;
agnss_delay=0;
aidtimeflag=0;
if(quec_asr_gps_user_callback_init!=NULL)
quec_asr_gps_user_callback_init(QUEC_GPS_DEINIT_SUCCESS,NULL,0);
}
else if (gps_flags & QUEC_GPS_NMEA_PARSE_EVENT){/*nmea数据解析*/
if(g_quec_gps_dev.power_state == QUEC_POWER_ON){
GPS_LOGI("nmea data cnt %d\n",cnt++);
buffer_len=GPS_COM_GetByteStatus();
rx_buf = malloc(buffer_len);
memset(rx_buf,0,buffer_len);
GPS_COM_GetByte_Buffer((char*)rx_buf,buffer_len);
if(g_quec_gps_dev.nmea_cb->nmea_packets_cb){
g_quec_gps_dev.nmea_cb->nmea_packets_cb(rx_buf,buffer_len);
}
for(i=0;i<buffer_len;i++){
if (overflow_flag) { /*如果检测到前面buffer已经超出缓冲大小那么我们要检测到结束符\n再开始记录buffer*/
overflow_flag = (rx_buf[i] != '\n');
continue;
}
if (pos >= (int) sizeof(nmea_r)-1 ) { /*如果检测到超出缓冲区大小直接开始下一次*/
overflow_flag = 1;
pos = 0;
continue;
}
nmea_r[pos] = (char)rx_buf[i];
pos += 1;
if(rx_buf[i] == '\n'){
ret = quec_gnss_nmea_parse(nmea_r,pos);
pos = 0;
}
}
if((1 == gnss_rom_type) ||(3 == gnss_rom_type))
{
/*检查本地apflash数据是否需要更新*/
if(hx_loactiong_para.valid && ((g_quec_gps_dev.worke_state & QUEC_APFLASH_REQED)==0)){
if(quec_apflsh_data_need_update()){
quec_apflash_req_flag_set();/*第一次定位成功立即获取apflash数据*/
}
else {
quec_gps->worke_state |= QUEC_APFLASH_REQED;
}
}
}
if(ret != QUEC_GPS_NO_ERROR)
GPS_LOGE("nmea data parse faile\n");
free(rx_buf);
if(GPS_GET_RTC_STATUS()==1 && !aidtimeflag){
quec_gnss_aidtime_msg_send();
aidtimeflag++;
}
/*开机到现在未同步过agps,可能是由于pdp尚未激活导致,这里查询到如果有pdp激活则会尝试请求一次*/
if(!quec_get_agps_status() && agnss_delay>=3){ //pony add 第一次开机等输出5s的nmea再注入agnss,过早注入可能导致agnss失效
/*如果有pdp激活,尝试同步一次agps*/
if(GPS_GET_NETIF_STATUS() && GPS_GET_RTC_STATUS()){
quec_agps_file_set_to_gps();
}
}
if(agnss_delay<6)
agnss_delay++;
if(quec_get_agps_status()&&aidtimeflag){
if(GPS_NW_DEACT) { /*删除网络监控线程节省资源*/
GPS_NW_DEACT();
}
}
}
}
#ifdef QUEC_HX_AGPS_TIMER
else if(gps_flags & QUEC_AGPS_DATA_REQ_EVENT)
{
quec_set_agps_status(0);
}
#endif
else if(gps_flags & QUEC_APFLSH_REQ_EVENT)
{
if(g_quec_gps_dev.power_state == QUEC_POWER_ON){
quec_gnss_apflash_data_request();
quec_gps->worke_state |= QUEC_APFLASH_REQED;
GPS_LOGI("GPS REQ APFLSH ");
}
}
else if(gps_flags & QUEC_GPS_APFLASH_EVENT)
{
if(g_quec_gps_dev.power_state == QUEC_POWER_ON){
GPS_LOGI("GPS RECV APFLSH");
ret = quec_gnss_apflash_recv(); /*接收gps数据*/
if(!ret){
GPS_LOGI("GPS RECV APFLSH not over");
}
}
}
else if(gps_flags & QUEC_GPS_RESTART)
{
/*step 0:关闭串口*/
GPS_COM_Deinit();
/*step 1:关闭nmea解析器*/
quec_gps_stop_nmea_parse();
/*step 2:gps下电*/
gps_close();
/*step 3:关闭agps定时器*/
quec_hx_agps_deinit();
if((1 == gnss_rom_type) ||(3 == gnss_rom_type))
{
/*step 3:关闭apflash定时器*/
quec_apflash_timer_deinit();
}
/*step 4:*/
memset(&hx_loactiong_para,0,sizeof(hx_locationg_t));
/*step 5:*/
g_quec_gps_dev.worke_state = QUEC_GPS_INIT_STATE;
/*step 1:gps 上电*/
gps_open();
/*step 2:开启agps定时器*/
quec_hx_agps_init();
/*step 3:初始化gps配置*/
quec_gnss_nmea_cnf();
#if defined (HX_GNSS_CC11_SUPPORT)
//CC11系列1PPS有380ms的误差,需要使用原厂指令进行修正
quec_gnss_cmd_1pps_config();
#endif
if((1 == gnss_rom_type) ||(3 == gnss_rom_type))
{
/*step 4:初始化gps配置*/
quec_apflash_timer_init();
}
quec_rtos_task_sleep_ms(10);
/*step 5:注入agps数据*/
quec_agps_file_set_to_gps();
/*step 6:检查导入的星历是否有效*/
quec_agps_check_vaild();
/*step 7:开启nmea解析器*/
quec_gps_start_parse();
if(quec_asr_gps_user_callback_init!=NULL)
quec_asr_gps_user_callback_init(QUEC_GPS_INITIAL_SUCCESS,NULL,0);
}
else {
GPS_LOGE("unknow gps event !!!\n");
}
}
}
int quec_gps_status_get(void)
{
QUEC_GPS_DEV_T * quec_gps = &g_quec_gps_dev;
return quec_gps->power_state;
}
void quec_gps_dev_init(void)
{
g_quec_gps_ops.q_gps_open = quec_gps_open;
g_quec_gps_ops.q_gps_close = quec_gps_close;
g_quec_gps_ops.q_gps_reset = quec_gps_reset;
g_quec_gps_ops.q_reg_nmea_str_cb = quec_gps_register_nmea_str_cb;
g_quec_gps_ops.q_reg_location_update_cb = quec_gps_register_location_para_cb;
g_quec_gps_ops.q_reg_open_gps_success_cb = quec_gps_register_open_success_cb;
g_quec_gps_ops.q_reg_agps_sate_num_cb = quec_gps_register_agps_sate_cb;
g_quec_gps_ops.q_reg_nmea_packet_cb = quec_gps_register_nmea_packet_cb;
g_quec_gps_dev.gps_manufacturer = HX_GPS_MODULE;
g_quec_gps_dev.power_state = QUEC_POWER_OFF;
g_quec_gps_dev.worke_state = QUEC_GPS_INIT_STATE;
g_quec_gps_dev.gps_event_flag_ref = NULL;
g_quec_gps_dev.gps_task_ref = NULL;
g_quec_gps_dev.gps_keep_alive_timer = NULL;
g_quec_gps_dev.ops = &g_quec_gps_ops;
g_quec_gps_dev.nmea_cb = &g_quec_nmea_cb;
}
QUEC_GPS_DEV_T *quec_get_gps_dev(void)
{
return &g_quec_gps_dev;
}
static void sys_32k_init(void)
{
if(1)
{
#if defined (HX_GNSS_CC11_SUPPORT) && !defined (__QUECTEL_PROJECT_EG915NLA_GK__)
unsigned int temp = (*(volatile unsigned long *)(0xD401E32C));
temp = temp & ~0x07;
temp |= 0x01; // function 2, select 32K clock mode
(*(volatile unsigned long *)(0xD401E32C)) = temp;
#else
volatile unsigned int temp = 0;
unsigned int addr = 0xD401E000 + 50*4; // address of GPIO 122
temp = (*(volatile unsigned long *)(0xD4050038));
GPS_LOGI("SCCR register %08x\r\n", temp);
temp = (*(volatile unsigned long *)(addr));
temp = temp & ~0x07;
temp |= 0x02; // function 2, select 32K clock mode
(*(volatile unsigned long *)(addr)) = temp;
#endif
}
else
{
GPS_LOGI("Pls Check DCS Mode!!");
}
}
void quec_gps_init(void)
{
/*STEP 2: gps主线程初始化*/
//20230807 兼容和芯gnss rom1 rom2处理,rom2需要输出32k
gnss_rom_type = quec_gnss_type_check();
int gnss_vbckp_select = quec_hx_bckp_get();
if((2==gnss_rom_type)&&(0 == gnss_vbckp_select)){
gnss_rom_type = 3;//20231011 add type 3:ROM2不接备电
}
if(2 == gnss_rom_type)
{
sys_32k_init();
}
quec_gps_dev_init();
quec_gnss_firm_init();
quec_rtos_flag_create(&g_quec_gps_dev.gps_event_flag_ref);
quec_rtos_task_create(&g_quec_gps_dev.gps_task_ref , QUEC_GPS_TASK_STACK_SIZE , 90, "qgps_task", quec_gps_process_thread, NULL, NULL);
quec_rtos_timer_create(&g_quec_gps_dev.gps_keep_alive_timer);/*gnss保活定时器*/
}
#ifdef HX_GNSS_CC11_SUPPORT
int read_gnss_id()
{
int ret = -1;
char ack_id[256]={0};
char cnt = 10;
int len = 0;
memset(ack_id,0,256);
while(cnt--)
{
if(select_read(200))
{
len = deal_read(ack_id+len,256-len);
//RTI_LOG("quec----,%s,%s",__func__,ack_id);
if(strstr((char *)ack_id, "CC1177W"))
{
ret=BEIDOU_ONLY;
break;
}
if(strstr((char *)ack_id, "CC1161W"))
{
ret=GNSS_SYS;
break;
}
len+=len;
if(len>=256)
break;
}
else
break;
}//读取超过256字节,退出循环判定硬件ID,防止没有读取到ID信息,一直接收导致数组越界或者硬件ID信息被截断,判定失败
return ret;
}
int quec_hxgnss_open_getid()
{
int i=0,reset_sucess=-1;
sys_32k_init();
quec_rtos_flag_create(&g_quec_gps_dev.gps_event_flag_ref);
g_quec_gps_dev.power_state = QUEC_POWER_OFF;
gps_channel_init();
GPS_COM_register_cb(quec_gps_load_fw_cb);
GPS_COM_Init();
GPS_COM_SetBaudRate(115200);
for(i=0;i<3;i++)
{
quec_gnss_power_on_off(0);
gps_delay_ms(50);
quec_gnss_power_on_off(1);
//读取GNSSID,-1:读取失败 0:CC1161W,1:CC1177W
reset_sucess =read_gnss_id();
if(reset_sucess!=-1)
break;
GPS_COM_PurgeFIFO();
}
quec_gnss_power_on_off(0);
GPS_COM_register_cb(NULL);
quec_rtos_flag_delete(g_quec_gps_dev.gps_event_flag_ref);
g_quec_gps_dev.gps_event_flag_ref = NULL;
g_quec_gps_dev.power_state = QUEC_POWER_ON;
GPS_COM_Deinit();
return reset_sucess;
}
#endif