
- 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
1400 lines
46 KiB
C
Executable File
1400 lines
46 KiB
C
Executable File
#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 ========*/
|
||
|
||
|
||
|
||
|