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