##// END OF EJS Templates
2.0.2.1
paul -
r185:193b5419a0cb VHDL_0_1_28
parent child
Show More
@@ -1,2 +1,2
1 1 a586fe639ac179e95bdc150ebdbab0312f31dc30 LFR_basic-parameters
2 b984c315bf99562bdfbbd6bda8de296d2e692adc header/lfr_common_headers
2 6d02d4b02291d2b25c387fa74037dc7929cd92b5 header/lfr_common_headers
@@ -1,48 +1,48
1 1 #ifndef FSW_MISC_H_INCLUDED
2 2 #define FSW_MISC_H_INCLUDED
3 3
4 4 #include <rtems.h>
5 5 #include <stdio.h>
6 6 #include <grspw.h>
7 7 #include <grlib_regs.h>
8 8
9 9 #include "fsw_params.h"
10 10 #include "fsw_spacewire.h"
11 11 #include "lfr_cpu_usage_report.h"
12 12
13 13 rtems_name name_hk_rate_monotonic; // name of the HK rate monotonic
14 14 rtems_id HK_id; // id of the HK rate monotonic period
15 15
16 16 void configure_timer(gptimer_regs_t *gptimer_regs, unsigned char timer, unsigned int clock_divider,
17 17 unsigned char interrupt_level, rtems_isr (*timer_isr)() );
18 18 void timer_start( gptimer_regs_t *gptimer_regs, unsigned char timer );
19 19 void timer_stop( gptimer_regs_t *gptimer_regs, unsigned char timer );
20 20 void timer_set_clock_divider(gptimer_regs_t *gptimer_regs, unsigned char timer, unsigned int clock_divider);
21 21
22 22 // SERIAL LINK
23 23 int send_console_outputs_on_apbuart_port( void );
24 24 int enable_apbuart_transmitter( void );
25 25 void set_apbuart_scaler_reload_register(unsigned int regs, unsigned int value);
26 26
27 27 // RTEMS TASKS
28 28 rtems_task stat_task( rtems_task_argument argument );
29 29 rtems_task hous_task( rtems_task_argument argument );
30 30 rtems_task dumb_task( rtems_task_argument unused );
31 31
32 32 void init_housekeeping_parameters( void );
33 33 void increment_seq_counter(unsigned short *packetSequenceControl);
34 34 void getTime( unsigned char *time);
35 35 unsigned long long int getTimeAsUnsignedLongLongInt( );
36 36 void send_dumb_hk( void );
37 void get_temperatures( unsigned char *temperatures );
37 38 void get_v_e1_e2_f3( unsigned char *spacecraft_potential );
38 void get_temperatures( unsigned char *temperatures );
39 39 void get_cpu_load( unsigned char *resource_statistics );
40 40
41 41 extern int sched_yield( void );
42 42 extern void rtems_cpu_usage_reset();
43 43 extern ring_node *current_ring_node_f3;
44 44 extern ring_node *ring_node_to_send_cwf_f3;
45 45 extern ring_node waveform_ring_f3[];
46 46 extern unsigned short sequenceCounterHK;
47 47
48 48 #endif // FSW_MISC_H_INCLUDED
@@ -1,321 +1,309
1 1 #ifndef FSW_PROCESSING_H_INCLUDED
2 2 #define FSW_PROCESSING_H_INCLUDED
3 3
4 4 #include <rtems.h>
5 5 #include <grspw.h>
6 6 #include <math.h>
7 7 #include <stdlib.h> // abs() is in the stdlib
8 8 #include <stdio.h> // printf()
9 9 #include <math.h>
10 10 #include <grlib_regs.h>
11 11
12 12 #include "fsw_params.h"
13 13 #include "fsw_spacewire.h"
14 14
15 15 typedef struct ring_node_asm
16 16 {
17 17 struct ring_node_asm *next;
18 18 float matrix[ TOTAL_SIZE_SM ];
19 19 unsigned int status;
20 20 } ring_node_asm;
21 21
22 22 typedef struct
23 23 {
24 24 unsigned char targetLogicalAddress;
25 25 unsigned char protocolIdentifier;
26 26 unsigned char reserved;
27 27 unsigned char userApplication;
28 28 unsigned char packetID[2];
29 29 unsigned char packetSequenceControl[2];
30 30 unsigned char packetLength[2];
31 31 // DATA FIELD HEADER
32 32 unsigned char spare1_pusVersion_spare2;
33 33 unsigned char serviceType;
34 34 unsigned char serviceSubType;
35 35 unsigned char destinationID;
36 36 unsigned char time[6];
37 37 // AUXILIARY HEADER
38 38 unsigned char sid;
39 39 unsigned char biaStatusInfo;
40 40 unsigned char acquisitionTime[6];
41 41 unsigned char pa_lfr_bp_blk_nr[2];
42 42 // SOURCE DATA
43 43 unsigned char data[ 780 ]; // MAX size is 26 bins * 30 Bytes [TM_LFR_SCIENCE_BURST_BP2_F1]
44 44 } bp_packet;
45 45
46 46 typedef struct
47 47 {
48 48 unsigned char targetLogicalAddress;
49 49 unsigned char protocolIdentifier;
50 50 unsigned char reserved;
51 51 unsigned char userApplication;
52 52 unsigned char packetID[2];
53 53 unsigned char packetSequenceControl[2];
54 54 unsigned char packetLength[2];
55 55 // DATA FIELD HEADER
56 56 unsigned char spare1_pusVersion_spare2;
57 57 unsigned char serviceType;
58 58 unsigned char serviceSubType;
59 59 unsigned char destinationID;
60 60 unsigned char time[6];
61 61 // AUXILIARY HEADER
62 62 unsigned char sid;
63 63 unsigned char biaStatusInfo;
64 64 unsigned char acquisitionTime[6];
65 65 unsigned char source_data_spare;
66 66 unsigned char pa_lfr_bp_blk_nr[2];
67 67 // SOURCE DATA
68 68 unsigned char data[ 117 ]; // 13 bins * 9 Bytes only for TM_LFR_SCIENCE_NORMAL_BP1_F0 and F1
69 69 } bp_packet_with_spare;
70 70
71 71 typedef struct
72 72 {
73 73 ring_node_asm *norm;
74 74 ring_node_asm *burst_sbm;
75 75 rtems_event_set event;
76 76 unsigned int coarseTimeNORM;
77 77 unsigned int fineTimeNORM;
78 78 unsigned int coarseTimeSBM;
79 79 unsigned int fineTimeSBM;
80 80 } asm_msg;
81 81
82 82 extern volatile int sm_f0[ ];
83 83 extern volatile int sm_f1[ ];
84 84 extern volatile int sm_f2[ ];
85 85
86 86 // parameters
87 87 extern struct param_local_str param_local;
88 88
89 89 // registers
90 90 extern time_management_regs_t *time_management_regs;
91 91 extern volatile spectral_matrix_regs_t *spectral_matrix_regs;
92 92
93 93 extern rtems_name misc_name[5];
94 94 extern rtems_id Task_id[20]; /* array of task ids */
95 95
96 96 //
97 97 ring_node * getRingNodeForAveraging( unsigned char frequencyChannel);
98 98 // ISR
99 99 rtems_isr spectral_matrices_isr( rtems_vector_number vector );
100 100 rtems_isr spectral_matrices_isr_simu( rtems_vector_number vector );
101 101
102 102 //******************
103 103 // Spectral Matrices
104 104 void reset_nb_sm( void );
105 105 // SM
106 106 void SM_init_rings( void );
107 107 void SM_reset_current_ring_nodes( void );
108 108 // ASM
109 109 void ASM_generic_init_ring(ring_node_asm *ring, unsigned char nbNodes );
110 110
111 111 //*****************
112 112 // Basic Parameters
113 113
114 114 void BP_reset_current_ring_nodes( void );
115 115 void BP_init_header(bp_packet *packet,
116 116 unsigned int apid, unsigned char sid,
117 117 unsigned int packetLength , unsigned char blkNr);
118 118 void BP_init_header_with_spare(bp_packet_with_spare *packet,
119 119 unsigned int apid, unsigned char sid,
120 120 unsigned int packetLength, unsigned char blkNr );
121 121 void BP_send( char *data,
122 122 rtems_id queue_id ,
123 123 unsigned int nbBytesToSend , unsigned int sid );
124 124
125 125 //******************
126 126 // general functions
127 127 void reset_sm_status( void );
128 128 void reset_spectral_matrix_regs( void );
129 129 void set_time(unsigned char *time, unsigned char *timeInBuffer );
130 130 unsigned long long int get_acquisition_time( unsigned char *timePtr );
131 131 unsigned char getSID( rtems_event_set event );
132 132
133 133 extern rtems_status_code get_message_queue_id_prc1( rtems_id *queue_id );
134 134 extern rtems_status_code get_message_queue_id_prc2( rtems_id *queue_id );
135 135
136 136 //***************************************
137 137 // DEFINITIONS OF STATIC INLINE FUNCTIONS
138 138 static inline void SM_average(float *averaged_spec_mat_NORM, float *averaged_spec_mat_SBM,
139 139 ring_node *ring_node_tab[],
140 140 unsigned int nbAverageNORM, unsigned int nbAverageSBM,
141 141 asm_msg *msgForMATR );
142 142 static inline void SM_average_debug( float *averaged_spec_mat_NORM, float *averaged_spec_mat_SBM,
143 143 ring_node *ring_node_tab[],
144 unsigned int nbAverageNORM, unsigned int nbAverageSBM );
144 unsigned int nbAverageNORM, unsigned int nbAverageSBM,
145 asm_msg *msgForMATR );
145 146
146 147 void ASM_patch( float *inputASM, float *outputASM );
147 148 void extractReImVectors(float *inputASM, float *outputASM, unsigned int asmComponent );
148 149
149 150 static inline void ASM_reorganize_and_divide(float *averaged_spec_mat, float *averaged_spec_mat_reorganized,
150 151 float divider );
151 152 static inline void ASM_compress_reorganize_and_divide(float *averaged_spec_mat, float *compressed_spec_mat,
152 153 float divider,
153 154 unsigned char nbBinsCompressedMatrix, unsigned char nbBinsToAverage , unsigned char ASMIndexStart);
154 155 static inline void ASM_convert(volatile float *input_matrix, char *output_matrix);
155 156
156 157 void SM_average( float *averaged_spec_mat_NORM, float *averaged_spec_mat_SBM,
157 158 ring_node *ring_node_tab[],
158 159 unsigned int nbAverageNORM, unsigned int nbAverageSBM,
159 160 asm_msg *msgForMATR )
160 161 {
161 162 float sum;
162 163 unsigned int i;
163 164
164 165 for(i=0; i<TOTAL_SIZE_SM; i++)
165 166 {
166 167 sum = ( (int *) (ring_node_tab[0]->buffer_address) ) [ i ]
167 168 + ( (int *) (ring_node_tab[1]->buffer_address) ) [ i ]
168 169 + ( (int *) (ring_node_tab[2]->buffer_address) ) [ i ]
169 170 + ( (int *) (ring_node_tab[3]->buffer_address) ) [ i ]
170 171 + ( (int *) (ring_node_tab[4]->buffer_address) ) [ i ]
171 172 + ( (int *) (ring_node_tab[5]->buffer_address) ) [ i ]
172 173 + ( (int *) (ring_node_tab[6]->buffer_address) ) [ i ]
173 174 + ( (int *) (ring_node_tab[7]->buffer_address) ) [ i ];
174 175
175 176 if ( (nbAverageNORM == 0) && (nbAverageSBM == 0) )
176 177 {
177 178 averaged_spec_mat_NORM[ i ] = sum;
178 179 averaged_spec_mat_SBM[ i ] = sum;
179 180 msgForMATR->coarseTimeNORM = ring_node_tab[0]->coarseTime;
180 181 msgForMATR->fineTimeNORM = ring_node_tab[0]->fineTime;
181 182 msgForMATR->coarseTimeSBM = ring_node_tab[0]->coarseTime;
182 183 msgForMATR->fineTimeSBM = ring_node_tab[0]->fineTime;
183 184 }
184 185 else if ( (nbAverageNORM != 0) && (nbAverageSBM != 0) )
185 186 {
186 187 averaged_spec_mat_NORM[ i ] = ( averaged_spec_mat_NORM[ i ] + sum );
187 188 averaged_spec_mat_SBM[ i ] = ( averaged_spec_mat_SBM[ i ] + sum );
188 189 }
189 190 else if ( (nbAverageNORM != 0) && (nbAverageSBM == 0) )
190 191 {
191 192 averaged_spec_mat_NORM[ i ] = ( averaged_spec_mat_NORM[ i ] + sum );
192 193 averaged_spec_mat_SBM[ i ] = sum;
193 194 msgForMATR->coarseTimeSBM = ring_node_tab[0]->coarseTime;
194 195 msgForMATR->fineTimeSBM = ring_node_tab[0]->fineTime;
195 196 }
196 197 else
197 198 {
198 199 PRINTF2("ERR *** in SM_average *** unexpected parameters %d %d\n", nbAverageNORM, nbAverageSBM)
199 200 }
200 201 }
201 202 }
202 203
203 204 void SM_average_debug( float *averaged_spec_mat_NORM, float *averaged_spec_mat_SBM,
204 205 ring_node *ring_node_tab[],
205 unsigned int nbAverageNORM, unsigned int nbAverageSBM )
206 unsigned int nbAverageNORM, unsigned int nbAverageSBM,
207 asm_msg *msgForMATR )
206 208 {
207 209 float sum;
208 210 unsigned int i;
209 211
210 212 for(i=0; i<TOTAL_SIZE_SM; i++)
211 213 {
212 214 sum = ( (int *) (ring_node_tab[0]->buffer_address) ) [ i ];
213
214 if ( (nbAverageNORM == 0) && (nbAverageSBM == 0) )
215 {
216 averaged_spec_mat_NORM[ i ] = sum;
217 averaged_spec_mat_SBM[ i ] = sum;
218 }
219 else if ( (nbAverageNORM != 0) && (nbAverageSBM != 0) )
220 {
221 215 averaged_spec_mat_NORM[ i ] = sum;
222 216 averaged_spec_mat_SBM[ i ] = sum;
223 }
224 else if ( (nbAverageNORM != 0) && (nbAverageSBM == 0) )
225 {
226 averaged_spec_mat_NORM[ i ] = sum;
227 averaged_spec_mat_SBM[ i ] = sum;
228 }
229 else
230 {
231 PRINTF2("ERR *** in SM_average *** unexpected parameters %d %d\n", nbAverageNORM, nbAverageSBM)
232 }
217 msgForMATR->coarseTimeNORM = ring_node_tab[0]->coarseTime;
218 msgForMATR->fineTimeNORM = ring_node_tab[0]->fineTime;
219 msgForMATR->coarseTimeSBM = ring_node_tab[0]->coarseTime;
220 msgForMATR->fineTimeSBM = ring_node_tab[0]->fineTime;
233 221 }
234 222 }
235 223
236 224 void ASM_reorganize_and_divide( float *averaged_spec_mat, float *averaged_spec_mat_reorganized, float divider )
237 225 {
238 226 int frequencyBin;
239 227 int asmComponent;
240 228 unsigned int offsetASM;
241 229 unsigned int offsetASMReorganized;
242 230
243 231 // BUILD DATA
244 232 for (asmComponent = 0; asmComponent < NB_VALUES_PER_SM; asmComponent++)
245 233 {
246 234 for( frequencyBin = 0; frequencyBin < NB_BINS_PER_SM; frequencyBin++ )
247 235 {
248 236 offsetASMReorganized =
249 237 frequencyBin * NB_VALUES_PER_SM
250 238 + asmComponent;
251 239 offsetASM =
252 240 asmComponent * NB_BINS_PER_SM
253 241 + frequencyBin;
254 242 averaged_spec_mat_reorganized[offsetASMReorganized ] =
255 243 averaged_spec_mat[ offsetASM ] / divider;
256 244 }
257 245 }
258 246 }
259 247
260 248 void ASM_compress_reorganize_and_divide(float *averaged_spec_mat, float *compressed_spec_mat , float divider,
261 249 unsigned char nbBinsCompressedMatrix, unsigned char nbBinsToAverage, unsigned char ASMIndexStart )
262 250 {
263 251 int frequencyBin;
264 252 int asmComponent;
265 253 int offsetASM;
266 254 int offsetCompressed;
267 255 int k;
268 256
269 257 // BUILD DATA
270 258 for (asmComponent = 0; asmComponent < NB_VALUES_PER_SM; asmComponent++)
271 259 {
272 260 for( frequencyBin = 0; frequencyBin < nbBinsCompressedMatrix; frequencyBin++ )
273 261 {
274 262 offsetCompressed = // NO TIME OFFSET
275 263 frequencyBin * NB_VALUES_PER_SM
276 264 + asmComponent;
277 265 offsetASM = // NO TIME OFFSET
278 266 asmComponent * NB_BINS_PER_SM
279 267 + ASMIndexStart
280 268 + frequencyBin * nbBinsToAverage;
281 269 compressed_spec_mat[ offsetCompressed ] = 0;
282 270 for ( k = 0; k < nbBinsToAverage; k++ )
283 271 {
284 272 compressed_spec_mat[offsetCompressed ] =
285 273 ( compressed_spec_mat[ offsetCompressed ]
286 274 + averaged_spec_mat[ offsetASM + k ] );
287 275 }
288 276 compressed_spec_mat[ offsetCompressed ] =
289 277 compressed_spec_mat[ offsetCompressed ] / (divider * nbBinsToAverage);
290 278 }
291 279 }
292 280 }
293 281
294 282 void ASM_convert( volatile float *input_matrix, char *output_matrix)
295 283 {
296 284 unsigned int frequencyBin;
297 285 unsigned int asmComponent;
298 286 char * pt_char_input;
299 287 char * pt_char_output;
300 288 unsigned int offsetInput;
301 289 unsigned int offsetOutput;
302 290
303 291 pt_char_input = (char*) &input_matrix;
304 292 pt_char_output = (char*) &output_matrix;
305 293
306 294 // convert all other data
307 295 for( frequencyBin=0; frequencyBin<NB_BINS_PER_SM; frequencyBin++)
308 296 {
309 297 for ( asmComponent=0; asmComponent<NB_VALUES_PER_SM; asmComponent++)
310 298 {
311 299 offsetInput = (frequencyBin*NB_VALUES_PER_SM) + asmComponent ;
312 300 offsetOutput = 2 * ( (frequencyBin*NB_VALUES_PER_SM) + asmComponent ) ;
313 301 pt_char_input = (char*) &input_matrix [ offsetInput ];
314 302 pt_char_output = (char*) &output_matrix[ offsetOutput ];
315 303 pt_char_output[0] = pt_char_input[0]; // bits 31 downto 24 of the float
316 304 pt_char_output[1] = pt_char_input[1]; // bits 23 downto 16 of the float
317 305 }
318 306 }
319 307 }
320 308
321 309 #endif // FSW_PROCESSING_H_INCLUDED
@@ -1,506 +1,506
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 configure_timer(gptimer_regs_t *gptimer_regs, 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( gptimer_regs, timer, clock_divider);
37 37 }
38 38
39 39 void timer_start(gptimer_regs_t *gptimer_regs, 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(gptimer_regs_t *gptimer_regs, 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(gptimer_regs_t *gptimer_regs, 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 int send_console_outputs_on_apbuart_port( void ) // Send the console outputs on the apbuart port
83 83 {
84 84 struct apbuart_regs_str *apbuart_regs = (struct apbuart_regs_str *) REGS_ADDR_APBUART;
85 85
86 86 apbuart_regs->ctrl = APBUART_CTRL_REG_MASK_TE;
87 87
88 88 return 0;
89 89 }
90 90
91 91 int enable_apbuart_transmitter( void ) // set the bit 1, TE Transmitter Enable to 1 in the APBUART control register
92 92 {
93 93 struct apbuart_regs_str *apbuart_regs = (struct apbuart_regs_str *) REGS_ADDR_APBUART;
94 94
95 95 apbuart_regs->ctrl = apbuart_regs->ctrl | APBUART_CTRL_REG_MASK_TE;
96 96
97 97 return 0;
98 98 }
99 99
100 100 void set_apbuart_scaler_reload_register(unsigned int regs, unsigned int value)
101 101 {
102 102 /** This function sets the scaler reload register of the apbuart module
103 103 *
104 104 * @param regs is the address of the apbuart registers in memory
105 105 * @param value is the value that will be stored in the scaler register
106 106 *
107 107 * The value shall be set by the software to get data on the serial interface.
108 108 *
109 109 */
110 110
111 111 struct apbuart_regs_str *apbuart_regs = (struct apbuart_regs_str *) regs;
112 112
113 113 apbuart_regs->scaler = value;
114 114 BOOT_PRINTF1("OK *** apbuart port scaler reload register set to 0x%x\n", value)
115 115 }
116 116
117 117 //************
118 118 // RTEMS TASKS
119 119
120 120 rtems_task stat_task(rtems_task_argument argument)
121 121 {
122 122 int i;
123 123 int j;
124 124 i = 0;
125 125 j = 0;
126 126 BOOT_PRINTF("in STAT *** \n")
127 127 while(1){
128 128 rtems_task_wake_after(1000);
129 129 PRINTF1("%d\n", j)
130 130 if (i == CPU_USAGE_REPORT_PERIOD) {
131 131 // #ifdef PRINT_TASK_STATISTICS
132 132 // rtems_cpu_usage_report();
133 133 // rtems_cpu_usage_reset();
134 134 // #endif
135 135 i = 0;
136 136 }
137 137 else i++;
138 138 j++;
139 139 }
140 140 }
141 141
142 142 rtems_task hous_task(rtems_task_argument argument)
143 143 {
144 144 rtems_status_code status;
145 145 rtems_status_code spare_status;
146 146 rtems_id queue_id;
147 147 rtems_rate_monotonic_period_status period_status;
148 148
149 149 status = get_message_queue_id_send( &queue_id );
150 150 if (status != RTEMS_SUCCESSFUL)
151 151 {
152 152 PRINTF1("in HOUS *** ERR get_message_queue_id_send %d\n", status)
153 153 }
154 154
155 155 BOOT_PRINTF("in HOUS ***\n")
156 156
157 157 if (rtems_rate_monotonic_ident( name_hk_rate_monotonic, &HK_id) != RTEMS_SUCCESSFUL) {
158 158 status = rtems_rate_monotonic_create( name_hk_rate_monotonic, &HK_id );
159 159 if( status != RTEMS_SUCCESSFUL ) {
160 160 PRINTF1( "rtems_rate_monotonic_create failed with status of %d\n", status )
161 161 }
162 162 }
163 163
164 164 housekeeping_packet.targetLogicalAddress = CCSDS_DESTINATION_ID;
165 165 housekeeping_packet.protocolIdentifier = CCSDS_PROTOCOLE_ID;
166 166 housekeeping_packet.reserved = DEFAULT_RESERVED;
167 167 housekeeping_packet.userApplication = CCSDS_USER_APP;
168 168 housekeeping_packet.packetID[0] = (unsigned char) (APID_TM_HK >> 8);
169 169 housekeeping_packet.packetID[1] = (unsigned char) (APID_TM_HK);
170 170 housekeeping_packet.packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
171 171 housekeeping_packet.packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
172 172 housekeeping_packet.packetLength[0] = (unsigned char) (PACKET_LENGTH_HK >> 8);
173 173 housekeeping_packet.packetLength[1] = (unsigned char) (PACKET_LENGTH_HK );
174 174 housekeeping_packet.spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
175 175 housekeeping_packet.serviceType = TM_TYPE_HK;
176 176 housekeeping_packet.serviceSubType = TM_SUBTYPE_HK;
177 177 housekeeping_packet.destinationID = TM_DESTINATION_ID_GROUND;
178 178 housekeeping_packet.sid = SID_HK;
179 179
180 180 status = rtems_rate_monotonic_cancel(HK_id);
181 181 if( status != RTEMS_SUCCESSFUL ) {
182 182 PRINTF1( "ERR *** in HOUS *** rtems_rate_monotonic_cancel(HK_id) ***code: %d\n", status )
183 183 }
184 184 else {
185 185 DEBUG_PRINTF("OK *** in HOUS *** rtems_rate_monotonic_cancel(HK_id)\n")
186 186 }
187 187
188 188 // startup phase
189 189 status = rtems_rate_monotonic_period( HK_id, SY_LFR_TIME_SYN_TIMEOUT_in_ticks );
190 190 status = rtems_rate_monotonic_get_status( HK_id, &period_status );
191 191 DEBUG_PRINTF1("startup HK, HK_id status = %d\n", period_status.state)
192 192 while(period_status.state != RATE_MONOTONIC_EXPIRED ) // after SY_LFR_TIME_SYN_TIMEOUT ms, starts HK anyway
193 193 {
194 194 if ((time_management_regs->coarse_time & 0x80000000) == 0x00000000) // check time synchronization
195 195 {
196 196 break; // break if LFR is synchronized
197 197 }
198 198 else
199 199 {
200 200 status = rtems_rate_monotonic_get_status( HK_id, &period_status );
201 201 // sched_yield();
202 202 status = rtems_task_wake_after( 10 ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 100 ms = 10 * 10 ms
203 203 }
204 204 }
205 205 status = rtems_rate_monotonic_cancel(HK_id);
206 206 DEBUG_PRINTF1("startup HK, HK_id status = %d\n", period_status.state)
207 207
208 208 while(1){ // launch the rate monotonic task
209 209 status = rtems_rate_monotonic_period( HK_id, HK_PERIOD );
210 210 if ( status != RTEMS_SUCCESSFUL ) {
211 211 PRINTF1( "in HOUS *** ERR period: %d\n", status);
212 212 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_6 );
213 213 }
214 214 else {
215 215 housekeeping_packet.packetSequenceControl[0] = (unsigned char) (sequenceCounterHK >> 8);
216 216 housekeeping_packet.packetSequenceControl[1] = (unsigned char) (sequenceCounterHK );
217 217 increment_seq_counter( &sequenceCounterHK );
218 218
219 219 housekeeping_packet.time[0] = (unsigned char) (time_management_regs->coarse_time>>24);
220 220 housekeeping_packet.time[1] = (unsigned char) (time_management_regs->coarse_time>>16);
221 221 housekeeping_packet.time[2] = (unsigned char) (time_management_regs->coarse_time>>8);
222 222 housekeeping_packet.time[3] = (unsigned char) (time_management_regs->coarse_time);
223 223 housekeeping_packet.time[4] = (unsigned char) (time_management_regs->fine_time>>8);
224 224 housekeeping_packet.time[5] = (unsigned char) (time_management_regs->fine_time);
225 225
226 226 spacewire_update_statistics();
227 227
228 get_temperatures( housekeeping_packet.hk_lfr_temp_scm );
228 229 get_v_e1_e2_f3( housekeeping_packet.hk_lfr_sc_v_f3 );
229 get_temperatures( housekeeping_packet.hk_lfr_temp_scm);
230 230 get_cpu_load( (unsigned char *) &housekeeping_packet.hk_lfr_cpu_load );
231 231
232 232 // SEND PACKET
233 233 status = rtems_message_queue_send( queue_id, &housekeeping_packet,
234 234 PACKET_LENGTH_HK + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES);
235 235 if (status != RTEMS_SUCCESSFUL) {
236 236 PRINTF1("in HOUS *** ERR send: %d\n", status)
237 237 }
238 238 }
239 239 }
240 240
241 241 PRINTF("in HOUS *** deleting task\n")
242 242
243 243 status = rtems_task_delete( RTEMS_SELF ); // should not return
244 244 printf( "rtems_task_delete returned with status of %d.\n", status );
245 245 return;
246 246 }
247 247
248 248 rtems_task dumb_task( rtems_task_argument unused )
249 249 {
250 250 /** This RTEMS taks is used to print messages without affecting the general behaviour of the software.
251 251 *
252 252 * @param unused is the starting argument of the RTEMS task
253 253 *
254 254 * The DUMB taks waits for RTEMS events and print messages depending on the incoming events.
255 255 *
256 256 */
257 257
258 258 unsigned int i;
259 259 unsigned int intEventOut;
260 260 unsigned int coarse_time = 0;
261 261 unsigned int fine_time = 0;
262 262 rtems_event_set event_out;
263 263
264 264 char *DumbMessages[12] = {"in DUMB *** default", // RTEMS_EVENT_0
265 265 "in DUMB *** timecode_irq_handler", // RTEMS_EVENT_1
266 266 "in DUMB *** f3 buffer changed", // RTEMS_EVENT_2
267 267 "in DUMB *** in SMIQ *** Error sending event to AVF0", // RTEMS_EVENT_3
268 268 "in DUMB *** spectral_matrices_isr *** Error sending event to SMIQ", // RTEMS_EVENT_4
269 269 "in DUMB *** waveforms_simulator_isr", // RTEMS_EVENT_5
270 270 "VHDL SM *** two buffers f0 ready", // RTEMS_EVENT_6
271 271 "ready for dump", // RTEMS_EVENT_7
272 272 "VHDL ERR *** spectral matrix", // RTEMS_EVENT_8
273 273 "tick", // RTEMS_EVENT_9
274 274 "VHDL ERR *** waveform picker", // RTEMS_EVENT_10
275 275 "VHDL ERR *** unexpected ready matrix values" // RTEMS_EVENT_11
276 276 };
277 277
278 278 BOOT_PRINTF("in DUMB *** \n")
279 279
280 280 while(1){
281 281 rtems_event_receive(RTEMS_EVENT_0 | RTEMS_EVENT_1 | RTEMS_EVENT_2 | RTEMS_EVENT_3
282 282 | RTEMS_EVENT_4 | RTEMS_EVENT_5 | RTEMS_EVENT_6 | RTEMS_EVENT_7
283 283 | RTEMS_EVENT_8 | RTEMS_EVENT_9,
284 284 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out); // wait for an RTEMS_EVENT
285 285 intEventOut = (unsigned int) event_out;
286 286 for ( i=0; i<32; i++)
287 287 {
288 288 if ( ((intEventOut >> i) & 0x0001) != 0)
289 289 {
290 290 coarse_time = time_management_regs->coarse_time;
291 291 fine_time = time_management_regs->fine_time;
292 292 printf("in DUMB *** coarse: %x, fine: %x, %s\n", coarse_time, fine_time, DumbMessages[i]);
293 293 if (i==8)
294 294 {
295 295 }
296 296 if (i==10)
297 297 {
298 298 }
299 299 }
300 300 }
301 301 }
302 302 }
303 303
304 304 //*****************************
305 305 // init housekeeping parameters
306 306
307 307 void init_housekeeping_parameters( void )
308 308 {
309 309 /** This function initialize the housekeeping_packet global variable with default values.
310 310 *
311 311 */
312 312
313 313 unsigned int i = 0;
314 314 unsigned char *parameters;
315 315
316 316 parameters = (unsigned char*) &housekeeping_packet.lfr_status_word;
317 317 for(i = 0; i< SIZE_HK_PARAMETERS; i++)
318 318 {
319 319 parameters[i] = 0x00;
320 320 }
321 321 // init status word
322 322 housekeeping_packet.lfr_status_word[0] = DEFAULT_STATUS_WORD_BYTE0;
323 323 housekeeping_packet.lfr_status_word[1] = DEFAULT_STATUS_WORD_BYTE1;
324 324 // init software version
325 325 housekeeping_packet.lfr_sw_version[0] = SW_VERSION_N1;
326 326 housekeeping_packet.lfr_sw_version[1] = SW_VERSION_N2;
327 327 housekeeping_packet.lfr_sw_version[2] = SW_VERSION_N3;
328 328 housekeeping_packet.lfr_sw_version[3] = SW_VERSION_N4;
329 329 // init fpga version
330 330 parameters = (unsigned char *) (REGS_ADDR_VHDL_VERSION);
331 331 housekeeping_packet.lfr_fpga_version[0] = parameters[1]; // n1
332 332 housekeeping_packet.lfr_fpga_version[1] = parameters[2]; // n2
333 333 housekeeping_packet.lfr_fpga_version[2] = parameters[3]; // n3
334 334 }
335 335
336 336 void increment_seq_counter( unsigned short *packetSequenceControl )
337 337 {
338 338 /** This function increment the sequence counter psased in argument.
339 339 *
340 340 * The increment does not affect the grouping flag. In case of an overflow, the counter is reset to 0.
341 341 *
342 342 */
343 343
344 344 unsigned short segmentation_grouping_flag;
345 345 unsigned short sequence_cnt;
346 346
347 347 segmentation_grouping_flag = TM_PACKET_SEQ_CTRL_STANDALONE << 8; // keep bits 7 downto 6
348 348 sequence_cnt = (*packetSequenceControl) & 0x3fff; // [0011 1111 1111 1111]
349 349
350 350 if ( sequence_cnt < SEQ_CNT_MAX)
351 351 {
352 352 sequence_cnt = sequence_cnt + 1;
353 353 }
354 354 else
355 355 {
356 356 sequence_cnt = 0;
357 357 }
358 358
359 359 *packetSequenceControl = segmentation_grouping_flag | sequence_cnt ;
360 360 }
361 361
362 362 void getTime( unsigned char *time)
363 363 {
364 364 /** This function write the current local time in the time buffer passed in argument.
365 365 *
366 366 */
367 367
368 368 time[0] = (unsigned char) (time_management_regs->coarse_time>>24);
369 369 time[1] = (unsigned char) (time_management_regs->coarse_time>>16);
370 370 time[2] = (unsigned char) (time_management_regs->coarse_time>>8);
371 371 time[3] = (unsigned char) (time_management_regs->coarse_time);
372 372 time[4] = (unsigned char) (time_management_regs->fine_time>>8);
373 373 time[5] = (unsigned char) (time_management_regs->fine_time);
374 374 }
375 375
376 376 unsigned long long int getTimeAsUnsignedLongLongInt( )
377 377 {
378 378 /** This function write the current local time in the time buffer passed in argument.
379 379 *
380 380 */
381 381 unsigned long long int time;
382 382
383 383 time = ( (unsigned long long int) (time_management_regs->coarse_time & 0x7fffffff) << 16 )
384 384 + time_management_regs->fine_time;
385 385
386 386 return time;
387 387 }
388 388
389 389 void send_dumb_hk( void )
390 390 {
391 391 Packet_TM_LFR_HK_t dummy_hk_packet;
392 392 unsigned char *parameters;
393 393 unsigned int i;
394 394 rtems_id queue_id;
395 395
396 396 dummy_hk_packet.targetLogicalAddress = CCSDS_DESTINATION_ID;
397 397 dummy_hk_packet.protocolIdentifier = CCSDS_PROTOCOLE_ID;
398 398 dummy_hk_packet.reserved = DEFAULT_RESERVED;
399 399 dummy_hk_packet.userApplication = CCSDS_USER_APP;
400 400 dummy_hk_packet.packetID[0] = (unsigned char) (APID_TM_HK >> 8);
401 401 dummy_hk_packet.packetID[1] = (unsigned char) (APID_TM_HK);
402 402 dummy_hk_packet.packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
403 403 dummy_hk_packet.packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
404 404 dummy_hk_packet.packetLength[0] = (unsigned char) (PACKET_LENGTH_HK >> 8);
405 405 dummy_hk_packet.packetLength[1] = (unsigned char) (PACKET_LENGTH_HK );
406 406 dummy_hk_packet.spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
407 407 dummy_hk_packet.serviceType = TM_TYPE_HK;
408 408 dummy_hk_packet.serviceSubType = TM_SUBTYPE_HK;
409 409 dummy_hk_packet.destinationID = TM_DESTINATION_ID_GROUND;
410 410 dummy_hk_packet.time[0] = (unsigned char) (time_management_regs->coarse_time>>24);
411 411 dummy_hk_packet.time[1] = (unsigned char) (time_management_regs->coarse_time>>16);
412 412 dummy_hk_packet.time[2] = (unsigned char) (time_management_regs->coarse_time>>8);
413 413 dummy_hk_packet.time[3] = (unsigned char) (time_management_regs->coarse_time);
414 414 dummy_hk_packet.time[4] = (unsigned char) (time_management_regs->fine_time>>8);
415 415 dummy_hk_packet.time[5] = (unsigned char) (time_management_regs->fine_time);
416 416 dummy_hk_packet.sid = SID_HK;
417 417
418 418 // init status word
419 419 dummy_hk_packet.lfr_status_word[0] = 0xff;
420 420 dummy_hk_packet.lfr_status_word[1] = 0xff;
421 421 // init software version
422 422 dummy_hk_packet.lfr_sw_version[0] = SW_VERSION_N1;
423 423 dummy_hk_packet.lfr_sw_version[1] = SW_VERSION_N2;
424 424 dummy_hk_packet.lfr_sw_version[2] = SW_VERSION_N3;
425 425 dummy_hk_packet.lfr_sw_version[3] = SW_VERSION_N4;
426 426 // init fpga version
427 427 parameters = (unsigned char *) (REGS_ADDR_WAVEFORM_PICKER + 0xb0);
428 428 dummy_hk_packet.lfr_fpga_version[0] = parameters[1]; // n1
429 429 dummy_hk_packet.lfr_fpga_version[1] = parameters[2]; // n2
430 430 dummy_hk_packet.lfr_fpga_version[2] = parameters[3]; // n3
431 431
432 432 parameters = (unsigned char *) &dummy_hk_packet.hk_lfr_cpu_load;
433 433
434 434 for (i=0; i<100; i++)
435 435 {
436 436 parameters[i] = 0xff;
437 437 }
438 438
439 439 get_message_queue_id_send( &queue_id );
440 440
441 441 rtems_message_queue_send( queue_id, &dummy_hk_packet,
442 442 PACKET_LENGTH_HK + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES);
443 443 }
444 444
445 void get_temperatures( unsigned char *temperatures )
446 {
447 unsigned char* temp_scm_ptr;
448 unsigned char* temp_pcb_ptr;
449 unsigned char* temp_fpga_ptr;
450
451 temp_scm_ptr = (unsigned char *) &time_management_regs->temp_scm;
452 temp_pcb_ptr = (unsigned char *) &time_management_regs->temp_pcb;
453 temp_fpga_ptr = (unsigned char *) &time_management_regs->temp_fpga;
454
455 temperatures[0] = temp_scm_ptr[2];
456 temperatures[1] = temp_scm_ptr[3];
457 temperatures[2] = temp_pcb_ptr[2];
458 temperatures[3] = temp_pcb_ptr[3];
459 temperatures[4] = temp_fpga_ptr[2];
460 temperatures[5] = temp_fpga_ptr[3];
461 }
462
445 463 void get_v_e1_e2_f3( unsigned char *spacecraft_potential )
446 464 {
447 465 unsigned char* v_ptr;
448 466 unsigned char* e1_ptr;
449 467 unsigned char* e2_ptr;
450 468
451 469 v_ptr = (unsigned char *) &waveform_picker_regs->v;
452 470 e1_ptr = (unsigned char *) &waveform_picker_regs->e1;
453 471 e2_ptr = (unsigned char *) &waveform_picker_regs->e2;
454 472
455 473 spacecraft_potential[0] = v_ptr[2];
456 474 spacecraft_potential[1] = v_ptr[3];
457 475 spacecraft_potential[2] = e1_ptr[2];
458 476 spacecraft_potential[3] = e1_ptr[3];
459 477 spacecraft_potential[4] = e2_ptr[2];
460 478 spacecraft_potential[5] = e2_ptr[3];
461 479 }
462 480
463 void get_temperatures( unsigned char *temperatures )
464 {
465 unsigned char* temp_scm_ptr;
466 unsigned char* temp_pcb_ptr;
467 unsigned char* temp_fpga_ptr;
468
469 temp_scm_ptr = (unsigned char *) &time_management_regs->temp_scm;
470 temp_pcb_ptr = (unsigned char *) &time_management_regs->temp_pcb;
471 temp_fpga_ptr = (unsigned char *) &time_management_regs->temp_fpga;
472
473 temperatures[0] = temp_scm_ptr[2];
474 temperatures[1] = temp_scm_ptr[3];
475 temperatures[2] = temp_pcb_ptr[2];
476 temperatures[3] = temp_pcb_ptr[3];
477 temperatures[4] = temp_fpga_ptr[2];
478 temperatures[5] = temp_fpga_ptr[3];
479 }
480
481 481 void get_cpu_load( unsigned char *resource_statistics )
482 482 {
483 483 unsigned char cpu_load;
484 484
485 485 cpu_load = lfr_rtems_cpu_usage_report();
486 486
487 487 // HK_LFR_CPU_LOAD
488 488 resource_statistics[0] = cpu_load;
489 489
490 490 // HK_LFR_CPU_LOAD_MAX
491 491 if (cpu_load > resource_statistics[1])
492 492 {
493 493 resource_statistics[1] = cpu_load;
494 494 }
495 495
496 496 // CPU_LOAD_AVE
497 497 resource_statistics[2] = 0;
498 498
499 499 #ifndef PRINT_TASK_STATISTICS
500 500 rtems_cpu_usage_reset();
501 501 #endif
502 502
503 503 }
504 504
505 505
506 506
@@ -1,1120 +1,1117
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 //***********
26 26 // RTEMS TASK
27 27 rtems_task spiq_task(rtems_task_argument unused)
28 28 {
29 29 /** This RTEMS task is awaken by an rtems_event sent by the interruption subroutine of the SpaceWire driver.
30 30 *
31 31 * @param unused is the starting argument of the RTEMS task
32 32 *
33 33 */
34 34
35 35 rtems_event_set event_out;
36 36 rtems_status_code status;
37 37 int linkStatus;
38 38
39 39 BOOT_PRINTF("in SPIQ *** \n")
40 40
41 41 while(true){
42 42 rtems_event_receive(SPW_LINKERR_EVENT, RTEMS_WAIT, RTEMS_NO_TIMEOUT, &event_out); // wait for an SPW_LINKERR_EVENT
43 43 PRINTF("in SPIQ *** got SPW_LINKERR_EVENT\n")
44 44
45 45 // [0] SUSPEND RECV AND SEND TASKS
46 46 status = rtems_task_suspend( Task_id[ TASKID_RECV ] );
47 47 if ( status != RTEMS_SUCCESSFUL ) {
48 48 PRINTF("in SPIQ *** ERR suspending RECV Task\n")
49 49 }
50 50 status = rtems_task_suspend( Task_id[ TASKID_SEND ] );
51 51 if ( status != RTEMS_SUCCESSFUL ) {
52 52 PRINTF("in SPIQ *** ERR suspending SEND Task\n")
53 53 }
54 54
55 55 // [1] CHECK THE LINK
56 56 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status (1)
57 57 if ( linkStatus != 5) {
58 58 PRINTF1("in SPIQ *** linkStatus %d, wait...\n", linkStatus)
59 59 status = rtems_task_wake_after( SY_LFR_DPU_CONNECT_TIMEOUT ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 1000 ms
60 60 }
61 61
62 62 // [2] RECHECK THE LINK AFTER SY_LFR_DPU_CONNECT_TIMEOUT
63 63 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status (2)
64 64 if ( linkStatus != 5 ) // [2.a] not in run state, reset the link
65 65 {
66 66 spacewire_compute_stats_offsets();
67 67 status = spacewire_reset_link( );
68 68 }
69 69 else // [2.b] in run state, start the link
70 70 {
71 71 status = spacewire_stop_and_start_link( fdSPW ); // start the link
72 72 if ( status != RTEMS_SUCCESSFUL)
73 73 {
74 74 PRINTF1("in SPIQ *** ERR spacewire_start_link %d\n", status)
75 75 }
76 76 }
77 77
78 78 // [3] COMPLETE RECOVERY ACTION AFTER SY_LFR_DPU_CONNECT_ATTEMPTS
79 79 if ( status == RTEMS_SUCCESSFUL ) // [3.a] the link is in run state and has been started successfully
80 80 {
81 81 status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
82 82 if ( status != RTEMS_SUCCESSFUL ) {
83 83 PRINTF("in SPIQ *** ERR resuming SEND Task\n")
84 84 }
85 85 status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
86 86 if ( status != RTEMS_SUCCESSFUL ) {
87 87 PRINTF("in SPIQ *** ERR resuming RECV Task\n")
88 88 }
89 89 }
90 90 else // [3.b] the link is not in run state, go in STANDBY mode
91 91 {
92 92 status = stop_current_mode();
93 93 if ( status != RTEMS_SUCCESSFUL ) {
94 94 PRINTF1("in SPIQ *** ERR stop_current_mode *** code %d\n", status)
95 95 }
96 96 status = enter_mode( LFR_MODE_STANDBY, 0 );
97 97 if ( status != RTEMS_SUCCESSFUL ) {
98 98 PRINTF1("in SPIQ *** ERR enter_standby_mode *** code %d\n", status)
99 99 }
100 100 // wake the WTDG task up to wait for the link recovery
101 101 status = rtems_event_send ( Task_id[TASKID_WTDG], RTEMS_EVENT_0 );
102 102 status = rtems_task_suspend( RTEMS_SELF );
103 103 }
104 104 }
105 105 }
106 106
107 107 rtems_task recv_task( rtems_task_argument unused )
108 108 {
109 109 /** This RTEMS task is dedicated to the reception of incoming TeleCommands.
110 110 *
111 111 * @param unused is the starting argument of the RTEMS task
112 112 *
113 113 * The RECV task blocks on a call to the read system call, waiting for incoming SpaceWire data. When unblocked:
114 114 * 1. It reads the incoming data.
115 115 * 2. Launches the acceptance procedure.
116 116 * 3. If the Telecommand is valid, sends it to a dedicated RTEMS message queue.
117 117 *
118 118 */
119 119
120 120 int len;
121 121 ccsdsTelecommandPacket_t currentTC;
122 122 unsigned char computed_CRC[ 2 ];
123 123 unsigned char currentTC_LEN_RCV[ 2 ];
124 124 unsigned char destinationID;
125 125 unsigned int estimatedPacketLength;
126 126 unsigned int parserCode;
127 127 rtems_status_code status;
128 128 rtems_id queue_recv_id;
129 129 rtems_id queue_send_id;
130 130
131 131 initLookUpTableForCRC(); // the table is used to compute Cyclic Redundancy Codes
132 132
133 133 status = get_message_queue_id_recv( &queue_recv_id );
134 134 if (status != RTEMS_SUCCESSFUL)
135 135 {
136 136 PRINTF1("in RECV *** ERR get_message_queue_id_recv %d\n", status)
137 137 }
138 138
139 139 status = get_message_queue_id_send( &queue_send_id );
140 140 if (status != RTEMS_SUCCESSFUL)
141 141 {
142 142 PRINTF1("in RECV *** ERR get_message_queue_id_send %d\n", status)
143 143 }
144 144
145 145 BOOT_PRINTF("in RECV *** \n")
146 146
147 147 while(1)
148 148 {
149 149 len = read( fdSPW, (char*) &currentTC, CCSDS_TC_PKT_MAX_SIZE ); // the call to read is blocking
150 150 if (len == -1){ // error during the read call
151 151 PRINTF1("in RECV *** last read call returned -1, ERRNO %d\n", errno)
152 152 }
153 153 else {
154 154 if ( (len+1) < CCSDS_TC_PKT_MIN_SIZE ) {
155 155 PRINTF("in RECV *** packet lenght too short\n")
156 156 }
157 157 else {
158 158 estimatedPacketLength = (unsigned int) (len - CCSDS_TC_TM_PACKET_OFFSET - 3); // => -3 is for Prot ID, Reserved and User App bytes
159 159 currentTC_LEN_RCV[ 0 ] = (unsigned char) (estimatedPacketLength >> 8);
160 160 currentTC_LEN_RCV[ 1 ] = (unsigned char) (estimatedPacketLength );
161 161 // CHECK THE TC
162 162 parserCode = tc_parser( &currentTC, estimatedPacketLength, computed_CRC ) ;
163 163 if ( (parserCode == ILLEGAL_APID) || (parserCode == WRONG_LEN_PKT)
164 164 || (parserCode == INCOR_CHECKSUM) || (parserCode == ILL_TYPE)
165 165 || (parserCode == ILL_SUBTYPE) || (parserCode == WRONG_APP_DATA)
166 166 || (parserCode == WRONG_SRC_ID) )
167 167 { // send TM_LFR_TC_EXE_CORRUPTED
168 168 PRINTF1("TC corrupted received, with code: %d\n", parserCode)
169 169 if ( !( (currentTC.serviceType==TC_TYPE_TIME) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_TIME) )
170 170 &&
171 171 !( (currentTC.serviceType==TC_TYPE_GEN) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_INFO))
172 172 )
173 173 {
174 174 if ( parserCode == WRONG_SRC_ID )
175 175 {
176 176 destinationID = SID_TC_GROUND;
177 177 }
178 178 else
179 179 {
180 180 destinationID = currentTC.sourceID;
181 181 }
182 182 send_tm_lfr_tc_exe_corrupted( &currentTC, queue_send_id,
183 183 computed_CRC, currentTC_LEN_RCV,
184 184 destinationID );
185 185 }
186 186 }
187 187 else
188 188 { // send valid TC to the action launcher
189 189 status = rtems_message_queue_send( queue_recv_id, &currentTC,
190 190 estimatedPacketLength + CCSDS_TC_TM_PACKET_OFFSET + 3);
191 191 }
192 192 }
193 193 }
194 194 }
195 195 }
196 196
197 197 rtems_task send_task( rtems_task_argument argument)
198 198 {
199 199 /** This RTEMS task is dedicated to the transmission of TeleMetry packets.
200 200 *
201 201 * @param unused is the starting argument of the RTEMS task
202 202 *
203 203 * The SEND task waits for a message to become available in the dedicated RTEMS queue. When a message arrives:
204 204 * - if the first byte is equal to CCSDS_DESTINATION_ID, the message is sent as is using the write system call.
205 205 * - if the first byte is not equal to CCSDS_DESTINATION_ID, the message is handled as a spw_ioctl_pkt_send. After
206 206 * analyzis, the packet is sent either using the write system call or using the ioctl call SPACEWIRE_IOCTRL_SEND, depending on the
207 207 * data it contains.
208 208 *
209 209 */
210 210
211 211 rtems_status_code status; // RTEMS status code
212 212 char incomingData[MSG_QUEUE_SIZE_SEND]; // incoming data buffer
213 213 ring_node *incomingRingNodePtr;
214 214 int ring_node_address;
215 215 char *charPtr;
216 216 spw_ioctl_pkt_send *spw_ioctl_send;
217 217 size_t size; // size of the incoming TC packet
218 218 u_int32_t count;
219 219 rtems_id queue_id;
220 220 unsigned char sid;
221 221
222 222 incomingRingNodePtr = NULL;
223 223 ring_node_address = 0;
224 224 charPtr = (char *) &ring_node_address;
225 225 sid = 0;
226 226
227 227 init_header_cwf( &headerCWF );
228 228 init_header_swf( &headerSWF );
229 229 init_header_asm( &headerASM );
230 230
231 231 status = get_message_queue_id_send( &queue_id );
232 232 if (status != RTEMS_SUCCESSFUL)
233 233 {
234 234 PRINTF1("in HOUS *** ERR get_message_queue_id_send %d\n", status)
235 235 }
236 236
237 237 BOOT_PRINTF("in SEND *** \n")
238 238
239 239 while(1)
240 240 {
241 241 status = rtems_message_queue_receive( queue_id, incomingData, &size,
242 242 RTEMS_WAIT, RTEMS_NO_TIMEOUT );
243 243
244 244 if (status!=RTEMS_SUCCESSFUL)
245 245 {
246 246 PRINTF1("in SEND *** (1) ERR = %d\n", status)
247 247 }
248 248 else
249 249 {
250 250 if ( size == sizeof(ring_node*) )
251 251 {
252 252 charPtr[0] = incomingData[0];
253 253 charPtr[1] = incomingData[1];
254 254 charPtr[2] = incomingData[2];
255 255 charPtr[3] = incomingData[3];
256 256 incomingRingNodePtr = (ring_node*) ring_node_address;
257 257 sid = incomingRingNodePtr->sid;
258 258 if ( (sid==SID_NORM_CWF_LONG_F3)
259 259 || (sid==SID_BURST_CWF_F2 )
260 260 || (sid==SID_SBM1_CWF_F1 )
261 261 || (sid==SID_SBM2_CWF_F2 ))
262 262 {
263 263 spw_send_waveform_CWF( incomingRingNodePtr, &headerCWF );
264 264 }
265 265 else if ( (sid==SID_NORM_SWF_F0) || (sid== SID_NORM_SWF_F1) || (sid==SID_NORM_SWF_F2) )
266 266 {
267 267 spw_send_waveform_SWF( incomingRingNodePtr, &headerSWF );
268 268 }
269 269 else if ( (sid==SID_NORM_CWF_F3) )
270 270 {
271 271 spw_send_waveform_CWF3_light( incomingRingNodePtr, &headerCWF );
272 272 }
273 273 else if ( (sid==SID_NORM_ASM_F0) || (SID_NORM_ASM_F1) || (SID_NORM_ASM_F2) )
274 274 {
275 275 spw_send_asm( incomingRingNodePtr, &headerASM );
276 276 }
277 277 else
278 278 {
279 279 printf("unexpected sid = %d\n", sid);
280 280 }
281 281 }
282 282 else if ( incomingData[0] == CCSDS_DESTINATION_ID ) // the incoming message is a ccsds packet
283 283 {
284 284 status = write( fdSPW, incomingData, size );
285 285 if (status == -1){
286 286 PRINTF2("in SEND *** (2.a) ERRNO = %d, size = %d\n", errno, size)
287 287 }
288 288 }
289 289 else // the incoming message is a spw_ioctl_pkt_send structure
290 290 {
291 291 spw_ioctl_send = (spw_ioctl_pkt_send*) incomingData;
292 292 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, spw_ioctl_send );
293 293 if (status == -1){
294 294 printf("size = %d, %x, %x, %x, %x, %x\n",
295 295 size,
296 296 incomingData[0],
297 297 incomingData[1],
298 298 incomingData[2],
299 299 incomingData[3],
300 300 incomingData[4]);
301 301 PRINTF2("in SEND *** (2.b) ERRNO = %d, RTEMS = %d\n", errno, status)
302 302 }
303 303 }
304 304 }
305 305
306 306 status = rtems_message_queue_get_number_pending( queue_id, &count );
307 307 if (status != RTEMS_SUCCESSFUL)
308 308 {
309 309 PRINTF1("in SEND *** (3) ERR = %d\n", status)
310 310 }
311 311 else
312 312 {
313 313 if (count > maxCount)
314 314 {
315 315 maxCount = count;
316 316 }
317 317 }
318 318 }
319 319 }
320 320
321 321 rtems_task wtdg_task( rtems_task_argument argument )
322 322 {
323 323 rtems_event_set event_out;
324 324 rtems_status_code status;
325 325 int linkStatus;
326 326
327 327 BOOT_PRINTF("in WTDG ***\n")
328 328
329 329 while(1)
330 330 {
331 331 // wait for an RTEMS_EVENT
332 332 rtems_event_receive( RTEMS_EVENT_0,
333 333 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
334 334 PRINTF("in WTDG *** wait for the link\n")
335 335 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
336 336 while( linkStatus != 5) // wait for the link
337 337 {
338 338 status = rtems_task_wake_after( 10 ); // monitor the link each 100ms
339 339 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
340 340 }
341 341
342 342 status = spacewire_stop_and_start_link( fdSPW );
343 343
344 344 if (status != RTEMS_SUCCESSFUL)
345 345 {
346 346 PRINTF1("in WTDG *** ERR link not started %d\n", status)
347 347 }
348 348 else
349 349 {
350 350 PRINTF("in WTDG *** OK link started\n")
351 351 }
352 352
353 353 // restart the SPIQ task
354 354 status = rtems_task_restart( Task_id[TASKID_SPIQ], 1 );
355 355 if ( status != RTEMS_SUCCESSFUL ) {
356 356 PRINTF("in SPIQ *** ERR restarting SPIQ Task\n")
357 357 }
358 358
359 359 // restart RECV and SEND
360 360 status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
361 361 if ( status != RTEMS_SUCCESSFUL ) {
362 362 PRINTF("in SPIQ *** ERR restarting SEND Task\n")
363 363 }
364 364 status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
365 365 if ( status != RTEMS_SUCCESSFUL ) {
366 366 PRINTF("in SPIQ *** ERR restarting RECV Task\n")
367 367 }
368 368 }
369 369 }
370 370
371 371 //****************
372 372 // OTHER FUNCTIONS
373 373 int spacewire_open_link( void ) // by default, the driver resets the core: [SPW_CTRL_WRITE(pDev, SPW_CTRL_RESET);]
374 374 {
375 375 /** This function opens the SpaceWire link.
376 376 *
377 377 * @return a valid file descriptor in case of success, -1 in case of a failure
378 378 *
379 379 */
380 380 rtems_status_code status;
381 381
382 382 fdSPW = open(GRSPW_DEVICE_NAME, O_RDWR); // open the device. the open call resets the hardware
383 383 if ( fdSPW < 0 ) {
384 384 PRINTF1("ERR *** in configure_spw_link *** error opening "GRSPW_DEVICE_NAME" with ERR %d\n", errno)
385 385 }
386 386 else
387 387 {
388 388 status = RTEMS_SUCCESSFUL;
389 389 }
390 390
391 391 return status;
392 392 }
393 393
394 394 int spacewire_start_link( int fd )
395 395 {
396 396 rtems_status_code status;
397 397
398 398 status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
399 399 // -1 default hardcoded driver timeout
400 400
401 401 return status;
402 402 }
403 403
404 404 int spacewire_stop_and_start_link( int fd )
405 405 {
406 406 rtems_status_code status;
407 407
408 408 status = ioctl( fd, SPACEWIRE_IOCTRL_STOP); // start fails if link pDev->running != 0
409 409 status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
410 410 // -1 default hardcoded driver timeout
411 411
412 412 return status;
413 413 }
414 414
415 415 int spacewire_configure_link( int fd )
416 416 {
417 417 /** This function configures the SpaceWire link.
418 418 *
419 419 * @return GR-RTEMS-DRIVER directive status codes:
420 420 * - 22 EINVAL - Null pointer or an out of range value was given as the argument.
421 421 * - 16 EBUSY - Only used for SEND. Returned when no descriptors are avialble in non-blocking mode.
422 422 * - 88 ENOSYS - Returned for SET_DESTKEY if RMAP command handler is not available or if a non-implemented call is used.
423 423 * - 116 ETIMEDOUT - REturned for SET_PACKET_SIZE and START if the link could not be brought up.
424 424 * - 12 ENOMEM - Returned for SET_PACKETSIZE if it was unable to allocate the new buffers.
425 425 * - 5 EIO - Error when writing to grswp hardware registers.
426 426 * - 2 ENOENT - No such file or directory
427 427 */
428 428
429 429 rtems_status_code status;
430 430
431 431 spacewire_set_NP(1, REGS_ADDR_GRSPW); // [N]o [P]ort force
432 432 spacewire_set_RE(1, REGS_ADDR_GRSPW); // [R]MAP [E]nable, the dedicated call seems to break the no port force configuration
433 433
434 434 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_RXBLOCK, 1); // sets the blocking mode for reception
435 435 if (status!=RTEMS_SUCCESSFUL) {
436 436 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_RXBLOCK\n")
437 437 }
438 438 //
439 439 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_EVENT_ID, Task_id[TASKID_SPIQ]); // sets the task ID to which an event is sent when a
440 440 if (status!=RTEMS_SUCCESSFUL) {
441 441 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_EVENT_ID\n") // link-error interrupt occurs
442 442 }
443 443 //
444 444 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_DISABLE_ERR, 0); // automatic link-disabling due to link-error interrupts
445 445 if (status!=RTEMS_SUCCESSFUL) {
446 446 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_DISABLE_ERR\n")
447 447 }
448 448 //
449 449 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ, 1); // sets the link-error interrupt bit
450 450 if (status!=RTEMS_SUCCESSFUL) {
451 451 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ\n")
452 452 }
453 453 //
454 454 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK, 1); // transmission blocks
455 455 if (status!=RTEMS_SUCCESSFUL) {
456 456 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK\n")
457 457 }
458 458 //
459 459 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL, 1); // transmission blocks when no transmission descriptor is available
460 460 if (status!=RTEMS_SUCCESSFUL) {
461 461 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL\n")
462 462 }
463 463 //
464 464 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TCODE_CTRL, 0x0909); // [Time Rx : Time Tx : Link error : Tick-out IRQ]
465 465 if (status!=RTEMS_SUCCESSFUL) {
466 466 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TCODE_CTRL,\n")
467 467 }
468 468
469 469 return status;
470 470 }
471 471
472 472 int spacewire_reset_link( void )
473 473 {
474 474 /** This function is executed by the SPIQ rtems_task wehn it has been awaken by an interruption raised by the SpaceWire driver.
475 475 *
476 476 * @return RTEMS directive status code:
477 477 * - RTEMS_UNSATISFIED is returned is the link is not in the running state after 10 s.
478 478 * - RTEMS_SUCCESSFUL is returned if the link is up before the timeout.
479 479 *
480 480 */
481 481
482 482 rtems_status_code status_spw;
483 483 rtems_status_code status;
484 484 int i;
485 485
486 486 for ( i=0; i<SY_LFR_DPU_CONNECT_ATTEMPT; i++ )
487 487 {
488 488 PRINTF1("in spacewire_reset_link *** link recovery, try %d\n", i);
489 489
490 490 // CLOSING THE DRIVER AT THIS POINT WILL MAKE THE SEND TASK BLOCK THE SYSTEM
491 491
492 492 status = rtems_task_wake_after( SY_LFR_DPU_CONNECT_TIMEOUT ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 1000 ms
493 493
494 494 status_spw = spacewire_stop_and_start_link( fdSPW );
495 495 if ( status_spw != RTEMS_SUCCESSFUL )
496 496 {
497 497 PRINTF1("in spacewire_reset_link *** ERR spacewire_start_link code %d\n", status_spw)
498 498 }
499 499
500 500 if ( status_spw == RTEMS_SUCCESSFUL)
501 501 {
502 502 break;
503 503 }
504 504 }
505 505
506 506 return status_spw;
507 507 }
508 508
509 509 void spacewire_set_NP( unsigned char val, unsigned int regAddr ) // [N]o [P]ort force
510 510 {
511 511 /** This function sets the [N]o [P]ort force bit of the GRSPW control register.
512 512 *
513 513 * @param val is the value, 0 or 1, used to set the value of the NP bit.
514 514 * @param regAddr is the address of the GRSPW control register.
515 515 *
516 516 * NP is the bit 20 of the GRSPW control register.
517 517 *
518 518 */
519 519
520 520 unsigned int *spwptr = (unsigned int*) regAddr;
521 521
522 522 if (val == 1) {
523 523 *spwptr = *spwptr | 0x00100000; // [NP] set the No port force bit
524 524 }
525 525 if (val== 0) {
526 526 *spwptr = *spwptr & 0xffdfffff;
527 527 }
528 528 }
529 529
530 530 void spacewire_set_RE( unsigned char val, unsigned int regAddr ) // [R]MAP [E]nable
531 531 {
532 532 /** This function sets the [R]MAP [E]nable bit of the GRSPW control register.
533 533 *
534 534 * @param val is the value, 0 or 1, used to set the value of the RE bit.
535 535 * @param regAddr is the address of the GRSPW control register.
536 536 *
537 537 * RE is the bit 16 of the GRSPW control register.
538 538 *
539 539 */
540 540
541 541 unsigned int *spwptr = (unsigned int*) regAddr;
542 542
543 543 if (val == 1)
544 544 {
545 545 *spwptr = *spwptr | 0x00010000; // [RE] set the RMAP Enable bit
546 546 }
547 547 if (val== 0)
548 548 {
549 549 *spwptr = *spwptr & 0xfffdffff;
550 550 }
551 551 }
552 552
553 553 void spacewire_compute_stats_offsets( void )
554 554 {
555 555 /** This function computes the SpaceWire statistics offsets in case of a SpaceWire related interruption raising.
556 556 *
557 557 * The offsets keep a record of the statistics in case of a reset of the statistics. They are added to the current statistics
558 558 * to keep the counters consistent even after a reset of the SpaceWire driver (the counter are set to zero by the driver when it
559 559 * during the open systel call).
560 560 *
561 561 */
562 562
563 563 spw_stats spacewire_stats_grspw;
564 564 rtems_status_code status;
565 565
566 566 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &spacewire_stats_grspw );
567 567
568 568 spacewire_stats_backup.packets_received = spacewire_stats_grspw.packets_received
569 569 + spacewire_stats.packets_received;
570 570 spacewire_stats_backup.packets_sent = spacewire_stats_grspw.packets_sent
571 571 + spacewire_stats.packets_sent;
572 572 spacewire_stats_backup.parity_err = spacewire_stats_grspw.parity_err
573 573 + spacewire_stats.parity_err;
574 574 spacewire_stats_backup.disconnect_err = spacewire_stats_grspw.disconnect_err
575 575 + spacewire_stats.disconnect_err;
576 576 spacewire_stats_backup.escape_err = spacewire_stats_grspw.escape_err
577 577 + spacewire_stats.escape_err;
578 578 spacewire_stats_backup.credit_err = spacewire_stats_grspw.credit_err
579 579 + spacewire_stats.credit_err;
580 580 spacewire_stats_backup.write_sync_err = spacewire_stats_grspw.write_sync_err
581 581 + spacewire_stats.write_sync_err;
582 582 spacewire_stats_backup.rx_rmap_header_crc_err = spacewire_stats_grspw.rx_rmap_header_crc_err
583 583 + spacewire_stats.rx_rmap_header_crc_err;
584 584 spacewire_stats_backup.rx_rmap_data_crc_err = spacewire_stats_grspw.rx_rmap_data_crc_err
585 585 + spacewire_stats.rx_rmap_data_crc_err;
586 586 spacewire_stats_backup.early_ep = spacewire_stats_grspw.early_ep
587 587 + spacewire_stats.early_ep;
588 588 spacewire_stats_backup.invalid_address = spacewire_stats_grspw.invalid_address
589 589 + spacewire_stats.invalid_address;
590 590 spacewire_stats_backup.rx_eep_err = spacewire_stats_grspw.rx_eep_err
591 591 + spacewire_stats.rx_eep_err;
592 592 spacewire_stats_backup.rx_truncated = spacewire_stats_grspw.rx_truncated
593 593 + spacewire_stats.rx_truncated;
594 594 }
595 595
596 596 void spacewire_update_statistics( void )
597 597 {
598 598 rtems_status_code status;
599 599 spw_stats spacewire_stats_grspw;
600 600
601 601 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &spacewire_stats_grspw );
602 602
603 603 spacewire_stats.packets_received = spacewire_stats_backup.packets_received
604 604 + spacewire_stats_grspw.packets_received;
605 605 spacewire_stats.packets_sent = spacewire_stats_backup.packets_sent
606 606 + spacewire_stats_grspw.packets_sent;
607 607 spacewire_stats.parity_err = spacewire_stats_backup.parity_err
608 608 + spacewire_stats_grspw.parity_err;
609 609 spacewire_stats.disconnect_err = spacewire_stats_backup.disconnect_err
610 610 + spacewire_stats_grspw.disconnect_err;
611 611 spacewire_stats.escape_err = spacewire_stats_backup.escape_err
612 612 + spacewire_stats_grspw.escape_err;
613 613 spacewire_stats.credit_err = spacewire_stats_backup.credit_err
614 614 + spacewire_stats_grspw.credit_err;
615 615 spacewire_stats.write_sync_err = spacewire_stats_backup.write_sync_err
616 616 + spacewire_stats_grspw.write_sync_err;
617 617 spacewire_stats.rx_rmap_header_crc_err = spacewire_stats_backup.rx_rmap_header_crc_err
618 618 + spacewire_stats_grspw.rx_rmap_header_crc_err;
619 619 spacewire_stats.rx_rmap_data_crc_err = spacewire_stats_backup.rx_rmap_data_crc_err
620 620 + spacewire_stats_grspw.rx_rmap_data_crc_err;
621 621 spacewire_stats.early_ep = spacewire_stats_backup.early_ep
622 622 + spacewire_stats_grspw.early_ep;
623 623 spacewire_stats.invalid_address = spacewire_stats_backup.invalid_address
624 624 + spacewire_stats_grspw.invalid_address;
625 625 spacewire_stats.rx_eep_err = spacewire_stats_backup.rx_eep_err
626 626 + spacewire_stats_grspw.rx_eep_err;
627 627 spacewire_stats.rx_truncated = spacewire_stats_backup.rx_truncated
628 628 + spacewire_stats_grspw.rx_truncated;
629 629 //spacewire_stats.tx_link_err;
630 630
631 631 //****************************
632 632 // DPU_SPACEWIRE_IF_STATISTICS
633 633 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[0] = (unsigned char) (spacewire_stats.packets_received >> 8);
634 634 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[1] = (unsigned char) (spacewire_stats.packets_received);
635 635 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[0] = (unsigned char) (spacewire_stats.packets_sent >> 8);
636 636 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[1] = (unsigned char) (spacewire_stats.packets_sent);
637 637 //housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt;
638 638 //housekeeping_packet.hk_lfr_dpu_spw_last_timc;
639 639
640 640 //******************************************
641 641 // ERROR COUNTERS / SPACEWIRE / LOW SEVERITY
642 642 housekeeping_packet.hk_lfr_dpu_spw_parity = (unsigned char) spacewire_stats.parity_err;
643 643 housekeeping_packet.hk_lfr_dpu_spw_disconnect = (unsigned char) spacewire_stats.disconnect_err;
644 644 housekeeping_packet.hk_lfr_dpu_spw_escape = (unsigned char) spacewire_stats.escape_err;
645 645 housekeeping_packet.hk_lfr_dpu_spw_credit = (unsigned char) spacewire_stats.credit_err;
646 646 housekeeping_packet.hk_lfr_dpu_spw_write_sync = (unsigned char) spacewire_stats.write_sync_err;
647 647
648 648 //*********************************************
649 649 // ERROR COUNTERS / SPACEWIRE / MEDIUM SEVERITY
650 650 housekeeping_packet.hk_lfr_dpu_spw_early_eop = (unsigned char) spacewire_stats.early_ep;
651 651 housekeeping_packet.hk_lfr_dpu_spw_invalid_addr = (unsigned char) spacewire_stats.invalid_address;
652 652 housekeeping_packet.hk_lfr_dpu_spw_eep = (unsigned char) spacewire_stats.rx_eep_err;
653 653 housekeeping_packet.hk_lfr_dpu_spw_rx_too_big = (unsigned char) spacewire_stats.rx_truncated;
654 654 }
655 655
656 656 void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc )
657 657 {
658 658 // a valid timecode has been received, write it in the HK report
659 659 unsigned int * grspwPtr;
660 660
661 661 grspwPtr = (unsigned int *) (REGS_ADDR_GRSPW + APB_OFFSET_GRSPW_TIME_REGISTER);
662 662
663 663 housekeeping_packet.hk_lfr_dpu_spw_last_timc = (unsigned char) (grspwPtr[0] & 0x3f); // [11 1111]
664 664
665 665 // update the number of valid timecodes that have been received
666 666 if (housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt == 255)
667 667 {
668 668 housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt = 0;
669 669 }
670 670 else
671 671 {
672 672 housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt = housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt + 1;
673 673 }
674 674 }
675 675
676 676 rtems_timer_service_routine user_routine( rtems_id timer_id, void *user_data )
677 677 {
678 678 int linkStatus;
679 679 rtems_status_code status;
680 680
681 681 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
682 682
683 683 if ( linkStatus == 5) {
684 684 PRINTF("in spacewire_reset_link *** link is running\n")
685 685 status = RTEMS_SUCCESSFUL;
686 686 }
687 687 }
688 688
689 689 void init_header_cwf( Header_TM_LFR_SCIENCE_CWF_t *header )
690 690 {
691 691 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
692 692 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
693 693 header->reserved = DEFAULT_RESERVED;
694 694 header->userApplication = CCSDS_USER_APP;
695 695 header->packetSequenceControl[0]= TM_PACKET_SEQ_CTRL_STANDALONE;
696 696 header->packetSequenceControl[1]= TM_PACKET_SEQ_CNT_DEFAULT;
697 697 header->packetLength[0] = 0x00;
698 698 header->packetLength[1] = 0x00;
699 699 // DATA FIELD HEADER
700 700 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
701 701 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
702 702 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE; // service subtype
703 703 header->destinationID = TM_DESTINATION_ID_GROUND;
704 704 header->time[0] = 0x00;
705 705 header->time[0] = 0x00;
706 706 header->time[0] = 0x00;
707 707 header->time[0] = 0x00;
708 708 header->time[0] = 0x00;
709 709 header->time[0] = 0x00;
710 710 // AUXILIARY DATA HEADER
711 711 header->sid = 0x00;
712 712 header->hkBIA = DEFAULT_HKBIA;
713 713 header->blkNr[0] = 0x00;
714 714 header->blkNr[1] = 0x00;
715 715 }
716 716
717 717 void init_header_swf( Header_TM_LFR_SCIENCE_SWF_t *header )
718 718 {
719 719 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
720 720 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
721 721 header->reserved = DEFAULT_RESERVED;
722 722 header->userApplication = CCSDS_USER_APP;
723 723 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
724 724 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
725 725 header->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
726 726 header->packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
727 727 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_336 >> 8);
728 728 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_336 );
729 729 // DATA FIELD HEADER
730 730 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
731 731 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
732 732 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE; // service subtype
733 733 header->destinationID = TM_DESTINATION_ID_GROUND;
734 734 header->time[0] = 0x00;
735 735 header->time[0] = 0x00;
736 736 header->time[0] = 0x00;
737 737 header->time[0] = 0x00;
738 738 header->time[0] = 0x00;
739 739 header->time[0] = 0x00;
740 740 // AUXILIARY DATA HEADER
741 741 header->sid = 0x00;
742 742 header->hkBIA = DEFAULT_HKBIA;
743 743 header->pktCnt = DEFAULT_PKTCNT; // PKT_CNT
744 744 header->pktNr = 0x00;
745 745 header->blkNr[0] = (unsigned char) (BLK_NR_CWF >> 8);
746 746 header->blkNr[1] = (unsigned char) (BLK_NR_CWF );
747 747 }
748 748
749 749 void init_header_asm( Header_TM_LFR_SCIENCE_ASM_t *header )
750 750 {
751 751 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
752 752 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
753 753 header->reserved = DEFAULT_RESERVED;
754 754 header->userApplication = CCSDS_USER_APP;
755 755 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
756 756 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
757 757 header->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
758 758 header->packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
759 759 header->packetLength[0] = 0x00;
760 760 header->packetLength[1] = 0x00;
761 761 // DATA FIELD HEADER
762 762 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
763 763 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
764 764 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE; // service subtype
765 765 header->destinationID = TM_DESTINATION_ID_GROUND;
766 766 header->time[0] = 0x00;
767 767 header->time[0] = 0x00;
768 768 header->time[0] = 0x00;
769 769 header->time[0] = 0x00;
770 770 header->time[0] = 0x00;
771 771 header->time[0] = 0x00;
772 772 // AUXILIARY DATA HEADER
773 773 header->sid = 0x00;
774 774 header->biaStatusInfo = 0x00;
775 775 header->pa_lfr_pkt_cnt_asm = 0x00;
776 776 header->pa_lfr_pkt_nr_asm = 0x00;
777 777 header->pa_lfr_asm_blk_nr[0] = 0x00;
778 778 header->pa_lfr_asm_blk_nr[1] = 0x00;
779 779 }
780 780
781 781 int spw_send_waveform_CWF( ring_node *ring_node_to_send,
782 782 Header_TM_LFR_SCIENCE_CWF_t *header )
783 783 {
784 784 /** This function sends CWF CCSDS packets (F2, F1 or F0).
785 785 *
786 786 * @param waveform points to the buffer containing the data that will be send.
787 787 * @param sid is the source identifier of the data that will be sent.
788 788 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
789 789 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
790 790 * contain information to setup the transmission of the data packets.
791 791 *
792 792 * One group of 2048 samples is sent as 7 consecutive packets, 6 packets containing 340 blocks and 8 packets containing 8 blocks.
793 793 *
794 794 */
795 795
796 796 unsigned int i;
797 797 int ret;
798 798 unsigned int coarseTime;
799 799 unsigned int fineTime;
800 800 rtems_status_code status;
801 801 spw_ioctl_pkt_send spw_ioctl_send_CWF;
802 802 int *dataPtr;
803 803 unsigned char sid;
804 804
805 805 spw_ioctl_send_CWF.hlen = TM_HEADER_LEN + 4 + 10; // + 4 is for the protocole extra header, + 10 is for the auxiliary header
806 806 spw_ioctl_send_CWF.options = 0;
807 807
808 808 ret = LFR_DEFAULT;
809 809 sid = (unsigned char) ring_node_to_send->sid;
810 810
811 811 coarseTime = ring_node_to_send->coarseTime;
812 812 fineTime = ring_node_to_send->fineTime;
813 813 dataPtr = (int*) ring_node_to_send->buffer_address;
814 814
815 815 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_336 >> 8);
816 816 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_336 );
817 817 header->blkNr[0] = (unsigned char) (BLK_NR_CWF >> 8);
818 818 header->blkNr[1] = (unsigned char) (BLK_NR_CWF );
819 819
820 820 for (i=0; i<NB_PACKETS_PER_GROUP_OF_CWF; i++) // send waveform
821 821 {
822 822 spw_ioctl_send_CWF.data = (char*) &dataPtr[ (i * BLK_NR_CWF * NB_WORDS_SWF_BLK) ];
823 823 spw_ioctl_send_CWF.hdr = (char*) header;
824 824 // BUILD THE DATA
825 825 spw_ioctl_send_CWF.dlen = BLK_NR_CWF * NB_BYTES_SWF_BLK;
826 826
827 827 // SET PACKET SEQUENCE CONTROL
828 828 increment_seq_counter_source_id( header->packetSequenceControl, sid );
829 829
830 830 // SET SID
831 831 header->sid = sid;
832 832
833 833 // SET PACKET TIME
834 834 compute_acquisition_time( coarseTime, fineTime, sid, i, header->acquisitionTime);
835 835 //
836 836 header->time[0] = header->acquisitionTime[0];
837 837 header->time[1] = header->acquisitionTime[1];
838 838 header->time[2] = header->acquisitionTime[2];
839 839 header->time[3] = header->acquisitionTime[3];
840 840 header->time[4] = header->acquisitionTime[4];
841 841 header->time[5] = header->acquisitionTime[5];
842 842
843 843 // SET PACKET ID
844 844 if ( (sid == SID_SBM1_CWF_F1) || (sid == SID_SBM2_CWF_F2) )
845 845 {
846 846 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_SBM1_SBM2 >> 8);
847 847 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_SBM1_SBM2);
848 848 }
849 849 else
850 850 {
851 851 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
852 852 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
853 853 }
854 854
855 855 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF );
856 856 if (status != RTEMS_SUCCESSFUL) {
857 857 printf("%d-%d, ERR %d\n", sid, i, (int) status);
858 858 ret = LFR_DEFAULT;
859 859 }
860 860 }
861 861
862 862 return ret;
863 863 }
864 864
865 865 int spw_send_waveform_SWF( ring_node *ring_node_to_send,
866 866 Header_TM_LFR_SCIENCE_SWF_t *header )
867 867 {
868 868 /** This function sends SWF CCSDS packets (F2, F1 or F0).
869 869 *
870 870 * @param waveform points to the buffer containing the data that will be send.
871 871 * @param sid is the source identifier of the data that will be sent.
872 872 * @param headerSWF points to a table of headers that have been prepared for the data transmission.
873 873 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
874 874 * contain information to setup the transmission of the data packets.
875 875 *
876 876 * One group of 2048 samples is sent as 7 consecutive packets, 6 packets containing 340 blocks and 8 packets containing 8 blocks.
877 877 *
878 878 */
879 879
880 880 unsigned int i;
881 881 int ret;
882 882 unsigned int coarseTime;
883 883 unsigned int fineTime;
884 884 rtems_status_code status;
885 885 spw_ioctl_pkt_send spw_ioctl_send_SWF;
886 886 int *dataPtr;
887 887 unsigned char sid;
888 888
889 889 spw_ioctl_send_SWF.hlen = TM_HEADER_LEN + 4 + 12; // + 4 is for the protocole extra header, + 12 is for the auxiliary header
890 890 spw_ioctl_send_SWF.options = 0;
891 891
892 892 ret = LFR_DEFAULT;
893 893
894 894 coarseTime = ring_node_to_send->coarseTime;
895 895 fineTime = ring_node_to_send->fineTime;
896 896 dataPtr = (int*) ring_node_to_send->buffer_address;
897 897 sid = ring_node_to_send->sid;
898 898
899 899 for (i=0; i<7; i++) // send waveform
900 900 {
901 901 spw_ioctl_send_SWF.data = (char*) &dataPtr[ (i * BLK_NR_304 * NB_WORDS_SWF_BLK) ];
902 902 spw_ioctl_send_SWF.hdr = (char*) header;
903 903
904 904 // SET PACKET SEQUENCE CONTROL
905 905 increment_seq_counter_source_id( header->packetSequenceControl, sid );
906 906
907 907 // SET PACKET LENGTH AND BLKNR
908 908 if (i == 6)
909 909 {
910 910 spw_ioctl_send_SWF.dlen = BLK_NR_224 * NB_BYTES_SWF_BLK;
911 911 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_SWF_224 >> 8);
912 912 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_SWF_224 );
913 913 header->blkNr[0] = (unsigned char) (BLK_NR_224 >> 8);
914 914 header->blkNr[1] = (unsigned char) (BLK_NR_224 );
915 915 }
916 916 else
917 917 {
918 918 spw_ioctl_send_SWF.dlen = BLK_NR_304 * NB_BYTES_SWF_BLK;
919 919 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_SWF_304 >> 8);
920 920 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_SWF_304 );
921 921 header->blkNr[0] = (unsigned char) (BLK_NR_304 >> 8);
922 922 header->blkNr[1] = (unsigned char) (BLK_NR_304 );
923 923 }
924 924
925 925 // SET PACKET TIME
926 926 compute_acquisition_time( coarseTime, fineTime, sid, i, header->acquisitionTime );
927 927 //
928 928 header->time[0] = header->acquisitionTime[0];
929 929 header->time[1] = header->acquisitionTime[1];
930 930 header->time[2] = header->acquisitionTime[2];
931 931 header->time[3] = header->acquisitionTime[3];
932 932 header->time[4] = header->acquisitionTime[4];
933 933 header->time[5] = header->acquisitionTime[5];
934 934
935 935 // SET SID
936 936 header->sid = sid;
937 937
938 938 // SET PKTNR
939 939 header->pktNr = i+1; // PKT_NR
940 940
941 941 // SEND PACKET
942 942 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_SWF );
943 943 if (status != RTEMS_SUCCESSFUL) {
944 944 printf("%d-%d, ERR %d\n", sid, i, (int) status);
945 945 ret = LFR_DEFAULT;
946 946 }
947 947 }
948 948
949 949 return ret;
950 950 }
951 951
952 952 int spw_send_waveform_CWF3_light( ring_node *ring_node_to_send,
953 953 Header_TM_LFR_SCIENCE_CWF_t *header )
954 954 {
955 955 /** This function sends CWF_F3 CCSDS packets without the b1, b2 and b3 data.
956 956 *
957 957 * @param waveform points to the buffer containing the data that will be send.
958 958 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
959 959 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
960 960 * contain information to setup the transmission of the data packets.
961 961 *
962 962 * By default, CWF_F3 packet are send without the b1, b2 and b3 data. This function rebuilds a data buffer
963 963 * from the incoming data and sends it in 7 packets, 6 containing 340 blocks and 1 one containing 8 blocks.
964 964 *
965 965 */
966 966
967 967 unsigned int i;
968 968 int ret;
969 969 unsigned int coarseTime;
970 970 unsigned int fineTime;
971 971 rtems_status_code status;
972 972 spw_ioctl_pkt_send spw_ioctl_send_CWF;
973 973 char *dataPtr;
974 974 unsigned char sid;
975 975
976 976 spw_ioctl_send_CWF.hlen = TM_HEADER_LEN + 4 + 10; // + 4 is for the protocole extra header, + 10 is for the auxiliary header
977 977 spw_ioctl_send_CWF.options = 0;
978 978
979 979 ret = LFR_DEFAULT;
980 980 sid = ring_node_to_send->sid;
981 981
982 982 coarseTime = ring_node_to_send->coarseTime;
983 983 fineTime = ring_node_to_send->fineTime;
984 984 dataPtr = (char*) ring_node_to_send->buffer_address;
985 985
986 986 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_672 >> 8);
987 987 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_672 );
988 988 header->blkNr[0] = (unsigned char) (BLK_NR_CWF_SHORT_F3 >> 8);
989 989 header->blkNr[1] = (unsigned char) (BLK_NR_CWF_SHORT_F3 );
990 990
991 printf("spw_send_waveform_CWF3_light => [0] = %x, [1] = %x, [2] = %x, [3] = %x, [4] = %x, [5] = %x\n",
992 dataPtr[0], dataPtr[1], dataPtr[2], dataPtr[3], dataPtr[4], dataPtr[5]);
993
994 991 //*********************
995 992 // SEND CWF3_light DATA
996 993 for (i=0; i<NB_PACKETS_PER_GROUP_OF_CWF_LIGHT; i++) // send waveform
997 994 {
998 995 spw_ioctl_send_CWF.data = (char*) &dataPtr[ (i * BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK) ];
999 996 spw_ioctl_send_CWF.hdr = (char*) header;
1000 997 // BUILD THE DATA
1001 998 spw_ioctl_send_CWF.dlen = BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK;
1002 999
1003 1000 // SET PACKET SEQUENCE COUNTER
1004 1001 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1005 1002
1006 1003 // SET SID
1007 1004 header->sid = sid;
1008 1005
1009 1006 // SET PACKET TIME
1010 1007 compute_acquisition_time( coarseTime, fineTime, SID_NORM_CWF_F3, i, header->acquisitionTime );
1011 1008 //
1012 1009 header->time[0] = header->acquisitionTime[0];
1013 1010 header->time[1] = header->acquisitionTime[1];
1014 1011 header->time[2] = header->acquisitionTime[2];
1015 1012 header->time[3] = header->acquisitionTime[3];
1016 1013 header->time[4] = header->acquisitionTime[4];
1017 1014 header->time[5] = header->acquisitionTime[5];
1018 1015
1019 1016 // SET PACKET ID
1020 1017 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
1021 1018 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1022 1019
1023 1020 // SEND PACKET
1024 1021 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF );
1025 1022 if (status != RTEMS_SUCCESSFUL) {
1026 1023 printf("%d-%d, ERR %d\n", sid, i, (int) status);
1027 1024 ret = LFR_DEFAULT;
1028 1025 }
1029 1026 }
1030 1027
1031 1028 return ret;
1032 1029 }
1033 1030
1034 1031 void spw_send_asm( ring_node *ring_node_to_send,
1035 1032 Header_TM_LFR_SCIENCE_ASM_t *header )
1036 1033 {
1037 1034 unsigned int i;
1038 1035 unsigned int length = 0;
1039 1036 rtems_status_code status;
1040 1037 unsigned int sid;
1041 1038 char *spectral_matrix;
1042 1039 int coarseTime;
1043 1040 int fineTime;
1044 1041 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1045 1042
1046 1043 sid = ring_node_to_send->sid;
1047 1044 spectral_matrix = (char*) ring_node_to_send->buffer_address;
1048 1045 coarseTime = ring_node_to_send->coarseTime;
1049 1046 fineTime = ring_node_to_send->fineTime;
1050 1047
1051 1048 for (i=0; i<2; i++)
1052 1049 {
1053 1050 // (1) BUILD THE DATA
1054 1051 switch(sid)
1055 1052 {
1056 1053 case SID_NORM_ASM_F0:
1057 1054 spw_ioctl_send_ASM.dlen = TOTAL_SIZE_ASM_F0_IN_BYTES / 2; // 2 packets will be sent
1058 1055 spw_ioctl_send_ASM.data = &spectral_matrix[
1059 1056 ( (ASM_F0_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F0) ) * NB_VALUES_PER_SM ) * 2
1060 1057 ];
1061 1058 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F0;
1062 1059 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F0) >> 8 ); // BLK_NR MSB
1063 1060 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F0); // BLK_NR LSB
1064 1061 break;
1065 1062 case SID_NORM_ASM_F1:
1066 1063 spw_ioctl_send_ASM.dlen = TOTAL_SIZE_ASM_F1_IN_BYTES / 2; // 2 packets will be sent
1067 1064 spw_ioctl_send_ASM.data = &spectral_matrix[
1068 1065 ( (ASM_F1_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F1) ) * NB_VALUES_PER_SM ) * 2
1069 1066 ];
1070 1067 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F1;
1071 1068 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F1) >> 8 ); // BLK_NR MSB
1072 1069 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F1); // BLK_NR LSB
1073 1070 break;
1074 1071 case SID_NORM_ASM_F2:
1075 1072 spw_ioctl_send_ASM.dlen = TOTAL_SIZE_ASM_F2_IN_BYTES / 2; // 2 packets will be sent
1076 1073 spw_ioctl_send_ASM.data = &spectral_matrix[
1077 1074 ( (ASM_F2_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F2) ) * NB_VALUES_PER_SM ) * 2
1078 1075 ];
1079 1076 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F2;
1080 1077 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F2) >> 8 ); // BLK_NR MSB
1081 1078 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F2); // BLK_NR LSB
1082 1079 break;
1083 1080 default:
1084 1081 PRINTF1("ERR *** in spw_send_asm *** unexpected sid %d\n", sid)
1085 1082 break;
1086 1083 }
1087 1084 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM + CCSDS_PROTOCOLE_EXTRA_BYTES;
1088 1085 spw_ioctl_send_ASM.hdr = (char *) header;
1089 1086 spw_ioctl_send_ASM.options = 0;
1090 1087
1091 1088 // (2) BUILD THE HEADER
1092 1089 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1093 1090 header->packetLength[0] = (unsigned char) (length>>8);
1094 1091 header->packetLength[1] = (unsigned char) (length);
1095 1092 header->sid = (unsigned char) sid; // SID
1096 1093 header->pa_lfr_pkt_cnt_asm = 2;
1097 1094 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1098 1095
1099 1096 // (3) SET PACKET TIME
1100 1097 header->time[0] = (unsigned char) (coarseTime>>24);
1101 1098 header->time[1] = (unsigned char) (coarseTime>>16);
1102 1099 header->time[2] = (unsigned char) (coarseTime>>8);
1103 1100 header->time[3] = (unsigned char) (coarseTime);
1104 1101 header->time[4] = (unsigned char) (fineTime>>8);
1105 1102 header->time[5] = (unsigned char) (fineTime);
1106 1103 //
1107 1104 header->acquisitionTime[0] = header->time[0];
1108 1105 header->acquisitionTime[1] = header->time[1];
1109 1106 header->acquisitionTime[2] = header->time[2];
1110 1107 header->acquisitionTime[3] = header->time[3];
1111 1108 header->acquisitionTime[4] = header->time[4];
1112 1109 header->acquisitionTime[5] = header->time[5];
1113 1110
1114 1111 // (4) SEND PACKET
1115 1112 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1116 1113 if (status != RTEMS_SUCCESSFUL) {
1117 1114 printf("in ASM_send *** ERR %d\n", (int) status);
1118 1115 }
1119 1116 }
1120 1117 }
@@ -1,1402 +1,1402
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 extractSWF = false;
35 35 bool swf_f0_ready = false;
36 36 bool swf_f1_ready = false;
37 37 bool swf_f2_ready = false;
38 38
39 39 int wf_snap_extracted[ (NB_SAMPLES_PER_SNAPSHOT * NB_WORDS_SWF_BLK) ];
40 40 ring_node ring_node_wf_snap_extracted;
41 41
42 42 //*********************
43 43 // Interrupt SubRoutine
44 44
45 45 ring_node * getRingNodeToSendCWF( unsigned char frequencyChannel)
46 46 {
47 47 ring_node *node;
48 48
49 49 node = NULL;
50 50 switch ( frequencyChannel ) {
51 51 case 1:
52 52 node = ring_node_to_send_cwf_f1;
53 53 break;
54 54 case 2:
55 55 node = ring_node_to_send_cwf_f2;
56 56 break;
57 57 case 3:
58 58 node = ring_node_to_send_cwf_f3;
59 59 break;
60 60 default:
61 61 break;
62 62 }
63 63
64 64 return node;
65 65 }
66 66
67 67 ring_node * getRingNodeToSendSWF( unsigned char frequencyChannel)
68 68 {
69 69 ring_node *node;
70 70
71 71 node = NULL;
72 72 switch ( frequencyChannel ) {
73 73 case 0:
74 74 node = ring_node_to_send_swf_f0;
75 75 break;
76 76 case 1:
77 77 node = ring_node_to_send_swf_f1;
78 78 break;
79 79 case 2:
80 80 node = ring_node_to_send_swf_f2;
81 81 break;
82 82 default:
83 83 break;
84 84 }
85 85
86 86 return node;
87 87 }
88 88
89 89 void reset_extractSWF( void )
90 90 {
91 91 extractSWF = false;
92 92 swf_f0_ready = false;
93 93 swf_f1_ready = false;
94 94 swf_f2_ready = false;
95 95 }
96 96
97 97 inline void waveforms_isr_f3( void )
98 98 {
99 99 rtems_status_code spare_status;
100 100
101 101 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
102 102 || (lfrCurrentMode == LFR_MODE_SBM1) || (lfrCurrentMode == LFR_MODE_SBM2) )
103 103 { // in modes other than STANDBY and BURST, send the CWF_F3 data
104 104 //***
105 105 // F3
106 106 if ( (waveform_picker_regs->status & 0xc0) != 0x00 ) { // [1100 0000] check the f3 full bits
107 107 ring_node_to_send_cwf_f3 = current_ring_node_f3->previous;
108 108 current_ring_node_f3 = current_ring_node_f3->next;
109 109 if ((waveform_picker_regs->status & 0x40) == 0x40){ // [0100 0000] f3 buffer 0 is full
110 110 ring_node_to_send_cwf_f3->coarseTime = waveform_picker_regs->f3_0_coarse_time;
111 111 ring_node_to_send_cwf_f3->fineTime = waveform_picker_regs->f3_0_fine_time;
112 112 waveform_picker_regs->addr_data_f3_0 = current_ring_node_f3->buffer_address;
113 113 waveform_picker_regs->status = waveform_picker_regs->status & 0x00008840; // [1000 1000 0100 0000]
114 114 }
115 115 else if ((waveform_picker_regs->status & 0x80) == 0x80){ // [1000 0000] f3 buffer 1 is full
116 116 ring_node_to_send_cwf_f3->coarseTime = waveform_picker_regs->f3_1_coarse_time;
117 117 ring_node_to_send_cwf_f3->fineTime = waveform_picker_regs->f3_1_fine_time;
118 118 waveform_picker_regs->addr_data_f3_1 = current_ring_node_f3->buffer_address;
119 119 waveform_picker_regs->status = waveform_picker_regs->status & 0x00008880; // [1000 1000 1000 0000]
120 120 }
121 121 if (rtems_event_send( Task_id[TASKID_CWF3], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) {
122 122 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 );
123 123 }
124 124 }
125 125 }
126 126 }
127 127
128 128 inline void waveforms_isr_normal( void )
129 129 {
130 130 rtems_status_code status;
131 131
132 132 if ( ( (waveform_picker_regs->status & 0x30) != 0x00 ) // [0011 0000] check the f2 full bits
133 133 && ( (waveform_picker_regs->status & 0x0c) != 0x00 ) // [0000 1100] check the f1 full bits
134 134 && ( (waveform_picker_regs->status & 0x03) != 0x00 )) // [0000 0011] check the f0 full bits
135 135 {
136 136 //***
137 137 // F0
138 138 ring_node_to_send_swf_f0 = current_ring_node_f0->previous;
139 139 current_ring_node_f0 = current_ring_node_f0->next;
140 140 if ( (waveform_picker_regs->status & 0x01) == 0x01)
141 141 {
142 142
143 143 ring_node_to_send_swf_f0->coarseTime = waveform_picker_regs->f0_0_coarse_time;
144 144 ring_node_to_send_swf_f0->fineTime = waveform_picker_regs->f0_0_fine_time;
145 145 waveform_picker_regs->addr_data_f0_0 = current_ring_node_f0->buffer_address;
146 146 waveform_picker_regs->status = waveform_picker_regs->status & 0x00001101; // [0001 0001 0000 0001]
147 147 }
148 148 else if ( (waveform_picker_regs->status & 0x02) == 0x02)
149 149 {
150 150 ring_node_to_send_swf_f0->coarseTime = waveform_picker_regs->f0_1_coarse_time;
151 151 ring_node_to_send_swf_f0->fineTime = waveform_picker_regs->f0_1_fine_time;
152 152 waveform_picker_regs->addr_data_f0_1 = current_ring_node_f0->buffer_address;
153 153 waveform_picker_regs->status = waveform_picker_regs->status & 0x00001102; // [0001 0001 0000 0010]
154 154 }
155 155
156 156 //***
157 157 // F1
158 158 ring_node_to_send_swf_f1 = current_ring_node_f1->previous;
159 159 current_ring_node_f1 = current_ring_node_f1->next;
160 160 if ( (waveform_picker_regs->status & 0x04) == 0x04)
161 161 {
162 162 ring_node_to_send_swf_f1->coarseTime = waveform_picker_regs->f1_0_coarse_time;
163 163 ring_node_to_send_swf_f1->fineTime = waveform_picker_regs->f1_0_fine_time;
164 164 waveform_picker_regs->addr_data_f1_0 = current_ring_node_f1->buffer_address;
165 165 waveform_picker_regs->status = waveform_picker_regs->status & 0x00002204; // [0010 0010 0000 0100] f1 bits = 0
166 166 }
167 167 else if ( (waveform_picker_regs->status & 0x08) == 0x08)
168 168 {
169 169 ring_node_to_send_swf_f1->coarseTime = waveform_picker_regs->f1_1_coarse_time;
170 170 ring_node_to_send_swf_f1->fineTime = waveform_picker_regs->f1_1_fine_time;
171 171 waveform_picker_regs->addr_data_f1_1 = current_ring_node_f1->buffer_address;
172 172 waveform_picker_regs->status = waveform_picker_regs->status & 0x00002208; // [0010 0010 0000 1000] f1 bits = 0
173 173 }
174 174
175 175 //***
176 176 // F2
177 177 ring_node_to_send_swf_f2 = current_ring_node_f2->previous;
178 178 current_ring_node_f2 = current_ring_node_f2->next;
179 179 if ( (waveform_picker_regs->status & 0x10) == 0x10)
180 180 {
181 181 ring_node_to_send_swf_f2->coarseTime = waveform_picker_regs->f2_0_coarse_time;
182 182 ring_node_to_send_swf_f2->fineTime = waveform_picker_regs->f2_0_fine_time;
183 183 waveform_picker_regs->addr_data_f2_0 = current_ring_node_f2->buffer_address;
184 184 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004410; // [0100 0100 0001 0000]
185 185 }
186 186 else if ( (waveform_picker_regs->status & 0x20) == 0x20)
187 187 {
188 188 ring_node_to_send_swf_f2->coarseTime = waveform_picker_regs->f2_1_coarse_time;
189 189 ring_node_to_send_swf_f2->fineTime = waveform_picker_regs->f2_1_fine_time;
190 190 waveform_picker_regs->addr_data_f2_1 = current_ring_node_f2->buffer_address;
191 191 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004420; // [0100 0100 0010 0000]
192 192 }
193 193 //
194 194 status = rtems_event_send( Task_id[TASKID_WFRM], RTEMS_EVENT_MODE_NORMAL );
195 195 if ( status != RTEMS_SUCCESSFUL)
196 196 {
197 197 status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 );
198 198 }
199 199 }
200 200 }
201 201
202 202 inline void waveforms_isr_burst( void )
203 203 {
204 204 unsigned char status;
205 205 rtems_status_code spare_status;
206 206
207 207 status = (waveform_picker_regs->status & 0x30) >> 4; // [0011 0000] get the status bits for f2
208 208
209 209
210 210 switch(status)
211 211 {
212 212 case 1:
213 213 ring_node_to_send_cwf_f2 = current_ring_node_f2->previous;
214 214 ring_node_to_send_cwf_f2->sid = SID_BURST_CWF_F2;
215 current_ring_node_f2 = current_ring_node_f2->next;
216 215 ring_node_to_send_cwf_f2->coarseTime = waveform_picker_regs->f2_0_coarse_time;
217 216 ring_node_to_send_cwf_f2->fineTime = waveform_picker_regs->f2_0_fine_time;
217 current_ring_node_f2 = current_ring_node_f2->next;
218 218 waveform_picker_regs->addr_data_f2_0 = current_ring_node_f2->buffer_address;
219 219 if (rtems_event_send( Task_id[TASKID_CWF2], RTEMS_EVENT_MODE_BURST ) != RTEMS_SUCCESSFUL) {
220 220 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 );
221 221 }
222 222 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004410; // [0100 0100 0001 0000]
223 223 break;
224 224 case 2:
225 225 ring_node_to_send_cwf_f2 = current_ring_node_f2->previous;
226 226 ring_node_to_send_cwf_f2->sid = SID_BURST_CWF_F2;
227 current_ring_node_f2 = current_ring_node_f2->next;
228 227 ring_node_to_send_cwf_f2->coarseTime = waveform_picker_regs->f2_1_coarse_time;
229 228 ring_node_to_send_cwf_f2->fineTime = waveform_picker_regs->f2_1_fine_time;
229 current_ring_node_f2 = current_ring_node_f2->next;
230 230 waveform_picker_regs->addr_data_f2_1 = current_ring_node_f2->buffer_address;
231 231 if (rtems_event_send( Task_id[TASKID_CWF2], RTEMS_EVENT_MODE_BURST ) != RTEMS_SUCCESSFUL) {
232 232 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 );
233 233 }
234 234 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004420; // [0100 0100 0010 0000]
235 235 break;
236 236 default:
237 237 break;
238 238 }
239 239 }
240 240
241 241 inline void waveforms_isr_sbm1( void )
242 242 {
243 243 rtems_status_code status;
244 244
245 245 //***
246 246 // F1
247 247 if ( (waveform_picker_regs->status & 0x0c) != 0x00 ) { // [0000 1100] check the f1 full bits
248 248 // (1) change the receiving buffer for the waveform picker
249 249 ring_node_to_send_cwf_f1 = current_ring_node_f1->previous;
250 250 current_ring_node_f1 = current_ring_node_f1->next;
251 251 if ( (waveform_picker_regs->status & 0x04) == 0x04)
252 252 {
253 253 ring_node_to_send_cwf_f1->coarseTime = waveform_picker_regs->f1_0_coarse_time;
254 254 ring_node_to_send_cwf_f1->fineTime = waveform_picker_regs->f1_0_fine_time;
255 255 waveform_picker_regs->addr_data_f1_0 = current_ring_node_f1->buffer_address;
256 256 waveform_picker_regs->status = waveform_picker_regs->status & 0x00002204; // [0010 0010 0000 0100] f1 bits = 0
257 257 }
258 258 else if ( (waveform_picker_regs->status & 0x08) == 0x08)
259 259 {
260 260 ring_node_to_send_cwf_f1->coarseTime = waveform_picker_regs->f1_1_coarse_time;
261 261 ring_node_to_send_cwf_f1->fineTime = waveform_picker_regs->f1_1_fine_time;
262 262 waveform_picker_regs->addr_data_f1_1 = current_ring_node_f1->buffer_address;
263 263 waveform_picker_regs->status = waveform_picker_regs->status & 0x00002208; // [0010 0010 0000 1000] f1 bits = 0
264 264 }
265 265 // (2) send an event for the the CWF1 task for transmission (and snapshot extraction if needed)
266 266 status = rtems_event_send( Task_id[TASKID_CWF1], RTEMS_EVENT_MODE_SBM1 );
267 267 }
268 268
269 269 //***
270 270 // F0
271 271 if ( (waveform_picker_regs->status & 0x03) != 0x00 ) { // [0000 0011] check the f0 full bits
272 272 swf_f0_ready = true;
273 273 // change f0 buffer
274 274 ring_node_to_send_swf_f0 = current_ring_node_f0->previous;
275 275 current_ring_node_f0 = current_ring_node_f0->next;
276 276 if ( (waveform_picker_regs->status & 0x01) == 0x01)
277 277 {
278 278
279 279 ring_node_to_send_swf_f0->coarseTime = waveform_picker_regs->f0_0_coarse_time;
280 280 ring_node_to_send_swf_f0->fineTime = waveform_picker_regs->f0_0_fine_time;
281 281 waveform_picker_regs->addr_data_f0_0 = current_ring_node_f0->buffer_address;
282 282 waveform_picker_regs->status = waveform_picker_regs->status & 0x00001101; // [0001 0001 0000 0001]
283 283 }
284 284 else if ( (waveform_picker_regs->status & 0x02) == 0x02)
285 285 {
286 286 ring_node_to_send_swf_f0->coarseTime = waveform_picker_regs->f0_1_coarse_time;
287 287 ring_node_to_send_swf_f0->fineTime = waveform_picker_regs->f0_1_fine_time;
288 288 waveform_picker_regs->addr_data_f0_1 = current_ring_node_f0->buffer_address;
289 289 waveform_picker_regs->status = waveform_picker_regs->status & 0x00001102; // [0001 0001 0000 0010]
290 290 }
291 291 }
292 292
293 293 //***
294 294 // F2
295 295 if ( (waveform_picker_regs->status & 0x30) != 0x00 ) { // [0011 0000] check the f2 full bits
296 296 swf_f2_ready = true;
297 297 // change f2 buffer
298 298 ring_node_to_send_swf_f2 = current_ring_node_f2->previous;
299 299 current_ring_node_f2 = current_ring_node_f2->next;
300 300 if ( (waveform_picker_regs->status & 0x10) == 0x10)
301 301 {
302 302 ring_node_to_send_swf_f2->coarseTime = waveform_picker_regs->f2_0_coarse_time;
303 303 ring_node_to_send_swf_f2->fineTime = waveform_picker_regs->f2_0_fine_time;
304 304 waveform_picker_regs->addr_data_f2_0 = current_ring_node_f2->buffer_address;
305 305 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004410; // [0100 0100 0001 0000]
306 306 }
307 307 else if ( (waveform_picker_regs->status & 0x20) == 0x20)
308 308 {
309 309 ring_node_to_send_swf_f2->coarseTime = waveform_picker_regs->f2_1_coarse_time;
310 310 ring_node_to_send_swf_f2->fineTime = waveform_picker_regs->f2_1_fine_time;
311 311 waveform_picker_regs->addr_data_f2_1 = current_ring_node_f2->buffer_address;
312 312 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004420; // [0100 0100 0010 0000]
313 313 }
314 314 }
315 315 }
316 316
317 317 inline void waveforms_isr_sbm2( void )
318 318 {
319 319 rtems_status_code status;
320 320
321 321 //***
322 322 // F2
323 323 if ( (waveform_picker_regs->status & 0x30) != 0x00 ) { // [0011 0000] check the f2 full bit
324 324 // (1) change the receiving buffer for the waveform picker
325 325 ring_node_to_send_cwf_f2 = current_ring_node_f2->previous;
326 326 ring_node_to_send_cwf_f2->sid = SID_SBM2_CWF_F2;
327 327 current_ring_node_f2 = current_ring_node_f2->next;
328 328 if ( (waveform_picker_regs->status & 0x10) == 0x10)
329 329 {
330 330 ring_node_to_send_cwf_f2->coarseTime = waveform_picker_regs->f2_0_coarse_time;
331 331 ring_node_to_send_cwf_f2->fineTime = waveform_picker_regs->f2_0_fine_time;
332 332 waveform_picker_regs->addr_data_f2_0 = current_ring_node_f2->buffer_address;
333 333 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004410; // [0100 0100 0001 0000]
334 334 }
335 335 else if ( (waveform_picker_regs->status & 0x20) == 0x20)
336 336 {
337 337 ring_node_to_send_cwf_f2->coarseTime = waveform_picker_regs->f2_1_coarse_time;
338 338 ring_node_to_send_cwf_f2->fineTime = waveform_picker_regs->f2_1_fine_time;
339 339 waveform_picker_regs->addr_data_f2_1 = current_ring_node_f2->buffer_address;
340 340 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004420; // [0100 0100 0010 0000]
341 341 }
342 342 // (2) send an event for the waveforms transmission
343 343 status = rtems_event_send( Task_id[TASKID_CWF2], RTEMS_EVENT_MODE_SBM2 );
344 344 }
345 345
346 346 //***
347 347 // F0
348 348 if ( (waveform_picker_regs->status & 0x03) != 0x00 ) { // [0000 0011] check the f0 full bit
349 349 swf_f0_ready = true;
350 350 // change f0 buffer
351 351 ring_node_to_send_swf_f0 = current_ring_node_f0->previous;
352 352 current_ring_node_f0 = current_ring_node_f0->next;
353 353 if ( (waveform_picker_regs->status & 0x01) == 0x01)
354 354 {
355 355
356 356 ring_node_to_send_swf_f0->coarseTime = waveform_picker_regs->f0_0_coarse_time;
357 357 ring_node_to_send_swf_f0->fineTime = waveform_picker_regs->f0_0_fine_time;
358 358 waveform_picker_regs->addr_data_f0_0 = current_ring_node_f0->buffer_address;
359 359 waveform_picker_regs->status = waveform_picker_regs->status & 0x00001101; // [0001 0001 0000 0001]
360 360 }
361 361 else if ( (waveform_picker_regs->status & 0x02) == 0x02)
362 362 {
363 363 ring_node_to_send_swf_f0->coarseTime = waveform_picker_regs->f0_1_coarse_time;
364 364 ring_node_to_send_swf_f0->fineTime = waveform_picker_regs->f0_1_fine_time;
365 365 waveform_picker_regs->addr_data_f0_1 = current_ring_node_f0->buffer_address;
366 366 waveform_picker_regs->status = waveform_picker_regs->status & 0x00001102; // [0001 0001 0000 0010]
367 367 }
368 368 }
369 369
370 370 //***
371 371 // F1
372 372 if ( (waveform_picker_regs->status & 0x0c) != 0x00 ) { // [0000 1100] check the f1 full bit
373 373 swf_f1_ready = true;
374 374 ring_node_to_send_swf_f1 = current_ring_node_f1->previous;
375 375 current_ring_node_f1 = current_ring_node_f1->next;
376 376 if ( (waveform_picker_regs->status & 0x04) == 0x04)
377 377 {
378 378 ring_node_to_send_swf_f1->coarseTime = waveform_picker_regs->f1_0_coarse_time;
379 379 ring_node_to_send_swf_f1->fineTime = waveform_picker_regs->f1_0_fine_time;
380 380 waveform_picker_regs->addr_data_f1_0 = current_ring_node_f1->buffer_address;
381 381 waveform_picker_regs->status = waveform_picker_regs->status & 0x00002204; // [0010 0010 0000 0100] f1 bits = 0
382 382 }
383 383 else if ( (waveform_picker_regs->status & 0x08) == 0x08)
384 384 {
385 385 ring_node_to_send_swf_f1->coarseTime = waveform_picker_regs->f1_1_coarse_time;
386 386 ring_node_to_send_swf_f1->fineTime = waveform_picker_regs->f1_1_fine_time;
387 387 waveform_picker_regs->addr_data_f1_1 = current_ring_node_f1->buffer_address;
388 388 waveform_picker_regs->status = waveform_picker_regs->status & 0x00002208; // [0010 0010 0000 1000] f1 bits = 0
389 389 }
390 390 }
391 391 }
392 392
393 393 rtems_isr waveforms_isr( rtems_vector_number vector )
394 394 {
395 395 /** This is the interrupt sub routine called by the waveform picker core.
396 396 *
397 397 * This ISR launch different actions depending mainly on two pieces of information:
398 398 * 1. the values read in the registers of the waveform picker.
399 399 * 2. the current LFR mode.
400 400 *
401 401 */
402 402
403 403 // STATUS
404 404 // new error error buffer full
405 405 // 15 14 13 12 11 10 9 8
406 406 // f3 f2 f1 f0 f3 f2 f1 f0
407 407 //
408 408 // ready buffer
409 409 // 7 6 5 4 3 2 1 0
410 410 // f3_1 f3_0 f2_1 f2_0 f1_1 f1_0 f0_1 f0_0
411 411
412 412 rtems_status_code spare_status;
413 413
414 414 waveforms_isr_f3();
415 415
416 416 if ( (waveform_picker_regs->status & 0xff00) != 0x00) // [1111 1111 0000 0000] check the error bits
417 417 {
418 418 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_10 );
419 419 }
420 420
421 421 switch(lfrCurrentMode)
422 422 {
423 423 //********
424 424 // STANDBY
425 425 case(LFR_MODE_STANDBY):
426 426 break;
427 427
428 428 //******
429 429 // NORMAL
430 430 case(LFR_MODE_NORMAL):
431 431 waveforms_isr_normal();
432 432 break;
433 433
434 434 //******
435 435 // BURST
436 436 case(LFR_MODE_BURST):
437 437 waveforms_isr_burst();
438 438 break;
439 439
440 440 //*****
441 441 // SBM1
442 442 case(LFR_MODE_SBM1):
443 443 waveforms_isr_sbm1();
444 444 break;
445 445
446 446 //*****
447 447 // SBM2
448 448 case(LFR_MODE_SBM2):
449 449 waveforms_isr_sbm2();
450 450 break;
451 451
452 452 //********
453 453 // DEFAULT
454 454 default:
455 455 break;
456 456 }
457 457 }
458 458
459 459 //************
460 460 // RTEMS TASKS
461 461
462 462 rtems_task wfrm_task(rtems_task_argument argument) //used with the waveform picker VHDL IP
463 463 {
464 464 /** This RTEMS task is dedicated to the transmission of snapshots of the NORMAL mode.
465 465 *
466 466 * @param unused is the starting argument of the RTEMS task
467 467 *
468 468 * The following data packets are sent by this task:
469 469 * - TM_LFR_SCIENCE_NORMAL_SWF_F0
470 470 * - TM_LFR_SCIENCE_NORMAL_SWF_F1
471 471 * - TM_LFR_SCIENCE_NORMAL_SWF_F2
472 472 *
473 473 */
474 474
475 475 rtems_event_set event_out;
476 476 rtems_id queue_id;
477 477 rtems_status_code status;
478 478 bool resynchronisationEngaged;
479 479 ring_node *ring_node_wf_snap_extracted_ptr;
480 480
481 481 ring_node_wf_snap_extracted_ptr = (ring_node *) &ring_node_wf_snap_extracted;
482 482
483 483 resynchronisationEngaged = false;
484 484
485 485 status = get_message_queue_id_send( &queue_id );
486 486 if (status != RTEMS_SUCCESSFUL)
487 487 {
488 488 PRINTF1("in WFRM *** ERR get_message_queue_id_send %d\n", status)
489 489 }
490 490
491 491 BOOT_PRINTF("in WFRM ***\n")
492 492
493 493 while(1){
494 494 // wait for an RTEMS_EVENT
495 495 rtems_event_receive(RTEMS_EVENT_MODE_NORMAL | RTEMS_EVENT_MODE_SBM1
496 496 | RTEMS_EVENT_MODE_SBM2 | RTEMS_EVENT_MODE_SBM2_WFRM,
497 497 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
498 498 if(resynchronisationEngaged == false)
499 499 { // engage resynchronisation
500 500 snapshot_resynchronization( (unsigned char *) &ring_node_to_send_swf_f0->coarseTime );
501 501 resynchronisationEngaged = true;
502 502 }
503 503 else
504 504 { // reset delta_snapshot to the nominal value
505 505 PRINTF("no resynchronisation, reset delta_snapshot to the nominal value\n")
506 506 set_wfp_delta_snapshot();
507 507 resynchronisationEngaged = false;
508 508 }
509 509 //
510 510
511 511 if (event_out == RTEMS_EVENT_MODE_NORMAL)
512 512 {
513 513 DEBUG_PRINTF("WFRM received RTEMS_EVENT_MODE_NORMAL\n")
514 514 ring_node_to_send_swf_f0->sid = SID_NORM_SWF_F0;
515 515 ring_node_to_send_swf_f1->sid = SID_NORM_SWF_F1;
516 516 ring_node_to_send_swf_f2->sid = SID_NORM_SWF_F2;
517 517 status = rtems_message_queue_send( queue_id, &ring_node_to_send_swf_f0, sizeof( ring_node* ) );
518 518 status = rtems_message_queue_send( queue_id, &ring_node_to_send_swf_f1, sizeof( ring_node* ) );
519 519 status = rtems_message_queue_send( queue_id, &ring_node_to_send_swf_f2, sizeof( ring_node* ) );
520 520 }
521 521 if (event_out == RTEMS_EVENT_MODE_SBM1)
522 522 {
523 523 DEBUG_PRINTF("WFRM received RTEMS_EVENT_MODE_SBM1\n")
524 524 ring_node_to_send_swf_f0->sid = SID_NORM_SWF_F0;
525 525 ring_node_wf_snap_extracted_ptr->sid = SID_NORM_SWF_F1;
526 526 ring_node_to_send_swf_f2->sid = SID_NORM_SWF_F2;
527 527 status = rtems_message_queue_send( queue_id, &ring_node_to_send_swf_f0, sizeof( ring_node* ) );
528 528 status = rtems_message_queue_send( queue_id, &ring_node_wf_snap_extracted_ptr, sizeof( ring_node* ) );
529 529 status = rtems_message_queue_send( queue_id, &ring_node_to_send_swf_f2, sizeof( ring_node* ) );
530 530 }
531 531 if (event_out == RTEMS_EVENT_MODE_SBM2)
532 532 {
533 533 DEBUG_PRINTF("WFRM received RTEMS_EVENT_MODE_SBM2\n")
534 534 ring_node_to_send_swf_f0->sid = SID_NORM_SWF_F0;
535 535 ring_node_to_send_swf_f1->sid = SID_NORM_SWF_F1;
536 536 ring_node_wf_snap_extracted_ptr->sid = SID_NORM_SWF_F2;
537 537 status = rtems_message_queue_send( queue_id, &ring_node_to_send_swf_f0, sizeof( ring_node* ) );
538 538 status = rtems_message_queue_send( queue_id, &ring_node_to_send_swf_f1, sizeof( ring_node* ) );
539 539 status = rtems_message_queue_send( queue_id, &ring_node_wf_snap_extracted_ptr, sizeof( ring_node* ) );
540 540 }
541 541 }
542 542 }
543 543
544 544 rtems_task cwf3_task(rtems_task_argument argument) //used with the waveform picker VHDL IP
545 545 {
546 546 /** This RTEMS task is dedicated to the transmission of continuous waveforms at f3.
547 547 *
548 548 * @param unused is the starting argument of the RTEMS task
549 549 *
550 550 * The following data packet is sent by this task:
551 551 * - TM_LFR_SCIENCE_NORMAL_CWF_F3
552 552 *
553 553 */
554 554
555 555 rtems_event_set event_out;
556 556 rtems_id queue_id;
557 557 rtems_status_code status;
558 558 ring_node ring_node_cwf3_light;
559 559
560 560 status = get_message_queue_id_send( &queue_id );
561 561 if (status != RTEMS_SUCCESSFUL)
562 562 {
563 563 PRINTF1("in CWF3 *** ERR get_message_queue_id_send %d\n", status)
564 564 }
565 565
566 566 ring_node_to_send_cwf_f3->sid = SID_NORM_CWF_LONG_F3;
567 567
568 568 // init the ring_node_cwf3_light structure
569 569 ring_node_cwf3_light.buffer_address = (int) wf_cont_f3_light;
570 570 ring_node_cwf3_light.coarseTime = 0x00;
571 571 ring_node_cwf3_light.fineTime = 0x00;
572 572 ring_node_cwf3_light.next = NULL;
573 573 ring_node_cwf3_light.previous = NULL;
574 574 ring_node_cwf3_light.sid = SID_NORM_CWF_F3;
575 575 ring_node_cwf3_light.status = 0x00;
576 576
577 577 BOOT_PRINTF("in CWF3 ***\n")
578 578
579 579 while(1){
580 580 // wait for an RTEMS_EVENT
581 581 rtems_event_receive( RTEMS_EVENT_0,
582 582 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
583 583 if ( (lfrCurrentMode == LFR_MODE_NORMAL)
584 584 || (lfrCurrentMode == LFR_MODE_SBM1) || (lfrCurrentMode==LFR_MODE_SBM2) )
585 585 {
586 586 if ( (parameter_dump_packet.sy_lfr_n_cwf_long_f3 & 0x01) == 0x01)
587 587 {
588 588 PRINTF("send CWF_LONG_F3\n")
589 589 ring_node_to_send_cwf_f3->sid = SID_NORM_CWF_LONG_F3;
590 590 status = rtems_message_queue_send( queue_id, &ring_node_to_send_cwf_f3, sizeof( ring_node* ) );
591 591 }
592 592 else
593 593 {
594 594 PRINTF("send CWF_F3 (light)\n")
595 595 send_waveform_CWF3_light( ring_node_to_send_cwf_f3, &ring_node_cwf3_light, queue_id );
596 596 }
597 597
598 598 }
599 599 else
600 600 {
601 601 PRINTF1("in CWF3 *** lfrCurrentMode is %d, no data will be sent\n", lfrCurrentMode)
602 602 }
603 603 }
604 604 }
605 605
606 606 rtems_task cwf2_task(rtems_task_argument argument) // ONLY USED IN BURST AND SBM2
607 607 {
608 608 /** This RTEMS task is dedicated to the transmission of continuous waveforms at f2.
609 609 *
610 610 * @param unused is the starting argument of the RTEMS task
611 611 *
612 612 * The following data packet is sent by this function:
613 613 * - TM_LFR_SCIENCE_BURST_CWF_F2
614 614 * - TM_LFR_SCIENCE_SBM2_CWF_F2
615 615 *
616 616 */
617 617
618 618 rtems_event_set event_out;
619 619 rtems_id queue_id;
620 620 rtems_status_code status;
621 621 ring_node *ring_node_to_send;
622 622 unsigned long long int acquisitionTimeF0_asLong;
623 623
624 624 acquisitionTimeF0_asLong = 0x00;
625 625
626 626 status = get_message_queue_id_send( &queue_id );
627 627 if (status != RTEMS_SUCCESSFUL)
628 628 {
629 629 PRINTF1("in CWF2 *** ERR get_message_queue_id_send %d\n", status)
630 630 }
631 631
632 632 BOOT_PRINTF("in CWF2 ***\n")
633 633
634 634 while(1){
635 635 // wait for an RTEMS_EVENT
636 636 rtems_event_receive( RTEMS_EVENT_MODE_BURST | RTEMS_EVENT_MODE_SBM2,
637 637 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
638 638 ring_node_to_send = getRingNodeToSendCWF( 2 );
639 639 if (event_out == RTEMS_EVENT_MODE_BURST)
640 640 {
641 641 status = rtems_message_queue_send( queue_id, &ring_node_to_send, sizeof( ring_node* ) );
642 642 }
643 643 if (event_out == RTEMS_EVENT_MODE_SBM2)
644 644 {
645 645 status = rtems_message_queue_send( queue_id, &ring_node_to_send, sizeof( ring_node* ) );
646 646 // launch snapshot extraction if needed
647 647 if (extractSWF == true)
648 648 {
649 649 ring_node_to_send_swf_f2 = ring_node_to_send_cwf_f2;
650 650 // extract the snapshot
651 651 build_snapshot_from_ring( ring_node_to_send_swf_f2, 2, acquisitionTimeF0_asLong );
652 652 // send the snapshot when built
653 653 status = rtems_event_send( Task_id[TASKID_WFRM], RTEMS_EVENT_MODE_SBM2 );
654 654 extractSWF = false;
655 655 }
656 656 if (swf_f0_ready && swf_f1_ready)
657 657 {
658 658 extractSWF = true;
659 659 // record the acquition time of the fΓ  snapshot to use to build the snapshot at f2
660 660 acquisitionTimeF0_asLong = get_acquisition_time( (unsigned char *) &ring_node_to_send_swf_f0->coarseTime );
661 661 swf_f0_ready = false;
662 662 swf_f1_ready = false;
663 663 }
664 664 }
665 665 }
666 666 }
667 667
668 668 rtems_task cwf1_task(rtems_task_argument argument) // ONLY USED IN SBM1
669 669 {
670 670 /** This RTEMS task is dedicated to the transmission of continuous waveforms at f1.
671 671 *
672 672 * @param unused is the starting argument of the RTEMS task
673 673 *
674 674 * The following data packet is sent by this function:
675 675 * - TM_LFR_SCIENCE_SBM1_CWF_F1
676 676 *
677 677 */
678 678
679 679 rtems_event_set event_out;
680 680 rtems_id queue_id;
681 681 rtems_status_code status;
682 682
683 683 ring_node * ring_node_to_send_cwf;
684 684
685 685 status = get_message_queue_id_send( &queue_id );
686 686 if (status != RTEMS_SUCCESSFUL)
687 687 {
688 688 PRINTF1("in CWF1 *** ERR get_message_queue_id_send %d\n", status)
689 689 }
690 690
691 691 BOOT_PRINTF("in CWF1 ***\n")
692 692
693 693 while(1){
694 694 // wait for an RTEMS_EVENT
695 695 rtems_event_receive( RTEMS_EVENT_MODE_SBM1,
696 696 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
697 697 ring_node_to_send_cwf = getRingNodeToSendCWF( 1 );
698 698 ring_node_to_send_cwf_f1->sid = SID_SBM1_CWF_F1;
699 699 status = rtems_message_queue_send( queue_id, &ring_node_to_send_cwf, sizeof( ring_node* ) );
700 700 // launch snapshot extraction if needed
701 701 if (extractSWF == true)
702 702 {
703 703 ring_node_to_send_swf_f1 = ring_node_to_send_cwf;
704 704 // launch the snapshot extraction
705 705 status = rtems_event_send( Task_id[TASKID_SWBD], RTEMS_EVENT_MODE_SBM1 );
706 706 extractSWF = false;
707 707 }
708 708 if (swf_f0_ready == true)
709 709 {
710 710 extractSWF = true;
711 711 swf_f0_ready = false; // this step shall be executed only one time
712 712 }
713 713 if ((swf_f1_ready == true) && (swf_f2_ready == true)) // swf_f1 is ready after the extraction
714 714 {
715 715 status = rtems_event_send( Task_id[TASKID_WFRM], RTEMS_EVENT_MODE_SBM1 );
716 716 swf_f1_ready = false;
717 717 swf_f2_ready = false;
718 718 }
719 719 }
720 720 }
721 721
722 722 rtems_task swbd_task(rtems_task_argument argument)
723 723 {
724 724 /** This RTEMS task is dedicated to the building of snapshots from different continuous waveforms buffers.
725 725 *
726 726 * @param unused is the starting argument of the RTEMS task
727 727 *
728 728 */
729 729
730 730 rtems_event_set event_out;
731 731 unsigned long long int acquisitionTimeF0_asLong;
732 732
733 733 acquisitionTimeF0_asLong = 0x00;
734 734
735 735 BOOT_PRINTF("in SWBD ***\n")
736 736
737 737 while(1){
738 738 // wait for an RTEMS_EVENT
739 739 rtems_event_receive( RTEMS_EVENT_MODE_SBM1 | RTEMS_EVENT_MODE_SBM2,
740 740 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
741 741 if (event_out == RTEMS_EVENT_MODE_SBM1)
742 742 {
743 743 acquisitionTimeF0_asLong = get_acquisition_time( (unsigned char *) &ring_node_to_send_swf_f0->coarseTime );
744 744 build_snapshot_from_ring( ring_node_to_send_swf_f1, 1, acquisitionTimeF0_asLong );
745 745 swf_f1_ready = true; // the snapshot has been extracted and is ready to be sent
746 746 }
747 747 else
748 748 {
749 749 PRINTF1("in SWBD *** unexpected rtems event received %x\n", (int) event_out)
750 750 }
751 751 }
752 752 }
753 753
754 754 //******************
755 755 // general functions
756 756
757 757 void WFP_init_rings( void )
758 758 {
759 759 // F0 RING
760 760 init_ring( waveform_ring_f0, NB_RING_NODES_F0, wf_buffer_f0, WFRM_BUFFER );
761 761 // F1 RING
762 762 init_ring( waveform_ring_f1, NB_RING_NODES_F1, wf_buffer_f1, WFRM_BUFFER );
763 763 // F2 RING
764 764 init_ring( waveform_ring_f2, NB_RING_NODES_F2, wf_buffer_f2, WFRM_BUFFER );
765 765 // F3 RING
766 766 init_ring( waveform_ring_f3, NB_RING_NODES_F3, wf_buffer_f3, WFRM_BUFFER );
767 767
768 768 ring_node_wf_snap_extracted.buffer_address = (int) wf_snap_extracted;
769 769
770 770 DEBUG_PRINTF1("waveform_ring_f0 @%x\n", (unsigned int) waveform_ring_f0)
771 771 DEBUG_PRINTF1("waveform_ring_f1 @%x\n", (unsigned int) waveform_ring_f1)
772 772 DEBUG_PRINTF1("waveform_ring_f2 @%x\n", (unsigned int) waveform_ring_f2)
773 773 DEBUG_PRINTF1("waveform_ring_f3 @%x\n", (unsigned int) waveform_ring_f3)
774 774 DEBUG_PRINTF1("wf_buffer_f0 @%x\n", (unsigned int) wf_buffer_f0)
775 775 DEBUG_PRINTF1("wf_buffer_f1 @%x\n", (unsigned int) wf_buffer_f1)
776 776 DEBUG_PRINTF1("wf_buffer_f2 @%x\n", (unsigned int) wf_buffer_f2)
777 777 DEBUG_PRINTF1("wf_buffer_f3 @%x\n", (unsigned int) wf_buffer_f3)
778 778
779 779 }
780 780
781 781 void init_ring(ring_node ring[], unsigned char nbNodes, volatile int buffer[], unsigned int bufferSize )
782 782 {
783 783 unsigned char i;
784 784
785 785 //***************
786 786 // BUFFER ADDRESS
787 787 for(i=0; i<nbNodes; i++)
788 788 {
789 789 ring[i].coarseTime = 0x00;
790 790 ring[i].fineTime = 0x00;
791 791 ring[i].sid = 0x00;
792 792 ring[i].status = 0x00;
793 793 ring[i].buffer_address = (int) &buffer[ i * bufferSize ];
794 794 }
795 795
796 796 //*****
797 797 // NEXT
798 798 ring[ nbNodes - 1 ].next = (ring_node*) &ring[ 0 ];
799 799 for(i=0; i<nbNodes-1; i++)
800 800 {
801 801 ring[i].next = (ring_node*) &ring[ i + 1 ];
802 802 }
803 803
804 804 //*********
805 805 // PREVIOUS
806 806 ring[ 0 ].previous = (ring_node*) &ring[ nbNodes - 1 ];
807 807 for(i=1; i<nbNodes; i++)
808 808 {
809 809 ring[i].previous = (ring_node*) &ring[ i - 1 ];
810 810 }
811 811 }
812 812
813 813 void WFP_reset_current_ring_nodes( void )
814 814 {
815 815 current_ring_node_f0 = waveform_ring_f0[0].next;
816 816 current_ring_node_f1 = waveform_ring_f1[0].next;
817 817 current_ring_node_f2 = waveform_ring_f2[0].next;
818 818 current_ring_node_f3 = waveform_ring_f3[0].next;
819 819
820 820 ring_node_to_send_swf_f0 = waveform_ring_f0;
821 821 ring_node_to_send_swf_f1 = waveform_ring_f1;
822 822 ring_node_to_send_swf_f2 = waveform_ring_f2;
823 823
824 824 ring_node_to_send_cwf_f1 = waveform_ring_f1;
825 825 ring_node_to_send_cwf_f2 = waveform_ring_f2;
826 826 ring_node_to_send_cwf_f3 = waveform_ring_f3;
827 827 }
828 828
829 829 int send_waveform_CWF3_light( ring_node *ring_node_to_send, ring_node *ring_node_cwf3_light, rtems_id queue_id )
830 830 {
831 831 /** This function sends CWF_F3 CCSDS packets without the b1, b2 and b3 data.
832 832 *
833 833 * @param waveform points to the buffer containing the data that will be send.
834 834 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
835 835 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
836 836 * contain information to setup the transmission of the data packets.
837 837 *
838 838 * By default, CWF_F3 packet are send without the b1, b2 and b3 data. This function rebuilds a data buffer
839 839 * from the incoming data and sends it in 7 packets, 6 containing 340 blocks and 1 one containing 8 blocks.
840 840 *
841 841 */
842 842
843 843 unsigned int i;
844 844 int ret;
845 845 rtems_status_code status;
846 846
847 847 char *sample;
848 848 int *dataPtr;
849 849
850 850 ret = LFR_DEFAULT;
851 851
852 852 dataPtr = (int*) ring_node_to_send->buffer_address;
853 853
854 854 ring_node_cwf3_light->coarseTime = ring_node_to_send->coarseTime;
855 855 ring_node_cwf3_light->fineTime = ring_node_to_send->fineTime;
856 856
857 857 //**********************
858 858 // BUILD CWF3_light DATA
859 859 for ( i=0; i< NB_SAMPLES_PER_SNAPSHOT; i++)
860 860 {
861 861 sample = (char*) &dataPtr[ (i * NB_WORDS_SWF_BLK) ];
862 862 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) ] = sample[ 0 ];
863 863 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) + 1 ] = sample[ 1 ];
864 864 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) + 2 ] = sample[ 2 ];
865 865 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) + 3 ] = sample[ 3 ];
866 866 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) + 4 ] = sample[ 4 ];
867 867 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) + 5 ] = sample[ 5 ];
868 868 }
869 869
870 printf("send_waveform_CWF3_light => [0] = %x, [1] = %x, [2] = %x\n", dataPtr[0], dataPtr[1], dataPtr[2]);
871
872 870 // SEND PACKET
873 871 status = rtems_message_queue_send( queue_id, &ring_node_cwf3_light, sizeof( ring_node* ) );
874 872 if (status != RTEMS_SUCCESSFUL) {
875 873 printf("%d-%d, ERR %d\n", SID_NORM_CWF_F3, i, (int) status);
876 874 ret = LFR_DEFAULT;
877 875 }
878 876
879 877 return ret;
880 878 }
881 879
882 880 void compute_acquisition_time( unsigned int coarseTime, unsigned int fineTime,
883 881 unsigned int sid, unsigned char pa_lfr_pkt_nr, unsigned char * acquisitionTime )
884 882 {
885 883 unsigned long long int acquisitionTimeAsLong;
886 884 unsigned char localAcquisitionTime[6];
887 885 double deltaT;
888 886
889 887 deltaT = 0.;
890 888
891 889 localAcquisitionTime[0] = (unsigned char) ( coarseTime >> 24 );
892 890 localAcquisitionTime[1] = (unsigned char) ( coarseTime >> 16 );
893 891 localAcquisitionTime[2] = (unsigned char) ( coarseTime >> 8 );
894 892 localAcquisitionTime[3] = (unsigned char) ( coarseTime );
895 893 localAcquisitionTime[4] = (unsigned char) ( fineTime >> 8 );
896 894 localAcquisitionTime[5] = (unsigned char) ( fineTime );
897 895
898 896 acquisitionTimeAsLong = ( (unsigned long long int) localAcquisitionTime[0] << 40 )
899 897 + ( (unsigned long long int) localAcquisitionTime[1] << 32 )
900 898 + ( (unsigned long long int) localAcquisitionTime[2] << 24 )
901 899 + ( (unsigned long long int) localAcquisitionTime[3] << 16 )
902 900 + ( (unsigned long long int) localAcquisitionTime[4] << 8 )
903 901 + ( (unsigned long long int) localAcquisitionTime[5] );
904 902
905 903 switch( sid )
906 904 {
907 905 case SID_NORM_SWF_F0:
908 906 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_304 * 65536. / 24576. ;
909 907 break;
910 908
911 909 case SID_NORM_SWF_F1:
912 910 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_304 * 65536. / 4096. ;
913 911 break;
914 912
915 913 case SID_NORM_SWF_F2:
916 914 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_304 * 65536. / 256. ;
917 915 break;
918 916
919 917 case SID_SBM1_CWF_F1:
920 918 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF * 65536. / 4096. ;
921 919 break;
922 920
923 921 case SID_SBM2_CWF_F2:
924 922 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF * 65536. / 256. ;
925 923 break;
926 924
927 925 case SID_BURST_CWF_F2:
928 926 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF * 65536. / 256. ;
929 927 break;
930 928
931 929 case SID_NORM_CWF_F3:
932 930 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF_SHORT_F3 * 65536. / 16. ;
933 931 break;
934 932
935 933 case SID_NORM_CWF_LONG_F3:
936 934 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF * 65536. / 16. ;
937 935 break;
938 936
939 937 default:
940 938 PRINTF1("in compute_acquisition_time *** ERR unexpected sid %d\n", sid)
941 939 deltaT = 0.;
942 940 break;
943 941 }
944 942
945 943 acquisitionTimeAsLong = acquisitionTimeAsLong + (unsigned long long int) deltaT;
946 944 //
947 945 acquisitionTime[0] = (unsigned char) (acquisitionTimeAsLong >> 40);
948 946 acquisitionTime[1] = (unsigned char) (acquisitionTimeAsLong >> 32);
949 947 acquisitionTime[2] = (unsigned char) (acquisitionTimeAsLong >> 24);
950 948 acquisitionTime[3] = (unsigned char) (acquisitionTimeAsLong >> 16);
951 949 acquisitionTime[4] = (unsigned char) (acquisitionTimeAsLong >> 8 );
952 950 acquisitionTime[5] = (unsigned char) (acquisitionTimeAsLong );
953 951
954 952 }
955 953
956 954 void build_snapshot_from_ring( ring_node *ring_node_to_send, unsigned char frequencyChannel, unsigned long long int acquisitionTimeF0_asLong )
957 955 {
958 956 unsigned int i;
959 957 unsigned long long int centerTime_asLong;
960 958 unsigned long long int acquisitionTime_asLong;
961 959 unsigned long long int bufferAcquisitionTime_asLong;
962 960 unsigned char *ptr1;
963 961 unsigned char *ptr2;
964 962 unsigned char *timeCharPtr;
965 963 unsigned char nb_ring_nodes;
966 964 unsigned long long int frequency_asLong;
967 965 unsigned long long int nbTicksPerSample_asLong;
968 966 unsigned long long int nbSamplesPart1_asLong;
969 967 unsigned long long int sampleOffset_asLong;
970 968
971 969 unsigned int deltaT_F0;
972 970 unsigned int deltaT_F1;
973 971 unsigned long long int deltaT_F2;
974 972
975 973 deltaT_F0 = 2731; // (2048. / 24576. / 2.) * 65536. = 2730.667;
976 974 deltaT_F1 = 16384; // (2048. / 4096. / 2.) * 65536. = 16384;
977 975 deltaT_F2 = 262144; // (2048. / 256. / 2.) * 65536. = 262144;
978 976 sampleOffset_asLong = 0x00;
979 977
980 978 // (1) get the f0 acquisition time => the value is passed in argument
981 979
982 980 // (2) compute the central reference time
983 981 centerTime_asLong = acquisitionTimeF0_asLong + deltaT_F0;
984 printf("centerTime_asLong = %llx\n", centerTime_asLong);
985 982
986 983 // (3) compute the acquisition time of the current snapshot
987 984 switch(frequencyChannel)
988 985 {
989 986 case 1: // 1 is for F1 = 4096 Hz
990 987 acquisitionTime_asLong = centerTime_asLong - deltaT_F1;
991 988 nb_ring_nodes = NB_RING_NODES_F1;
992 989 frequency_asLong = 4096;
993 990 nbTicksPerSample_asLong = 16; // 65536 / 4096;
994 991 break;
995 992 case 2: // 2 is for F2 = 256 Hz
996 993 acquisitionTime_asLong = centerTime_asLong - deltaT_F2;
997 994 nb_ring_nodes = NB_RING_NODES_F2;
998 995 frequency_asLong = 256;
999 996 nbTicksPerSample_asLong = 256; // 65536 / 256;
1000 997 break;
1001 998 default:
1002 999 acquisitionTime_asLong = centerTime_asLong;
1003 1000 frequency_asLong = 256;
1004 1001 nbTicksPerSample_asLong = 256;
1005 1002 break;
1006 1003 }
1007 1004
1008 1005 //****************************************************************************
1009 1006 // (4) search the ring_node with the acquisition time <= acquisitionTime_asLong
1010 1007 for (i=0; i<nb_ring_nodes; i++)
1011 1008 {
1012 1009 PRINTF1("%d ... ", i)
1013 1010 bufferAcquisitionTime_asLong = get_acquisition_time( (unsigned char *) &ring_node_to_send->coarseTime );
1014 1011 if (bufferAcquisitionTime_asLong <= acquisitionTime_asLong)
1015 1012 {
1016 1013 PRINTF1("buffer found with acquisition time = %llx\n", bufferAcquisitionTime_asLong)
1017 1014 break;
1018 1015 }
1019 1016 ring_node_to_send = ring_node_to_send->previous;
1020 1017 }
1021 1018
1022 1019 // (5) compute the number of samples to take in the current buffer
1023 1020 sampleOffset_asLong = ((acquisitionTime_asLong - bufferAcquisitionTime_asLong) * frequency_asLong ) >> 16;
1024 1021 nbSamplesPart1_asLong = NB_SAMPLES_PER_SNAPSHOT - sampleOffset_asLong;
1025 1022 PRINTF2("sampleOffset_asLong = %lld, nbSamplesPart1_asLong = %lld\n", sampleOffset_asLong, nbSamplesPart1_asLong)
1026 1023
1027 1024 // (6) compute the final acquisition time
1028 1025 acquisitionTime_asLong = bufferAcquisitionTime_asLong +
1029 1026 sampleOffset_asLong * nbTicksPerSample_asLong;
1030 1027
1031 1028 // (7) copy the acquisition time at the beginning of the extrated snapshot
1032 1029 ptr1 = (unsigned char*) &acquisitionTime_asLong;
1033 1030 // fine time
1034 1031 ptr2 = (unsigned char*) &ring_node_wf_snap_extracted.fineTime;
1035 1032 ptr2[2] = ptr1[ 4 + 2 ];
1036 1033 ptr2[3] = ptr1[ 5 + 2 ];
1037 1034 // coarse time
1038 1035 ptr2 = (unsigned char*) &ring_node_wf_snap_extracted.coarseTime;
1039 1036 ptr2[0] = ptr1[ 0 + 2 ];
1040 1037 ptr2[1] = ptr1[ 1 + 2 ];
1041 1038 ptr2[2] = ptr1[ 2 + 2 ];
1042 1039 ptr2[3] = ptr1[ 3 + 2 ];
1043 1040
1044 1041 // re set the synchronization bit
1045 1042 timeCharPtr = (unsigned char*) &ring_node_to_send->coarseTime;
1046 1043 ptr2[0] = ptr2[0] | (timeCharPtr[0] & 0x80); // [1000 0000]
1047 1044
1048 1045 if ( (nbSamplesPart1_asLong >= NB_SAMPLES_PER_SNAPSHOT) | (nbSamplesPart1_asLong < 0) )
1049 1046 {
1050 1047 nbSamplesPart1_asLong = 0;
1051 1048 }
1052 1049 // copy the part 1 of the snapshot in the extracted buffer
1053 1050 for ( i = 0; i < (nbSamplesPart1_asLong * NB_WORDS_SWF_BLK); i++ )
1054 1051 {
1055 1052 wf_snap_extracted[i] =
1056 1053 ((int*) ring_node_to_send->buffer_address)[ i + (sampleOffset_asLong * NB_WORDS_SWF_BLK) ];
1057 1054 }
1058 1055 // copy the part 2 of the snapshot in the extracted buffer
1059 1056 ring_node_to_send = ring_node_to_send->next;
1060 1057 for ( i = (nbSamplesPart1_asLong * NB_WORDS_SWF_BLK); i < (NB_SAMPLES_PER_SNAPSHOT * NB_WORDS_SWF_BLK); i++ )
1061 1058 {
1062 1059 wf_snap_extracted[i] =
1063 1060 ((int*) ring_node_to_send->buffer_address)[ (i-(nbSamplesPart1_asLong * NB_WORDS_SWF_BLK)) ];
1064 1061 }
1065 1062 }
1066 1063
1067 1064 void snapshot_resynchronization( unsigned char *timePtr )
1068 1065 {
1069 1066 unsigned long long int acquisitionTime;
1070 1067 unsigned long long int centerTime;
1071 1068 unsigned long long int previousTick;
1072 1069 unsigned long long int nextTick;
1073 1070 unsigned long long int deltaPreviousTick;
1074 1071 unsigned long long int deltaNextTick;
1075 1072 unsigned int deltaTickInF2;
1076 1073 double deltaPrevious;
1077 1074 double deltaNext;
1078 1075
1079 1076 acquisitionTime = get_acquisition_time( timePtr );
1080 1077
1081 1078 // compute center time
1082 1079 centerTime = acquisitionTime + 2731; // (2048. / 24576. / 2.) * 65536. = 2730.667;
1083 1080 previousTick = centerTime - (centerTime & 0xffff);
1084 1081 nextTick = previousTick + 65536;
1085 1082
1086 1083 deltaPreviousTick = centerTime - previousTick;
1087 1084 deltaNextTick = nextTick - centerTime;
1088 1085
1089 1086 deltaPrevious = ((double) deltaPreviousTick) / 65536. * 1000.;
1090 1087 deltaNext = ((double) deltaNextTick) / 65536. * 1000.;
1091 1088
1092 printf("delta previous = %f ms, delta next = %f ms\n", deltaPrevious, deltaNext);
1093 printf("delta previous = %llu, delta next = %llu\n", deltaPreviousTick, deltaNextTick);
1089 PRINTF2("delta previous = %f ms, delta next = %f ms\n", deltaPrevious, deltaNext)
1090 PRINTF2("delta previous = %llu, delta next = %llu\n", deltaPreviousTick, deltaNextTick)
1094 1091
1095 1092 // which tick is the closest
1096 1093 if (deltaPreviousTick > deltaNextTick)
1097 1094 {
1098 1095 deltaTickInF2 = floor( (deltaNext * 256. / 1000.) ); // the division by 2 is important here
1099 1096 waveform_picker_regs->delta_snapshot = waveform_picker_regs->delta_snapshot + deltaTickInF2;
1100 1097 printf("correction of = + %u\n", deltaTickInF2);
1101 1098 }
1102 1099 else
1103 1100 {
1104 1101 deltaTickInF2 = floor( (deltaPrevious * 256. / 1000.) ); // the division by 2 is important here
1105 1102 waveform_picker_regs->delta_snapshot = waveform_picker_regs->delta_snapshot - deltaTickInF2;
1106 1103 printf("correction of = - %u\n", deltaTickInF2);
1107 1104 }
1108 1105 }
1109 1106
1110 1107 //**************
1111 1108 // wfp registers
1112 1109 void reset_wfp_burst_enable( void )
1113 1110 {
1114 1111 /** This function resets the waveform picker burst_enable register.
1115 1112 *
1116 1113 * The burst bits [f2 f1 f0] and the enable bits [f3 f2 f1 f0] are set to 0.
1117 1114 *
1118 1115 */
1119 1116
1120 1117 // [1000 000] burst f2, f1, f0 enable f3, f2, f1, f0
1121 1118 waveform_picker_regs->run_burst_enable = waveform_picker_regs->run_burst_enable & 0x80;
1122 1119 }
1123 1120
1124 1121 void reset_wfp_status( void )
1125 1122 {
1126 1123 /** This function resets the waveform picker status register.
1127 1124 *
1128 1125 * All status bits are set to 0 [new_err full_err full].
1129 1126 *
1130 1127 */
1131 1128
1132 1129 waveform_picker_regs->status = 0xffff;
1133 1130 }
1134 1131
1135 1132 void reset_wfp_buffer_addresses( void )
1136 1133 {
1137 1134 // F0
1138 1135 waveform_picker_regs->addr_data_f0_0 = current_ring_node_f0->previous->buffer_address; // 0x08
1139 1136 waveform_picker_regs->addr_data_f0_1 = current_ring_node_f0->buffer_address; // 0x0c
1140 1137 // F1
1141 1138 waveform_picker_regs->addr_data_f1_0 = current_ring_node_f1->previous->buffer_address; // 0x10
1142 1139 waveform_picker_regs->addr_data_f1_1 = current_ring_node_f1->buffer_address; // 0x14
1143 1140 // F2
1144 1141 waveform_picker_regs->addr_data_f2_0 = current_ring_node_f2->previous->buffer_address; // 0x18
1145 1142 waveform_picker_regs->addr_data_f2_1 = current_ring_node_f2->buffer_address; // 0x1c
1146 1143 // F3
1147 1144 waveform_picker_regs->addr_data_f3_0 = current_ring_node_f3->previous->buffer_address; // 0x20
1148 1145 waveform_picker_regs->addr_data_f3_1 = current_ring_node_f3->buffer_address; // 0x24
1149 1146 }
1150 1147
1151 1148 void reset_waveform_picker_regs( void )
1152 1149 {
1153 1150 /** This function resets the waveform picker module registers.
1154 1151 *
1155 1152 * The registers affected by this function are located at the following offset addresses:
1156 1153 * - 0x00 data_shaping
1157 1154 * - 0x04 run_burst_enable
1158 1155 * - 0x08 addr_data_f0
1159 1156 * - 0x0C addr_data_f1
1160 1157 * - 0x10 addr_data_f2
1161 1158 * - 0x14 addr_data_f3
1162 1159 * - 0x18 status
1163 1160 * - 0x1C delta_snapshot
1164 1161 * - 0x20 delta_f0
1165 1162 * - 0x24 delta_f0_2
1166 1163 * - 0x28 delta_f1
1167 1164 * - 0x2c delta_f2
1168 1165 * - 0x30 nb_data_by_buffer
1169 1166 * - 0x34 nb_snapshot_param
1170 1167 * - 0x38 start_date
1171 1168 * - 0x3c nb_word_in_buffer
1172 1169 *
1173 1170 */
1174 1171
1175 1172 set_wfp_data_shaping(); // 0x00 *** R1 R0 SP1 SP0 BW
1176 1173
1177 1174 reset_wfp_burst_enable(); // 0x04 *** [run *** burst f2, f1, f0 *** enable f3, f2, f1, f0 ]
1178 1175
1179 1176 reset_wfp_buffer_addresses();
1180 1177
1181 1178 reset_wfp_status(); // 0x18
1182 1179
1183 1180 set_wfp_delta_snapshot(); // 0x1c *** 300 s => 0x12bff
1184 1181
1185 1182 set_wfp_delta_f0_f0_2(); // 0x20, 0x24
1186 1183
1187 1184 set_wfp_delta_f1(); // 0x28
1188 1185
1189 1186 set_wfp_delta_f2(); // 0x2c
1190 1187
1191 1188 DEBUG_PRINTF1("delta_snapshot %x\n", waveform_picker_regs->delta_snapshot)
1192 1189 DEBUG_PRINTF1("delta_f0 %x\n", waveform_picker_regs->delta_f0)
1193 1190 DEBUG_PRINTF1("delta_f0_2 %x\n", waveform_picker_regs->delta_f0_2)
1194 1191 DEBUG_PRINTF1("delta_f1 %x\n", waveform_picker_regs->delta_f1)
1195 1192 DEBUG_PRINTF1("delta_f2 %x\n", waveform_picker_regs->delta_f2)
1196 1193 // 2688 = 8 * 336
1197 1194 waveform_picker_regs->nb_data_by_buffer = 0xa7f; // 0x30 *** 2688 - 1 => nb samples -1
1198 1195 waveform_picker_regs->snapshot_param = 0xa80; // 0x34 *** 2688 => nb samples
1199 1196 waveform_picker_regs->start_date = 0x7fffffff; // 0x38
1200 1197 //
1201 1198 // coarse time and fine time registers are not initialized, they are volatile
1202 1199 //
1203 1200 waveform_picker_regs->buffer_length = 0x1f8;// buffer length in burst = 3 * 2688 / 16 = 504 = 0x1f8
1204 1201 }
1205 1202
1206 1203 void set_wfp_data_shaping( void )
1207 1204 {
1208 1205 /** This function sets the data_shaping register of the waveform picker module.
1209 1206 *
1210 1207 * The value is read from one field of the parameter_dump_packet structure:\n
1211 1208 * bw_sp0_sp1_r0_r1
1212 1209 *
1213 1210 */
1214 1211
1215 1212 unsigned char data_shaping;
1216 1213
1217 1214 // get the parameters for the data shaping [BW SP0 SP1 R0 R1] in sy_lfr_common1 and configure the register
1218 1215 // waveform picker : [R1 R0 SP1 SP0 BW]
1219 1216
1220 1217 data_shaping = parameter_dump_packet.bw_sp0_sp1_r0_r1;
1221 1218
1222 1219 waveform_picker_regs->data_shaping =
1223 1220 ( (data_shaping & 0x10) >> 4 ) // BW
1224 1221 + ( (data_shaping & 0x08) >> 2 ) // SP0
1225 1222 + ( (data_shaping & 0x04) ) // SP1
1226 1223 + ( (data_shaping & 0x02) << 2 ) // R0
1227 1224 + ( (data_shaping & 0x01) << 4 ); // R1
1225
1226 // this is a temporary way to set R2, compatible with the release 2 of the flight software
1227 waveform_picker_regs->data_shaping = waveform_picker_regs->data_shaping + ( (0x1) << 5 ); // R2
1228 1228 }
1229 1229
1230 1230 void set_wfp_burst_enable_register( unsigned char mode )
1231 1231 {
1232 1232 /** This function sets the waveform picker burst_enable register depending on the mode.
1233 1233 *
1234 1234 * @param mode is the LFR mode to launch.
1235 1235 *
1236 1236 * The burst bits shall be before the enable bits.
1237 1237 *
1238 1238 */
1239 1239
1240 1240 // [0000 0000] burst f2, f1, f0 enable f3 f2 f1 f0
1241 1241 // the burst bits shall be set first, before the enable bits
1242 1242 switch(mode) {
1243 1243 case(LFR_MODE_NORMAL):
1244 1244 waveform_picker_regs->run_burst_enable = 0x00; // [0000 0000] no burst enable
1245 1245 waveform_picker_regs->run_burst_enable = 0x0f; // [0000 1111] enable f3 f2 f1 f0
1246 1246 break;
1247 1247 case(LFR_MODE_BURST):
1248 1248 waveform_picker_regs->run_burst_enable = 0x40; // [0100 0000] f2 burst enabled
1249 1249 // waveform_picker_regs->run_burst_enable = waveform_picker_regs->run_burst_enable | 0x04; // [0100] enable f2
1250 1250 waveform_picker_regs->run_burst_enable = waveform_picker_regs->run_burst_enable | 0x0c; // [1100] enable f3 AND f2
1251 1251 break;
1252 1252 case(LFR_MODE_SBM1):
1253 1253 waveform_picker_regs->run_burst_enable = 0x20; // [0010 0000] f1 burst enabled
1254 1254 waveform_picker_regs->run_burst_enable = waveform_picker_regs->run_burst_enable | 0x0f; // [1111] enable f3 f2 f1 f0
1255 1255 break;
1256 1256 case(LFR_MODE_SBM2):
1257 1257 waveform_picker_regs->run_burst_enable = 0x40; // [0100 0000] f2 burst enabled
1258 1258 waveform_picker_regs->run_burst_enable = waveform_picker_regs->run_burst_enable | 0x0f; // [1111] enable f3 f2 f1 f0
1259 1259 break;
1260 1260 default:
1261 1261 waveform_picker_regs->run_burst_enable = 0x00; // [0000 0000] no burst enabled, no waveform enabled
1262 1262 break;
1263 1263 }
1264 1264 }
1265 1265
1266 1266 void set_wfp_delta_snapshot( void )
1267 1267 {
1268 1268 /** This function sets the delta_snapshot register of the waveform picker module.
1269 1269 *
1270 1270 * The value is read from two (unsigned char) of the parameter_dump_packet structure:
1271 1271 * - sy_lfr_n_swf_p[0]
1272 1272 * - sy_lfr_n_swf_p[1]
1273 1273 *
1274 1274 */
1275 1275
1276 1276 unsigned int delta_snapshot;
1277 1277 unsigned int delta_snapshot_in_T2;
1278 1278
1279 1279 delta_snapshot = parameter_dump_packet.sy_lfr_n_swf_p[0]*256
1280 1280 + parameter_dump_packet.sy_lfr_n_swf_p[1];
1281 1281
1282 1282 delta_snapshot_in_T2 = delta_snapshot * 256;
1283 1283 waveform_picker_regs->delta_snapshot = delta_snapshot_in_T2 - 1; // max 4 bytes
1284 1284 }
1285 1285
1286 1286 void set_wfp_delta_f0_f0_2( void )
1287 1287 {
1288 1288 unsigned int delta_snapshot;
1289 1289 unsigned int nb_samples_per_snapshot;
1290 1290 float delta_f0_in_float;
1291 1291
1292 1292 delta_snapshot = waveform_picker_regs->delta_snapshot;
1293 1293 nb_samples_per_snapshot = parameter_dump_packet.sy_lfr_n_swf_l[0] * 256 + parameter_dump_packet.sy_lfr_n_swf_l[1];
1294 1294 delta_f0_in_float =nb_samples_per_snapshot / 2. * ( 1. / 256. - 1. / 24576.) * 256.;
1295 1295
1296 1296 waveform_picker_regs->delta_f0 = delta_snapshot - floor( delta_f0_in_float );
1297 1297 waveform_picker_regs->delta_f0_2 = 0x7; // max 7 bits
1298 1298 }
1299 1299
1300 1300 void set_wfp_delta_f1( void )
1301 1301 {
1302 1302 unsigned int delta_snapshot;
1303 1303 unsigned int nb_samples_per_snapshot;
1304 1304 float delta_f1_in_float;
1305 1305
1306 1306 delta_snapshot = waveform_picker_regs->delta_snapshot;
1307 1307 nb_samples_per_snapshot = parameter_dump_packet.sy_lfr_n_swf_l[0] * 256 + parameter_dump_packet.sy_lfr_n_swf_l[1];
1308 1308 delta_f1_in_float = nb_samples_per_snapshot / 2. * ( 1. / 256. - 1. / 4096.) * 256.;
1309 1309
1310 1310 waveform_picker_regs->delta_f1 = delta_snapshot - floor( delta_f1_in_float );
1311 1311 }
1312 1312
1313 1313 void set_wfp_delta_f2()
1314 1314 {
1315 1315 unsigned int delta_snapshot;
1316 1316 unsigned int nb_samples_per_snapshot;
1317 1317
1318 1318 delta_snapshot = waveform_picker_regs->delta_snapshot;
1319 1319 nb_samples_per_snapshot = parameter_dump_packet.sy_lfr_n_swf_l[0] * 256 + parameter_dump_packet.sy_lfr_n_swf_l[1];
1320 1320
1321 1321 waveform_picker_regs->delta_f2 = delta_snapshot - nb_samples_per_snapshot / 2;
1322 1322 }
1323 1323
1324 1324 //*****************
1325 1325 // local parameters
1326 1326
1327 1327 void increment_seq_counter_source_id( unsigned char *packet_sequence_control, unsigned int sid )
1328 1328 {
1329 1329 /** This function increments the parameter "sequence_cnt" depending on the sid passed in argument.
1330 1330 *
1331 1331 * @param packet_sequence_control is a pointer toward the parameter sequence_cnt to update.
1332 1332 * @param sid is the source identifier of the packet being updated.
1333 1333 *
1334 1334 * REQ-LFR-SRS-5240 / SSS-CP-FS-590
1335 1335 * The sequence counters shall wrap around from 2^14 to zero.
1336 1336 * The sequence counter shall start at zero at startup.
1337 1337 *
1338 1338 * REQ-LFR-SRS-5239 / SSS-CP-FS-580
1339 1339 * All TM_LFR_SCIENCE_ packets are sent to ground, i.e. destination id = 0
1340 1340 *
1341 1341 */
1342 1342
1343 1343 unsigned short *sequence_cnt;
1344 1344 unsigned short segmentation_grouping_flag;
1345 1345 unsigned short new_packet_sequence_control;
1346 1346 rtems_mode initial_mode_set;
1347 1347 rtems_mode current_mode_set;
1348 1348 rtems_status_code status;
1349 1349
1350 1350 //******************************************
1351 1351 // CHANGE THE MODE OF THE CALLING RTEMS TASK
1352 1352 status = rtems_task_mode( RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &initial_mode_set );
1353 1353
1354 1354 if ( (sid == SID_NORM_SWF_F0) || (sid == SID_NORM_SWF_F1) || (sid == SID_NORM_SWF_F2)
1355 1355 || (sid == SID_NORM_CWF_F3) || (sid == SID_NORM_CWF_LONG_F3)
1356 1356 || (sid == SID_BURST_CWF_F2)
1357 1357 || (sid == SID_NORM_ASM_F0) || (sid == SID_NORM_ASM_F1) || (sid == SID_NORM_ASM_F2)
1358 1358 || (sid == SID_NORM_BP1_F0) || (sid == SID_NORM_BP1_F1) || (sid == SID_NORM_BP1_F2)
1359 1359 || (sid == SID_NORM_BP2_F0) || (sid == SID_NORM_BP2_F1) || (sid == SID_NORM_BP2_F2)
1360 1360 || (sid == SID_BURST_BP1_F0) || (sid == SID_BURST_BP2_F0)
1361 1361 || (sid == SID_BURST_BP1_F1) || (sid == SID_BURST_BP2_F1) )
1362 1362 {
1363 1363 sequence_cnt = (unsigned short *) &sequenceCounters_SCIENCE_NORMAL_BURST;
1364 1364 }
1365 1365 else if ( (sid ==SID_SBM1_CWF_F1) || (sid ==SID_SBM2_CWF_F2)
1366 1366 || (sid == SID_SBM1_BP1_F0) || (sid == SID_SBM1_BP2_F0)
1367 1367 || (sid == SID_SBM2_BP1_F0) || (sid == SID_SBM2_BP2_F0)
1368 1368 || (sid == SID_SBM2_BP1_F1) || (sid == SID_SBM2_BP2_F1) )
1369 1369 {
1370 1370 sequence_cnt = (unsigned short *) &sequenceCounters_SCIENCE_SBM1_SBM2;
1371 1371 }
1372 1372 else
1373 1373 {
1374 1374 sequence_cnt = (unsigned short *) NULL;
1375 1375 PRINTF1("in increment_seq_counter_source_id *** ERR apid_destid %d not known\n", sid)
1376 1376 }
1377 1377
1378 1378 if (sequence_cnt != NULL)
1379 1379 {
1380 1380 segmentation_grouping_flag = TM_PACKET_SEQ_CTRL_STANDALONE << 8;
1381 1381 *sequence_cnt = (*sequence_cnt) & 0x3fff;
1382 1382
1383 1383 new_packet_sequence_control = segmentation_grouping_flag | (*sequence_cnt) ;
1384 1384
1385 1385 packet_sequence_control[0] = (unsigned char) (new_packet_sequence_control >> 8);
1386 1386 packet_sequence_control[1] = (unsigned char) (new_packet_sequence_control );
1387 1387
1388 1388 // increment the sequence counter
1389 1389 if ( *sequence_cnt < SEQ_CNT_MAX)
1390 1390 {
1391 1391 *sequence_cnt = *sequence_cnt + 1;
1392 1392 }
1393 1393 else
1394 1394 {
1395 1395 *sequence_cnt = 0;
1396 1396 }
1397 1397 }
1398 1398
1399 1399 //***********************************
1400 1400 // RESET THE MODE OF THE CALLING TASK
1401 1401 status = rtems_task_mode( initial_mode_set, RTEMS_PREEMPT_MASK, &current_mode_set );
1402 1402 }
General Comments 0
You need to be logged in to leave comments. Login now