|
1 | | -# Embedded-SDLP |
| 1 | +# EmbeddedSDLP |
2 | 2 |
|
3 | | -A minimal Space Data Link Protocol (SDLP) implementation in C designed for embedded and resource-constrained space applications. |
| 3 | +Minimal, embedded-optimized implementation of **CCSDS Space Data Link Protocol (SDLP)** for TM (Telemetry) and TC (Telecommand) frame handling, following international standards. |
4 | 4 |
|
5 | | -## Overview |
| 5 | +## Standards Compliance |
6 | 6 |
|
7 | | -EmbeddedSDLP provides a lightweight implementation of TM (Telemetry) and TC (Telecommand) frame handling based on CCSDS standards. It's designed for use in spacecraft, CubeSats, and other space systems where code size and reliability are critical. |
| 7 | +- **CCSDS 132.0-B-3**: TM Space Data Link Protocol |
| 8 | +- **CCSDS 232.0-B-4**: TC Space Data Link Protocol |
8 | 9 |
|
9 | 10 | ## Features |
10 | 11 |
|
| 12 | +### Core Protocol Implementation |
| 13 | + |
11 | 14 | - **Telemetry (TM) Frame Handling**: Create, encode, and decode TM frames with CRC validation |
12 | 15 | - **Telecommand (TC) Frame Handling**: Create, encode, and decode TC frames with CRC validation |
13 | | -- **Minimal Dependencies**: Pure C99 with no external dependencies |
14 | | -- **Embedded-Friendly**: Small memory footprint and predictable behavior |
15 | 16 | - **CRC16 Error Detection**: Built-in frame error control field (FECF) for data integrity |
16 | 17 | - **Configurable**: Support for virtual channels, spacecraft IDs, and frame sequence numbers |
| 18 | +- **TC Segment Header**: Optional MAP-based segmentation support (enabled with `TC_SEGMENT_HEADER_ENABLED`) |
| 19 | + |
| 20 | +### Design Principles |
| 21 | + |
| 22 | +- **Minimal footprint**: Small library size (stripped) |
| 23 | +- **Zero allocation**: Stack-based, no dynamic memory |
| 24 | +- **Embedded-optimized**: Pure C99, no external dependencies |
| 25 | +- **Portable**: Standard C99, big-endian network byte order |
| 26 | +- **Reliable**: CRC-16-CCITT frame error control |
| 27 | + |
| 28 | +## Project Structure |
| 29 | + |
| 30 | +``` |
| 31 | +EmbeddedSDLP/ |
| 32 | +├── include/ |
| 33 | +│ ├── sdlp_common.h # Common definitions and CRC |
| 34 | +│ ├── sdlp_tm.h # TM frame definitions |
| 35 | +│ └── sdlp_tc.h # TC frame definitions |
| 36 | +├── src/ |
| 37 | +│ ├── sdlp_common.c # CRC16 implementation |
| 38 | +│ ├── sdlp_tm.c # TM frame implementation |
| 39 | +│ └── sdlp_tc.c # TC frame implementation |
| 40 | +├── examples/ |
| 41 | +│ ├── tm_example.c # TM frame example |
| 42 | +│ └── tc_example.c # TC frame example |
| 43 | +├── docs/ |
| 44 | +│ ├── 132x0b3_TM_SDLP.pdf # CCSDS 132.0-B-3 standard |
| 45 | +│ └── 232x0b4e1c1_TC_SDLP.pdf # CCSDS 232.0-B-4 standard |
| 46 | +├── Makefile |
| 47 | +└── README.md |
| 48 | +``` |
17 | 49 |
|
18 | 50 | ## Building |
19 | 51 |
|
20 | | -Build the library and examples using Make: |
| 52 | +### Build Everything |
21 | 53 |
|
22 | 54 | ```bash |
23 | | -make all # Build library and examples |
24 | | -make lib # Build library only |
25 | | -make examples # Build examples only |
26 | | -make test # Run example programs |
27 | | -make clean # Clean build artifacts |
| 55 | +make all |
28 | 56 | ``` |
29 | 57 |
|
30 | 58 | This will create: |
31 | 59 | - `libsdlp.a` - Static library |
32 | 60 | - `bin/tm_example` - TM frame example |
33 | 61 | - `bin/tc_example` - TC frame example |
34 | 62 |
|
35 | | -## Usage |
| 63 | +### Build Library Only |
| 64 | + |
| 65 | +```bash |
| 66 | +make lib |
| 67 | +# Produces: libsdlp.a (static) |
| 68 | +``` |
| 69 | + |
| 70 | +### Build Examples |
| 71 | + |
| 72 | +```bash |
| 73 | +make examples |
| 74 | +``` |
36 | 75 |
|
37 | | -### Telemetry (TM) Example |
| 76 | +### Run Tests |
| 77 | + |
| 78 | +```bash |
| 79 | +make test |
| 80 | +``` |
| 81 | + |
| 82 | +### Clean |
| 83 | + |
| 84 | +```bash |
| 85 | +make clean # Remove build artifacts |
| 86 | +``` |
| 87 | + |
| 88 | +## Quick Start |
| 89 | + |
| 90 | +### Create and Send a TM Frame |
38 | 91 |
|
39 | 92 | ```c |
40 | 93 | #include "sdlp_tm.h" |
41 | 94 |
|
42 | | -sdlp_tm_frame_t frame; |
43 | 95 | uint8_t buffer[1500]; |
44 | 96 | size_t encoded_size; |
45 | 97 |
|
46 | 98 | // Create a TM frame |
47 | | -const char *data = "Temperature: 25C"; |
| 99 | +const char *data = "Temperature: 25C, Voltage: 3.3V"; |
| 100 | +sdlp_tm_frame_t frame; |
48 | 101 | sdlp_tm_create_frame(&frame, 0x123, 2, (uint8_t *)data, strlen(data)); |
49 | 102 |
|
50 | 103 | // Encode frame to buffer |
51 | | -sdlp_tm_encode_frame(&frame, buffer, sizeof(buffer), &encoded_size); |
| 104 | +if (sdlp_tm_encode_frame(&frame, buffer, sizeof(buffer), &encoded_size) == SDLP_SUCCESS) { |
| 105 | + printf("TM frame encoded: %zu bytes\n", encoded_size); |
| 106 | +} |
| 107 | +``` |
| 108 | +
|
| 109 | +### Parse an Incoming TM Frame |
52 | 110 |
|
53 | | -// Decode frame from buffer |
| 111 | +```c |
54 | 112 | sdlp_tm_frame_t decoded; |
55 | | -sdlp_tm_decode_frame(buffer, encoded_size, &decoded); |
| 113 | +if (sdlp_tm_decode_frame(buffer, encoded_size, &decoded) == SDLP_SUCCESS) { |
| 114 | + printf("Spacecraft ID: 0x%03X, Data: %.*s\n", |
| 115 | + decoded.header.spacecraft_id, |
| 116 | + (int)decoded.data_length, decoded.data); |
| 117 | +} |
56 | 118 | ``` |
57 | 119 |
|
58 | | -### Telecommand (TC) Example |
| 120 | +### Create and Send a TC Frame |
59 | 121 |
|
60 | 122 | ```c |
61 | 123 | #include "sdlp_tc.h" |
62 | 124 |
|
63 | | -sdlp_tc_frame_t frame; |
| 125 | +/* Telecommand identifiers */ |
| 126 | +#define TC_CMD_SET_MODE_SAFE 0x01U |
| 127 | + |
64 | 128 | uint8_t buffer[1500]; |
65 | 129 | size_t encoded_size; |
66 | 130 |
|
67 | | -// Create a TC frame |
68 | | -const char *cmd = "ENABLE_SENSOR"; |
69 | | -sdlp_tc_create_frame(&frame, 0x456, 1, 0, (uint8_t *)cmd, strlen(cmd)); |
| 131 | +// Create a TC frame with a numeric command ID |
| 132 | +uint8_t cmd_id = TC_CMD_SET_MODE_SAFE; |
| 133 | +sdlp_tc_frame_t frame; |
| 134 | +sdlp_tc_create_frame(&frame, 0x123, 1, 42, &cmd_id, sizeof(cmd_id)); |
70 | 135 |
|
71 | 136 | // Encode frame to buffer |
72 | | -sdlp_tc_encode_frame(&frame, buffer, sizeof(buffer), &encoded_size); |
| 137 | +if (sdlp_tc_encode_frame(&frame, buffer, sizeof(buffer), &encoded_size) == SDLP_SUCCESS) { |
| 138 | + printf("TC frame encoded: %zu bytes\n", encoded_size); |
| 139 | +} |
| 140 | +``` |
73 | 141 |
|
74 | | -// Decode frame from buffer |
| 142 | +### Parse an Incoming TC Frame |
| 143 | +
|
| 144 | +```c |
75 | 145 | sdlp_tc_frame_t decoded; |
76 | | -sdlp_tc_decode_frame(buffer, encoded_size, &decoded); |
| 146 | +if (sdlp_tc_decode_frame(buffer, encoded_size, &decoded) == SDLP_SUCCESS) { |
| 147 | + printf("Spacecraft ID: 0x%03X, Command ID: 0x%02X\n", |
| 148 | + decoded.header.spacecraft_id, |
| 149 | + decoded.data[0]); |
| 150 | +} |
77 | 151 | ``` |
78 | 152 |
|
79 | | -## API Overview |
| 153 | +## API Reference |
| 154 | + |
| 155 | +### Common |
80 | 156 |
|
81 | | -### Common Functions |
82 | | -- `sdlp_crc16()` - Calculate CRC16 checksum |
| 157 | +```c |
| 158 | +// Calculate CRC-16-CCITT checksum |
| 159 | +uint16_t sdlp_crc16(const uint8_t *data, size_t length); |
| 160 | +``` |
83 | 161 |
|
84 | 162 | ### TM Functions |
85 | | -- `sdlp_tm_create_frame()` - Create a TM frame with data |
86 | | -- `sdlp_tm_encode_frame()` - Encode frame to byte buffer |
87 | | -- `sdlp_tm_decode_frame()` - Decode frame from byte buffer |
| 163 | +
|
| 164 | +```c |
| 165 | +// Create a TM frame with payload data |
| 166 | +int sdlp_tm_create_frame(sdlp_tm_frame_t *frame, uint16_t spacecraft_id, |
| 167 | + uint8_t virtual_channel_id, const uint8_t *data, |
| 168 | + uint16_t data_length); |
| 169 | +
|
| 170 | +// Encode a TM frame into a byte buffer |
| 171 | +int sdlp_tm_encode_frame(const sdlp_tm_frame_t *frame, uint8_t *buffer, |
| 172 | + size_t buffer_size, size_t *encoded_size); |
| 173 | +
|
| 174 | +// Decode a TM frame from a byte buffer (validates CRC) |
| 175 | +int sdlp_tm_decode_frame(const uint8_t *buffer, size_t buffer_size, |
| 176 | + sdlp_tm_frame_t *frame); |
| 177 | +``` |
88 | 178 |
|
89 | 179 | ### TC Functions |
90 | | -- `sdlp_tc_create_frame()` - Create a TC frame with data |
91 | | -- `sdlp_tc_encode_frame()` - Encode frame to byte buffer |
92 | | -- `sdlp_tc_decode_frame()` - Decode frame from byte buffer |
93 | 180 |
|
94 | | -All functions return `SDLP_SUCCESS` (0) on success or a negative error code on failure. |
| 181 | +```c |
| 182 | +// Create a TC frame with command data |
| 183 | +int sdlp_tc_create_frame(sdlp_tc_frame_t *frame, uint16_t spacecraft_id, |
| 184 | + uint8_t virtual_channel_id, uint8_t frame_seq_num, |
| 185 | + const uint8_t *data, uint16_t data_length); |
| 186 | + |
| 187 | +// Encode a TC frame into a byte buffer |
| 188 | +int sdlp_tc_encode_frame(const sdlp_tc_frame_t *frame, uint8_t *buffer, |
| 189 | + size_t buffer_size, size_t *encoded_size); |
| 190 | + |
| 191 | +// Decode a TC frame from a byte buffer (validates CRC) |
| 192 | +int sdlp_tc_decode_frame(const uint8_t *buffer, size_t buffer_size, |
| 193 | + sdlp_tc_frame_t *frame); |
| 194 | + |
| 195 | +// Set TC segment header fields (requires TC_SEGMENT_HEADER_ENABLED) |
| 196 | +int sdlp_tc_set_segment_header(sdlp_tc_frame_t *frame, |
| 197 | + sdlp_tc_seq_flag_t sequence_flags, uint8_t map_id); |
| 198 | +``` |
95 | 199 |
|
96 | | -## Project Structure |
| 200 | +All functions return `SDLP_SUCCESS` (0) on success or a negative error code on failure: |
| 201 | +- `SDLP_ERROR_INVALID_PARAM` (-1): NULL pointer or invalid parameter |
| 202 | +- `SDLP_ERROR_BUFFER_TOO_SMALL` (-2): Output buffer too small |
| 203 | +- `SDLP_ERROR_INVALID_FRAME` (-3): Frame structure invalid |
| 204 | +- `SDLP_ERROR_CRC_MISMATCH` (-4): CRC validation failed |
97 | 205 |
|
98 | | -``` |
99 | | -. |
100 | | -├── include/ # Header files |
101 | | -│ ├── sdlp_common.h # Common definitions and CRC |
102 | | -│ ├── sdlp_tm.h # TM frame definitions |
103 | | -│ └── sdlp_tc.h # TC frame definitions |
104 | | -├── src/ # Implementation files |
105 | | -│ ├── sdlp_common.c |
106 | | -│ ├── sdlp_tm.c |
107 | | -│ └── sdlp_tc.c |
108 | | -├── examples/ # Example programs |
109 | | -│ ├── tm_example.c |
110 | | -│ └── tc_example.c |
111 | | -└── Makefile # Build configuration |
112 | | -``` |
| 206 | +## Memory Usage (Estimated) |
| 207 | +
|
| 208 | +- **Library (stripped)**: < 5 KB |
| 209 | +- **Per TM frame buffer**: `TM_PRIMARY_HEADER_SIZE` (6) + data + 2 bytes FECF |
| 210 | +- **Per TC frame buffer**: `TC_PRIMARY_HEADER_SIZE` (5) + data + 2 bytes FECF |
| 211 | +- **Maximum data per frame**: 1024 bytes (`TM_MAX_DATA_SIZE` / `TC_MAX_DATA_SIZE`) |
| 212 | +
|
| 213 | +## Limitations and Extensions |
| 214 | +
|
| 215 | +Current implementation focuses on core protocol features: |
| 216 | +
|
| 217 | +- No automatic retransmission handling |
| 218 | +- No flow control or bandwidth management |
| 219 | +- No segmentation beyond optional TC segment header |
| 220 | +- Single static frame counter (not thread-safe) |
| 221 | +
|
| 222 | +These can be extended as needed for specific mission requirements. |
113 | 223 |
|
114 | | -## Requirements |
| 224 | +## References |
115 | 225 |
|
116 | | -- C compiler with C99 support (gcc, clang, etc.) |
117 | | -- Make |
| 226 | +- CCSDS 132.0-B-3: TM Space Data Link Protocol ([docs/132x0b3_TM_SDLP.pdf](docs/132x0b3_TM_SDLP.pdf)) |
| 227 | +- CCSDS 232.0-B-4: TC Space Data Link Protocol ([docs/232x0b4e1c1_TC_SDLP.pdf](docs/232x0b4e1c1_TC_SDLP.pdf)) |
118 | 228 |
|
119 | 229 | ## License |
120 | 230 |
|
|
0 commit comments