Skip to content

Commit 037b6f8

Browse files
committed
drivers: api: GNSS/GPS api first commit
The no-OS GNSS API provides a unified interface for GNSS timing and positioning functionality across different gnss-gps device types and protocols. This API abstracts the underlying complexity of UBX and NMEA protocols while maintaining high precision timing capabilities. Generic API works with any GNSS hardware through platform operations. Easy to add support for new GNSS chipsets. Signed-off-by: Radu Etz <[email protected]>
1 parent 930b915 commit 037b6f8

File tree

2 files changed

+476
-0
lines changed

2 files changed

+476
-0
lines changed

drivers/api/no_os_gnss.c

Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
/***************************************************************************//**
2+
* @file no_os_gnss.c
3+
* @brief Implementation of GNSS Interface
4+
* @author Radu Etz ([email protected])
5+
********************************************************************************
6+
* Copyright 2025(c) Analog Devices, Inc.
7+
*
8+
* Redistribution and use in source and binary forms, with or without
9+
* modification, are permitted provided that the following conditions are met:
10+
*
11+
* 1. Redistributions of source code must retain the above copyright notice,
12+
* this list of conditions and the following disclaimer.
13+
*
14+
* 2. Redistributions in binary form must reproduce the above copyright notice,
15+
* this list of conditions and the following disclaimer in the documentation
16+
* and/or other materials provided with the distribution.
17+
*
18+
* 3. Neither the name of Analog Devices, Inc. nor the names of its
19+
* contributors may be used to endorse or promote products derived from this
20+
* software without specific prior written permission.
21+
*
22+
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. "AS IS" AND ANY EXPRESS OR
23+
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24+
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
25+
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
26+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
28+
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29+
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
31+
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32+
*******************************************************************************/
33+
34+
#include <stdlib.h>
35+
#include <errno.h>
36+
#include "no_os_gnss.h"
37+
#include "no_os_alloc.h"
38+
#include "no_os_mutex.h"
39+
40+
/* Forward declarations of ublox platform operations */
41+
static int32_t ublox_gnss_platform_init(struct no_os_gnss_desc **desc,
42+
const struct no_os_gnss_init_param *param);
43+
static int32_t ublox_gnss_platform_refresh_timing_data(
44+
struct no_os_gnss_desc *desc);
45+
static int32_t ublox_gnss_platform_is_timing_valid(struct no_os_gnss_desc *desc,
46+
bool *valid);
47+
static int32_t ublox_gnss_platform_get_unified_timing(
48+
struct no_os_gnss_desc *desc,
49+
struct gnss_precise_time *timing);
50+
static uint32_t ublox_gnss_platform_get_unix_epoch_unified(
51+
struct no_os_gnss_desc *desc,
52+
uint32_t *fractional_seconds);
53+
static int32_t ublox_gnss_platform_get_position_data(
54+
struct no_os_gnss_desc *desc,
55+
struct gnss_nmea_position *position_data);
56+
static int32_t ublox_gnss_platform_remove(struct no_os_gnss_desc *desc);
57+
58+
/**
59+
* @brief Platform operations structure for ublox GNSS devices
60+
*/
61+
const struct no_os_gnss_platform_ops ublox_gnss_ops = {
62+
.init = ublox_gnss_platform_init,
63+
.refresh_timing_data = ublox_gnss_platform_refresh_timing_data,
64+
.is_timing_valid = ublox_gnss_platform_is_timing_valid,
65+
.get_unified_timing = ublox_gnss_platform_get_unified_timing,
66+
.get_unix_epoch_unified = ublox_gnss_platform_get_unix_epoch_unified,
67+
.get_position_data = ublox_gnss_platform_get_position_data,
68+
.remove = ublox_gnss_platform_remove
69+
};
70+
71+
/**
72+
* @brief Initialize ublox GNSS platform device
73+
*/
74+
static int32_t ublox_gnss_platform_init(struct no_os_gnss_desc **desc,
75+
const struct no_os_gnss_init_param *param)
76+
{
77+
struct no_os_gnss_desc *gnss_desc;
78+
struct gnss_dev *gnss_dev;
79+
struct gnss_init_param gnss_init_param;
80+
int32_t ret;
81+
82+
if (!desc || !param)
83+
return -EINVAL;
84+
85+
gnss_desc = (struct no_os_gnss_desc *)no_os_calloc(1, sizeof(*gnss_desc));
86+
if (!gnss_desc)
87+
return -ENOMEM;
88+
89+
/* Copy and modify the gnss_init_param with PPS settings */
90+
gnss_init_param = param->gnss_init_param;
91+
gnss_init_param.pps_enable = param->pps_config.pps_enable;
92+
gnss_init_param.pps_frequency = param->pps_config.frequency;
93+
gnss_init_param.pps_pulse_length = param->pps_config.pulse_length;
94+
95+
/* Initialize underlying ublox_gnss driver */
96+
ret = gnss_init(&gnss_dev, gnss_init_param);
97+
if (ret) {
98+
no_os_free(gnss_desc);
99+
return ret;
100+
}
101+
102+
/* Set up the descriptor */
103+
gnss_desc->device_id = param->device_id;
104+
gnss_desc->gnss_device = gnss_dev;
105+
gnss_desc->platform_ops = param->platform_ops;
106+
gnss_desc->extra = param->extra;
107+
108+
/* Initialize the PPS output */
109+
ret = gnss_init_pps(gnss_desc->gnss_device, true);
110+
if (ret) {
111+
no_os_free(gnss_desc);
112+
return ret;
113+
}
114+
115+
/* Initialize mutex if needed */
116+
no_os_mutex_init(&gnss_desc->mutex);
117+
118+
*desc = gnss_desc;
119+
120+
return 0;
121+
}
122+
123+
/**
124+
* @brief Refresh timing data from ublox GNSS device
125+
*/
126+
static int32_t ublox_gnss_platform_refresh_timing_data(
127+
struct no_os_gnss_desc *desc)
128+
{
129+
if (!desc || !desc->gnss_device)
130+
return -EINVAL;
131+
132+
return gnss_refresh_timing_data(desc->gnss_device);
133+
}
134+
135+
/**
136+
* @brief Check if timing data is valid for ublox GNSS device
137+
*/
138+
static int32_t ublox_gnss_platform_is_timing_valid(struct no_os_gnss_desc *desc,
139+
bool *valid)
140+
{
141+
if (!desc || !desc->gnss_device || !valid)
142+
return -EINVAL;
143+
144+
*valid = gnss_is_timing_valid(desc->gnss_device);
145+
return 0;
146+
}
147+
148+
/**
149+
* @brief Get unified timing from ublox GNSS device
150+
*/
151+
static int32_t ublox_gnss_platform_get_unified_timing(
152+
struct no_os_gnss_desc *desc,
153+
struct gnss_precise_time *timing)
154+
{
155+
if (!desc || !desc->gnss_device || !timing)
156+
return -EINVAL;
157+
158+
return gnss_get_unified_timing(desc->gnss_device, timing);
159+
}
160+
161+
/**
162+
* @brief Get Unix epoch with unified precision from ublox GNSS device
163+
*/
164+
static uint32_t ublox_gnss_platform_get_unix_epoch_unified(
165+
struct no_os_gnss_desc *desc,
166+
uint32_t *fractional_seconds)
167+
{
168+
if (!desc || !desc->gnss_device || !fractional_seconds)
169+
return 0;
170+
171+
return gnss_get_unix_epoch_unified(desc->gnss_device, fractional_seconds);
172+
}
173+
174+
/**
175+
* @brief Remove ublox GNSS platform device
176+
*/
177+
static int32_t ublox_gnss_platform_remove(struct no_os_gnss_desc *desc)
178+
{
179+
if (!desc)
180+
return -EINVAL;
181+
182+
/* Remove underlying ublox_gnss device */
183+
if (desc->gnss_device)
184+
gnss_remove(desc->gnss_device);
185+
186+
/* Remove mutex */
187+
if (desc->mutex)
188+
no_os_mutex_remove(desc->mutex);
189+
190+
no_os_free(desc);
191+
192+
return 0;
193+
}
194+
195+
/* Public API Functions */
196+
197+
/**
198+
* @brief Initialize the GNSS communication peripheral.
199+
*/
200+
int32_t no_os_gnss_init(struct no_os_gnss_desc **desc,
201+
const struct no_os_gnss_init_param *param)
202+
{
203+
if (!desc || !param || !param->platform_ops)
204+
return -EINVAL;
205+
206+
return param->platform_ops->init(desc, param);
207+
}
208+
209+
/**
210+
* @brief Free the resources allocated by no_os_gnss_init().
211+
*/
212+
int32_t no_os_gnss_remove(struct no_os_gnss_desc *desc)
213+
{
214+
if (!desc || !desc->platform_ops)
215+
return -EINVAL;
216+
217+
return desc->platform_ops->remove(desc);
218+
}
219+
220+
/**
221+
* @brief Refresh timing data from GNSS device.
222+
*/
223+
int32_t no_os_gnss_refresh_timing_data(struct no_os_gnss_desc *desc)
224+
{
225+
if (!desc || !desc->platform_ops)
226+
return -EINVAL;
227+
228+
return desc->platform_ops->refresh_timing_data(desc);
229+
}
230+
231+
/**
232+
* @brief Check if timing data is valid.
233+
*/
234+
int32_t no_os_gnss_is_timing_valid(struct no_os_gnss_desc *desc, bool *valid)
235+
{
236+
if (!desc || !desc->platform_ops || !valid)
237+
return -EINVAL;
238+
239+
return desc->platform_ops->is_timing_valid(desc, valid);
240+
}
241+
242+
/**
243+
* @brief Get unified timing information with best available precision.
244+
*/
245+
int32_t no_os_gnss_get_unified_timing(struct no_os_gnss_desc *desc,
246+
struct gnss_precise_time *timing)
247+
{
248+
if (!desc || !desc->platform_ops || !timing)
249+
return -EINVAL;
250+
251+
return desc->platform_ops->get_unified_timing(desc, timing);
252+
}
253+
254+
/**
255+
* @brief Get Unix epoch timestamp with unified precision.
256+
*/
257+
uint32_t no_os_gnss_get_unix_epoch_unified(struct no_os_gnss_desc *desc,
258+
uint32_t *fractional_seconds)
259+
{
260+
if (!desc || !desc->platform_ops || !fractional_seconds)
261+
return 0;
262+
263+
return desc->platform_ops->get_unix_epoch_unified(desc, fractional_seconds);
264+
}
265+
266+
/**
267+
* @brief Get position data from ublox GNSS device
268+
*/
269+
static int32_t ublox_gnss_platform_get_position_data(
270+
struct no_os_gnss_desc *desc,
271+
struct gnss_nmea_position *position_data)
272+
{
273+
if (!desc || !desc->gnss_device || !position_data)
274+
return -EINVAL;
275+
276+
return gnss_get_nmea_position_data(desc->gnss_device, position_data);
277+
}
278+
279+
/**
280+
* @brief Get GPS position and fix quality data (NMEA-only devices).
281+
*/
282+
int32_t no_os_gnss_get_position_data(struct no_os_gnss_desc *desc,
283+
struct gnss_nmea_position *position_data)
284+
{
285+
if (!desc || !desc->platform_ops || !position_data)
286+
return -EINVAL;
287+
288+
return desc->platform_ops->get_position_data(desc, position_data);
289+
}

0 commit comments

Comments
 (0)