Back Midas Rome Roody Rootana
  Midas DAQ System, Page 112 of 137  Not logged in ELOG logo
New entries since:Wed Dec 31 16:00:00 1969
IDdown Date Author Topic Subject
  505   13 Oct 2008 Stefan RittInfomhttpd multi-experiment support removed
Previously, one mhttpd server could sever several experiments at the same time. 
This caused however sometimes problems and was hard to maintain. Starting from 
SVN revision 4348, I removed the multi-experiment support, which I believe is 
now a much cleaner implementation. So if several experiments are defined on a 
computer, each one need a separate mhttpd process listening on a different 
port. The experiment name can now be supplied on the command line to mhttpd 
like for any other midas program. I have tested this so far at two experiments 
at PSI, but this does not cover all possibilities. What I did not try was 
experiments with web passwords and odb passwords. If there is any problem after 
upgrading to 4348, please report.
  504   11 Oct 2008 Stefan RittBug Reportmhttpd "messages" broken
> mhttpd "messages" page stopped working after svn revision 4327 because of uninitialized variable 
> "filename2" in midas.c:cm_message_retrieve(). Attached patch fixes the problem for me.
> K.O.
> 
> 
> --- src/midas.c (revision 4342)
> +++ src/midas.c (working copy)
> @@ -978,6 +978,8 @@
>        size = sizeof(filename);
>        db_get_value(hDB, 0, "/Logger/Message file", filename, &size, TID_STRING, TRUE);
>  
> +      strlcpy(filename2, filename, sizeof(filename2));
> +
>        if (strchr(filename, '%')) {
>           /* replace strings such as midas_%y%m%d.mid with current date */
>           tzset();

Ups, was my fault, sorry. I committed your change.
  503   10 Oct 2008 Konstantin OlchanskiBug Reportmhttpd "messages" broken
mhttpd "messages" page stopped working after svn revision 4327 because of uninitialized variable 
"filename2" in midas.c:cm_message_retrieve(). Attached patch fixes the problem for me.
K.O.


--- src/midas.c (revision 4342)
+++ src/midas.c (working copy)
@@ -978,6 +978,8 @@
       size = sizeof(filename);
       db_get_value(hDB, 0, "/Logger/Message file", filename, &size, TID_STRING, TRUE);
 
+      strlcpy(filename2, filename, sizeof(filename2));
+
       if (strchr(filename, '%')) {
          /* replace strings such as midas_%y%m%d.mid with current date */
          tzset();
  502   03 Oct 2008 Konstantin OlchanskiInfoImplement non-default mserver tcp port numbers.
midas revision 4342 implements non-default tcp port numbers for the mserver.

To use, run "mserver -p 7070" and say "setenv MIDAS_SERVER_HOST
host.example.com:7070".

This is useful when multiple experiments share the same computer, but one does
not want to setup a global /etc/exptab (non-root users cannot change it) or one
does not want to run the mserver from xinetd (i.e. all experiments run different
versions of midas and cannot use the same common mserver executable).

Changed files:
src/mserver.c
src/midas.c
doxfiles/utilities.dox
doxfiles/appendixD.dox

Revision 4342.

K.O.
  501   19 Sep 2008 Stefan RittInfoLazylogger logging changed
I modified the logging behavior of lazylogger. Originally, it was writing 
messages (run copied, removed, ...) both into midas.log and 
lazy_log_update.log. Since we have many files, it kind of clutters up the 
logging files. I think it is a good idea to have a separate file (which I 
changed not to "lazy.log" instead of "lazy_log_update.log" which I guess was a 
bug), so I put the logging into the main file under a conditional compile:

#ifdef WRITE_MIDAS_LOG
   cm_msg(MINFO, "lazy_log_update", str);
#endif

so it can be turned on again by adding -DWRITE_MIDAS_LOG to the compile line. 
If other experiments have different needs, one could make the logging behavior 
controllable through the ODB. In that case, I would suggest a single parameter 
"Logging file" which can be either "midas.log" for the normal logging or 
"lazy.log" for logging into the extra file. I guess having the messages twice 
on the system is not needed by any experiment.

- Stefan
  500   18 Sep 2008 Stefan RittInfoPotential problems in multi-threaded slow control front-end
We had recently some problems at our experiment which I would like to share 
with the community. This affects however only experiments which have a slow 
control front-end in multi-threaded mode.

The problem is related with the fact that the midas API is not thread safe, so 
a device driver or bus driver from the slow control system may not call any ODB 
function. We found several drivers (mainly psi_separator.c, psi_beamline.c etc) 
which use inside read/write function the midas PAI function cm_msg() to report 
any error. While this is ok for the init section (which is executed in the main 
frontend thread) this is not ok for the read/write function inside the driver. 
If this is done anyhow, it can happen that the main thread locks the ODB (via 
db_lock_database()) and the thread interrupts that call and locks the ODB 
again. In rare cases this can cause a stale lock on the ODB. This blocks all 
other programs to access the ODB and the experiment will die loudly. It is hard 
to identify, since error messages cannot be produced any more, and remote 
programs (not affected by the lock) just show a rpc timeout.

I fixed all drivers now in our experiment which solved the problem for us, but 
I urge other people to double check their device drivers as well.

In case of problems, there is a thread ID check in 
db_lock_database()/db_unlock_database() which can be activated by supplying 

-DCHECK_THREAD_ID

in the compile command line. If then these functions are called from different 
threads, the program aborts with an assertion failure, which can then be 
debugged. 

There is also a stack history system implemented with new functions 
ss_stack_xxxx. Using this system, one can check which functions called 
db_lock_database() *before* an error occurs. Using this system, I identified 
the malicious drivers. Maybe this system can also be used in other error 
debugging scenarios.
  499   17 Sep 2008 Stefan RittInfoNew flag for auto restart
A new ODB flag has been introduced. When the logger is configured for automatic 
stop and restart (/Logger/Auto restart = y), the restart delay was hard-wired 
to 20 sec., which might be too long or short for some experiments. Therefore a 
new parameter "/Logger/Auto restart delay" has been introduced which can be 
used to accommodate different delays. A non-zero delay is necessary for 
experiments where some lengthy activities occur during the stop of a run, like 
an analyzer writing many histograms to disk.
  498   29 Aug 2008 Konstantin OlchanskiInfohistory_odbc: store MIDAS history in ODBC/MySQL database
The code for storing midas history in an odbc sql database has been committed.
Changes:
include/history_odbc.h, src/history_odbc.cxx --- implementation
src/mlogger.c --- call the history_odbc functions
utils/mh2sql.cxx --- import existing midas history files (*.hst) into an odbc
sql database.

This new code is enabled by the HAVE_ODBC gunk in the Makefile. If compilation
bombs, please let me know and as a work around, comment out all instances of
HAVE_ODBC from your Makefile.

Limitations:
- mhttpd support for reading history data from odbc sql database is missing
- many sql functions are implemented in a very minimalistic form (i.e. when
defining a history event, we blindly ask sql to create the tables, even if they
already exist - this works, but spams the midas log with sql errors).
- error handling is incomplete: after any sql error, the odbc connection is closed.
- only MySQL (and ascii output) are supported: we use mysql-specific data types
as they match midas types exactly. Code to support PgSQL is present and it used
to work, but is commented out. (At TRIUMF/T2K, we intend to use MySQL exclusively).
- ODBC ascii interface is used, instead of the potentially more efficient binary
interface.

To enable:
- create a MySQL database,
- create $HOME/.odbc.ini (see attached example)
- set ODB "/History/PerVariableHistory" to "1" - the new code is intended to be
used with per-variable history. Per-equipment (traditional) history would work,
but will result in suboptimal layout of SQL tables.
- set ODB "/Logger/ODBC_DSN" to the DSN defined in .odc.ini.
- set ODB "/Logger/ODBC_Debug" to non-zero to enable debugging output from the
new code.

To use the "ascii output" mode:
Included is code to write "ascii" sql output into a text file, instead of using
an actual SQL database. To enable it, set "ODBC_DSN" to
"/path/to/some/text/file" and all SQL output will be written to this file. No
actual SQL database required. This mode exists mostly for debugging the SQL syntax.

Despite limitations, the committed code is fully functional - we are presently
using it to record history data from slow controls of T2K detector tests
(voltages, currents, temperatures).

Comments and suggestions on naming and mapping from odb structures to SQL tables
is very much welcome.

K.O.
  497   28 Aug 2008 Konstantin OlchanskiInfotriumf/t2k midas updates
Following changes to midas produced from the TRIUMF T2K project have been
committed to svn:
1) cm_shutdown() will now SIGKILL clients that cannot be stopped via normal
means. Previously cm_shutdown() would print a message to the effect "please kill
this client yourself manually". The user action in this case (assuming they did
not issue cm_shutdown() by mistake) has been to find out the client pid using
"ps", kill -KILL it, then "odbedit clean". cm_shutdown() now performs all this
automatically.
2) rpc_send_event() did not correctly detect loss of connection to the remote
mserver (i.e. in case it was killed by cm_shutdown() above). Now, correct error
handling is in place and the remote frontend should gracefully shutdown if
mserver connection is lost. (However I observe that some of my remote frontends
fail to exit unless I do "exit(1);" from my frontend_exit() function.
3) mhttpd bug fixed: when editing odb entries, the "cancel" button did not work
correctly.
4) lazylogger "script" backup type is now fully tested and documented. Example
scripts for writing to dcache are available by request.
5) mlogger and mhttpd changes for writing history data to an sql database are
mostly completed and will be committed after some more debugging. (If you are
interested in details, please contact me directly).
6) (committed some time ago) Makefile changes for cross-compiling midas are now
in: "make linux32", "make linux64", "make crosscompile".
K.O.
  496   31 Jul 2008 Stefan RittInfoImprovement of custom pages
Even more improvements have been implemented into custom pages recently, containing a complete JavaScript library for ODB communication. This JavaScript library relies on certain new commands built into mhttpd, and is therefore hardcoded into mhttpd. It can be seen by entering

http://<your mhttpd host>/mhttpd.js

To include it in your custom page, put following statement inside the <head>...</head> tag:
<script type="text/javascript" src="../mhttpd.js"></script>

It contains several functions:

Display of cursor location



When writing custom pages with large background images and labels placed on that image, it is hard to figure out X and Y coordinates of the labels. This can now be simplified by adding a new tag to the background image like
<img id="refimg" src="...">

If the "refimg" tag is present, the cursor changes into a crosshair and it's absolute and relative locations in respect to the reference image are shown in the status bar:



To make this work under Firefox, the user has to explicitly allow for status bar changes. To do so, enter about:config in the address bar. In the filter bar, enter status. Then locate dom.disable_window_status_change and set it to false.

Retrieving ODB values



Retrieving individual or array values from the ODB through the AJAX interface is now very simple. Just call:
  ODBGet(<path>);

to obtain a value. If <path> points to an array in the ODB, an individual value can be retrieved by using an index, like
  ODBGet('/Equipment/Environment/Variables/Input[3]');

or the complete array can be obtained with
  ODBGet('/Equipment/Environment/Variables/Input[*]');

The function then returns a JavaScript array which can be used like
  var a = ODBGet('/Equipment/Environment/Variables/Input[*]');

  for (i=0 ; i<a.length ; i++)
    alert(a[i]);

This functionality together with the window.setInterval() function can be used to update parts of the web page periodically such as:
  window.setInterval("Refresh()", 10000);

  function Refresh() {
    document.getElementById("run_number").innerHTML = ODBGet('/Runinfo/Run number');
  }

This function updates the current run number every 10 seconds in the background. The custom page has to contain an element with id="run_number", such as
  <td id="run_number"></td>

The formatting of any number uses the internal default. If this should be changed, the format can directly appended in the ODB path such as:
  ODBGet('/Equipment/Environment/Variables/Input[3]&format=%1.2lf');

the format %1.2lf is then directly passed to the sprintf() function.

Retrieving System Messages



A similar function ODBGetMsg(<n>) has been defined. It retrieves the last <n> system messages, which can then be displayed in some message area. If n=1 a single string is returned, if n>1 an array of strings is returned similar to ODB arrays.

Setting ODB values



Individual ODB values can be set in the background with
  ODBSet(<path>,<value>);

or
  ODBSet(<path>,<value>,<password_name>);

The password_name has the same meaning as described in elog:492. It must be defined under /Custom/Pwd/<password_name>. The function ODBSet can be used for example when one clicks on an checkbox for example:
  <input type="checkbox" onClick="ODBSet('/Logger/Write data',this.checked?'1':'0')">

If used as above, the state of the checkbox must be initialized when the page is loaded. This can be either done with some JavaScript code called on initialization, which then uses ODBGet() as described above. Alternatively, the <odb> tag can be used like:
  <odb src="/Logger/Write data" type="checkbox" edit="2" onclick="ODBSet('/Logger/Write data',this.checked?'1':'0')">

The special code edit="2" instructs mhttpd not to put any JavaScript code into the checkbox tag, since setting this value in the ODB is now handled by the user-supplied ODBSet() code. With edit="1" the internal JavaScript is activated, which uses the old form submission for sending the value to the ODB.
  495   16 Jul 2008 Stefan RittInfoImplementation of db_set_link_data() and db_set_link_data_index()
The current implementation of ODB links has the problem that once a link is
created, it cannot be changed any more through odbedit. This is because each
"set" command works on the destination of the link instead of the link. The same
happens when one loads a *.odb file. To overcome this problem, two new functions
db_set_link_data() and db_set_link_data_index() have been implemented. They
resemble their counterparts db_set_data() and db_set_data_index(), but they can
be used to directly modify a link instead of the link target. I use these
functions now in odbedit and db_paste() so that the above described problems are
fixed now. I do not expect any side effect of this, but if people experience
problems with db_paste(), please let me know.
  494   04 Jul 2008 Stefan RittInfoImproved alarm conditions implemented
I implemented improved alarm conditions in the alarm system. Now one can write
conditions like

  /Equipment/HV/Variables/Input[*] < 100

or 

  /Equipment/HV/Variables/Input[2-3] < 100

to check all values from an array or a certain range. If one array element
fulfills the alarm condition, the alarm is trigger. In addition, bit-wise alarm
conditions are possible

  /Equipment/Environment/Variables/Input[0] & 8

is triggered if bit #2 is set in Input[0].

The changes are committed to SVN revision 4242.
  493   01 Jul 2008 Jimmy NgaiForumCAEN V792N QDC with MIDAS
Dear All,

I have a problem when testing the V792N 16 CH QDC with the V1718 VME-USB 
Bridge on Scientific Linux 5.1 i386 (kernel 2.6.18-53.1.21.e15).

The problem is that the V792N does not response normally after a few minutes 
of continuous polling and readout of data. It seems like the V792N is hanged 
and a hardware reset of the VME system is required to bring it working again. 
If I do not poll for DREADY first and directly read the Output Buffer 
continuously, the system can work properly.

I have worked on this problem many days but I cannot find any clues to solve 
it. I have tried to use the CAENVMEDemo program (with some modifications) to 
do the same thing (polling and readout) and it works fine. CAEN technical 
support also doesn't know why the VME system is hanged. I think it might be a 
problem of MIDAS itself. I have tried with MIDAS revision 4132 and the trunk 
version, but the problem is still there. Is there any parameter in MIDAS 
(buffer size etc?) which may cause this problem? I have attached my frontend 
code and drivers for your reference.

Thank you for your kind attention.

Best Regards,
Jimmy
Attachment 1: frontend.c
/********************************************************************\

  Name:         frontend.c
  Created by:   Stefan Ritt
  Modified by:  Jimmy Ngai

  Date:         July 1, 2008

  Contents:     Experiment specific readout code (user part) of
                Midas frontend. This example simulates a "trigger
                event" which are filled with VME data. The trigger
                event is filled with two banks(ADC0 and TDC0).

  $Id: frontend.c 4089 2007-11-27 07:28:17Z ritt@PSI.CH $

\********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include "midas.h"
#include "mvmestd.h"
#include "experim.h"

#define HAVE_V792N

/* make frontend functions callable from the C framework */
#ifdef __cplusplus
extern "C" {
#endif

#ifdef HAVE_V792N
#include "vme/v792n.h"
#endif

/*-- Globals -------------------------------------------------------*/

/* The frontend name (client name) as seen by other MIDAS clients   */
char *frontend_name = "Sample Frontend";
/* The frontend file name, don't change it */
char *frontend_file_name = __FILE__;

/* frontend_loop is called periodically if this variable is TRUE    */
BOOL frontend_call_loop = FALSE;

/* a frontend status page is displayed with this frequency in ms */
INT display_period = 3000;

/* maximum event size produced by this frontend */
INT max_event_size = 10000;

/* maximum event size for fragmented events (EQ_FRAGMENTED) */
INT max_event_size_frag = 5 * 1024 * 1024;

/* buffer size to hold events */
INT event_buffer_size = 100 * 10000;

/* Hardware */
MVME_INTERFACE *myvme;

/* VME base address */
DWORD V792N_BASE = 0x32100000;

/* number of channels */
#define N_ADC      16

/*-- Function declarations -----------------------------------------*/

INT frontend_init();
INT frontend_exit();
INT begin_of_run(INT run_number, char *error);
INT end_of_run(INT run_number, char *error);
INT pause_run(INT run_number, char *error);
INT resume_run(INT run_number, char *error);
INT frontend_loop();

INT read_trigger_event(char *pevent, INT off);
INT read_scaler_event(char *pevent, INT off);

/*-- Equipment list ------------------------------------------------*/

EQUIPMENT equipment[] = {

   {"Trigger",               /* equipment name */
    {1, 0,                   /* event ID, trigger mask */
     "SYSTEM",               /* event buffer */
     EQ_POLLED,              /* equipment type */
     LAM_SOURCE(0, 0xFFFFFF),        /* event source crate 0, all stations */
     "MIDAS",                /* format */
     TRUE,                   /* enabled */
     RO_RUNNING,             /* read only when running */
     500,                    /* poll for 500ms */
     0,                      /* stop run after this event limit */
     0,                      /* number of sub events */
     0,                      /* don't log history */
     "", "", "",},
    read_trigger_event,      /* readout routine */
    },

   {""}
};

#ifdef __cplusplus
}
#endif

/********************************************************************\
              Callback routines for system transitions

  These routines are called whenever a system transition like start/
  stop of a run occurs. The routines are called on the following
  occations:

  frontend_init:  When the frontend program is started. This routine
                  should initialize the hardware.

  frontend_exit:  When the frontend program is shut down. Can be used
                  to releas any locked resources like memory, commu-
                  nications ports etc.

  begin_of_run:   When a new run is started. Clear scalers, open
                  rungates, etc.

  end_of_run:     Called on a request to stop a run. Can send
                  end-of-run event and close run gates.

  pause_run:      When a run is paused. Should disable trigger events.

  resume_run:     When a run is resumed. Should enable trigger events.
\********************************************************************/

INT init_vme_modules()
{
#ifdef HAVE_V792N
   v792n_SoftReset(myvme, V792N_BASE);
   v792n_Setup(myvme, V792N_BASE, 3);
//   v792n_Status(myvme, V792N_BASE);
#endif

   return SUCCESS;
}

/*-- Frontend Init -------------------------------------------------*/

INT frontend_init()
{
   int status;

   /* hardware initialization */

   // Open VME interface
   status = mvme_open(&myvme, 0);

   // Set am to A32 non-privileged Data
   mvme_set_am(myvme, MVME_AM_A32_ND);

   // Initialize all VME modules
   init_vme_modules();

   v792n_OfflineSet(myvme, V792N_BASE);
   v792n_DataClear(myvme, V792N_BASE);

   /* print message and return FE_ERR_HW if frontend should not be started */
   if (status != MVME_SUCCESS) {
      cm_msg(MERROR, "frontend_init", "VME interface could not be opened.");
//      return FE_ERR_HW;
   }

   return SUCCESS;
}

/*-- Frontend Exit -------------------------------------------------*/

INT frontend_exit()
{
   // Close VME interface
   mvme_close(myvme);

   return SUCCESS;
}

/*-- Begin of Run --------------------------------------------------*/

INT begin_of_run(INT run_number, char *error)
{
   // Initialize all VME modules
   init_vme_modules();

   v792n_OnlineSet(myvme, V792N_BASE);

   return SUCCESS;
}

/*-- End of Run ----------------------------------------------------*/

INT end_of_run(INT run_number, char *error)
{
   v792n_OfflineSet(myvme, V792N_BASE);
   v792n_DataClear(myvme, V792N_BASE);

   return SUCCESS;
}

/*-- Pause Run -----------------------------------------------------*/

INT pause_run(INT run_number, char *error)
{
   v792n_OfflineSet(myvme, V792N_BASE);

   return SUCCESS;
}

/*-- Resuem Run ----------------------------------------------------*/

INT resume_run(INT run_number, char *error)
{
   v792n_OnlineSet(myvme, V792N_BASE);

   return SUCCESS;
}

/*-- Frontend Loop -------------------------------------------------*/

INT frontend_loop()
{
   /* if frontend_call_loop is true, this routine gets called when
      the frontend is idle or once between every event */
   return SUCCESS;
}

/*------------------------------------------------------------------*/

/********************************************************************\

  Readout routines for different events

\********************************************************************/

/*-- Trigger event routines ----------------------------------------*/

INT poll_event(INT source, INT count, BOOL test)
/* Polling routine for events. Returns TRUE if event
   is available. If test equals TRUE, don't return. The test
   flag is used to time the polling */
{
   int i;
   DWORD lam;

   for (i = 0; i < count; i++) {
      lam = v792n_DataReady(myvme, V792N_BASE);
      if (lam)
         if (!test)
            return TRUE;
   }

   return FALSE;
}

/*-- Interrupt configuration ---------------------------------------*/

INT interrupt_configure(INT cmd, INT source, POINTER_T adr)
{
   switch (cmd) {
   case CMD_INTERRUPT_ENABLE:
      break;
   case CMD_INTERRUPT_DISABLE:
      break;
   case CMD_INTERRUPT_ATTACH:
      break;
   case CMD_INTERRUPT_DETACH:
      break;
   }
   return SUCCESS;
}

/*-- Event readout -------------------------------------------------*/

#ifdef HAVE_V792N
INT read_v792n(INT base, const char *bk_name, char *pevent, INT n_chn)
{
   INT i;
   INT nentry = 0, counter;
   DWORD data[V792N_MAX_CHANNELS+2];
   WORD *pdata;

   // Event counter
//   v792n_EvtCntRead(myvme, base, &counter);

   // Read event
   v792n_EventRead(myvme, base, data, &nentry);

   // Clear ADC
//   v792n_DataClear(myvme, base);

   // Create ADC bank
   bk_create(pevent, bk_name, TID_WORD, &pdata);

   for (i = 0; i < n_chn; i++)
      pdata[i] = 0;

   for (i = 0; i < nentry; i++) {
... 27 more lines ...
Attachment 2: v1718.c
/********************************************************************

  Name:         v1718.c
  Created by:   Jimmy Ngai

  Contents:     Midas VME standard (MVMESTD) layer for CAEN V1718
                VME-USB2.0 Bridge using CAENVMElib Linux library

  Based on sis3100.c by Stefan Ritt

  $Id: $

\********************************************************************/

#ifdef __linux__
#ifndef OS_LINUX
#define OS_LINUX
#endif
#endif

#ifdef OS_LINUX

#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>

#include "CAENVMElib.h"

#endif // OS_LINUX

#include "mvmestd.h"

/*------------------------------------------------------------------*/

int mvme_open(MVME_INTERFACE **vme, int idx)
{
   *vme = (MVME_INTERFACE *) malloc(sizeof(MVME_INTERFACE));
   if (*vme == NULL)
      return MVME_NO_MEM;

   memset(*vme, 0, sizeof(MVME_INTERFACE));

   /* open VME */
   if (CAENVME_Init(cvV1718, 0, idx, &(*vme)->handle) != cvSuccess)
      return MVME_NO_INTERFACE;

   /* default values */
   (*vme)->am        = MVME_AM_DEFAULT;
   (*vme)->dmode     = MVME_DMODE_D32;
   (*vme)->blt_mode  = MVME_BLT_NONE;
   (*vme)->table     = NULL; // not used

   return MVME_SUCCESS;
}

/*------------------------------------------------------------------*/

int mvme_close(MVME_INTERFACE *vme)
{
   CAENVME_End(vme->handle);

   return MVME_SUCCESS;
}

/*------------------------------------------------------------------*/

int mvme_sysreset(MVME_INTERFACE *vme)
{
   CAENVME_SystemReset(vme->handle);

   return MVME_SUCCESS;
}

/*------------------------------------------------------------------*/

int mvme_write(MVME_INTERFACE *vme, mvme_addr_t vme_addr, void *src, mvme_size_t n_bytes)
{
   mvme_size_t n;
   DWORD data;
   int status=0;
   int hvme;
   hvme = vme->handle;

   if (n_bytes <= 4) {
      data = n = 0;
      memcpy(&data, src, n_bytes);

      /* D8 */
      if (vme->dmode == MVME_DMODE_D8)
         status = CAENVME_WriteCycle(hvme, vme_addr, &data, vme->am, cvD8);
      /* D16 */
      else if (vme->dmode == MVME_DMODE_D16)
         status = CAENVME_WriteCycle(hvme, vme_addr, &data, vme->am, cvD16);
      /* D32 */
      else if (vme->dmode == MVME_DMODE_D32)
         status = CAENVME_WriteCycle(hvme, vme_addr, &data, vme->am, cvD32);
      
      if (status == cvSuccess)
         n = n_bytes;
      else
         n = 0;
   } else {

      /* D32 BLT */
      if (vme->blt_mode == MVME_BLT_BLT32)
         status |= CAENVME_BLTWriteCycle(hvme, vme_addr, src, n_bytes, vme->am, cvD32, &n);
      /* D64 MBLT */
      else if (vme->blt_mode == MVME_BLT_MBLT64)
         status |= CAENVME_MBLTWriteCycle(hvme, vme_addr, src, n_bytes, vme->am, &n);

      if (status != cvSuccess)
         n = 0;
   }

   return n;
}

/*------------------------------------------------------------------*/

int mvme_write_value(MVME_INTERFACE *vme, mvme_addr_t vme_addr, unsigned int value)
{
   mvme_size_t n;
   int status=0;
   int hvme;
   hvme = vme->handle;

   if (vme->dmode == MVME_DMODE_D8)
      n = 1;
   else if (vme->dmode == MVME_DMODE_D16)
      n = 2;
   else
      n = 4;

   /* D8 */
   if (vme->dmode == MVME_DMODE_D8)
      status = CAENVME_WriteCycle(hvme, vme_addr, &value, vme->am, cvD8);
   /* D16 */
   else if (vme->dmode == MVME_DMODE_D16)
      status = CAENVME_WriteCycle(hvme, vme_addr, &value, vme->am, cvD16);
   /* D32 */
   else if (vme->dmode == MVME_DMODE_D32)
      status = CAENVME_WriteCycle(hvme, vme_addr, &value, vme->am, cvD32);

   if (status != cvSuccess)
      n = 0;

   return n;
}

/*------------------------------------------------------------------*/

int mvme_read(MVME_INTERFACE *vme, void *dst, mvme_addr_t vme_addr, mvme_size_t n_bytes)
{
   mvme_size_t i, n;
   DWORD data;
   int status=0, cfifo;
   int hvme;
   hvme = vme->handle;

   if (n_bytes <= 4) {
      data = 0;

      /* D8 */
      if (vme->dmode == MVME_DMODE_D8)
         status = CAENVME_ReadCycle(hvme, vme_addr, &data, vme->am, cvD8);
      /* D16 */
      else if (vme->dmode == MVME_DMODE_D16)
         status = CAENVME_ReadCycle(hvme, vme_addr, &data, vme->am, cvD16);
      /* D32 */
      else if (vme->dmode == MVME_DMODE_D32)
         status = CAENVME_ReadCycle(hvme, vme_addr, &data, vme->am, cvD32);
      
      memcpy(dst, &data, n_bytes);
      if (status == cvSuccess)
         n = n_bytes;
      else
         n = 0;

   } else {

      n = 0;

      /* normal I/O */
      if (vme->blt_mode == MVME_BLT_NONE) {
         for (i=0 ; i<n_bytes ; i++)
            status = CAENVME_ReadCycle(hvme, vme_addr, dst+i, vme->am, cvD8);
         n = n_bytes;
      /* D32 BLT */
      } else if (vme->blt_mode == MVME_BLT_BLT32)
         status |= CAENVME_BLTReadCycle(hvme, vme_addr, dst, n_bytes, vme->am, cvD32, &n);
      /* D32 FIFO BLT */
      else if (vme->blt_mode == MVME_BLT_BLT32FIFO) {
         CAENVME_GetFIFOMode(hvme, &cfifo);
         status = CAENVME_SetFIFOMode(hvme, 1);
         status |= CAENVME_BLTReadCycle(hvme, vme_addr, dst, n_bytes, vme->am, cvD32, &n);
         CAENVME_SetFIFOMode(hvme, cfifo);
      /* D64 MBLT */
      } else if (vme->blt_mode == MVME_BLT_MBLT64)
         status |= CAENVME_MBLTReadCycle(hvme, vme_addr, dst, n_bytes, vme->am, &n);
      /* D64 FIFO MBLT */
      else if (vme->blt_mode == MVME_BLT_MBLT64FIFO) {
         CAENVME_GetFIFOMode(hvme, &cfifo);
         status = CAENVME_SetFIFOMode(hvme, 1);
         status |= CAENVME_MBLTReadCycle(hvme, vme_addr, dst, n_bytes, vme->am, &n);
         CAENVME_SetFIFOMode(hvme, cfifo);
      }

      if (status != cvSuccess)
         n = 0;
   }

   return n;
}

/*------------------------------------------------------------------*/

unsigned int mvme_read_value(MVME_INTERFACE *vme, mvme_addr_t vme_addr)
{
   unsigned int data;
   int status=0;
   int hvme;
   hvme = vme->handle;

   data = 0;

   /* D8 */
   if (vme->dmode == MVME_DMODE_D8)
      status = CAENVME_ReadCycle(hvme, vme_addr, &data, vme->am, cvD8);
   /* D16 */
   else if (vme->dmode == MVME_DMODE_D16)
      status = CAENVME_ReadCycle(hvme, vme_addr, &data, vme->am, cvD16);
   /* D32 */
   else if (vme->dmode == MVME_DMODE_D32)
      status = CAENVME_ReadCycle(hvme, vme_addr, &data, vme->am, cvD32);

   return data;
}

/*------------------------------------------------------------------*/

int mvme_set_am(MVME_INTERFACE *vme, int am)
{
   vme->am = am;
   return MVME_SUCCESS;
}

/*------------------------------------------------------------------*/

int mvme_get_am(MVME_INTERFACE *vme, int *am)
{
   *am = vme->am;
   return MVME_SUCCESS;
}

/*------------------------------------------------------------------*/

int mvme_set_dmode(MVME_INTERFACE *vme, int dmode)
{
   vme->dmode = dmode;
   return MVME_SUCCESS;
}

/*------------------------------------------------------------------*/

int mvme_get_dmode(MVME_INTERFACE *vme, int *dmode)
{
   *dmode = vme->dmode;
   return MVME_SUCCESS;
}

/*------------------------------------------------------------------*/

int mvme_set_blt(MVME_INTERFACE *vme, int mode)
{
   vme->blt_mode = mode;
   return MVME_SUCCESS;
}

/*------------------------------------------------------------------*/

int mvme_get_blt(MVME_INTERFACE *vme, int *mode)
{
   *mode = vme->blt_mode;
   return MVME_SUCCESS;
}
Attachment 3: v792n.h
/*********************************************************************

  Name:         v792n.h
  Created by:   Jimmy Ngai

  Contents:     V792N 16ch. QDC include

  Based on v792.h by Pierre-Andre Amaudruz

  $Id: $
*********************************************************************/
#ifndef  V792N_INCLUDE_H
#define  V792N_INCLUDE_H

#include <stdio.h>
#include <string.h>
#include "mvmestd.h"

#ifdef __cplusplus
extern "C" {
#endif

#define  V792N_MAX_CHANNELS       (DWORD) 16
#define  V792N_REG_BASE           (DWORD) (0x1000)
#define  V792N_FIRM_REV           (DWORD) (0x1000)
#define  V792N_GEO_ADDR_RW        (DWORD) (0x1002)
#define  V792N_MCST_CBLT_RW       (DWORD) (0x1004)
#define  V792N_BIT_SET1_RW        (DWORD) (0x1006)
#define  V792N_BIT_CLEAR1_WO      (DWORD) (0x1008)
#define  V792N_SOFT_RESET         (DWORD) (0x1<<7)
#define  V792N_INT_LEVEL_WO       (DWORD) (0x100A)
#define  V792N_INT_VECTOR_WO      (DWORD) (0x100C)
#define  V792N_CSR1_RO            (DWORD) (0x100E)
#define  V792N_CR1_RW             (DWORD) (0x1010)
#define  V792N_ADER_H_RW          (DWORD) (0x1012)
#define  V792N_ADER_L_RW          (DWORD) (0x1014)
#define  V792N_SINGLE_RST_WO      (DWORD) (0x1016)
#define  V792N_MCST_CBLT_CTRL_RW  (DWORD) (0x101A)
#define  V792N_EVTRIG_REG_RW      (DWORD) (0x1020)
#define  V792N_CSR2_RO            (DWORD) (0x1022)
#define  V792N_EVT_CNT_L_RO       (DWORD) (0x1024)
#define  V792N_EVT_CNT_H_RO       (DWORD) (0x1026)
#define  V792N_INCR_EVT_WO        (DWORD) (0x1028)
#define  V792N_INCR_OFFSET_WO     (DWORD) (0x102A)
#define  V792N_LD_TEST_RW         (DWORD) (0x102C)
#define  V792N_DELAY_CLEAR_RW     (DWORD) (0x102E)
#define  V792N_FCLR_WIN_RW        (DWORD) (0x102E)
#define  V792N_BIT_SET2_RW        (DWORD) (0x1032)
#define  V792N_BIT_CLEAR2_WO      (DWORD) (0x1034)
#define  V792N_W_MEM_TEST_WO      (DWORD) (0x1036)
#define  V792N_MEM_TEST_WORD_H_WO (DWORD) (0x1038)
#define  V792N_MEM_TEST_WORD_L_WO (DWORD) (0x103A)
#define  V792N_CRATE_SEL_RW       (DWORD) (0x103C)
#define  V792N_TEST_EVENT_WO      (DWORD) (0x103E)
#define  V792N_EVT_CNT_RST_WO     (DWORD) (0x1040)
#define  V792N_IPED_RW            (DWORD) (0x1060)
#define  V792N_R_MEM_TEST_WO      (DWORD) (0x1064)
#define  V792N_SWCOMM_WO          (DWORD) (0x1068)
#define  V792N_SLIDECONST_RW      (DWORD) (0x106A)
#define  V792N_AAD_RO             (DWORD) (0x1070)
#define  V792N_BAD_RO             (DWORD) (0x1072)
#define  V792N_THRES_BASE         (DWORD) (0x1080)

WORD v792n_Read16(MVME_INTERFACE *mvme, DWORD base, int offset);
void v792n_Write16(MVME_INTERFACE *mvme, DWORD base, int offset, WORD value);
DWORD v792n_Read32(MVME_INTERFACE *mvme, DWORD base, int offset);
void v792n_Write32(MVME_INTERFACE *mvme, DWORD base, int offset, DWORD value);

int  v792n_DataReady(MVME_INTERFACE *mvme, DWORD base);
int  v792n_isEvtReady(MVME_INTERFACE *mvme, DWORD base);
int  v792n_isBusy(MVME_INTERFACE *mvme, DWORD base);
int  v792n_EventRead(MVME_INTERFACE *mvme, DWORD base, DWORD *pdest, int *nentry);
int  v792n_DataRead(MVME_INTERFACE *mvme, DWORD base, DWORD *pdest, int *nentry);
void v792n_DataClear(MVME_INTERFACE *mvme, DWORD base);
void v792n_EvtCntRead(MVME_INTERFACE *mvme, DWORD base, DWORD *evtcnt);
void v792n_EvtCntReset(MVME_INTERFACE *mvme, DWORD base);
void v792n_IntSet(MVME_INTERFACE *mvme, DWORD base, int level, int vector);
void v792n_IntEnable(MVME_INTERFACE *mvme, DWORD base, int level);
void v792n_IntDisable(MVME_INTERFACE *mvme, DWORD base);
void v792n_EvtTriggerSet(MVME_INTERFACE *mvme, DWORD base, int count);
void v792n_SingleShotReset(MVME_INTERFACE *mvme, DWORD base);
void v792n_SoftReset(MVME_INTERFACE *mvme, DWORD base);
void v792n_Trigger(MVME_INTERFACE *mvme, DWORD base);
int  v792n_ThresholdRead(MVME_INTERFACE *mvme, DWORD base, WORD *threshold);
int  v792n_ThresholdWrite(MVME_INTERFACE *mvme, DWORD base, WORD *threshold);
int  v792n_CSR1Read(MVME_INTERFACE *mvme, DWORD base);
int  v792n_CSR2Read(MVME_INTERFACE *mvme, DWORD base);
int  v792n_BitSet2Read(MVME_INTERFACE *mvme, DWORD base);
void v792n_BitSet2Set(MVME_INTERFACE *mvme, DWORD base, WORD pat);
void v792n_BitSet2Clear(MVME_INTERFACE *mvme, DWORD base, WORD pat);
WORD v792n_ControlRegister1Read(MVME_INTERFACE *mvme, DWORD base);
void v792n_ControlRegister1Write(MVME_INTERFACE *mvme, DWORD base, WORD pat);
void v792n_OnlineSet(MVME_INTERFACE *mvme, DWORD base);
void v792n_OfflineSet(MVME_INTERFACE *mvme, DWORD base);
void v792n_BlkEndEnable(MVME_INTERFACE *mvme, DWORD base);
void v792n_OverRangeEnable(MVME_INTERFACE *mvme, DWORD base);
void v792n_OverRangeDisable(MVME_INTERFACE *mvme, DWORD base);
void v792n_LowThEnable(MVME_INTERFACE *mvme, DWORD base);
void v792n_LowThDisable(MVME_INTERFACE *mvme, DWORD base);
void v792n_EmptyEnable(MVME_INTERFACE *mvme, DWORD base);
void v792n_CrateSet(MVME_INTERFACE *mvme, DWORD base, DWORD *evtcnt);
void v792n_DelayClearSet(MVME_INTERFACE *mvme, DWORD base, int delay);
int  v792n_Setup(MVME_INTERFACE *mvme, DWORD base, int mode);
void v792n_Status(MVME_INTERFACE *mvme, DWORD base);
int  v792n_isPresent(MVME_INTERFACE *mvme, DWORD base);

  enum v792n_DataType {
    v792n_typeMeasurement=0,
    v792n_typeHeader     =2,
    v792n_typeFooter     =4,
    v792n_typeFiller     =6
  };

  typedef union {
    DWORD raw;
    struct v792n_Entry {
      unsigned adc:12; // bit0 here
      unsigned ov:1;
      unsigned un:1;
      unsigned _pad_1:3;
      unsigned channel:4;
      unsigned _pad_2:3;
      unsigned type:3;
      unsigned geo:5;
    } data ;
    struct v792n_Header {
      unsigned _pad_1:8; // bit0 here
      unsigned cnt:6;
      unsigned _pad_2:2;
      unsigned crate:8;
      unsigned type:3;
      unsigned geo:5;
    } header;
    struct v792n_Footer {
      unsigned evtCnt:24; // bit0 here
      unsigned type:3;
      unsigned geo:5;
    } footer;
  } v792n_Data;

  typedef union {
    DWORD raw;
    struct {
      unsigned DataReady:1; // bit0 here
      unsigned GlobalDataReady:1;
      unsigned Busy:1;
      unsigned GlobalBusy:1;
      unsigned Amnesia:1;
      unsigned Purge:1;
      unsigned TermOn:1;
      unsigned TermOff:1;
      unsigned EventReady:1; //bit 8 here
    };
  } v792n_StatusRegister1;
  typedef union {
    DWORD raw;
    struct {
      unsigned _pad_1:1; // bit0 here
      unsigned BufferEmpty:1;
      unsigned BufferFull:1;
      unsigned _pad_2:1;
      unsigned PB:4;
      //unsigned DSEL0:1;
      //unsigned DSEL1:1;
      //unsigned CSEL0:1;
      //unsigned CSEL1:1;
    };
  } v792n_StatusRegister2;
  typedef union {
    DWORD raw;
    struct {
      unsigned _pad_1:2;
      unsigned BlkEnd:1;
      unsigned _pad_2:1;
      unsigned ProgReset:1;
      unsigned BErr:1;
      unsigned Align64:1;
    };
  } v792n_ControlRegister1;
  typedef union {
    DWORD raw;
    struct {
      unsigned MemTest:1;
      unsigned OffLine:1;
      unsigned ClearData:1;
      unsigned OverRange:1;
      unsigned LowThresh:1;
      unsigned _pad_1:1;//bit5
      unsigned TestAcq:1;
      unsigned SLDEnable:1;
      unsigned StepTH:1;
      unsigned _pad_2:2;//bits 9-10
      unsigned AutoIncr:1;
      unsigned EmptyProg:1;
      unsigned SlideSubEnable:1;
      unsigned AllTrg:1;
    };
  } v792n_BitSet2Register;

  void v792n_printEntry(const v792n_Data* v);

#ifdef __cplusplus
}
#endif

#endif // V792N_INCLUDE_H

/* emacs
 * Local Variables:
 * mode:C
 * mode:font-lock
 * tab-width: 8
 * c-basic-offset: 2
 * End:
 */
Attachment 4: v792n.c
/*********************************************************************

  Name:         v792n.c
  Created by:   Jimmy Ngai

  Contents:     V792N 16ch. QDC

  Based on v792.c by Pierre-Andre Amaudruz
                
  $Id: $
*********************************************************************/
#include <stdio.h>
#include <string.h>
#include <signal.h>
#if defined(OS_LINUX)
#include <unistd.h>
#endif
#include "v792n.h"

WORD v792n_Read16(MVME_INTERFACE *mvme, DWORD base, int offset)
{
  int cmode;
  WORD data;

  mvme_get_dmode(mvme, &cmode);
  mvme_set_dmode(mvme, MVME_DMODE_D16);
  data = mvme_read_value(mvme, base+offset);
  mvme_set_dmode(mvme, cmode);
  return data;
}

void v792n_Write16(MVME_INTERFACE *mvme, DWORD base, int offset, WORD value)
{
  int cmode;
  mvme_get_dmode(mvme, &cmode);
  mvme_set_dmode(mvme, MVME_DMODE_D16);
  mvme_write_value(mvme, base+offset, value);
  mvme_set_dmode(mvme, cmode);
}

DWORD v792n_Read32(MVME_INTERFACE *mvme, DWORD base, int offset)
{
  int cmode;
  DWORD data;

  mvme_get_dmode(mvme, &cmode);
  mvme_set_dmode(mvme, MVME_DMODE_D32);
  data = mvme_read_value(mvme, base+offset);
  mvme_set_dmode(mvme, cmode);
  return data;
}

void v792n_Write32(MVME_INTERFACE *mvme, DWORD base, int offset, DWORD value)
{
  int cmode;
  mvme_get_dmode(mvme, &cmode);
  mvme_set_dmode(mvme, MVME_DMODE_D32);
  mvme_write_value(mvme, base+offset, value);
  mvme_set_dmode(mvme, cmode);
}

/*****************************************************************/
int v792n_DataReady(MVME_INTERFACE *mvme, DWORD base)
{
  int data_ready, cmode;

  mvme_get_dmode(mvme, &cmode);
  mvme_set_dmode(mvme, MVME_DMODE_D16);
  data_ready = mvme_read_value(mvme, base+V792N_CSR1_RO) & 0x1;
  mvme_set_dmode(mvme, cmode);
  return data_ready;
}

/*****************************************************************/
int v792n_isEvtReady(MVME_INTERFACE *mvme, DWORD base)
{
  int csr;
  csr = v792n_CSR1Read(mvme, base);
  return (csr & 0x100);
}

/*****************************************************************/
int v792n_isBusy(MVME_INTERFACE *mvme, DWORD base)
{
  int status, busy, timeout, cmode;

  mvme_get_dmode(mvme, &cmode);
  mvme_set_dmode(mvme, MVME_DMODE_D16);
  timeout = 1000;
  do {
    status = mvme_read_value(mvme, base+V792N_CSR1_RO);
    busy = status & 0x4;
    timeout--;
  } while (busy || timeout);
  mvme_set_dmode(mvme, cmode);
  return (busy != 0 ? 1 : 0);
}

/*****************************************************************/
/*
Read single event, return event length (number of entries)
Uses single vme access! (1us/D32)
*/
int v792n_EventRead(MVME_INTERFACE *mvme, DWORD base, DWORD *pdest, int *nentry)
{
#define USE_BLT_READ_2

#ifdef USE_SINGLE_READ
  DWORD hdata;
  int   cmode;

  mvme_get_dmode(mvme, &cmode);
  mvme_set_dmode(mvme, MVME_DMODE_D32);

  *nentry = 0;
  if (v792n_DataReady(mvme, base)) {
    do {
      hdata = mvme_read_value(mvme, base);
    } while (!(hdata & 0x02000000)); // skip up to the header

    pdest[*nentry] = hdata;
    *nentry += 1;
    do {
      pdest[*nentry] = mvme_read_value(mvme, base);
      *nentry += 1;
    } while (!(pdest[*nentry-1] & 0x04000000)); // copy until the trailer

    nentry--;
  }

  mvme_set_dmode(mvme, cmode);
#endif // USE_SINGLE_READ

#ifdef USE_BLT_READ_1
  DWORD hdata, data[V792N_MAX_CHANNELS+2];
  int   cam, cmode, cnt, i;

  mvme_get_am(mvme, &cam);
  mvme_get_dmode(mvme, &cmode);
  mvme_set_dmode(mvme, MVME_DMODE_D32);

  *nentry = 0;
  if (v792n_DataReady(mvme, base)) {
    do {
      hdata = mvme_read_value(mvme, base);
    } while (!(hdata & 0x02000000)); // skip up to the header

    mvme_set_am(mvme, MVME_AM_A32_NB);
    mvme->blt_mode = MVME_BLT_BLT32;
    cnt = (hdata >> 8) & 0x3F;

    mvme_read(mvme, data, base, (cnt+1)*4);
    pdest[0] = hdata;
    for (i=1;i<=cnt+1;i++)
      pdest[i] = data[i-1];

    *nentry = cnt + 2;
  }

  mvme_set_am(mvme, cam);
  mvme_set_dmode(mvme, cmode);
#endif // USE_BLT_READ_1

#ifdef USE_BLT_READ_2
  DWORD hdata;
  int   cam, cmode, cnt;

  mvme_get_am(mvme, &cam);
  mvme_get_dmode(mvme, &cmode);

  *nentry = 0;
//  if (v792n_DataReady(mvme, base)) {
    mvme_set_am(mvme, MVME_AM_A32_NB);
    mvme->blt_mode = MVME_BLT_BLT32;
    mvme_read(mvme, pdest, base, (V792N_MAX_CHANNELS+2)*4);
    cnt = (pdest[0] >> 8) & 0x3F;
    *nentry = cnt + 2;
//  }

  mvme_set_am(mvme, cam);
  mvme_set_dmode(mvme, cmode);
#endif //USE_BLT_READ_2

  return *nentry;
}

/*****************************************************************/
/*
Read nentry of data from the data buffer. Will use the DMA engine
if size is larger than 127 bytes.
*/
int v792n_DataRead(MVME_INTERFACE *mvme, DWORD base, DWORD *pdest, int *nentry)
{
  int  cmode;

  mvme_get_dmode(mvme, &cmode);
  mvme_set_dmode(mvme, MVME_DMODE_D32);
//  *nentry = 128;
  if (v792n_DataReady(mvme, base)) {
    mvme_read(mvme, pdest, base, *nentry*4);
  }
  mvme_set_dmode(mvme, cmode);
  return *nentry;
}

/*****************************************************************/
void v792n_DataClear(MVME_INTERFACE *mvme, DWORD base)
{
  int cmode;
  mvme_get_dmode(mvme, &cmode);
  mvme_set_dmode(mvme, MVME_DMODE_D16);
  mvme_write_value(mvme, base+V792N_BIT_SET2_RW, 0x4);
  mvme_write_value(mvme, base+V792N_BIT_CLEAR2_WO, 0x4);
  mvme_set_dmode(mvme, cmode);
}

/*****************************************************************/
void v792n_EvtCntRead(MVME_INTERFACE *mvme, DWORD base, DWORD *evtcnt)
{
  int cmode;

  mvme_get_dmode(mvme, &cmode);
  mvme_set_dmode(mvme, MVME_DMODE_D16);
  *evtcnt  = mvme_read_value(mvme, base+V792N_EVT_CNT_L_RO);
  *evtcnt += (mvme_read_value(mvme, base+V792N_EVT_CNT_H_RO) << 16);
  mvme_set_dmode(mvme, cmode);
}

/*****************************************************************/
void v792n_EvtCntReset(MVME_INTERFACE *mvme, DWORD base)
{
  int cmode;
  mvme_get_dmode(mvme, &cmode);
  mvme_set_dmode(mvme, MVME_DMODE_D16);
  mvme_write_value(mvme, base+V792N_EVT_CNT_RST_WO, 1);
  mvme_set_dmode(mvme, cmode);
}

/*****************************************************************/
void v792n_IntSet(MVME_INTERFACE *mvme, DWORD base, int level, int vector)
{
  int cmode;
  mvme_get_dmode(mvme, &cmode);
  mvme_set_dmode(mvme, MVME_DMODE_D16);
  mvme_write_value(mvme, base+V792N_INT_VECTOR_WO, (vector & 0xFF));
  mvme_write_value(mvme, base+V792N_INT_LEVEL_WO, (level & 0x7));
  mvme_set_dmode(mvme, cmode);
}

/*****************************************************************/
void v792n_IntEnable(MVME_INTERFACE *mvme, DWORD base, int level)
{
  int cmode;
  mvme_get_dmode(mvme, &cmode);
  mvme_set_dmode(mvme, MVME_DMODE_D16);
  mvme_write_value(mvme, base+V792N_EVTRIG_REG_RW, (level & 0x1F));
  /* Use the trigger buffer for int enable/disable
  mvme_write_value(mvme, base+V792N_INT_LEVEL_WO, (level & 0x7));
  */
  mvme_set_dmode(mvme, cmode);
}

/*****************************************************************/
void v792n_IntDisable(MVME_INTERFACE *mvme, DWORD base)
{
  int cmode;
  mvme_get_dmode(mvme, &cmode);
  mvme_set_dmode(mvme, MVME_DMODE_D16);
  mvme_write_value(mvme, base+V792N_EVTRIG_REG_RW, 0);
  /* Use the trigger buffer for int enable/disable
     Setting a level 0 reboot the VMIC !
  mvme_write_value(mvme, base+V792N_INT_LEVEL_WO, 0);
  */
  mvme_set_dmode(mvme, cmode);
}

/*****************************************************************/
void v792n_EvtTriggerSet(MVME_INTERFACE *mvme, DWORD base, int count)
{
  int cmode;

  mvme_get_dmode(mvme, &cmode);
  mvme_set_dmode(mvme, MVME_DMODE_D16);
  mvme_write_value(mvme, base+V792N_EVTRIG_REG_RW, (count & 0x1F));
  mvme_set_dmode(mvme, cmode);
}

/*****************************************************************/
void v792n_SingleShotReset(MVME_INTERFACE *mvme, DWORD base)
{
  int cmode;
  mvme_get_dmode(mvme, &cmode);
  mvme_set_dmode(mvme, MVME_DMODE_D16);
  mvme_write_value(mvme, base+V792N_SINGLE_RST_WO, 1);
  mvme_set_dmode(mvme, cmode);
}

/*****************************************************************/
void v792n_SoftReset(MVME_INTERFACE *mvme, DWORD base)
{
... 407 more lines ...
  492   17 Jun 2008 Stefan RittInfoImprovement of custom pages
Some improvement of custom pages have been implemented. The idea behind is that
a custom page would contain a large background image containing indicators but
also controls. While indicators (values, bars) are already available, the field
of controls have been improved.

Edit boxes floating on top of a graphic
---------------------------------------

The first option has been there from the beginning, but was never documented. It
makes it possible to put an edit box right on top of a graphic by means of a CSS
style tag. The custom page code could look like this:

<div style="position:absolute; top:100px; left:50px;">
<odb src="/Runinfo/run number" edit=1>
</div>
<img src="cusgom.gif">

The "div" tag surrounding the "odb" tag places this directly on top of the
"custom.gif" image, where it can be clicked to be edited.

Password protection of an edit box
----------------------------------

Being able to control an experiment through a web interface of course rises the
question about safety. This is not so much about external access (for which we
have other protection schemes like host lists etc.) but it's about accidental
access by the normal shift crew. If a single click on a web page opens a
critical valve, this might be a problem. In order to restrict access to some
"experts", an additional password can be chosen for all or some controls on a
custom page. This is done by a new option in the "odb" tag and by adding a small
JavaScript function into the custom page:

<script type="text/javascript">
<!--
function promptpwd(path)
{
    pwd = prompt('Please enter password', '');
    document.cookie = "cpwd=" + pwd;
    location.href = path;
}
//-->
</script>

...

<odb src="/..." edit=1 pwd="CustomPwd">

...

If the "pwd" option is present in the "odb" tag, mhttpd establishes a call to
the promptpwd() function if one click on the value. The password is then asked
from the user and submitted as a cookie. mhttpd then check this password against
the ODB entry

/Custom/Pwd/CustomPwd

and shows an error if they don't match. By using an explicit name ("CustomPwd"
in the above example) one can use a single password for all controls on a page,
or one could use several passwords on the same page. Like a shift crew password
for the less severe controls (/Custom/Pwd/ShiftPwd), and an "expert" password
(/Custom/Pwd/ExpertPwd) for the critical things. This password is of course not
secure in the sense that it's placed in plain text into the ODB, it's more to
prevent accidental modifications of things.

Area map to toggle values
-------------------------

Sometimes it's desirable to toggle a value, like the state of a valve. This can
be done now with a new function like this:

<map name="Custom1">
<area shape="rect" coords="40,200,100,300" alt="Main Valve"
  href="Custom1?cmd=Toggle&odb=/Equipment/Environment/Variables/Output[2]">
</map>
<img src="cusgom.gif" usemap="#Custom1">

This defines a clickable map on top of the custom image. The area(s) should
match with some areas on the image like the box of a valve. By clicking on it,
the supplied path to the ODB is used (in this case
"/Equpiment/Environment/Variables[2]") and it's value is toggled (set to 0 if it
is 1, set to 0 if it is 1). If the valve value is then used in the image via a
"fill" statement to change the color of the valve, it can turn green or red
depending on it's state.

Are map with password check
---------------------------

The above area map can be combined with the password check. To do so, one needs:

<area shape="rect" coords="40,200,100,300" alt="Main Valve"
  href="#"
onClick="promptpwd('Custom1?cmd=toggle&pnam=CustomPwd?odb=/Equipment/Environment/Variables/Output[2]')">

in combination with the JavaScript from above.


An example of the are map technology is shown in the attachment. This page from the MEG experiment at PSI
shows a complex gas system. The valves are represented as green circles. If they are clicked, they close
and become red (after the user successfully supplied the correct password).
Attachment 1: Capture.png
Capture.png
  491   16 Jun 2008 Stefan RittSuggestionmlogger is flooding the message queue
> > The current versions of mlogger SVN 4215 is flooding our message system with
> > stuff like
> > 
> > > Tue Jun 10 16:42:01 2008 [Logger,INFO] Configured history with 22 events
> > > Tue Jun 10 16:42:14 2008 [Logger,INFO] Configured history with 22 events
> > > Tue Jun 10 16:42:26 2008 [Logger,INFO] Configured history with 22 events
> 
> Problem confirmed on the M11 DAQ system at TRIUMF. We definitely do nothing funny
> there, so what is going on? Will investigate.

The only place I see where this could happen is in mlogger.c, lines 3064ff:

   /* check if event size has changed */
   db_get_record_size(hDB, hKey, 0, &size);
   if (size != hist_log[i].buffer_size) {
      close_history();
      open_history();
      return;
   }

The record size corresponds to /Equipment/<name>/Variables. If this array changes in
size, it will trigger the re-definition of the history. So please have a look there
and check why the record size changes.
  490   16 Jun 2008 Konstantin OlchanskiSuggestionmlogger is flooding the message queue
> The current versions of mlogger SVN 4215 is flooding our message system with
> stuff like
> 
> > Tue Jun 10 16:42:01 2008 [Logger,INFO] Configured history with 22 events
> > Tue Jun 10 16:42:14 2008 [Logger,INFO] Configured history with 22 events
> > Tue Jun 10 16:42:26 2008 [Logger,INFO] Configured history with 22 events

Problem confirmed on the M11 DAQ system at TRIUMF. We definitely do nothing funny
there, so what is going on? Will investigate.

K.O.
  489   16 Jun 2008 Stefan RittBug Fix"Missing event" problem fixed in front-end framework
Since the very beginning midas had the problem that the last event of a run was
sometimes missing in the data. While for most experiments this is not an issue,
it starts to hurt on experiments using event building (front-end 1 and front-end
2 in the example below). A missing event can screw up the event builder on the
next begin of run, where the "missing event" would show up as the first event of
the new run, triggering an event mismatch error in the event builder.

After some analysis, we identified the problem as follows. Assume FE1 controls
the trigger, while FE2 generates the second event fragment.

1) Stop is requested to FE1
2) tr_stop gets called on FE1
3) tr_stop calls end_of_run() use code
4) end_of_run() disables the trigger
5) FE1 finishes stop transition
6) Stop is requested to FE2
7) FE2 finishes stop transition

What can now happen is the following: An additional event occurs between 2) and
4). This event triggers ADCs and TDCs, and is then stored in the front-end
hardware. FE2 sees this event, since it has not yet done the stop transition,
and reads it out. FE1 is however already in the end_of_run() routine, and simply
disables the trigger, without reading this last event, and thus causing the
event mismatch at the beginning of the next run.

To fix the problem, the framework in mfe.c was changed:

1) Stop is requested to FE1
2) tr_stop gets called on FE1
3) tr_stop calls end_of_run() use code
4) end_of_run() disables the trigger
4b) tr_stop calls check_polled_events()
5) FE1 finishes stop transition
6) Stop is requested to FE2
7) FE2 finishes stop transition

The new routine check_polled_events checks if there is any more event in the
hardware by calling the user polling routine. If there is one more event, calls
the user readout routine and sends it to the back-end before concluding the run
transition. 

This modification solved our problem at the MEG experiment at PSI, but it might
be good that all experiments using event building update midas to revision 4225.

I do not expect any bad side effect, but one never knows. So if there are new
problems caused by this modification, please report.

- Stefan
  488   11 Jun 2008 Konstantin OlchanskiSuggestionmlogger is flooding the message queue
> The current versions of mlogger SVN 4215 is flooding our message system with
> stuff like
> 
> > Tue Jun 10 16:42:01 2008 [Logger,INFO] Configured history with 22 events
> > Tue Jun 10 16:42:14 2008 [Logger,INFO] Configured history with 22 events
> > Tue Jun 10 16:42:26 2008 [Logger,INFO] Configured history with 22 events
> 
> This is fatal to us and blowing up the midas.log like hell. I would prefer if
> one could flag these kind of messages (ODB /Logger/..), i.e. enable and disable
> it. At the moment I have to comment it out in the source code since we cannot
> work with it.

I just sent the attached message to Stefan - please read it.

Before we take any action, we need to understand why history is being
reconfigured every 10 seconds (according to your logfile snippet).

Are you starting a new run every 10 seconds?

If that is what you do and that is your intent, I guess it is atypical usage of
MIDAS and the message from the mlogger is offensive and should be removed/disabled.

If something else is going on, we need to understand it before we sweep trouble
under the carpet by disabling this message.

K.O.

Stefan - there is more bad news - the message is produced when the history
is being reconfigured. This only is supposed to happen when the mlogger
starts or at the begin of run.

So these messages are just a tip of an iceberg of some other trouble.

The logic of when history is reconfigured I did not change. So likely
the trouble existed before, but you did not know about it.

We can kill the message, but why is the history being reconfigured
at a rate that "floods the log file"? That cannot possibly be good.

K.O.
  487   11 Jun 2008 Andreas SuterSuggestionmlogger is flooding the message queue
The current versions of mlogger SVN 4215 is flooding our message system with
stuff like

> Tue Jun 10 16:42:01 2008 [Logger,INFO] Configured history with 22 events
> Tue Jun 10 16:42:14 2008 [Logger,INFO] Configured history with 22 events
> Tue Jun 10 16:42:26 2008 [Logger,INFO] Configured history with 22 events

This is fatal to us and blowing up the midas.log like hell. I would prefer if
one could flag these kind of messages (ODB /Logger/..), i.e. enable and disable
it. At the moment I have to comment it out in the source code since we cannot
work with it.

Cheers,
  Andreas 
  486   07 Jun 2008 Jimmy NgaiForumCAEN VME-USE Bridge with MIDAS
Hi All,

I am testing the libraries provided by CAEN with the sample softwares in the 
bundle CD. The Windows sample program works fine, but I cannot get started with 
the Linux sample program. When I run CAENVMEDemo in Scientific Linux 5.1, it 
gives me a message "Error opening the device". I have followed the instructions 
in CAENVMElibReadme.txt: 
- compile and load the device driver v1718.ko
- install the library libCAENVME.so

Does anyone have any experience of using V1718 in Scientific Linux? Thanks.

Regards,
Jimmy


> Hi All,
> 
> Is there any example code for using MIDAS with the CAEN VME-USB Bridge V1718? 
> Thanks.
> 
> Regards,
> Jimmy
ELOG V3.1.4-2e1708b5