Skip to content

Commit

Permalink
examples: zephyr: location: add nRF91 support
Browse files Browse the repository at this point in the history
Add nRF91 specific cellular tower information fetching and use when
requesting location data.

Use current cell only for now, as that is the only information provided
with the tested modem and SIM card. Leave logs for neighbour cells enabled,
so that extending this sample in the future is easy.

Signed-off-by: Marcin Niestroj <[email protected]>
  • Loading branch information
mniestroj committed Jan 21, 2025
1 parent 53bce5e commit 3b33bd3
Show file tree
Hide file tree
Showing 7 changed files with 256 additions and 0 deletions.
1 change: 1 addition & 0 deletions examples/zephyr/location/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ project(location)
target_sources(app PRIVATE src/main.c)
target_sources_ifdef(CONFIG_GOLIOTH_CELLULAR_PLAYBACK app PRIVATE src/cellular_playback.c)
target_sources_ifdef(CONFIG_GOLIOTH_WIFI_PLAYBACK app PRIVATE src/wifi_playback.c)
target_sources_ifdef(CONFIG_SOC_SERIES_NRF91X app PRIVATE src/cellular_nrf91.c)
1 change: 1 addition & 0 deletions examples/zephyr/location/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# SPDX-License-Identifier: Apache-2.0

configdefault GOLIOTH_LOCATION_CELLULAR
default y if SOC_SERIES_NRF91X
default y if GOLIOTH_CELLULAR_PLAYBACK

configdefault GOLIOTH_LOCATION_WIFI
Expand Down
10 changes: 10 additions & 0 deletions examples/zephyr/location/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,16 @@ $ west build -b nrf52840dk/nrf52840 examples/zephyr/location
$ west flash
```

#### nRF9160 DK

On your host computer open a terminal window, locate the source code of
this sample application (i.e., `examples/zephyr/location`) and type:

```console
$ west build -b nrf9160dk/nrf9160/ns examples/zephyr/location
$ west flash
```

### Sample output

This is the output from the serial console:
Expand Down
2 changes: 2 additions & 0 deletions examples/zephyr/location/sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ tests:
- native_sim
- native_sim/native/64
- nrf52840dk/nrf52840
- nrf9151dk/nrf9151/ns
- nrf9160dk/nrf9160/ns
sample.golioth.location.wifi_only:
extra_configs:
- CONFIG_GOLIOTH_CELLULAR_PLAYBACK=n
Expand Down
41 changes: 41 additions & 0 deletions examples/zephyr/location/socs/nrf9151_ns.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# General config
CONFIG_HEAP_MEM_POOL_SIZE=4096
CONFIG_NEWLIB_LIBC=y

# Networking
CONFIG_NET_SOCKETS_OFFLOAD=y
CONFIG_NET_IPV6=y
CONFIG_NET_IPV6_NBR_CACHE=n
CONFIG_NET_IPV6_MLD=n

# Increase native TLS socket implementation, so that it is chosen instead of
# offloaded nRF91 sockets
CONFIG_NET_SOCKETS_TLS_PRIORITY=35

# Modem library
CONFIG_NRF_MODEM_LIB=y

# LTE connectivity with network connection manager
CONFIG_NRF_MODEM_LIB_NET_IF=y
CONFIG_NRF_MODEM_LIB_NET_IF_AUTO_START=y
CONFIG_NRF_MODEM_LIB_NET_IF_AUTO_CONNECT=y
CONFIG_NET_CONNECTION_MANAGER=y
CONFIG_NET_CONNECTION_MANAGER_MONITOR_STACK_SIZE=1024

# Increased sysworkq size, due to LTE connectivity
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048

# Disable options y-selected by NCS for no good reason
CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED=n
CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED=n

# MbedTLS configuration to support p-384 curve. These options
# enable using the MbedTLS built-in support for operations not
# supported by the default nRF Oberon crypto backend
CONFIG_NORDIC_SECURITY_BACKEND=n
CONFIG_MBEDTLS_LEGACY_CRYPTO_C=y

# Generate MCUboot compatible images
CONFIG_BOOTLOADER_MCUBOOT=y

CONFIG_LTE_LC_NEIGHBOR_CELL_MEAS_MODULE=y
38 changes: 38 additions & 0 deletions examples/zephyr/location/socs/nrf9160_ns.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# General config
CONFIG_HEAP_MEM_POOL_SIZE=4096
CONFIG_NEWLIB_LIBC=y

# Networking
CONFIG_NET_SOCKETS_OFFLOAD=y
CONFIG_NET_IPV6=y
CONFIG_NET_IPV6_NBR_CACHE=n
CONFIG_NET_IPV6_MLD=n

# Increase native TLS socket implementation, so that it is chosen instead of
# offloaded nRF91 sockets
CONFIG_NET_SOCKETS_TLS_PRIORITY=35

# Modem library
CONFIG_NRF_MODEM_LIB=y

# LTE connectivity with network connection manager
CONFIG_NRF_MODEM_LIB_NET_IF=y
CONFIG_NRF_MODEM_LIB_NET_IF_AUTO_START=y
CONFIG_NRF_MODEM_LIB_NET_IF_AUTO_CONNECT=y
CONFIG_NET_CONNECTION_MANAGER=y
CONFIG_NET_CONNECTION_MANAGER_MONITOR_STACK_SIZE=1024

# Increased sysworkq size, due to LTE connectivity
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048

# Disable options y-selected by NCS for no good reason
CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED=n
CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED=n

# MbedTLS configuration to support p-384 curve. These options
# enable using the MbedTLS built-in support for operations not
# supported by the default nRF Oberon crypto backend
CONFIG_NORDIC_SECURITY_BACKEND=n
CONFIG_MBEDTLS_LEGACY_CRYPTO_C=y

CONFIG_LTE_LC_NEIGHBOR_CELL_MEAS_MODULE=y
163 changes: 163 additions & 0 deletions examples/zephyr/location/src/cellular_nrf91.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/*
* Copyright (c) 2025 Golioth, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(cellular_nrf91);

#include <modem/lte_lc.h>

#include "cellular.h"

/* Indicates when individual ncellmeas operation is completed. This is internal to this file. */
static K_SEM_DEFINE(scan_cellular_sem_ncellmeas_evt, 0, 1);

static enum lte_lc_lte_mode lte_mode;
static struct lte_lc_ncell neighbor_cells[CONFIG_LTE_NEIGHBOR_CELLS_MAX];
static struct lte_lc_cells_info scan_cellular_info = {
.neighbor_cells = neighbor_cells,
};

static const char *lte_mode_to_str(enum lte_lc_lte_mode mode)
{
switch (mode)
{
case LTE_LC_LTE_MODE_LTEM:
return "LTEM";
case LTE_LC_LTE_MODE_NBIOT:
return "NBIOT";
case LTE_LC_LTE_MODE_NONE:
return "NONE";
}

return "unknown";
}

static void lte_ind_handler(const struct lte_lc_evt *const evt)
{
switch (evt->type)
{
case LTE_LC_EVT_LTE_MODE_UPDATE:
LOG_INF("LTE mode: %s", lte_mode_to_str(evt->lte_mode));
lte_mode = evt->lte_mode;
break;
case LTE_LC_EVT_CELL_UPDATE:
LOG_INF("LTE cell changed: Cell ID: %d, Tracking area: %d",
evt->cell.id,
evt->cell.tac);
break;
case LTE_LC_EVT_NEIGHBOR_CELL_MEAS:
LOG_INF("LTE current cell: MCC %d, MNC %d, Cell ID: %d, Tracking area: %d",
evt->cells_info.current_cell.mcc,
evt->cells_info.current_cell.mnc,
evt->cells_info.current_cell.id,
evt->cells_info.current_cell.tac);

LOG_INF(
"Cell measurements results received: "
"ncells_count=%d, gci_cells_count=%d, current_cell.id=0x%08X",
evt->cells_info.ncells_count,
evt->cells_info.gci_cells_count,
evt->cells_info.current_cell.id);

if (evt->cells_info.current_cell.id != LTE_LC_CELL_EUTRAN_ID_INVALID)
{
/* Copy current cell information. We are seeing this is not set for GCI
* search sometimes but we have it for the previous normal neighbor search.
*/
memcpy(&scan_cellular_info.current_cell,
&evt->cells_info.current_cell,
sizeof(struct lte_lc_cell));
}

/* Copy neighbor cell information if present */
if (evt->cells_info.ncells_count > 0 && evt->cells_info.neighbor_cells)
{
memcpy(scan_cellular_info.neighbor_cells,
evt->cells_info.neighbor_cells,
sizeof(struct lte_lc_ncell) * evt->cells_info.ncells_count);

scan_cellular_info.ncells_count = evt->cells_info.ncells_count;
}
else
{
LOG_DBG("No neighbor cell information from modem");
}

/* Copy surrounding cell information if present */
if (evt->cells_info.gci_cells_count > 0 && evt->cells_info.gci_cells)
{
memcpy(scan_cellular_info.gci_cells,
evt->cells_info.gci_cells,
sizeof(struct lte_lc_cell) * evt->cells_info.gci_cells_count);

scan_cellular_info.gci_cells_count = evt->cells_info.gci_cells_count;
}
else
{
LOG_DBG("No surrounding cell information from modem");
}

k_sem_give(&scan_cellular_sem_ncellmeas_evt);
break;

default:
break;
}
}

int cellular_info_get(struct golioth_cellular_info *infos,
size_t num_max_infos,
size_t *num_returned_infos)
{
struct lte_lc_ncellmeas_params params = {
.search_type = LTE_LC_NEIGHBOR_SEARCH_TYPE_EXTENDED_LIGHT,
};
struct lte_lc_cell *current = &scan_cellular_info.current_cell;
int err;

err = lte_lc_neighbor_cell_measurement(&params);
if (err)
{
return err;
}

err = k_sem_take(&scan_cellular_sem_ncellmeas_evt, K_FOREVER);
if (err)
{
/* Semaphore was reset so stop search procedure */
err = 0;
}

switch (lte_mode)
{
case LTE_LC_LTE_MODE_LTEM:
infos[0].type = GOLIOTH_CELLULAR_TYPE_LTECATM;
break;
case LTE_LC_LTE_MODE_NBIOT:
infos[0].type = GOLIOTH_CELLULAR_TYPE_NBIOT;
break;
default:
*num_returned_infos = 0;
return 0;
}

infos[0].mcc = current->mcc;
infos[0].mnc = current->mnc;
infos[0].id = current->id;

*num_returned_infos = 1;

return 0;
}

static int cellular_nrf91_init(void)
{
lte_lc_register_handler(lte_ind_handler);

return 0;
}

SYS_INIT(cellular_nrf91_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);

0 comments on commit 3b33bd3

Please sign in to comment.