Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
drivers: gnss: add a generic NMEA GNSS driver
wip Signed-off-by: Fabio Baltieri <fabiobaltieri@google.com>
- Loading branch information
1 parent
bc08e80
commit 2ae7a75
Showing
5 changed files
with
293 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Copyright 2023 Google LLC | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
config GNSS_NMEA_GENERIC | ||
bool "Generic GNSS NMEA device" | ||
default y | ||
depends on GNSS | ||
depends on DT_HAS_GNSS_NMEA_GENERIC_ENABLED | ||
select UART_INTERRUPT_DRIVEN | ||
select MODEM_MODULES | ||
select MODEM_BACKEND_UART | ||
select MODEM_CHAT | ||
select GNSS_PARSE | ||
select GNSS_NMEA0183 | ||
select GNSS_NMEA0183_MATCH | ||
help | ||
TODO |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,265 @@ | ||
/* | ||
* Copyright 2023 Google LLC | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <zephyr/drivers/gnss.h> | ||
#include <zephyr/modem/chat.h> | ||
#include <zephyr/modem/backend/uart.h> | ||
#include <zephyr/kernel.h> | ||
#include <zephyr/pm/device.h> | ||
#include <zephyr/drivers/gpio.h> | ||
#include <zephyr/pm/device_runtime.h> | ||
#include <string.h> | ||
|
||
#include "gnss_publish.h" | ||
#include "gnss_nmea0183.h" | ||
#include "gnss_nmea0183_match.h" | ||
#include "gnss_parse.h" | ||
|
||
#include <zephyr/logging/log.h> | ||
LOG_MODULE_REGISTER(gnss_nmea_generic, CONFIG_GNSS_LOG_LEVEL); | ||
|
||
#define DT_DRV_COMPAT gnss_nmea_generic | ||
|
||
struct gnss_nmea_generic_config { | ||
const struct device *uart; | ||
}; | ||
|
||
struct gnss_nmea_generic_data { | ||
struct gnss_nmea0183_match_data match_data; | ||
#if CONFIG_GNSS_SATELLITES | ||
struct gnss_satellite satellites[24]; | ||
#endif | ||
|
||
/* UART backend */ | ||
struct modem_pipe *uart_pipe; | ||
struct modem_backend_uart uart_backend; | ||
uint8_t uart_backend_receive_buf[128]; | ||
|
||
/* Modem chat */ | ||
struct modem_chat chat; | ||
uint8_t chat_receive_buf[256]; | ||
uint8_t chat_delimiter[2]; | ||
uint8_t *chat_argv[32]; | ||
|
||
/* Dynamic chat script */ | ||
uint8_t dynamic_match_buf[32]; | ||
uint8_t dynamic_separators_buf[2]; | ||
uint8_t dynamic_request_buf[32]; | ||
struct modem_chat_match dynamic_match; | ||
struct modem_chat_script_chat dynamic_script_chat; | ||
struct modem_chat_script dynamic_script; | ||
|
||
struct k_spinlock lock; | ||
}; | ||
|
||
#define MODEM_CHAT_SCRIPT_NO_ABORT_DEFINE(_sym, _script_chats, _callback, _timeout) \ | ||
static struct modem_chat_script _sym = { \ | ||
.name = #_sym, \ | ||
.script_chats = _script_chats, \ | ||
.script_chats_size = ARRAY_SIZE(_script_chats), \ | ||
.abort_matches = NULL, \ | ||
.abort_matches_size = 0, \ | ||
.callback = _callback, \ | ||
.timeout = _timeout, \ | ||
} | ||
|
||
MODEM_CHAT_MATCHES_DEFINE(unsol_matches, | ||
MODEM_CHAT_MATCH_WILDCARD("$??GGA,", ",*", gnss_nmea0183_match_gga_callback), | ||
MODEM_CHAT_MATCH_WILDCARD("$??RMC,", ",*", gnss_nmea0183_match_rmc_callback), | ||
#if CONFIG_GNSS_SATELLITES | ||
MODEM_CHAT_MATCH_WILDCARD("$??GSV,", ",*", gnss_nmea0183_match_gsv_callback), | ||
#endif | ||
); | ||
|
||
static int gnss_nmea_generic_resume(const struct device *dev) | ||
{ | ||
struct gnss_nmea_generic_data *data = dev->data; | ||
int ret; | ||
|
||
ret = modem_pipe_open(data->uart_pipe); | ||
if (ret < 0) { | ||
return ret; | ||
} | ||
|
||
ret = modem_chat_attach(&data->chat, data->uart_pipe); | ||
if (ret < 0) { | ||
modem_pipe_close(data->uart_pipe); | ||
return ret; | ||
} | ||
|
||
return ret; | ||
} | ||
|
||
#ifdef CONFIG_PM_DEVICE | ||
static int gnss_nmea_generic_suspend(const struct device *dev) | ||
{ | ||
return 0; | ||
} | ||
|
||
static int gnss_nmea_generic_turn_off(const struct device *dev) | ||
{ | ||
struct gnss_nmea_generic_data *data = dev->data; | ||
|
||
return modem_pipe_close(data->uart_pipe); | ||
} | ||
|
||
static int gnss_nmea_generic_pm_action(const struct device *dev, enum pm_device_action action) | ||
{ | ||
struct gnss_nmea_generic_data *data = dev->data; | ||
k_spinlock_key_t key; | ||
int ret = -ENOTSUP; | ||
|
||
key = k_spin_lock(&data->lock); | ||
|
||
switch (action) { | ||
case PM_DEVICE_ACTION_SUSPEND: | ||
ret = gnss_nmea_generic_suspend(dev); | ||
break; | ||
|
||
case PM_DEVICE_ACTION_RESUME: | ||
ret = gnss_nmea_generic_resume(dev); | ||
break; | ||
|
||
case PM_DEVICE_ACTION_TURN_ON: | ||
ret = 0; | ||
break; | ||
|
||
case PM_DEVICE_ACTION_TURN_OFF: | ||
ret = gnss_nmea_generic_turn_off(dev); | ||
break; | ||
|
||
default: | ||
break; | ||
} | ||
|
||
k_spin_unlock(&data->lock, key); | ||
return ret; | ||
} | ||
#endif /* CONFIG_PM_DEVICE */ | ||
|
||
static struct gnss_driver_api gnss_api = { | ||
}; | ||
|
||
static int gnss_nmea_generic_init_nmea0183_match(const struct device *dev) | ||
{ | ||
struct gnss_nmea_generic_data *data = dev->data; | ||
|
||
const struct gnss_nmea0183_match_config config = { | ||
.gnss = dev, | ||
#if CONFIG_GNSS_SATELLITES | ||
.satellites = data->satellites, | ||
.satellites_size = ARRAY_SIZE(data->satellites), | ||
#endif | ||
.timeout_ms = 200, | ||
}; | ||
|
||
return gnss_nmea0183_match_init(&data->match_data, &config); | ||
} | ||
|
||
static void gnss_nmea_generic_init_pipe(const struct device *dev) | ||
{ | ||
const struct gnss_nmea_generic_config *config = dev->config; | ||
struct gnss_nmea_generic_data *data = dev->data; | ||
|
||
const struct modem_backend_uart_config uart_backend_config = { | ||
.uart = config->uart, | ||
.receive_buf = data->uart_backend_receive_buf, | ||
.receive_buf_size = ARRAY_SIZE(data->uart_backend_receive_buf), | ||
}; | ||
|
||
data->uart_pipe = modem_backend_uart_init(&data->uart_backend, &uart_backend_config); | ||
} | ||
|
||
static int gnss_nmea_generic_init_chat(const struct device *dev) | ||
{ | ||
struct gnss_nmea_generic_data *data = dev->data; | ||
|
||
const struct modem_chat_config chat_config = { | ||
.user_data = data, | ||
.receive_buf = data->chat_receive_buf, | ||
.receive_buf_size = ARRAY_SIZE(data->chat_receive_buf), | ||
.delimiter = data->chat_delimiter, | ||
.delimiter_size = ARRAY_SIZE(data->chat_delimiter), | ||
.filter = NULL, | ||
.filter_size = 0, | ||
.argv = data->chat_argv, | ||
.argv_size = ARRAY_SIZE(data->chat_argv), | ||
.unsol_matches = unsol_matches, | ||
.unsol_matches_size = ARRAY_SIZE(unsol_matches), | ||
.process_timeout = K_MSEC(2), | ||
}; | ||
|
||
return modem_chat_init(&data->chat, &chat_config); | ||
} | ||
|
||
static void gnss_nmea_generic_init_dynamic_script(const struct device *dev) | ||
{ | ||
struct gnss_nmea_generic_data *data = dev->data; | ||
|
||
data->dynamic_match.match = data->dynamic_match_buf; | ||
data->dynamic_match.separators = data->dynamic_separators_buf; | ||
data->dynamic_match.separators_size = sizeof(data->dynamic_separators_buf); | ||
data->dynamic_match.wildcards = false; | ||
data->dynamic_match.partial = false; | ||
|
||
data->dynamic_script_chat.request = data->dynamic_request_buf; | ||
data->dynamic_script_chat.response_matches = &data->dynamic_match; | ||
data->dynamic_script_chat.response_matches_size = 1; | ||
data->dynamic_script_chat.timeout = 0; | ||
|
||
data->dynamic_script.name = "pair"; | ||
data->dynamic_script.script_chats = &data->dynamic_script_chat; | ||
data->dynamic_script.script_chats_size = 1; | ||
data->dynamic_script.abort_matches = NULL; | ||
data->dynamic_script.abort_matches_size = 0; | ||
data->dynamic_script.callback = NULL; | ||
data->dynamic_script.timeout = 10; | ||
} | ||
|
||
static int gnss_nmea_generic_init(const struct device *dev) | ||
{ | ||
int ret; | ||
|
||
ret = gnss_nmea_generic_init_nmea0183_match(dev); | ||
if (ret < 0) { | ||
return ret; | ||
} | ||
|
||
gnss_nmea_generic_init_pipe(dev); | ||
|
||
ret = gnss_nmea_generic_init_chat(dev); | ||
if (ret < 0) { | ||
return ret; | ||
} | ||
|
||
gnss_nmea_generic_init_dynamic_script(dev); | ||
|
||
#ifdef CONFIG_PM_DEVICE | ||
pm_device_init_suspended(dev); | ||
#else | ||
ret = gnss_nmea_generic_resume(dev); | ||
#endif | ||
return ret; | ||
} | ||
|
||
#define GNSS_NMEA_GENERIC(inst) \ | ||
static struct gnss_nmea_generic_config gnss_nmea_generic_cfg_##inst = { \ | ||
.uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ | ||
}; \ | ||
\ | ||
static struct gnss_nmea_generic_data gnss_nmea_generic_data_##inst = { \ | ||
.chat_delimiter = {'\r', '\n'}, \ | ||
.dynamic_separators_buf = {',', '*'}, \ | ||
}; \ | ||
\ | ||
PM_DEVICE_DT_INST_DEFINE(inst, gnss_nmea_generic_pm_action); \ | ||
\ | ||
DEVICE_DT_INST_DEFINE(inst, gnss_nmea_generic_init, PM_DEVICE_DT_INST_GET(inst),\ | ||
&gnss_nmea_generic_data_##inst, \ | ||
&gnss_nmea_generic_cfg_##inst, \ | ||
POST_KERNEL, 99, &gnss_api); | ||
|
||
DT_INST_FOREACH_STATUS_OKAY(GNSS_NMEA_GENERIC) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Copyright 2023 Google LLC | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
description: Generic GNSS NMEA receiver | ||
|
||
compatible: "gnss-nmea-generic" | ||
|
||
include: | ||
- uart-device.yaml |