nRF Example Code¶
Note: These are legacy C reference examples. For new development, use the Rust SDK examples with the Rust SDK instead.
C example code for using the Xylolabs API on Nordic Semiconductor nRF platforms.
File Structure¶
| File | Description |
|---|---|
nrf52840_ble_example.c |
nRF52840 BLE sensor beacon with XMBP, ultra-low power sleep |
Design Principles¶
Zephyr RTOS¶
All examples use the nRF Connect SDK which is built on Zephyr RTOS. Zephyr provides portable abstractions for GPIO, I2C, SPI, BLE, and power management across nRF devices.
// Zephyr device tree binding (preferred over direct register access)
static const struct device *accel = DEVICE_DT_GET(DT_NODELABEL(lis2dh));
static const struct device *temp = DEVICE_DT_GET(DT_NODELABEL(hts221));
// Zephyr sensor API
sensor_sample_fetch(accel);
sensor_channel_get(accel, SENSOR_CHAN_ACCEL_XYZ, &accel_val);
BLE GATT Notifications¶
The nRF52840 example operates as a BLE peripheral. It advertises a custom GATT service and sends XMBP-encoded sensor data as BLE notifications to a connected gateway (e.g., a Raspberry Pi, smartphone, or nRF9160-based gateway).
The gateway is responsible for forwarding the XMBP binary payload to the Xylolabs HTTP API. The XMBP format is passed through unchanged.
Ultra-Low Power¶
The nRF52840 targets battery-powered deployments. Between BLE transmissions, the device enters System OFF or System ON (light sleep) mode:
- Advertising interval: 1000 ms (reduces duty cycle)
- Connection interval: 200 ms (7.5 ms minimum supported)
- System ON sleep:
k_sleep(K_MSEC(SAMPLE_INTERVAL_MS))between sensor reads - RTC wakeup: Zephyr
k_timeruses the 32.768 kHz LFXO, not the main CPU clock
Typical current consumption: ~5 µA in sleep, ~6 mA during BLE TX.
XAP 2ch@48kHz Capable¶
The nRF52840 (Cortex-M4F, 256KB RAM) is capable of XAP (LC3-based) encoding at 2 channels / 48 kHz / 64 kbps per channel. However, the BLE GATT notification MTU (up to 247 bytes per notification) limits throughput. For audio use cases, the nRF9160 target with direct LTE-M1 is recommended instead.
The BLE sensor beacon example focuses on sensor data (accelerometer, temperature) rather than audio, which is the primary use case for battery-powered BLE nodes.
Legacy C Build¶
These examples use the nRF Connect SDK
and the west build tool. Tested with nRF Connect SDK v2.x.
# Initialize nRF Connect SDK workspace (one-time)
west init -m https://github.com/nrfconnect/sdk-nrf --mr v2.6.0 nrf-workspace
cd nrf-workspace
west update
# Build for nRF52840 DK
west build -b nrf52840dk_nrf52840 docs/examples/nrf/
# Flash
west flash
# Monitor serial output
west espressif monitor # or: screen /dev/ttyACM0 115200
prj.conf (minimal Kconfig)¶
CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_GATT_DYNAMIC_DB=y
CONFIG_BT_DEVICE_NAME="XyloSensor"
CONFIG_SENSOR=y
CONFIG_WDT=y
CONFIG_PM=y
CONFIG_PM_DEVICE=y
CMakeLists.txt¶
cmake_minimum_required(VERSION 3.20)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(xylolabs_nrf52840_example)
target_sources(app PRIVATE nrf52840_ble_example.c)
target_include_directories(app PRIVATE
${CMAKE_SOURCE_DIR}/../../../sdk/c/common/include
${CMAKE_SOURCE_DIR}/../../../sdk/c/nrf
)
BLE Gateway Reference¶
The BLE gateway receives XMBP binary payloads over BLE GATT and forwards them to the Xylolabs API via HTTP POST.
# Example Python gateway (using bleak)
import asyncio, httpx
from bleak import BleakClient
XYLOLABS_API = "https://api.xylolabs.com/api/v1/ingest"
API_KEY = "xk_your_api_key_here"
XMBP_NOTIFY_UUID = "12345678-1234-1234-1234-1234567890ab"
async def on_notify(sender, data: bytearray):
async with httpx.AsyncClient() as client:
await client.post(XYLOLABS_API,
content=bytes(data),
headers={"X-Api-Key": API_KEY,
"Content-Type": "application/octet-stream"})
async def main():
async with BleakClient("AA:BB:CC:DD:EE:FF") as client:
await client.start_notify(XMBP_NOTIFY_UUID, on_notify)
await asyncio.sleep(3600)
asyncio.run(main())
API Documentation Reference¶
- API Reference -- XMBP protocol, ingest sessions, audio uploads, API key management, device management