##// END OF EJS Templates
two fields added to the housekeeping parameters:...
paul -
r265:09ea64972ca9 R3a
parent child
Show More
@@ -1,57 +1,56
1 1 #ifndef FSW_SPACEWIRE_H_INCLUDED
2 2 #define FSW_SPACEWIRE_H_INCLUDED
3 3
4 4 #include <rtems.h>
5 5 #include <grspw.h>
6 6
7 7 #include <fcntl.h> // for O_RDWR
8 8 #include <unistd.h> // for the read call
9 9 #include <sys/ioctl.h> // for the ioctl call
10 10 #include <errno.h>
11 11
12 12 #include "fsw_params.h"
13 13 #include "tc_handler.h"
14 14 #include "fsw_init.h"
15 15
16 16 extern spw_stats grspw_stats;
17 extern spw_stats spw_backup;
18 17 extern rtems_name timecode_timer_name;
19 18 extern rtems_id timecode_timer_id;
20 19
21 20 // RTEMS TASK
22 21 rtems_task spiq_task( rtems_task_argument argument );
23 22 rtems_task recv_task( rtems_task_argument unused );
24 23 rtems_task send_task( rtems_task_argument argument );
25 24 rtems_task link_task( rtems_task_argument argument );
26 25
27 26 int spacewire_open_link( void );
28 27 int spacewire_start_link( int fd );
29 28 int spacewire_stop_and_start_link( int fd );
30 29 int spacewire_configure_link(int fd );
31 30 int spacewire_several_connect_attemps( void );
32 31 void spacewire_set_NP( unsigned char val, unsigned int regAddr ); // No Port force
33 32 void spacewire_set_RE( unsigned char val, unsigned int regAddr ); // RMAP Enable
34 33 void spacewire_read_statistics( void );
35 34 void update_hk_lfr_last_er_fields(unsigned int rid, unsigned char code);
36 35 void update_hk_with_grspw_stats(void );
37 36 void increase_unsigned_char_counter( unsigned char *counter );
38 37
39 38 void init_header_cwf( Header_TM_LFR_SCIENCE_CWF_t *header );
40 39 void init_header_swf( Header_TM_LFR_SCIENCE_SWF_t *header );
41 40 void init_header_asm( Header_TM_LFR_SCIENCE_ASM_t *header );
42 41 int spw_send_waveform_CWF( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_CWF_t *header );
43 42 int spw_send_waveform_SWF( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_SWF_t *header );
44 43 int spw_send_waveform_CWF3_light( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_CWF_t *header );
45 44 void spw_send_asm_f0( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header );
46 45 void spw_send_asm_f1( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header );
47 46 void spw_send_asm_f2( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header );
48 47 void spw_send_k_dump( ring_node *ring_node_to_send );
49 48
50 49 rtems_timer_service_routine timecode_timer_routine( rtems_id timer_id, void *user_data );
51 50 unsigned int check_timecode_and_previous_timecode_coherency(unsigned char currentTimecodeCtr);
52 51 unsigned int check_timecode_and_internal_time_coherency(unsigned char timecode, unsigned char internalTime);
53 52 void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc );
54 53
55 54 void (*grspw_timecode_callback) ( void *pDev, void *regs, int minor, unsigned int tc );
56 55
57 56 #endif // FSW_SPACEWIRE_H_INCLUDED
@@ -1,83 +1,80
1 1 /** Global variables of the LFR flight software.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * Among global variables, there are:
7 7 * - RTEMS names and id.
8 8 * - APB configuration registers.
9 9 * - waveforms global buffers, used by the waveform picker hardware module to store data.
10 10 * - spectral matrices buffesr, used by the hardware module to store data.
11 11 * - variable related to LFR modes parameters.
12 12 * - the global HK packet buffer.
13 13 * - the global dump parameter buffer.
14 14 *
15 15 */
16 16
17 17 #include <rtems.h>
18 18 #include <grspw.h>
19 19
20 20 #include "ccsds_types.h"
21 21 #include "grlib_regs.h"
22 22 #include "fsw_params.h"
23 23 #include "fsw_params_wf_handler.h"
24 24
25 25 // RTEMS GLOBAL VARIABLES
26 26 rtems_name misc_name[5];
27 27 rtems_name Task_name[20]; /* array of task names */
28 28 rtems_id Task_id[20]; /* array of task ids */
29 29 rtems_name timecode_timer_name;
30 30 rtems_id timecode_timer_id;
31 31 int fdSPW = 0;
32 32 int fdUART = 0;
33 33 unsigned char lfrCurrentMode;
34 34 unsigned char pa_bia_status_info;
35 35 unsigned char thisIsAnASMRestart = 0;
36 36
37 37 // WAVEFORMS GLOBAL VARIABLES // 2048 * 3 * 4 + 2 * 4 = 24576 + 8 bytes = 24584
38 38 // 97 * 256 = 24832 => delta = 248 bytes = 62 words
39 39 // WAVEFORMS GLOBAL VARIABLES // 2688 * 3 * 4 + 2 * 4 = 32256 + 8 bytes = 32264
40 40 // 127 * 256 = 32512 => delta = 248 bytes = 62 words
41 41 // F0 F1 F2 F3
42 42 volatile int wf_buffer_f0[ NB_RING_NODES_F0 * WFRM_BUFFER ] __attribute__((aligned(0x100)));
43 43 volatile int wf_buffer_f1[ NB_RING_NODES_F1 * WFRM_BUFFER ] __attribute__((aligned(0x100)));
44 44 volatile int wf_buffer_f2[ NB_RING_NODES_F2 * WFRM_BUFFER ] __attribute__((aligned(0x100)));
45 45 volatile int wf_buffer_f3[ NB_RING_NODES_F3 * WFRM_BUFFER ] __attribute__((aligned(0x100)));
46 46
47 47 //***********************************
48 48 // SPECTRAL MATRICES GLOBAL VARIABLES
49 49
50 50 // alignment constraints for the spectral matrices buffers => the first data after the time (8 bytes) shall be aligned on 0x00
51 51 volatile int sm_f0[ NB_RING_NODES_SM_F0 * TOTAL_SIZE_SM ] __attribute__((aligned(0x100)));
52 52 volatile int sm_f1[ NB_RING_NODES_SM_F1 * TOTAL_SIZE_SM ] __attribute__((aligned(0x100)));
53 53 volatile int sm_f2[ NB_RING_NODES_SM_F2 * TOTAL_SIZE_SM ] __attribute__((aligned(0x100)));
54 54
55 55 // APB CONFIGURATION REGISTERS
56 56 time_management_regs_t *time_management_regs = (time_management_regs_t*) REGS_ADDR_TIME_MANAGEMENT;
57 57 gptimer_regs_t *gptimer_regs = (gptimer_regs_t *) REGS_ADDR_GPTIMER;
58 58 waveform_picker_regs_0_1_18_t *waveform_picker_regs = (waveform_picker_regs_0_1_18_t*) REGS_ADDR_WAVEFORM_PICKER;
59 59 spectral_matrix_regs_t *spectral_matrix_regs = (spectral_matrix_regs_t*) REGS_ADDR_SPECTRAL_MATRIX;
60 60
61 61 // MODE PARAMETERS
62 62 Packet_TM_LFR_PARAMETER_DUMP_t parameter_dump_packet;
63 63 struct param_local_str param_local;
64 64 unsigned int lastValidEnterModeTime;
65 65
66 66 // HK PACKETS
67 67 Packet_TM_LFR_HK_t housekeeping_packet;
68 68 // message queues occupancy
69 69 unsigned char hk_lfr_q_sd_fifo_size_max;
70 70 unsigned char hk_lfr_q_rv_fifo_size_max;
71 71 unsigned char hk_lfr_q_p0_fifo_size_max;
72 72 unsigned char hk_lfr_q_p1_fifo_size_max;
73 73 unsigned char hk_lfr_q_p2_fifo_size_max;
74 74 // sequence counters are incremented by APID (PID + CAT) and destination ID
75 75 unsigned short sequenceCounters_SCIENCE_NORMAL_BURST;
76 76 unsigned short sequenceCounters_SCIENCE_SBM1_SBM2;
77 77 unsigned short sequenceCounters_TC_EXE[SEQ_CNT_NB_DEST_ID];
78 78 unsigned short sequenceCounters_TM_DUMP[SEQ_CNT_NB_DEST_ID];
79 79 unsigned short sequenceCounterHK;
80 80 spw_stats grspw_stats;
81 spw_stats spw_backup;
82
83
@@ -1,1569 +1,1580
1 1 /** Functions related to the SpaceWire interface.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * A group of functions to handle SpaceWire transmissions:
7 7 * - configuration of the SpaceWire link
8 8 * - SpaceWire related interruption requests processing
9 9 * - transmission of TeleMetry packets by a dedicated RTEMS task
10 10 * - reception of TeleCommands by a dedicated RTEMS task
11 11 *
12 12 */
13 13
14 14 #include "fsw_spacewire.h"
15 15
16 16 rtems_name semq_name;
17 17 rtems_id semq_id;
18 18
19 19 //*****************
20 20 // waveform headers
21 21 Header_TM_LFR_SCIENCE_CWF_t headerCWF;
22 22 Header_TM_LFR_SCIENCE_SWF_t headerSWF;
23 23 Header_TM_LFR_SCIENCE_ASM_t headerASM;
24 24
25 25 unsigned char previousTimecodeCtr = 0;
26 26 unsigned int *grspwPtr = (unsigned int *) (REGS_ADDR_GRSPW + APB_OFFSET_GRSPW_TIME_REGISTER);
27 27
28 28 //***********
29 29 // RTEMS TASK
30 30 rtems_task spiq_task(rtems_task_argument unused)
31 31 {
32 32 /** This RTEMS task is awaken by an rtems_event sent by the interruption subroutine of the SpaceWire driver.
33 33 *
34 34 * @param unused is the starting argument of the RTEMS task
35 35 *
36 36 */
37 37
38 38 rtems_event_set event_out;
39 39 rtems_status_code status;
40 40 int linkStatus;
41 41
42 42 BOOT_PRINTF("in SPIQ *** \n")
43 43
44 44 while(true){
45 45 rtems_event_receive(SPW_LINKERR_EVENT, RTEMS_WAIT, RTEMS_NO_TIMEOUT, &event_out); // wait for an SPW_LINKERR_EVENT
46 46 PRINTF("in SPIQ *** got SPW_LINKERR_EVENT\n")
47 47
48 48 // [0] SUSPEND RECV AND SEND TASKS
49 49 status = rtems_task_suspend( Task_id[ TASKID_RECV ] );
50 50 if ( status != RTEMS_SUCCESSFUL ) {
51 51 PRINTF("in SPIQ *** ERR suspending RECV Task\n")
52 52 }
53 53 status = rtems_task_suspend( Task_id[ TASKID_SEND ] );
54 54 if ( status != RTEMS_SUCCESSFUL ) {
55 55 PRINTF("in SPIQ *** ERR suspending SEND Task\n")
56 56 }
57 57
58 58 // [1] CHECK THE LINK
59 59 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status (1)
60 60 if ( linkStatus != 5) {
61 61 PRINTF1("in SPIQ *** linkStatus %d, wait...\n", linkStatus)
62 62 status = rtems_task_wake_after( SY_LFR_DPU_CONNECT_TIMEOUT ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 1000 ms
63 63 }
64 64
65 65 // [2] RECHECK THE LINK AFTER SY_LFR_DPU_CONNECT_TIMEOUT
66 66 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status (2)
67 67 if ( linkStatus != 5 ) // [2.a] not in run state, reset the link
68 68 {
69 69 spacewire_read_statistics();
70 70 status = spacewire_several_connect_attemps( );
71 71 }
72 72 else // [2.b] in run state, start the link
73 73 {
74 74 status = spacewire_stop_and_start_link( fdSPW ); // start the link
75 75 if ( status != RTEMS_SUCCESSFUL)
76 76 {
77 77 PRINTF1("in SPIQ *** ERR spacewire_stop_and_start_link %d\n", status)
78 78 }
79 79 }
80 80
81 81 // [3] COMPLETE RECOVERY ACTION AFTER SY_LFR_DPU_CONNECT_ATTEMPTS
82 82 if ( status == RTEMS_SUCCESSFUL ) // [3.a] the link is in run state and has been started successfully
83 83 {
84 84 status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
85 85 if ( status != RTEMS_SUCCESSFUL ) {
86 86 PRINTF("in SPIQ *** ERR resuming SEND Task\n")
87 87 }
88 88 status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
89 89 if ( status != RTEMS_SUCCESSFUL ) {
90 90 PRINTF("in SPIQ *** ERR resuming RECV Task\n")
91 91 }
92 92 }
93 93 else // [3.b] the link is not in run state, go in STANDBY mode
94 94 {
95 95 status = enter_mode_standby();
96 96 if ( status != RTEMS_SUCCESSFUL )
97 97 {
98 98 PRINTF1("in SPIQ *** ERR enter_standby_mode *** code %d\n", status)
99 99 }
100 100 {
101 101 updateLFRCurrentMode( LFR_MODE_STANDBY );
102 102 }
103 103 // wake the LINK task up to wait for the link recovery
104 104 status = rtems_event_send ( Task_id[TASKID_LINK], RTEMS_EVENT_0 );
105 105 status = rtems_task_suspend( RTEMS_SELF );
106 106 }
107 107 }
108 108 }
109 109
110 110 rtems_task recv_task( rtems_task_argument unused )
111 111 {
112 112 /** This RTEMS task is dedicated to the reception of incoming TeleCommands.
113 113 *
114 114 * @param unused is the starting argument of the RTEMS task
115 115 *
116 116 * The RECV task blocks on a call to the read system call, waiting for incoming SpaceWire data. When unblocked:
117 117 * 1. It reads the incoming data.
118 118 * 2. Launches the acceptance procedure.
119 119 * 3. If the Telecommand is valid, sends it to a dedicated RTEMS message queue.
120 120 *
121 121 */
122 122
123 123 int len;
124 124 ccsdsTelecommandPacket_t currentTC;
125 125 unsigned char computed_CRC[ 2 ];
126 126 unsigned char currentTC_LEN_RCV[ 2 ];
127 127 unsigned char destinationID;
128 128 unsigned int estimatedPacketLength;
129 129 unsigned int parserCode;
130 130 rtems_status_code status;
131 131 rtems_id queue_recv_id;
132 132 rtems_id queue_send_id;
133 133
134 134 initLookUpTableForCRC(); // the table is used to compute Cyclic Redundancy Codes
135 135
136 136 status = get_message_queue_id_recv( &queue_recv_id );
137 137 if (status != RTEMS_SUCCESSFUL)
138 138 {
139 139 PRINTF1("in RECV *** ERR get_message_queue_id_recv %d\n", status)
140 140 }
141 141
142 142 status = get_message_queue_id_send( &queue_send_id );
143 143 if (status != RTEMS_SUCCESSFUL)
144 144 {
145 145 PRINTF1("in RECV *** ERR get_message_queue_id_send %d\n", status)
146 146 }
147 147
148 148 BOOT_PRINTF("in RECV *** \n")
149 149
150 150 while(1)
151 151 {
152 152 len = read( fdSPW, (char*) &currentTC, CCSDS_TC_PKT_MAX_SIZE ); // the call to read is blocking
153 153 if (len == -1){ // error during the read call
154 154 PRINTF1("in RECV *** last read call returned -1, ERRNO %d\n", errno)
155 155 }
156 156 else {
157 157 if ( (len+1) < CCSDS_TC_PKT_MIN_SIZE ) {
158 158 PRINTF("in RECV *** packet lenght too short\n")
159 159 }
160 160 else {
161 161 estimatedPacketLength = (unsigned int) (len - CCSDS_TC_TM_PACKET_OFFSET - 3); // => -3 is for Prot ID, Reserved and User App bytes
162 162 currentTC_LEN_RCV[ 0 ] = (unsigned char) (estimatedPacketLength >> 8);
163 163 currentTC_LEN_RCV[ 1 ] = (unsigned char) (estimatedPacketLength );
164 164 // CHECK THE TC
165 165 parserCode = tc_parser( &currentTC, estimatedPacketLength, computed_CRC ) ;
166 166 if ( (parserCode == ILLEGAL_APID) || (parserCode == WRONG_LEN_PKT)
167 167 || (parserCode == INCOR_CHECKSUM) || (parserCode == ILL_TYPE)
168 168 || (parserCode == ILL_SUBTYPE) || (parserCode == WRONG_APP_DATA)
169 169 || (parserCode == WRONG_SRC_ID) )
170 170 { // send TM_LFR_TC_EXE_CORRUPTED
171 171 PRINTF1("TC corrupted received, with code: %d\n", parserCode)
172 172 if ( !( (currentTC.serviceType==TC_TYPE_TIME) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_TIME) )
173 173 &&
174 174 !( (currentTC.serviceType==TC_TYPE_GEN) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_INFO))
175 175 )
176 176 {
177 177 if ( parserCode == WRONG_SRC_ID )
178 178 {
179 179 destinationID = SID_TC_GROUND;
180 180 }
181 181 else
182 182 {
183 183 destinationID = currentTC.sourceID;
184 184 }
185 185 send_tm_lfr_tc_exe_corrupted( &currentTC, queue_send_id,
186 186 computed_CRC, currentTC_LEN_RCV,
187 187 destinationID );
188 188 }
189 189 }
190 190 else
191 191 { // send valid TC to the action launcher
192 192 status = rtems_message_queue_send( queue_recv_id, &currentTC,
193 193 estimatedPacketLength + CCSDS_TC_TM_PACKET_OFFSET + 3);
194 194 }
195 195 }
196 196 }
197 197
198 198 update_queue_max_count( queue_recv_id, &hk_lfr_q_rv_fifo_size_max );
199 199
200 200 }
201 201 }
202 202
203 203 rtems_task send_task( rtems_task_argument argument)
204 204 {
205 205 /** This RTEMS task is dedicated to the transmission of TeleMetry packets.
206 206 *
207 207 * @param unused is the starting argument of the RTEMS task
208 208 *
209 209 * The SEND task waits for a message to become available in the dedicated RTEMS queue. When a message arrives:
210 210 * - if the first byte is equal to CCSDS_DESTINATION_ID, the message is sent as is using the write system call.
211 211 * - if the first byte is not equal to CCSDS_DESTINATION_ID, the message is handled as a spw_ioctl_pkt_send. After
212 212 * analyzis, the packet is sent either using the write system call or using the ioctl call SPACEWIRE_IOCTRL_SEND, depending on the
213 213 * data it contains.
214 214 *
215 215 */
216 216
217 217 rtems_status_code status; // RTEMS status code
218 218 char incomingData[MSG_QUEUE_SIZE_SEND]; // incoming data buffer
219 219 ring_node *incomingRingNodePtr;
220 220 int ring_node_address;
221 221 char *charPtr;
222 222 spw_ioctl_pkt_send *spw_ioctl_send;
223 223 size_t size; // size of the incoming TC packet
224 224 rtems_id queue_send_id;
225 225 unsigned int sid;
226 226 unsigned char sidAsUnsignedChar;
227 227 unsigned char type;
228 228
229 229 incomingRingNodePtr = NULL;
230 230 ring_node_address = 0;
231 231 charPtr = (char *) &ring_node_address;
232 232 sid = 0;
233 233 sidAsUnsignedChar = 0;
234 234
235 235 init_header_cwf( &headerCWF );
236 236 init_header_swf( &headerSWF );
237 237 init_header_asm( &headerASM );
238 238
239 239 status = get_message_queue_id_send( &queue_send_id );
240 240 if (status != RTEMS_SUCCESSFUL)
241 241 {
242 242 PRINTF1("in HOUS *** ERR get_message_queue_id_send %d\n", status)
243 243 }
244 244
245 245 BOOT_PRINTF("in SEND *** \n")
246 246
247 247 while(1)
248 248 {
249 249 status = rtems_message_queue_receive( queue_send_id, incomingData, &size,
250 250 RTEMS_WAIT, RTEMS_NO_TIMEOUT );
251 251
252 252 if (status!=RTEMS_SUCCESSFUL)
253 253 {
254 254 PRINTF1("in SEND *** (1) ERR = %d\n", status)
255 255 }
256 256 else
257 257 {
258 258 if ( size == sizeof(ring_node*) )
259 259 {
260 260 charPtr[0] = incomingData[0];
261 261 charPtr[1] = incomingData[1];
262 262 charPtr[2] = incomingData[2];
263 263 charPtr[3] = incomingData[3];
264 264 incomingRingNodePtr = (ring_node*) ring_node_address;
265 265 sid = incomingRingNodePtr->sid;
266 266 if ( (sid==SID_NORM_CWF_LONG_F3)
267 267 || (sid==SID_BURST_CWF_F2 )
268 268 || (sid==SID_SBM1_CWF_F1 )
269 269 || (sid==SID_SBM2_CWF_F2 ))
270 270 {
271 271 spw_send_waveform_CWF( incomingRingNodePtr, &headerCWF );
272 272 }
273 273 else if ( (sid==SID_NORM_SWF_F0) || (sid== SID_NORM_SWF_F1) || (sid==SID_NORM_SWF_F2) )
274 274 {
275 275 spw_send_waveform_SWF( incomingRingNodePtr, &headerSWF );
276 276 }
277 277 else if ( (sid==SID_NORM_CWF_F3) )
278 278 {
279 279 spw_send_waveform_CWF3_light( incomingRingNodePtr, &headerCWF );
280 280 }
281 281 else if (sid==SID_NORM_ASM_F0)
282 282 {
283 283 spw_send_asm_f0( incomingRingNodePtr, &headerASM );
284 284 }
285 285 else if (sid==SID_NORM_ASM_F1)
286 286 {
287 287 spw_send_asm_f1( incomingRingNodePtr, &headerASM );
288 288 }
289 289 else if (sid==SID_NORM_ASM_F2)
290 290 {
291 291 spw_send_asm_f2( incomingRingNodePtr, &headerASM );
292 292 }
293 293 else if ( sid==TM_CODE_K_DUMP )
294 294 {
295 295 spw_send_k_dump( incomingRingNodePtr );
296 296 }
297 297 else
298 298 {
299 299 PRINTF1("unexpected sid = %d\n", sid);
300 300 }
301 301 }
302 302 else if ( incomingData[0] == CCSDS_DESTINATION_ID ) // the incoming message is a ccsds packet
303 303 {
304 304 sidAsUnsignedChar = (unsigned char) incomingData[ PACKET_POS_PA_LFR_SID_PKT ];
305 305 sid = sidAsUnsignedChar;
306 306 type = (unsigned char) incomingData[ PACKET_POS_SERVICE_TYPE ];
307 307 if (type == TM_TYPE_LFR_SCIENCE) // this is a BP packet, all other types are handled differently
308 308 // SET THE SEQUENCE_CNT PARAMETER IN CASE OF BP0 OR BP1 PACKETS
309 309 {
310 310 increment_seq_counter_source_id( (unsigned char*) &incomingData[ PACKET_POS_SEQUENCE_CNT ], sid );
311 311 }
312 312
313 313 status = write( fdSPW, incomingData, size );
314 314 if (status == -1){
315 315 PRINTF2("in SEND *** (2.a) ERRNO = %d, size = %d\n", errno, size)
316 316 }
317 317 }
318 318 else // the incoming message is a spw_ioctl_pkt_send structure
319 319 {
320 320 spw_ioctl_send = (spw_ioctl_pkt_send*) incomingData;
321 321 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, spw_ioctl_send );
322 322 if (status == -1){
323 323 PRINTF2("in SEND *** (2.b) ERRNO = %d, RTEMS = %d\n", errno, status)
324 324 }
325 325 }
326 326 }
327 327
328 328 update_queue_max_count( queue_send_id, &hk_lfr_q_sd_fifo_size_max );
329 329
330 330 }
331 331 }
332 332
333 333 rtems_task link_task( rtems_task_argument argument )
334 334 {
335 335 rtems_event_set event_out;
336 336 rtems_status_code status;
337 337 int linkStatus;
338 338
339 339 BOOT_PRINTF("in LINK ***\n")
340 340
341 341 while(1)
342 342 {
343 343 // wait for an RTEMS_EVENT
344 344 rtems_event_receive( RTEMS_EVENT_0,
345 345 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
346 346 PRINTF("in LINK *** wait for the link\n")
347 347 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
348 348 while( linkStatus != 5) // wait for the link
349 349 {
350 350 status = rtems_task_wake_after( 10 ); // monitor the link each 100ms
351 351 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
352 352 watchdog_reload();
353 353 }
354 354
355 355 spacewire_read_statistics();
356 356 status = spacewire_stop_and_start_link( fdSPW );
357 357
358 358 if (status != RTEMS_SUCCESSFUL)
359 359 {
360 360 PRINTF1("in LINK *** ERR link not started %d\n", status)
361 361 }
362 362 else
363 363 {
364 364 PRINTF("in LINK *** OK link started\n")
365 365 }
366 366
367 367 // restart the SPIQ task
368 368 status = rtems_task_restart( Task_id[TASKID_SPIQ], 1 );
369 369 if ( status != RTEMS_SUCCESSFUL ) {
370 370 PRINTF("in SPIQ *** ERR restarting SPIQ Task\n")
371 371 }
372 372
373 373 // restart RECV and SEND
374 374 status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
375 375 if ( status != RTEMS_SUCCESSFUL ) {
376 376 PRINTF("in SPIQ *** ERR restarting SEND Task\n")
377 377 }
378 378 status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
379 379 if ( status != RTEMS_SUCCESSFUL ) {
380 380 PRINTF("in SPIQ *** ERR restarting RECV Task\n")
381 381 }
382 382 }
383 383 }
384 384
385 385 //****************
386 386 // OTHER FUNCTIONS
387 387 int spacewire_open_link( void ) // by default, the driver resets the core: [SPW_CTRL_WRITE(pDev, SPW_CTRL_RESET);]
388 388 {
389 389 /** This function opens the SpaceWire link.
390 390 *
391 391 * @return a valid file descriptor in case of success, -1 in case of a failure
392 392 *
393 393 */
394 394 rtems_status_code status;
395 395
396 396 fdSPW = open(GRSPW_DEVICE_NAME, O_RDWR); // open the device. the open call resets the hardware
397 397 if ( fdSPW < 0 ) {
398 398 PRINTF1("ERR *** in configure_spw_link *** error opening "GRSPW_DEVICE_NAME" with ERR %d\n", errno)
399 399 }
400 400 else
401 401 {
402 402 status = RTEMS_SUCCESSFUL;
403 403 }
404 404
405 405 return status;
406 406 }
407 407
408 408 int spacewire_start_link( int fd )
409 409 {
410 410 rtems_status_code status;
411 411
412 412 status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
413 413 // -1 default hardcoded driver timeout
414 414
415 415 return status;
416 416 }
417 417
418 418 int spacewire_stop_and_start_link( int fd )
419 419 {
420 420 rtems_status_code status;
421 421
422 422 status = ioctl( fd, SPACEWIRE_IOCTRL_STOP); // start fails if link pDev->running != 0
423 423 status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
424 424 // -1 default hardcoded driver timeout
425 425
426 426 return status;
427 427 }
428 428
429 429 int spacewire_configure_link( int fd )
430 430 {
431 431 /** This function configures the SpaceWire link.
432 432 *
433 433 * @return GR-RTEMS-DRIVER directive status codes:
434 434 * - 22 EINVAL - Null pointer or an out of range value was given as the argument.
435 435 * - 16 EBUSY - Only used for SEND. Returned when no descriptors are avialble in non-blocking mode.
436 436 * - 88 ENOSYS - Returned for SET_DESTKEY if RMAP command handler is not available or if a non-implemented call is used.
437 437 * - 116 ETIMEDOUT - REturned for SET_PACKET_SIZE and START if the link could not be brought up.
438 438 * - 12 ENOMEM - Returned for SET_PACKETSIZE if it was unable to allocate the new buffers.
439 439 * - 5 EIO - Error when writing to grswp hardware registers.
440 440 * - 2 ENOENT - No such file or directory
441 441 */
442 442
443 443 rtems_status_code status;
444 444
445 445 spacewire_set_NP(1, REGS_ADDR_GRSPW); // [N]o [P]ort force
446 446 spacewire_set_RE(1, REGS_ADDR_GRSPW); // [R]MAP [E]nable, the dedicated call seems to break the no port force configuration
447 447
448 448 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_RXBLOCK, 1); // sets the blocking mode for reception
449 449 if (status!=RTEMS_SUCCESSFUL) {
450 450 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_RXBLOCK\n")
451 451 }
452 452 //
453 453 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_EVENT_ID, Task_id[TASKID_SPIQ]); // sets the task ID to which an event is sent when a
454 454 if (status!=RTEMS_SUCCESSFUL) {
455 455 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_EVENT_ID\n") // link-error interrupt occurs
456 456 }
457 457 //
458 458 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_DISABLE_ERR, 0); // automatic link-disabling due to link-error interrupts
459 459 if (status!=RTEMS_SUCCESSFUL) {
460 460 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_DISABLE_ERR\n")
461 461 }
462 462 //
463 463 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ, 1); // sets the link-error interrupt bit
464 464 if (status!=RTEMS_SUCCESSFUL) {
465 465 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ\n")
466 466 }
467 467 //
468 468 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK, 1); // transmission blocks
469 469 if (status!=RTEMS_SUCCESSFUL) {
470 470 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK\n")
471 471 }
472 472 //
473 473 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL, 1); // transmission blocks when no transmission descriptor is available
474 474 if (status!=RTEMS_SUCCESSFUL) {
475 475 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL\n")
476 476 }
477 477 //
478 478 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TCODE_CTRL, 0x0909); // [Time Rx : Time Tx : Link error : Tick-out IRQ]
479 479 if (status!=RTEMS_SUCCESSFUL) {
480 480 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TCODE_CTRL,\n")
481 481 }
482 482
483 483 return status;
484 484 }
485 485
486 486 int spacewire_several_connect_attemps( void )
487 487 {
488 488 /** This function is executed by the SPIQ rtems_task wehn it has been awaken by an interruption raised by the SpaceWire driver.
489 489 *
490 490 * @return RTEMS directive status code:
491 491 * - RTEMS_UNSATISFIED is returned is the link is not in the running state after 10 s.
492 492 * - RTEMS_SUCCESSFUL is returned if the link is up before the timeout.
493 493 *
494 494 */
495 495
496 496 rtems_status_code status_spw;
497 497 rtems_status_code status;
498 498 int i;
499 499
500 500 for ( i=0; i<SY_LFR_DPU_CONNECT_ATTEMPT; i++ )
501 501 {
502 502 PRINTF1("in spacewire_reset_link *** link recovery, try %d\n", i);
503 503
504 504 // CLOSING THE DRIVER AT THIS POINT WILL MAKE THE SEND TASK BLOCK THE SYSTEM
505 505
506 506 status = rtems_task_wake_after( SY_LFR_DPU_CONNECT_TIMEOUT ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 1000 ms
507 507
508 508 status_spw = spacewire_stop_and_start_link( fdSPW );
509 509
510 510 if ( status_spw != RTEMS_SUCCESSFUL )
511 511 {
512 512 PRINTF1("in spacewire_reset_link *** ERR spacewire_start_link code %d\n", status_spw)
513 513 }
514 514
515 515 if ( status_spw == RTEMS_SUCCESSFUL)
516 516 {
517 517 break;
518 518 }
519 519 }
520 520
521 521 return status_spw;
522 522 }
523 523
524 524 void spacewire_set_NP( unsigned char val, unsigned int regAddr ) // [N]o [P]ort force
525 525 {
526 526 /** This function sets the [N]o [P]ort force bit of the GRSPW control register.
527 527 *
528 528 * @param val is the value, 0 or 1, used to set the value of the NP bit.
529 529 * @param regAddr is the address of the GRSPW control register.
530 530 *
531 531 * NP is the bit 20 of the GRSPW control register.
532 532 *
533 533 */
534 534
535 535 unsigned int *spwptr = (unsigned int*) regAddr;
536 536
537 537 if (val == 1) {
538 538 *spwptr = *spwptr | 0x00100000; // [NP] set the No port force bit
539 539 }
540 540 if (val== 0) {
541 541 *spwptr = *spwptr & 0xffdfffff;
542 542 }
543 543 }
544 544
545 545 void spacewire_set_RE( unsigned char val, unsigned int regAddr ) // [R]MAP [E]nable
546 546 {
547 547 /** This function sets the [R]MAP [E]nable bit of the GRSPW control register.
548 548 *
549 549 * @param val is the value, 0 or 1, used to set the value of the RE bit.
550 550 * @param regAddr is the address of the GRSPW control register.
551 551 *
552 552 * RE is the bit 16 of the GRSPW control register.
553 553 *
554 554 */
555 555
556 556 unsigned int *spwptr = (unsigned int*) regAddr;
557 557
558 558 if (val == 1)
559 559 {
560 560 *spwptr = *spwptr | 0x00010000; // [RE] set the RMAP Enable bit
561 561 }
562 562 if (val== 0)
563 563 {
564 564 *spwptr = *spwptr & 0xfffdffff;
565 565 }
566 566 }
567 567
568 568 void spacewire_read_statistics( void )
569 569 {
570 /** This function reads the SpaceWire statistics from the grspw RTEMS driver.
571 *
572 * @param void
573 *
574 * @return void
575 *
576 * Once they are read, the counters are stored in a global variable used during the building of the
577 * HK packets.
578 *
579 */
580
570 581 rtems_status_code status;
571 582 spw_stats current;
572 583
573 584 // read the current statistics
574 585 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &current );
575 586
576 587 // clear the counters
577 588 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_CLR_STATISTICS );
578 589
579 590 // typedef struct {
580 591 // unsigned int tx_link_err; // NOT IN HK
581 592 // unsigned int rx_rmap_header_crc_err; // NOT IN HK
582 593 // unsigned int rx_rmap_data_crc_err; // NOT IN HK
583 594 // unsigned int rx_eep_err;
584 595 // unsigned int rx_truncated;
585 596 // unsigned int parity_err;
586 597 // unsigned int escape_err;
587 598 // unsigned int credit_err;
588 599 // unsigned int write_sync_err;
589 600 // unsigned int disconnect_err;
590 601 // unsigned int early_ep;
591 602 // unsigned int invalid_address;
592 603 // unsigned int packets_sent;
593 604 // unsigned int packets_received;
594 605 // } spw_stats;
595 606
596 607 // rx_eep_err
597 608 grspw_stats.rx_eep_err = grspw_stats.rx_eep_err + current.rx_eep_err;
598 609 // rx_truncated
599 610 grspw_stats.rx_truncated = grspw_stats.rx_truncated + current.rx_truncated;
600 611 // parity_err
601 612 grspw_stats.parity_err = grspw_stats.parity_err + current.parity_err;
602 613 // escape_err
603 614 grspw_stats.escape_err = grspw_stats.escape_err + current.escape_err;
604 615 // credit_err
605 616 grspw_stats.credit_err = grspw_stats.credit_err + current.credit_err;
606 617 // write_sync_err
607 618 grspw_stats.write_sync_err = grspw_stats.write_sync_err + current.write_sync_err;
608 619 // disconnect_err
609 620 grspw_stats.disconnect_err = grspw_stats.disconnect_err + current.disconnect_err;
610 621 // early_ep
611 622 grspw_stats.early_ep = grspw_stats.early_ep + current.early_ep;
612 623 // invalid_address
613 624 grspw_stats.invalid_address = grspw_stats.invalid_address + current.invalid_address;
614 625 // packets_sent
615 626 grspw_stats.packets_sent = grspw_stats.packets_sent + current.packets_sent;
616 627 // packets_received
617 628 grspw_stats.packets_received= grspw_stats.packets_received + current.packets_received;
618 629
619 630 }
620 631
621 632 void spacewire_get_last_error( void )
622 633 {
623 634 static spw_stats previous;
624 635 spw_stats current;
625 636 rtems_status_code status;
626 637
627 638 unsigned int hk_lfr_last_er_rid;
628 639 unsigned char hk_lfr_last_er_code;
629 640 int coarseTime;
630 641 int fineTime;
631 642 unsigned char update_hk_lfr_last_er;
632 643
633 644 update_hk_lfr_last_er = 0;
634 645
635 646 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &current );
636 647
637 648 // get current time
638 649 coarseTime = time_management_regs->coarse_time;
639 650 fineTime = time_management_regs->fine_time;
640 651
641 652 // typedef struct {
642 653 // unsigned int tx_link_err; // NOT IN HK
643 654 // unsigned int rx_rmap_header_crc_err; // NOT IN HK
644 655 // unsigned int rx_rmap_data_crc_err; // NOT IN HK
645 656 // unsigned int rx_eep_err;
646 657 // unsigned int rx_truncated;
647 658 // unsigned int parity_err;
648 659 // unsigned int escape_err;
649 660 // unsigned int credit_err;
650 661 // unsigned int write_sync_err;
651 662 // unsigned int disconnect_err;
652 663 // unsigned int early_ep;
653 664 // unsigned int invalid_address;
654 665 // unsigned int packets_sent;
655 666 // unsigned int packets_received;
656 667 // } spw_stats;
657 668
658 669 // tx_link_err *** no code associated to this field
659 670 // rx_rmap_header_crc_err *** LE *** in HK
660 671 if (previous.rx_rmap_header_crc_err != current.rx_rmap_header_crc_err)
661 672 {
662 673 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
663 674 hk_lfr_last_er_code = CODE_HEADER_CRC;
664 675 update_hk_lfr_last_er = 1;
665 676 }
666 677 // rx_rmap_data_crc_err *** LE *** NOT IN HK
667 678 if (previous.rx_rmap_data_crc_err != current.rx_rmap_data_crc_err)
668 679 {
669 680 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
670 681 hk_lfr_last_er_code = CODE_DATA_CRC;
671 682 update_hk_lfr_last_er = 1;
672 683 }
673 684 // rx_eep_err
674 685 if (previous.rx_eep_err != current.rx_eep_err)
675 686 {
676 687 hk_lfr_last_er_rid = RID_ME_LFR_DPU_SPW;
677 688 hk_lfr_last_er_code = CODE_EEP;
678 689 update_hk_lfr_last_er = 1;
679 690 }
680 691 // rx_truncated
681 692 if (previous.rx_truncated != current.rx_truncated)
682 693 {
683 694 hk_lfr_last_er_rid = RID_ME_LFR_DPU_SPW;
684 695 hk_lfr_last_er_code = CODE_RX_TOO_BIG;
685 696 update_hk_lfr_last_er = 1;
686 697 }
687 698 // parity_err
688 699 if (previous.parity_err != current.parity_err)
689 700 {
690 701 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
691 702 hk_lfr_last_er_code = CODE_PARITY;
692 703 update_hk_lfr_last_er = 1;
693 704 }
694 705 // escape_err
695 706 if (previous.parity_err != current.parity_err)
696 707 {
697 708 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
698 709 hk_lfr_last_er_code = CODE_ESCAPE;
699 710 update_hk_lfr_last_er = 1;
700 711 }
701 712 // credit_err
702 713 if (previous.credit_err != current.credit_err)
703 714 {
704 715 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
705 716 hk_lfr_last_er_code = CODE_CREDIT;
706 717 update_hk_lfr_last_er = 1;
707 718 }
708 719 // write_sync_err
709 720 if (previous.write_sync_err != current.write_sync_err)
710 721 {
711 722 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
712 723 hk_lfr_last_er_code = CODE_WRITE_SYNC;
713 724 update_hk_lfr_last_er = 1;
714 725 }
715 726 // disconnect_err
716 727 if (previous.disconnect_err != current.disconnect_err)
717 728 {
718 729 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
719 730 hk_lfr_last_er_code = CODE_DISCONNECT;
720 731 update_hk_lfr_last_er = 1;
721 732 }
722 733 // early_ep
723 734 if (previous.early_ep != current.early_ep)
724 735 {
725 736 hk_lfr_last_er_rid = RID_ME_LFR_DPU_SPW;
726 737 hk_lfr_last_er_code = CODE_EARLY_EOP_EEP;
727 738 update_hk_lfr_last_er = 1;
728 739 }
729 740 // invalid_address
730 741 if (previous.invalid_address != current.invalid_address)
731 742 {
732 743 hk_lfr_last_er_rid = RID_ME_LFR_DPU_SPW;
733 744 hk_lfr_last_er_code = CODE_INVALID_ADDRESS;
734 745 update_hk_lfr_last_er = 1;
735 746 }
736 747
737 748 // if a field has changed, update the hk_last_er fields
738 749 if (update_hk_lfr_last_er == 1)
739 750 {
740 751 update_hk_lfr_last_er_fields( hk_lfr_last_er_rid, hk_lfr_last_er_code );
741 752 }
742 753
743 754 previous = current;
744 755 }
745 756
746 757 void update_hk_lfr_last_er_fields(unsigned int rid, unsigned char code)
747 758 {
748 759 unsigned char *coarseTimePtr;
749 760 unsigned char *fineTimePtr;
750 761
751 762 coarseTimePtr = (unsigned char*) &time_management_regs->coarse_time;
752 763 fineTimePtr = (unsigned char*) &time_management_regs->fine_time;
753 764
754 765 housekeeping_packet.hk_lfr_last_er_rid[0] = (unsigned char) ((rid & 0xff00) >> 8 );
755 766 housekeeping_packet.hk_lfr_last_er_rid[1] = (unsigned char) (rid & 0x00ff);
756 767 housekeeping_packet.hk_lfr_last_er_code = code;
757 768 housekeeping_packet.hk_lfr_last_er_time[0] = coarseTimePtr[0];
758 769 housekeeping_packet.hk_lfr_last_er_time[1] = coarseTimePtr[1];
759 770 housekeeping_packet.hk_lfr_last_er_time[2] = coarseTimePtr[2];
760 771 housekeeping_packet.hk_lfr_last_er_time[3] = coarseTimePtr[3];
761 772 housekeeping_packet.hk_lfr_last_er_time[4] = fineTimePtr[2];
762 773 housekeeping_packet.hk_lfr_last_er_time[5] = fineTimePtr[3];
763 774 }
764 775
765 776 void update_hk_with_grspw_stats( void )
766 777 {
767 778 //****************************
768 779 // DPU_SPACEWIRE_IF_STATISTICS
769 780 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[0] = (unsigned char) (grspw_stats.packets_received >> 8);
770 781 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[1] = (unsigned char) (grspw_stats.packets_received);
771 782 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[0] = (unsigned char) (grspw_stats.packets_sent >> 8);
772 783 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[1] = (unsigned char) (grspw_stats.packets_sent);
773 784
774 785 //******************************************
775 786 // ERROR COUNTERS / SPACEWIRE / LOW SEVERITY
776 787 housekeeping_packet.hk_lfr_dpu_spw_parity = (unsigned char) grspw_stats.parity_err;
777 788 housekeeping_packet.hk_lfr_dpu_spw_disconnect = (unsigned char) grspw_stats.disconnect_err;
778 789 housekeeping_packet.hk_lfr_dpu_spw_escape = (unsigned char) grspw_stats.escape_err;
779 790 housekeeping_packet.hk_lfr_dpu_spw_credit = (unsigned char) grspw_stats.credit_err;
780 791 housekeeping_packet.hk_lfr_dpu_spw_write_sync = (unsigned char) grspw_stats.write_sync_err;
781 792
782 793 //*********************************************
783 794 // ERROR COUNTERS / SPACEWIRE / MEDIUM SEVERITY
784 795 housekeeping_packet.hk_lfr_dpu_spw_early_eop = (unsigned char) grspw_stats.early_ep;
785 796 housekeeping_packet.hk_lfr_dpu_spw_invalid_addr = (unsigned char) grspw_stats.invalid_address;
786 797 housekeeping_packet.hk_lfr_dpu_spw_eep = (unsigned char) grspw_stats.rx_eep_err;
787 798 housekeeping_packet.hk_lfr_dpu_spw_rx_too_big = (unsigned char) grspw_stats.rx_truncated;
788 799 }
789 800
790 801 void increase_unsigned_char_counter( unsigned char *counter )
791 802 {
792 803 // update the number of valid timecodes that have been received
793 804 if (*counter == 255)
794 805 {
795 806 *counter = 0;
796 807 }
797 808 else
798 809 {
799 810 *counter = *counter + 1;
800 811 }
801 812 }
802 813
803 814 rtems_timer_service_routine timecode_timer_routine( rtems_id timer_id, void *user_data )
804 815 {
805 816 static unsigned char initStep = 1;
806 817
807 818 unsigned char currentTimecodeCtr;
808 819
809 820 currentTimecodeCtr = (unsigned char) (grspwPtr[0] & TIMECODE_MASK);
810 821
811 822 if (initStep == 1)
812 823 {
813 824 if (currentTimecodeCtr == previousTimecodeCtr)
814 825 {
815 826 //************************
816 827 // HK_LFR_TIMECODE_MISSING
817 828 // the timecode value has not changed, no valid timecode has been received, the timecode is MISSING
818 829 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_missing );
819 830 update_hk_lfr_last_er_fields( RID_LE_LFR_TIMEC, CODE_MISSING );
820 831 }
821 832 else if (currentTimecodeCtr == (previousTimecodeCtr+1))
822 833 {
823 834 // the timecode value has changed and the value is valid, this is unexpected because
824 835 // the timer should not have fired, the timecode_irq_handler should have been raised
825 836 }
826 837 else
827 838 {
828 839 //************************
829 840 // HK_LFR_TIMECODE_INVALID
830 841 // the timecode value has changed and the value is not valid, no tickout has been generated
831 842 // this is why the timer has fired
832 843 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_invalid );
833 844 update_hk_lfr_last_er_fields( RID_LE_LFR_TIMEC, CODE_INVALID );
834 845 }
835 846 }
836 847 else
837 848 {
838 849 initStep = 1;
839 850 //************************
840 851 // HK_LFR_TIMECODE_MISSING
841 852 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_missing );
842 853 update_hk_lfr_last_er_fields( RID_LE_LFR_TIMEC, CODE_MISSING );
843 854 }
844 855
845 856 rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_13 );
846 857 }
847 858
848 859 unsigned int check_timecode_and_previous_timecode_coherency(unsigned char currentTimecodeCtr)
849 860 {
850 861 /** This function checks the coherency between the incoming timecode and the last valid timecode.
851 862 *
852 863 * @param currentTimecodeCtr is the incoming timecode
853 864 *
854 865 * @return returned codes::
855 866 * - LFR_DEFAULT
856 867 * - LFR_SUCCESSFUL
857 868 *
858 869 */
859 870
860 871 static unsigned char firstTickout = 1;
861 872 unsigned char ret;
862 873
863 874 ret = LFR_DEFAULT;
864 875
865 876 if (firstTickout == 0)
866 877 {
867 878 if (currentTimecodeCtr == 0)
868 879 {
869 880 if (previousTimecodeCtr == 63)
870 881 {
871 882 ret = LFR_SUCCESSFUL;
872 883 }
873 884 else
874 885 {
875 886 ret = LFR_DEFAULT;
876 887 }
877 888 }
878 889 else
879 890 {
880 891 if (currentTimecodeCtr == (previousTimecodeCtr +1))
881 892 {
882 893 ret = LFR_SUCCESSFUL;
883 894 }
884 895 else
885 896 {
886 897 ret = LFR_DEFAULT;
887 898 }
888 899 }
889 900 }
890 901 else
891 902 {
892 903 firstTickout = 0;
893 904 ret = LFR_SUCCESSFUL;
894 905 }
895 906
896 907 return ret;
897 908 }
898 909
899 910 unsigned int check_timecode_and_internal_time_coherency(unsigned char timecode, unsigned char internalTime)
900 911 {
901 912 unsigned int ret;
902 913
903 914 ret = LFR_DEFAULT;
904 915
905 916 if (timecode == internalTime)
906 917 {
907 918 ret = LFR_SUCCESSFUL;
908 919 }
909 920 else
910 921 {
911 922 ret = LFR_DEFAULT;
912 923 }
913 924
914 925 return ret;
915 926 }
916 927
917 928 void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc )
918 929 {
919 930 // a tickout has been emitted, perform actions on the incoming timecode
920 931
921 932 unsigned char incomingTimecode;
922 933 unsigned char updateTime;
923 934 unsigned char internalTime;
924 935 rtems_status_code status;
925 936
926 937 incomingTimecode = (unsigned char) (grspwPtr[0] & TIMECODE_MASK);
927 938 updateTime = time_management_regs->coarse_time_load & TIMECODE_MASK;
928 939 internalTime = time_management_regs->coarse_time & TIMECODE_MASK;
929 940
930 941 housekeeping_packet.hk_lfr_dpu_spw_last_timc = incomingTimecode;
931 942
932 943 // update the number of tickout that have been generated
933 944 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt );
934 945
935 946 //**************************
936 947 // HK_LFR_TIMECODE_ERRONEOUS
937 948 // MISSING and INVALID are handled by the timecode_timer_routine service routine
938 949 if (check_timecode_and_previous_timecode_coherency( incomingTimecode ) == LFR_DEFAULT)
939 950 {
940 951 // this is unexpected but a tickout could have been raised despite of the timecode being erroneous
941 952 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_erroneous );
942 953 update_hk_lfr_last_er_fields( RID_LE_LFR_TIMEC, CODE_ERRONEOUS );
943 954 }
944 955
945 956 //************************
946 957 // HK_LFR_TIME_TIMECODE_IT
947 958 // check the coherency between the SpaceWire timecode and the Internal Time
948 959 if (check_timecode_and_internal_time_coherency( incomingTimecode, internalTime ) == LFR_DEFAULT)
949 960 {
950 961 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_time_timecode_it );
951 962 update_hk_lfr_last_er_fields( RID_LE_LFR_TIME, CODE_TIMECODE_IT );
952 963 }
953 964
954 965 //********************
955 966 // HK_LFR_TIMECODE_CTR
956 967 // check the value of the timecode with respect to the last TC_LFR_UPDATE_TIME => SSS-CP-FS-370
957 968 if (incomingTimecode != updateTime)
958 969 {
959 970 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_time_timecode_ctr );
960 971 update_hk_lfr_last_er_fields( RID_LE_LFR_TIME, CODE_TIMECODE_CTR );
961 972 }
962 973
963 974 // launch the timecode timer to detect missing or invalid timecodes
964 975 previousTimecodeCtr = incomingTimecode; // update the previousTimecodeCtr value
965 976 status = rtems_timer_fire_after( timecode_timer_id, TIMECODE_TIMER_TIMEOUT, timecode_timer_routine, NULL );
966 977 if (status != RTEMS_SUCCESSFUL)
967 978 {
968 979 rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_14 );
969 980 }
970 981 }
971 982
972 983 void init_header_cwf( Header_TM_LFR_SCIENCE_CWF_t *header )
973 984 {
974 985 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
975 986 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
976 987 header->reserved = DEFAULT_RESERVED;
977 988 header->userApplication = CCSDS_USER_APP;
978 989 header->packetSequenceControl[0]= TM_PACKET_SEQ_CTRL_STANDALONE;
979 990 header->packetSequenceControl[1]= TM_PACKET_SEQ_CNT_DEFAULT;
980 991 header->packetLength[0] = 0x00;
981 992 header->packetLength[1] = 0x00;
982 993 // DATA FIELD HEADER
983 994 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
984 995 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
985 996 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6; // service subtype
986 997 header->destinationID = TM_DESTINATION_ID_GROUND;
987 998 header->time[0] = 0x00;
988 999 header->time[0] = 0x00;
989 1000 header->time[0] = 0x00;
990 1001 header->time[0] = 0x00;
991 1002 header->time[0] = 0x00;
992 1003 header->time[0] = 0x00;
993 1004 // AUXILIARY DATA HEADER
994 1005 header->sid = 0x00;
995 1006 header->hkBIA = DEFAULT_HKBIA;
996 1007 header->blkNr[0] = 0x00;
997 1008 header->blkNr[1] = 0x00;
998 1009 }
999 1010
1000 1011 void init_header_swf( Header_TM_LFR_SCIENCE_SWF_t *header )
1001 1012 {
1002 1013 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
1003 1014 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
1004 1015 header->reserved = DEFAULT_RESERVED;
1005 1016 header->userApplication = CCSDS_USER_APP;
1006 1017 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
1007 1018 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1008 1019 header->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
1009 1020 header->packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
1010 1021 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_336 >> 8);
1011 1022 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_336 );
1012 1023 // DATA FIELD HEADER
1013 1024 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
1014 1025 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
1015 1026 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6; // service subtype
1016 1027 header->destinationID = TM_DESTINATION_ID_GROUND;
1017 1028 header->time[0] = 0x00;
1018 1029 header->time[0] = 0x00;
1019 1030 header->time[0] = 0x00;
1020 1031 header->time[0] = 0x00;
1021 1032 header->time[0] = 0x00;
1022 1033 header->time[0] = 0x00;
1023 1034 // AUXILIARY DATA HEADER
1024 1035 header->sid = 0x00;
1025 1036 header->hkBIA = DEFAULT_HKBIA;
1026 1037 header->pktCnt = DEFAULT_PKTCNT; // PKT_CNT
1027 1038 header->pktNr = 0x00;
1028 1039 header->blkNr[0] = (unsigned char) (BLK_NR_CWF >> 8);
1029 1040 header->blkNr[1] = (unsigned char) (BLK_NR_CWF );
1030 1041 }
1031 1042
1032 1043 void init_header_asm( Header_TM_LFR_SCIENCE_ASM_t *header )
1033 1044 {
1034 1045 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
1035 1046 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
1036 1047 header->reserved = DEFAULT_RESERVED;
1037 1048 header->userApplication = CCSDS_USER_APP;
1038 1049 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
1039 1050 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1040 1051 header->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
1041 1052 header->packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
1042 1053 header->packetLength[0] = 0x00;
1043 1054 header->packetLength[1] = 0x00;
1044 1055 // DATA FIELD HEADER
1045 1056 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
1046 1057 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
1047 1058 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_3; // service subtype
1048 1059 header->destinationID = TM_DESTINATION_ID_GROUND;
1049 1060 header->time[0] = 0x00;
1050 1061 header->time[0] = 0x00;
1051 1062 header->time[0] = 0x00;
1052 1063 header->time[0] = 0x00;
1053 1064 header->time[0] = 0x00;
1054 1065 header->time[0] = 0x00;
1055 1066 // AUXILIARY DATA HEADER
1056 1067 header->sid = 0x00;
1057 1068 header->biaStatusInfo = 0x00;
1058 1069 header->pa_lfr_pkt_cnt_asm = 0x00;
1059 1070 header->pa_lfr_pkt_nr_asm = 0x00;
1060 1071 header->pa_lfr_asm_blk_nr[0] = 0x00;
1061 1072 header->pa_lfr_asm_blk_nr[1] = 0x00;
1062 1073 }
1063 1074
1064 1075 int spw_send_waveform_CWF( ring_node *ring_node_to_send,
1065 1076 Header_TM_LFR_SCIENCE_CWF_t *header )
1066 1077 {
1067 1078 /** This function sends CWF CCSDS packets (F2, F1 or F0).
1068 1079 *
1069 1080 * @param waveform points to the buffer containing the data that will be send.
1070 1081 * @param sid is the source identifier of the data that will be sent.
1071 1082 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
1072 1083 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
1073 1084 * contain information to setup the transmission of the data packets.
1074 1085 *
1075 1086 * One group of 2048 samples is sent as 7 consecutive packets, 6 packets containing 340 blocks and 8 packets containing 8 blocks.
1076 1087 *
1077 1088 */
1078 1089
1079 1090 unsigned int i;
1080 1091 int ret;
1081 1092 unsigned int coarseTime;
1082 1093 unsigned int fineTime;
1083 1094 rtems_status_code status;
1084 1095 spw_ioctl_pkt_send spw_ioctl_send_CWF;
1085 1096 int *dataPtr;
1086 1097 unsigned char sid;
1087 1098
1088 1099 spw_ioctl_send_CWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_CWF;
1089 1100 spw_ioctl_send_CWF.options = 0;
1090 1101
1091 1102 ret = LFR_DEFAULT;
1092 1103 sid = (unsigned char) ring_node_to_send->sid;
1093 1104
1094 1105 coarseTime = ring_node_to_send->coarseTime;
1095 1106 fineTime = ring_node_to_send->fineTime;
1096 1107 dataPtr = (int*) ring_node_to_send->buffer_address;
1097 1108
1098 1109 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_336 >> 8);
1099 1110 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_336 );
1100 1111 header->hkBIA = pa_bia_status_info;
1101 1112 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1102 1113 header->blkNr[0] = (unsigned char) (BLK_NR_CWF >> 8);
1103 1114 header->blkNr[1] = (unsigned char) (BLK_NR_CWF );
1104 1115
1105 1116 for (i=0; i<NB_PACKETS_PER_GROUP_OF_CWF; i++) // send waveform
1106 1117 {
1107 1118 spw_ioctl_send_CWF.data = (char*) &dataPtr[ (i * BLK_NR_CWF * NB_WORDS_SWF_BLK) ];
1108 1119 spw_ioctl_send_CWF.hdr = (char*) header;
1109 1120 // BUILD THE DATA
1110 1121 spw_ioctl_send_CWF.dlen = BLK_NR_CWF * NB_BYTES_SWF_BLK;
1111 1122
1112 1123 // SET PACKET SEQUENCE CONTROL
1113 1124 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1114 1125
1115 1126 // SET SID
1116 1127 header->sid = sid;
1117 1128
1118 1129 // SET PACKET TIME
1119 1130 compute_acquisition_time( coarseTime, fineTime, sid, i, header->acquisitionTime);
1120 1131 //
1121 1132 header->time[0] = header->acquisitionTime[0];
1122 1133 header->time[1] = header->acquisitionTime[1];
1123 1134 header->time[2] = header->acquisitionTime[2];
1124 1135 header->time[3] = header->acquisitionTime[3];
1125 1136 header->time[4] = header->acquisitionTime[4];
1126 1137 header->time[5] = header->acquisitionTime[5];
1127 1138
1128 1139 // SET PACKET ID
1129 1140 if ( (sid == SID_SBM1_CWF_F1) || (sid == SID_SBM2_CWF_F2) )
1130 1141 {
1131 1142 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_SBM1_SBM2 >> 8);
1132 1143 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_SBM1_SBM2);
1133 1144 }
1134 1145 else
1135 1146 {
1136 1147 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
1137 1148 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1138 1149 }
1139 1150
1140 1151 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF );
1141 1152 if (status != RTEMS_SUCCESSFUL) {
1142 1153 ret = LFR_DEFAULT;
1143 1154 }
1144 1155 }
1145 1156
1146 1157 return ret;
1147 1158 }
1148 1159
1149 1160 int spw_send_waveform_SWF( ring_node *ring_node_to_send,
1150 1161 Header_TM_LFR_SCIENCE_SWF_t *header )
1151 1162 {
1152 1163 /** This function sends SWF CCSDS packets (F2, F1 or F0).
1153 1164 *
1154 1165 * @param waveform points to the buffer containing the data that will be send.
1155 1166 * @param sid is the source identifier of the data that will be sent.
1156 1167 * @param headerSWF points to a table of headers that have been prepared for the data transmission.
1157 1168 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
1158 1169 * contain information to setup the transmission of the data packets.
1159 1170 *
1160 1171 * One group of 2048 samples is sent as 7 consecutive packets, 6 packets containing 340 blocks and 8 packets containing 8 blocks.
1161 1172 *
1162 1173 */
1163 1174
1164 1175 unsigned int i;
1165 1176 int ret;
1166 1177 unsigned int coarseTime;
1167 1178 unsigned int fineTime;
1168 1179 rtems_status_code status;
1169 1180 spw_ioctl_pkt_send spw_ioctl_send_SWF;
1170 1181 int *dataPtr;
1171 1182 unsigned char sid;
1172 1183
1173 1184 spw_ioctl_send_SWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_SWF;
1174 1185 spw_ioctl_send_SWF.options = 0;
1175 1186
1176 1187 ret = LFR_DEFAULT;
1177 1188
1178 1189 coarseTime = ring_node_to_send->coarseTime;
1179 1190 fineTime = ring_node_to_send->fineTime;
1180 1191 dataPtr = (int*) ring_node_to_send->buffer_address;
1181 1192 sid = ring_node_to_send->sid;
1182 1193
1183 1194 header->hkBIA = pa_bia_status_info;
1184 1195 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1185 1196
1186 1197 for (i=0; i<7; i++) // send waveform
1187 1198 {
1188 1199 spw_ioctl_send_SWF.data = (char*) &dataPtr[ (i * BLK_NR_304 * NB_WORDS_SWF_BLK) ];
1189 1200 spw_ioctl_send_SWF.hdr = (char*) header;
1190 1201
1191 1202 // SET PACKET SEQUENCE CONTROL
1192 1203 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1193 1204
1194 1205 // SET PACKET LENGTH AND BLKNR
1195 1206 if (i == 6)
1196 1207 {
1197 1208 spw_ioctl_send_SWF.dlen = BLK_NR_224 * NB_BYTES_SWF_BLK;
1198 1209 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_SWF_224 >> 8);
1199 1210 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_SWF_224 );
1200 1211 header->blkNr[0] = (unsigned char) (BLK_NR_224 >> 8);
1201 1212 header->blkNr[1] = (unsigned char) (BLK_NR_224 );
1202 1213 }
1203 1214 else
1204 1215 {
1205 1216 spw_ioctl_send_SWF.dlen = BLK_NR_304 * NB_BYTES_SWF_BLK;
1206 1217 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_SWF_304 >> 8);
1207 1218 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_SWF_304 );
1208 1219 header->blkNr[0] = (unsigned char) (BLK_NR_304 >> 8);
1209 1220 header->blkNr[1] = (unsigned char) (BLK_NR_304 );
1210 1221 }
1211 1222
1212 1223 // SET PACKET TIME
1213 1224 compute_acquisition_time( coarseTime, fineTime, sid, i, header->acquisitionTime );
1214 1225 //
1215 1226 header->time[0] = header->acquisitionTime[0];
1216 1227 header->time[1] = header->acquisitionTime[1];
1217 1228 header->time[2] = header->acquisitionTime[2];
1218 1229 header->time[3] = header->acquisitionTime[3];
1219 1230 header->time[4] = header->acquisitionTime[4];
1220 1231 header->time[5] = header->acquisitionTime[5];
1221 1232
1222 1233 // SET SID
1223 1234 header->sid = sid;
1224 1235
1225 1236 // SET PKTNR
1226 1237 header->pktNr = i+1; // PKT_NR
1227 1238
1228 1239 // SEND PACKET
1229 1240 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_SWF );
1230 1241 if (status != RTEMS_SUCCESSFUL) {
1231 1242 ret = LFR_DEFAULT;
1232 1243 }
1233 1244 }
1234 1245
1235 1246 return ret;
1236 1247 }
1237 1248
1238 1249 int spw_send_waveform_CWF3_light( ring_node *ring_node_to_send,
1239 1250 Header_TM_LFR_SCIENCE_CWF_t *header )
1240 1251 {
1241 1252 /** This function sends CWF_F3 CCSDS packets without the b1, b2 and b3 data.
1242 1253 *
1243 1254 * @param waveform points to the buffer containing the data that will be send.
1244 1255 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
1245 1256 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
1246 1257 * contain information to setup the transmission of the data packets.
1247 1258 *
1248 1259 * By default, CWF_F3 packet are send without the b1, b2 and b3 data. This function rebuilds a data buffer
1249 1260 * from the incoming data and sends it in 7 packets, 6 containing 340 blocks and 1 one containing 8 blocks.
1250 1261 *
1251 1262 */
1252 1263
1253 1264 unsigned int i;
1254 1265 int ret;
1255 1266 unsigned int coarseTime;
1256 1267 unsigned int fineTime;
1257 1268 rtems_status_code status;
1258 1269 spw_ioctl_pkt_send spw_ioctl_send_CWF;
1259 1270 char *dataPtr;
1260 1271 unsigned char sid;
1261 1272
1262 1273 spw_ioctl_send_CWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_CWF;
1263 1274 spw_ioctl_send_CWF.options = 0;
1264 1275
1265 1276 ret = LFR_DEFAULT;
1266 1277 sid = ring_node_to_send->sid;
1267 1278
1268 1279 coarseTime = ring_node_to_send->coarseTime;
1269 1280 fineTime = ring_node_to_send->fineTime;
1270 1281 dataPtr = (char*) ring_node_to_send->buffer_address;
1271 1282
1272 1283 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_672 >> 8);
1273 1284 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_672 );
1274 1285 header->hkBIA = pa_bia_status_info;
1275 1286 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1276 1287 header->blkNr[0] = (unsigned char) (BLK_NR_CWF_SHORT_F3 >> 8);
1277 1288 header->blkNr[1] = (unsigned char) (BLK_NR_CWF_SHORT_F3 );
1278 1289
1279 1290 //*********************
1280 1291 // SEND CWF3_light DATA
1281 1292 for (i=0; i<NB_PACKETS_PER_GROUP_OF_CWF_LIGHT; i++) // send waveform
1282 1293 {
1283 1294 spw_ioctl_send_CWF.data = (char*) &dataPtr[ (i * BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK) ];
1284 1295 spw_ioctl_send_CWF.hdr = (char*) header;
1285 1296 // BUILD THE DATA
1286 1297 spw_ioctl_send_CWF.dlen = BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK;
1287 1298
1288 1299 // SET PACKET SEQUENCE COUNTER
1289 1300 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1290 1301
1291 1302 // SET SID
1292 1303 header->sid = sid;
1293 1304
1294 1305 // SET PACKET TIME
1295 1306 compute_acquisition_time( coarseTime, fineTime, SID_NORM_CWF_F3, i, header->acquisitionTime );
1296 1307 //
1297 1308 header->time[0] = header->acquisitionTime[0];
1298 1309 header->time[1] = header->acquisitionTime[1];
1299 1310 header->time[2] = header->acquisitionTime[2];
1300 1311 header->time[3] = header->acquisitionTime[3];
1301 1312 header->time[4] = header->acquisitionTime[4];
1302 1313 header->time[5] = header->acquisitionTime[5];
1303 1314
1304 1315 // SET PACKET ID
1305 1316 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
1306 1317 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1307 1318
1308 1319 // SEND PACKET
1309 1320 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF );
1310 1321 if (status != RTEMS_SUCCESSFUL) {
1311 1322 ret = LFR_DEFAULT;
1312 1323 }
1313 1324 }
1314 1325
1315 1326 return ret;
1316 1327 }
1317 1328
1318 1329 void spw_send_asm_f0( ring_node *ring_node_to_send,
1319 1330 Header_TM_LFR_SCIENCE_ASM_t *header )
1320 1331 {
1321 1332 unsigned int i;
1322 1333 unsigned int length = 0;
1323 1334 rtems_status_code status;
1324 1335 unsigned int sid;
1325 1336 float *spectral_matrix;
1326 1337 int coarseTime;
1327 1338 int fineTime;
1328 1339 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1329 1340
1330 1341 sid = ring_node_to_send->sid;
1331 1342 spectral_matrix = (float*) ring_node_to_send->buffer_address;
1332 1343 coarseTime = ring_node_to_send->coarseTime;
1333 1344 fineTime = ring_node_to_send->fineTime;
1334 1345
1335 1346 header->biaStatusInfo = pa_bia_status_info;
1336 1347 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1337 1348
1338 1349 for (i=0; i<3; i++)
1339 1350 {
1340 1351 if ((i==0) || (i==1))
1341 1352 {
1342 1353 spw_ioctl_send_ASM.dlen = DLEN_ASM_F0_PKT_1;
1343 1354 spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1344 1355 ( (ASM_F0_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F0_1) ) * NB_VALUES_PER_SM )
1345 1356 ];
1346 1357 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F0_1;
1347 1358 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1348 1359 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F0_1) >> 8 ); // BLK_NR MSB
1349 1360 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F0_1); // BLK_NR LSB
1350 1361 }
1351 1362 else
1352 1363 {
1353 1364 spw_ioctl_send_ASM.dlen = DLEN_ASM_F0_PKT_2;
1354 1365 spw_ioctl_send_ASM.data = (char*) &spectral_matrix[
1355 1366 ( (ASM_F0_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F0_1) ) * NB_VALUES_PER_SM )
1356 1367 ];
1357 1368 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F0_2;
1358 1369 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1359 1370 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F0_2) >> 8 ); // BLK_NR MSB
1360 1371 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F0_2); // BLK_NR LSB
1361 1372 }
1362 1373
1363 1374 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1364 1375 spw_ioctl_send_ASM.hdr = (char *) header;
1365 1376 spw_ioctl_send_ASM.options = 0;
1366 1377
1367 1378 // (2) BUILD THE HEADER
1368 1379 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1369 1380 header->packetLength[0] = (unsigned char) (length>>8);
1370 1381 header->packetLength[1] = (unsigned char) (length);
1371 1382 header->sid = (unsigned char) sid; // SID
1372 1383 header->pa_lfr_pkt_cnt_asm = 3;
1373 1384 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1374 1385
1375 1386 // (3) SET PACKET TIME
1376 1387 header->time[0] = (unsigned char) (coarseTime>>24);
1377 1388 header->time[1] = (unsigned char) (coarseTime>>16);
1378 1389 header->time[2] = (unsigned char) (coarseTime>>8);
1379 1390 header->time[3] = (unsigned char) (coarseTime);
1380 1391 header->time[4] = (unsigned char) (fineTime>>8);
1381 1392 header->time[5] = (unsigned char) (fineTime);
1382 1393 //
1383 1394 header->acquisitionTime[0] = header->time[0];
1384 1395 header->acquisitionTime[1] = header->time[1];
1385 1396 header->acquisitionTime[2] = header->time[2];
1386 1397 header->acquisitionTime[3] = header->time[3];
1387 1398 header->acquisitionTime[4] = header->time[4];
1388 1399 header->acquisitionTime[5] = header->time[5];
1389 1400
1390 1401 // (4) SEND PACKET
1391 1402 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1392 1403 if (status != RTEMS_SUCCESSFUL) {
1393 1404 PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1394 1405 }
1395 1406 }
1396 1407 }
1397 1408
1398 1409 void spw_send_asm_f1( ring_node *ring_node_to_send,
1399 1410 Header_TM_LFR_SCIENCE_ASM_t *header )
1400 1411 {
1401 1412 unsigned int i;
1402 1413 unsigned int length = 0;
1403 1414 rtems_status_code status;
1404 1415 unsigned int sid;
1405 1416 float *spectral_matrix;
1406 1417 int coarseTime;
1407 1418 int fineTime;
1408 1419 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1409 1420
1410 1421 sid = ring_node_to_send->sid;
1411 1422 spectral_matrix = (float*) ring_node_to_send->buffer_address;
1412 1423 coarseTime = ring_node_to_send->coarseTime;
1413 1424 fineTime = ring_node_to_send->fineTime;
1414 1425
1415 1426 header->biaStatusInfo = pa_bia_status_info;
1416 1427 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1417 1428
1418 1429 for (i=0; i<3; i++)
1419 1430 {
1420 1431 if ((i==0) || (i==1))
1421 1432 {
1422 1433 spw_ioctl_send_ASM.dlen = DLEN_ASM_F1_PKT_1;
1423 1434 spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1424 1435 ( (ASM_F1_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F1_1) ) * NB_VALUES_PER_SM )
1425 1436 ];
1426 1437 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F1_1;
1427 1438 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1428 1439 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F1_1) >> 8 ); // BLK_NR MSB
1429 1440 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F1_1); // BLK_NR LSB
1430 1441 }
1431 1442 else
1432 1443 {
1433 1444 spw_ioctl_send_ASM.dlen = DLEN_ASM_F1_PKT_2;
1434 1445 spw_ioctl_send_ASM.data = (char*) &spectral_matrix[
1435 1446 ( (ASM_F1_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F1_1) ) * NB_VALUES_PER_SM )
1436 1447 ];
1437 1448 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F1_2;
1438 1449 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1439 1450 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F1_2) >> 8 ); // BLK_NR MSB
1440 1451 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F1_2); // BLK_NR LSB
1441 1452 }
1442 1453
1443 1454 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1444 1455 spw_ioctl_send_ASM.hdr = (char *) header;
1445 1456 spw_ioctl_send_ASM.options = 0;
1446 1457
1447 1458 // (2) BUILD THE HEADER
1448 1459 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1449 1460 header->packetLength[0] = (unsigned char) (length>>8);
1450 1461 header->packetLength[1] = (unsigned char) (length);
1451 1462 header->sid = (unsigned char) sid; // SID
1452 1463 header->pa_lfr_pkt_cnt_asm = 3;
1453 1464 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1454 1465
1455 1466 // (3) SET PACKET TIME
1456 1467 header->time[0] = (unsigned char) (coarseTime>>24);
1457 1468 header->time[1] = (unsigned char) (coarseTime>>16);
1458 1469 header->time[2] = (unsigned char) (coarseTime>>8);
1459 1470 header->time[3] = (unsigned char) (coarseTime);
1460 1471 header->time[4] = (unsigned char) (fineTime>>8);
1461 1472 header->time[5] = (unsigned char) (fineTime);
1462 1473 //
1463 1474 header->acquisitionTime[0] = header->time[0];
1464 1475 header->acquisitionTime[1] = header->time[1];
1465 1476 header->acquisitionTime[2] = header->time[2];
1466 1477 header->acquisitionTime[3] = header->time[3];
1467 1478 header->acquisitionTime[4] = header->time[4];
1468 1479 header->acquisitionTime[5] = header->time[5];
1469 1480
1470 1481 // (4) SEND PACKET
1471 1482 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1472 1483 if (status != RTEMS_SUCCESSFUL) {
1473 1484 PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1474 1485 }
1475 1486 }
1476 1487 }
1477 1488
1478 1489 void spw_send_asm_f2( ring_node *ring_node_to_send,
1479 1490 Header_TM_LFR_SCIENCE_ASM_t *header )
1480 1491 {
1481 1492 unsigned int i;
1482 1493 unsigned int length = 0;
1483 1494 rtems_status_code status;
1484 1495 unsigned int sid;
1485 1496 float *spectral_matrix;
1486 1497 int coarseTime;
1487 1498 int fineTime;
1488 1499 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1489 1500
1490 1501 sid = ring_node_to_send->sid;
1491 1502 spectral_matrix = (float*) ring_node_to_send->buffer_address;
1492 1503 coarseTime = ring_node_to_send->coarseTime;
1493 1504 fineTime = ring_node_to_send->fineTime;
1494 1505
1495 1506 header->biaStatusInfo = pa_bia_status_info;
1496 1507 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1497 1508
1498 1509 for (i=0; i<3; i++)
1499 1510 {
1500 1511
1501 1512 spw_ioctl_send_ASM.dlen = DLEN_ASM_F2_PKT;
1502 1513 spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1503 1514 ( (ASM_F2_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F2) ) * NB_VALUES_PER_SM )
1504 1515 ];
1505 1516 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F2;
1506 1517 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_3;
1507 1518 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F2) >> 8 ); // BLK_NR MSB
1508 1519 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F2); // BLK_NR LSB
1509 1520
1510 1521 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1511 1522 spw_ioctl_send_ASM.hdr = (char *) header;
1512 1523 spw_ioctl_send_ASM.options = 0;
1513 1524
1514 1525 // (2) BUILD THE HEADER
1515 1526 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1516 1527 header->packetLength[0] = (unsigned char) (length>>8);
1517 1528 header->packetLength[1] = (unsigned char) (length);
1518 1529 header->sid = (unsigned char) sid; // SID
1519 1530 header->pa_lfr_pkt_cnt_asm = 3;
1520 1531 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1521 1532
1522 1533 // (3) SET PACKET TIME
1523 1534 header->time[0] = (unsigned char) (coarseTime>>24);
1524 1535 header->time[1] = (unsigned char) (coarseTime>>16);
1525 1536 header->time[2] = (unsigned char) (coarseTime>>8);
1526 1537 header->time[3] = (unsigned char) (coarseTime);
1527 1538 header->time[4] = (unsigned char) (fineTime>>8);
1528 1539 header->time[5] = (unsigned char) (fineTime);
1529 1540 //
1530 1541 header->acquisitionTime[0] = header->time[0];
1531 1542 header->acquisitionTime[1] = header->time[1];
1532 1543 header->acquisitionTime[2] = header->time[2];
1533 1544 header->acquisitionTime[3] = header->time[3];
1534 1545 header->acquisitionTime[4] = header->time[4];
1535 1546 header->acquisitionTime[5] = header->time[5];
1536 1547
1537 1548 // (4) SEND PACKET
1538 1549 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1539 1550 if (status != RTEMS_SUCCESSFUL) {
1540 1551 PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1541 1552 }
1542 1553 }
1543 1554 }
1544 1555
1545 1556 void spw_send_k_dump( ring_node *ring_node_to_send )
1546 1557 {
1547 1558 rtems_status_code status;
1548 1559 Packet_TM_LFR_KCOEFFICIENTS_DUMP_t *kcoefficients_dump;
1549 1560 unsigned int packetLength;
1550 1561 unsigned int size;
1551 1562
1552 1563 PRINTF("spw_send_k_dump\n")
1553 1564
1554 1565 kcoefficients_dump = (Packet_TM_LFR_KCOEFFICIENTS_DUMP_t *) ring_node_to_send->buffer_address;
1555 1566
1556 1567 packetLength = kcoefficients_dump->packetLength[0] * 256 + kcoefficients_dump->packetLength[1];
1557 1568
1558 1569 size = packetLength + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES;
1559 1570
1560 1571 PRINTF2("packetLength %d, size %d\n", packetLength, size )
1561 1572
1562 1573 status = write( fdSPW, (char *) ring_node_to_send->buffer_address, size );
1563 1574
1564 1575 if (status == -1){
1565 1576 PRINTF2("in SEND *** (2.a) ERRNO = %d, size = %d\n", errno, size)
1566 1577 }
1567 1578
1568 1579 ring_node_to_send->status = 0x00;
1569 1580 }
@@ -1,708 +1,719
1 1 /** Functions related to data processing.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * These function are related to data processing, i.e. spectral matrices averaging and basic parameters computation.
7 7 *
8 8 */
9 9
10 10 #include "fsw_processing.h"
11 11 #include "fsw_processing_globals.c"
12 12 #include "fsw_init.h"
13 13
14 14 unsigned int nb_sm_f0;
15 15 unsigned int nb_sm_f0_aux_f1;
16 16 unsigned int nb_sm_f1;
17 17 unsigned int nb_sm_f0_aux_f2;
18 18
19 19 typedef enum restartState_t
20 20 {
21 21 WAIT_FOR_F2,
22 22 WAIT_FOR_F1,
23 23 WAIT_FOR_F0
24 24 } restartState;
25 25
26 26 //************************
27 27 // spectral matrices rings
28 28 ring_node sm_ring_f0[ NB_RING_NODES_SM_F0 ];
29 29 ring_node sm_ring_f1[ NB_RING_NODES_SM_F1 ];
30 30 ring_node sm_ring_f2[ NB_RING_NODES_SM_F2 ];
31 31 ring_node *current_ring_node_sm_f0;
32 32 ring_node *current_ring_node_sm_f1;
33 33 ring_node *current_ring_node_sm_f2;
34 34 ring_node *ring_node_for_averaging_sm_f0;
35 35 ring_node *ring_node_for_averaging_sm_f1;
36 36 ring_node *ring_node_for_averaging_sm_f2;
37 37
38 38 //
39 39 ring_node * getRingNodeForAveraging( unsigned char frequencyChannel)
40 40 {
41 41 ring_node *node;
42 42
43 43 node = NULL;
44 44 switch ( frequencyChannel ) {
45 45 case 0:
46 46 node = ring_node_for_averaging_sm_f0;
47 47 break;
48 48 case 1:
49 49 node = ring_node_for_averaging_sm_f1;
50 50 break;
51 51 case 2:
52 52 node = ring_node_for_averaging_sm_f2;
53 53 break;
54 54 default:
55 55 break;
56 56 }
57 57
58 58 return node;
59 59 }
60 60
61 61 //***********************************************************
62 62 // Interrupt Service Routine for spectral matrices processing
63 63
64 void spectral_matrices_isr_f0( unsigned char statusReg )
64 void spectral_matrices_isr_f0( int statusReg )
65 65 {
66 66 unsigned char status;
67 67 rtems_status_code status_code;
68 68 ring_node *full_ring_node;
69 69
70 status = statusReg & 0x03; // [0011] get the status_ready_matrix_f0_x bits
70 status = (unsigned char) (statusReg & 0x03); // [0011] get the status_ready_matrix_f0_x bits
71 71
72 72 switch(status)
73 73 {
74 74 case 0:
75 75 break;
76 76 case 3:
77 77 // UNEXPECTED VALUE
78 78 spectral_matrix_regs->status = 0x03; // [0011]
79 79 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_11 );
80 80 break;
81 81 case 1:
82 82 full_ring_node = current_ring_node_sm_f0->previous;
83 83 full_ring_node->coarseTime = spectral_matrix_regs->f0_0_coarse_time;
84 84 full_ring_node->fineTime = spectral_matrix_regs->f0_0_fine_time;
85 85 current_ring_node_sm_f0 = current_ring_node_sm_f0->next;
86 86 spectral_matrix_regs->f0_0_address = current_ring_node_sm_f0->buffer_address;
87 87 // if there are enough ring nodes ready, wake up an AVFx task
88 88 nb_sm_f0 = nb_sm_f0 + 1;
89 89 if (nb_sm_f0 == NB_SM_BEFORE_AVF0)
90 90 {
91 91 ring_node_for_averaging_sm_f0 = full_ring_node;
92 92 if (rtems_event_send( Task_id[TASKID_AVF0], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL)
93 93 {
94 94 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_3 );
95 95 }
96 96 nb_sm_f0 = 0;
97 97 }
98 98 spectral_matrix_regs->status = 0x01; // [0000 0001]
99 99 break;
100 100 case 2:
101 101 full_ring_node = current_ring_node_sm_f0->previous;
102 102 full_ring_node->coarseTime = spectral_matrix_regs->f0_1_coarse_time;
103 103 full_ring_node->fineTime = spectral_matrix_regs->f0_1_fine_time;
104 104 current_ring_node_sm_f0 = current_ring_node_sm_f0->next;
105 105 spectral_matrix_regs->f0_1_address = current_ring_node_sm_f0->buffer_address;
106 106 // if there are enough ring nodes ready, wake up an AVFx task
107 107 nb_sm_f0 = nb_sm_f0 + 1;
108 108 if (nb_sm_f0 == NB_SM_BEFORE_AVF0)
109 109 {
110 110 ring_node_for_averaging_sm_f0 = full_ring_node;
111 111 if (rtems_event_send( Task_id[TASKID_AVF0], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL)
112 112 {
113 113 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_3 );
114 114 }
115 115 nb_sm_f0 = 0;
116 116 }
117 117 spectral_matrix_regs->status = 0x02; // [0000 0010]
118 118 break;
119 119 }
120 120 }
121 121
122 void spectral_matrices_isr_f1( unsigned char statusReg )
122 void spectral_matrices_isr_f1( int statusReg )
123 123 {
124 124 rtems_status_code status_code;
125 125 unsigned char status;
126 126 ring_node *full_ring_node;
127 127
128 status = (statusReg & 0x0c) >> 2; // [1100] get the status_ready_matrix_f1_x bits
128 status = (unsigned char) ((statusReg & 0x0c) >> 2); // [1100] get the status_ready_matrix_f1_x bits
129 129
130 130 switch(status)
131 131 {
132 132 case 0:
133 133 break;
134 134 case 3:
135 135 // UNEXPECTED VALUE
136 136 spectral_matrix_regs->status = 0xc0; // [1100]
137 137 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_11 );
138 138 break;
139 139 case 1:
140 140 full_ring_node = current_ring_node_sm_f1->previous;
141 141 full_ring_node->coarseTime = spectral_matrix_regs->f1_0_coarse_time;
142 142 full_ring_node->fineTime = spectral_matrix_regs->f1_0_fine_time;
143 143 current_ring_node_sm_f1 = current_ring_node_sm_f1->next;
144 144 spectral_matrix_regs->f1_0_address = current_ring_node_sm_f1->buffer_address;
145 145 // if there are enough ring nodes ready, wake up an AVFx task
146 146 nb_sm_f1 = nb_sm_f1 + 1;
147 147 if (nb_sm_f1 == NB_SM_BEFORE_AVF1)
148 148 {
149 149 ring_node_for_averaging_sm_f1 = full_ring_node;
150 150 if (rtems_event_send( Task_id[TASKID_AVF1], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL)
151 151 {
152 152 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_3 );
153 153 }
154 154 nb_sm_f1 = 0;
155 155 }
156 156 spectral_matrix_regs->status = 0x04; // [0000 0100]
157 157 break;
158 158 case 2:
159 159 full_ring_node = current_ring_node_sm_f1->previous;
160 160 full_ring_node->coarseTime = spectral_matrix_regs->f1_1_coarse_time;
161 161 full_ring_node->fineTime = spectral_matrix_regs->f1_1_fine_time;
162 162 current_ring_node_sm_f1 = current_ring_node_sm_f1->next;
163 163 spectral_matrix_regs->f1_1_address = current_ring_node_sm_f1->buffer_address;
164 164 // if there are enough ring nodes ready, wake up an AVFx task
165 165 nb_sm_f1 = nb_sm_f1 + 1;
166 166 if (nb_sm_f1 == NB_SM_BEFORE_AVF1)
167 167 {
168 168 ring_node_for_averaging_sm_f1 = full_ring_node;
169 169 if (rtems_event_send( Task_id[TASKID_AVF1], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL)
170 170 {
171 171 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_3 );
172 172 }
173 173 nb_sm_f1 = 0;
174 174 }
175 175 spectral_matrix_regs->status = 0x08; // [1000 0000]
176 176 break;
177 177 }
178 178 }
179 179
180 void spectral_matrices_isr_f2( unsigned char statusReg )
180 void spectral_matrices_isr_f2( int statusReg )
181 181 {
182 182 unsigned char status;
183 183 rtems_status_code status_code;
184 184
185 status = (statusReg & 0x30) >> 4; // [0011 0000] get the status_ready_matrix_f2_x bits
185 status = (unsigned char) ((statusReg & 0x30) >> 4); // [0011 0000] get the status_ready_matrix_f2_x bits
186 186
187 187 switch(status)
188 188 {
189 189 case 0:
190 190 break;
191 191 case 3:
192 192 // UNEXPECTED VALUE
193 193 spectral_matrix_regs->status = 0x30; // [0011 0000]
194 194 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_11 );
195 195 break;
196 196 case 1:
197 197 ring_node_for_averaging_sm_f2 = current_ring_node_sm_f2->previous;
198 198 current_ring_node_sm_f2 = current_ring_node_sm_f2->next;
199 199 ring_node_for_averaging_sm_f2->coarseTime = spectral_matrix_regs->f2_0_coarse_time;
200 200 ring_node_for_averaging_sm_f2->fineTime = spectral_matrix_regs->f2_0_fine_time;
201 201 spectral_matrix_regs->f2_0_address = current_ring_node_sm_f2->buffer_address;
202 202 spectral_matrix_regs->status = 0x10; // [0001 0000]
203 203 if (rtems_event_send( Task_id[TASKID_AVF2], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL)
204 204 {
205 205 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_3 );
206 206 }
207 207 break;
208 208 case 2:
209 209 ring_node_for_averaging_sm_f2 = current_ring_node_sm_f2->previous;
210 210 current_ring_node_sm_f2 = current_ring_node_sm_f2->next;
211 211 ring_node_for_averaging_sm_f2->coarseTime = spectral_matrix_regs->f2_1_coarse_time;
212 212 ring_node_for_averaging_sm_f2->fineTime = spectral_matrix_regs->f2_1_fine_time;
213 213 spectral_matrix_regs->f2_1_address = current_ring_node_sm_f2->buffer_address;
214 214 spectral_matrix_regs->status = 0x20; // [0010 0000]
215 215 if (rtems_event_send( Task_id[TASKID_AVF2], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL)
216 216 {
217 217 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_3 );
218 218 }
219 219 break;
220 220 }
221 221 }
222 222
223 void spectral_matrix_isr_error_handler( unsigned char statusReg )
223 void spectral_matrix_isr_error_handler( int statusReg )
224 224 {
225 // STATUS REGISTER
226 // input_fifo_write(2) *** input_fifo_write(1) *** input_fifo_write(0)
227 // 10 9 8
228 // buffer_full ** bad_component_err ** f2_1 ** f2_0 ** f1_1 ** f1_0 ** f0_1 ** f0_0
229 // 7 6 5 4 3 2 1 0
230
225 231 rtems_status_code status_code;
226 232
233 //***************************************************
234 // the ASM status register is copied in the HK packet
235 housekeeping_packet.hk_lfr_vhdl_aa_sm = (unsigned char) (statusReg & 0x7c0 >> 6); // [0111 1100 0000]
236
227 237 if (statusReg & 0x7c0) // [0111 1100 0000]
228 238 {
229 239 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_8 );
230 240 }
231 241
232 242 spectral_matrix_regs->status = spectral_matrix_regs->status & 0x7c0;
243
233 244 }
234 245
235 246 rtems_isr spectral_matrices_isr( rtems_vector_number vector )
236 247 {
237 248 // STATUS REGISTER
238 249 // input_fifo_write(2) *** input_fifo_write(1) *** input_fifo_write(0)
239 250 // 10 9 8
240 251 // buffer_full ** bad_component_err ** f2_1 ** f2_0 ** f1_1 ** f1_0 ** f0_1 ** f0_0
241 252 // 7 6 5 4 3 2 1 0
242 253
243 unsigned char statusReg;
254 int statusReg;
244 255
245 256 static restartState state = WAIT_FOR_F2;
246 257
247 258 statusReg = spectral_matrix_regs->status;
248 259
249 260 if (thisIsAnASMRestart == 0)
250 261 { // this is not a restart sequence, process incoming matrices normally
251 262 spectral_matrices_isr_f0( statusReg );
252 263
253 264 spectral_matrices_isr_f1( statusReg );
254 265
255 266 spectral_matrices_isr_f2( statusReg );
256 267 }
257 268 else
258 269 { // a restart sequence has to be launched
259 270 switch (state) {
260 271 case WAIT_FOR_F2:
261 272 if ((statusReg & 0x30) != 0x00) // [0011 0000] check the status_ready_matrix_f2_x bits
262 273 {
263 274 state = WAIT_FOR_F1;
264 275 }
265 276 break;
266 277 case WAIT_FOR_F1:
267 278 if ((statusReg & 0x0c) != 0x00) // [0000 1100] check the status_ready_matrix_f1_x bits
268 279 {
269 280 state = WAIT_FOR_F0;
270 281 }
271 282 break;
272 283 case WAIT_FOR_F0:
273 284 if ((statusReg & 0x03) != 0x00) // [0000 0011] check the status_ready_matrix_f0_x bits
274 285 {
275 286 state = WAIT_FOR_F2;
276 287 thisIsAnASMRestart = 0;
277 288 }
278 289 break;
279 290 default:
280 291 break;
281 292 }
282 293 reset_sm_status();
283 294 }
284 295
285 296 spectral_matrix_isr_error_handler( statusReg );
286 297
287 298 }
288 299
289 300 //******************
290 301 // Spectral Matrices
291 302
292 303 void reset_nb_sm( void )
293 304 {
294 305 nb_sm_f0 = 0;
295 306 nb_sm_f0_aux_f1 = 0;
296 307 nb_sm_f0_aux_f2 = 0;
297 308
298 309 nb_sm_f1 = 0;
299 310 }
300 311
301 312 void SM_init_rings( void )
302 313 {
303 314 init_ring( sm_ring_f0, NB_RING_NODES_SM_F0, sm_f0, TOTAL_SIZE_SM );
304 315 init_ring( sm_ring_f1, NB_RING_NODES_SM_F1, sm_f1, TOTAL_SIZE_SM );
305 316 init_ring( sm_ring_f2, NB_RING_NODES_SM_F2, sm_f2, TOTAL_SIZE_SM );
306 317
307 318 DEBUG_PRINTF1("sm_ring_f0 @%x\n", (unsigned int) sm_ring_f0)
308 319 DEBUG_PRINTF1("sm_ring_f1 @%x\n", (unsigned int) sm_ring_f1)
309 320 DEBUG_PRINTF1("sm_ring_f2 @%x\n", (unsigned int) sm_ring_f2)
310 321 DEBUG_PRINTF1("sm_f0 @%x\n", (unsigned int) sm_f0)
311 322 DEBUG_PRINTF1("sm_f1 @%x\n", (unsigned int) sm_f1)
312 323 DEBUG_PRINTF1("sm_f2 @%x\n", (unsigned int) sm_f2)
313 324 }
314 325
315 326 void ASM_generic_init_ring( ring_node_asm *ring, unsigned char nbNodes )
316 327 {
317 328 unsigned char i;
318 329
319 330 ring[ nbNodes - 1 ].next
320 331 = (ring_node_asm*) &ring[ 0 ];
321 332
322 333 for(i=0; i<nbNodes-1; i++)
323 334 {
324 335 ring[ i ].next = (ring_node_asm*) &ring[ i + 1 ];
325 336 }
326 337 }
327 338
328 339 void SM_reset_current_ring_nodes( void )
329 340 {
330 341 current_ring_node_sm_f0 = sm_ring_f0[0].next;
331 342 current_ring_node_sm_f1 = sm_ring_f1[0].next;
332 343 current_ring_node_sm_f2 = sm_ring_f2[0].next;
333 344
334 345 ring_node_for_averaging_sm_f0 = NULL;
335 346 ring_node_for_averaging_sm_f1 = NULL;
336 347 ring_node_for_averaging_sm_f2 = NULL;
337 348 }
338 349
339 350 //*****************
340 351 // Basic Parameters
341 352
342 353 void BP_init_header( bp_packet *packet,
343 354 unsigned int apid, unsigned char sid,
344 355 unsigned int packetLength, unsigned char blkNr )
345 356 {
346 357 packet->targetLogicalAddress = CCSDS_DESTINATION_ID;
347 358 packet->protocolIdentifier = CCSDS_PROTOCOLE_ID;
348 359 packet->reserved = 0x00;
349 360 packet->userApplication = CCSDS_USER_APP;
350 361 packet->packetID[0] = (unsigned char) (apid >> 8);
351 362 packet->packetID[1] = (unsigned char) (apid);
352 363 packet->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
353 364 packet->packetSequenceControl[1] = 0x00;
354 365 packet->packetLength[0] = (unsigned char) (packetLength >> 8);
355 366 packet->packetLength[1] = (unsigned char) (packetLength);
356 367 // DATA FIELD HEADER
357 368 packet->spare1_pusVersion_spare2 = 0x10;
358 369 packet->serviceType = TM_TYPE_LFR_SCIENCE; // service type
359 370 packet->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_3; // service subtype
360 371 packet->destinationID = TM_DESTINATION_ID_GROUND;
361 372 packet->time[0] = 0x00;
362 373 packet->time[1] = 0x00;
363 374 packet->time[2] = 0x00;
364 375 packet->time[3] = 0x00;
365 376 packet->time[4] = 0x00;
366 377 packet->time[5] = 0x00;
367 378 // AUXILIARY DATA HEADER
368 379 packet->sid = sid;
369 380 packet->biaStatusInfo = 0x00;
370 381 packet->sy_lfr_common_parameters_spare = 0x00;
371 382 packet->sy_lfr_common_parameters = 0x00;
372 383 packet->acquisitionTime[0] = 0x00;
373 384 packet->acquisitionTime[1] = 0x00;
374 385 packet->acquisitionTime[2] = 0x00;
375 386 packet->acquisitionTime[3] = 0x00;
376 387 packet->acquisitionTime[4] = 0x00;
377 388 packet->acquisitionTime[5] = 0x00;
378 389 packet->pa_lfr_bp_blk_nr[0] = 0x00; // BLK_NR MSB
379 390 packet->pa_lfr_bp_blk_nr[1] = blkNr; // BLK_NR LSB
380 391 }
381 392
382 393 void BP_init_header_with_spare( bp_packet_with_spare *packet,
383 394 unsigned int apid, unsigned char sid,
384 395 unsigned int packetLength , unsigned char blkNr)
385 396 {
386 397 packet->targetLogicalAddress = CCSDS_DESTINATION_ID;
387 398 packet->protocolIdentifier = CCSDS_PROTOCOLE_ID;
388 399 packet->reserved = 0x00;
389 400 packet->userApplication = CCSDS_USER_APP;
390 401 packet->packetID[0] = (unsigned char) (apid >> 8);
391 402 packet->packetID[1] = (unsigned char) (apid);
392 403 packet->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
393 404 packet->packetSequenceControl[1] = 0x00;
394 405 packet->packetLength[0] = (unsigned char) (packetLength >> 8);
395 406 packet->packetLength[1] = (unsigned char) (packetLength);
396 407 // DATA FIELD HEADER
397 408 packet->spare1_pusVersion_spare2 = 0x10;
398 409 packet->serviceType = TM_TYPE_LFR_SCIENCE; // service type
399 410 packet->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_3; // service subtype
400 411 packet->destinationID = TM_DESTINATION_ID_GROUND;
401 412 // AUXILIARY DATA HEADER
402 413 packet->sid = sid;
403 414 packet->biaStatusInfo = 0x00;
404 415 packet->sy_lfr_common_parameters_spare = 0x00;
405 416 packet->sy_lfr_common_parameters = 0x00;
406 417 packet->time[0] = 0x00;
407 418 packet->time[0] = 0x00;
408 419 packet->time[0] = 0x00;
409 420 packet->time[0] = 0x00;
410 421 packet->time[0] = 0x00;
411 422 packet->time[0] = 0x00;
412 423 packet->source_data_spare = 0x00;
413 424 packet->pa_lfr_bp_blk_nr[0] = 0x00; // BLK_NR MSB
414 425 packet->pa_lfr_bp_blk_nr[1] = blkNr; // BLK_NR LSB
415 426 }
416 427
417 428 void BP_send(char *data, rtems_id queue_id, unsigned int nbBytesToSend, unsigned int sid )
418 429 {
419 430 rtems_status_code status;
420 431
421 432 // SEND PACKET
422 433 status = rtems_message_queue_send( queue_id, data, nbBytesToSend);
423 434 if (status != RTEMS_SUCCESSFUL)
424 435 {
425 436 PRINTF1("ERR *** in BP_send *** ERR %d\n", (int) status)
426 437 }
427 438 }
428 439
429 440 void BP_send_s1_s2(char *data, rtems_id queue_id, unsigned int nbBytesToSend, unsigned int sid )
430 441 {
431 442 /** This function is used to send the BP paquets when needed.
432 443 *
433 444 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
434 445 *
435 446 * @return void
436 447 *
437 448 * SBM1 and SBM2 paquets are sent depending on the type of the LFR mode transition.
438 449 * BURST paquets are sent everytime.
439 450 *
440 451 */
441 452
442 453 rtems_status_code status;
443 454
444 455 // SEND PACKET
445 456 // before lastValidTransitionDate, the data are drops even if they are ready
446 457 // this guarantees that no SBM packets will be received before the requested enter mode time
447 458 if ( time_management_regs->coarse_time >= lastValidEnterModeTime)
448 459 {
449 460 status = rtems_message_queue_send( queue_id, data, nbBytesToSend);
450 461 if (status != RTEMS_SUCCESSFUL)
451 462 {
452 463 PRINTF1("ERR *** in BP_send *** ERR %d\n", (int) status)
453 464 }
454 465 }
455 466 }
456 467
457 468 //******************
458 469 // general functions
459 470
460 471 void reset_sm_status( void )
461 472 {
462 473 // error
463 474 // 10 --------------- 9 ---------------- 8 ---------------- 7 ---------
464 475 // input_fif0_write_2 input_fifo_write_1 input_fifo_write_0 buffer_full
465 476 // ---------- 5 -- 4 -- 3 -- 2 -- 1 -- 0 --
466 477 // ready bits f2_1 f2_0 f1_1 f1_1 f0_1 f0_0
467 478
468 479 spectral_matrix_regs->status = 0x7ff; // [0111 1111 1111]
469 480 }
470 481
471 482 void reset_spectral_matrix_regs( void )
472 483 {
473 484 /** This function resets the spectral matrices module registers.
474 485 *
475 486 * The registers affected by this function are located at the following offset addresses:
476 487 *
477 488 * - 0x00 config
478 489 * - 0x04 status
479 490 * - 0x08 matrixF0_Address0
480 491 * - 0x10 matrixFO_Address1
481 492 * - 0x14 matrixF1_Address
482 493 * - 0x18 matrixF2_Address
483 494 *
484 495 */
485 496
486 497 set_sm_irq_onError( 0 );
487 498
488 499 set_sm_irq_onNewMatrix( 0 );
489 500
490 501 reset_sm_status();
491 502
492 503 // F1
493 504 spectral_matrix_regs->f0_0_address = current_ring_node_sm_f0->previous->buffer_address;
494 505 spectral_matrix_regs->f0_1_address = current_ring_node_sm_f0->buffer_address;
495 506 // F2
496 507 spectral_matrix_regs->f1_0_address = current_ring_node_sm_f1->previous->buffer_address;
497 508 spectral_matrix_regs->f1_1_address = current_ring_node_sm_f1->buffer_address;
498 509 // F3
499 510 spectral_matrix_regs->f2_0_address = current_ring_node_sm_f2->previous->buffer_address;
500 511 spectral_matrix_regs->f2_1_address = current_ring_node_sm_f2->buffer_address;
501 512
502 513 spectral_matrix_regs->matrix_length = 0xc8; // 25 * 128 / 16 = 200 = 0xc8
503 514 }
504 515
505 516 void set_time( unsigned char *time, unsigned char * timeInBuffer )
506 517 {
507 518 time[0] = timeInBuffer[0];
508 519 time[1] = timeInBuffer[1];
509 520 time[2] = timeInBuffer[2];
510 521 time[3] = timeInBuffer[3];
511 522 time[4] = timeInBuffer[6];
512 523 time[5] = timeInBuffer[7];
513 524 }
514 525
515 526 unsigned long long int get_acquisition_time( unsigned char *timePtr )
516 527 {
517 528 unsigned long long int acquisitionTimeAslong;
518 529 acquisitionTimeAslong = 0x00;
519 530 acquisitionTimeAslong = ( (unsigned long long int) (timePtr[0] & 0x7f) << 40 ) // [0111 1111] mask the synchronization bit
520 531 + ( (unsigned long long int) timePtr[1] << 32 )
521 532 + ( (unsigned long long int) timePtr[2] << 24 )
522 533 + ( (unsigned long long int) timePtr[3] << 16 )
523 534 + ( (unsigned long long int) timePtr[6] << 8 )
524 535 + ( (unsigned long long int) timePtr[7] );
525 536 return acquisitionTimeAslong;
526 537 }
527 538
528 539 unsigned char getSID( rtems_event_set event )
529 540 {
530 541 unsigned char sid;
531 542
532 543 rtems_event_set eventSetBURST;
533 544 rtems_event_set eventSetSBM;
534 545
535 546 //******
536 547 // BURST
537 548 eventSetBURST = RTEMS_EVENT_BURST_BP1_F0
538 549 | RTEMS_EVENT_BURST_BP1_F1
539 550 | RTEMS_EVENT_BURST_BP2_F0
540 551 | RTEMS_EVENT_BURST_BP2_F1;
541 552
542 553 //****
543 554 // SBM
544 555 eventSetSBM = RTEMS_EVENT_SBM_BP1_F0
545 556 | RTEMS_EVENT_SBM_BP1_F1
546 557 | RTEMS_EVENT_SBM_BP2_F0
547 558 | RTEMS_EVENT_SBM_BP2_F1;
548 559
549 560 if (event & eventSetBURST)
550 561 {
551 562 sid = SID_BURST_BP1_F0;
552 563 }
553 564 else if (event & eventSetSBM)
554 565 {
555 566 sid = SID_SBM1_BP1_F0;
556 567 }
557 568 else
558 569 {
559 570 sid = 0;
560 571 }
561 572
562 573 return sid;
563 574 }
564 575
565 576 void extractReImVectors( float *inputASM, float *outputASM, unsigned int asmComponent )
566 577 {
567 578 unsigned int i;
568 579 float re;
569 580 float im;
570 581
571 582 for (i=0; i<NB_BINS_PER_SM; i++){
572 583 re = inputASM[ (asmComponent*NB_BINS_PER_SM) + i * 2 ];
573 584 im = inputASM[ (asmComponent*NB_BINS_PER_SM) + i * 2 + 1];
574 585 outputASM[ (asmComponent *NB_BINS_PER_SM) + i] = re;
575 586 outputASM[ (asmComponent+1)*NB_BINS_PER_SM + i] = im;
576 587 }
577 588 }
578 589
579 590 void copyReVectors( float *inputASM, float *outputASM, unsigned int asmComponent )
580 591 {
581 592 unsigned int i;
582 593 float re;
583 594
584 595 for (i=0; i<NB_BINS_PER_SM; i++){
585 596 re = inputASM[ (asmComponent*NB_BINS_PER_SM) + i];
586 597 outputASM[ (asmComponent*NB_BINS_PER_SM) + i] = re;
587 598 }
588 599 }
589 600
590 601 void ASM_patch( float *inputASM, float *outputASM )
591 602 {
592 603 extractReImVectors( inputASM, outputASM, 1); // b1b2
593 604 extractReImVectors( inputASM, outputASM, 3 ); // b1b3
594 605 extractReImVectors( inputASM, outputASM, 5 ); // b1e1
595 606 extractReImVectors( inputASM, outputASM, 7 ); // b1e2
596 607 extractReImVectors( inputASM, outputASM, 10 ); // b2b3
597 608 extractReImVectors( inputASM, outputASM, 12 ); // b2e1
598 609 extractReImVectors( inputASM, outputASM, 14 ); // b2e2
599 610 extractReImVectors( inputASM, outputASM, 17 ); // b3e1
600 611 extractReImVectors( inputASM, outputASM, 19 ); // b3e2
601 612 extractReImVectors( inputASM, outputASM, 22 ); // e1e2
602 613
603 614 copyReVectors(inputASM, outputASM, 0 ); // b1b1
604 615 copyReVectors(inputASM, outputASM, 9 ); // b2b2
605 616 copyReVectors(inputASM, outputASM, 16); // b3b3
606 617 copyReVectors(inputASM, outputASM, 21); // e1e1
607 618 copyReVectors(inputASM, outputASM, 24); // e2e2
608 619 }
609 620
610 621 void ASM_compress_reorganize_and_divide_mask(float *averaged_spec_mat, float *compressed_spec_mat , float divider,
611 622 unsigned char nbBinsCompressedMatrix, unsigned char nbBinsToAverage,
612 623 unsigned char ASMIndexStart,
613 624 unsigned char channel )
614 625 {
615 626 //*************
616 627 // input format
617 628 // component0[0 .. 127] component1[0 .. 127] .. component24[0 .. 127]
618 629 //**************
619 630 // output format
620 631 // matr0[0 .. 24] matr1[0 .. 24] .. matr127[0 .. 24]
621 632 //************
622 633 // compression
623 634 // matr0[0 .. 24] matr1[0 .. 24] .. matr11[0 .. 24] => f0 NORM
624 635 // matr0[0 .. 24] matr1[0 .. 24] .. matr22[0 .. 24] => f0 BURST, SBM
625 636
626 637 int frequencyBin;
627 638 int asmComponent;
628 639 int offsetASM;
629 640 int offsetCompressed;
630 641 int offsetFBin;
631 642 int fBinMask;
632 643 int k;
633 644
634 645 // BUILD DATA
635 646 for (asmComponent = 0; asmComponent < NB_VALUES_PER_SM; asmComponent++)
636 647 {
637 648 for( frequencyBin = 0; frequencyBin < nbBinsCompressedMatrix; frequencyBin++ )
638 649 {
639 650 offsetCompressed = // NO TIME OFFSET
640 651 frequencyBin * NB_VALUES_PER_SM
641 652 + asmComponent;
642 653 offsetASM = // NO TIME OFFSET
643 654 asmComponent * NB_BINS_PER_SM
644 655 + ASMIndexStart
645 656 + frequencyBin * nbBinsToAverage;
646 657 offsetFBin = ASMIndexStart
647 658 + frequencyBin * nbBinsToAverage;
648 659 compressed_spec_mat[ offsetCompressed ] = 0;
649 660 for ( k = 0; k < nbBinsToAverage; k++ )
650 661 {
651 662 fBinMask = getFBinMask( offsetFBin + k, channel );
652 663 compressed_spec_mat[offsetCompressed ] =
653 664 ( compressed_spec_mat[ offsetCompressed ]
654 665 + averaged_spec_mat[ offsetASM + k ] * fBinMask );
655 666 }
656 667 compressed_spec_mat[ offsetCompressed ] =
657 668 compressed_spec_mat[ offsetCompressed ] / (divider * nbBinsToAverage);
658 669 }
659 670 }
660 671
661 672 }
662 673
663 674 int getFBinMask( int index, unsigned char channel )
664 675 {
665 676 unsigned int indexInChar;
666 677 unsigned int indexInTheChar;
667 678 int fbin;
668 679 unsigned char *sy_lfr_fbins_fx_word1;
669 680
670 681 sy_lfr_fbins_fx_word1 = parameter_dump_packet.sy_lfr_fbins_f0_word1;
671 682
672 683 switch(channel)
673 684 {
674 685 case 0:
675 686 sy_lfr_fbins_fx_word1 = parameter_dump_packet.sy_lfr_fbins_f0_word1;
676 687 break;
677 688 case 1:
678 689 sy_lfr_fbins_fx_word1 = parameter_dump_packet.sy_lfr_fbins_f1_word1;
679 690 break;
680 691 case 2:
681 692 sy_lfr_fbins_fx_word1 = parameter_dump_packet.sy_lfr_fbins_f2_word1;
682 693 break;
683 694 default:
684 695 PRINTF("ERR *** in getFBinMask, wrong frequency channel")
685 696 }
686 697
687 698 indexInChar = index >> 3;
688 699 indexInTheChar = index - indexInChar * 8;
689 700
690 701 fbin = (int) ((sy_lfr_fbins_fx_word1[ NB_BYTES_PER_FREQ_MASK - 1 - indexInChar] >> indexInTheChar) & 0x1);
691 702
692 703 return fbin;
693 704 }
694 705
695 706 void init_kcoeff_sbm_from_kcoeff_norm(float *input_kcoeff, float *output_kcoeff, unsigned char nb_bins_norm)
696 707 {
697 708 unsigned char bin;
698 709 unsigned char kcoeff;
699 710
700 711 for (bin=0; bin<nb_bins_norm; bin++)
701 712 {
702 713 for (kcoeff=0; kcoeff<NB_K_COEFF_PER_BIN; kcoeff++)
703 714 {
704 715 output_kcoeff[ (bin*NB_K_COEFF_PER_BIN + kcoeff)*2 ] = input_kcoeff[ bin*NB_K_COEFF_PER_BIN + kcoeff ];
705 716 output_kcoeff[ (bin*NB_K_COEFF_PER_BIN + kcoeff)*2 + 1 ] = input_kcoeff[ bin*NB_K_COEFF_PER_BIN + kcoeff ];
706 717 }
707 718 }
708 719 }
@@ -1,1305 +1,1310
1 1 /** Functions and tasks related to waveform packet generation.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * A group of functions to handle waveforms, in snapshot or continuous format.\n
7 7 *
8 8 */
9 9
10 10 #include "wf_handler.h"
11 11
12 12 //***************
13 13 // waveform rings
14 14 // F0
15 15 ring_node waveform_ring_f0[NB_RING_NODES_F0];
16 16 ring_node *current_ring_node_f0;
17 17 ring_node *ring_node_to_send_swf_f0;
18 18 // F1
19 19 ring_node waveform_ring_f1[NB_RING_NODES_F1];
20 20 ring_node *current_ring_node_f1;
21 21 ring_node *ring_node_to_send_swf_f1;
22 22 ring_node *ring_node_to_send_cwf_f1;
23 23 // F2
24 24 ring_node waveform_ring_f2[NB_RING_NODES_F2];
25 25 ring_node *current_ring_node_f2;
26 26 ring_node *ring_node_to_send_swf_f2;
27 27 ring_node *ring_node_to_send_cwf_f2;
28 28 // F3
29 29 ring_node waveform_ring_f3[NB_RING_NODES_F3];
30 30 ring_node *current_ring_node_f3;
31 31 ring_node *ring_node_to_send_cwf_f3;
32 32 char wf_cont_f3_light[ (NB_SAMPLES_PER_SNAPSHOT) * NB_BYTES_CWF3_LIGHT_BLK ];
33 33
34 34 bool extractSWF1 = false;
35 35 bool extractSWF2 = false;
36 36 bool swf0_ready_flag_f1 = false;
37 37 bool swf0_ready_flag_f2 = false;
38 38 bool swf1_ready = false;
39 39 bool swf2_ready = false;
40 40
41 41 int swf1_extracted[ (NB_SAMPLES_PER_SNAPSHOT * NB_WORDS_SWF_BLK) ];
42 42 int swf2_extracted[ (NB_SAMPLES_PER_SNAPSHOT * NB_WORDS_SWF_BLK) ];
43 43 ring_node ring_node_swf1_extracted;
44 44 ring_node ring_node_swf2_extracted;
45 45
46 46 typedef enum resynchro_state_t
47 47 {
48 48 MEASURE_0,
49 49 MEASURE_1,
50 50 CORRECTION_0,
51 51 CORRECTION_1
52 52 } resynchro_state;
53 53
54 54 //*********************
55 55 // Interrupt SubRoutine
56 56
57 57 ring_node * getRingNodeToSendCWF( unsigned char frequencyChannel)
58 58 {
59 59 ring_node *node;
60 60
61 61 node = NULL;
62 62 switch ( frequencyChannel ) {
63 63 case 1:
64 64 node = ring_node_to_send_cwf_f1;
65 65 break;
66 66 case 2:
67 67 node = ring_node_to_send_cwf_f2;
68 68 break;
69 69 case 3:
70 70 node = ring_node_to_send_cwf_f3;
71 71 break;
72 72 default:
73 73 break;
74 74 }
75 75
76 76 return node;
77 77 }
78 78
79 79 ring_node * getRingNodeToSendSWF( unsigned char frequencyChannel)
80 80 {
81 81 ring_node *node;
82 82
83 83 node = NULL;
84 84 switch ( frequencyChannel ) {
85 85 case 0:
86 86 node = ring_node_to_send_swf_f0;
87 87 break;
88 88 case 1:
89 89 node = ring_node_to_send_swf_f1;
90 90 break;
91 91 case 2:
92 92 node = ring_node_to_send_swf_f2;
93 93 break;
94 94 default:
95 95 break;
96 96 }
97 97
98 98 return node;
99 99 }
100 100
101 101 void reset_extractSWF( void )
102 102 {
103 103 extractSWF1 = false;
104 104 extractSWF2 = false;
105 105 swf0_ready_flag_f1 = false;
106 106 swf0_ready_flag_f2 = false;
107 107 swf1_ready = false;
108 108 swf2_ready = false;
109 109 }
110 110
111 111 inline void waveforms_isr_f3( void )
112 112 {
113 113 rtems_status_code spare_status;
114 114
115 115 if ( (lfrCurrentMode == LFR_MODE_NORMAL) || (lfrCurrentMode == LFR_MODE_BURST) // in BURST the data are used to place v, e1 and e2 in the HK packet
116 116 || (lfrCurrentMode == LFR_MODE_SBM1) || (lfrCurrentMode == LFR_MODE_SBM2) )
117 117 { // in modes other than STANDBY and BURST, send the CWF_F3 data
118 118 //***
119 119 // F3
120 120 if ( (waveform_picker_regs->status & 0xc0) != 0x00 ) { // [1100 0000] check the f3 full bits
121 121 ring_node_to_send_cwf_f3 = current_ring_node_f3->previous;
122 122 current_ring_node_f3 = current_ring_node_f3->next;
123 123 if ((waveform_picker_regs->status & 0x40) == 0x40){ // [0100 0000] f3 buffer 0 is full
124 124 ring_node_to_send_cwf_f3->coarseTime = waveform_picker_regs->f3_0_coarse_time;
125 125 ring_node_to_send_cwf_f3->fineTime = waveform_picker_regs->f3_0_fine_time;
126 126 waveform_picker_regs->addr_data_f3_0 = current_ring_node_f3->buffer_address;
127 127 waveform_picker_regs->status = waveform_picker_regs->status & 0x00008840; // [1000 1000 0100 0000]
128 128 }
129 129 else if ((waveform_picker_regs->status & 0x80) == 0x80){ // [1000 0000] f3 buffer 1 is full
130 130 ring_node_to_send_cwf_f3->coarseTime = waveform_picker_regs->f3_1_coarse_time;
131 131 ring_node_to_send_cwf_f3->fineTime = waveform_picker_regs->f3_1_fine_time;
132 132 waveform_picker_regs->addr_data_f3_1 = current_ring_node_f3->buffer_address;
133 133 waveform_picker_regs->status = waveform_picker_regs->status & 0x00008880; // [1000 1000 1000 0000]
134 134 }
135 135 if (rtems_event_send( Task_id[TASKID_CWF3], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) {
136 136 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 );
137 137 }
138 138 }
139 139 }
140 140 }
141 141
142 142 inline void waveforms_isr_burst( void )
143 143 {
144 144 unsigned char status;
145 145 rtems_status_code spare_status;
146 146
147 147 status = (waveform_picker_regs->status & 0x30) >> 4; // [0011 0000] get the status bits for f2
148 148
149 149
150 150 switch(status)
151 151 {
152 152 case 1:
153 153 ring_node_to_send_cwf_f2 = current_ring_node_f2->previous;
154 154 ring_node_to_send_cwf_f2->sid = SID_BURST_CWF_F2;
155 155 ring_node_to_send_cwf_f2->coarseTime = waveform_picker_regs->f2_0_coarse_time;
156 156 ring_node_to_send_cwf_f2->fineTime = waveform_picker_regs->f2_0_fine_time;
157 157 current_ring_node_f2 = current_ring_node_f2->next;
158 158 waveform_picker_regs->addr_data_f2_0 = current_ring_node_f2->buffer_address;
159 159 if (rtems_event_send( Task_id[TASKID_CWF2], RTEMS_EVENT_MODE_BURST ) != RTEMS_SUCCESSFUL) {
160 160 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 );
161 161 }
162 162 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004410; // [0100 0100 0001 0000]
163 163 break;
164 164 case 2:
165 165 ring_node_to_send_cwf_f2 = current_ring_node_f2->previous;
166 166 ring_node_to_send_cwf_f2->sid = SID_BURST_CWF_F2;
167 167 ring_node_to_send_cwf_f2->coarseTime = waveform_picker_regs->f2_1_coarse_time;
168 168 ring_node_to_send_cwf_f2->fineTime = waveform_picker_regs->f2_1_fine_time;
169 169 current_ring_node_f2 = current_ring_node_f2->next;
170 170 waveform_picker_regs->addr_data_f2_1 = current_ring_node_f2->buffer_address;
171 171 if (rtems_event_send( Task_id[TASKID_CWF2], RTEMS_EVENT_MODE_BURST ) != RTEMS_SUCCESSFUL) {
172 172 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 );
173 173 }
174 174 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004420; // [0100 0100 0010 0000]
175 175 break;
176 176 default:
177 177 break;
178 178 }
179 179 }
180 180
181 181 inline void waveform_isr_normal_sbm1_sbm2( void )
182 182 {
183 183 rtems_status_code status;
184 184
185 185 //***
186 186 // F0
187 187 if ( (waveform_picker_regs->status & 0x03) != 0x00 ) // [0000 0011] check the f0 full bits
188 188 {
189 189 swf0_ready_flag_f1 = true;
190 190 swf0_ready_flag_f2 = true;
191 191 ring_node_to_send_swf_f0 = current_ring_node_f0->previous;
192 192 current_ring_node_f0 = current_ring_node_f0->next;
193 193 if ( (waveform_picker_regs->status & 0x01) == 0x01)
194 194 {
195 195
196 196 ring_node_to_send_swf_f0->coarseTime = waveform_picker_regs->f0_0_coarse_time;
197 197 ring_node_to_send_swf_f0->fineTime = waveform_picker_regs->f0_0_fine_time;
198 198 waveform_picker_regs->addr_data_f0_0 = current_ring_node_f0->buffer_address;
199 199 waveform_picker_regs->status = waveform_picker_regs->status & 0x00001101; // [0001 0001 0000 0001]
200 200 }
201 201 else if ( (waveform_picker_regs->status & 0x02) == 0x02)
202 202 {
203 203 ring_node_to_send_swf_f0->coarseTime = waveform_picker_regs->f0_1_coarse_time;
204 204 ring_node_to_send_swf_f0->fineTime = waveform_picker_regs->f0_1_fine_time;
205 205 waveform_picker_regs->addr_data_f0_1 = current_ring_node_f0->buffer_address;
206 206 waveform_picker_regs->status = waveform_picker_regs->status & 0x00001102; // [0001 0001 0000 0010]
207 207 }
208 208 }
209 209
210 210 //***
211 211 // F1
212 212 if ( (waveform_picker_regs->status & 0x0c) != 0x00 ) { // [0000 1100] check the f1 full bits
213 213 // (1) change the receiving buffer for the waveform picker
214 214 ring_node_to_send_cwf_f1 = current_ring_node_f1->previous;
215 215 current_ring_node_f1 = current_ring_node_f1->next;
216 216 if ( (waveform_picker_regs->status & 0x04) == 0x04)
217 217 {
218 218 ring_node_to_send_cwf_f1->coarseTime = waveform_picker_regs->f1_0_coarse_time;
219 219 ring_node_to_send_cwf_f1->fineTime = waveform_picker_regs->f1_0_fine_time;
220 220 waveform_picker_regs->addr_data_f1_0 = current_ring_node_f1->buffer_address;
221 221 waveform_picker_regs->status = waveform_picker_regs->status & 0x00002204; // [0010 0010 0000 0100] f1 bits = 0
222 222 }
223 223 else if ( (waveform_picker_regs->status & 0x08) == 0x08)
224 224 {
225 225 ring_node_to_send_cwf_f1->coarseTime = waveform_picker_regs->f1_1_coarse_time;
226 226 ring_node_to_send_cwf_f1->fineTime = waveform_picker_regs->f1_1_fine_time;
227 227 waveform_picker_regs->addr_data_f1_1 = current_ring_node_f1->buffer_address;
228 228 waveform_picker_regs->status = waveform_picker_regs->status & 0x00002208; // [0010 0010 0000 1000] f1 bits = 0
229 229 }
230 230 // (2) send an event for the the CWF1 task for transmission (and snapshot extraction if needed)
231 231 status = rtems_event_send( Task_id[TASKID_CWF1], RTEMS_EVENT_MODE_NORM_S1_S2 );
232 232 }
233 233
234 234 //***
235 235 // F2
236 236 if ( (waveform_picker_regs->status & 0x30) != 0x00 ) { // [0011 0000] check the f2 full bit
237 237 // (1) change the receiving buffer for the waveform picker
238 238 ring_node_to_send_cwf_f2 = current_ring_node_f2->previous;
239 239 ring_node_to_send_cwf_f2->sid = SID_SBM2_CWF_F2;
240 240 current_ring_node_f2 = current_ring_node_f2->next;
241 241 if ( (waveform_picker_regs->status & 0x10) == 0x10)
242 242 {
243 243 ring_node_to_send_cwf_f2->coarseTime = waveform_picker_regs->f2_0_coarse_time;
244 244 ring_node_to_send_cwf_f2->fineTime = waveform_picker_regs->f2_0_fine_time;
245 245 waveform_picker_regs->addr_data_f2_0 = current_ring_node_f2->buffer_address;
246 246 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004410; // [0100 0100 0001 0000]
247 247 }
248 248 else if ( (waveform_picker_regs->status & 0x20) == 0x20)
249 249 {
250 250 ring_node_to_send_cwf_f2->coarseTime = waveform_picker_regs->f2_1_coarse_time;
251 251 ring_node_to_send_cwf_f2->fineTime = waveform_picker_regs->f2_1_fine_time;
252 252 waveform_picker_regs->addr_data_f2_1 = current_ring_node_f2->buffer_address;
253 253 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004420; // [0100 0100 0010 0000]
254 254 }
255 255 // (2) send an event for the waveforms transmission
256 256 status = rtems_event_send( Task_id[TASKID_CWF2], RTEMS_EVENT_MODE_NORM_S1_S2 );
257 257 }
258 258 }
259 259
260 260 rtems_isr waveforms_isr( rtems_vector_number vector )
261 261 {
262 262 /** This is the interrupt sub routine called by the waveform picker core.
263 263 *
264 264 * This ISR launch different actions depending mainly on two pieces of information:
265 265 * 1. the values read in the registers of the waveform picker.
266 266 * 2. the current LFR mode.
267 267 *
268 268 */
269 269
270 270 // STATUS
271 271 // new error error buffer full
272 272 // 15 14 13 12 11 10 9 8
273 273 // f3 f2 f1 f0 f3 f2 f1 f0
274 274 //
275 275 // ready buffer
276 276 // 7 6 5 4 3 2 1 0
277 277 // f3_1 f3_0 f2_1 f2_0 f1_1 f1_0 f0_1 f0_0
278 278
279 279 rtems_status_code spare_status;
280 280
281 281 waveforms_isr_f3();
282 282
283 //*************************************************
284 // copy the status bits in the housekeeping packets
285 housekeeping_packet.hk_lfr_vhdl_iir_cal =
286 (unsigned char) ((waveform_picker_regs->status & 0xff00) >> 8);
287
283 288 if ( (waveform_picker_regs->status & 0xff00) != 0x00) // [1111 1111 0000 0000] check the error bits
284 289 {
285 290 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_10 );
286 291 }
287 292
288 293 switch(lfrCurrentMode)
289 294 {
290 295 //********
291 296 // STANDBY
292 297 case LFR_MODE_STANDBY:
293 298 break;
294 299 //**************************
295 300 // LFR NORMAL, SBM1 and SBM2
296 301 case LFR_MODE_NORMAL:
297 302 case LFR_MODE_SBM1:
298 303 case LFR_MODE_SBM2:
299 304 waveform_isr_normal_sbm1_sbm2();
300 305 break;
301 306 //******
302 307 // BURST
303 308 case LFR_MODE_BURST:
304 309 waveforms_isr_burst();
305 310 break;
306 311 //********
307 312 // DEFAULT
308 313 default:
309 314 break;
310 315 }
311 316 }
312 317
313 318 //************
314 319 // RTEMS TASKS
315 320
316 321 rtems_task wfrm_task(rtems_task_argument argument) //used with the waveform picker VHDL IP
317 322 {
318 323 /** This RTEMS task is dedicated to the transmission of snapshots of the NORMAL mode.
319 324 *
320 325 * @param unused is the starting argument of the RTEMS task
321 326 *
322 327 * The following data packets are sent by this task:
323 328 * - TM_LFR_SCIENCE_NORMAL_SWF_F0
324 329 * - TM_LFR_SCIENCE_NORMAL_SWF_F1
325 330 * - TM_LFR_SCIENCE_NORMAL_SWF_F2
326 331 *
327 332 */
328 333
329 334 rtems_event_set event_out;
330 335 rtems_id queue_id;
331 336 rtems_status_code status;
332 337 ring_node *ring_node_swf1_extracted_ptr;
333 338 ring_node *ring_node_swf2_extracted_ptr;
334 339
335 340 ring_node_swf1_extracted_ptr = (ring_node *) &ring_node_swf1_extracted;
336 341 ring_node_swf2_extracted_ptr = (ring_node *) &ring_node_swf2_extracted;
337 342
338 343 status = get_message_queue_id_send( &queue_id );
339 344 if (status != RTEMS_SUCCESSFUL)
340 345 {
341 346 PRINTF1("in WFRM *** ERR get_message_queue_id_send %d\n", status);
342 347 }
343 348
344 349 BOOT_PRINTF("in WFRM ***\n");
345 350
346 351 while(1){
347 352 // wait for an RTEMS_EVENT
348 353 rtems_event_receive(RTEMS_EVENT_MODE_NORMAL,
349 354 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
350 355
351 356 snapshot_resynchronization( (unsigned char *) &ring_node_to_send_swf_f0->coarseTime );
352 357
353 358 if (event_out == RTEMS_EVENT_MODE_NORMAL)
354 359 {
355 360 DEBUG_PRINTF("WFRM received RTEMS_EVENT_MODE_SBM2\n");
356 361 ring_node_to_send_swf_f0->sid = SID_NORM_SWF_F0;
357 362 ring_node_swf1_extracted_ptr->sid = SID_NORM_SWF_F1;
358 363 ring_node_swf2_extracted_ptr->sid = SID_NORM_SWF_F2;
359 364 status = rtems_message_queue_send( queue_id, &ring_node_to_send_swf_f0, sizeof( ring_node* ) );
360 365 status = rtems_message_queue_send( queue_id, &ring_node_swf1_extracted_ptr, sizeof( ring_node* ) );
361 366 status = rtems_message_queue_send( queue_id, &ring_node_swf2_extracted_ptr, sizeof( ring_node* ) );
362 367 }
363 368 }
364 369 }
365 370
366 371 rtems_task cwf3_task(rtems_task_argument argument) //used with the waveform picker VHDL IP
367 372 {
368 373 /** This RTEMS task is dedicated to the transmission of continuous waveforms at f3.
369 374 *
370 375 * @param unused is the starting argument of the RTEMS task
371 376 *
372 377 * The following data packet is sent by this task:
373 378 * - TM_LFR_SCIENCE_NORMAL_CWF_F3
374 379 *
375 380 */
376 381
377 382 rtems_event_set event_out;
378 383 rtems_id queue_id;
379 384 rtems_status_code status;
380 385 ring_node ring_node_cwf3_light;
381 386 ring_node *ring_node_to_send_cwf;
382 387
383 388 status = get_message_queue_id_send( &queue_id );
384 389 if (status != RTEMS_SUCCESSFUL)
385 390 {
386 391 PRINTF1("in CWF3 *** ERR get_message_queue_id_send %d\n", status)
387 392 }
388 393
389 394 ring_node_to_send_cwf_f3->sid = SID_NORM_CWF_LONG_F3;
390 395
391 396 // init the ring_node_cwf3_light structure
392 397 ring_node_cwf3_light.buffer_address = (int) wf_cont_f3_light;
393 398 ring_node_cwf3_light.coarseTime = 0x00;
394 399 ring_node_cwf3_light.fineTime = 0x00;
395 400 ring_node_cwf3_light.next = NULL;
396 401 ring_node_cwf3_light.previous = NULL;
397 402 ring_node_cwf3_light.sid = SID_NORM_CWF_F3;
398 403 ring_node_cwf3_light.status = 0x00;
399 404
400 405 BOOT_PRINTF("in CWF3 ***\n")
401 406
402 407 while(1){
403 408 // wait for an RTEMS_EVENT
404 409 rtems_event_receive( RTEMS_EVENT_0,
405 410 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
406 411 if ( (lfrCurrentMode == LFR_MODE_NORMAL)
407 412 || (lfrCurrentMode == LFR_MODE_SBM1) || (lfrCurrentMode==LFR_MODE_SBM2) )
408 413 {
409 414 ring_node_to_send_cwf = getRingNodeToSendCWF( 3 );
410 415 if ( (parameter_dump_packet.sy_lfr_n_cwf_long_f3 & 0x01) == 0x01)
411 416 {
412 417 PRINTF("send CWF_LONG_F3\n")
413 418 ring_node_to_send_cwf_f3->sid = SID_NORM_CWF_LONG_F3;
414 419 status = rtems_message_queue_send( queue_id, &ring_node_to_send_cwf, sizeof( ring_node* ) );
415 420 }
416 421 else
417 422 {
418 423 PRINTF("send CWF_F3 (light)\n")
419 424 send_waveform_CWF3_light( ring_node_to_send_cwf, &ring_node_cwf3_light, queue_id );
420 425 }
421 426
422 427 }
423 428 else
424 429 {
425 430 PRINTF1("in CWF3 *** lfrCurrentMode is %d, no data will be sent\n", lfrCurrentMode)
426 431 }
427 432 }
428 433 }
429 434
430 435 rtems_task cwf2_task(rtems_task_argument argument) // ONLY USED IN BURST AND SBM2
431 436 {
432 437 /** This RTEMS task is dedicated to the transmission of continuous waveforms at f2.
433 438 *
434 439 * @param unused is the starting argument of the RTEMS task
435 440 *
436 441 * The following data packet is sent by this function:
437 442 * - TM_LFR_SCIENCE_BURST_CWF_F2
438 443 * - TM_LFR_SCIENCE_SBM2_CWF_F2
439 444 *
440 445 */
441 446
442 447 rtems_event_set event_out;
443 448 rtems_id queue_id;
444 449 rtems_status_code status;
445 450 ring_node *ring_node_to_send;
446 451 unsigned long long int acquisitionTimeF0_asLong;
447 452
448 453 acquisitionTimeF0_asLong = 0x00;
449 454
450 455 status = get_message_queue_id_send( &queue_id );
451 456 if (status != RTEMS_SUCCESSFUL)
452 457 {
453 458 PRINTF1("in CWF2 *** ERR get_message_queue_id_send %d\n", status)
454 459 }
455 460
456 461 BOOT_PRINTF("in CWF2 ***\n")
457 462
458 463 while(1){
459 464 // wait for an RTEMS_EVENT
460 465 rtems_event_receive( RTEMS_EVENT_MODE_NORM_S1_S2 | RTEMS_EVENT_MODE_BURST,
461 466 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
462 467 ring_node_to_send = getRingNodeToSendCWF( 2 );
463 468 if (event_out == RTEMS_EVENT_MODE_BURST)
464 469 {
465 470 status = rtems_message_queue_send( queue_id, &ring_node_to_send, sizeof( ring_node* ) );
466 471 }
467 472 else if (event_out == RTEMS_EVENT_MODE_NORM_S1_S2)
468 473 {
469 474 if ( lfrCurrentMode == LFR_MODE_SBM2 )
470 475 {
471 476 status = rtems_message_queue_send( queue_id, &ring_node_to_send, sizeof( ring_node* ) );
472 477 }
473 478 // launch snapshot extraction if needed
474 479 if (extractSWF2 == true)
475 480 {
476 481 ring_node_to_send_swf_f2 = ring_node_to_send_cwf_f2;
477 482 // extract the snapshot
478 483 build_snapshot_from_ring( ring_node_to_send_swf_f2, 2, acquisitionTimeF0_asLong,
479 484 &ring_node_swf2_extracted, swf2_extracted );
480 485 // send the snapshot when built
481 486 status = rtems_event_send( Task_id[TASKID_WFRM], RTEMS_EVENT_MODE_SBM2 );
482 487 extractSWF2 = false;
483 488 swf2_ready = true;
484 489 }
485 490 if (swf0_ready_flag_f2 == true)
486 491 {
487 492 extractSWF2 = true;
488 493 // record the acquition time of the f0 snapshot to use to build the snapshot at f2
489 494 acquisitionTimeF0_asLong = get_acquisition_time( (unsigned char *) &ring_node_to_send_swf_f0->coarseTime );
490 495 swf0_ready_flag_f2 = false;
491 496 }
492 497 }
493 498 }
494 499 }
495 500
496 501 rtems_task cwf1_task(rtems_task_argument argument) // ONLY USED IN SBM1
497 502 {
498 503 /** This RTEMS task is dedicated to the transmission of continuous waveforms at f1.
499 504 *
500 505 * @param unused is the starting argument of the RTEMS task
501 506 *
502 507 * The following data packet is sent by this function:
503 508 * - TM_LFR_SCIENCE_SBM1_CWF_F1
504 509 *
505 510 */
506 511
507 512 rtems_event_set event_out;
508 513 rtems_id queue_id;
509 514 rtems_status_code status;
510 515
511 516 ring_node *ring_node_to_send_cwf;
512 517
513 518 status = get_message_queue_id_send( &queue_id );
514 519 if (status != RTEMS_SUCCESSFUL)
515 520 {
516 521 PRINTF1("in CWF1 *** ERR get_message_queue_id_send %d\n", status)
517 522 }
518 523
519 524 BOOT_PRINTF("in CWF1 ***\n");
520 525
521 526 while(1){
522 527 // wait for an RTEMS_EVENT
523 528 rtems_event_receive( RTEMS_EVENT_MODE_NORM_S1_S2,
524 529 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
525 530 ring_node_to_send_cwf = getRingNodeToSendCWF( 1 );
526 531 ring_node_to_send_cwf_f1->sid = SID_SBM1_CWF_F1;
527 532 if (lfrCurrentMode == LFR_MODE_SBM1)
528 533 {
529 534 status = rtems_message_queue_send( queue_id, &ring_node_to_send_cwf, sizeof( ring_node* ) );
530 535 if (status != 0)
531 536 {
532 537 PRINTF("cwf sending failed\n")
533 538 }
534 539 }
535 540 // launch snapshot extraction if needed
536 541 if (extractSWF1 == true)
537 542 {
538 543 ring_node_to_send_swf_f1 = ring_node_to_send_cwf;
539 544 // launch the snapshot extraction
540 545 status = rtems_event_send( Task_id[TASKID_SWBD], RTEMS_EVENT_MODE_NORM_S1_S2 );
541 546 extractSWF1 = false;
542 547 }
543 548 if (swf0_ready_flag_f1 == true)
544 549 {
545 550 extractSWF1 = true;
546 551 swf0_ready_flag_f1 = false; // this step shall be executed only one time
547 552 }
548 553 if ((swf1_ready == true) && (swf2_ready == true)) // swf_f1 is ready after the extraction
549 554 {
550 555 status = rtems_event_send( Task_id[TASKID_WFRM], RTEMS_EVENT_MODE_NORMAL );
551 556 swf1_ready = false;
552 557 swf2_ready = false;
553 558 }
554 559 }
555 560 }
556 561
557 562 rtems_task swbd_task(rtems_task_argument argument)
558 563 {
559 564 /** This RTEMS task is dedicated to the building of snapshots from different continuous waveforms buffers.
560 565 *
561 566 * @param unused is the starting argument of the RTEMS task
562 567 *
563 568 */
564 569
565 570 rtems_event_set event_out;
566 571 unsigned long long int acquisitionTimeF0_asLong;
567 572
568 573 acquisitionTimeF0_asLong = 0x00;
569 574
570 575 BOOT_PRINTF("in SWBD ***\n")
571 576
572 577 while(1){
573 578 // wait for an RTEMS_EVENT
574 579 rtems_event_receive( RTEMS_EVENT_MODE_NORM_S1_S2,
575 580 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
576 581 if (event_out == RTEMS_EVENT_MODE_NORM_S1_S2)
577 582 {
578 583 acquisitionTimeF0_asLong = get_acquisition_time( (unsigned char *) &ring_node_to_send_swf_f0->coarseTime );
579 584 build_snapshot_from_ring( ring_node_to_send_swf_f1, 1, acquisitionTimeF0_asLong,
580 585 &ring_node_swf1_extracted, swf1_extracted );
581 586 swf1_ready = true; // the snapshot has been extracted and is ready to be sent
582 587 }
583 588 else
584 589 {
585 590 PRINTF1("in SWBD *** unexpected rtems event received %x\n", (int) event_out)
586 591 }
587 592 }
588 593 }
589 594
590 595 //******************
591 596 // general functions
592 597
593 598 void WFP_init_rings( void )
594 599 {
595 600 // F0 RING
596 601 init_ring( waveform_ring_f0, NB_RING_NODES_F0, wf_buffer_f0, WFRM_BUFFER );
597 602 // F1 RING
598 603 init_ring( waveform_ring_f1, NB_RING_NODES_F1, wf_buffer_f1, WFRM_BUFFER );
599 604 // F2 RING
600 605 init_ring( waveform_ring_f2, NB_RING_NODES_F2, wf_buffer_f2, WFRM_BUFFER );
601 606 // F3 RING
602 607 init_ring( waveform_ring_f3, NB_RING_NODES_F3, wf_buffer_f3, WFRM_BUFFER );
603 608
604 609 ring_node_swf1_extracted.buffer_address = (int) swf1_extracted;
605 610 ring_node_swf2_extracted.buffer_address = (int) swf2_extracted;
606 611
607 612 DEBUG_PRINTF1("waveform_ring_f0 @%x\n", (unsigned int) waveform_ring_f0)
608 613 DEBUG_PRINTF1("waveform_ring_f1 @%x\n", (unsigned int) waveform_ring_f1)
609 614 DEBUG_PRINTF1("waveform_ring_f2 @%x\n", (unsigned int) waveform_ring_f2)
610 615 DEBUG_PRINTF1("waveform_ring_f3 @%x\n", (unsigned int) waveform_ring_f3)
611 616 DEBUG_PRINTF1("wf_buffer_f0 @%x\n", (unsigned int) wf_buffer_f0)
612 617 DEBUG_PRINTF1("wf_buffer_f1 @%x\n", (unsigned int) wf_buffer_f1)
613 618 DEBUG_PRINTF1("wf_buffer_f2 @%x\n", (unsigned int) wf_buffer_f2)
614 619 DEBUG_PRINTF1("wf_buffer_f3 @%x\n", (unsigned int) wf_buffer_f3)
615 620
616 621 }
617 622
618 623 void WFP_reset_current_ring_nodes( void )
619 624 {
620 625 current_ring_node_f0 = waveform_ring_f0[0].next;
621 626 current_ring_node_f1 = waveform_ring_f1[0].next;
622 627 current_ring_node_f2 = waveform_ring_f2[0].next;
623 628 current_ring_node_f3 = waveform_ring_f3[0].next;
624 629
625 630 ring_node_to_send_swf_f0 = waveform_ring_f0;
626 631 ring_node_to_send_swf_f1 = waveform_ring_f1;
627 632 ring_node_to_send_swf_f2 = waveform_ring_f2;
628 633
629 634 ring_node_to_send_cwf_f1 = waveform_ring_f1;
630 635 ring_node_to_send_cwf_f2 = waveform_ring_f2;
631 636 ring_node_to_send_cwf_f3 = waveform_ring_f3;
632 637 }
633 638
634 639 int send_waveform_CWF3_light( ring_node *ring_node_to_send, ring_node *ring_node_cwf3_light, rtems_id queue_id )
635 640 {
636 641 /** This function sends CWF_F3 CCSDS packets without the b1, b2 and b3 data.
637 642 *
638 643 * @param waveform points to the buffer containing the data that will be send.
639 644 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
640 645 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
641 646 * contain information to setup the transmission of the data packets.
642 647 *
643 648 * By default, CWF_F3 packet are send without the b1, b2 and b3 data. This function rebuilds a data buffer
644 649 * from the incoming data and sends it in 7 packets, 6 containing 340 blocks and 1 one containing 8 blocks.
645 650 *
646 651 */
647 652
648 653 unsigned int i;
649 654 int ret;
650 655 rtems_status_code status;
651 656
652 657 char *sample;
653 658 int *dataPtr;
654 659
655 660 ret = LFR_DEFAULT;
656 661
657 662 dataPtr = (int*) ring_node_to_send->buffer_address;
658 663
659 664 ring_node_cwf3_light->coarseTime = ring_node_to_send->coarseTime;
660 665 ring_node_cwf3_light->fineTime = ring_node_to_send->fineTime;
661 666
662 667 //**********************
663 668 // BUILD CWF3_light DATA
664 669 for ( i=0; i< NB_SAMPLES_PER_SNAPSHOT; i++)
665 670 {
666 671 sample = (char*) &dataPtr[ (i * NB_WORDS_SWF_BLK) ];
667 672 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) ] = sample[ 0 ];
668 673 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) + 1 ] = sample[ 1 ];
669 674 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) + 2 ] = sample[ 2 ];
670 675 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) + 3 ] = sample[ 3 ];
671 676 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) + 4 ] = sample[ 4 ];
672 677 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) + 5 ] = sample[ 5 ];
673 678 }
674 679
675 680 // SEND PACKET
676 681 status = rtems_message_queue_send( queue_id, &ring_node_cwf3_light, sizeof( ring_node* ) );
677 682 if (status != RTEMS_SUCCESSFUL) {
678 683 ret = LFR_DEFAULT;
679 684 }
680 685
681 686 return ret;
682 687 }
683 688
684 689 void compute_acquisition_time( unsigned int coarseTime, unsigned int fineTime,
685 690 unsigned int sid, unsigned char pa_lfr_pkt_nr, unsigned char * acquisitionTime )
686 691 {
687 692 unsigned long long int acquisitionTimeAsLong;
688 693 unsigned char localAcquisitionTime[6];
689 694 double deltaT;
690 695
691 696 deltaT = 0.;
692 697
693 698 localAcquisitionTime[0] = (unsigned char) ( coarseTime >> 24 );
694 699 localAcquisitionTime[1] = (unsigned char) ( coarseTime >> 16 );
695 700 localAcquisitionTime[2] = (unsigned char) ( coarseTime >> 8 );
696 701 localAcquisitionTime[3] = (unsigned char) ( coarseTime );
697 702 localAcquisitionTime[4] = (unsigned char) ( fineTime >> 8 );
698 703 localAcquisitionTime[5] = (unsigned char) ( fineTime );
699 704
700 705 acquisitionTimeAsLong = ( (unsigned long long int) localAcquisitionTime[0] << 40 )
701 706 + ( (unsigned long long int) localAcquisitionTime[1] << 32 )
702 707 + ( (unsigned long long int) localAcquisitionTime[2] << 24 )
703 708 + ( (unsigned long long int) localAcquisitionTime[3] << 16 )
704 709 + ( (unsigned long long int) localAcquisitionTime[4] << 8 )
705 710 + ( (unsigned long long int) localAcquisitionTime[5] );
706 711
707 712 switch( sid )
708 713 {
709 714 case SID_NORM_SWF_F0:
710 715 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_304 * 65536. / 24576. ;
711 716 break;
712 717
713 718 case SID_NORM_SWF_F1:
714 719 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_304 * 65536. / 4096. ;
715 720 break;
716 721
717 722 case SID_NORM_SWF_F2:
718 723 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_304 * 65536. / 256. ;
719 724 break;
720 725
721 726 case SID_SBM1_CWF_F1:
722 727 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF * 65536. / 4096. ;
723 728 break;
724 729
725 730 case SID_SBM2_CWF_F2:
726 731 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF * 65536. / 256. ;
727 732 break;
728 733
729 734 case SID_BURST_CWF_F2:
730 735 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF * 65536. / 256. ;
731 736 break;
732 737
733 738 case SID_NORM_CWF_F3:
734 739 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF_SHORT_F3 * 65536. / 16. ;
735 740 break;
736 741
737 742 case SID_NORM_CWF_LONG_F3:
738 743 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF * 65536. / 16. ;
739 744 break;
740 745
741 746 default:
742 747 PRINTF1("in compute_acquisition_time *** ERR unexpected sid %d\n", sid)
743 748 deltaT = 0.;
744 749 break;
745 750 }
746 751
747 752 acquisitionTimeAsLong = acquisitionTimeAsLong + (unsigned long long int) deltaT;
748 753 //
749 754 acquisitionTime[0] = (unsigned char) (acquisitionTimeAsLong >> 40);
750 755 acquisitionTime[1] = (unsigned char) (acquisitionTimeAsLong >> 32);
751 756 acquisitionTime[2] = (unsigned char) (acquisitionTimeAsLong >> 24);
752 757 acquisitionTime[3] = (unsigned char) (acquisitionTimeAsLong >> 16);
753 758 acquisitionTime[4] = (unsigned char) (acquisitionTimeAsLong >> 8 );
754 759 acquisitionTime[5] = (unsigned char) (acquisitionTimeAsLong );
755 760
756 761 }
757 762
758 763 void build_snapshot_from_ring( ring_node *ring_node_to_send,
759 764 unsigned char frequencyChannel,
760 765 unsigned long long int acquisitionTimeF0_asLong,
761 766 ring_node *ring_node_swf_extracted,
762 767 int *swf_extracted)
763 768 {
764 769 unsigned int i;
765 770 unsigned long long int centerTime_asLong;
766 771 unsigned long long int acquisitionTime_asLong;
767 772 unsigned long long int bufferAcquisitionTime_asLong;
768 773 unsigned char *ptr1;
769 774 unsigned char *ptr2;
770 775 unsigned char *timeCharPtr;
771 776 unsigned char nb_ring_nodes;
772 777 unsigned long long int frequency_asLong;
773 778 unsigned long long int nbTicksPerSample_asLong;
774 779 unsigned long long int nbSamplesPart1_asLong;
775 780 unsigned long long int sampleOffset_asLong;
776 781
777 782 unsigned int deltaT_F0;
778 783 unsigned int deltaT_F1;
779 784 unsigned long long int deltaT_F2;
780 785
781 786 deltaT_F0 = 2731; // (2048. / 24576. / 2.) * 65536. = 2730.667;
782 787 deltaT_F1 = 16384; // (2048. / 4096. / 2.) * 65536. = 16384;
783 788 deltaT_F2 = 262144; // (2048. / 256. / 2.) * 65536. = 262144;
784 789 sampleOffset_asLong = 0x00;
785 790
786 791 // (1) get the f0 acquisition time => the value is passed in argument
787 792
788 793 // (2) compute the central reference time
789 794 centerTime_asLong = acquisitionTimeF0_asLong + deltaT_F0;
790 795
791 796 // (3) compute the acquisition time of the current snapshot
792 797 switch(frequencyChannel)
793 798 {
794 799 case 1: // 1 is for F1 = 4096 Hz
795 800 acquisitionTime_asLong = centerTime_asLong - deltaT_F1;
796 801 nb_ring_nodes = NB_RING_NODES_F1;
797 802 frequency_asLong = 4096;
798 803 nbTicksPerSample_asLong = 16; // 65536 / 4096;
799 804 break;
800 805 case 2: // 2 is for F2 = 256 Hz
801 806 acquisitionTime_asLong = centerTime_asLong - deltaT_F2;
802 807 nb_ring_nodes = NB_RING_NODES_F2;
803 808 frequency_asLong = 256;
804 809 nbTicksPerSample_asLong = 256; // 65536 / 256;
805 810 break;
806 811 default:
807 812 acquisitionTime_asLong = centerTime_asLong;
808 813 frequency_asLong = 256;
809 814 nbTicksPerSample_asLong = 256;
810 815 break;
811 816 }
812 817
813 818 //****************************************************************************
814 819 // (4) search the ring_node with the acquisition time <= acquisitionTime_asLong
815 820 for (i=0; i<nb_ring_nodes; i++)
816 821 {
817 822 //PRINTF1("%d ... ", i);
818 823 bufferAcquisitionTime_asLong = get_acquisition_time( (unsigned char *) &ring_node_to_send->coarseTime );
819 824 if (bufferAcquisitionTime_asLong <= acquisitionTime_asLong)
820 825 {
821 826 //PRINTF1("buffer found with acquisition time = %llx\n", bufferAcquisitionTime_asLong);
822 827 break;
823 828 }
824 829 ring_node_to_send = ring_node_to_send->previous;
825 830 }
826 831
827 832 // (5) compute the number of samples to take in the current buffer
828 833 sampleOffset_asLong = ((acquisitionTime_asLong - bufferAcquisitionTime_asLong) * frequency_asLong ) >> 16;
829 834 nbSamplesPart1_asLong = NB_SAMPLES_PER_SNAPSHOT - sampleOffset_asLong;
830 835 //PRINTF2("sampleOffset_asLong = %lld, nbSamplesPart1_asLong = %lld\n", sampleOffset_asLong, nbSamplesPart1_asLong);
831 836
832 837 // (6) compute the final acquisition time
833 838 acquisitionTime_asLong = bufferAcquisitionTime_asLong +
834 839 sampleOffset_asLong * nbTicksPerSample_asLong;
835 840
836 841 // (7) copy the acquisition time at the beginning of the extrated snapshot
837 842 ptr1 = (unsigned char*) &acquisitionTime_asLong;
838 843 // fine time
839 844 ptr2 = (unsigned char*) &ring_node_swf_extracted->fineTime;
840 845 ptr2[2] = ptr1[ 4 + 2 ];
841 846 ptr2[3] = ptr1[ 5 + 2 ];
842 847 // coarse time
843 848 ptr2 = (unsigned char*) &ring_node_swf_extracted->coarseTime;
844 849 ptr2[0] = ptr1[ 0 + 2 ];
845 850 ptr2[1] = ptr1[ 1 + 2 ];
846 851 ptr2[2] = ptr1[ 2 + 2 ];
847 852 ptr2[3] = ptr1[ 3 + 2 ];
848 853
849 854 // re set the synchronization bit
850 855 timeCharPtr = (unsigned char*) &ring_node_to_send->coarseTime;
851 856 ptr2[0] = ptr2[0] | (timeCharPtr[0] & 0x80); // [1000 0000]
852 857
853 858 if ( (nbSamplesPart1_asLong >= NB_SAMPLES_PER_SNAPSHOT) | (nbSamplesPart1_asLong < 0) )
854 859 {
855 860 nbSamplesPart1_asLong = 0;
856 861 }
857 862 // copy the part 1 of the snapshot in the extracted buffer
858 863 for ( i = 0; i < (nbSamplesPart1_asLong * NB_WORDS_SWF_BLK); i++ )
859 864 {
860 865 swf_extracted[i] =
861 866 ((int*) ring_node_to_send->buffer_address)[ i + (sampleOffset_asLong * NB_WORDS_SWF_BLK) ];
862 867 }
863 868 // copy the part 2 of the snapshot in the extracted buffer
864 869 ring_node_to_send = ring_node_to_send->next;
865 870 for ( i = (nbSamplesPart1_asLong * NB_WORDS_SWF_BLK); i < (NB_SAMPLES_PER_SNAPSHOT * NB_WORDS_SWF_BLK); i++ )
866 871 {
867 872 swf_extracted[i] =
868 873 ((int*) ring_node_to_send->buffer_address)[ (i-(nbSamplesPart1_asLong * NB_WORDS_SWF_BLK)) ];
869 874 }
870 875 }
871 876
872 877 double computeCorrection( unsigned char *timePtr )
873 878 {
874 879 unsigned long long int acquisitionTime;
875 880 unsigned long long int centerTime;
876 881 unsigned long long int previousTick;
877 882 unsigned long long int nextTick;
878 883 unsigned long long int deltaPreviousTick;
879 884 unsigned long long int deltaNextTick;
880 885 double deltaPrevious_ms;
881 886 double deltaNext_ms;
882 887 double correctionInF2;
883 888
884 889 // get acquisition time in fine time ticks
885 890 acquisitionTime = get_acquisition_time( timePtr );
886 891
887 892 // compute center time
888 893 centerTime = acquisitionTime + 2731; // (2048. / 24576. / 2.) * 65536. = 2730.667;
889 894 previousTick = centerTime - (centerTime & 0xffff);
890 895 nextTick = previousTick + 65536;
891 896
892 897 deltaPreviousTick = centerTime - previousTick;
893 898 deltaNextTick = nextTick - centerTime;
894 899
895 900 deltaPrevious_ms = ((double) deltaPreviousTick) / 65536. * 1000.;
896 901 deltaNext_ms = ((double) deltaNextTick) / 65536. * 1000.;
897 902
898 903 PRINTF2(" delta previous = %.3f ms, delta next = %.2f ms\n", deltaPrevious_ms, deltaNext_ms);
899 904 // PRINTF2(" delta previous = %llu fine time ticks, delta next = %llu fine time ticks\n",
900 905 // deltaPreviousTick, deltaNextTick);
901 906
902 907 // which tick is the closest?
903 908 if (deltaPreviousTick > deltaNextTick)
904 909 {
905 910 // the snapshot center is just before the second => increase delta_snapshot
906 911 correctionInF2 = + (deltaNext_ms * 256. / 1000. );
907 912 }
908 913 else
909 914 {
910 915 // the snapshot center is just after the second => decrease delta_snapshot
911 916 correctionInF2 = - (deltaPrevious_ms * 256. / 1000. );
912 917 }
913 918
914 919 PRINTF1(" correctionInF2 = %.2f\n", correctionInF2);
915 920
916 921 return correctionInF2;
917 922 }
918 923
919 924 void applyCorrection( double correction )
920 925 {
921 926 int correctionInt;
922 927
923 928 if (correction>=0.)
924 929 {
925 930 if ( correction > 0.5 )
926 931 {
927 932 correctionInt = 1;
928 933 }
929 934 else
930 935 {
931 936 correctionInt = floor(correction);
932 937 }
933 938 }
934 939 else
935 940 {
936 941 if ( correction < -0.5)
937 942 {
938 943 correctionInt = -1;
939 944 }
940 945 else
941 946 {
942 947 correctionInt = ceil(correction);
943 948 }
944 949 }
945 950 waveform_picker_regs->delta_snapshot = waveform_picker_regs->delta_snapshot + correctionInt;
946 951 }
947 952
948 953 void snapshot_resynchronization( unsigned char *timePtr )
949 954 {
950 955 static double correction = 0.;
951 956 static resynchro_state state = MEASURE_0;
952 957
953 958 int correctionInt;
954 959
955 960 correctionInt = 0;
956 961
957 962 switch (state)
958 963 {
959 964
960 965 case MEASURE_0:
961 966 // ********
962 967 PRINTF("MEASURE_0 ===\n");
963 968 state = CORRECTION_0;
964 969 correction = computeCorrection( timePtr );
965 970 PRINTF1("MEASURE_0 === correction = %.2f\n", correction );
966 971 applyCorrection( correction );
967 972 PRINTF1("MEASURE_0 === delta_snapshot = %d\n", waveform_picker_regs->delta_snapshot);
968 973 //****
969 974 break;
970 975
971 976 case CORRECTION_0:
972 977 //************
973 978 PRINTF("CORRECTION_0 ===\n");
974 979 state = CORRECTION_1;
975 980 computeCorrection( timePtr );
976 981 correction = -correction;
977 982 PRINTF1("CORRECTION_0 === correction = %.2f\n", correction );
978 983 applyCorrection( correction );
979 984 PRINTF1("CORRECTION_0 === delta_snapshot = %d\n", waveform_picker_regs->delta_snapshot);
980 985 //****
981 986 break;
982 987
983 988 case CORRECTION_1:
984 989 //************
985 990 PRINTF("CORRECTION_1 ===\n");
986 991 state = MEASURE_0;
987 992 computeCorrection( timePtr );
988 993 PRINTF1("CORRECTION_1 === delta_snapshot = %d\n", waveform_picker_regs->delta_snapshot);
989 994 //****
990 995 break;
991 996
992 997 default:
993 998 break;
994 999
995 1000 }
996 1001 }
997 1002
998 1003 //**************
999 1004 // wfp registers
1000 1005 void reset_wfp_burst_enable( void )
1001 1006 {
1002 1007 /** This function resets the waveform picker burst_enable register.
1003 1008 *
1004 1009 * The burst bits [f2 f1 f0] and the enable bits [f3 f2 f1 f0] are set to 0.
1005 1010 *
1006 1011 */
1007 1012
1008 1013 // [1000 000] burst f2, f1, f0 enable f3, f2, f1, f0
1009 1014 waveform_picker_regs->run_burst_enable = waveform_picker_regs->run_burst_enable & 0x80;
1010 1015 }
1011 1016
1012 1017 void reset_wfp_status( void )
1013 1018 {
1014 1019 /** This function resets the waveform picker status register.
1015 1020 *
1016 1021 * All status bits are set to 0 [new_err full_err full].
1017 1022 *
1018 1023 */
1019 1024
1020 1025 waveform_picker_regs->status = 0xffff;
1021 1026 }
1022 1027
1023 1028 void reset_wfp_buffer_addresses( void )
1024 1029 {
1025 1030 // F0
1026 1031 waveform_picker_regs->addr_data_f0_0 = current_ring_node_f0->previous->buffer_address; // 0x08
1027 1032 waveform_picker_regs->addr_data_f0_1 = current_ring_node_f0->buffer_address; // 0x0c
1028 1033 // F1
1029 1034 waveform_picker_regs->addr_data_f1_0 = current_ring_node_f1->previous->buffer_address; // 0x10
1030 1035 waveform_picker_regs->addr_data_f1_1 = current_ring_node_f1->buffer_address; // 0x14
1031 1036 // F2
1032 1037 waveform_picker_regs->addr_data_f2_0 = current_ring_node_f2->previous->buffer_address; // 0x18
1033 1038 waveform_picker_regs->addr_data_f2_1 = current_ring_node_f2->buffer_address; // 0x1c
1034 1039 // F3
1035 1040 waveform_picker_regs->addr_data_f3_0 = current_ring_node_f3->previous->buffer_address; // 0x20
1036 1041 waveform_picker_regs->addr_data_f3_1 = current_ring_node_f3->buffer_address; // 0x24
1037 1042 }
1038 1043
1039 1044 void reset_waveform_picker_regs( void )
1040 1045 {
1041 1046 /** This function resets the waveform picker module registers.
1042 1047 *
1043 1048 * The registers affected by this function are located at the following offset addresses:
1044 1049 * - 0x00 data_shaping
1045 1050 * - 0x04 run_burst_enable
1046 1051 * - 0x08 addr_data_f0
1047 1052 * - 0x0C addr_data_f1
1048 1053 * - 0x10 addr_data_f2
1049 1054 * - 0x14 addr_data_f3
1050 1055 * - 0x18 status
1051 1056 * - 0x1C delta_snapshot
1052 1057 * - 0x20 delta_f0
1053 1058 * - 0x24 delta_f0_2
1054 1059 * - 0x28 delta_f1 (obsolet parameter)
1055 1060 * - 0x2c delta_f2
1056 1061 * - 0x30 nb_data_by_buffer
1057 1062 * - 0x34 nb_snapshot_param
1058 1063 * - 0x38 start_date
1059 1064 * - 0x3c nb_word_in_buffer
1060 1065 *
1061 1066 */
1062 1067
1063 1068 set_wfp_data_shaping(); // 0x00 *** R1 R0 SP1 SP0 BW
1064 1069
1065 1070 reset_wfp_burst_enable(); // 0x04 *** [run *** burst f2, f1, f0 *** enable f3, f2, f1, f0 ]
1066 1071
1067 1072 reset_wfp_buffer_addresses();
1068 1073
1069 1074 reset_wfp_status(); // 0x18
1070 1075
1071 1076 set_wfp_delta_snapshot(); // 0x1c *** 300 s => 0x12bff
1072 1077
1073 1078 set_wfp_delta_f0_f0_2(); // 0x20, 0x24
1074 1079
1075 1080 //the parameter delta_f1 [0x28] is not used anymore
1076 1081
1077 1082 set_wfp_delta_f2(); // 0x2c
1078 1083
1079 1084 DEBUG_PRINTF1("delta_snapshot %x\n", waveform_picker_regs->delta_snapshot);
1080 1085 DEBUG_PRINTF1("delta_f0 %x\n", waveform_picker_regs->delta_f0);
1081 1086 DEBUG_PRINTF1("delta_f0_2 %x\n", waveform_picker_regs->delta_f0_2);
1082 1087 DEBUG_PRINTF1("delta_f1 %x\n", waveform_picker_regs->delta_f1);
1083 1088 DEBUG_PRINTF1("delta_f2 %x\n", waveform_picker_regs->delta_f2);
1084 1089 // 2688 = 8 * 336
1085 1090 waveform_picker_regs->nb_data_by_buffer = 0xa7f; // 0x30 *** 2688 - 1 => nb samples -1
1086 1091 waveform_picker_regs->snapshot_param = 0xa80; // 0x34 *** 2688 => nb samples
1087 1092 waveform_picker_regs->start_date = 0x7fffffff; // 0x38
1088 1093 //
1089 1094 // coarse time and fine time registers are not initialized, they are volatile
1090 1095 //
1091 1096 waveform_picker_regs->buffer_length = 0x1f8;// buffer length in burst = 3 * 2688 / 16 = 504 = 0x1f8
1092 1097 }
1093 1098
1094 1099 void set_wfp_data_shaping( void )
1095 1100 {
1096 1101 /** This function sets the data_shaping register of the waveform picker module.
1097 1102 *
1098 1103 * The value is read from one field of the parameter_dump_packet structure:\n
1099 1104 * bw_sp0_sp1_r0_r1
1100 1105 *
1101 1106 */
1102 1107
1103 1108 unsigned char data_shaping;
1104 1109
1105 1110 // get the parameters for the data shaping [BW SP0 SP1 R0 R1] in sy_lfr_common1 and configure the register
1106 1111 // waveform picker : [R1 R0 SP1 SP0 BW]
1107 1112
1108 1113 data_shaping = parameter_dump_packet.sy_lfr_common_parameters;
1109 1114
1110 1115 waveform_picker_regs->data_shaping =
1111 1116 ( (data_shaping & 0x20) >> 5 ) // BW
1112 1117 + ( (data_shaping & 0x10) >> 3 ) // SP0
1113 1118 + ( (data_shaping & 0x08) >> 1 ) // SP1
1114 1119 + ( (data_shaping & 0x04) << 1 ) // R0
1115 1120 + ( (data_shaping & 0x02) << 3 ) // R1
1116 1121 + ( (data_shaping & 0x01) << 5 ); // R2
1117 1122 }
1118 1123
1119 1124 void set_wfp_burst_enable_register( unsigned char mode )
1120 1125 {
1121 1126 /** This function sets the waveform picker burst_enable register depending on the mode.
1122 1127 *
1123 1128 * @param mode is the LFR mode to launch.
1124 1129 *
1125 1130 * The burst bits shall be before the enable bits.
1126 1131 *
1127 1132 */
1128 1133
1129 1134 // [0000 0000] burst f2, f1, f0 enable f3 f2 f1 f0
1130 1135 // the burst bits shall be set first, before the enable bits
1131 1136 switch(mode) {
1132 1137 case LFR_MODE_NORMAL:
1133 1138 case LFR_MODE_SBM1:
1134 1139 case LFR_MODE_SBM2:
1135 1140 waveform_picker_regs->run_burst_enable = 0x60; // [0110 0000] enable f2 and f1 burst
1136 1141 waveform_picker_regs->run_burst_enable = waveform_picker_regs->run_burst_enable | 0x0f; // [1111] enable f3 f2 f1 f0
1137 1142 break;
1138 1143 case LFR_MODE_BURST:
1139 1144 waveform_picker_regs->run_burst_enable = 0x40; // [0100 0000] f2 burst enabled
1140 1145 waveform_picker_regs->run_burst_enable = waveform_picker_regs->run_burst_enable | 0x0c; // [1100] enable f3 and f2
1141 1146 break;
1142 1147 default:
1143 1148 waveform_picker_regs->run_burst_enable = 0x00; // [0000 0000] no burst enabled, no waveform enabled
1144 1149 break;
1145 1150 }
1146 1151 }
1147 1152
1148 1153 void set_wfp_delta_snapshot( void )
1149 1154 {
1150 1155 /** This function sets the delta_snapshot register of the waveform picker module.
1151 1156 *
1152 1157 * The value is read from two (unsigned char) of the parameter_dump_packet structure:
1153 1158 * - sy_lfr_n_swf_p[0]
1154 1159 * - sy_lfr_n_swf_p[1]
1155 1160 *
1156 1161 */
1157 1162
1158 1163 unsigned int delta_snapshot;
1159 1164 unsigned int delta_snapshot_in_T2;
1160 1165
1161 1166 delta_snapshot = parameter_dump_packet.sy_lfr_n_swf_p[0]*256
1162 1167 + parameter_dump_packet.sy_lfr_n_swf_p[1];
1163 1168
1164 1169 delta_snapshot_in_T2 = delta_snapshot * 256;
1165 1170 waveform_picker_regs->delta_snapshot = delta_snapshot_in_T2 - 1; // max 4 bytes
1166 1171 }
1167 1172
1168 1173 void set_wfp_delta_f0_f0_2( void )
1169 1174 {
1170 1175 unsigned int delta_snapshot;
1171 1176 unsigned int nb_samples_per_snapshot;
1172 1177 float delta_f0_in_float;
1173 1178
1174 1179 delta_snapshot = waveform_picker_regs->delta_snapshot;
1175 1180 nb_samples_per_snapshot = parameter_dump_packet.sy_lfr_n_swf_l[0] * 256 + parameter_dump_packet.sy_lfr_n_swf_l[1];
1176 1181 delta_f0_in_float = nb_samples_per_snapshot / 2. * ( 1. / 256. - 1. / 24576.) * 256.;
1177 1182
1178 1183 waveform_picker_regs->delta_f0 = delta_snapshot - floor( delta_f0_in_float );
1179 1184 waveform_picker_regs->delta_f0_2 = 0x30; // 48 = 11 0000, max 7 bits
1180 1185 }
1181 1186
1182 1187 void set_wfp_delta_f1( void )
1183 1188 {
1184 1189 /** Sets the value of the delta_f1 parameter
1185 1190 *
1186 1191 * @param void
1187 1192 *
1188 1193 * @return void
1189 1194 *
1190 1195 * delta_f1 is not used, the snapshots are extracted from CWF_F1 waveforms.
1191 1196 *
1192 1197 */
1193 1198
1194 1199 unsigned int delta_snapshot;
1195 1200 unsigned int nb_samples_per_snapshot;
1196 1201 float delta_f1_in_float;
1197 1202
1198 1203 delta_snapshot = waveform_picker_regs->delta_snapshot;
1199 1204 nb_samples_per_snapshot = parameter_dump_packet.sy_lfr_n_swf_l[0] * 256 + parameter_dump_packet.sy_lfr_n_swf_l[1];
1200 1205 delta_f1_in_float = nb_samples_per_snapshot / 2. * ( 1. / 256. - 1. / 4096.) * 256.;
1201 1206
1202 1207 waveform_picker_regs->delta_f1 = delta_snapshot - floor( delta_f1_in_float );
1203 1208 }
1204 1209
1205 1210 void set_wfp_delta_f2( void ) // parameter not used, only delta_f0 and delta_f0_2 are used
1206 1211 {
1207 1212 /** Sets the value of the delta_f2 parameter
1208 1213 *
1209 1214 * @param void
1210 1215 *
1211 1216 * @return void
1212 1217 *
1213 1218 * delta_f2 is used only for the first snapshot generation, even when the snapshots are extracted from CWF_F2
1214 1219 * waveforms (see lpp_waveform_snapshot_controler.vhd for details).
1215 1220 *
1216 1221 */
1217 1222
1218 1223 unsigned int delta_snapshot;
1219 1224 unsigned int nb_samples_per_snapshot;
1220 1225
1221 1226 delta_snapshot = waveform_picker_regs->delta_snapshot;
1222 1227 nb_samples_per_snapshot = parameter_dump_packet.sy_lfr_n_swf_l[0] * 256 + parameter_dump_packet.sy_lfr_n_swf_l[1];
1223 1228
1224 1229 waveform_picker_regs->delta_f2 = delta_snapshot - nb_samples_per_snapshot / 2 - 1;
1225 1230 }
1226 1231
1227 1232 //*****************
1228 1233 // local parameters
1229 1234
1230 1235 void increment_seq_counter_source_id( unsigned char *packet_sequence_control, unsigned int sid )
1231 1236 {
1232 1237 /** This function increments the parameter "sequence_cnt" depending on the sid passed in argument.
1233 1238 *
1234 1239 * @param packet_sequence_control is a pointer toward the parameter sequence_cnt to update.
1235 1240 * @param sid is the source identifier of the packet being updated.
1236 1241 *
1237 1242 * REQ-LFR-SRS-5240 / SSS-CP-FS-590
1238 1243 * The sequence counters shall wrap around from 2^14 to zero.
1239 1244 * The sequence counter shall start at zero at startup.
1240 1245 *
1241 1246 * REQ-LFR-SRS-5239 / SSS-CP-FS-580
1242 1247 * All TM_LFR_SCIENCE_ packets are sent to ground, i.e. destination id = 0
1243 1248 *
1244 1249 */
1245 1250
1246 1251 unsigned short *sequence_cnt;
1247 1252 unsigned short segmentation_grouping_flag;
1248 1253 unsigned short new_packet_sequence_control;
1249 1254 rtems_mode initial_mode_set;
1250 1255 rtems_mode current_mode_set;
1251 1256 rtems_status_code status;
1252 1257
1253 1258 //******************************************
1254 1259 // CHANGE THE MODE OF THE CALLING RTEMS TASK
1255 1260 status = rtems_task_mode( RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &initial_mode_set );
1256 1261
1257 1262 if ( (sid == SID_NORM_SWF_F0) || (sid == SID_NORM_SWF_F1) || (sid == SID_NORM_SWF_F2)
1258 1263 || (sid == SID_NORM_CWF_F3) || (sid == SID_NORM_CWF_LONG_F3)
1259 1264 || (sid == SID_BURST_CWF_F2)
1260 1265 || (sid == SID_NORM_ASM_F0) || (sid == SID_NORM_ASM_F1) || (sid == SID_NORM_ASM_F2)
1261 1266 || (sid == SID_NORM_BP1_F0) || (sid == SID_NORM_BP1_F1) || (sid == SID_NORM_BP1_F2)
1262 1267 || (sid == SID_NORM_BP2_F0) || (sid == SID_NORM_BP2_F1) || (sid == SID_NORM_BP2_F2)
1263 1268 || (sid == SID_BURST_BP1_F0) || (sid == SID_BURST_BP2_F0)
1264 1269 || (sid == SID_BURST_BP1_F1) || (sid == SID_BURST_BP2_F1) )
1265 1270 {
1266 1271 sequence_cnt = (unsigned short *) &sequenceCounters_SCIENCE_NORMAL_BURST;
1267 1272 }
1268 1273 else if ( (sid ==SID_SBM1_CWF_F1) || (sid ==SID_SBM2_CWF_F2)
1269 1274 || (sid == SID_SBM1_BP1_F0) || (sid == SID_SBM1_BP2_F0)
1270 1275 || (sid == SID_SBM2_BP1_F0) || (sid == SID_SBM2_BP2_F0)
1271 1276 || (sid == SID_SBM2_BP1_F1) || (sid == SID_SBM2_BP2_F1) )
1272 1277 {
1273 1278 sequence_cnt = (unsigned short *) &sequenceCounters_SCIENCE_SBM1_SBM2;
1274 1279 }
1275 1280 else
1276 1281 {
1277 1282 sequence_cnt = (unsigned short *) NULL;
1278 1283 PRINTF1("in increment_seq_counter_source_id *** ERR apid_destid %d not known\n", sid)
1279 1284 }
1280 1285
1281 1286 if (sequence_cnt != NULL)
1282 1287 {
1283 1288 segmentation_grouping_flag = TM_PACKET_SEQ_CTRL_STANDALONE << 8;
1284 1289 *sequence_cnt = (*sequence_cnt) & 0x3fff;
1285 1290
1286 1291 new_packet_sequence_control = segmentation_grouping_flag | (*sequence_cnt) ;
1287 1292
1288 1293 packet_sequence_control[0] = (unsigned char) (new_packet_sequence_control >> 8);
1289 1294 packet_sequence_control[1] = (unsigned char) (new_packet_sequence_control );
1290 1295
1291 1296 // increment the sequence counter
1292 1297 if ( *sequence_cnt < SEQ_CNT_MAX)
1293 1298 {
1294 1299 *sequence_cnt = *sequence_cnt + 1;
1295 1300 }
1296 1301 else
1297 1302 {
1298 1303 *sequence_cnt = 0;
1299 1304 }
1300 1305 }
1301 1306
1302 1307 //*************************************
1303 1308 // RESTORE THE MODE OF THE CALLING TASK
1304 1309 status = rtems_task_mode( initial_mode_set, RTEMS_PREEMPT_MASK, &current_mode_set );
1305 1310 }
General Comments 0
You need to be logged in to leave comments. Login now