GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/wf_handler.c Lines: 456 483 94.4 %
Date: 2018-10-05 11:31:56 Branches: 131 160 81.9 %

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 and tasks related to waveform packet generation.
26
 *
27
 * @file
28
 * @author P. LEROY
29
 *
30
 * A group of functions to handle waveforms, in snapshot or continuous format.\n
31
 *
32
 */
33
34
#include "wf_handler.h"
35
36
//***************
37
// waveform rings
38
// F0
39
ring_node waveform_ring_f0[NB_RING_NODES_F0]= {0};
40
ring_node *current_ring_node_f0             = NULL;
41
ring_node *ring_node_to_send_swf_f0         = NULL;
42
// F1
43
ring_node waveform_ring_f1[NB_RING_NODES_F1] = {0};
44
ring_node *current_ring_node_f1             = NULL;
45
ring_node *ring_node_to_send_swf_f1         = NULL;
46
ring_node *ring_node_to_send_cwf_f1         = NULL;
47
// F2
48
ring_node waveform_ring_f2[NB_RING_NODES_F2] = {0};
49
ring_node *current_ring_node_f2             = NULL;
50
ring_node *ring_node_to_send_swf_f2         = NULL;
51
ring_node *ring_node_to_send_cwf_f2         = NULL;
52
// F3
53
ring_node waveform_ring_f3[NB_RING_NODES_F3] = {0};
54
ring_node *current_ring_node_f3             = NULL;
55
ring_node *ring_node_to_send_cwf_f3         = NULL;
56
char wf_cont_f3_light[ (NB_SAMPLES_PER_SNAPSHOT) * NB_BYTES_CWF3_LIGHT_BLK ] = {0};
57
58
bool extractSWF1 = false;
59
bool extractSWF2 = false;
60
bool swf0_ready_flag_f1 = false;
61
bool swf0_ready_flag_f2 = false;
62
bool swf1_ready = false;
63
bool swf2_ready = false;
64
65
int swf1_extracted[ (NB_SAMPLES_PER_SNAPSHOT * NB_WORDS_SWF_BLK) ] = {0};
66
int swf2_extracted[ (NB_SAMPLES_PER_SNAPSHOT * NB_WORDS_SWF_BLK) ] = {0};
67
ring_node ring_node_swf1_extracted = {0};
68
ring_node ring_node_swf2_extracted = {0};
69
70
typedef enum resynchro_state_t
71
{
72
    MEASURE,
73
    CORRECTION
74
} resynchro_state;
75
76
//*********************
77
// Interrupt SubRoutine
78
79
4184
ring_node * getRingNodeToSendCWF( unsigned char frequencyChannel)
80
{
81
    ring_node *node;
82
83
4184
    node = NULL;
84

4184
    switch ( frequencyChannel ) {
85
    case CHANNELF1:
86
3896
        node = ring_node_to_send_cwf_f1;
87
3896
        break;
88
    case CHANNELF2:
89
279
        node = ring_node_to_send_cwf_f2;
90
279
        break;
91
    case CHANNELF3:
92
9
        node = ring_node_to_send_cwf_f3;
93
        break;
94
    default:
95
        break;
96
    }
97
98
4184
    return node;
99
}
100
101
ring_node * getRingNodeToSendSWF( unsigned char frequencyChannel)
102
{
103
    ring_node *node;
104
105
    node = NULL;
106
    switch ( frequencyChannel ) {
107
    case CHANNELF0:
108
        node = ring_node_to_send_swf_f0;
109
        break;
110
    case CHANNELF1:
111
        node = ring_node_to_send_swf_f1;
112
        break;
113
    case CHANNELF2:
114
        node = ring_node_to_send_swf_f2;
115
        break;
116
    default:
117
        break;
118
    }
119
120
    return node;
121
}
122
123
144
void reset_extractSWF( void )
124
{
125
144
    extractSWF1 = false;
126
144
    extractSWF2 = false;
127
144
    swf0_ready_flag_f1 = false;
128
144
    swf0_ready_flag_f2 = false;
129
144
    swf1_ready = false;
130
144
    swf2_ready = false;
131
144
}
132
133
4211
inline void waveforms_isr_f3( void )
134
{
135
    rtems_status_code spare_status;
136
137
4211
    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
138
         || (lfrCurrentMode == LFR_MODE_SBM1) || (lfrCurrentMode == LFR_MODE_SBM2) )
139
    { // in modes other than STANDBY and BURST, send the CWF_F3 data
140
        //***
141
        // F3
142
4211
        if ( (waveform_picker_regs->status & BITS_WFP_STATUS_F3) != INIT_CHAR ) {  // [1100 0000] check the f3 full bits
143
12
            ring_node_to_send_cwf_f3    = current_ring_node_f3->previous;
144
12
            current_ring_node_f3        = current_ring_node_f3->next;
145
12
            if ((waveform_picker_regs->status & BIT_WFP_BUF_F3_0) == BIT_WFP_BUF_F3_0){             // [0100 0000] f3 buffer 0 is full
146
7
                ring_node_to_send_cwf_f3->coarseTime    = waveform_picker_regs->f3_0_coarse_time;
147
7
                ring_node_to_send_cwf_f3->fineTime      = waveform_picker_regs->f3_0_fine_time;
148
7
                waveform_picker_regs->addr_data_f3_0    = current_ring_node_f3->buffer_address;
149
7
                waveform_picker_regs->status            = waveform_picker_regs->status & RST_WFP_F3_0; // [1000 1000 0100 0000]
150
            }
151
5
            else if ((waveform_picker_regs->status & BIT_WFP_BUF_F3_1) == BIT_WFP_BUF_F3_1){    // [1000 0000] f3 buffer 1 is full
152
5
                ring_node_to_send_cwf_f3->coarseTime    = waveform_picker_regs->f3_1_coarse_time;
153
5
                ring_node_to_send_cwf_f3->fineTime      = waveform_picker_regs->f3_1_fine_time;
154
5
                waveform_picker_regs->addr_data_f3_1    = current_ring_node_f3->buffer_address;
155
5
                waveform_picker_regs->status            = waveform_picker_regs->status & RST_WFP_F3_1; // [1000 1000 1000 0000]
156
            }
157
12
            if (rtems_event_send( Task_id[TASKID_CWF3], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) {
158
                spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 );
159
            }
160
        }
161
    }
162
4211
}
163
164
67
inline void waveforms_isr_burst( void )
165
{
166
    unsigned char status;
167
    rtems_status_code spare_status;
168
169
67
    status = (waveform_picker_regs->status & BITS_WFP_STATUS_F2) >> SHIFT_WFP_STATUS_F2;   // [0011 0000] get the status bits for f2
170
171
67
    switch(status)
172
    {
173
    case BIT_WFP_BUFFER_0:
174
35
        ring_node_to_send_cwf_f2                = current_ring_node_f2->previous;
175
35
        ring_node_to_send_cwf_f2->sid           = SID_BURST_CWF_F2;
176
35
        ring_node_to_send_cwf_f2->coarseTime    = waveform_picker_regs->f2_0_coarse_time;
177
35
        ring_node_to_send_cwf_f2->fineTime      = waveform_picker_regs->f2_0_fine_time;
178
35
        current_ring_node_f2                    = current_ring_node_f2->next;
179
35
        waveform_picker_regs->addr_data_f2_0    = current_ring_node_f2->buffer_address;
180
35
        if (rtems_event_send( Task_id[TASKID_CWF2], RTEMS_EVENT_MODE_BURST ) != RTEMS_SUCCESSFUL) {
181
            spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 );
182
        }
183
35
        waveform_picker_regs->status            = waveform_picker_regs->status & RST_WFP_F2_0; // [0100 0100 0001 0000]
184
35
        break;
185
    case BIT_WFP_BUFFER_1:
186
29
        ring_node_to_send_cwf_f2                = current_ring_node_f2->previous;
187
29
        ring_node_to_send_cwf_f2->sid           = SID_BURST_CWF_F2;
188
29
        ring_node_to_send_cwf_f2->coarseTime    = waveform_picker_regs->f2_1_coarse_time;
189
29
        ring_node_to_send_cwf_f2->fineTime      = waveform_picker_regs->f2_1_fine_time;
190
29
        current_ring_node_f2                    = current_ring_node_f2->next;
191
29
        waveform_picker_regs->addr_data_f2_1    = current_ring_node_f2->buffer_address;
192
29
        if (rtems_event_send( Task_id[TASKID_CWF2], RTEMS_EVENT_MODE_BURST ) != RTEMS_SUCCESSFUL) {
193
            spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 );
194
        }
195
29
        waveform_picker_regs->status            = waveform_picker_regs->status & RST_WFP_F2_1; // [0100 0100 0010 0000]
196
        break;
197
    default:
198
        break;
199
    }
200
67
}
201
202
4144
inline void waveform_isr_normal_sbm1_sbm2( void )
203
{
204
    rtems_status_code status;
205
206
    //***
207
    // F0
208
4144
    if ( (waveform_picker_regs->status & BITS_WFP_STATUS_F0) != INIT_CHAR )  // [0000 0011] check the f0 full bits
209
    {
210
24
        swf0_ready_flag_f1 = true;
211
24
        swf0_ready_flag_f2 = true;
212
24
        ring_node_to_send_swf_f0    = current_ring_node_f0->previous;
213
24
        current_ring_node_f0        = current_ring_node_f0->next;
214
24
        if ( (waveform_picker_regs->status & BIT_WFP_BUFFER_0) == BIT_WFP_BUFFER_0)
215
        {
216
217
13
            ring_node_to_send_swf_f0->coarseTime    = waveform_picker_regs->f0_0_coarse_time;
218
13
            ring_node_to_send_swf_f0->fineTime      = waveform_picker_regs->f0_0_fine_time;
219
13
            waveform_picker_regs->addr_data_f0_0    = current_ring_node_f0->buffer_address;
220
13
            waveform_picker_regs->status            = waveform_picker_regs->status & RST_WFP_F0_0; // [0001 0001 0000 0001]
221
        }
222
11
        else if ( (waveform_picker_regs->status & BIT_WFP_BUFFER_1) == BIT_WFP_BUFFER_1)
223
        {
224
11
            ring_node_to_send_swf_f0->coarseTime    = waveform_picker_regs->f0_1_coarse_time;
225
11
            ring_node_to_send_swf_f0->fineTime      = waveform_picker_regs->f0_1_fine_time;
226
11
            waveform_picker_regs->addr_data_f0_1    = current_ring_node_f0->buffer_address;
227
11
            waveform_picker_regs->status            = waveform_picker_regs->status & RST_WFP_F0_1; // [0001 0001 0000 0010]
228
        }
229
        // send an event to the WFRM task for resynchro activities
230
24
        status = rtems_event_send( Task_id[TASKID_WFRM], RTEMS_EVENT_SWF_RESYNCH );
231
24
        status = rtems_event_send( Task_id[TASKID_CALI], RTEMS_EVENT_CAL_SWEEP_WAKE );
232
    }
233
234
    //***
235
    // F1
236
4144
    if ( (waveform_picker_regs->status & BITS_WFP_STATUS_F1) != INIT_CHAR ) {  // [0000 1100] check the f1 full bits
237
        // (1) change the receiving buffer for the waveform picker
238
3896
        ring_node_to_send_cwf_f1    = current_ring_node_f1->previous;
239
3896
        current_ring_node_f1        = current_ring_node_f1->next;
240
3896
        if ( (waveform_picker_regs->status & BIT_WFP_BUF_F1_0) == BIT_WFP_BUF_F1_0)
241
        {
242
1970
            ring_node_to_send_cwf_f1->coarseTime    = waveform_picker_regs->f1_0_coarse_time;
243
1970
            ring_node_to_send_cwf_f1->fineTime      = waveform_picker_regs->f1_0_fine_time;
244
1970
            waveform_picker_regs->addr_data_f1_0    = current_ring_node_f1->buffer_address;
245
1970
            waveform_picker_regs->status            = waveform_picker_regs->status & RST_WFP_F1_0; // [0010 0010 0000 0100] f1 bits = 0
246
        }
247
1926
        else if ( (waveform_picker_regs->status & BIT_WFP_BUF_F1_1) == BIT_WFP_BUF_F1_1)
248
        {
249
1926
            ring_node_to_send_cwf_f1->coarseTime    = waveform_picker_regs->f1_1_coarse_time;
250
1926
            ring_node_to_send_cwf_f1->fineTime      = waveform_picker_regs->f1_1_fine_time;
251
1926
            waveform_picker_regs->addr_data_f1_1    = current_ring_node_f1->buffer_address;
252
1926
            waveform_picker_regs->status            = waveform_picker_regs->status & RST_WFP_F1_1; // [0010 0010 0000 1000] f1 bits = 0
253
        }
254
        // (2) send an event for the the CWF1 task for transmission (and snapshot extraction if needed)
255
3896
        status = rtems_event_send( Task_id[TASKID_CWF1], RTEMS_EVENT_MODE_NORM_S1_S2 );
256
    }
257
258
    //***
259
    // F2
260
4144
    if ( (waveform_picker_regs->status & BITS_WFP_STATUS_F2) != INIT_CHAR ) {  // [0011 0000] check the f2 full bit
261
        // (1) change the receiving buffer for the waveform picker
262
215
        ring_node_to_send_cwf_f2      = current_ring_node_f2->previous;
263
215
        ring_node_to_send_cwf_f2->sid = SID_SBM2_CWF_F2;
264
215
        current_ring_node_f2          = current_ring_node_f2->next;
265
215
        if ( (waveform_picker_regs->status & BIT_WFP_BUF_F2_0) == BIT_WFP_BUF_F2_0)
266
        {
267
115
            ring_node_to_send_cwf_f2->coarseTime    = waveform_picker_regs->f2_0_coarse_time;
268
115
            ring_node_to_send_cwf_f2->fineTime      = waveform_picker_regs->f2_0_fine_time;
269
115
            waveform_picker_regs->addr_data_f2_0    = current_ring_node_f2->buffer_address;
270
115
            waveform_picker_regs->status            = waveform_picker_regs->status & RST_WFP_F2_0; // [0100 0100 0001 0000]
271
        }
272
100
        else if ( (waveform_picker_regs->status & BIT_WFP_BUF_F2_1) == BIT_WFP_BUF_F2_1)
273
        {
274
100
            ring_node_to_send_cwf_f2->coarseTime    = waveform_picker_regs->f2_1_coarse_time;
275
100
            ring_node_to_send_cwf_f2->fineTime      = waveform_picker_regs->f2_1_fine_time;
276
100
            waveform_picker_regs->addr_data_f2_1    = current_ring_node_f2->buffer_address;
277
100
            waveform_picker_regs->status            = waveform_picker_regs->status & RST_WFP_F2_1; // [0100 0100 0010 0000]
278
        }
279
        // (2) send an event for the waveforms transmission
280
215
        status = rtems_event_send( Task_id[TASKID_CWF2], RTEMS_EVENT_MODE_NORM_S1_S2 );
281
    }
282
4144
}
283
284
4211
rtems_isr waveforms_isr( rtems_vector_number vector )
285
{
286
    /** This is the interrupt sub routine called by the waveform picker core.
287
     *
288
     * This ISR launch different actions depending mainly on two pieces of information:
289
     * 1. the values read in the registers of the waveform picker.
290
     * 2. the current LFR mode.
291
     *
292
     */
293
294
    // STATUS
295
    // new error        error buffer full
296
    // 15 14 13 12      11 10 9  8
297
    // f3 f2 f1 f0      f3 f2 f1 f0
298
    //
299
    // ready buffer
300
    // 7    6    5    4    3    2    1    0
301
    // f3_1 f3_0 f2_1 f2_0 f1_1 f1_0 f0_1 f0_0
302
303
    rtems_status_code spare_status;
304
305
4211
    waveforms_isr_f3();
306
307
    //*************************************************
308
    // copy the status bits in the housekeeping packets
309
4211
    housekeeping_packet.hk_lfr_vhdl_iir_cal =
310
4211
            (unsigned char) ((waveform_picker_regs->status & BYTE0_MASK) >> SHIFT_1_BYTE);
311
312
4211
    if ( (waveform_picker_regs->status & BYTE0_MASK) != INIT_CHAR)    // [1111 1111 0000 0000] check the error bits
313
    {
314
        spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_10 );
315
    }
316
317
4211
    switch(lfrCurrentMode)
318
    {
319
    //********
320
    // STANDBY
321
    case LFR_MODE_STANDBY:
322
        break;
323
        //**************************
324
        // LFR NORMAL, SBM1 and SBM2
325
    case LFR_MODE_NORMAL:
326
    case LFR_MODE_SBM1:
327
    case LFR_MODE_SBM2:
328
4144
        waveform_isr_normal_sbm1_sbm2();
329
4144
        break;
330
        //******
331
        // BURST
332
    case LFR_MODE_BURST:
333
67
        waveforms_isr_burst();
334
        break;
335
        //********
336
        // DEFAULT
337
    default:
338
        break;
339
    }
340
4211
}
341
342
//************
343
// RTEMS TASKS
344
345
137
rtems_task wfrm_task(rtems_task_argument argument) //used with the waveform picker VHDL IP
346
{
347
    /** This RTEMS task is dedicated to the transmission of snapshots of the NORMAL mode.
348
     *
349
     * @param unused is the starting argument of the RTEMS task
350
     *
351
     * The following data packets are sent by this task:
352
     * - TM_LFR_SCIENCE_NORMAL_SWF_F0
353
     * - TM_LFR_SCIENCE_NORMAL_SWF_F1
354
     * - TM_LFR_SCIENCE_NORMAL_SWF_F2
355
     *
356
     */
357
358
    rtems_event_set event_out;
359
    rtems_id queue_id;
360
    rtems_status_code status;
361
    ring_node *ring_node_swf1_extracted_ptr;
362
    ring_node *ring_node_swf2_extracted_ptr;
363
364
137
    event_out = EVENT_SETS_NONE_PENDING;
365
137
    queue_id = RTEMS_ID_NONE;
366
367
137
    ring_node_swf1_extracted_ptr = (ring_node *) &ring_node_swf1_extracted;
368
137
    ring_node_swf2_extracted_ptr = (ring_node *) &ring_node_swf2_extracted;
369
370
137
    status =  get_message_queue_id_send( &queue_id );
371
    if (status != RTEMS_SUCCESSFUL)
372
    {
373
        PRINTF1("in WFRM *** ERR get_message_queue_id_send %d\n", status);
374
    }
375
376
    BOOT_PRINTF("in WFRM ***\n");
377
378
    while(1){
379
        // wait for an RTEMS_EVENT
380
184
        rtems_event_receive(RTEMS_EVENT_MODE_NORMAL | RTEMS_EVENT_SWF_RESYNCH,
381
                            RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
382
383
47
        if (event_out == RTEMS_EVENT_MODE_NORMAL)
384
        {
385
            DEBUG_PRINTF("WFRM received RTEMS_EVENT_MODE_SBM2\n");
386
23
            ring_node_to_send_swf_f0->sid           = SID_NORM_SWF_F0;
387
23
            ring_node_swf1_extracted_ptr->sid       = SID_NORM_SWF_F1;
388
23
            ring_node_swf2_extracted_ptr->sid       = SID_NORM_SWF_F2;
389
23
            status =  rtems_message_queue_send( queue_id, &ring_node_to_send_swf_f0,     sizeof( ring_node* ) );
390
23
            status =  rtems_message_queue_send( queue_id, &ring_node_swf1_extracted_ptr, sizeof( ring_node* ) );
391
23
            status =  rtems_message_queue_send( queue_id, &ring_node_swf2_extracted_ptr, sizeof( ring_node* ) );
392
        }
393
47
        if (event_out == RTEMS_EVENT_SWF_RESYNCH)
394
        {
395
24
            snapshot_resynchronization( (unsigned char *)  &ring_node_to_send_swf_f0->coarseTime );
396
        }
397
    }
398
}
399
400
137
rtems_task cwf3_task(rtems_task_argument argument) //used with the waveform picker VHDL IP
401
{
402
    /** This RTEMS task is dedicated to the transmission of continuous waveforms at f3.
403
     *
404
     * @param unused is the starting argument of the RTEMS task
405
     *
406
     * The following data packet is sent by this task:
407
     * - TM_LFR_SCIENCE_NORMAL_CWF_F3
408
     *
409
     */
410
411
    rtems_event_set event_out;
412
    rtems_id queue_id;
413
    rtems_status_code status;
414
    ring_node ring_node_cwf3_light;
415
    ring_node *ring_node_to_send_cwf;
416
417
137
    event_out = EVENT_SETS_NONE_PENDING;
418
137
    queue_id = RTEMS_ID_NONE;
419
420
137
    status =  get_message_queue_id_send( &queue_id );
421
    if (status != RTEMS_SUCCESSFUL)
422
    {
423
        PRINTF1("in CWF3 *** ERR get_message_queue_id_send %d\n", status)
424
    }
425
426
137
    ring_node_to_send_cwf_f3->sid = SID_NORM_CWF_LONG_F3;
427
428
    // init the ring_node_cwf3_light structure
429
137
    ring_node_cwf3_light.buffer_address = (int) wf_cont_f3_light;
430
137
    ring_node_cwf3_light.coarseTime = INIT_CHAR;
431
137
    ring_node_cwf3_light.fineTime = INIT_CHAR;
432
137
    ring_node_cwf3_light.next = NULL;
433
137
    ring_node_cwf3_light.previous = NULL;
434
137
    ring_node_cwf3_light.sid = SID_NORM_CWF_F3;
435
137
    ring_node_cwf3_light.status = INIT_CHAR;
436
437
    BOOT_PRINTF("in CWF3 ***\n");
438
439
    while(1){
440
        // wait for an RTEMS_EVENT
441
149
        rtems_event_receive( RTEMS_EVENT_0,
442
                             RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
443

15
        if ( (lfrCurrentMode == LFR_MODE_NORMAL)
444
15
             || (lfrCurrentMode == LFR_MODE_SBM1) || (lfrCurrentMode==LFR_MODE_SBM2) )
445
        {
446
9
            ring_node_to_send_cwf = getRingNodeToSendCWF( CHANNELF3 );
447
9
            if ( (parameter_dump_packet.sy_lfr_n_cwf_long_f3 & BIT_CWF_LONG_F3) == BIT_CWF_LONG_F3)
448
            {
449
                PRINTF("send CWF_LONG_F3\n");
450
2
                ring_node_to_send_cwf_f3->sid = SID_NORM_CWF_LONG_F3;
451
2
                status =  rtems_message_queue_send( queue_id, &ring_node_to_send_cwf, sizeof( ring_node* ) );
452
            }
453
            else
454
            {
455
                PRINTF("send CWF_F3 (light)\n");
456
7
                send_waveform_CWF3_light( ring_node_to_send_cwf, &ring_node_cwf3_light, queue_id );
457
            }
458
459
        }
460
        else
461
        {
462
            PRINTF1("in CWF3 *** lfrCurrentMode is %d, no data will be sent\n", lfrCurrentMode)
463
        }
464
    }
465
}
466
467
137
rtems_task cwf2_task(rtems_task_argument argument)  // ONLY USED IN BURST AND SBM2
468
{
469
    /** This RTEMS task is dedicated to the transmission of continuous waveforms at f2.
470
     *
471
     * @param unused is the starting argument of the RTEMS task
472
     *
473
     * The following data packet is sent by this function:
474
     * - TM_LFR_SCIENCE_BURST_CWF_F2
475
     * - TM_LFR_SCIENCE_SBM2_CWF_F2
476
     *
477
     */
478
479
    rtems_event_set event_out;
480
    rtems_id queue_id;
481
    rtems_status_code status;
482
    ring_node *ring_node_to_send;
483
    unsigned long long int acquisitionTimeF0_asLong;
484
485
137
    event_out = EVENT_SETS_NONE_PENDING;
486
137
    queue_id = RTEMS_ID_NONE;
487
488
137
    acquisitionTimeF0_asLong = INIT_CHAR;
489
490
137
    status =  get_message_queue_id_send( &queue_id );
491
    if (status != RTEMS_SUCCESSFUL)
492
    {
493
        PRINTF1("in CWF2 *** ERR get_message_queue_id_send %d\n", status)
494
    }
495
496
    BOOT_PRINTF("in CWF2 ***\n");
497
498
    while(1){
499
        // wait for an RTEMS_EVENT// send the snapshot when built
500
416
        status = rtems_event_send( Task_id[TASKID_WFRM], RTEMS_EVENT_MODE_SBM2 );
501
416
        rtems_event_receive( RTEMS_EVENT_MODE_NORM_S1_S2 | RTEMS_EVENT_MODE_BURST,
502
                             RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
503
279
        ring_node_to_send = getRingNodeToSendCWF( CHANNELF2 );
504
279
        if (event_out == RTEMS_EVENT_MODE_BURST)
505
        {   // data are sent whatever the transition time
506
64
            status =  rtems_message_queue_send( queue_id, &ring_node_to_send, sizeof( ring_node* ) );
507
        }
508
215
        else if (event_out == RTEMS_EVENT_MODE_NORM_S1_S2)
509
        {
510
215
            if ( lfrCurrentMode == LFR_MODE_SBM2 )
511
            {
512
                // data are sent depending on the transition time
513
18
                if ( time_management_regs->coarse_time >= lastValidEnterModeTime)
514
                {
515
18
                    status =  rtems_message_queue_send( queue_id, &ring_node_to_send, sizeof( ring_node* ) );
516
                }
517
            }
518
            // launch snapshot extraction if needed
519
215
            if (extractSWF2 == true)
520
            {
521
23
                ring_node_to_send_swf_f2 = ring_node_to_send_cwf_f2;
522
                // extract the snapshot
523
23
                build_snapshot_from_ring( ring_node_to_send_swf_f2, CHANNELF2, acquisitionTimeF0_asLong,
524
                                          &ring_node_swf2_extracted, swf2_extracted );
525
23
                extractSWF2 = false;
526
23
                swf2_ready = true;  // once the snapshot at f2 is ready the CWF1 task will send an event to WFRM
527
            }
528
215
            if (swf0_ready_flag_f2 == true)
529
            {
530
24
                extractSWF2 = true;
531
                // record the acquition time of the f0 snapshot to use to build the snapshot at f2
532
24
                acquisitionTimeF0_asLong = get_acquisition_time( (unsigned char *) &ring_node_to_send_swf_f0->coarseTime );
533
24
                swf0_ready_flag_f2 = false;
534
            }
535
        }
536
    }
537
}
538
539
137
rtems_task cwf1_task(rtems_task_argument argument)  // ONLY USED IN SBM1
540
{
541
    /** This RTEMS task is dedicated to the transmission of continuous waveforms at f1.
542
     *
543
     * @param unused is the starting argument of the RTEMS task
544
     *
545
     * The following data packet is sent by this function:
546
     * - TM_LFR_SCIENCE_SBM1_CWF_F1
547
     *
548
     */
549
550
    rtems_event_set event_out;
551
    rtems_id queue_id;
552
    rtems_status_code status;
553
554
    ring_node *ring_node_to_send_cwf;
555
556
137
    event_out = EVENT_SETS_NONE_PENDING;
557
137
    queue_id = RTEMS_ID_NONE;
558
559
137
    status =  get_message_queue_id_send( &queue_id );
560
    if (status != RTEMS_SUCCESSFUL)
561
    {
562
        PRINTF1("in CWF1 *** ERR get_message_queue_id_send %d\n", status)
563
    }
564
565
    BOOT_PRINTF("in CWF1 ***\n");
566
567
    while(1){
568
        // wait for an RTEMS_EVENT
569
4033
        rtems_event_receive( RTEMS_EVENT_MODE_NORM_S1_S2,
570
                             RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
571
3896
        ring_node_to_send_cwf = getRingNodeToSendCWF( 1 );
572
3896
        ring_node_to_send_cwf_f1->sid = SID_SBM1_CWF_F1;
573
3896
        if (lfrCurrentMode == LFR_MODE_SBM1)
574
        {
575
            // data are sent depending on the transition time
576
1870
            if ( time_management_regs->coarse_time >= lastValidEnterModeTime )
577
            {
578
1864
                status =  rtems_message_queue_send( queue_id, &ring_node_to_send_cwf, sizeof( ring_node* ) );
579
            }
580
        }
581
        // launch snapshot extraction if needed
582
3896
        if (extractSWF1 == true)
583
        {
584
24
            ring_node_to_send_swf_f1 = ring_node_to_send_cwf;
585
            // launch the snapshot extraction
586
24
            status = rtems_event_send( Task_id[TASKID_SWBD], RTEMS_EVENT_MODE_NORM_S1_S2 );
587
24
            extractSWF1 = false;
588
        }
589
3896
        if (swf0_ready_flag_f1 == true)
590
        {
591
24
            extractSWF1 = true;
592
24
            swf0_ready_flag_f1 = false;   // this step shall be executed only one time
593
        }
594

3896
        if ((swf1_ready == true) && (swf2_ready == true))   // swf_f1 is ready after the extraction
595
        {
596
23
            status = rtems_event_send( Task_id[TASKID_WFRM], RTEMS_EVENT_MODE_NORMAL );
597
23
            swf1_ready = false;
598
23
            swf2_ready = false;
599
        }
600
    }
601
}
602
603
3
rtems_task swbd_task(rtems_task_argument argument)
604
{
605
    /** This RTEMS task is dedicated to the building of snapshots from different continuous waveforms buffers.
606
     *
607
     * @param unused is the starting argument of the RTEMS task
608
     *
609
     */
610
611
    rtems_event_set event_out;
612
    unsigned long long int acquisitionTimeF0_asLong;
613
614
3
    event_out = EVENT_SETS_NONE_PENDING;
615
3
    acquisitionTimeF0_asLong = INIT_CHAR;
616
617
    BOOT_PRINTF("in SWBD ***\n")
618
619
            while(1){
620
        // wait for an RTEMS_EVENT
621
27
        rtems_event_receive( RTEMS_EVENT_MODE_NORM_S1_S2,
622
                             RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
623
24
        if (event_out == RTEMS_EVENT_MODE_NORM_S1_S2)
624
        {
625
24
            acquisitionTimeF0_asLong = get_acquisition_time( (unsigned char *) &ring_node_to_send_swf_f0->coarseTime );
626
24
            build_snapshot_from_ring( ring_node_to_send_swf_f1, CHANNELF1, acquisitionTimeF0_asLong,
627
                                      &ring_node_swf1_extracted, swf1_extracted );
628
24
            swf1_ready = true;    // the snapshot has been extracted and is ready to be sent
629
        }
630
        else
631
        {
632
            PRINTF1("in SWBD *** unexpected rtems event received %x\n", (int) event_out)
633
        }
634
    }
635
}
636
637
//******************
638
// general functions
639
640
3
void WFP_init_rings( void )
641
{
642
    // F0 RING
643
3
    init_ring( waveform_ring_f0, NB_RING_NODES_F0, wf_buffer_f0, WFRM_BUFFER );
644
    // F1 RING
645
3
    init_ring( waveform_ring_f1, NB_RING_NODES_F1, wf_buffer_f1, WFRM_BUFFER );
646
    // F2 RING
647
3
    init_ring( waveform_ring_f2, NB_RING_NODES_F2, wf_buffer_f2, WFRM_BUFFER );
648
    // F3 RING
649
3
    init_ring( waveform_ring_f3, NB_RING_NODES_F3, wf_buffer_f3, WFRM_BUFFER );
650
651
3
    ring_node_swf1_extracted.buffer_address = (int) swf1_extracted;
652
3
    ring_node_swf2_extracted.buffer_address = (int) swf2_extracted;
653
654
    DEBUG_PRINTF1("waveform_ring_f0 @%x\n", (unsigned int) waveform_ring_f0)
655
            DEBUG_PRINTF1("waveform_ring_f1 @%x\n", (unsigned int) waveform_ring_f1)
656
            DEBUG_PRINTF1("waveform_ring_f2 @%x\n", (unsigned int) waveform_ring_f2)
657
            DEBUG_PRINTF1("waveform_ring_f3 @%x\n", (unsigned int) waveform_ring_f3)
658
            DEBUG_PRINTF1("wf_buffer_f0 @%x\n", (unsigned int) wf_buffer_f0)
659
            DEBUG_PRINTF1("wf_buffer_f1 @%x\n", (unsigned int) wf_buffer_f1)
660
            DEBUG_PRINTF1("wf_buffer_f2 @%x\n", (unsigned int) wf_buffer_f2)
661
            DEBUG_PRINTF1("wf_buffer_f3 @%x\n", (unsigned int) wf_buffer_f3)
662
663
3
}
664
665
140
void WFP_reset_current_ring_nodes( void )
666
{
667
140
    current_ring_node_f0      = waveform_ring_f0[0].next;
668
140
    current_ring_node_f1      = waveform_ring_f1[0].next;
669
140
    current_ring_node_f2      = waveform_ring_f2[0].next;
670
140
    current_ring_node_f3      = waveform_ring_f3[0].next;
671
672
140
    ring_node_to_send_swf_f0  = waveform_ring_f0;
673
140
    ring_node_to_send_swf_f1  = waveform_ring_f1;
674
140
    ring_node_to_send_swf_f2  = waveform_ring_f2;
675
676
140
    ring_node_to_send_cwf_f1  = waveform_ring_f1;
677
140
    ring_node_to_send_cwf_f2  = waveform_ring_f2;
678
140
    ring_node_to_send_cwf_f3  = waveform_ring_f3;
679
140
}
680
681
7
int send_waveform_CWF3_light( ring_node *ring_node_to_send, ring_node *ring_node_cwf3_light, rtems_id queue_id )
682
{
683
    /** This function sends CWF_F3 CCSDS packets without the b1, b2 and b3 data.
684
     *
685
     * @param waveform points to the buffer containing the data that will be send.
686
     * @param headerCWF points to a table of headers that have been prepared for the data transmission.
687
     * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
688
     * contain information to setup the transmission of the data packets.
689
     *
690
     * By default, CWF_F3 packet are send without the b1, b2 and b3 data. This function rebuilds a data buffer
691
     * from the incoming data and sends it in 7 packets, 6 containing 340 blocks and 1 one containing 8 blocks.
692
     *
693
     */
694
695
    unsigned int i;
696
    unsigned int j;
697
    int ret;
698
    rtems_status_code status;
699
700
    char *sample;
701
    int *dataPtr;
702
703
7
    ret = LFR_DEFAULT;
704
705
7
    dataPtr     = (int*) ring_node_to_send->buffer_address;
706
707
7
    ring_node_cwf3_light->coarseTime = ring_node_to_send->coarseTime;
708
7
    ring_node_cwf3_light->fineTime = ring_node_to_send->fineTime;
709
710
    //**********************
711
    // BUILD CWF3_light DATA
712
18823
    for ( i=0; i< NB_SAMPLES_PER_SNAPSHOT; i++)
713
    {
714
18816
        sample = (char*) &dataPtr[ (i * NB_WORDS_SWF_BLK) ];
715
131712
        for (j=0; j < CWF_BLK_SIZE; j++)
716
        {
717
112896
            wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) + j] = sample[ j ];
718
        }
719
    }
720
721
    // SEND PACKET
722
7
    status =  rtems_message_queue_send( queue_id, &ring_node_cwf3_light, sizeof( ring_node* ) );
723
7
    if (status != RTEMS_SUCCESSFUL) {
724
        ret = LFR_DEFAULT;
725
    }
726
727
7
    return ret;
728
}
729
730
16070
void compute_acquisition_time( unsigned int coarseTime, unsigned int fineTime,
731
                               unsigned int sid, unsigned char pa_lfr_pkt_nr, unsigned char * acquisitionTime )
732
{
733
    unsigned long long int acquisitionTimeAsLong;
734
    unsigned char localAcquisitionTime[BYTES_PER_TIME];
735
    double deltaT;
736
737
16070
    deltaT = INIT_FLOAT;
738
739
16070
    localAcquisitionTime[BYTE_0] = (unsigned char) ( coarseTime >> SHIFT_3_BYTES );
740
16070
    localAcquisitionTime[BYTE_1] = (unsigned char) ( coarseTime >> SHIFT_2_BYTES );
741
16070
    localAcquisitionTime[BYTE_2] = (unsigned char) ( coarseTime >> SHIFT_1_BYTE  );
742
16070
    localAcquisitionTime[BYTE_3] = (unsigned char) ( coarseTime                  );
743
16070
    localAcquisitionTime[BYTE_4] = (unsigned char) ( fineTime   >> SHIFT_1_BYTE  );
744
16070
    localAcquisitionTime[BYTE_5] = (unsigned char) ( fineTime                    );
745
746
32140
    acquisitionTimeAsLong = ( (unsigned long long int) localAcquisitionTime[BYTE_0] << SHIFT_5_BYTES )
747
16070
            + ( (unsigned long long int) localAcquisitionTime[BYTE_1] << SHIFT_4_BYTES )
748
16070
            + ( (unsigned long long int) localAcquisitionTime[BYTE_2] << SHIFT_3_BYTES )
749
16070
            + ( (unsigned long long int) localAcquisitionTime[BYTE_3] << SHIFT_2_BYTES )
750
16070
            + ( (unsigned long long int) localAcquisitionTime[BYTE_4] << SHIFT_1_BYTE  )
751
16070
            + ( (unsigned long long int) localAcquisitionTime[BYTE_5]       );
752
753


16070
    switch( sid )
754
    {
755
    case SID_NORM_SWF_F0:
756
161
        deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_304 * T0_IN_FINETIME ;
757
161
        break;
758
759
    case SID_NORM_SWF_F1:
760
161
        deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_304 * T1_IN_FINETIME ;
761
161
        break;
762
763
    case SID_NORM_SWF_F2:
764
161
        deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_304 * T2_IN_FINETIME ;
765
161
        break;
766
767
    case SID_SBM1_CWF_F1:
768
14887
        deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF * T1_IN_FINETIME ;
769
14887
        break;
770
771
    case SID_SBM2_CWF_F2:
772
144
        deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF * T2_IN_FINETIME ;
773
144
        break;
774
775
    case SID_BURST_CWF_F2:
776
512
        deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF * T2_IN_FINETIME ;
777
512
        break;
778
779
    case SID_NORM_CWF_F3:
780
28
        deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF_SHORT_F3 * T3_IN_FINETIME ;
781
28
        break;
782
783
    case SID_NORM_CWF_LONG_F3:
784
16
        deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF * T3_IN_FINETIME ;
785
16
        break;
786
787
    default:
788
        PRINTF1("in compute_acquisition_time *** ERR unexpected sid %d\n", sid)
789
                deltaT = 0.;
790
        break;
791
    }
792
793
16070
    acquisitionTimeAsLong = acquisitionTimeAsLong + (unsigned long long int) deltaT;
794
    //
795
16070
    acquisitionTime[BYTE_0] = (unsigned char) (acquisitionTimeAsLong >> SHIFT_5_BYTES);
796
16070
    acquisitionTime[BYTE_1] = (unsigned char) (acquisitionTimeAsLong >> SHIFT_4_BYTES);
797
16070
    acquisitionTime[BYTE_2] = (unsigned char) (acquisitionTimeAsLong >> SHIFT_3_BYTES);
798
16070
    acquisitionTime[BYTE_3] = (unsigned char) (acquisitionTimeAsLong >> SHIFT_2_BYTES);
799
16070
    acquisitionTime[BYTE_4] = (unsigned char) (acquisitionTimeAsLong >> SHIFT_1_BYTE );
800
16070
    acquisitionTime[BYTE_5] = (unsigned char) (acquisitionTimeAsLong                 );
801
802
16070
}
803
804
47
void build_snapshot_from_ring( ring_node *ring_node_to_send,
805
                               unsigned char frequencyChannel,
806
                               unsigned long long int acquisitionTimeF0_asLong,
807
                               ring_node *ring_node_swf_extracted,
808
                               int *swf_extracted)
809
{
810
    unsigned int i;
811
    unsigned int node;
812
    unsigned long long int centerTime_asLong;
813
    unsigned long long int acquisitionTime_asLong;
814
    unsigned long long int bufferAcquisitionTime_asLong;
815
    unsigned char *ptr1;
816
    unsigned char *ptr2;
817
    unsigned char *timeCharPtr;
818
    unsigned char nb_ring_nodes;
819
    unsigned long long int frequency_asLong;
820
    unsigned long long int nbTicksPerSample_asLong;
821
    unsigned long long int nbSamplesPart1_asLong;
822
    unsigned long long int sampleOffset_asLong;
823
824
    unsigned int deltaT_F0;
825
    unsigned int deltaT_F1;
826
    unsigned long long int deltaT_F2;
827
828
47
    deltaT_F0 = DELTAT_F0;
829
47
    deltaT_F1 = DELTAT_F1;
830
47
    deltaT_F2 = DELTAT_F2;
831
47
    sampleOffset_asLong = INIT_CHAR;
832
833
    // (1) get the f0 acquisition time => the value is passed in argument
834
835
    // (2) compute the central reference time
836
47
    centerTime_asLong = acquisitionTimeF0_asLong + deltaT_F0;
837
47
    acquisitionTime_asLong = centerTime_asLong;         //set to default value (Don_Initialisation_P2)
838
47
    bufferAcquisitionTime_asLong = centerTime_asLong;   //set to default value (Don_Initialisation_P2)
839
47
    nbTicksPerSample_asLong = TICKS_PER_T2;             //set to default value (Don_Initialisation_P2)
840
841
    // (3) compute the acquisition time of the current snapshot
842
47
    switch(frequencyChannel)
843
    {
844
    case CHANNELF1: // 1 is for F1 = 4096 Hz
845
24
        acquisitionTime_asLong = centerTime_asLong - deltaT_F1;
846
24
        nb_ring_nodes = NB_RING_NODES_F1;
847
24
        frequency_asLong = FREQ_F1;
848
24
        nbTicksPerSample_asLong = TICKS_PER_T1;  // 65536 / 4096;
849
24
        break;
850
    case CHANNELF2: // 2 is for F2 = 256 Hz
851
23
        acquisitionTime_asLong = centerTime_asLong - deltaT_F2;
852
23
        nb_ring_nodes = NB_RING_NODES_F2;
853
23
        frequency_asLong = FREQ_F2;
854
23
        nbTicksPerSample_asLong = TICKS_PER_T2;  // 65536 / 256;
855
23
        break;
856
    default:
857
        acquisitionTime_asLong = centerTime_asLong;
858
        nb_ring_nodes = 0;
859
        frequency_asLong = FREQ_F2;
860
        nbTicksPerSample_asLong = TICKS_PER_T2;
861
        break;
862
    }
863
864
    //*****************************************************************************
865
    // (4) search the ring_node with the acquisition time <= acquisitionTime_asLong
866
47
    node = 0;
867
210
    while ( node < nb_ring_nodes)
868
    {
869
116
        bufferAcquisitionTime_asLong = get_acquisition_time( (unsigned char *) &ring_node_to_send->coarseTime );
870
116
        if (bufferAcquisitionTime_asLong <= acquisitionTime_asLong)
871
        {
872
47
            node = nb_ring_nodes;
873
        }
874
        else
875
        {
876
69
            node = node + 1;
877
69
            ring_node_to_send = ring_node_to_send->previous;
878
        }
879
    }
880
881
    // (5) compute the number of samples to take in the current buffer
882
47
    sampleOffset_asLong = ((acquisitionTime_asLong - bufferAcquisitionTime_asLong) * frequency_asLong ) >> SHIFT_2_BYTES;
883
47
    nbSamplesPart1_asLong = NB_SAMPLES_PER_SNAPSHOT - sampleOffset_asLong;
884
885
    // (6) compute the final acquisition time
886
47
    acquisitionTime_asLong = bufferAcquisitionTime_asLong +
887
47
            (sampleOffset_asLong * nbTicksPerSample_asLong);
888
889
    // (7) copy the acquisition time at the beginning of the extrated snapshot
890
47
    ptr1 = (unsigned char*) &acquisitionTime_asLong;
891
    // fine time
892
47
    ptr2 = (unsigned char*) &ring_node_swf_extracted->fineTime;
893
47
    ptr2[BYTE_2] = ptr1[ BYTE_4 + OFFSET_2_BYTES ];
894
47
    ptr2[BYTE_3] = ptr1[ BYTE_5 + OFFSET_2_BYTES ];
895
    // coarse time
896
47
    ptr2 = (unsigned char*) &ring_node_swf_extracted->coarseTime;
897
47
    ptr2[BYTE_0] = ptr1[ BYTE_0 + OFFSET_2_BYTES ];
898
47
    ptr2[BYTE_1] = ptr1[ BYTE_1 + OFFSET_2_BYTES ];
899
47
    ptr2[BYTE_2] = ptr1[ BYTE_2 + OFFSET_2_BYTES ];
900
47
    ptr2[BYTE_3] = ptr1[ BYTE_3 + OFFSET_2_BYTES ];
901
902
    // re set the synchronization bit
903
47
    timeCharPtr = (unsigned char*) &ring_node_to_send->coarseTime;
904
47
    ptr2[0] = ptr2[0] | (timeCharPtr[0] & SYNC_BIT); // [1000 0000]
905
906
47
    if ( (nbSamplesPart1_asLong > NB_SAMPLES_PER_SNAPSHOT) | (nbSamplesPart1_asLong < 0) )
907
    {
908
        nbSamplesPart1_asLong = 0;
909
    }
910
    // copy the part 1 of the snapshot in the extracted buffer
911
192149
    for ( i = 0; i < (nbSamplesPart1_asLong * NB_WORDS_SWF_BLK); i++ )
912
    {
913
384204
        swf_extracted[i] =
914
192102
                ((int*) ring_node_to_send->buffer_address)[ i + (sampleOffset_asLong * NB_WORDS_SWF_BLK) ];
915
    }
916
    // copy the part 2 of the snapshot in the extracted buffer
917
47
    ring_node_to_send = ring_node_to_send->next;
918
186953
    for ( i = (nbSamplesPart1_asLong * NB_WORDS_SWF_BLK); i < (NB_SAMPLES_PER_SNAPSHOT * NB_WORDS_SWF_BLK); i++ )
919
    {
920
373812
        swf_extracted[i] =
921
186906
                ((int*) ring_node_to_send->buffer_address)[ (i-(nbSamplesPart1_asLong * NB_WORDS_SWF_BLK)) ];
922
    }
923
47
}
924
925
24
double computeCorrection( unsigned char *timePtr )
926
{
927
    unsigned long long int acquisitionTime;
928
    unsigned long long int centerTime;
929
    unsigned long long int previousTick;
930
    unsigned long long int nextTick;
931
    unsigned long long int deltaPreviousTick;
932
    unsigned long long int deltaNextTick;
933
    double deltaPrevious_ms;
934
    double deltaNext_ms;
935
    double correctionInF2;
936
937
24
    correctionInF2 = 0; //set to default value (Don_Initialisation_P2)
938
939
    // get acquisition time in fine time ticks
940
24
    acquisitionTime = get_acquisition_time( timePtr );
941
942
    // compute center time
943
24
    centerTime = acquisitionTime + DELTAT_F0;    // (2048. / 24576. / 2.) * 65536. = 2730.667;
944
24
    previousTick = centerTime - (centerTime & INT16_ALL_F);
945
24
    nextTick = previousTick + TICKS_PER_S;
946
947
24
    deltaPreviousTick   = centerTime - previousTick;
948
24
    deltaNextTick       = nextTick - centerTime;
949
950
24
    deltaPrevious_ms    = (((double) deltaPreviousTick) / TICKS_PER_S) * MS_PER_S;
951
24
    deltaNext_ms        = (((double) deltaNextTick)     / TICKS_PER_S) * MS_PER_S;
952
953
    PRINTF2("    delta previous = %.3f ms, delta next = %.2f ms\n", deltaPrevious_ms, deltaNext_ms);
954
955
    // which tick is the closest?
956
24
    if (deltaPreviousTick > deltaNextTick)
957
    {
958
        // the snapshot center is just before the second => increase delta_snapshot
959
13
        correctionInF2 = + (deltaNext_ms * FREQ_F2 / MS_PER_S );
960
    }
961
    else
962
    {
963
        // the snapshot center is just after the second => decrease delta_snapshot
964
11
        correctionInF2 = - (deltaPrevious_ms * FREQ_F2 / MS_PER_S );
965
    }
966
967
    PRINTF1("    correctionInF2 = %.2f\n", correctionInF2);
968
969
24
    return correctionInF2;
970
}
971
972
12
void applyCorrection( double correction )
973
{
974
    int correctionInt;
975
976
12
    correctionInt = 0;
977
978
12
    if (correction >= 0.)
979
    {
980

8
        if ( (ONE_TICK_CORR_INTERVAL_0_MIN < correction) && (correction < ONE_TICK_CORR_INTERVAL_0_MAX) )
981
        {
982
2
            correctionInt = ONE_TICK_CORR;
983
        }
984
        else
985
        {
986
4
            correctionInt = CORR_MULT * floor(correction);
987
        }
988
    }
989
    else
990
    {
991

7
        if ( (ONE_TICK_CORR_INTERVAL_1_MIN < correction) && (correction < ONE_TICK_CORR_INTERVAL_1_MAX) )
992
        {
993
1
            correctionInt = -ONE_TICK_CORR;
994
        }
995
        else
996
        {
997
5
            correctionInt =  CORR_MULT * ceil(correction);
998
        }
999
    }
1000
12
    waveform_picker_regs->delta_snapshot = waveform_picker_regs->delta_snapshot + correctionInt;
1001
12
}
1002
1003
24
void snapshot_resynchronization( unsigned char *timePtr )
1004
{
1005
    /** This function compute a correction to apply on delta_snapshot.
1006
     *
1007
     *
1008
     * @param timePtr is a pointer to the acquisition time of the snapshot being considered.
1009
     *
1010
     * @return void
1011
     *
1012
     */
1013
1014
    static double correction    = INIT_FLOAT;
1015
    static resynchro_state state = MEASURE;
1016
    static unsigned int nbSnapshots = 0;
1017
1018
    int correctionInt;
1019
1020
24
    correctionInt = 0;
1021
1022
24
    switch (state)
1023
    {
1024
1025
    case MEASURE:
1026
        // ********
1027
        PRINTF1("MEASURE === %d\n", nbSnapshots);
1028
12
        state = CORRECTION;
1029
12
        correction = computeCorrection( timePtr );
1030
        PRINTF1("MEASURE === correction = %.2f\n", correction );
1031
12
        applyCorrection( correction );
1032
        PRINTF1("MEASURE === delta_snapshot = %d\n", waveform_picker_regs->delta_snapshot);
1033
        //****
1034
12
        break;
1035
1036
    case CORRECTION:
1037
        //************
1038
        PRINTF1("CORRECTION === %d\n", nbSnapshots);
1039
12
        state = MEASURE;
1040
12
        computeCorrection( timePtr );
1041
12
        set_wfp_delta_snapshot();
1042
        PRINTF1("CORRECTION === delta_snapshot = %d\n", waveform_picker_regs->delta_snapshot);
1043
        //****
1044
        break;
1045
1046
    default:
1047
        break;
1048
1049
    }
1050
1051
24
    nbSnapshots++;
1052
24
}
1053
1054
//**************
1055
// wfp registers
1056
284
void reset_wfp_burst_enable( void )
1057
{
1058
    /** This function resets the waveform picker burst_enable register.
1059
     *
1060
     * The burst bits [f2 f1 f0] and the enable bits [f3 f2 f1 f0] are set to 0.
1061
     *
1062
     */
1063
1064
    // [1000 000] burst f2, f1, f0     enable f3, f2, f1, f0
1065
284
    waveform_picker_regs->run_burst_enable = waveform_picker_regs->run_burst_enable & RST_BITS_RUN_BURST_EN;
1066
284
}
1067
1068
284
void reset_wfp_status( void )
1069
{
1070
    /** This function resets the waveform picker status register.
1071
     *
1072
     * All status bits are set to 0 [new_err full_err full].
1073
     *
1074
     */
1075
1076
284
    waveform_picker_regs->status = INT16_ALL_F;
1077
284
}
1078
1079
140
void reset_wfp_buffer_addresses( void )
1080
{
1081
    // F0
1082
140
    waveform_picker_regs->addr_data_f0_0 = current_ring_node_f0->previous->buffer_address;  // 0x08
1083
140
    waveform_picker_regs->addr_data_f0_1 = current_ring_node_f0->buffer_address;            // 0x0c
1084
    // F1
1085
140
    waveform_picker_regs->addr_data_f1_0 = current_ring_node_f1->previous->buffer_address;  // 0x10
1086
140
    waveform_picker_regs->addr_data_f1_1 = current_ring_node_f1->buffer_address;            // 0x14
1087
    // F2
1088
140
    waveform_picker_regs->addr_data_f2_0 = current_ring_node_f2->previous->buffer_address;  // 0x18
1089
140
    waveform_picker_regs->addr_data_f2_1 = current_ring_node_f2->buffer_address;            // 0x1c
1090
    // F3
1091
140
    waveform_picker_regs->addr_data_f3_0 = current_ring_node_f3->previous->buffer_address;  // 0x20
1092
140
    waveform_picker_regs->addr_data_f3_1 = current_ring_node_f3->buffer_address;            // 0x24
1093
140
}
1094
1095
140
void reset_waveform_picker_regs( void )
1096
{
1097
    /** This function resets the waveform picker module registers.
1098
    *
1099
    * The registers affected by this function are located at the following offset addresses:
1100
    * - 0x00 data_shaping
1101
    * - 0x04 run_burst_enable
1102
    * - 0x08 addr_data_f0
1103
    * - 0x0C addr_data_f1
1104
    * - 0x10 addr_data_f2
1105
    * - 0x14 addr_data_f3
1106
    * - 0x18 status
1107
    * - 0x1C delta_snapshot
1108
    * - 0x20 delta_f0
1109
    * - 0x24 delta_f0_2
1110
    * - 0x28 delta_f1 (obsolet parameter)
1111
    * - 0x2c delta_f2
1112
    * - 0x30 nb_data_by_buffer
1113
    * - 0x34 nb_snapshot_param
1114
    * - 0x38 start_date
1115
    * - 0x3c nb_word_in_buffer
1116
    *
1117
    */
1118
1119
140
    set_wfp_data_shaping();                                     // 0x00 *** R1 R0 SP1 SP0 BW
1120
1121
140
    reset_wfp_burst_enable();                                   // 0x04 *** [run *** burst f2, f1, f0 *** enable f3, f2, f1, f0 ]
1122
1123
140
    reset_wfp_buffer_addresses();
1124
1125
140
    reset_wfp_status();                                         // 0x18
1126
1127
140
    set_wfp_delta_snapshot();   // 0x1c *** 300 s => 0x12bff
1128
1129
140
    set_wfp_delta_f0_f0_2();    // 0x20, 0x24
1130
1131
    //the parameter delta_f1 [0x28] is not used anymore
1132
1133
140
    set_wfp_delta_f2();         // 0x2c
1134
1135
    DEBUG_PRINTF1("delta_snapshot %x\n",    waveform_picker_regs->delta_snapshot);
1136
    DEBUG_PRINTF1("delta_f0 %x\n",          waveform_picker_regs->delta_f0);
1137
    DEBUG_PRINTF1("delta_f0_2 %x\n",        waveform_picker_regs->delta_f0_2);
1138
    DEBUG_PRINTF1("delta_f1 %x\n",          waveform_picker_regs->delta_f1);
1139
    DEBUG_PRINTF1("delta_f2 %x\n",          waveform_picker_regs->delta_f2);
1140
    // 2688 = 8 * 336
1141
140
    waveform_picker_regs->nb_data_by_buffer = DFLT_WFP_NB_DATA_BY_BUFFER;   // 0x30 *** 2688 - 1 => nb samples -1
1142
140
    waveform_picker_regs->snapshot_param    = DFLT_WFP_SNAPSHOT_PARAM;      // 0x34 *** 2688 => nb samples
1143
140
    waveform_picker_regs->start_date        = COARSE_TIME_MASK;
1144
    //
1145
    // coarse time and fine time registers are not initialized, they are volatile
1146
    //
1147
140
    waveform_picker_regs->buffer_length     = DFLT_WFP_BUFFER_LENGTH;   // buffer length in burst = 3 * 2688 / 16 = 504 = 0x1f8
1148
140
}
1149
1150
314
void set_wfp_data_shaping( void )
1151
{
1152
    /** This function sets the data_shaping register of the waveform picker module.
1153
     *
1154
     * The value is read from one field of the parameter_dump_packet structure:\n
1155
     * bw_sp0_sp1_r0_r1
1156
     *
1157
     */
1158
1159
    unsigned char data_shaping;
1160
1161
    // get the parameters for the data shaping [BW SP0 SP1 R0 R1] in sy_lfr_common1 and configure the register
1162
    // waveform picker : [R1 R0 SP1 SP0 BW]
1163
1164
314
    data_shaping = parameter_dump_packet.sy_lfr_common_parameters;
1165
1166
628
    waveform_picker_regs->data_shaping =
1167
628
            ( (data_shaping & BIT_5) >> SHIFT_5_BITS )      // BW
1168
314
            + ( (data_shaping & BIT_4) >> SHIFT_3_BITS )    // SP0
1169
314
            + ( (data_shaping & BIT_3) >> 1 )               // SP1
1170
314
            + ( (data_shaping & BIT_2) << 1 )               // R0
1171
314
            + ( (data_shaping & BIT_1) << SHIFT_3_BITS )    // R1
1172
314
            + ( (data_shaping & BIT_0) << SHIFT_5_BITS );   // R2
1173
314
}
1174
1175
137
void set_wfp_burst_enable_register( unsigned char mode )
1176
{
1177
    /** This function sets the waveform picker burst_enable register depending on the mode.
1178
     *
1179
     * @param mode is the LFR mode to launch.
1180
     *
1181
     * The burst bits shall be before the enable bits.
1182
     *
1183
     */
1184
1185
    // [0000 0000] burst f2, f1, f0 enable f3 f2 f1 f0
1186
    // the burst bits shall be set first, before the enable bits
1187
137
    switch(mode) {
1188
    case LFR_MODE_NORMAL:
1189
    case LFR_MODE_SBM1:
1190
    case LFR_MODE_SBM2:
1191
89
        waveform_picker_regs->run_burst_enable = RUN_BURST_ENABLE_SBM2;  // [0110 0000] enable f2 and f1 burst
1192
89
        waveform_picker_regs->run_burst_enable = waveform_picker_regs->run_burst_enable | BITS_WFP_ENABLE_ALL; // [1111] enable f3 f2 f1 f0
1193
89
        break;
1194
    case LFR_MODE_BURST:
1195
48
        waveform_picker_regs->run_burst_enable = RUN_BURST_ENABLE_BURST;  // [0100 0000] f2 burst enabled
1196
48
        waveform_picker_regs->run_burst_enable = waveform_picker_regs->run_burst_enable | BITS_WFP_ENABLE_BURST; // [1100] enable f3 and f2
1197
48
        break;
1198
    default:
1199
        waveform_picker_regs->run_burst_enable = INIT_CHAR;  // [0000 0000] no burst enabled, no waveform enabled
1200
        break;
1201
    }
1202
137
}
1203
1204
152
void set_wfp_delta_snapshot( void )
1205
{
1206
    /** This function sets the delta_snapshot register of the waveform picker module.
1207
     *
1208
     * The value is read from two (unsigned char) of the parameter_dump_packet structure:
1209
     * - sy_lfr_n_swf_p[0]
1210
     * - sy_lfr_n_swf_p[1]
1211
     *
1212
     */
1213
1214
    unsigned int delta_snapshot;
1215
    unsigned int delta_snapshot_in_T2;
1216
1217
304
    delta_snapshot = (parameter_dump_packet.sy_lfr_n_swf_p[0] * CONST_256)
1218
152
            + parameter_dump_packet.sy_lfr_n_swf_p[1];
1219
1220
152
    delta_snapshot_in_T2 = delta_snapshot * FREQ_F2;
1221
152
    waveform_picker_regs->delta_snapshot = delta_snapshot_in_T2 - 1;    // max 4 bytes
1222
152
}
1223
1224
140
void set_wfp_delta_f0_f0_2( void )
1225
{
1226
    unsigned int delta_snapshot;
1227
    unsigned int nb_samples_per_snapshot;
1228
    float delta_f0_in_float;
1229
1230
140
    delta_snapshot = waveform_picker_regs->delta_snapshot;
1231
140
    nb_samples_per_snapshot = (parameter_dump_packet.sy_lfr_n_swf_l[0] * CONST_256) + parameter_dump_packet.sy_lfr_n_swf_l[1];
1232
140
    delta_f0_in_float = (nb_samples_per_snapshot / 2.) * ( (1. / FREQ_F2) - (1. / FREQ_F0) ) * FREQ_F2;
1233
1234
140
    waveform_picker_regs->delta_f0      = delta_snapshot - floor( delta_f0_in_float );
1235
140
    waveform_picker_regs->delta_f0_2    = DFLT_WFP_DELTA_F0_2;
1236
140
}
1237
1238
void set_wfp_delta_f1( void )
1239
{
1240
    /** Sets the value of the delta_f1 parameter
1241
     *
1242
     * @param void
1243
     *
1244
     * @return void
1245
     *
1246
     * delta_f1 is not used, the snapshots are extracted from CWF_F1 waveforms.
1247
     *
1248
     */
1249
1250
    unsigned int delta_snapshot;
1251
    unsigned int nb_samples_per_snapshot;
1252
    float delta_f1_in_float;
1253
1254
    delta_snapshot = waveform_picker_regs->delta_snapshot;
1255
    nb_samples_per_snapshot = (parameter_dump_packet.sy_lfr_n_swf_l[0] * CONST_256) + parameter_dump_packet.sy_lfr_n_swf_l[1];
1256
    delta_f1_in_float = (nb_samples_per_snapshot / 2.) * ( (1. / FREQ_F2) - (1. / FREQ_F1) ) * FREQ_F2;
1257
1258
    waveform_picker_regs->delta_f1 = delta_snapshot - floor( delta_f1_in_float );
1259
}
1260
1261
140
void set_wfp_delta_f2( void )   // parameter not used, only delta_f0 and delta_f0_2 are used
1262
{
1263
    /** Sets the value of the delta_f2 parameter
1264
     *
1265
     * @param void
1266
     *
1267
     * @return void
1268
     *
1269
     * delta_f2 is used only for the first snapshot generation, even when the snapshots are extracted from CWF_F2
1270
     * waveforms (see lpp_waveform_snapshot_controler.vhd for details).
1271
     *
1272
     */
1273
1274
    unsigned int delta_snapshot;
1275
    unsigned int nb_samples_per_snapshot;
1276
1277
140
    delta_snapshot = waveform_picker_regs->delta_snapshot;
1278
140
    nb_samples_per_snapshot = (parameter_dump_packet.sy_lfr_n_swf_l[0] * CONST_256) + parameter_dump_packet.sy_lfr_n_swf_l[1];
1279
1280
140
    waveform_picker_regs->delta_f2 = delta_snapshot - (nb_samples_per_snapshot / 2) - 1;
1281
140
}
1282
1283
//*****************
1284
// local parameters
1285
1286
27506
void increment_seq_counter_source_id( unsigned char *packet_sequence_control, unsigned int sid )
1287
{
1288
    /** This function increments the parameter "sequence_cnt" depending on the sid passed in argument.
1289
     *
1290
     * @param packet_sequence_control is a pointer toward the parameter sequence_cnt to update.
1291
     * @param sid is the source identifier of the packet being updated.
1292
     *
1293
     * REQ-LFR-SRS-5240 / SSS-CP-FS-590
1294
     * The sequence counters shall wrap around from 2^14 to zero.
1295
     * The sequence counter shall start at zero at startup.
1296
     *
1297
     * REQ-LFR-SRS-5239 / SSS-CP-FS-580
1298
     * All TM_LFR_SCIENCE_ packets are sent to ground, i.e. destination id = 0
1299
     *
1300
     */
1301
1302
    unsigned short *sequence_cnt;
1303
    unsigned short segmentation_grouping_flag;
1304
    unsigned short new_packet_sequence_control;
1305
    rtems_mode initial_mode_set;
1306
    rtems_mode current_mode_set;
1307
    rtems_status_code status;
1308
1309
27506
    initial_mode_set = RTEMS_DEFAULT_MODES;
1310
27506
    current_mode_set = RTEMS_DEFAULT_MODES;
1311
27506
    sequence_cnt = NULL;
1312
1313
    //******************************************
1314
    // CHANGE THE MODE OF THE CALLING RTEMS TASK
1315
27506
    status =  rtems_task_mode( RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &initial_mode_set );
1316
1317




207412
    if ( (sid == SID_NORM_SWF_F0)    || (sid == SID_NORM_SWF_F1) || (sid == SID_NORM_SWF_F2)
1318
54501
         || (sid == SID_NORM_CWF_F3) || (sid == SID_NORM_CWF_LONG_F3)
1319
26995
         || (sid == SID_BURST_CWF_F2)
1320
52250
         || (sid == SID_NORM_ASM_F0) || (sid == SID_NORM_ASM_F1) || (sid == SID_NORM_ASM_F2)
1321
50646
         || (sid == SID_NORM_BP1_F0) || (sid == SID_NORM_BP1_F1) || (sid == SID_NORM_BP1_F2)
1322
47233
         || (sid == SID_NORM_BP2_F0) || (sid == SID_NORM_BP2_F1) || (sid == SID_NORM_BP2_F2)
1323
46158
         || (sid == SID_BURST_BP1_F0) || (sid == SID_BURST_BP2_F0)
1324
22639
         || (sid == SID_BURST_BP1_F1) || (sid == SID_BURST_BP2_F1) )
1325
    {
1326
5926
        sequence_cnt = (unsigned short *) &sequenceCounters_SCIENCE_NORMAL_BURST;
1327
    }
1328


45045
    else if ( (sid ==SID_SBM1_CWF_F1) || (sid ==SID_SBM2_CWF_F2)
1329
23226
              || (sid == SID_SBM1_BP1_F0) || (sid == SID_SBM1_BP2_F0)
1330
1885
              || (sid == SID_SBM2_BP1_F0) || (sid == SID_SBM2_BP2_F0)
1331
239
              || (sid == SID_SBM2_BP1_F1) || (sid == SID_SBM2_BP2_F1) )
1332
    {
1333
21580
        sequence_cnt = (unsigned short *) &sequenceCounters_SCIENCE_SBM1_SBM2;
1334
    }
1335
    else
1336
    {
1337
        sequence_cnt = (unsigned short *) NULL;
1338
        PRINTF1("in increment_seq_counter_source_id *** ERR apid_destid %d not known\n", sid)
1339
    }
1340
1341
27506
    if (sequence_cnt != NULL)
1342
    {
1343
27506
        segmentation_grouping_flag  = TM_PACKET_SEQ_CTRL_STANDALONE << SHIFT_1_BYTE;
1344
27506
        *sequence_cnt                = (*sequence_cnt) & SEQ_CNT_MASK;
1345
1346
27506
        new_packet_sequence_control = segmentation_grouping_flag | (*sequence_cnt) ;
1347
1348
27506
        packet_sequence_control[0] = (unsigned char) (new_packet_sequence_control >> SHIFT_1_BYTE);
1349
27506
        packet_sequence_control[1] = (unsigned char) (new_packet_sequence_control     );
1350
1351
        // increment the sequence counter
1352
27506
        if ( *sequence_cnt < SEQ_CNT_MAX)
1353
        {
1354
27505
            *sequence_cnt = *sequence_cnt + 1;
1355
        }
1356
        else
1357
        {
1358
1
            *sequence_cnt = 0;
1359
        }
1360
    }
1361
1362
    //*************************************
1363
    // RESTORE THE MODE OF THE CALLING TASK
1364
27506
    status =  rtems_task_mode( initial_mode_set, RTEMS_PREEMPT_MASK, &current_mode_set );
1365
27506
}
1366