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