@@ -1,6 +1,6 | |||
|
1 | 1 | ############################################################################# |
|
2 | 2 | # Makefile for building: bin/fsw |
|
3 |
# Generated by qmake (2.01a) (Qt 4.8.5) on: Tue Mar 4 |
|
|
3 | # Generated by qmake (2.01a) (Qt 4.8.5) on: Tue Mar 4 13:06:39 2014 | |
|
4 | 4 | # Project: fsw-qt.pro |
|
5 | 5 | # Template: app |
|
6 | 6 | # Command: /usr/bin/qmake-qt4 -spec /usr/lib64/qt4/mkspecs/linux-g++ -o Makefile fsw-qt.pro |
@@ -10,7 +10,7 | |||
|
10 | 10 | |
|
11 | 11 | CC = sparc-rtems-gcc |
|
12 | 12 | CXX = sparc-rtems-g++ |
|
13 |
DEFINES = -DSW_VERSION_N1=1 -DSW_VERSION_N2=0 -DSW_VERSION_N3=0 -DSW_VERSION_N4= |
|
|
13 | DEFINES = -DSW_VERSION_N1=1 -DSW_VERSION_N2=0 -DSW_VERSION_N3=0 -DSW_VERSION_N4=3 -DPRINT_MESSAGES_ON_CONSOLE | |
|
14 | 14 | CFLAGS = -pipe -O3 -Wall $(DEFINES) |
|
15 | 15 | CXXFLAGS = -pipe -O3 -Wall $(DEFINES) |
|
16 | 16 | INCPATH = -I/usr/lib64/qt4/mkspecs/linux-g++ -I. -I../src -I../header -I../../LFR_basic-parameters |
@@ -1,7 +1,7 | |||
|
1 | 1 | TEMPLATE = app |
|
2 | 2 | # CONFIG += console v8 sim |
|
3 | 3 | # CONFIG options = verbose *** boot_messages *** debug_messages *** cpu_usage_report *** stack_report |
|
4 |
CONFIG += console verbose |
|
|
4 | CONFIG += console verbose | |
|
5 | 5 | CONFIG -= qt |
|
6 | 6 | |
|
7 | 7 | include(./sparc.pri) |
@@ -11,7 +11,7 SWVERSION=-1-0 | |||
|
11 | 11 | DEFINES += SW_VERSION_N1=1 # major |
|
12 | 12 | DEFINES += SW_VERSION_N2=0 # minor |
|
13 | 13 | DEFINES += SW_VERSION_N3=0 # patch |
|
14 |
DEFINES += SW_VERSION_N4= |
|
|
14 | DEFINES += SW_VERSION_N4=3 # internal | |
|
15 | 15 | |
|
16 | 16 | contains( CONFIG, verbose ) { |
|
17 | 17 | DEFINES += PRINT_MESSAGES_ON_CONSOLE |
@@ -1,6 +1,6 | |||
|
1 | 1 | <?xml version="1.0" encoding="UTF-8"?> |
|
2 | 2 | <!DOCTYPE QtCreatorProject> |
|
3 |
<!-- Written by QtCreator 3.0.0, 2014-03-0 |
|
|
3 | <!-- Written by QtCreator 3.0.0, 2014-03-06T15:56:18. --> | |
|
4 | 4 | <qtcreator> |
|
5 | 5 | <data> |
|
6 | 6 | <variable>ProjectExplorer.Project.ActiveTarget</variable> |
@@ -144,7 +144,7 typedef struct ring_node | |||
|
144 | 144 | #define TASKID_SMIQ 4 |
|
145 | 145 | #define TASKID_STAT 5 |
|
146 | 146 | #define TASKID_AVF0 6 |
|
147 |
|
|
|
147 | #define TASKID_SWBD 7 | |
|
148 | 148 | #define TASKID_WFRM 8 |
|
149 | 149 | #define TASKID_DUMB 9 |
|
150 | 150 | #define TASKID_HOUS 10 |
@@ -163,6 +163,7 typedef struct ring_node | |||
|
163 | 163 | #define TASK_PRIORITY_CWF2 35 // |
|
164 | 164 | #define TASK_PRIORITY_WFRM 40 |
|
165 | 165 | #define TASK_PRIORITY_CWF3 40 // there is a printf in this function, be careful with its priority wrt CWF1 |
|
166 | #define TASK_PRIORITY_SWBD 40 | |
|
166 | 167 | #define TASK_PRIORITY_SEND 45 |
|
167 | 168 | #define TASK_PRIORITY_RECV 50 |
|
168 | 169 | #define TASK_PRIORITY_ACTN 50 |
@@ -40,12 +40,17 extern rtems_id Task_id[20]; | |||
|
40 | 40 | |
|
41 | 41 | extern unsigned char lfrCurrentMode; |
|
42 | 42 | |
|
43 | //********** | |
|
44 | // RTEMS_ISR | |
|
43 | 45 | rtems_isr waveforms_isr( rtems_vector_number vector ); |
|
44 | rtems_isr waveforms_isr_alt( rtems_vector_number vector ); | |
|
46 | ||
|
47 | //*********** | |
|
48 | // RTEMS_TASK | |
|
45 | 49 | rtems_task wfrm_task( rtems_task_argument argument ); |
|
46 | 50 | rtems_task cwf3_task( rtems_task_argument argument ); |
|
47 | 51 | rtems_task cwf2_task( rtems_task_argument argument ); |
|
48 | 52 | rtems_task cwf1_task( rtems_task_argument argument ); |
|
53 | rtems_task swbd_task( rtems_task_argument argument ); | |
|
49 | 54 | |
|
50 | 55 | //****************** |
|
51 | 56 | // general functions |
@@ -64,6 +69,7 int send_waveform_CWF3_light( volatile i | |||
|
64 | 69 | // |
|
65 | 70 | void compute_acquisition_time(unsigned int coarseTime, unsigned int fineTime, |
|
66 | 71 | unsigned int sid, unsigned char pa_lfr_pkt_nr, unsigned char *acquisitionTime ); |
|
72 | void build_snapshot_from_ring( void ); | |
|
67 | 73 | // |
|
68 | 74 | rtems_id get_pkts_queue_id( void ); |
|
69 | 75 |
@@ -46,9 +46,9 volatile int wf_cont_f3_b [ (NB_SAMPL | |||
|
46 | 46 | char wf_cont_f3_light[ (NB_SAMPLES_PER_SNAPSHOT) * NB_BYTES_CWF3_LIGHT_BLK + TIME_OFFSET_IN_BYTES ] __attribute__((aligned(0x100))); |
|
47 | 47 | |
|
48 | 48 | // SPECTRAL MATRICES GLOBAL VARIABLES |
|
49 | volatile int sm_f0[ NB_RING_NODES_ASM_F0 ][ TIME_OFFSET + TOTAL_SIZE_SM ] __attribute__((aligned(0x100))); | |
|
50 | volatile int sm_f1[ NB_RING_NODES_ASM_F1 ][ TIME_OFFSET + TOTAL_SIZE_SM ] __attribute__((aligned(0x100))); | |
|
51 | volatile int sm_f2[ NB_RING_NODES_ASM_F2 ][ TIME_OFFSET + TOTAL_SIZE_SM ] __attribute__((aligned(0x100))); | |
|
49 | volatile int sm_f0[ NB_RING_NODES_ASM_F0 ][ TIME_OFFSET + TOTAL_SIZE_SM + 62 ] __attribute__((aligned(0x100))); | |
|
50 | volatile int sm_f1[ NB_RING_NODES_ASM_F1 ][ TIME_OFFSET + TOTAL_SIZE_SM + 62 ] __attribute__((aligned(0x100))); | |
|
51 | volatile int sm_f2[ NB_RING_NODES_ASM_F2 ][ TIME_OFFSET + TOTAL_SIZE_SM + 62 ] __attribute__((aligned(0x100))); | |
|
52 | 52 | |
|
53 | 53 | // APB CONFIGURATION REGISTERS |
|
54 | 54 | time_management_regs_t *time_management_regs = (time_management_regs_t*) REGS_ADDR_TIME_MANAGEMENT; |
@@ -246,7 +246,7 void create_names( void ) // create all | |||
|
246 | 246 | Task_name[TASKID_SMIQ] = rtems_build_name( 'S', 'M', 'I', 'Q' ); |
|
247 | 247 | Task_name[TASKID_STAT] = rtems_build_name( 'S', 'T', 'A', 'T' ); |
|
248 | 248 | Task_name[TASKID_AVF0] = rtems_build_name( 'A', 'V', 'F', '0' ); |
|
249 |
|
|
|
249 | Task_name[TASKID_SWBD] = rtems_build_name( 'S', 'W', 'B', 'D' ); | |
|
250 | 250 | Task_name[TASKID_WFRM] = rtems_build_name( 'W', 'F', 'R', 'M' ); |
|
251 | 251 | Task_name[TASKID_DUMB] = rtems_build_name( 'D', 'U', 'M', 'B' ); |
|
252 | 252 | Task_name[TASKID_HOUS] = rtems_build_name( 'H', 'O', 'U', 'S' ); |
@@ -282,13 +282,30 int create_all_tasks( void ) // create a | |||
|
282 | 282 | |
|
283 | 283 | rtems_status_code status; |
|
284 | 284 | |
|
285 | //********** | |
|
286 | // SPACEWIRE | |
|
285 | 287 | // RECV |
|
286 | 288 | status = rtems_task_create( |
|
287 | 289 | Task_name[TASKID_RECV], TASK_PRIORITY_RECV, RTEMS_MINIMUM_STACK_SIZE, |
|
288 | 290 | RTEMS_DEFAULT_MODES, |
|
289 | 291 | RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_RECV] |
|
290 | 292 | ); |
|
291 | ||
|
293 | if (status == RTEMS_SUCCESSFUL) // SEND | |
|
294 | { | |
|
295 | status = rtems_task_create( | |
|
296 | Task_name[TASKID_SEND], TASK_PRIORITY_SEND, RTEMS_MINIMUM_STACK_SIZE, | |
|
297 | RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT, | |
|
298 | RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_SEND] | |
|
299 | ); | |
|
300 | } | |
|
301 | if (status == RTEMS_SUCCESSFUL) // WTDG | |
|
302 | { | |
|
303 | status = rtems_task_create( | |
|
304 | Task_name[TASKID_WTDG], TASK_PRIORITY_WTDG, RTEMS_MINIMUM_STACK_SIZE, | |
|
305 | RTEMS_DEFAULT_MODES, | |
|
306 | RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_WTDG] | |
|
307 | ); | |
|
308 | } | |
|
292 | 309 | if (status == RTEMS_SUCCESSFUL) // ACTN |
|
293 | 310 | { |
|
294 | 311 | status = rtems_task_create( |
@@ -305,6 +322,9 int create_all_tasks( void ) // create a | |||
|
305 | 322 | RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_SPIQ] |
|
306 | 323 | ); |
|
307 | 324 | } |
|
325 | ||
|
326 | //****************** | |
|
327 | // SPECTRAL MATRICES | |
|
308 | 328 | if (status == RTEMS_SUCCESSFUL) // SMIQ |
|
309 | 329 | { |
|
310 | 330 | status = rtems_task_create( |
@@ -313,14 +333,6 int create_all_tasks( void ) // create a | |||
|
313 | 333 | RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_SMIQ] |
|
314 | 334 | ); |
|
315 | 335 | } |
|
316 | if (status == RTEMS_SUCCESSFUL) // STAT | |
|
317 | { | |
|
318 | status = rtems_task_create( | |
|
319 | Task_name[TASKID_STAT], TASK_PRIORITY_STAT, RTEMS_MINIMUM_STACK_SIZE, | |
|
320 | RTEMS_DEFAULT_MODES, | |
|
321 | RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_STAT] | |
|
322 | ); | |
|
323 | } | |
|
324 | 336 | if (status == RTEMS_SUCCESSFUL) // AVF0 |
|
325 | 337 | { |
|
326 | 338 | status = rtems_task_create( |
@@ -329,6 +341,17 int create_all_tasks( void ) // create a | |||
|
329 | 341 | RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_AVF0] |
|
330 | 342 | ); |
|
331 | 343 | } |
|
344 | if (status == RTEMS_SUCCESSFUL) // MATR | |
|
345 | { | |
|
346 | status = rtems_task_create( | |
|
347 | Task_name[TASKID_MATR], TASK_PRIORITY_MATR, RTEMS_MINIMUM_STACK_SIZE, | |
|
348 | RTEMS_DEFAULT_MODES, | |
|
349 | RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_MATR] | |
|
350 | ); | |
|
351 | } | |
|
352 | ||
|
353 | //**************** | |
|
354 | // WAVEFORM PICKER | |
|
332 | 355 | if (status == RTEMS_SUCCESSFUL) // WFRM |
|
333 | 356 | { |
|
334 | 357 | status = rtems_task_create( |
@@ -337,30 +360,6 int create_all_tasks( void ) // create a | |||
|
337 | 360 | RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_WFRM] |
|
338 | 361 | ); |
|
339 | 362 | } |
|
340 | if (status == RTEMS_SUCCESSFUL) // DUMB | |
|
341 | { | |
|
342 | status = rtems_task_create( | |
|
343 | Task_name[TASKID_DUMB], TASK_PRIORITY_DUMB, RTEMS_MINIMUM_STACK_SIZE, | |
|
344 | RTEMS_DEFAULT_MODES, | |
|
345 | RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_DUMB] | |
|
346 | ); | |
|
347 | } | |
|
348 | if (status == RTEMS_SUCCESSFUL) // HOUS | |
|
349 | { | |
|
350 | status = rtems_task_create( | |
|
351 | Task_name[TASKID_HOUS], TASK_PRIORITY_HOUS, RTEMS_MINIMUM_STACK_SIZE, | |
|
352 | RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT, | |
|
353 | RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_HOUS] | |
|
354 | ); | |
|
355 | } | |
|
356 | if (status == RTEMS_SUCCESSFUL) // MATR | |
|
357 | { | |
|
358 | status = rtems_task_create( | |
|
359 | Task_name[TASKID_MATR], TASK_PRIORITY_MATR, RTEMS_MINIMUM_STACK_SIZE, | |
|
360 | RTEMS_DEFAULT_MODES, | |
|
361 | RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_MATR] | |
|
362 | ); | |
|
363 | } | |
|
364 | 363 | if (status == RTEMS_SUCCESSFUL) // CWF3 |
|
365 | 364 | { |
|
366 | 365 | status = rtems_task_create( |
@@ -385,20 +384,39 int create_all_tasks( void ) // create a | |||
|
385 | 384 | RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_CWF1] |
|
386 | 385 | ); |
|
387 | 386 | } |
|
388 |
if (status == RTEMS_SUCCESSFUL) // S |
|
|
387 | if (status == RTEMS_SUCCESSFUL) // SWBD | |
|
388 | { | |
|
389 | status = rtems_task_create( | |
|
390 | Task_name[TASKID_SWBD], TASK_PRIORITY_SWBD, RTEMS_MINIMUM_STACK_SIZE, | |
|
391 | RTEMS_DEFAULT_MODES, | |
|
392 | RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_SWBD] | |
|
393 | ); | |
|
394 | } | |
|
395 | ||
|
396 | //***** | |
|
397 | // MISC | |
|
398 | if (status == RTEMS_SUCCESSFUL) // STAT | |
|
389 | 399 | { |
|
390 | 400 | status = rtems_task_create( |
|
391 |
Task_name[TASKID_S |
|
|
392 |
RTEMS_DEFAULT_MODES |
|
|
393 |
RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_S |
|
|
401 | Task_name[TASKID_STAT], TASK_PRIORITY_STAT, RTEMS_MINIMUM_STACK_SIZE, | |
|
402 | RTEMS_DEFAULT_MODES, | |
|
403 | RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_STAT] | |
|
394 | 404 | ); |
|
395 | 405 | } |
|
396 |
if (status == RTEMS_SUCCESSFUL) // |
|
|
406 | if (status == RTEMS_SUCCESSFUL) // DUMB | |
|
397 | 407 | { |
|
398 | 408 | status = rtems_task_create( |
|
399 |
Task_name[TASKID_ |
|
|
409 | Task_name[TASKID_DUMB], TASK_PRIORITY_DUMB, RTEMS_MINIMUM_STACK_SIZE, | |
|
400 | 410 | RTEMS_DEFAULT_MODES, |
|
401 |
RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_ |
|
|
411 | RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_DUMB] | |
|
412 | ); | |
|
413 | } | |
|
414 | if (status == RTEMS_SUCCESSFUL) // HOUS | |
|
415 | { | |
|
416 | status = rtems_task_create( | |
|
417 | Task_name[TASKID_HOUS], TASK_PRIORITY_HOUS, RTEMS_MINIMUM_STACK_SIZE, | |
|
418 | RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT, | |
|
419 | RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_HOUS] | |
|
402 | 420 | ); |
|
403 | 421 | } |
|
404 | 422 | |
@@ -441,6 +459,8 int start_all_tasks( void ) // start all | |||
|
441 | 459 | |
|
442 | 460 | rtems_status_code status; |
|
443 | 461 | |
|
462 | //********** | |
|
463 | // SPACEWIRE | |
|
444 | 464 | status = rtems_task_start( Task_id[TASKID_SPIQ], spiq_task, 1 ); |
|
445 | 465 | if (status!=RTEMS_SUCCESSFUL) { |
|
446 | 466 | BOOT_PRINTF("in INIT *** Error starting TASK_SPIQ\n") |
@@ -454,14 +474,6 int start_all_tasks( void ) // start all | |||
|
454 | 474 | } |
|
455 | 475 | } |
|
456 | 476 | |
|
457 | if (status == RTEMS_SUCCESSFUL) // SMIQ | |
|
458 | { | |
|
459 | status = rtems_task_start( Task_id[TASKID_SMIQ], smiq_task, 1 ); | |
|
460 | if (status!=RTEMS_SUCCESSFUL) { | |
|
461 | BOOT_PRINTF("in INIT *** Error starting TASK_BPPR\n") | |
|
462 | } | |
|
463 | } | |
|
464 | ||
|
465 | 477 | if (status == RTEMS_SUCCESSFUL) // ACTN |
|
466 | 478 | { |
|
467 | 479 | status = rtems_task_start( Task_id[TASKID_ACTN], actn_task, 1 ); |
@@ -470,11 +482,13 int start_all_tasks( void ) // start all | |||
|
470 | 482 | } |
|
471 | 483 | } |
|
472 | 484 | |
|
473 | if (status == RTEMS_SUCCESSFUL) // STAT | |
|
485 | //****************** | |
|
486 | // SPECTRAL MATRICES | |
|
487 | if (status == RTEMS_SUCCESSFUL) // SMIQ | |
|
474 | 488 | { |
|
475 |
status = rtems_task_start( Task_id[TASKID_S |
|
|
489 | status = rtems_task_start( Task_id[TASKID_SMIQ], smiq_task, 1 ); | |
|
476 | 490 | if (status!=RTEMS_SUCCESSFUL) { |
|
477 |
BOOT_PRINTF("in INIT *** Error starting TASK_ |
|
|
491 | BOOT_PRINTF("in INIT *** Error starting TASK_BPPR\n") | |
|
478 | 492 | } |
|
479 | 493 | } |
|
480 | 494 | |
@@ -486,6 +500,16 int start_all_tasks( void ) // start all | |||
|
486 | 500 | } |
|
487 | 501 | } |
|
488 | 502 | |
|
503 | if (status == RTEMS_SUCCESSFUL) // MATR | |
|
504 | { | |
|
505 | status = rtems_task_start( Task_id[TASKID_MATR], matr_task, 1 ); | |
|
506 | if (status!=RTEMS_SUCCESSFUL) { | |
|
507 | BOOT_PRINTF("in INIT *** Error starting TASK_MATR\n") | |
|
508 | } | |
|
509 | } | |
|
510 | ||
|
511 | //**************** | |
|
512 | // WAVEFORM PICKER | |
|
489 | 513 | if (status == RTEMS_SUCCESSFUL) // WFRM |
|
490 | 514 | { |
|
491 | 515 | status = rtems_task_start( Task_id[TASKID_WFRM], wfrm_task, 1 ); |
@@ -494,30 +518,6 int start_all_tasks( void ) // start all | |||
|
494 | 518 | } |
|
495 | 519 | } |
|
496 | 520 | |
|
497 | if (status == RTEMS_SUCCESSFUL) // DUMB | |
|
498 | { | |
|
499 | status = rtems_task_start( Task_id[TASKID_DUMB], dumb_task, 1 ); | |
|
500 | if (status!=RTEMS_SUCCESSFUL) { | |
|
501 | BOOT_PRINTF("in INIT *** Error starting TASK_DUMB\n") | |
|
502 | } | |
|
503 | } | |
|
504 | ||
|
505 | if (status == RTEMS_SUCCESSFUL) // HOUS | |
|
506 | { | |
|
507 | status = rtems_task_start( Task_id[TASKID_HOUS], hous_task, 1 ); | |
|
508 | if (status!=RTEMS_SUCCESSFUL) { | |
|
509 | BOOT_PRINTF("in INIT *** Error starting TASK_HOUS\n") | |
|
510 | } | |
|
511 | } | |
|
512 | ||
|
513 | if (status == RTEMS_SUCCESSFUL) // MATR | |
|
514 | { | |
|
515 | status = rtems_task_start( Task_id[TASKID_MATR], matr_task, 1 ); | |
|
516 | if (status!=RTEMS_SUCCESSFUL) { | |
|
517 | BOOT_PRINTF("in INIT *** Error starting TASK_MATR\n") | |
|
518 | } | |
|
519 | } | |
|
520 | ||
|
521 | 521 | if (status == RTEMS_SUCCESSFUL) // CWF3 |
|
522 | 522 | { |
|
523 | 523 | status = rtems_task_start( Task_id[TASKID_CWF3], cwf3_task, 1 ); |
@@ -541,6 +541,41 int start_all_tasks( void ) // start all | |||
|
541 | 541 | BOOT_PRINTF("in INIT *** Error starting TASK_CWF1\n") |
|
542 | 542 | } |
|
543 | 543 | } |
|
544 | ||
|
545 | if (status == RTEMS_SUCCESSFUL) // SWBD | |
|
546 | { | |
|
547 | status = rtems_task_start( Task_id[TASKID_SWBD], swbd_task, 1 ); | |
|
548 | if (status!=RTEMS_SUCCESSFUL) { | |
|
549 | BOOT_PRINTF("in INIT *** Error starting TASK_SWBD\n") | |
|
550 | } | |
|
551 | } | |
|
552 | ||
|
553 | //***** | |
|
554 | // MISC | |
|
555 | if (status == RTEMS_SUCCESSFUL) // HOUS | |
|
556 | { | |
|
557 | status = rtems_task_start( Task_id[TASKID_HOUS], hous_task, 1 ); | |
|
558 | if (status!=RTEMS_SUCCESSFUL) { | |
|
559 | BOOT_PRINTF("in INIT *** Error starting TASK_HOUS\n") | |
|
560 | } | |
|
561 | } | |
|
562 | ||
|
563 | if (status == RTEMS_SUCCESSFUL) // DUMB | |
|
564 | { | |
|
565 | status = rtems_task_start( Task_id[TASKID_DUMB], dumb_task, 1 ); | |
|
566 | if (status!=RTEMS_SUCCESSFUL) { | |
|
567 | BOOT_PRINTF("in INIT *** Error starting TASK_DUMB\n") | |
|
568 | } | |
|
569 | } | |
|
570 | ||
|
571 | if (status == RTEMS_SUCCESSFUL) // STAT | |
|
572 | { | |
|
573 | status = rtems_task_start( Task_id[TASKID_STAT], stat_task, 1 ); | |
|
574 | if (status!=RTEMS_SUCCESSFUL) { | |
|
575 | BOOT_PRINTF("in INIT *** Error starting TASK_STAT\n") | |
|
576 | } | |
|
577 | } | |
|
578 | ||
|
544 | 579 | return status; |
|
545 | 580 | } |
|
546 | 581 |
@@ -36,6 +36,10 ring_node *current_ring_node_f2; | |||
|
36 | 36 | ring_node *ring_node_to_send_swf_f2; |
|
37 | 37 | ring_node *ring_node_to_send_cwf_f2; |
|
38 | 38 | |
|
39 | bool extractSWF = false; | |
|
40 | ||
|
41 | int wf_snap_f1_extracted[ (NB_SAMPLES_PER_SNAPSHOT * NB_WORDS_SWF_BLK) + TIME_OFFSET ]; | |
|
42 | ||
|
39 | 43 | rtems_isr waveforms_isr( rtems_vector_number vector ) |
|
40 | 44 | { |
|
41 | 45 | /** This is the interrupt sub routine called by the waveform picker core. |
@@ -135,175 +139,34 rtems_isr waveforms_isr( rtems_vector_nu | |||
|
135 | 139 | // SBM1 |
|
136 | 140 | case(LFR_MODE_SBM1): |
|
137 | 141 | if ( (waveform_picker_regs->status & 0x02) == 0x02 ) { // [0010] check the f1 full bit |
|
142 | // (0) launch snapshot extraction if needed | |
|
143 | if (extractSWF == true) | |
|
144 | { | |
|
145 | ring_node_to_send_swf_f1 = current_ring_node_f1; | |
|
146 | if (rtems_event_send( Task_id[TASKID_SWBD], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) { | |
|
147 | rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_2 ); | |
|
148 | } | |
|
149 | extractSWF = false; | |
|
150 | } | |
|
138 | 151 | // (1) change the receiving buffer for the waveform picker |
|
139 | 152 | ring_node_to_send_cwf_f1 = current_ring_node_f1; |
|
140 | 153 | current_ring_node_f1 = current_ring_node_f1->next; |
|
141 | 154 | waveform_picker_regs->addr_data_f1 = current_ring_node_f1->buffer_address; |
|
142 |
// (2) send an event for the |
|
|
155 | // (2) send an event for the the CWF1 task for transmission | |
|
143 | 156 | if (rtems_event_send( Task_id[TASKID_CWF1], RTEMS_EVENT_MODE_SBM1 ) != RTEMS_SUCCESSFUL) { |
|
144 | 157 | rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_2 ); |
|
145 | 158 | } |
|
146 | waveform_picker_regs->status = waveform_picker_regs->status & 0xfffffddd; // [1111 1101 1101 1101] f1 bit = 0 | |
|
147 | } | |
|
148 | if ( (waveform_picker_regs->status & 0x01) == 0x01 ) { // [0001] check the f0 full bit | |
|
149 | ring_node_to_send_swf_f1 = current_ring_node_f1->previous; | |
|
150 | } | |
|
151 | if ( (waveform_picker_regs->status & 0x04) == 0x04 ) { // [0100] check the f2 full bit | |
|
152 | if (rtems_event_send( Task_id[TASKID_WFRM], RTEMS_EVENT_MODE_NORMAL ) != RTEMS_SUCCESSFUL) { | |
|
153 | rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_2 ); | |
|
154 | } | |
|
155 | waveform_picker_regs->status = waveform_picker_regs->status & 0xfffffaaa; // [1111 1010 1010 1010] f2 and f0 bits = 0 | |
|
156 | } | |
|
157 | break; | |
|
158 | ||
|
159 | //***** | |
|
160 | // SBM2 | |
|
161 | case(LFR_MODE_SBM2): | |
|
162 | if ( (waveform_picker_regs->status & 0x04) == 0x04 ){ // [0100] check the f2 full bit | |
|
163 | // (1) change the receiving buffer for the waveform picker | |
|
164 | ring_node_to_send_cwf_f2 = current_ring_node_f2; | |
|
165 | current_ring_node_f2 = current_ring_node_f2->next; | |
|
166 | waveform_picker_regs->addr_data_f2 = current_ring_node_f2->buffer_address; | |
|
167 | // (2) send an event for the waveforms transmission | |
|
168 | if (rtems_event_send( Task_id[TASKID_CWF2], RTEMS_EVENT_MODE_SBM2 ) != RTEMS_SUCCESSFUL) { | |
|
169 | rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_2 ); | |
|
170 | } | |
|
171 | waveform_picker_regs->status = waveform_picker_regs->status & 0xfffffbbb; // [1111 1011 1011 1011] f2 bit = 0 | |
|
159 | waveform_picker_regs->status = waveform_picker_regs->status & 0xfffffddd; // [1111 1101 1101 1101] f1 bits = 0 | |
|
172 | 160 | } |
|
173 | 161 | if ( (waveform_picker_regs->status & 0x01) == 0x01 ) { // [0001] check the f0 full bit |
|
174 | ring_node_to_send_swf_f2 = current_ring_node_f2->previous; | |
|
175 | } | |
|
176 | if ( (waveform_picker_regs->status & 0x02) == 0x02 ) { // [0010] check the f1 full bit | |
|
177 | if (rtems_event_send( Task_id[TASKID_WFRM], RTEMS_EVENT_MODE_NORMAL ) != RTEMS_SUCCESSFUL) { | |
|
178 | rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_2 ); | |
|
179 | } | |
|
180 | waveform_picker_regs->status = waveform_picker_regs->status & 0xfffffccc; // [1111 1100 1100 1100] f1, f0 bits = 0 | |
|
162 | extractSWF = true; | |
|
163 | waveform_picker_regs->status = waveform_picker_regs->status & 0xfffffeee; // [1111 1110 1110 1110] f0 bits = 0 | |
|
181 | 164 | } |
|
182 | break; | |
|
183 | ||
|
184 | //******** | |
|
185 | // DEFAULT | |
|
186 | default: | |
|
187 | break; | |
|
188 | } | |
|
189 | } | |
|
190 | ||
|
191 | rtems_isr waveforms_isr_alt( rtems_vector_number vector ) | |
|
192 | { | |
|
193 | /** This is the interrupt sub routine called by the waveform picker core. | |
|
194 | * | |
|
195 | * This ISR launch different actions depending mainly on two pieces of information: | |
|
196 | * 1. the values read in the registers of the waveform picker. | |
|
197 | * 2. the current LFR mode. | |
|
198 | * | |
|
199 | */ | |
|
200 | ||
|
201 | if ( (lfrCurrentMode == LFR_MODE_NORMAL) | |
|
202 | || (lfrCurrentMode == LFR_MODE_SBM1) || (lfrCurrentMode == LFR_MODE_SBM2) ) | |
|
203 | { // in modes other than STANDBY and BURST, send the CWF_F3 data | |
|
204 | if ((waveform_picker_regs->status & 0x08) == 0x08){ // [1000] f3 is full | |
|
205 | // (1) change the receiving buffer for the waveform picker | |
|
206 | if (waveform_picker_regs->addr_data_f3 == (int) wf_cont_f3_a) { | |
|
207 | waveform_picker_regs->addr_data_f3 = (int) (wf_cont_f3_b); | |
|
208 | } | |
|
209 | else { | |
|
210 | waveform_picker_regs->addr_data_f3 = (int) (wf_cont_f3_a); | |
|
211 | } | |
|
212 | // (2) send an event for the waveforms transmission | |
|
213 | if (rtems_event_send( Task_id[TASKID_CWF3], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) { | |
|
165 | if ( (waveform_picker_regs->status & 0x04) == 0x04 ) { // [0100] check the f2 full bit | |
|
166 | if (rtems_event_send( Task_id[TASKID_WFRM], RTEMS_EVENT_MODE_SBM1 ) != RTEMS_SUCCESSFUL) { | |
|
214 | 167 | rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_2 ); |
|
215 | 168 | } |
|
216 |
waveform_picker_regs->status = waveform_picker_regs->status & 0xfffff |
|
|
217 | } | |
|
218 | } | |
|
219 | ||
|
220 | switch(lfrCurrentMode) | |
|
221 | { | |
|
222 | //******** | |
|
223 | // STANDBY | |
|
224 | case(LFR_MODE_STANDBY): | |
|
225 | break; | |
|
226 | ||
|
227 | //****** | |
|
228 | // NORMAL | |
|
229 | case(LFR_MODE_NORMAL): | |
|
230 | if ( (waveform_picker_regs->status & 0xff8) != 0x00) // [1000] check the error bits | |
|
231 | { | |
|
232 | rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_2 ); | |
|
233 | } | |
|
234 | if ( (waveform_picker_regs->status & 0x01) == 0x01) // [0001] check the f0 full bit | |
|
235 | { | |
|
236 | // change F0 ring node | |
|
237 | ring_node_to_send_swf_f0 = current_ring_node_f0; | |
|
238 | current_ring_node_f0 = current_ring_node_f0->next; | |
|
239 | waveform_picker_regs->addr_data_f0 = current_ring_node_f0->buffer_address; | |
|
240 | waveform_picker_regs->status = waveform_picker_regs->status & 0xfffffeee; // [1110 1110 1110] | |
|
241 | if (rtems_event_send( Task_id[TASKID_WFRM], RTEMS_EVENT_MODE_NORMAL_SWF_F0 ) != RTEMS_SUCCESSFUL) { | |
|
242 | rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_2 ); | |
|
243 | } | |
|
244 | } | |
|
245 | if ( (waveform_picker_regs->status & 0x02) == 0x02) // [0010] check the f1 full bit | |
|
246 | { | |
|
247 | // change F1 ring node | |
|
248 | ring_node_to_send_swf_f1 = current_ring_node_f1; | |
|
249 | current_ring_node_f1 = current_ring_node_f1->next; | |
|
250 | waveform_picker_regs->addr_data_f1 = current_ring_node_f1->buffer_address; | |
|
251 | waveform_picker_regs->status = waveform_picker_regs->status & 0xfffffddd; // [1101 1101 1101] | |
|
252 | if (rtems_event_send( Task_id[TASKID_WFRM], RTEMS_EVENT_MODE_NORMAL_SWF_F1 ) != RTEMS_SUCCESSFUL) { | |
|
253 | rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_2 ); | |
|
254 | } | |
|
255 | } | |
|
256 | if ( (waveform_picker_regs->status & 0x04) == 0x04) // [0100] check the f2 full bit | |
|
257 | { | |
|
258 | // change F2 ring node | |
|
259 | ring_node_to_send_swf_f2 = current_ring_node_f2; | |
|
260 | current_ring_node_f2 = current_ring_node_f2->next; | |
|
261 | waveform_picker_regs->addr_data_f2 = current_ring_node_f2->buffer_address; | |
|
262 | waveform_picker_regs->status = waveform_picker_regs->status & 0xfffffbbb; // [1011 1011 1011] | |
|
263 | if (rtems_event_send( Task_id[TASKID_WFRM], RTEMS_EVENT_MODE_NORMAL_SWF_F2 ) != RTEMS_SUCCESSFUL) { | |
|
264 | rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_2 ); | |
|
265 | } | |
|
266 | } | |
|
267 | break; | |
|
268 | ||
|
269 | //****** | |
|
270 | // BURST | |
|
271 | case(LFR_MODE_BURST): | |
|
272 | if ( (waveform_picker_regs->status & 0x04) == 0x04 ){ // [0100] check the f2 full bit | |
|
273 | // (1) change the receiving buffer for the waveform picker | |
|
274 | ring_node_to_send_cwf_f2 = current_ring_node_f2; | |
|
275 | current_ring_node_f2 = current_ring_node_f2->next; | |
|
276 | waveform_picker_regs->addr_data_f2 = current_ring_node_f2->buffer_address; | |
|
277 | // (2) send an event for the waveforms transmission | |
|
278 | if (rtems_event_send( Task_id[TASKID_CWF2], RTEMS_EVENT_MODE_BURST ) != RTEMS_SUCCESSFUL) { | |
|
279 | rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_2 ); | |
|
280 | } | |
|
281 | waveform_picker_regs->status = waveform_picker_regs->status & 0xfffffbbb; // [1111 1011 1011 1011] f2 bit = 0 | |
|
282 | } | |
|
283 | break; | |
|
284 | ||
|
285 | //***** | |
|
286 | // SBM1 | |
|
287 | case(LFR_MODE_SBM1): | |
|
288 | if ( (waveform_picker_regs->status & 0x02) == 0x02 ) { // [0010] check the f1 full bit | |
|
289 | // (1) change the receiving buffer for the waveform picker | |
|
290 | ring_node_to_send_cwf_f1 = current_ring_node_f1; | |
|
291 | current_ring_node_f1 = current_ring_node_f1->next; | |
|
292 | waveform_picker_regs->addr_data_f1 = current_ring_node_f1->buffer_address; | |
|
293 | // (2) send an event for the waveforms transmission | |
|
294 | if (rtems_event_send( Task_id[TASKID_CWF1], RTEMS_EVENT_MODE_SBM1 ) != RTEMS_SUCCESSFUL) { | |
|
295 | rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_2 ); | |
|
296 | } | |
|
297 | waveform_picker_regs->status = waveform_picker_regs->status & 0xfffffddd; // [1111 1101 1101 1101] f1 bit = 0 | |
|
298 | } | |
|
299 | if ( (waveform_picker_regs->status & 0x01) == 0x01 ) { // [0001] check the f0 full bit | |
|
300 | ring_node_to_send_swf_f1 = current_ring_node_f1->previous; | |
|
301 | } | |
|
302 | if ( (waveform_picker_regs->status & 0x04) == 0x04 ) { // [0100] check the f2 full bit | |
|
303 | if (rtems_event_send( Task_id[TASKID_WFRM], RTEMS_EVENT_MODE_NORMAL ) != RTEMS_SUCCESSFUL) { | |
|
304 | rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_2 ); | |
|
305 | } | |
|
306 | waveform_picker_regs->status = waveform_picker_regs->status & 0xfffffaaa; // [1111 1010 1010 1010] f2 and f0 bits = 0 | |
|
169 | waveform_picker_regs->status = waveform_picker_regs->status & 0xfffffbbb; // [1111 1011 1011 1011] f2 bits = 0 | |
|
307 | 170 | } |
|
308 | 171 | break; |
|
309 | 172 | |
@@ -373,27 +236,20 rtems_task wfrm_task(rtems_task_argument | |||
|
373 | 236 | while(1){ |
|
374 | 237 | // wait for an RTEMS_EVENT |
|
375 | 238 | rtems_event_receive(RTEMS_EVENT_MODE_NORMAL | RTEMS_EVENT_MODE_SBM1 |
|
376 | | RTEMS_EVENT_MODE_SBM2 | RTEMS_EVENT_MODE_SBM2_WFRM | |
|
377 | | RTEMS_EVENT_MODE_NORMAL_SWF_F0 | |
|
378 | | RTEMS_EVENT_MODE_NORMAL_SWF_F1 | |
|
379 | | RTEMS_EVENT_MODE_NORMAL_SWF_F2, | |
|
239 | | RTEMS_EVENT_MODE_SBM2 | RTEMS_EVENT_MODE_SBM2_WFRM, | |
|
380 | 240 | RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out); |
|
381 | 241 | if (event_out == RTEMS_EVENT_MODE_NORMAL) |
|
382 | 242 | { |
|
243 | PRINTF("WFRM received RTEMS_EVENT_MODE_NORMAL\n") | |
|
383 | 244 | send_waveform_SWF((volatile int*) ring_node_to_send_swf_f0->buffer_address, SID_NORM_SWF_F0, headerSWF_F0, queue_id); |
|
384 | 245 | send_waveform_SWF((volatile int*) ring_node_to_send_swf_f1->buffer_address, SID_NORM_SWF_F1, headerSWF_F1, queue_id); |
|
385 | 246 | send_waveform_SWF((volatile int*) ring_node_to_send_swf_f2->buffer_address, SID_NORM_SWF_F2, headerSWF_F2, queue_id); |
|
386 | 247 | } |
|
387 |
if ( |
|
|
248 | if (event_out == RTEMS_EVENT_MODE_SBM1) | |
|
388 | 249 | { |
|
250 | PRINTF("WFRM received RTEMS_EVENT_MODE_SBM1\n") | |
|
389 | 251 | send_waveform_SWF((volatile int*) ring_node_to_send_swf_f0->buffer_address, SID_NORM_SWF_F0, headerSWF_F0, queue_id); |
|
390 | } | |
|
391 | if ( (event_out & RTEMS_EVENT_MODE_NORMAL_SWF_F1) == RTEMS_EVENT_MODE_NORMAL_SWF_F1) | |
|
392 | { | |
|
393 | send_waveform_SWF((volatile int*) ring_node_to_send_swf_f1->buffer_address, SID_NORM_SWF_F1, headerSWF_F1, queue_id); | |
|
394 | } | |
|
395 | if ( (event_out & RTEMS_EVENT_MODE_NORMAL_SWF_F2) == RTEMS_EVENT_MODE_NORMAL_SWF_F2) | |
|
396 | { | |
|
252 | send_waveform_SWF((volatile int*) wf_snap_f1_extracted , SID_NORM_SWF_F1, headerSWF_F1, queue_id); | |
|
397 | 253 | send_waveform_SWF((volatile int*) ring_node_to_send_swf_f2->buffer_address, SID_NORM_SWF_F2, headerSWF_F2, queue_id); |
|
398 | 254 | } |
|
399 | 255 | } |
@@ -537,6 +393,26 rtems_task cwf1_task(rtems_task_argument | |||
|
537 | 393 | } |
|
538 | 394 | } |
|
539 | 395 | |
|
396 | rtems_task swbd_task(rtems_task_argument argument) | |
|
397 | { | |
|
398 | /** This RTEMS task is dedicated to the building of snapshots from different continuous waveforms buffers. | |
|
399 | * | |
|
400 | * @param unused is the starting argument of the RTEMS task | |
|
401 | * | |
|
402 | */ | |
|
403 | ||
|
404 | rtems_event_set event_out; | |
|
405 | ||
|
406 | BOOT_PRINTF("in SWBD ***\n") | |
|
407 | ||
|
408 | while(1){ | |
|
409 | // wait for an RTEMS_EVENT | |
|
410 | rtems_event_receive( RTEMS_EVENT_0, | |
|
411 | RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out); | |
|
412 | build_snapshot_from_ring(); | |
|
413 | } | |
|
414 | } | |
|
415 | ||
|
540 | 416 | //****************** |
|
541 | 417 | // general functions |
|
542 | 418 | void init_waveforms( void ) |
@@ -990,7 +866,9 void compute_acquisition_time( unsigned | |||
|
990 | 866 | { |
|
991 | 867 | unsigned long long int acquisitionTimeAsLong; |
|
992 | 868 | unsigned char localAcquisitionTime[6]; |
|
993 |
double deltaT |
|
|
869 | double deltaT; | |
|
870 | ||
|
871 | deltaT = 0.; | |
|
994 | 872 | |
|
995 | 873 | localAcquisitionTime[0] = (unsigned char) ( coarseTime >> 8 ); |
|
996 | 874 | localAcquisitionTime[1] = (unsigned char) ( coarseTime ); |
@@ -1054,6 +932,59 void compute_acquisition_time( unsigned | |||
|
1054 | 932 | acquisitionTime[3] = (unsigned char) (acquisitionTimeAsLong >> 16); |
|
1055 | 933 | acquisitionTime[4] = (unsigned char) (acquisitionTimeAsLong >> 8 ); |
|
1056 | 934 | acquisitionTime[5] = (unsigned char) (acquisitionTimeAsLong ); |
|
935 | ||
|
936 | } | |
|
937 | ||
|
938 | void build_snapshot_from_ring( void ) | |
|
939 | { | |
|
940 | unsigned int i; | |
|
941 | unsigned long long int centerTime_asLong; | |
|
942 | unsigned long long int acquisitionTimeF0_asLong; | |
|
943 | unsigned long long int acquisitionTimeF1_asLong; | |
|
944 | unsigned char *acquisitionTimeF0; | |
|
945 | unsigned char *acquisitionTimeF1; | |
|
946 | unsigned char *ptr1; | |
|
947 | unsigned char *ptr2; | |
|
948 | ||
|
949 | unsigned int deltaT; | |
|
950 | ||
|
951 | deltaT = 2731; // (2048. / 24576. / 2.) * 65536. = 2730.667; | |
|
952 | ||
|
953 | acquisitionTimeF0 = (unsigned char*) current_ring_node_f0->buffer_address; | |
|
954 | acquisitionTimeF1 = (unsigned char*) ring_node_to_send_cwf_f1->buffer_address; | |
|
955 | ||
|
956 | acquisitionTimeF0_asLong = 0x00; | |
|
957 | acquisitionTimeF1_asLong = 0x00; | |
|
958 | acquisitionTimeF0_asLong = ( acquisitionTimeF0[0] << 24 ) | |
|
959 | + ( acquisitionTimeF0[1] << 16 ) | |
|
960 | + ( (unsigned long long int) acquisitionTimeF0[2] << 40 ) | |
|
961 | + ( (unsigned long long int) acquisitionTimeF0[3] << 32 ) | |
|
962 | + ( acquisitionTimeF0[4] << 8 ) | |
|
963 | + ( acquisitionTimeF0[5] ); | |
|
964 | ||
|
965 | acquisitionTimeF1_asLong = ( acquisitionTimeF1[0] << 24 ) | |
|
966 | + ( acquisitionTimeF1[1] << 16 ) | |
|
967 | + ( (unsigned long long int) acquisitionTimeF1[2] << 40 ) | |
|
968 | + ( (unsigned long long int) acquisitionTimeF1[3] << 32 ) | |
|
969 | + ( acquisitionTimeF1[4] << 8 ) | |
|
970 | + ( acquisitionTimeF1[5] ); | |
|
971 | ||
|
972 | centerTime_asLong = acquisitionTimeF0_asLong + deltaT; | |
|
973 | ||
|
974 | ptr1 = (unsigned char*) &acquisitionTimeF1_asLong; | |
|
975 | ptr2 = (unsigned char*) wf_snap_f1_extracted; | |
|
976 | ||
|
977 | ptr2[0] = ptr1[ 2 + 2 ]; | |
|
978 | ptr2[1] = ptr1[ 3 + 2 ]; | |
|
979 | ptr2[2] = ptr1[ 0 + 2 ]; | |
|
980 | ptr2[3] = ptr1[ 1 + 2 ]; | |
|
981 | ptr2[4] = ptr1[ 4 + 2 ]; | |
|
982 | ptr2[5] = ptr1[ 5 + 2 ]; | |
|
983 | ||
|
984 | for (i=0; i<(NB_SAMPLES_PER_SNAPSHOT * NB_WORDS_SWF_BLK); i++ ) | |
|
985 | { | |
|
986 | wf_snap_f1_extracted[i + TIME_OFFSET] = ((int*)(ring_node_to_send_cwf_f1->buffer_address))[i + TIME_OFFSET]; | |
|
987 | } | |
|
1057 | 988 | } |
|
1058 | 989 | |
|
1059 | 990 | //************** |
General Comments 0
You need to be logged in to leave comments.
Login now