GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/fsw_spacewire.c Lines: 624 655 95.3 %
Date: 2018-11-13 11:16:07 Branches: 117 140 83.6 %

Line Branch Exec Source
1
/*------------------------------------------------------------------------------
2
--  Solar Orbiter's Low Frequency Receiver Flight Software (LFR FSW),
3
--  This file is a part of the LFR FSW
4
--  Copyright (C) 2012-2018, Plasma Physics Laboratory - CNRS
5
--
6
--  This program is free software; you can redistribute it and/or modify
7
--  it under the terms of the GNU General Public License as published by
8
--  the Free Software Foundation; either version 2 of the License, or
9
--  (at your option) any later version.
10
--
11
--  This program is distributed in the hope that it will be useful,
12
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
--  GNU General Public License for more details.
15
--
16
--  You should have received a copy of the GNU General Public License
17
--  along with this program; if not, write to the Free Software
18
--  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
-------------------------------------------------------------------------------*/
20
/*--                  Author : Paul Leroy
21
--                   Contact : Alexis Jeandet
22
--                      Mail : alexis.jeandet@lpp.polytechnique.fr
23
----------------------------------------------------------------------------*/
24
25
/** Functions related to the SpaceWire interface.
26
 *
27
 * @file
28
 * @author P. LEROY
29
 *
30
 * A group of functions to handle SpaceWire transmissions:
31
 * - configuration of the SpaceWire link
32
 * - SpaceWire related interruption requests processing
33
 * - transmission of TeleMetry packets by a dedicated RTEMS task
34
 * - reception of TeleCommands by a dedicated RTEMS task
35
 *
36
 */
37
38
#include "fsw_spacewire.h"
39
40
rtems_name semq_name    = 0;
41
rtems_id semq_id        = RTEMS_ID_NONE;
42
43
//*****************
44
// waveform headers
45
Header_TM_LFR_SCIENCE_CWF_t headerCWF = {0};
46
Header_TM_LFR_SCIENCE_SWF_t headerSWF = {0};
47
Header_TM_LFR_SCIENCE_ASM_t headerASM = {0};
48
49
unsigned char previousTimecodeCtr = 0;
50
unsigned int *grspwPtr = (unsigned int *) (REGS_ADDR_GRSPW + APB_OFFSET_GRSPW_TIME_REGISTER);
51
52
//***********
53
// RTEMS TASK
54
92
rtems_task spiq_task(rtems_task_argument unused)
55
{
56
    /** This RTEMS task is awaken by an rtems_event sent by the interruption subroutine of the SpaceWire driver.
57
     *
58
     * @param unused is the starting argument of the RTEMS task
59
     *
60
     */
61
62
    rtems_event_set event_out;
63
    rtems_status_code status;
64
    int linkStatus;
65
66
92
    event_out = EVENT_SETS_NONE_PENDING;
67
92
    linkStatus = 0;
68
69
    BOOT_PRINTF("in SPIQ *** \n")
70
71
    while(true){
72
94
        rtems_event_receive(SPW_LINKERR_EVENT, RTEMS_WAIT, RTEMS_NO_TIMEOUT, &event_out); // wait for an SPW_LINKERR_EVENT
73
        PRINTF("in SPIQ *** got SPW_LINKERR_EVENT\n")
74
75
        // [0] SUSPEND RECV AND SEND TASKS
76
7
        status = rtems_task_suspend( Task_id[ TASKID_RECV ] );
77
        if ( status != RTEMS_SUCCESSFUL ) {
78
            PRINTF("in SPIQ *** ERR suspending RECV Task\n")
79
        }
80
7
        status = rtems_task_suspend( Task_id[ TASKID_SEND ] );
81
        if ( status != RTEMS_SUCCESSFUL ) {
82
            PRINTF("in SPIQ *** ERR suspending SEND Task\n")
83
        }
84
85
        // [1] CHECK THE LINK
86
7
        status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus);   // get the link status (1)
87
7
        if ( linkStatus != SPW_LINK_OK) {
88
            PRINTF1("in SPIQ *** linkStatus %d, wait...\n", linkStatus)
89
5
            status = rtems_task_wake_after( SY_LFR_DPU_CONNECT_TIMEOUT );        // wait SY_LFR_DPU_CONNECT_TIMEOUT 1000 ms
90
        }
91
92
        // [2] RECHECK THE LINK AFTER SY_LFR_DPU_CONNECT_TIMEOUT
93
7
        status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus);   // get the link status (2)
94
7
        if ( linkStatus != SPW_LINK_OK )  // [2.a] not in run state, reset the link
95
        {
96
5
            spacewire_read_statistics();
97
5
            status = spacewire_several_connect_attemps( );
98
        }
99
        else                    // [2.b] in run state, start the link
100
        {
101
2
            status = spacewire_stop_and_start_link( fdSPW ); // start the link
102
            if ( status != RTEMS_SUCCESSFUL)
103
            {
104
                PRINTF1("in SPIQ *** ERR spacewire_stop_and_start_link %d\n", status)
105
            }
106
        }
107
108
        // [3] COMPLETE RECOVERY ACTION AFTER SY_LFR_DPU_CONNECT_ATTEMPTS
109
7
        if ( status == RTEMS_SUCCESSFUL )   // [3.a] the link is in run state and has been started successfully
110
        {
111
2
            status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
112
            if ( status != RTEMS_SUCCESSFUL ) {
113
                PRINTF("in SPIQ *** ERR resuming SEND Task\n")
114
            }
115
2
            status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
116
            if ( status != RTEMS_SUCCESSFUL ) {
117
                PRINTF("in SPIQ *** ERR resuming RECV Task\n")
118
            }
119
        }
120
        else                                // [3.b] the link is not in run state, go in STANDBY mode
121
        {
122
5
            status = enter_mode_standby();
123
            if ( status != RTEMS_SUCCESSFUL )
124
            {
125
                PRINTF1("in SPIQ *** ERR enter_standby_mode *** code %d\n", status)
126
            }
127
            {
128
5
                updateLFRCurrentMode( LFR_MODE_STANDBY );
129
            }
130
            // wake the LINK task up to wait for the link recovery
131
5
            status =  rtems_event_send ( Task_id[TASKID_LINK], RTEMS_EVENT_0 );
132
5
            status = rtems_task_suspend( RTEMS_SELF );
133
        }
134
    }
135
}
136
137
94
rtems_task recv_task( rtems_task_argument unused )
138
{
139
    /** This RTEMS task is dedicated to the reception of incoming TeleCommands.
140
     *
141
     * @param unused is the starting argument of the RTEMS task
142
     *
143
     * The RECV task blocks on a call to the read system call, waiting for incoming SpaceWire data. When unblocked:
144
     * 1. It reads the incoming data.
145
     * 2. Launches the acceptance procedure.
146
     * 3. If the Telecommand is valid, sends it to a dedicated RTEMS message queue.
147
     *
148
     */
149
150
    int len;
151
    ccsdsTelecommandPacket_t __attribute__((aligned(4))) currentTC;
152
    unsigned char computed_CRC[ BYTES_PER_CRC ];
153
    unsigned char currentTC_LEN_RCV[ BYTES_PER_PKT_LEN ];
154
    unsigned char destinationID;
155
    unsigned int estimatedPacketLength;
156
    unsigned int parserCode;
157
    rtems_status_code status;
158
    rtems_id queue_recv_id;
159
    rtems_id queue_send_id;
160
161
94
    memset( &currentTC, 0, sizeof(ccsdsTelecommandPacket_t) );
162
94
    destinationID = 0;
163
94
    queue_recv_id = RTEMS_ID_NONE;
164
94
    queue_send_id = RTEMS_ID_NONE;
165
166
94
    initLookUpTableForCRC(); // the table is used to compute Cyclic Redundancy Codes
167
168
94
    status =  get_message_queue_id_recv( &queue_recv_id );
169
    if (status != RTEMS_SUCCESSFUL)
170
    {
171
        PRINTF1("in RECV *** ERR get_message_queue_id_recv %d\n", status)
172
    }
173
174
94
    status =  get_message_queue_id_send( &queue_send_id );
175
    if (status != RTEMS_SUCCESSFUL)
176
    {
177
        PRINTF1("in RECV *** ERR get_message_queue_id_send %d\n", status)
178
    }
179
180
    BOOT_PRINTF("in RECV *** \n")
181
182
    while(1)
183
    {
184
42271
        len = read( fdSPW, (char*) &currentTC, CCSDS_TC_PKT_MAX_SIZE ); // the call to read is blocking
185
42177
        if (len == -1){ // error during the read call
186
            PRINTF1("in RECV *** last read call returned -1, ERRNO %d\n", errno)
187
        }
188
        else {
189
42177
            if ( (len+1) < CCSDS_TC_PKT_MIN_SIZE ) {
190
                PRINTF("in RECV *** packet lenght too short\n")
191
            }
192
            else {
193
42177
                estimatedPacketLength = (unsigned int) (len - CCSDS_TC_TM_PACKET_OFFSET - PROTID_RES_APP); // => -3 is for Prot ID, Reserved and User App bytes
194
                PRINTF1("incoming TC with Length (byte): %d\n", len - 3);
195
42177
                currentTC_LEN_RCV[ 0 ] = (unsigned char) (estimatedPacketLength >> SHIFT_1_BYTE);
196
42177
                currentTC_LEN_RCV[ 1 ] = (unsigned char) (estimatedPacketLength     );
197
                // CHECK THE TC
198
42177
                parserCode = tc_parser( &currentTC, estimatedPacketLength, computed_CRC ) ;
199
42177
                if ( (parserCode == ILLEGAL_APID)       || (parserCode == WRONG_LEN_PKT)
200
                     || (parserCode == INCOR_CHECKSUM)  || (parserCode == ILL_TYPE)
201
                     || (parserCode == ILL_SUBTYPE)     || (parserCode == WRONG_APP_DATA)
202
42177
                     || (parserCode == WRONG_SRC_ID) )
203
                { // send TM_LFR_TC_EXE_CORRUPTED
204
                    PRINTF1("TC corrupted received, with code: %d\n", parserCode);
205


12374
                    if ( !( (currentTC.serviceType==TC_TYPE_TIME) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_TIME) )
206
                         &&
207
                         !( (currentTC.serviceType==TC_TYPE_GEN) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_INFO))
208
                         )
209
                    {
210
12277
                        if ( parserCode == WRONG_SRC_ID )
211
                        {
212
3273
                            destinationID = SID_TC_GROUND;
213
                        }
214
                        else
215
                        {
216
9004
                            destinationID = currentTC.sourceID;
217
                        }
218
12277
                        send_tm_lfr_tc_exe_corrupted( &currentTC, queue_send_id,
219
                                                      computed_CRC, currentTC_LEN_RCV,
220
                                                      destinationID );
221
                    }
222
                }
223
                else
224
                { // send valid TC to the action launcher
225
29803
                    status =  rtems_message_queue_send( queue_recv_id, &currentTC,
226
                                                        estimatedPacketLength + CCSDS_TC_TM_PACKET_OFFSET + PROTID_RES_APP);
227
                }
228
            }
229
        }
230
231
42177
        update_queue_max_count( queue_recv_id, &hk_lfr_q_rv_fifo_size_max );
232
233
42177
    }
234
}
235
236
94
rtems_task send_task( rtems_task_argument argument)
237
{
238
    /** This RTEMS task is dedicated to the transmission of TeleMetry packets.
239
     *
240
     * @param unused is the starting argument of the RTEMS task
241
     *
242
     * The SEND task waits for a message to become available in the dedicated RTEMS queue. When a message arrives:
243
     * - if the first byte is equal to CCSDS_DESTINATION_ID, the message is sent as is using the write system call.
244
     * - if the first byte is not equal to CCSDS_DESTINATION_ID, the message is handled as a spw_ioctl_pkt_send. After
245
     * analyzis, the packet is sent either using the write system call or using the ioctl call SPACEWIRE_IOCTRL_SEND, depending on the
246
     * data it contains.
247
     *
248
     */
249
250
    rtems_status_code status;                // RTEMS status code
251
    char incomingData[MSG_QUEUE_SIZE_SEND];  // incoming data buffer
252
    ring_node *incomingRingNodePtr;
253
    int ring_node_address;
254
    char *charPtr;
255
    spw_ioctl_pkt_send *spw_ioctl_send;
256
    size_t size;                            // size of the incoming TC packet
257
    rtems_id queue_send_id;
258
    unsigned int sid;
259
    unsigned char sidAsUnsignedChar;
260
    unsigned char type;
261
262
94
    incomingRingNodePtr = NULL;
263
94
    ring_node_address = 0;
264
94
    charPtr = (char *) &ring_node_address;
265
94
    size = 0;
266
94
    queue_send_id = RTEMS_ID_NONE;
267
94
    sid = 0;
268
94
    sidAsUnsignedChar = 0;
269
270
94
    init_header_cwf( &headerCWF );
271
94
    init_header_swf( &headerSWF );
272
94
    init_header_asm( &headerASM );
273
274
94
    status =  get_message_queue_id_send( &queue_send_id );
275
    if (status != RTEMS_SUCCESSFUL)
276
    {
277
        PRINTF1("in HOUS *** ERR get_message_queue_id_send %d\n", status)
278
    }
279
280
    BOOT_PRINTF("in SEND *** \n")
281
282
    while(1)
283
    {
284
567365
        status = rtems_message_queue_receive( queue_send_id, incomingData, &size,
285
                                             RTEMS_WAIT, RTEMS_NO_TIMEOUT );
286
287
567271
        if (status!=RTEMS_SUCCESSFUL)
288
        {
289
            PRINTF1("in SEND *** (1) ERR = %d\n", status)
290
        }
291
        else
292
        {
293
567271
            if ( size == sizeof(ring_node*) )
294
            {
295
101382
                charPtr[0] = incomingData[0];
296
101382
                charPtr[1] = incomingData[1];
297
101382
                charPtr[BYTE_2] = incomingData[BYTE_2];
298
101382
                charPtr[BYTE_3] = incomingData[BYTE_3];
299
101382
                incomingRingNodePtr = (ring_node*) ring_node_address;
300
101382
                sid = incomingRingNodePtr->sid;
301

347137
                if ( (sid==SID_NORM_CWF_LONG_F3)
302
101382
                     || (sid==SID_BURST_CWF_F2 )
303
201675
                     || (sid==SID_SBM1_CWF_F1  )
304
100293
                     || (sid==SID_SBM2_CWF_F2  ))
305
                {
306
44080
                    spw_send_waveform_CWF( incomingRingNodePtr, &headerCWF );
307
                }
308
57302
                else if ( (sid==SID_NORM_SWF_F0) || (sid==SID_NORM_SWF_F1) || (sid==SID_NORM_SWF_F2) )
309
                {
310
5535
                    spw_send_waveform_SWF( incomingRingNodePtr, &headerSWF );
311
                }
312
51767
                else if (sid==SID_NORM_CWF_F3)
313
                {
314
391
                    spw_send_waveform_CWF3_light( incomingRingNodePtr, &headerCWF );
315
                }
316
51376
                else if (sid==SID_NORM_ASM_F0)
317
                {
318
16114
                    spw_send_asm_f0( incomingRingNodePtr, &headerASM );
319
                }
320
35262
                else if (sid==SID_NORM_ASM_F1)
321
                {
322
16112
                    spw_send_asm_f1( incomingRingNodePtr, &headerASM );
323
                }
324
19150
                else if (sid==SID_NORM_ASM_F2)
325
                {
326
16100
                    spw_send_asm_f2( incomingRingNodePtr, &headerASM );
327
                }
328
3050
                else if (sid==TM_CODE_K_DUMP)
329
                {
330
3050
                    spw_send_k_dump( incomingRingNodePtr );
331
                }
332
                else
333
                {
334
                    PRINTF1("unexpected sid = %d\n", sid);
335
                }
336
            }
337
465889
            else if ( incomingData[0] == CCSDS_DESTINATION_ID ) // the incoming message is a ccsds packet
338
            {
339
465889
                sidAsUnsignedChar = (unsigned char) incomingData[ PACKET_POS_PA_LFR_SID_PKT ];
340
465889
                sid = sidAsUnsignedChar;
341
465889
                type = (unsigned char) incomingData[ PACKET_POS_SERVICE_TYPE ];
342
465889
                if (type == TM_TYPE_LFR_SCIENCE)    // this is a BP packet, all other types are handled differently
343
                // SET THE SEQUENCE_CNT PARAMETER IN CASE OF BP0 OR BP1 PACKETS
344
                {
345
295839
                    increment_seq_counter_source_id( (unsigned char*) &incomingData[ PACKET_POS_SEQUENCE_CNT ], sid );
346
                }
347
348
465889
                status = write( fdSPW, incomingData, size );
349
                if (status == -1){
350
                    PRINTF2("in SEND *** (2.a) ERRNO = %d, size = %d\n", errno, size)
351
                }
352
            }
353
            else // the incoming message is a spw_ioctl_pkt_send structure
354
            {
355
                spw_ioctl_send = (spw_ioctl_pkt_send*) incomingData;
356
                status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, spw_ioctl_send );
357
                if (status == -1){
358
                    PRINTF2("in SEND *** (2.b) ERRNO = %d, RTEMS = %d\n", errno, status)
359
                }
360
            }
361
        }
362
363
567271
        update_queue_max_count( queue_send_id, &hk_lfr_q_sd_fifo_size_max );
364
365
567271
    }
366
}
367
368
87
rtems_task link_task( rtems_task_argument argument )
369
{
370
    rtems_event_set event_out;
371
    rtems_status_code status;
372
    int linkStatus;
373
374
87
    event_out = EVENT_SETS_NONE_PENDING;
375
87
    linkStatus = 0;
376
377
    BOOT_PRINTF("in LINK ***\n")
378
379
    while(1)
380
    {
381
        // wait for an RTEMS_EVENT
382
92
        rtems_event_receive( RTEMS_EVENT_0,
383
                            RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
384
        PRINTF("in LINK *** wait for the link\n")
385
5
        status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus);       // get the link status
386
125
        while( linkStatus != SPW_LINK_OK)                                           // wait for the link
387
        {
388
115
            status = rtems_task_wake_after( SPW_LINK_WAIT );                        // monitor the link each 100ms
389
115
            status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus);   // get the link status
390
115
            watchdog_reload();
391
        }
392
393
5
        spacewire_read_statistics();
394
5
        status = spacewire_stop_and_start_link( fdSPW );
395
396
        if (status != RTEMS_SUCCESSFUL)
397
        {
398
            PRINTF1("in LINK *** ERR link not started %d\n", status)
399
        }
400
        else
401
        {
402
            PRINTF("in LINK *** OK  link started\n")
403
        }
404
405
        // restart the SPIQ task
406
5
        status = rtems_task_restart( Task_id[TASKID_SPIQ], 1 );
407
        if ( status != RTEMS_SUCCESSFUL ) {
408
            PRINTF("in SPIQ *** ERR restarting SPIQ Task\n")
409
        }
410
411
        // restart RECV and SEND
412
5
        status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
413
        if ( status != RTEMS_SUCCESSFUL ) {
414
            PRINTF("in SPIQ *** ERR restarting SEND Task\n")
415
        }
416
5
        status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
417
        if ( status != RTEMS_SUCCESSFUL ) {
418
            PRINTF("in SPIQ *** ERR restarting RECV Task\n")
419
        }
420
    }
421
}
422
423
//****************
424
// OTHER FUNCTIONS
425
87
int spacewire_open_link( void )  // by default, the driver resets the core: [SPW_CTRL_WRITE(pDev, SPW_CTRL_RESET);]
426
{
427
    /** This function opens the SpaceWire link.
428
     *
429
     * @return a valid file descriptor in case of success, -1 in case of a failure
430
     *
431
     */
432
    rtems_status_code status;
433
434
87
    status = RTEMS_SUCCESSFUL;
435
436
87
    fdSPW = open(GRSPW_DEVICE_NAME, O_RDWR); // open the device. the open call resets the hardware
437
87
    if ( fdSPW < 0 ) {
438
        PRINTF1("ERR *** in configure_spw_link *** error opening "GRSPW_DEVICE_NAME" with ERR %d\n", errno)
439
    }
440
    else
441
    {
442
87
        status = RTEMS_SUCCESSFUL;
443
    }
444
445
87
    return status;
446
}
447
448
87
int spacewire_start_link( int fd )
449
{
450
    rtems_status_code status;
451
452
87
    status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
453
                                                        // -1 default hardcoded driver timeout
454
455
87
    return status;
456
}
457
458
22
int spacewire_stop_and_start_link( int fd )
459
{
460
    rtems_status_code status;
461
462
22
    status = ioctl( fd, SPACEWIRE_IOCTRL_STOP);      // start fails if link pDev->running != 0
463
22
    status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
464
                                                        // -1 default hardcoded driver timeout
465
466
22
    return status;
467
}
468
469
87
int spacewire_configure_link( int fd )
470
{
471
    /** This function configures the SpaceWire link.
472
     *
473
     * @return GR-RTEMS-DRIVER directive status codes:
474
     * - 22  EINVAL - Null pointer or an out of range value was given as the argument.
475
     * - 16  EBUSY - Only used for SEND. Returned when no descriptors are avialble in non-blocking mode.
476
     * - 88  ENOSYS - Returned for SET_DESTKEY if RMAP command handler is not available or if a non-implemented call is used.
477
     * - 116 ETIMEDOUT - REturned for SET_PACKET_SIZE and START if the link could not be brought up.
478
     * - 12  ENOMEM - Returned for SET_PACKETSIZE if it was unable to allocate the new buffers.
479
     * - 5   EIO - Error when writing to grswp hardware registers.
480
     * - 2   ENOENT - No such file or directory
481
     */
482
483
    rtems_status_code status;
484
485
87
    spacewire_set_NP(1, REGS_ADDR_GRSPW); // [N]o [P]ort force
486
87
    spacewire_set_RE(1, REGS_ADDR_GRSPW); // [R]MAP [E]nable, the dedicated call seems to  break the no port force configuration
487
    spw_ioctl_packetsize packetsize;
488
489
87
    packetsize.rxsize   = SPW_RXSIZE;
490
87
    packetsize.txdsize  = SPW_TXDSIZE;
491
87
    packetsize.txhsize  = SPW_TXHSIZE;
492
493
87
    status = ioctl(fd, SPACEWIRE_IOCTRL_SET_RXBLOCK, 1);              // sets the blocking mode for reception
494
    if (status!=RTEMS_SUCCESSFUL) {
495
        PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_RXBLOCK\n")
496
    }
497
    //
498
87
    status = ioctl(fd, SPACEWIRE_IOCTRL_SET_EVENT_ID, Task_id[TASKID_SPIQ]); // sets the task ID to which an event is sent when a
499
    if (status!=RTEMS_SUCCESSFUL) {
500
        PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_EVENT_ID\n")          // link-error interrupt occurs
501
    }
502
    //
503
87
    status = ioctl(fd, SPACEWIRE_IOCTRL_SET_DISABLE_ERR, 0);          // automatic link-disabling due to link-error interrupts
504
    if (status!=RTEMS_SUCCESSFUL) {
505
        PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_DISABLE_ERR\n")
506
    }
507
    //
508
87
    status = ioctl(fd, SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ, 1);         // sets the link-error interrupt bit
509
    if (status!=RTEMS_SUCCESSFUL) {
510
        PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ\n")
511
    }
512
    //
513
87
    status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK, 1);              // transmission blocks
514
    if (status!=RTEMS_SUCCESSFUL) {
515
        PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK\n")
516
    }
517
    //
518
87
    status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL, 1);      // transmission blocks when no transmission descriptor is available
519
    if (status!=RTEMS_SUCCESSFUL) {
520
        PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL\n")
521
    }
522
    //
523
87
    status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TCODE_CTRL, CONF_TCODE_CTRL); // [Time Rx : Time Tx : Link error : Tick-out IRQ]
524
    if (status!=RTEMS_SUCCESSFUL) {
525
        PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TCODE_CTRL,\n")
526
    }
527
    //
528
87
    status = ioctl(fd, SPACEWIRE_IOCTRL_SET_PACKETSIZE, packetsize); // set rxsize, txdsize and txhsize
529
    if (status!=RTEMS_SUCCESSFUL) {
530
        PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_PACKETSIZE,\n")
531
    }
532
533
87
    return status;
534
}
535
536
5
int spacewire_several_connect_attemps( void )
537
{
538
    /** This function is executed by the SPIQ rtems_task wehn it has been awaken by an interruption raised by the SpaceWire driver.
539
     *
540
     * @return RTEMS directive status code:
541
     * - RTEMS_UNSATISFIED is returned is the link is not in the running state after 10 s.
542
     * - RTEMS_SUCCESSFUL is returned if the link is up before the timeout.
543
     *
544
     */
545
546
    rtems_status_code status_spw;
547
    rtems_status_code status;
548
    int i;
549
550
5
    status_spw = RTEMS_SUCCESSFUL;
551
552
5
    i = 0;
553
25
    while (i < SY_LFR_DPU_CONNECT_ATTEMPT)
554
    {
555
        PRINTF1("in spacewire_reset_link *** link recovery, try %d\n", i);
556
557
        // CLOSING THE DRIVER AT THIS POINT WILL MAKE THE SEND TASK BLOCK THE SYSTEM
558
559
15
        status = rtems_task_wake_after( SY_LFR_DPU_CONNECT_TIMEOUT );        // wait SY_LFR_DPU_CONNECT_TIMEOUT 1000 ms
560
561
15
        status_spw = spacewire_stop_and_start_link( fdSPW );
562
563
15
        if (  status_spw != RTEMS_SUCCESSFUL )
564
        {
565
15
            i = i + 1;
566
            PRINTF1("in spacewire_reset_link *** ERR spacewire_start_link code %d\n",  status_spw);
567
        }
568
        else
569
        {
570
            i = SY_LFR_DPU_CONNECT_ATTEMPT;
571
        }
572
    }
573
574
5
    return status_spw;
575
}
576
577
87
void spacewire_set_NP( unsigned char val, unsigned int regAddr ) // [N]o [P]ort force
578
{
579
    /** This function sets the [N]o [P]ort force bit of the GRSPW control register.
580
     *
581
     * @param val is the value, 0 or 1, used to set the value of the NP bit.
582
     * @param regAddr is the address of the GRSPW control register.
583
     *
584
     * NP is the bit 20 of the GRSPW control register.
585
     *
586
     */
587
588
87
    unsigned int *spwptr = (unsigned int*) regAddr;
589
590
87
    if (val == 1) {
591
87
        *spwptr = *spwptr | SPW_BIT_NP; // [NP] set the No port force bit
592
    }
593
87
    if (val== 0) {
594
        *spwptr = *spwptr & SPW_BIT_NP_MASK;
595
    }
596
87
}
597
598
87
void spacewire_set_RE( unsigned char val, unsigned int regAddr ) // [R]MAP [E]nable
599
{
600
    /** This function sets the [R]MAP [E]nable bit of the GRSPW control register.
601
     *
602
     * @param val is the value, 0 or 1, used to set the value of the RE bit.
603
     * @param regAddr is the address of the GRSPW control register.
604
     *
605
     * RE is the bit 16 of the GRSPW control register.
606
     *
607
     */
608
609
87
    unsigned int *spwptr = (unsigned int*) regAddr;
610
611
87
    if (val == 1)
612
    {
613
87
        *spwptr = *spwptr | SPW_BIT_RE; // [RE] set the RMAP Enable bit
614
    }
615
87
    if (val== 0)
616
    {
617
        *spwptr = *spwptr & SPW_BIT_RE_MASK;
618
    }
619
87
}
620
621
129642
void spacewire_read_statistics( void )
622
{
623
    /** This function reads the SpaceWire statistics from the grspw RTEMS driver.
624
     *
625
     * @param void
626
     *
627
     * @return void
628
     *
629
     * Once they are read, the counters are stored in a global variable used during the building of the
630
     * HK packets.
631
     *
632
     */
633
634
    rtems_status_code status;
635
    spw_stats current;
636
637
129642
    memset(&current, 0, sizeof(spw_stats));
638
639
129642
    spacewire_get_last_error();
640
641
    // read the current statistics
642
129642
    status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &current );
643
644
    // clear the counters
645
129642
    status = ioctl( fdSPW, SPACEWIRE_IOCTRL_CLR_STATISTICS );
646
647
    // rx_eep_err
648
129642
    grspw_stats.rx_eep_err      = grspw_stats.rx_eep_err        + current.rx_eep_err;
649
    // rx_truncated
650
129642
    grspw_stats.rx_truncated    = grspw_stats.rx_truncated      + current.rx_truncated;
651
    // parity_err
652
129642
    grspw_stats.parity_err      = grspw_stats.parity_err        + current.parity_err;
653
    // escape_err
654
129642
    grspw_stats.escape_err      = grspw_stats.escape_err        + current.escape_err;
655
    // credit_err
656
129642
    grspw_stats.credit_err      = grspw_stats.credit_err        + current.credit_err;
657
    // write_sync_err
658
129642
    grspw_stats.write_sync_err  = grspw_stats.write_sync_err    + current.write_sync_err;
659
    // disconnect_err
660
129642
    grspw_stats.disconnect_err  = grspw_stats.disconnect_err    + current.disconnect_err;
661
    // early_ep
662
129642
    grspw_stats.early_ep        = grspw_stats.early_ep          + current.early_ep;
663
    // invalid_address
664
129642
    grspw_stats.invalid_address = grspw_stats.invalid_address   + current.invalid_address;
665
    // packets_sent
666
129642
    grspw_stats.packets_sent    = grspw_stats.packets_sent      + current.packets_sent;
667
    // packets_received
668
129642
    grspw_stats.packets_received= grspw_stats.packets_received  + current.packets_received;
669
670
129642
}
671
672
129642
void spacewire_get_last_error( void )
673
{
674
    static spw_stats previous = {0};
675
    spw_stats current;
676
    rtems_status_code status;
677
678
    unsigned int  hk_lfr_last_er_rid;
679
    unsigned char hk_lfr_last_er_code;
680
    int coarseTime;
681
    int fineTime;
682
    unsigned char update_hk_lfr_last_er;
683
684
129642
    memset(&current, 0, sizeof(spw_stats));
685
129642
    hk_lfr_last_er_rid  = INIT_CHAR;
686
129642
    hk_lfr_last_er_code = INIT_CHAR;
687
129642
    update_hk_lfr_last_er = INIT_CHAR;
688
689
129642
    status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &current );
690
691
    // get current time
692
129642
    coarseTime = time_management_regs->coarse_time;
693
129642
    fineTime   = time_management_regs->fine_time;
694
695
    // tx_link_err *** no code associated to this field
696
    // rx_rmap_header_crc_err ***  LE *** in HK
697
129642
    if (previous.rx_rmap_header_crc_err != current.rx_rmap_header_crc_err)
698
    {
699
        hk_lfr_last_er_rid  = RID_LE_LFR_DPU_SPW;
700
        hk_lfr_last_er_code = CODE_HEADER_CRC;
701
        update_hk_lfr_last_er = 1;
702
    }
703
    // rx_rmap_data_crc_err ***  LE *** NOT IN HK
704
129642
    if (previous.rx_rmap_data_crc_err != current.rx_rmap_data_crc_err)
705
    {
706
        hk_lfr_last_er_rid  = RID_LE_LFR_DPU_SPW;
707
        hk_lfr_last_er_code = CODE_DATA_CRC;
708
        update_hk_lfr_last_er = 1;
709
    }
710
    // rx_eep_err
711
129642
    if (previous.rx_eep_err != current.rx_eep_err)
712
    {
713
        hk_lfr_last_er_rid  = RID_ME_LFR_DPU_SPW;
714
        hk_lfr_last_er_code = CODE_EEP;
715
        update_hk_lfr_last_er = 1;
716
    }
717
    // rx_truncated
718
129642
    if (previous.rx_truncated != current.rx_truncated)
719
    {
720
534
        hk_lfr_last_er_rid  = RID_ME_LFR_DPU_SPW;
721
534
        hk_lfr_last_er_code = CODE_RX_TOO_BIG;
722
534
        update_hk_lfr_last_er = 1;
723
    }
724
    // parity_err
725
129642
    if (previous.parity_err != current.parity_err)
726
    {
727
4
        hk_lfr_last_er_rid  = RID_LE_LFR_DPU_SPW;
728
4
        hk_lfr_last_er_code = CODE_PARITY;
729
4
        update_hk_lfr_last_er = 1;
730
    }
731
    // escape_err
732
129642
    if (previous.parity_err != current.parity_err)
733
    {
734
4
        hk_lfr_last_er_rid  = RID_LE_LFR_DPU_SPW;
735
4
        hk_lfr_last_er_code = CODE_ESCAPE;
736
4
        update_hk_lfr_last_er = 1;
737
    }
738
    // credit_err
739
129642
    if (previous.credit_err != current.credit_err)
740
    {
741
        hk_lfr_last_er_rid  = RID_LE_LFR_DPU_SPW;
742
        hk_lfr_last_er_code = CODE_CREDIT;
743
        update_hk_lfr_last_er = 1;
744
    }
745
    // write_sync_err
746
129642
    if (previous.write_sync_err != current.write_sync_err)
747
    {
748
        hk_lfr_last_er_rid  = RID_LE_LFR_DPU_SPW;
749
        hk_lfr_last_er_code = CODE_WRITE_SYNC;
750
        update_hk_lfr_last_er = 1;
751
    }
752
    // disconnect_err
753
129642
    if (previous.disconnect_err != current.disconnect_err)
754
    {
755
6
        hk_lfr_last_er_rid  = RID_LE_LFR_DPU_SPW;
756
6
        hk_lfr_last_er_code = CODE_DISCONNECT;
757
6
        update_hk_lfr_last_er = 1;
758
    }
759
    // early_ep
760
129642
    if (previous.early_ep != current.early_ep)
761
    {
762
        hk_lfr_last_er_rid  = RID_ME_LFR_DPU_SPW;
763
        hk_lfr_last_er_code = CODE_EARLY_EOP_EEP;
764
        update_hk_lfr_last_er = 1;
765
    }
766
    // invalid_address
767
129642
    if (previous.invalid_address != current.invalid_address)
768
    {
769
2
        hk_lfr_last_er_rid = RID_ME_LFR_DPU_SPW;
770
2
        hk_lfr_last_er_code = CODE_INVALID_ADDRESS;
771
2
        update_hk_lfr_last_er = 1;
772
    }
773
774
    // if a field has changed, update the hk_last_er fields
775
129642
    if (update_hk_lfr_last_er == 1)
776
    {
777
544
        update_hk_lfr_last_er_fields( hk_lfr_last_er_rid, hk_lfr_last_er_code );
778
    }
779
780
129642
    previous = current;
781
129642
}
782
783
4506
void update_hk_lfr_last_er_fields(unsigned int rid, unsigned char code)
784
{
785
    unsigned char *coarseTimePtr;
786
    unsigned char *fineTimePtr;
787
788
4506
    coarseTimePtr = (unsigned char*) &time_management_regs->coarse_time;
789
4506
    fineTimePtr = (unsigned char*) &time_management_regs->fine_time;
790
791
4506
    housekeeping_packet.hk_lfr_last_er_rid[0]   = (unsigned char) ((rid & BYTE0_MASK) >> SHIFT_1_BYTE );
792
4506
    housekeeping_packet.hk_lfr_last_er_rid[1]   = (unsigned char)  (rid & BYTE1_MASK);
793
4506
    housekeeping_packet.hk_lfr_last_er_code     = code;
794
4506
    housekeeping_packet.hk_lfr_last_er_time[0]  = coarseTimePtr[0];
795
4506
    housekeeping_packet.hk_lfr_last_er_time[1]  = coarseTimePtr[1];
796
4506
    housekeeping_packet.hk_lfr_last_er_time[BYTE_2]  = coarseTimePtr[BYTE_2];
797
4506
    housekeeping_packet.hk_lfr_last_er_time[BYTE_3]  = coarseTimePtr[BYTE_3];
798
4506
    housekeeping_packet.hk_lfr_last_er_time[BYTE_4]  = fineTimePtr[BYTE_2];
799
4506
    housekeeping_packet.hk_lfr_last_er_time[BYTE_5]  = fineTimePtr[BYTE_3];
800
4506
}
801
802
129632
void update_hk_with_grspw_stats( void )
803
{
804
    //****************************
805
    // DPU_SPACEWIRE_IF_STATISTICS
806
129632
    housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[0]   = (unsigned char) (grspw_stats.packets_received >> SHIFT_1_BYTE);
807
129632
    housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[1]   = (unsigned char) (grspw_stats.packets_received);
808
129632
    housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[0]  = (unsigned char) (grspw_stats.packets_sent >> SHIFT_1_BYTE);
809
129632
    housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[1]  = (unsigned char) (grspw_stats.packets_sent);
810
811
    //******************************************
812
    // ERROR COUNTERS / SPACEWIRE / LOW SEVERITY
813
129632
    housekeeping_packet.hk_lfr_dpu_spw_parity       = (unsigned char) grspw_stats.parity_err;
814
129632
    housekeeping_packet.hk_lfr_dpu_spw_disconnect   = (unsigned char) grspw_stats.disconnect_err;
815
129632
    housekeeping_packet.hk_lfr_dpu_spw_escape       = (unsigned char) grspw_stats.escape_err;
816
129632
    housekeeping_packet.hk_lfr_dpu_spw_credit       = (unsigned char) grspw_stats.credit_err;
817
129632
    housekeeping_packet.hk_lfr_dpu_spw_write_sync   = (unsigned char) grspw_stats.write_sync_err;
818
819
    //*********************************************
820
    // ERROR COUNTERS / SPACEWIRE / MEDIUM SEVERITY
821
129632
    housekeeping_packet.hk_lfr_dpu_spw_early_eop    = (unsigned char) grspw_stats.early_ep;
822
129632
    housekeeping_packet.hk_lfr_dpu_spw_invalid_addr = (unsigned char) grspw_stats.invalid_address;
823
129632
    housekeeping_packet.hk_lfr_dpu_spw_eep          = (unsigned char) grspw_stats.rx_eep_err;
824
129632
    housekeeping_packet.hk_lfr_dpu_spw_rx_too_big   = (unsigned char) grspw_stats.rx_truncated;
825
129632
}
826
827
129632
void spacewire_update_hk_lfr_link_state( unsigned char *hk_lfr_status_word_0 )
828
{
829
    unsigned int *statusRegisterPtr;
830
    unsigned char linkState;
831
832
129632
    statusRegisterPtr = (unsigned int *) (REGS_ADDR_GRSPW + APB_OFFSET_GRSPW_STATUS_REGISTER);
833
129632
    linkState =
834
129632
            (unsigned char) ( ( (*statusRegisterPtr) >>  SPW_LINK_STAT_POS) & STATUS_WORD_LINK_STATE_BITS);   // [0000 0111]
835
836
129632
    *hk_lfr_status_word_0 = *hk_lfr_status_word_0 & STATUS_WORD_LINK_STATE_MASK;       // [1111 1000] set link state to 0
837
838
129632
    *hk_lfr_status_word_0 = *hk_lfr_status_word_0 | linkState;  // update hk_lfr_dpu_spw_link_state
839
129632
}
840
841
6193
void increase_unsigned_char_counter( unsigned char *counter )
842
{
843
    // update the number of valid timecodes that have been received
844
6193
    if (*counter == UINT8_MAX)
845
    {
846
8
        *counter = 0;
847
    }
848
    else
849
    {
850
6185
        *counter = *counter + 1;
851
    }
852
6193
}
853
854
2231
unsigned int check_timecode_and_previous_timecode_coherency(unsigned char currentTimecodeCtr)
855
{
856
    /** This function checks the coherency between the incoming timecode and the last valid timecode.
857
     *
858
     * @param currentTimecodeCtr is the incoming timecode
859
     *
860
     * @return returned codes::
861
     * - LFR_DEFAULT
862
     * - LFR_SUCCESSFUL
863
     *
864
     */
865
866
    static unsigned char firstTickout = 1;
867
    unsigned char ret;
868
869
2231
    ret = LFR_DEFAULT;
870
871
2231
    if (firstTickout == 0)
872
    {
873
2207
        if (currentTimecodeCtr == 0)
874
        {
875
26
            if (previousTimecodeCtr == SPW_TIMECODE_MAX)
876
            {
877
26
                ret = LFR_SUCCESSFUL;
878
            }
879
            else
880
            {
881
                ret = LFR_DEFAULT;
882
            }
883
        }
884
        else
885
        {
886
2181
            if (currentTimecodeCtr == (previousTimecodeCtr +1))
887
            {
888
2176
                ret = LFR_SUCCESSFUL;
889
            }
890
            else
891
            {
892
5
                ret = LFR_DEFAULT;
893
            }
894
        }
895
    }
896
    else
897
    {
898
24
        firstTickout = 0;
899
24
        ret = LFR_SUCCESSFUL;
900
    }
901
902
2231
    return ret;
903
}
904
905
2231
unsigned int check_timecode_and_internal_time_coherency(unsigned char timecode, unsigned char internalTime)
906
{
907
    unsigned int ret;
908
909
2231
    ret = LFR_DEFAULT;
910
911
2231
    if (timecode == internalTime)
912
    {
913
735
        ret = LFR_SUCCESSFUL;
914
    }
915
    else
916
    {
917
1496
        ret = LFR_DEFAULT;
918
    }
919
920
2231
    return ret;
921
}
922
923
2231
void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc )
924
{
925
    // a tickout has been emitted, perform actions on the incoming timecode
926
927
    unsigned char incomingTimecode;
928
    unsigned char updateTime;
929
    unsigned char internalTime;
930
    rtems_status_code status;
931
932
2231
    incomingTimecode =        (unsigned char) (grspwPtr[0] & TIMECODE_MASK);
933
2231
    updateTime    = time_management_regs->coarse_time_load & TIMECODE_MASK;
934
2231
    internalTime  = time_management_regs->coarse_time      & TIMECODE_MASK;
935
936
2231
    housekeeping_packet.hk_lfr_dpu_spw_last_timc = incomingTimecode;
937
938
    // update the number of tickout that have been generated
939
2231
    increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt );
940
941
    //**************************
942
    // HK_LFR_TIMECODE_ERRONEOUS
943
    // MISSING and INVALID are handled by the timecode_timer_routine service routine
944
2231
    if (check_timecode_and_previous_timecode_coherency( incomingTimecode ) == LFR_DEFAULT)
945
    {
946
        // this is unexpected but a tickout could have been raised despite of the timecode being erroneous
947
5
        increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_erroneous );
948
5
        update_hk_lfr_last_er_fields( RID_LE_LFR_TIMEC, CODE_ERRONEOUS );
949
    }
950
951
    //************************
952
    // HK_LFR_TIME_TIMECODE_IT
953
    // check the coherency between the SpaceWire timecode and the Internal Time
954
2231
    if (check_timecode_and_internal_time_coherency( incomingTimecode, internalTime ) == LFR_DEFAULT)
955
    {
956
1496
        increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_time_timecode_it );
957
1496
        update_hk_lfr_last_er_fields( RID_LE_LFR_TIME, CODE_TIMECODE_IT );
958
    }
959
960
    //********************
961
    // HK_LFR_TIMECODE_CTR
962
    // check the value of the timecode with respect to the last TC_LFR_UPDATE_TIME => SSS-CP-FS-370
963
2231
    if (oneTcLfrUpdateTimeReceived == 1)
964
    {
965
2006
        if ( incomingTimecode != updateTime )
966
        {
967
1660
            increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_time_timecode_ctr );
968
1660
            update_hk_lfr_last_er_fields( RID_LE_LFR_TIME, CODE_TIMECODE_CTR );
969
        }
970
    }
971
972
    // launch the timecode timer to detect missing or invalid timecodes
973
2231
    previousTimecodeCtr = incomingTimecode;  // update the previousTimecodeCtr value
974
2231
    status = rtems_timer_fire_after( timecode_timer_id, TIMECODE_TIMER_TIMEOUT, timecode_timer_routine, NULL );
975
2231
    if (status != RTEMS_SUCCESSFUL)
976
    {
977
        rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_14 );
978
    }
979
2231
}
980
981
771
rtems_timer_service_routine timecode_timer_routine( rtems_id timer_id, void *user_data )
982
{
983
    static unsigned char initStep = 1;
984
985
    unsigned char currentTimecodeCtr;
986
987
771
    currentTimecodeCtr = (unsigned char) (grspwPtr[0] & TIMECODE_MASK);
988
989
771
    if (initStep == 1)
990
    {
991
771
        if (currentTimecodeCtr == previousTimecodeCtr)
992
        {
993
            //************************
994
            // HK_LFR_TIMECODE_MISSING
995
            // the timecode value has not changed, no valid timecode has been received, the timecode is MISSING
996
751
            increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_missing );
997
751
            update_hk_lfr_last_er_fields( RID_LE_LFR_TIMEC, CODE_MISSING );
998
        }
999
20
        else if (currentTimecodeCtr == (previousTimecodeCtr+1))
1000
        {
1001
            // the timecode value has changed and the value is valid, this is unexpected because
1002
            // the timer should not have fired, the timecode_irq_handler should have been raised
1003
        }
1004
        else
1005
        {
1006
            //************************
1007
            // HK_LFR_TIMECODE_INVALID
1008
            // the timecode value has changed and the value is not valid, no tickout has been generated
1009
            // this is why the timer has fired
1010
17
            increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_invalid );
1011
17
            update_hk_lfr_last_er_fields( RID_LE_LFR_TIMEC, CODE_INVALID );
1012
        }
1013
    }
1014
    else
1015
    {
1016
        initStep = 1;
1017
        //************************
1018
        // HK_LFR_TIMECODE_MISSING
1019
        increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_missing );
1020
        update_hk_lfr_last_er_fields( RID_LE_LFR_TIMEC, CODE_MISSING );
1021
    }
1022
1023
771
    rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_13 );
1024
771
}
1025
1026
94
void init_header_cwf( Header_TM_LFR_SCIENCE_CWF_t *header )
1027
{
1028
94
    header->targetLogicalAddress    = CCSDS_DESTINATION_ID;
1029
94
    header->protocolIdentifier      = CCSDS_PROTOCOLE_ID;
1030
94
    header->reserved                = DEFAULT_RESERVED;
1031
94
    header->userApplication         = CCSDS_USER_APP;
1032
94
    header->packetSequenceControl[0]= TM_PACKET_SEQ_CTRL_STANDALONE;
1033
94
    header->packetSequenceControl[1]= TM_PACKET_SEQ_CNT_DEFAULT;
1034
94
    header->packetLength[0] = INIT_CHAR;
1035
94
    header->packetLength[1] = INIT_CHAR;
1036
    // DATA FIELD HEADER
1037
94
    header->spare1_pusVersion_spare2    = DEFAULT_SPARE1_PUSVERSION_SPARE2;
1038
94
    header->serviceType     = TM_TYPE_LFR_SCIENCE; // service type
1039
94
    header->serviceSubType  = TM_SUBTYPE_LFR_SCIENCE_6; // service subtype
1040
94
    header->destinationID   = TM_DESTINATION_ID_GROUND;
1041
94
    header->time[BYTE_0] = INIT_CHAR;
1042
94
    header->time[BYTE_1] = INIT_CHAR;
1043
94
    header->time[BYTE_2] = INIT_CHAR;
1044
94
    header->time[BYTE_3] = INIT_CHAR;
1045
94
    header->time[BYTE_4] = INIT_CHAR;
1046
94
    header->time[BYTE_5] = INIT_CHAR;
1047
    // AUXILIARY DATA HEADER
1048
94
    header->sid = INIT_CHAR;
1049
94
    header->pa_bia_status_info = DEFAULT_HKBIA;
1050
94
    header->blkNr[0] = INIT_CHAR;
1051
94
    header->blkNr[1] = INIT_CHAR;
1052
94
}
1053
1054
94
void init_header_swf( Header_TM_LFR_SCIENCE_SWF_t *header )
1055
{
1056
94
    header->targetLogicalAddress        = CCSDS_DESTINATION_ID;
1057
94
    header->protocolIdentifier          = CCSDS_PROTOCOLE_ID;
1058
94
    header->reserved        = DEFAULT_RESERVED;
1059
94
    header->userApplication = CCSDS_USER_APP;
1060
94
    header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> SHIFT_1_BYTE);
1061
94
    header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1062
94
    header->packetSequenceControl[0]    = TM_PACKET_SEQ_CTRL_STANDALONE;
1063
94
    header->packetSequenceControl[1]    = TM_PACKET_SEQ_CNT_DEFAULT;
1064
94
    header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_336 >> SHIFT_1_BYTE);
1065
94
    header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_336     );
1066
    // DATA FIELD HEADER
1067
94
    header->spare1_pusVersion_spare2    = DEFAULT_SPARE1_PUSVERSION_SPARE2;
1068
94
    header->serviceType     = TM_TYPE_LFR_SCIENCE; // service type
1069
94
    header->serviceSubType  = TM_SUBTYPE_LFR_SCIENCE_6; // service subtype
1070
94
    header->destinationID   = TM_DESTINATION_ID_GROUND;
1071
94
    header->time[BYTE_0] = INIT_CHAR;
1072
94
    header->time[BYTE_1] = INIT_CHAR;
1073
94
    header->time[BYTE_2] = INIT_CHAR;
1074
94
    header->time[BYTE_3] = INIT_CHAR;
1075
94
    header->time[BYTE_4] = INIT_CHAR;
1076
94
    header->time[BYTE_5] = INIT_CHAR;
1077
    // AUXILIARY DATA HEADER
1078
94
    header->sid     = INIT_CHAR;
1079
94
    header->pa_bia_status_info   = DEFAULT_HKBIA;
1080
94
    header->pktCnt  = PKTCNT_SWF;  // PKT_CNT
1081
94
    header->pktNr   = INIT_CHAR;
1082
94
    header->blkNr[0]        = (unsigned char) (BLK_NR_CWF >> SHIFT_1_BYTE);
1083
94
    header->blkNr[1]        = (unsigned char) (BLK_NR_CWF     );
1084
94
}
1085
1086
94
void init_header_asm( Header_TM_LFR_SCIENCE_ASM_t *header )
1087
{
1088
94
    header->targetLogicalAddress        = CCSDS_DESTINATION_ID;
1089
94
    header->protocolIdentifier          = CCSDS_PROTOCOLE_ID;
1090
94
    header->reserved        = DEFAULT_RESERVED;
1091
94
    header->userApplication = CCSDS_USER_APP;
1092
94
    header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> SHIFT_1_BYTE);
1093
94
    header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1094
94
    header->packetSequenceControl[0]    = TM_PACKET_SEQ_CTRL_STANDALONE;
1095
94
    header->packetSequenceControl[1]    = TM_PACKET_SEQ_CNT_DEFAULT;
1096
94
    header->packetLength[0] = INIT_CHAR;
1097
94
    header->packetLength[1] = INIT_CHAR;
1098
    // DATA FIELD HEADER
1099
94
    header->spare1_pusVersion_spare2    = DEFAULT_SPARE1_PUSVERSION_SPARE2;
1100
94
    header->serviceType     = TM_TYPE_LFR_SCIENCE; // service type
1101
94
    header->serviceSubType  = TM_SUBTYPE_LFR_SCIENCE_3; // service subtype
1102
94
    header->destinationID   = TM_DESTINATION_ID_GROUND;
1103
94
    header->time[BYTE_0] = INIT_CHAR;
1104
94
    header->time[BYTE_1] = INIT_CHAR;
1105
94
    header->time[BYTE_2] = INIT_CHAR;
1106
94
    header->time[BYTE_3] = INIT_CHAR;
1107
94
    header->time[BYTE_4] = INIT_CHAR;
1108
94
    header->time[BYTE_5] = INIT_CHAR;
1109
    // AUXILIARY DATA HEADER
1110
94
    header->sid     = INIT_CHAR;
1111
94
    header->pa_bia_status_info = INIT_CHAR;
1112
94
    header->pa_lfr_pkt_cnt_asm = INIT_CHAR;
1113
94
    header->pa_lfr_pkt_nr_asm = INIT_CHAR;
1114
94
    header->pa_lfr_asm_blk_nr[0] = INIT_CHAR;
1115
94
    header->pa_lfr_asm_blk_nr[1] = INIT_CHAR;
1116
94
}
1117
1118
44080
int spw_send_waveform_CWF( ring_node *ring_node_to_send,
1119
                      Header_TM_LFR_SCIENCE_CWF_t *header )
1120
{
1121
    /** This function sends CWF CCSDS packets (F2, F1 or F0).
1122
     *
1123
     * @param waveform points to the buffer containing the data that will be send.
1124
     * @param sid is the source identifier of the data that will be sent.
1125
     * @param headerCWF points to a table of headers that have been prepared for the data transmission.
1126
     * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
1127
     * contain information to setup the transmission of the data packets.
1128
     *
1129
     * One group of 2048 samples is sent as 7 consecutive packets, 6 packets containing 340 blocks and 8 packets containing 8 blocks.
1130
     *
1131
     */
1132
1133
    unsigned int i;
1134
    int ret;
1135
    unsigned int coarseTime;
1136
    unsigned int fineTime;
1137
    rtems_status_code status;
1138
    spw_ioctl_pkt_send spw_ioctl_send_CWF;
1139
    int *dataPtr;
1140
    unsigned char sid;
1141
1142
44080
    spw_ioctl_send_CWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_CWF;
1143
44080
    spw_ioctl_send_CWF.options = 0;
1144
1145
44080
    ret = LFR_DEFAULT;
1146
44080
    sid = (unsigned char) ring_node_to_send->sid;
1147
1148
44080
    coarseTime  = ring_node_to_send->coarseTime;
1149
44080
    fineTime    = ring_node_to_send->fineTime;
1150
44080
    dataPtr     = (int*) ring_node_to_send->buffer_address;
1151
1152
44080
    header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_336 >> SHIFT_1_BYTE);
1153
44080
    header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_336     );
1154
44080
    header->pa_bia_status_info = pa_bia_status_info;
1155
44080
    header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1156
44080
    header->blkNr[0] = (unsigned char) (BLK_NR_CWF >> SHIFT_1_BYTE);
1157
44080
    header->blkNr[1] = (unsigned char) (BLK_NR_CWF     );
1158
1159
396720
    for (i=0; i<NB_PACKETS_PER_GROUP_OF_CWF; i++) // send waveform
1160
    {
1161
352640
        spw_ioctl_send_CWF.data = (char*) &dataPtr[ (i * BLK_NR_CWF * NB_WORDS_SWF_BLK) ];
1162
352640
        spw_ioctl_send_CWF.hdr  = (char*) header;
1163
        // BUILD THE DATA
1164
352640
        spw_ioctl_send_CWF.dlen = BLK_NR_CWF * NB_BYTES_SWF_BLK;
1165
1166
        // SET PACKET SEQUENCE CONTROL
1167
352640
        increment_seq_counter_source_id( header->packetSequenceControl, sid );
1168
1169
        // SET SID
1170
352640
        header->sid = sid;
1171
1172
        // SET PACKET TIME
1173
352640
        compute_acquisition_time( coarseTime, fineTime, sid, i, header->acquisitionTime);
1174
        //
1175
352640
        header->time[0] = header->acquisitionTime[0];
1176
352640
        header->time[1] = header->acquisitionTime[1];
1177
352640
        header->time[BYTE_2] = header->acquisitionTime[BYTE_2];
1178
352640
        header->time[BYTE_3] = header->acquisitionTime[BYTE_3];
1179
352640
        header->time[BYTE_4] = header->acquisitionTime[BYTE_4];
1180
352640
        header->time[BYTE_5] = header->acquisitionTime[BYTE_5];
1181
1182
        // SET PACKET ID
1183
352640
        if ( (sid == SID_SBM1_CWF_F1) || (sid == SID_SBM2_CWF_F2) )
1184
        {
1185
343928
            header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_SBM1_SBM2 >> SHIFT_1_BYTE);
1186
343928
            header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_SBM1_SBM2);
1187
        }
1188
        else
1189
        {
1190
8712
            header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> SHIFT_1_BYTE);
1191
8712
            header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1192
        }
1193
1194
352640
        status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF );
1195
352640
        if (status != RTEMS_SUCCESSFUL) {
1196
            ret = LFR_DEFAULT;
1197
        }
1198
    }
1199
1200
44080
    return ret;
1201
}
1202
1203
5535
int spw_send_waveform_SWF( ring_node *ring_node_to_send,
1204
                       Header_TM_LFR_SCIENCE_SWF_t *header )
1205
{
1206
    /** This function sends SWF CCSDS packets (F2, F1 or F0).
1207
     *
1208
     * @param waveform points to the buffer containing the data that will be send.
1209
     * @param sid is the source identifier of the data that will be sent.
1210
     * @param headerSWF points to a table of headers that have been prepared for the data transmission.
1211
     * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
1212
     * contain information to setup the transmission of the data packets.
1213
     *
1214
     * One group of 2048 samples is sent as 7 consecutive packets, 6 packets containing 340 blocks and 8 packets containing 8 blocks.
1215
     *
1216
     */
1217
1218
    unsigned int i;
1219
    int ret;
1220
    unsigned int coarseTime;
1221
    unsigned int fineTime;
1222
    rtems_status_code status;
1223
    spw_ioctl_pkt_send spw_ioctl_send_SWF;
1224
    int *dataPtr;
1225
    unsigned char sid;
1226
1227
5535
    spw_ioctl_send_SWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_SWF;
1228
5535
    spw_ioctl_send_SWF.options = 0;
1229
1230
5535
    ret = LFR_DEFAULT;
1231
1232
5535
    coarseTime  = ring_node_to_send->coarseTime;
1233
5535
    fineTime    = ring_node_to_send->fineTime;
1234
5535
    dataPtr     = (int*) ring_node_to_send->buffer_address;
1235
5535
    sid = ring_node_to_send->sid;
1236
1237
5535
    header->pa_bia_status_info = pa_bia_status_info;
1238
5535
    header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1239
1240
44280
    for (i=0; i<PKTCNT_SWF; i++) // send waveform
1241
    {
1242
38745
        spw_ioctl_send_SWF.data = (char*) &dataPtr[ (i * BLK_NR_304 * NB_WORDS_SWF_BLK) ];
1243
38745
        spw_ioctl_send_SWF.hdr = (char*) header;
1244
1245
        // SET PACKET SEQUENCE CONTROL
1246
38745
        increment_seq_counter_source_id( header->packetSequenceControl, sid );
1247
1248
        // SET PACKET LENGTH AND BLKNR
1249
38745
        if (i == (PKTCNT_SWF-1))
1250
        {
1251
5535
            spw_ioctl_send_SWF.dlen = BLK_NR_224 * NB_BYTES_SWF_BLK;
1252
5535
            header->packetLength[0] = (unsigned char) (TM_LEN_SCI_SWF_224 >> SHIFT_1_BYTE);
1253
5535
            header->packetLength[1] = (unsigned char) (TM_LEN_SCI_SWF_224     );
1254
5535
            header->blkNr[0] = (unsigned char) (BLK_NR_224 >> SHIFT_1_BYTE);
1255
5535
            header->blkNr[1] = (unsigned char) (BLK_NR_224     );
1256
        }
1257
        else
1258
        {
1259
33210
            spw_ioctl_send_SWF.dlen = BLK_NR_304 * NB_BYTES_SWF_BLK;
1260
33210
            header->packetLength[0] = (unsigned char) (TM_LEN_SCI_SWF_304 >> SHIFT_1_BYTE);
1261
33210
            header->packetLength[1] = (unsigned char) (TM_LEN_SCI_SWF_304     );
1262
33210
            header->blkNr[0] = (unsigned char) (BLK_NR_304 >> SHIFT_1_BYTE);
1263
33210
            header->blkNr[1] = (unsigned char) (BLK_NR_304     );
1264
        }
1265
1266
        // SET PACKET TIME
1267
38745
        compute_acquisition_time( coarseTime, fineTime, sid, i, header->acquisitionTime );
1268
        //
1269
38745
        header->time[BYTE_0] = header->acquisitionTime[BYTE_0];
1270
38745
        header->time[BYTE_1] = header->acquisitionTime[BYTE_1];
1271
38745
        header->time[BYTE_2] = header->acquisitionTime[BYTE_2];
1272
38745
        header->time[BYTE_3] = header->acquisitionTime[BYTE_3];
1273
38745
        header->time[BYTE_4] = header->acquisitionTime[BYTE_4];
1274
38745
        header->time[BYTE_5] = header->acquisitionTime[BYTE_5];
1275
1276
        // SET SID
1277
38745
        header->sid = sid;
1278
1279
        // SET PKTNR
1280
38745
        header->pktNr = i+1;    // PKT_NR
1281
1282
        // SEND PACKET
1283
38745
        status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_SWF );
1284
38745
        if (status != RTEMS_SUCCESSFUL) {
1285
            ret = LFR_DEFAULT;
1286
        }
1287
    }
1288
1289
5535
    return ret;
1290
}
1291
1292
391
int spw_send_waveform_CWF3_light( ring_node *ring_node_to_send,
1293
                                  Header_TM_LFR_SCIENCE_CWF_t *header )
1294
{
1295
    /** This function sends CWF_F3 CCSDS packets without the b1, b2 and b3 data.
1296
     *
1297
     * @param waveform points to the buffer containing the data that will be send.
1298
     * @param headerCWF points to a table of headers that have been prepared for the data transmission.
1299
     * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
1300
     * contain information to setup the transmission of the data packets.
1301
     *
1302
     * By default, CWF_F3 packet are send without the b1, b2 and b3 data. This function rebuilds a data buffer
1303
     * from the incoming data and sends it in 7 packets, 6 containing 340 blocks and 1 one containing 8 blocks.
1304
     *
1305
     */
1306
1307
    unsigned int i;
1308
    int ret;
1309
    unsigned int coarseTime;
1310
    unsigned int fineTime;
1311
    rtems_status_code status;
1312
    spw_ioctl_pkt_send spw_ioctl_send_CWF;
1313
    char *dataPtr;
1314
    unsigned char sid;
1315
1316
391
    spw_ioctl_send_CWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_CWF;
1317
391
    spw_ioctl_send_CWF.options = 0;
1318
1319
391
    ret = LFR_DEFAULT;
1320
391
    sid = ring_node_to_send->sid;
1321
1322
391
    coarseTime  = ring_node_to_send->coarseTime;
1323
391
    fineTime    = ring_node_to_send->fineTime;
1324
391
    dataPtr     = (char*) ring_node_to_send->buffer_address;
1325
1326
391
    header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_672 >> SHIFT_1_BYTE);
1327
391
    header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_672     );
1328
391
    header->pa_bia_status_info = pa_bia_status_info;
1329
391
    header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1330
391
    header->blkNr[0] = (unsigned char) (BLK_NR_CWF_SHORT_F3 >> SHIFT_1_BYTE);
1331
391
    header->blkNr[1] = (unsigned char) (BLK_NR_CWF_SHORT_F3     );
1332
1333
    //*********************
1334
    // SEND CWF3_light DATA
1335
1955
    for (i=0; i<NB_PACKETS_PER_GROUP_OF_CWF_LIGHT; i++) // send waveform
1336
    {
1337
1564
        spw_ioctl_send_CWF.data = (char*) &dataPtr[ (i * BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK) ];
1338
1564
        spw_ioctl_send_CWF.hdr = (char*) header;
1339
        // BUILD THE DATA
1340
1564
        spw_ioctl_send_CWF.dlen = BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK;
1341
1342
        // SET PACKET SEQUENCE COUNTER
1343
1564
        increment_seq_counter_source_id( header->packetSequenceControl, sid );
1344
1345
        // SET SID
1346
1564
        header->sid = sid;
1347
1348
        // SET PACKET TIME
1349
1564
        compute_acquisition_time( coarseTime, fineTime, SID_NORM_CWF_F3, i, header->acquisitionTime );
1350
        //
1351
1564
        header->time[BYTE_0] = header->acquisitionTime[BYTE_0];
1352
1564
        header->time[BYTE_1] = header->acquisitionTime[BYTE_1];
1353
1564
        header->time[BYTE_2] = header->acquisitionTime[BYTE_2];
1354
1564
        header->time[BYTE_3] = header->acquisitionTime[BYTE_3];
1355
1564
        header->time[BYTE_4] = header->acquisitionTime[BYTE_4];
1356
1564
        header->time[BYTE_5] = header->acquisitionTime[BYTE_5];
1357
1358
        // SET PACKET ID
1359
1564
        header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> SHIFT_1_BYTE);
1360
1564
        header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1361
1362
        // SEND PACKET
1363
1564
        status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF );
1364
1564
        if (status != RTEMS_SUCCESSFUL) {
1365
            ret = LFR_DEFAULT;
1366
        }
1367
    }
1368
1369
391
    return ret;
1370
}
1371
1372
16114
void spw_send_asm_f0( ring_node *ring_node_to_send,
1373
                   Header_TM_LFR_SCIENCE_ASM_t *header )
1374
{
1375
    unsigned int i;
1376
16114
    unsigned int length = 0;
1377
    rtems_status_code status;
1378
    unsigned int sid;
1379
    float *spectral_matrix;
1380
    int coarseTime;
1381
    int fineTime;
1382
    spw_ioctl_pkt_send spw_ioctl_send_ASM;
1383
1384
16114
    sid = ring_node_to_send->sid;
1385
16114
    spectral_matrix = (float*) ring_node_to_send->buffer_address;
1386
16114
    coarseTime = ring_node_to_send->coarseTime;
1387
16114
    fineTime = ring_node_to_send->fineTime;
1388
1389
16114
    header->pa_bia_status_info = pa_bia_status_info;
1390
16114
    header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1391
1392
64456
    for (i=0; i<PKTCNT_ASM; i++)
1393
    {
1394
48342
        if ((i==0) || (i==1))
1395
        {
1396
32228
            spw_ioctl_send_ASM.dlen = DLEN_ASM_F0_PKT_1;
1397
32228
            spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1398
                    ( (ASM_F0_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F0_1) ) * NB_VALUES_PER_SM )
1399
32228
                    ];
1400
32228
            length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F0_1;
1401
32228
            header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1402
32228
            header->pa_lfr_asm_blk_nr[0] = (unsigned char)  ( (NB_BINS_PER_PKT_ASM_F0_1) >> SHIFT_1_BYTE ); // BLK_NR MSB
1403
32228
            header->pa_lfr_asm_blk_nr[1] = (unsigned char)    (NB_BINS_PER_PKT_ASM_F0_1);        // BLK_NR LSB
1404
        }
1405
        else
1406
        {
1407
16114
            spw_ioctl_send_ASM.dlen = DLEN_ASM_F0_PKT_2;
1408
16114
            spw_ioctl_send_ASM.data = (char*) &spectral_matrix[
1409
                    ( (ASM_F0_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F0_1) ) * NB_VALUES_PER_SM )
1410
16114
                    ];
1411
16114
            length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F0_2;
1412
16114
            header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1413
16114
            header->pa_lfr_asm_blk_nr[0] = (unsigned char)  ( (NB_BINS_PER_PKT_ASM_F0_2) >> SHIFT_1_BYTE ); // BLK_NR MSB
1414
16114
            header->pa_lfr_asm_blk_nr[1] = (unsigned char)    (NB_BINS_PER_PKT_ASM_F0_2);        // BLK_NR LSB
1415
        }
1416
1417
48342
        spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1418
48342
        spw_ioctl_send_ASM.hdr = (char *) header;
1419
48342
        spw_ioctl_send_ASM.options = 0;
1420
1421
        // (2) BUILD THE HEADER
1422
48342
        increment_seq_counter_source_id( header->packetSequenceControl, sid );
1423
48342
        header->packetLength[0] = (unsigned char) (length >> SHIFT_1_BYTE);
1424
48342
        header->packetLength[1] = (unsigned char) (length);
1425
48342
        header->sid = (unsigned char) sid;   // SID
1426
48342
        header->pa_lfr_pkt_cnt_asm = PKTCNT_ASM;
1427
48342
        header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1428
1429
        // (3) SET PACKET TIME
1430
48342
        header->time[BYTE_0] = (unsigned char) (coarseTime >> SHIFT_3_BYTES);
1431
48342
        header->time[BYTE_1] = (unsigned char) (coarseTime >> SHIFT_2_BYTES);
1432
48342
        header->time[BYTE_2] = (unsigned char) (coarseTime >> SHIFT_1_BYTE);
1433
48342
        header->time[BYTE_3] = (unsigned char) (coarseTime);
1434
48342
        header->time[BYTE_4] = (unsigned char) (fineTime >> SHIFT_1_BYTE);
1435
48342
        header->time[BYTE_5] = (unsigned char) (fineTime);
1436
        //
1437
48342
        header->acquisitionTime[BYTE_0] = header->time[BYTE_0];
1438
48342
        header->acquisitionTime[BYTE_1] = header->time[BYTE_1];
1439
48342
        header->acquisitionTime[BYTE_2] = header->time[BYTE_2];
1440
48342
        header->acquisitionTime[BYTE_3] = header->time[BYTE_3];
1441
48342
        header->acquisitionTime[BYTE_4] = header->time[BYTE_4];
1442
48342
        header->acquisitionTime[BYTE_5] = header->time[BYTE_5];
1443
1444
        // (4) SEND PACKET
1445
48342
        status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1446
        if (status != RTEMS_SUCCESSFUL) {
1447
            PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1448
        }
1449
    }
1450
16114
}
1451
1452
16112
void spw_send_asm_f1( ring_node *ring_node_to_send,
1453
                   Header_TM_LFR_SCIENCE_ASM_t *header )
1454
{
1455
    unsigned int i;
1456
16112
    unsigned int length = 0;
1457
    rtems_status_code status;
1458
    unsigned int sid;
1459
    float *spectral_matrix;
1460
    int coarseTime;
1461
    int fineTime;
1462
    spw_ioctl_pkt_send spw_ioctl_send_ASM;
1463
1464
16112
    sid = ring_node_to_send->sid;
1465
16112
    spectral_matrix = (float*) ring_node_to_send->buffer_address;
1466
16112
    coarseTime = ring_node_to_send->coarseTime;
1467
16112
    fineTime = ring_node_to_send->fineTime;
1468
1469
16112
    header->pa_bia_status_info = pa_bia_status_info;
1470
16112
    header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1471
1472
64448
    for (i=0; i<PKTCNT_ASM; i++)
1473
    {
1474
48336
        if ((i==0) || (i==1))
1475
        {
1476
32224
            spw_ioctl_send_ASM.dlen = DLEN_ASM_F1_PKT_1;
1477
32224
            spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1478
                    ( (ASM_F1_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F1_1) ) * NB_VALUES_PER_SM )
1479
32224
                    ];
1480
32224
            length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F1_1;
1481
32224
            header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1482
32224
            header->pa_lfr_asm_blk_nr[0] = (unsigned char)  ( (NB_BINS_PER_PKT_ASM_F1_1) >> SHIFT_1_BYTE ); // BLK_NR MSB
1483
32224
            header->pa_lfr_asm_blk_nr[1] = (unsigned char)    (NB_BINS_PER_PKT_ASM_F1_1);        // BLK_NR LSB
1484
        }
1485
        else
1486
        {
1487
16112
            spw_ioctl_send_ASM.dlen = DLEN_ASM_F1_PKT_2;
1488
16112
            spw_ioctl_send_ASM.data = (char*) &spectral_matrix[
1489
                    ( (ASM_F1_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F1_1) ) * NB_VALUES_PER_SM )
1490
16112
                    ];
1491
16112
            length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F1_2;
1492
16112
            header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1493
16112
            header->pa_lfr_asm_blk_nr[0] = (unsigned char)  ( (NB_BINS_PER_PKT_ASM_F1_2) >> SHIFT_1_BYTE ); // BLK_NR MSB
1494
16112
            header->pa_lfr_asm_blk_nr[1] = (unsigned char)    (NB_BINS_PER_PKT_ASM_F1_2);        // BLK_NR LSB
1495
        }
1496
1497
48336
        spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1498
48336
        spw_ioctl_send_ASM.hdr = (char *) header;
1499
48336
        spw_ioctl_send_ASM.options = 0;
1500
1501
        // (2) BUILD THE HEADER
1502
48336
        increment_seq_counter_source_id( header->packetSequenceControl, sid );
1503
48336
        header->packetLength[0] = (unsigned char) (length >> SHIFT_1_BYTE);
1504
48336
        header->packetLength[1] = (unsigned char) (length);
1505
48336
        header->sid = (unsigned char) sid;   // SID
1506
48336
        header->pa_lfr_pkt_cnt_asm = PKTCNT_ASM;
1507
48336
        header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1508
1509
        // (3) SET PACKET TIME
1510
48336
        header->time[BYTE_0] = (unsigned char) (coarseTime >> SHIFT_3_BYTES);
1511
48336
        header->time[BYTE_1] = (unsigned char) (coarseTime >> SHIFT_2_BYTES);
1512
48336
        header->time[BYTE_2] = (unsigned char) (coarseTime >> SHIFT_1_BYTE);
1513
48336
        header->time[BYTE_3] = (unsigned char) (coarseTime);
1514
48336
        header->time[BYTE_4] = (unsigned char) (fineTime >> SHIFT_1_BYTE);
1515
48336
        header->time[BYTE_5] = (unsigned char) (fineTime);
1516
        //
1517
48336
        header->acquisitionTime[BYTE_0] = header->time[BYTE_0];
1518
48336
        header->acquisitionTime[BYTE_1] = header->time[BYTE_1];
1519
48336
        header->acquisitionTime[BYTE_2] = header->time[BYTE_2];
1520
48336
        header->acquisitionTime[BYTE_3] = header->time[BYTE_3];
1521
48336
        header->acquisitionTime[BYTE_4] = header->time[BYTE_4];
1522
48336
        header->acquisitionTime[BYTE_5] = header->time[BYTE_5];
1523
1524
        // (4) SEND PACKET
1525
48336
        status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1526
        if (status != RTEMS_SUCCESSFUL) {
1527
            PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1528
        }
1529
    }
1530
16112
}
1531
1532
/**
1533
 * @brief spw_send_asm_f2 Sends an ASM packet at F2 over spacewire
1534
 * @param ring_node_to_send node pointing to the actual buffer to send
1535
 * @param header
1536
 */
1537
16100
void spw_send_asm_f2( ring_node *ring_node_to_send,
1538
                   Header_TM_LFR_SCIENCE_ASM_t *header )
1539
{
1540
    unsigned int i;
1541
16100
    unsigned int length = 0;
1542
    rtems_status_code status;
1543
    unsigned int sid;
1544
    float *spectral_matrix;
1545
    int coarseTime;
1546
    int fineTime;
1547
    spw_ioctl_pkt_send spw_ioctl_send_ASM;
1548
1549
16100
    sid = ring_node_to_send->sid;
1550
16100
    spectral_matrix = (float*) ring_node_to_send->buffer_address;
1551
16100
    coarseTime = ring_node_to_send->coarseTime;
1552
16100
    fineTime = ring_node_to_send->fineTime;
1553
1554
16100
    header->pa_bia_status_info = pa_bia_status_info;
1555
16100
    header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1556
1557
64400
    for (i=0; i<PKTCNT_ASM; i++)
1558
    {
1559
1560
48300
        spw_ioctl_send_ASM.dlen = DLEN_ASM_F2_PKT;
1561
48300
        spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1562
                ( (ASM_F2_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F2) ) * NB_VALUES_PER_SM )
1563
48300
                ];
1564
48300
        length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F2;
1565
48300
        header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_3;
1566
48300
        header->pa_lfr_asm_blk_nr[0] = (unsigned char)  ( (NB_BINS_PER_PKT_ASM_F2) >> SHIFT_1_BYTE ); // BLK_NR MSB
1567
48300
        header->pa_lfr_asm_blk_nr[1] = (unsigned char)    (NB_BINS_PER_PKT_ASM_F2);        // BLK_NR LSB
1568
1569
48300
        spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1570
48300
        spw_ioctl_send_ASM.hdr = (char *) header;
1571
48300
        spw_ioctl_send_ASM.options = 0;
1572
1573
        // (2) BUILD THE HEADER
1574
48300
        increment_seq_counter_source_id( header->packetSequenceControl, sid );
1575
48300
        header->packetLength[0] = (unsigned char) (length >> SHIFT_1_BYTE);
1576
48300
        header->packetLength[1] = (unsigned char) (length);
1577
48300
        header->sid = (unsigned char) sid;   // SID
1578
48300
        header->pa_lfr_pkt_cnt_asm = PKTCNT_ASM;
1579
48300
        header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1580
1581
        // (3) SET PACKET TIME
1582
48300
        header->time[BYTE_0] = (unsigned char) (coarseTime >> SHIFT_3_BYTES);
1583
48300
        header->time[BYTE_1] = (unsigned char) (coarseTime >> SHIFT_2_BYTES);
1584
48300
        header->time[BYTE_2] = (unsigned char) (coarseTime >> SHIFT_1_BYTE);
1585
48300
        header->time[BYTE_3] = (unsigned char) (coarseTime);
1586
48300
        header->time[BYTE_4] = (unsigned char) (fineTime >> SHIFT_1_BYTE);
1587
48300
        header->time[BYTE_5] = (unsigned char) (fineTime);
1588
        //
1589
48300
        header->acquisitionTime[BYTE_0] = header->time[BYTE_0];
1590
48300
        header->acquisitionTime[BYTE_1] = header->time[BYTE_1];
1591
48300
        header->acquisitionTime[BYTE_2] = header->time[BYTE_2];
1592
48300
        header->acquisitionTime[BYTE_3] = header->time[BYTE_3];
1593
48300
        header->acquisitionTime[BYTE_4] = header->time[BYTE_4];
1594
48300
        header->acquisitionTime[BYTE_5] = header->time[BYTE_5];
1595
1596
        // (4) SEND PACKET
1597
48300
        status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1598
        if (status != RTEMS_SUCCESSFUL) {
1599
            PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1600
        }
1601
    }
1602
16100
}
1603
1604
/**
1605
 * @brief spw_send_k_dump Sends k coefficients dump packet over spacewire
1606
 * @param ring_node_to_send node pointing to the actual buffer to send
1607
 */
1608
3050
void spw_send_k_dump( ring_node *ring_node_to_send )
1609
{
1610
    rtems_status_code status;
1611
    Packet_TM_LFR_KCOEFFICIENTS_DUMP_t *kcoefficients_dump;
1612
    unsigned int packetLength;
1613
    unsigned int size;
1614
1615
    PRINTF("spw_send_k_dump\n")
1616
1617
3050
    kcoefficients_dump = (Packet_TM_LFR_KCOEFFICIENTS_DUMP_t *) ring_node_to_send->buffer_address;
1618
1619
3050
    packetLength = (kcoefficients_dump->packetLength[0] * CONST_256) + kcoefficients_dump->packetLength[1];
1620
1621
3050
    size = packetLength + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES;
1622
1623
    PRINTF2("packetLength %d, size %d\n", packetLength, size )
1624
1625
3050
    status = write( fdSPW, (char *) ring_node_to_send->buffer_address, size );
1626
1627
    if (status == -1){
1628
        PRINTF2("in SEND *** (2.a) ERRNO = %d, size = %d\n", errno, size)
1629
    }
1630
1631
3050
    ring_node_to_send->status = INIT_CHAR;
1632
3050
}