# What Is the F Prime Telemetry Module? Architecture and Implementation Guide

> Discover the F Prime telemetry module architecture and implementation. Publish flight software data, retrieve it with ground systems, and ensure bandwidth efficiency with CCSDS packets.

- Repository: [NASA/fprime](https://github.com/nasa/fprime)
- Tags: architecture
- Published: 2026-07-13

---

**The F Prime telemetry module provides the runtime infrastructure that enables flight software components to publish data through telemetry channels and allows ground systems to retrieve that data in a deterministic, bandwidth-efficient manner using CCSDS-compliant packets.**

The telemetry module in NASA's F Prime framework serves as the critical bridge between application-level data production and ground-system consumption. This subsystem handles everything from channel buffering and timestamping to packet serialization and transport, ensuring that spacecraft health and status data reaches operators reliably over bandwidth-constrained links. Understanding the F Prime telemetry module is essential for developers building flight software that must communicate with ground stations using standardized space protocols.

## How the F Prime Telemetry Module Works

The telemetry subsystem implements a five-stage pipeline that moves data from component-level variables to ground-ready packets. Each stage is optimized for deterministic behavior and real-time performance.

### Component-Level Channel Definition

Flight software components declare telemetry channels in their **Port XML** (`.xml`) or using the **FPP** (F Prime Prime) modeling language. Each channel receives a unique 16-bit ID (supporting up to 65,535 distinct channels), a strongly typed data format, and optional metadata such as limit thresholds. In `FppTestProject/FppTest/component/include/telemetry.fppi`, you can see production examples of these declarations.

### Channel Buffering and Write Operations

When a component needs to send data, it calls the generated `tlmWrite_<channelName>(value)` stub. This stub writes the value into a **lock-free channel buffer** managed by the telemetry subsystem. The buffer stores the latest value for every channel ID with an associated timestamp, providing O(1) lookup performance. The implementation in [`TelemetryChannel.hpp`](https://github.com/nasa/fprime/blob/main/TelemetryChannel.hpp) and [`TelemetryChannel.cpp`](https://github.com/nasa/fprime/blob/main/TelemetryChannel.cpp) handles this buffering without dynamic memory allocation, using only static memory pools suitable for safety-critical systems.

### Packetization and Transport

The **Telemetry Packetizer**, implemented in [`TelemetryPacketizer.hpp`](https://github.com/nasa/fprime/blob/main/TelemetryPacketizer.hpp) and [`TelemetryPacketizer.cpp`](https://github.com/nasa/fprime/blob/main/TelemetryPacketizer.cpp), runs periodically in its own thread (typically every 10 ms). It walks the channel buffer and packs selected channels into a **Telemetry Packet** following the **CCSDS Space Packet** standard. The packetizer supports configurable filtering by category or priority, allowing different downlinks to receive specific subsets of telemetry data.

### Ground System Processing

Once generated, packets pass to the **Serial Driver** or a custom transport layer. On the ground side, tools unpack the CCSDS primary header, secondary header, and payload, resolving channel IDs back to human-readable names for display, logging, or autonomous decision-making.

## Design Goals and Safety-Critical Features

The telemetry module achieves specific engineering goals critical to spaceflight operations:

- **Deterministic bandwidth**: The packetizer builds fixed-size packets each cycle, including only channels that have changed state or are scheduled for sampling, preventing buffer overflows during high-activity periods.
- **Low-latency delivery**: Lock-free buffer writes and dedicated packetizer threads ensure minimal delay between data generation and transmission.
- **Scalability**: The 16-bit ID space and array-indexed buffer design provide constant-time O(1) lookup regardless of channel count.
- **Configurable filtering**: Ground operators can adjust packetizer configurations to tailor telemetry flows for different mission phases or communication windows.
- **Safety-critical friendliness**: All telemetry code resides in the *Fw* (framework) layer, isolated from application logic, and uses only static memory allocation with no heap operations.

## Implementation: From Channel Definition to Ground Reception

### Declaring Telemetry Channels in FPP

Components define telemetry channels using FPP syntax. The following example from the F Prime test suite shows a temperature channel declaration:

```fpp
module MyComponent {
  telemetry {
    /** Temperature of the sensor, in deg C */
    channel temp : F32 id 2000
  }
}

```

### Writing Telemetry Data in C++

The FPP compiler generates write stubs that handle timestamping automatically. Application code calls these stubs to update channel values:

```cpp
void MyComponentImpl::runCycle() {
    // … compute temperature …
    F32 temperature = readSensor();
    // Write telemetry; the stub adds the timestamp and buffers the value.
    tlmWrite_temp(temperature);
}

```

### Configuring the Telemetry Packetizer

Ground system integrators configure packet composition using XML. This example creates a 10 ms periodic packet containing specific channels:

```xml
<packetizer>
    <packet name="TelemetryPacket" period="0.01"> <!-- 10 ms -->
        <channel id="2000" />   <!-- temp -->
        <channel id="2001" />   <!-- other channel -->
    </packet>
</packetizer>

```

### Receiving Telemetry on the Ground

Ground systems parse the CCSDS-compliant binary packets using standard libraries. The following Python example extracts floating-point telemetry values from the packet payload:

```python
import struct
from ccsds import SpacePacket

def parse_telemetry(pkt_bytes):
    sp = SpacePacket.from_bytes(pkt_bytes)
    payload = sp.payload
    # Assuming the payload layout: [temp (float), …]

    temp, = struct.unpack('>f', payload[:4])
    print(f"Temperature: {temp:.2f} °C")

```

## Core Source Files and Implementation Details

The telemetry subsystem spans several key files in the F Prime repository:

- **[`TelemetryChannel.hpp`](https://github.com/nasa/fprime/blob/main/TelemetryChannel.hpp) and [`TelemetryChannel.cpp`](https://github.com/nasa/fprime/blob/main/TelemetryChannel.cpp)**: Implement the core buffer that stores the latest value for each telemetry ID with timestamps and change-detection logic.
- **[`TelemetryPacketizer.hpp`](https://github.com/nasa/fprime/blob/main/TelemetryPacketizer.hpp) and [`TelemetryPacketizer.cpp`](https://github.com/nasa/fprime/blob/main/TelemetryPacketizer.cpp)**: Walk the channel buffer, construct CCSDS Space Packets, and hand them to transport drivers.
- **[`docs/reference/system-functional/telemetry-chan.md`](https://github.com/nasa/fprime/blob/main/docs/reference/system-functional/telemetry-chan.md)**: Documents channel definition semantics, write API behavior, and buffering internals.
- **[`docs/reference/system-functional/telemetry-packetizer.md`](https://github.com/nasa/fprime/blob/main/docs/reference/system-functional/telemetry-packetizer.md)**: Describes packetizer configuration options, packet format specifications, and filtering capabilities.
- **`FppTestProject/FppTest/component/include/telemetry.fppi`**: Provides reference examples of component telemetry definitions used in the framework's test suite.

These files together demonstrate how data flows from component-level variables through the F Prime framework to serialized CCSDS packets ready for radio transmission.

## Summary

- The F Prime telemetry module bridges flight software components and ground systems through a deterministic, CCSDS-compliant packet pipeline.
- Components write data via generated `tlmWrite_<channelName>()` stubs into lock-free buffers managed by `TelemetryChannel`.
- The `TelemetryPacketizer` constructs fixed-size packets at configurable intervals, supporting change-of-state and sample-rate filtering.
- The subsystem uses 16-bit channel IDs for O(1) lookup scalability and operates entirely with static memory allocation.
- Configuration occurs through FPP declarations and XML packetizer definitions, with ground processing using standard CCSDS parsing libraries.

## Frequently Asked Questions

### How does the F Prime telemetry module handle bandwidth constraints?

The telemetry packetizer implements deterministic bandwidth management by constructing fixed-size packets at regular intervals (e.g., 10 ms) and including only channels that have changed value or are scheduled for sampling. This prevents communication link saturation while ensuring critical data reaches the ground system without packet loss.

### What is the maximum number of telemetry channels supported in F Prime?

The F Prime telemetry module uses 16-bit channel identifiers, supporting up to **65,535 distinct telemetry channels** per spacecraft. The channel buffer uses array indexing by ID, providing constant-time O(1) lookup performance regardless of how many channels are active in the system.

### Where does the telemetry module store channel data to ensure real-time performance?

Channel data resides in a lock-free buffer implemented in [`TelemetryChannel.hpp`](https://github.com/nasa/fprime/blob/main/TelemetryChannel.hpp) that uses only static memory allocation. This design eliminates heap fragmentation risks and ensures deterministic write performance, making the subsystem suitable for safety-critical flight software where dynamic memory allocation is prohibited.

### How are telemetry packets formatted for transmission to ground stations?

The `TelemetryPacketizer` constructs packets following the **CCSDS Space Packet** standard, which includes a primary header, secondary header, and payload containing serialized channel data. This standardization allows F Prime missions to use generic ground station infrastructure and CCSDS-compliant parsing libraries for telemetry decoding.