1+ /**
2+ * @author Edwin Mwiti
3+ * emwiti658@gmail.com
4+ *
5+ */
6+
7+ #include <stdlib.h>
8+ #include <stdio.h>
9+ #include <string.h>
10+ #include "ccsds_tm.h"
11+
12+ char * mission_id = "PSF_ADVENT_1" ;
13+ uint32_t spacecraft_id = 26001001 ; // YYXXXAA -> see telemetry packet diagram
14+ uint8_t craft_id = 100 ; // to fit into 10 bit value
15+
16+ /* create CCDS packet struct */
17+ CCSDS_packet * CCSDS_packet_create () {
18+ CCSDS_packet * pkt = (CCSDS_packet * ) malloc (sizeof (CCSDS_packet ));
19+
20+ if (pkt != NULL ) {
21+ CCSDS_packet_init (
22+ pkt ,
23+ CCSDS_packet_set_spacecraft_id ,
24+ CCSDS_packet_get_spacecraft_id ,
25+ CCSDS_packet_create_transfer_frame_primary_header ,
26+ CCSDS_packet_create_transfer_frame_secondary_header ,
27+ CCSDS_packet_extract_packet_primary_header ,
28+ CCSDS_packet_dump_metadata ,
29+ CCSDS_packet_telemetry_faker ,
30+ CCSDS_packet_telemetry_cleanup ,
31+ CCSDS_packet_print_bin
32+ );
33+
34+ }
35+ }
36+
37+ /* call init with the created functions */
38+ void CCSDS_packet_init (
39+ CCSDS_packet * p ,
40+ void (* CCSDS_packet_set_spacecraft_id )(CCSDS_packet * , uint32_t ),
41+ uint32_t (* CCSDS_packet_get_spacecraft_id )(CCSDS_packet * ),
42+ void (* CCSDS_packet_create_transfer_frame_primary_header )(CCSDS_packet * ),
43+ void (* CCSDS_packet_create_transfer_frame_secondary_header )(CCSDS_packet * ),
44+ void (* CCSDS_packet_extract_packet_primary_header )(CCSDS_packet * ),
45+ void (* CCSDS_packet_dump_metadata )(CCSDS_packet * ),
46+ void (* CCSDS_packet_telemetry_faker )(CCSDS_packet * p ),
47+ void (* CCSDS_packet_cleanup )(CCSDS_packet * ),
48+ void (* CCSDS_packet_print_bin )(int )
49+ ) {
50+ if (p != NULL ){
51+
52+ p -> version_number = VERSION_NUMBER ;
53+ p -> spacecraft_id = craft_id ;
54+ strncpy (p -> mission_id , mission_id , strlen (mission_id ) + 1 );
55+
56+ // assign function pointer objects
57+ p -> _CCSDS_packet_set_spacecraft_id = CCSDS_packet_set_spacecraft_id ;
58+ p -> _CCSDS_packet_get_spacecraft_id = CCSDS_packet_get_spacecraft_id ;
59+ p -> _CCSDS_packet_create_transfer_frame_primary_header = CCSDS_packet_create_transfer_frame_primary_header ;
60+ p -> _CCSDS_packet_create_transfer_frame_secondary_header = CCSDS_packet_create_transfer_frame_secondary_header ,
61+ p -> _CCSDS_packet_extract_packet_primary_header = CCSDS_packet_extract_packet_primary_header ;
62+ p -> _CCSDS_packet_cleanup = CCSDS_packet_cleanup ;
63+ p -> _CCSDS_packet_dump_metadata = CCSDS_packet_dump_metadata ;
64+ p -> _CCSDS_packet_telemetry_faker = CCSDS_packet_telemetry_faker ;
65+ p -> _CCSDS_packet_print_bin = CCSDS_packet_print_bin ;
66+
67+ /* initialize defaults packet headers according to CCSDS protocol */
68+ p -> version_number = VERSION_NUMBER ;
69+ p -> transfer_frame_primary_header = 0x00 ;
70+
71+ } else {
72+ // only for embedded todo: log to logger on MCU
73+ puts ("packet instance is NULL" );
74+ }
75+ }
76+
77+ /* set the spacecraft ID in case there is need to change */
78+ void CCSDS_packet_set_spacecraft_id (CCSDS_packet * p , uint32_t id ) {
79+ p -> spacecraft_id = id ;
80+ }
81+
82+ /* get spacecraft ID*/
83+ uint32_t CCSDS_packet_get_spacecraft_id (CCSDS_packet * p ) {
84+ return p -> spacecraft_id ;
85+ }
86+
87+ /* destructor*/
88+ void CCSDS_packet_telemetry_cleanup (CCSDS_packet * p ) {
89+ if (p != NULL ) {
90+ free (p );
91+ }
92+ }
93+
94+ /**
95+ * @brief Create the transfer frame primary header
96+ */
97+ void CCSDS_packet_create_transfer_frame_primary_header (CCSDS_packet * p ) {
98+ /* package the version number */
99+ uint8_t v_num = 0x00 ;
100+ v_num |= VERSION_NUMBER ;
101+
102+ /* package the craft ID */
103+ uint16_t id = 0x00 ;
104+ id |= ( (id >> 6 ) | (craft_id ));
105+
106+ /* package the virtual channel ID, op control flag, master channel frame count and virtual channel frame count */
107+ uint8_t virtual_channel_id = 0x00 ;
108+ uint8_t op_control_flag = 0x00 ;
109+ uint8_t master_channel_frame_count = 0x00 ;
110+ uint8_t virtual_channel_frame_count = 0x00 ;
111+
112+ /* set the transfer frame data field status to 0 -> can be packed later */
113+ #if TPFH_TRANSFER_FRAME_DATA_FIELD_STATUS_DISABLE
114+ uint64_t transfer_frame_data_status = 0x0000 ; // todo: optimize
115+ #endif
116+
117+ /* final packaged primary header 0 -> primary header is the first 48 bits(from LSB) */
118+ p -> transfer_frame_primary_header |= (
119+ (v_num ) | // LSB
120+ (id << 2 ) |
121+ (virtual_channel_id << 12 ) |
122+ (op_control_flag << 15 ) |
123+ (master_channel_frame_count << 16 ) |
124+ (virtual_channel_frame_count << 24 ) |
125+ (transfer_frame_data_status << 32 )
126+ );
127+
128+ printf ("version num: %d\n" , v_num );
129+ printf ("Craft ID: %d\n" , id );
130+ //printf("TFPH:%d\n", p->transfer_frame_primary_header);
131+ }
132+
133+ /**
134+ * @brief create transfer frame secondary header
135+ * in this version, this header contains metadata about the data frame
136+ */
137+ void CCSDS_packet_create_transfer_frame_secondary_header (CCSDS_packet * p ) {
138+ uint32_t secondary_header = 0 ;
139+ uint8_t secondary_version_num = 0x00 ;
140+ uint8_t secondary_sync_flag = 0x00 ;
141+ uint16_t secondary_header_data_field = 0x0000 ;
142+
143+ /* pack the header */
144+ secondary_header |= ( (secondary_version_num ) | (secondary_sync_flag << 2 ) );
145+
146+ /* get the length of data field */
147+ // uint16_t data_len = p->_data_field_length;
148+
149+ // if(data_len > CCSDS_MAX_PACKET_SIZE) {
150+ // puts("Data field too long\r\n"); // todo: log
151+ // } else {
152+ // secondary_header_data_field |= data_len;
153+ // }
154+
155+ secondary_header |= (secondary_header_data_field << 8 );
156+
157+ // return ?
158+
159+ }
160+
161+ void CCSDS_packet_create_data_field (CCSDS_packet * p ) {
162+
163+ }
164+
165+ /*============ generate dummy data ================== */
166+ // generate EPS data
167+ // this will come from the EPS board as a struct from an RTOS task
168+ eps_data_t * generate_eps_fake (void ) {
169+ eps_data_t * data = (eps_data_t * ) malloc (sizeof (eps_data_t ));
170+
171+ if (data != NULL ) {
172+
173+ }
174+
175+
176+ return data ;
177+ }
178+
179+
180+
181+ // generate ADCS data
182+ // generate EPS data
183+ // generate PAYLOAD data
184+
185+ /**
186+ * @brief extract primary header fields
187+ */
188+ void CCSDS_packet_extract_packet_primary_header (CCSDS_packet * p ) {
189+ uint8_t version = p -> transfer_frame_primary_header & ( (1 << 1UL ) | (1 << 0UL ) );
190+ uint16_t cr_id = (p -> transfer_frame_primary_header >> 2 ) & (0b1111111111 );
191+
192+ puts ("\n===== Primary frame extracted data =======\n" );
193+ printf ("version num: %d\n" , version );
194+ printf ("spacecraft ID: %d\n" , cr_id );
195+ }
196+
197+ /* print the spacecraft metadata */
198+ void CCSDS_packet_dump_metadata (CCSDS_packet * p ) {
199+ char metadata [256 ];
200+
201+ sprintf (metadata ,
202+ "\r\nSpacecraft ID: %u\nMission ID: %s\r\n" ,
203+ p -> spacecraft_id ,
204+ p -> mission_id
205+ );
206+
207+ puts (metadata );
208+
209+ }
210+
211+ /**
212+ * @brief generate dummy telemetry data
213+ */
214+ void CCSDS_packet_telemetry_faker (CCSDS_packet * p ) {
215+ /*generate OBS data */
216+ uint32_t obs_timestamp = UINT32_MAX ; // timestamp
217+ float obs_board_voltage = 3.3 ; // board_voltage
218+ float obs_board_current = 250.5 ; // board_current
219+ uint32_t obs_uptime = 45500 ; // uptime in seconds
220+ uint8_t obs_reset_count = 10 ; // number_of_resets
221+
222+ /*generate ADCS data*/
223+ float adcs_x_acc = 0.3 ;
224+ float adcs_y_acc = 6.3 ;
225+ float adcs_z_acc = 0.3 ;
226+
227+ /* generate COMMS data */
228+ /* generate PAYLOAD data */
229+ /* generate EPS data */
230+ }
231+
232+ /**
233+ * @brief print integer in binary
234+ */
235+ void CCSDS_packet_print_bin (int x ) {
236+ int leading_zero ;
237+
238+ if (x == 0 ) {
239+ puts ("0\n" );
240+ return ;
241+ } else {
242+ for (int k = 32 ; k >= 0 ; k -- ) {
243+ int b = (x >> k ) & 1 ;
244+
245+ if (b == 1 ) {
246+ leading_zero = 0 ;
247+ }
248+
249+ if (!leading_zero ) {
250+ printf ("%d" , b );
251+ }
252+ }
253+ }
254+
255+ puts ("\n" );
256+ }
0 commit comments