Files
sicspsi/sinqhm/SinqHM_srv_filler.c
cvs 064ec37e9a - Rearranged directory structure for forking out ANSTO
- Refactored site specific stuff into a site module
- PSI specific stuff is now in the PSI directory.
- The old version has been tagged with pre-ansto
2003-06-20 10:18:47 +00:00

1400 lines
46 KiB
C
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#define IDENT "1C05"
/*
** +--------------------------------------------------------------+
** | Paul Scherrer Institute |
** | SINQ Division |
** | |
** | This software may be used freely by non-profit organizations.|
** | It may be copied provided that the name of P.S.I. and of the |
** | author is included. Neither P.S.I. nor the author assume any |
** | responsibility for the use of this software outside of P.S.I.|
** +--------------------------------------------------------------+
**
** Module Name . . . . . . . . : [...SinqHM]SinqHM_srv_filler.c
**
** Author . . . . . . . . . . : D. Maden
** Date of creation . . . . . . : Oct 1996
**
** Updates:
** 1A01 2-Oct-1996 DM Initial version.
** 1B01 10-Jun-1998 DM Add code for SQMH__TOF mode.
** 1C01 11-Jun-1999 DM Add code for SQMH__HRPT mode.
** 1C03 10-Aug-1999 DM Make Lwl_hdr_daq_mask/Lwl_hdr_daq_soll dependent
** on the instrument.
**
** SinqHM_srv_filler.c forms a child process of the SINQ Histogram Memory
** process. It reads data from the detector via the PCI bus and fills the
** histogram(s).
**
** To compile this module for VxWorks on PSS123, use:
**
ccvx SinqHM_srv_filler.c
** where
ccvx = ccppc -O0 \
-mcpu=603 \
-I${WIND_BASE}/target/h \
-fno-builtin \
-fno-for-scope \
-nostdinc \
-DCPU=PPC603 \
-D_GNU_TOOL \
-gdwarf -c -Wimplicit
**====================================================================
*/
#include <vxWorks.h>
#include <taskLib.h>
#include <sysLib.h>
#include <msgQLib.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <timers.h>
#include <errno.h>
#include <setjmp.h>
/*
**==================== Global Definitions =====================================
*/
#define ESC 27
#include "SinqHM_def.h"
#include "SinqHM_gbl.h"
#include "vmio10_def.h"
/*==============================================================================
Global Routines
**
** SinqHM_filler_setup_id - copy some ident information to global variables.
**
** Local Routines
**
** SinqHM_filler_timer_handler - routine to handle timer interrupts.
**
** SinqHM_filler_daq_hm_dig - routine called by SinqHM_filler_daq for
** performing data acquisition in
** SQHM__HM_DIG mode, i.e. for data from
** detectors with digitised read-out
** electronics.
** SinqHM_filler_daq_hrpt - routine called by SinqHM_filler_daq for
** performing data acquisition in
** SQHM__HRPT mode, i.e. for data from
** detectors connected to a CERCA interface
** as in the HRPT instrument.
** SinqHM_filler_daq_tof - routine called by SinqHM_filler_daq for
** performing data acquisition in
** SQHM__TOF mode, i.e. for data from
** time-of-flight detectors.
** SinqHM_filler_daq_psd - routine called by SinqHM_filler_daq for
** performing data acquisition in
** SQHM__HM_PSD mode, i.e. for data from
** EMBL detectors.
**
** SinqHM_filler_daq - routine called by SinqHM_filler for
** performing data acquisition.
**
** SinqHM_filler - the main entry point for the FILLER child
** process.
**------------------------------------------------------------------------------
**
*/
/*==============================================================================
** Global Routines for Filler
*/
void SinqHM_filler_setup_id () {
/* ======================
** Simply copy some ident information to global variables
** for use by the SQHM_IDENT request.
*/
StrJoin (Sqhm_fill_ident, sizeof (Sqhm_fill_ident), IDENT, "");
StrJoin (Sqhm_fill_date, sizeof (Sqhm_fill_date), __DATE__, ", ");
StrJoin (Sqhm_fill_date, sizeof (Sqhm_fill_date), Sqhm_fill_date, __TIME__);
}
/*==============================================================================
** Local Routines for Filler
*/
void SinqHM_filler_timer_handler (int arg) {
/* ===========================
** Routine to handle timer interrupts.
*/
FillTimer_expired = True;
}
/*
**------------------------------------------------------------------------------
**
*/
void SinqHM_filler_daq_hm_dig () {
/* ========================
** Routine to handle Histogram Mode for
** detectors with single channel digitised
** read-out.
** Note:
** Lwl_fifo could, in principle, be accessed via a register for better
** efficiency. However, this can cause trouble with the GDB debugger
** when single stepping. I think this is probably connected with
** instruction pipe-lining.
** For the time being, the register copy of Lwl_fifo will NOT be used.
*/
register uint *my_lwl_fifo;
register uint my_lo_bin, my_hi_bin;
register union {
uint ui4;
usint ui2[2];
uchar ui1[4];
} lwl_hdr, lwl_data;
uchar my_buff[32];
int i, is;
char er_eol[] = {ESC, '[', '0', 'J'}; /* Erase to End-of-Line */
register uchar *my_char_base;
register usint *my_word_base;
register uint *my_long_base;
/*-----------------------------------------------
** Make register copies of some items for speed.
*/
my_lwl_fifo = Lwl_fifo;
my_lo_bin = Lo_bin;
my_hi_bin = Hi_bin;
switch (Bytes_per_bin) {
case 1: my_char_base = (uchar *) Hist_base_addr; break;
case 2: my_word_base = (usint *) Hist_base_addr; break;
default: my_long_base = (uint *) Hist_base_addr;
}
/*-----------------------------------------------*/
while (Filler_flag == 0) { /* Loop till flag gets set */
lwl_hdr.ui4 = *Lwl_fifo; /* Read a header from the FIFO */
if (lwl_hdr.ui4 == LWL_FIFO_EMPTY) {
taskDelay (0); /* If FIFO is empty, we can take a breather! */
}else if ((lwl_hdr.ui4 & LWL_HDR_TYPE_MASK) == LWL_HM_NC_C1) {
VmioBase[VMIO_PORT_A] = 0xff; /* Set timer level (if present) */
for (i=0; i<1000000; i++) {
lwl_data.ui4 = *Lwl_fifo; /* Get the 16 bits of data */
if (lwl_data.ui4 != LWL_FIFO_EMPTY) {
break;
}
taskDelay (0); /* But wait if FIFO is slow! */
}
if (lwl_data.ui4 == LWL_FIFO_EMPTY) {
printf ("Time-out getting histogram data word! Event # = %d\n",
N_events);
}else if ((lwl_hdr.ui4 & Lwl_hdr_daq_mask) != Lwl_hdr_daq_soll) {
/* Some header bits are not what they should be (e.g. NRL may
** be set) so skip the event.
*/
N_skipped++;
if (Dbg_lev1) {
printf("Skipped header: 0x%08x\n"
" Mask: 0x%08x\n"
" Soll: 0x%08x\n",
lwl_hdr.ui4, Lwl_hdr_daq_mask, Lwl_hdr_daq_soll);
}
}else if (lwl_data.ui4 < my_lo_bin) { /* Check "out-of-rnge" */
if (Cnts_lo != 0xffffffff) Cnts_lo++;
}else if (lwl_data.ui4 > my_hi_bin) { /* Check "out-of-rnge" */
if (Cnts_hi != 0xffffffff) Cnts_hi++;
}else {
if (Hm_mode_REFLECT == 0) { /* Calculate bin number */
lwl_data.ui4 -= my_lo_bin; /* No reflection */
}else {
lwl_data.ui4 = my_hi_bin - lwl_data.ui4; /* Histogram must be reflected */
}
switch (Bytes_per_bin) {
case 1:
if (my_char_base[lwl_data.ui4] != 0xff) { /* Check bin ovfl */
my_char_base[lwl_data.ui4]++; /* Incr the bin */
}else {
switch (Hm_mode_BO) { /* Bin overflow */
case SQHM__BO_SMAX: break; /* Stop-at-max */
case SQHM__BO_CNT: break; /* Not programmed yet */
default:
my_char_base[lwl_data.ui4] = 0; /* By default, wrap-to-zero */
}
}
break;
case 2:
if (my_word_base[lwl_data.ui4] != 0xffff) { /* Check bin ovfl */
my_word_base[lwl_data.ui4]++; /* Incr the bin */
}else {
switch (Hm_mode_BO) { /* Bin overflow */
case SQHM__BO_SMAX: break; /* Stop-at-max */
case SQHM__BO_CNT: break; /* Not programmed yet */
default:
my_word_base[lwl_data.ui4] = 0; /* By default, wrap-to-zero */
}
}
break;
default:
if (my_long_base[lwl_data.ui4] != 0xffffffff) { /* Check bin ovfl */
my_long_base[lwl_data.ui4]++; /* Incr the bin */
}else {
switch (Hm_mode_BO) { /* Bin overflow */
case SQHM__BO_SMAX: break; /* Stop-at-max */
case SQHM__BO_CNT: break; /* Not programmed yet */
default:
my_long_base[lwl_data.ui4] = 0; /* By default, wrap-to-zero */
}
}
}
}
VmioBase[VMIO_PORT_A] = 0x00; /* Reset timer level (if present) */
N_events++;
}else if ((lwl_hdr.ui4 & LWL_HDR_TYPE_MASK) == LWL_TSI_HM_NC) {
process_no_coinc_tsi (lwl_hdr.ui4); /* We have found a "normal"
** TSI (Timing-Status-Info) header. Process
** it.
*/
}else if ((lwl_hdr.ui4 & LWL_HDR_TYPE_MASK) == LWL_TSI_HM_C) {
process_coinc_tsi (lwl_hdr.ui4); /* We have found a "coincidence"
** type TSI header. The packet has 10 bytes
** altogether. Process it.
*/
}else { /* Anything else gets flushed */
lwl_Packet_Read (lwl_hdr.ui4, my_buff);
}
/* if (FillTimer_expired) { */
if (0) {
if (Print_hdr) printf ("\nTaking data in Digitised Histogramming Mode\n"
" #-Events #-Skip #-TSI Dead-Time Sync-Status\n");
Print_hdr = False;
FillTimer_expired = False;
printf ("\r%10u %10u %10u %10u %s", N_events, N_skipped,
(N_no_coin_tsi + N_coin_tsi), Dt_or_dts.dead_time, er_eol);
if (Daq_active) printf (" DAQ");
if ((Tsi_flags & STATUS_FLAGS__PF) != 0) printf (" PF");
if ((Tsi_flags & STATUS_FLAGS__SWC) != 0) printf (" SWC");
if (Nrl_active) printf (" NRL");
if ((Tsi_flags & STATUS_FLAGS__SYNC3) != 0) printf (" SYNC3");
if ((Tsi_flags & STATUS_FLAGS__SYNC2) != 0) printf (" SYNC2");
if ((Tsi_flags & STATUS_FLAGS__SYNC1) != 0) printf (" SYNC1");
if ((Tsi_flags & STATUS_FLAGS__SYNC0) != 0) printf (" SYNC0");
if ((Tsi_flags & STATUS_FLAGS__UD) != 0) printf (" UD");
if ((Tsi_flags & STATUS_FLAGS__GU) != 0) printf (" GU");
is = timer_settime (FillTimerId, ~TIMER_ABSTIME, &FillerTime, NULL);
if (is != 0) {
printf ("%s -- failed to set timer\n", Filler_name);
}
}
}
/* Our flag has been set. There should be ..
** .. a message waiting for us. Return to process it.
*/
}
/*
**------------------------------------------------------------------------------
**
*/
void SinqHM_filler_daq_hrpt () {
/* ======================
** Routine to handle Histogram Mode for
** detectors connected to a CERCA interface
** as in the HRPT instrument.
**
** The wires of the detector are read out frame by frame.
** Each wire comes as a 3-word packet (i.e. Hist Mode mit 3 Kanaele).
** The first word is 15-bit Wire Address (0 .. 1601) + Error Bit
** The second word is 10-bit Count
** The third word is 16-bit Frame Number
**
** To avoid skewing the histograms, the data is read out frame by frame
** and the frame is merged with the overall histogram only when it is
** complete and the LWL header information was OK for Wire 0 of the frame.
**
** Note:
** Lwl_fifo could, in principle, be accessed via a register for better
** efficiency. However, this can cause trouble with the GDB debugger
** when single stepping. I think this is probably connected with
** instruction pipe-lining.
** For the time being, the register copy of Lwl_fifo will NOT be used.
**
** Another Note:
** The HRPT detector has 1600 wires numbered 0 to 1599. The physicists
** want these numbers reflected for reasons of their own.
** The CERCA readout also uses wire numbers 1600 and 1601 to present
** time information about the frame. This information is discarded.
*/
register uint *my_lwl_fifo;
register uint my_lo_bin, my_hi_bin;
register union {
uint ui4;
usint ui2[2];
uchar ui1[4];
} lwl_hdr, lwl_data_0, lwl_data_1, lwl_data_2;
uchar my_buff[32];
uint wire;
int i, j, k, is, my_state;
int n_errors = 0;
char err_txt[128];
char er_eol[] = {ESC, '[', '0', 'J'}; /* Erase to End-of-Line */
register uchar *my_char_base;
register usint *my_word_base;
register uint *my_long_base;
register uchar *my_char_frame;
register usint *my_word_frame;
register uint *my_long_frame;
/*-----------------------------------------------
** Make register copies of some items for speed.
*/
my_lwl_fifo = Lwl_fifo;
my_lo_bin = Lo_bin;
my_hi_bin = Hi_bin;
switch (Bytes_per_bin) {
case 1: my_char_base = (uchar *) Hist_base_addr; break;
case 2: my_word_base = (usint *) Hist_base_addr; break;
default: my_long_base = (uint *) Hist_base_addr;
}
switch (Bytes_per_bin) {
case 1: my_char_frame = (uchar *) Frame_base_addr; break;
case 2: my_word_frame = (usint *) Frame_base_addr; break;
default: my_long_frame = (uint *) Frame_base_addr;
}
my_state = HRPT__SRCH_FRAME;
/*-----------------------------------------------*/
while (Filler_flag == 0) { /* Loop till flag gets set */
lwl_hdr.ui4 = *Lwl_fifo; /* Read a header from the FIFO */
if (lwl_hdr.ui4 == LWL_FIFO_EMPTY) {
taskDelay (0); /* If FIFO is empty, we can take a breather! */
}else if ((lwl_hdr.ui4 & LWL_HDR_TYPE_MASK) == LWL_HM_NC_C3) {
/* Histo data, three channel -- this is what we are
** interested in in HRPT mode. Start by reading out
** the 3 data words which should follow the header.
*/
VmioBase[VMIO_PORT_A] = 0xff; /* Set timer level (if present) */
for (i=0; i<1000; i++) {
lwl_data_0.ui4 = *Lwl_fifo; /* Get first 16 bits of data */
if (lwl_data_0.ui4 != LWL_FIFO_EMPTY) break;
taskDelay (0); /* But wait if FIFO is slow! */
}
if (lwl_data_0.ui4 != LWL_FIFO_EMPTY) {
for (i=0; i<1000; i++) {
lwl_data_1.ui4 = *Lwl_fifo; /* Get second 16 bits of data */
if (lwl_data_1.ui4 != LWL_FIFO_EMPTY) break;
taskDelay (0); /* But wait if FIFO is slow! */
}
if (lwl_data_1.ui4 != LWL_FIFO_EMPTY) {
for (i=0; i<1000; i++) {
lwl_data_2.ui4 = *Lwl_fifo; /* Get third 16 bits of data */
if (lwl_data_2.ui4 != LWL_FIFO_EMPTY) break;
taskDelay (0); /* But wait if FIFO is slow! */
}
if (Dbg_lev1 && (lwl_data_1.ui4 > 0)) {
printf ("Got address = %d, shifted = %d, counts = %d\n",
lwl_data_0.ui4, (lwl_data_0.ui4 >> 1), lwl_data_1.ui4);
}
}
}
if ((lwl_data_0.ui4 == LWL_FIFO_EMPTY) ||
(lwl_data_1.ui4 == LWL_FIFO_EMPTY) ||
(lwl_data_2.ui4 == LWL_FIFO_EMPTY)) {
if (n_errors == 0) {
sprintf (err_txt, "Time-out getting the three data words! "
"Event # = %d\n", N_events);
}
n_errors++;
}else {
wire = lwl_data_0.ui4 >> 1; /* Shift out error bit */
if (wire < my_lo_bin) { /* Out-of-rnge? */
if (Cnts_lo != 0xffffffff) Cnts_lo++;
}else if (wire == my_lo_bin) { /* Start of new frame? */
my_state = HRPT__READ_FRAME; /* Yes. Note our new state */
Frame_hdr = lwl_hdr.ui4; /* Remember hdr for frame */
Frame_num = lwl_data_2.ui4;
switch (Bytes_per_bin) {
case 1: my_char_frame[0] = lwl_data_1.ui4; break;
case 2: my_word_frame[0] = lwl_data_1.ui4; break;
default: my_long_frame[0] = lwl_data_1.ui4;
}
}else if (wire <= my_hi_bin) { /* In range? */
if (my_state == HRPT__READ_FRAME) { /* Yes. Check state */
if (lwl_data_2.ui4 == Frame_num) { /* And check frame # */
switch (Bytes_per_bin) {
case 1: my_char_frame[wire-my_lo_bin] = lwl_data_1.ui4; break;
case 2: my_word_frame[wire-my_lo_bin] = lwl_data_1.ui4; break;
default: my_long_frame[wire-my_lo_bin] = lwl_data_1.ui4;
}
}else {
if (n_errors == 0) {
sprintf (err_txt, "Frame sequence error: Frame 0x%04x\n"
" Packet: 0x%08x 0x%04x 0x%04x 0x%04x\n",
lwl_hdr.ui4, lwl_data_0.ui4, lwl_data_1.ui4, lwl_data_2.ui4);
}
n_errors++;
}
if (wire == my_hi_bin) { /* End of frame? */
/* Yes, merge it in if the
** header bits are OK
*/
if ((Frame_hdr & Lwl_hdr_daq_mask) != Lwl_hdr_daq_soll) {
N_skipped++;
if (Dbg_lev1) {
printf("Skipped frame %d\n"
" Hdr: 0x%08x\n"
" Mask: 0x%08x\n"
" Soll: 0x%08x\n", Frame_num,
Frame_hdr, Lwl_hdr_daq_mask, Lwl_hdr_daq_soll);
}
}else {
N_events++;
k = 0;
for (i = my_lo_bin; i <= my_hi_bin; i++) {
if (Hm_mode_REFLECT == 0) { /* Reflect if necessary */
j = i - my_lo_bin;
}else {
j = my_hi_bin - i;
}
switch (Bytes_per_bin) {
case 1: my_char_base[j] += my_char_frame[k]; break;
case 2: my_word_base[j] += my_word_frame[k]; break;
default: my_long_base[j] += my_long_frame[k];
}
k++;
}
}
my_state == HRPT__SRCH_FRAME;
}
}
}else if (wire == (my_hi_bin + 1)) { /* Frame timing #1? */
continue; /* Yes, ignore */
}else if (wire == (my_hi_bin + 2)) { /* Frame timing #2? */
continue; /* Yes, ignore */
}else if (wire > (my_hi_bin + 2)) { /* Out-of-rnge? */
if (Cnts_hi != 0xffffffff) Cnts_hi++;
}
}
VmioBase[VMIO_PORT_A] = 0x00; /* Reset timer level (if present) */
}else if ((lwl_hdr.ui4 & LWL_HDR_TYPE_MASK) == LWL_TSI_HM_NC) {
process_no_coinc_tsi (lwl_hdr.ui4); /* We have found a "normal"
** TSI (Timing-Status-Info) header. Process
** it.
*/
}else if ((lwl_hdr.ui4 & LWL_HDR_TYPE_MASK) == LWL_TSI_HM_C) {
process_coinc_tsi (lwl_hdr.ui4); /* We have found a "coincidence"
** type TSI header. The packet has 10 bytes
** altogether. Process it.
*/
}else { /* Anything else gets flushed */
lwl_Packet_Read (lwl_hdr.ui4, my_buff);
}
if (FillTimer_expired) {
if (Print_hdr) printf ("\nTaking data in HRPT Mode\n"
" #-Events #-Skip #-TSI #-Frame Sync-Status\n");
Print_hdr = False;
FillTimer_expired = False;
printf ("\r%10u %10u %10u %10u %s", N_events, N_skipped,
(N_no_coin_tsi + N_coin_tsi), Frame_num, er_eol);
if (Daq_active) printf (" DAQ");
if ((Tsi_flags & STATUS_FLAGS__PF) != 0) printf (" PF");
if ((Tsi_flags & STATUS_FLAGS__SWC) != 0) printf (" SWC");
if (Nrl_active) printf (" NRL");
if ((Tsi_flags & STATUS_FLAGS__SYNC3) != 0) printf (" SYNC3");
if ((Tsi_flags & STATUS_FLAGS__SYNC2) != 0) printf (" SYNC2");
if ((Tsi_flags & STATUS_FLAGS__SYNC1) != 0) printf (" SYNC1");
if ((Tsi_flags & STATUS_FLAGS__SYNC0) != 0) printf (" SYNC0");
if ((Tsi_flags & STATUS_FLAGS__UD) != 0) printf (" UD");
if ((Tsi_flags & STATUS_FLAGS__GU) != 0) printf (" GU");
if (n_errors != 0) {
printf ("\n%d errors occurred in the last time period\n", n_errors);
printf ("The first one was:\n%s\n", err_txt);
n_errors = 0;
}
is = timer_settime (FillTimerId, ~TIMER_ABSTIME, &FillerTime, NULL);
if (is != 0) {
printf ("%s -- failed to set timer\n", Filler_name);
}
}
}
/* Our flag has been set. There should be ..
** .. a message waiting for us. Return to process it.
*/
}
/*
**-----------------------------------------------------------------------------
*/
void SinqHM_filler_daq_tof () {
/* =====================
** Routine to handle Time-of-flight Mode
** Note:
** Lwl_fifo could, in principle, be accessed via a register for better
** efficiency. However, this can cause trouble with the GDB debugger
** when single stepping. I think this is probably connected with
** instruction pipe-lining.
** For the time being, the register copy of Lwl_fifo will NOT be used.
*/
register uint *my_lwl_fifo;
register union {
uint ui4;
usint ui2[2];
uchar ui1[4];
} lwl_hdr, lwl_data;
int i, j, is, ts, left, right, middl, not_finished;
uchar my_buff[32];
register struct tof_histog *my_tof_descr;
uint *edge_pntr;
char er_eol[] = {ESC, '[', '0', 'J'}; /* Erase to End-of-Line */
/*-----------------------------------------------
** Make register copies of some items for speed.
*/
my_lwl_fifo = Lwl_fifo;
/*-----------------------------------------------*/
while (Filler_flag == 0) { /* Loop till flag gets set */
lwl_hdr.ui4 = *Lwl_fifo; /* Read a header from the FIFO */
if (lwl_hdr.ui4 == LWL_FIFO_EMPTY) {
taskDelay (0); /* If FIFO is empty, we can take a breather! */
}else if (((lwl_hdr.ui4 & LWL_HDR_TYPE_MASK) == LWL_TOF_C1) ||
((lwl_hdr.ui4 & LWL_HDR_TYPE_MASK) == LWL_TOF_C2) ||
((lwl_hdr.ui4 & LWL_HDR_TYPE_MASK) == LWL_TOF_C3) ||
((lwl_hdr.ui4 & LWL_HDR_TYPE_MASK) == LWL_TOF_C4) ||
((lwl_hdr.ui4 & LWL_HDR_TYPE_MASK) == LWL_TOF_C5) ||
((lwl_hdr.ui4 & LWL_HDR_TYPE_MASK) == LWL_TOF_C6) ||
((lwl_hdr.ui4 & LWL_HDR_TYPE_MASK) == LWL_TOF_C7) ||
((lwl_hdr.ui4 & LWL_HDR_TYPE_MASK) == LWL_TOF_C8) ||
((lwl_hdr.ui4 & LWL_HDR_TYPE_MASK) == LWL_TOF_C9)) {
/* We have found a header of the type we are
** interested in, i.e. a TOF packet. So
** process it. We must first get the 16 bits
** of data which give the counter number.
*/
VmioBase[VMIO_PORT_A] = 0xff; /* Set timer level (if present) */
for (i=0; i<1000; i++) {
lwl_data.ui4 = *Lwl_fifo; /* Get the counter number */
if (lwl_data.ui4 != LWL_FIFO_EMPTY) break;
taskDelay (0); /* But wait if FIFO is slow! */
}
if (lwl_data.ui4 == LWL_FIFO_EMPTY) {
printf ("Time-out getting counter number!\n");
}else if ((lwl_hdr.ui4 & Lwl_hdr_daq_mask) != Lwl_hdr_daq_soll) {
/* Some header bits are not what they should be (e.g. NRL may
** be set) so skip the event.
*/
N_skipped++;
if (Dbg_lev1) {
printf("Skipped header: 0x%08x\n"
" Mask: 0x%08x\n"
" Soll: 0x%08x\n",
lwl_hdr.ui4, Lwl_hdr_daq_mask, Lwl_hdr_daq_soll);
}
}else {
/* We have a valid TOF packet. Validate it
** thoroughly and process it. First check
** that the counter number is valid.
*/
if (lwl_data.ui4 >= MAX_TOF_CNTR) {
Tof_count_bad_counter_number++; /* It isn't */
}else {
my_tof_descr = Tof_descr[lwl_data.ui4];
if (my_tof_descr == NULL) {
Tof_count_bad_counter_number++; /* It isn't */
}else {
/* The counter number is valid. Process the time-stamp
** (20-bit quantity) to find which bin to increment.
*/
ts = lwl_hdr.ui4 & LWL_HDR_TS_MASK;
if (ts < my_tof_descr->lo_edge) {
if ((Hm_mode_UD != 0) &&
(lwl_hdr.ui4 & LWL_HDR_UD_MASK) == 0) {
my_tof_descr->cnt_early_down++;
}else {
my_tof_descr->cnt_early_up++;
}
}else {
if (ts > my_tof_descr->hi_edge) {
if ((Hm_mode_UD != 0) &&
(lwl_hdr.ui4 & LWL_HDR_UD_MASK) == 0) {
my_tof_descr->cnt_late_down++;
}else {
my_tof_descr->cnt_late_up++;
}
}else {
/* Now search the bin boundary list to find the
** bin to which this event belongs.
*/
edge_pntr = my_tof_descr->bin_edge;
left = 0;
right = my_tof_descr->n_bins;
middl = (left + right)/2;
not_finished = True;
while (not_finished) {
switch (right - left) {
case 0:
not_finished = False;
break;
case 1:
middl = (ts >= edge_pntr[right]) ? right : left;
not_finished = False;
break;
default:
middl = (left + right)/2;
if (ts == edge_pntr[middl]) {
not_finished = False;
}else if (ts > edge_pntr[middl]) {
left = middl;
}else {
right = middl;
}
}
}
if ((Hm_mode_UD != 0) &&
((lwl_hdr.ui4 & LWL_HDR_UD_MASK) != 0)) {
middl += my_tof_descr->n_bins;
}
switch (my_tof_descr->bytes_per_bin) {
case 1:
my_tof_descr->u.b_bin_data[middl]++; break;
case 2:
my_tof_descr->u.w_bin_data[middl]++; break;
default:
my_tof_descr->u.l_bin_data[middl]++; break;
}
}
}
}
}
}
VmioBase[VMIO_PORT_A] = 0x00; /* Reset timer level (if present) */
N_events++;
}else if ((lwl_hdr.ui4 & LWL_HDR_TYPE_MASK) == LWL_TSI_HM_NC) {
process_no_coinc_tsi (lwl_hdr.ui4); /* We have found a "normal"
** TSI (Timing-Status-Info) header. Process
** it.
*/
}else if ((lwl_hdr.ui4 & LWL_HDR_TYPE_MASK) == LWL_TSI_HM_C) {
process_coinc_tsi (lwl_hdr.ui4); /* We have found a "coincidence"
** type TSI header. The packet has 10 bytes
** altogether. Process it.
*/
}else if ((lwl_hdr.ui4 & LWL_HDR_TYPE_MASK) == LWL_GUMMI_MON) {
/*
process a SANS gummi mode monitor datagram
*/
process_gummi_monitor(lwl_hdr.ui4);
}else { /* Anything else gets flushed */
lwl_Packet_Read (lwl_hdr.ui4, my_buff);
}
if (FillTimer_expired) {
if (Print_hdr) printf ("\nTaking data in TOF Mode\n"
" #-Events #-Skip #-TSI Delay-Time Sync-Status\n");
Print_hdr = False;
FillTimer_expired = False;
printf ("\r%10u %10u %10u %10u %s", N_events, N_skipped,
(N_no_coin_tsi + N_coin_tsi), Dt_or_dts.dts, er_eol);
if (Daq_active) printf (" DAQ");
if ((Tsi_flags & STATUS_FLAGS__PF) != 0) printf (" PF");
if ((Tsi_flags & STATUS_FLAGS__SWC) != 0) printf (" SWC");
if (Nrl_active) printf (" NRL");
if ((Tsi_flags & STATUS_FLAGS__SYNC3) != 0) printf (" SYNC3");
if ((Tsi_flags & STATUS_FLAGS__SYNC2) != 0) printf (" SYNC2");
if ((Tsi_flags & STATUS_FLAGS__SYNC1) != 0) printf (" SYNC1");
if ((Tsi_flags & STATUS_FLAGS__SYNC0) != 0) printf (" SYNC0");
if ((Tsi_flags & STATUS_FLAGS__UD) != 0) printf (" UD");
if ((Tsi_flags & STATUS_FLAGS__GU) != 0) printf (" GU");
is = timer_settime (FillTimerId, ~TIMER_ABSTIME, &FillerTime, NULL);
if (is != 0) {
printf ("%s -- failed to set timer\n", Filler_name);
}
}
}
/* Our flag has been set. There should be ..
** .. a message waiting for us. Return to process it.
*/
}
/*
**-----------------------------------------------------------------------------
*/
void SinqHM_filler_daq_psd () {
/* =====================
** Routine to handle PSD-TOF Mode
** Note:
** Lwl_fifo could, in principle, be accessed via a register for better
** efficiency. However, this can cause trouble with the GDB debugger
** when single stepping. I think this is probably connected with
** instruction pipe-lining.
** For the time being, the register copy of Lwl_fifo will NOT be used.
*/
register uint *my_lwl_fifo;
register union {
uint ui4;
usint ui2[2];
uchar ui1[4];
} lwl_hdr, xData, yData, edData;
int xPos, yPos, iTime, dataPos, edNum, xOff, yOff;
signed int sPosx, sPosy;
int i, j, is, ts, left, right, middl, not_finished;
uint *edge_pntr;
char er_eol[] = {ESC, '[', '0', 'J'}; /* Erase to End-of-Line */
uchar my_buff[32];
uint *histlPtr = (uint *)Hist_base_addr;
usint *histsPtr = (usint *)Hist_base_addr;
uchar *histcPtr = (uchar *)Hist_base_addr;
/*
precalculate some offsets
*/
xOff = psdXOffset*psdXFactor;
yOff = psdYOffset*psdYFactor;
/*-----------------------------------------------
** Make register copies of some items for speed.
*/
my_lwl_fifo = Lwl_fifo;
/*-----------------------------------------------*/
while (Filler_flag == 0) { /* Loop till flag gets set */
lwl_hdr.ui4 = *Lwl_fifo; /* Read a header from the FIFO */
if (lwl_hdr.ui4 == LWL_FIFO_EMPTY) {
taskDelay (0); /* If FIFO is empty, we can take a breather! */
}else if ( (lwl_hdr.ui4 & LWL_HDR_TYPE_MASK) == LWL_PSD_DATA) {
/*
we have located a PSD data packet. Let us read the xPos and
yPos packes.
*/
VmioBase[VMIO_PORT_A] = 0xff; /* Set timer level (if present) */
for (i=0; i<1000; i++) {
xData.ui4 = *Lwl_fifo; /* Get the x Position */
if (xData.ui4 != LWL_FIFO_EMPTY) break;
taskDelay (0); /* But wait if FIFO is slow! */
}
if (xData.ui4 == LWL_FIFO_EMPTY) {
printf ("Time-out getting X position !\n");
continue;
}
for (i=0; i<1000; i++) {
yData.ui4 = *Lwl_fifo; /* Get the y Position */
if (yData.ui4 != LWL_FIFO_EMPTY) break;
taskDelay (0); /* But wait if FIFO is slow! */
}
if (yData.ui4 == LWL_FIFO_EMPTY) {
printf ("Time-out getting Y position!\n");
continue;
}
/*
check if data aquisition is active
*/
if ((lwl_hdr.ui4 & Lwl_hdr_daq_mask) != Lwl_hdr_daq_soll) {
/* Some header bits are not what they should be (e.g. NRL
** ow PWF may be set) so skip the event.
*/
N_skipped++;
if (Dbg_lev1) {
printf("Skipped header: 0x%08x\n"
" Mask: 0x%08x\n"
" Soll: 0x%08x\n",
lwl_hdr.ui4, Lwl_hdr_daq_mask, Lwl_hdr_daq_soll);
}
continue;
}
/*
We have a valid PSD packet. Find and check positions.
*/
/*
This is the new version where all values are offset by 4096
in order to give positive values at all times. This relates
to a zero point in the middle of the detector. As we want a
zero point in the lower left corner, we subtract 2048.
*/
xPos = xData.ui2[1];
xPos = (xPos - 2048)/psdXFactor;
yPos = yData.ui2[1];
yPos = (yPos - 2048)/psdYFactor;
if(xPos < 0 || xPos >= psdXSize)
{
printf("X position out of range: %d, alllowed 0 - %d\n",
xPos, psdXSize);
continue;
}
if(yPos < 0 || yPos >= psdYSize)
{
printf("Y position out of range: %d, alllowed 0 - %d\n",
yPos, psdYSize);
continue;
}
/*
Extract time stamp and match to the appropriate time bin.
*/
iTime = lwl_hdr.ui4 & LWL_PSD_TIME;
if(Dbg_lev1){
printf("Received detector hit at x,y, time: %d, %d, %d\n",
xPos, yPos, iTime);
}
edge_pntr = Tof_edges[0]->edges;
left = 0;
right = Tof_edges[0]->n_bins;
middl = (left + right)/2;
not_finished = True;
iTime -= Tof_dts_soll;
while (not_finished) {
switch (right - left) {
case 0:
not_finished = False;
break;
case 1:
middl = (iTime >= edge_pntr[right]) ? right : left;
not_finished = False;
break;
default:
middl = (left + right)/2;
if (iTime == edge_pntr[middl]) {
not_finished = False;
}else if (iTime > edge_pntr[middl]) {
left = middl;
}else {
right = middl;
}
}
}
if(Dbg_lev1){
printf("Matched time stamp %d into bin %d\n", iTime,middl);
}
if(middl >= Tof_edges[0]->n_bins){
if(Tof_edges[0]->n_bins < 5){
/*
fix for PSD without TOF
*/
middl = Tof_edges[0]->n_bins-1;
} else {
/*
skip it, out of range
*/
continue;
}
}
/*
calculate histogram position to update
*/
dataPos = yPos*psdXSize*Tof_edges[0]->n_bins +
xPos*Tof_edges[0]->n_bins + middl;
/* UD must come but the bit is not yet defined
if ((Hm_mode_UD != 0) &&
((lwl_hdr.ui4 & LWL_HDR_UD_MASK) != 0)) {
dataPos +=
(psdXSize*psdYSize+MAX_PSD_ED)*Tof_edges[0]->n_bins ;
}
*/
switch(Bytes_per_bin)
{
case 1:
histcPtr[dataPos]++;
break;
case 2:
histsPtr[dataPos]++;
break;
case 4:
histlPtr[dataPos]++;
break;
}
VmioBase[VMIO_PORT_A] = 0x00; /* Reset timer level (if present) */
N_events++;
}else if ( (lwl_hdr.ui4 & LWL_HDR_ED_MASK) == 0) {
/*
we have located a single detector packet from AMOR. We need to
read the detector number
*/
VmioBase[VMIO_PORT_A] = 0xff; /* Set timer level (if present) */
for (i=0; i<1000; i++) {
edData.ui4 = *Lwl_fifo; /* Get the detector number */
if (edData.ui4 != LWL_FIFO_EMPTY) break;
taskDelay (0); /* But wait if FIFO is slow! */
}
if (xData.ui4 == LWL_FIFO_EMPTY) {
printf ("Time-out getting detector number !\n");
continue;
}
/*
check if data aquisition is active
*/
if ((lwl_hdr.ui4 & Lwl_hdr_daq_mask) != Lwl_hdr_daq_soll) {
/* Some header bits are not what they should be (e.g. NRL
** ow PWF may be set) so skip the event.
*/
N_skipped++;
if (Dbg_lev1) {
printf("Skipped header: 0x%08x\n"
" Mask: 0x%08x\n"
" Soll: 0x%08x\n",
lwl_hdr.ui4, Lwl_hdr_daq_mask, Lwl_hdr_daq_soll);
}
continue;
}
/*
We have a valid single detector packet.
Subtract one from the number because Urs Greuter starts
counting at 1, and ANSI-C at 0
*/
edNum = edData.ui2[1] - 1;
if(edNum < 0 || edNum >= MAX_PSD_ED){
printf("Got invalid single detector number %d\n",edNum);
continue;
}
/*
Extract time stamp and match to the appropriate time bin.
*/
iTime = lwl_hdr.ui4 & LWL_PSD_TIME;
if(Dbg_lev1){
printf("Received single detector hit at no, time: %d, %d\n",
edNum, iTime);
}
edge_pntr = Tof_edges[0]->edges;
left = 0;
right = Tof_edges[0]->n_bins;
middl = (left + right)/2;
not_finished = True;
iTime -= Tof_dts_soll;
while (not_finished) {
switch (right - left) {
case 0:
not_finished = False;
break;
case 1:
middl = (iTime >= edge_pntr[right]) ? right : left;
not_finished = False;
break;
default:
middl = (left + right)/2;
if (iTime == edge_pntr[middl]) {
not_finished = False;
}else if (iTime > edge_pntr[middl]) {
left = middl;
}else {
right = middl;
}
}
}
if(Dbg_lev1){
printf("Matched time stamp %d into bin %d\n", iTime,middl);
}
if(middl >= Tof_edges[0]->n_bins){
middl = Tof_edges[0]->n_bins-1;
if(Dbg_lev1){
printf("WARNING: Fixed bad time bin for single detector!\n");
}
continue;
}
/*
calculate histogram position to update
*/
dataPos = (psdYSize*psdXSize)*Tof_edges[0]->n_bins
+ edNum*Tof_edges[0]->n_bins + middl - 1;
if(Dbg_lev1){
printf("dataPos = %d\n", dataPos);
}
/* UD must come but the UD bit is not defined......
if ((Hm_mode_UD != 0) &&
((lwl_hdr.ui4 & LWL_HDR_UD_MASK) != 0)) {
dataPos +=
(psdXSize*psdYSize+MAX_PSD_ED)*Tof_edges[0]->n_bins ;
}
*/
switch(Bytes_per_bin)
{
case 1:
histcPtr[dataPos]++;
break;
case 2:
histsPtr[dataPos]++;
break;
case 4:
histlPtr[dataPos]++;
break;
}
VmioBase[VMIO_PORT_A] = 0x00; /* Reset timer level (if present) */
N_events++;
}else if ((lwl_hdr.ui4 & LWL_HDR_TYPE_MASK) == LWL_PSD_TSI) {
/*
we have located a PSD style TSI telegram
*/
process_psd_tsi(lwl_hdr.ui4);
}else {
/* Anything else gets flushed */
lwl_Packet_Read (lwl_hdr.ui4, my_buff);
}
if (FillTimer_expired) {
if (Print_hdr) printf ("\nTaking data in PSD Mode\n"
" #-Events #-Skip #-TSI #-Hits %s",
"#-Flash Delay-Time Sync-Status\n");
Print_hdr = False;
FillTimer_expired = False;
printf ("\r%10u %10u %10u %10u %10u %10u %s", N_events, N_skipped,
(N_no_coin_tsi + N_coin_tsi), psdHitCount,
psdFlashCount, Dt_or_dts.dts, er_eol);
if (Daq_active) printf (" DAQ");
if ((Tsi_flags & STATUS_FLAGS__PF) != 0) printf (" PF");
if ((Tsi_flags & STATUS_FLAGS__SWC) != 0) printf (" SWC");
if (Nrl_active) printf (" NRL");
if ((Tsi_flags & STATUS_FLAGS__SYNC3) != 0) printf (" SYNC3");
if ((Tsi_flags & STATUS_FLAGS__SYNC2) != 0) printf (" SYNC2");
if ((Tsi_flags & STATUS_FLAGS__SYNC1) != 0) printf (" SYNC1");
if ((Tsi_flags & STATUS_FLAGS__SYNC0) != 0) printf (" SYNC0");
if ((Tsi_flags & STATUS_FLAGS__UD) != 0) printf (" UD");
if ((Tsi_flags & STATUS_FLAGS__GU) != 0) printf (" GU");
if(psdXORF) printf(" XORF");
if(psdConf) printf(" CONF");
is = timer_settime (FillTimerId, ~TIMER_ABSTIME, &FillerTime, NULL);
if (is != 0) {
printf ("%s -- failed to set timer\n", Filler_name);
}
}
}
/* Our flag has been set. There should be ..
** .. a message waiting for us. Return to process it.
*/
}
/*
**-----------------------------------------------------------------------------
*/
void SinqHM_filler_daq_trans () {
/* =======================
** Routine to handle Transparent Mode. Data is simply read
** and packed into the buffers. The buffers are used
** cyclically.
** The routine attempts to read packets of data from the
** fibre-optic channel. This code, however, assumes that
** the packets obey the LWL protocol specification.
** Note:
** Lwl_fifo could, in principle, be accessed via a register for better
** efficiency. However, this can cause trouble with the GDB debugger
** when single stepping. I think this is probably connected with
** instruction pipe-lining.
** For the time being, the register copy of Lwl_fifo will NOT be used.
*/
register uint *my_lwl_fifo;
register union {
uint ui4;
usint ui2[2];
uchar ui1[4];
} lwl_hdr, lwl_data;
uint status_info;
int i, j;
register uchar *my_char_nxt;
/*-----------------------------------------------
** Make register copies of some items for speed.
*/
my_lwl_fifo = Lwl_fifo;
my_char_nxt = Next_char;
while (Filler_flag == 0) { /* Loop till flag gets set */
lwl_hdr.ui4 = *Lwl_fifo; /* Read a header from the FIFO */
if (lwl_hdr.ui4 == LWL_FIFO_EMPTY) {
taskDelay (0); /* If FIFO is empty, we can take a breather! */
}else {
#ifdef TRANNY
VmioBase[VMIO_PORT_A] = 0xff; /* Set timer level (if present) */
*my_char_nxt = lwl_Packet_Read (lwl_hdr.ui4, &my_char_nxt[1]);
Bytes_free = Bytes_free - *my_char_nxt - 1;
my_char_nxt = my_char_nxt + *my_char_nxt + 1;
if (Bytes_free < 24) my_char_nxt = selectNewBuffer (my_char_nxt);
VmioBase[VMIO_PORT_A] = 0x00; /* Reset timer level (if present) */
#else
printf("%#8.8x\n",lwl_hdr.ui4);
#endif
}
}
/* Our flag has been set. There should be ..
** .. a message waiting for us. Return to process it.
*/
}
/*
**-----------------------------------------------------------------------------
*/
void SinqHM_filler_daq () {
/* =================
*/
int is;
switch (Hm_mode & (~SQHM__SUB_MODE_MSK)) {
case SQHM__TRANS:
SinqHM_filler_daq_trans (); /* Do Transparent mode */
break;
case SQHM__HM_DIG:
SinqHM_filler_daq_hm_dig (); /* Do Digitised-type detectors */
break;
case SQHM__HRPT:
SinqHM_filler_daq_hrpt (); /* Do HRPT (CERCA) type detectors */
break;
case SQHM__HM_PSD:
SinqHM_filler_daq_psd (); /* Do PSD readout */
break;
case SQHM__TOF:
SinqHM_filler_daq_tof (); /* Do time-of-flight read-out */
break;
}
}
/*
**=============================================================================
** Here beginneth the main code for FILLER ...
*/
int SinqHM_filler (int suspend_flag) {
/* =============
** FILLER - Scaler Overflow Handler for SinqHM sub-system.
*/
int status, i, is, j, k, wait_result, indx;
int keep_cycling;
int shm_size;
char recd[80];
struct msg_to_filler_struct msg_buff;
sigset_t proc_sigmask;
struct sigaction sig_action;
/*============================================================================
*/
if (suspend_flag != 0) {
printf ("%s: Suspending ...", Filler_name);
taskSuspend (0); /* We've been told to suspend ourself, ..
** .. presumably for debug reasons.
*/
printf (" suspension ended!\n");
}
/*============================================================================
** Create message queue for receiving requests from clients.
*/
if (MsgQ_to_filler == NULL) {
MsgQ_to_filler = msgQCreate (8, sizeof (msg_buff), MSG_Q_FIFO);
if (MsgQ_to_filler == NULL) {
printf ("%s -- failed to create MsgQ_to_filler message queue.\n",
Filler_name);
exit (KER__BAD_VALUE);
}
if (Dbg_lev1) {
printf ("%s -- created MsgQ_to_filler message queue.\n", Filler_name);
}
}
while (msgQNumMsgs (MsgQ_to_filler) > 0) { /* Ensure Q is empty */
msgQReceive (MsgQ_to_filler, (char *) &msg_buff, sizeof (msg_buff),
WAIT_FOREVER);
}
/*============================================================================
** Create message queues for sending replies to servers.
** Note: MsgQ_to_server[0] is used for messages to SinqHM-master.
*/
for (i = 0; i <= MAX_CLIENTS; i++) {
if (MsgQ_to_server[i] == NULL) {
MsgQ_to_server[i] = msgQCreate (8, sizeof (msg_buff), MSG_Q_FIFO);
if (MsgQ_to_server[i] == NULL) {
printf ("%s -- failed to create MsgQ_to_server[%d] message queue.\n",
Filler_name, i);
exit (KER__BAD_VALUE);
}
if (Dbg_lev1) {
printf ("%s -- created MsgQ_to_server[%d] message queue.\n",
Filler_name, i);
}
}
while (msgQNumMsgs (MsgQ_to_server[i]) > 0) { /* Ensure Q is empty */
msgQReceive (MsgQ_to_server[i], (char *) &msg_buff, sizeof (msg_buff),
WAIT_FOREVER);
}
}
/*============================================================================*/
Filler_flag = 0; /* Ensure the communication flag is zero */
Server_masks[0] = 0x8000; /* This is our bit in SinqHM_Dsbl_Mask */
for (i = 1; i <= MAX_CLIENTS; i++) Server_masks[i] = 1 << (i - 1);
SinqHM_Dsbl_Mask = 0; /* Start up with DAQ enabled */
/*
set up address of fibre optic. This is very board specific!
The last 3 bytes of this address are set in the programmable logic
of the mezzanine card. The first byte is the offset of the PCI memory
space in the processor memory map. Together the address must result
in a valid address lying in the region reserved for PCI I/O. The
program on the mezzanine card may need updating in order to ensure just
that.
Mark Koennecke, February 2002
*/
#ifdef MV2600
Lwl_fifo = (uint *) 0x80008080;
#else
Lwl_fifo = (uint *) 0x80810080; /* for MVME1603 boards */
#endif
/*
For the MEN board the pci-to-pci bridge to the mezzanine card
has to be configured...........
*/
#ifdef MEN_A012
printf("Configuring for MEN....\n");
Lwl_fifo = (uint *) 0x8a200000;
pciConfigOutWord(0,0x1d,0,0x04,0x0007);
pciConfigOutWord(0,0x1d,0,0x20,0x8a20);
pciConfigOutWord(0,0x1d,0,0x22,0x8a20);
#endif
printf("Value at lwl_fifo = %x, address = %x\n", *Lwl_fifo, Lwl_fifo);
Lwl_csr = &Lwl_dummy_csr; /* Set up address of dummy CSR */
/*============================================================================
** Define our signal mask first and define an action routine to catch
** the SIGINT signal our parent will send us when he wants us to exit.
*/
status = sigemptyset (&proc_sigmask);
status = sigprocmask (SIG_SETMASK, &proc_sigmask, NULL);
status = sigemptyset (&sig_action.sa_mask);
sig_action.sa_handler = catch_int_signal;
sig_action.sa_flags = 0;
if (sigaction (SIGINT, &sig_action, NULL) == -1) {
getErrno (&My_errno);
perror ("sigaction error:");
exit (KER__BAD_VALUE);
}
/*============================================================================
** When we can do it, ensure the detector read-out is inhibited and
** flush out any data in the fibre-optic FIFO.
*/
*Lwl_csr = 0x0001; /* This will (maybe) initialise the fibre-optic FIFO. */
printf("vxWorks thinks it still has %d bytes of memory\n",memFindMax());
printf("Flushing lwl.....\n");
lwl_Fifo_Flush (); /* Flush the fibre-optic FIFO. */
/*============================================================================
** Initialisation done, release semaphore so that our parent can continue.
*/
if (Dbg_lev1) printf ("%s -- releasing Sem_Filler semaphore\n",
Filler_name);
is = semGive (Sem_Filler);
if (Dbg_lev1)
printf ("%s -- returned from sem release: %d\n", Filler_name, is);
if (is != OK) {
printf ("%s -- sem release error\n", Filler_name);
exit (KER__BAD_VALUE);
}
taskDelay ((sysClkRateGet())/2); /* Give parent time to display a message */
/*============================================================================
** Make a timer to give occasional status on console
*/
FillTimer_active = False;
FillTimer_expired = False;
if (Hm_mode_NO_STAT != 0) {
printf ("%s -- display of TSI information suppressed\n", Filler_name);
}else {
is = timer_create (CLOCK_REALTIME, NULL, &FillTimerId);
if (is != 0) {
printf ("%s -- timer creation failed\n", Filler_name);
}else {
is = timer_connect (FillTimerId, SinqHM_filler_timer_handler, 0);
if (is != 0) {
printf ("%s -- failed to connect to timer\n", Filler_name);
}else {
FillerTime.it_value.tv_sec = 2; /* Set a 2 second timer */
FillerTime.it_value.tv_nsec = 0;
FillerTime.it_interval.tv_sec = 0;
FillerTime.it_interval.tv_nsec = 0;
is = timer_settime (FillTimerId, ~TIMER_ABSTIME, &FillerTime, NULL);
if (is != 0) {
printf ("%s -- failed to set timer\n", Filler_name);
}
FillTimer_active = True;
}
}
}
/*============================================================================
** Loop taking data and waiting for requests from clients.
*/
for (keep_cycling = True; keep_cycling;) {
if (SinqHM_Dsbl_Mask == 0) {
SinqHM_filler_daq (); /* Start data acquisition ..
** .. We return here whenever Filler_flag ..
** .. indicates that a message is waiting ..
** .. to be processed.
*/
}
is = msgQReceive (MsgQ_to_filler, (char *) &msg_buff, sizeof (msg_buff),
WAIT_FOREVER);
if (is <= 0) {
printf ("%s -- error status from msgQReceive: %d\n", Filler_name, is);
exit (KER__BAD_VALUE);
}
if (Dbg_lev1) printf ("%s -- received a message of %d bytes!\n",
Filler_name, is);
Filler_flag = 0;
indx = msg_buff.u.uu.index;
switch (msg_buff.u.uu.cmnd) {
case DAQ__EXIT:
keep_cycling = False; /* Break out of the loop */
break;
case DAQ__CLR:
SinqHM_Dsbl_Mask &= (~Server_masks[indx]); /* Clear user's mask bit. */
break;
case DAQ__GO:
SinqHM_Dsbl_Mask &= (~Server_masks[0]); /* Clear our mask bit */
break;
case DAQ__INH:
SinqHM_Dsbl_Mask |= Server_masks[indx]; /* Set user's mask bit */
break;
case DAQ__STOP:
SinqHM_Dsbl_Mask |= Server_masks[0]; /* Set our mask bit. */
break;
}
msg_buff.u.uu.new_mask = SinqHM_Dsbl_Mask; /* Put new mask in reply */
is = msgQSend (MsgQ_to_server[indx], /* Tell user to continue */
(char *) &msg_buff,
sizeof (msg_buff),
WAIT_FOREVER, MSG_PRI_NORMAL);
if (is != OK) {
printf ("%s -- error status from msgQSend: %d\n", Filler_name, is);
exit (KER__BAD_VALUE);
}
}
exit (KER__SUCCESS);
}
/*======================================= End of SinqHM_srv_filler.c ========*/