Hubble Device SDK Logo
  • Introduction
    • The Networks
      • Terrestrial Network (BLE)
      • Satellite Network
    • Key Characteristics
    • Platform Support
    • Where to go next
  • Architecture
    • Service Modules
      • Satellite Module
      • BLE Network Module
    • Port Layer
      • Project Organization
  • Terrestrial Network Overview
    • Introduction
      • Key Features
    • How It Works
    • Advertising Packet
      • Packet Header
      • Addressing
      • Payload Structure
      • Customer Payload
    • API Overview
      • Initialization
      • Time Management
      • Encryption Key Management
      • Advertisement Retrieval
    • Common API Workflow
    • Configuration Notes
  • Satellite Network Overview
    • Introduction
    • How It Works
      • Packet Generation
      • Transmission
    • Pass Prediction
      • Orbital Parameters (Satellites information)
      • Computing a Pass
    • Common API Workflow
      • Continuous Transmission
      • Dual Stack with Pass Prediction
    • Radio Timing
    • Reliability and Clock Drift
    • Supporting New Boards
    • Configuration Notes
      • Reliability and Power Consumption
      • Clock Drift Compensation
      • Supporting New Boards
  • Platform Setup
    • Zephyr
      • Adding Hubble Network to Zephyr
      • Using Hubble Network as the manifest repository
    • FreeRTOS
      • Prerequisites
      • Adding Hubble Network to FreeRTOS
    • TI SDK (SysConfig)
      • Prerequisites
      • Adding the Hubble Device SDK SysConfig Product
      • Configuring the Hubble Module in a .syscfg Script
      • Configuring the Radio for Satellite
      • Using Code Composer Studio (CCS)
      • Building the Application
    • ESP-IDF
      • Prerequisites
      • Adding Hubble Network to an ESP-IDF Project
      • Satellite Network on ESP32-C6: Required PHY Blob
    • Bare Metal
      • Requirements
      • Overview
      • Counter Source
      • Source Files
      • Configuration Defines
      • Abstraction Layers
      • Complete Example
      • Validation
      • Troubleshooting
  • Integration Guides
    • Nordic nRF Connect SDK Integration Guide
      • Supported NCS Version and Boards
      • Prerequisites
      • Create your Hubble Account
      • SDK Setup
      • Board Bring-Up
      • Project Configuration
      • Preparing for Satellite Transmission
      • Initializing the Hubble Device SDK
      • The Pass Prediction Loop
      • Building and Flashing
      • Verifying the Application
      • Troubleshooting
      • Next Steps
    • TI SimpleLink Integration Guide
      • Supported Devices and SDK Version
      • Prerequisites
      • Create your Hubble Account
      • SDK Setup
      • Project Configuration
      • Preparing for Satellite Transmission
      • Initializing the Hubble Device SDK
      • The Pass Prediction Loop
      • Building and Flashing
      • Verifying the Application
      • Troubleshooting
      • Next Steps
    • ESP-IDF Integration Guide
      • Supported Devices and SDK Version
      • Prerequisites
      • Create your Hubble Account
      • SDK Setup
      • Project Configuration
      • Preparing for Satellite Transmission
      • Initializing the Hubble Device SDK
      • The Pass Prediction Loop
      • Building and Flashing
      • Verifying the Application
      • Troubleshooting
      • Next Steps
  • Best Practices
    • Time Management
      • Provisioning Unix Time
      • Accounting for Time Drifts
      • Tips for Handling Time Persistence Across Power Cycles
      • Encryption and Time Dependency
    • Pass Prediction
      • Prerequisites
      • The API at a Glance
      • Getting a satellite pass
      • Reading the Result
      • Selecting the Minimum Elevation Angle
      • Getting Multiple Passes in the Future
      • Time, Drift, and the Search Start
      • Decision Summary
  • Security
    • Cryptographic Overview
      • Key concepts
      • Encryption steps
      • Additional references
    • Hubble Network Security Vulnerability Handling
      • Introduction
      • Security Issue Management
      • Fix Recommendations
      • Vulnerability Notification
      • Backporting of Security Vulnerabilities
    • Vulnerabilities
  • Release Notes and Lifecycle
    • Overview
    • Release Lifecycle
      • Development Phase
      • Release Candidate Phase
      • Hardening and Validation Phase
    • Release Model
      • Version Components
      • Versioning Rules
    • Release Types
      • Stable Releases
      • Long-Term Support (LTS) Releases
    • Support Policy
      • Stable Releases
      • Long-Term Support Releases
    • Release Schedule
      • Regular Releases
      • Release Announcements
    • Migration and Upgrade Guidance
    • Release Notes
      • Release 3.0.0
      • Release 2.0.0
      • Release 1.0.0

Reference

  • API
    • Core API
    • BLE Network API
    • Satellite Network API
      • Application APIs
      • Port APIs
  • Configuration Options
Hubble Device SDK
  • Docs »
  • Integration Guides »
  • TI SimpleLink Integration Guide

TI SimpleLink Integration Guide

This guide walks through integrating the Hubble Network dual-stack Satellite and BLE application with the TI SimpleLink Low Power F3 SDK.

By the end of this guide you will know how to:

  • Integrate the Hubble Satellite and Terrestrial (BLE) network stacks into a TI SimpleLink application.

  • Obtain ephemeris data and use pass prediction to schedule satellite transmissions.

  • Transmit data to the Hubble satellite network from a TI device.

Supported Devices and SDK Version

The Hubble Device SDK currently supports SimpleLink Low Power F3 SDK v9.20. If you require support for a different version, contact us.

The following TI SimpleLink device families are supported:

Device

Family

Notes

CC2340R5

CC23xx

Max 8 dBm; external amplifier required to reach 20 dBm

CC2755P10

CC27xx

20 dBm integrated PA

The following toolchain versions are validated against SimpleLink Low Power F3 SDK v9.20.00.81. See the SimpleLink Low Power F3 SDK v9.20.00.81 release notes for the full compatibility matrix. For other patch or build versions, refer to their respective release notes.

Tool

Version

Code Composer Studio

20.4.0

TI ARM Clang Compiler

4.0.4.LTS

SysConfig

1.26.3

UniFlash

9.5.0

Prerequisites

Before starting, ensure you have the following:

  • A supported development kit or custom board with a PA or FEM capable of at least +20 dBm transmit output power. The Hubble satellite link budget requires this minimum output to reach the network reliably.

  • An antenna tuned to the Hubble satellite frequency band, connected to the RF output of the PA or FEM.

  • A Hubble account and API key to fetch ephemeris data for pass prediction.

  • ADALM-PLUTO SDR (optional, recommended for custom board bring-up): used to verify RF output at the physical layer. Available from common distributors such as DigiKey and Mouser. See the ADALM-PLUTO product page for details.

Create your Hubble Account

A Hubble account is required to access the Hubble Dashboard and generate an API key for fetching ephemeris data used in pass prediction.

  1. Create an account at the Hubble Dashboard.

  2. Once logged in, follow the Hubble Platform API documentation to authenticate and generate your API key.

Keep your API key accessible. It is used later in this guide when fetching orbital parameters for pass prediction.

SDK Setup

Clone the Hubble Device SDK:

git clone https://github.com/HubbleNetwork/hubble-device-sdk.git

Adding the Hubble Device SDK to SysConfig

The steps below cover both Code Composer Studio (CCS) and a Makefile-based workflow.

If you do not have a CCS project yet, refer to the TI CCS Getting Started guide for instructions on creating one.

  1. Right-click your project folder and select Properties.

  2. Navigate to Build → Tools → SysConfig.

  3. In the SysConfig Flags field, append:

    -s "/path/to/hubble-device-sdk/.metadata/product.json"
    
  4. Click the checkmark to confirm, then Save and Close.

Set the following environment variables before building:

export TICLANG_ARMCOMPILER=/path/to/ti-cgt-armllvm
export SIMPLELINK_LOWPOWER_F3_SDK_INSTALL_DIR=/path/to/simplelink_lowpower_f3_sdk
export SYSCONFIG_TOOL=/path/to/sysconfig_cli.sh
export HUBBLE_NETWORK_SDK=/path/to/hubble-device-sdk

Pass both product descriptors to the SysConfig CLI:

SYSCFG_CMD_STUB = $(SYSCONFIG_TOOL) --compiler ticlang \
    --product $(SIMPLELINK_LOWPOWER_F3_SDK_INSTALL_DIR)/.metadata/product.json \
    -s $(HUBBLE_NETWORK_SDK)/.metadata/product.json

Generate the configuration files into your build directory:

SYSCFG_FILES := $(shell $(SYSCFG_CMD_STUB) \
    --listGeneratedFiles --listReferencedFiles \
    --output $(BUILD_DIR) your-app.syscfg)

SYSCFG_C_FILES   = $(filter %.c,$(SYSCFG_FILES))
SYSCFG_H_FILES   = $(filter %.h,$(SYSCFG_FILES))
SYSCFG_OPT_FILES = $(filter %.opt,$(SYSCFG_FILES))

Pass the generated .opt files to the compiler:

CFLAGS += $(addprefix @,$(SYSCFG_OPT_FILES))

Besides this, you will need to pull in the correct header and source files from TI SimpleLink. See samples/freertos/ti/sat-dual-stack for a complete reference Makefile for each target device.

Project Configuration

Enable the Hubble dual-stack functionality by adding Hubble configuration options to your project’s .syscfg file.

  1. Double-click your project’s .syscfg file to open it in the SysConfig editor.

  2. In the left pane, scroll to the bottom and locate HUBBLE DEVICE SDK. Click + to add it.

  3. Check Enable Hubble Satellite Network and Enable Hubble Terrestrial Network.

  4. Set Device time drift retry rate in PPM to your oscillator’s PPM rating (check your crystal datasheet). See Clock Drift Compensation for details.

  5. Use FreeRTOS Daemon Hook is enabled by default to automatically set up the BLE and satellite stacks. If you disable it, you must call hubble_init() in your application before the BLE stack is started. More details are in the Initializing the Hubble Device SDK section.

  6. Hover over the (?) icon next to each option to learn more, or refer to Configuration Options for the complete options reference.

  7. Save the file, then right-click it → Open With… → Text Editor and add the following at the bottom to enable both BLE and satellite stacks:

    var hubble_radio = system.getScript("/hubble_radio.js");
    hubble_radio.config_dual_stack("ble");
    

Add the following to your .syscfg file. hubble_radio.js sets up the radioconfig and the Dynamic Multi-protocol Manager (DMM) so the BLE and satellite stacks can share the radio:

var Hubble = scripting.addModule("/Hubble");
Hubble.useSatellite   = true;
Hubble.useTerrestrial = true;
/* Set to your oscillator's PPM rating (check your crystal datasheet) */
Hubble.deviceTDR      = 10;

var hubble_radio = system.getScript("/hubble_radio.js");
hubble_radio.config_dual_stack("ble");

Then set the following in your application’s hubble_config.h, which you need to include along with your source files in the Makefile:

#define CONFIG_HUBBLE_SAT_NETWORK              1
#define CONFIG_HUBBLE_BLE_NETWORK              1
#define CONFIG_HUBBLE_KEY_SIZE                 16 /* 16 for 128-bit, 32 for 256-bit */
#define CONFIG_HUBBLE_COUNTER_SOURCE_UNIX_TIME 1
#define CONFIG_HUBBLE_SAT_NETWORK_DEVICE_TDR   10 /* Check your oscillator's PPM rating */

See Clock Drift Compensation for details on TDR and how it affects retransmissions.

Optionally, enable the Hubble FreeRTOS daemon hook to automatically set up the BLE and satellite stacks.

#define CONFIG_HUBBLE_FREERTOS_DAEMON_HOOK 1

Note

Crypto: A custom AES-CMAC and AES-CTR implementation is required. Make sure to select the correct crypto options in your .syscfg file. See src/hubble_ti_crypto.c in the Hubble samples for a reference implementation.

Note

Make sure the RCL command symbol in the custom RF settings is generated automatically (set Symbol Name Generation Method to Automatic). See samples/freertos/ti/sat-dual-stack for complete reference .syscfg scripts.

Preparing for Satellite Transmission

The satellite stack requires three inputs before it can schedule and transmit:

  • Unix time: used for pass prediction and key derivation

  • Device location: latitude and longitude, used to compute satellite passes

  • Orbital parameters: satellite ephemeris data describing each satellite’s orbit

How these are provisioned is up to the application.

Time

Many approaches work: BLE provisioning from a phone, NTP over Wi-Fi, GPS, an RTC, or reading from persistent storage across reboots. See Time Management for best practices and trade-offs.

Location

If the device is deployed at a fixed location, latitude and longitude can be hard-coded directly in firmware:

struct hubble_sat_device_pos device_pos = {
    .lat = 47.6,
    .lon = -122.3,
};

For mobile devices, location can be obtained from an onboard GPS module if present, or provisioned at runtime from a companion app. For example, delivered over BLE from a phone/gateway that has GPS access.

Orbital Parameters

Orbital parameters describe each satellite’s orbit and are used by hubble_sat_next_pass_get() to predict when a satellite will be visible from the device location.

Since Hubble satellites are station-keeping, orbital parameters are stable enough to be baked into firmware at build time. Use the tools/orbital_params_fetch.py helper to fetch current parameters from the Hubble API and generate a sat_params.c file ready to compile into your application:

export HUBBLE_API_TOKEN=<your-api-token>
python tools/orbital_params_fetch.py path/to/output

See Orbital Parameters (Satellites information) for details on the generated format and how to register the array with the SDK.

Initializing the Hubble Device SDK

Once time, location, and orbital parameters are available, initialize the SDK before calling any other Hubble API:

/*
 * At this point unix_time_ms, device_pos, and orb_params are assumed to be
 * valid. Either baked into firmware or received via BLE provisioning.
 */
err = hubble_init(unix_time_ms, master_key);
if (err != 0) {
    LOG_ERR("Failed to initialize Hubble Device SDK (err %d)", err);
    return err;
}

err = hubble_sat_satellites_set(orb_params, orb_params_count);
if (err != 0) {
    LOG_ERR("Failed to set orbital parameters (err %d)", err);
    return err;
}

hubble_init() takes the current Unix time in milliseconds and a pointer to the master key. hubble_sat_satellites_set() registers the orbital parameters array with the SDK.

Warning

  • The key buffer MUST remain valid for the lifetime of SDK usage. The SDK stores the pointer directly and does not copy the key. Do not use a stack or temporary buffer.

  • Unix time must be non-zero. Passing 0 in CONFIG_HUBBLE_COUNTER_SOURCE_UNIX_TIME mode returns an error.

  • The orbital parameters array MUST remain valid for as long as pass prediction is used. The SDK stores a pointer and does not copy the array.

If CONFIG_HUBBLE_FREERTOS_DAEMON_HOOK is disabled, hubble_init() must be called before BLEAppUtil_init:

/* Hardware initialization: Board_init(), clocks, peripherals, etc. */

/*
 * unix_time_ms must be > device uptime in CONFIG_HUBBLE_COUNTER_SOURCE_UNIX_TIME
 * mode. We can use UINT64_MAX as a sentinel value until real Unix time is provisioned.
 */
hubble_init(UINT64_MAX, master_key);

/* Update user configuration of the BLE stack */
user0Cfg.appServiceInfo->timerTickPeriod     = ICall_getTickPeriod();
user0Cfg.appServiceInfo->timerMaxMillisecond = ICall_getMaxMSecs();

BLEAppUtil_init(&criticalErrorHandler, &App_StackInitDoneHandler,
                &appMainParams, &appMainPeriCentParams);

Once real Unix time and orbital parameters are available (e.g. provisioned over BLE), call hubble_sat_satellites_set() before starting pass prediction.

The Pass Prediction Loop

With the SDK initialized, the application enters the main dual-stack loop: compute the next satellite pass, beacon over BLE while waiting, stop BLE, transmit to the satellite, then repeat.

Compute the Next Pass

for (;;) {
    now_ms = hubble_time_get();

    err = hubble_sat_next_pass_get(now_ms, &device_pos, &pass_info);
    if (err != 0) {
        LOG_ERR("Failed to get next pass (err %d)", err);
        return err;
    }

    /* If the pass has already started, find the next one. */
    if (pass_info.start <= now_ms) {
        err = hubble_sat_next_pass_get(
            pass_info.start + pass_info.duration,
            &device_pos, &pass_info);
        if (err != 0) {
            LOG_ERR("Failed to get next pass (err %d)", err);
            return err;
        }
    }

hubble_sat_next_pass_get() returns the soonest pass visible from the device location. If pass_info.start is already in the past, a pass is in progress, skip it and compute the next one by searching from after its end (pass_info.start + pass_info.duration).

Beacon over BLE While Waiting

Schedule a timer for the pass window and start BLE advertising while the device waits. The example below uses ClockP; any timer peripheral that can schedule a future callback works equally well.

/*
 * Schedule a ClockP timer for the satellite pass window.
 * Verify configTICK_RATE_HZ: the sleep duration must not exceed
 * the maximum timeout ClockP supports at your tick rate.
  */
ClockP_setTimeout(&satPassClock,
                  ClockP_usToTicks((pass_info.start - now_ms) * 1000U));
ClockP_start(&satPassClock);

/* Get the Hubble beacon payload and start advertising */
hubble_ble_advertise_get(inputBuf, inputBufLen, outBuf, &outBufLen);
ble_adv_start();

/*
 * Block until the pass timer fires. Common approaches are
 * a semaphore, task notification, or event flag.
 */
SemaphoreP_pend(&satPassSem, SemaphoreP_WAIT_FOREVER);

Transmit to the Satellite

Stop advertising, then build and send the packet:

    ble_adv_stop();

    err = hubble_sat_packet_get(&packet, NULL, 0);
    if (err != 0) {
        LOG_ERR("Failed to build packet (err %d)", err);
        return err;
    }

    /* Blocking call. Retries are handled internally by the SDK */
    err = hubble_sat_packet_send(&packet, HUBBLE_SAT_RELIABILITY_NORMAL);
    if (err != 0) {
        LOG_ERR("Failed to send packet (err %d)", err);
        return err;
    }
} /* end while loop, back to compute the next pass, re-enable bluetooth, and beacon */

hubble_sat_packet_send() is blocking. It returns only after the full transmission sequence completes, including all retries. See Reliability and Power Consumption for guidance on reliability modes and their effect on power consumption.

Note

BLEAppUtil_advStart and BLEAppUtil_advStop must be called from within the BLEAppUtil context. Calling them directly from another thread will cause a crash or silently fail. Use BLEAppUtil_invokeFunction to put the call into the correct context:

bStatus_t ble_adv_start(void)
{
    return BLEAppUtil_invokeFunction(
        (InvokeFromBLEAppUtilContext_t)_beacon_start, NULL);
}

bStatus_t ble_adv_stop(void)
{
    return BLEAppUtil_invokeFunction(
        (InvokeFromBLEAppUtilContext_t)_beacon_stop, NULL);
}

where _beacon_start calls BLEAppUtil_advStart(_beacon_adv_handle, &_hubble_start_adv_set) and _beacon_stop calls BLEAppUtil_advStop(_beacon_adv_handle). See samples/freertos/ti/sat-dual-stack for a complete reference implementation.

Building and Flashing

  1. Right-click your project in the Project Explorer and select Build Project (or use Project → Build Project from the menu bar).

  2. Once the build succeeds, right-click the project and select Flash Project to flash the firmware to the device.

Build your application by invoking the Makefile:

make -f <your-makefile>

To flash, use UniFlash. Connect your device and load the built .hex or .out file.

Note

CC2755P10 (CC27xx): If the Hardware Security Module (HSM) has not been provisioned on your device yet, BLE may not function correctly. Refer to the TI SimpleLink CC27xx Getting Started guide for instructions on loading the HSM before running your application.

Verifying the Application

Unlike other ports, the TI port does not include a logging backend built in for Hubble Device SDK log. Verification is done using external tools, or enabling logging module and calling log functions manually in your application.

Verify BLE

Use the SDK’s scan script to confirm BLE advertising is working. Install the dependencies and run:

pip install -r tools/requirements-scan.txt
python tools/scan.py --key "<your-device-key>"

The script scans for Hubble BLE beacons (UUID 0xFCA6) and prints decoded packets in real time. Running without --key prints raw packets without decryption.

Alternatively, use the Hubble Connect mobile app to see nearby Hubble devices:

  • Hubble Connect on the App Store

  • Hubble Connect on Google Play

Verify Satellite RF

To verify the satellite RF output before a live pass, use an ADALM-PLUTO SDR and the pyhubblenetwork scan tool. See the RF Verification with an SDR section in Next Steps below for full instructions.

Troubleshooting

hubble_init returns an error

Symptom: <wrn> hubblenetwork: Failed to set Unix Epoch time

Cause: unix_time_ms passed to hubble_init() is 0. The SDK requires a valid non-zero Unix timestamp.

Fix: Ensure time is provisioned (over BLE, NTP, GPS, or RTC) before calling hubble_init(). See the Preparing for Satellite Transmission section in this guide.

—

Symptom: <wrn> hubblenetwork: Failed to set key

Cause: The key buffer is NULL, zero-length, or the wrong size for the configured key type.

Fix: Verify the key is correctly decoded and its length matches the configured key size.

Pass prediction returns an error

Symptom: <wrn> hubblenetwork: Hubble Satellite next pass get: no satellites configured

Cause: hubble_sat_satellites_set() was not called before hubble_sat_next_pass_get().

Fix: Call hubble_sat_satellites_set() with a valid orbital parameters array immediately after hubble_init().

—

Symptom: <wrn> hubblenetwork: Hubble Satellite next pass get: no pass found

Cause: No satellite pass is visible from the given location within the search window. Most commonly caused by incorrect device coordinates or a stale Unix timestamp.

Fix: Verify that device_pos.lat and device_pos.lon are correct and that unix_time_ms reflects current wall-clock time.

—

Symptom: Firmware appears to hang or stall inside hubble_sat_next_pass_get().

Cause: The pass prediction algorithm iterates forward orbit-by-orbit until it finds a pass. If the input time is near zero (e.g. Unix time was passed in seconds instead of milliseconds), or if device_pos.lat and device_pos.lon are invalid, the loop can spin through thousands of orbits before returning.

Fix: Confirm unix_time_ms is in milliseconds and that device_pos.lat and device_pos.lon hold the actual device coordinates.

Transmission fails

Symptom: hubble_sat_packet_send() returns an error or BLE silently fails to send any advertising packets.

Cause:

  • BLEAppUtil_advStop or BLEAppUtil_advStart was not called from within the BLEAppUtil context.

  • Stack is too tight: the call stack needs to have enough space to handle both BLE and satellite stack operations.

Fix:

  • Verify the return status of BLEAppUtil_invokeFunction.

  • Increase the stack size of the task that calls hubble_sat_packet_send, pass prediction API, or BLE advertising start/stop.

Next Steps

RF Verification with an SDR

Before waiting for a live satellite pass, you can verify that your device is transmitting a valid Hubble packet at the physical layer using an ADALM-PLUTO product page and the pyhubblenetwork Python library.

Install the library:

pip install pyhubblenetwork

Connect the ADALM-PLUTO near the device antenna and run the scanner with your device key to decode captured packets in real time:

hubblenetwork sat scan --key "<your-device-key>"

A successfully decoded packet confirms the RF output, packet framing, channel hopping sequence, and PA/FEM sequencing are all correct. For the full list of available commands, run:

hubblenetwork --help

See the pyhubblenetwork repository for detailed usage and setup instructions.

Viewing Upcoming Passes

Use the Hubble Pass Explorer to see when the next satellite pass is predicted for your location. This is useful to cross-check pass prediction results from the device and to plan test windows.

Dashboard Verification

Once a live satellite pass has occurred and hubble_sat_packet_send() returned without error, after the downlink data is successful, log into the Hubble Dashboard Devices Page to confirm the packet was received by the network. A packet appearing on the dashboard is end-to-end proof that the device is operational on the Hubble satellite network.

Further Reading

  • Satellite Network Overview: satellite protocol details, reliability modes, and power trade-offs.

  • Configuration Options: full configuration reference for all CONFIG_HUBBLE_* options.

  • Time Management: time management best practices for devices with and without a real-time clock.

  • TI SimpleLink Low Power F3 SDK: TI’s SDK documentation, examples, and release notes.

Previous Next

© Copyright 2025-2026, Hubble Network, Inc.