Back Midas Rome Roody Rootana
  Midas DAQ System  Not logged in ELOG logo
Entry  10 Jul 2014, Clemens Sauerzopf, Forum, Adding Interrupt handling to SIS3100 driver 
    Reply  11 Jul 2014, Pierre-Andre Amaudruz, Forum, Adding Interrupt handling to SIS3100 driver 
       Reply  14 Jul 2014, Clemens Sauerzopf, Forum, Adding Interrupt handling to SIS3100 driver 
          Reply  15 Jul 2014, Pierre-Andre Amaudruz, Forum, Adding Interrupt handling to SIS3100 driver 
             Reply  06 Aug 2014, Clemens Sauerzopf, Forum, Adding Interrupt handling to SIS3100 driver sis3100.hhsis3100.hh
Message ID: 1018     Entry time: 06 Aug 2014     In reply to: 1016
Author: Clemens Sauerzopf 
Topic: Forum 
Subject: Adding Interrupt handling to SIS3100 driver 
Hello Pierre-Andre,

thank you for your help with the interrupt handling. To close this case I'll
attach my interrupt
handling code for the SIS 3100 to this post as a reference. Maybe someone wants
to do something
similar in the future. 

I've decide to go for a C++ frontend therefore it is a class that handles
everything. The user only
has to provide a function pointer to the constructor that handles the interrupt
bitmask. The
interrupt handling is done with a timedwait within a separate thread. 

Cheers,
Clemens

> Hello Clemens,
> 
> The hardware readout is triggered by the interrupt within this thread. The
main thread poll on  
> the data availability (from the rb) to filter/compose the frontend event.
> In a similar multi-threaded implementation presently used in a dark matter
experiment we start 
> as many thread as necessary to constantly poll on the hardware for "data
fragment" collection.
> The event composition is done in the main thread through polling on the RBs.
> 
> Depending on the trigger rate and readout time, we can afford to analyze the
data fragment at 
> the thread level and add computed/summary information to the ring buffer on a
event-by-event 
> basis. This facilitate the overall event filtering happening later on in our
event builder. 
> 
> "polling the trigger signal?", I don't understand. You can poll on the trigger
condition but 
> then you don't need interrupt.
> 
> The original Midas interrupt implementation was to let the interrupt function
set a acknowledge 
> flag which is picked up by the standard midas polling function (user code) for
triggering the 
> readout. This method ensure a minimal time spent in the IRQ and works fine for
a single thread.
> 
> In regards of the CAEN V1742, we do have a VME driver for it, but it hasn't
been added to the 
> Midas yet (quite recent), but please don't hesitate to send us a copy.
> 
> Cheers, PAA
> 
Attachment 1: sis3100.hh  3 kB  | Hide | Hide all | Show all
/*! 
  \file sis3100.hh
  \brief provides an interface for interrupt handling with the Struck SIS3100 VME interface
  \author Clemens Sauerzopf <clemens.sauerzopf@oeaw.ac.at>  
  \date 06.08.2014
  \version 1.0
*/ 


#ifndef __SIS3100_HH__
#define __SIS3100_HH__

#include<stdint.h>
#include<sys/types.h>

 #if HAVE_MIDAS__
 extern "C" {
 #include "midas.h"
 #include "sis3100/linux/sis3100_vme_calls.h"
 #include "sis3100/linux/sis1100_var.h"
 }
 #else
 #include <pthread.h>
 #include "sis3100/linux/sis3100_vme_calls.h"
 #include "sis3100/linux/sis1100_var.h"
 #endif

//! interrupt frontend handling class for SIS 3100 VME interface with veto gate and trigger generation
/*!
  This class provides an easy to use interface for handling interrupts with the Stuck SIS3100 VME 
  interface. When using this class create an instance and pass an unused device number to the 
  constructor and a function pointer to handle the interrupt. 

  The interrupt handling is done in a separate thread that waits with a timeout of 500 ms for a 
  SIGUSR1 signal from the SIS kernel driver. In case of a timeout the loop checks if a thread stop 
  signal from midas is present and then waits again for an interrupt. If an interrupt occurs the
  interrupt vector is loaded and a veto gate is produced by the @ref startVeto function on the 
  NIM port 1. Afterwards a user supplied function that takes the interrupt bitask, the highest 
  interrupt level and its vector as arguments is executed. After that the interrupts get acknowledged
  and the veto gate is closed.

  This class uses a separate device to avoid race conditions and for the low level interface to the
  irq setup.
 */
class sis3100 {
public:
  sis3100(int sisDeviceNum,  bool (*eventFunction)(int,int,int));
  bool enableFrontInterrupts();
  bool disbaleFrontInterrupts();
  bool enableVMEInterrupts();
  bool disbaleVMEInterrupts();

  bool enableOutputs();
  bool disableOutputs();

  static inline void startVeto(int p)       {s3100_control_write(p, 0x80, 0x00000001);}
  static inline void stopVeto(int p)        {s3100_control_write(p, 0x80, 0x00010000);}
  static inline void startVeto2(int p)      {s3100_control_write(p, 0x80, 0x00000002);}
  static inline void stopVeto2(int p)       {s3100_control_write(p, 0x80, 0x00020000);}
  static inline void generateTrigger(int p) {s3100_control_write(p, 0x80, 0x02000000);}

  inline bool isOpen() const {return (p==-1 ? false : true);}

  inline void setIsRunning(bool isRun){isRunning = isRun;}
private:
  int p; // SIS3100 device handler

  u_int32_t iobits;
  struct sis1100_irq_ctl irqctl;
  struct sis1100_irq_get irqget;
  struct sis1100_irq_ack irqack; 
  sigset_t mask, old_mask;

  bool isRunning;

  // for testing
#if HAVE_MIDAS__
  midas_thread_t thread;
#else
  pthread_t thread;
#endif

  static 
#if HAVE_MIDAS__
  INT
#else
  void*
#endif
 interruptThread(void *param);

  struct threadInit {
    bool (*eventFunction)(int, int, int);
    bool *isRunning;
    int p; // SIS3100 device handler
    u_int32_t *iobits;
    struct sis1100_irq_ctl *irqctl;
    struct sis1100_irq_get *irqget;
    struct sis1100_irq_ack *irqack; 
    sigset_t mask;
    struct timespec waitTime;
  };

  threadInit threadData;
};

#endif // compile guard
Attachment 2: sis3100.hh  3 kB  | Show | Hide all | Show all
ELOG V3.1.4-2e1708b5