Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

147 lines
4.0 KiB

/*
* Copyright (c) 2025 Croxel Inc.
* Copyright (c) 2025 CogniPilot Foundation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/drivers/gnss.h>
#include <zephyr/drivers/gnss/gnss_publish.h>
#include "gnss_ubx_common.h"
void gnss_ubx_common_pvt_callback(struct modem_ubx *ubx, const struct ubx_frame *frame,
size_t len, void *user_data)
{
if (len < UBX_FRAME_SZ(sizeof(struct ubx_nav_pvt))) {
return;
}
struct gnss_ubx_common_data *data = user_data;
const struct device *dev = data->gnss;
const struct ubx_nav_pvt *nav_pvt = (const struct ubx_nav_pvt *)frame->payload_and_checksum;
enum gnss_fix_quality fix_quality = GNSS_FIX_QUALITY_INVALID;
enum gnss_fix_status fix_status = GNSS_FIX_STATUS_NO_FIX;
if ((nav_pvt->flags & UBX_NAV_PVT_FLAGS_GNSS_FIX_OK) &&
!(nav_pvt->nav.flags3 & UBX_NAV_PVT_FLAGS3_INVALID_LLH)) {
switch (nav_pvt->fix_type) {
case UBX_NAV_FIX_TYPE_DR:
case UBX_NAV_FIX_TYPE_GNSS_DR_COMBINED:
fix_quality = GNSS_FIX_QUALITY_ESTIMATED;
fix_status = GNSS_FIX_STATUS_ESTIMATED_FIX;
break;
case UBX_NAV_FIX_TYPE_2D:
case UBX_NAV_FIX_TYPE_3D:
fix_quality = GNSS_FIX_QUALITY_GNSS_SPS;
fix_status = GNSS_FIX_STATUS_GNSS_FIX;
break;
default:
break;
}
}
struct gnss_data gnss_data = {
.info = {
.satellites_cnt = nav_pvt->nav.num_sv,
.hdop = nav_pvt->nav.pdop * 10,
.geoid_separation = (nav_pvt->nav.height -
nav_pvt->nav.hmsl),
.fix_status = fix_status,
.fix_quality = fix_quality,
},
.nav_data = {
.latitude = (int64_t)nav_pvt->nav.latitude * 100,
.longitude = (int64_t)nav_pvt->nav.longitude * 100,
.bearing = (((nav_pvt->nav.head_motion < 0) ?
(nav_pvt->nav.head_motion + (360 * 100000)) :
(nav_pvt->nav.head_motion)) / 100),
.speed = nav_pvt->nav.ground_speed,
.altitude = nav_pvt->nav.hmsl,
},
.utc = {
.hour = nav_pvt->time.hour,
.minute = nav_pvt->time.minute,
.millisecond = (nav_pvt->time.second * 1000) +
(nav_pvt->time.nano / 1000000),
.month_day = nav_pvt->time.day,
.month = nav_pvt->time.month,
.century_year = (nav_pvt->time.year % 100),
},
};
gnss_publish_data(dev, &gnss_data);
}
#if CONFIG_GNSS_SATELLITES
void gnss_ubx_common_satellite_callback(struct modem_ubx *ubx, const struct ubx_frame *frame,
size_t len, void *user_data)
{
if (len < UBX_FRAME_SZ(sizeof(struct ubx_nav_sat))) {
return;
}
const struct ubx_nav_sat *ubx_sat = (const struct ubx_nav_sat *)frame->payload_and_checksum;
int num_satellites = (len - UBX_FRAME_SZ_WITHOUT_PAYLOAD - sizeof(struct ubx_nav_sat)) /
sizeof(struct ubx_nav_sat_info);
struct gnss_ubx_common_data *data = user_data;
const struct device *dev = data->gnss;
num_satellites = MIN(num_satellites, data->satellites.size);
for (size_t i = 0 ; i < num_satellites ; i++) {
enum gnss_system gnss_system = 0;
switch (ubx_sat->sat[i].gnss_id) {
case UBX_GNSS_ID_GPS:
gnss_system = GNSS_SYSTEM_GPS;
break;
case UBX_GNSS_ID_SBAS:
gnss_system = GNSS_SYSTEM_SBAS;
break;
case UBX_GNSS_ID_GALILEO:
gnss_system = GNSS_SYSTEM_GALILEO;
break;
case UBX_GNSS_ID_BEIDOU:
gnss_system = GNSS_SYSTEM_BEIDOU;
break;
case UBX_GNSS_ID_QZSS:
gnss_system = GNSS_SYSTEM_QZSS;
break;
case UBX_GNSS_ID_GLONASS:
gnss_system = GNSS_SYSTEM_GLONASS;
break;
default:
break;
}
struct gnss_satellite sat = {
/** TODO: Determine how to determine PRN from UBX sat info.
* For now passing SV_ID.
*/
.prn = ubx_sat->sat[i].sv_id,
.snr = ubx_sat->sat[i].cno,
.elevation = ubx_sat->sat[i].elevation,
.azimuth = ubx_sat->sat[i].azimuth,
.system = gnss_system,
.is_tracked = (ubx_sat->sat[i].flags & UBX_NAV_SAT_FLAGS_SV_USED),
};
data->satellites.data[i] = sat;
}
gnss_publish_satellites(dev, data->satellites.data, num_satellites);
}
#endif
void gnss_ubx_common_init(struct gnss_ubx_common_data *data,
const struct gnss_ubx_common_config *config)
{
data->gnss = config->gnss;
#if CONFIG_GNSS_SATELLITES
data->satellites.data = config->satellites.buf;
data->satellites.size = config->satellites.size;
#endif
}