GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/tc_handler.c Lines: 526 538 97.8 %
Date: 2018-11-13 11:16:07 Branches: 163 232 70.3 %

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
/** Functions and tasks related to TeleCommand handling.
25
 *
26
 * @file
27
 * @author P. LEROY
28
 *
29
 * A group of functions to handle TeleCommands:\n
30
 * action launching\n
31
 * TC parsing\n
32
 * ...
33
 *
34
 */
35
36
#include "tc_handler.h"
37
#include "math.h"
38
39
//***********
40
// RTEMS TASK
41
42
87
rtems_task actn_task( rtems_task_argument unused )
43
{
44
    /** This RTEMS task is responsible for launching actions upton the reception of valid TeleCommands.
45
     *
46
     * @param unused is the starting argument of the RTEMS task
47
     *
48
     * The ACTN task waits for data coming from an RTEMS msesage queue. When data arrives, it launches specific actions depending
49
     * on the incoming TeleCommand.
50
     *
51
     */
52
53
    int result;
54
    rtems_status_code status;       // RTEMS status code
55
    ccsdsTelecommandPacket_t __attribute__((aligned(4))) TC;    // TC sent to the ACTN task
56
    size_t size;                    // size of the incoming TC packet
57
    unsigned char subtype;          // subtype of the current TC packet
58
    unsigned char time[BYTES_PER_TIME];
59
    rtems_id queue_rcv_id;
60
    rtems_id queue_snd_id;
61
62
87
    memset(&TC, 0, sizeof(ccsdsTelecommandPacket_t));
63
87
    size = 0;
64
87
    queue_rcv_id = RTEMS_ID_NONE;
65
87
    queue_snd_id = RTEMS_ID_NONE;
66
67
87
    status =  get_message_queue_id_recv( &queue_rcv_id );
68
    if (status != RTEMS_SUCCESSFUL)
69
    {
70
        PRINTF1("in ACTN *** ERR get_message_queue_id_recv %d\n", status)
71
    }
72
73
87
    status =  get_message_queue_id_send( &queue_snd_id );
74
    if (status != RTEMS_SUCCESSFUL)
75
    {
76
        PRINTF1("in ACTN *** ERR get_message_queue_id_send %d\n", status)
77
    }
78
79
87
    result = LFR_SUCCESSFUL;
80
87
    subtype = 0;          // subtype of the current TC packet
81
82
    BOOT_PRINTF("in ACTN *** \n");
83
84
    while(1)
85
    {
86
29803
        status = rtems_message_queue_receive( queue_rcv_id, (char*) &TC, &size,
87
                                              RTEMS_WAIT, RTEMS_NO_TIMEOUT);
88
29803
        getTime( time );    // set time to the current time
89
29803
        if (status!=RTEMS_SUCCESSFUL)
90
        {
91
            PRINTF1("ERR *** in task ACTN *** error receiving a message, code %d \n", status)
92
        }
93
        else
94
        {
95
29803
            subtype = TC.serviceSubType;
96




29803
            switch(subtype)
97
            {
98
            case TC_SUBTYPE_RESET:
99
87
                result = action_reset( &TC, queue_snd_id, time );
100
                close_action( &TC, result, queue_snd_id );
101
                break;
102
            case TC_SUBTYPE_LOAD_COMM:
103
1409
                result = action_load_common_par( &TC );
104
1409
                close_action( &TC, result, queue_snd_id );
105
1409
                break;
106
            case TC_SUBTYPE_LOAD_NORM:
107
1255
                result = action_load_normal_par( &TC, queue_snd_id, time );
108
1255
                close_action( &TC, result, queue_snd_id );
109
1255
                break;
110
            case TC_SUBTYPE_LOAD_BURST:
111
1208
                result = action_load_burst_par( &TC, queue_snd_id, time );
112
1208
                close_action( &TC, result, queue_snd_id );
113
1208
                break;
114
            case TC_SUBTYPE_LOAD_SBM1:
115
1210
                result = action_load_sbm1_par( &TC, queue_snd_id, time );
116
1210
                close_action( &TC, result, queue_snd_id );
117
1210
                break;
118
            case TC_SUBTYPE_LOAD_SBM2:
119
1210
                result = action_load_sbm2_par( &TC, queue_snd_id, time );
120
1210
                close_action( &TC, result, queue_snd_id );
121
1210
                break;
122
            case TC_SUBTYPE_DUMP:
123
1655
                result = action_dump_par( &TC,  queue_snd_id );
124
1655
                close_action( &TC, result, queue_snd_id );
125
1655
                break;
126
            case TC_SUBTYPE_ENTER:
127
10718
                result = action_enter_mode( &TC, queue_snd_id );
128
10718
                close_action( &TC, result, queue_snd_id );
129
10718
                break;
130
            case TC_SUBTYPE_UPDT_INFO:
131
1302
                result = action_update_info( &TC, queue_snd_id );
132
1302
                close_action( &TC, result, queue_snd_id );
133
1302
                break;
134
            case TC_SUBTYPE_EN_CAL:
135
1182
                result = action_enable_calibration( &TC, queue_snd_id, time );
136
1182
                close_action( &TC, result, queue_snd_id );
137
1182
                break;
138
            case TC_SUBTYPE_DIS_CAL:
139
1182
                result = action_disable_calibration( &TC, queue_snd_id, time );
140
1182
                close_action( &TC, result, queue_snd_id );
141
1182
                break;
142
            case TC_SUBTYPE_LOAD_K:
143
1526
                result = action_load_kcoefficients( &TC, queue_snd_id, time );
144
1526
                close_action( &TC, result, queue_snd_id );
145
1526
                break;
146
            case TC_SUBTYPE_DUMP_K:
147
1525
                result = action_dump_kcoefficients( &TC, queue_snd_id, time );
148
1525
                close_action( &TC, result, queue_snd_id );
149
1525
                break;
150
            case TC_SUBTYPE_LOAD_FBINS:
151
1183
                result = action_load_fbins_mask( &TC, queue_snd_id, time );
152
1183
                close_action( &TC, result, queue_snd_id );
153
1183
                break;
154
            case TC_SUBTYPE_LOAD_FILTER_PAR:
155
1225
                result = action_load_filter_par( &TC, queue_snd_id, time );
156
1225
                close_action( &TC, result, queue_snd_id );
157
1225
                break;
158
            case TC_SUBTYPE_UPDT_TIME:
159
1926
                result = action_update_time( &TC );
160
1926
                close_action( &TC, result, queue_snd_id );
161
                break;
162
            default:
163
                break;
164
            }
165
        }
166
    }
167
}
168
169
//***********
170
// TC ACTIONS
171
172
87
int action_reset(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
173
{
174
    /** This function executes specific actions when a TC_LFR_RESET TeleCommand has been received.
175
     *
176
     * @param TC points to the TeleCommand packet that is being processed
177
     * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
178
     *
179
     */
180
181
    PRINTF("this is the end!!!\n");
182
#ifdef GCOV_ENABLED
183
#ifndef GCOV_USE_EXIT
184
    extern void gcov_exit (void);
185
    gcov_exit();
186
#endif
187
#endif
188
87
    exit(0);
189
190
#ifdef ENABLE_DEAD_CODE
191
    send_tm_lfr_tc_exe_not_implemented( TC, queue_id, time );
192
#endif
193
194
    return LFR_DEFAULT;
195
}
196
197
10718
int action_enter_mode(ccsdsTelecommandPacket_t *TC, rtems_id queue_id )
198
{
199
    /** This function executes specific actions when a TC_LFR_ENTER_MODE TeleCommand has been received.
200
     *
201
     * @param TC points to the TeleCommand packet that is being processed
202
     * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
203
     *
204
     */
205
206
    rtems_status_code status;
207
    unsigned char requestedMode;
208
    unsigned int transitionCoarseTime;
209
    unsigned char * bytePosPtr;
210
211
10718
    bytePosPtr = (unsigned char *) &TC->packetID;
212
10718
    requestedMode = bytePosPtr[ BYTE_POS_CP_MODE_LFR_SET ];
213
10718
    copyInt32ByChar( (char*) &transitionCoarseTime, &bytePosPtr[ BYTE_POS_CP_LFR_ENTER_MODE_TIME ] );
214
10718
    transitionCoarseTime = transitionCoarseTime & COARSE_TIME_MASK;
215
10718
    status = check_mode_value( requestedMode );
216
217
10718
    if ( status != LFR_SUCCESSFUL )     // the mode value is inconsistent
218
    {
219
17
        send_tm_lfr_tc_exe_inconsistent( TC, queue_id, BYTE_POS_CP_MODE_LFR_SET, requestedMode );
220
    }
221
222
    else                                // the mode value is valid, check the transition
223
    {
224
10701
        status = check_mode_transition(requestedMode);
225
10701
        if (status != LFR_SUCCESSFUL)
226
        {
227
            PRINTF("ERR *** in action_enter_mode *** check_mode_transition\n")
228
8514
                    send_tm_lfr_tc_exe_not_executable( TC, queue_id );
229
        }
230
    }
231
232
10718
    if ( status == LFR_SUCCESSFUL )     // the transition is valid, check the date
233
    {
234
2187
        status = check_transition_date( transitionCoarseTime );
235
2187
        if (status != LFR_SUCCESSFUL)
236
        {
237
            PRINTF("ERR *** in action_enter_mode *** check_transition_date\n");
238
127
            send_tm_lfr_tc_exe_not_executable(TC, queue_id );
239
        }
240
    }
241
242
10718
    if ( status == LFR_SUCCESSFUL )     // the date is valid, enter the mode
243
    {
244
        PRINTF1("OK  *** in action_enter_mode *** enter mode %d\n", requestedMode);
245
246

2060
        switch(requestedMode)
247
        {
248
        case LFR_MODE_STANDBY:
249
454
            status = enter_mode_standby();
250
454
            break;
251
        case LFR_MODE_NORMAL:
252
404
            status = enter_mode_normal( transitionCoarseTime );
253
404
            break;
254
        case LFR_MODE_BURST:
255
398
            status = enter_mode_burst( transitionCoarseTime );
256
398
            break;
257
        case LFR_MODE_SBM1:
258
391
            status = enter_mode_sbm1( transitionCoarseTime );
259
391
            break;
260
        case LFR_MODE_SBM2:
261
413
            status = enter_mode_sbm2( transitionCoarseTime );
262
            break;
263
        default:
264
            break;
265
        }
266
267
2060
        if (status != RTEMS_SUCCESSFUL)
268
        {
269
            status = LFR_EXE_ERROR;
270
        }
271
    }
272
273
10718
    return status;
274
}
275
276
1302
int action_update_info(ccsdsTelecommandPacket_t *TC, rtems_id queue_id)
277
{
278
    /** This function executes specific actions when a TC_LFR_UPDATE_INFO TeleCommand has been received.
279
     *
280
     * @param TC points to the TeleCommand packet that is being processed
281
     * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
282
     *
283
     * @return LFR directive status code:
284
     * - LFR_DEFAULT
285
     * - LFR_SUCCESSFUL
286
     *
287
     */
288
289
    unsigned int val;
290
    unsigned int status;
291
    unsigned char mode;
292
    unsigned char * bytePosPtr;
293
    int pos;
294
    float value;
295
296
1302
    pos = INIT_CHAR;
297
1302
    value = INIT_FLOAT;
298
299
1302
    status = LFR_DEFAULT;
300
301
1302
    bytePosPtr = (unsigned char *) &TC->packetID;
302
303
    // check LFR mode
304
1302
    mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET5 ] & BITS_LFR_MODE) >> SHIFT_LFR_MODE;
305
1302
    status = check_update_info_hk_lfr_mode( mode );
306
1302
    if (status == LFR_SUCCESSFUL)  // check TDS mode
307
    {
308
1292
        mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET6 ] & BITS_TDS_MODE) >> SHIFT_TDS_MODE;
309
1292
        status = check_update_info_hk_tds_mode( mode );
310
    }
311
1302
    if (status == LFR_SUCCESSFUL)  // check THR mode
312
    {
313
1282
        mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET6 ] & BITS_THR_MODE);
314
1282
        status = check_update_info_hk_thr_mode( mode );
315
    }
316
1302
    if (status == LFR_SUCCESSFUL) // check reaction wheels frequencies
317
    {
318
1272
        status = check_all_sy_lfr_rw_f(TC, &pos, &value);
319
    }
320
321
    // if the parameters checking succeeds, udpate all parameters
322
1302
    if (status == LFR_SUCCESSFUL)
323
    {
324
        // pa_bia_status_info
325
        // => pa_bia_mode_mux_set       3 bits
326
        // => pa_bia_mode_hv_enabled    1 bit
327
        // => pa_bia_mode_bias1_enabled 1 bit
328
        // => pa_bia_mode_bias2_enabled 1 bit
329
        // => pa_bia_mode_bias3_enabled 1 bit
330
        // => pa_bia_on_off (cp_dpu_bias_on_off)
331
1266
        pa_bia_status_info = bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET2 ] & BITS_BIA; // [1111 1110]
332
1266
        pa_bia_status_info = pa_bia_status_info
333
1266
                | (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET1 ] & 1);
334
335
        // REACTION_WHEELS_FREQUENCY, copy the incoming parameters in the local variable (to be copied in HK packets)
336
1266
        getReactionWheelsFrequencies( TC );
337
1266
        set_hk_lfr_sc_rw_f_flags();
338
1266
        build_sy_lfr_rw_masks();
339
340
        // once the masks are built, they have to be merged with the fbins_mask
341
1266
        merge_fbins_masks();
342
343
        // increase the TC_LFR_UPDATE_INFO counter
344
1266
        if (status == LFR_SUCCESSFUL)  // if the parameter check is successful
345
        {
346
2532
            val = (housekeeping_packet.hk_lfr_update_info_tc_cnt[0] * CONST_256)
347
1266
                    + housekeeping_packet.hk_lfr_update_info_tc_cnt[1];
348
1266
            val++;
349
1266
            housekeeping_packet.hk_lfr_update_info_tc_cnt[0] = (unsigned char) (val >> SHIFT_1_BYTE);
350
1266
            housekeeping_packet.hk_lfr_update_info_tc_cnt[1] = (unsigned char) (val);
351
        }
352
    }
353
354
1302
    return status;
355
}
356
357
1182
int action_enable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
358
{
359
    /** This function executes specific actions when a TC_LFR_ENABLE_CALIBRATION TeleCommand has been received.
360
     *
361
     * @param TC points to the TeleCommand packet that is being processed
362
     * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
363
     *
364
     */
365
366
    int result;
367
368
1182
    result = LFR_DEFAULT;
369
370
1182
    setCalibration( true );
371
372
1182
    result = LFR_SUCCESSFUL;
373
374
1182
    return result;
375
}
376
377
1182
int action_disable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
378
{
379
    /** This function executes specific actions when a TC_LFR_DISABLE_CALIBRATION TeleCommand has been received.
380
     *
381
     * @param TC points to the TeleCommand packet that is being processed
382
     * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
383
     *
384
     */
385
386
    int result;
387
388
1182
    result = LFR_DEFAULT;
389
390
1182
    setCalibration( false );
391
392
1182
    result = LFR_SUCCESSFUL;
393
394
1182
    return result;
395
}
396
397
1926
int action_update_time(ccsdsTelecommandPacket_t *TC)
398
{
399
    /** This function executes specific actions when a TC_LFR_UPDATE_TIME TeleCommand has been received.
400
     *
401
     * @param TC points to the TeleCommand packet that is being processed
402
     * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
403
     *
404
     * @return LFR_SUCCESSFUL
405
     *
406
     */
407
408
    unsigned int val;
409
410
3852
    time_management_regs->coarse_time_load = (TC->dataAndCRC[BYTE_0] << SHIFT_3_BYTES)
411
1926
            + (TC->dataAndCRC[BYTE_1] << SHIFT_2_BYTES)
412
1926
            + (TC->dataAndCRC[BYTE_2] << SHIFT_1_BYTE)
413
1926
            + TC->dataAndCRC[BYTE_3];
414
415
3852
    val = (housekeeping_packet.hk_lfr_update_time_tc_cnt[0] * CONST_256)
416
1926
            + housekeeping_packet.hk_lfr_update_time_tc_cnt[1];
417
1926
    val++;
418
1926
    housekeeping_packet.hk_lfr_update_time_tc_cnt[0] = (unsigned char) (val >> SHIFT_1_BYTE);
419
1926
    housekeeping_packet.hk_lfr_update_time_tc_cnt[1] = (unsigned char) (val);
420
421
1926
    oneTcLfrUpdateTimeReceived = 1;
422
423
1926
    return LFR_SUCCESSFUL;
424
}
425
426
//*******************
427
// ENTERING THE MODES
428
10718
int check_mode_value( unsigned char requestedMode )
429
{
430
    int status;
431
432
10718
    status = LFR_DEFAULT;
433
434
10718
    if ( (requestedMode != LFR_MODE_STANDBY)
435
         && (requestedMode != LFR_MODE_NORMAL) && (requestedMode != LFR_MODE_BURST)
436
         && (requestedMode != LFR_MODE_SBM1) && (requestedMode != LFR_MODE_SBM2) )
437
    {
438
17
        status = LFR_DEFAULT;
439
    }
440
    else
441
    {
442
10701
        status = LFR_SUCCESSFUL;
443
    }
444
445
10718
    return status;
446
}
447
448
10701
int check_mode_transition( unsigned char requestedMode )
449
{
450
    /** This function checks the validity of the transition requested by the TC_LFR_ENTER_MODE.
451
     *
452
     * @param requestedMode is the mode requested by the TC_LFR_ENTER_MODE
453
     *
454
     * @return LFR directive status codes:
455
     * - LFR_SUCCESSFUL - the transition is authorized
456
     * - LFR_DEFAULT - the transition is not authorized
457
     *
458
     */
459
460
    int status;
461
462

10701
    switch (requestedMode)
463
    {
464
    case LFR_MODE_STANDBY:
465
8786
        if ( lfrCurrentMode == LFR_MODE_STANDBY ) {
466
8297
            status = LFR_DEFAULT;
467
        }
468
        else
469
        {
470
489
            status = LFR_SUCCESSFUL;
471
        }
472
        break;
473
    case LFR_MODE_NORMAL:
474
483
        if ( lfrCurrentMode == LFR_MODE_NORMAL ) {
475
50
            status = LFR_DEFAULT;
476
        }
477
        else {
478
433
            status = LFR_SUCCESSFUL;
479
        }
480
        break;
481
    case LFR_MODE_BURST:
482
465
        if ( lfrCurrentMode == LFR_MODE_BURST ) {
483
38
            status = LFR_DEFAULT;
484
        }
485
        else {
486
427
            status = LFR_SUCCESSFUL;
487
        }
488
        break;
489
    case LFR_MODE_SBM1:
490
484
        if ( lfrCurrentMode == LFR_MODE_SBM1 ) {
491
61
            status = LFR_DEFAULT;
492
        }
493
        else {
494
423
            status = LFR_SUCCESSFUL;
495
        }
496
        break;
497
    case LFR_MODE_SBM2:
498
483
        if ( lfrCurrentMode == LFR_MODE_SBM2 ) {
499
68
            status = LFR_DEFAULT;
500
        }
501
        else {
502
415
            status = LFR_SUCCESSFUL;
503
        }
504
        break;
505
    default:
506
        status = LFR_DEFAULT;
507
        break;
508
    }
509
510
10701
    return status;
511
}
512
513
1693
void update_last_valid_transition_date( unsigned int transitionCoarseTime )
514
{
515
1693
    if (transitionCoarseTime == 0)
516
    {
517
384
        lastValidEnterModeTime = time_management_regs->coarse_time + 1;
518
        PRINTF1("lastValidEnterModeTime = 0x%x (transitionCoarseTime = 0 => coarse_time+1)\n", lastValidEnterModeTime);
519
    }
520
    else
521
    {
522
1309
        lastValidEnterModeTime = transitionCoarseTime;
523
        PRINTF1("lastValidEnterModeTime = 0x%x\n", transitionCoarseTime);
524
    }
525
1693
}
526
527
2187
int check_transition_date( unsigned int transitionCoarseTime )
528
{
529
    int status;
530
    unsigned int localCoarseTime;
531
    unsigned int deltaCoarseTime;
532
533
2187
    status = LFR_SUCCESSFUL;
534
535
2187
    if (transitionCoarseTime == 0)  // transition time = 0 means an instant transition
536
    {
537
1887
        status = LFR_SUCCESSFUL;
538
    }
539
    else
540
    {
541
300
        localCoarseTime = time_management_regs->coarse_time & COARSE_TIME_MASK;
542
543
        PRINTF2("localTime = %x, transitionTime = %x\n", localCoarseTime, transitionCoarseTime);
544
545
300
        if ( transitionCoarseTime <= localCoarseTime )   // SSS-CP-EQS-322
546
        {
547
93
            status = LFR_DEFAULT;
548
            PRINTF("ERR *** in check_transition_date *** transitionCoarseTime <= localCoarseTime\n");
549
        }
550
551
300
        if (status == LFR_SUCCESSFUL)
552
        {
553
207
            deltaCoarseTime = transitionCoarseTime - localCoarseTime;
554
207
            if ( deltaCoarseTime > MAX_DELTA_COARSE_TIME )  // SSS-CP-EQS-323
555
            {
556
34
                status = LFR_DEFAULT;
557
                PRINTF1("ERR *** in check_transition_date *** deltaCoarseTime = %x\n", deltaCoarseTime)
558
            }
559
        }
560
    }
561
562
2187
    return status;
563
}
564
565
438
int restart_asm_activities( unsigned char lfrRequestedMode )
566
{
567
    rtems_status_code status;
568
569
438
    status = stop_spectral_matrices();
570
571
438
    thisIsAnASMRestart = 1;
572
573
438
    status = restart_asm_tasks( lfrRequestedMode );
574
575
438
    launch_spectral_matrix();
576
577
438
    return status;
578
}
579
580
438
int stop_spectral_matrices( void )
581
{
582
    /** This function stops and restarts the current mode average spectral matrices activities.
583
     *
584
     * @return RTEMS directive status codes:
585
     * - RTEMS_SUCCESSFUL - task restarted successfully
586
     * - RTEMS_INVALID_ID - task id invalid
587
     * - RTEMS_ALREADY_SUSPENDED - task already suspended
588
     *
589
     */
590
591
    rtems_status_code status;
592
593
438
    status = RTEMS_SUCCESSFUL;
594
595
    // (1) mask interruptions
596
438
    LEON_Mask_interrupt( IRQ_SPECTRAL_MATRIX );     // mask spectral matrix interrupt
597
598
    // (2) reset spectral matrices registers
599
438
    set_sm_irq_onNewMatrix( 0 );                    // stop the spectral matrices
600
438
    reset_sm_status();
601
602
    // (3) clear interruptions
603
438
    LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX );    // clear spectral matrix interrupt
604
605
    // suspend several tasks
606
438
    if (lfrCurrentMode != LFR_MODE_STANDBY) {
607
438
        status = suspend_asm_tasks();
608
    }
609
610
    if (status != RTEMS_SUCCESSFUL)
611
    {
612
        PRINTF1("in stop_current_mode *** in suspend_science_tasks *** ERR code: %d\n", status)
613
    }
614
615
438
    return status;
616
}
617
618
1215
int stop_current_mode( void )
619
{
620
    /** This function stops the current mode by masking interrupt lines and suspending science tasks.
621
     *
622
     * @return RTEMS directive status codes:
623
     * - RTEMS_SUCCESSFUL - task restarted successfully
624
     * - RTEMS_INVALID_ID - task id invalid
625
     * - RTEMS_ALREADY_SUSPENDED - task already suspended
626
     *
627
     */
628
629
    rtems_status_code status;
630
631
1215
    status = RTEMS_SUCCESSFUL;
632
633
    // (1) mask interruptions
634
1215
    LEON_Mask_interrupt( IRQ_WAVEFORM_PICKER );     // mask waveform picker interrupt
635
1215
    LEON_Mask_interrupt( IRQ_SPECTRAL_MATRIX );     // clear spectral matrix interrupt
636
637
    // (2) reset waveform picker registers
638
1215
    reset_wfp_burst_enable();                       // reset burst and enable bits
639
1215
    reset_wfp_status();                             // reset all the status bits
640
641
    // (3) reset spectral matrices registers
642
1215
    set_sm_irq_onNewMatrix( 0 );                    // stop the spectral matrices
643
1215
    reset_sm_status();
644
645
    // reset lfr VHDL module
646
1215
    reset_lfr();
647
648
1215
    reset_extractSWF();                             // reset the extractSWF flag to false
649
650
    // (4) clear interruptions
651
1215
    LEON_Clear_interrupt( IRQ_WAVEFORM_PICKER );    // clear waveform picker interrupt
652
1215
    LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX );    // clear spectral matrix interrupt
653
654
    // suspend several tasks
655
1215
    if (lfrCurrentMode != LFR_MODE_STANDBY) {
656
1167
        status = suspend_science_tasks();
657
    }
658
659
    if (status != RTEMS_SUCCESSFUL)
660
    {
661
        PRINTF1("in stop_current_mode *** in suspend_science_tasks *** ERR code: %d\n", status)
662
    }
663
664
1215
    return status;
665
}
666
667
459
int enter_mode_standby( void )
668
{
669
    /** This function is used to put LFR in the STANDBY mode.
670
     *
671
     * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
672
     *
673
     * @return RTEMS directive status codes:
674
     * - RTEMS_SUCCESSFUL - task restarted successfully
675
     * - RTEMS_INVALID_ID - task id invalid
676
     * - RTEMS_INCORRECT_STATE - task never started
677
     * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
678
     *
679
     * The STANDBY mode does not depends on a specific transition date, the effect of the TC_LFR_ENTER_MODE
680
     * is immediate.
681
     *
682
     */
683
684
    int status;
685
686
459
    status = stop_current_mode();       // STOP THE CURRENT MODE
687
688
#ifdef PRINT_TASK_STATISTICS
689
    rtems_cpu_usage_report();
690
#endif
691
692
#ifdef PRINT_STACK_REPORT
693
    PRINTF("stack report selected\n")
694
    rtems_stack_checker_report_usage();
695
#endif
696
697
459
    return status;
698
}
699
700
404
int enter_mode_normal( unsigned int transitionCoarseTime )
701
{
702
    /** This function is used to start the NORMAL mode.
703
     *
704
     * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
705
     *
706
     * @return RTEMS directive status codes:
707
     * - RTEMS_SUCCESSFUL - task restarted successfully
708
     * - RTEMS_INVALID_ID - task id invalid
709
     * - RTEMS_INCORRECT_STATE - task never started
710
     * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
711
     *
712
     * The way the NORMAL mode is started depends on the LFR current mode. If LFR is in SBM1 or SBM2,
713
     * the snapshots are not restarted, only ASM, BP and CWF data generation are affected.
714
     *
715
     */
716
717
    int status;
718
719
#ifdef PRINT_TASK_STATISTICS
720
    rtems_cpu_usage_reset();
721
#endif
722
723
404
    status = RTEMS_UNSATISFIED;
724
725

404
    switch( lfrCurrentMode )
726
    {
727
    case LFR_MODE_STANDBY:
728
297
        status = restart_science_tasks( LFR_MODE_NORMAL ); // restart science tasks
729
297
        if (status == RTEMS_SUCCESSFUL)         // relaunch spectral_matrix and waveform_picker modules
730
        {
731
297
            launch_spectral_matrix( );
732
297
            launch_waveform_picker( LFR_MODE_NORMAL, transitionCoarseTime );
733
        }
734
        break;
735
    case LFR_MODE_BURST:
736
39
        status = stop_current_mode();           // stop the current mode
737
39
        status = restart_science_tasks( LFR_MODE_NORMAL ); // restart the science tasks
738
39
        if (status == RTEMS_SUCCESSFUL)         // relaunch spectral_matrix and waveform_picker modules
739
        {
740
39
            launch_spectral_matrix( );
741
39
            launch_waveform_picker( LFR_MODE_NORMAL, transitionCoarseTime );
742
        }
743
        break;
744
    case LFR_MODE_SBM1:
745
27
        status = restart_asm_activities( LFR_MODE_NORMAL ); // this is necessary to restart ASM tasks to update the parameters
746
27
        status = LFR_SUCCESSFUL;                   // lfrCurrentMode will be updated after the execution of close_action
747
27
        update_last_valid_transition_date( transitionCoarseTime );
748
27
        break;
749
    case LFR_MODE_SBM2:
750
41
        status = restart_asm_activities( LFR_MODE_NORMAL ); // this is necessary to restart ASM tasks to update the parameters
751
41
        status = LFR_SUCCESSFUL;                   // lfrCurrentMode will be updated after the execution of close_action
752
41
        update_last_valid_transition_date( transitionCoarseTime );
753
        break;
754
    default:
755
        break;
756
    }
757
758
404
    if (status != RTEMS_SUCCESSFUL)
759
    {
760
        PRINTF1("ERR *** in enter_mode_normal *** status = %d\n", status)
761
                status = RTEMS_UNSATISFIED;
762
    }
763
764
404
    return status;
765
}
766
767
398
int enter_mode_burst( unsigned int transitionCoarseTime )
768
{
769
    /** This function is used to start the BURST mode.
770
     *
771
     * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
772
     *
773
     * @return RTEMS directive status codes:
774
     * - RTEMS_SUCCESSFUL - task restarted successfully
775
     * - RTEMS_INVALID_ID - task id invalid
776
     * - RTEMS_INCORRECT_STATE - task never started
777
     * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
778
     *
779
     * The way the BURST mode is started does not depend on the LFR current mode.
780
     *
781
     */
782
783
784
    int status;
785
786
#ifdef PRINT_TASK_STATISTICS
787
    rtems_cpu_usage_reset();
788
#endif
789
790
398
    status = stop_current_mode();           // stop the current mode
791
398
    status = restart_science_tasks( LFR_MODE_BURST ); // restart the science tasks
792
398
    if (status == RTEMS_SUCCESSFUL)         // relaunch spectral_matrix and waveform_picker modules
793
    {
794
398
        launch_spectral_matrix( );
795
398
        launch_waveform_picker( LFR_MODE_BURST, transitionCoarseTime );
796
    }
797
798
398
    if (status != RTEMS_SUCCESSFUL)
799
    {
800
        PRINTF1("ERR *** in enter_mode_burst *** status = %d\n", status)
801
                status = RTEMS_UNSATISFIED;
802
    }
803
804
398
    return status;
805
}
806
807
391
int enter_mode_sbm1( unsigned int transitionCoarseTime )
808
{
809
    /** This function is used to start the SBM1 mode.
810
     *
811
     * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
812
     *
813
     * @return RTEMS directive status codes:
814
     * - RTEMS_SUCCESSFUL - task restarted successfully
815
     * - RTEMS_INVALID_ID - task id invalid
816
     * - RTEMS_INCORRECT_STATE - task never started
817
     * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
818
     *
819
     * The way the SBM1 mode is started depends on the LFR current mode. If LFR is in NORMAL or SBM2,
820
     * the snapshots are not restarted, only ASM, BP and CWF data generation are affected. In other
821
     * cases, the acquisition is completely restarted.
822
     *
823
     */
824
825
    int status;
826
827
#ifdef PRINT_TASK_STATISTICS
828
    rtems_cpu_usage_reset();
829
#endif
830
831
391
    status = RTEMS_UNSATISFIED;
832
833

391
    switch( lfrCurrentMode )
834
    {
835
    case LFR_MODE_STANDBY:
836
45
        status = restart_science_tasks( LFR_MODE_SBM1 ); // restart science tasks
837
45
        if (status == RTEMS_SUCCESSFUL)         // relaunch spectral_matrix and waveform_picker modules
838
        {
839
45
            launch_spectral_matrix( );
840
45
            launch_waveform_picker( LFR_MODE_SBM1, transitionCoarseTime );
841
        }
842
        break;
843
    case LFR_MODE_NORMAL:                       // lfrCurrentMode will be updated after the execution of close_action
844
36
        status = restart_asm_activities( LFR_MODE_SBM1 );
845
36
        status = LFR_SUCCESSFUL;
846
36
        update_last_valid_transition_date( transitionCoarseTime );
847
36
        break;
848
    case LFR_MODE_BURST:
849
283
        status = stop_current_mode();           // stop the current mode
850
283
        status = restart_science_tasks( LFR_MODE_SBM1 ); // restart the science tasks
851
283
        if (status == RTEMS_SUCCESSFUL)         // relaunch spectral_matrix and waveform_picker modules
852
        {
853
283
            launch_spectral_matrix( );
854
283
            launch_waveform_picker( LFR_MODE_SBM1, transitionCoarseTime );
855
        }
856
        break;
857
    case LFR_MODE_SBM2:
858
27
        status = restart_asm_activities( LFR_MODE_SBM1 );
859
27
        status = LFR_SUCCESSFUL;                // lfrCurrentMode will be updated after the execution of close_action
860
27
        update_last_valid_transition_date( transitionCoarseTime );
861
        break;
862
    default:
863
        break;
864
    }
865
866
391
    if (status != RTEMS_SUCCESSFUL)
867
    {
868
        PRINTF1("ERR *** in enter_mode_sbm1 *** status = %d\n", status);
869
        status = RTEMS_UNSATISFIED;
870
    }
871
872
391
    return status;
873
}
874
875
413
int enter_mode_sbm2( unsigned int transitionCoarseTime )
876
{
877
    /** This function is used to start the SBM2 mode.
878
     *
879
     * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
880
     *
881
     * @return RTEMS directive status codes:
882
     * - RTEMS_SUCCESSFUL - task restarted successfully
883
     * - RTEMS_INVALID_ID - task id invalid
884
     * - RTEMS_INCORRECT_STATE - task never started
885
     * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
886
     *
887
     * The way the SBM2 mode is started depends on the LFR current mode. If LFR is in NORMAL or SBM1,
888
     * the snapshots are not restarted, only ASM, BP and CWF data generation are affected. In other
889
     * cases, the acquisition is completely restarted.
890
     *
891
     */
892
893
    int status;
894
895
#ifdef PRINT_TASK_STATISTICS
896
    rtems_cpu_usage_reset();
897
#endif
898
899
413
    status = RTEMS_UNSATISFIED;
900
901

413
    switch( lfrCurrentMode )
902
    {
903
    case LFR_MODE_STANDBY:
904
70
        status = restart_science_tasks( LFR_MODE_SBM2 ); // restart science tasks
905
70
        if (status == RTEMS_SUCCESSFUL)         // relaunch spectral_matrix and waveform_picker modules
906
        {
907
70
            launch_spectral_matrix( );
908
70
            launch_waveform_picker( LFR_MODE_SBM2, transitionCoarseTime );
909
        }
910
        break;
911
    case LFR_MODE_NORMAL:
912
28
        status = restart_asm_activities( LFR_MODE_SBM2 );
913
28
        status = LFR_SUCCESSFUL;                // lfrCurrentMode will be updated after the execution of close_action
914
28
        update_last_valid_transition_date( transitionCoarseTime );
915
28
        break;
916
    case LFR_MODE_BURST:
917
36
        status = stop_current_mode();           // stop the current mode
918
36
        status = restart_science_tasks( LFR_MODE_SBM2 ); // restart the science tasks
919
36
        if (status == RTEMS_SUCCESSFUL)         // relaunch spectral_matrix and waveform_picker modules
920
        {
921
36
            launch_spectral_matrix( );
922
36
            launch_waveform_picker( LFR_MODE_SBM2, transitionCoarseTime );
923
        }
924
        break;
925
    case LFR_MODE_SBM1:
926
279
        status = restart_asm_activities( LFR_MODE_SBM2 );
927
279
        status = LFR_SUCCESSFUL;                // lfrCurrentMode will be updated after the execution of close_action
928
279
        update_last_valid_transition_date( transitionCoarseTime );
929
        break;
930
    default:
931
        break;
932
    }
933
934
413
    if (status != RTEMS_SUCCESSFUL)
935
    {
936
        PRINTF1("ERR *** in enter_mode_sbm2 *** status = %d\n", status)
937
                status = RTEMS_UNSATISFIED;
938
    }
939
940
413
    return status;
941
}
942
943
1168
int restart_science_tasks( unsigned char lfrRequestedMode )
944
{
945
    /** This function is used to restart all science tasks.
946
     *
947
     * @return RTEMS directive status codes:
948
     * - RTEMS_SUCCESSFUL - task restarted successfully
949
     * - RTEMS_INVALID_ID - task id invalid
950
     * - RTEMS_INCORRECT_STATE - task never started
951
     * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
952
     *
953
     * Science tasks are AVF0, PRC0, WFRM, CWF3, CW2, CWF1
954
     *
955
     */
956
957
    rtems_status_code status[NB_SCIENCE_TASKS];
958
    rtems_status_code ret;
959
960
1168
    ret = RTEMS_SUCCESSFUL;
961
962
1168
    status[STATUS_0] = rtems_task_restart( Task_id[TASKID_AVF0], lfrRequestedMode );
963
1168
    if (status[STATUS_0] != RTEMS_SUCCESSFUL)
964
    {
965
        PRINTF1("in restart_science_task *** AVF0 ERR %d\n", status[STATUS_0])
966
    }
967
968
1168
    status[STATUS_1] = rtems_task_restart( Task_id[TASKID_PRC0], lfrRequestedMode );
969
1168
    if (status[STATUS_1] != RTEMS_SUCCESSFUL)
970
    {
971
        PRINTF1("in restart_science_task *** PRC0 ERR %d\n", status[STATUS_1])
972
    }
973
974
1168
    status[STATUS_2] = rtems_task_restart( Task_id[TASKID_WFRM],1 );
975
1168
    if (status[STATUS_2] != RTEMS_SUCCESSFUL)
976
    {
977
        PRINTF1("in restart_science_task *** WFRM ERR %d\n", status[STATUS_2])
978
    }
979
980
1168
    status[STATUS_3] = rtems_task_restart( Task_id[TASKID_CWF3],1 );
981
1168
    if (status[STATUS_3] != RTEMS_SUCCESSFUL)
982
    {
983
        PRINTF1("in restart_science_task *** CWF3 ERR %d\n", status[STATUS_3])
984
    }
985
986
1168
    status[STATUS_4] = rtems_task_restart( Task_id[TASKID_CWF2],1 );
987
1168
    if (status[STATUS_4] != RTEMS_SUCCESSFUL)
988
    {
989
        PRINTF1("in restart_science_task *** CWF2 ERR %d\n", status[STATUS_4])
990
    }
991
992
1168
    status[STATUS_5] = rtems_task_restart( Task_id[TASKID_CWF1],1 );
993
1168
    if (status[STATUS_5] != RTEMS_SUCCESSFUL)
994
    {
995
        PRINTF1("in restart_science_task *** CWF1 ERR %d\n", status[STATUS_5])
996
    }
997
998
1168
    status[STATUS_6] = rtems_task_restart( Task_id[TASKID_AVF1], lfrRequestedMode );
999
1168
    if (status[STATUS_6] != RTEMS_SUCCESSFUL)
1000
    {
1001
        PRINTF1("in restart_science_task *** AVF1 ERR %d\n", status[STATUS_6])
1002
    }
1003
1004
1168
    status[STATUS_7] = rtems_task_restart( Task_id[TASKID_PRC1],lfrRequestedMode );
1005
1168
    if (status[STATUS_7] != RTEMS_SUCCESSFUL)
1006
    {
1007
        PRINTF1("in restart_science_task *** PRC1 ERR %d\n", status[STATUS_7])
1008
    }
1009
1010
1168
    status[STATUS_8] = rtems_task_restart( Task_id[TASKID_AVF2], 1 );
1011
1168
    if (status[STATUS_8] != RTEMS_SUCCESSFUL)
1012
    {
1013
        PRINTF1("in restart_science_task *** AVF2 ERR %d\n", status[STATUS_8])
1014
    }
1015
1016
1168
    status[STATUS_9] = rtems_task_restart( Task_id[TASKID_PRC2], 1 );
1017
1168
    if (status[STATUS_9] != RTEMS_SUCCESSFUL)
1018
    {
1019
        PRINTF1("in restart_science_task *** PRC2 ERR %d\n", status[STATUS_9])
1020
    }
1021
1022





10512
    if ( (status[STATUS_0] != RTEMS_SUCCESSFUL) || (status[STATUS_1] != RTEMS_SUCCESSFUL) ||
1023
2336
         (status[STATUS_2] != RTEMS_SUCCESSFUL) || (status[STATUS_3] != RTEMS_SUCCESSFUL) ||
1024
2336
         (status[STATUS_4] != RTEMS_SUCCESSFUL) || (status[STATUS_5] != RTEMS_SUCCESSFUL) ||
1025
2336
         (status[STATUS_6] != RTEMS_SUCCESSFUL) || (status[STATUS_7] != RTEMS_SUCCESSFUL) ||
1026
2336
         (status[STATUS_8] != RTEMS_SUCCESSFUL) || (status[STATUS_9] != RTEMS_SUCCESSFUL) )
1027
    {
1028
        ret = RTEMS_UNSATISFIED;
1029
    }
1030
1031
1168
    return ret;
1032
}
1033
1034
438
int restart_asm_tasks( unsigned char lfrRequestedMode )
1035
{
1036
    /** This function is used to restart average spectral matrices tasks.
1037
     *
1038
     * @return RTEMS directive status codes:
1039
     * - RTEMS_SUCCESSFUL - task restarted successfully
1040
     * - RTEMS_INVALID_ID - task id invalid
1041
     * - RTEMS_INCORRECT_STATE - task never started
1042
     * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
1043
     *
1044
     * ASM tasks are AVF0, PRC0, AVF1, PRC1, AVF2 and PRC2
1045
     *
1046
     */
1047
1048
    rtems_status_code status[NB_ASM_TASKS];
1049
    rtems_status_code ret;
1050
1051
438
    ret = RTEMS_SUCCESSFUL;
1052
1053
438
    status[STATUS_0] = rtems_task_restart( Task_id[TASKID_AVF0], lfrRequestedMode );
1054
438
    if (status[STATUS_0] != RTEMS_SUCCESSFUL)
1055
    {
1056
        PRINTF1("in restart_science_task *** AVF0 ERR %d\n", status[STATUS_0])
1057
    }
1058
1059
438
    status[STATUS_1] = rtems_task_restart( Task_id[TASKID_PRC0], lfrRequestedMode );
1060
438
    if (status[STATUS_1] != RTEMS_SUCCESSFUL)
1061
    {
1062
        PRINTF1("in restart_science_task *** PRC0 ERR %d\n", status[STATUS_1])
1063
    }
1064
1065
438
    status[STATUS_2] = rtems_task_restart( Task_id[TASKID_AVF1], lfrRequestedMode );
1066
438
    if (status[STATUS_2] != RTEMS_SUCCESSFUL)
1067
    {
1068
        PRINTF1("in restart_science_task *** AVF1 ERR %d\n", status[STATUS_2])
1069
    }
1070
1071
438
    status[STATUS_3] = rtems_task_restart( Task_id[TASKID_PRC1],lfrRequestedMode );
1072
438
    if (status[STATUS_3] != RTEMS_SUCCESSFUL)
1073
    {
1074
        PRINTF1("in restart_science_task *** PRC1 ERR %d\n", status[STATUS_3])
1075
    }
1076
1077
438
    status[STATUS_4] = rtems_task_restart( Task_id[TASKID_AVF2], 1 );
1078
438
    if (status[STATUS_4] != RTEMS_SUCCESSFUL)
1079
    {
1080
        PRINTF1("in restart_science_task *** AVF2 ERR %d\n", status[STATUS_4])
1081
    }
1082
1083
438
    status[STATUS_5] = rtems_task_restart( Task_id[TASKID_PRC2], 1 );
1084
438
    if (status[STATUS_5] != RTEMS_SUCCESSFUL)
1085
    {
1086
        PRINTF1("in restart_science_task *** PRC2 ERR %d\n", status[STATUS_5])
1087
    }
1088
1089



2190
    if ( (status[STATUS_0] != RTEMS_SUCCESSFUL) || (status[STATUS_1] != RTEMS_SUCCESSFUL) ||
1090
876
         (status[STATUS_2] != RTEMS_SUCCESSFUL) || (status[STATUS_3] != RTEMS_SUCCESSFUL) ||
1091
876
         (status[STATUS_4] != RTEMS_SUCCESSFUL) || (status[STATUS_5] != RTEMS_SUCCESSFUL) )
1092
    {
1093
        ret = RTEMS_UNSATISFIED;
1094
    }
1095
1096
438
    return ret;
1097
}
1098
1099
1254
int suspend_science_tasks( void )
1100
{
1101
    /** This function suspends the science tasks.
1102
     *
1103
     * @return RTEMS directive status codes:
1104
     * - RTEMS_SUCCESSFUL - task restarted successfully
1105
     * - RTEMS_INVALID_ID - task id invalid
1106
     * - RTEMS_ALREADY_SUSPENDED - task already suspended
1107
     *
1108
     */
1109
1110
    rtems_status_code status;
1111
1112
    PRINTF("in suspend_science_tasks\n")
1113
1114
1254
            status = rtems_task_suspend( Task_id[TASKID_AVF0] );    // suspend AVF0
1115
1254
    if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1116
    {
1117
        PRINTF1("in suspend_science_task *** AVF0 ERR %d\n", status)
1118
    }
1119
    else
1120
    {
1121
1254
        status = RTEMS_SUCCESSFUL;
1122
    }
1123
1254
    if (status == RTEMS_SUCCESSFUL)        // suspend PRC0
1124
    {
1125
1254
        status = rtems_task_suspend( Task_id[TASKID_PRC0] );
1126
1254
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1127
        {
1128
            PRINTF1("in suspend_science_task *** PRC0 ERR %d\n", status)
1129
        }
1130
        else
1131
        {
1132
1254
            status = RTEMS_SUCCESSFUL;
1133
        }
1134
    }
1135
1254
    if (status == RTEMS_SUCCESSFUL)        // suspend AVF1
1136
    {
1137
1254
        status = rtems_task_suspend( Task_id[TASKID_AVF1] );
1138
1254
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1139
        {
1140
            PRINTF1("in suspend_science_task *** AVF1 ERR %d\n", status)
1141
        }
1142
        else
1143
        {
1144
1254
            status = RTEMS_SUCCESSFUL;
1145
        }
1146
    }
1147
1254
    if (status == RTEMS_SUCCESSFUL)        // suspend PRC1
1148
    {
1149
1254
        status = rtems_task_suspend( Task_id[TASKID_PRC1] );
1150
1254
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1151
        {
1152
            PRINTF1("in suspend_science_task *** PRC1 ERR %d\n", status)
1153
        }
1154
        else
1155
        {
1156
1254
            status = RTEMS_SUCCESSFUL;
1157
        }
1158
    }
1159
1254
    if (status == RTEMS_SUCCESSFUL)        // suspend AVF2
1160
    {
1161
1254
        status = rtems_task_suspend( Task_id[TASKID_AVF2] );
1162
1254
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1163
        {
1164
            PRINTF1("in suspend_science_task *** AVF2 ERR %d\n", status)
1165
        }
1166
        else
1167
        {
1168
1254
            status = RTEMS_SUCCESSFUL;
1169
        }
1170
    }
1171
1254
    if (status == RTEMS_SUCCESSFUL)        // suspend PRC2
1172
    {
1173
1254
        status = rtems_task_suspend( Task_id[TASKID_PRC2] );
1174
1254
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1175
        {
1176
            PRINTF1("in suspend_science_task *** PRC2 ERR %d\n", status)
1177
        }
1178
        else
1179
        {
1180
1254
            status = RTEMS_SUCCESSFUL;
1181
        }
1182
    }
1183
1254
    if (status == RTEMS_SUCCESSFUL)        // suspend WFRM
1184
    {
1185
1254
        status = rtems_task_suspend( Task_id[TASKID_WFRM] );
1186
1254
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1187
        {
1188
            PRINTF1("in suspend_science_task *** WFRM ERR %d\n", status)
1189
        }
1190
        else
1191
        {
1192
1254
            status = RTEMS_SUCCESSFUL;
1193
        }
1194
    }
1195
1254
    if (status == RTEMS_SUCCESSFUL)        // suspend CWF3
1196
    {
1197
1254
        status = rtems_task_suspend( Task_id[TASKID_CWF3] );
1198
1254
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1199
        {
1200
            PRINTF1("in suspend_science_task *** CWF3 ERR %d\n", status)
1201
        }
1202
        else
1203
        {
1204
1254
            status = RTEMS_SUCCESSFUL;
1205
        }
1206
    }
1207
1254
    if (status == RTEMS_SUCCESSFUL)        // suspend CWF2
1208
    {
1209
1254
        status = rtems_task_suspend( Task_id[TASKID_CWF2] );
1210
1254
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1211
        {
1212
            PRINTF1("in suspend_science_task *** CWF2 ERR %d\n", status)
1213
        }
1214
        else
1215
        {
1216
1254
            status = RTEMS_SUCCESSFUL;
1217
        }
1218
    }
1219
1254
    if (status == RTEMS_SUCCESSFUL)        // suspend CWF1
1220
    {
1221
1254
        status = rtems_task_suspend( Task_id[TASKID_CWF1] );
1222
1254
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1223
        {
1224
            PRINTF1("in suspend_science_task *** CWF1 ERR %d\n", status)
1225
        }
1226
        else
1227
        {
1228
1254
            status = RTEMS_SUCCESSFUL;
1229
        }
1230
    }
1231
1232
1254
    return status;
1233
}
1234
1235
438
int suspend_asm_tasks( void )
1236
{
1237
    /** This function suspends the science tasks.
1238
     *
1239
     * @return RTEMS directive status codes:
1240
     * - RTEMS_SUCCESSFUL - task restarted successfully
1241
     * - RTEMS_INVALID_ID - task id invalid
1242
     * - RTEMS_ALREADY_SUSPENDED - task already suspended
1243
     *
1244
     */
1245
1246
    rtems_status_code status;
1247
1248
    PRINTF("in suspend_science_tasks\n")
1249
1250
438
            status = rtems_task_suspend( Task_id[TASKID_AVF0] );    // suspend AVF0
1251
438
    if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1252
    {
1253
        PRINTF1("in suspend_science_task *** AVF0 ERR %d\n", status)
1254
    }
1255
    else
1256
    {
1257
438
        status = RTEMS_SUCCESSFUL;
1258
    }
1259
1260
438
    if (status == RTEMS_SUCCESSFUL)        // suspend PRC0
1261
    {
1262
438
        status = rtems_task_suspend( Task_id[TASKID_PRC0] );
1263
438
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1264
        {
1265
            PRINTF1("in suspend_science_task *** PRC0 ERR %d\n", status)
1266
        }
1267
        else
1268
        {
1269
438
            status = RTEMS_SUCCESSFUL;
1270
        }
1271
    }
1272
1273
438
    if (status == RTEMS_SUCCESSFUL)        // suspend AVF1
1274
    {
1275
438
        status = rtems_task_suspend( Task_id[TASKID_AVF1] );
1276
438
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1277
        {
1278
            PRINTF1("in suspend_science_task *** AVF1 ERR %d\n", status)
1279
        }
1280
        else
1281
        {
1282
438
            status = RTEMS_SUCCESSFUL;
1283
        }
1284
    }
1285
1286
438
    if (status == RTEMS_SUCCESSFUL)        // suspend PRC1
1287
    {
1288
438
        status = rtems_task_suspend( Task_id[TASKID_PRC1] );
1289
438
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1290
        {
1291
            PRINTF1("in suspend_science_task *** PRC1 ERR %d\n", status)
1292
        }
1293
        else
1294
        {
1295
438
            status = RTEMS_SUCCESSFUL;
1296
        }
1297
    }
1298
1299
438
    if (status == RTEMS_SUCCESSFUL)        // suspend AVF2
1300
    {
1301
438
        status = rtems_task_suspend( Task_id[TASKID_AVF2] );
1302
438
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1303
        {
1304
            PRINTF1("in suspend_science_task *** AVF2 ERR %d\n", status)
1305
        }
1306
        else
1307
        {
1308
438
            status = RTEMS_SUCCESSFUL;
1309
        }
1310
    }
1311
1312
438
    if (status == RTEMS_SUCCESSFUL)        // suspend PRC2
1313
    {
1314
438
        status = rtems_task_suspend( Task_id[TASKID_PRC2] );
1315
438
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1316
        {
1317
            PRINTF1("in suspend_science_task *** PRC2 ERR %d\n", status)
1318
        }
1319
        else
1320
        {
1321
438
            status = RTEMS_SUCCESSFUL;
1322
        }
1323
    }
1324
1325
438
    return status;
1326
}
1327
1328
1168
void launch_waveform_picker( unsigned char mode, unsigned int transitionCoarseTime )
1329
{
1330
1331
1168
    WFP_reset_current_ring_nodes();
1332
1333
1168
    reset_waveform_picker_regs();
1334
1335
1168
    set_wfp_burst_enable_register( mode );
1336
1337
1168
    LEON_Clear_interrupt( IRQ_WAVEFORM_PICKER );
1338
1168
    LEON_Unmask_interrupt( IRQ_WAVEFORM_PICKER );
1339
1340
1168
    if (transitionCoarseTime == 0)
1341
    {
1342
        // instant transition means transition on the next valid date
1343
        // this is mandatory to have a good snapshot period and a good correction of the snapshot period
1344
1089
        waveform_picker_regs->start_date = time_management_regs->coarse_time + 1;
1345
    }
1346
    else
1347
    {
1348
79
        waveform_picker_regs->start_date = transitionCoarseTime;
1349
    }
1350
1351
1168
    update_last_valid_transition_date(waveform_picker_regs->start_date);
1352
1353
1168
}
1354
1355
1606
void launch_spectral_matrix( void )
1356
{
1357
1606
    SM_reset_current_ring_nodes();
1358
1359
1606
    reset_spectral_matrix_regs();
1360
1361
1606
    reset_nb_sm();
1362
1363
1606
    set_sm_irq_onNewMatrix( 1 );
1364
1365
1606
    LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX );
1366
1606
    LEON_Unmask_interrupt( IRQ_SPECTRAL_MATRIX );
1367
1368
1606
}
1369
1370
4952
void set_sm_irq_onNewMatrix( unsigned char value )
1371
{
1372
4952
    if (value == 1)
1373
    {
1374
1606
        spectral_matrix_regs->config = spectral_matrix_regs->config | BIT_IRQ_ON_NEW_MATRIX;
1375
    }
1376
    else
1377
    {
1378
3346
        spectral_matrix_regs->config = spectral_matrix_regs->config & MASK_IRQ_ON_NEW_MATRIX;   // 1110
1379
    }
1380
4952
}
1381
1382
1693
void set_sm_irq_onError( unsigned char value )
1383
{
1384
1693
    if (value == 1)
1385
    {
1386
        spectral_matrix_regs->config = spectral_matrix_regs->config | BIT_IRQ_ON_ERROR;
1387
    }
1388
    else
1389
    {
1390
1693
        spectral_matrix_regs->config = spectral_matrix_regs->config & MASK_IRQ_ON_ERROR;   // 1101
1391
    }
1392
1693
}
1393
1394
//*****************************
1395
// CONFIGURE CALIBRATION SIGNAL
1396
87
void setCalibrationPrescaler( unsigned int prescaler )
1397
{
1398
    // prescaling of the master clock (25 MHz)
1399
    // master clock is divided by 2^prescaler
1400
87
    time_management_regs->calPrescaler = prescaler;
1401
87
}
1402
1403
87
void setCalibrationDivisor( unsigned int divisionFactor )
1404
{
1405
    // division of the prescaled clock by the division factor
1406
87
    time_management_regs->calDivisor = divisionFactor;
1407
87
}
1408
1409
87
void setCalibrationData( void )
1410
{
1411
    /** This function is used to store the values used to drive the DAC in order to generate the SCM calibration signal
1412
     *
1413
     * @param void
1414
     *
1415
     * @return void
1416
     *
1417
     */
1418
1419
    unsigned int k;
1420
    unsigned short data;
1421
    float val;
1422
    float Ts;
1423
1424
87
    time_management_regs->calDataPtr = INIT_CHAR;
1425
1426
87
    Ts = 1 / CAL_FS;
1427
1428
    // build the signal for the SCM calibration
1429
22359
    for (k = 0; k < CAL_NB_PTS; k++)
1430
    {
1431
44544
        val = CAL_A0 *  sin( CAL_W0 * k * Ts )
1432
22272
                        + CAL_A1 * sin(  CAL_W1 * k * Ts );
1433
22272
        data = (unsigned short) ((val * CAL_SCALE_FACTOR) + CONST_2048);
1434
22272
        time_management_regs->calData = data & CAL_DATA_MASK;
1435
    }
1436
87
}
1437
1438
#ifdef ENABLE_DEAD_CODE
1439
void setCalibrationDataInterleaved( void )
1440
{
1441
    /** This function is used to store the values used to drive the DAC in order to generate the SCM calibration signal
1442
     *
1443
     * @param void
1444
     *
1445
     * @return void
1446
     *
1447
     * In interleaved mode, one can store more values than in normal mode.
1448
     * The data are stored in bunch of 18 bits, 12 bits from one sample and 6 bits from another sample.
1449
     * T store 3 values, one need two write operations.
1450
     * s1 [ b11 b10 b9 b8 b7 b6 ] s0 [ b11 b10 b9 b8 b7 b6 b5 b3 b2 b1 b0 ]
1451
     * s1 [ b5  b4  b3 b2 b1 b0 ] s2 [ b11 b10 b9 b8 b7 b6 b5 b3 b2 b1 b0 ]
1452
     *
1453
     */
1454
1455
    unsigned int k;
1456
    float val;
1457
    float Ts;
1458
    unsigned short data[CAL_NB_PTS_INTER];
1459
    unsigned char *dataPtr;
1460
1461
    Ts = 1 / CAL_FS_INTER;
1462
1463
    time_management_regs->calDataPtr = INIT_CHAR;
1464
1465
    // build the signal for the SCM calibration
1466
    for (k=0; k<CAL_NB_PTS_INTER; k++)
1467
    {
1468
        val = sin( 2 * pi * CAL_F0 * k * Ts )
1469
                + sin(  2 * pi * CAL_F1 * k * Ts );
1470
        data[k] = (unsigned short) ((val * CONST_512) + CONST_2048);
1471
    }
1472
1473
    // write the signal in interleaved mode
1474
    for (k=0; k < STEPS_FOR_STORAGE_INTER; k++)
1475
    {
1476
        dataPtr = (unsigned char*) &data[ (k * BYTES_FOR_2_SAMPLES) + 2 ];
1477
        time_management_regs->calData = ( data[ k * BYTES_FOR_2_SAMPLES ]     & CAL_DATA_MASK )
1478
                + ( (dataPtr[0] & CAL_DATA_MASK_INTER) << CAL_DATA_SHIFT_INTER);
1479
        time_management_regs->calData = ( data[(k * BYTES_FOR_2_SAMPLES) + 1] & CAL_DATA_MASK )
1480
                + ( (dataPtr[1] & CAL_DATA_MASK_INTER) << CAL_DATA_SHIFT_INTER);
1481
    }
1482
}
1483
#endif
1484
1485
2451
void setCalibrationReload( bool state)
1486
{
1487
2451
    if (state == true)
1488
    {
1489
1269
        time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | BIT_CAL_RELOAD;   // [0001 0000]
1490
    }
1491
    else
1492
    {
1493
1182
        time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & MASK_CAL_RELOAD;   // [1110 1111]
1494
    }
1495
2451
}
1496
1497
2451
void setCalibrationEnable( bool state )
1498
{
1499
    // this bit drives the multiplexer
1500
2451
    if (state == true)
1501
    {
1502
1182
        time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | BIT_CAL_ENABLE;   // [0100 0000]
1503
    }
1504
    else
1505
    {
1506
1269
        time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & MASK_CAL_ENABLE; // [1011 1111]
1507
    }
1508
2451
}
1509
1510
#ifdef ENABLE_DEAD_CODE
1511
void setCalibrationInterleaved( bool state )
1512
{
1513
    // this bit drives the multiplexer
1514
    if (state == true)
1515
    {
1516
        time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | BIT_SET_INTERLEAVED;   // [0010 0000]
1517
    }
1518
    else
1519
    {
1520
        time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & MASK_SET_INTERLEAVED; // [1101 1111]
1521
    }
1522
}
1523
#endif
1524
1525
2451
void setCalibration( bool state )
1526
{
1527
2451
    if (state == true)
1528
    {
1529
1182
        setCalibrationEnable( true );
1530
1182
        setCalibrationReload( false );
1531
1182
        set_hk_lfr_calib_enable( true );
1532
    }
1533
    else
1534
    {
1535
1269
        setCalibrationEnable( false );
1536
1269
        setCalibrationReload( true );
1537
1269
        set_hk_lfr_calib_enable( false );
1538
    }
1539
2451
}
1540
1541
87
void configureCalibration( bool interleaved )
1542
{
1543
87
    setCalibration( false );
1544
#ifdef ENABLE_DEAD_CODE
1545
    if ( interleaved == true )
1546
    {
1547
        setCalibrationInterleaved( true );
1548
        setCalibrationPrescaler( 0 );                   // 25 MHz   => 25 000 000
1549
        setCalibrationDivisor( CAL_F_DIVISOR_INTER );   //          => 240 384
1550
        setCalibrationDataInterleaved();
1551
    }
1552
    else
1553
#endif
1554
    {
1555
87
        setCalibrationPrescaler( 0 );           // 25 MHz   => 25 000 000
1556
87
        setCalibrationDivisor( CAL_F_DIVISOR ); //          => 160 256 (39 - 1)
1557
87
        setCalibrationData();
1558
    }
1559
87
}
1560
1561
//****************
1562
// CLOSING ACTIONS
1563
17617
void update_last_TC_exe( ccsdsTelecommandPacket_t *TC, unsigned char * time )
1564
{
1565
    /** This function is used to update the HK packets statistics after a successful TC execution.
1566
     *
1567
     * @param TC points to the TC being processed
1568
     * @param time is the time used to date the TC execution
1569
     *
1570
     */
1571
1572
    unsigned int val;
1573
1574
17617
    housekeeping_packet.hk_lfr_last_exe_tc_id[0] = TC->packetID[0];
1575
17617
    housekeeping_packet.hk_lfr_last_exe_tc_id[1] = TC->packetID[1];
1576
17617
    housekeeping_packet.hk_lfr_last_exe_tc_type[0] = INIT_CHAR;
1577
17617
    housekeeping_packet.hk_lfr_last_exe_tc_type[1] = TC->serviceType;
1578
17617
    housekeeping_packet.hk_lfr_last_exe_tc_subtype[0] = INIT_CHAR;
1579
17617
    housekeeping_packet.hk_lfr_last_exe_tc_subtype[1] = TC->serviceSubType;
1580
17617
    housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_0] = time[BYTE_0];
1581
17617
    housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_1] = time[BYTE_1];
1582
17617
    housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_2] = time[BYTE_2];
1583
17617
    housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_3] = time[BYTE_3];
1584
17617
    housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_4] = time[BYTE_4];
1585
17617
    housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_5] = time[BYTE_5];
1586
1587
17617
    val = (housekeeping_packet.hk_lfr_exe_tc_cnt[0] * CONST_256) + housekeeping_packet.hk_lfr_exe_tc_cnt[1];
1588
17617
    val++;
1589
17617
    housekeeping_packet.hk_lfr_exe_tc_cnt[0] = (unsigned char) (val >> SHIFT_1_BYTE);
1590
17617
    housekeeping_packet.hk_lfr_exe_tc_cnt[1] = (unsigned char) (val);
1591
17617
}
1592
1593
21148
void update_last_TC_rej(ccsdsTelecommandPacket_t *TC, unsigned char * time )
1594
{
1595
    /** This function is used to update the HK packets statistics after a TC rejection.
1596
     *
1597
     * @param TC points to the TC being processed
1598
     * @param time is the time used to date the TC rejection
1599
     *
1600
     */
1601
1602
    unsigned int val;
1603
1604
21148
    housekeeping_packet.hk_lfr_last_rej_tc_id[0] = TC->packetID[0];
1605
21148
    housekeeping_packet.hk_lfr_last_rej_tc_id[1] = TC->packetID[1];
1606
21148
    housekeeping_packet.hk_lfr_last_rej_tc_type[0] = INIT_CHAR;
1607
21148
    housekeeping_packet.hk_lfr_last_rej_tc_type[1] = TC->serviceType;
1608
21148
    housekeeping_packet.hk_lfr_last_rej_tc_subtype[0] = INIT_CHAR;
1609
21148
    housekeeping_packet.hk_lfr_last_rej_tc_subtype[1] = TC->serviceSubType;
1610
21148
    housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_0] = time[BYTE_0];
1611
21148
    housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_1] = time[BYTE_1];
1612
21148
    housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_2] = time[BYTE_2];
1613
21148
    housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_3] = time[BYTE_3];
1614
21148
    housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_4] = time[BYTE_4];
1615
21148
    housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_5] = time[BYTE_5];
1616
1617
21148
    val = (housekeeping_packet.hk_lfr_rej_tc_cnt[0] * CONST_256) + housekeeping_packet.hk_lfr_rej_tc_cnt[1];
1618
21148
    val++;
1619
21148
    housekeeping_packet.hk_lfr_rej_tc_cnt[0] = (unsigned char) (val >> SHIFT_1_BYTE);
1620
21148
    housekeeping_packet.hk_lfr_rej_tc_cnt[1] = (unsigned char) (val);
1621
21148
}
1622
1623
29716
void close_action(ccsdsTelecommandPacket_t *TC, int result, rtems_id queue_id )
1624
{
1625
    /** This function is the last step of the TC execution workflow.
1626
     *
1627
     * @param TC points to the TC being processed
1628
     * @param result is the result of the TC execution (LFR_SUCCESSFUL / LFR_DEFAULT)
1629
     * @param queue_id is the id of the RTEMS message queue used to send TM packets
1630
     * @param time is the time used to date the TC execution
1631
     *
1632
     */
1633
1634
    unsigned char requestedMode;
1635
1636
29716
    if (result == LFR_SUCCESSFUL)
1637
    {
1638
41618
        if ( !( (TC->serviceType==TC_TYPE_TIME) & (TC->serviceSubType==TC_SUBTYPE_UPDT_TIME) )
1639
             &
1640
20809
             !( (TC->serviceType==TC_TYPE_GEN) & (TC->serviceSubType==TC_SUBTYPE_UPDT_INFO))
1641
             )
1642
        {
1643
17617
            send_tm_lfr_tc_exe_success( TC, queue_id );
1644
        }
1645
20809
        if ( (TC->serviceType == TC_TYPE_GEN) & (TC->serviceSubType == TC_SUBTYPE_ENTER) )
1646
        {
1647
            //**********************************
1648
            // UPDATE THE LFRMODE LOCAL VARIABLE
1649
2060
            requestedMode = TC->dataAndCRC[1];
1650
2060
            updateLFRCurrentMode( requestedMode );
1651
        }
1652
    }
1653
8907
    else if (result == LFR_EXE_ERROR)
1654
    {
1655
        send_tm_lfr_tc_exe_error( TC, queue_id );
1656
    }
1657
29716
}
1658
1659
//****************
1660
// OTHER FUNCTIONS
1661
2152
void updateLFRCurrentMode( unsigned char requestedMode )
1662
{
1663
    /** This function updates the value of the global variable lfrCurrentMode.
1664
     *
1665
     * lfrCurrentMode is a parameter used by several functions to know in which mode LFR is running.
1666
     *
1667
     */
1668
1669
    // update the local value of lfrCurrentMode with the value contained in the housekeeping_packet structure
1670
2152
    housekeeping_packet.lfr_status_word[0] = (housekeeping_packet.lfr_status_word[0] & STATUS_WORD_LFR_MODE_MASK)
1671
            + (unsigned char) ( requestedMode << STATUS_WORD_LFR_MODE_SHIFT );
1672
2152
    lfrCurrentMode = requestedMode;
1673
2152
}
1674
1675
2604
void set_lfr_soft_reset( unsigned char value )
1676
{
1677
2604
    if (value == 1)
1678
    {
1679
1302
        time_management_regs->ctrl = time_management_regs->ctrl | BIT_SOFT_RESET; // [0100]
1680
    }
1681
    else
1682
    {
1683
1302
        time_management_regs->ctrl = time_management_regs->ctrl & MASK_SOFT_RESET; // [1011]
1684
    }
1685
2604
}
1686
1687
1302
void reset_lfr( void )
1688
{
1689
1302
    set_lfr_soft_reset( 1 );
1690
1691
1302
    set_lfr_soft_reset( 0 );
1692
1693
1302
    set_hk_lfr_sc_potential_flag( true );
1694
1302
}