Subversion Repositories f9daq

Compare Revisions

Ignore whitespace Rev 194 → Rev 195

/cvi/instr/drsctrl/DRS.cpp
0,0 → 1,7733
/********************************************************************
 
Name: DRS.cpp
Created by: Stefan Ritt, Matthias Schneebeli
 
Contents: Library functions for DRS mezzanine and USB boards
 
$Id: DRS.cpp 22289 2016-04-27 09:40:58Z ritt $
 
\********************************************************************/
#define NEW_TIMING_CALIBRATION
 
#ifdef USE_DRS_MUTEX
#include "wx/wx.h" // must be before <windows.h>
#endif
 
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
#include <algorithm>
#include <sys/stat.h>
#include <fcntl.h>
#include "strlcpy.h"
#include "DRS.h"
 
#ifdef _MSC_VER
#pragma warning(disable:4996)
# include <windows.h>
# include <direct.h>
#else
# include <unistd.h>
# include <sys/time.h>
inline void Sleep(useconds_t x)
{
usleep(x * 1000);
}
#endif
 
#ifdef _MSC_VER
#include <conio.h>
#define drs_kbhit() kbhit()
#else
#include <sys/ioctl.h>
 
int drs_kbhit()
{
int n;
 
ioctl(0, FIONREAD, &n);
return (n > 0);
}
static inline int getch()
{
return getchar();
}
#endif
 
#include "DRS.h"
 
#ifdef _MSC_VER
extern "C" {
#endif
 
#include "mxml.h"
 
#ifdef _MSC_VER
}
#endif
 
/*---- minimal FPGA firmvare version required for this library -----*/
const int REQUIRED_FIRMWARE_VERSION_DRS2 = 5268;
const int REQUIRED_FIRMWARE_VERSION_DRS3 = 6981;
const int REQUIRED_FIRMWARE_VERSION_DRS4 = 15147;
 
/*---- calibration methods to be stored in EEPROMs -----------------*/
 
#define VCALIB_METHOD_V4 1
#define TCALIB_METHOD_V4 1
 
#define VCALIB_METHOD 2
#define TCALIB_METHOD 2 // correct for sampling frequency, calibrate every channel
 
/*---- VME addresses -----------------------------------------------*/
#ifdef HAVE_VME
/* assuming following DIP Switch settings:
 
SW1-1: 1 (off) use geographical addressing (1=left, 21=right)
SW1-2: 1 (off) \
SW1-3: 1 (off) > VME_WINSIZE = 8MB, subwindow = 1MB
SW1-4: 0 (on) /
SW1-5: 0 (on) reserverd
SW1-6: 0 (on) reserverd
SW1-7: 0 (on) reserverd
SW1-8: 0 (on) \
|
SW2-1: 0 (on) |
SW2-2: 0 (on) |
SW2-3: 0 (on) |
SW2-4: 0 (on) > VME_ADDR_OFFSET = 0
SW2-5: 0 (on) |
SW2-6: 0 (on) |
SW2-7: 0 (on) |
SW2-8: 0 (on) /
 
which gives
VME base address = SlotNo * VME_WINSIZE + VME_ADDR_OFFSET
= SlotNo * 0x80'0000
*/
#define GEVPC_BASE_ADDR 0x00000000
#define GEVPC_WINSIZE 0x800000
#define GEVPC_USER_FPGA (GEVPC_WINSIZE*2/8)
#define PMC1_OFFSET 0x00000
#define PMC2_OFFSET 0x80000
#define PMC_CTRL_OFFSET 0x00000 /* all registers 32 bit */
#define PMC_STATUS_OFFSET 0x10000
#define PMC_FIFO_OFFSET 0x20000
#define PMC_RAM_OFFSET 0x40000
#endif // HAVE_VME
/*---- USB addresses -----------------------------------------------*/
#define USB_TIMEOUT 1000 // one second
#ifdef HAVE_USB
#define USB_CTRL_OFFSET 0x00 /* all registers 32 bit */
#define USB_STATUS_OFFSET 0x40
#define USB_RAM_OFFSET 0x80
#define USB_CMD_IDENT 0 // Query identification
#define USB_CMD_ADDR 1 // Address cycle
#define USB_CMD_READ 2 // "VME" read <addr><size>
#define USB_CMD_WRITE 3 // "VME" write <addr><size>
#define USB_CMD_READ12 4 // 12-bit read <LSB><MSB>
#define USB_CMD_WRITE12 5 // 12-bit write <LSB><MSB>
 
#define USB2_CMD_READ 1
#define USB2_CMD_WRITE 2
#define USB2_CTRL_OFFSET 0x00000 /* all registers 32 bit */
#define USB2_STATUS_OFFSET 0x10000
#define USB2_FIFO_OFFSET 0x20000
#define USB2_RAM_OFFSET 0x40000
#endif // HAVE_USB
 
/*------------------------------------------------------------------*/
 
using namespace std;
 
#ifdef HAVE_USB
#define USB2_BUFFER_SIZE (1024*1024+10)
unsigned char static *usb2_buffer = NULL;
#endif
 
/*------------------------------------------------------------------*/
 
#ifdef USE_DRS_MUTEX
static wxMutex *s_drsMutex = NULL; // used for wxWidgets multi-threaded programs
#endif
 
/*------------------------------------------------------------------*/
 
DRS::DRS()
: fNumberOfBoards(0)
#ifdef HAVE_VME
, fVmeInterface(0)
#endif
{
#ifdef HAVE_USB
MUSB_INTERFACE *usb_interface;
#endif
 
#if defined(HAVE_VME) || defined(HAVE_USB)
int index = 0, i=0;
#endif
 
memset(fError, 0, sizeof(fError));
 
#ifdef HAVE_VME
unsigned short type, fw, magic, serial, temperature;
mvme_addr_t addr;
 
if (mvme_open(&fVmeInterface, 0) == MVME_SUCCESS) {
 
mvme_set_am(fVmeInterface, MVME_AM_A32);
mvme_set_dmode(fVmeInterface, MVME_DMODE_D16);
 
/* check all VME slave slots */
for (index = 2; index <= 21; index++) {
 
/* check PMC1 */
addr = GEVPC_BASE_ADDR + index * GEVPC_WINSIZE; // VME board base address
addr += GEVPC_USER_FPGA; // UsrFPGA base address
addr += PMC1_OFFSET; // PMC1 offset
 
mvme_set_dmode(fVmeInterface, MVME_DMODE_D16);
i = mvme_read(fVmeInterface, &magic, addr + PMC_STATUS_OFFSET + REG_MAGIC, 2);
if (i == 2) {
if (magic != 0xC0DE) {
printf("Found old firmware, please upgrade immediately!\n");
fBoard[fNumberOfBoards] = new DRSBoard(fVmeInterface, addr, (index - 2) << 1);
fNumberOfBoards++;
} else {
 
/* read board type */
mvme_read(fVmeInterface, &type, addr + PMC_STATUS_OFFSET + REG_BOARD_TYPE, 2);
type &= 0xFF;
if (type == 2 || type == 3 || type == 4) { // DRS2 or DRS3 or DRS4
 
/* read firmware number */
mvme_read(fVmeInterface, &fw, addr + PMC_STATUS_OFFSET + REG_VERSION_FW, 2);
 
/* read serial number */
mvme_read(fVmeInterface, &serial, addr + PMC_STATUS_OFFSET + REG_SERIAL_BOARD, 2);
 
/* read temperature register to see if CMC card is present */
mvme_read(fVmeInterface, &temperature, addr + PMC_STATUS_OFFSET + REG_TEMPERATURE, 2);
 
/* LED blinking */
#if 0
do {
data = 0x00040000;
mvme_write(fVmeInterface, addr + PMC_CTRL_OFFSET + REG_CTRL, &data, sizeof(data));
mvme_write(fVmeInterface, addr + PMC2_OFFSET + PMC_CTRL_OFFSET + REG_CTRL, &data,
sizeof(data));
 
Sleep(500);
 
data = 0x00000000;
mvme_write(fVmeInterface, addr + PMC_CTRL_OFFSET + REG_CTRL, &data, sizeof(data));
mvme_write(fVmeInterface, addr + PMC2_OFFSET + PMC_CTRL_OFFSET + REG_CTRL, data,
sizeof(data));
 
Sleep(500);
 
} while (1);
#endif
 
if (temperature == 0xFFFF) {
printf("Found VME board in slot %d, fw %d, but no CMC board in upper slot\n", index, fw);
} else {
printf("Found DRS%d board %2d in upper VME slot %2d, serial #%d, firmware revision %d\n", type, fNumberOfBoards, index, serial, fw);
 
fBoard[fNumberOfBoards] = new DRSBoard(fVmeInterface, addr, (index - 2) << 1);
if (!fBoard[fNumberOfBoards]->HasCorrectFirmware())
sprintf(fError, "Wrong firmware version: board has %d, required is %d. Board may not work correctly.\n",
fBoard[fNumberOfBoards]->GetFirmwareVersion(),
fBoard[fNumberOfBoards]->GetRequiredFirmwareVersion());
fNumberOfBoards++;
}
}
}
}
 
/* check PMC2 */
addr = GEVPC_BASE_ADDR + index * GEVPC_WINSIZE; // VME board base address
addr += GEVPC_USER_FPGA; // UsrFPGA base address
addr += PMC2_OFFSET; // PMC2 offset
 
mvme_set_dmode(fVmeInterface, MVME_DMODE_D16);
i = mvme_read(fVmeInterface, &fw, addr + PMC_STATUS_OFFSET + REG_MAGIC, 2);
if (i == 2) {
if (magic != 0xC0DE) {
printf("Found old firmware, please upgrade immediately!\n");
fBoard[fNumberOfBoards] = new DRSBoard(fVmeInterface, addr, (index - 2) << 1 | 1);
fNumberOfBoards++;
} else {
 
/* read board type */
mvme_read(fVmeInterface, &type, addr + PMC_STATUS_OFFSET + REG_BOARD_TYPE, 2);
type &= 0xFF;
if (type == 2 || type == 3 || type == 4) { // DRS2 or DRS3 or DRS4
 
/* read firmware number */
mvme_read(fVmeInterface, &fw, addr + PMC_STATUS_OFFSET + REG_VERSION_FW, 2);
 
/* read serial number */
mvme_read(fVmeInterface, &serial, addr + PMC_STATUS_OFFSET + REG_SERIAL_BOARD, 2);
 
/* read temperature register to see if CMC card is present */
mvme_read(fVmeInterface, &temperature, addr + PMC_STATUS_OFFSET + REG_TEMPERATURE, 2);
 
if (temperature == 0xFFFF) {
printf("Found VME board in slot %d, fw %d, but no CMC board in lower slot\n", index, fw);
} else {
printf("Found DRS%d board %2d in lower VME slot %2d, serial #%d, firmware revision %d\n", type, fNumberOfBoards, index, serial, fw);
 
fBoard[fNumberOfBoards] = new DRSBoard(fVmeInterface, addr, ((index - 2) << 1) | 1);
if (!fBoard[fNumberOfBoards]->HasCorrectFirmware())
sprintf(fError, "Wrong firmware version: board has %d, required is %d. Board may not work correctly.\n",
fBoard[fNumberOfBoards]->GetFirmwareVersion(),
fBoard[fNumberOfBoards]->GetRequiredFirmwareVersion());
fNumberOfBoards++;
}
}
}
}
}
} else
printf("Cannot access VME crate, check driver, power and connection\n");
#endif // HAVE_VME
 
#ifdef HAVE_USB
unsigned char buffer[512];
int found, one_found, usb_slot;
 
one_found = 0;
usb_slot = 0;
for (index = 0; index < 127; index++) {
found = 0;
 
/* check for USB-Mezzanine test board */
if (musb_open(&usb_interface, 0x10C4, 0x1175, index, 1, 0) == MUSB_SUCCESS) {
 
/* check ID */
buffer[0] = USB_CMD_IDENT;
musb_write(usb_interface, 2, buffer, 1, USB_TIMEOUT);
 
i = musb_read(usb_interface, 1, (char *) buffer, sizeof(buffer), USB_TIMEOUT);
if (strcmp((char *) buffer, "USB_MEZZ2 V1.0") != 0) {
/* no USB-Mezzanine board found */
musb_close(usb_interface);
} else {
usb_interface->usb_type = 1; // USB 1.1
fBoard[fNumberOfBoards] = new DRSBoard(usb_interface, usb_slot++);
if (!fBoard[fNumberOfBoards]->HasCorrectFirmware())
sprintf(fError, "Wrong firmware version: board has %d, required is %d. Board may not work correctly.\n",
fBoard[fNumberOfBoards]->GetFirmwareVersion(),
fBoard[fNumberOfBoards]->GetRequiredFirmwareVersion());
fNumberOfBoards++;
found = 1;
one_found = 1;
}
}
 
/* check for DRS4 evaluation board */
if (musb_open(&usb_interface, 0x04B4, 0x1175, index, 1, 0) == MUSB_SUCCESS) {
 
/* check ID */
if (musb_get_device(usb_interface) != 1) {
/* no DRS evaluation board found */
musb_close(usb_interface);
} else {
 
/* drain any data from Cy7C68013 FIFO if FPGA startup caused erratic write */
do {
i = musb_read(usb_interface, 8, buffer, sizeof(buffer), 100);
if (i > 0)
printf("%d bytes stuck in buffer\n", i);
} while (i > 0);
 
usb_interface->usb_type = 2; // USB 2.0
fBoard[fNumberOfBoards] = new DRSBoard(usb_interface, usb_slot++);
if (!fBoard[fNumberOfBoards]->HasCorrectFirmware())
sprintf(fError, "Wrong firmware version: board has %d, required is %d. Board may not work correctly.\n",
fBoard[fNumberOfBoards]->GetFirmwareVersion(),
fBoard[fNumberOfBoards]->GetRequiredFirmwareVersion());
fNumberOfBoards++;
found = 1;
one_found = 1;
}
}
 
if (!found) {
if (!one_found)
printf("USB successfully scanned, but no boards found\n");
break;
}
}
#endif // HAVE_USB
 
return;
}
 
/*------------------------------------------------------------------*/
 
DRS::~DRS()
{
int i;
for (i = 0; i < fNumberOfBoards; i++) {
delete fBoard[i];
}
 
#ifdef HAVE_USB
if (usb2_buffer) {
free(usb2_buffer);
usb2_buffer = NULL;
}
#endif
 
#ifdef HAVE_VME
mvme_close(fVmeInterface);
#endif
}
 
/*------------------------------------------------------------------*/
 
void DRS::SortBoards()
{
/* sort boards according to serial number (simple bubble sort) */
for (int i=0 ; i<fNumberOfBoards-1 ; i++) {
for (int j=i+1 ; j<fNumberOfBoards ; j++) {
if (fBoard[i]->GetBoardSerialNumber() < fBoard[j]->GetBoardSerialNumber()) {
DRSBoard* b = fBoard[i];
fBoard[i] = fBoard[j];
fBoard[j] = b;
}
}
}
}
 
/*------------------------------------------------------------------*/
 
void DRS::SetBoard(int i, DRSBoard *b)
{
fBoard[i] = b;
}
 
/*------------------------------------------------------------------*/
 
bool DRS::GetError(char *str, int size)
{
if (fError[0])
strlcpy(str, fError, size);
 
return fError[0] > 0;
}
 
/*------------------------------------------------------------------*/
 
#ifdef HAVE_USB
DRSBoard::DRSBoard(MUSB_INTERFACE * musb_interface, int usb_slot)
: fDAC_COFSA(0)
, fDAC_COFSB(0)
, fDAC_DRA(0)
, fDAC_DSA(0)
, fDAC_TLEVEL(0)
, fDAC_ACALIB(0)
, fDAC_DSB(0)
, fDAC_DRB(0)
, fDAC_COFS(0)
, fDAC_ADCOFS(0)
, fDAC_CLKOFS(0)
, fDAC_ROFS_1(0)
, fDAC_ROFS_2(0)
, fDAC_INOFS(0)
, fDAC_BIAS(0)
, fDRSType(0)
, fBoardType(0)
, fRequiredFirmwareVersion(0)
, fFirmwareVersion(0)
, fBoardSerialNumber(0)
, fHasMultiBuffer(0)
, fCtrlBits(0)
, fNumberOfReadoutChannels(0)
, fReadoutChannelConfig(0)
, fADCClkPhase(0)
, fADCClkInvert(0)
, fExternalClockFrequency(0)
, fUsbInterface(musb_interface)
#ifdef HAVE_VME
, fVmeInterface(0)
, fBaseAddress(0)
#endif
, fSlotNumber(usb_slot)
, fNominalFrequency(0)
, fMultiBuffer(0)
, fDominoMode(0)
, fDominoActive(0)
, fChannelConfig(0)
, fChannelCascading(1)
, fChannelDepth(1024)
, fWSRLoop(0)
, fReadoutMode(0)
, fReadPointer(0)
, fNMultiBuffer(0)
, fTriggerEnable1(0)
, fTriggerEnable2(0)
, fTriggerSource(0)
, fTriggerDelay(0)
, fTriggerDelayNs(0)
, fSyncDelay(0)
, fDelayedStart(0)
, fTranspMode(0)
, fDecimation(0)
, fRange(0)
, fCommonMode(0.8)
, fAcalMode(0)
, fAcalVolt(0)
, fTcalFreq(0)
, fTcalLevel(0)
, fTcalPhase(0)
, fTcalSource(0)
, fRefclk(0)
, fMaxChips(0)
, fResponseCalibration(0)
, fVoltageCalibrationValid(false)
, fCellCalibratedRange(0)
, fCellCalibratedTemperature(0)
, fTimeData(0)
, fNumberOfTimeData(0)
, fDebug(0)
, fTriggerStartBin(0)
{
if (musb_interface->usb_type == 1)
fTransport = TR_USB;
else
fTransport = TR_USB2;
memset(fStopCell, 0, sizeof(fStopCell));
memset(fStopWSR, 0, sizeof(fStopWSR));
fTriggerBus = 0;
ConstructBoard();
}
 
#endif
 
#ifdef HAVE_VME
/*------------------------------------------------------------------*/
 
DRSBoard::DRSBoard(MVME_INTERFACE * mvme_interface, mvme_addr_t base_address, int slot_number)
:fDAC_COFSA(0)
, fDAC_COFSB(0)
, fDAC_DRA(0)
, fDAC_DSA(0)
, fDAC_TLEVEL(0)
, fDAC_ACALIB(0)
, fDAC_DSB(0)
, fDAC_DRB(0)
, fDAC_COFS(0)
, fDAC_ADCOFS(0)
, fDAC_CLKOFS(0)
, fDAC_ROFS_1(0)
, fDAC_ROFS_2(0)
, fDAC_INOFS(0)
, fDAC_BIAS(0)
, fDRSType(0)
, fBoardType(0)
, fRequiredFirmwareVersion(0)
, fFirmwareVersion(0)
, fBoardSerialNumber(0)
, fHasMultiBuffer(0)
, fTransport(TR_VME)
, fCtrlBits(0)
, fNumberOfReadoutChannels(0)
, fReadoutChannelConfig(0)
, fADCClkPhase(0)
, fADCClkInvert(0)
, fExternalClockFrequency(0)
#ifdef HAVE_USB
, fUsbInterface(0)
#endif
#ifdef HAVE_VME
, fVmeInterface(mvme_interface)
, fBaseAddress(base_address)
, fSlotNumber(slot_number)
#endif
, fNominalFrequency(0)
, fRefClock(0)
, fMultiBuffer(0)
, fDominoMode(1)
, fDominoActive(1)
, fChannelConfig(0)
, fChannelCascading(1)
, fChannelDepth(1024)
, fWSRLoop(1)
, fReadoutMode(0)
, fReadPointer(0)
, fNMultiBuffer(0)
, fTriggerEnable1(0)
, fTriggerEnable2(0)
, fTriggerSource(0)
, fTriggerDelay(0)
, fTriggerDelayNs(0)
, fSyncDelay(0)
, fDelayedStart(0)
, fTranspMode(0)
, fDecimation(0)
, fRange(0)
, fCommonMode(0.8)
, fAcalMode(0)
, fAcalVolt(0)
, fTcalFreq(0)
, fTcalLevel(0)
, fTcalPhase(0)
, fTcalSource(0)
, fRefclk(0)
, fMaxChips(0)
, fResponseCalibration(0)
, fTimeData(0)
, fNumberOfTimeData(0)
, fDebug(0)
, fTriggerStartBin(0)
{
ConstructBoard();
}
 
#endif
 
/*------------------------------------------------------------------*/
 
DRSBoard::~DRSBoard()
{
int i;
#ifdef HAVE_USB
if (fTransport == TR_USB || fTransport == TR_USB2)
musb_close(fUsbInterface);
#endif
 
#ifdef USE_DRS_MUTEX
if (s_drsMutex)
delete s_drsMutex;
s_drsMutex = NULL;
#endif
 
// Response Calibration
delete fResponseCalibration;
 
// Time Calibration
for (i = 0; i < fNumberOfTimeData; i++) {
delete fTimeData[i];
}
delete[]fTimeData;
}
 
/*------------------------------------------------------------------*/
 
void DRSBoard::ConstructBoard()
{
unsigned char buffer[2];
unsigned int bits;
 
fDebug = 0;
fWSRLoop = 1;
fCtrlBits = 0;
 
fExternalClockFrequency = 1000. / 30.;
strcpy(fCalibDirectory, ".");
 
/* check board communication */
if (Read(T_STATUS, buffer, REG_MAGIC, 2) < 0) {
InitFPGA();
if (Read(T_STATUS, buffer, REG_MAGIC, 2) < 0)
return;
}
 
ReadSerialNumber();
 
/* set correct reference clock */
if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9)
fRefClock = 60;
else
fRefClock = 33;
 
/* get mode from hardware */
bits = GetCtrlReg();
fMultiBuffer = (bits & BIT_MULTI_BUFFER) > 0;
fNMultiBuffer = 0;
if (fHasMultiBuffer && fMultiBuffer)
fNMultiBuffer = 3;
if (fDRSType == 4) {
fDominoMode = (bits & BIT_CONFIG_DMODE) > 0;
} else {
fDominoMode = (bits & BIT_DMODE) > 0;
}
fTriggerEnable1 = (bits & BIT_ENABLE_TRIGGER1) > 0;
fTriggerEnable2 = (bits & BIT_ENABLE_TRIGGER2) > 0;
fTriggerSource = ((bits & BIT_TR_SOURCE1) > 0) | (((bits & BIT_TR_SOURCE2) > 0) << 1);
fReadoutMode = (bits & BIT_READOUT_MODE) > 0;
Read(T_CTRL, &fReadPointer, REG_READ_POINTER, 2);
fADCClkInvert = (bits & BIT_ADCCLK_INVERT) > 0;
fDominoActive = (bits & BIT_DACTIVE) > 0;
ReadFrequency(0, &fNominalFrequency);
if (fNominalFrequency < 0.1 || fNominalFrequency > 6)
fNominalFrequency = 1;
 
/* initialize number of channels */
if (fDRSType == 4) {
if (fBoardType == 6) {
unsigned short d;
Read(T_CTRL, &d, REG_CHANNEL_MODE, 2);
fReadoutChannelConfig = d & 0xFF;
if (d == 7)
fNumberOfReadoutChannels = 9;
else
fNumberOfReadoutChannels = 5;
} else
fNumberOfReadoutChannels = 9;
} else
fNumberOfReadoutChannels = 10;
 
if (fBoardType == 1) {
fDAC_COFSA = 0;
fDAC_COFSB = 1;
fDAC_DRA = 2;
fDAC_DSA = 3;
fDAC_TLEVEL = 4;
fDAC_ACALIB = 5;
fDAC_DSB = 6;
fDAC_DRB = 7;
} else if (fBoardType == 2 || fBoardType == 3) {
fDAC_COFS = 0;
fDAC_DSA = 1;
fDAC_DSB = 2;
fDAC_TLEVEL = 3;
fDAC_CLKOFS = 5;
fDAC_ACALIB = 6;
fDAC_ADCOFS = 7;
} else if (fBoardType == 4) {
fDAC_ROFS_1 = 0;
fDAC_DSA = 1;
fDAC_DSB = 2;
fDAC_ROFS_2 = 3;
fDAC_BIAS = 4;
fDAC_INOFS = 5;
fDAC_ACALIB = 6;
fDAC_ADCOFS = 7;
} else if (fBoardType == 5) {
fDAC_ROFS_1 = 0;
fDAC_CMOFS = 1;
fDAC_CALN = 2;
fDAC_CALP = 3;
fDAC_BIAS = 4;
fDAC_TLEVEL = 5;
fDAC_ONOFS = 6;
} else if (fBoardType == 6) {
fDAC_ONOFS = 0;
fDAC_CMOFSP = 1;
fDAC_CALN = 2;
fDAC_CALP = 3;
fDAC_CMOFSN = 5;
fDAC_ROFS_1 = 6;
fDAC_BIAS = 7;
} else if (fBoardType == 7) {
fDAC_ROFS_1 = 0;
fDAC_CMOFS = 1;
fDAC_CALN = 2;
fDAC_CALP = 3;
fDAC_BIAS = 4;
fDAC_TLEVEL = 5;
fDAC_ONOFS = 6;
} else if (fBoardType == 8 || fBoardType == 9) {
fDAC_ROFS_1 = 0;
fDAC_TLEVEL4 = 1;
fDAC_CALN = 2;
fDAC_CALP = 3;
fDAC_BIAS = 4;
fDAC_TLEVEL1 = 5;
fDAC_TLEVEL2 = 6;
fDAC_TLEVEL3 = 7;
}
if (fDRSType < 4) {
// Response Calibration
fResponseCalibration = new ResponseCalibration(this);
 
// Time Calibration
fTimeData = new DRSBoard::TimeData *[kNumberOfChipsMax];
fNumberOfTimeData = 0;
}
}
 
/*------------------------------------------------------------------*/
 
void DRSBoard::ReadSerialNumber()
{
unsigned char buffer[2];
int number;
 
// check magic number
if (Read(T_STATUS, buffer, REG_MAGIC, 2) < 0) {
printf("Cannot read from board\n");
return;
}
 
number = (static_cast < int >(buffer[1]) << 8) +buffer[0];
if (number != 0xC0DE) {
printf("Invalid magic number: %04X\n", number);
return;
}
// read board type
Read(T_STATUS, buffer, REG_BOARD_TYPE, 2);
fDRSType = buffer[0];
fBoardType = buffer[1];
 
// read firmware version
Read(T_STATUS, buffer, REG_VERSION_FW, 2);
fFirmwareVersion = (static_cast < int >(buffer[1]) << 8) +buffer[0];
 
// retrieve board serial number
Read(T_STATUS, buffer, REG_SERIAL_BOARD, 2);
number = (static_cast < int >(buffer[1]) << 8) +buffer[0];
fBoardSerialNumber = number;
 
// determine DRS type and board type for old boards from setial number
if (fBoardType == 0) {
// determine board version from serial number
if (number >= 2000 && number < 5000) {
fBoardType = 6;
fDRSType = 4;
} else if (number >= 1000) {
fBoardType = 4;
fDRSType = 3;
} else if (number >= 100)
fBoardType = 3;
else if (number > 0)
fBoardType = 2;
else {
fBoardType = 3;
fDRSType = 2;
fRequiredFirmwareVersion = REQUIRED_FIRMWARE_VERSION_DRS2;
}
}
 
// set constants according to board type
if (fBoardType == 6)
fNumberOfChips = 4;
else
fNumberOfChips = 1;
 
if (fDRSType == 4)
fNumberOfChannels = 9;
else
fNumberOfChannels = 10;
 
// retrieve firmware version
if (fDRSType == 2)
fRequiredFirmwareVersion = REQUIRED_FIRMWARE_VERSION_DRS2;
if (fDRSType == 3)
fRequiredFirmwareVersion = REQUIRED_FIRMWARE_VERSION_DRS3;
if (fDRSType == 4)
fRequiredFirmwareVersion = REQUIRED_FIRMWARE_VERSION_DRS4;
 
fHasMultiBuffer = ((fBoardType == 6) && fTransport == TR_VME);
}
 
/*------------------------------------------------------------------*/
 
void DRSBoard::ReadCalibration(void)
{
unsigned short buf[1024*16]; // 32 kB
int i, j, chip;
 
fVoltageCalibrationValid = false;
fTimingCalibratedFrequency = 0;
 
memset(fCellOffset, 0, sizeof(fCellOffset));
memset(fCellGain, 0, sizeof(fCellGain));
memset(fCellOffset2, 0, sizeof(fCellOffset2));
memset(fCellDT, 0, sizeof(fCellDT));
 
/* read offsets and gain from eeprom */
if (fBoardType == 9) {
memset(buf, 0, sizeof(buf));
ReadEEPROM(0, buf, 4096);
/* check voltage calibration method */
if ((buf[2] & 0xFF) == VCALIB_METHOD)
fVoltageCalibrationValid = true;
else {
fCellCalibratedRange = 0;
fCellCalibratedTemperature = -100;
return;
}
/* check timing calibration method */
if ((buf[2] >> 8) == TCALIB_METHOD) {
float fl; // float from two 16-bit integers
memcpy(&fl, &buf[8], sizeof(float));
fTimingCalibratedFrequency = fl;
} else
fTimingCalibratedFrequency = -1;
fCellCalibratedRange = ((int) (buf[10] & 0xFF)) / 100.0; // -50 ... +50 => -0.5 V ... +0.5 V
fCellCalibratedTemperature = (buf[10] >> 8) / 2.0;
ReadEEPROM(1, buf, 1024*32);
for (i=0 ; i<8 ; i++)
for (j=0 ; j<1024; j++) {
fCellOffset[i][j] = buf[(i*1024+j)*2];
fCellGain[i][j] = buf[(i*1024+j)*2 + 1]/65535.0*0.4+0.7;
}
ReadEEPROM(2, buf, 1024*32);
for (i=0 ; i<8 ; i++)
for (j=0 ; j<1024; j++)
fCellOffset2[i][j] = buf[(i*1024+j)*2];
} else if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8) {
memset(buf, 0, sizeof(buf));
ReadEEPROM(0, buf, 32);
 
/* check voltage calibration method */
if ((buf[2] & 0xFF) == VCALIB_METHOD_V4) // board < 9 has "1", board 9 has "2"
fVoltageCalibrationValid = true;
else {
fCellCalibratedRange = 0;
return;
}
fCellCalibratedTemperature = -100;
 
/* check timing calibration method */
if ((buf[4] & 0xFF) == TCALIB_METHOD_V4) { // board < 9 has "1", board 9 has "2"
fTimingCalibratedFrequency = buf[6] / 1000.0;
} else
fTimingCalibratedFrequency = -1;
 
fCellCalibratedRange = ((int) (buf[2] >> 8)) / 100.0; // -50 ... +50 => -0.5 V ... +0.5 V
ReadEEPROM(1, buf, 1024*32);
for (i=0 ; i<8 ; i++)
for (j=0 ; j<1024; j++) {
fCellOffset[i][j] = buf[(i*1024+j)*2];
fCellGain[i][j] = buf[(i*1024+j)*2 + 1]/65535.0*0.4+0.7;
}
 
ReadEEPROM(2, buf, 1024*5*4);
for (i=0 ; i<1 ; i++)
for (j=0 ; j<1024; j++) {
fCellOffset[i+8][j] = buf[(i*1024+j)*2];
fCellGain[i+8][j] = buf[(i*1024+j)*2 + 1]/65535.0*0.4+0.7;
}
 
for (i=0 ; i<4 ; i++)
for (j=0 ; j<1024; j++) {
fCellOffset2[i*2][j] = buf[2*1024+(i*1024+j)*2];
fCellOffset2[i*2+1][j] = buf[2*1024+(i*1024+j)*2+1];
}
 
} else if (fBoardType == 6) {
ReadEEPROM(0, buf, 16);
 
/* check voltage calibration method */
if ((buf[2] & 0xFF) == VCALIB_METHOD)
fVoltageCalibrationValid = true;
else {
fCellCalibratedRange = 0;
return;
}
 
/* check timing calibration method */
if ((buf[4] & 0xFF) == TCALIB_METHOD)
fTimingCalibratedFrequency = buf[6] / 1000.0; // 0 ... 6000 => 0 ... 6 GHz
else
fTimingCalibratedFrequency = 0;
 
fCellCalibratedRange = ((int) (buf[2] >> 8)) / 100.0; // -50 ... +50 => -0.5 V ... +0.5 V
 
for (chip=0 ; chip<4 ; chip++) {
ReadEEPROM(1+chip, buf, 1024*32);
for (i=0 ; i<8 ; i++)
for (j=0 ; j<1024; j++) {
fCellOffset[i+chip*9][j] = buf[(i*1024+j)*2];
fCellGain[i+chip*9][j] = buf[(i*1024+j)*2 + 1]/65535.0*0.4+0.7;
}
}
 
ReadEEPROM(5, buf, 1024*4*4);
for (chip=0 ; chip<4 ; chip++)
for (j=0 ; j<1024; j++) {
fCellOffset[8+chip*9][j] = buf[j*2+chip*0x0800];
fCellGain[8+chip*9][j] = buf[j*2+1+chip*0x0800]/65535.0*0.4+0.7;
}
 
ReadEEPROM(7, buf, 1024*32);
for (i=0 ; i<8 ; i++) {
for (j=0 ; j<1024; j++) {
fCellOffset2[i][j] = buf[i*0x800 + j*2];
fCellOffset2[i+9][j] = buf[i*0x800 + j*2+1];
}
}
 
ReadEEPROM(8, buf, 1024*32);
for (i=0 ; i<8 ; i++) {
for (j=0 ; j<1024; j++) {
fCellOffset2[i+18][j] = buf[i*0x800 + j*2];
fCellOffset2[i+27][j] = buf[i*0x800 + j*2+1];
}
}
 
} else
return;
 
/* read timing calibration from eeprom */
if (fBoardType == 9) {
if (fTimingCalibratedFrequency == 0) {
for (i=0 ; i<8 ; i++)
for (j=0 ; j<1024 ; j++) {
fCellDT[0][i][j] = 1/fNominalFrequency;
}
} else {
ReadEEPROM(2, buf, 1024*32);
for (i=0 ; i<8 ; i++)
for (j=0 ; j<1024; j++) {
fCellDT[0][i][j] = (buf[(i*1024+j)*2+1] - 1000) / 10000.0;
}
}
} else if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8) {
if (fTimingCalibratedFrequency == 0) {
for (i=0 ; i<1024 ; i++)
fCellDT[0][0][i] = 1/fNominalFrequency;
} else {
ReadEEPROM(0, buf, 1024*sizeof(short)*2);
for (i=0 ; i<8 ; i++) {
for (j=0 ; j<1024; j++) {
// use calibration for all channels
fCellDT[0][i][j] = buf[j*2+1]/10000.0;
}
}
}
} else if (fBoardType == 6) {
if (fTimingCalibratedFrequency == 0) {
for (i=0 ; i<1024 ; i++)
for (j=0 ; j<4 ; j++)
fCellDT[0][j][i] = 1/fNominalFrequency;
} else {
ReadEEPROM(6, buf, 1024*sizeof(short)*4);
for (i=0 ; i<1024; i++) {
fCellDT[0][0][i] = buf[i*2]/10000.0;
fCellDT[1][0][i] = buf[i*2+1]/10000.0;
fCellDT[2][0][i] = buf[i*2+0x800]/10000.0;
fCellDT[3][0][i] = buf[i*2+0x800+1]/10000.0;
}
}
}
#if 0
/* Read Daniel's file */
int fh = open("cal_ch2.dat", O_RDONLY);
float v;
read(fh, &v, sizeof(float));
for (i=0 ; i<1024 ; i++) {
read(fh, &v, sizeof(float));
fCellDT[0][2][(i+0) % 1024] = v;
}
close(fh);
fh = open("cal_ch4.dat", O_RDONLY);
read(fh, &v, sizeof(float));
for (i=0 ; i<1024 ; i++) {
read(fh, &v, sizeof(float));
fCellDT[0][6][(i+0)%1024] = v;
}
close(fh);
#endif
 
#if 0
/* write timing calibration to EEPROM page 0 */
double t1, t2;
ReadEEPROM(0, buf, sizeof(buf));
for (i=0,t1=0 ; i<1024; i++) {
t2 = fCellT[0][i] - t1;
t2 = (unsigned short) (t2 * 10000 + 0.5);
t1 += t2 / 10000.0;
buf[i*2+1] = (unsigned short) t2;
}
/* write calibration method and frequency */
buf[4] = TCALIB_METHOD;
buf[6] = (unsigned short) (fNominalFrequency * 1000 + 0.5);
fTimingCalibratedFrequency = buf[6] / 1000.0;
WriteEEPROM(0, buf, sizeof(buf));
#endif
}
 
/*------------------------------------------------------------------*/
 
bool DRSBoard::HasCorrectFirmware()
{
/* check for required firmware version */
return (fFirmwareVersion >= fRequiredFirmwareVersion);
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::InitFPGA(void)
{
 
#ifdef HAVE_USB
if (fTransport == TR_USB2) {
unsigned char buffer[1];
int i, status;
 
/* blink Cy7C68013A LED and issue an FPGA reset */
buffer[0] = 0; // LED off
musb_write(fUsbInterface, 1, buffer, 1, 100);
Sleep(50);
 
buffer[0] = 1; // LED on
musb_write(fUsbInterface, 1, buffer, 1, 100);
 
/* wait until EEPROM page #0 has been read */
for (i=0 ; i<100 ; i++) {
Read(T_STATUS, &status, REG_STATUS, 4);
if ((status & BIT_SERIAL_BUSY) == 0)
break;
Sleep(10);
}
}
#endif
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
/* Generic read function accessing VME or USB */
 
int DRSBoard::Write(int type, unsigned int addr, void *data, int size)
{
#ifdef USE_DRS_MUTEX
if (!s_drsMutex) {
s_drsMutex = new wxMutex();
assert(s_drsMutex);
}
s_drsMutex->Lock();
#endif
 
if (fTransport == TR_VME) {
 
#ifdef HAVE_VME
unsigned int base_addr;
 
base_addr = fBaseAddress;
 
if (type == T_CTRL)
base_addr += PMC_CTRL_OFFSET;
else if (type == T_STATUS)
base_addr += PMC_STATUS_OFFSET;
else if (type == T_RAM)
base_addr += PMC_RAM_OFFSET;
 
if (size == 1) {
/* 8-bit write access */
mvme_set_dmode(fVmeInterface, MVME_DMODE_D8);
mvme_write(fVmeInterface, base_addr + addr, static_cast < mvme_locaddr_t * >(data), size);
} else if (size == 2) {
/* 16-bit write access */
mvme_set_dmode(fVmeInterface, MVME_DMODE_D16);
mvme_write(fVmeInterface, base_addr + addr, static_cast < mvme_locaddr_t * >(data), size);
} else {
mvme_set_dmode(fVmeInterface, MVME_DMODE_D32);
 
/* as long as no block transfer is supported, do pseudo block transfer */
mvme_set_blt(fVmeInterface, MVME_BLT_NONE);
 
mvme_write(fVmeInterface, base_addr + addr, static_cast < mvme_locaddr_t * >(data), size);
}
 
#ifdef USE_DRS_MUTEX
s_drsMutex->Unlock();
#endif
return size;
#endif // HAVE_VME
 
} else if (fTransport == TR_USB) {
#ifdef HAVE_USB
unsigned char buffer[64], ack;
unsigned int base_addr;
int i, j, n;
 
if (type == T_CTRL)
base_addr = USB_CTRL_OFFSET;
else if (type == T_STATUS)
base_addr = USB_STATUS_OFFSET;
else if (type == T_RAM)
base_addr = USB_RAM_OFFSET;
else
base_addr = 0;
 
if (type != T_RAM) {
 
/*---- register access ----*/
 
if (size == 2) {
/* word swapping: first 16 bit sit at upper address */
if ((addr % 4) == 0)
addr = addr + 2;
else
addr = addr - 2;
}
 
buffer[0] = USB_CMD_WRITE;
buffer[1] = base_addr + addr;
buffer[2] = size;
 
for (i = 0; i < size; i++)
buffer[3 + i] = *((unsigned char *) data + i);
 
/* try 10 times */
ack = 0;
for (i = 0; i < 10; i++) {
n = musb_write(fUsbInterface, 2, buffer, 3 + size, USB_TIMEOUT);
if (n == 3 + size) {
for (j = 0; j < 10; j++) {
/* wait for acknowledge */
n = musb_read(fUsbInterface, 1, &ack, 1, USB_TIMEOUT);
if (n == 1 && ack == 1)
break;
 
printf("Redo receive\n");
}
}
 
if (ack == 1) {
#ifdef USE_DRS_MUTEX
s_drsMutex->Unlock();
#endif
return size;
}
 
printf("Redo send\n");
}
} else {
 
/*---- RAM access ----*/
 
buffer[0] = USB_CMD_ADDR;
buffer[1] = base_addr + addr;
musb_write(fUsbInterface, 2, buffer, 2, USB_TIMEOUT);
 
/* chop buffer into 60-byte packets */
for (i = 0; i <= (size - 1) / 60; i++) {
n = size - i * 60;
if (n > 60)
n = 60;
buffer[0] = USB_CMD_WRITE12;
buffer[1] = n;
 
for (j = 0; j < n; j++)
buffer[2 + j] = *((unsigned char *) data + j + i * 60);
 
musb_write(fUsbInterface, 2, buffer, 2 + n, USB_TIMEOUT);
 
for (j = 0; j < 10; j++) {
/* wait for acknowledge */
n = musb_read(fUsbInterface, 1, &ack, 1, USB_TIMEOUT);
if (n == 1 && ack == 1)
break;
 
printf("Redo receive acknowledge\n");
}
}
 
#ifdef USE_DRS_MUTEX
s_drsMutex->Unlock();
#endif
return size;
}
#endif // HAVE_USB
} else if (fTransport == TR_USB2) {
#ifdef HAVE_USB
unsigned int base_addr;
int i;
 
if (usb2_buffer == NULL)
usb2_buffer = (unsigned char *) malloc(USB2_BUFFER_SIZE);
assert(usb2_buffer);
 
/* only accept even address and number of bytes */
assert(addr % 2 == 0);
assert(size % 2 == 0);
 
/* check for maximum size */
assert(size <= USB2_BUFFER_SIZE - 10);
 
if (type == T_CTRL)
base_addr = USB2_CTRL_OFFSET;
else if (type == T_STATUS)
base_addr = USB2_STATUS_OFFSET;
else if (type == T_FIFO)
base_addr = USB2_FIFO_OFFSET;
else if (type == T_RAM)
base_addr = USB2_RAM_OFFSET;
else
base_addr = 0;
 
if (type != T_RAM && size == 2) {
/* word swapping: first 16 bit sit at upper address */
if ((addr % 4) == 0)
addr = addr + 2;
else
addr = addr - 2;
}
 
addr += base_addr;
 
usb2_buffer[0] = USB2_CMD_WRITE;
usb2_buffer[1] = 0;
 
usb2_buffer[2] = (addr >> 0) & 0xFF;
usb2_buffer[3] = (addr >> 8) & 0xFF;
usb2_buffer[4] = (addr >> 16) & 0xFF;
usb2_buffer[5] = (addr >> 24) & 0xFF;
 
usb2_buffer[6] = (size >> 0) & 0xFF;
usb2_buffer[7] = (size >> 8) & 0xFF;
usb2_buffer[8] = (size >> 16) & 0xFF;
usb2_buffer[9] = (size >> 24) & 0xFF;
 
for (i = 0; i < size; i++)
usb2_buffer[10 + i] = *((unsigned char *) data + i);
 
i = musb_write(fUsbInterface, 4, usb2_buffer, 10 + size, USB_TIMEOUT);
if (i != 10 + size)
printf("musb_write error: %d\n", i);
 
#ifdef USE_DRS_MUTEX
s_drsMutex->Unlock();
#endif
return i;
#endif // HAVE_USB
}
 
#ifdef USE_DRS_MUTEX
s_drsMutex->Unlock();
#endif
return 0;
}
 
/*------------------------------------------------------------------*/
 
/* Generic read function accessing VME or USB */
 
int DRSBoard::Read(int type, void *data, unsigned int addr, int size)
{
#ifdef USE_DRS_MUTEX
if (!s_drsMutex) {
s_drsMutex = new wxMutex();
assert(s_drsMutex);
}
s_drsMutex->Lock();
#endif
 
memset(data, 0, size);
if (fTransport == TR_VME) {
 
#ifdef HAVE_VME
unsigned int base_addr;
int n, i;
 
base_addr = fBaseAddress;
 
if (type == T_CTRL)
base_addr += PMC_CTRL_OFFSET;
else if (type == T_STATUS)
base_addr += PMC_STATUS_OFFSET;
else if (type == T_RAM)
base_addr += PMC_RAM_OFFSET;
else if (type == T_FIFO)
base_addr += PMC_FIFO_OFFSET;
 
mvme_set_dmode(fVmeInterface, MVME_DMODE_D32);
 
n = 0;
if (size == 1) {
/* 8-bit read access */
mvme_set_dmode(fVmeInterface, MVME_DMODE_D8);
n = mvme_read(fVmeInterface, static_cast < mvme_locaddr_t * >(data), base_addr + addr, size);
} else if (size == 2) {
/* 16-bit read access */
mvme_set_dmode(fVmeInterface, MVME_DMODE_D16);
n = mvme_read(fVmeInterface, static_cast < mvme_locaddr_t * >(data), base_addr + addr, size);
} else {
mvme_set_dmode(fVmeInterface, MVME_DMODE_D32);
 
//mvme_set_blt(fVmeInterface, MVME_BLT_NONE); // pseudo block transfer
mvme_set_blt(fVmeInterface, MVME_BLT_2EVME); // 2eVME if implemented
n = mvme_read(fVmeInterface, static_cast < mvme_locaddr_t * >(data), base_addr + addr, size);
while (n != size) {
printf("Only read %d out of %d, retry with %d: ", n, size, size - n);
i = mvme_read(fVmeInterface, static_cast < mvme_locaddr_t * >(data) + n / 4, base_addr + addr + n,
size - n);
printf("read %d\n", i);
if (i == 0) {
printf("Error reading VME\n");
return n;
}
n += i;
}
 
//for (i = 0; i < size; i += 4)
// mvme_read(fVmeInterface, (mvme_locaddr_t *)((char *)data+i), base_addr + addr+i, 4);
}
 
#ifdef USE_DRS_MUTEX
s_drsMutex->Unlock();
#endif
 
return n;
 
#endif // HAVE_VME
} else if (fTransport == TR_USB) {
#ifdef HAVE_USB
unsigned char buffer[64];
unsigned int base_addr;
int i, j, ret, n;
 
if (type == T_CTRL)
base_addr = USB_CTRL_OFFSET;
else if (type == T_STATUS)
base_addr = USB_STATUS_OFFSET;
else if (type == T_RAM)
base_addr = USB_RAM_OFFSET;
else
assert(0); // FIFO not implemented
 
if (type != T_RAM) {
 
/*---- register access ----*/
 
if (size == 2) {
/* word swapping: first 16 bit sit at uppder address */
if ((addr % 4) == 0)
addr = addr + 2;
else
addr = addr - 2;
}
 
buffer[0] = USB_CMD_READ;
buffer[1] = base_addr + addr;
buffer[2] = size;
 
musb_write(fUsbInterface, 2, buffer, 2 + size, USB_TIMEOUT);
i = musb_read(fUsbInterface, 1, data, size, USB_TIMEOUT);
 
#ifdef USE_DRS_MUTEX
s_drsMutex->Unlock();
#endif
if (i != size)
return 0;
 
return size;
} else {
 
/*---- RAM access ----*/
 
/* in RAM mode, only the 2048-byte page can be selected */
buffer[0] = USB_CMD_ADDR;
buffer[1] = base_addr + (addr >> 11);
musb_write(fUsbInterface, 2, buffer, 2, USB_TIMEOUT);
 
/* receive data in 60-byte packets */
for (i = 0; i <= (size - 1) / 60; i++) {
n = size - i * 60;
if (n > 60)
n = 60;
buffer[0] = USB_CMD_READ12;
buffer[1] = n;
musb_write(fUsbInterface, 2, buffer, 2, USB_TIMEOUT);
 
ret = musb_read(fUsbInterface, 1, buffer, n, USB_TIMEOUT);
 
if (ret != n) {
/* try again */
ret = musb_read(fUsbInterface, 1, buffer, n, USB_TIMEOUT);
if (ret != n) {
#ifdef USE_DRS_MUTEX
s_drsMutex->Unlock();
#endif
return 0;
}
}
 
for (j = 0; j < ret; j++)
*((unsigned char *) data + j + i * 60) = buffer[j];
}
 
#ifdef USE_DRS_MUTEX
s_drsMutex->Unlock();
#endif
return size;
}
#endif // HAVE_USB
} else if (fTransport == TR_USB2) {
#ifdef HAVE_USB
unsigned char buffer[10];
unsigned int base_addr;
int i;
 
/* only accept even address and number of bytes */
assert(addr % 2 == 0);
assert(size % 2 == 0);
 
/* check for maximum size */
assert(size <= USB2_BUFFER_SIZE - 10);
 
if (type == T_CTRL)
base_addr = USB2_CTRL_OFFSET;
else if (type == T_STATUS)
base_addr = USB2_STATUS_OFFSET;
else if (type == T_FIFO)
base_addr = USB2_FIFO_OFFSET;
else if (type == T_RAM)
base_addr = USB2_RAM_OFFSET;
else
base_addr = 0;
 
if (type != T_RAM && size == 2) {
/* word swapping: first 16 bit sit at upper address */
if ((addr % 4) == 0)
addr = addr + 2;
else
addr = addr - 2;
}
 
addr += base_addr;
 
buffer[0] = USB2_CMD_READ;
buffer[1] = 0;
 
buffer[2] = (addr >> 0) & 0xFF;
buffer[3] = (addr >> 8) & 0xFF;
buffer[4] = (addr >> 16) & 0xFF;
buffer[5] = (addr >> 24) & 0xFF;
 
buffer[6] = (size >> 0) & 0xFF;
buffer[7] = (size >> 8) & 0xFF;
buffer[8] = (size >> 16) & 0xFF;
buffer[9] = (size >> 24) & 0xFF;
 
i = musb_write(fUsbInterface, 4, buffer, 10, USB_TIMEOUT);
if (i != 10)
printf("musb_read error %d\n", i);
 
i = musb_read(fUsbInterface, 8, data, size, USB_TIMEOUT);
#ifdef USE_DRS_MUTEX
s_drsMutex->Unlock();
#endif
return i;
#endif // HAVE_USB
}
 
#ifdef USE_DRS_MUTEX
s_drsMutex->Unlock();
#endif
return 0;
}
 
/*------------------------------------------------------------------*/
 
void DRSBoard::SetLED(int state)
{
// Set LED state
if (state)
fCtrlBits |= BIT_LED;
else
fCtrlBits &= ~BIT_LED;
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetChannelConfig(int firstChannel, int lastChannel, int nConfigChannels)
{
unsigned short d;
 
if (lastChannel < 0 || lastChannel > 10) {
printf("Invalid number of channels: %d (must be between 0 and 10)\n", lastChannel);
return 0;
}
 
// Set number of channels
if (fDRSType == 2) {
// register must contain last channel to read out starting from 9
d = 9 - lastChannel;
Write(T_CTRL, REG_CHANNEL_CONFIG, &d, 2);
} else if (fDRSType == 3) {
// upper four bits of register must contain last channel to read out starting from 9
d = (firstChannel << 4) | lastChannel;
Write(T_CTRL, REG_CHANNEL_MODE, &d, 2);
 
// set bit pattern for write shift register
switch (nConfigChannels) {
case 1:
d = 0x001;
break;
case 2:
d = 0x041;
break;
case 3:
d = 0x111;
break;
case 4:
d = 0x249;
break;
case 6:
d = 0x555;
break;
case 12:
d = 0xFFF;
break;
default:
printf("Invalid channel configuration\n");
return 0;
}
Write(T_CTRL, REG_CHANNEL_CONFIG, &d, 2);
} else if (fDRSType == 4) {
int oldMultiBuffer = fMultiBuffer;
 
// make sure FPGA state machine is idle
if (fHasMultiBuffer) {
SetMultiBuffer(0);
if (IsBusy()) {
SoftTrigger();
while (IsBusy());
}
}
 
if (fBoardType == 6) {
// determined channel readout mode A/C[even/odd], B/D[even/odd] or A/B/C/D
fReadoutChannelConfig = firstChannel;
Read(T_CTRL, &d, REG_CHANNEL_MODE, 2);
d = (d & 0xFF00) | firstChannel; // keep higher 8 bits which are ADClkPhase
Write(T_CTRL, REG_CHANNEL_MODE, &d, 2);
} else {
// upper four bits of register must contain last channel to read out starting from 9
Read(T_CTRL, &d, REG_CHANNEL_MODE, 2);
d = (d & 0xFF00) | (firstChannel << 4) | lastChannel; // keep higher 8 bits which are ADClkPhase
Write(T_CTRL, REG_CHANNEL_MODE, &d, 2);
}
 
// set bit pattern for write shift register
fChannelConfig = 0;
switch (nConfigChannels) {
case 1:
fChannelConfig = 0x01;
fChannelCascading = 8;
break;
case 2:
fChannelConfig = 0x11;
fChannelCascading = 4;
break;
case 4:
fChannelConfig = 0x55;
fChannelCascading = 2;
break;
case 8:
fChannelConfig = 0xFF;
fChannelCascading = 1;
break;
default:
printf("Invalid channel configuration\n");
return 0;
}
d = fChannelConfig | (fDominoMode << 8) | (1 << 9) | (fWSRLoop << 10) | (0xF8 << 8);
 
Write(T_CTRL, REG_CHANNEL_CONFIG, &d, 2);
 
fChannelDepth = fChannelCascading * (fDecimation ? kNumberOfBins/2 : kNumberOfBins);
 
if (fHasMultiBuffer && oldMultiBuffer) {
Reinit(); // set WP=0
SetMultiBuffer(oldMultiBuffer);
SetMultiBufferRP(0);
}
}
 
if (fBoardType == 6) {
if (fReadoutChannelConfig == 7)
fNumberOfReadoutChannels = 9;
else
fNumberOfReadoutChannels = 5;
} else {
fNumberOfReadoutChannels = lastChannel - firstChannel + 1;
}
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
void DRSBoard::SetNumberOfChannels(int nChannels)
{
SetChannelConfig(0, nChannels - 1, 12);
}
 
/*------------------------------------------------------------------*/
 
void DRSBoard::SetADCClkPhase(int phase, bool invert)
{
unsigned short d = 0;
 
/* Set the clock phase of the ADC via the variable phase shift
in the Xilinx DCM. One unit is equal to the clock period / 256,
so at 30 MHz this is about 130ps. The possible range at 30 MHz
is -87 ... +87 */
 
// keep lower 8 bits which are the channel mode
Read(T_CTRL, &d, REG_ADCCLK_PHASE, 2);
d = (d & 0x00FF) | (phase << 8);
Write(T_CTRL, REG_ADCCLK_PHASE, &d, 2);
 
if (invert)
fCtrlBits |= BIT_ADCCLK_INVERT;
else
fCtrlBits &= ~BIT_ADCCLK_INVERT;
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
 
fADCClkPhase = phase;
fADCClkInvert = invert;
}
 
/*------------------------------------------------------------------*/
 
void DRSBoard::SetWarmup(unsigned int microseconds)
{
/* Set the "warmup" time. When starting the domino wave, the DRS4
chip together with its power supply need some time to stabilize
before high resolution data can be taken (jumping baseline
problem). This sets the time in ticks of 900ns before triggers
are accepted */
 
unsigned short ticks;
 
if (microseconds == 0)
ticks = 0;
else
ticks = (unsigned short) (microseconds / 0.9 + 0.5) - 1;
Write(T_CTRL, REG_WARMUP, &ticks, 2);
}
 
/*------------------------------------------------------------------*/
 
void DRSBoard::SetCooldown(unsigned int microseconds)
{
/* Set the "cooldown" time. When stopping the domino wave, the
power supply needs some time to stabilize before high resolution
data can read out (slanted baseline problem). This sets the
time in ticks of 900 ns before the readout is started */
 
unsigned short ticks;
 
ticks = (unsigned short) (microseconds / 0.9 + 0.5) - 1;
Write(T_CTRL, REG_COOLDOWN, &ticks, 2);
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetDAC(unsigned char channel, double value)
{
// Set DAC value
unsigned short d;
 
/* normalize to 2.5V for 16 bit */
if (value < 0)
value = 0;
if (value > 2.5)
value = 2.5;
d = static_cast < unsigned short >(value / 2.5 * 0xFFFF + 0.5);
 
Write(T_CTRL, REG_DAC_OFS + (channel * 2), &d, 2);
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::ReadDAC(unsigned char channel, double *value)
{
// Readback DAC value from control register
unsigned char buffer[2];
 
/* map 0->1, 1->0, 2->3, 3->2, etc. */
//ofs = channel + 1 - 2*(channel % 2);
 
Read(T_CTRL, buffer, REG_DAC_OFS + (channel * 2), 2);
 
/* normalize to 2.5V for 16 bit */
*value = 2.5 * (buffer[0] + (buffer[1] << 8)) / 0xFFFF;
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::GetRegulationDAC(double *value)
{
// Get DAC value from status register (-> freq. regulation)
unsigned char buffer[2];
 
if (fBoardType == 1)
Read(T_STATUS, buffer, REG_RDAC3, 2);
else if (fBoardType == 2 || fBoardType == 3 || fBoardType == 4)
Read(T_STATUS, buffer, REG_RDAC1, 2);
else
memset(buffer, 0, sizeof(buffer));
 
/* normalize to 2.5V for 16 bit */
*value = 2.5 * (buffer[0] + (buffer[1] << 8)) / 0xFFFF;
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::StartDomino()
{
// Start domino sampling
fCtrlBits |= BIT_START_TRIG;
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
fCtrlBits &= ~BIT_START_TRIG;
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::Reinit()
{
// Stop domino sampling
// reset readout state machine
// reset FIFO counters
fCtrlBits |= BIT_REINIT_TRIG;
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
fCtrlBits &= ~BIT_REINIT_TRIG;
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::Init()
{
// Init FPGA on USB2 board
InitFPGA();
 
// Turn off multi-buffer mode to avoid immediate startup
SetMultiBuffer(0);
 
// Reinitialize
fCtrlBits |= BIT_REINIT_TRIG; // reset readout state machine
if (fDRSType == 2)
fCtrlBits &= ~BIT_FREQ_AUTO_ADJ; // turn auto. freq regul. off
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
fCtrlBits &= ~BIT_REINIT_TRIG;
 
if (fBoardType == 1) {
// set max. domino speed
SetDAC(fDAC_DRA, 2.5);
SetDAC(fDAC_DSA, 2.5);
SetDAC(fDAC_DRB, 2.5);
SetDAC(fDAC_DSB, 2.5);
// set readout offset
SetDAC(fDAC_COFSA, 0.9);
SetDAC(fDAC_COFSB, 0.9);
SetDAC(fDAC_TLEVEL, 1.7);
} else if (fBoardType == 2 || fBoardType == 3) {
// set max. domino speed
SetDAC(fDAC_DSA, 2.5);
SetDAC(fDAC_DSB, 2.5);
 
// set readout offset
SetDAC(fDAC_COFS, 0.9);
SetDAC(fDAC_TLEVEL, 1.7);
SetDAC(fDAC_ADCOFS, 1.7); // 1.7 for DC coupling, 1.25 for AC
SetDAC(fDAC_CLKOFS, 1);
} else if (fBoardType == 4) {
// set max. domino speed
SetDAC(fDAC_DSA, 2.5);
SetDAC(fDAC_DSB, 2.5);
 
// set readout offset
SetDAC(fDAC_ROFS_1, 1.25); // LVDS level
//SetDAC(fDAC_ROFS_2, 0.85); // linear range 0.1V ... 1.1V
SetDAC(fDAC_ROFS_2, 1.05); // differential input from Lecce splitter
 
SetDAC(fDAC_ADCOFS, 1.25);
SetDAC(fDAC_ACALIB, 0.5);
SetDAC(fDAC_INOFS, 0.6);
SetDAC(fDAC_BIAS, 0.70); // a bit above the internal bias of 0.68V
} else if (fBoardType == 5) {
// DRS4 USB Evaluation Board 1.1 + 2.0
 
// set max. domino speed
SetDAC(fDAC_DSA, 2.5);
 
// set readout offset
fROFS = 1.6; // differential input range -0.5V ... +0.5V
fRange = 0;
SetDAC(fDAC_ROFS_1, fROFS);
 
// set common mode offset
fCommonMode = 0.8; // 0.8V +- 0.5V inside NMOS range
SetDAC(fDAC_CMOFS, fCommonMode);
 
// calibration voltage
SetDAC(fDAC_CALP, fCommonMode);
SetDAC(fDAC_CALN, fCommonMode);
 
// OUT- offset
SetDAC(fDAC_ONOFS, 1.25);
 
SetDAC(fDAC_BIAS, 0.70);
 
} else if (fBoardType == 6) {
// DRS4 Mezzanine Board 1.0
// set readout offset
fROFS = 1.6; // differential input range -0.5V ... +0.5V
fRange = 0;
SetDAC(fDAC_ROFS_1, fROFS);
 
// set common mode offset
fCommonMode = 0.8; // 0.8V +- 0.5V inside NMOS range
SetDAC(fDAC_CMOFSP, fCommonMode);
SetDAC(fDAC_CMOFSN, fCommonMode);
 
// calibration voltage
SetDAC(fDAC_CALN, fCommonMode);
SetDAC(fDAC_CALP, fCommonMode);
 
// OUT- offset
SetDAC(fDAC_ONOFS, 1.25);
 
SetDAC(fDAC_BIAS, 0.70);
} else if (fBoardType == 7) {
// DRS4 USB Evaluation 3.0
 
// set max. domino speed
SetDAC(fDAC_DSA, 2.5);
 
// set readout offset
fROFS = 1.6; // differential input range -0.5V ... +0.5V
fRange = 0;
SetDAC(fDAC_ROFS_1, fROFS);
 
// set common mode for THS4508
SetDAC(fDAC_CMOFS, 2.4);
 
// calibration voltage
fCommonMode = 0.8; // 0.8V +- 0.5V inside NMOS range
SetDAC(fDAC_CALP, fCommonMode);
SetDAC(fDAC_CALN, fCommonMode);
 
// OUT- offset
SetDAC(fDAC_ONOFS, 1.25);
 
SetDAC(fDAC_BIAS, 0.70);
} else if (fBoardType == 8 || fBoardType == 9) {
// DRS4 USB Evaluation 4.0
 
// set readout offset
fROFS = 1.6; // differential input range -0.5V ... +0.5V
fRange = 0;
SetDAC(fDAC_ROFS_1, fROFS);
 
// calibration voltage
fCommonMode = 0.8; // 0.8V +- 0.5V inside NMOS range
SetDAC(fDAC_CALP, fCommonMode);
SetDAC(fDAC_CALN, fCommonMode);
 
SetDAC(fDAC_BIAS, 0.70);
}
 
/* set default number of channels per chip */
if (fDRSType == 4) {
if (fTransport == TR_USB2)
SetChannelConfig(0, fNumberOfReadoutChannels - 1, 8);
else
SetChannelConfig(7, fNumberOfReadoutChannels - 1, 8);
} else
SetChannelConfig(0, fNumberOfReadoutChannels - 1, 12);
 
// set ADC clock phase
if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
fADCClkPhase = 0;
fADCClkInvert = 0;
} else if (fBoardType == 6) {
fADCClkPhase = 65;
fADCClkInvert = 0;
}
 
// default settings
fMultiBuffer = 0;
fNMultiBuffer = 0;
fDominoMode = 1;
fReadoutMode = 1;
fReadPointer = 0;
fTriggerEnable1 = 0;
fTriggerEnable2 = 0;
fTriggerSource = 0;
fTriggerDelay = 0;
fTriggerDelayNs = 0;
fSyncDelay = 0;
fNominalFrequency = 1;
fDominoActive = 1;
 
// load calibration from EEPROM
ReadCalibration();
 
// get some settings from hardware
fRange = GetCalibratedInputRange();
if (fRange < 0 || fRange > 0.5)
fRange = 0;
fNominalFrequency = GetCalibratedFrequency();
if (fNominalFrequency < 0.1 || fNominalFrequency > 6)
fNominalFrequency = 1;
 
if (fHasMultiBuffer) {
SetMultiBuffer(fMultiBuffer);
SetMultiBufferRP(fReadPointer);
}
SetDominoMode(fDominoMode);
SetReadoutMode(fReadoutMode);
EnableTrigger(fTriggerEnable1, fTriggerEnable2);
SetTriggerSource(fTriggerSource);
SetTriggerDelayPercent(0);
SetSyncDelay(fSyncDelay);
SetDominoActive(fDominoActive);
SetFrequency(fNominalFrequency, true);
SetInputRange(fRange);
if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9)
SelectClockSource(0); // FPGA clock
if (fBoardType == 6) {
SetADCClkPhase(fADCClkPhase, fADCClkInvert);
SetWarmup(0);
SetCooldown(100);
SetDecimation(0);
}
 
// disable calibration signals
EnableAcal(0, 0);
SetCalibTiming(0, 0);
EnableTcal(0);
 
// got to idle state
Reinit();
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetDominoMode(unsigned char mode)
{
// Set domino mode
// mode == 0: single sweep
// mode == 1: run continously
//
fDominoMode = mode;
 
if (fDRSType == 4) {
unsigned short d;
Read(T_CTRL, &d, REG_CONFIG, 2);
fChannelConfig = d & 0xFF;
 
d = fChannelConfig | (fDominoMode << 8) | (1 << 9) | (fWSRLoop << 10) | (0xF8 << 8);
Write(T_CTRL, REG_CONFIG, &d, 2);
} else {
if (mode)
fCtrlBits |= BIT_DMODE;
else
fCtrlBits &= ~BIT_DMODE;
 
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
}
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetDominoActive(unsigned char mode)
{
// Set domino activity
// mode == 0: stop during readout
// mode == 1: keep domino wave running
//
fDominoActive = mode;
if (mode)
fCtrlBits |= BIT_DACTIVE;
else
fCtrlBits &= ~BIT_DACTIVE;
 
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetReadoutMode(unsigned char mode)
{
// Set readout mode
// mode == 0: start from first bin
// mode == 1: start from domino stop
//
fReadoutMode = mode;
if (mode)
fCtrlBits |= BIT_READOUT_MODE;
else
fCtrlBits &= ~BIT_READOUT_MODE;
 
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SoftTrigger(void)
{
// Send a software trigger
fCtrlBits |= BIT_SOFT_TRIG;
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
fCtrlBits &= ~BIT_SOFT_TRIG;
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::EnableTrigger(int flag1, int flag2)
{
// Enable external trigger
fTriggerEnable1 = flag1;
fTriggerEnable2 = flag2;
if (flag1)
fCtrlBits |= BIT_ENABLE_TRIGGER1;
else
fCtrlBits &= ~BIT_ENABLE_TRIGGER1;
 
if (flag2)
fCtrlBits |= BIT_ENABLE_TRIGGER2;
else
fCtrlBits &= ~BIT_ENABLE_TRIGGER2;
 
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetDelayedTrigger(int flag)
{
// Select delayed trigger from trigger bus
if (flag)
fCtrlBits |= BIT_TRIGGER_DELAYED;
else
fCtrlBits &= ~BIT_TRIGGER_DELAYED;
 
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetTriggerPolarity(bool negative)
{
if (fBoardType == 5 || fBoardType == 7) {
fTcalLevel = negative;
if (negative)
fCtrlBits |= BIT_NEG_TRIGGER;
else
fCtrlBits &= ~BIT_NEG_TRIGGER;
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
return 1;
} else if (fBoardType == 8 || fBoardType == 9) {
fTcalLevel = negative;
if (negative)
fCtrlBits |= BIT_NEG_TRIGGER;
else
fCtrlBits &= ~BIT_NEG_TRIGGER;
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
return 1;
}
return 0;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetTriggerLevel(double voltage)
{
if (fBoardType == 5 || fBoardType == 7) {
return SetDAC(fDAC_TLEVEL, voltage/2 + 0.8);
} else if (fBoardType == 8 || fBoardType == 9) {
SetIndividualTriggerLevel(0, voltage);
SetIndividualTriggerLevel(1, voltage);
SetIndividualTriggerLevel(2, voltage);
SetIndividualTriggerLevel(3, voltage);
return 1;
}
 
return 0;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetIndividualTriggerLevel(int channel, double voltage)
{
if (fBoardType == 8 || fBoardType == 9) {
switch (channel) {
case 0: SetDAC(fDAC_TLEVEL1, voltage/2 + 0.8); break;
case 1: SetDAC(fDAC_TLEVEL2, voltage/2 + 0.8); break;
case 2: SetDAC(fDAC_TLEVEL3, voltage/2 + 0.8); break;
case 3: SetDAC(fDAC_TLEVEL4, voltage/2 + 0.8); break;
default: return -1;
}
}
return 0;
}
 
/*------------------------------------------------------------------*/
 
#define LUT_DELAY_S3_8 6.2 // Spartan 3 Octal LUTs 2 GSPS
#define LUT_DELAY_S3_4 2.1 // Spartan 3 Quad LUTs
#define LUT_DELAY_V2_8 4.6 // Virtex PRO II Octal LUTs
#define LUT_DELAY_V2_4 2.3 // Virtex PRO II Quad LUTs
 
 
int DRSBoard::SetTriggerDelayPercent(int delay)
/* set trigger delay in percent 0..100 */
{
short ticks, reg;
fTriggerDelay = delay;
 
if (fBoardType == 5 || fBoardType == 6 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
// convert delay (0..100) into ticks
ticks = (unsigned short) (delay/100.0*255+0.5);
if (ticks > 255)
ticks = 255;
if (ticks < 0)
ticks = 0;
 
// convert delay into ns
if (fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
if (fFirmwareVersion >= 17147)
fTriggerDelayNs = ticks * LUT_DELAY_S3_8;
else
fTriggerDelayNs = ticks * LUT_DELAY_S3_4;
} else {
if (fFirmwareVersion >= 17382)
fTriggerDelayNs = ticks * LUT_DELAY_V2_8;
else
fTriggerDelayNs = ticks * LUT_DELAY_V2_4;
}
 
// adjust for fixed delay, measured and approximated experimentally
fTriggerDelayNs += 23.5 + 28.2/fNominalFrequency;
 
Read(T_CTRL, &reg, REG_TRG_DELAY, 2);
reg = (reg & 0xFF00) | ticks;
Write(T_CTRL, REG_TRG_DELAY, &ticks, 2);
 
return 1;
}
 
return 0;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetTriggerDelayNs(int delay)
/* set trigger delay in nanoseconds */
{
short ticks, reg;
fTriggerDelayNs = delay;
 
if (fBoardType == 5 || fBoardType == 6 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
 
// convert delay in ns into ticks
if (fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
if (fFirmwareVersion >= 17147)
ticks = (short int)(delay / LUT_DELAY_S3_8 + 0.5);
else
ticks = (short int)(delay / LUT_DELAY_S3_4 + 0.5);
} else {
if (fFirmwareVersion >= 17382)
ticks = (short int)(delay / LUT_DELAY_V2_8 + 0.5);
else
ticks = (short int)(delay / LUT_DELAY_V2_4 + 0.5);
}
 
if (ticks > 255)
ticks = 255;
if (ticks < 0)
ticks = 0;
 
fTriggerDelay = ticks / 255 * 100;
 
Read(T_CTRL, &reg, REG_TRG_DELAY, 2);
reg = (reg & 0xFF00) | ticks;
Write(T_CTRL, REG_TRG_DELAY, &ticks, 2);
 
return 1;
}
 
return 0;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetSyncDelay(int ticks)
{
short int reg;
 
if (fBoardType == 5 || fBoardType == 6 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
Read(T_CTRL, &reg, REG_TRG_DELAY, 2);
reg = (reg & 0xFF) | (ticks << 8);
Write(T_CTRL, REG_TRG_DELAY, &reg, 2);
 
return 1;
}
 
return 0;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetTriggerSource(int source)
{
short int reg;
 
fTriggerSource = source;
if (fBoardType == 5 || fBoardType == 7) {
// Set trigger source
// 0=CH1, 1=CH2, 2=CH3, 3=CH4
if (source & 1)
fCtrlBits |= BIT_TR_SOURCE1;
else
fCtrlBits &= ~BIT_TR_SOURCE1;
if (source & 2)
fCtrlBits |= BIT_TR_SOURCE2;
else
fCtrlBits &= ~BIT_TR_SOURCE2;
 
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
} else if (fBoardType == 8 || fBoardType == 9) {
// Set trigger configuration
// OR Bit0=CH1, Bit1=CH2, Bit2=CH3, Bit3=CH4, Bit4=EXT
// AND Bit8=CH1, Bit9=CH2, Bit10=CH3, Bit11=CH4, Bit12=EXT
// TRANSP Bit15
reg = (unsigned short) source;
Write(T_CTRL, REG_TRG_CONFIG, &reg, 2);
}
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetDelayedStart(int flag)
{
// Enable external trigger
fDelayedStart = flag;
if (flag)
fCtrlBits |= BIT_DELAYED_START;
else
fCtrlBits &= ~BIT_DELAYED_START;
 
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetTranspMode(int flag)
{
// Enable/disable transparent mode
fTranspMode = flag;
if (flag)
fCtrlBits |= BIT_TRANSP_MODE;
else
fCtrlBits &= ~BIT_TRANSP_MODE;
 
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetStandbyMode(int flag)
{
// Enable/disable standby mode
fTranspMode = flag;
if (flag)
fCtrlBits |= BIT_STANDBY_MODE;
else
fCtrlBits &= ~BIT_STANDBY_MODE;
 
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetDecimation(int flag)
{
// Drop every odd sample
fDecimation = flag;
if (flag)
fCtrlBits |= BIT_DECIMATION;
else
fCtrlBits &= ~BIT_DECIMATION;
 
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
 
// Calculate channel depth
fChannelDepth = fChannelCascading * (fDecimation ? kNumberOfBins/2 : kNumberOfBins);
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::IsBusy()
{
// Get running flag
unsigned int status;
 
Read(T_STATUS, &status, REG_STATUS, 4);
return (status & BIT_RUNNING) > 0;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::IsEventAvailable()
{
if (!fMultiBuffer)
return !IsBusy();
 
return GetMultiBufferWP() != fReadPointer;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::IsPLLLocked()
{
// Get running flag
unsigned int status;
 
Read(T_STATUS, &status, REG_STATUS, 4);
if (GetBoardType() == 6)
return ((status >> 1) & 0x0F) == 0x0F;
return (status & BIT_PLL_LOCKED0) > 0;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::IsLMKLocked()
{
// Get running flag
unsigned int status;
 
Read(T_STATUS, &status, REG_STATUS, 4);
if (GetBoardType() == 6)
return (status & BIT_LMK_LOCKED) > 0;
return 0;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::IsNewFreq(unsigned char chipIndex)
{
unsigned int status;
 
Read(T_STATUS, &status, REG_STATUS, 4);
if (chipIndex == 0)
return (status & BIT_NEW_FREQ1) > 0;
return (status & BIT_NEW_FREQ2) > 0;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::ReadFrequency(unsigned char chipIndex, double *f)
{
if (fDRSType == 4) {
 
if (fBoardType == 6) {
*f = fNominalFrequency;
return 1;
}
 
unsigned short ticks;
 
Read(T_CTRL, &ticks, REG_FREQ_SET, 2);
ticks += 2;
 
/* convert rounded ticks back to frequency */
if (ticks > 2)
*f = 1.024 / ticks * fRefClock;
else
*f = 0;
} else {
// Read domino sampling frequency
unsigned char buffer[2];
 
if (chipIndex == 0)
Read(T_STATUS, buffer, REG_FREQ1, 2);
else
Read(T_STATUS, buffer, REG_FREQ2, 2);
 
*f = (static_cast < unsigned int >(buffer[1]) << 8) +buffer[0];
 
/* convert counts to frequency */
if (*f != 0)
*f = 1024 * 200 * (32.768E6 * 4) / (*f) / 1E9;
}
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
double DRSBoard::VoltToFreq(double volt)
{
if (fDRSType == 3) {
if (volt <= 1.2001)
return (volt - 0.6) / 0.2;
else
return 0.73 / 0.28 + sqrt((0.73 / 0.28) * (0.73 / 0.28) - 2.2 / 0.14 + volt / 0.14);
} else
return (volt - 0.5) / 0.2;
}
 
/*------------------------------------------------------------------*/
 
double DRSBoard::FreqToVolt(double freq)
{
if (fDRSType == 3) {
if (freq <= 3)
return 0.6 + 0.2 * freq;
else
return 2.2 - 0.73 * freq + 0.14 * freq * freq;
} else
return 0.55 + 0.25 * freq;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::ConfigureLMK(double sampFreq, bool freqChange, int calFreq, int calPhase)
{
unsigned int data[] = { 0x80000100, // RESET=1
0x0007FF00, // CLKOUT0: EN=1, DIV=FF (=510) MUX=Div&Delay
0x00000101, // CLKOUT1: Disabled
0x0082000B, // R11: DIV4=0
0x028780AD, // R13: VCO settings
0x0830000E, // R14: PLL settings
0xC000000F }; // R15: PLL settings
 
/* calculate dividing ratio */
int divider, vco_divider, n_counter, r_counter;
unsigned int status;
double clk, vco;
 
if (fTransport == TR_USB2) {
/* 30 MHz clock */
data[4] = 0x028780AD; // R13 according to CodeLoader 4
clk = 30;
if (sampFreq < 1) {
r_counter = 1;
vco_divider = 8;
n_counter = 5;
} else {
r_counter = 1;
vco_divider = 5;
n_counter = 8;
}
} else {
if (fCtrlBits & BIT_REFCLK_SOURCE) {
/* 19.44 MHz clock */
data[4] = 0x0284C0AD; // R13 according to CodeLoader 4
clk = 19.44; // global clock through P2
 
r_counter = 2;
vco_divider = 8;
n_counter = 16;
} else {
/* 33 MHz clock */
data[4] = 0x028840AD; // R13 according to CodeLoader 4
clk = 33; // FPGA clock
 
r_counter = 2;
vco_divider = 8;
n_counter = 9;
}
}
 
vco = clk/r_counter*n_counter*vco_divider;
divider = (int) ((vco / vco_divider / (sampFreq/2.048) / 2.0) + 0.5);
 
/* return exact frequency */
fNominalFrequency = vco/vco_divider/(divider*2)*2.048;
 
/* return exact timing calibration frequency */
fTCALFrequency = vco/vco_divider;
 
/* change registers accordingly */
data[1] = 0x00070000 | (divider << 8); // R0
data[5] = 0x0830000E | (r_counter << 8); // R14
data[6] = 0xC000000F | (n_counter << 8) | (vco_divider << 26); // R15
 
/* enable TCA output if requested */
if (calFreq) {
if (calFreq == 1)
data[2] = 0x00050001 | ( 1<<8) ; // 148.5 MHz (33 MHz PLL)
// 150 MHz (30 MHz PLL)
// 155.52 MHz (19.44 MHz PLL)
else if (calFreq == 2) {
data[2] = 0x00070001 | ( 4<<8); // above values divided by 8
fTCALFrequency /= 8;
} else if (calFreq == 3) {
data[2] = 0x00070001 | (255<<8); // above values divided by 510
fTCALFrequency /= 510;
}
}
 
/* set delay to adjsut phase */
if (calPhase > 0)
data[2] |= (( calPhase & 0x0F) << 4);
else if (calPhase < 0)
data[1] |= ((-calPhase & 0x0F) << 4);
 
if (freqChange) {
/* set all registers */
for (int i=0 ; i<(int)(sizeof(data)/sizeof(unsigned int)) ; i++) {
Write(T_CTRL, REG_LMK_LSB, &data[i], 2);
Write(T_CTRL, REG_LMK_MSB, ((char *)&data[i])+2, 2);
// poll on serial_busy flag
for (int j=0 ; j<100 ; j++) {
Read(T_STATUS, &status, REG_STATUS, 4);
if ((status & BIT_SERIAL_BUSY) == 0)
break;
}
}
} else {
/* only enable/disable timing calibration frequency */
Write(T_CTRL, REG_LMK_LSB, &data[1], 2);
Write(T_CTRL, REG_LMK_MSB, ((char *)&data[1])+2, 2);
 
/* poll on serial_busy flag */
for (int j=0 ; j<100 ; j++) {
Read(T_STATUS, &status, REG_STATUS, 4);
if ((status & BIT_SERIAL_BUSY) == 0)
break;
}
 
Write(T_CTRL, REG_LMK_LSB, &data[2], 2);
Write(T_CTRL, REG_LMK_MSB, ((char *)&data[2])+2, 2);
 
/* poll on serial_busy flag */
for (int j=0 ; j<100 ; j++) {
Read(T_STATUS, &status, REG_STATUS, 4);
if ((status & BIT_SERIAL_BUSY) == 0)
break;
}
}
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetFrequency(double demand, bool wait)
{
// Set domino sampling frequency
double freq, voltage, delta_voltage;
unsigned short ticks;
int i, index, timeout;
int dominoModeSave = fDominoMode;
int triggerEnableSave1 = fTriggerEnable1;
int triggerEnableSave2 = fTriggerEnable2;
 
if (fDRSType == 4) {
/* allowed range is 100 MHz to 6 GHz */
if (demand > 6 || demand < 0.1)
return 0;
 
if (fBoardType == 6) {
for (i=1 ; i<100 ; i++) {
ConfigureLMK(demand, true, fTcalFreq, fTcalPhase);
Sleep(10);
if (IsLMKLocked())
return 1;
printf("Re-start LMK in VME slot %2d %s\n",
(GetSlotNumber() >> 1)+2, ((GetSlotNumber() & 1) == 0) ? "upper" : "lower");
}
return 0;
}
 
/* convert frequency in GHz into ticks counted by reference clock */
if (demand == 0)
ticks = 0; // turn off frequency generation
else
ticks = static_cast < unsigned short >(1.024 / demand * fRefClock + 0.5);
 
ticks -= 2; // firmware counter need two additional clock cycles
Write(T_CTRL, REG_FREQ_SET, &ticks, 2);
ticks += 2;
 
/* convert rounded ticks back to frequency */
if (demand > 0)
demand = 1.024 / ticks * fRefClock;
fNominalFrequency = demand;
 
/* wait for PLL lock if asked */
if (wait) {
StartDomino();
for (i=0 ; i<1000 ; i++)
if (GetStatusReg() & BIT_PLL_LOCKED0)
break;
SoftTrigger();
if (i == 1000) {
printf("PLL did not lock for frequency %lf\n", demand);
return 0;
}
}
} else { // fDRSType == 4
SetDominoMode(1);
EnableTrigger(0, 0);
EnableAcal(0, 0);
 
fNominalFrequency = demand;
 
/* turn automatic adjustment off */
fCtrlBits &= ~BIT_FREQ_AUTO_ADJ;
 
/* disable external trigger */
fCtrlBits &= ~BIT_ENABLE_TRIGGER1;
fCtrlBits &= ~BIT_ENABLE_TRIGGER2;
 
/* set start pulse length for future DRSBoard_domino_start() */
if (fDRSType == 2) {
if (demand < 0.8)
fCtrlBits |= BIT_LONG_START_PULSE;
else
fCtrlBits &= ~BIT_LONG_START_PULSE;
 
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
}
 
/* stop any running domino wave */
Reinit();
 
/* estimate DAC setting */
voltage = FreqToVolt(demand);
 
SetDAC(fDAC_DSA, voltage);
SetDAC(fDAC_DSB, voltage);
 
/* wait until new DAC value has settled */
Sleep(10);
 
/* restart domino wave */
StartDomino();
 
ticks = static_cast < unsigned short >(1024 * 200 * (32.768E6 * 4) / demand / 1E9);
 
/* iterate over both DRS chips */
for (index = 0; index < 2; index++) {
 
/* starting voltage */
voltage = FreqToVolt(demand);
 
for (i = 0; i < 100; i++) {
 
/* wait until measurement finished */
for (timeout = 0; timeout < 1000; timeout++)
if (IsNewFreq(index))
break;
 
freq = 0;
if (timeout == 1000)
break;
 
ReadFrequency(index, &freq);
 
delta_voltage = FreqToVolt(demand) - FreqToVolt(freq);
 
if (fDebug) {
if (fabs(freq - demand) < 0.001)
printf("CHIP-%d, iter%3d: %1.5lf(%05d) %7.5lf\n", index, i, voltage,
static_cast < int >(voltage / 2.5 * 65535 + 0.5), freq);
else
printf("CHIP-%d, iter%3d: %1.5lf(%05d) %7.5lf %+5d\n", index, i, voltage,
static_cast < int >(voltage / 2.5 * 65535 + 0.5), freq,
static_cast < int >(delta_voltage / 2.5 * 65535 + 0.5));
}
 
if (fabs(freq - demand) < 0.001)
break;
 
voltage += delta_voltage;
if (voltage > 2.5)
voltage = 2.5;
if (voltage < 0)
voltage = 0;
 
if (freq == 0)
break;
 
if (index == 0)
SetDAC(fDAC_DSA, voltage);
else
SetDAC(fDAC_DSB, voltage);
 
Sleep(10);
}
if (i == 100 || freq == 0 || timeout == 1000) {
printf("Board %d --> Could not set frequency of CHIP-#%d to %1.3f GHz\n", GetBoardSerialNumber(),
index, demand);
return 0;
}
}
 
SetDominoMode(dominoModeSave);
EnableTrigger(triggerEnableSave1, triggerEnableSave2);
}
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::RegulateFrequency(double demand)
{
// Set frequency regulation
unsigned short target, target_hi, target_lo;
 
if (demand < 0.42 || demand > 5.2)
return 0;
 
fNominalFrequency = demand;
 
/* first iterate DAC value from host */
if (!SetFrequency(demand, true))
return 0;
 
/* convert frequency in GHz into counts for 200 cycles */
target = static_cast < unsigned short >(1024 * 200 * (32.768E6 * 4) / demand / 1E9);
target_hi = target + 6;
target_lo = target - 6;
Write(T_CTRL, REG_FREQ_SET_HI, &target_hi, 2);
Write(T_CTRL, REG_FREQ_SET_LO, &target_lo, 2);
 
/* turn on regulation */
fCtrlBits |= BIT_FREQ_AUTO_ADJ;
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
 
/* optional monitoring code ... */
#if 0
do {
double freq;
unsigned short dac, cnt;
 
ReadFrequency(0, &freq);
 
if (fBoardType == 1)
Read(T_STATUS, &dac, REG_RDAC3, 2);
else if (fBoardType == 2 || fBoardType == 3)
Read(T_STATUS, &dac, REG_RDAC1, 2);
 
Read(T_STATUS, &cnt, REG_FREQ1, 2);
 
if (cnt < 65535)
printf("%5d %5d %5d %1.5lf\n", dac, target, cnt, freq);
 
Sleep(500);
} while (1);
#endif
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
void DRSBoard::RegisterTest()
{
// Register test
#define N_REG 8
 
int i, n, n_err;
unsigned int buffer[N_REG], ret[N_REG];
 
/* test single register */
buffer[0] = 0x12345678;
Write(T_CTRL, 0, buffer, 4);
memset(ret, 0, sizeof(ret));
i = Read(T_CTRL, ret, 0, 4);
while (i != 4)
printf("Read error single register!\n");
 
printf("Reg.0: %08X - %08X\n", buffer[0], ret[0]);
 
n_err = 0;
for (n = 0; n < 100; n++) {
for (i = 0; i < N_REG; i++)
buffer[i] = (rand() << 16) | rand();
Write(T_CTRL, 0, buffer, sizeof(buffer));
 
memset(ret, 0, sizeof(ret));
i = Read(T_CTRL, ret, 0, sizeof(ret));
while (i != sizeof(ret)) {
printf("Read error!\n");
return;
}
 
for (i = 0; i < N_REG; i++) {
if (n == 0)
printf("Reg.%d: %08X - %08X\n", i, buffer[i], ret[i]);
if (buffer[i] != ret[i]) {
n_err++;
}
}
}
 
printf("Register test: %d errors\n", n_err);
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::RAMTest(int flag)
{
#define MAX_N_BYTES 128*1024 // 128 kB
 
int i, j, n, bits, n_bytes, n_words, n_dwords;
unsigned int buffer[MAX_N_BYTES/4], ret[MAX_N_BYTES/4];
time_t now;
 
if (fBoardType == 6 && fTransport == TR_VME) {
bits = 32;
n_bytes = 128*1024; // test full 128 kB
n_words = n_bytes/2;
n_dwords = n_words/2;
} else {
bits = 24;
n_words = 9*1024;
n_bytes = n_words * 2;
n_dwords = n_words/2;
}
 
if (flag & 1) {
/* integrety test */
printf("Buffer size: %d (%1.1lfk)\n", n_words * 2, n_words * 2 / 1024.0);
if (flag & 1) {
for (i = 0; i < n_dwords; i++) {
if (bits == 24)
buffer[i] = (rand() | rand() << 16) & 0x00FFFFFF; // random 24-bit values
else
buffer[i] = (rand() | rand() << 16); // random 32-bit values
}
 
Reinit();
Write(T_RAM, 0, buffer, n_bytes);
memset(ret, 0, n_bytes);
Read(T_RAM, ret, 0, n_bytes);
Reinit();
 
for (i = n = 0; i < n_dwords; i++) {
if (buffer[i] != ret[i]) {
n++;
}
if (i < 10)
printf("written: %08X read: %08X\n", buffer[i], ret[i]);
}
 
printf("RAM test: %d errors\n", n);
}
}
 
/* speed test */
if (flag & 2) {
/* read continously to determine speed */
time(&now);
while (now == time(NULL));
time(&now);
i = n = 0;
do {
memset(ret, 0, n_bytes);
 
for (j = 0; j < 10; j++) {
Read(T_RAM, ret, 0, n_bytes);
i += n_bytes;
}
 
if (flag & 1) {
for (j = 0; j < n_dwords; j++)
if (buffer[j] != ret[j])
n++;
}
 
if (now != time(NULL)) {
if (flag & 1)
printf("%d read/sec, %1.2lf MB/sec, %d errors\n", static_cast < int >(i / n_bytes),
i / 1024.0 / 1024.0, n);
else
printf("%d read/sec, %1.2lf MB/sec\n", static_cast < int >(i / n_bytes),
i / 1024.0 / 1024.0);
time(&now);
i = 0;
}
 
if (drs_kbhit())
break;
 
} while (1);
 
while (drs_kbhit())
getch();
}
 
return 0;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::ChipTest()
{
int i, j, t;
double freq, old_freq, min, max, mean, std;
float waveform[1024];
 
Init();
SetChannelConfig(0, 8, 8);
SetDominoMode(1);
SetReadoutMode(1);
SetDominoActive(1);
SetTranspMode(0);
EnableTrigger(0, 0);
EnableTcal(1, 0);
SelectClockSource(0);
EnableAcal(1, 0);
 
/* test 1 GHz */
SetFrequency(1, true);
StartDomino();
Sleep(100);
if (!(GetStatusReg() & BIT_PLL_LOCKED0)) {
puts("PLL did not lock at 1 GHz");
return 0;
}
 
/* test up to 6 GHz */
for (freq = 5 ; freq < 6 ; freq += 0.1) {
SetFrequency(freq, false);
Sleep(10);
if (!(GetStatusReg() & BIT_PLL_LOCKED0)) {
printf("Max. frequency is %1.1lf GHz\n", old_freq);
break;
}
ReadFrequency(0, &old_freq);
}
 
/* read and check at 0 calibration voltage */
SetFrequency(5, true);
Sleep(10);
SoftTrigger();
while (IsBusy());
TransferWaves(0, 8);
 
for (i=0 ; i<8 ; i++) {
t = GetStopCell(0);
GetWave(0, i, waveform, false, t, 0, false);
for (j=0 ; j<1024; j++)
if (waveform[j] < -100 || waveform[j] > 100) {
if (j<5) {
/* skip this cells */
} else {
printf("Cell error on channel %d, cell %d: %1.1lf mV instead 0 mV\n", i, j, waveform[j]);
return 0;
}
}
}
 
/* read and check at +0.5V calibration voltage */
EnableAcal(1, 0.5);
StartDomino();
SoftTrigger();
while (IsBusy());
TransferWaves(0, 8);
 
for (i=0 ; i<8 ; i++) {
t = GetStopCell(0);
GetWave(0, i, waveform, false, t, 0, false);
for (j=0 ; j<1024; j++)
if (waveform[j] < 350) {
if (j<5) {
/* skip this cell */
} else {
printf("Cell error on channel %d, cell %d: %1.1lf mV instead 400 mV\n", i, j, waveform[j]);
return 0;
}
}
}
 
/* read and check at -0.5V calibration voltage */
EnableAcal(1, -0.5);
StartDomino();
Sleep(10);
SoftTrigger();
while (IsBusy());
TransferWaves(0, 8);
 
for (i=0 ; i<8 ; i++) {
t = GetStopCell(0);
GetWave(0, i, waveform, false, t, 0, false);
for (j=0 ; j<1024; j++)
if (waveform[j] > -350) {
if (j<5) {
/* skip this cell */
} else {
printf("Cell error on channel %d, cell %d: %1.1lf mV instead -400mV\n", i, j, waveform[j]);
return 0;
}
}
}
 
/* check clock channel */
GetWave(0, 8, waveform, false, 0, 0);
min = max = mean = std = 0;
for (j=0 ; j<1024 ; j++) {
if (waveform[j] > max)
max = waveform[j];
if (waveform[j] < min)
min = waveform[j];
mean += waveform[j];
}
mean /= 1024.0;
for (j=0 ; j<1024 ; j++)
std += (waveform[j] - mean) * (waveform[j] - mean);
std = sqrt(std/1024);
 
if (max - min < 400) {
printf("Error on clock channel amplitude: %1.1lf mV\n", max-min);
return 0;
}
 
if (std < 100 || std > 300) {
printf("Error on clock channel Std: %1.1lf mV\n", std);
return 0;
}
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
void DRSBoard::SetVoltageOffset(double offset1, double offset2)
{
if (fDRSType == 3) {
SetDAC(fDAC_ROFS_1, 0.95 - offset1);
SetDAC(fDAC_ROFS_2, 0.95 - offset2);
} else if (fDRSType == 2)
SetDAC(fDAC_COFS, 0.9 - offset1);
 
// let DAC settle
Sleep(100);
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetInputRange(double center)
{
if (fBoardType == 5 || fBoardType == 6 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
// DRS4 USB Evaluation Boards + Mezzanine Board
 
// only allow -0.5...0.5 to 0...1.0
if (center < 0 || center > 0.5)
return 0;
 
// remember range
fRange = center;
 
// correct for sampling cell charge injection
center *= 1.125;
 
// set readout offset
fROFS = 1.6 - center;
SetDAC(fDAC_ROFS_1, fROFS);
}
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetExternalClockFrequency(double frequencyMHz)
{
// Set the frequency of the external clock
fExternalClockFrequency = frequencyMHz;
return 0;
}
 
/*------------------------------------------------------------------*/
 
double DRSBoard::GetExternalClockFrequency()
{
// Return the frequency of the external clock
return fExternalClockFrequency;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetMultiBuffer(int flag)
{
if (fHasMultiBuffer) {
// Enable/disable multi-buffering
fMultiBuffer = flag;
if (flag)
fCtrlBits |= BIT_MULTI_BUFFER;
else
fCtrlBits &= ~BIT_MULTI_BUFFER;
 
if (flag) {
if (fBoardType == 6)
fNMultiBuffer = 3; // 3 buffers for VME board
} else
fNMultiBuffer = 0;
 
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
}
return 1;
}
 
/*------------------------------------------------------------------*/
 
void DRSBoard::ResetMultiBuffer(void)
{
Reinit(); // set WP=0
fReadPointer = 0;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::GetMultiBufferRP(void)
{
return fReadPointer;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetMultiBufferRP(unsigned short rp)
{
if (fHasMultiBuffer) {
fReadPointer = rp;
Write(T_CTRL, REG_READ_POINTER, &rp, 2);
}
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::GetMultiBufferWP(void)
{
unsigned short wp = 0;
 
if (fHasMultiBuffer)
Read(T_STATUS, &wp, REG_WRITE_POINTER, 2);
else
wp = 0;
return wp;
}
 
/*------------------------------------------------------------------*/
 
void DRSBoard::IncrementMultiBufferRP()
{
if (fHasMultiBuffer && fMultiBuffer)
SetMultiBufferRP((fReadPointer + 1) % fNMultiBuffer);
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::TransferWaves(int numberOfChannels)
{
return TransferWaves(fWaveforms, numberOfChannels);
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::TransferWaves(unsigned char *p, int numberOfChannels)
{
return TransferWaves(p, 0, numberOfChannels - 1);
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::TransferWaves(int firstChannel, int lastChannel)
{
int offset;
 
if (fTransport == TR_USB)
offset = firstChannel * sizeof(short int) * kNumberOfBins;
else
offset = 0; //in VME and USB2, always start from zero
 
return TransferWaves(fWaveforms + offset, firstChannel, lastChannel);
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::TransferWaves(unsigned char *p, int firstChannel, int lastChannel)
{
// Transfer all waveforms at once from VME or USB to location
int n, i, offset, n_requested, n_bins;
unsigned int dw;
unsigned short w;
unsigned char *ptr;
 
if (lastChannel >= fNumberOfChips * fNumberOfChannels)
lastChannel = fNumberOfChips * fNumberOfChannels - 1;
if (lastChannel < 0) {
printf("Error: Invalid channel index %d\n", lastChannel);
return 0;
}
 
if (firstChannel < 0 || firstChannel > fNumberOfChips * fNumberOfChannels) {
printf("Error: Invalid channel index %d\n", firstChannel);
return 0;
}
 
if (fTransport == TR_VME) {
/* in VME, always transfer all waveforms, since channels sit 'next' to each other */
firstChannel = 0;
lastChannel = fNumberOfChips * fNumberOfChannels - 1;
if (fReadoutChannelConfig == 4)
lastChannel = fNumberOfChips * 5 - 1; // special mode to read only even channels + clock
}
 
else if (fTransport == TR_USB2) {
/* USB2 FPGA contains 9 (Eval) or 10 (Mezz) channels */
firstChannel = 0;
if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9)
lastChannel = 8;
else if (fBoardType == 6)
lastChannel = 9;
}
 
else if (fTransport == TR_USB) {
/* USB1 FPGA contains only 16 channels */
if (lastChannel > 15)
lastChannel = 15;
}
 
n_bins = fDecimation ? kNumberOfBins/2 : kNumberOfBins;
n_requested = (lastChannel - firstChannel + 1) * sizeof(short int) * n_bins;
offset = firstChannel * sizeof(short int) * n_bins;
 
if (fBoardType == 6 && fFirmwareVersion >= 17147)
n_requested += 16; // add trailer four chips
if ((fBoardType == 7 || fBoardType == 8 || fBoardType == 9) && fFirmwareVersion >= 17147)
n_requested += 4; // add trailer one chip
 
if (fMultiBuffer)
offset += n_requested * fReadPointer;
 
n = Read(T_RAM, p, offset, n_requested);
 
if (fMultiBuffer)
IncrementMultiBufferRP();
 
if (n != n_requested) {
printf("Error: only %d bytes read instead of %d\n", n, n_requested);
return n;
}
 
// read trigger cells
if (fDRSType == 4) {
if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
if ((fBoardType == 7 || fBoardType == 8 || fBoardType == 9) && fFirmwareVersion >= 17147) {
// new code reading trailer
ptr = p + n_requested - 4;
fStopCell[0] = *((unsigned short *)(ptr));
fStopWSR[0] = *(ptr + 2);
} else {
// old code reading status register
Read(T_STATUS, fStopCell, REG_STOP_CELL0, 2);
Read(T_STATUS, &w, REG_STOP_WSR0, 2);
fStopWSR[0] = (w >> 8) & 0xFFFF;
}
} else {
 
if (fBoardType == 6) {
// new code reading trailer
ptr = p + n_requested - 16;
for (i=0 ; i<4 ; i++) {
fStopCell[i] = *((unsigned short *)(ptr + i*2));
fStopWSR[i] = *(ptr + 8 + i);
}
fTriggerBus = *((unsigned short *)(ptr + 12));
} else {
// old code reading registers
Read(T_STATUS, &dw, REG_STOP_CELL0, 4);
fStopCell[0] = (dw >> 16) & 0xFFFF;
fStopCell[1] = (dw >> 0) & 0xFFFF;
Read(T_STATUS, &dw, REG_STOP_CELL2, 4);
fStopCell[2] = (dw >> 16) & 0xFFFF;
fStopCell[3] = (dw >> 0) & 0xFFFF;
 
Read(T_STATUS, &dw, REG_STOP_WSR0, 4);
fStopWSR[0] = (dw >> 24) & 0xFF;
fStopWSR[1] = (dw >> 16) & 0xFF;
fStopWSR[2] = (dw >> 8) & 0xFF;
fStopWSR[3] = (dw >> 0) & 0xFF;
 
Read(T_STATUS, &fTriggerBus, REG_TRIGGER_BUS, 2);
}
}
}
return n;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::DecodeWave(unsigned int chipIndex, unsigned char channel, unsigned short *waveform)
{
return DecodeWave(fWaveforms, chipIndex, channel, waveform);
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::DecodeWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel,
unsigned short *waveform)
{
// Get waveform
int i, offset=0, ind, n_bins;
 
/* check valid parameters */
assert((int)channel < fNumberOfChannels);
assert((int)chipIndex < fNumberOfChips);
 
/* remap channel */
if (fBoardType == 1) {
if (channel < 8)
channel = 7 - channel;
else
channel = 16 - channel;
} else if (fBoardType == 6) {
if (fReadoutChannelConfig == 7) {
if (channel < 8)
channel = 7-channel;
} else if (fReadoutChannelConfig == 4) {
if (channel == 8)
channel = 4;
else
channel = 3 - channel/2;
} else {
channel = channel / 2;
if (channel != 4)
channel = 3-channel;
}
} /* else
channel = channel; */
 
// Read channel
if (fTransport == TR_USB) {
offset = kNumberOfBins * 2 * (chipIndex * 16 + channel);
for (i = 0; i < kNumberOfBins; i++) {
// 12-bit data
waveform[i] = ((waveforms[i * 2 + 1 + offset] & 0x0f) << 8) + waveforms[i * 2 + offset];
}
} else if (fTransport == TR_USB2) {
 
if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9)
// see dpram_map_eval1.xls
offset = kNumberOfBins * 2 * (chipIndex * 16 + channel);
else if (fBoardType == 6) {
// see dpram_map_mezz1.xls mode 0-3
offset = (kNumberOfBins * 4) * (channel % 9) + 2 * (chipIndex/2);
}
for (i = 0; i < kNumberOfBins; i++) {
// 16-bit data
if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9)
waveform[i] = ((waveforms[i * 2 + 1 + offset] & 0xff) << 8) + waveforms[i * 2 + offset];
else if (fBoardType == 6)
waveform[i] = ((waveforms[i * 4 + 1 + offset] & 0xff) << 8) + waveforms[i * 4 + offset];
}
 
} else if (fTransport == TR_VME) {
 
if (fBoardType == 6) {
n_bins = fDecimation ? kNumberOfBins/2 : kNumberOfBins;
if (fReadoutChannelConfig == 7) // see dpram_map_mezz1.xls mode 7
offset = (n_bins * 4) * (channel % 9 + 9*(chipIndex % 2)) + 2 * (chipIndex/2);
else if (fReadoutChannelConfig == 4) // see dpram_map_mezz1.xls mode 4
offset = (n_bins * 4) * (channel % 5 + 5*(chipIndex % 2)) + 2 * (chipIndex/2);
for (i = 0; i < n_bins; i++)
waveform[i] = ((waveforms[i * 4 + 1 + offset] & 0xff) << 8) + waveforms[i * 4 + offset];
} else {
offset = (kNumberOfBins * 4) * channel;
for (i = 0; i < kNumberOfBins; i++) {
ind = i * 4 + offset;
if (chipIndex == 0)
// lower 12 bit
waveform[i] = ((waveforms[ind + 1] & 0x0f) << 8) | waveforms[ind];
else
// upper 12 bit
waveform[i] = (waveforms[ind + 2] << 4) | (waveforms[ind + 1] >> 4);
}
}
} else {
printf("Error: invalid transport %d\n", fTransport);
return kInvalidTransport;
}
return kSuccess;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::GetWave(unsigned int chipIndex, unsigned char channel, float *waveform)
{
return GetWave(chipIndex, channel, waveform, true, fStopCell[chipIndex], -1, false, 0, true);
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::GetWave(unsigned int chipIndex, unsigned char channel, short *waveform, bool responseCalib,
int triggerCell, int wsr, bool adjustToClock, float threshold, bool offsetCalib)
{
return GetWave(fWaveforms, chipIndex, channel, waveform, responseCalib, triggerCell, wsr, adjustToClock,
threshold, offsetCalib);
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::GetWave(unsigned int chipIndex, unsigned char channel, float *waveform, bool responseCalib,
int triggerCell, int wsr, bool adjustToClock, float threshold, bool offsetCalib)
{
return GetWave(fWaveforms, chipIndex, channel, waveform, responseCalib, triggerCell, wsr, adjustToClock, threshold,
offsetCalib);
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::GetWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel,
float *waveform, bool responseCalib, int triggerCell, int wsr, bool adjustToClock,
float threshold, bool offsetCalib)
{
int ret, i;
short waveS[2*kNumberOfBins];
ret =
GetWave(waveforms, chipIndex, channel, waveS, responseCalib, triggerCell, wsr, adjustToClock, threshold,
offsetCalib);
if (responseCalib)
for (i = 0; i < fChannelDepth ; i++)
waveform[i] = static_cast < float >(static_cast <short> (waveS[i]) * GetPrecision());
else {
for (i = 0; i < fChannelDepth ; i++) {
if (fBoardType == 4 || fBoardType == 5 || fBoardType == 6 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
waveform[i] = static_cast < float >(waveS[i] * GetPrecision());
} else
waveform[i] = static_cast < float >(waveS[i]);
}
}
return ret;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::GetWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel,
short *waveform, bool responseCalib, int triggerCell, int wsr, bool adjustToClock,
float threshold, bool offsetCalib)
{
unsigned short adcWaveform[kNumberOfBins];
int i, ret;
 
if (fChannelCascading == 1 || channel == 8) {
/* single channel configuration */
ret = DecodeWave(waveforms, chipIndex, channel, adcWaveform);
if (ret != kSuccess)
return ret;
 
ret = CalibrateWaveform(chipIndex, channel, adcWaveform, waveform, responseCalib,
triggerCell, adjustToClock, threshold, offsetCalib);
 
return ret;
} else if (fChannelCascading == 2) {
/* double channel configuration */
short wf1[kNumberOfBins];
short wf2[kNumberOfBins];
 
// first half
ret = DecodeWave(waveforms, chipIndex, 2*channel, adcWaveform);
if (ret != kSuccess)
return ret;
 
ret = CalibrateWaveform(chipIndex, 2*channel, adcWaveform, wf1, responseCalib,
triggerCell, adjustToClock, threshold, offsetCalib);
 
// second half
ret = DecodeWave(waveforms, chipIndex, 2*channel+1, adcWaveform);
if (ret != kSuccess)
return ret;
 
ret = CalibrateWaveform(chipIndex, 2*channel+1, adcWaveform, wf2, responseCalib,
triggerCell, adjustToClock, threshold, offsetCalib);
 
 
// combine two halfs correctly, see 2048_mode.ppt
if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
if ((wsr == 0 && triggerCell < 767) ||
(wsr == 1 && triggerCell >= 767)) {
for (i=0 ; i<kNumberOfBins-triggerCell ; i++)
waveform[i] = wf1[i];
for (; i<kNumberOfBins; i++)
waveform[i] = wf2[i];
for (i=0 ; i<kNumberOfBins-triggerCell ; i++)
waveform[i+kNumberOfBins] = wf2[i];
for (; i<kNumberOfBins; i++)
waveform[i+kNumberOfBins] = wf1[i];
} else {
for (i=0 ; i<kNumberOfBins-triggerCell ; i++)
waveform[i] = wf2[i];
for (; i<kNumberOfBins; i++)
waveform[i] = wf1[i];
for (i=0 ; i<kNumberOfBins-triggerCell ; i++)
waveform[i+kNumberOfBins] = wf1[i];
for (; i<kNumberOfBins; i++)
waveform[i+kNumberOfBins] = wf2[i];
}
} else {
if (wsr == 1) {
if (fDecimation) {
for (i=0 ; i<kNumberOfBins/2-triggerCell/2 ; i++)
waveform[i] = wf1[i];
for (; i<kNumberOfBins/2; i++)
waveform[i] = wf2[i];
for (i=0 ; i<kNumberOfBins/2-triggerCell/2 ; i++)
waveform[i+kNumberOfBins/2] = wf2[i];
for (; i<kNumberOfBins/2; i++)
waveform[i+kNumberOfBins/2] = wf1[i];
} else {
for (i=0 ; i<kNumberOfBins-triggerCell ; i++)
waveform[i] = wf1[i];
for (; i<kNumberOfBins; i++)
waveform[i] = wf2[i];
for (i=0 ; i<kNumberOfBins-triggerCell ; i++)
waveform[i+kNumberOfBins] = wf2[i];
for (; i<kNumberOfBins; i++)
waveform[i+kNumberOfBins] = wf1[i];
}
} else {
if (fDecimation) {
for (i=0 ; i<kNumberOfBins/2-triggerCell/2 ; i++)
waveform[i] = wf2[i];
for (; i<kNumberOfBins/2; i++)
waveform[i] = wf1[i];
for (i=0 ; i<kNumberOfBins/2-triggerCell/2 ; i++)
waveform[i+kNumberOfBins/2] = wf1[i];
for (; i<kNumberOfBins/2; i++)
waveform[i+kNumberOfBins/2] = wf2[i];
} else {
for (i=0 ; i<kNumberOfBins-triggerCell ; i++)
waveform[i] = wf2[i];
for (; i<kNumberOfBins; i++)
waveform[i] = wf1[i];
for (i=0 ; i<kNumberOfBins-triggerCell ; i++)
waveform[i+kNumberOfBins] = wf1[i];
for (; i<kNumberOfBins; i++)
waveform[i+kNumberOfBins] = wf2[i];
}
}
}
 
return ret;
} else
assert(!"Not implemented");
 
return 0;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::GetRawWave(unsigned int chipIndex, unsigned char channel, unsigned short *waveform,
bool adjustToClock)
{
return GetRawWave(fWaveforms, chipIndex, channel, waveform, adjustToClock);
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::GetRawWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel,
unsigned short *waveform, bool adjustToClock)
{
int i, status, tc;
unsigned short wf[kNumberOfBins];
 
status = DecodeWave(waveforms, chipIndex, channel, wf);
 
if (adjustToClock) {
tc = GetTriggerCell(chipIndex);
for (i = 0 ; i < kNumberOfBins; i++)
waveform[(i + tc) % kNumberOfBins] = wf[i];
} else {
for (i = 0 ; i < kNumberOfBins; i++)
waveform[i] = wf[i];
}
 
return status;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::CalibrateWaveform(unsigned int chipIndex, unsigned char channel, unsigned short *adcWaveform,
short *waveform, bool responseCalib,
int triggerCell, bool adjustToClock, float threshold, bool offsetCalib)
{
int j, n_bins, skip;
double value;
short left, right;
 
// calibrate waveform
if (responseCalib && fVoltageCalibrationValid) {
if (GetDRSType() == 4) {
// if Mezz though USB2 -> select correct calibration channel
if (fBoardType == 6 && (fReadoutChannelConfig == 0 || fReadoutChannelConfig == 2) &&
channel != 8)
channel++;
 
// Channel readout mode #4 -> select correct calibration channel
if (fBoardType == 6 && fReadoutChannelConfig == 4 && channel % 2 == 0 && channel != 8)
channel++;
 
n_bins = fDecimation ? kNumberOfBins/2 : kNumberOfBins;
skip = fDecimation ? 2 : 1;
for (j = 0; j < n_bins; j++) {
value = adcWaveform[j] - fCellOffset[channel+chipIndex*9][(j*skip + triggerCell) % kNumberOfBins];
value = value / fCellGain[channel+chipIndex*9][(j*skip + triggerCell) % kNumberOfBins];
if (offsetCalib && channel != 8)
value = value - fCellOffset2[channel+chipIndex*9][j*skip] + 32768;
 
/* convert to units of 0.1 mV */
value = value / 65536.0 * 1000 * 10;
 
/* apply clipping */
if (channel != 8) {
if (adcWaveform[j] >= 0xFFF0 || value > (fRange * 1000 + 500) * 10)
value = (fRange * 1000 + 500) * 10;
if (adcWaveform[j] < 0x0010 || value < (fRange * 1000 - 500) * 10)
value = (fRange * 1000 - 500) * 10;
}
 
if (adjustToClock)
waveform[(j + triggerCell) % kNumberOfBins] = (short) (value + 0.5);
else
waveform[j] = (short) (value + 0.5);
}
 
// check for stuck pixels and replace by average of neighbors
for (j = 0 ; j < n_bins; j++) {
if (adjustToClock) {
if (fCellOffset[channel+chipIndex*9][j*skip] == 0) {
left = waveform[(j-1+kNumberOfBins) % kNumberOfBins];
right = waveform[(j+1) % kNumberOfBins];
waveform[j] = (short) ((left+right)/2);
}
} else {
if (fCellOffset[channel+chipIndex*9][(j*skip + triggerCell) % kNumberOfBins] == 0) {
left = waveform[(j-1+kNumberOfBins) % kNumberOfBins];
right = waveform[(j+1) % kNumberOfBins];
waveform[j] = (short) ((left+right)/2);
}
}
}
 
} else {
if (!fResponseCalibration->
Calibrate(chipIndex, channel % 10, adcWaveform, waveform, triggerCell, threshold, offsetCalib))
return kZeroSuppression; // return immediately if below threshold
}
} else {
if (GetDRSType() == 4) {
// if Mezz though USB2 -> select correct calibration channel
if (fBoardType == 6 && (fReadoutChannelConfig == 0 || fReadoutChannelConfig == 2) &&
channel != 8)
channel++;
for (j = 0 ; j < kNumberOfBins; j++) {
value = adcWaveform[j];
 
/* convert to units of 0.1 mV */
value = (value - 32768) / 65536.0 * 1000 * 10;
 
/* correct for range */
value += fRange * 1000 * 10;
 
if (adjustToClock)
waveform[(j + triggerCell) % kNumberOfBins] = (short) (value + 0.5);
else
waveform[j] = (short) (value + 0.5);
}
} else {
for (j = 0; j < kNumberOfBins; j++) {
if (adjustToClock) {
// rotate waveform such that waveform[0] corresponds to bin #0 on the chip
waveform[j] = adcWaveform[(kNumberOfBins-triggerCell+j) % kNumberOfBins];
} else {
waveform[j] = adcWaveform[j];
}
}
}
}
 
// fix bad cells for single turn mode
if (GetDRSType() == 2) {
if (fDominoMode == 0 && triggerCell == -1) {
waveform[0] = 2 * waveform[1] - waveform[2];
short m1 = (waveform[kNumberOfBins - 5] + waveform[kNumberOfBins - 6]) / 2;
short m2 = (waveform[kNumberOfBins - 6] + waveform[kNumberOfBins - 7]) / 2;
waveform[kNumberOfBins - 4] = m1 - 1 * (m2 - m1);
waveform[kNumberOfBins - 3] = m1 - 2 * (m2 - m1);
waveform[kNumberOfBins - 2] = m1 - 3 * (m2 - m1);
waveform[kNumberOfBins - 1] = m1 - 4 * (m2 - m1);
}
}
 
return kSuccess;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::GetStretchedTime(float *time, float *measurement, int numberOfMeasurements, float period)
{
int j;
if (*time >= measurement[numberOfMeasurements - 1]) {
*time -= measurement[numberOfMeasurements - 1];
return 1;
}
if (*time < measurement[0]) {
*time = *time - measurement[0] - (numberOfMeasurements - 1) * period / 2;
return 1;
}
for (j = 0; j < numberOfMeasurements - 1; j++) {
if (*time > measurement[j] && *time <= measurement[j + 1]) {
*time =
(period / 2) / (measurement[j + 1] - measurement[j]) * (*time - measurement[j + 1]) -
(numberOfMeasurements - 2 - j) * period / 2;
return 1;
}
}
return 0;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::GetTriggerCell(unsigned int chipIndex)
{
if (fDRSType == 4)
return GetStopCell(chipIndex);
 
return GetTriggerCell(fWaveforms, chipIndex);
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::GetTriggerCell(unsigned char *waveforms, unsigned int chipIndex)
{
int j, triggerCell;
bool calib;
unsigned short baseLevel = 1000;
unsigned short triggerChannel[1024];
 
if (fDRSType == 4)
return GetStopCell(chipIndex);
 
GetRawWave(waveforms, chipIndex, 8, triggerChannel);
calib = fResponseCalibration->SubtractADCOffset(chipIndex, 8, triggerChannel, triggerChannel, baseLevel);
 
triggerCell = -1;
for (j = 0; j < kNumberOfBins; j++) {
if (calib) {
if (triggerChannel[j] <= baseLevel + 200
&& triggerChannel[(j + 1) % kNumberOfBins] > baseLevel + 200) {
triggerCell = j;
break;
}
} else {
if (fDRSType == 3) {
if (triggerChannel[j] <= 2000 && triggerChannel[(j + 1) % kNumberOfBins] > 2000) {
triggerCell = j;
break;
}
} else {
if (triggerChannel[j] >= 2000 && triggerChannel[(j + 1) % kNumberOfBins] < 2000) {
triggerCell = j;
break;
}
}
}
}
if (triggerCell == -1) {
return kInvalidTriggerSignal;
}
fStopCell[0] = triggerCell;
return triggerCell;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::GetStopCell(unsigned int chipIndex)
{
return fStopCell[chipIndex];
}
 
/*------------------------------------------------------------------*/
 
unsigned char DRSBoard::GetStopWSR(unsigned int chipIndex)
{
return fStopWSR[chipIndex];
}
 
/*------------------------------------------------------------------*/
 
void DRSBoard::TestDAC(int channel)
{
// Test DAC
int status;
 
do {
status = SetDAC(channel, 0);
Sleep(1000);
status = SetDAC(channel, 0.5);
Sleep(1000);
status = SetDAC(channel, 1);
Sleep(1000);
status = SetDAC(channel, 1.5);
Sleep(1000);
status = SetDAC(channel, 2);
Sleep(1000);
status = SetDAC(channel, 2.5);
Sleep(1000);
} while (status);
}
 
/*------------------------------------------------------------------*/
 
void DRSBoard::MeasureSpeed()
{
// Measure domino sampling speed
FILE *f;
double vdr, vds, freq;
 
f = fopen("speed.txt", "wt");
fprintf(f, "\t");
printf("\t");
for (vdr = 0.5; vdr <= 2.501; vdr += 0.05) {
fprintf(f, "%1.2lf\t", vdr);
printf("%1.2lf\t", vdr);
}
fprintf(f, "\n");
printf("\n");
 
for (vds = 0.5; vds <= 2.501; vds += 0.05) {
fprintf(f, "%1.2lf\t", vds);
printf("%1.2lf\t", vds);
 
SetDAC(fDAC_DSA, vds);
StartDomino();
Sleep(1000);
ReadFrequency(0, &freq);
 
fprintf(f, "%1.3lf\t", freq);
printf("%1.3lf\t", freq);
 
fprintf(f, "\n");
printf("\n");
fflush(f);
}
}
 
/*------------------------------------------------------------------*/
 
void DRSBoard::InteractSpeed()
{
int status, i;
double freq, vds;
 
do {
printf("DS: ");
scanf("%lf", &vds);
if (vds == 0)
break;
 
SetDAC(fDAC_DSA, vds);
SetDAC(fDAC_DSB, vds);
 
StartDomino();
for (i = 0; i < 4; i++) {
Sleep(1000);
 
status = ReadFrequency(0, &freq);
if (!status)
break;
printf("%1.6lf GHz\n", freq);
}
 
/* turn BOARD_LED off */
SetLED(0);
 
} while (1);
}
 
/*------------------------------------------------------------------*/
 
void DRSBoard::MonitorFrequency()
{
// Monitor domino sampling frequency
int status;
unsigned int data;
double freq, dac;
FILE *f;
time_t now;
char str[256];
 
f = fopen("DRSBoard.log", "w");
 
do {
Sleep(1000);
 
status = ReadFrequency(0, &freq);
if (!status)
break;
 
data = 0;
if (fBoardType == 1)
Read(T_STATUS, &data, REG_RDAC3, 2);
else if (fBoardType == 2 || fBoardType == 3)
Read(T_STATUS, &data, REG_RDAC1, 2);
 
dac = data / 65536.0 * 2.5;
printf("%1.6lf GHz, %1.4lf V\n", freq, dac);
time(&now);
strcpy(str, ctime(&now) + 11);
str[8] = 0;
 
fprintf(f, "%s %1.6lf GHz, %1.4lf V\n", str, freq, dac);
fflush(f);
 
} while (!drs_kbhit());
 
fclose(f);
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::TestShift(int n)
{
// Test shift register
unsigned char buffer[3];
 
memset(buffer, 0, sizeof(buffer));
 
#if 0
buffer[0] = CMD_TESTSHIFT;
buffer[1] = n;
 
status = msend_usb(buffer, 2);
if (status != 2)
return status;
 
status = mrecv_usb(buffer, sizeof(buffer));
if (status != 1)
return status;
#endif
 
if (buffer[0] == 1)
printf("Shift register %c works correctly\n", 'A' + n);
else if (buffer[0] == 2)
printf("SROUT%c does hot go high after reset\n", 'A' + n);
else if (buffer[0] == 3)
printf("SROUT%c does hot go low after 1024 clocks\n", 'A' + n);
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
unsigned int DRSBoard::GetCtrlReg()
{
unsigned int status;
 
Read(T_CTRL, &status, REG_CTRL, 4);
return status;
}
 
/*------------------------------------------------------------------*/
 
unsigned short DRSBoard::GetConfigReg()
{
unsigned short status;
 
Read(T_CTRL, &status, REG_CONFIG, 2);
return status;
}
 
/*------------------------------------------------------------------*/
 
unsigned int DRSBoard::GetStatusReg()
{
unsigned int status;
 
Read(T_STATUS, &status, REG_STATUS, 4);
return status;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::EnableTcal(int freq, int level, int phase)
{
fTcalFreq = freq;
fTcalLevel = level;
fTcalPhase = phase;
 
if (fBoardType == 6) {
ConfigureLMK(fNominalFrequency, false, freq, phase);
} else {
if (fBoardType == 9) {
// Enable clock a switch channel multiplexers
if (freq) {
fCtrlBits |= (BIT_TCAL_EN | BIT_ACAL_EN);
} else
fCtrlBits &= ~(BIT_TCAL_EN | BIT_ACAL_EN);
} else {
// Enable clock channel
if (freq)
fCtrlBits |= BIT_TCAL_EN;
else
fCtrlBits &= ~(BIT_TCAL_EN | BIT_TCAL_SOURCE);
// Set output level, needed for gain calibration
if (fDRSType == 4) {
if (level)
fCtrlBits |= BIT_NEG_TRIGGER;
else
fCtrlBits &= ~BIT_NEG_TRIGGER;
}
}
 
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
}
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SelectClockSource(int source)
{
fTcalSource = source;
 
// Select clock source:
// EVAL1: synchronous (0) or asynchronous (1) (2nd quartz)
if (fBoardType <= 8) {
if (source)
fCtrlBits |= BIT_TCAL_SOURCE;
else
fCtrlBits &= ~BIT_TCAL_SOURCE;
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
}
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetRefclk(int source)
{
// Select reference clock source to internal FPGA (0) or external P2 (1)
if (fBoardType == 6) {
if (source)
fCtrlBits |= BIT_REFCLK_SOURCE;
else
fCtrlBits &= ~BIT_REFCLK_SOURCE;
} else if (fBoardType == 8 || fBoardType == 9) {
if (source)
fCtrlBits |= BIT_REFCLK_EXT;
else
fCtrlBits &= ~BIT_REFCLK_EXT;
}
 
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
fRefclk = source;
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::EnableAcal(int mode, double voltage)
{
double t1, t2;
 
fAcalMode = mode;
fAcalVolt = voltage;
 
if (mode == 0) {
/* turn calibration off */
SetCalibTiming(0, 0);
if (fBoardType == 5 || fBoardType == 6) {
/* turn voltages off (50 Ohm analog switch!) */
SetDAC(fDAC_CALP, 0);
SetDAC(fDAC_CALN, 0);
}
if (fBoardType == 7 || fBoardType == 8 || fBoardType == 9)
SetCalibVoltage(0);
 
fCtrlBits &= ~BIT_ACAL_EN;
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
} else if (mode == 1) {
/* static calibration */
SetCalibVoltage(voltage);
SetCalibTiming(0, 0);
fCtrlBits |= BIT_ACAL_EN;
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
} else if (mode == 2) {
/* first part calibration:
stop domino wave after 1.2 revolutions
turn on calibration voltage after 0.1 revolutions */
 
/* ensure circulating domino wave */
SetDominoMode(1);
 
/* set calibration voltage but do not turn it on now */
SetCalibVoltage(voltage);
fCtrlBits &= ~BIT_ACAL_EN;
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
 
/* calculate duration of DENABLE signal as 1.2 revolutions */
t1 = 1 / fNominalFrequency * 1024 * 1.2; // ns
t1 = static_cast < int >((t1 - 30) / 30 + 1); // 30 ns offset, 30 ns units, rounded up
t2 = 1 / fNominalFrequency * 1024 * 0.1; // ns
t2 = static_cast < int >((t2 - 30) / 30 + 1); // 30 ns offset, 30 ns units, rounded up
SetCalibTiming(static_cast < int >(t1), static_cast < int >(t2));
 
} else if (mode == 3) {
/* second part calibration:
stop domino wave after 1.05 revolutions */
 
/* ensure circulating domino wave */
SetDominoMode(1);
 
/* turn on and let settle calibration voltage */
SetCalibVoltage(voltage);
fCtrlBits |= BIT_ACAL_EN;
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
 
/* calculate duration of DENABLE signal as 1.1 revolutions */
t1 = 1 / fNominalFrequency * 1024 * 1.05; // ns
t1 = static_cast < int >((t1 - 30) / 30 + 1); // 30 ns offset, 30 ns units, rounded up
SetCalibTiming(static_cast < int >(t1), 0);
}
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetCalibTiming(int t_enable, int t_cal)
{
unsigned short d;
 
if (fDRSType == 2) {
d = t_cal | (t_enable << 8);
Write(T_CTRL, REG_CALIB_TIMING, &d, 2);
}
 
if (fDRSType == 3) {
d = t_cal;
Write(T_CTRL, REG_CALIB_TIMING, &d, 2);
}
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetCalibVoltage(double value)
{
// Set Calibration Voltage
if (fBoardType == 5 || fBoardType == 6 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
if (fBoardType == 5)
value = value * (1+fNominalFrequency/65); // rough correction factor for input current
if (fBoardType == 7 || fBoardType == 8 || fBoardType == 9)
value = value * (1+fNominalFrequency/47); // rough correction factor for input current
SetDAC(fDAC_CALP, fCommonMode + value / 2);
SetDAC(fDAC_CALN, fCommonMode - value / 2);
} else
SetDAC(fDAC_ACALIB, value);
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::StartClearCycle()
{
/* clear cycle is necessary for DRS4 to reduce noise */
 
fbkAcalVolt = fAcalVolt;
fbkAcalMode = fAcalMode;
fbkTcalFreq = fTcalFreq;
fbkTcalLevel = fTcalLevel;
 
/* switch all inputs to zero */
EnableAcal(1, 0);
 
/* start, stop and readout of zero */
StartDomino();
SoftTrigger();
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::FinishClearCycle()
{
while (IsBusy());
 
/* restore old values */
EnableAcal(fbkAcalMode, fbkAcalVolt);
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
double DRSBoard::GetTemperature()
{
// Read Out Temperature Sensor
unsigned char buffer[2];
unsigned short d;
double temperature;
 
Read(T_STATUS, buffer, REG_TEMPERATURE, 2);
 
d = (static_cast < unsigned int >(buffer[1]) << 8) +buffer[0];
temperature = ((d >> 3) & 0x0FFF) * 0.0625;
 
return temperature;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::Is2048ModeCapable()
{
unsigned int status;
if (fFirmwareVersion < 21305)
return 0;
// Read pin J44 and return 1 if 2048 mode has been soldered
Read(T_STATUS, &status, REG_STATUS, 4);
if ((status & BIT_2048_MODE))
return 0;
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::GetTriggerBus()
{
unsigned size, d;
 
if (fBoardType == 6 && fTransport == TR_VME) {
if (fReadoutChannelConfig == 4)
size = (20 * sizeof(short int) * (fDecimation ? kNumberOfBins/2 : kNumberOfBins) + 16);
else
size = (36 * sizeof(short int) * (fDecimation ? kNumberOfBins/2 : kNumberOfBins) + 16);
 
Read(T_RAM, &d, size * fReadPointer + size - 16 + 12, 4);
fTriggerBus = (unsigned short)d;
} else {
Read(T_STATUS, &fTriggerBus, REG_TRIGGER_BUS, 2);
}
return static_cast < int >(fTriggerBus);
}
 
 
/*------------------------------------------------------------------*/
 
unsigned int DRSBoard::GetScaler(int channel)
{
int reg = 0;
unsigned d;
if (fBoardType < 9 || fFirmwareVersion < 21000 || fTransport != TR_USB2)
return 0;
switch (channel ) {
case 0: reg = REG_SCALER0; break;
case 1: reg = REG_SCALER1; break;
case 2: reg = REG_SCALER2; break;
case 3: reg = REG_SCALER3; break;
case 4: reg = REG_SCALER4; break;
case 5: reg = REG_SCALER5; break;
}
Read(T_STATUS, &d, reg, 4);
 
return static_cast < unsigned int >(d * 10); // measurement clock is 10 Hz
}
 
 
/*------------------------------------------------------------------*/
 
int DRSBoard::SetBoardSerialNumber(unsigned short serialNumber)
{
unsigned char buf[32768];
 
unsigned short dac;
 
if (fDRSType < 4) {
// read current DAC register
Read(T_CTRL, &dac, REG_DAC0, 2);
 
// put serial in DAC register
Write(T_CTRL, REG_DAC0, &serialNumber, 2);
 
// execute flash
fCtrlBits |= BIT_EEPROM_WRITE_TRIG;
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
fCtrlBits &= ~BIT_EEPROM_WRITE_TRIG;
 
// wait 6ms per word
Sleep(20);
 
// write back old DAC registers
Write(T_CTRL, REG_DAC0, &dac, 2);
 
// read back serial number
ReadSerialNumber();
 
} else if (fDRSType == 4) {
/* merge serial number into eeprom page #0 */
ReadEEPROM(0, buf, sizeof(buf));
buf[0] = serialNumber & 0xFF;
buf[1] = serialNumber >> 8;
WriteEEPROM(0, buf, sizeof(buf));
 
/* erase DPRAM */
memset(buf, 0, sizeof(buf));
Write(T_RAM, 0, buf, sizeof(buf));
 
/* read back EEPROM */
ReadEEPROM(0, buf, sizeof(buf));
 
/* check if correctly set */
if (((buf[1] << 8) | buf[0]) != serialNumber)
return 0;
 
fBoardSerialNumber = serialNumber;
}
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::ReadEEPROM(unsigned short page, void *buffer, int size)
{
int i;
unsigned long status;
// write eeprom page number
if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9)
Write(T_CTRL, REG_EEPROM_PAGE_EVAL, &page, 2);
else if (fBoardType == 6)
Write(T_CTRL, REG_EEPROM_PAGE_MEZZ, &page, 2);
else
return -1;
 
// execute eeprom read
fCtrlBits |= BIT_EEPROM_READ_TRIG;
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
fCtrlBits &= ~BIT_EEPROM_READ_TRIG;
 
// poll on serial_busy flag
for (i=0 ; i<100 ; i++) {
Read(T_STATUS, &status, REG_STATUS, 4);
if ((status & BIT_SERIAL_BUSY) == 0)
break;
Sleep(10);
}
 
return Read(T_RAM, buffer, 0, size);
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::WriteEEPROM(unsigned short page, void *buffer, int size)
{
int i;
unsigned long status;
unsigned char buf[32768];
 
// read previous page
ReadEEPROM(page, buf, sizeof(buf));
// combine with new page
memcpy(buf, buffer, size);
// write eeprom page number
if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9)
Write(T_CTRL, REG_EEPROM_PAGE_EVAL, &page, 2);
else if (fBoardType == 6)
Write(T_CTRL, REG_EEPROM_PAGE_MEZZ, &page, 2);
else
return -1;
 
// write eeprom page to RAM
Write(T_RAM, 0, buf, size);
 
// execute eeprom write
fCtrlBits |= BIT_EEPROM_WRITE_TRIG;
Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
fCtrlBits &= ~BIT_EEPROM_WRITE_TRIG;
 
// poll on serail_busy flag
for (i=0 ; i<500 ; i++) {
Read(T_STATUS, &status, REG_STATUS, 4);
if ((status & BIT_SERIAL_BUSY) == 0)
break;
Sleep(10);
}
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
bool DRSBoard::IsTimingCalibrationValid()
{
return fabs(fNominalFrequency - fTimingCalibratedFrequency) < 0.001;
}
 
double DRSBoard::GetTrueFrequency()
{
int i;
double f;
if (IsTimingCalibrationValid()) {
/* calculate true frequency */
for (i=0,f=0 ; i<1024 ; i++)
f += fCellDT[0][0][i];
f = 1024.0 / f;
} else
f = fNominalFrequency;
return f;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::GetTime(unsigned int chipIndex, int channelIndex, int tc, float *time, bool tcalibrated, bool rotated)
{
int i, scale, iend;
double gt0, gt;
 
/* for DRS2, please use function below */
if (fDRSType < 4)
return GetTime(chipIndex, channelIndex, fNominalFrequency, tc, time, tcalibrated, rotated);
 
scale = fDecimation ? 2 : 1;
 
if (!IsTimingCalibrationValid() || !tcalibrated) {
double t0 = tc / fNominalFrequency;
for (i = 0; i < fChannelDepth; i++) {
if (rotated)
time[i] = static_cast < float >(((i*scale+tc) % kNumberOfBins) / fNominalFrequency - t0);
else
time[i] = static_cast < float >((i*scale) / fNominalFrequency);
if (time[i] < 0)
time[i] += static_cast < float > (kNumberOfBins / fNominalFrequency);
if (i*scale >= kNumberOfBins)
time[i] += static_cast < float > (kNumberOfBins / fNominalFrequency);
}
return 1;
}
 
time[0] = 0;
for (i=1 ; i<fChannelDepth ; i++) {
if (rotated)
time[i] = time[i-1] + (float)fCellDT[chipIndex][channelIndex][(i-1+tc) % kNumberOfBins];
else
time[i] = time[i-1] + (float)fCellDT[chipIndex][channelIndex][(i-1) % kNumberOfADCBins];
}
 
if (channelIndex > 0) {
// correct all channels to channel 0 (Daniel's method)
iend = tc >= 700 ? 700+1024 : 700;
for (i=tc,gt0=0 ; i<iend ; i++)
gt0 += fCellDT[chipIndex][0][i % 1024];
for (i=tc,gt=0 ; i<iend ; i++)
gt += fCellDT[chipIndex][channelIndex][i % 1024];
for (i=0 ; i<fChannelDepth ; i++)
time[i] += (float)(gt0 - gt);
}
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::GetTimeCalibration(unsigned int chipIndex, int channelIndex, int mode, float *time, bool force)
{
int i;
float tint;
 
/* not implemented for DRS2 */
if (fDRSType < 4)
return -1;
 
if (!force && !IsTimingCalibrationValid()) {
for (i = 0; i < kNumberOfBins; i++)
time[i] = (float) (1/fNominalFrequency);
return 1;
}
 
if (mode == 0) {
/* differential nonlinearity */
for (i=0 ; i<kNumberOfBins ; i++)
time[i] = static_cast < float > (fCellDT[chipIndex][channelIndex][i]);
} else {
/* integral nonlinearity */
for (i=0,tint=0; i<kNumberOfBins ; i++) {
time[i] = static_cast < float > (tint - i/fNominalFrequency);
tint += (float)fCellDT[chipIndex][channelIndex][i];
}
}
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::GetTime(unsigned int chipIndex, int channelIndex, double freqGHz, int tc, float *time, bool tcalibrated, bool rotated)
{
/* for DRS4, use function above */
if (fDRSType == 4)
return GetTime(chipIndex, channelIndex, tc, time, tcalibrated, rotated);
 
int i, irot;
DRSBoard::TimeData * init;
DRSBoard::TimeData::FrequencyData * freq;
int frequencyMHz = (int)(freqGHz*1000);
 
init = GetTimeCalibration(chipIndex);
 
if (init == NULL) {
for (i = 0; i < kNumberOfBins; i++)
time[i] = static_cast < float >(i / fNominalFrequency);
return 1;
}
freq = NULL;
for (i = 0; i < init->fNumberOfFrequencies; i++) {
if (init->fFrequency[i]->fFrequency == frequencyMHz) {
freq = init->fFrequency[i];
break;
}
}
if (freq == NULL) {
for (i = 0; i < kNumberOfBins; i++)
time[i] = static_cast < float >(i / fNominalFrequency);
return 1;
}
for (i = 0; i < kNumberOfBins; i++) {
irot = (fStopCell[chipIndex] + i) % kNumberOfBins;
if (fStopCell[chipIndex] + i < kNumberOfBins)
time[i] = static_cast < float >((freq->fBin[irot] - freq->fBin[fStopCell[chipIndex]]) / fNominalFrequency);
else
time[i] =
static_cast <
float
>((freq->fBin[irot] - freq->fBin[fStopCell[chipIndex]] + freq->fBin[kNumberOfBins - 1] - 2 * freq->fBin[0] +
freq->fBin[1]) / fNominalFrequency);
}
return 1;
}
 
/*------------------------------------------------------------------*/
 
bool DRSBoard::InitTimeCalibration(unsigned int chipIndex)
{
return GetTimeCalibration(chipIndex, true) != NULL;
}
 
/*------------------------------------------------------------------*/
 
DRSBoard::TimeData * DRSBoard::GetTimeCalibration(unsigned int chipIndex, bool reinit)
{
int i, l, index;
char *cstop;
char fileName[500];
char error[240];
PMXML_NODE node, rootNode, mainNode;
 
index = fNumberOfTimeData;
for (i = 0; i < fNumberOfTimeData; i++) {
if (fTimeData[i]->fChip == static_cast < int >(chipIndex)) {
if (!reinit)
return fTimeData[i];
else {
index = i;
break;
}
}
}
 
fTimeData[index] = new DRSBoard::TimeData();
DRSBoard::TimeData * init = fTimeData[index];
 
init->fChip = chipIndex;
 
for (i = 0; i < init->kMaxNumberOfFrequencies; i++) {
if (i <= 499 || (i >= 501 && i <= 999) || (i >= 1001 && i <= 1499) || (i >= 1501 && i <= 1999) ||
(i >= 2001 && i <= 2499) || i >= 2501)
continue;
sprintf(fileName, "%s/board%d/TimeCalib_board%d_chip%d_%dMHz.xml", fCalibDirectory, fBoardSerialNumber,
fBoardSerialNumber, chipIndex, i);
rootNode = mxml_parse_file(fileName, error, sizeof(error), NULL);
if (rootNode == NULL)
continue;
 
init->fFrequency[init->fNumberOfFrequencies] = new DRSBoard::TimeData::FrequencyData();
init->fFrequency[init->fNumberOfFrequencies]->fFrequency = i;
 
mainNode = mxml_find_node(rootNode, "/DRSTimeCalibration");
 
for (l = 0; l < kNumberOfBins; l++) {
node = mxml_subnode(mainNode, l + 2);
init->fFrequency[init->fNumberOfFrequencies]->fBin[l] = strtod(mxml_get_value(node), &cstop);
}
mxml_free_tree(rootNode);
init->fNumberOfFrequencies++;
}
if (init->fNumberOfFrequencies == 0) {
printf("Board %d --> Could not find time calibration file\n", GetBoardSerialNumber());
}
 
if (index == fNumberOfTimeData)
fNumberOfTimeData++;
 
return fTimeData[index];
}
 
/*------------------------------------------------------------------*/
 
void DRSBoard::SetCalibrationDirectory(const char *calibrationDirectoryPath)
{
strncpy(fCalibDirectory, calibrationDirectoryPath, strlen(calibrationDirectoryPath));
fCalibDirectory[strlen(calibrationDirectoryPath)] = 0;
};
 
/*------------------------------------------------------------------*/
 
void DRSBoard::GetCalibrationDirectory(char *calibrationDirectoryPath)
{
strncpy(calibrationDirectoryPath, fCalibDirectory, strlen(fCalibDirectory));
calibrationDirectoryPath[strlen(fCalibDirectory)] = 0;
};
 
/*------------------------------------------------------------------*/
 
void DRSBoard::LinearRegression(double *x, double *y, int n, double *a, double *b)
{
int i;
double sx, sxx, sy, sxy;
 
sx = sxx = sy = sxy = 0;
for (i = 0; i < n; i++) {
sx += x[i];
sxx += x[i] * x[i];
sy += y[i];
sxy += x[i] * y[i];
}
 
*a = (n * sxy - sx * sy) / (n * sxx - sx * sx);
*b = (sy - *a * sx) / n;
}
 
/*------------------------------------------------------------------*/
 
void DRSBoard::ReadSingleWaveform(int nChip, int nChan,
unsigned short wf[kNumberOfChipsMax][kNumberOfChannelsMax][kNumberOfBins],
bool rotated)
{
int i, j, k, tc;
 
StartDomino();
SoftTrigger();
while (IsBusy());
TransferWaves();
 
for (i=0 ; i<nChip ; i++) {
tc = GetTriggerCell(i);
 
for (j=0 ; j<nChan ; j++) {
GetRawWave(i, j, wf[i][j], rotated);
if (!rotated) {
for (k=0 ; k<kNumberOfBins ; k++) {
/* do primary offset calibration */
wf[i][j][k] = wf[i][j][k] - fCellOffset[j+i*9][(k + tc) % kNumberOfBins] + 32768;
}
}
}
}
}
static unsigned short swf[kNumberOfChipsMax][kNumberOfChannelsMax][kNumberOfBins];
static float center[kNumberOfChipsMax][kNumberOfChannelsMax][kNumberOfBins];
 
int DRSBoard::AverageWaveforms(DRSCallback *pcb, int nChip, int nChan,
int prog1, int prog2, unsigned short *awf, int n, bool rotated)
{
int i, j, k, l, prog, old_prog = 0;
float cm;
 
if (pcb != NULL)
pcb->Progress(prog1);
 
memset(center, 0, sizeof(center));
 
for (i=0 ; i<n; i++) {
ReadSingleWaveform(nChip, nChan, swf, rotated);
 
for (j=0 ; j<nChip ; j++) {
for (k=0 ; k<nChan ; k++) {
if (i > 5) {
/* calculate and subtract common mode */
for (l=0,cm=0 ; l<kNumberOfBins ; l++)
cm += swf[j][k][l] - 32768;
cm /= kNumberOfBins;
for (l=0 ; l<kNumberOfBins ; l++)
center[j][k][l] += swf[j][k][l]- cm;
}
}
}
 
prog = (int)(((double)i/n)*(prog2-prog1)+prog1);
if (prog > old_prog) {
old_prog = prog;
if (pcb != NULL)
pcb->Progress(prog);
}
}
 
for (i=0 ; i<nChip ; i++)
for (j=0 ; j<nChan ; j++)
for (k=0 ; k<kNumberOfBins ; k++)
awf[(i*nChan+j)*kNumberOfBins+k] = (unsigned short)(center[i][j][k]/(n-6) + 0.5);
return 1;
}
 
int DRSBoard::RobustAverageWaveforms(DRSCallback *pcb, int nChip, int nChan,
int prog1, int prog2, unsigned short *awf, int n, bool rotated)
{
int i, j, k, l, prog, old_prog = 0;
 
if (pcb != NULL)
pcb->Progress(prog1);
 
Averager *ave = new Averager(nChip, nChan, kNumberOfBins, 200);
/* fill histograms */
for (i=0 ; i<n ; i++) {
ReadSingleWaveform(nChip, nChan, swf, rotated);
for (j=0 ; j<nChip ; j++)
for (k=0 ; k<nChan ; k++)
for (l=0 ; l<kNumberOfBins ; l++)
ave->Add(j, k, l, swf[j][k][l]);
/* update progress bar */
prog = (int)(((double)(i+10)/(n+10))*(prog2-prog1)+prog1);
if (prog > old_prog) {
old_prog = prog;
if (pcb != NULL)
pcb->Progress(prog);
}
}
 
/*
FILE *fh = fopen("calib.csv", "wt");
for (i=40 ; i<60 ; i++) {
for (j=0 ; j<WFH_SIZE ; j++)
fprintf(fh, "%d;", wfh[0][0][i][j]);
fprintf(fh, "\n");
}
fclose(fh);
*/
 
for (i=0 ; i<nChip ; i++)
for (j=0 ; j<nChan ; j++)
for (k=0 ; k<kNumberOfBins ; k++)
awf[(i*nChan+j)*kNumberOfBins+k] = (unsigned short)ave->RobustAverage(100, i, j, k);
 
ave->SaveNormalizedDistribution("wv.csv", 0, 100);
/*
FILE *fh = fopen("calib.csv", "wt");
for (i=40 ; i<60 ; i++) {
fprintf(fh, "%d;", icenter[0][0][0] + (i - WFH_SIZE/2)*16);
fprintf(fh, "%d;", wfh[0][0][0][i]);
if (i == 50)
fprintf(fh, "%d;", awf[0]);
fprintf(fh, "\n");
}
fclose(fh);
*/
 
if (pcb != NULL)
pcb->Progress(prog2);
delete ave;
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int idx[4][10] = {
{ 0, 2, 4, 6, 8, 18, 20, 22, 24, 26 },
{ 1, 3, 5, 7, 39, 19, 21, 23, 25, 39 },
{ 9, 11, 13, 15, 17, 27, 29, 31, 33, 35 },
{ 10, 12, 14, 16, 39, 28, 30, 32, 34, 39 },
};
 
#define F1(x) ((int) (84.0/24 * (x)))
#define F2(x) ((int) (92.0/8 * (x)))
 
static unsigned short wft[kNumberOfChipsMax*kNumberOfChannelsMax*kNumberOfChipsMax][1024],
wf1[kNumberOfChipsMax*kNumberOfChannelsMax*kNumberOfChipsMax][1024],
wf2[kNumberOfChipsMax*kNumberOfChannelsMax*kNumberOfChipsMax][1024],
wf3[kNumberOfChipsMax*kNumberOfChannelsMax*kNumberOfChipsMax][1024];
 
int DRSBoard::CalibrateVolt(DRSCallback *pcb)
{
int i, j, nChan, timingChan, chip, config, p, clkon, refclk, trg1, trg2, n_stuck, readchn, casc;
double f, r;
unsigned short buf[1024*16]; // 32 kB
f = fNominalFrequency;
r = fRange;
clkon = (GetCtrlReg() & BIT_TCAL_EN) > 0;
refclk = (GetCtrlReg() & BIT_REFCLK_SOURCE) > 0;
trg1 = fTriggerEnable1;
trg2 = fTriggerEnable2;
readchn = fNumberOfReadoutChannels;
casc = fChannelCascading;
 
Init();
fNominalFrequency = f;
SetRefclk(refclk);
SetFrequency(fNominalFrequency, true);
SetDominoMode(1);
SetDominoActive(1);
SetReadoutMode(1);
SetInputRange(r);
if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9)
SelectClockSource(0);
else if (fBoardType == 6)
SetRefclk(refclk);
EnableTrigger(0, 0);
if (readchn == 5)
SetChannelConfig(4, 8, 8); // even channel readout mode
// WSROUT toggling causes some noise, so calibrate that out
if (casc == 2) {
if (fTransport == TR_USB2)
SetChannelConfig(0, 8, 4);
else
SetChannelConfig(7, 8, 4);
}
 
StartDomino();
 
nChan = 0;
timingChan = 0;
 
if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
if (fBoardType == 9) {
nChan = 8;
timingChan = -1;
} else {
nChan = 9;
timingChan = 8;
}
 
/* measure offset */
if (fBoardType == 5)
EnableAcal(0, 0); // no inputs signal is allowed during calibration!
else
EnableAcal(1, 0); // disconnect analog inputs
EnableTcal(0, 0);
Sleep(100);
RobustAverageWaveforms(pcb, 1, nChan, 0, 25, wf1[0], 200, true);
 
/* measure gain at upper range */
EnableAcal(1, fRange+0.4);
EnableTcal(0, 1);
Sleep(100);
RobustAverageWaveforms(pcb, 1, nChan, 25, 50, wf2[0], 200, true);
 
} else if (fBoardType == 6) {
if (fTransport == TR_USB2) {
nChan = 36;
timingChan = 8;
memset(wf1, 0, sizeof(wf1));
memset(wf2, 0, sizeof(wf2));
memset(wf3, 0, sizeof(wf3));
for (config=p=0 ; config<4 ; config++) {
SetChannelConfig(config, 8, 8);
 
/* measure offset */
EnableAcal(1, 0);
EnableTcal(0, 0);
Sleep(100);
RobustAverageWaveforms(pcb, 0, 10, F1(p), F1(p+1), wft[0], 500, true); p++;
for (i=0 ; i<5 ; i++)
memcpy(wf1[idx[config][i]], wft[i*2], sizeof(float)*kNumberOfBins);
RobustAverageWaveforms(pcb, 2, 10, F1(p), F1(p+1), wft[0], 500, true); p++;
for (i=0 ; i<5 ; i++)
memcpy(wf1[idx[config][i+5]], wft[i*2], sizeof(float)*kNumberOfBins);
 
/* measure gain at +400 mV */
EnableAcal(1, 0.4);
EnableTcal(0, 0);
Sleep(100);
RobustAverageWaveforms(pcb, 0, 8, F1(p), F1(p+1), wft[0], 500, true); p++;
for (i=0 ; i<4 ; i++)
memcpy(wf2[idx[config][i]], wft[i*2], sizeof(float)*kNumberOfBins);
RobustAverageWaveforms(pcb, 2, 8, F1(p), F1(p+1), wft[0], 500, true); p++;
for (i=0 ; i<4 ; i++)
memcpy(wf2[idx[config][i+5]], wft[i*2], sizeof(float)*kNumberOfBins);
 
/* measure gain at -400 mV */
EnableAcal(1, -0.4);
EnableTcal(0, 1);
Sleep(100);
RobustAverageWaveforms(pcb, 0, 8, F1(p), F1(p+1), wft[0], 500, true); p++;
for (i=0 ; i<4 ; i++)
memcpy(wf3[idx[config][i]], wft[i], sizeof(float)*kNumberOfBins);
RobustAverageWaveforms(pcb, 2, 8, F1(p), F1(p+1), wft[0], 500, true); p++;
for (i=0 ; i<4 ; i++)
memcpy(wf3[idx[config][i+5]], wft[i], sizeof(float)*kNumberOfBins);
}
} else {
nChan = 36;
timingChan = 8;
/* measure offset */
EnableAcal(0, 0); // no inputs signal is allowed during calibration!
EnableTcal(0, 0);
Sleep(100);
RobustAverageWaveforms(pcb, 4, 9, 0, 25, wf1[0], 500, true);
 
/* measure gain at upper range */
EnableAcal(1, fRange+0.4);
EnableTcal(0, 0);
Sleep(100);
RobustAverageWaveforms(pcb, 4, 9, 25, 50, wf2[0], 500, true);
}
}
 
/* convert offsets and gains to 16-bit values */
memset(fCellOffset, 0, sizeof(fCellOffset));
n_stuck = 0;
for (i=0 ; i<nChan ; i++) {
for (j=0 ; j<kNumberOfBins; j++) {
if (i % 9 == timingChan) {
/* calculate offset and gain for timing channel */
if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
/* we have a +325mV and a -325mV value */
fCellOffset[i][j] = (unsigned short) ((wf1[i][j]+wf2[i][j])/2+0.5);
fCellGain[i][j] = (wf2[i][j] - wf1[i][j])/65536.0*1000 / 650.0;
} else {
/* only have offset */
fCellOffset[i][j] = wf1[i][j];
fCellGain[i][j] = 1;
}
} else {
/* calculate offset and gain for data channel */
fCellOffset[i][j] = wf1[i][j];
if (fCellOffset[i][j] < 100) {
// mark stuck pixel
n_stuck ++;
fCellOffset[i][j] = 0;
fCellGain[i][j] = 1;
} else
fCellGain[i][j] = (wf2[i][j] - fCellOffset[i][j])/65536.0*1000 / ((0.4+fRange)*1000);
}
 
/* check gain */
if (fCellGain[i][j] < 0.5 || fCellGain[i][j] > 1.1) {
if ((fBoardType == 7 || fBoardType == 8 || fBoardType == 9) && i % 2 == 1) {
/* channels are not connected, so don't print error */
} else {
printf("Gain of %6.3lf for channel %2d, cell %4d out of range 0.5 ... 1.1\n",
fCellGain[i][j], i, j);
}
fCellGain[i][j] = 1;
}
}
}
 
/*
FILE *fh = fopen("calib.txt", "wt");
for (i=0 ; i<nChan ; i++) {
fprintf(fh, "CH%02d:", i);
for (j=0 ; j<20 ; j++)
fprintf(fh, " %5d", fCellOffset[i][j]-32768);
fprintf(fh, "\n");
}
fclose(fh);
*/
 
/* perform secondary calibration */
if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
nChan = 9;
timingChan = 8;
 
/* measure offset */
if (fBoardType == 5)
EnableAcal(0, 0); // no inputs signal is allowed during calibration!
else
EnableAcal(1, 0); // disconnect analog inputs
EnableTcal(0, 0);
Sleep(100);
AverageWaveforms(pcb, 1, 9, 50, 90, wf1[0], 500, false);
} else if (fBoardType == 6 && fTransport == TR_VME) {
nChan = 36;
timingChan = 8;
 
/* measure offset */
EnableAcal(0, 0); // no inputs signal is allowed during calibration!
EnableTcal(0, 0);
Sleep(100);
AverageWaveforms(pcb, 4, 9, 50, 75, wf1[0], 500, false);
}
 
/* convert offset to 16-bit values */
memset(fCellOffset2, 0, sizeof(fCellOffset2));
for (i=0 ; i<nChan ; i++)
for (j=0 ; j<kNumberOfBins; j++)
if (i % 9 != timingChan)
fCellOffset2[i][j] = wf1[i][j];
 
/*
FILE *fh = fopen("calib.txt", "wt");
for (i=0 ; i<nChan ; i++) {
for (j=0 ; j<kNumberOfBins; j++)
fprintf(fh, "%5d: %5d %5d\n", j, fCellOffset2[0][j]-32768, fCellOffset2[1][j]-32768);
fprintf(fh, "\n");
}
fclose(fh);
*/
 
if (fBoardType == 9) {
/* write calibration CH0-CH7 to EEPROM page 1 */
for (i=0 ; i<8 ; i++)
for (j=0 ; j<1024; j++) {
buf[(i*1024+j)*2] = fCellOffset[i][j];
buf[(i*1024+j)*2+1] = (unsigned short) ((fCellGain[i][j] - 0.7) / 0.4 * 65535);
}
WriteEEPROM(1, buf, 1024*32);
if (pcb != NULL)
pcb->Progress(93);
 
/* write secondary calibration to EEPROM page 2 */
ReadEEPROM(2, buf, 1024*32);
for (i=0 ; i<8 ; i++)
for (j=0 ; j<1024; j++)
buf[(i*1024+j)*2] = fCellOffset2[i][j];
WriteEEPROM(2, buf, 1024*32);
if (pcb != NULL)
pcb->Progress(96);
 
/* update page # 0 */
ReadEEPROM(0, buf, 4096); // 0-0x0FFF
/* write calibration method */
buf[2] = (buf[2] & 0xFF00) | VCALIB_METHOD;
/* write temperature and range */
buf[10] = ((unsigned short) (GetTemperature() * 2 + 0.5) << 8) | ((signed char)(fRange * 100));
buf[11] = 1; // EEPROM page #1+2
WriteEEPROM(0, buf, 4096);
fCellCalibratedRange = fRange;
if (pcb != NULL)
pcb->Progress(100);
 
} else if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8) {
/* write calibration CH0-CH7 to EEPROM page 1 */
for (i=0 ; i<8 ; i++)
for (j=0 ; j<1024; j++) {
buf[(i*1024+j)*2] = fCellOffset[i][j];
buf[(i*1024+j)*2+1] = (unsigned short) ((fCellGain[i][j] - 0.7) / 0.4 * 65535);
}
WriteEEPROM(1, buf, 1024*32);
 
/* write calibration CH8 and secondary calibration to EEPROM page 2 */
for (j=0 ; j<1024; j++) {
buf[j*2] = fCellOffset[8][j];
buf[j*2+1] = (unsigned short) ((fCellGain[8][j] - 0.7) / 0.4 * 65535);
}
for (i=0 ; i<4 ; i++)
for (j=0 ; j<1024; j++) {
buf[2*1024+(i*1024+j)*2] = fCellOffset2[i*2][j];
buf[2*1024+(i*1024+j)*2+1] = fCellOffset2[i*2+1][j];
}
WriteEEPROM(2, buf, 1024*5*4);
 
/* write calibration method and range */
ReadEEPROM(0, buf, 2048); // 0-0x0FFF
buf[2] = VCALIB_METHOD_V4 | ((signed char)(fRange * 100)) << 8;
WriteEEPROM(0, buf, 2048);
fCellCalibratedRange = fRange;
 
} else if (fBoardType == 6) {
for (chip=0 ; chip<4 ; chip++) {
/* write calibration of A0 to A7 to EEPROM page 1
B0 to B7 to EEPROM page 2 and so on */
for (i=0 ; i<8 ; i++)
for (j=0 ; j<1024; j++) {
buf[(i*1024+j)*2] = fCellOffset[i+chip*9][j];
buf[(i*1024+j)*2+1] = (unsigned short) ((fCellGain[i+chip*9][j] - 0.7) / 0.4 * 65535);
}
WriteEEPROM(1+chip, buf, 1024*32);
if (pcb != NULL)
pcb->Progress(75+chip*4);
}
 
/* write calibration A/B/C/D/CLK to EEPROM page 5 */
ReadEEPROM(5, buf, 1024*4*4);
for (chip=0 ; chip<4 ; chip++) {
for (j=0 ; j<1024; j++) {
buf[j*2+chip*0x0800] = fCellOffset[8+chip*9][j];
buf[j*2+1+chip*0x0800] = (unsigned short) ((fCellGain[8+chip*9][j] - 0.7) / 0.4 * 65535);
}
}
WriteEEPROM(5, buf, 1024*4*4);
if (pcb != NULL)
pcb->Progress(90);
 
/* write secondary calibration to EEPROM page 7 and 8 */
for (i=0 ; i<8 ; i++) {
for (j=0 ; j<1024; j++) {
buf[i*0x800 + j*2] = fCellOffset2[i][j];
buf[i*0x800 + j*2+1] = fCellOffset2[i+9][j];
}
}
WriteEEPROM(7, buf, 1024*32);
if (pcb != NULL)
pcb->Progress(94);
 
for (i=0 ; i<8 ; i++) {
for (j=0 ; j<1024; j++) {
buf[i*0x800 + j*2] = fCellOffset2[i+18][j];
buf[i*0x800 + j*2+1] = fCellOffset2[i+27][j];
}
}
WriteEEPROM(8, buf, 1024*32);
if (pcb != NULL)
pcb->Progress(98);
 
/* write calibration method and range */
ReadEEPROM(0, buf, 2048); // 0-0x0FFF
buf[2] = VCALIB_METHOD | ((signed char)(fRange * 100)) << 8;
WriteEEPROM(0, buf, 2048);
fCellCalibratedRange = fRange;
if (pcb != NULL)
pcb->Progress(100);
}
 
if (n_stuck)
printf("\nFound %d stuck pixels on this board\n", n_stuck);
 
fVoltageCalibrationValid = true;
 
/* remove calibration voltage */
EnableAcal(0, 0);
EnableTcal(clkon, 0);
EnableTrigger(trg1, trg2);
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::AnalyzeSlope(Averager *ave, int iIter, int nIter, int channel, float wf[kNumberOfBins], int tCell,
double cellDV[kNumberOfBins], double cellDT[kNumberOfBins])
{
int i;
float dv, llim, ulim;
double sum, dtCell;
if (fNominalFrequency > 3) {
llim = -100;
ulim = 100;
} else {
llim = -300;
ulim = 300;
}
 
// rising edges ----
 
// skip first cells after trigger cell
for (i=tCell+5 ; i<tCell+kNumberOfBins-5 ; i++) {
// test slope between previous and next cell to allow for negative cell width
if (wf[(i+kNumberOfBins-1) % kNumberOfBins] < wf[(i+2) % kNumberOfBins] &&
wf[i % kNumberOfBins] > llim &&
wf[(i+1) % kNumberOfBins] < ulim) {
// calculate delta_v
dv = wf[(i+1) % kNumberOfBins] - wf[i % kNumberOfBins];
// average delta_v
ave->Add(0, channel, i % kNumberOfBins, dv);
}
}
 
// falling edges ----
// skip first cells after trigger cell
for (i=tCell+5 ; i<tCell+kNumberOfBins-5 ; i++) {
// test slope between previous and next cell to allow for negative cell width
if (wf[(i+kNumberOfBins-1) % kNumberOfBins] > wf[(i+2) % kNumberOfBins] &&
wf[i % kNumberOfBins] < ulim &&
wf[(i+1) % kNumberOfBins] > llim) {
// calcualte delta_v
dv = wf[(i+1) % kNumberOfBins] - wf[i % kNumberOfBins];
ave->Add(0, channel, i % kNumberOfBins, -dv);
}
}
// calculate calibration every 100 events
if ((iIter + 1) % 100 == 0) {
// average over all 1024 dU
sum = 0;
for (i=0 ; i<kNumberOfBins ; i++) {
if (fBoardType == 8)
cellDV[i] = ave->Median(0, channel, i);
else {
// use empirically found limits for averaging
if (fNominalFrequency >= 4)
cellDV[i] = ave->RobustAverage(3, 0, channel, i);
else if (fNominalFrequency >= 3)
cellDV[i] = ave->RobustAverage(6, 0, channel, i);
else
cellDV[i] = ave->Median(0, channel, i);
}
sum += cellDV[i];
}
sum /= kNumberOfBins;
dtCell = (float)1/fNominalFrequency;
// here comes the central calculation, dT = dV/average * dt_cell
for (i=0 ; i<kNumberOfBins ; i++)
cellDT[i] = cellDV[i] / sum * dtCell;
}
return 1;
}
 
/*------------------------------------------------------------------*/
 
int DRSBoard::AnalyzePeriod(Averager *ave, int iIter, int nIter, int channel, float wf[kNumberOfBins], int tCell,
double cellDV[kNumberOfBins], double cellDT[kNumberOfBins])
{
int i, i1, i2, j, nzx, zeroXing[1000], edge, n_correct, nest;
double damping, zeroLevel, tPeriod, corr, dv, dv_limit, corr_limit;
/* calculate zero level */
for (i=0,zeroLevel=0 ; i<1024 ; i++)
zeroLevel += wf[i];
zeroLevel /= 1024;
 
/* correct for zero common mode */
for (i=0 ; i<1024 ; i++)
wf[i] -= (float)zeroLevel;
 
/* estimate damping factor */
if (fBoardType == 9)
damping = 0.01;
else
damping = fNominalFrequency / nIter * 2 ;
 
/* estimate number of zero crossings */
nest = (int) (1/fNominalFrequency*1024 / (1/fTCALFrequency*1000));
if (fNominalFrequency >= 4)
dv_limit = 4;
else if (fNominalFrequency >= 3)
dv_limit = 6;
else
dv_limit = 10000;
 
for (edge = 0 ; edge < 2 ; edge ++) {
 
/* find edge zero crossing with wrap-around */
for (i=tCell+5,nzx=0 ; i<tCell+1023-5 && nzx < (int)(sizeof(zeroXing)/sizeof(int)) ; i++) {
dv = fabs(wf[(i+1) % 1024] - wf[i % 1024]);
if (edge == 0) {
if (wf[(i+1) % 1024] < 0 && wf[i % 1024] > 0) { // falling edge
if (fBoardType != 9 || fabs(dv-cellDV[i % 1024]) < dv_limit) // only if DV is not more the dv_limit away from average
zeroXing[nzx++] = i % 1024;
}
} else {
if (wf[(i+1) % 1024] > 0 && wf[i % 1024] < 0) { // rising edge
if (fBoardType != 9 || fabs(dv-cellDV[i % 1024]) < dv_limit)
zeroXing[nzx++] = i % 1024;
}
}
}
 
/* abort if uncorrect number of edges is found */
if (abs(nest - nzx) > nest / 3)
return 0;
 
for (i=n_correct=0 ; i<nzx-1 ; i++) {
i1 = zeroXing[i];
i2 = zeroXing[i+1];
if (i1 == 1023 || i2 == 1023)
continue;
if (wf[(i1 + 1) % 1024] == 0 || wf[i2 % 1024] == 0)
continue;
/* first partial cell */
tPeriod = cellDT[i1]*(1/(1-wf[i1]/wf[(i1 + 1) % 1024]));
 
/* full cells between i1 and i2 */
if (i2 < i1)
i2 += 1024;
for (j=i1+1 ; j<i2 ; j++)
tPeriod += cellDT[j % 1024];
/* second partial cell */
tPeriod += cellDT[i2 % 1024]*(1/(1-wf[(i2+1) % 1024]/wf[i2 % 1024]));
 
/* calculate correction to nominal period as a fraction */
corr = (1/fTCALFrequency*1000) / tPeriod;
 
/* skip very large corrections (noise) */
if (fBoardType == 9 && fNominalFrequency >= 2)
corr_limit = 0.001;
else if (fBoardType == 9)
corr_limit = 0.004;
else
corr_limit = 0.01;
 
if (fBoardType == 9 && fabs(1-corr) > corr_limit)
continue;
 
/* remeber number of valid corrections */
n_correct++;
 
/* apply damping factor */
corr = (corr-1)*damping + 1;
 
/* apply from i1 to i2-1 inclusive */
if (i1 == i2)
continue;
 
/* distribute correciton equally into bins inside the region ... */
for (j=i1 ; j<=i2 ; j++)
cellDT[j % 1024] *= corr;
/* test correction */
tPeriod = cellDT[i1]*(1/(1-wf[i1]/wf[(i1 + 1) % 1024]));
for (j=i1+1 ; j<i2 ; j++)
tPeriod += cellDT[j % 1024];
tPeriod += cellDT[i2]*(1/(1-wf[(i2+1) % 1024]/wf[i2]));
}
 
if (n_correct < nzx/3)
return 0;
}
 
return 1;
}
 
/*------------------------------------------------------------------*/
 
 
int DRSBoard::CalibrateTiming(DRSCallback *pcb)
{
int index, status, error, tCell, i, j, c, chip, mode, nIterPeriod, nIterSlope, clkon, phase, refclk, trg1, trg2, n_error, channel;
double f, range, tTrue, tRounded, dT, t1[8], t2[8], cellDV[kNumberOfChipsMax*kNumberOfChannelsMax][kNumberOfBins];
unsigned short buf[1024*16]; // 32 kB
float wf[1024];
Averager *ave = NULL;
nIterPeriod = 5000;
nIterSlope = 5000;
n_error = 0;
refclk = 0;
f = fNominalFrequency;
range = fRange;
clkon = (GetCtrlReg() & BIT_TCAL_EN) > 0;
if (fBoardType == 6)
refclk = (GetCtrlReg() & BIT_REFCLK_SOURCE) > 0;
trg1 = fTriggerEnable1;
trg2 = fTriggerEnable2;
 
Init();
fNominalFrequency = f;
fTimingCalibratedFrequency = 0;
if (fBoardType == 6) // don't set refclk for evaluation boards
SetRefclk(refclk);
SetFrequency(fNominalFrequency, true);
if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8)
fTCALFrequency = 132; // 132 MHz for EVAL1, for MEZZ this is set by ConfigureLMK
else if (fBoardType == 9)
fTCALFrequency = 100;
SetDominoMode(1);
SetDominoActive(1);
SetReadoutMode(1);
EnableTrigger(0, 0);
if (fBoardType == 5 || fBoardType == 7) {
EnableTcal(1, 0, 0);
SelectClockSource(1); // 2nd quartz
} else if (fBoardType == 8) {
nIterSlope = 0;
nIterPeriod = 1500;
EnableTcal(1, 0, 0);
SelectClockSource(1); // 2nd quartz
ave = new Averager(1, 1, 1024, 500); // one chip, 1 channel @ 1024 bins
} else if (fBoardType == 9) {
EnableTcal(1);
nIterSlope = 500;
nIterPeriod = 500;
ave = new Averager(1, 9, 1024, 500); // one chip, 9 channels @ 1024 bins
}
StartDomino();
 
/* initialize time array */
for (i=0 ; i<1024 ; i++)
for (chip=0 ; chip<4 ; chip++)
for (channel = 0 ; channel < 8 ; channel++) {
fCellDT[chip][channel][i] = (float)1/fNominalFrequency; // [ns]
}
 
error = 0;
for (index = 0 ; index < nIterSlope+nIterPeriod ; index++) {
if (index % 10 == 0)
if (pcb)
pcb->Progress(100*index/(nIterSlope+nIterPeriod));
 
if (fTransport == TR_VME) {
SoftTrigger();
while (IsBusy());
 
/* select random phase */
phase = (rand() % 30) - 15;
if (phase == 0)
phase = 15;
EnableTcal(1, 0, phase);
 
StartDomino();
TransferWaves();
 
for (chip=0 ; chip<4 ; chip++) {
tCell = GetStopCell(chip);
GetWave(chip, 8, wf, true, tCell, 0, true);
status = AnalyzePeriod(ave, index, nIterPeriod, 0, wf, tCell, cellDV[chip], fCellDT[chip][0]);
 
if (!status)
n_error++;
 
if (n_error > nIterPeriod / 10) {
error = 1;
break;
}
}
} else {
if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8) { // DRS4 Evaluation board: 1 Chip
SoftTrigger();
while (IsBusy());
 
StartDomino();
TransferWaves();
 
tCell = GetStopCell(0);
GetWave(0, 8, wf, true, tCell, 0, true);
if (index < nIterSlope)
status = AnalyzeSlope(ave, index, nIterSlope, 0, wf, tCell, cellDV[0], fCellDT[0][0]);
else
status = AnalyzePeriod(ave, index, nIterPeriod, 0, wf, tCell, cellDV[0], fCellDT[0][0]);
 
if (!status)
n_error++;
 
if (n_error > nIterPeriod / 10) {
error = 1;
break;
}
} else if (fBoardType == 9) { // DRS4 Evaluation board V5: all channels from one chip
SoftTrigger();
while (IsBusy());
StartDomino();
TransferWaves();
// calibrate all channels individually
for (channel = 0 ; channel < 8 ; channel+=2) {
tCell = GetStopCell(0);
GetWave(0, channel, wf, true, tCell, 0, true);
if (index < nIterSlope)
status = AnalyzeSlope(ave, index, nIterSlope, channel, wf, tCell, cellDV[channel], fCellDT[0][channel]);
else
status = AnalyzePeriod(ave, index, nIterPeriod, channel, wf, tCell, cellDV[channel], fCellDT[0][channel]);
if (!status)
n_error++;
if (n_error > nIterPeriod / 2) {
error = 1;
break;
}
}
if (!status)
break;
 
} else { // DRS4 Mezzanine board: 4 Chips
for (mode=0 ; mode<2 ; mode++) {
SetChannelConfig(mode*2, 8, 8);
SoftTrigger();
while (IsBusy());
 
/* select random phase */
phase = (rand() % 30) - 15;
if (phase == 0)
phase = 15;
EnableTcal(1, 0, phase);
 
StartDomino();
TransferWaves();
 
for (chip=0 ; chip<4 ; chip+=2) {
tCell = GetStopCell(chip+mode);
GetWave(chip+mode, 8, wf, true, tCell, 0, true);
status = AnalyzePeriod(ave, index, nIterPeriod, 0, wf, tCell, cellDV[chip+mode], fCellDT[chip+mode][0]);
 
if (!status) {
error = 1;
break;
}
}
if (!status)
break;
 
}
}
}
}
 
if (pcb)
pcb->Progress(100);
// DRS4 Evaluation board V5: copy even channels to odd channels (usually not connected)
if (fBoardType == 9) {
for (channel = 0 ; channel < 8 ; channel+=2)
memcpy(fCellDT[0][channel+1], fCellDT[0][channel], sizeof(unsigned short)*1024);
}
 
// use following lines to save calibration into an ASCII file
#if 0
FILE *fh;
 
fh = fopen("cellt.csv", "wt");
if (!fh)
printf("Cannot open file \"cellt.csv\"\n");
else {
fprintf(fh, "index,dt_ch1,dt_ch2,dt_ch3,dt_ch4\n");
for (i=0 ; i<1024 ; i++)
fprintf(fh, "%4d,%5.3lf,%5.3lf,%5.3lf,%5.3lf\n", i, fCellDT[0][0][i], fCellDT[0][2][i], fCellDT[0][4][i], fCellDT[0][6][i]);
fclose(fh);
}
#endif
if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8) {
/* write timing calibration to EEPROM page 0 */
ReadEEPROM(0, buf, sizeof(buf));
for (i=0,t1[0]=0 ; i<1024; i++)
buf[i*2+1] = (unsigned short) (fCellDT[0][0][i] * 10000 + 0.5);
 
/* write calibration method and frequency */
buf[4] = TCALIB_METHOD_V4;
buf[6] = (unsigned short)(fNominalFrequency*1000+0.5);
fTimingCalibratedFrequency = fNominalFrequency;
WriteEEPROM(0, buf, sizeof(buf));
// copy calibration to all channels
for (i=1 ; i<8 ; i++)
for (j=0 ; j<1024; j++)
fCellDT[0][i][j] = fCellDT[0][0][j];
 
} else if (fBoardType == 9) {
/* write timing calibration to EEPROM page 2 */
ReadEEPROM(2, buf, sizeof(buf));
for (i=0 ; i<8 ; i++) {
tTrue = 0; // true cellT
tRounded = 0; // rounded cellT
for (j=0 ; j<1024; j++) {
tTrue += fCellDT[0][i][j];
dT = tTrue - tRounded;
// shift by 1 ns to allow negative widths
dT = (unsigned short) (dT*10000+1000+0.5);
tRounded += (dT - 1000) / 10000.0;
buf[(i*1024+j)*2+1] = (unsigned short) dT;
}
}
WriteEEPROM(2, buf, sizeof(buf));
/* write calibration method and frequency to EEPROM page 0 */
ReadEEPROM(0, buf, sizeof(buf));
buf[4] = 1; // number of calibrations
buf[2] = (TCALIB_METHOD << 8) | (buf[2] & 0xFF); // calibration method
float fl = (float) fNominalFrequency;
memcpy(&buf[8], &fl, sizeof(float)); // exact freqeuncy
fTimingCalibratedFrequency = fNominalFrequency;
WriteEEPROM(0, buf, sizeof(buf));
} else {
/* write timing calibration to EEPROM page 6 */
ReadEEPROM(6, buf, sizeof(buf));
for (c=0 ; c<4 ; c++)
t1[c] = 0;
for (i=0 ; i<1024; i++) {
for (c=0 ; c<4 ; c++) {
t2[c] = fCellDT[0][c][i] - t1[c];
t2[c] = (unsigned short) (t2[c] * 10000 + 0.5);
t1[c] += t2[c] / 10000.0;
}
buf[i*2] = (unsigned short) t2[0];
buf[i*2+1] = (unsigned short) t2[1];
buf[i*2+0x800] = (unsigned short) t2[2];
buf[i*2+0x800+1] = (unsigned short) t2[3];
}
WriteEEPROM(6, buf, sizeof(buf));
 
/* write calibration method and frequency */
ReadEEPROM(0, buf, 16);
buf[4] = TCALIB_METHOD;
buf[6] = (unsigned short) (fNominalFrequency * 1000 + 0.5);
fTimingCalibratedFrequency = buf[6] / 1000.0;
WriteEEPROM(0, buf, 16);
}
 
if (ave)
delete ave;
 
/* remove calibration voltage */
EnableAcal(0, 0);
EnableTcal(clkon, 0);
SetInputRange(range);
EnableTrigger(trg1, trg2);
 
if (error)
return 0;
 
return 1;
}
 
 
/*------------------------------------------------------------------*/
 
 
void DRSBoard::RemoveSymmetricSpikes(short **wf, int nwf,
short diffThreshold, int spikeWidth,
short maxPeakToPeak, short spikeVoltage,
int nTimeRegionThreshold)
{
// Remove a specific kind of spike on DRS4.
// This spike has some features,
// - Common on all the channels on a chip
// - Constant heigh and width
// - Two spikes per channel
// - Symmetric to cell #0.
//
// This is not general purpose spike-removing function.
//
// wf : Waveform data. cell#0 must be at bin0,
// and number of bins must be kNumberOfBins.
// nwf : Number of channels which "wf" holds.
// diffThreshold : Amplitude threshold to find peak
// spikeWidth : Width of spike
// maxPeakToPeak : When peak-to-peak is larger than this, the channel
// is not used to find spikes.
// spikeVoltage : Amplitude of spikes. When it is 0, it is calculated in this function
// from voltage difference from neighboring bins.
// nTimeRegionThreshold : Requirement of number of time regions having spike at common position.
// Total number of time regions is 2*"nwf".
 
if (!wf || !nwf || !diffThreshold || !spikeWidth) {
return;
}
 
int ibin, jbin, kbin;
double v;
int nbin;
int iwf;
short maximum, minimum;
int spikeCount[kNumberOfBins / 2];
int spikeCountSum[kNumberOfBins / 2] = {0};
bool largePulse[kNumberOfChannelsMax * 2] = {0};
const short diffThreshold2 = diffThreshold + diffThreshold;
 
const short maxShort = 0xFFFF>>1;
const short minShort = -maxShort - 1;
 
// search spike
for (iwf = 0; iwf < nwf; iwf++) {
// first half
memset(spikeCount, 0, sizeof(spikeCount));
maximum = minShort;
minimum = maxShort;
for (ibin = 0; ibin < kNumberOfBins / 2; ibin++) {
jbin = ibin;
maximum = max(maximum, wf[iwf][jbin]);
minimum = min(minimum, wf[iwf][jbin]);
if (jbin - 1 >= 0 && jbin + spikeWidth < kNumberOfBins) {
v = 0;
nbin = 0;
for (kbin = 0; kbin < spikeWidth; kbin++) {
v += wf[iwf][jbin + kbin];
nbin++;
}
if ((nbin == 2 && v - (wf[iwf][jbin - 1] + wf[iwf][jbin + spikeWidth]) > diffThreshold2) ||
(nbin != 2 && nbin && v / nbin - (wf[iwf][jbin - 1] + wf[iwf][jbin + spikeWidth]) / 2 > diffThreshold)) {
spikeCount[ibin]++;
}
}
}
if (maximum != minShort && minimum != maxShort &&
(!maxPeakToPeak || maximum - minimum < maxPeakToPeak)) {
for (ibin = 0; ibin < kNumberOfBins / 2; ibin++) {
spikeCountSum[ibin] += spikeCount[ibin];
}
largePulse[iwf] = false;
#if 0 /* this part can be enabled to skip checking other channels */
if (maximum != minShort && minimum != maxShort &&
maximum - minimum < diffThreshold) {
return;
}
#endif
} else {
largePulse[iwf] = true;
}
 
// second half
memset(spikeCount, 0, sizeof(spikeCount));
maximum = minShort;
minimum = maxShort;
for (ibin = 0; ibin < kNumberOfBins / 2; ibin++) {
jbin = kNumberOfBins - 1 - ibin;
maximum = max(maximum, wf[iwf][jbin]);
minimum = min(minimum, wf[iwf][jbin]);
if (jbin + 1 < kNumberOfBins && jbin - spikeWidth >= 0) {
v = 0;
nbin = 0;
for (kbin = 0; kbin < spikeWidth; kbin++) {
v += wf[iwf][jbin - kbin];
nbin++;
}
if ((nbin == 2 && v - (wf[iwf][jbin + 1] + wf[iwf][jbin - spikeWidth]) > diffThreshold2) ||
(nbin != 2 && nbin && v / nbin - (wf[iwf][jbin + 1] + wf[iwf][jbin - spikeWidth]) / 2 > diffThreshold)) {
spikeCount[ibin]++;
}
}
}
if (maximum != minShort && minimum != maxShort &&
maximum - minimum < maxPeakToPeak) {
for (ibin = 0; ibin < kNumberOfBins / 2; ibin++) {
spikeCountSum[ibin] += spikeCount[ibin];
}
largePulse[iwf + nwf] = false;
#if 0 /* this part can be enabled to skip checking other channels */
if (maximum != minShort && minimum != maxShort &&
maximum - minimum < diffThreshold) {
return;
}
#endif
} else {
largePulse[iwf + nwf] = true;
}
}
 
// Find common spike
int commonSpikeBin = -1;
int commonSpikeMax = -1;
for (ibin = 0; ibin < kNumberOfBins / 2; ibin++) {
if (commonSpikeMax < spikeCountSum[ibin]) {
commonSpikeMax = spikeCountSum[ibin];
commonSpikeBin = ibin;
}
}
 
if (spikeCountSum[commonSpikeBin] >= nTimeRegionThreshold) {
if (spikeVoltage == 0) {
// Estimate spike amplitude
double baseline = 0;
int nBaseline = 0;
double peakAmplitude = 0;
int nPeakAmplitude = 0;
for (iwf = 0; iwf < nwf; iwf++) {
// first half
if (!largePulse[iwf]) {
// baseline
if ((jbin = commonSpikeBin - 1) >= 0 && jbin < kNumberOfBins) {
baseline += wf[iwf][jbin];
nBaseline++;
}
if ((jbin = commonSpikeBin + spikeWidth + 1) >= 0 && jbin < kNumberOfBins) {
baseline += wf[iwf][jbin];
nBaseline++;
}
// spike
for (ibin = 0; ibin < spikeWidth; ibin++) {
if ((jbin = commonSpikeBin + ibin) >= 0 && jbin < kNumberOfBins) {
peakAmplitude += wf[iwf][jbin];
nPeakAmplitude++;
}
}
}
 
// second half
if (!largePulse[iwf + nwf]) {
// baseline
if ((jbin = kNumberOfBins - 1 - commonSpikeBin + 1) >= 0 && jbin < kNumberOfBins) {
baseline += wf[iwf][jbin];
nBaseline++;
}
if ((jbin = kNumberOfBins - 1 - commonSpikeBin - spikeWidth - 1) >= 0 && jbin < kNumberOfBins) {
baseline += wf[iwf][jbin];
nBaseline++;
}
// spike
for (ibin = 0; ibin < spikeWidth; ibin++) {
if ((jbin = kNumberOfBins - 1 - commonSpikeBin - ibin) >= 0 && jbin < kNumberOfBins) {
peakAmplitude += wf[iwf][jbin];
nPeakAmplitude++;
}
}
}
}
if (nBaseline && nPeakAmplitude) {
baseline /= nBaseline;
peakAmplitude /= nPeakAmplitude;
spikeVoltage = static_cast<short>(peakAmplitude - baseline);
} else {
spikeVoltage = 0;
}
}
 
// Remove spike
if (spikeVoltage > 0) {
for (iwf = 0; iwf < nwf; iwf++) {
for (ibin = 0; ibin < spikeWidth; ibin++) {
if ((jbin = commonSpikeBin + ibin) >= 0 && jbin < kNumberOfBins) {
wf[iwf][jbin] -= spikeVoltage;
}
if ((jbin = kNumberOfBins - 1 - commonSpikeBin - ibin) >= 0 && jbin < kNumberOfBins) {
wf[iwf][jbin] -= spikeVoltage;
}
}
}
}
}
}
 
/*------------------------------------------------------------------*/
 
void ResponseCalibration::SetCalibrationParameters(int numberOfPointsLowVolt, int numberOfPoints,
int numberOfMode2Bins, int numberOfSamples,
int numberOfGridPoints, int numberOfXConstPoints,
int numberOfXConstGridPoints, double triggerFrequency,
int showStatistics)
{
DeleteFields();
InitFields(numberOfPointsLowVolt, numberOfPoints, numberOfMode2Bins, numberOfSamples, numberOfGridPoints,
numberOfXConstPoints, numberOfXConstGridPoints, triggerFrequency, showStatistics);
}
 
/*------------------------------------------------------------------*/
 
void ResponseCalibration::ResetCalibration()
{
int i;
for (i = 0; i < kNumberOfChipsMax; i++)
fCalibrationData[i]->fRead = false;
fCurrentPoint = 0;
fCurrentLowVoltPoint = 0;
fCurrentSample = 0;
fCurrentFitChannel = 0;
fCurrentFitBin = 0;
fRecorded = false;
fFitted = false;
fOffset = false;
};
 
/*------------------------------------------------------------------*/
 
bool ResponseCalibration::WriteCalibration(unsigned int chipIndex)
{
if (!fOffset)
return false;
if (fBoard->GetDRSType() == 3)
return WriteCalibrationV4(chipIndex);
else
return WriteCalibrationV3(chipIndex);
}
 
/*------------------------------------------------------------------*/
 
bool ResponseCalibration::WriteCalibrationV3(unsigned int chipIndex)
{
if (!fOffset)
return false;
 
int ii, j, k;
char str[1000];
char strt[1000];
short tempShort;
CalibrationData *data = fCalibrationData[chipIndex];
CalibrationData::CalibrationDataChannel * chn;
 
// Open File
fBoard->GetCalibrationDirectory(strt);
sprintf(str, "%s/board%d", strt, fBoard->GetBoardSerialNumber());
if (MakeDir(str) == -1) {
printf("Error: Cannot create directory \"%s\"\n", str);
return false;
}
sprintf(str, "%s/board%d/ResponseCalib_board%d_chip%d_%dMHz.bin", strt, fBoard->GetBoardSerialNumber(),
fBoard->GetBoardSerialNumber(), chipIndex, static_cast < int >(fBoard->GetNominalFrequency() * 1000));
fCalibFile = fopen(str, "wb");
if (fCalibFile == NULL) {
printf("Error: Cannot write to file \"%s\"\n", str);
return false;
}
// Write File
fwrite(&data->fNumberOfGridPoints, 1, 1, fCalibFile);
tempShort = static_cast < short >(data->fStartTemperature) * 10;
fwrite(&tempShort, 2, 1, fCalibFile);
tempShort = static_cast < short >(data->fEndTemperature) * 10;
fwrite(&tempShort, 2, 1, fCalibFile);
fwrite(&data->fMin, 4, 1, fCalibFile);
fwrite(&data->fMax, 4, 1, fCalibFile);
fwrite(&data->fNumberOfLimitGroups, 1, 1, fCalibFile);
 
for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
chn = data->fChannel[ii];
for (j = 0; j < kNumberOfBins; j++) {
fwrite(&chn->fLimitGroup[j], 1, 1, fCalibFile);
fwrite(&chn->fLookUpOffset[j], 2, 1, fCalibFile);
fwrite(&chn->fNumberOfLookUpPoints[j], 1, 1, fCalibFile);
for (k = 0; k < chn->fNumberOfLookUpPoints[j]; k++) {
fwrite(&chn->fLookUp[j][k], 1, 1, fCalibFile);
}
for (k = 0; k < data->fNumberOfGridPoints; k++) {
fwrite(&chn->fData[j][k], 2, 1, fCalibFile);
}
fwrite(&chn->fOffsetADC[j], 2, 1, fCalibFile);
fwrite(&chn->fOffset[j], 2, 1, fCalibFile);
}
}
fclose(fCalibFile);
 
printf("Calibration successfully written to\n\"%s\"\n", str);
return true;
}
 
/*------------------------------------------------------------------*/
 
bool ResponseCalibration::WriteCalibrationV4(unsigned int chipIndex)
{
if (!fOffset)
return false;
 
int ii, j;
char str[1000];
char strt[1000];
CalibrationData *data = fCalibrationData[chipIndex];
CalibrationData::CalibrationDataChannel * chn;
 
// Open File
fBoard->GetCalibrationDirectory(strt);
sprintf(str, "%s/board%d", strt, fBoard->GetBoardSerialNumber());
if (MakeDir(str) == -1) {
printf("Error: Cannot create directory \"%s\"\n", str);
return false;
}
sprintf(str, "%s/board%d/ResponseCalib_board%d_chip%d_%dMHz.bin", strt, fBoard->GetBoardSerialNumber(),
fBoard->GetBoardSerialNumber(), chipIndex, static_cast < int >(fBoard->GetNominalFrequency() * 1000));
fCalibFile = fopen(str, "wb");
if (fCalibFile == NULL) {
printf("Error: Cannot write to file \"%s\"\n", str);
return false;
}
// Write File
for (ii = 0; ii < kNumberOfCalibChannelsV4; ii++) {
chn = data->fChannel[ii];
for (j = 0; j < kNumberOfBins; j++) {
fwrite(&chn->fOffset[j], 2, 1, fCalibFile);
fwrite(&chn->fGain[j], 2, 1, fCalibFile);
}
}
fclose(fCalibFile);
 
printf("Calibration successfully written to\n\"%s\"\n", str);
return true;
}
 
/*------------------------------------------------------------------*/
 
void ResponseCalibration::CalibrationTrigger(int mode, double voltage)
{
fBoard->Reinit();
fBoard->EnableAcal(mode, voltage);
fBoard->StartDomino();
fBoard->SoftTrigger();
while (fBoard->IsBusy()) {
}
}
 
/*------------------------------------------------------------------*/
 
void ResponseCalibration::CalibrationStart(double voltage)
{
fBoard->SetDominoMode(1);
fBoard->EnableAcal(0, voltage);
fBoard->StartDomino();
fBoard->IsBusy();
fBoard->IsBusy();
fBoard->IsBusy();
}
 
/*------------------------------------------------------------------*/
 
bool ResponseCalibration::RecordCalibrationPoints(int chipNumber)
{
if (!fInitialized)
return true;
if (fBoard->GetDRSType() == 3)
return RecordCalibrationPointsV4(chipNumber);
else
return RecordCalibrationPointsV3(chipNumber);
}
 
/*------------------------------------------------------------------*/
 
bool ResponseCalibration::RecordCalibrationPointsV3(int chipNumber)
{
int j, k, ii;
int notdone, nsample;
double voltage;
float mean;
const double minVolt = 0.006;
const double xpos[50] =
{ 0.010, 0.027, 0.052, 0.074, 0.096, 0.117, 0.136, 0.155, 0.173, 0.191, 0.208, 0.226, 0.243, 0.260,
0.277, 0.294, 0.310,
0.325, 0.342, 0.358, 0.374, 0.390, 0.406, 0.422, 0.439, 0.457, 0.477, 0.497, 0.520, 0.546, 0.577, 0.611,
0.656, 0.710,
0.772, 0.842, 0.916,
0.995, 1.075, 1.157, 1.240, 1.323, 1.407, 1.490, 1.575, 1.659, 1.744, 1.829, 1.914, 2.000
};
 
// Initialisations
if (fCurrentLowVoltPoint == 0) {
fBoard->SetDAC(fBoard->fDAC_CLKOFS, 0);
// Record Temperature
fCalibrationData[chipNumber]->fStartTemperature = static_cast < float >(fBoard->GetTemperature());
}
// Record current Voltage
if (fCurrentLowVoltPoint < fNumberOfPointsLowVolt)
voltage =
(xpos[0] - minVolt) * fCurrentLowVoltPoint / static_cast <
double >(fNumberOfPointsLowVolt) + minVolt;
else
voltage = xpos[fCurrentPoint];
fBoard->SetCalibVoltage(voltage);
fResponseY[fCurrentPoint + fCurrentLowVoltPoint] = static_cast < float >(voltage) * 1000;
 
// Loop Over Number Of Samples For Statistics
for (j = 0; j < fNumberOfSamples; j++) {
// Read Out Second Part of the Waveform
CalibrationTrigger(3, voltage);
fBoard->TransferWaves();
for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
fBoard->GetRawWave(chipNumber, ii, fWaveFormMode3[ii][j]);
}
// Read Out First Part of the Waveform
CalibrationStart(voltage);
CalibrationTrigger(2, voltage);
fBoard->TransferWaves();
for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
fBoard->GetRawWave(chipNumber, ii, fWaveFormMode2[ii][j]);
}
CalibrationStart(voltage);
}
// Average Sample Points
for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
for (k = 0; k < kNumberOfBins; k++) {
fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] = 0;
for (j = 0; j < fNumberOfSamples; j++) {
fSampleUsed[j] = 1;
if (k < fNumberOfMode2Bins)
fSamples[j] = fWaveFormMode2[ii][j][k];
else
fSamples[j] = fWaveFormMode3[ii][j][k];
fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] += fSamples[j];
}
mean = fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] / fNumberOfSamples;
notdone = 1;
nsample = fNumberOfSamples;
while (notdone) {
notdone = 0;
for (j = 0; j < fNumberOfSamples; j++) {
if (fSampleUsed[j] && abs(static_cast < int >(fSamples[j] - mean)) > 3) {
notdone = 1;
fSampleUsed[j] = 0;
nsample--;
fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] -= fSamples[j];
mean = fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] / nsample;
}
}
}
fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] = mean;
}
}
if (fCurrentLowVoltPoint < fNumberOfPointsLowVolt)
fCurrentLowVoltPoint++;
else
fCurrentPoint++;
 
if (fCurrentPoint == fNumberOfPoints) {
fCalibrationData[chipNumber]->fEndTemperature = static_cast < float >(fBoard->GetTemperature());
fRecorded = true;
fFitted = false;
fOffset = false;
fCalibrationData[chipNumber]->fRead = false;
fCalibrationData[chipNumber]->fHasOffsetCalibration = false;
fBoard->SetCalibVoltage(0.0);
fBoard->EnableAcal(1, 0.0);
fBoard->SetDAC(fBoard->fDAC_CLKOFS, 0.0);
return true;
}
 
return false;
}
 
/*------------------------------------------------------------------*/
 
bool ResponseCalibration::RecordCalibrationPointsV4(int chipNumber)
{
int i, j, k, n;
double voltage, s, s2, average;
 
if (fCurrentPoint == 0) {
fBoard->SetDominoMode(1);
fBoard->EnableAcal(1, 0);
fBoard->SoftTrigger();
while (fBoard->IsBusy());
fBoard->StartDomino();
fCalibrationData[chipNumber]->fStartTemperature = static_cast < float >(fBoard->GetTemperature());
}
voltage = 1.0 * fCurrentPoint / (static_cast < double >(fNumberOfPoints) - 1) +0.1;
fBoard->SetCalibVoltage(voltage);
Sleep(10);
fBoard->SetCalibVoltage(voltage);
Sleep(10);
 
// One dummy cycle for unknown reasons
fBoard->SoftTrigger();
while (fBoard->IsBusy());
fBoard->StartDomino();
Sleep(50);
fBoard->TransferWaves();
 
// Loop over number of samples for statistics
for (i = 0; i < fNumberOfSamples; i++) {
if (fBoard->Debug()) {
printf("%02d:%02d\r", fNumberOfPoints - fCurrentPoint, fNumberOfSamples - i);
fflush(stdout);
}
 
 
fBoard->SoftTrigger();
while (fBoard->IsBusy());
fBoard->StartDomino();
Sleep(50);
fBoard->TransferWaves();
for (j = 0; j < kNumberOfCalibChannelsV4; j++) {
fBoard->GetRawWave(chipNumber, j, fWaveFormMode3[j][i]);
}
}
 
// Calculate averages
for (i = 0; i < kNumberOfCalibChannelsV4; i++) {
for (k = 0; k < kNumberOfBins; k++) {
s = s2 = 0;
 
for (j = 0; j < fNumberOfSamples; j++) {
s += fWaveFormMode3[i][j][k];
s2 += fWaveFormMode3[i][j][k] * fWaveFormMode3[i][j][k];
}
n = fNumberOfSamples;
average = s / n;
 
fResponseX[i][k][fCurrentPoint] = static_cast < float >(average);
}
}
 
fCurrentPoint++;
if (fCurrentPoint == fNumberOfPoints) {
fCalibrationData[chipNumber]->fEndTemperature = static_cast < float >(fBoard->GetTemperature());
fRecorded = true;
return true;
}
 
return false;
}
 
/*------------------------------------------------------------------*/
 
bool ResponseCalibration::FitCalibrationPoints(int chipNumber)
{
if (!fRecorded || fFitted)
return true;
if (fBoard->GetDRSType() == 3)
return FitCalibrationPointsV4(chipNumber);
else
return FitCalibrationPointsV3(chipNumber);
}
 
/*------------------------------------------------------------------*/
 
bool ResponseCalibration::FitCalibrationPointsV3(int chipNumber)
{
int i, j, k;
float x1, x2, y1, y2;
float uu;
float yc, yr;
float xminExt, xrangeExt;
float xmin, xrange;
float average, averageError, averageExt, averageErrorExt;
unsigned short i0, i1;
 
CalibrationData *data = fCalibrationData[chipNumber];
CalibrationData::CalibrationDataChannel * chn = data->fChannel[fCurrentFitChannel];
 
data->DeletePreCalculatedBSpline();
 
if (fCurrentFitBin == 0 && fCurrentFitChannel == 0) {
data->fNumberOfLimitGroups = 0;
data->fMin = 100000;
data->fMax = -100000;
for (i = 0; i < kNumberOfCalibChannelsV3; i++) {
for (j = 0; j < kNumberOfBins; j++) {
if (data->fMin > fResponseX[i][j][fNumberOfPointsLowVolt + fNumberOfPoints - 1])
data->fMin = fResponseX[i][j][fNumberOfPointsLowVolt + fNumberOfPoints - 1];
if (data->fMax < fResponseX[i][j][fNumberOfPointsLowVolt])
data->fMax = fResponseX[i][j][fNumberOfPointsLowVolt];
}
}
}
// Low Volt
i0 = static_cast < unsigned short >(fResponseX[fCurrentFitChannel][fCurrentFitBin][0]);
i1 = static_cast <
unsigned short >(fResponseX[fCurrentFitChannel][fCurrentFitBin][fNumberOfPointsLowVolt]) + 1;
chn->fLookUpOffset[fCurrentFitBin] = i0;
delete chn->fLookUp[fCurrentFitBin];
if (i0 - i1 + 1 < 2) {
chn->fNumberOfLookUpPoints[fCurrentFitBin] = 2;
chn->fLookUp[fCurrentFitBin] = new unsigned char[2];
chn->fLookUp[fCurrentFitBin][0] = 0;
chn->fLookUp[fCurrentFitBin][1] = 0;
} else {
chn->fNumberOfLookUpPoints[fCurrentFitBin] = i0 - i1 + 1;
chn->fLookUp[fCurrentFitBin] = new unsigned char[i0 - i1 + 1];
for (i = 0; i < i0 - i1 + 1; i++) {
for (j = 0; j < fNumberOfPointsLowVolt; j++) {
if (i0 - i >= fResponseX[fCurrentFitChannel][fCurrentFitBin][j + 1]) {
x1 = fResponseX[fCurrentFitChannel][fCurrentFitBin][j];
x2 = fResponseX[fCurrentFitChannel][fCurrentFitBin][j + 1];
y1 = fResponseY[j];
y2 = fResponseY[j + 1];
chn->fLookUp[fCurrentFitBin][i] =
static_cast < unsigned char >(((y2 - y1) * (i0 - i - x1) / (x2 - x1) + y1) / fPrecision);
break;
}
}
}
}
 
// Copy Points
for (i = 0; i < fNumberOfPoints; i++) {
fPntX[0][i] = fResponseX[fCurrentFitChannel][fCurrentFitBin][fNumberOfPointsLowVolt + i];
fPntY[0][i] = fResponseY[fNumberOfPointsLowVolt + i];
}
// Fit BSpline
for (i = 0; i < fNumberOfPoints; i++) {
fUValues[0][i] = static_cast < float >(1 - i / (fNumberOfPoints - 1.));
}
if (!Approx(fPntX[0], fUValues[0], fNumberOfPoints, fNumberOfGridPoints, fResX[fCurrentFitBin]))
return true;
if (!Approx(fPntY[0], fUValues[0], fNumberOfPoints, fNumberOfGridPoints, fRes[fCurrentFitBin]))
return true;
 
// X constant fit
for (k = 0; k < fNumberOfXConstPoints - 2; k++) {
fPntX[1][k + 1] =
GetValue(fResX[fCurrentFitBin],
static_cast < float >(1 - k / static_cast < float >(fNumberOfXConstPoints - 3)),
fNumberOfGridPoints);
fPntY[1][k + 1] =
GetValue(fRes[fCurrentFitBin],
static_cast < float >(1 - k / static_cast < float >(fNumberOfXConstPoints - 3)),
fNumberOfGridPoints);
}
xmin = fPntX[1][fNumberOfXConstPoints - 2];
xrange = fPntX[1][1] - xmin;
 
for (i = 0; i < fNumberOfXConstPoints - 2; i++) {
fUValues[1][i + 1] = (fPntX[1][i + 1] - xmin) / xrange;
}
 
if (!Approx
(&fPntY[1][1], &fUValues[1][1], fNumberOfXConstPoints - 2, fNumberOfXConstGridPoints, chn->fTempData))
return true;
 
// error statistics
if (fShowStatistics) {
for (i = 0; i < fNumberOfPoints; i++) {
uu = (fPntX[0][i] - xmin) / xrange;
yc = GetValue(chn->fTempData, uu, fNumberOfXConstGridPoints);
yr = fPntY[0][i];
fStatisticsApprox[i][fCurrentFitBin + fCurrentFitChannel * kNumberOfBins] = yc - yr;
}
}
// Add min and max point
chn->fLimitGroup[fCurrentFitBin] = 0;
while (xmin - kBSplineXMinOffset > data->fMin + kBSplineXMinOffset * chn->fLimitGroup[fCurrentFitBin]) {
chn->fLimitGroup[fCurrentFitBin]++;
}
if (data->fNumberOfLimitGroups <= chn->fLimitGroup[fCurrentFitBin])
data->fNumberOfLimitGroups = chn->fLimitGroup[fCurrentFitBin] + 1;
xminExt = data->fMin + kBSplineXMinOffset * chn->fLimitGroup[fCurrentFitBin];
xrangeExt = data->fMax - xminExt;
 
fPntX[1][0] = data->fMax;
uu = (fPntX[1][0] - xmin) / xrange;
fPntY[1][0] = GetValue(chn->fTempData, uu, fNumberOfXConstGridPoints);
 
fPntX[1][fNumberOfXConstPoints - 1] = xminExt;
uu = (fPntX[1][fNumberOfXConstPoints - 1] - xmin) / xrange;
fPntY[1][fNumberOfXConstPoints - 1] = GetValue(chn->fTempData, uu, fNumberOfXConstGridPoints);
 
for (i = 0; i < fNumberOfXConstPoints; i++) {
fUValues[1][i] = (fPntX[1][i] - xminExt) / xrangeExt;
}
 
if (!Approx(fPntY[1], fUValues[1], fNumberOfXConstPoints, fNumberOfXConstGridPoints, chn->fTempData))
return true;
 
// error statistics
if (fShowStatistics) {
for (i = 0; i < fNumberOfPoints; i++) {
uu = (fPntX[0][i] - xminExt) / xrangeExt;
yc = GetValue(chn->fTempData, uu, fNumberOfXConstGridPoints);
yr = fPntY[0][i];
fStatisticsApproxExt[i][fCurrentFitBin + fCurrentFitChannel * kNumberOfBins] = yc - yr;
}
}
for (i = 0; i < fNumberOfXConstGridPoints; i++) {
chn->fData[fCurrentFitBin][i] = static_cast < short >(chn->fTempData[i] / fPrecision);
}
 
// write end of file
fCurrentFitBin++;
if (fCurrentFitBin == kNumberOfBins) {
fCurrentFitChannel++;
fCurrentFitBin = 0;
}
if (fCurrentFitChannel == kNumberOfCalibChannelsV3) {
if (fShowStatistics) {
for (i = 0; i < fNumberOfPoints; i++) {
average = 0;
averageError = 0;
averageExt = 0;
averageErrorExt = 0;
for (j = 0; j < kNumberOfCalibChannelsV3 * kNumberOfBins; j++) {
average += fStatisticsApprox[i][j];
averageError += fStatisticsApprox[i][j] * fStatisticsApprox[i][j];
averageExt += fStatisticsApproxExt[i][j];
averageErrorExt += fStatisticsApproxExt[i][j] * fStatisticsApproxExt[i][j];
}
average /= kNumberOfCalibChannelsV3 * kNumberOfBins;
averageError =
sqrt((averageError -
average * average / kNumberOfCalibChannelsV3 * kNumberOfBins) /
(kNumberOfCalibChannelsV3 * kNumberOfBins - 1));
averageExt /= kNumberOfCalibChannelsV3 * kNumberOfBins;
averageErrorExt =
sqrt((averageErrorExt -
averageExt * averageExt / kNumberOfCalibChannelsV3 * kNumberOfBins) /
(kNumberOfCalibChannelsV3 * kNumberOfBins - 1));
printf("Error at %3.1f V : % 2.3f +- % 2.3f ; % 2.3f +- % 2.3f\n", fPntY[0][i], average,
averageError, averageExt, averageErrorExt);
}
}
fFitted = true;
fOffset = false;
fCalibrationData[chipNumber]->fRead = true;
fCalibrationData[chipNumber]->fHasOffsetCalibration = false;
data->PreCalculateBSpline();
return true;
}
return false;
}
 
/*------------------------------------------------------------------*/
 
bool ResponseCalibration::FitCalibrationPointsV4(int chipNumber)
{
if (!fRecorded || fFitted)
return true;
int i;
double par[2];
static int error;
 
CalibrationData *data = fCalibrationData[chipNumber];
CalibrationData::CalibrationDataChannel * chn = data->fChannel[fCurrentFitChannel];
 
if (fCurrentFitBin == 0 && fCurrentFitChannel == 0) {
error = 0;
for (i = 0; i < fNumberOfPoints; i++)
fWWFit[i] = 1;
}
 
for (i = 0; i < fNumberOfPoints; i++) {
fXXFit[i] = 1.0 * i / (static_cast < double >(fNumberOfPoints) - 1) +0.1;
fYYFit[i] = fResponseX[fCurrentFitChannel][fCurrentFitBin][i];
if (fCurrentFitBin == 10 && fCurrentFitChannel == 1) {
fXXSave[i] = fXXFit[i];
fYYSave[i] = fYYFit[i];
}
}
 
// DRSBoard::LinearRegression(fXXFit, fYYFit, fNumberOfPoints, &par[1], &par[0]);
// exclude first two points (sometimes are on limit of FADC)
DRSBoard::LinearRegression(fXXFit + 2, fYYFit + 2, fNumberOfPoints - 2, &par[1], &par[0]);
 
chn->fOffset[fCurrentFitBin] = static_cast < unsigned short >(par[0] + 0.5);
chn->fGain[fCurrentFitBin] = static_cast < unsigned short >(par[1] + 0.5);
 
// Remember min/max of gain
if (fCurrentFitBin == 0 && fCurrentFitChannel == 0)
fGainMin = fGainMax = chn->fGain[0];
if (chn->fGain[fCurrentFitBin] < fGainMin)
fGainMin = chn->fGain[fCurrentFitBin];
if (chn->fGain[fCurrentFitBin] > fGainMax)
fGainMax = chn->fGain[fCurrentFitBin];
 
// abort if outside normal region
if (chn->fGain[fCurrentFitBin] / 4096.0 < 0.8 || chn->fGain[fCurrentFitBin] / 4096.0 > 1) {
error++;
 
if (error < 20)
printf("Gain=%1.3lf for bin %d on channel %d on chip %d outside valid region\n",
chn->fGain[fCurrentFitBin] / 4096.0, fCurrentFitBin, fCurrentFitChannel, chipNumber);
}
 
if (fCurrentFitChannel == 1 && fCurrentFitBin == 10) {
for (i = 0; i < fNumberOfPoints; i++) {
fXXSave[i] = fXXFit[i];
fYYSave[i] = (fYYFit[i] - chn->fOffset[10]) / chn->fGain[10] - fXXFit[i];
}
}
 
fCurrentFitBin++;
if (fCurrentFitBin == kNumberOfBins) {
fCurrentFitChannel++;
fCurrentFitBin = 0;
}
if (fCurrentFitChannel == kNumberOfCalibChannelsV4) {
 
if (fBoard->Debug()) {
printf("Gain min=%1.3lf max=%1.3lf\n", fGainMin / 4096.0, fGainMax / 4096.0);
fflush(stdout);
}
// allow up to three bad bins
if (error > 3) {
printf("Aborting calibration!\n");
return true;
}
 
fFitted = true;
fOffset = false;
fCalibrationData[chipNumber]->fRead = true;
fCalibrationData[chipNumber]->fHasOffsetCalibration = false;
return true;
}
 
return false;
}
 
unsigned int millitime()
{
#ifdef _MSC_VER
 
return (int) GetTickCount();
 
#else
struct timeval tv;
 
gettimeofday(&tv, NULL);
 
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
#endif
return 0;
}
 
/*------------------------------------------------------------------*/
 
bool ResponseCalibration::OffsetCalibration(int chipNumber)
{
if (!fFitted || fOffset)
return true;
if (fBoard->GetDRSType() == 3)
return OffsetCalibrationV4(chipNumber);
else
return OffsetCalibrationV3(chipNumber);
}
 
/*------------------------------------------------------------------*/
 
bool ResponseCalibration::OffsetCalibrationV3(int chipNumber)
{
int k, ii, j;
int t1, t2;
float mean, error;
CalibrationData *data = fCalibrationData[chipNumber];
CalibrationData::CalibrationDataChannel * chn;
 
if (fCurrentSample == 0) {
data->fHasOffsetCalibration = false;
fBoard->SetCalibVoltage(0.0);
fBoard->EnableAcal(0, 0.0);
}
// Loop Over Number Of Samples For Statistics
t1 = millitime();
fBoard->SoftTrigger();
while (fBoard->IsBusy()) {
}
fBoard->TransferWaves();
for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
fBoard->GetRawWave(chipNumber, ii, fWaveFormOffsetADC[ii][fCurrentSample]);
fBoard->CalibrateWaveform(chipNumber, ii, fWaveFormOffsetADC[ii][fCurrentSample],
fWaveFormOffset[ii][fCurrentSample], true, false, false, 0, true);
}
fBoard->StartDomino();
fBoard->IsBusy();
fBoard->IsBusy();
fBoard->IsBusy();
t2 = millitime();
while (t2 - t1 < (1000 / fTriggerFrequency)) {
t2 = millitime();
}
fCurrentSample++;
 
if (fCurrentSample == fNumberOfSamples) {
// Average Sample Points
float *sample = new float[fNumberOfSamples];
for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
chn = data->fChannel[ii];
for (k = 0; k < kNumberOfBins; k++) {
for (j = 0; j < fNumberOfSamples; j++)
sample[j] = static_cast < float >(fWaveFormOffset[ii][j][k]);
Average(1, sample, fNumberOfSamples, mean, error, 2);
chn->fOffset[k] = static_cast < short >(mean);
for (j = 0; j < fNumberOfSamples; j++)
sample[j] = fWaveFormOffsetADC[ii][j][k];
Average(1, sample, fNumberOfSamples, mean, error, 2);
chn->fOffsetADC[k] = static_cast < unsigned short >(mean);
}
}
fOffset = true;
fCalibrationData[chipNumber]->fHasOffsetCalibration = true;
delete[] sample;
return true;
}
 
return false;
}
 
/*------------------------------------------------------------------*/
 
bool ResponseCalibration::OffsetCalibrationV4(int chipNumber)
{
int k, ii, j;
float mean, error;
CalibrationData *data = fCalibrationData[chipNumber];
CalibrationData::CalibrationDataChannel * chn;
 
/* switch DRS to input, hope that no real signal occurs */
if (fCurrentSample == 0) {
data->fHasOffsetCalibration = false;
fBoard->SetCalibVoltage(0.0);
fBoard->EnableAcal(0, 0.0);
/* one dummy trigger for unknown reasons */
fBoard->SoftTrigger();
while (fBoard->IsBusy());
fBoard->StartDomino();
Sleep(50);
}
// Loop Over Number Of Samples For Statistics
fBoard->SoftTrigger();
while (fBoard->IsBusy());
fBoard->TransferWaves();
for (ii = 0; ii < kNumberOfCalibChannelsV4; ii++)
fBoard->GetRawWave(chipNumber, ii, fWaveFormOffsetADC[ii][fCurrentSample]);
 
fBoard->StartDomino();
Sleep(50);
fCurrentSample++;
 
if (fBoard->Debug()) {
printf("%02d\r", fNumberOfSamples - fCurrentSample);
fflush(stdout);
}
 
if (fCurrentSample == fNumberOfSamples) {
// Average Sample Points
float *sample = new float[fNumberOfSamples];
for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
chn = data->fChannel[ii];
for (k = 0; k < kNumberOfBins; k++) {
for (j = 0; j < fNumberOfSamples; j++)
sample[j] = static_cast < float >(fWaveFormOffsetADC[ii][j][k]);
Average(1, sample, fNumberOfSamples, mean, error, 2);
chn->fOffset[k] = static_cast < unsigned short >(mean);
}
}
fOffset = true;
fCalibrationData[chipNumber]->fHasOffsetCalibration = true;
delete[] sample;
return true;
}
 
return false;
}
 
/*------------------------------------------------------------------*/
 
void ResponseCalibration::InitFields(int numberOfPointsLowVolt, int numberOfPoints, int numberOfMode2Bins,
int numberOfSamples, int numberOfGridPoints, int numberOfXConstPoints,
int numberOfXConstGridPoints, double triggerFrequency,
int showStatistics)
{
int ii, j, i;
fInitialized = true;
fNumberOfPointsLowVolt = numberOfPointsLowVolt;
fNumberOfPoints = numberOfPoints;
fNumberOfMode2Bins = numberOfMode2Bins;
fNumberOfSamples = numberOfSamples;
fNumberOfGridPoints = numberOfGridPoints;
fNumberOfXConstPoints = numberOfXConstPoints;
fNumberOfXConstGridPoints = numberOfXConstGridPoints;
fTriggerFrequency = triggerFrequency;
fShowStatistics = showStatistics;
fCurrentPoint = 0;
fCurrentSample = 0;
fCurrentFitChannel = 0;
fCurrentFitBin = 0;
for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
for (j = 0; j < kNumberOfBins; j++) {
fResponseX[ii][j] = new float[fNumberOfPoints + fNumberOfPointsLowVolt];
}
}
fResponseY = new float[fNumberOfPoints + fNumberOfPointsLowVolt];
for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
fWaveFormMode3[ii] = new unsigned short *[fNumberOfSamples];
fWaveFormMode2[ii] = new unsigned short *[fNumberOfSamples];
fWaveFormOffset[ii] = new short *[fNumberOfSamples];
fWaveFormOffsetADC[ii] = new unsigned short *[fNumberOfSamples];
for (i = 0; i < fNumberOfSamples; i++) {
fWaveFormMode3[ii][i] = new unsigned short[kNumberOfBins];
fWaveFormMode2[ii][i] = new unsigned short[kNumberOfBins];
fWaveFormOffset[ii][i] = new short[kNumberOfBins];
fWaveFormOffsetADC[ii][i] = new unsigned short[kNumberOfBins];
}
}
fSamples = new unsigned short[fNumberOfSamples];
fSampleUsed = new int[fNumberOfSamples];
 
for (j = 0; j < kNumberOfBins; j++) {
fRes[j] = new float[fNumberOfGridPoints];
fResX[j] = new float[fNumberOfGridPoints];
}
for (i = 0; i < 2; i++) {
fPntX[i] = new float[fNumberOfPoints * (1 - i) + fNumberOfXConstPoints * i];
fPntY[i] = new float[fNumberOfPoints * (1 - i) + fNumberOfXConstPoints * i];
fUValues[i] = new float[fNumberOfPoints * (1 - i) + fNumberOfXConstPoints * i];
}
fXXFit = new double[fNumberOfPoints];
fYYFit = new double[fNumberOfPoints];
fWWFit = new double[fNumberOfPoints];
fYYFitRes = new double[fNumberOfPoints];
fYYSave = new double[fNumberOfPoints];
fXXSave = new double[fNumberOfPoints];
 
fStatisticsApprox = new float *[fNumberOfPoints];
fStatisticsApproxExt = new float *[fNumberOfPoints];
for (i = 0; i < fNumberOfPoints; i++) {
fStatisticsApprox[i] = new float[kNumberOfCalibChannelsV3 * kNumberOfBins];
fStatisticsApproxExt[i] = new float[kNumberOfCalibChannelsV3 * kNumberOfBins];
}
for (i = 0; i < kNumberOfChipsMax; i++) {
fCalibrationData[i] = new CalibrationData(numberOfXConstGridPoints);
}
}
 
/*------------------------------------------------------------------*/
 
void ResponseCalibration::DeleteFields()
{
if (!fInitialized)
return;
fInitialized = false;
int ii, j, i;
for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
for (j = 0; j < kNumberOfBins; j++) {
delete fResponseX[ii][j];
}
}
delete fResponseY;
for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
for (i = 0; i < fNumberOfSamples; i++) {
if (fWaveFormMode3[ii] != NULL)
delete fWaveFormMode3[ii][i];
if (fWaveFormMode2[ii] != NULL)
delete fWaveFormMode2[ii][i];
if (fWaveFormOffset[ii] != NULL)
delete fWaveFormOffset[ii][i];
if (fWaveFormOffsetADC[ii] != NULL)
delete fWaveFormOffsetADC[ii][i];
}
delete fWaveFormMode3[ii];
delete fWaveFormMode2[ii];
delete fWaveFormOffset[ii];
delete fWaveFormOffsetADC[ii];
}
delete fSamples;
delete fSampleUsed;
 
for (j = 0; j < kNumberOfBins; j++) {
delete fRes[j];
delete fResX[j];
}
for (i = 0; i < 2; i++) {
delete fPntX[i];
delete fPntY[i];
delete fUValues[i];
}
delete fXXFit;
delete fYYFit;
delete fWWFit;
delete fYYFitRes;
delete fYYSave;
delete fXXSave;
 
for (i = 0; i < fNumberOfPoints; i++) {
delete fStatisticsApprox[i];
delete fStatisticsApproxExt[i];
}
delete fStatisticsApprox;
delete fStatisticsApproxExt;
for (i = 0; i < kNumberOfChipsMax; i++)
delete fCalibrationData[i];
}
 
/*------------------------------------------------------------------*/
 
double ResponseCalibration::GetTemperature(unsigned int chipIndex)
{
if (fCalibrationData[chipIndex] == NULL)
return 0;
if (!fCalibrationData[chipIndex]->fRead)
return 0;
return (fCalibrationData[chipIndex]->fStartTemperature + fCalibrationData[chipIndex]->fEndTemperature) / 2;
}
 
/*------------------------------------------------------------------*/
 
bool ResponseCalibration::Calibrate(unsigned int chipIndex, unsigned int channel, unsigned short *adcWaveform,
short *uWaveform, int triggerCell, float threshold, bool offsetCalib)
{
int i;
unsigned int NumberOfCalibChannels;
int hasOffset;
bool aboveThreshold;
float wave, v;
int j, irot;
 
CalibrationData *data = fCalibrationData[chipIndex];
CalibrationData::CalibrationDataChannel * chn;
 
if (fBoard->GetDRSType() == 3)
NumberOfCalibChannels = kNumberOfCalibChannelsV4;
else
NumberOfCalibChannels = kNumberOfCalibChannelsV3;
 
if (channel >= NumberOfCalibChannels || data == NULL) {
for (i = 0; i < kNumberOfBins; i++) {
irot = i;
if (triggerCell > -1)
irot = (triggerCell + i) % kNumberOfBins;
 
uWaveform[i] = adcWaveform[irot];
}
return true;
}
if (!data->fRead) {
for (i = 0; i < kNumberOfBins; i++) {
uWaveform[i] = adcWaveform[i];
}
return true;
}
 
chn = data->fChannel[channel];
 
hasOffset = data->fHasOffsetCalibration;
aboveThreshold = (threshold == 0); // if threshold equal zero, always return true
 
short offset;
 
// Calibrate
for (i = 0; i < kNumberOfBins; i++) {
if (fBoard->GetDRSType() != 3) {
irot = i;
if (triggerCell > -1)
irot = (triggerCell + i) % kNumberOfBins;
offset = offsetCalib ? chn->fOffset[irot] : 0;
if (adcWaveform[irot] > chn->fLookUpOffset[irot]) {
uWaveform[i] =
((chn->fLookUp[irot][0] - chn->fLookUp[irot][1]) * (adcWaveform[irot] -
chn->fLookUpOffset[irot]) +
chn->fLookUp[irot][0]);
} else if (adcWaveform[irot] <= chn->fLookUpOffset[irot]
&& adcWaveform[irot] > chn->fLookUpOffset[irot] - chn->fNumberOfLookUpPoints[irot]) {
uWaveform[i] = chn->fLookUp[irot][chn->fLookUpOffset[irot] - adcWaveform[irot]];
} else {
wave = 0;
for (j = 0; j < kBSplineOrder; j++) {
wave +=
chn->fData[irot][data->fBSplineOffsetLookUp[adcWaveform[irot]][chn->fLimitGroup[irot]] + j]
* data->fBSplineLookUp[adcWaveform[irot]][chn->fLimitGroup[irot]][j];
}
uWaveform[i] = static_cast < short >(wave);
}
// Offset Calibration
if (hasOffset)
uWaveform[i] -= offset;
} else {
irot = i;
if (triggerCell > -1)
irot = (triggerCell + i) % kNumberOfBins;
#if 0 /* not enabled yet for DRS3 */
offset = offsetCalib ? chn->fOffset[irot] : 0;
#else
offset = chn->fOffset[irot];
#endif
v = static_cast < float >(adcWaveform[irot] - offset) / chn->fGain[irot];
uWaveform[i] = static_cast < short >(v * 1000 / GetPrecision() + 0.5);
}
 
// Check for Threshold
if (!aboveThreshold) {
if (uWaveform[i] >= threshold)
aboveThreshold = true;
}
}
return aboveThreshold;
}
 
/*------------------------------------------------------------------*/
 
bool ResponseCalibration::SubtractADCOffset(unsigned int chipIndex, unsigned int channel,
unsigned short *adcWaveform,
unsigned short *adcCalibratedWaveform,
unsigned short newBaseLevel)
{
int i;
unsigned int NumberOfCalibChannels;
CalibrationData *data = fCalibrationData[chipIndex];
CalibrationData::CalibrationDataChannel * chn;
 
if (fBoard->GetDRSType() == 3)
NumberOfCalibChannels = kNumberOfCalibChannelsV4;
else
NumberOfCalibChannels = kNumberOfCalibChannelsV3;
 
if (channel >= NumberOfCalibChannels || data == NULL)
return false;
if (!data->fRead || !data->fHasOffsetCalibration)
return false;
 
chn = data->fChannel[channel];
for (i = 0; i < kNumberOfBins; i++)
adcCalibratedWaveform[i] = adcWaveform[i] - chn->fOffsetADC[i] + newBaseLevel;
return true;
}
 
 
/*------------------------------------------------------------------*/
 
bool ResponseCalibration::ReadCalibration(unsigned int chipIndex)
{
if (fBoard->GetDRSType() == 3)
return ReadCalibrationV4(chipIndex);
else
return ReadCalibrationV3(chipIndex);
}
 
/*------------------------------------------------------------------*/
 
bool ResponseCalibration::ReadCalibrationV3(unsigned int chipIndex)
{
int k, l, m, num;
unsigned char ng;
short tempShort;
char fileName[2000];
FILE *fileHandle;
char calibDir[1000];
 
// Read Response Calibration
delete fCalibrationData[chipIndex];
fCalibrationData[chipIndex] = NULL;
 
fBoard->GetCalibrationDirectory(calibDir);
sprintf(fileName, "%s/board%d/ResponseCalib_board%d_chip%d_%dMHz.bin", calibDir,
fBoard->GetBoardSerialNumber(), fBoard->GetBoardSerialNumber(), chipIndex,
static_cast < int >(fBoard->GetNominalFrequency() * 1000));
 
fileHandle = fopen(fileName, "rb");
if (fileHandle == NULL) {
printf("Board %d --> Could not find response calibration file:\n", fBoard->GetBoardSerialNumber());
printf("%s\n", fileName);
return false;
}
// Number Of Grid Points
num = fread(&ng, 1, 1, fileHandle);
if (num != 1) {
printf("Error while reading response calibration file '%s'\n", fileName);
printf(" at 'NumberOfGridPoints'.\n");
return false;
}
 
fCalibrationData[chipIndex] = new CalibrationData(ng);
CalibrationData *data = fCalibrationData[chipIndex];
CalibrationData::CalibrationDataChannel * chn;
data->fRead = true;
data->fHasOffsetCalibration = 1;
data->DeletePreCalculatedBSpline();
fCalibrationValid[chipIndex] = true;
 
// Start Temperature
num = fread(&tempShort, 2, 1, fileHandle);
if (num != 1) {
printf("Error while reading response calibration file '%s'\n", fileName);
printf(" at 'StartTemperature'.\n");
return false;
}
data->fStartTemperature = static_cast < float >(tempShort) / 10;
// End Temperature
num = fread(&tempShort, 2, 1, fileHandle);
if (num != 1) {
printf("Error while reading response calibration file '%s'\n", fileName);
printf(" at 'EndTemperature'.\n");
return false;
}
data->fEndTemperature = static_cast < float >(tempShort) / 10;
if (fBoard->GetDRSType() != 3) {
// Min
num = fread(&data->fMin, 4, 1, fileHandle);
if (num != 1) {
printf("Error while reading response calibration file '%s'\n", fileName);
printf(" at 'Min'.\n");
return false;
}
// Max
num = fread(&data->fMax, 4, 1, fileHandle);
if (num != 1) {
printf("Error while reading response calibration file '%s'\n", fileName);
printf(" at 'Max'.\n");
return false;
}
// Number Of Limit Groups
num = fread(&data->fNumberOfLimitGroups, 1, 1, fileHandle);
if (num != 1) {
printf("Error while reading response calibration file '%s'\n", fileName);
printf(" at 'NumberOfLimitGroups'.\n");
return false;
}
}
// read channel
for (k = 0; k < kNumberOfCalibChannelsV3; k++) {
chn = data->fChannel[k];
for (l = 0; l < kNumberOfBins; l++) {
if (fBoard->GetDRSType() != 3) {
// Range Group
num = fread(&chn->fLimitGroup[l], 1, 1, fileHandle);
if (num != 1) {
printf("Error while reading response calibration file '%s'\n", fileName);
printf(" at 'RangeGroup' of channel %d bin %d.\n", k, l);
return false;
}
// Look Up Offset
num = fread(&chn->fLookUpOffset[l], 2, 1, fileHandle);
if (num != 1) {
printf("Error while reading response calibration file '%s'\n", fileName);
printf(" at 'LookUpOffset' of channel %d bin %d.\n", k, l);
return false;
}
// Number Of Look Up Points
num = fread(&chn->fNumberOfLookUpPoints[l], 1, 1, fileHandle);
if (num != 1) {
printf("Error while reading response calibration file '%s'\n", fileName);
printf(" at 'NumberOfLookUpPoints' of channel %d bin %d.\n", k, l);
return false;
}
// Look Up Points
delete chn->fLookUp[l];
chn->fLookUp[l] = new unsigned char[chn->fNumberOfLookUpPoints[l]];
for (m = 0; m < chn->fNumberOfLookUpPoints[l]; m++) {
num = fread(&chn->fLookUp[l][m], 1, 1, fileHandle);
if (num != 1) {
printf("Error while reading response calibration file '%s'\n", fileName);
printf(" at 'LookUp %d' of channel %d bin %d.\n", m, k, l);
return false;
}
}
// Points
for (m = 0; m < data->fNumberOfGridPoints; m++) {
num = fread(&chn->fData[l][m], 2, 1, fileHandle);
if (num != 1) {
printf("Error while reading response calibration file '%s'\n", fileName);
printf(" at 'Point %d' of channel %d bin %d.\n", m, k, l);
return false;
}
}
// ADC Offset
num = fread(&chn->fOffsetADC[l], 2, 1, fileHandle);
if (num != 1) {
printf("Error while reading response calibration file '%s'\n", fileName);
printf(" at 'ADC Offset' of channel %d bin %d.\n", k, l);
return false;
}
}
// Offset
num = fread(&chn->fOffset[l], 2, 1, fileHandle);
if (num != 1) {
printf("Error while reading response calibration file '%s'\n", fileName);
printf(" at 'Offset' of channel %d bin %d.\n", k, l);
return false;
}
if (fBoard->GetDRSType() == 3) {
// Gain
num = fread(&chn->fGain[l], 2, 1, fileHandle);
if (num != 1) {
printf("Error while reading response calibration file '%s'\n", fileName);
printf(" at 'Gain' of channel %d bin %d.\n", k, l);
return false;
}
}
}
}
fclose(fileHandle);
 
if (fBoard->GetDRSType() != 3) {
data->PreCalculateBSpline();
}
 
return true;
}
 
/*------------------------------------------------------------------*/
 
bool ResponseCalibration::ReadCalibrationV4(unsigned int chipIndex)
{
int k, l, num;
char fileName[2000];
FILE *fileHandle;
char calibDir[1000];
 
// Read Response Calibration
 
fBoard->GetCalibrationDirectory(calibDir);
sprintf(fileName, "%s/board%d/ResponseCalib_board%d_chip%d_%dMHz.bin", calibDir,
fBoard->GetBoardSerialNumber(), fBoard->GetBoardSerialNumber(), chipIndex,
static_cast < int >(fBoard->GetNominalFrequency() * 1000));
 
fileHandle = fopen(fileName, "rb");
if (fileHandle == NULL) {
printf("Board %d --> Could not find response calibration file:\n", fBoard->GetBoardSerialNumber());
printf("%s\n", fileName);
return false;
}
 
if (fInitialized)
delete fCalibrationData[chipIndex];
fCalibrationData[chipIndex] = new CalibrationData(1);
CalibrationData *data = fCalibrationData[chipIndex];
CalibrationData::CalibrationDataChannel * chn;
data->fRead = true;
data->fHasOffsetCalibration = 1;
fCalibrationValid[chipIndex] = true;
data->fStartTemperature = 0;
data->fEndTemperature = 0;
 
// read channel
for (k = 0; k < kNumberOfCalibChannelsV4; k++) {
chn = data->fChannel[k];
for (l = 0; l < kNumberOfBins; l++) {
// Offset
num = fread(&chn->fOffset[l], 2, 1, fileHandle);
if (num != 1) {
printf("Error while reading response calibration file '%s'\n", fileName);
printf(" at 'Offset' of channel %d bin %d.\n", k, l);
return false;
}
if (fBoard->GetDRSType() == 3) {
// Gain
num = fread(&chn->fGain[l], 2, 1, fileHandle);
if (num != 1) {
printf("Error while reading response calibration file '%s'\n", fileName);
printf(" at 'Gain' of channel %d bin %d.\n", k, l);
return false;
}
}
}
}
 
fclose(fileHandle);
return true;
}
 
/*------------------------------------------------------------------*/
 
float ResponseCalibration::GetValue(float *coefficients, float u, int n)
{
int j, ii;
float bsplines[4];
ii = CalibrationData::CalculateBSpline(n, u, bsplines);
 
float s = 0;
for (j = 0; j < kBSplineOrder; j++) {
s += coefficients[ii + j] * bsplines[j];
}
return s;
}
 
/*------------------------------------------------------------------*/
 
int ResponseCalibration::Approx(float *p, float *uu, int np, int nu, float *coef)
{
int i, iu, j;
 
const int mbloc = 50;
int ip = 0;
int ir = 0;
int mt = 0;
int ileft, irow;
float bu[kBSplineOrder];
float *matrix[kBSplineOrder + 2];
for (i = 0; i < kBSplineOrder + 2; i++)
matrix[i] = new float[mbloc + nu + 1];
for (iu = kBSplineOrder - 1; iu < nu; iu++) {
for (i = 0; i < np; i++) {
if (1 <= uu[i])
ileft = nu - 1;
else if (uu[i] < 0)
ileft = kBSplineOrder - 2;
else
ileft = kBSplineOrder - 1 + static_cast < int >(uu[i] * (nu - kBSplineOrder + 1));
if (ileft != iu)
continue;
irow = ir + mt;
mt++;
CalibrationData::CalculateBSpline(nu, uu[i], bu);
for (j = 0; j < kBSplineOrder; j++) {
matrix[j][irow] = bu[j];
}
matrix[kBSplineOrder][irow] = p[i];
if (mt < mbloc)
continue;
LeastSquaresAccumulation(matrix, kBSplineOrder, &ip, &ir, mt, iu - kBSplineOrder + 1);
mt = 0;
}
if (mt == 0)
continue;
LeastSquaresAccumulation(matrix, kBSplineOrder, &ip, &ir, mt, iu - kBSplineOrder + 1);
mt = 0;
}
if (!LeastSquaresSolving(matrix, kBSplineOrder, ip, ir, coef, nu)) {
for (i = 0; i < kBSplineOrder + 2; i++)
delete matrix[i];
return 0;
}
 
for (i = 0; i < kBSplineOrder + 2; i++)
delete matrix[i];
return 1;
}
 
/*------------------------------------------------------------------*/
 
void ResponseCalibration::LeastSquaresAccumulation(float **matrix, int nb, int *ip, int *ir, int mt, int jt)
{
int i, j, l, mu, k, kh;
float rho;
 
if (mt <= 0)
return;
if (jt != *ip) {
if (jt > (*ir)) {
for (i = 0; i < mt; i++) {
for (j = 0; j < nb + 1; j++) {
matrix[j][jt + mt - i] = matrix[j][(*ir) + mt - i];
}
}
for (i = 0; i < jt - (*ir); i++) {
for (j = 0; j < nb + 1; j++) {
matrix[j][(*ir) + i] = 0;
}
}
*ir = jt;
}
mu = min(nb - 1, (*ir) - (*ip) - 1);
if (mu != 0) {
for (l = 0; l < mu; l++) {
k = min(l + 1, jt - (*ip));
for (i = l + 1; i < nb; i++) {
matrix[i - k][(*ip) + l + 1] = matrix[i][(*ip) + l + 1];
}
for (i = 0; i < k; i++) {
matrix[nb - i - 1][(*ip) + l + 1] = 0;
}
}
}
*ip = jt;
}
kh = min(nb + 1, (*ir) + mt - (*ip));
 
for (i = 0; i < kh; i++) {
Housholder(i, max(i + 1, (*ir) - (*ip)), (*ir) + mt - (*ip), matrix, i, (*ip), &rho, matrix, i + 1,
(*ip), 1, nb - i);
}
 
*ir = (*ip) + kh;
if (kh < nb + 1)
return;
for (i = 0; i < nb; i++) {
matrix[i][(*ir) - 1] = 0;
}
}
 
/*------------------------------------------------------------------*/
 
int ResponseCalibration::LeastSquaresSolving(float **matrix, int nb, int ip, int ir, float *x, int n)
{
int i, j, l, ii;
float s, rsq;
for (j = 0; j < n; j++) {
x[j] = matrix[nb][j];
}
rsq = 0;
if (n <= ir - 1) {
for (j = n; j < ir; j++) {
rsq += pow(matrix[nb][j], 2);
}
}
 
for (ii = 0; ii < n; ii++) {
i = n - ii - 1;
s = 0;
l = max(0, i - ip);
if (i != n - 1) {
for (j = 1; j < min(n - i, nb); j++) {
s += matrix[j + l][i] * x[i + j];
}
}
if (matrix[l][i] == 0) {
printf("Error in LeastSquaresSolving.\n");
return 0;
}
x[i] = (x[i] - s) / matrix[l][i];
}
return 1;
}
 
/*------------------------------------------------------------------*/
 
void ResponseCalibration::Housholder(int lpivot, int l1, int m, float **u, int iU1, int iU2, float *up,
float **c, int iC1, int iC2, int ice, int ncv)
{
int i, j, incr;
float tol = static_cast < float >(1e-20);
float tolb = static_cast < float >(1e-24);
float cl, clinv, sm, b;
 
if (lpivot < 0 || lpivot >= l1 || l1 > m - 1)
return;
cl = fabs(u[iU1][iU2 + lpivot]);
 
// Construct the transformation
for (j = l1 - 1; j < m; j++)
cl = max(fabsf(u[iU1][iU2 + j]), cl);
if (cl < tol)
return;
clinv = 1 / cl;
sm = pow(u[iU1][iU2 + lpivot] * clinv, 2);
for (j = l1; j < m; j++) {
sm = sm + pow(u[iU1][iU2 + j] * clinv, 2);
}
cl *= sqrt(sm);
if (u[iU1][iU2 + lpivot] > 0)
cl = -cl;
*up = u[iU1][iU2 + lpivot] - cl;
u[iU1][iU2 + lpivot] = cl;
 
if (ncv <= 0)
return;
b = (*up) * u[iU1][iU2 + lpivot];
if (fabs(b) < tolb)
return;
if (b >= 0)
return;
b = 1 / b;
incr = ice * (l1 - lpivot);
for (j = 0; j < ncv; j++) {
sm = c[iC1 + j][iC2 + lpivot] * (*up);
for (i = l1; i < m; i++) {
sm = sm + c[iC1 + j][iC2 + lpivot + incr + (i - l1) * ice] * u[iU1][iU2 + i];
}
if (sm == 0)
continue;
sm *= b;
c[iC1 + j][iC2 + lpivot] = c[iC1 + j][iC2 + lpivot] + sm * (*up);
for (i = l1; i < m; i++) {
c[iC1 + j][iC2 + lpivot + incr + (i - l1) * ice] =
c[iC1 + j][iC2 + lpivot + incr + (i - l1) * ice] + sm * u[iU1][iU2 + i];
}
}
}
 
/*------------------------------------------------------------------*/
 
int ResponseCalibration::MakeDir(const char *path)
{
struct stat buf;
if (stat(path, &buf)) {
#ifdef _MSC_VER
return mkdir(path);
#else
return mkdir(path, 0711);
#endif // R__UNIX
}
return 0;
}
 
/*------------------------------------------------------------------*/
 
ResponseCalibration::ResponseCalibration(DRSBoard * board)
: fBoard(board)
, fPrecision(0.1) // mV
, fInitialized(false)
, fRecorded(false)
, fFitted(false)
, fOffset(false)
, fNumberOfPointsLowVolt(0)
, fNumberOfPoints(0)
, fNumberOfMode2Bins(0)
, fNumberOfSamples(0)
, fNumberOfGridPoints(0)
, fNumberOfXConstPoints(0)
, fNumberOfXConstGridPoints(0)
, fTriggerFrequency(0)
, fShowStatistics(0)
, fCalibFile(0)
, fCurrentLowVoltPoint(0)
, fCurrentPoint(0)
, fCurrentSample(0)
, fCurrentFitChannel(0)
, fCurrentFitBin(0)
, fResponseY(0)
, fSamples(0)
, fSampleUsed(0)
, fXXFit(0)
, fYYFit(0)
, fWWFit(0)
, fYYFitRes(0)
, fYYSave(0)
, fXXSave(0)
, fStatisticsApprox(0)
, fStatisticsApproxExt(0)
{
int i;
// Initializing the Calibration Class
CalibrationData::fIntRevers[0] = 0;
for (i = 1; i < 2 * kBSplineOrder - 2; i++) {
CalibrationData::fIntRevers[i] = static_cast < float >(1.) / i;
}
for (i = 0; i < kNumberOfChipsMax; i++) {
fCalibrationData[i] = NULL;
}
// Initializing the Calibration Creation
fCalibrationValid[0] = false;
fCalibrationValid[1] = false;
}
 
/*------------------------------------------------------------------*/
 
ResponseCalibration::~ResponseCalibration()
{
// Delete the Calibration
for (int i=0 ; i<kNumberOfChipsMax ; i++)
delete fCalibrationData[i];
 
// Deleting the Calibration Creation
DeleteFields();
}
 
/*------------------------------------------------------------------*/
 
float ResponseCalibration::CalibrationData::fIntRevers[2 * kBSplineOrder - 2];
ResponseCalibration::CalibrationData::CalibrationData(int numberOfGridPoints)
:fRead(false)
, fNumberOfGridPoints(numberOfGridPoints)
, fHasOffsetCalibration(0)
, fStartTemperature(0)
, fEndTemperature(0)
, fMin(0)
, fMax(0)
, fNumberOfLimitGroups(0)
{
int i;
for (i = 0; i < kNumberOfCalibChannelsV3; i++) {
fChannel[i] = new CalibrationDataChannel(numberOfGridPoints);
}
for (i = 0; i < kNumberOfADCBins; i++) {
fBSplineOffsetLookUp[i] = NULL;
fBSplineLookUp[i] = NULL;
}
};
 
/*------------------------------------------------------------------*/
 
void ResponseCalibration::CalibrationData::PreCalculateBSpline()
{
int i, j;
float uu;
float xmin, xrange;
int nk = fNumberOfGridPoints - kBSplineOrder + 1;
for (i = 0; i < kNumberOfADCBins; i++) {
fBSplineLookUp[i] = new float *[fNumberOfLimitGroups];
fBSplineOffsetLookUp[i] = new int[fNumberOfLimitGroups];
for (j = 0; j < fNumberOfLimitGroups; j++) {
fBSplineLookUp[i][j] = new float[kBSplineOrder];
xmin = fMin + j * kBSplineXMinOffset;
xrange = fMax - xmin;
uu = (i - xmin) / xrange;
if (i < xmin) {
uu = 0;
}
if (i - xmin > xrange) {
uu = 1;
}
fBSplineOffsetLookUp[i][j] = static_cast < int >(uu * nk);
CalculateBSpline(fNumberOfGridPoints, uu, fBSplineLookUp[i][j]);
}
}
}
 
/*------------------------------------------------------------------*/
 
void ResponseCalibration::CalibrationData::DeletePreCalculatedBSpline()
{
int i, j;
for (i = 0; i < kNumberOfADCBins; i++) {
if (fBSplineLookUp[i] != NULL) {
for (j = 0; j < fNumberOfLimitGroups; j++)
delete fBSplineLookUp[i][j];
}
delete fBSplineLookUp[i];
delete fBSplineOffsetLookUp[i];
}
}
 
/*------------------------------------------------------------------*/
 
ResponseCalibration::CalibrationData::~CalibrationData()
{
int i, j;
for (i = 0; i < kNumberOfCalibChannelsV3; i++) {
delete fChannel[i];
}
for (i = 0; i < kNumberOfADCBins; i++) {
if (fBSplineLookUp[i] != NULL) {
for (j = 0; j < fNumberOfLimitGroups; j++) {
delete fBSplineLookUp[i][j];
}
}
delete fBSplineLookUp[i];
delete fBSplineOffsetLookUp[i];
}
};
 
/*------------------------------------------------------------------*/
 
int ResponseCalibration::CalibrationData::CalculateBSpline(int nGrid, float value, float *bsplines)
{
int minimum;
int maximum;
float xl;
 
int nk = nGrid - kBSplineOrder + 1;
float vl = value * nk;
int ivl = static_cast < int >(vl);
 
if (1 <= value) {
xl = vl - nk + 1;
minimum = 1 - nk;
} else if (value < 0) {
xl = vl;
minimum = 0;
} else {
xl = vl - ivl;
minimum = -ivl;
}
maximum = nk + minimum;
 
// printf("xl = %f\n",xl);
float vm, vmprev;
int jl, ju;
int nb = 0;
 
bsplines[0] = 1;
for (int i = 0; i < kBSplineOrder - 1; i++) {
vmprev = 0;
for (int j = 0; j < nb + 1; j++) {
jl = max(minimum, j - nb);
ju = min(maximum, j + 1);
vm = bsplines[j] * fIntRevers[ju - jl];
bsplines[j] = vm * (ju - xl) + vmprev;
vmprev = vm * (xl - jl);
}
nb++;
bsplines[nb] = vmprev;
}
return -minimum;
}
 
/*------------------------------------------------------------------*/
 
void ResponseCalibration::Average(int method, float *points, int numberOfPoints, float &mean, float &error,
float sigmaBoundary)
{
// Methods :
// 0 : Average
// 1 : Average inside sigmaBoundary*sigma
int i;
float sum = 0;
float sumSquare = 0;
 
if (method == 0 || method == 1) {
for (i = 0; i < numberOfPoints; i++) {
sum += points[i];
sumSquare += points[i] * points[i];
}
 
mean = sum / numberOfPoints;
error = sqrt((sumSquare - sum * sum / numberOfPoints) / (numberOfPoints - 1));
}
if (method == 1) {
int numberOfGoodPoints = numberOfPoints;
bool found = true;
bool *goodSample = new bool[numberOfGoodPoints];
for (i = 0; i < numberOfGoodPoints; i++)
goodSample[i] = true;
 
while (found) {
found = false;
for (i = 0; i < numberOfPoints; i++) {
if (goodSample[i] && fabs(points[i] - mean) > sigmaBoundary * error) {
found = true;
goodSample[i] = false;
numberOfGoodPoints--;
sum -= points[i];
sumSquare -= points[i] * points[i];
mean = sum / numberOfGoodPoints;
error = sqrt((sumSquare - sum * sum / numberOfGoodPoints) / (numberOfGoodPoints - 1));
}
}
}
delete[] goodSample;
}
}
/cvi/instr/drsctrl/DRS.obj
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: instr/drsctrl/LinkDef.h
===================================================================
--- instr/drsctrl/LinkDef.h (nonexistent)
+++ instr/drsctrl/LinkDef.h (revision 195)
@@ -0,0 +1,7 @@
+#ifdef __CINT__
+
+#pragma link off all globals;
+#pragma link off all classes;
+#pragma link C++ function TimerOut;
+
+#endif
Index: instr/drsctrl/Makefile
===================================================================
--- instr/drsctrl/Makefile (nonexistent)
+++ instr/drsctrl/Makefile (revision 195)
@@ -0,0 +1,208 @@
+#cmd.exe /k ""C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"" x86
+#set INCLUDE=%INCLUDE%;"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include"
+#set ROOTSYS=C:\root_v5.34.34
+#
+#nmake -f Makefile.win32
+#
+#set INCLUDE=%INCLUDE%;C:\Program Files\Microsoft SDKs\Windows\v7.1A\Include
+!if "$(CFG)" == ""
+!if ([findstr /c:"--build=debug" $(ROOTSYS)\bin\root-config > nul ] == 0)
+CFG = Win32 Debug
+!if ([findstr /c:"--disable-winrtdebug" $(ROOTSYS)\bin\root-config > nul ] == 0)
+RUNTIME = Release
+!else
+RUNTIME = Debug
+!endif
+!message No configuration specified: Defaulting to Win32 Debug
+!message With $(RUNTIME) Runtime DLL (Taken from ROOT config).
+!message .
+!else
+CFG = Win32 Release
+RUNTIME = Release
+!message No configuration specified: Defaulting to Win32 Release
+!message With $(RUNTIME) Runtime DLL (Taken from ROOT config).
+!message .
+!endif
+!else
+!if "$(CFG)" == "Win32 Release"
+RUNTIME = Release
+!elseif "$(CFG)" == "Win32 Debug"
+RUNTIME = Debug
+!endif
+!endif
+
+!if "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug"
+!message Invalid configuration "$(CFG)" specified.
+!message You can specify a configuration when running NMAKE
+!message by defining the macro CFG on the command line. For example:
+!message
+!message NMAKE /f "Makefile.msc" CFG="Win32 Debug"
+!message
+!message Possible choices for configuration are:
+!message
+!message "Win32 Release" (based on "Win32 (x86) Dynamic Library")
+!message "Win32 Debug" (based on "Win32 (x86) Dynamic Library")
+!message
+!error An invalid configuration is specified.
+!endif
+!message ROOTSYS = "$(ROOTSYS)/include"
+
+ObjSuf = obj
+SrcSuf = c
+SrcSuf1 = cpp
+ExeSuf = .exe
+DllSuf = dll
+OutPutOpt = -out:
+
+
+## VS2012 (VC11): configure subsystem version
+## See: https://blogs.msdn.com/b/vcblog/archive/2012/10/08/10357555.aspx
+## (APPVER used in win32.mak to set subsystem version)
+!if ([nmake /? 2>&1 | findstr /c:"Version 14\." > nul ] == 0)
+APPVER = 5.01
+!endif
+
+# Win32 system with Microsoft Visual C/C++
+!include <win32.mak>
+CC = $(cc)
+CXX = $(cc)
+CXXFLAGS = -nologo -EHsc -GR -DWIN32 -W3 -D_WINDOWS -DMAIN -DDLLMAIN -DHAVE_USB -DHAVE_LIBUSB10 -D_XKEYCHECK_H -DMYDLL_API\
+ -DVISUAL_CPLUSPLUS -I$(ROOTSYS)/include -Icvi -I. \
+ -wd4244
+#-FIw32pragma.h
+LD = $(link)
+
+!if "$(CFG)" == "Win32 Release"
+CXXOPT = -O2 -arch:SSE2 -MD
+LDOPT = -opt:ref
+!elseif "$(CFG)" == "Win32 Debug"
+!if "$(RUNTIME)" == "Debug"
+CXXOPT = -Z7 -MDd
+!else
+CXXOPT = -Z7 -O2 -arch:SSE2 -MD
+!endif
+LDOPT = -debug
+!endif
+
+# Check if nmake version is 8.xx or 9.xx
+!if ([nmake /? 2>&1 | findstr /c:"Version 8\." > nul ] == 0) || \
+ ([nmake /? 2>&1 | findstr /c:"Version 9\." > nul ] == 0)
+MT_EXE = mt -nologo -manifest $@.manifest -outputresource:$@;1
+MT_DLL = mt -nologo -manifest $@.manifest -outputresource:$@;2
+EXTRAFLAGS = -D_CRT_SECURE_NO_DEPRECATE
+!else if ([nmake /? 2>&1 | findstr /c:"Version 12\." > nul ] == 0)
+MT_EXE =
+MT_DLL =
+EXTRAFLAGS =
+!else if ([nmake /? 2>&1 | findstr /c:"Version 10\." > nul ] == 0)
+EXTRAFLAGS = -D_CRT_SECURE_NO_DEPRECATE
+!else if ([nmake /? 2>&1 | findstr /c:"Version 14\." > nul ] == 0)
+EXTRAFLAGS = -D_CRT_SECURE_NO_DEPRECATE
+!else
+MT_EXE =
+MT_DLL =
+EXTRAFLAGS = -G5
+!endif
+
+LDFLAGS1 = $(LDOPT) $(conlflags) -nologo -include:_G__cpp_setupG__Hist \
+ -include:_G__cpp_setupG__Graf -include:_G__cpp_setupG__G3D \
+ -include:_G__cpp_setupG__GPad -include:_G__cpp_setupG__Tree \
+ -include:_G__cpp_setupG__Rint -include:_G__cpp_setupG__PostScript \
+ -include:_G__cpp_setupG__Matrix -include:_G__cpp_setupG__Physics
+
+LDFLAGS1 = $(LDOPT) $(conlflags) -nologo
+
+SOFLAGS = $(dlllflags:-pdb:none=)
+ROOTLIBS = $(ROOTSYS)\lib\libCore.lib \
+ $(ROOTSYS)\lib\libCint.lib $(ROOTSYS)\lib\libHist.lib \
+ $(ROOTSYS)\lib\libGraf.lib $(ROOTSYS)\lib\libGraf3d.lib \
+ $(ROOTSYS)\lib\libGpad.lib $(ROOTSYS)\lib\libTree.lib \
+ $(ROOTSYS)\lib\libRint.lib $(ROOTSYS)\lib\libPostscript.lib \
+ $(ROOTSYS)\lib\libMatrix.lib $(ROOTSYS)\lib\libPhysics.lib \
+ $(ROOTSYS)\lib\libNet.lib $(ROOTSYS)\lib\libRIO.lib \
+ $(ROOTSYS)\lib\libMathCore.lib
+LIBS = libusb-1.0.lib
+GLIBS = $(LIBS) $(ROOTSYS)\lib\libGui.lib $(ROOTSYS)\lib\libGraf.lib \
+ $(ROOTSYS)\lib\libGpad.lib
+LIBSALL = libusb-1.0.lib
+
+
+
+
+#------------------------------------------------------------------------------
+MYAPP = drscl$(ExeSuf)
+MYAPPS = drscl.$(SrcSuf1) musbstd.$(SrcSuf) mxml.$(SrcSuf) strlcpy.$(SrcSuf) DRS.$(SrcSuf1) averager.$(SrcSuf1)
+
+MYAPPO = drscl.$(ObjSuf) musbstd.$(ObjSuf) mxml.$(ObjSuf) strlcpy.$(ObjSuf) DRS.$(ObjSuf) averager.$(ObjSuf)
+
+MYREADO = musbstd.$(ObjSuf) mxml.$(ObjSuf) DRS.$(ObjSuf) averager.$(ObjSuf) drsread.$(ObjSuf) XGetopt.$(ObjSuf) getopt_long.$(ObjSuf) timer.$(ObjSuf) gettimeofday.$(ObjSuf)
+
+OBJS = $(MYAPPO)
+PROGRAMS = $(MYAPP)
+
+#------------------------------------------------------------------------------
+
+!message LDFLAGS = "$(LDFLAGS)"
+!message MYAPP = "$(MYAPP)"
+!message MYAPPO = "$(MYAPPO)"
+!message PROGRAMS = "$(PROGRAMS)"
+
+
+all: $(PROGRAMS) drsread.exe drsread.dll
+
+
+
+RootShowerDict.$(SrcSuf): MyParticle.h MyDetector.h MyEvent.h RSLinkDef.h
+ @echo "Generating dictionary $@..."
+ @rootcint -f $@ -c MyParticle.h MyDetector.h MyEvent.h RSLinkDef.h
+
+#------------------------------------------------------------------------------
+
+clean:
+ @del *.obj *Dict.* *.def *.exp *.d *.log .def *.pdb *.ilk *.manifest
+
+distclean: clean
+ @del *.exe *.root *.ps *.lib *.dll
+
+$(MYAPP): $(MYAPPO)
+ @echo "Compiling $@ "
+ $(LD) $(LDFLAGS) /SUBSYSTEM:CONSOLE \
+ $(MYAPPO) $(LIBSALL) $(OutPutOpt)$@
+ @echo "$@ done"
+
+drscl.$(ObjSuf): drscl.$(SrcSuf1)
+ @echo "Compiling drs $@ "
+ $(CXX) $(CXXFLAGS) $(EXTRAFLAGS) $(CXXOPT) -c drscl.$(SrcSuf1)
+
+drsread.exe: $(MYREADO)
+ @echo "Compiling $@ "
+ $(LD) $(LDFLAGS) /SUBSYSTEM:CONSOLE \
+ $(MYREADO) $(LIBSALL) $(ROOTLIBS) $(OutPutOpt)$@
+ @echo "$@ done"
+
+drsread.dll: $(MYREADO)
+ @echo "DLL library $@ "
+ $(LD) /DLL $(MYREADO) $(LIBSALL) $(ROOTLIBS) /OUT:drsread.dll
+ @echo "$@ done"
+
+
+drsreadDict.cpp: drsread.h LinkDef.h
+ rootcint -f drsreadDict.cpp -c drsread.h LinkDef.h
+
+drsread.$(ObjSuf): drsread.$(SrcSuf1)
+ @echo "Compiling drsread $@ "
+ $(CXX) $(CXXFLAGS) $(EXTRAFLAGS) $(CXXOPT) -c drsread.$(SrcSuf1)
+
+drsread.$(ObjSuf): drsread.$(SrcSuf1)
+ @echo "Compiling drsread $@ "
+ $(CXX) $(CXXFLAGS) $(EXTRAFLAGS) $(CXXOPT) -c drsread.$(SrcSuf1)
+
+
+.$(SrcSuf1).$(ObjSuf):
+ @echo "Compiling object $@ "
+ $(CXX) $(CXXFLAGS) $(EXTRAFLAGS) $(CXXOPT) -c $<
+
+.c.$(ObjSuf):
+ @echo "Compiling object $@ "
+ $(CXX) $(CXXFLAGS) $(EXTRAFLAGS) $(CXXOPT) -c $<
+
Index: instr/drsctrl/XGetopt.cpp
===================================================================
--- instr/drsctrl/XGetopt.cpp (nonexistent)
+++ instr/drsctrl/XGetopt.cpp (revision 195)
@@ -0,0 +1,225 @@
+// XGetopt.cpp Version 1.2
+//
+// Author: Hans Dietrich
+// hdietrich2@hotmail.com
+//
+// Description:
+// XGetopt.cpp implements getopt(), a function to parse command lines.
+//
+// History
+// Version 1.2 - 2003 May 17
+// - Added Unicode support
+//
+// Version 1.1 - 2002 March 10
+// - Added example to XGetopt.cpp module header
+//
+// This software is released into the public domain.
+// You are free to use it in any way you like.
+//
+// This software is provided "as is" with no expressed
+// or implied warranty. I accept no liability for any
+// damage or loss of business that this software may cause.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////////////////////////////
+// if you are using precompiled headers then include this line:
+//#include "stdafx.h"
+///////////////////////////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////////////////////////////
+// if you are not using precompiled headers then include these lines:
+#include <windows.h>
+#include <stdio.h>
+#include <tchar.h>
+///////////////////////////////////////////////////////////////////////////////
+
+
+#include "XGetopt.h"
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// X G e t o p t . c p p
+//
+//
+// NAME
+// getopt -- parse command line options
+//
+// SYNOPSIS
+// int getopt(int argc, TCHAR *argv[], TCHAR *optstring)
+//
+// extern TCHAR *optarg;
+// extern int optind;
+//
+// DESCRIPTION
+// The getopt() function parses the command line arguments. Its
+// arguments argc and argv are the argument count and array as
+// passed into the application on program invocation. In the case
+// of Visual C++ programs, argc and argv are available via the
+// variables __argc and __argv (double underscores), respectively.
+// getopt returns the next option letter in argv that matches a
+// letter in optstring. (Note: Unicode programs should use
+// __targv instead of __argv. Also, all character and string
+// literals should be enclosed in _T( ) ).
+//
+// optstring is a string of recognized option letters; if a letter
+// is followed by a colon, the option is expected to have an argument
+// that may or may not be separated from it by white space. optarg
+// is set to point to the start of the option argument on return from
+// getopt.
+//
+// Option letters may be combined, e.g., "-ab" is equivalent to
+// "-a -b". Option letters are case sensitive.
+//
+// getopt places in the external variable optind the argv index
+// of the next argument to be processed. optind is initialized
+// to 0 before the first call to getopt.
+//
+// When all options have been processed (i.e., up to the first
+// non-option argument), getopt returns EOF, optarg will point
+// to the argument, and optind will be set to the argv index of
+// the argument. If there are no non-option arguments, optarg
+// will be set to NULL.
+//
+// The special option "--" may be used to delimit the end of the
+// options; EOF will be returned, and "--" (and everything after it)
+// will be skipped.
+//
+// RETURN VALUE
+// For option letters contained in the string optstring, getopt
+// will return the option letter. getopt returns a question mark (?)
+// when it encounters an option letter not included in optstring.
+// EOF is returned when processing is finished.
+//
+// BUGS
+// 1) Long options are not supported.
+// 2) The GNU double-colon extension is not supported.
+// 3) The environment variable POSIXLY_CORRECT is not supported.
+// 4) The + syntax is not supported.
+// 5) The automatic permutation of arguments is not supported.
+// 6) This implementation of getopt() returns EOF if an error is
+// encountered, instead of -1 as the latest standard requires.
+//
+// EXAMPLE
+// BOOL CMyApp::ProcessCommandLine(int argc, TCHAR *argv[])
+// {
+// int c;
+//
+// while ((c = getopt(argc, argv, _T("aBn:"))) != EOF)
+// {
+// switch (c)
+// {
+// case _T('a'):
+// TRACE(_T("option a\n"));
+// //
+// // set some flag here
+// //
+// break;
+//
+// case _T('B'):
+// TRACE( _T("option B\n"));
+// //
+// // set some other flag here
+// //
+// break;
+//
+// case _T('n'):
+// TRACE(_T("option n: value=%d\n"), atoi(optarg));
+// //
+// // do something with value here
+// //
+// break;
+//
+// case _T('?'):
+// TRACE(_T("ERROR: illegal option %s\n"), argv[optind-1]);
+// return FALSE;
+// break;
+//
+// default:
+// TRACE(_T("WARNING: no handler for option %c\n"), c);
+// return FALSE;
+// break;
+// }
+// }
+// //
+// // check for non-option args here
+// //
+// return TRUE;
+// }
+//
+///////////////////////////////////////////////////////////////////////////////
+
+//TCHAR *optarg; // global argument pointer
+char *optarg; // global argument pointer
+int optind = 0; // global argv index
+
+//int getopt(int argc, TCHAR *argv[], TCHAR *optstring)
+int getopt(int argc, char *argv[], char *optstring)
+{
+ //static TCHAR *next = NULL;
+ static char *next = NULL;
+ if (optind == 0)
+ next = NULL;
+
+ optarg = NULL;
+
+ if (next == NULL || *next == _T('\0'))
+ {
+ if (optind == 0)
+ optind++;
+
+ if (optind >= argc || argv[optind][0] != _T('-') || argv[optind][1] == _T('\0'))
+ {
+ optarg = NULL;
+ if (optind < argc)
+ optarg = argv[optind];
+ return EOF;
+ }
+
+ if (strcmp( argv[optind], _T("--")) == 0)
+ {
+ optind++;
+ optarg = NULL;
+ if (optind < argc)
+ optarg = argv[optind];
+ return EOF;
+ }
+
+ next = argv[optind];
+ next++; // skip past -
+ optind++;
+ }
+
+ //TCHAR c = *next++;
+ //TCHAR *cp = _tcschr(optstring, c);
+ char c = *next++;
+ //char *cp = _tcschr(optstring, c);
+ char *cp =strchr(optstring, c);
+
+ if (cp == NULL || c == _T(':'))
+ return _T('?');
+
+ cp++;
+ if (*cp == _T(':'))
+ {
+ if (*next != _T('\0'))
+ {
+ optarg = next;
+ next = NULL;
+ }
+ else if (optind < argc)
+ {
+ optarg = argv[optind];
+ optind++;
+ }
+ else
+ {
+ return _T('?');
+ }
+ }
+
+ return c;
+}
Index: instr/drsctrl/XGetopt.h
===================================================================
--- instr/drsctrl/XGetopt.h (nonexistent)
+++ instr/drsctrl/XGetopt.h (revision 195)
@@ -0,0 +1,25 @@
+// XGetopt.h Version 1.2
+//
+// Author: Hans Dietrich
+// hdietrich2@hotmail.com
+//
+// This software is released into the public domain.
+// You are free to use it in any way you like.
+//
+// This software is provided "as is" with no expressed
+// or implied warranty. I accept no liability for any
+// damage or loss of business that this software may cause.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef XGETOPT_H
+#define XGETOPT_H
+
+extern int optind, opterr;
+//extern TCHAR *optarg;
+extern char *optarg;
+
+//int getopt(int argc, TCHAR *argv[], TCHAR *optstring);
+int getopt(int argc, char *argv[], char *optstring);
+
+#endif //XGETOPT_H
Index: instr/drsctrl/XGetopt.obj
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/instr/drsctrl/XGetopt.obj
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: instr/drsctrl/averager.cpp
===================================================================
--- instr/drsctrl/averager.cpp (nonexistent)
+++ instr/drsctrl/averager.cpp (revision 195)
@@ -0,0 +1,214 @@
+/********************************************************************\
+
+ Name: averager.cpp
+ Created by: Stefan Ritt
+
+ Contents: Robust averager
+
+ $Id: averager.cpp 21210 2013-12-12 11:36:59Z ritt $
+
+\********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+
+#include "averager.h"
+
+/*----------------------------------------------------------------*/
+
+Averager::Averager(int nx, int ny, int nz, int dim)
+{
+ fNx = nx;
+ fNy = ny;
+ fNz = nz;
+ fDim = dim;
+
+ int size = sizeof(float)*nx*ny*nz * dim;
+ fArray = (float *)malloc(size);
+ assert(fArray);
+ memset(fArray, 0, size);
+ size = sizeof(float)*nx*ny*nz;
+ fN = (unsigned short *)malloc(size);
+ assert(fN);
+ memset(fN, 0, size);
+}
+
+/*----------------------------------------------------------------*/
+
+Averager::~Averager()
+{
+ if (fN)
+ free(fN);
+ if (fArray)
+ free(fArray);
+ fN = NULL;
+ fArray = NULL;
+}
+
+/*----------------------------------------------------------------*/
+
+void Averager::Add(int x, int y, int z, float value)
+{
+ assert(x < fNx);
+ assert(y < fNy);
+ assert(z < fNz);
+
+ int nIndex = (x*fNy + y)*fNz + z;
+ if (fN[nIndex] == fDim - 1) // check if array full
+ return;
+
+ int aIndex = ((x*fNy + y)*fNz + z) * fDim + fN[nIndex];
+ fN[nIndex]++;
+ fArray[aIndex] = value;
+}
+
+/*----------------------------------------------------------------*/
+
+void Averager::Reset()
+{
+ int size = sizeof(float)*fNx*fNy*fNz * fDim;
+ memset(fArray, 0, size);
+ size = sizeof(float)*fNx*fNy*fNz;
+ memset(fN, 0, size);
+}
+
+/*----------------------------------------------------------------*/
+
+int compar(const void *a, const void *b);
+
+int compar(const void *a, const void *b)
+{
+ if (*((float *)a) == *((float *)b))
+ return 0;
+
+ return (*((float *)a) < *((float *)b)) ? -1 : 1;
+}
+
+double Averager::Average(int x, int y, int z)
+{
+ assert(x < fNx);
+ assert(y < fNy);
+ assert(z < fNz);
+
+ double a = 0;
+
+ int nIndex = (x*fNy + y)*fNz + z;
+ int aIndex = ((x*fNy + y)*fNz + z) * fDim;
+
+ for (int i=0 ; i<fN[nIndex] ; i++)
+ a += fArray[aIndex + i];
+
+ if (fN[nIndex] > 0)
+ a /= fN[nIndex];
+
+ return a;
+}
+
+/*----------------------------------------------------------------*/
+
+double Averager::Median(int x, int y, int z)
+{
+ assert(x < fNx);
+ assert(y < fNy);
+ assert(z < fNz);
+
+ double m = 0;
+
+ int nIndex = (x*fNy + y)*fNz + z;
+ int aIndex = ((x*fNy + y)*fNz + z) * fDim;
+
+ qsort(&fArray[aIndex], fN[nIndex], sizeof(float), compar);
+ m = fArray[aIndex + fN[nIndex]/2];
+
+ return m;
+}
+
+/*----------------------------------------------------------------*/
+
+double Averager::RobustAverage(double range, int x, int y, int z)
+{
+ assert(x < fNx);
+ assert(y < fNy);
+ assert(z < fNz);
+
+ double ra = 0;
+ int n = 0;
+ double m = Median(x, y, z);
+
+ int nIndex = (x*fNy + y)*fNz + z;
+ int aIndex = ((x*fNy + y)*fNz + z) * fDim;
+
+ for (int i=0 ; i<fN[nIndex] ; i++) {
+ if (fArray[aIndex + i] > m - range && fArray[aIndex + i] < m + range) {
+ ra += fArray[aIndex + i];
+ n++;
+ }
+ }
+
+ if (n > 0)
+ ra /= n;
+
+ //if (y == 0 && z == 7 && fN[nIndex] > 10)
+ // printf("%d %lf %lf %lf\n", fN[nIndex], a, m, ra);
+
+ return ra;
+}
+
+/*----------------------------------------------------------------*/
+
+int Averager::SaveNormalizedDistribution(const char *filename, int x, float range)
+{
+ assert(x < fNx);
+ FILE *f = fopen(filename, "wt");
+
+ if (!f)
+ return 0;
+
+ fprintf(f, "X, Y, Z, Min, Max, Ave, Sigma\n");
+
+ for (int y=0 ; y<fNy ; y++)
+ for (int z=0 ; z<fNz ; z++) {
+
+ int nIndex = (x*fNy + y)*fNz + z;
+ int aIndex = ((x*fNy + y)*fNz + z) * fDim;
+
+ if (fN[nIndex] > 1) {
+ fprintf(f, "%d,%d, %d, ", x, y, z);
+
+ double s = 0;
+ double s2 = 0;
+ double min = 0;
+ double max = 0;
+ int n = fN[nIndex];
+ double m = Median(x, y, z);
+
+ for (int i=0 ; i<n ; i++) {
+ double v = fArray[aIndex + i] - m;
+ s += v;
+ s2 += v*v;
+ if (v < min)
+ min = v;
+ if (v > max)
+ max = v;
+ }
+ double sigma = sqrt((n * s2 - s * s) / (n * (n-1)));
+ double average = s / n;
+
+ fprintf(f, "%3.1lf, %3.1lf, %3.1lf, %3.3lf, ", min, max, average, sigma);
+
+ if (min < -range || max > range) {
+ for (int i=0 ; i<n ; i++)
+ fprintf(f, "%3.1lf,", fArray[aIndex + i] - m);
+ }
+
+ fprintf(f, "\n");
+ }
+ }
+
+ fclose(f);
+ return 1;
+}
+
Index: instr/drsctrl/averager.h
===================================================================
--- instr/drsctrl/averager.h (nonexistent)
+++ instr/drsctrl/averager.h (revision 195)
@@ -0,0 +1,28 @@
+/********************************************************************\
+
+ Name: averager.h
+ Created by: Stefan Ritt
+
+ Contents: Robust averager
+
+ $Id: averager.h 21220 2013-12-20 13:47:43Z ritt $
+
+\********************************************************************/
+
+class Averager {
+ int fNx, fNy, fNz, fDim;
+ float *fArray;
+ unsigned short *fN;
+
+public:
+ Averager(int nx, int ny, int nz, int dim);
+ ~Averager();
+
+ void Add(int x, int y, int z, float value);
+ void Reset();
+ double Average(int x, int y, int z);
+ double Median(int x, int y, int z);
+ double RobustAverage(double range, int x, int y, int z);
+ int SaveNormalizedDistribution(const char *filename, int x, float range);
+
+};
Index: instr/drsctrl/averager.obj
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/instr/drsctrl/averager.obj
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: instr/drsctrl/daq.h
===================================================================
--- instr/drsctrl/daq.h (nonexistent)
+++ instr/drsctrl/daq.h (revision 195)
@@ -0,0 +1,18 @@
+#ifndef _daq_h_
+#define _daq_h_
+
+#define BUFF_L 2048
+class daq {
+public:
+ unsigned long stackwrite[BUFF_L],stackdata[10000],stackdump[27000];
+int debug;
+int fStop;
+int event(unsigned int *, int);
+int init();
+int connect();
+int disconnect();
+daq();
+~daq();
+};
+
+#endif
Index: instr/drsctrl/drs.h
===================================================================
--- instr/drsctrl/drs.h (nonexistent)
+++ instr/drsctrl/drs.h (revision 195)
@@ -0,0 +1,950 @@
+/********************************************************************
+ DRS.h, S.Ritt, M. Schneebeli - PSI
+
+ $Id: DRS.h 21309 2014-04-11 14:51:29Z ritt $
+
+********************************************************************/
+#ifndef DRS_H
+#define DRS_H
+#include <stdio.h>
+#include <string.h>
+#include "averager.h"
+
+#ifdef HAVE_LIBUSB
+# ifndef HAVE_USB
+# define HAVE_USB
+# endif
+#endif
+
+#ifdef HAVE_USB
+# include "musbstd.h"
+#endif // HAVE_USB
+
+#ifdef HAVE_VME
+# include <mvmestd.h>
+#endif // HAVE_VME
+
+/* disable "deprecated" warning */
+#ifdef _MSC_VER
+#pragma warning(disable: 4996)
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+int drs_kbhit();
+unsigned int millitime();
+
+/* transport mode */
+#define TR_VME 1
+#define TR_USB 2
+#define TR_USB2 3
+
+/* address types */
+#ifndef T_CTRL
+#define T_CTRL 1
+#define T_STATUS 2
+#define T_RAM 3
+#define T_FIFO 4
+#endif
+
+/*---- Register addresses ------------------------------------------*/
+
+#define REG_CTRL 0x00000 /* 32 bit control reg */
+#define REG_DAC_OFS 0x00004
+#define REG_DAC0 0x00004
+#define REG_DAC1 0x00006
+#define REG_DAC2 0x00008
+#define REG_DAC3 0x0000A
+#define REG_DAC4 0x0000C
+#define REG_DAC5 0x0000E
+#define REG_DAC6 0x00010
+#define REG_DAC7 0x00012
+#define REG_CHANNEL_CONFIG 0x00014 // low byte
+#define REG_CONFIG 0x00014 // high byte
+#define REG_CHANNEL_MODE 0x00016
+#define REG_ADCCLK_PHASE 0x00016
+#define REG_FREQ_SET_HI 0x00018 // DRS2
+#define REG_FREQ_SET_LO 0x0001A // DRS2
+#define REG_TRG_DELAY 0x00018 // DRS4
+#define REG_FREQ_SET 0x0001A // DRS4
+#define REG_TRIG_DELAY 0x0001C
+#define REG_LMK_MSB 0x0001C // DRS4 Mezz
+#define REG_CALIB_TIMING 0x0001E // DRS2
+#define REG_EEPROM_PAGE_EVAL 0x0001E // DRS4 Eval
+#define REG_EEPROM_PAGE_MEZZ 0x0001A // DRS4 Mezz
+#define REG_TRG_CONFIG 0x0001C // DRS4 Eval4
+#define REG_LMK_LSB 0x0001E // DRS4 Mezz
+#define REG_WARMUP 0x00020 // DRS4 Mezz
+#define REG_COOLDOWN 0x00022 // DRS4 Mezz
+#define REG_READ_POINTER 0x00026 // DRS4 Mezz
+
+#define REG_MAGIC 0x00000
+#define REG_BOARD_TYPE 0x00002
+#define REG_STATUS 0x00004
+#define REG_RDAC_OFS 0x0000E
+#define REG_RDAC0 0x00008
+#define REG_STOP_CELL0 0x00008
+#define REG_RDAC1 0x0000A
+#define REG_STOP_CELL1 0x0000A
+#define REG_RDAC2 0x0000C
+#define REG_STOP_CELL2 0x0000C
+#define REG_RDAC3 0x0000E
+#define REG_STOP_CELL3 0x0000E
+#define REG_RDAC4 0x00000
+#define REG_RDAC5 0x00002
+#define REG_STOP_WSR0 0x00010
+#define REG_STOP_WSR1 0x00011
+#define REG_STOP_WSR2 0x00012
+#define REG_STOP_WSR3 0x00013
+#define REG_RDAC6 0x00014
+#define REG_RDAC7 0x00016
+#define REG_EVENTS_IN_FIFO 0x00018
+#define REG_EVENT_COUNT 0x0001A
+#define REG_FREQ1 0x0001C
+#define REG_FREQ2 0x0001E
+#define REG_WRITE_POINTER 0x0001E
+#define REG_TEMPERATURE 0x00020
+#define REG_TRIGGER_BUS 0x00022
+#define REG_SERIAL_BOARD 0x00024
+#define REG_VERSION_FW 0x00026
+#define REG_SCALER0 0x00028
+#define REG_SCALER1 0x0002C
+#define REG_SCALER2 0x00030
+#define REG_SCALER3 0x00034
+#define REG_SCALER4 0x00038
+#define REG_SCALER5 0x0003C
+
+/*---- Control register bit definitions ----------------------------*/
+
+#define BIT_START_TRIG (1<<0) // write a "1" to start domino wave
+#define BIT_REINIT_TRIG (1<<1) // write a "1" to stop & reset DRS
+#define BIT_SOFT_TRIG (1<<2) // write a "1" to stop and read data to RAM
+#define BIT_EEPROM_WRITE_TRIG (1<<3) // write a "1" to write into serial EEPROM
+#define BIT_EEPROM_READ_TRIG (1<<4) // write a "1" to read from serial EEPROM
+#define BIT_MULTI_BUFFER (1<<16) // Use multi buffering when "1"
+#define BIT_DMODE (1<<17) // (*DRS2*) 0: single shot, 1: circular
+#define BIT_ADC_ACTIVE (1<<17) // (*DRS4*) 0: stop ADC when running, 1: ADC always clocked
+#define BIT_LED (1<<18) // 1=on, 0=blink during readout
+#define BIT_TCAL_EN (1<<19) // switch on (1) / off (0) for 33 MHz calib signal
+#define BIT_TCAL_SOURCE (1<<20)
+#define BIT_REFCLK_SOURCE (1<<20)
+#define BIT_FREQ_AUTO_ADJ (1<<21) // DRS2/3
+#define BIT_TRANSP_MODE (1<<21) // DRS4
+#define BIT_ENABLE_TRIGGER1 (1<<22) // External LEMO/FP/TRBUS trigger
+#define BIT_LONG_START_PULSE (1<<23) // (*DRS2*) 0:short start pulse (>0.8GHz), 1:long start pulse (<0.8GHz)
+#define BIT_READOUT_MODE (1<<23) // (*DRS3*,*DRS4*) 0:start from first bin, 1:start from domino stop
+#define BIT_DELAYED_START (1<<24) // DRS2: start domino wave 400ns after soft trigger, used for waveform
+ // generator startup
+#define BIT_NEG_TRIGGER (1<<24) // DRS4: use high-to-low trigger if set
+#define BIT_ACAL_EN (1<<25) // connect DRS to inputs (0) or to DAC6 (1)
+#define BIT_TRIGGER_DELAYED (1<<26) // select delayed trigger from trigger bus
+#define BIT_ADCCLK_INVERT (1<<26) // invert ADC clock
+#define BIT_REFCLK_EXT (1<<26) // use external MMCX CLKIN refclk
+#define BIT_DACTIVE (1<<27) // keep domino wave running during readout
+#define BIT_STANDBY_MODE (1<<28) // put chip in standby mode
+#define BIT_TR_SOURCE1 (1<<29) // trigger source selection bits
+#define BIT_DECIMATION (1<<29) // drop all odd samples (DRS4 mezz.)
+#define BIT_TR_SOURCE2 (1<<30) // trigger source selection bits
+#define BIT_ENABLE_TRIGGER2 (1<<31) // analog threshold (internal) trigger
+
+/* DRS4 configuration register bit definitions */
+#define BIT_CONFIG_DMODE (1<<8) // 0: single shot, 1: circular
+#define BIT_CONFIG_PLLEN (1<<9) // write a "1" to enable the internal PLL
+#define BIT_CONFIG_WSRLOOP (1<<10) // write a "1" to connect WSROUT to WSRIN internally
+
+/*---- Status register bit definitions -----------------------------*/
+
+#define BIT_RUNNING (1<<0) // one if domino wave running or readout in progress
+#define BIT_NEW_FREQ1 (1<<1) // one if new frequency measurement available
+#define BIT_NEW_FREQ2 (1<<2)
+#define BIT_PLL_LOCKED0 (1<<1) // 1 if PLL has locked (DRS4 evaluation board only)
+#define BIT_PLL_LOCKED1 (1<<2) // 1 if PLL DRS4 B has locked (DRS4 mezzanine board only)
+#define BIT_PLL_LOCKED2 (1<<3) // 1 if PLL DRS4 C has locked (DRS4 mezzanine board only)
+#define BIT_PLL_LOCKED3 (1<<4) // 1 if PLL DRS4 D has locked (DRS4 mezzanine board only)
+#define BIT_SERIAL_BUSY (1<<5) // 1 if EEPROM operation in progress
+#define BIT_LMK_LOCKED (1<<6) // 1 if PLL of LMK chip has locked (DRS4 mezzanine board only)
+#define BIT_2048_MODE (1<<7) // 1 if 2048-bin mode has been soldered
+
+enum DRSBoardConstants {
+ kNumberOfChannelsMax = 10,
+ kNumberOfCalibChannelsV3 = 10,
+ kNumberOfCalibChannelsV4 = 8,
+ kNumberOfBins = 1024,
+ kNumberOfChipsMax = 4,
+ kFrequencyCacheSize = 10,
+ kBSplineOrder = 4,
+ kPreCaliculatedBSplines = 1000,
+ kPreCaliculatedBSplineGroups = 5,
+ kNumberOfADCBins = 4096,
+ kBSplineXMinOffset = 20,
+ kMaxNumberOfClockCycles = 100,
+};
+
+enum DRSErrorCodes {
+ kSuccess = 0,
+ kInvalidTriggerSignal = -1,
+ kWrongChannelOrChip = -2,
+ kInvalidTransport = -3,
+ kZeroSuppression = -4,
+ kWaveNotAvailable = -5
+};
+
+/*---- callback class ----*/
+
+class DRSCallback
+{
+public:
+ virtual void Progress(int value) = 0;
+ virtual ~DRSCallback() {};
+};
+
+/*------------------------*/
+
+class DRSBoard;
+
+class ResponseCalibration {
+protected:
+
+ class CalibrationData {
+ public:
+ class CalibrationDataChannel {
+ public:
+ unsigned char fLimitGroup[kNumberOfBins]; //!
+ float fMin[kNumberOfBins]; //!
+ float fRange[kNumberOfBins]; //!
+ short fOffset[kNumberOfBins]; //!
+ short fGain[kNumberOfBins]; //!
+ unsigned short fOffsetADC[kNumberOfBins]; //!
+ short *fData[kNumberOfBins]; //!
+ unsigned char *fLookUp[kNumberOfBins]; //!
+ unsigned short fLookUpOffset[kNumberOfBins]; //!
+ unsigned char fNumberOfLookUpPoints[kNumberOfBins]; //!
+ float *fTempData; //!
+
+ private:
+ CalibrationDataChannel(const CalibrationDataChannel &c); // not implemented
+ CalibrationDataChannel &operator=(const CalibrationDataChannel &rhs); // not implemented
+
+ public:
+ CalibrationDataChannel(int numberOfGridPoints)
+ :fTempData(new float[numberOfGridPoints]) {
+ int i;
+ for (i = 0; i < kNumberOfBins; i++) {
+ fData[i] = new short[numberOfGridPoints];
+ }
+ memset(fLimitGroup, 0, sizeof(fLimitGroup));
+ memset(fMin, 0, sizeof(fMin));
+ memset(fRange, 0, sizeof(fRange));
+ memset(fOffset, 0, sizeof(fOffset));
+ memset(fGain, 0, sizeof(fGain));
+ memset(fOffsetADC, 0, sizeof(fOffsetADC));
+ memset(fLookUp, 0, sizeof(fLookUp));
+ memset(fLookUpOffset, 0, sizeof(fLookUpOffset));
+ memset(fNumberOfLookUpPoints, 0, sizeof(fNumberOfLookUpPoints));
+ }
+ ~CalibrationDataChannel() {
+ int i;
+ delete fTempData;
+ for (i = 0; i < kNumberOfBins; i++) {
+ delete fData[i];
+ delete fLookUp[i];
+ }
+ }
+ };
+
+ bool fRead; //!
+ CalibrationDataChannel *fChannel[10]; //!
+ unsigned char fNumberOfGridPoints; //!
+ int fHasOffsetCalibration; //!
+ float fStartTemperature; //!
+ float fEndTemperature; //!
+ int *fBSplineOffsetLookUp[kNumberOfADCBins]; //!
+ float **fBSplineLookUp[kNumberOfADCBins]; //!
+ float fMin; //!
+ float fMax; //!
+ unsigned char fNumberOfLimitGroups; //!
+ static float fIntRevers[2 * kBSplineOrder - 2];
+
+ private:
+ CalibrationData(const CalibrationData &c); // not implemented
+ CalibrationData &operator=(const CalibrationData &rhs); // not implemented
+
+ public:
+ CalibrationData(int numberOfGridPoints);
+ ~CalibrationData();
+ static int CalculateBSpline(int nGrid, float value, float *bsplines);
+ void PreCalculateBSpline();
+ void DeletePreCalculatedBSpline();
+ };
+
+ // General Fields
+ DRSBoard *fBoard;
+
+ double fPrecision;
+
+ // Fields for creating the Calibration
+ bool fInitialized;
+ bool fRecorded;
+ bool fFitted;
+ bool fOffset;
+ bool fCalibrationValid[2];
+
+ int fNumberOfPointsLowVolt;
+ int fNumberOfPoints;
+ int fNumberOfMode2Bins;
+ int fNumberOfSamples;
+ int fNumberOfGridPoints;
+ int fNumberOfXConstPoints;
+ int fNumberOfXConstGridPoints;
+ double fTriggerFrequency;
+ int fShowStatistics;
+ FILE *fCalibFile;
+
+ int fCurrentLowVoltPoint;
+ int fCurrentPoint;
+ int fCurrentSample;
+ int fCurrentFitChannel;
+ int fCurrentFitBin;
+
+ float *fResponseX[10][kNumberOfBins];
+ float *fResponseY;
+ unsigned short **fWaveFormMode3[10];
+ unsigned short **fWaveFormMode2[10];
+ short **fWaveFormOffset[10];
+ unsigned short **fWaveFormOffsetADC[10];
+ unsigned short *fSamples;
+ int *fSampleUsed;
+
+ float *fPntX[2];
+ float *fPntY[2];
+ float *fUValues[2];
+ float *fRes[kNumberOfBins];
+ float *fResX[kNumberOfBins];
+
+ double *fXXFit;
+ double *fYYFit;
+ double *fWWFit;
+ double *fYYFitRes;
+ double *fYYSave;
+ double *fXXSave;
+ double fGainMin;
+ double fGainMax;
+
+ float **fStatisticsApprox;
+ float **fStatisticsApproxExt;
+
+ // Fields for applying the Calibration
+ CalibrationData *fCalibrationData[kNumberOfChipsMax];
+
+private:
+ ResponseCalibration(const ResponseCalibration &c); // not implemented
+ ResponseCalibration &operator=(const ResponseCalibration &rhs); // not implemented
+
+public:
+ ResponseCalibration(DRSBoard* board);
+ ~ResponseCalibration();
+
+ void SetCalibrationParameters(int numberOfPointsLowVolt, int numberOfPoints, int numberOfMode2Bins,
+ int numberOfSamples, int numberOfGridPoints, int numberOfXConstPoints,
+ int numberOfXConstGridPoints, double triggerFrequency, int showStatistics = 0);
+ void ResetCalibration();
+ bool RecordCalibrationPoints(int chipNumber);
+ bool RecordCalibrationPointsV3(int chipNumber);
+ bool RecordCalibrationPointsV4(int chipNumber);
+ bool FitCalibrationPoints(int chipNumber);
+ bool FitCalibrationPointsV3(int chipNumber);
+ bool FitCalibrationPointsV4(int chipNumber);
+ bool OffsetCalibration(int chipNumber);
+ bool OffsetCalibrationV3(int chipNumber);
+ bool OffsetCalibrationV4(int chipNumber);
+ double GetTemperature(unsigned int chipIndex);
+
+ bool WriteCalibration(unsigned int chipIndex);
+ bool WriteCalibrationV3(unsigned int chipIndex);
+ bool WriteCalibrationV4(unsigned int chipIndex);
+ bool ReadCalibration(unsigned int chipIndex);
+ bool ReadCalibrationV3(unsigned int chipIndex);
+ bool ReadCalibrationV4(unsigned int chipIndex);
+ bool Calibrate(unsigned int chipIndex, unsigned int channel, unsigned short *adcWaveform, short *uWaveform,
+ int triggerCell, float threshold, bool offsetCalib);
+ bool SubtractADCOffset(unsigned int chipIndex, unsigned int channel, unsigned short *adcWaveform,
+ unsigned short *adcCalibratedWaveform, unsigned short newBaseLevel);
+ bool IsRead(int chipIndex) const { return fCalibrationValid[chipIndex]; }
+ double GetPrecision() const { return fPrecision; };
+
+ double GetOffsetAt(int chip,int chn,int bin) const { return fCalibrationData[chip]->fChannel[chn]->fOffset[bin]; };
+ double GetGainAt(int chip,int chn,int bin) const { return fCalibrationData[chip]->fChannel[chn]->fGain[bin]; };
+ double GetMeasPointXAt(int ip) const { return fXXSave[ip]; };
+ double GetMeasPointYAt(int ip) const { return fYYSave[ip]; };
+
+protected:
+ void InitFields(int numberOfPointsLowVolt, int numberOfPoints, int numberOfMode2Bins, int numberOfSamples,
+ int numberOfGridPoints, int numberOfXConstPoints, int numberOfXConstGridPoints,
+ double triggerFrequency, int showStatistics);
+ void DeleteFields();
+ void CalibrationTrigger(int mode, double voltage);
+ void CalibrationStart(double voltage);
+
+ static float GetValue(float *coefficients, float u, int n);
+ static int Approx(float *p, float *uu, int np, int nu, float *coef);
+ static void LeastSquaresAccumulation(float **matrix, int nb, int *ip, int *ir, int mt, int jt);
+ static int LeastSquaresSolving(float **matrix, int nb, int ip, int ir, float *x, int n);
+ static void Housholder(int lpivot, int l1, int m, float **u, int iU1, int iU2, float *up, float **c, int iC1,
+ int iC2, int ice, int ncv);
+
+ static int MakeDir(const char *path);
+ static void Average(int method,float *samples,int numberOfSamples,float &mean,float &error,float sigmaBoundary);
+};
+
+
+class DRSBoard {
+protected:
+ class TimeData {
+ public:
+ class FrequencyData {
+ public:
+ int fFrequency;
+ double fBin[kNumberOfBins];
+ };
+
+ enum {
+ kMaxNumberOfFrequencies = 4000
+ };
+ int fChip;
+ int fNumberOfFrequencies;
+ FrequencyData *fFrequency[kMaxNumberOfFrequencies];
+
+ private:
+ TimeData(const TimeData &c); // not implemented
+ TimeData &operator=(const TimeData &rhs); // not implemented
+
+ public:
+ TimeData()
+ :fChip(0)
+ ,fNumberOfFrequencies(0) {
+ }
+ ~TimeData() {
+ int i;
+ for (i = 0; i < fNumberOfFrequencies; i++) {
+ delete fFrequency[i];
+ }
+ }
+ };
+
+public:
+ // DAC channels (CMC Version 1 : DAC_COFSA,DAC_COFSB,DAC_DRA,DAC_DSA,DAC_TLEVEL,DAC_ACALIB,DAC_DSB,DAC_DRB)
+ unsigned int fDAC_COFSA;
+ unsigned int fDAC_COFSB;
+ unsigned int fDAC_DRA;
+ unsigned int fDAC_DSA;
+ unsigned int fDAC_TLEVEL;
+ unsigned int fDAC_ACALIB;
+ unsigned int fDAC_DSB;
+ unsigned int fDAC_DRB;
+ // DAC channels (CMC Version 2+3 : DAC_COFS,DAC_DSA,DAC_DSB,DAC_TLEVEL,DAC_ADCOFS,DAC_CLKOFS,DAC_ACALIB)
+ unsigned int fDAC_COFS;
+ unsigned int fDAC_ADCOFS;
+ unsigned int fDAC_CLKOFS;
+ // DAC channels (CMC Version 4 : DAC_ROFS_1,DAC_DSA,DAC_DSB,DAC_ROFS_2,DAC_ADCOFS,DAC_ACALIB,DAC_INOFS,DAC_BIAS)
+ unsigned int fDAC_ROFS_1;
+ unsigned int fDAC_ROFS_2;
+ unsigned int fDAC_INOFS;
+ unsigned int fDAC_BIAS;
+ // DAC channels (USB EVAL1 (fBoardType 5) : DAC_ROFS_1,DAC_CMOFS,DAC_CALN,DAC_CALP,DAC_BIAS,DAC_TLEVEL,DAC_ONOFS)
+ // DAC channels (USB EVAL3 (fBoardType 7) : DAC_ROFS_1,DAC_CMOFS,DAC_CALN,DAC_CALP,DAC_BIAS,DAC_TLEVEL,DAC_ONOFS)
+ unsigned int fDAC_CMOFS;
+ unsigned int fDAC_CALN;
+ unsigned int fDAC_CALP;
+ unsigned int fDAC_ONOFS;
+ // DAC channels (DRS4 MEZZ1 (fBoardType 6) : DAC_ONOFS,DAC_CMOFSP,DAC_CALN,DAC_CALP,DAC_BIAS,DAC_CMOFSN,DAC_ROFS_1)
+ unsigned int fDAC_CMOFSP;
+ unsigned int fDAC_CMOFSN;
+ // DAC channels (DRS4 EVAL4 (fBoardType 8) : DAC_ONOFS,DAC_TLEVEL4,DAC_CALN,DAC_CALP,DAC_BIAS,DAC_TLEVEL1,DAC_TLEVEL2,DAC_TLEVEL3)
+ unsigned int fDAC_TLEVEL1;
+ unsigned int fDAC_TLEVEL2;
+ unsigned int fDAC_TLEVEL3;
+ unsigned int fDAC_TLEVEL4;
+
+protected:
+ // Fields for DRS
+ int fDRSType;
+ int fBoardType;
+ int fNumberOfChips;
+ int fNumberOfChannels;
+ int fRequiredFirmwareVersion;
+ int fFirmwareVersion;
+ int fBoardSerialNumber;
+ int fHasMultiBuffer;
+ unsigned int fTransport;
+ unsigned int fCtrlBits;
+ int fNumberOfReadoutChannels;
+ int fReadoutChannelConfig;
+ int fADCClkPhase;
+ bool fADCClkInvert;
+ double fExternalClockFrequency;
+#ifdef HAVE_USB
+ MUSB_INTERFACE *fUsbInterface;
+#endif
+#ifdef HAVE_VME
+ MVME_INTERFACE *fVmeInterface;
+ mvme_addr_t fBaseAddress;
+#endif
+ int fSlotNumber;
+ double fNominalFrequency;
+ double fTrueFrequency;
+ double fTCALFrequency;
+ double fRefClock;
+ int fMultiBuffer;
+ int fDominoMode;
+ int fDominoActive;
+ int fADCActive;
+ int fChannelConfig;
+ int fChannelCascading;
+ int fChannelDepth;
+ int fWSRLoop;
+ int fReadoutMode;
+ unsigned short fReadPointer;
+ int fNMultiBuffer;
+ int fTriggerEnable1;
+ int fTriggerEnable2;
+ int fTriggerSource;
+ int fTriggerDelay;
+ double fTriggerDelayNs;
+ int fSyncDelay;
+ int fDelayedStart;
+ int fTranspMode;
+ int fDecimation;
+ unsigned short fStopCell[4];
+ unsigned char fStopWSR[4];
+ unsigned short fTriggerBus;
+ double fROFS;
+ double fRange;
+ double fCommonMode;
+ int fAcalMode;
+ int fbkAcalMode;
+ double fAcalVolt;
+ double fbkAcalVolt;
+ int fTcalFreq;
+ int fbkTcalFreq;
+ int fTcalLevel;
+ int fbkTcalLevel;
+ int fTcalPhase;
+ int fTcalSource;
+ int fRefclk;
+
+ unsigned char fWaveforms[kNumberOfChipsMax * kNumberOfChannelsMax * 2 * kNumberOfBins];
+
+ // Fields for Calibration
+ int fMaxChips;
+ char fCalibDirectory[1000];
+
+ // Fields for Response Calibration old method
+ ResponseCalibration *fResponseCalibration;
+
+ // Fields for Calibration new method
+ bool fVoltageCalibrationValid;
+ double fCellCalibratedRange;
+ double fCellCalibratedTemperature;
+ unsigned short fCellOffset[kNumberOfChipsMax * kNumberOfChannelsMax][kNumberOfBins];
+ unsigned short fCellOffset2[kNumberOfChipsMax * kNumberOfChannelsMax][kNumberOfBins];
+ double fCellGain[kNumberOfChipsMax * kNumberOfChannelsMax][kNumberOfBins];
+
+ double fTimingCalibratedFrequency;
+ double fCellDT[kNumberOfChipsMax][kNumberOfChannelsMax][kNumberOfBins];
+
+ // Fields for Time Calibration
+ TimeData **fTimeData;
+ int fNumberOfTimeData;
+
+ // General debugging flag
+ int fDebug;
+
+ // Fields for wave transfer
+ bool fWaveTransferred[kNumberOfChipsMax * kNumberOfChannelsMax];
+
+ // Waveform Rotation
+ int fTriggerStartBin; // Start Bin of the trigger
+
+private:
+ DRSBoard(const DRSBoard &c); // not implemented
+ DRSBoard &operator=(const DRSBoard &rhs); // not implemented
+
+public:
+ // Public Methods
+#ifdef HAVE_USB
+ DRSBoard(MUSB_INTERFACE * musb_interface, int usb_slot);
+#endif
+#ifdef HAVE_VME
+ DRSBoard(MVME_INTERFACE * mvme_interface, mvme_addr_t base_address, int slot_number);
+
+ MVME_INTERFACE *GetVMEInterface() const { return fVmeInterface; };
+#endif
+ ~DRSBoard();
+
+ int SetBoardSerialNumber(unsigned short serialNumber);
+ int GetBoardSerialNumber() const { return fBoardSerialNumber; }
+ int HasMultiBuffer() const { return fHasMultiBuffer; }
+ int GetFirmwareVersion() const { return fFirmwareVersion; }
+ int GetRequiredFirmwareVersion() const { return fRequiredFirmwareVersion; }
+ int GetDRSType() const { return fDRSType; }
+ int GetBoardType() const { return fBoardType; }
+ int GetNumberOfChips() const { return fNumberOfChips; }
+ // channel : Flash ADC index
+ // readout channel : VME readout index
+ // input : Input on board
+ int GetNumberOfChannels() const { return fNumberOfChannels; }
+ int GetChannelDepth() const { return fChannelDepth; }
+ int GetChannelCascading() const { return fChannelCascading; }
+ inline int GetNumberOfReadoutChannels() const;
+ inline int GetWaveformBufferSize() const;
+ inline int GetNumberOfInputs() const;
+ inline int GetNumberOfCalibInputs() const;
+ inline int GetClockChannel() const;
+ inline int GetTriggerChannel() const;
+ inline int GetClockInput() const { return Channel2Input(GetClockChannel()); }
+ inline int GetTriggerInput() const { return fDRSType < 4 ? Channel2Input(GetTriggerChannel()) : -1; }
+ inline int Channel2Input(int channel) const;
+ inline int Channel2ReadoutChannel(int channel) const;
+ inline int Input2Channel(int input, int ind = 0) const;
+ inline int Input2ReadoutChannel(int input, int ind = 0) const;
+ inline int ReadoutChannel2Channel(int readout) const;
+ inline int ReadoutChannel2Input(int readout) const;
+
+ inline bool IsCalibChannel(int ch) const;
+ inline bool IsCalibInput(int input) const;
+ int GetSlotNumber() const { return fSlotNumber; }
+ int InitFPGA(void);
+ int Write(int type, unsigned int addr, void *data, int size);
+ int Read(int type, void *data, unsigned int addr, int size);
+ int GetTransport() const { return fTransport; }
+ void RegisterTest(void);
+ int RAMTest(int flag);
+ int ChipTest();
+ unsigned int GetCtrlReg(void);
+ unsigned short GetConfigReg(void);
+ unsigned int GetStatusReg(void);
+ void SetLED(int state);
+ int SetChannelConfig(int firstChannel, int lastChannel, int nConfigChannels);
+ void SetADCClkPhase(int phase, bool invert);
+ void SetWarmup(unsigned int ticks);
+ void SetCooldown(unsigned int ticks);
+ int GetReadoutChannelConfig() { return fReadoutChannelConfig; }
+ void SetNumberOfChannels(int nChannels);
+ int EnableTrigger(int flag1, int flag2);
+ int GetTriggerEnable(int i) { return i?fTriggerEnable2:fTriggerEnable1; }
+ int SetDelayedTrigger(int flag);
+ int SetTriggerDelayPercent(int delay);
+ int SetTriggerDelayNs(int delay);
+ int GetTriggerDelay() { return fTriggerDelay; }
+ double GetTriggerDelayNs() { return fTriggerDelayNs; }
+ int SetSyncDelay(int ticks);
+ int SetTriggerLevel(double value);
+ int SetIndividualTriggerLevel(int channel, double voltage);
+ int SetTriggerPolarity(bool negative);
+ int SetTriggerSource(int source);
+ int GetTriggerSource() { return fTriggerSource; }
+ int SetDelayedStart(int flag);
+ int SetTranspMode(int flag);
+ int SetStandbyMode(int flag);
+ int SetDecimation(int flag);
+ int GetDecimation() { return fDecimation; }
+ int IsBusy(void);
+ int IsEventAvailable(void);
+ int IsPLLLocked(void);
+ int IsLMKLocked(void);
+ int IsNewFreq(unsigned char chipIndex);
+ int SetDAC(unsigned char channel, double value);
+ int ReadDAC(unsigned char channel, double *value);
+ int GetRegulationDAC(double *value);
+ int StartDomino();
+ int StartClearCycle();
+ int FinishClearCycle();
+ int Reinit();
+ int Init();
+ void SetDebug(int debug) { fDebug = debug; }
+ int Debug() { return fDebug; }
+ int SetDominoMode(unsigned char mode);
+ int SetDominoActive(unsigned char mode);
+ int SetReadoutMode(unsigned char mode);
+ int SoftTrigger(void);
+ int ReadFrequency(unsigned char chipIndex, double *f);
+ int SetFrequency(double freq, bool wait);
+ double VoltToFreq(double volt);
+ double FreqToVolt(double freq);
+ double GetNominalFrequency() const { return fNominalFrequency; }
+ double GetTrueFrequency();
+ int RegulateFrequency(double freq);
+ int SetExternalClockFrequency(double frequencyMHz);
+ double GetExternalClockFrequency();
+ int SetMultiBuffer(int flag);
+ int IsMultiBuffer() { return fMultiBuffer; }
+ void ResetMultiBuffer(void);
+ int GetMultiBufferRP(void);
+ int SetMultiBufferRP(unsigned short rp);
+ int GetMultiBufferWP(void);
+ void IncrementMultiBufferRP(void);
+ void SetVoltageOffset(double offset1, double offset2);
+ int SetInputRange(double center);
+ double GetInputRange(void) { return fRange; }
+ double GetCalibratedInputRange(void) { return fCellCalibratedRange; }
+ double GetCalibratedTemperature(void) { return fCellCalibratedTemperature; }
+ double GetCalibratedFrequency(void) { return fTimingCalibratedFrequency; }
+ int TransferWaves(int numberOfChannels = kNumberOfChipsMax * kNumberOfChannelsMax);
+ int TransferWaves(unsigned char *p, int numberOfChannels = kNumberOfChipsMax * kNumberOfChannelsMax);
+ int TransferWaves(int firstChannel, int lastChannel);
+ int TransferWaves(unsigned char *p, int firstChannel, int lastChannel);
+ int DecodeWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel,
+ unsigned short *waveform);
+ int DecodeWave(unsigned int chipIndex, unsigned char channel, unsigned short *waveform);
+ int GetWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel, short *waveform,
+ bool responseCalib = false, int triggerCell = -1, int wsr = -1, bool adjustToClock = false,
+ float threshold = 0, bool offsetCalib = true);
+ int GetWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel, float *waveform,
+ bool responseCalib = false, int triggerCell = -1, int wsr = -1, bool adjustToClock = false,
+ float threshold = 0, bool offsetCalib = true);
+ int GetWave(unsigned int chipIndex, unsigned char channel, short *waveform, bool responseCalib = false,
+ int triggerCell = -1, int wsr = -1, bool adjustToClock = false, float threshold = 0, bool offsetCalib = true);
+ int GetWave(unsigned int chipIndex, unsigned char channel, float *waveform, bool responseCalib,
+ int triggerCell = -1, int wsr = -1, bool adjustToClock = false, float threshold = 0, bool offsetCalib = true);
+ int GetWave(unsigned int chipIndex, unsigned char channel, float *waveform);
+ int GetRawWave(unsigned int chipIndex, unsigned char channel, unsigned short *waveform, bool adjustToClock = false);
+ int GetRawWave(unsigned char *waveforms,unsigned int chipIndex, unsigned char channel,
+ unsigned short *waveform, bool adjustToClock = false);
+ bool IsTimingCalibrationValid(void);
+ bool IsVoltageCalibrationValid(void) { return fVoltageCalibrationValid; }
+ int GetTime(unsigned int chipIndex, int channelIndex, double freq, int tc, float *time, bool tcalibrated=true, bool rotated=true);
+ int GetTime(unsigned int chipIndex, int channelIndex, int tc, float *time, bool tcalibrated=true, bool rotated=true);
+ int GetTimeCalibration(unsigned int chipIndex, int channelIndex, int mode, float *time, bool force=false);
+ int GetTriggerCell(unsigned int chipIndex);
+ int GetStopCell(unsigned int chipIndex);
+ unsigned char GetStopWSR(unsigned int chipIndex);
+ int GetTriggerCell(unsigned char *waveforms,unsigned int chipIndex);
+ void TestDAC(int channel);
+ void MeasureSpeed();
+ void InteractSpeed();
+ void MonitorFrequency();
+ int TestShift(int n);
+ int EnableAcal(int mode, double voltage);
+ int GetAcalMode() { return fAcalMode; }
+ double GetAcalVolt() { return fAcalVolt; }
+ int EnableTcal(int freq, int level=0, int phase=0);
+ int SelectClockSource(int source);
+ int SetRefclk(int source);
+ int GetRefclk() { return fRefclk; }
+ int GetTcalFreq() { return fTcalFreq; }
+ int GetTcalLevel() { return fTcalLevel; }
+ int GetTcalPhase() { return fTcalPhase; }
+ int GetTcalSource() { return fTcalSource; }
+ int SetCalibVoltage(double value);
+ int SetCalibTiming(int t1, int t2);
+ double GetTemperature();
+ int Is2048ModeCapable();
+ int GetTriggerBus();
+ unsigned int GetScaler(int channel);
+ int ReadEEPROM(unsigned short page, void *buffer, int size);
+ int WriteEEPROM(unsigned short page, void *buffer, int size);
+ bool HasCorrectFirmware();
+ int ConfigureLMK(double sampFreq, bool freqChange, int calFreq, int calPhase);
+
+ bool InitTimeCalibration(unsigned int chipIndex);
+ void SetCalibrationDirectory(const char *calibrationDirectoryPath);
+ void GetCalibrationDirectory(char *calibrationDirectoryPath);
+
+ ResponseCalibration *GetResponseCalibration() const { return fResponseCalibration; }
+
+ double GetPrecision() const { return fResponseCalibration ? fResponseCalibration->GetPrecision() : 0.1; }
+ int CalibrateWaveform(unsigned int chipIndex, unsigned char channel, unsigned short *adcWaveform,
+ short *waveform, bool responseCalib, int triggerCell, bool adjustToClock,
+ float threshold, bool offsetCalib);
+
+ static void LinearRegression(double *x, double *y, int n, double *a, double *b);
+
+ void ReadSingleWaveform(int nChips, int nChan,
+ unsigned short wfu[kNumberOfChipsMax][kNumberOfChannelsMax][kNumberOfBins], bool rotated);
+ int AverageWaveforms(DRSCallback *pcb, int chipIndex, int nChan, int prog1, int prog2, unsigned short *awf, int n, bool rotated);
+ int RobustAverageWaveforms(DRSCallback *pcb, int chipIndex, int nChan, int prog1, int prog2, unsigned short *awf, int n, bool rotated);
+ int CalibrateVolt(DRSCallback *pcb);
+ int AnalyzePeriod(Averager *ave, int iIter, int nIter, int channel, float wf[kNumberOfBins], int tCell, double cellDV[kNumberOfBins], double cellDT[kNumberOfBins]);
+ int AnalyzeSlope(Averager *ave, int iIter, int nIter, int channel, float wf[kNumberOfBins], int tCell, double cellDV[kNumberOfBins], double cellDT[kNumberOfBins]);
+ int CalibrateTiming(DRSCallback *pcb);
+ static void RemoveSymmetricSpikes(short **wf, int nwf,
+ short diffThreshold, int spikeWidth,
+ short maxPeakToPeak, short spikeVoltage,
+ int nTimeRegionThreshold);
+protected:
+ // Protected Methods
+ void ConstructBoard();
+ void ReadSerialNumber();
+ void ReadCalibration(void);
+
+ TimeData *GetTimeCalibration(unsigned int chipIndex, bool reinit = false);
+
+ int GetStretchedTime(float *time, float *measurement, int numberOfMeasurements, float period);
+};
+
+int DRSBoard::GetNumberOfReadoutChannels() const
+{
+ return (fDRSType == 4 && fReadoutChannelConfig == 4) ? 5 : fNumberOfChannels;
+}
+
+int DRSBoard::GetWaveformBufferSize() const
+{
+ int nbin=0;
+ if (fDRSType < 4) {
+ nbin = fNumberOfChips * fNumberOfChannels * kNumberOfBins;
+ } else {
+ if (fBoardType == 6) {
+ if (fDecimation) {
+ nbin = fNumberOfChips * (4 * kNumberOfBins + kNumberOfBins / 2);
+ } else {
+ nbin = fNumberOfChips * 5 * kNumberOfBins;
+ }
+ } else if (fBoardType == 7 || fBoardType == 8 || fBoardType == 9)
+ nbin = fNumberOfChips * fNumberOfChannels * kNumberOfBins;
+ }
+ return nbin * static_cast<int>(sizeof(short int));
+}
+
+int DRSBoard::GetNumberOfInputs() const
+{
+ // return number of input channels excluding clock and trigger channels.
+ if (fDRSType < 4) {
+ return fNumberOfChannels - 2;
+ } else {
+ return fNumberOfChannels / 2;
+ }
+}
+int DRSBoard::GetNumberOfCalibInputs() const
+{
+ return (fDRSType < 4) ? 2 : 1;
+}
+int DRSBoard::GetClockChannel() const
+{
+ return fDRSType < 4 ? 9 : 8;
+}
+int DRSBoard::GetTriggerChannel() const
+{
+ return fDRSType < 4 ? 8 : -1;
+}
+
+int DRSBoard::Channel2Input(int channel) const
+{
+ return (fDRSType < 4) ? channel : channel / 2;
+}
+int DRSBoard::Channel2ReadoutChannel(int channel) const
+{
+ if (fDRSType < 4) {
+ return channel;
+ } else {
+ if (fReadoutChannelConfig == 4) {
+ return channel / 2;
+ } else {
+ return channel;
+ }
+ }
+}
+int DRSBoard::Input2Channel(int input, int ind) const
+{
+ if (fChannelCascading == 1) {
+ return (fDRSType < 4) ? input : (input * 2 + ind);
+ } else {
+ if (input == 4) { // clock
+ return 8;
+ } else {
+ return input;
+ }
+ }
+}
+int DRSBoard::Input2ReadoutChannel(int input, int ind) const
+{
+ if (fDRSType < 4) {
+ return input;
+ } else {
+ if (fReadoutChannelConfig == 4) {
+ return input;
+ } else {
+ return (input * 2 + ind);
+ }
+ }
+}
+int DRSBoard::ReadoutChannel2Channel(int readout) const
+{
+ if (fDRSType < 4) {
+ return readout;
+ } else {
+ if (fReadoutChannelConfig == 4) {
+ return readout * 2;
+ } else {
+ return readout;
+ }
+ }
+}
+int DRSBoard::ReadoutChannel2Input(int readout) const
+{
+ if (fDRSType < 4) {
+ return readout;
+ } else {
+ if (fReadoutChannelConfig == 4) {
+ return readout;
+ } else {
+ return readout / 2;
+ }
+ }
+}
+bool DRSBoard::IsCalibChannel(int ch) const
+{
+ // return if it is clock or trigger channel
+ if (fDRSType < 4)
+ return ch == GetClockChannel() || ch == GetTriggerChannel();
+ else
+ return ch == GetClockChannel();
+}
+bool DRSBoard::IsCalibInput(int input) const
+{
+ // return if it is clock or trigger channel
+ int ch = Input2Channel(input);
+ if (fDRSType < 4)
+ return ch == GetClockChannel() || ch == GetTriggerChannel();
+ else
+ return ch == GetClockChannel();
+}
+
+class DRS {
+protected:
+ // constants
+ enum {
+ kMaxNumberOfBoards = 40
+ };
+
+protected:
+ DRSBoard *fBoard[kMaxNumberOfBoards];
+ int fNumberOfBoards;
+ char fError[256];
+#ifdef HAVE_VME
+ MVME_INTERFACE *fVmeInterface;
+#endif
+
+private:
+ DRS(const DRS &c); // not implemented
+ DRS &operator=(const DRS &rhs); // not implemented
+
+public:
+ // Public Methods
+ DRS();
+ ~DRS();
+
+ DRSBoard *GetBoard(int i) { return fBoard[i]; }
+ void SetBoard(int i, DRSBoard *b);
+ DRSBoard **GetBoards() { return fBoard; }
+ int GetNumberOfBoards() const { return fNumberOfBoards; }
+ bool GetError(char *str, int size);
+ void SortBoards();
+
+#ifdef HAVE_VME
+ MVME_INTERFACE *GetVMEInterface() const { return fVmeInterface; };
+#endif
+};
+
+#endif // DRS_H
Index: instr/drsctrl/drs4.c
===================================================================
--- instr/drsctrl/drs4.c (nonexistent)
+++ instr/drsctrl/drs4.c (revision 195)
@@ -0,0 +1,216 @@
+#include <utility.h>
+#include <ansi_c.h>
+#include <cvirte.h>
+#include <userint.h>
+#include "drs4.h"
+#include "drsread.h"
+
+static int daq_on;
+static int ph, plothandle;
+static int tfID;
+static int controlID;
+
+#define MAX_THREADS 10
+
+static CmtThreadPoolHandle poolHandle = 0;
+
+int main (int argc, char *argv[]) {
+ if (InitCVIRTE (0, argv, 0) == 0)
+ return -1; /* out of memory */
+ if ((ph = LoadPanel (0, "drs4.uir", PANEL)) < 0)
+ return -1;
+ SetStdioPort (CVI_STDIO_WINDOW);
+ SetSleepPolicy(VAL_SLEEP_MORE);
+ CmtNewThreadPool (MAX_THREADS, &poolHandle);
+
+ DisplayPanel (ph);
+ RunUserInterface ();
+ DiscardPanel (ph);
+ CmtDiscardThreadPool (poolHandle);
+ return 0;
+}
+
+
+
+
+
+static void start_timer (double tout) {
+ SetCtrlAttribute (ph, PANEL_TIMER, ATTR_INTERVAL, tout);
+ SetCtrlAttribute (ph, PANEL_TIMER, ATTR_ENABLED, 1);
+}
+
+static void stop_timer ( void ) {
+ SetCtrlAttribute (ph, PANEL_TIMER, ATTR_ENABLED, 0);
+ DRSSetTimeout();
+}
+
+
+
+
+void CVICALLBACK EndOfThread ( CmtThreadPoolHandle poolhandle,
+ CmtThreadFunctionID functionID, unsigned int event,
+ int value, void *callbackData ) {
+
+ daq_on=0;
+ //SetDimming(0);
+ printf("End of Thread \n");
+ return ;
+
+}
+
+
+int CVICALLBACK daq(void *functionData) {
+
+
+ int neve;
+ char filename[0xff];
+ char smask[0xff];
+ unsigned long mask;
+ int frequency;
+ double trgdelay;
+ double trglevel;
+ int trgtype;
+ int trgchannel;
+ int trgpolarity;
+ int verbose;
+ double range;
+
+
+ GetCtrlVal(ph, PANEL_FILENAME, filename );
+ GetCtrlVal(ph, PANEL_MASK, smask );
+ mask = strtoul (smask,NULL,0);
+ GetCtrlVal(ph,PANEL_NEVE, &neve);
+
+ GetCtrlVal(ph,PANEL_FREQUENCY, &frequency);
+ GetCtrlVal(ph,PANEL_TRGDELAY, &trgdelay);
+ GetCtrlVal(ph,PANEL_TRGCHANNEL, &trgchannel);
+ GetCtrlVal(ph,PANEL_TRGTYPE, &trgtype);
+ GetCtrlVal(ph,PANEL_TRGLEVEL, &trglevel);
+ GetCtrlVal(ph,PANEL_TRGPOLARITY, &trgpolarity);
+ GetCtrlVal(ph,PANEL_RANGE, &range);
+ GetCtrlVal(ph,PANEL_DEBUG, &verbose);
+
+ printf("mask=0x%x\n",mask);
+
+ DRSSetMask( (unsigned char)( mask & 0xF ) );
+
+ DRSSetFrequency( frequency );
+ DRSSetTriggerPolarity(trgpolarity);
+ DRSSetTriggerLevel(trglevel);
+ DRSSetRange ( range );
+ DRSSetTriggerType( trgtype );
+ DRSSetTriggerChannel(trgchannel );
+
+ FILE *fp=fopen(filename,"wb");
+
+
+ static unsigned char *buffer;
+
+ int buffer_size = 0;
+const int nBoards=1;
+const int waveDepth=1024;
+if (buffer_size == 0) {
+ buffer_size = 4 + nBoards * (4 + 4*(4+waveDepth*4));
+ buffer_size += 24 + nBoards * (8 + 4*(4+waveDepth*2));
+ buffer = (unsigned char *)malloc(buffer_size);
+}
+
+time_t t,told, tstart;
+
+if (!DRSInit()){
+ time(&tstart);
+ told=tstart;
+ int i=0;
+ for (i=0; i<neve; i++) {
+ start_timer(1);// 1 s timeout
+ int retval = DRSRead(0);
+ stop_timer();
+ int nb = ( retval == 0 && fp ) ? DRSToBuffer( buffer , i ) : 0;
+ SetCtrlVal(ph,PANEL_CEVE,i);
+ if (retval) i--;
+ if (!daq_on) break;
+ time(&t);
+ if (t!=told ) {
+ printf("%d events in %2.2f min (%d s) %s",i+1, (double)(t-tstart)/60.,(t-tstart), ctime(&t));
+
+ }
+ told=t;
+// Save data
+ if (nb>0 && fp) fwrite(buffer, 1,nb ,fp);
+// Plot Data
+ for (int k=0;k<4;k++){
+ if (! (mask & ( 0x1<<k )) ) continue;
+ float *t=DRSGetTime(k);
+ float *x=DRSGetWave(k);
+
+ if (!k){
+ if (plothandle) DeleteGraphPlot (ph, PANEL_GRAPH, plothandle, VAL_DELAYED_DRAW);
+ plothandle = PlotXY (ph, PANEL_GRAPH, t, x, 1024, VAL_FLOAT, VAL_FLOAT, VAL_THIN_LINE, VAL_NO_POINT, VAL_SOLID, 1, VAL_BLUE);
+ }
+
+
+ for (int i=0 ; i<1024 ; i++) {
+ if (verbose) printf("[%d] %d. x= %3.2f y=%3.2f\n", k, i, t[i], x[i] );
+ //h[k]->Fill( t[i], x[i]*1e-3);
+ }
+ }
+ }
+ time(&t);
+ printf("%d events in %2.2f min (%d s) %s",i+1, (double)(t-tstart)/60.,t-tstart, ctime(&t));
+
+ DRSEnd();
+}
+
+if (fp) fclose(fp);
+
+free(buffer);
+
+ return 0;
+
+}
+
+int CVICALLBACK StartCB (int panel, int control, int event,
+ void *callbackData, int eventData1, int eventData2) {
+ ThreadFunctionPtr mythread = NULL;
+ switch (event) {
+
+ case EVENT_COMMIT:
+
+ mythread = daq;
+ if (mythread!=NULL) {
+ printf("New Thread panel=%d button=%d\n", panel, control);
+
+ // SetDimming(1);
+ controlID= control;
+ daq_on=1;
+ CmtScheduleThreadPoolFunctionAdv (poolHandle, mythread, &controlID,
+ DEFAULT_THREAD_PRIORITY,
+ EndOfThread,
+ EVENT_TP_THREAD_FUNCTION_END,
+ NULL, RUN_IN_SCHEDULED_THREAD,
+ &tfID);
+ }
+ break;
+ }
+ return 0;
+}
+
+int CVICALLBACK StopCB (int panel, int control, int event,
+ void *callbackData, int eventData1, int eventData2) {
+ switch (event) {
+ case EVENT_COMMIT:
+ daq_on=0;
+ break;
+ }
+ return 0;
+}
+
+int CVICALLBACK ExitCB (int panel, int control, int event,
+ void *callbackData, int eventData1, int eventData2) {
+ switch (event) {
+ case EVENT_COMMIT:
+ QuitUserInterface (0);
+ break;
+ }
+ return 0;
+}
Index: instr/drsctrl/drs4.cws
===================================================================
--- instr/drsctrl/drs4.cws (nonexistent)
+++ instr/drsctrl/drs4.cws (revision 195)
@@ -0,0 +1,232 @@
+[Workspace Header]
+Version = 1302
+Pathname = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.cws"
+CVI Dir = "/c/program files (x86)/national instruments/cvi2013"
+CVI Shared Dir = "/C/Program Files (x86)/National Instruments/Shared/CVI"
+CVI Pub Local Dir = "/C/ProgramData/National Instruments/CVI2013"
+CVI Pub Global Dir = "/C/ProgramData/National Instruments/CVI"
+IVI Standard Root Dir = "/C/Program Files (x86)/IVI Foundation/IVI"
+IVI Standard Root 64-bit Dir = "/C/Program Files/IVI Foundation/IVI"
+VXIplug&play Framework Dir = "/C/Program Files (x86)/IVI Foundation/VISA/winnt"
+VXIplug&play Framework 64-bit Dir = "/C/Program Files/IVI Foundation/VISA/win64"
+Number of Projects = 1
+Active Project = 1
+Project 0001 = "drs4.prj"
+Drag Bar Left = 360
+Window Top = 277
+Window Left = 205
+Window Bottom = 1617
+Window Right = 2435
+Maximized = False
+Maximized Children = True
+Max32 Number Of Errors = 20
+Track Include File Dependencies = True
+Prompt For Missing Includes = True
+Stop On First Error File = False
+Bring Up Err Win At Start = True
+Bring Up Err Win For Errors = False
+Save Changes Before Running = "Always"
+Save Changes Before Compiling = "Always"
+Hide Windows = False
+Break At First Statement = False
+Sort Type = "File Name"
+Number of Opened Files = 8
+Window Confinement Region Enabled = True
+MainColumnWidth = 343
+FileDateColumnWidth = 70
+FileSizeColumnWidth = 70
+
+[Project Header 0001]
+Version = 1302
+Don't Update DistKit = False
+Platform Code = 4
+Build Configuration = "Debug"
+Warn User If Debugging Release = 1
+Batch Build Release = False
+Batch Build Debug = False
+
+[File 0001]
+Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.c"
+File Type = "CSource"
+Disk Date = 3566382302
+In Projects = "1,"
+Window Top = 522
+Window Left = 247
+Window Z-Order = 1
+Source Window State = "1,147,148,148,0,0,0,0,0,229,0,2,0,2,0,67,14,0,26,2,349,683,1,0,"
+
+[File 0002]
+Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.uir"
+File Type = "User Interface Resource"
+Disk Date = 3566382690
+In Projects = "1,"
+Window Top = 132
+Window Left = 49
+Window Height = 349
+Window Width = 811
+Window Z-Order = 2
+
+[File 0003]
+Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.h"
+File Type = "Include"
+Disk Date = 3566380515
+In Projects = ""
+Window Top = 67
+Window Left = 16
+Window Z-Order = 6
+Source Window State = "1,0,0,0,0,0,0,0,0,96,0,0,0,0,0,25,0,0,0,0,349,811,1,0,"
+
+[File 0004]
+Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drsread.h"
+File Type = "Include"
+Disk Date = 3566381442
+In Projects = ""
+Window Top = 197
+Window Left = 82
+Window Z-Order = 5
+Source Window State = "1,0,0,0,0,0,0,0,0,96,0,0,0,0,0,25,0,0,31,70,349,811,1,0,"
+
+[File 0005]
+Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drsread.c"
+File Type = "CSource"
+Disk Date = 3566381600
+In Projects = ""
+Window Top = 262
+Window Left = 115
+Window Z-Order = 4
+Source Window State = "1,0,0,0,0,0,0,0,0,96,0,0,0,0,0,25,0,0,30,26,349,811,1,0,"
+
+[File 0006]
+Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drsread.lib"
+File Type = "Library"
+Disk Date = 3566381587
+In Projects = "1,"
+
+[File 0007]
+Path = "/c/Users/rok/Documents/rok/lab/praktikum/mioni/mioni.c"
+File Type = "CSource"
+Disk Date = 3564730349
+In Projects = ""
+Window Top = 132
+Window Left = 49
+Window Z-Order = 8
+Source Window State = "1,26,26,26,0,25,25,0,3,96,0,0,0,0,0,25,0,0,26,0,349,811,1,0,"
+
+[File 0008]
+Path = "/c/home/git/arich/daq/sa02_daq/cvi/sa02_CVI.c"
+File Type = "CSource"
+Disk Date = 3559701358
+In Projects = ""
+Window Top = 197
+Window Left = 82
+Window Z-Order = 3
+Source Window State = "1,362,370,362,7,60,7,0,3,96,0,0,0,0,0,25,330,0,370,60,349,811,1,0,"
+
+[File 0009]
+Path = "/c/home/git/arich/daq/sa02_daq/sa02lib.c"
+File Type = "CSource"
+Disk Date = 3559701358
+In Projects = ""
+Window Top = 262
+Window Left = 115
+Window Z-Order = 7
+Source Window State = "1,240,240,240,1,21,21,0,3,96,0,0,0,0,0,25,213,0,240,1,349,811,1,0,"
+
+[Tab Order]
+Tab 0001 = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.uir"
+Tab 0002 = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.c"
+Tab 0003 = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drsread.c"
+Tab 0004 = "/c/Users/rok/Documents/rok/lab/praktikum/mioni/mioni.c"
+Tab 0005 = "/c/home/git/arich/daq/sa02_daq/cvi/sa02_CVI.c"
+Tab 0006 = "/c/home/git/arich/daq/sa02_daq/sa02lib.c"
+Tab 0007 = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.h"
+Tab 0008 = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drsread.h"
+
+[Default Build Config 0001 Debug]
+Generate Browse Info = False
+Enable Uninitialized Locals Runtime Warning = True
+Batch Build = False
+Profile = "Disabled"
+Debugging Level = "Standard"
+Execution Trace = "Disabled"
+Command Line Args = ""
+Working Directory = ""
+Environment Options = ""
+External Process Path = ""
+
+[Default Build Config 0001 Release]
+Generate Browse Info = False
+Enable Uninitialized Locals Runtime Warning = True
+Batch Build = False
+Profile = "Disabled"
+Debugging Level = "Standard"
+Execution Trace = "Disabled"
+Command Line Args = ""
+Working Directory = ""
+Environment Options = ""
+External Process Path = ""
+
+[Default Build Config 0001 Debug64]
+Generate Browse Info = False
+Enable Uninitialized Locals Runtime Warning = True
+Batch Build = False
+Profile = "Disabled"
+Debugging Level = "Standard"
+Execution Trace = "Disabled"
+Command Line Args = ""
+Working Directory = ""
+Environment Options = ""
+External Process Path = ""
+
+[Default Build Config 0001 Release64]
+Generate Browse Info = False
+Enable Uninitialized Locals Runtime Warning = True
+Batch Build = False
+Profile = "Disabled"
+Debugging Level = "Standard"
+Execution Trace = "Disabled"
+Command Line Args = ""
+Working Directory = ""
+Environment Options = ""
+External Process Path = ""
+
+[Build Dependencies 0001]
+Number of Dependencies = 0
+
+[Build Options 0001]
+Generate Browse Info = False
+Enable Uninitialized Locals Runtime Warning = True
+Execution Trace = "Disabled"
+Profile = "Disabled"
+Debugging Level = "Standard"
+Break On Library Errors = True
+Break On First Chance Exceptions = False
+
+[Execution Target 0001]
+Execution Target Address = "Local desktop computer"
+Execution Target Port = 0
+Execution Target Type = 0
+
+[SCC Options 0001]
+Use global settings = True
+SCC Provider = ""
+SCC Project = ""
+Local Path = ""
+Auxiliary Path = ""
+Perform Same Action For .h File As For .uir File = "Ask"
+Perform Same Action For .cds File As For .prj File = "Ask"
+Username = ""
+Comment = ""
+Use Default Username = False
+Use Default Comment = False
+Suppress CVI Error Messages = False
+Always show confirmation dialog = True
+
+[DLL Debugging Support 0001]
+External Process Path = ""
+
+[Command Line Args 0001]
+Command Line Args = ""
+Working Directory = ""
+Environment Options = ""
+
Index: instr/drsctrl/drs4.exe
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/instr/drsctrl/drs4.exe
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: instr/drsctrl/drs4.h
===================================================================
--- instr/drsctrl/drs4.h (nonexistent)
+++ instr/drsctrl/drs4.h (revision 195)
@@ -0,0 +1,55 @@
+/**************************************************************************/
+/* LabWindows/CVI User Interface Resource (UIR) Include File */
+/* */
+/* WARNING: Do not add to, delete from, or otherwise modify the contents */
+/* of this include file. */
+/**************************************************************************/
+
+#include <userint.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+ /* Panels and Controls: */
+
+#define PANEL 1
+#define PANEL_Exit 2 /* control type: command, callback function: ExitCB */
+#define PANEL_STOP 3 /* control type: command, callback function: StopCB */
+#define PANEL_START 4 /* control type: command, callback function: StartCB */
+#define PANEL_TRGTYPE 5 /* control type: numeric, callback function: (none) */
+#define PANEL_TRGLEVEL 6 /* control type: numeric, callback function: (none) */
+#define PANEL_TRGDELAY 7 /* control type: numeric, callback function: (none) */
+#define PANEL_RANGE 8 /* control type: numeric, callback function: (none) */
+#define PANEL_TRGCHANNEL 9 /* control type: numeric, callback function: (none) */
+#define PANEL_CEVE 10 /* control type: numeric, callback function: (none) */
+#define PANEL_NEVE 11 /* control type: numeric, callback function: (none) */
+#define PANEL_FREQUENCY 12 /* control type: numeric, callback function: (none) */
+#define PANEL_TRGPOLARITY 13 /* control type: binary, callback function: (none) */
+#define PANEL_MASK 14 /* control type: string, callback function: (none) */
+#define PANEL_FILENAME 15 /* control type: string, callback function: (none) */
+#define PANEL_GRAPH 16 /* control type: graph, callback function: (none) */
+#define PANEL_DEBUG 17 /* control type: radioButton, callback function: (none) */
+#define PANEL_TIMER 18 /* control type: timer, callback function: (none) */
+
+
+ /* Control Arrays: */
+
+ /* (no control arrays in the resource file) */
+
+
+ /* Menu Bars, Menus, and Menu Items: */
+
+ /* (no menu bars in the resource file) */
+
+
+ /* Callback Prototypes: */
+
+int CVICALLBACK ExitCB(int panel, int control, int event, void *callbackData, int eventData1, int eventData2);
+int CVICALLBACK StartCB(int panel, int control, int event, void *callbackData, int eventData1, int eventData2);
+int CVICALLBACK StopCB(int panel, int control, int event, void *callbackData, int eventData1, int eventData2);
+
+
+#ifdef __cplusplus
+ }
+#endif
Index: instr/drsctrl/drs4.prj
===================================================================
--- instr/drsctrl/drs4.prj (nonexistent)
+++ instr/drsctrl/drs4.prj (revision 195)
@@ -0,0 +1,432 @@
+[Project Header]
+Version = 1302
+Pathname = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.prj"
+CVI Dir = "/c/program files (x86)/national instruments/cvi2013"
+CVI Shared Dir = "/C/Program Files (x86)/National Instruments/Shared/CVI"
+CVI Pub Local Dir = "/C/ProgramData/National Instruments/CVI2013"
+CVI Pub Global Dir = "/C/ProgramData/National Instruments/CVI"
+IVI Standard Root Dir = "/C/Program Files (x86)/IVI Foundation/IVI"
+VXIplug&play Framework Dir = "/C/Program Files (x86)/IVI Foundation/VISA/winnt"
+IVI Standard Root 64-bit Dir = "/C/Program Files/IVI Foundation/IVI"
+VXIplug&play Framework 64-bit Dir = "/C/Program Files/IVI Foundation/VISA/win64"
+Number of Files = 3
+Target Type = "Executable"
+Flags = 2064
+Copied From Locked InstrDrv Directory = False
+Copied from VXIPNP Directory = False
+Locked InstrDrv Name = ""
+Don't Display Deploy InstrDrv Dialog = False
+
+[Folders]
+Include Files Folder Not Added Yet = True
+Instrument Files Folder Not Added Yet = True
+Folder 0 = "User Interface Files"
+FolderEx 0 = "User Interface Files"
+Folder 1 = "Source Files"
+FolderEx 1 = "Source Files"
+Folder 2 = "Library Files"
+FolderEx 2 = "Library Files"
+
+[File 0001]
+File Type = "User Interface Resource"
+Res Id = 1
+Path Is Rel = True
+Path Rel To = "Project"
+Path Rel Path = "drs4.uir"
+Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.uir"
+Exclude = False
+Project Flags = 0
+Folder = "User Interface Files"
+Folder Id = 0
+
+[File 0002]
+File Type = "CSource"
+Res Id = 2
+Path Is Rel = True
+Path Rel To = "Project"
+Path Rel Path = "drs4.c"
+Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.c"
+Exclude = False
+Compile Into Object File = False
+Project Flags = 0
+Folder = "Source Files"
+Folder Id = 1
+
+[File 0003]
+File Type = "Library"
+Res Id = 3
+Path Is Rel = True
+Path Rel To = "Project"
+Path Rel Path = "drsread.lib"
+Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drsread.lib"
+Exclude = False
+Project Flags = 0
+Folder = "Library Files"
+Folder Id = 2
+
+[Custom Build Configs]
+Num Custom Build Configs = 0
+
+[Default Build Config Debug]
+Config Name = "Debug"
+Is 64-Bit = False
+Is Release = False
+Default Calling Convention = "cdecl"
+Optimization Level = "Optimize for speed (level 2)"
+Require Prototypes = True
+Show Warning IDs in Build Output = False
+Selected Warning Level = "None"
+Warning List None = "4,9,84,105,106,107,108,109,110,111"
+Warning List Common = ""
+Warning List Extended = ""
+Warning List All = ""
+Warning Mode = 0
+Enable Unreferenced Identifiers Warning = False
+Enable Pointer Mismatch Warning = False
+Enable Unreachable Code Warning = False
+Enable Assignment In Conditional Warning = False
+Uninitialized Locals Compile Warning = "Aggressive"
+Require Return Values = True
+Enable C99 Extensions = False
+Enable OpenMP Extensions = False
+Stack Size = 250000
+Stack Reserve = 1048576
+Stack Commit = 4096
+Image Base Address = 4194304
+Image Base Address x64 = 4194304
+Compiler Defines = "/DWIN32_LEAN_AND_MEAN"
+Sign = False
+Sign Store = ""
+Sign Certificate = ""
+Sign Timestamp URL = ""
+Sign URL = ""
+Manifest Embed = False
+Icon File Is Rel = False
+Icon File = ""
+Application Title = ""
+Use IVI Subdirectories for Import Libraries = False
+Use VXIPNP Subdirectories for Import Libraries = False
+Use Dflt Import Lib Base Name = True
+Where to Copy DLL = "Do not copy"
+Custom Directory to Copy DLL Is Rel = False
+Custom Directory to Copy DLL = ""
+Generate Source Documentation = "None"
+Runtime Support = "Full Runtime Support"
+Runtime Binding = "Shared"
+Embed Project .UIRs = False
+Generate Map File = False
+Embed Timestamp = True
+Create Console Application = False
+Using LoadExternalModule = False
+DLL Exports = "Include File Symbols"
+Register ActiveX Server = False
+Numeric File Version = "1,0,0,0"
+Numeric Prod Version = "1,0,0,0"
+Comments = ""
+Comments Ex = ""
+Company Name = ""
+Company Name Ex = "%company"
+File Description = "drs4 (Debug x86)"
+File Description Ex = "%application (%rel_dbg %arch)"
+File Version = "1.0"
+File Version Ex = "%f1.%f2"
+Internal Name = "drs4"
+Internal Name Ex = "%basename"
+Legal Copyright = "Copyright © 2017"
+Legal Copyright Ex = "Copyright © %company %Y"
+Legal Trademarks = ""
+Legal Trademarks Ex = ""
+Original Filename = "drs4.exe"
+Original Filename Ex = "%filename"
+Private Build = ""
+Private Build Ex = ""
+Product Name = " drs4"
+Product Name Ex = "%company %application"
+Product Version = "1.0"
+Product Version Ex = "%p1.%p2"
+Special Build = ""
+Special Build Ex = ""
+Add Type Lib To DLL = False
+Include Type Lib Help Links = False
+TLB Help Style = "HLP"
+Type Lib FP File Is Rel = False
+Type Lib FP File = ""
+
+[Default Build Config Release]
+Config Name = "Release"
+Is 64-Bit = False
+Is Release = True
+Default Calling Convention = "cdecl"
+Optimization Level = "Optimize for speed (level 2)"
+Require Prototypes = True
+Show Warning IDs in Build Output = False
+Selected Warning Level = "None"
+Warning List None = "4,9,84,105,106,107,108,109,110,111"
+Warning List Common = ""
+Warning List Extended = ""
+Warning List All = ""
+Warning Mode = 0
+Enable Unreferenced Identifiers Warning = False
+Enable Pointer Mismatch Warning = False
+Enable Unreachable Code Warning = False
+Enable Assignment In Conditional Warning = False
+Uninitialized Locals Compile Warning = "Aggressive"
+Require Return Values = True
+Enable C99 Extensions = False
+Enable OpenMP Extensions = False
+Stack Size = 250000
+Stack Reserve = 1048576
+Stack Commit = 4096
+Image Base Address = 4194304
+Image Base Address x64 = 4194304
+Compiler Defines = "/DWIN32_LEAN_AND_MEAN"
+Sign = False
+Sign Store = ""
+Sign Certificate = ""
+Sign Timestamp URL = ""
+Sign URL = ""
+Manifest Embed = False
+Icon File Is Rel = False
+Icon File = ""
+Application Title = ""
+Use IVI Subdirectories for Import Libraries = False
+Use VXIPNP Subdirectories for Import Libraries = False
+Use Dflt Import Lib Base Name = True
+Where to Copy DLL = "Do not copy"
+Custom Directory to Copy DLL Is Rel = False
+Custom Directory to Copy DLL = ""
+Generate Source Documentation = "None"
+Runtime Support = "Full Runtime Support"
+Runtime Binding = "Shared"
+Embed Project .UIRs = False
+Generate Map File = False
+Embed Timestamp = True
+Create Console Application = False
+Using LoadExternalModule = False
+DLL Exports = "Include File Symbols"
+Register ActiveX Server = False
+Add Type Lib To DLL = False
+Include Type Lib Help Links = False
+TLB Help Style = "HLP"
+Type Lib FP File Is Rel = False
+Type Lib FP File = ""
+
+[Default Build Config Debug64]
+Config Name = "Debug64"
+Is 64-Bit = True
+Is Release = False
+Default Calling Convention = "cdecl"
+Optimization Level = "Optimize for speed (level 2)"
+Require Prototypes = True
+Show Warning IDs in Build Output = False
+Selected Warning Level = "None"
+Warning List None = "4,9,84,105,106,107,108,109,110,111"
+Warning List Common = ""
+Warning List Extended = ""
+Warning List All = ""
+Warning Mode = 0
+Enable Unreferenced Identifiers Warning = False
+Enable Pointer Mismatch Warning = False
+Enable Unreachable Code Warning = False
+Enable Assignment In Conditional Warning = False
+Uninitialized Locals Compile Warning = "Aggressive"
+Require Return Values = True
+Enable C99 Extensions = False
+Enable OpenMP Extensions = False
+Stack Size = 250000
+Stack Reserve = 1048576
+Stack Commit = 4096
+Image Base Address = 4194304
+Image Base Address x64 = 4194304
+Compiler Defines = "/DWIN32_LEAN_AND_MEAN"
+Sign = False
+Sign Store = ""
+Sign Certificate = ""
+Sign Timestamp URL = ""
+Sign URL = ""
+Manifest Embed = False
+Icon File Is Rel = False
+Icon File = ""
+Application Title = ""
+Use IVI Subdirectories for Import Libraries = False
+Use VXIPNP Subdirectories for Import Libraries = False
+Use Dflt Import Lib Base Name = True
+Where to Copy DLL = "Do not copy"
+Custom Directory to Copy DLL Is Rel = False
+Custom Directory to Copy DLL = ""
+Generate Source Documentation = "None"
+Runtime Support = "Full Runtime Support"
+Runtime Binding = "Shared"
+Embed Project .UIRs = False
+Generate Map File = False
+Embed Timestamp = True
+Create Console Application = False
+Using LoadExternalModule = False
+DLL Exports = "Include File Symbols"
+Register ActiveX Server = False
+Add Type Lib To DLL = False
+Include Type Lib Help Links = False
+TLB Help Style = "HLP"
+Type Lib FP File Is Rel = False
+Type Lib FP File = ""
+
+[Default Build Config Release64]
+Config Name = "Release64"
+Is 64-Bit = True
+Is Release = True
+Default Calling Convention = "cdecl"
+Optimization Level = "Optimize for speed (level 2)"
+Require Prototypes = True
+Show Warning IDs in Build Output = False
+Selected Warning Level = "None"
+Warning List None = "4,9,84,105,106,107,108,109,110,111"
+Warning List Common = ""
+Warning List Extended = ""
+Warning List All = ""
+Warning Mode = 0
+Enable Unreferenced Identifiers Warning = False
+Enable Pointer Mismatch Warning = False
+Enable Unreachable Code Warning = False
+Enable Assignment In Conditional Warning = False
+Uninitialized Locals Compile Warning = "Aggressive"
+Require Return Values = True
+Enable C99 Extensions = False
+Enable OpenMP Extensions = False
+Stack Size = 250000
+Stack Reserve = 1048576
+Stack Commit = 4096
+Image Base Address = 4194304
+Image Base Address x64 = 4194304
+Compiler Defines = "/DWIN32_LEAN_AND_MEAN"
+Sign = False
+Sign Store = ""
+Sign Certificate = ""
+Sign Timestamp URL = ""
+Sign URL = ""
+Manifest Embed = False
+Icon File Is Rel = False
+Icon File = ""
+Application Title = ""
+Use IVI Subdirectories for Import Libraries = False
+Use VXIPNP Subdirectories for Import Libraries = False
+Use Dflt Import Lib Base Name = True
+Where to Copy DLL = "Do not copy"
+Custom Directory to Copy DLL Is Rel = False
+Custom Directory to Copy DLL = ""
+Generate Source Documentation = "None"
+Runtime Support = "Full Runtime Support"
+Runtime Binding = "Shared"
+Embed Project .UIRs = False
+Generate Map File = False
+Embed Timestamp = True
+Create Console Application = False
+Using LoadExternalModule = False
+DLL Exports = "Include File Symbols"
+Register ActiveX Server = False
+Add Type Lib To DLL = False
+Include Type Lib Help Links = False
+TLB Help Style = "HLP"
+Type Lib FP File Is Rel = False
+Type Lib FP File = ""
+
+[Compiler Options]
+Default Calling Convention = "cdecl"
+Require Prototypes = True
+Require Return Values = True
+Enable Pointer Mismatch Warning = False
+Enable Unreachable Code Warning = False
+Enable Unreferenced Identifiers Warning = False
+Enable Assignment In Conditional Warning = False
+O Option Compatible With 5.0 = False
+Enable C99 Extensions = False
+Uninitialized Locals Compile Warning = "Aggressive"
+Precompile Prefix Header = False
+Prefix Header File = ""
+
+[Run Options]
+Stack Size = 250000
+Stack Commit = 4096
+Image Base Address = 4194304
+Image Base Address x64 = 4194304
+
+[Compiler Defines]
+Compiler Defines = "/DWIN32_LEAN_AND_MEAN"
+
+[Create Executable]
+Executable File_Debug Is Rel = True
+Executable File_Debug Rel To = "Project"
+Executable File_Debug Rel Path = "drs4.exe"
+Executable File_Debug = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.exe"
+Executable File_Release Is Rel = True
+Executable File_Release Rel To = "Project"
+Executable File_Release Rel Path = "drs4.exe"
+Executable File_Release = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.exe"
+Executable File_Debug64 Is Rel = True
+Executable File_Debug64 Rel To = "Project"
+Executable File_Debug64 Rel Path = "drs4.exe"
+Executable File_Debug64 = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.exe"
+Executable File_Release64 Is Rel = True
+Executable File_Release64 Rel To = "Project"
+Executable File_Release64 Rel Path = "drs4.exe"
+Executable File_Release64 = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.exe"
+Icon File Is Rel = False
+Icon File = ""
+Application Title = ""
+DLL Exports = "Include File Symbols"
+Use IVI Subdirectories for Import Libraries = False
+Use VXIPNP Subdirectories for Import Libraries = False
+Use Dflt Import Lib Base Name = True
+Where to Copy DLL = "Do not copy"
+Custom Directory to Copy DLL Is Rel = False
+Custom Directory to Copy DLL = ""
+Generate Source Documentation = "None"
+Add Type Lib To DLL = False
+Include Type Lib Help Links = False
+TLB Help Style = "HLP"
+Type Lib FP File Is Rel = False
+Type Lib FP File = ""
+Type Lib Guid = ""
+Runtime Support = "Full Runtime Support"
+Instrument Driver Support Only = False
+Embed Project .UIRs = False
+Generate Map File = False
+
+[External Compiler Support]
+UIR Callbacks File Option = 0
+Using LoadExternalModule = False
+Create Project Symbols File = True
+UIR Callbacks Obj File Is Rel = False
+UIR Callbacks Obj File = ""
+Project Symbols H File Is Rel = False
+Project Symbols H File = ""
+Project Symbols Obj File Is Rel = False
+Project Symbols Obj File = ""
+
+[ActiveX Server Options]
+Specification File Is Rel = False
+Specification File = ""
+Source File Is Rel = False
+Source File = ""
+Include File Is Rel = False
+Include File = ""
+IDL File Is Rel = False
+IDL File = ""
+Register ActiveX Server = False
+
+[Signing Info]
+Sign = False
+Sign Debug Build = False
+Store = ""
+Certificate = ""
+Timestamp URL = ""
+URL = ""
+
+[Manifest Info]
+Embed = False
+
+[tpcSection]
+tpcEnabled = 0
+tpcOverrideEnvironment = 0
+tpcEnabled x64 = 0
+tpcOverrideEnvironment x64 = 0
+
Index: instr/drsctrl/drs4.uir
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/instr/drsctrl/drs4.uir
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: instr/drsctrl/drscl.cpp
===================================================================
--- instr/drsctrl/drscl.cpp (nonexistent)
+++ instr/drsctrl/drscl.cpp (revision 195)
@@ -0,0 +1,1647 @@
+/********************************************************************\
+
+ Name: drscl.cpp
+ Created by: Stefan Ritt
+
+ Contents: Command line interface to DRS chip via USB and VME
+
+ $Id: drscl.cpp 21435 2014-07-30 13:02:31Z ritt $
+
+\********************************************************************/
+
+#include <math.h>
+
+#ifdef _MSC_VER
+
+#include <windows.h>
+#include <conio.h>
+#include <io.h>
+#include <direct.h>
+
+#define DIR_SEPARATOR '\\'
+
+#elif defined(OS_LINUX) || defined(OS_DARWIN)
+
+#define O_BINARY 0
+
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#define DIR_SEPARATOR '/'
+
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <assert.h>
+
+#include "strlcpy.h"
+#include "DRS.h"
+#ifdef HAVE_VME
+#include "ace.h"
+#endif
+
+const char *drscl_svn_revision = "$Id: drscl.cpp 21435 2014-07-30 13:02:31Z ritt $";
+
+void print_help();
+void clear_screen();
+int match(const char *str, const char *cmd);
+void cmd_loop();
+
+#if defined(OS_LINUX) || defined(OS_DARWIN)
+#define getch() getchar()
+#define Sleep(x) usleep(x*1000)
+#endif
+
+#ifdef _MSC_VER
+#include <conio.h>
+#define drs_kbhit() kbhit()
+#endif
+
+void print_help()
+{
+ puts("Available commands:\n");
+ puts("active <0|1> Set domino active mode on (1) or off (0)");
+ puts("board <i>|<i1> <i2>|all Address individual board/range/all boards");
+ puts("calib [dir] Response Calibration. Use dir=\"area\" for MEG");
+ puts("chn [n] Set number of channels: 8, 4, 2, 1");
+ puts("ct Chip Test");
+ puts("del <0|1> Switch delayed start on/off");
+ puts("dir Show CF directory");
+ puts("dmode <0|1> Set Domino mode 0=single, 1=cont.");
+ puts("et EEPROM test");
+ puts("exit Exit program");
+ puts("freq <ghz> [0|1] Set frequency of board [without/with] regulation");
+ puts("info Show information about board");
+ puts("init Initialize board");
+ puts("led <0|1> Turn LED on (1) or off (0)");
+ puts("lock [0|1] Display lock status [without/with] restart");
+ puts("multi [0|1] Turn multi-buffer mode on/off");
+ puts("offset <voltage> Set offset voltage");
+ puts("phase <value> [0|1] Set ADC clock phase and inversion");
+ puts("quit Exit program");
+ puts("ram Test speed to FPGA RAM");
+ puts("range <center> Change input range to <center>+=0.5V");
+ puts("read <chn> [0|1] [file] Read waveform to [file], chn=0..19 [with] calibration");
+ puts("refclk [0|1] Use FPGA ref. clk (0) or ext. P2 ref. clk (1)");
+ puts("reg Register test");
+ puts("serial <number> Set serial number of board");
+ puts("scan Scan for boards");
+ puts("standby <0|1> Turn standby mode on (1) or off (0)");
+ puts("start Start domino wave");
+ puts("stop Issue soft trigger");
+ puts("tcout [file] [idx_offset] Print time calibration of DRS4, or write it onto [file]");
+ puts("tcs <0|1> Timing calibration signal on (1) or off (0)");
+ puts("tcalib [freq] Timing Calibration");
+ puts("tlevel <voltage> Set trigger level in Volts");
+ puts("trans <0|1> Set transparent mode on (1) or off (0)");
+ puts("trig <0|1> Hardware trigger on (1) or off (0)");
+ puts("upload <file> Upload ACE file to CF");
+ puts("volt off|<voltage> Turn calibration voltage on/off");
+
+ puts("");
+}
+
+/*------------------------------------------------------------------*/
+
+void clear_screen()
+{
+#ifdef _MSC_VER
+
+ HANDLE hConsole;
+ COORD coordScreen = { 0, 0 }; /* here's where we'll home the cursor */
+ BOOL bSuccess;
+ DWORD cCharsWritten;
+ CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */
+ DWORD dwConSize; /* number of character cells in the current buffer */
+
+ hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+
+ /* get the number of character cells in the current buffer */
+ bSuccess = GetConsoleScreenBufferInfo(hConsole, &csbi);
+ dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
+
+ /* fill the entire screen with blanks */
+ bSuccess = FillConsoleOutputCharacter(hConsole, (TCHAR) ' ', dwConSize, coordScreen, &cCharsWritten);
+
+ /* put the cursor at (0, 0) */
+ bSuccess = SetConsoleCursorPosition(hConsole, coordScreen);
+ return;
+
+#else
+ printf("\033[2J");
+#endif
+}
+
+/*------------------------------------------------------------------*/
+
+int match(const char *str, const char *cmd)
+{
+ int i;
+
+ if (str[0] == '\r' || str[0] == '\n')
+ return 0;
+
+ for (i = 0; i < (int) strlen(str); i++) {
+ if (toupper(str[i]) != toupper(cmd[i]) && str[i] != '\r' && str[i] != '\n')
+ return 0;
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+class ProgressBar : public DRSCallback
+{
+public:
+ void Progress(int prog);
+};
+
+void ProgressBar::Progress(int prog)
+{
+ if (prog == 0)
+ printf("[--------------------------------------------------]\r");
+ printf("[");
+ for (int i=0 ; i<prog/2 ; i++)
+ printf("=");
+ printf("\r");
+ fflush(stdout);
+}
+
+/*------------------------------------------------------------------*/
+
+void cmd_loop()
+{
+ int i, j, idx, i_start, i_end, nparam, calib, status, debug, cascading,
+ ext_refclk;
+ char str[256], dir[256], line[256], file_name[256], param[10][100], *pc;
+ double freq, triggerfreq, range;
+ FILE *f = NULL;
+ DRS *drs;
+ DRSBoard *b;
+#ifdef HAVE_VME
+ ACE ace;
+#endif
+ static char bar[] = {'\\', '|', '/', '-'};
+
+ /* do initial scan */
+ drs = new DRS();
+ if (drs->GetError(str, sizeof(str)))
+ printf("%s", str);
+
+ for (i=0 ; i<drs->GetNumberOfBoards() ; i++) {
+ b = drs->GetBoard(i);
+#ifdef HAVE_VME
+ if (b->GetTransport() != 1)
+ printf("Found DRS%d board %2d on USB, serial #%04d, firmware revision %5d\n",
+ b->GetDRSType(), i, b->GetBoardSerialNumber(), b->GetFirmwareVersion());
+#else
+ printf("Found DRS%d board %2d on USB, serial #%04d, firmware revision %5d\n",
+ b->GetDRSType(), i, b->GetBoardSerialNumber(), b->GetFirmwareVersion());
+#endif
+ }
+
+ if (drs->GetNumberOfBoards()) {
+ i_start = 0;
+ i_end = 1;
+ b = drs->GetBoard(0);
+ }
+ else {
+ printf("No DRS Boards found\n");
+ i_start = i_end = 0;
+ b = NULL;
+ }
+
+ puts("");
+
+ do {
+ /* print prompt */
+ if (i_start == i_end-1)
+ printf("B%d> ", i_start);
+ else if (i_start == 0 && i_end == 0)
+ printf("> ");
+ else
+ printf("B%d-%d> ", i_start, i_end-1);
+ memset(line, 0, sizeof(line));
+ fgets(line, sizeof(line), stdin);
+ /* strip \r\n */
+ while (strpbrk(line,"\n\r"))
+ *strpbrk(line,"\n\r") = 0;
+
+ /* analyze line */
+ nparam = 0;
+ pc = line;
+ while (*pc == ' ')
+ pc++;
+
+ memset(param, 0, sizeof(param));
+ do {
+ if (*pc == '"') {
+ pc++;
+ for (i = 0; *pc && *pc != '"'; i++)
+ param[nparam][i] = *pc++;
+ if (*pc)
+ pc++;
+ } else if (*pc == '\'') {
+ pc++;
+ for (i = 0; *pc && *pc != '\''; i++)
+ param[nparam][i] = *pc++;
+ if (*pc)
+ pc++;
+ } else if (*pc == '`') {
+ pc++;
+ for (i = 0; *pc && *pc != '`'; i++)
+ param[nparam][i] = *pc++;
+ if (*pc)
+ pc++;
+ } else
+ for (i = 0; *pc && *pc != ' '; i++)
+ param[nparam][i] = *pc++;
+ param[nparam][i] = 0;
+ while (*pc == ' ' || *pc == '\r' || *pc == '\n')
+ pc++;
+ nparam++;
+ } while (*pc);
+
+ if (param[0][0] == 0) {
+ }
+
+ /* help ---------- */
+ else if ((param[0][0] == 'h' && param[0][1] == 'e') || param[0][0] == '?')
+ print_help();
+
+ /* scan ---------- */
+ else if (match(param[0], "scan")) {
+ j = 0;
+
+ do {
+ delete drs;
+ drs = new DRS();
+
+ for (i=0 ; i<drs->GetNumberOfBoards() ; i++) {
+ b = drs->GetBoard(i);
+#ifdef HAVE_VME
+ if (b->GetTransport() != 1)
+ printf("Found DRS%d board %2d on USB, serial #%04d, firmware revision %5d\n",
+ b->GetDRSType(), i, b->GetBoardSerialNumber(), b->GetFirmwareVersion());
+#else
+ printf("Found DRS%d board %2d on USB, serial #%04d, firmware revision %5d\n",
+ b->GetDRSType(), i, b->GetBoardSerialNumber(), b->GetFirmwareVersion());
+#endif
+ }
+
+ if (drs_kbhit())
+ break;
+
+ if (param[1][0] == 'r') {
+ printf("%c\r", bar[j]);
+ fflush(stdout);
+ j = (j+1) % 4;
+ Sleep(1000);
+ }
+
+ } while (param[1][0] == 'r');
+
+ while (drs_kbhit())
+ getch();
+
+ if (drs->GetNumberOfBoards()) {
+ i_start = 0;
+ i_end = 1;
+ b = drs->GetBoard(0);
+ } else {
+ printf("No DRS Boards found\n");
+ i_start = i_end = 0;
+ b = NULL;
+ }
+ }
+
+ /* address board ---------- */
+ else if (match(param[0], "board")) {
+ if (param[1][0] == 'a') {
+ i_start = 0;
+ i_end = drs->GetNumberOfBoards();
+ b = drs->GetBoard(0);
+ } else if (param[2][0] && atoi(param[2]) > 0 && atoi(param[2]) < drs->GetNumberOfBoards()) {
+ i_start = atoi(param[1]);
+ i_end = atoi(param[2]) + 1;
+ b = drs->GetBoard(i_start);
+ } else if (atoi(param[1]) >= 0 && atoi(param[1]) < drs->GetNumberOfBoards()) {
+ i_start = atoi(param[1]);
+ i_end = i_start + 1;
+ b = drs->GetBoard(i_start);
+ } else
+ printf("Board #%d does not exist\n", atoi(param[1]));
+ }
+
+ /* info ---------- */
+ else if (match(param[0], "info")) {
+ for (idx=i_start ; idx<i_end ; idx++) {
+ b = drs->GetBoard(idx);
+ printf("==============================\n");
+ printf("Mezz. Board index: %d\n", idx);
+#ifdef HAVE_VME
+ if (b->GetTransport() == TR_VME) {
+ printf("Slot: %d", (b->GetSlotNumber() >> 1)+2);
+ if ((b->GetSlotNumber() & 1) == 0)
+ printf(" upper\n");
+ else
+ printf(" lower\n");
+ }
+#endif
+ printf("DRS type: DRS%d\n", b->GetDRSType());
+ printf("Board type: %d\n", b->GetBoardType());
+ printf("Serial number: %04d\n", b->GetBoardSerialNumber());
+ printf("Firmware revision: %d\n", b->GetFirmwareVersion());
+ printf("Temperature: %1.1lf C\n", b->GetTemperature());
+ if (b->GetDRSType() == 4) {
+ printf("Input range: %1.2lgV...%1.2lgV\n",
+ b->GetInputRange()-0.5, b->GetInputRange()+0.5);
+ printf("Calibrated range: %1.2lgV...%1.2lgV\n", b->GetCalibratedInputRange()-0.5,
+ b->GetCalibratedInputRange()+0.5);
+ printf("Calibrated frequency: %1.3lf GHz\n", b->GetCalibratedFrequency());
+
+ if (b->GetTransport() == TR_VME) {
+ printf("Multi Buffer WP: %d\n", b->GetMultiBufferWP());
+ printf("Multi Buffer RP: %d\n", b->GetMultiBufferRP());
+ }
+ }
+
+ printf("Status reg.: %08X\n", b->GetStatusReg());
+ if (b->GetStatusReg() & BIT_RUNNING)
+ puts(" Domino wave running");
+ if (b->GetDRSType() == 4) {
+ if (b->GetBoardType() == 5) {
+ if (b->GetStatusReg() & BIT_PLL_LOCKED0)
+ puts(" PLL locked");
+ } else if (b->GetBoardType() == 6) {
+ i = 0;
+ if (b->GetStatusReg() & BIT_PLL_LOCKED0) i++;
+ if (b->GetStatusReg() & BIT_PLL_LOCKED1) i++;
+ if (b->GetStatusReg() & BIT_PLL_LOCKED2) i++;
+ if (b->GetStatusReg() & BIT_PLL_LOCKED3) i++;
+ if (i == 4)
+ puts(" All PLLs locked");
+ else if (i == 0)
+ puts(" No PLL locked");
+ else
+ printf(" %d PLLs locked\n", i);
+ if (b->GetStatusReg() & BIT_LMK_LOCKED)
+ puts(" LMK PLL locked");
+ }
+ } else {
+ if (b->GetStatusReg() & BIT_NEW_FREQ1)
+ puts(" New Freq1 ready");
+ if (b->GetStatusReg() & BIT_NEW_FREQ2)
+ puts(" New Freq2 ready");
+ }
+
+ printf("Control reg.: %08X\n", b->GetCtrlReg());
+ if (b->GetCtrlReg() & BIT_MULTI_BUFFER)
+ puts(" Multi-buffering enabled");
+ if (b->GetDRSType() == 4) {
+ if (b->GetConfigReg() & BIT_CONFIG_DMODE)
+ puts(" DMODE circular");
+ else
+ puts(" DMODE single shot");
+ } else {
+ if (b->GetCtrlReg() & BIT_DMODE)
+ puts(" DMODE circular");
+ else
+ puts(" DMODE single shot");
+ }
+ if (b->GetCtrlReg() & BIT_LED)
+ puts(" LED");
+ if (b->GetCtrlReg() & BIT_TCAL_EN)
+ puts(" TCAL enabled");
+ if (b->GetDRSType() == 4) {
+ if (b->GetCtrlReg() & BIT_TRANSP_MODE)
+ puts(" TRANSP_MODE enabled");
+ } else {
+ if (b->GetCtrlReg() & BIT_FREQ_AUTO_ADJ)
+ puts(" FREQ_AUTO_ADJ enabled");
+ }
+ if (b->GetCtrlReg() & BIT_ENABLE_TRIGGER1)
+ puts(" Hardware trigger enabled");
+ if (b->GetDRSType() == 4) {
+ if (b->GetCtrlReg() & BIT_READOUT_MODE)
+ puts(" Readout from stop");
+ if (b->GetCtrlReg() & BIT_ENABLE_TRIGGER2)
+ puts(" Internal trigger enabled");
+ } else {
+ if (b->GetCtrlReg() & BIT_LONG_START_PULSE)
+ puts(" LONG_START_PULSE");
+ }
+ if (b->GetCtrlReg() & BIT_DELAYED_START)
+ puts(" DELAYED_START");
+ if (b->GetCtrlReg() & BIT_ACAL_EN)
+ puts(" ACAL enabled");
+ if (b->GetDRSType() < 4)
+ if (b->GetCtrlReg() & BIT_TRIGGER_DELAYED)
+ puts(" DELAYED_TRIGGER selected");
+ if (b->GetBoardType() != 5)
+ printf("Trigger bus: %08X\n", b->GetTriggerBus());
+ if (b->GetDRSType() == 4) {
+ if (b->GetRefclk() == 1) {
+ if (b->IsPLLLocked() && b->IsLMKLocked()) {
+ b->ReadFrequency(0, &freq);
+ printf("Frequency: %1.3lf GHz\n", freq);
+ } else {
+ if (!b->IsPLLLocked())
+ printf("Frequency: PLL not locked\n");
+ else
+ printf("Frequency: LMK chip not locked\n");
+ }
+ } else {
+ if (b->IsPLLLocked()) {
+ b->ReadFrequency(0, &freq);
+ printf("Frequency: %1.3lf GHz\n", freq);
+ } else {
+ printf("Frequency: PLL not locked\n");
+ }
+ }
+ } else {
+ if (b->IsBusy()) {
+ b->ReadFrequency(0, &freq);
+ printf("Frequency0: %1.4lf GHz\n", freq);
+ b->ReadFrequency(1, &freq);
+ printf("Frequency1: %1.4lf GHz\n", freq);
+ } else
+ puts("Domino wave stopped");
+ }
+ }
+ }
+
+ /* init ---------- */
+ else if (match(param[0], "init")) {
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ b->Init();
+ }
+ }
+
+ /* set led ---------- */
+ else if (match(param[0], "led")) {
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ if (atoi(param[1]))
+ b->SetLED(1);
+ else
+ b->SetLED(0);
+ }
+ }
+
+ /* set multi buffer mode ---------- */
+ else if (match(param[0], "multi")) {
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ if (atoi(param[1]))
+ b->SetMultiBuffer(1);
+ else
+ b->SetMultiBuffer(0);
+ }
+ }
+
+ /* lock status ---------- */
+ else if (match(param[0], "lock")) {
+ int slot, found, restart;
+
+ restart = atoi(param[1]);
+
+ // select external reference clock
+ for (i=0 ; i<drs->GetNumberOfBoards() ; i++) {
+ b = drs->GetBoard(i);
+ b->SetRefclk(1);
+ b->SetFrequency(b->GetNominalFrequency(), true);
+ }
+
+ // loop until keyboard hit
+ do {
+ clear_screen();
+ printf(" 1 1 1 1 1 1 1 1 1 1 2 2\n");
+ printf("2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\n\n");
+
+ // upper slots
+ for (slot = 2 ; slot<22 ; slot++) {
+ found = 0;
+ for (i=0 ; i<drs->GetNumberOfBoards() ; i++) {
+ b = drs->GetBoard(i);
+ if ((b->GetSlotNumber() & 1) == 0 && (b->GetSlotNumber() >> 1)+2 == slot) {
+ found = 1;
+ if (b->IsLMKLocked())
+ printf("O ");
+ else
+ printf("- ");
+ }
+ }
+ if (!found)
+ printf(" ");
+ }
+ printf("\n");
+
+ // lower slots
+ for (slot = 2 ; slot<22 ; slot++) {
+ found = 0;
+ for (i=0 ; i<drs->GetNumberOfBoards() ; i++) {
+ b = drs->GetBoard(i);
+ if ((b->GetSlotNumber() & 1) == 1 && (b->GetSlotNumber() >> 1)+2 == slot) {
+ found = 1;
+ if (b->IsLMKLocked())
+ printf("O ");
+ else
+ printf("- ");
+ }
+ }
+ if (!found)
+ printf(" ");
+ }
+ printf("\n");
+
+ if (restart) {
+ for (i=0 ; i<drs->GetNumberOfBoards() ; i++) {
+ b = drs->GetBoard(i);
+ b->SetFrequency(b->GetNominalFrequency(), true);
+ }
+ }
+
+ Sleep(300);
+
+ } while (!drs_kbhit());
+ puts("");
+ while (drs_kbhit())
+ getch();
+ }
+
+ /* start domino wave ---------- */
+ else if (match(param[0], "start")) {
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ b->StartDomino();
+ b->ReadFrequency(0, &freq);
+ for (j=0 ; j<10 ; j++)
+ if (b->GetDRSType() != 4 || b->IsPLLLocked())
+ break;
+ if (j == 10)
+ printf("Domino wave started but PLL did not lock!\n");
+ else
+ printf("Domino wave started at %1.3lf GHz\n", freq);
+ }
+ }
+
+ /* issue soft trigger ---------- */
+ else if (match(param[0], "stop")) {
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ b->SoftTrigger();
+ }
+ }
+
+ /* set serial ---------- */
+ else if (match(param[0], "serial")) {
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ if (param[1][0] == 0) {
+ printf("Serial number: ");
+ fgets(str, sizeof(str), stdin);
+ } else
+ strlcpy(str, param[1], sizeof(str));
+
+ if (!b->SetBoardSerialNumber(atoi(str)))
+ printf("Board EEPROM is write protected\n");
+ else
+ printf("Serial number successfully changed\n");
+ }
+ }
+
+ /* eeprom test ---------- */
+ else if (match(param[0], "et")) {
+ unsigned short buf[16384];
+ unsigned short rbuf[16384];
+ int n_error;
+
+ do {
+ for (i=0 ; i<16384 ; i++)
+ buf[i] = rand();
+ b->WriteEEPROM(1, buf, sizeof(buf));
+ memset(rbuf, 0, sizeof(rbuf));
+ b->Write(T_RAM, 0, rbuf, sizeof(rbuf));
+ b->ReadEEPROM(1, rbuf, sizeof(rbuf));
+ for (i=n_error=0 ; i<16384 ; i++)
+ if (buf[i] != rbuf[i]) {
+ printf("%04X %04X - %04X\n", i, buf[i], rbuf[i]);
+ n_error++;
+ }
+
+ printf("32 kb written, %d errors\n", n_error);
+ } while (!drs_kbhit());
+
+ while (drs_kbhit())
+ getch();
+ }
+
+ /* set frequency ---------- */
+ else if (match(param[0], "freq")) {
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ if (param[1][0] == 0) {
+ printf("Frequency: ");
+ fgets(str, sizeof(str), stdin);
+ } else
+ strlcpy(str, param[1], sizeof(str));
+
+ b->SetDebug(1);
+
+ if (param[2][0] && atoi(param[2]))
+ b->RegulateFrequency(atof(str));
+ else
+ b->SetFrequency(atof(str), true);
+ }
+ }
+
+ /* set calibration voltage ---------- */
+ else if (match(param[0], "volt")) {
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ if (param[1][0] == 0) {
+ printf("Voltage or \"off\": ");
+ fgets(str, sizeof(str), stdin);
+ } else
+ strlcpy(str, param[1], sizeof(str));
+
+ if (str[0] == 'o') {
+ b->EnableAcal(0, 0);
+ puts("Calibration voltage turned off");
+ } else {
+ b->EnableAcal(1, atof(str));
+ printf("Voltage set to %1.3lf Volt\n", atof(str));
+ }
+ }
+ }
+
+ /* set channel configuration ---------- */
+ else if (match(param[0], "chn")) {
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ if (param[1][0] == 0) {
+ printf("Number of channels (8,4,2,1): ");
+ fgets(str, sizeof(str), stdin);
+ } else
+ strlcpy(str, param[1], sizeof(str));
+
+ if (b->SetChannelConfig(0, 8, atoi(str)))
+ printf("DRS4 configured for %d channels\n", atoi(str));
+ }
+ }
+
+ /* set trigger level ---------- */
+ else if (match(param[0], "tlevel")) {
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ if (param[1][0] == 0) {
+ printf("Voltage: ");
+ fgets(str, sizeof(str), stdin);
+ } else
+ strlcpy(str, param[1], sizeof(str));
+
+ b->SetTriggerLevel(atof(str));
+ printf("Trigger level set to %1.3lf Volt\n", atof(str));
+ }
+ }
+
+ /* trigger on/off ---------- */
+ else if (match(param[0], "trig")) {
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ b->EnableTrigger(atoi(param[1]), 0);
+ if (atoi(param[1]) == 1) {
+ puts("Hardware fast trigger is on");
+ } else if (atoi(param[1]) == 2) {
+ puts("Hardware slow trigger is on");
+ } else {
+ puts("Hardware trigger is off");
+ }
+ }
+ }
+
+ /* timing calibration signal on/off ---------- */
+ else if (match(param[0], "tcs")) {
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ b->EnableTcal(atoi(param[1]), 0, 0);
+ b->SelectClockSource(0);
+ if (atoi(param[1]))
+ puts("Timing calibration signal is on");
+ else
+ puts("Timing calibration signal is off");
+ }
+ }
+
+ /* timing calibration signal on/off ---------- */
+ else if (match(param[0], "refclk")) {
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ b->SetRefclk(atoi(param[1]));
+ // re-set frequency since LMK configuration needs to be changed
+ b->SetFrequency(b->GetNominalFrequency(), true);
+ if (atoi(param[1]))
+ puts("Refclock set to external through P2");
+ else
+ puts("Refclock set to internal (FPGA)");
+ }
+ }
+
+ /* domino mode 0/1 ---------- */
+ else if (match(param[0], "dmode")) {
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ if (atoi(param[1]) == 1) {
+ b->SetDominoMode(1);
+ puts("Domino mode switched to cyclic");
+ } else {
+ b->SetDominoMode(0);
+ puts("Domino mode switched to single shot");
+ }
+ }
+ }
+
+ /* active mode 0/1 ---------- */
+ else if (match(param[0], "active")) {
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ if (atoi(param[1]) == 1) {
+ b->SetDominoActive(1);
+ puts("Domino wave active during readout");
+ } else {
+ b->SetDominoMode(0);
+ puts("Domino wave stopped during readout");
+ }
+ }
+ }
+
+ /* delayed start on/off ---------- */
+ else if (match(param[0], "del")) {
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ if (b->GetDRSType() == 4)
+ puts("Delayed start not possible for DRS4");
+ else {
+ if (atoi(param[1]) == 1) {
+ b->SetDelayedStart(1);
+ puts("Delayed start is on");
+ } else {
+ b->SetDelayedStart(0);
+ puts("Delayed start is off");
+ }
+ }
+ }
+ }
+
+ /* transparent mode on/off ---------- */
+ else if (match(param[0], "trans")) {
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ if (b->GetDRSType() != 4)
+ puts("Transparen mode only possible for DRS4");
+ else {
+ if (atoi(param[1]) == 1) {
+ b->SetTranspMode(1);
+ puts("Transparent mode is on");
+ } else {
+ b->SetTranspMode(0);
+ puts("Transparent mode is off");
+ }
+ }
+ }
+ }
+
+ /* standby mode on/off ---------- */
+ else if (match(param[0], "standby")) {
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ if (b->GetDRSType() != 4)
+ puts("Standby mode only possible for DRS4");
+ else {
+ if (atoi(param[1]) == 1) {
+ b->SetStandbyMode(1);
+ puts("Standby mode is on");
+ } else {
+ b->SetStandbyMode(0);
+ puts("Standby mode is off");
+ }
+ }
+ }
+ }
+
+ /* offset ---------- */
+ else if (match(param[0], "offset")) {
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ b->SetVoltageOffset(atof(param[1]), atof(param[2]));
+ }
+ }
+
+ /* phase ---------- */
+ else if (match(param[0], "phase")) {
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ b->SetADCClkPhase(atoi(param[1]), atoi(param[2]) > 0);
+ }
+ }
+
+ /* directory ---------- */
+ else if (match(param[0], "dir")) {
+
+#ifdef HAVE_VME
+#ifdef CF_VIA_USB
+ {
+ if (param[2][0])
+ i = atoi(param[2]);
+ else
+ i = 1;
+ printf("Physical drive %d:\n", i);
+
+ if (ace_init(NULL, i, &ace) != ACE_SUCCESS) {
+ printf("Cannot access ACE on physical drive %d\n", i);
+ } else {
+#else
+ for (i=i_start ; i<i_end ; i++) {
+
+ /* do only once per VME board */
+ if (i_end - i_start > 1 && (i % 2) == 1)
+ continue;
+
+ b = drs->GetBoard(i);
+
+ printf("VME slot %2d: ", (b->GetSlotNumber() >> 1) + 2);
+
+ if (ace_init(b->GetVMEInterface(), (b->GetSlotNumber() >> 1)+2, &ace) != ACE_SUCCESS) {
+ printf("Cannot access ACE in slot %d\n", (b->GetSlotNumber() >> 1)+2);
+ } else {
+#endif
+ ace_dir(&ace);
+ }
+ }
+#else
+ printf("No VME support compiled into drscl\n");
+#endif // HAVE_VME
+ }
+
+ /* upload ---------- */
+ else if (match(param[0], "upload")) {
+
+#ifdef HAVE_VME
+#ifdef CF_VIA_USB
+ {
+ if (param[2][0])
+ i = atoi(param[2]);
+ else
+ i = 1;
+ printf("Physical drive %d:\n", i);
+
+ if (ace_init(NULL, i, &ace) != ACE_SUCCESS) {
+ printf("Cannot access ACE on physical drive %d\n", i);
+ } else {
+#else
+
+ /* use SVN file as default */
+ if (param[1][0] == 0) {
+#ifdef _MSC_VER
+ if (b->GetDRSType() == 4)
+ strcpy(str, "c:\\meg\\online\\VPC\\drs4\\2vp30\\cflash\\drs4\\rev0\\rev0.ace");
+ else if (b->GetDRSType() == 3)
+ strcpy(str, "c:\\meg\\online\\VPC\\drs3\\2vp30\\cflash\\drs3\\rev0\\rev0.ace");
+ else
+ strcpy(str, "c:\\meg\\online\\VPC\\drs2\\2vp30\\cflash\\drs2\\rev0\\rev0.ace");
+#else
+ if (b->GetDRSType() == 4)
+ strcpy(str, "/home/meg/meg/online/VPC/drs4/2vp30/cflash/drs4/rev0/rev0.ace");
+ else if (b->GetDRSType() == 3)
+ strcpy(str, "/home/meg/meg/online/VPC/drs3/2vp30/cflash/drs3/rev0/rev0.ace");
+ else
+ strcpy(str, "/home/meg/meg/online/VPC/drs2/2vp30/cflash/drs2/rev0/rev0.ace");
+#endif
+ printf("Enter filename or hit return for \n%s\n", str);
+ fgets(line, sizeof(line), stdin);
+ if (line[0] == '\r' || line[0] == '\n')
+ strcpy(file_name, str);
+ else
+ strcpy(file_name, line);
+ strcpy(param[1], str);
+ } else
+ strcpy(file_name, param[1]);
+
+ for (i=i_start ; i<i_end ; i++) {
+
+ /* do only once per VME board */
+ if (i_end - i_start > 1 && (i % 2) == 1)
+ continue;
+
+ b = drs->GetBoard(i);
+
+ if (b->GetTransport() == TR_USB) {
+ printf("Cannot upload to USB board.\n");
+ } else {
+ printf("VME slot %d:\n", (b->GetSlotNumber() >> 1)+2);
+ if (ace_init(b->GetVMEInterface(), (b->GetSlotNumber() >> 1)+2, &ace) != ACE_SUCCESS) {
+ printf("Cannot access ACE in slot %d\n", (b->GetSlotNumber() >> 1)+2);
+ } else {
+#endif
+ status = ace_upload(&ace, file_name);
+ }
+ }
+ }
+ printf("\nPlease issue a power cycle to activate new firmware\n");
+#else
+ printf("No VME support compiled into drscl\n");
+#endif // HAVE_VME
+ }
+
+ /* download ---------- */
+ else if (match(param[0], "download")) {
+
+#ifdef HAVE_VME
+ b = drs->GetBoard(i_start);
+
+ if (b->GetTransport() == TR_USB) {
+ printf("Cannot upload to USB board.\n");
+ } else {
+ printf("VME slot %d:\n", (b->GetSlotNumber() >> 1)+2);
+ if (ace_init(b->GetVMEInterface(), (b->GetSlotNumber() >> 1)+2, &ace) != ACE_SUCCESS) {
+ printf("Cannot access ACE in slot %d\n", (b->GetSlotNumber() >> 1)+2);
+ } else {
+ strcpy(str, "rev0.ace");
+ if (param[1][0] == 0) {
+ printf("Enter filename or hit return for \n%s\n", str);
+ fgets(line, sizeof(line), stdin);
+ if (line[0] == '\r' || line[0] == '\n')
+ strcpy(file_name, str);
+ else
+ strcpy(file_name, line);
+ strcpy(param[1], str);
+ } else
+ strcpy(file_name, param[1]);
+
+ if (strchr(file_name, '\r'))
+ *strchr(file_name, '\r') = 0;
+ if (strchr(file_name, '\n'))
+ *strchr(file_name, '\n') = 0;
+
+ status = ace_download(&ace, file_name);
+ }
+ }
+#else
+ printf("No VME support compiled into drscl\n");
+#endif // HAVE_VME
+ }
+
+ /* calibration ---------- */
+ else if (match(param[0], "calib")) {
+ debug = strcmp(param[1], "debug") == 0 || strcmp(param[2], "debug") == 0 || strcmp(param[3], "debug") == 0;
+ if (param[1][0]) {
+ strlcpy(dir, param[1], sizeof(str));
+ } else
+ getcwd(dir, sizeof(dir));
+
+ while (dir[strlen(dir)-1] == '\n' || dir[strlen(dir)-1] == '\r')
+ dir[strlen(dir)-1] = 0;
+
+ b = drs->GetBoard(i_start);
+
+ printf("\n Enter calibration frequency [GHz]: ");
+ fgets(line, sizeof(line), stdin);
+ freq = atof(line);
+
+ if (b->GetDRSType() == 2) {
+ printf(" Enter the expected trigger frequency [Hz]: ");
+ fgets(line, sizeof(line), stdin);
+ triggerfreq = atof(line);
+ } else
+ triggerfreq = 0;
+
+ ext_refclk = 0;
+ if (b->GetBoardType() == 6) {
+ printf("Use [e]xternal or [i]nternal reference clock: ");
+ fgets(line, sizeof(line), stdin);
+ ext_refclk = line[0] == 'e';
+ }
+
+ if (b->GetDRSType() == 4) {
+ printf(" Enter range [V]: ");
+ fgets(line, sizeof(line), stdin);
+ range = atof(line);
+
+ printf(" Enter mode [1]024 or [2]048 bin mode: ");
+ fgets(line, sizeof(line), stdin);
+ cascading = atoi(line);
+ } else {
+ range = 0;
+ cascading = 0;
+ }
+
+ if (b->GetDRSType() == 4) {
+ printf("\nPlease make sure that no input signal are present then hit any key\r");
+ fflush(stdout);
+ while (!drs_kbhit());
+ printf(" \r");
+ while (drs_kbhit())
+ getchar();
+ }
+
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ if (b->GetTransport() == TR_VME)
+ printf("Creating Calibration of Board in VME slot %2d %s, serial #%04d\n",
+ (b->GetSlotNumber() >> 1)+2, ((b->GetSlotNumber() & 1) == 0) ? "upper" : "lower",
+ b->GetBoardSerialNumber());
+ else
+ printf("Creating Calibration of Board on USB, serial #%04d\n",
+ b->GetBoardSerialNumber());
+ if (b->GetDRSType() == 4) {
+ ProgressBar p;
+ if (b->GetTransport() == TR_VME) {
+ if (cascading == 2)
+ b->SetChannelConfig(7, 8, 4); // 7 means read all 9 channels per chip
+ else
+ b->SetChannelConfig(7, 8, 8);
+ } else {
+ if (cascading == 2)
+ b->SetChannelConfig(0, 8, 4);
+ else
+ b->SetChannelConfig(0, 8, 8);
+ }
+
+ b->SetRefclk(ext_refclk);
+ b->SetFrequency(freq, true);
+ b->SetInputRange(range);
+ b->CalibrateVolt(&p);
+ } else {
+ b->SetDebug(debug);
+ b->Init();
+ b->SetFrequency(freq, true);
+ b->SoftTrigger();
+
+ if (b->GetDRSType() == 3)
+ b->GetResponseCalibration()->SetCalibrationParameters(1,11,0,20,0,0,0,0,0);
+ else
+ b->GetResponseCalibration()->SetCalibrationParameters(1,36,110,20,19,40,15,triggerfreq,0);
+ if (!strcmp(dir,"lab"))
+ b->SetCalibrationDirectory("C:/experiment/calibrations");
+ else if (!strcmp(dir,"area"))
+ b->SetCalibrationDirectory("/home/meg/meg/online/calibrations");
+ else
+ b->SetCalibrationDirectory(dir);
+ for (j=0;j<2;j++) {
+ b->GetResponseCalibration()->ResetCalibration();
+ while (!b->GetResponseCalibration()->RecordCalibrationPoints(j)) {}
+ while (!b->GetResponseCalibration()->FitCalibrationPoints(j)) {}
+ while (!b->GetResponseCalibration()->OffsetCalibration(j)) {}
+ if (!b->GetResponseCalibration()->WriteCalibration(j))
+ break;
+ }
+ }
+ }
+ }
+
+ /* timing calibration ---------- */
+ else if (match(param[0], "tcalib")) {
+
+ freq = 0;
+ if (param[1][0])
+ freq = atof(param[1]);
+
+ if (freq == 0) {
+ printf("Enter calibration frequency [GHz]: ");
+ fgets(line, sizeof(line), stdin);
+ freq = atof(line);
+ }
+
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ if (b->GetDRSType() < 4)
+ printf("Timing calibration not possivle for DRS2 or DRS3\n");
+ else if (b->GetFirmwareVersion() < 13279)
+ printf("Firmware revision 13279 or later required for timing calibration\n");
+ else if (b->GetDRSType() == 4) {
+ printf("Creating Timing Calibration of Board #%d\n", b->GetBoardSerialNumber());
+ ProgressBar p;
+ b->SetFrequency(freq, true);
+ status = b->CalibrateTiming(&p);
+ if (!status)
+ printf("Error performing timing calibration, please check waveforms\n");
+ printf("\n");
+ }
+ }
+ }
+
+ /* tcout ---------- */
+ else if (match(param[0], "tcout")) {
+ float time[1024];
+ int chip;
+ int k;
+ int idx = 0;
+ int first_board = i_start;
+ int last_board = i_end;
+
+ file_name[0] = 0;
+ strcpy(file_name, param[1]);
+ if (file_name[0]) {
+ f = fopen(file_name, "wt");
+ if (f == NULL) {
+ printf("Cannot open file \"%s\"\n", file_name);
+ } else {
+ first_board = 0;
+ last_board = drs->GetNumberOfBoards();
+ }
+ idx += atoi(param[2]);
+ } else
+ f = NULL;
+
+ if (f) {
+ fprintf(f, "-- Replace %%%% with correct id\n");
+ }
+ for (i=first_board ; i<last_board ; i++) {
+ b = drs->GetBoard(i);
+ if (b->GetDRSType() >= 4) {
+ for (chip = 0; chip < b->GetNumberOfChips(); chip++) {
+ b->GetTime(chip, 0, b->GetTriggerCell(0), time, true, false);
+ if (f) {
+ fprintf(f, "INSERT INTO MEGDRSTimeCalibration VALUES(%%%%,%d,%d", idx,
+ static_cast<int>(b->GetNominalFrequency() * 10 + 0.5) * 100);
+ for (j=0 ; j<1024 ; j++)
+ fprintf(f, ",%g", time[j] * 1e-9);
+ fprintf(f, ",%d,%d", b->GetBoardSerialNumber(), chip);
+ fprintf(f, ",%g);\n", 1 / (b->GetNominalFrequency() * 1e9) * 1024);
+ idx++;
+ } else {
+ printf("Board %d\n", b->GetBoardSerialNumber());
+ for (j=0 ; j<128 ; j++) {
+ printf("%4d: ", j*8);
+ for (k=0 ; k<7 ; k++)
+ printf("%6.1lf ", time[j*8+k]);
+ printf("%6.1lf\n", time[j*8+k]);
+ }
+ printf("n");
+ }
+ }
+ } else {
+ // DRS2 or DRS3
+ idx += 2;
+ }
+ }
+ if (f) {
+ fclose(f);
+ printf("Data successfully written to \"%s\"\n", file_name);
+ }
+ }
+
+ /* read */
+ else if (match(param[0], "read")) {
+ float waveform[2048];
+ short swaveform[2048];
+ calib = 0;
+
+ file_name[0] = 0;
+ if (param[1][0]) {
+ idx = atoi(param[1]);
+ calib = atoi(param[2]);
+ if (strlen(param[2]) > 2)
+ strcpy(file_name, param[2]);
+ else
+ strcpy(file_name, param[3]);
+ } else {
+ printf("Enter channel number (0..19): ");
+ fgets(line, sizeof(line), stdin);
+ idx = atoi(line);
+ }
+
+ if (idx<0 || idx>19)
+ printf("Channel number must be between 0 and 19\n");
+ else {
+ b = drs->GetBoard(i_start);
+ if (!b->IsEventAvailable())
+ printf("Error: Domino wave is running, please issue a \"stop\" first\n");
+ else {
+ if (calib == 1) {
+ if (b->GetDRSType() == 4) {
+ if (!b->IsVoltageCalibrationValid()) {
+ printf("Calibration not valid for board #%d\n", b->GetBoardSerialNumber());
+ calib = 0;
+ }
+
+ } else {
+#ifdef _MSC_VER
+ b->SetCalibrationDirectory("C:/experiment/calibrations");
+#else
+ b->SetCalibrationDirectory("/home/meg/meg/online/calibrations");
+#endif
+ if (!b->GetResponseCalibration()->IsRead(0))
+ if (!b->GetResponseCalibration()->ReadCalibration(0))
+ calib = 0;
+ if (!b->GetResponseCalibration()->IsRead(1))
+ if (!b->GetResponseCalibration()->ReadCalibration(1))
+ calib = 0;
+ }
+ }
+
+ status = b->TransferWaves(idx, idx);
+ if (file_name[0]) {
+ f = fopen(file_name, "wt");
+ if (f == NULL)
+ printf("Cannot open file \"%s\"\n", file_name);
+ } else
+ f = NULL;
+
+ if (calib) {
+ status = b->GetWave(idx/b->GetNumberOfChannels(), idx%b->GetNumberOfChannels(), waveform,
+ true, b->GetTriggerCell(idx/b->GetNumberOfChannels()), b->GetStopWSR(idx/b->GetNumberOfChannels()));
+ if (status == 0) {
+ if (f)
+ for (i=0 ; i<b->GetChannelDepth() ; i++)
+ fprintf(f, "%6.1lf\n", waveform[i]);
+ else {
+ for (i=0 ; i<b->GetChannelDepth()/8 ; i++) {
+ printf("%4d: ", i*8);
+ for (j=0 ; j<7 ; j++)
+ printf("%6.1lf ", waveform[i*8+j]);
+ printf("%6.1lf\n", waveform[i*8+j]);
+ }
+ }
+ }
+ } else {
+ status = b->GetWave(idx/b->GetNumberOfChannels(), idx%b->GetNumberOfChannels(), swaveform, 0, 0);
+ if (status == 0) {
+ if (f)
+ for (i=0 ; i<b->GetChannelDepth() ; i++)
+ fprintf(f, "%4d\n", swaveform[i]);
+ else {
+ for (i=0 ; i<b->GetChannelDepth()/16 ; i++) {
+ for (j=0 ; j<15 ; j++)
+ printf("%4d ", swaveform[i*16+j] >> 4);
+ printf("%4d\n", swaveform[i*16+j] >> 4);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (f) {
+ fclose(f);
+ printf("Data successfully written to \"%s\"\n", file_name);
+ }
+ }
+
+ /* register test ---------- */
+ else if (match(param[0], "reg")) {
+ b->RegisterTest();
+ }
+
+ /* RAM test */
+ else if (match(param[0], "ram")) {
+ if (param[1][0] == 0)
+ b->RAMTest(3);
+ else
+ b->RAMTest(atoi(param[1]));
+ }
+
+ /* Change input range */
+ else if (match(param[0], "range")) {
+ for (i=i_start ; i<i_end ; i++) {
+ b = drs->GetBoard(i);
+ if (param[1][0] == 0) {
+ printf("Input range: ");
+ fgets(str, sizeof(str), stdin);
+ } else
+ strlcpy(str, param[1], sizeof(str));
+
+ b->SetInputRange(atof(str));
+ printf("Range set to %1.2lg V ... %1.2lg V\n", atof(str)-0.5, atof(str)+0.5);
+ }
+ }
+
+ /* Chip Test */
+ else if (match(param[0], "ct")) {
+ if (drs->GetNumberOfBoards() == 0)
+ puts("No DRS board found");
+ else {
+ puts("Press 'q' to quit, any other key to repeat test.\n");
+ do {
+ if (b->ChipTest())
+ puts("Chip test successfully finished");
+ else
+ puts("\007Chip Error!");
+
+ b->SetStandbyMode(1);
+ for (i=0 ; i<8 ; i++)
+ b->SetDAC(i, 0);
+ i = getch();
+ b->SetStandbyMode(0);
+ } while (i != 'q');
+ }
+ }
+
+ /* calib0 for speed vs. temperature calibration */
+ else if (match(param[0], "c0")) {
+
+ double volt, freq;
+
+ b->Init();
+ b->SetFrequency(5, true);
+ b->EnableAcal(0, 0);
+ b->SetDominoMode(1);
+
+ for (volt=2.5 ; volt > 0 ; volt -= 0.05) {
+ printf("%4.1lf - %5.3lf ", b->GetTemperature(), volt);
+ b->SetDAC(1, volt);
+ b->SetDAC(2, volt);
+ Sleep(100);
+ b->ReadFrequency(0, &freq);
+
+ printf("%5.3lf\n", freq);
+
+ if (drs_kbhit())
+ break;
+ }
+
+ while (drs_kbhit())
+ getch();
+
+ b->Init(); // reset voltage offset
+ }
+
+ /* calib1 */
+ else if (match(param[0], "c1")) {
+
+ short swaveform[1024];
+ double volt;
+ double av[1024];
+ int k;
+
+ b->Init();
+ b->SetFrequency(5, true);
+ b->SetDominoMode(1);
+ b->SetDominoActive(1);
+ b->SetReadoutMode(1);
+
+ for (volt=-0.5 ; volt <= 0.5001 ; volt += 0.02) {
+ printf("%4.1lf - %6.0lf ", b->GetTemperature(), 1000*volt);
+ b->EnableAcal(1, volt);
+ b->StartDomino();
+ Sleep(100);
+
+ memset(av, 0, sizeof(av));
+
+ for (j=0 ; j<100 ; j++) {
+ for (i=0 ; i<10 ; i++)
+ b->IsBusy();
+ b->SoftTrigger();
+ while (b->IsBusy());
+ b->StartDomino();
+ b->TransferWaves(b->GetNumberOfChannels()*b->GetNumberOfChips());
+ i = b->GetTriggerCell(0);
+ b->GetWave(0, 0, swaveform, false, i, 1);
+
+ for (k=0 ; k<1024 ; k++)
+ av[k] += swaveform[k];
+
+ if (drs_kbhit())
+ break;
+ }
+
+ for (k=0 ; k<1024 ; k++)
+ av[k] /= j;
+
+ for (k=0 ; k<5 ; k++)
+ printf("%10.2lf ", 1000*(av[k]/65536-0.5));
+ printf("\n");
+
+ if (drs_kbhit())
+ break;
+ }
+ // keep chip "warm"
+ b->StartDomino();
+ }
+
+ /* test0 */
+ else if (match(param[0], "t0")) {
+ b->Init();
+ b->SetDominoMode(1);
+ b->SetDominoActive(1);
+ b->SetReadoutMode(1);
+ b->SetFrequency(0.8, true);
+ b->EnableTrigger(1, 0);
+ b->SetTriggerLevel(1);
+ b->SetChannelConfig(0, 8, 4);
+
+ do {
+ b->StartDomino();
+ while (b->IsBusy())
+ if (drs_kbhit())
+ break;
+
+ b->TransferWaves();
+
+ if (b->GetBoardType() == 5) {
+ printf("%04d(0x%03X) - %3d\n", b->GetTriggerCell(0), b->GetTriggerCell(0),
+ b->GetStopWSR(0));
+ } else {
+ printf("%04d %04d %04d %04d - %3d %3d %3d\n",
+ b->GetTriggerCell(0),
+ b->GetTriggerCell(1),
+ b->GetTriggerCell(2),
+ b->GetTriggerCell(3),
+ b->GetTriggerCell(1)-b->GetTriggerCell(0),
+ b->GetTriggerCell(2)-b->GetTriggerCell(0),
+ b->GetTriggerCell(3)-b->GetTriggerCell(0));
+ }
+ Sleep(300);
+ } while (!drs_kbhit());
+
+ while (drs_kbhit())
+ getch();
+ }
+
+ /* test1 simple start/stop loop */
+ else if (match(param[0], "t1")) {
+ time_t t1, t2;
+
+ b->SetDebug(1);
+ b->Init();
+ b->SetFrequency(5, true);
+ b->SetDominoMode(1);
+ b->SetReadoutMode(0);
+ b->SetTranspMode(0);
+ b->SetDominoActive(1);
+ b->EnableAcal(1, 0.5);
+ b->EnableTcal(1);
+ time(&t1);
+ do {
+ time(&t2);
+ } while (t1 == t2);
+ i=0;
+ t1 = t2;
+ do {
+ b->StartDomino();
+ b->SoftTrigger();
+ b->TransferWaves();
+ i++;
+ time(&t2);
+ if (t2 > t1) {
+ printf("%d events/sec\n", i);
+ i = 0;
+ t1 = t2;
+ }
+ } while (!drs_kbhit());
+
+ while (drs_kbhit())
+ getch();
+ }
+
+ /* test2 readout from stop position */
+ else if (match(param[0], "t2")) {
+ short sw[1024];
+ double volt = 0.5;
+
+ b->Init();
+ b->SetNumberOfChannels(10);
+ b->SetChannelConfig(0, 9, 12);
+ b->SetFrequency(2, true);
+ b->EnableTcal(1);
+ b->SetReadoutMode(0);
+ b->SetDominoActive(0);
+ b->SetDominoMode(1);
+ b->SetCalibTiming(0, 0);
+ b->StartDomino();
+ b->EnableAcal(1, 0.5);
+ if (!b->GetResponseCalibration()->IsRead(0))
+ if (!b->GetResponseCalibration()->ReadCalibration(0))
+ printf("cannot read calibration\n");
+
+ do {
+ //volt += 0.25;
+ if (volt > 1)
+ volt = 0;
+ b->SoftTrigger();
+ while (b->IsBusy());
+ b->StartDomino();
+ b->EnableAcal(1, volt);
+ b->TransferWaves();
+
+ b->GetWave(0, 1, sw, 0, 0);
+ printf("%d ", sw[100]);
+ b->GetWave(0, 1, sw, 1, 0);
+ printf("%1.4lf\n", sw[100]/4096.0);
+ } while (!drs_kbhit());
+ while (drs_kbhit()) getch();
+ }
+
+ /* DAC Loop */
+ else if (match(param[0], "t3")) {
+ double volt;
+ do {
+ for (volt=2.5 ; volt > 0 ; volt -= 0.05) {
+
+ printf("%4.1lf - %5.3lf\n", b->GetTemperature(), volt);
+ b->SetDAC(0, volt);
+ b->SetDAC(1, 2.5-volt);
+ Sleep(100);
+ if (drs_kbhit())
+ break;
+ }
+ } while (!drs_kbhit());
+
+ while (drs_kbhit())
+ getch();
+ }
+
+ /* noise measurement */
+ else if (match(param[0], "t4")) {
+ int i, n;
+ short sw[1024];
+ double ofs[1024], sx, sxx, avg, stdev, enob;
+
+ b->Init();
+ b->SetFrequency(2, true);
+ b->EnableTcal(0);
+ b->SetDominoMode(1);
+ b->StartDomino();
+ b->EnableAcal(1, 0.5);
+ Sleep(100);
+ b->SoftTrigger();
+ while (b->IsBusy());
+ b->StartDomino();
+ Sleep(100);
+ memset(ofs, 0, sizeof(ofs));
+
+ for (i=0 ; i<10 ; i++) {
+ b->SoftTrigger();
+ while (b->IsBusy());
+ b->StartDomino();
+ b->TransferWaves(1);
+ b->GetWave(0, 0, sw, 0, 0);
+ sx = sxx = 0;
+ for (n=0 ; n<1024 ; n++) {
+ ofs[n] += sw[n];
+ }
+ }
+
+ for (n=0 ; n<1024 ; n++)
+ ofs[n] /= i;
+
+ for (i=0 ; i<10 ; i++) {
+ b->SoftTrigger();
+ while (b->IsBusy());
+ b->StartDomino();
+ b->TransferWaves(1);
+ b->GetWave(0, 0, sw, 0, 0);
+
+ sx = sxx = 0;
+ for (n=10 ; n<1014 ; n++) {
+ sx += (sw[n]-ofs[n])/4096.0;
+ sxx += (sw[n]-ofs[n])/4096.0*(sw[n]-ofs[n])/4096.0;
+ }
+
+ if (i>5)
+ Sleep(5000);
+
+ avg = sx / n;
+ stdev = sqrt((sxx-sx*sx/n)/(n-1));
+ enob = log(1/stdev)/log(2.);
+ printf("avg=%1.4lf sd=%1.4lf ENOB=%1.1lf\n", avg, stdev, enob);
+ };
+ }
+
+ /* exit/quit ---------- */
+ else if (match(param[0], "exit") || match(param[0], "quit"))
+ break;
+
+ else {
+ if (strchr(param[0], '\r'))
+ *strchr(param[0], '\r') = 0;
+ if (strchr(param[0], '\n'))
+ *strchr(param[0], '\n') = 0;
+ printf("Unknon command \"%s\"\n", param[0]);
+ }
+
+ } while (1);
+
+ delete drs;
+}
+
+/*------------------------------------------------------------------*/
+
+int main()
+{
+ printf("DRS command line tool, Revision %d\n", atoi(drscl_svn_revision+15));
+ printf("Type 'help' for a list of available commands.\n\n");
+
+ cmd_loop();
+ return 1;
+}
Index: instr/drsctrl/drscl.exe
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/instr/drsctrl/drscl.exe
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: instr/drsctrl/drscl.obj
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/instr/drsctrl/drscl.obj
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: instr/drsctrl/drsread.c
===================================================================
--- instr/drsctrl/drsread.c (nonexistent)
+++ instr/drsctrl/drsread.c (revision 195)
@@ -0,0 +1,283 @@
+#include <windows.h>
+#include <drsread.h>
+
+/* The two macros below are used as error return codes */
+/* in case the DLL does not load, or is missing one or */
+/* more functions, respectively. You must define them */
+/* to whatever values are meaningful for your DLL. */
+#define kFailedToLoadDLLError ???
+#define kCouldNotFindFunction ???
+
+static HINSTANCE DLLHandle;
+
+/* Declare the variables that hold the addresses of the function */
+/* pointers. */
+static void (__cdecl *DRSSetMask_Ptr)(int mask);
+static void (__cdecl *DRSSetTriggerType_Ptr)(int type);
+static void (__cdecl *DRSSetFrequency_Ptr)(int freq);
+static void (__cdecl *DRSSetRange_Ptr)(double range);
+static void (__cdecl *DRSSetTriggerChannel_Ptr)(int channel);
+static void (__cdecl *DRSSetTriggerDelay_Ptr)(double delay);
+static void (__cdecl *DRSSetTriggerLevel_Ptr)(double level);
+static void (__cdecl *DRSSetTriggerPolarity_Ptr)(int polarity);
+static float *(__cdecl *DRSGetTime_Ptr)(int ch);
+static float *(__cdecl *DRSGetWave_Ptr)(int ch);
+static int (__cdecl *DRSInit_Ptr)();
+static int (__cdecl *DRSRead_Ptr)(int drstimer);
+static int (__cdecl *DRSEnd_Ptr)();
+static int (__cdecl *DRSToBuffer_Ptr)(unsigned char *p, int m_evSerial);
+static int (__cdecl *DRSIsTimeout_Ptr)();
+static void (__cdecl *DRSSetTimeout_Ptr)();
+static void (__cdecl *DRSSigInt_Ptr)(int k);
+
+
+/* Load the DLL and get the addresses of the functions */
+static int LoadDLLIfNeeded(void)
+{
+ if (DLLHandle)
+ return 0;
+
+ DLLHandle = LoadLibrary("drsread.dll");
+ if (DLLHandle == NULL) {
+ return kFailedToLoadDLLError;
+ }
+
+ if (!(DRSSetMask_Ptr = (void*) GetProcAddress(DLLHandle, "DRSSetMask")))
+ goto FunctionNotFoundError;
+
+ if (!(DRSSetTriggerType_Ptr = (void*) GetProcAddress(DLLHandle,
+ "DRSSetTriggerType")))
+ goto FunctionNotFoundError;
+
+ if (!(DRSSetFrequency_Ptr = (void*) GetProcAddress(DLLHandle,
+ "DRSSetFrequency")))
+ goto FunctionNotFoundError;
+
+ if (!(DRSSetRange_Ptr = (void*) GetProcAddress(DLLHandle, "DRSSetRange")))
+ goto FunctionNotFoundError;
+
+ if (!(DRSSetTriggerChannel_Ptr = (void*) GetProcAddress(DLLHandle,
+ "DRSSetTriggerChannel")))
+ goto FunctionNotFoundError;
+
+ if (!(DRSSetTriggerDelay_Ptr = (void*) GetProcAddress(DLLHandle,
+ "DRSSetTriggerDelay")))
+ goto FunctionNotFoundError;
+
+ if (!(DRSSetTriggerLevel_Ptr = (void*) GetProcAddress(DLLHandle,
+ "DRSSetTriggerLevel")))
+ goto FunctionNotFoundError;
+
+ if (!(DRSSetTriggerPolarity_Ptr = (void*) GetProcAddress(DLLHandle,
+ "DRSSetTriggerPolarity")))
+ goto FunctionNotFoundError;
+
+ if (!(DRSGetTime_Ptr = (void*) GetProcAddress(DLLHandle, "DRSGetTime")))
+ goto FunctionNotFoundError;
+
+ if (!(DRSGetWave_Ptr = (void*) GetProcAddress(DLLHandle, "DRSGetWave")))
+ goto FunctionNotFoundError;
+
+ if (!(DRSInit_Ptr = (void*) GetProcAddress(DLLHandle, "DRSInit")))
+ goto FunctionNotFoundError;
+
+ if (!(DRSRead_Ptr = (void*) GetProcAddress(DLLHandle, "DRSRead")))
+ goto FunctionNotFoundError;
+
+ if (!(DRSEnd_Ptr = (void*) GetProcAddress(DLLHandle, "DRSEnd")))
+ goto FunctionNotFoundError;
+
+ if (!(DRSToBuffer_Ptr = (void*) GetProcAddress(DLLHandle, "DRSToBuffer")))
+ goto FunctionNotFoundError;
+
+ if (!(DRSIsTimeout_Ptr = (void*) GetProcAddress(DLLHandle, "DRSIsTimeout")))
+ goto FunctionNotFoundError;
+
+ if (!(DRSSetTimeout_Ptr = (void*) GetProcAddress(DLLHandle, "DRSSetTimeout")))
+ goto FunctionNotFoundError;
+
+ if (!(DRSSigInt_Ptr = (void*) GetProcAddress(DLLHandle, "DRSSigInt")))
+ goto FunctionNotFoundError;
+
+ return 0;
+
+FunctionNotFoundError:
+ FreeLibrary(DLLHandle);
+ DLLHandle = 0;
+ return kCouldNotFindFunction;
+}
+
+
+/* Glue Code for each of the DLL functions */
+
+
+
+void DRSSetMask(int mask)
+{
+ int dllLoadError;
+
+ if (dllLoadError = LoadDLLIfNeeded())
+ return;
+ (*DRSSetMask_Ptr)(mask);
+}
+
+
+void DRSSetTriggerType(int type)
+{
+ int dllLoadError;
+
+ if (dllLoadError = LoadDLLIfNeeded())
+ return;
+ (*DRSSetTriggerType_Ptr)(type);
+}
+
+
+void DRSSetFrequency(int freq)
+{
+ int dllLoadError;
+
+ if (dllLoadError = LoadDLLIfNeeded())
+ return;
+ (*DRSSetFrequency_Ptr)(freq);
+}
+
+
+void DRSSetRange(double range)
+{
+ int dllLoadError;
+
+ if (dllLoadError = LoadDLLIfNeeded())
+ return;
+ (*DRSSetRange_Ptr)(range);
+}
+
+
+void DRSSetTriggerChannel(int channel)
+{
+ int dllLoadError;
+
+ if (dllLoadError = LoadDLLIfNeeded())
+ return;
+ (*DRSSetTriggerChannel_Ptr)(channel);
+}
+
+
+void DRSSetTriggerDelay(double delay)
+{
+ int dllLoadError;
+
+ if (dllLoadError = LoadDLLIfNeeded())
+ return;
+ (*DRSSetTriggerDelay_Ptr)(delay);
+}
+
+
+void DRSSetTriggerLevel(double level)
+{
+ int dllLoadError;
+
+ if (dllLoadError = LoadDLLIfNeeded())
+ return;
+ (*DRSSetTriggerLevel_Ptr)(level);
+}
+
+
+void DRSSetTriggerPolarity(int polarity)
+{
+ int dllLoadError;
+
+ if (dllLoadError = LoadDLLIfNeeded())
+ return;
+ (*DRSSetTriggerPolarity_Ptr)(polarity);
+}
+
+
+float *DRSGetTime(int ch)
+{
+ int dllLoadError;
+
+ if (dllLoadError = LoadDLLIfNeeded())
+ return ???;
+ return (*DRSGetTime_Ptr)(ch);
+}
+
+
+float *DRSGetWave(int ch)
+{
+ int dllLoadError;
+
+ if (dllLoadError = LoadDLLIfNeeded())
+ return ???;
+ return (*DRSGetWave_Ptr)(ch);
+}
+
+
+int DRSInit()
+{
+ int dllLoadError;
+
+ if (dllLoadError = LoadDLLIfNeeded())
+ return dllLoadError;
+ return (*DRSInit_Ptr)();
+}
+
+
+int DRSRead(int drstimer)
+{
+ int dllLoadError;
+
+ if (dllLoadError = LoadDLLIfNeeded())
+ return dllLoadError;
+ return (*DRSRead_Ptr)(drstimer);
+}
+
+
+int DRSEnd()
+{
+ int dllLoadError;
+
+ if (dllLoadError = LoadDLLIfNeeded())
+ return dllLoadError;
+ return (*DRSEnd_Ptr)();
+}
+
+
+int DRSToBuffer(unsigned char *p, int m_evSerial)
+{
+ int dllLoadError;
+
+ if (dllLoadError = LoadDLLIfNeeded())
+ return dllLoadError;
+ return (*DRSToBuffer_Ptr)(p, m_evSerial);
+}
+
+
+int DRSIsTimeout()
+{
+ int dllLoadError;
+
+ if (dllLoadError = LoadDLLIfNeeded())
+ return dllLoadError;
+ return (*DRSIsTimeout_Ptr)();
+}
+
+
+void DRSSetTimeout()
+{
+ int dllLoadError;
+
+ if (dllLoadError = LoadDLLIfNeeded())
+ return;
+ (*DRSSetTimeout_Ptr)();
+}
+
+
+void DRSSigInt(int k)
+{
+ int dllLoadError;
+
+ if (dllLoadError = LoadDLLIfNeeded())
+ return;
+ (*DRSSigInt_Ptr)(k);
+}
+
Index: instr/drsctrl/drsread.cpp
===================================================================
--- instr/drsctrl/drsread.cpp (nonexistent)
+++ instr/drsctrl/drsread.cpp (revision 195)
@@ -0,0 +1,620 @@
+/********************************************************************\
+
+ Name: drsread.cpp
+ Created by: Rok Pestotnik
+
+ Contents: Simple example application to read out a DRS4
+ evaluation board and save into the data file
+ Interface dll for LabWindows CVI
+
+\********************************************************************/
+#ifdef DLLMAIN
+#define DLLEXPORT __declspec(dllexport)
+#else
+#define DLLEXPORT
+#endif
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <math.h>
+#include <time.h>
+#include <signal.h>
+
+#include <TFile.h>
+#include <TH2F.h>
+#include <TCanvas.h>
+//#include <TApplication.h>
+
+#ifdef _MSC_VER
+
+#include "gettimeofday.h"
+#include "timer.h"
+
+#define DIR_SEPARATOR '\\'
+
+#elif defined(OS_LINUX) || defined(OS_DARWIN)
+
+#define O_BINARY 0
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#define DIR_SEPARATOR '/'
+#endif
+
+#include "DRS.h"
+#include "drsread.h"
+
+
+/*------------------------------------------------------------------*/
+class drssettings {
+ static drssettings *s_instance;
+public:
+ drssettings(){
+ mask = 0xF;
+ range = 0;
+ trigger_type = 1;
+ sampling_frequency = 5;
+ trigger_delay = 0;
+ trigger_channel=0;
+ trigger_polarity=false;
+ trigger_level=0.05;
+
+ };
+ ~drssettings(){};
+ static drssettings *instance()
+ {
+ if (!s_instance)
+ s_instance = new drssettings;
+ return s_instance;
+ };
+
+
+ unsigned char mask;
+ double range;
+ int trigger_type; // 0 software, 1 fast hardware, 2 slow hardware
+ int trigger_channel;
+ int sampling_frequency;
+ double trigger_delay;
+ double trigger_level;
+ bool trigger_polarity;
+};
+drssettings *drssettings::s_instance = 0;
+drssettings *DRSParameters;
+DLLEXPORT void DRSSetMask(int mask){ drssettings::instance()->mask;};
+DLLEXPORT void DRSSetTriggerType(int type){ drssettings::instance()->trigger_type = type;};
+DLLEXPORT void DRSSetFrequency(int freq){ drssettings::instance()->sampling_frequency = freq;};
+DLLEXPORT void DRSSetRange(double range){ drssettings::instance()->range = range;};
+DLLEXPORT void DRSSetTriggerChannel(int channel){ drssettings::instance()->trigger_channel = channel;};
+DLLEXPORT void DRSSetTriggerDelay(double delay){ drssettings::instance()->trigger_delay = delay;};
+DLLEXPORT void DRSSetTriggerLevel(double level){ drssettings::instance()->trigger_level = level;};
+DLLEXPORT void DRSSetTriggerPolarity(int polarity){ drssettings::instance()->trigger_polarity = (polarity==1);};
+
+
+static int DRSTimeout;
+
+DLLEXPORT int DRSIsTimeout()
+{
+ return DRSTimeout;
+}
+
+DLLEXPORT void DRSSetTimeout ( void )
+{
+ DRSTimeout=1;
+ printf("->>> Timer Out !!!\n");
+}
+
+static DRS *drs=NULL;
+
+DLLEXPORT int DRSInit()
+{
+
+ DRSBoard *b;
+ /* do drsinitial scan */
+ drs = new DRS();
+ if (!drs) return -1;
+ DRSParameters = drssettings::instance();
+
+ /* show any found board(s) */
+ for (int i=0 ; i<drs->GetNumberOfBoards() ; i++) {
+ b = drs->GetBoard(i);
+ printf("Found DRS4 evaluation board, serial #%d, firmware revision %d\n",
+ b->GetBoardSerialNumber(), b->GetFirmwareVersion());
+ }
+
+ /* exit if no board found */
+ int nBoards = drs->GetNumberOfBoards();
+ if (nBoards == 0) {
+ printf("No DRS4 evaluation board found\n");
+ return -2;
+ }
+
+ /* continue working with first board only */
+ b = drs->GetBoard(0);
+
+ /* drsinitialize board */
+ b->Init();
+
+ /* set sampling frequency default 5 */
+ b->SetFrequency(DRSParameters->sampling_frequency, true);
+
+ /* enable transparent mode needed for analog trigger */
+ b->SetTranspMode(1);
+
+ /* set input range to -0.5V ... +0.5V -> range=0 */
+ b->SetInputRange(DRSParameters->range);
+
+ /* use following line to set range to 0..1V */
+ //b->SetInputRange(0.5);
+
+ /* use following line to turn on the internal 100 MHz clock connected to all channels */
+ //b->EnableTcal(1);
+
+ /* kaj je to ....
+ // Set domino mode
+ // mode == 0: single sweep
+ // mode == 1: run continously -- default
+ b->SetDominoMode(1);
+ // Set domino activity
+ // mode == 0: stop during readout
+ // mode == 1: keep domino wave running -- default
+ //
+ b->SetDominoActive(1);
+
+ // Set readout mode
+ // mode == 0: start from first bin -- default
+ // mode == 1: start from domino stop
+ //
+ b->SetReadoutMode(1);
+ */
+
+ /* use following lines to enable hardware trigger on CH1 at 50 mV positive edge */
+ printf("Board Type:%d\n",b->GetBoardType() );
+ if (b->GetBoardType() >= 8) { // Evaluaiton Board V4&5
+
+ b->EnableTrigger(DRSParameters->trigger_type, 0); // enable hardware trigger - 1 fast trigger, 2 slow trigger, 0 disable hw trigger
+ b->SetTriggerSource(1<<DRSParameters->trigger_channel); // set CH1 as source // simple or of single channel
+ } else if (b->GetBoardType() == 7) { // Evaluation Board V3
+ b->EnableTrigger(0, 1); // lemo off, analog trigger on
+ b->SetTriggerSource(0); // use CH1 as source
+ }
+ b->SetTriggerLevel(DRSParameters->trigger_level); // 0.05 V
+ b->SetTriggerPolarity(DRSParameters->trigger_polarity); // positive edge
+
+ /* use following lines to set individual trigger elvels */
+ //b->SetIndividualTriggerLevel(1, 0.1);
+ //b->SetIndividualTriggerLevel(2, 0.2);
+ //b->SetIndividualTriggerLevel(3, 0.3);
+ //b->SetIndividualTriggerLevel(4, 0.4);
+ //b->SetTriggerSource(15);
+
+ b->SetTriggerDelayNs( DRSParameters->trigger_delay); // zero ns trigger delay
+
+ /* use following lines to enable the external trigger */
+ //if (b->GetBoardType() == 8) { // Evaluaiton Board V4
+ // b->EnableTrigger(1, 0); // enable hardware trigger
+ // b->SetTriggerSource(1<<4); // set external trigger as source
+ //} else { // Evaluation Board V3
+ // b->EnableTrigger(1, 0); // lemo on, analog trigger off
+ // }
+
+ return 0;
+
+
+}
+
+static float DRSTimeArray[8][1024];
+static float DRSWaveArray[8][1024];
+
+DLLEXPORT float * DRSGetTime(int ch){ return DRSTimeArray[ch];}
+DLLEXPORT float * DRSGetWave(int ch){ return DRSWaveArray[ch];}
+
+DLLEXPORT int DRSRead( int DRStimer)
+{
+
+ DRSBoard *b = drs->GetBoard(0);
+
+
+
+ /* wait for trigger */
+
+
+ int tout=1000; /* timeout in mili seconds */
+ DRSTimeout=0;
+
+ if (DRStimer) start_timer(tout, &DRSSetTimeout);
+
+ /* start board (activate domino wave) */
+ b->StartDomino();
+
+ if (!DRSParameters->trigger_type) b->SoftTrigger();
+
+ while (b->IsBusy()){
+
+ if (DRSTimeout) {
+ printf("Waiting for Trigger.. at line %d\n", __LINE__);
+
+ if (DRStimer) stop_timer();
+
+ return -1;
+ }
+ };
+
+
+ if (DRStimer) stop_timer();
+
+
+
+ /* read all waveforms */
+ b->TransferWaves(0, 8);
+
+
+ for (int k=0;k<4;k++){
+ if (! (DRSParameters->mask & ( 0x1<<k )) ) continue;
+ /* Note: On the evaluation board input #1 is connected to channel 0 and 1 of
+ the DRS chip, input #2 is connected to channel 2 and 3 and so on. So to
+ get the input #2 we have to read DRS channel #2, not #1. */
+
+ /* read time (X) array of k-th channel in ns and waveform (Y) array of k-th channel in mV */
+ b->GetTime(0, 2*k, b->GetTriggerCell(DRSParameters->trigger_channel), DRSTimeArray[k]);
+ b->GetWave(0, 2*k, DRSWaveArray[k]);
+
+
+ }
+
+ return 0;
+}
+
+DLLEXPORT int DRSEnd(){
+
+ /* delete DRS object -> close USB connection */
+ if (drs) delete drs;
+ drs = NULL;
+ return 0;
+}
+
+
+
+DLLEXPORT int DRSToBuffer( unsigned char *p, int m_evSerial )
+{
+
+ unsigned short d;
+ float t;
+ unsigned char *p0 = p;
+
+ int m_nBoards = drs->GetNumberOfBoards();
+ int m_waveDepth = 1024 ;// 2048
+ int m_inputRange = drs->GetBoard(0)->GetInputRange();
+ time_t rawtime;
+ time ( &rawtime );
+ struct tm m_evTimestamp;
+ m_evTimestamp = *(localtime ( &rawtime ));
+ struct timeval mtime;
+ gettimeofday(&mtime, NULL);
+
+ if (m_evSerial == 0) {
+ // time calibration header
+ memcpy(p, "TIME", 4);
+ p += 4;
+
+ for (int b=0 ; b<m_nBoards ; b++) {
+ // store board serial number
+ sprintf((char *)p, "B#");
+ p += 2;
+ *(unsigned short *)p = drs->GetBoard(b)->GetBoardSerialNumber();
+ p += sizeof(unsigned short);
+
+ for (int i=0 ; i<4 ; i++) {
+ if (DRSParameters->mask & (0x1<<i)) {
+ sprintf((char *)p, "C%03d", i+1);
+ p += 4;
+ float tcal[2048];
+ drs->GetBoard(b)->GetTimeCalibration(0, i*2, 0, tcal, 0);
+ for (int j=0 ; j<m_waveDepth ; j++) {
+ // save binary time as 32-bit float value
+ if (m_waveDepth == 2048) {
+ t = (tcal[j]+tcal[j+1])/2;
+ j++;
+ } else
+ t = tcal[j];
+ *(float *)p = t;
+ p += sizeof(float);
+ }
+ }
+ }
+ }
+ }
+
+
+
+ memcpy(p, "EHDR", 4);
+ p += 4;
+ *(int *)p = m_evSerial;
+ p += sizeof(int);
+ *(unsigned short *)p = m_evTimestamp.tm_year;
+ p += sizeof(unsigned short);
+ *(unsigned short *)p = m_evTimestamp.tm_mon;
+ p += sizeof(unsigned short);
+ *(unsigned short *)p = m_evTimestamp.tm_mday;
+ p += sizeof(unsigned short);
+ *(unsigned short *)p = m_evTimestamp.tm_hour;
+ p += sizeof(unsigned short);
+ *(unsigned short *)p = m_evTimestamp.tm_min;
+ p += sizeof(unsigned short);
+ *(unsigned short *)p = m_evTimestamp.tm_sec;
+ p += sizeof(unsigned short);
+ *(unsigned short *)p = mtime.tv_usec/1000;
+ p += sizeof(unsigned short);
+ *(unsigned short *)p = (unsigned short)(m_inputRange * 1000); // range
+ p += sizeof(unsigned short);
+
+ int b=0; // only for board 0
+
+ // store board serial number
+ sprintf((char *)p, "B#");
+ p += 2;
+ *(unsigned short *)p = drs->GetBoard(b)->GetBoardSerialNumber();
+ p += sizeof(unsigned short);
+
+ // store trigger cell
+ sprintf((char *)p, "T#");
+ p += 2;
+ *(unsigned short *)p = drs->GetBoard(b)->GetTriggerCell(DRSParameters->trigger_channel);
+ p += sizeof(unsigned short);
+
+ for (int i=0 ; i<4 ; i++) {
+ if (DRSParameters->mask & (0x1<<i)) {
+ sprintf((char *)p, "C%03d", i+1);
+ p += 4;
+ for (int j=0 ; j<m_waveDepth ; j++) {
+ // save binary date as 16-bit value:
+ // 0 = -0.5V, 65535 = +0.5V for range 0
+ // 0 = -0.05V, 65535 = +0.95V for range 0.45
+ if (m_waveDepth == 2048) {
+ // in cascaded mode, save 1024 values as averages of the 2048 values
+ d = (unsigned short)(((DRSWaveArray[i][j]+DRSWaveArray[i][j+1])/2000.0 - m_inputRange + 0.5) * 65535);
+ *(unsigned short *)p = d;
+ p += sizeof(unsigned short);
+ j++;
+ } else {
+ d = (unsigned short)((DRSWaveArray[i][j]/1000.0 - m_inputRange + 0.5) * 65535);
+ *(unsigned short *)p = d;
+ p += sizeof(unsigned short);
+ }
+ }
+ }
+ }
+
+ return (p-p0); // return number of bytes
+}
+
+
+
+#ifdef MAIN
+
+
+
+#include "XGetopt.h"
+#include "getopt.h"
+
+TH2F *h[4];
+
+typedef struct {
+ char recid[4];
+ unsigned int posx, posy, posz;
+ unsigned int iposx, iposy, iposz;
+} POSREC;
+
+
+int help() {
+ printf ("*********************************************************************************:\n");
+ printf ("Usage: Read of the DRS4 PSI board and dump of the waveforms in the file:\n\n");
+ printf ("Arguments: \n");
+ printf ("-v verbosity \n");
+ printf ("-a output rootfile \n");
+ printf ("-o output filename \n");
+ printf ("-r output root filename \n");
+ printf ("-n number of events\n");
+ printf ("-m channel bit mask\n");
+ printf ("-h trigger type (0 software, 1 fast hardware, 2 slow hardware)\n");
+ printf ("-d trigger delay in ns\n");
+ printf ("-f sampling frequency\n");
+ printf ("-t trigger channel\n");
+ printf ("-l trigger level\n");
+ printf ("-p trigger polarity (0 positive\n");
+ printf ("*********************************************************************************:\n");
+ printf ("Examples:\n\n");
+
+ return 0;
+}
+
+
+
+char filename[0xFF]="";
+char rootfile[0xFF]="";
+int neve = 0;
+int verbose = 0;
+
+void Init(int argc, char **argv){
+ DRSParameters = drssettings::instance();
+ char c;
+
+ extern char *optarg;
+ extern int optind;
+ extern int optopt;
+ while ((c = getopt (argc, argv, "a:o:v:m:n:f:d:r:h:t:p:l:")) != -1){
+
+ switch (c)
+ {
+
+ case 'a':
+ sprintf(rootfile,"%s", optarg );
+ break; // root output
+
+ case 'o':
+ sprintf(filename,"%s", optarg );
+ break; // output
+
+ case 'v':
+ verbose = atoi(optarg);
+ break; // verbosity
+ case 'm':{
+ unsigned long ul = strtoul (optarg,NULL,0);
+ DRSSetMask( (unsigned char)( ul & 0xF ) ) ;
+ break;
+ } // channel mask
+ case 'n':
+ neve = atoi (optarg);
+ break; // number of events or number of scan points
+
+ case 'f':
+ DRSSetFrequency( atoi (optarg) );
+ break; // sampling frequency
+
+ case 'd':
+ DRSSetTriggerDelay( atof (optarg) );
+ break; // trigger delay
+ case 'p':
+ DRSSetTriggerPolarity( atoi (optarg));
+ break; // trigger polarity
+ case 'l':
+ DRSSetTriggerLevel(atoi (optarg));
+ break; // trigger level
+
+
+ case 'r':
+ DRSSetRange ( atof (optarg) );
+ break; // range
+ case 'h':
+ DRSSetTriggerType( atoi (optarg) );
+ break; // send sotware trigger before reading out the dat
+ case 't':
+ DRSSetTriggerChannel( atoi(optarg) );
+ break; // trigger channel
+
+
+ case '?':
+ if (optopt == 'c')
+ fprintf (stderr, "Option -%c requires an argument.\n", optopt);
+ else if (isprint (optopt))
+ fprintf (stderr, "Unknown option `-%c'.\n", optopt);
+ else
+ fprintf (stderr,
+ "Unknown option character `\\x%x'.\n",
+ optopt);
+ abort ();
+ default:
+ abort ();
+ }
+ }
+ //for (int i=optind; i<argc; i++) data = strtoul (argv[i],NULL,0);
+
+}
+
+int ctrl_c=0;
+DLLEXPORT void DRSSigInt ( int )
+{
+ ctrl_c = 1;
+ printf("->>> CTRL+c !!!\n");
+}
+
+//#ifdef __CINT__
+int main(int argc, char **argv){
+//#else
+//int drsread(int argc, char **argv){
+//#endif
+
+ if (signal (SIGINT, DRSSigInt) == SIG_ERR) {
+ perror ("sigignore");
+ }
+
+
+Init(argc, argv);
+if (argc==1) { help(); return 0; }
+
+FILE *fp=NULL;
+if (strlen(filename)>0) {
+ if (verbose) printf("Data in the file:%s\n", filename);
+ fp=fopen(filename,"wb");
+}
+
+TFile *rfile= NULL;
+if (strlen(rootfile)>0) {
+ if (verbose) printf("Data in the file:%s\n", rootfile);
+ rfile = new TFile(rootfile,"RECREATE");
+}
+
+
+TCanvas *c = new TCanvas(); c->Divide(2,2);
+c->Draw();
+for (int i=0;i<4;i++){
+ if (! (DRSParameters->mask & ( 0x1<<i )) ) continue;
+ char name[0xff];
+ sprintf(name,"h%d",i);
+ h[i]=new TH2F(name,name,1024,0,204,1024,-0.6+DRSParameters->range,0.6+DRSParameters->range);
+ c->cd(i+1); h[i]->Draw("colz");
+
+}
+
+
+
+//---------------------------------------
+static unsigned char *buffer;
+static int buffer_size = 0;
+const int nBoards=1;
+const int waveDepth=1024;
+if (buffer_size == 0) {
+ buffer_size = 4 + nBoards * (4 + 4*(4+waveDepth*4));
+ buffer_size += 24 + nBoards * (8 + 4*(4+waveDepth*2));
+ buffer = (unsigned char *)malloc(buffer_size);
+}
+
+time_t t,told, tstart;
+if (!DRSInit()){
+ time(&tstart);
+ told=tstart;
+ int i=0;
+ for (i=0; i<neve; i++) {
+ int nb = (DRSRead(1) == 0 && fp ) ? DRSToBuffer( buffer , i ) : 0;
+
+ if (DRSTimeout) i--;
+ if (ctrl_c) break;
+ time(&t);
+ if (t!=told ) {
+ printf("%d events in %2.2f min (%d s) %s",i+1, (double)(t-tstart)/60.,int(t-tstart), ctime(&t));
+ c->Modified(); c->Update();
+ }
+ told=t;
+// Save data
+ if (nb>0 && fp) fwrite(buffer, 1,nb ,fp);
+// Plot Data
+ for (int k=0;k<4;k++){
+ if (! (DRSParameters->mask & ( 0x1<<k )) ) continue;
+ float *t=DRSGetTime(k);
+ float *x=DRSGetWave(k);
+ for (int i=0 ; i<1024 ; i++) {
+ if (verbose) printf("[%d] %d. x= %3.2f y=%3.2f\n", k, i, t[i], x[i] );
+ h[k]->Fill( t[i], x[i]*1e-3);
+ }
+ }
+ }
+ time(&t);
+ printf("%d events in %2.2f min (%d s) %s",i+1, (double)(t-tstart)/60.,int(t-tstart), ctime(&t));
+
+ DRSEnd();
+}
+//---------------------------------------
+if (rfile !=NULL) rfile->Write();
+if (fp) fclose(fp);
+if (c) c->SaveAs("drsread.pdf");
+// TApplication* theApp = new TApplication("App", NULL, NULL);
+// theApp->Run();
+
+
+
+}
+
+#endif
\ No newline at end of file
Index: instr/drsctrl/drsread.dll
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/instr/drsctrl/drsread.dll
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: instr/drsctrl/drsread.exe
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/instr/drsctrl/drsread.exe
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: instr/drsctrl/drsread.exp
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/instr/drsctrl/drsread.exp
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: instr/drsctrl/drsread.h
===================================================================
--- instr/drsctrl/drsread.h (nonexistent)
+++ instr/drsctrl/drsread.h (revision 195)
@@ -0,0 +1,31 @@
+#ifndef _DRSREAD_H_
+#define _DRSREAD_H_
+#ifdef DLLMAIN
+#define DLLEXPORT extern "C" __declspec(dllexport)
+#else
+//#define DLLEXPORT __declspec(dllimport)
+#define DLLEXPORT
+#endif
+
+DLLEXPORT void DRSSetMask(int mask);
+DLLEXPORT void DRSSetTriggerType(int type);
+DLLEXPORT void DRSSetFrequency(int freq);
+DLLEXPORT void DRSSetRange(double range);
+DLLEXPORT void DRSSetTriggerChannel(int channel);
+DLLEXPORT void DRSSetTriggerDelay(double delay);
+DLLEXPORT void DRSSetTriggerLevel(double level);
+DLLEXPORT void DRSSetTriggerPolarity(int polarity);
+
+DLLEXPORT float * DRSGetTime(int ch);
+DLLEXPORT float * DRSGetWave(int ch);
+
+DLLEXPORT int DRSInit();
+DLLEXPORT int DRSRead( int drstimer);
+DLLEXPORT int DRSEnd();
+DLLEXPORT int DRSToBuffer( unsigned char *p, int m_evSerial );
+
+DLLEXPORT int DRSIsTimeout();
+DLLEXPORT void DRSSetTimeout ( void );
+
+DLLEXPORT void DRSSigInt ( int k );
+#endif
Index: instr/drsctrl/drsread.lib
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/instr/drsctrl/drsread.lib
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: instr/drsctrl/drsread.obj
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/instr/drsctrl/drsread.obj
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: instr/drsctrl/getopt.h
===================================================================
--- instr/drsctrl/getopt.h (nonexistent)
+++ instr/drsctrl/getopt.h (revision 195)
@@ -0,0 +1,74 @@
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $
+ */
+
+#ifndef _GETOPT_H_
+#define _GETOPT_H_
+
+/*
+ * Gnu like getopt_long() and BSD4.4 getsubopt()/optreset extensions
+ */
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct option {
+ /* name of long option */
+ const char *name;
+ /*
+ * one of no_argument, required_argument, and optional_argument:
+ * whether option takes an argument
+ */
+ int has_arg;
+ /* if not NULL, set *flag to val when option found */
+ int *flag;
+ /* if flag not NULL, value to set *flag to; else return value */
+ int val;
+};
+
+int getopt_long(int, char * const *, const char *,
+ const struct option *, int *);
+
+extern int optreset;
+extern char *optarg;
+extern int opterr;
+extern int optind;
+extern int optopt;
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* !_GETOPT_H_ */
Index: instr/drsctrl/getopt_long.c
===================================================================
--- instr/drsctrl/getopt_long.c (nonexistent)
+++ instr/drsctrl/getopt_long.c (revision 195)
@@ -0,0 +1,466 @@
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $NetBSD: getopt_long.c,v 1.3 2008/04/29 05:46:09 martin Exp $
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "getopt.h"
+
+#ifndef _DIAGASSERT
+#define _DIAGASSERT(e)
+#endif
+
+int opterr = 1; /* if error message should be printed */
+int optind = 1; /* index into parent argv vector */
+int optopt = '?'; /* character checked for validity */
+int optreset; /* reset getopt */
+char *optarg; /* argument associated with option */
+
+
+#define IGNORE_FIRST (*options == '-' || *options == '+')
+#define PRINT_ERROR ((opterr) && ((*options != ':') \
+ || (IGNORE_FIRST && options[1] != ':')))
+#define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL)
+#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST)
+/* XXX: GNU ignores PC if *options == '-' */
+#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-')
+
+/* return values */
+#define BADCH (int)'?'
+#define BADARG (int)':'
+#define INORDER (int)1
+
+#define EMSG ""
+
+static int getopt_internal(int, char * const *, const char *);
+static int gcd(int, int);
+static void permute_args(int, int, int, char * const *);
+static void xwarnx(const char *, ...);
+
+static char *place = EMSG; /* option letter processing */
+
+/* XXX: set optreset to 1 rather than these two */
+static int nonopt_start = -1; /* first non option argument (for permute) */
+static int nonopt_end = -1; /* first option after non options (for permute) */
+
+/* Error messages */
+static const char recargchar[] = "option requires an argument -- %c";
+static const char recargstring[] = "option requires an argument -- %s";
+static const char ambig[] = "ambiguous option -- %.*s";
+static const char noarg[] = "option doesn't take an argument -- %.*s";
+static const char illoptchar[] = "illegal option -- %c";
+static const char illoptstring[] = "illegal option -- %s";
+
+static const char *progname;
+
+
+/* Replacement for warnx(3) for systems without it. */
+static void xwarnx(const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ if (progname)
+ (void) fprintf(stderr, "%s: ", progname);
+ if (fmt)
+ (void) vfprintf(stderr, fmt, ap);
+ (void) fprintf(stderr, "\n");
+ va_end(ap);
+}
+
+/*
+ * Compute the greatest common divisor of a and b.
+ */
+static int
+gcd(int a, int b)
+{
+ int c;
+
+ c = a % b;
+ while (c != 0) {
+ a = b;
+ b = c;
+ c = a % b;
+ }
+
+ return b;
+}
+
+/*
+ * Exchange the block from nonopt_start to nonopt_end with the block
+ * from nonopt_end to opt_end (keeping the same order of arguments
+ * in each block).
+ */
+static void
+permute_args(int nonopt_start, int nonopt_end, int opt_end, char * const *nargv)
+{
+ int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
+ char *swap;
+
+ /*
+ * compute lengths of blocks and number and size of cycles
+ */
+ nnonopts = nonopt_end - nonopt_start;
+ nopts = opt_end - nonopt_end;
+ ncycle = gcd(nnonopts, nopts);
+ cyclelen = (opt_end - nonopt_start) / ncycle;
+
+ for (i = 0; i < ncycle; i++) {
+ cstart = nonopt_end+i;
+ pos = cstart;
+ for (j = 0; j < cyclelen; j++) {
+ if (pos >= nonopt_end)
+ pos -= nnonopts;
+ else
+ pos += nopts;
+ swap = nargv[pos];
+ /* LINTED const cast */
+ ((char **) nargv)[pos] = nargv[cstart];
+ /* LINTED const cast */
+ ((char **)nargv)[cstart] = swap;
+ }
+ }
+}
+
+/*
+ * getopt_internal --
+ * Parse argc/argv argument vector. Called by user level routines.
+ * Returns -2 if -- is found (can be long option or end of options marker).
+ */
+static int
+getopt_internal(int nargc, char * const *nargv, const char *options)
+{
+ char *oli; /* option letter list index */
+ int optchar;
+
+ _DIAGASSERT(nargv != NULL);
+ _DIAGASSERT(options != NULL);
+
+ optarg = NULL;
+
+ /*
+ * XXX Some programs (like rsyncd) expect to be able to
+ * XXX re-initialize optind to 0 and have getopt_long(3)
+ * XXX properly function again. Work around this braindamage.
+ */
+ if (optind == 0)
+ optind = 1;
+
+ if (optreset)
+ nonopt_start = nonopt_end = -1;
+start:
+ if (optreset || !*place) { /* update scanning pointer */
+ optreset = 0;
+ if (optind >= nargc) { /* end of argument vector */
+ place = EMSG;
+ if (nonopt_end != -1) {
+ /* do permutation, if we have to */
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ optind -= nonopt_end - nonopt_start;
+ }
+ else if (nonopt_start != -1) {
+ /*
+ * If we skipped non-options, set optind
+ * to the first of them.
+ */
+ optind = nonopt_start;
+ }
+ nonopt_start = nonopt_end = -1;
+ return -1;
+ }
+ if (*(place = nargv[optind]) != '-') { /* found non-option */
+ place = EMSG;
+ if (IN_ORDER) {
+ /*
+ * GNU extension:
+ * return non-option as argument to option 1
+ */
+ optarg = nargv[optind++];
+ return INORDER;
+ }
+ if (!PERMUTE) {
+ /*
+ * if no permutation wanted, stop parsing
+ * at first non-option
+ */
+ return -1;
+ }
+ /* do permutation */
+ if (nonopt_start == -1)
+ nonopt_start = optind;
+ else if (nonopt_end != -1) {
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ nonopt_start = optind -
+ (nonopt_end - nonopt_start);
+ nonopt_end = -1;
+ }
+ optind++;
+ /* process next argument */
+ goto start;
+ }
+ if (nonopt_start != -1 && nonopt_end == -1)
+ nonopt_end = optind;
+ if (place[1] && *++place == '-') { /* found "--" */
+ place++;
+ return -2;
+ }
+ }
+ if ((optchar = (int)*place++) == (int)':' ||
+ (oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) {
+ /* option letter unknown or ':' */
+ if (!*place)
+ ++optind;
+ if (PRINT_ERROR)
+ xwarnx(illoptchar, optchar);
+ optopt = optchar;
+ return BADCH;
+ }
+ if (optchar == 'W' && oli[1] == ';') { /* -W long-option */
+ /* XXX: what if no long options provided (called by getopt)? */
+ if (*place)
+ return -2;
+
+ if (++optind >= nargc) { /* no arg */
+ place = EMSG;
+ if (PRINT_ERROR)
+ xwarnx(recargchar, optchar);
+ optopt = optchar;
+ /* XXX: GNU returns '?' if options[0] != ':' */
+ return BADARG;
+ } else /* white space */
+ place = nargv[optind];
+ /*
+ * Handle -W arg the same as --arg (which causes getopt to
+ * stop parsing).
+ */
+ return -2;
+ }
+ if (*++oli != ':') { /* doesn't take argument */
+ if (!*place)
+ ++optind;
+ } else { /* takes (optional) argument */
+ optarg = NULL;
+ if (*place) /* no white space */
+ optarg = place;
+ /* XXX: disable test for :: if PC? (GNU doesn't) */
+ else if (oli[1] != ':') { /* arg not optional */
+ if (++optind >= nargc) { /* no arg */
+ place = EMSG;
+ if (PRINT_ERROR)
+ xwarnx(recargchar, optchar);
+ optopt = optchar;
+ /* XXX: GNU returns '?' if options[0] != ':' */
+ return BADARG;
+ } else
+ optarg = nargv[optind];
+ }
+ place = EMSG;
+ ++optind;
+ }
+ /* dump back option letter */
+ return optchar;
+}
+
+/*
+ * getopt --
+ * Parse argc/argv argument vector.
+ *
+ * [eventually this will replace the real getopt]
+ */
+int
+getopt(int nargc, char * const *nargv, const char *options)
+{
+ int retval;
+
+ progname = nargv[0];
+
+ if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
+ ++optind;
+ /*
+ * We found an option (--), so if we skipped non-options,
+ * we have to permute.
+ */
+ if (nonopt_end != -1) {
+ permute_args(nonopt_start, nonopt_end, optind,
+ nargv);
+ optind -= nonopt_end - nonopt_start;
+ }
+ nonopt_start = nonopt_end = -1;
+ retval = -1;
+ }
+ return retval;
+}
+
+/*
+ * getopt_long --
+ * Parse argc/argv argument vector.
+ */
+int
+getopt_long(int nargc,
+ char * const *nargv,
+ const char *options,
+ const struct option *long_options,
+ int *idx)
+{
+ int retval;
+
+ _DIAGASSERT(nargv != NULL);
+ _DIAGASSERT(options != NULL);
+ _DIAGASSERT(long_options != NULL);
+ /* idx may be NULL */
+
+ progname = nargv[0];
+
+ if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
+ char *current_argv, *has_equal;
+ size_t current_argv_len;
+ int i, match;
+
+ current_argv = place;
+ match = -1;
+
+ optind++;
+ place = EMSG;
+
+ if (*current_argv == '\0') { /* found "--" */
+ /*
+ * We found an option (--), so if we skipped
+ * non-options, we have to permute.
+ */
+ if (nonopt_end != -1) {
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ optind -= nonopt_end - nonopt_start;
+ }
+ nonopt_start = nonopt_end = -1;
+ return -1;
+ }
+ if ((has_equal = strchr(current_argv, '=')) != NULL) {
+ /* argument found (--option=arg) */
+ current_argv_len = has_equal - current_argv;
+ has_equal++;
+ } else
+ current_argv_len = strlen(current_argv);
+
+ for (i = 0; long_options[i].name; i++) {
+ /* find matching long option */
+ if (strncmp(current_argv, long_options[i].name,
+ current_argv_len))
+ continue;
+
+ if (strlen(long_options[i].name) ==
+ (unsigned)current_argv_len) {
+ /* exact match */
+ match = i;
+ break;
+ }
+ if (match == -1) /* partial match */
+ match = i;
+ else {
+ /* ambiguous abbreviation */
+ if (PRINT_ERROR)
+ xwarnx(ambig, (int)current_argv_len,
+ current_argv);
+ optopt = 0;
+ return BADCH;
+ }
+ }
+ if (match != -1) { /* option found */
+ if (long_options[match].has_arg == no_argument
+ && has_equal) {
+ if (PRINT_ERROR)
+ xwarnx(noarg, (int)current_argv_len,
+ current_argv);
+ /*
+ * XXX: GNU sets optopt to val regardless of
+ * flag
+ */
+ if (long_options[match].flag == NULL)
+ optopt = long_options[match].val;
+ else
+ optopt = 0;
+ /* XXX: GNU returns '?' if options[0] != ':' */
+ return BADARG;
+ }
+ if (long_options[match].has_arg == required_argument ||
+ long_options[match].has_arg == optional_argument) {
+ if (has_equal)
+ optarg = has_equal;
+ else if (long_options[match].has_arg ==
+ required_argument) {
+ /*
+ * optional argument doesn't use
+ * next nargv
+ */
+ optarg = nargv[optind++];
+ }
+ }
+ if ((long_options[match].has_arg == required_argument)
+ && (optarg == NULL)) {
+ /*
+ * Missing argument; leading ':'
+ * indicates no error should be generated
+ */
+ if (PRINT_ERROR)
+ xwarnx(recargstring, current_argv);
+ /*
+ * XXX: GNU sets optopt to val regardless
+ * of flag
+ */
+ if (long_options[match].flag == NULL)
+ optopt = long_options[match].val;
+ else
+ optopt = 0;
+ /* XXX: GNU returns '?' if options[0] != ':' */
+ --optind;
+ return BADARG;
+ }
+ } else { /* unknown option */
+ if (PRINT_ERROR)
+ xwarnx(illoptstring, current_argv);
+ optopt = 0;
+ return BADCH;
+ }
+ if (long_options[match].flag) {
+ *long_options[match].flag = long_options[match].val;
+ retval = 0;
+ } else
+ retval = long_options[match].val;
+ if (idx)
+ *idx = match;
+ }
+ return retval;
+}
Index: instr/drsctrl/getopt_long.obj
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/instr/drsctrl/getopt_long.obj
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: instr/drsctrl/gettimeofday.c
===================================================================
--- instr/drsctrl/gettimeofday.c (nonexistent)
+++ instr/drsctrl/gettimeofday.c (revision 195)
@@ -0,0 +1,57 @@
+/*
+ * gettimeofday.c
+ * Win32 gettimeofday() replacement
+ *
+ * src/port/gettimeofday.c
+ *
+ * Copyright (c) 2003 SRA, Inc.
+ * Copyright (c) 2003 SKC, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose, without fee, and without a
+ * written agreement is hereby granted, provided that the above
+ * copyright notice and this paragraph and the following two
+ * paragraphs appear in all copies.
+ *
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
+ * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
+ * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
+ * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS
+ * IS" BASIS, AND THE AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE,
+ * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+//#include "c.h"
+#include <windows.h>
+#include <time.h>
+
+
+/* FILETIME of Jan 1 1970 00:00:00. */
+static const unsigned __int64 epoch = ((unsigned __int64) 116444736000000000ULL);
+
+/*
+ * timezone information is stored outside the kernel so tzp isn't used anymore.
+ *
+ * Note: this function is not for Win32 high precision timing purpose. See
+ * elapsed_time().
+ */
+int gettimeofday(struct timeval * tp, struct timezone * tzp){
+ FILETIME file_time;
+ SYSTEMTIME system_time;
+ ULARGE_INTEGER ularge;
+
+ GetSystemTime(&system_time);
+ SystemTimeToFileTime(&system_time, &file_time);
+ ularge.LowPart = file_time.dwLowDateTime;
+ ularge.HighPart = file_time.dwHighDateTime;
+
+ tp->tv_sec = (long) ((ularge.QuadPart - epoch) / 10000000L);
+ tp->tv_usec = (long) (system_time.wMilliseconds * 1000);
+
+ return 0;
+}
\ No newline at end of file
Index: instr/drsctrl/gettimeofday.h
===================================================================
--- instr/drsctrl/gettimeofday.h (nonexistent)
+++ instr/drsctrl/gettimeofday.h (revision 195)
@@ -0,0 +1,12 @@
+#ifndef _GETTIMEOFDAY_H_
+#define _GETTIMEOFDAY_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int gettimeofday(struct timeval * tp, struct timezone * tzp);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
\ No newline at end of file
Index: instr/drsctrl/gettimeofday.obj
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/instr/drsctrl/gettimeofday.obj
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: instr/drsctrl/gui.cpp
===================================================================
--- instr/drsctrl/gui.cpp (nonexistent)
+++ instr/drsctrl/gui.cpp (revision 195)
@@ -0,0 +1,503 @@
+// By ROOT version 5.17/02 on 2008-03-13 06:46:41
+
+#ifndef ROOT_TGDockableFrame
+#include "TGDockableFrame.h"
+#endif
+#ifndef ROOT_TGMenu
+#include "TGMenu.h"
+#endif
+#ifndef ROOT_TGMdiDecorFrame
+#include "TGMdiDecorFrame.h"
+#endif
+#ifndef ROOT_TG3DLine
+#include "TG3DLine.h"
+#endif
+#ifndef ROOT_TGMdiFrame
+#include "TGMdiFrame.h"
+#endif
+#ifndef ROOT_TGMdiMainFrame
+#include "TGMdiMainFrame.h"
+#endif
+//#ifndef ROOT_TGuiBldHintsButton
+//#include "TGuiBldHintsButton.h"
+//#endif
+#ifndef ROOT_TGMdiMenu
+#include "TGMdiMenu.h"
+#endif
+#ifndef ROOT_TGListBox
+#include "TGListBox.h"
+#endif
+#ifndef ROOT_TGNumberEntry
+#include "TGNumberEntry.h"
+#endif
+#ifndef ROOT_TGScrollBar
+#include "TGScrollBar.h"
+#endif
+//#ifndef ROOT_TGuiBldHintsEditor
+//#include "TGuiBldHintsEditor.h"
+//#endif
+#ifndef ROOT_TRootBrowser
+#include "TRootBrowser.h"
+#endif
+#ifndef ROOT_TGFrame
+#include "TGFrame.h"
+#endif
+#ifndef ROOT_TGFileDialog
+#include "TGFileDialog.h"
+#endif
+#ifndef ROOT_TGShutter
+#include "TGShutter.h"
+#endif
+#ifndef ROOT_TGButtonGroup
+#include "TGButtonGroup.h"
+#endif
+#ifndef ROOT_TGCanvas
+#include "TGCanvas.h"
+#endif
+#ifndef ROOT_TGFSContainer
+#include "TGFSContainer.h"
+#endif
+#ifndef ROOT_TGButton
+#include "TGButton.h"
+#endif
+//#ifndef ROOT_TGuiBldEditor
+//#include "TGuiBldEditor.h"
+//#endif
+#ifndef ROOT_TGTextEdit
+#include "TGTextEdit.h"
+#endif
+#ifndef ROOT_TGFSComboBox
+#include "TGFSComboBox.h"
+#endif
+#ifndef ROOT_TGLabel
+#include "TGLabel.h"
+#endif
+#ifndef ROOT_TGView
+#include "TGView.h"
+#endif
+//#ifndef ROOT_TRootGuiBuilder
+//#include "TRootGuiBuilder.h"
+//#endif
+#ifndef ROOT_TGTab
+#include "TGTab.h"
+#endif
+#ifndef ROOT_TGListView
+#include "TGListView.h"
+#endif
+#ifndef ROOT_TGSplitter
+#include "TGSplitter.h"
+#endif
+#ifndef ROOT_TGStatusBar
+#include "TGStatusBar.h"
+#endif
+#ifndef ROOT_TGListTree
+#include "TGListTree.h"
+#endif
+#ifndef ROOT_TGToolTip
+#include "TGToolTip.h"
+#endif
+#ifndef ROOT_TGToolBar
+#include "TGToolBar.h"
+#endif
+#ifndef ROOT_TRootEmbeddedCanvas
+#include "TRootEmbeddedCanvas.h"
+#endif
+#ifndef ROOT_TCanvas
+#include "TCanvas.h"
+#endif
+//#ifndef ROOT_TGuiBldDragManager
+//#include "TGuiBldDragManager.h"
+//#endif
+
+#include "Riostream.h"
+#include "TThread.h"
+#include "TApplication.h"
+#include "TROOT.h"
+#include "TGraph.h"
+#include "TH1F.h"
+//#include "daq.h"
+
+TGTextButton *gTextButton[10];
+TCanvas *fCanvas;
+TGMainFrame *fMain;
+TGTextEntry *gFilename;
+TGNumberEntry *gCh;
+
+TGTextEntry *gTimeDisplay;
+TGCheckButton *gDebugButton;
+
+
+
+ TGNumberEntry *gMaxEve;
+TGNumberEntry *gNeve;
+TGNumberEntry *gMask;
+TGNumberEntry *gRange;
+TGNumberEntry *gSoftwareTrigger;
+TGNumberEntry *gTriggerChannel;
+TGNumberEntry *gSamplingFrequency;
+TGNumberEntry *gTriggerDelay;
+
+
+
+
+
+const char gParNames[30][30]={"Events:","EventNo:","Channel Mask:","Range:", "SwTrg", "TriggerChannel:","Sampling Freq.:","TRG Delay:" };
+
+TGNumberFormat::EStyle gParStyle[10] = {
+TGNumberFormat::kNESInteger ,
+TGNumberFormat::kNESInteger,
+TGNumberFormat::kNESInteger ,
+TGNumberFormat::kNESReal,
+TGNumberFormat::kNESInteger,
+TGNumberFormat::kNESInteger,
+TGNumberFormat::kNESInteger,
+TGNumberFormat::kNESReal
+};
+TGNumberEntry *gParameters[10];
+
+
+
+TRootEmbeddedCanvas *gCanvas;
+#define MAXCH 32
+TH1F* gHisto[MAXCH];
+//daq * gDaq;
+#define WINDOW_NAME "Praktikum IV MAPMT PET"
+//----------------------------------------------------
+int UIRDimming(int state){
+ switch (state) {
+ case 0:
+ gTextButton[0]->SetEnabled(0);
+ gTextButton[1]->SetEnabled(1);
+ gTextButton[2]->SetEnabled(0);
+
+ break;
+
+ case 1:
+ gTextButton[0]->SetEnabled(0);
+ gTextButton[1]->SetEnabled(0);
+ gTextButton[2]->SetEnabled(1);
+
+ break;
+
+ case 2:
+ gTextButton[0]->SetEnabled(1);
+ gTextButton[1]->SetEnabled(1);
+ gTextButton[2]->SetEnabled(0);
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+int fDebug;
+void GetDebug(){
+ if ( gDebugButton->IsOn() ) fDebug=1;
+ else fDebug=0;
+}
+
+int GetTime(char *x){
+ time_t rawtime;
+ struct tm * timeinfo;
+ time ( &rawtime );
+ timeinfo = localtime ( &rawtime );
+ sprintf(x,"%s",asctime (timeinfo));
+ int len=strlen(x);
+ if (len) x[len-1]=0;
+ return 0;
+}
+void MyTimer(){
+ char cmd[100];
+ GetTime(cmd);
+ if (gTimeDisplay) gTimeDisplay->SetText(cmd);
+ /* Canvas ni thread safe
+ if (gCanvas){
+ gCanvas->GetCanvas()->Modified();
+ gCanvas->GetCanvas()->Update();
+ }
+ */
+}
+
+//----------------------------------------------------
+// thread function
+int gStop=0;
+#define BSIZE 10000
+unsigned int gBuf[BSIZE];
+void *MyThread(void *ptr)
+{
+ TThread::Printf("Start of MyThread %x \n" ,(int *)ptr);
+
+ // odpremo datoteko za pisanje
+ char fname[128];
+ sprintf(fname,"%s.dat",gFilename->GetText());
+ FILE *fp=fopen(fname,"w");
+ int neve = (int) gMaxEve->GetNumber();
+ int hdr[4]={1};
+
+ //if (gDaq) gDaq->fStop=0;
+ // zajem zeljenega kolicine podatkov
+ for (int n=0;n<neve;n++){
+ int nb=0;
+ /*
+ if (!gDaq) break;
+ nb = gDaq->event(gBuf,BSIZE);
+ if (gDaq->fStop) break;
+ */
+ if (nb<0){
+ n--;
+ continue;
+ }
+
+ // zapis v datoteko
+ hdr[1]=nb+4*sizeof(int);
+ hdr[2]=time(NULL);
+ hdr[3]=n;
+
+ fwrite(hdr, sizeof(int),4 , fp);
+ fwrite(gBuf, sizeof(int),nb, fp);
+ // napolni histograme
+ //*****************
+ unsigned int *data= gBuf;
+ int evsize=0;
+ int events=0;
+ int ib=1,count=0;
+ events = data[0];
+ evsize = data[1]&0xffff;
+ if (evsize<2){
+ n--;
+ continue;
+ }
+ const unsigned int END_MARKER=0xFAF5;
+ if (fDebug) printf("nb=%d Event:%d events=%d EvSize:%d\n",nb, n, events, evsize);
+ for (int i=0;i<evsize;i++) {
+ //if (fDebug) printf("%d\t%08x\n", ib, data[ib]);
+
+ if (data[ib]== END_MARKER) break;
+ if (ib%2==0) {
+ unsigned short word1 =data[ib ]&0xFFFF;
+ unsigned short word2 =data[ib+1]&0xFFFF;
+ unsigned short tdc = word1;
+ unsigned short ch = (word2 >> 1 ) &0x1F;
+ unsigned short edge = word2 & 0x1;
+ unsigned short q = (word2 >> 8) &0x1;
+ unsigned short x = (word2 >> 9) &0x1;
+ TThread::Lock();
+ if (edge && ch < MAXCH) gHisto[ch]->Fill(tdc);
+ TThread::UnLock();
+ if (fDebug) TThread::Printf("%d. [ch=%2d] edge=%d data=%d q=%d x=%d\n",count,ch,edge,tdc, q, x);
+
+ count++;
+ }
+ ib++;
+ }
+ if (data[evsize+1]!=END_MARKER) printf("Error! END_MARKER not found\n");
+//*****************
+
+
+
+
+
+ gNeve->SetNumber(n);
+ }
+ fclose(fp);
+ UIRDimming(2);
+ TThread::Printf("End of MyThread neve=%d\n",neve);
+ return 0;
+}
+
+
+int save2ascii(){
+ if (!gHisto[0]) return 0;
+ char fname[128];
+ sprintf(fname,"%s.txt",gFilename->GetText());
+ FILE *fp= fopen(fname, "w");
+ fprintf(fp, "%s\n",WINDOW_NAME);
+ char cmd[128];
+ GetTime(cmd);
+ fprintf(fp, "Shranjeno: %s\n\n", cmd );
+ fprintf(fp, "Kanal hid=") ;
+ for (int j=0;j<MAXCH;j++) fprintf(fp, "%d\t",j);
+ fprintf(fp, "\n-------------------------------------------------\n");
+ for (int i=0;i<gHisto[0]->GetNbinsX();i++){
+ fprintf(fp, "%d\t",i);
+ for (int j=0;j<MAXCH;j++) fprintf(fp, "%d\t",(int) gHisto[j]->GetBinContent(i+1));
+ fprintf(fp, "\n");
+ }
+ fclose(fp);
+ printf("Rezultati meritev so zapisani v datoteki %s\n",fname);
+ return 0;
+ }
+
+void MyEventHandler(int i){
+ static TTimer * tmr = new TTimer(1000, kFALSE);
+ UIRDimming(i);
+ TThread *fThread;
+ switch (i) {
+ case 0: // Init
+ //gDaq->init();
+ break;
+ case 1: // Start
+ fThread = new TThread(MyThread,(void*)0);
+ fThread->Run();
+ tmr->SetCommand("MyTimer()");
+ tmr->TurnOn();
+ tmr->Start(1000, kFALSE); // 1 second single-shot
+ break;
+ case 2: // Stop
+ //gDaq->fStop=1;
+ tmr->Stop();
+ tmr->TurnOff();
+ break;
+ case 3: // ReDraw
+ gCanvas->GetCanvas()->Modified();
+ gCanvas->GetCanvas()->Update();
+ break;
+ case 4: // Clear
+ for (int j=0;j<MAXCH;j++) if (gHisto[j]) gHisto[j]->Reset();
+ break;
+ case 5: // Save
+ save2ascii();
+ break;
+ case 6: // Print
+ gCanvas->GetCanvas()->SaveAs("zivljenjski_cas_mionov.pdf");
+ break;
+ case 7: // exit
+ gApplication->Terminate(0);
+ break;
+ }
+
+}
+
+int Redraw(long val=0){
+ unsigned int ch= (unsigned int)(gCh->GetNumber());
+ if (ch<MAXCH && gHisto[ch]) {
+ gCanvas->GetCanvas()->cd();
+ gHisto[ch]->Draw();
+ gCanvas->GetCanvas()->Modified();
+ gCanvas->GetCanvas()->Update();
+ } else {
+ if (gCh->GetNumber()>=MAXCH) gCh->SetNumber(MAXCH-1);
+ if (gCh->GetNumber()< 0) gCh->SetNumber(0);
+ }
+ return 0;
+}
+//----------------------------------------------------
+
+int gui(){
+
+ for (int i=0;i<MAXCH;i++){
+ char hname[50];
+ sprintf(hname,"TDC Ch. %d;TDC;N",i);
+ char hn[50];
+ sprintf(hn,"ch%d",i);
+ gHisto[i] = new TH1F(hn,hname,128,-0.5,1024*8-0.5);
+ }
+ //gDaq= new daq();
+ fMain = new TGMainFrame(0,800,800);
+ TGHorizontalFrame *fH=new TGHorizontalFrame(fMain,800,400);
+ //------------------------------------------------------------
+ TGLayoutHints *f0= new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2);
+ TGLayoutHints *layout2= new TGLayoutHints(kLHintsLeft | kLHintsTop,20,20,20,20);
+ // gumbi
+
+ int nbut=8;
+ const char *names[10]={"Init","Start","Stop","Refresh","Clear","Export to ASCII", "Print" , "Exit"};
+ for (int i=0;i<nbut;i++){
+
+ gTextButton[i]= new TGTextButton(fH, names[i]);
+ gTextButton[i]->SetTextJustify(36);
+ gTextButton[i]->SetMargins(0,0,0,0);
+ gTextButton[i]->SetWrapLength(-1);
+ gTextButton[i]->ChangeOptions(gTextButton[i]->GetOptions() | kFixedWidth); // | kFixedSize
+ gTextButton[i]->Resize(100,gTextButton[i]->GetDefaultHeight());
+
+ fH->AddFrame(gTextButton[i], f0);
+ char cmd[50];
+ sprintf(cmd,"MyEventHandler(=%d)",i);
+ TQObject::Connect(gTextButton[i],"Clicked()",0,0,cmd);
+ }
+
+ gDebugButton = new TGCheckButton( fH,"Debug");
+ gDebugButton->Resize(50,22);
+ TQObject::Connect(gDebugButton,"Clicked()", 0, 0 , "GetDebug()");
+ gDebugButton->SetState(kButtonDown);
+ fH->AddFrame(gDebugButton, f0);
+
+ fMain->AddFrame(fH , f0);
+
+ TGHorizontalFrame *fH1=new TGHorizontalFrame(fMain,800,400);
+ //---------------------------------------------------------
+ // ura
+ TGLabel *lab1;
+ fH=new TGHorizontalFrame(fH1,800,200);
+ lab1 = new TGLabel( fH ,"Ura:");
+ fH->AddFrame(lab1, f0);
+ gTimeDisplay = new TGTextEntry( fH,"");
+ gTimeDisplay->Resize(200,22);
+ fH->AddFrame(gTimeDisplay, f0);
+ fH1->AddFrame(fH , f0);
+ //---------------------------------------------------------
+ // inputi
+ fH=new TGHorizontalFrame(fH1,800,200);
+ lab1 = new TGLabel( fH ,"Filename:");
+ fH->AddFrame(lab1, f0);
+ gFilename = new TGTextEntry( fH,"tmp");
+ gFilename->Resize(200,22);
+ fH->AddFrame(gFilename, f0);
+ fH1->AddFrame(fH , f0);
+ //---------------------------------------------------------
+ fH=new TGHorizontalFrame(fH1,800,200);
+ lab1 = new TGLabel( fH ,"Events:");
+ fH->AddFrame(lab1, f0);
+ gMaxEve = new TGNumberEntry( fH,10000);
+ gMaxEve->Resize(100,22);
+ fH->AddFrame(gMaxEve, f0);
+ fH1->AddFrame(fH , f0);
+ //---------------------------------------------------------
+ fH=new TGHorizontalFrame(fH1,800,200);
+ lab1 = new TGLabel( fH ,"Event no:");
+ fH->AddFrame(lab1, f0);
+ gNeve = new TGNumberEntry( fH,0);
+ gNeve->Resize(100,22);
+ fH->AddFrame(gNeve, f0);
+ fH1->AddFrame(fH , f0);
+ //---------------------------------------------------------
+ fMain->AddFrame(fH1 , f0);
+ TGVerticalFrame *fV=new TGVerticalFrame(fMain,800,200);
+ nbut = 8;
+ for (int i=0;i<nbut;i++){
+ fH=new TGHorizontalFrame(fV,800,200);
+ lab1 = new TGLabel( fH ,gParNames[i]);
+ lab1->Resize(100,22);
+ fH->AddFrame(lab1, f0);
+ gParameters[i] = new TGNumberEntry( fH,0,5,i, gParStyle[i] );
+ gParameters[i]->Resize(100,22);
+ fH->AddFrame(gParameters[i] , f0);
+ fV->AddFrame(fH , f0);
+ }
+ fMain->AddFrame(fV , f0);
+ //---------------------------------------------------------
+ // canvas
+ fH=new TGHorizontalFrame(fMain,800,200);
+ gCanvas = new TRootEmbeddedCanvas ("gCanvas",fH,800,400);
+ fH->AddFrame(gCanvas, f0);
+ fMain->AddFrame(fH , f0);
+ //------------------------------------------------------------
+ fH=new TGHorizontalFrame(fMain,800,200);
+ lab1 = new TGLabel( fH ,"Ch. Number(0..3):");
+ fH->AddFrame(lab1, f0);
+ gCh = new TGNumberEntry( fH,0);
+ fH->AddFrame(gCh, f0);
+ TQObject::Connect(gCh,"ValueSet(Long_t)",0,0,"Redraw(Long_t )");
+
+ fMain->AddFrame(fH , f0);
+ //------------------------------------------------------------
+ fMain->SetWindowName(WINDOW_NAME);
+ fMain->MapSubwindows();
+ fMain->Resize(fMain->GetDefaultSize());
+ fMain->MapWindow();
+ Redraw();
+ GetDebug();
+ return 0;
+}
Index: instr/drsctrl/libusb-1.0/libusb.h
===================================================================
--- instr/drsctrl/libusb-1.0/libusb.h (nonexistent)
+++ instr/drsctrl/libusb-1.0/libusb.h (revision 195)
@@ -0,0 +1,1443 @@
+/*
+ * Public libusb header file
+ * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
+ * Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LIBUSB_H
+#define LIBUSB_H
+
+#ifdef _MSC_VER
+/* on MS environments, the inline keyword is available in C++ only */
+#define inline __inline
+/* ssize_t is also not available (copy/paste from MinGW) */
+#ifndef _SSIZE_T_DEFINED
+#define _SSIZE_T_DEFINED
+#undef ssize_t
+#ifdef _WIN64
+ typedef __int64 ssize_t;
+#else
+ typedef int ssize_t;
+#endif /* _WIN64 */
+#endif /* _SSIZE_T_DEFINED */
+#endif /* _MSC_VER */
+
+/* stdint.h is also not usually available on MS */
+#if defined(_MSC_VER) && (_MSC_VER < 1600) && (!defined(_STDINT)) && (!defined(_STDINT_H))
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int32 uint32_t;
+#else
+#include <stdint.h>
+#endif
+
+#include <sys/types.h>
+#include <time.h>
+#include <limits.h>
+
+#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__)
+#include <sys/time.h>
+#endif
+
+/* 'interface' might be defined as a macro on Windows, so we need to
+ * undefine it so as not to break the current libusb API, because
+ * libusb_config_descriptor has an 'interface' member
+ * As this can be problematic if you include windows.h after libusb.h
+ * in your sources, we force windows.h to be included first. */
+#if defined(_WIN32) || defined(__CYGWIN__)
+#include <windows.h>
+#if defined(interface)
+#undef interface
+#endif
+#endif
+
+/** \def LIBUSB_CALL
+ * \ingroup misc
+ * libusb's Windows calling convention.
+ *
+ * Under Windows, the selection of available compilers and configurations
+ * means that, unlike other platforms, there is not <em>one true calling
+ * convention</em> (calling convention: the manner in which parameters are
+ * passed to funcions in the generated assembly code).
+ *
+ * Matching the Windows API itself, libusb uses the WINAPI convention (which
+ * translates to the <tt>stdcall</tt> convention) and guarantees that the
+ * library is compiled in this way. The public header file also includes
+ * appropriate annotations so that your own software will use the right
+ * convention, even if another convention is being used by default within
+ * your codebase.
+ *
+ * The one consideration that you must apply in your software is to mark
+ * all functions which you use as libusb callbacks with this LIBUSB_CALL
+ * annotation, so that they too get compiled for the correct calling
+ * convention.
+ *
+ * On non-Windows operating systems, this macro is defined as nothing. This
+ * means that you can apply it to your code without worrying about
+ * cross-platform compatibility.
+ */
+/* LIBUSB_CALL must be defined on both definition and declaration of libusb
+ * functions. You'd think that declaration would be enough, but cygwin will
+ * complain about conflicting types unless both are marked this way.
+ * The placement of this macro is important too; it must appear after the
+ * return type, before the function name. See internal documentation for
+ * API_EXPORTED.
+ */
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define LIBUSB_CALL WINAPI
+#else
+#define LIBUSB_CALL
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \def libusb_cpu_to_le16
+ * \ingroup misc
+ * Convert a 16-bit value from host-endian to little-endian format. On
+ * little endian systems, this function does nothing. On big endian systems,
+ * the bytes are swapped.
+ * \param x the host-endian value to convert
+ * \returns the value in little-endian byte order
+ */
+static inline uint16_t libusb_cpu_to_le16(const uint16_t x)
+{
+ union {
+ uint8_t b8[2];
+ uint16_t b16;
+ } _tmp;
+ _tmp.b8[1] = x >> 8;
+ _tmp.b8[0] = x & 0xff;
+ return _tmp.b16;
+}
+
+/** \def libusb_le16_to_cpu
+ * \ingroup misc
+ * Convert a 16-bit value from little-endian to host-endian format. On
+ * little endian systems, this function does nothing. On big endian systems,
+ * the bytes are swapped.
+ * \param x the little-endian value to convert
+ * \returns the value in host-endian byte order
+ */
+#define libusb_le16_to_cpu libusb_cpu_to_le16
+
+/* standard USB stuff */
+
+/** \ingroup desc
+ * Device and/or Interface Class codes */
+enum libusb_class_code {
+ /** In the context of a \ref libusb_device_descriptor "device descriptor",
+ * this bDeviceClass value indicates that each interface specifies its
+ * own class information and all interfaces operate independently.
+ */
+ LIBUSB_CLASS_PER_INTERFACE = 0,
+
+ /** Audio class */
+ LIBUSB_CLASS_AUDIO = 1,
+
+ /** Communications class */
+ LIBUSB_CLASS_COMM = 2,
+
+ /** Human Interface Device class */
+ LIBUSB_CLASS_HID = 3,
+
+ /** Physical */
+ LIBUSB_CLASS_PHYSICAL = 5,
+
+ /** Printer class */
+ LIBUSB_CLASS_PRINTER = 7,
+
+ /** Image class */
+ LIBUSB_CLASS_PTP = 6, /* legacy name from libusb-0.1 usb.h */
+ LIBUSB_CLASS_IMAGE = 6,
+
+ /** Mass storage class */
+ LIBUSB_CLASS_MASS_STORAGE = 8,
+
+ /** Hub class */
+ LIBUSB_CLASS_HUB = 9,
+
+ /** Data class */
+ LIBUSB_CLASS_DATA = 10,
+
+ /** Smart Card */
+ LIBUSB_CLASS_SMART_CARD = 0x0b,
+
+ /** Content Security */
+ LIBUSB_CLASS_CONTENT_SECURITY = 0x0d,
+
+ /** Video */
+ LIBUSB_CLASS_VIDEO = 0x0e,
+
+ /** Personal Healthcare */
+ LIBUSB_CLASS_PERSONAL_HEALTHCARE = 0x0f,
+
+ /** Diagnostic Device */
+ LIBUSB_CLASS_DIAGNOSTIC_DEVICE = 0xdc,
+
+ /** Wireless class */
+ LIBUSB_CLASS_WIRELESS = 0xe0,
+
+ /** Application class */
+ LIBUSB_CLASS_APPLICATION = 0xfe,
+
+ /** Class is vendor-specific */
+ LIBUSB_CLASS_VENDOR_SPEC = 0xff
+};
+
+/** \ingroup desc
+ * Descriptor types as defined by the USB specification. */
+enum libusb_descriptor_type {
+ /** Device descriptor. See libusb_device_descriptor. */
+ LIBUSB_DT_DEVICE = 0x01,
+
+ /** Configuration descriptor. See libusb_config_descriptor. */
+ LIBUSB_DT_CONFIG = 0x02,
+
+ /** String descriptor */
+ LIBUSB_DT_STRING = 0x03,
+
+ /** Interface descriptor. See libusb_interface_descriptor. */
+ LIBUSB_DT_INTERFACE = 0x04,
+
+ /** Endpoint descriptor. See libusb_endpoint_descriptor. */
+ LIBUSB_DT_ENDPOINT = 0x05,
+
+ /** HID descriptor */
+ LIBUSB_DT_HID = 0x21,
+
+ /** HID report descriptor */
+ LIBUSB_DT_REPORT = 0x22,
+
+ /** Physical descriptor */
+ LIBUSB_DT_PHYSICAL = 0x23,
+
+ /** Hub descriptor */
+ LIBUSB_DT_HUB = 0x29,
+};
+
+/* Descriptor sizes per descriptor type */
+#define LIBUSB_DT_DEVICE_SIZE 18
+#define LIBUSB_DT_CONFIG_SIZE 9
+#define LIBUSB_DT_INTERFACE_SIZE 9
+#define LIBUSB_DT_ENDPOINT_SIZE 7
+#define LIBUSB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
+#define LIBUSB_DT_HUB_NONVAR_SIZE 7
+
+#define LIBUSB_ENDPOINT_ADDRESS_MASK 0x0f /* in bEndpointAddress */
+#define LIBUSB_ENDPOINT_DIR_MASK 0x80
+
+/** \ingroup desc
+ * Endpoint direction. Values for bit 7 of the
+ * \ref libusb_endpoint_descriptor::bEndpointAddress "endpoint address" scheme.
+ */
+enum libusb_endpoint_direction {
+ /** In: device-to-host */
+ LIBUSB_ENDPOINT_IN = 0x80,
+
+ /** Out: host-to-device */
+ LIBUSB_ENDPOINT_OUT = 0x00
+};
+
+#define LIBUSB_TRANSFER_TYPE_MASK 0x03 /* in bmAttributes */
+
+/** \ingroup desc
+ * Endpoint transfer type. Values for bits 0:1 of the
+ * \ref libusb_endpoint_descriptor::bmAttributes "endpoint attributes" field.
+ */
+enum libusb_transfer_type {
+ /** Control endpoint */
+ LIBUSB_TRANSFER_TYPE_CONTROL = 0,
+
+ /** Isochronous endpoint */
+ LIBUSB_TRANSFER_TYPE_ISOCHRONOUS = 1,
+
+ /** Bulk endpoint */
+ LIBUSB_TRANSFER_TYPE_BULK = 2,
+
+ /** Interrupt endpoint */
+ LIBUSB_TRANSFER_TYPE_INTERRUPT = 3
+};
+
+/** \ingroup misc
+ * Standard requests, as defined in table 9-3 of the USB2 specifications */
+enum libusb_standard_request {
+ /** Request status of the specific recipient */
+ LIBUSB_REQUEST_GET_STATUS = 0x00,
+
+ /** Clear or disable a specific feature */
+ LIBUSB_REQUEST_CLEAR_FEATURE = 0x01,
+
+ /* 0x02 is reserved */
+
+ /** Set or enable a specific feature */
+ LIBUSB_REQUEST_SET_FEATURE = 0x03,
+
+ /* 0x04 is reserved */
+
+ /** Set device address for all future accesses */
+ LIBUSB_REQUEST_SET_ADDRESS = 0x05,
+
+ /** Get the specified descriptor */
+ LIBUSB_REQUEST_GET_DESCRIPTOR = 0x06,
+
+ /** Used to update existing descriptors or add new descriptors */
+ LIBUSB_REQUEST_SET_DESCRIPTOR = 0x07,
+
+ /** Get the current device configuration value */
+ LIBUSB_REQUEST_GET_CONFIGURATION = 0x08,
+
+ /** Set device configuration */
+ LIBUSB_REQUEST_SET_CONFIGURATION = 0x09,
+
+ /** Return the selected alternate setting for the specified interface */
+ LIBUSB_REQUEST_GET_INTERFACE = 0x0A,
+
+ /** Select an alternate interface for the specified interface */
+ LIBUSB_REQUEST_SET_INTERFACE = 0x0B,
+
+ /** Set then report an endpoint's synchronization frame */
+ LIBUSB_REQUEST_SYNCH_FRAME = 0x0C,
+};
+
+/** \ingroup misc
+ * Request type bits of the
+ * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control
+ * transfers. */
+enum libusb_request_type {
+ /** Standard */
+ LIBUSB_REQUEST_TYPE_STANDARD = (0x00 << 5),
+
+ /** Class */
+ LIBUSB_REQUEST_TYPE_CLASS = (0x01 << 5),
+
+ /** Vendor */
+ LIBUSB_REQUEST_TYPE_VENDOR = (0x02 << 5),
+
+ /** Reserved */
+ LIBUSB_REQUEST_TYPE_RESERVED = (0x03 << 5)
+};
+
+/** \ingroup misc
+ * Recipient bits of the
+ * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control
+ * transfers. Values 4 through 31 are reserved. */
+enum libusb_request_recipient {
+ /** Device */
+ LIBUSB_RECIPIENT_DEVICE = 0x00,
+
+ /** Interface */
+ LIBUSB_RECIPIENT_INTERFACE = 0x01,
+
+ /** Endpoint */
+ LIBUSB_RECIPIENT_ENDPOINT = 0x02,
+
+ /** Other */
+ LIBUSB_RECIPIENT_OTHER = 0x03,
+};
+
+#define LIBUSB_ISO_SYNC_TYPE_MASK 0x0C
+
+/** \ingroup desc
+ * Synchronization type for isochronous endpoints. Values for bits 2:3 of the
+ * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in
+ * libusb_endpoint_descriptor.
+ */
+enum libusb_iso_sync_type {
+ /** No synchronization */
+ LIBUSB_ISO_SYNC_TYPE_NONE = 0,
+
+ /** Asynchronous */
+ LIBUSB_ISO_SYNC_TYPE_ASYNC = 1,
+
+ /** Adaptive */
+ LIBUSB_ISO_SYNC_TYPE_ADAPTIVE = 2,
+
+ /** Synchronous */
+ LIBUSB_ISO_SYNC_TYPE_SYNC = 3
+};
+
+#define LIBUSB_ISO_USAGE_TYPE_MASK 0x30
+
+/** \ingroup desc
+ * Usage type for isochronous endpoints. Values for bits 4:5 of the
+ * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in
+ * libusb_endpoint_descriptor.
+ */
+enum libusb_iso_usage_type {
+ /** Data endpoint */
+ LIBUSB_ISO_USAGE_TYPE_DATA = 0,
+
+ /** Feedback endpoint */
+ LIBUSB_ISO_USAGE_TYPE_FEEDBACK = 1,
+
+ /** Implicit feedback Data endpoint */
+ LIBUSB_ISO_USAGE_TYPE_IMPLICIT = 2,
+};
+
+/** \ingroup desc
+ * A structure representing the standard USB device descriptor. This
+ * descriptor is documented in section 9.6.1 of the USB 2.0 specification.
+ * All multiple-byte fields are represented in host-endian format.
+ */
+struct libusb_device_descriptor {
+ /** Size of this descriptor (in bytes) */
+ uint8_t bLength;
+
+ /** Descriptor type. Will have value
+ * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE LIBUSB_DT_DEVICE in this
+ * context. */
+ uint8_t bDescriptorType;
+
+ /** USB specification release number in binary-coded decimal. A value of
+ * 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1, etc. */
+ uint16_t bcdUSB;
+
+ /** USB-IF class code for the device. See \ref libusb_class_code. */
+ uint8_t bDeviceClass;
+
+ /** USB-IF subclass code for the device, qualified by the bDeviceClass
+ * value */
+ uint8_t bDeviceSubClass;
+
+ /** USB-IF protocol code for the device, qualified by the bDeviceClass and
+ * bDeviceSubClass values */
+ uint8_t bDeviceProtocol;
+
+ /** Maximum packet size for endpoint 0 */
+ uint8_t bMaxPacketSize0;
+
+ /** USB-IF vendor ID */
+ uint16_t idVendor;
+
+ /** USB-IF product ID */
+ uint16_t idProduct;
+
+ /** Device release number in binary-coded decimal */
+ uint16_t bcdDevice;
+
+ /** Index of string descriptor describing manufacturer */
+ uint8_t iManufacturer;
+
+ /** Index of string descriptor describing product */
+ uint8_t iProduct;
+
+ /** Index of string descriptor containing device serial number */
+ uint8_t iSerialNumber;
+
+ /** Number of possible configurations */
+ uint8_t bNumConfigurations;
+};
+
+/** \ingroup desc
+ * A structure representing the standard USB endpoint descriptor. This
+ * descriptor is documented in section 9.6.3 of the USB 2.0 specification.
+ * All multiple-byte fields are represented in host-endian format.
+ */
+struct libusb_endpoint_descriptor {
+ /** Size of this descriptor (in bytes) */
+ uint8_t bLength;
+
+ /** Descriptor type. Will have value
+ * \ref libusb_descriptor_type::LIBUSB_DT_ENDPOINT LIBUSB_DT_ENDPOINT in
+ * this context. */
+ uint8_t bDescriptorType;
+
+ /** The address of the endpoint described by this descriptor. Bits 0:3 are
+ * the endpoint number. Bits 4:6 are reserved. Bit 7 indicates direction,
+ * see \ref libusb_endpoint_direction.
+ */
+ uint8_t bEndpointAddress;
+
+ /** Attributes which apply to the endpoint when it is configured using
+ * the bConfigurationValue. Bits 0:1 determine the transfer type and
+ * correspond to \ref libusb_transfer_type. Bits 2:3 are only used for
+ * isochronous endpoints and correspond to \ref libusb_iso_sync_type.
+ * Bits 4:5 are also only used for isochronous endpoints and correspond to
+ * \ref libusb_iso_usage_type. Bits 6:7 are reserved.
+ */
+ uint8_t bmAttributes;
+
+ /** Maximum packet size this endpoint is capable of sending/receiving. */
+ uint16_t wMaxPacketSize;
+
+ /** Interval for polling endpoint for data transfers. */
+ uint8_t bInterval;
+
+ /** For audio devices only: the rate at which synchronization feedback
+ * is provided. */
+ uint8_t bRefresh;
+
+ /** For audio devices only: the address if the synch endpoint */
+ uint8_t bSynchAddress;
+
+ /** Extra descriptors. If libusb encounters unknown endpoint descriptors,
+ * it will store them here, should you wish to parse them. */
+ const unsigned char *extra;
+
+ /** Length of the extra descriptors, in bytes. */
+ int extra_length;
+};
+
+/** \ingroup desc
+ * A structure representing the standard USB interface descriptor. This
+ * descriptor is documented in section 9.6.5 of the USB 2.0 specification.
+ * All multiple-byte fields are represented in host-endian format.
+ */
+struct libusb_interface_descriptor {
+ /** Size of this descriptor (in bytes) */
+ uint8_t bLength;
+
+ /** Descriptor type. Will have value
+ * \ref libusb_descriptor_type::LIBUSB_DT_INTERFACE LIBUSB_DT_INTERFACE
+ * in this context. */
+ uint8_t bDescriptorType;
+
+ /** Number of this interface */
+ uint8_t bInterfaceNumber;
+
+ /** Value used to select this alternate setting for this interface */
+ uint8_t bAlternateSetting;
+
+ /** Number of endpoints used by this interface (excluding the control
+ * endpoint). */
+ uint8_t bNumEndpoints;
+
+ /** USB-IF class code for this interface. See \ref libusb_class_code. */
+ uint8_t bInterfaceClass;
+
+ /** USB-IF subclass code for this interface, qualified by the
+ * bInterfaceClass value */
+ uint8_t bInterfaceSubClass;
+
+ /** USB-IF protocol code for this interface, qualified by the
+ * bInterfaceClass and bInterfaceSubClass values */
+ uint8_t bInterfaceProtocol;
+
+ /** Index of string descriptor describing this interface */
+ uint8_t iInterface;
+
+ /** Array of endpoint descriptors. This length of this array is determined
+ * by the bNumEndpoints field. */
+ const struct libusb_endpoint_descriptor *endpoint;
+
+ /** Extra descriptors. If libusb encounters unknown interface descriptors,
+ * it will store them here, should you wish to parse them. */
+ const unsigned char *extra;
+
+ /** Length of the extra descriptors, in bytes. */
+ int extra_length;
+};
+
+/** \ingroup desc
+ * A collection of alternate settings for a particular USB interface.
+ */
+struct libusb_interface {
+ /** Array of interface descriptors. The length of this array is determined
+ * by the num_altsetting field. */
+ const struct libusb_interface_descriptor *altsetting;
+
+ /** The number of alternate settings that belong to this interface */
+ int num_altsetting;
+};
+
+/** \ingroup desc
+ * A structure representing the standard USB configuration descriptor. This
+ * descriptor is documented in section 9.6.3 of the USB 2.0 specification.
+ * All multiple-byte fields are represented in host-endian format.
+ */
+struct libusb_config_descriptor {
+ /** Size of this descriptor (in bytes) */
+ uint8_t bLength;
+
+ /** Descriptor type. Will have value
+ * \ref libusb_descriptor_type::LIBUSB_DT_CONFIG LIBUSB_DT_CONFIG
+ * in this context. */
+ uint8_t bDescriptorType;
+
+ /** Total length of data returned for this configuration */
+ uint16_t wTotalLength;
+
+ /** Number of interfaces supported by this configuration */
+ uint8_t bNumInterfaces;
+
+ /** Identifier value for this configuration */
+ uint8_t bConfigurationValue;
+
+ /** Index of string descriptor describing this configuration */
+ uint8_t iConfiguration;
+
+ /** Configuration characteristics */
+ uint8_t bmAttributes;
+
+ /** Maximum power consumption of the USB device from this bus in this
+ * configuration when the device is fully opreation. Expressed in units
+ * of 2 mA. */
+ uint8_t MaxPower;
+
+ /** Array of interfaces supported by this configuration. The length of
+ * this array is determined by the bNumInterfaces field. */
+ const struct libusb_interface *interface;
+
+ /** Extra descriptors. If libusb encounters unknown configuration
+ * descriptors, it will store them here, should you wish to parse them. */
+ const unsigned char *extra;
+
+ /** Length of the extra descriptors, in bytes. */
+ int extra_length;
+};
+
+/** \ingroup asyncio
+ * Setup packet for control transfers. */
+struct libusb_control_setup {
+ /** Request type. Bits 0:4 determine recipient, see
+ * \ref libusb_request_recipient. Bits 5:6 determine type, see
+ * \ref libusb_request_type. Bit 7 determines data transfer direction, see
+ * \ref libusb_endpoint_direction.
+ */
+ uint8_t bmRequestType;
+
+ /** Request. If the type bits of bmRequestType are equal to
+ * \ref libusb_request_type::LIBUSB_REQUEST_TYPE_STANDARD
+ * "LIBUSB_REQUEST_TYPE_STANDARD" then this field refers to
+ * \ref libusb_standard_request. For other cases, use of this field is
+ * application-specific. */
+ uint8_t bRequest;
+
+ /** Value. Varies according to request */
+ uint16_t wValue;
+
+ /** Index. Varies according to request, typically used to pass an index
+ * or offset */
+ uint16_t wIndex;
+
+ /** Number of bytes to transfer */
+ uint16_t wLength;
+};
+
+#define LIBUSB_CONTROL_SETUP_SIZE (sizeof(struct libusb_control_setup))
+
+/* libusb */
+
+struct libusb_context;
+struct libusb_device;
+struct libusb_device_handle;
+
+/** \ingroup lib
+ * Structure representing the libusb version.
+ */
+struct libusb_version {
+ /** Library major version. */
+ const uint16_t major;
+
+ /** Library minor version. */
+ const uint16_t minor;
+
+ /** Library micro version. */
+ const uint16_t micro;
+
+ /** Library nano version. This field is only nonzero on Windows. */
+ const uint16_t nano;
+
+ /** Library release candidate suffix string, e.g. "-rc4". */
+ const char *rc;
+
+ /** Output of `git describe --tags` at library build time. */
+ const char *describe;
+};
+
+/** \ingroup lib
+ * Structure representing a libusb session. The concept of individual libusb
+ * sessions allows for your program to use two libraries (or dynamically
+ * load two modules) which both independently use libusb. This will prevent
+ * interference between the individual libusb users - for example
+ * libusb_set_debug() will not affect the other user of the library, and
+ * libusb_exit() will not destroy resources that the other user is still
+ * using.
+ *
+ * Sessions are created by libusb_init() and destroyed through libusb_exit().
+ * If your application is guaranteed to only ever include a single libusb
+ * user (i.e. you), you do not have to worry about contexts: pass NULL in
+ * every function call where a context is required. The default context
+ * will be used.
+ *
+ * For more information, see \ref contexts.
+ */
+typedef struct libusb_context libusb_context;
+
+/** \ingroup dev
+ * Structure representing a USB device detected on the system. This is an
+ * opaque type for which you are only ever provided with a pointer, usually
+ * originating from libusb_get_device_list().
+ *
+ * Certain operations can be performed on a device, but in order to do any
+ * I/O you will have to first obtain a device handle using libusb_open().
+ *
+ * Devices are reference counted with libusb_device_ref() and
+ * libusb_device_unref(), and are freed when the reference count reaches 0.
+ * New devices presented by libusb_get_device_list() have a reference count of
+ * 1, and libusb_free_device_list() can optionally decrease the reference count
+ * on all devices in the list. libusb_open() adds another reference which is
+ * later destroyed by libusb_close().
+ */
+typedef struct libusb_device libusb_device;
+
+
+/** \ingroup dev
+ * Structure representing a handle on a USB device. This is an opaque type for
+ * which you are only ever provided with a pointer, usually originating from
+ * libusb_open().
+ *
+ * A device handle is used to perform I/O and other operations. When finished
+ * with a device handle, you should call libusb_close().
+ */
+typedef struct libusb_device_handle libusb_device_handle;
+
+/** \ingroup dev
+ * Speed codes. Indicates the speed at which the device is operating.
+ */
+enum libusb_speed {
+ /** The OS doesn't report or know the device speed. */
+ LIBUSB_SPEED_UNKNOWN = 0,
+
+ /** The device is operating at low speed (1.5MBit/s). */
+ LIBUSB_SPEED_LOW = 1,
+
+ /** The device is operating at full speed (12MBit/s). */
+ LIBUSB_SPEED_FULL = 2,
+
+ /** The device is operating at high speed (480MBit/s). */
+ LIBUSB_SPEED_HIGH = 3,
+
+ /** The device is operating at super speed (5000MBit/s). */
+ LIBUSB_SPEED_SUPER = 4,
+};
+
+/** \ingroup misc
+ * Error codes. Most libusb functions return 0 on success or one of these
+ * codes on failure.
+ * You can call \ref libusb_error_name() to retrieve a string representation
+ * of an error code.
+ */
+enum libusb_error {
+ /** Success (no error) */
+ LIBUSB_SUCCESS = 0,
+
+ /** Input/output error */
+ LIBUSB_ERROR_IO = -1,
+
+ /** Invalid parameter */
+ LIBUSB_ERROR_INVALID_PARAM = -2,
+
+ /** Access denied (insufficient permissions) */
+ LIBUSB_ERROR_ACCESS = -3,
+
+ /** No such device (it may have been disconnected) */
+ LIBUSB_ERROR_NO_DEVICE = -4,
+
+ /** Entity not found */
+ LIBUSB_ERROR_NOT_FOUND = -5,
+
+ /** Resource busy */
+ LIBUSB_ERROR_BUSY = -6,
+
+ /** Operation timed out */
+ LIBUSB_ERROR_TIMEOUT = -7,
+
+ /** Overflow */
+ LIBUSB_ERROR_OVERFLOW = -8,
+
+ /** Pipe error */
+ LIBUSB_ERROR_PIPE = -9,
+
+ /** System call interrupted (perhaps due to signal) */
+ LIBUSB_ERROR_INTERRUPTED = -10,
+
+ /** Insufficient memory */
+ LIBUSB_ERROR_NO_MEM = -11,
+
+ /** Operation not supported or unimplemented on this platform */
+ LIBUSB_ERROR_NOT_SUPPORTED = -12,
+
+ /* NB! Remember to update libusb_error_name()
+ when adding new error codes here. */
+
+ /** Other error */
+ LIBUSB_ERROR_OTHER = -99,
+};
+
+/** \ingroup asyncio
+ * Transfer status codes */
+enum libusb_transfer_status {
+ /** Transfer completed without error. Note that this does not indicate
+ * that the entire amount of requested data was transferred. */
+ LIBUSB_TRANSFER_COMPLETED,
+
+ /** Transfer failed */
+ LIBUSB_TRANSFER_ERROR,
+
+ /** Transfer timed out */
+ LIBUSB_TRANSFER_TIMED_OUT,
+
+ /** Transfer was cancelled */
+ LIBUSB_TRANSFER_CANCELLED,
+
+ /** For bulk/interrupt endpoints: halt condition detected (endpoint
+ * stalled). For control endpoints: control request not supported. */
+ LIBUSB_TRANSFER_STALL,
+
+ /** Device was disconnected */
+ LIBUSB_TRANSFER_NO_DEVICE,
+
+ /** Device sent more data than requested */
+ LIBUSB_TRANSFER_OVERFLOW,
+};
+
+/** \ingroup asyncio
+ * libusb_transfer.flags values */
+enum libusb_transfer_flags {
+ /** Report short frames as errors */
+ LIBUSB_TRANSFER_SHORT_NOT_OK = 1<<0,
+
+ /** Automatically free() transfer buffer during libusb_free_transfer() */
+ LIBUSB_TRANSFER_FREE_BUFFER = 1<<1,
+
+ /** Automatically call libusb_free_transfer() after callback returns.
+ * If this flag is set, it is illegal to call libusb_free_transfer()
+ * from your transfer callback, as this will result in a double-free
+ * when this flag is acted upon. */
+ LIBUSB_TRANSFER_FREE_TRANSFER = 1<<2,
+
+ /** Terminate transfers that are a multiple of the endpoint's
+ * wMaxPacketSize with an extra zero length packet. This is useful
+ * when a device protocol mandates that each logical request is
+ * terminated by an incomplete packet (i.e. the logical requests are
+ * not separated by other means).
+ *
+ * This flag only affects host-to-device transfers to bulk and interrupt
+ * endpoints. In other situations, it is ignored.
+ *
+ * This flag only affects transfers with a length that is a multiple of
+ * the endpoint's wMaxPacketSize. On transfers of other lengths, this
+ * flag has no effect. Therefore, if you are working with a device that
+ * needs a ZLP whenever the end of the logical request falls on a packet
+ * boundary, then it is sensible to set this flag on <em>every</em>
+ * transfer (you do not have to worry about only setting it on transfers
+ * that end on the boundary).
+ *
+ * This flag is currently only supported on Linux.
+ * On other systems, libusb_submit_transfer() will return
+ * LIBUSB_ERROR_NOT_SUPPORTED for every transfer where this flag is set.
+ *
+ * Available since libusb-1.0.9.
+ */
+ LIBUSB_TRANSFER_ADD_ZERO_PACKET = 1 << 3,
+};
+
+/** \ingroup asyncio
+ * Isochronous packet descriptor. */
+struct libusb_iso_packet_descriptor {
+ /** Length of data to request in this packet */
+ unsigned int length;
+
+ /** Amount of data that was actually transferred */
+ unsigned int actual_length;
+
+ /** Status code for this packet */
+ enum libusb_transfer_status status;
+};
+
+struct libusb_transfer;
+
+/** \ingroup asyncio
+ * Asynchronous transfer callback function type. When submitting asynchronous
+ * transfers, you pass a pointer to a callback function of this type via the
+ * \ref libusb_transfer::callback "callback" member of the libusb_transfer
+ * structure. libusb will call this function later, when the transfer has
+ * completed or failed. See \ref asyncio for more information.
+ * \param transfer The libusb_transfer struct the callback function is being
+ * notified about.
+ */
+typedef void (LIBUSB_CALL *libusb_transfer_cb_fn)(struct libusb_transfer *transfer);
+
+/** \ingroup asyncio
+ * The generic USB transfer structure. The user populates this structure and
+ * then submits it in order to request a transfer. After the transfer has
+ * completed, the library populates the transfer with the results and passes
+ * it back to the user.
+ */
+struct libusb_transfer {
+ /** Handle of the device that this transfer will be submitted to */
+ libusb_device_handle *dev_handle;
+
+ /** A bitwise OR combination of \ref libusb_transfer_flags. */
+ uint8_t flags;
+
+ /** Address of the endpoint where this transfer will be sent. */
+ unsigned char endpoint;
+
+ /** Type of the endpoint from \ref libusb_transfer_type */
+ unsigned char type;
+
+ /** Timeout for this transfer in millseconds. A value of 0 indicates no
+ * timeout. */
+ unsigned int timeout;
+
+ /** The status of the transfer. Read-only, and only for use within
+ * transfer callback function.
+ *
+ * If this is an isochronous transfer, this field may read COMPLETED even
+ * if there were errors in the frames. Use the
+ * \ref libusb_iso_packet_descriptor::status "status" field in each packet
+ * to determine if errors occurred. */
+ enum libusb_transfer_status status;
+
+ /** Length of the data buffer */
+ int length;
+
+ /** Actual length of data that was transferred. Read-only, and only for
+ * use within transfer callback function. Not valid for isochronous
+ * endpoint transfers. */
+ int actual_length;
+
+ /** Callback function. This will be invoked when the transfer completes,
+ * fails, or is cancelled. */
+ libusb_transfer_cb_fn callback;
+
+ /** User context data to pass to the callback function. */
+ void *user_data;
+
+ /** Data buffer */
+ unsigned char *buffer;
+
+ /** Number of isochronous packets. Only used for I/O with isochronous
+ * endpoints. */
+ int num_iso_packets;
+
+ /** Isochronous packet descriptors, for isochronous transfers only. */
+ struct libusb_iso_packet_descriptor iso_packet_desc
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+ [] /* valid C99 code */
+#else
+ [0] /* non-standard, but usually working code */
+#endif
+ ;
+};
+
+/** \ingroup misc
+ * Capabilities supported by this instance of libusb. Test if the loaded
+ * library supports a given capability by calling
+ * \ref libusb_has_capability().
+ */
+enum libusb_capability {
+ /** The libusb_has_capability() API is available. */
+ LIBUSB_CAP_HAS_CAPABILITY = 0,
+};
+
+int LIBUSB_CALL libusb_init(libusb_context **ctx);
+void LIBUSB_CALL libusb_exit(libusb_context *ctx);
+void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level);
+const struct libusb_version * LIBUSB_CALL libusb_get_version(void);
+int LIBUSB_CALL libusb_has_capability(uint32_t capability);
+const char * LIBUSB_CALL libusb_error_name(int errcode);
+
+ssize_t LIBUSB_CALL libusb_get_device_list(libusb_context *ctx,
+ libusb_device ***list);
+void LIBUSB_CALL libusb_free_device_list(libusb_device **list,
+ int unref_devices);
+libusb_device * LIBUSB_CALL libusb_ref_device(libusb_device *dev);
+void LIBUSB_CALL libusb_unref_device(libusb_device *dev);
+
+int LIBUSB_CALL libusb_get_configuration(libusb_device_handle *dev,
+ int *config);
+int LIBUSB_CALL libusb_get_device_descriptor(libusb_device *dev,
+ struct libusb_device_descriptor *desc);
+int LIBUSB_CALL libusb_get_active_config_descriptor(libusb_device *dev,
+ struct libusb_config_descriptor **config);
+int LIBUSB_CALL libusb_get_config_descriptor(libusb_device *dev,
+ uint8_t config_index, struct libusb_config_descriptor **config);
+int LIBUSB_CALL libusb_get_config_descriptor_by_value(libusb_device *dev,
+ uint8_t bConfigurationValue, struct libusb_config_descriptor **config);
+void LIBUSB_CALL libusb_free_config_descriptor(
+ struct libusb_config_descriptor *config);
+uint8_t LIBUSB_CALL libusb_get_bus_number(libusb_device *dev);
+uint8_t LIBUSB_CALL libusb_get_device_address(libusb_device *dev);
+int LIBUSB_CALL libusb_get_device_speed(libusb_device *dev);
+int LIBUSB_CALL libusb_get_max_packet_size(libusb_device *dev,
+ unsigned char endpoint);
+int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev,
+ unsigned char endpoint);
+
+int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **handle);
+void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle);
+libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle);
+
+int LIBUSB_CALL libusb_set_configuration(libusb_device_handle *dev,
+ int configuration);
+int LIBUSB_CALL libusb_claim_interface(libusb_device_handle *dev,
+ int interface_number);
+int LIBUSB_CALL libusb_release_interface(libusb_device_handle *dev,
+ int interface_number);
+
+libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid(
+ libusb_context *ctx, uint16_t vendor_id, uint16_t product_id);
+
+int LIBUSB_CALL libusb_set_interface_alt_setting(libusb_device_handle *dev,
+ int interface_number, int alternate_setting);
+int LIBUSB_CALL libusb_clear_halt(libusb_device_handle *dev,
+ unsigned char endpoint);
+int LIBUSB_CALL libusb_reset_device(libusb_device_handle *dev);
+
+int LIBUSB_CALL libusb_kernel_driver_active(libusb_device_handle *dev,
+ int interface_number);
+int LIBUSB_CALL libusb_detach_kernel_driver(libusb_device_handle *dev,
+ int interface_number);
+int LIBUSB_CALL libusb_attach_kernel_driver(libusb_device_handle *dev,
+ int interface_number);
+
+/* async I/O */
+
+/** \ingroup asyncio
+ * Get the data section of a control transfer. This convenience function is here
+ * to remind you that the data does not start until 8 bytes into the actual
+ * buffer, as the setup packet comes first.
+ *
+ * Calling this function only makes sense from a transfer callback function,
+ * or situations where you have already allocated a suitably sized buffer at
+ * transfer->buffer.
+ *
+ * \param transfer a transfer
+ * \returns pointer to the first byte of the data section
+ */
+static inline unsigned char *libusb_control_transfer_get_data(
+ struct libusb_transfer *transfer)
+{
+ return transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE;
+}
+
+/** \ingroup asyncio
+ * Get the control setup packet of a control transfer. This convenience
+ * function is here to remind you that the control setup occupies the first
+ * 8 bytes of the transfer data buffer.
+ *
+ * Calling this function only makes sense from a transfer callback function,
+ * or situations where you have already allocated a suitably sized buffer at
+ * transfer->buffer.
+ *
+ * \param transfer a transfer
+ * \returns a casted pointer to the start of the transfer data buffer
+ */
+static inline struct libusb_control_setup *libusb_control_transfer_get_setup(
+ struct libusb_transfer *transfer)
+{
+ return (struct libusb_control_setup *) transfer->buffer;
+}
+
+/** \ingroup asyncio
+ * Helper function to populate the setup packet (first 8 bytes of the data
+ * buffer) for a control transfer. The wIndex, wValue and wLength values should
+ * be given in host-endian byte order.
+ *
+ * \param buffer buffer to output the setup packet into
+ * \param bmRequestType see the
+ * \ref libusb_control_setup::bmRequestType "bmRequestType" field of
+ * \ref libusb_control_setup
+ * \param bRequest see the
+ * \ref libusb_control_setup::bRequest "bRequest" field of
+ * \ref libusb_control_setup
+ * \param wValue see the
+ * \ref libusb_control_setup::wValue "wValue" field of
+ * \ref libusb_control_setup
+ * \param wIndex see the
+ * \ref libusb_control_setup::wIndex "wIndex" field of
+ * \ref libusb_control_setup
+ * \param wLength see the
+ * \ref libusb_control_setup::wLength "wLength" field of
+ * \ref libusb_control_setup
+ */
+static inline void libusb_fill_control_setup(unsigned char *buffer,
+ uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
+ uint16_t wLength)
+{
+ struct libusb_control_setup *setup = (struct libusb_control_setup *) buffer;
+ setup->bmRequestType = bmRequestType;
+ setup->bRequest = bRequest;
+ setup->wValue = libusb_cpu_to_le16(wValue);
+ setup->wIndex = libusb_cpu_to_le16(wIndex);
+ setup->wLength = libusb_cpu_to_le16(wLength);
+}
+
+struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(int iso_packets);
+int LIBUSB_CALL libusb_submit_transfer(struct libusb_transfer *transfer);
+int LIBUSB_CALL libusb_cancel_transfer(struct libusb_transfer *transfer);
+void LIBUSB_CALL libusb_free_transfer(struct libusb_transfer *transfer);
+
+/** \ingroup asyncio
+ * Helper function to populate the required \ref libusb_transfer fields
+ * for a control transfer.
+ *
+ * If you pass a transfer buffer to this function, the first 8 bytes will
+ * be interpreted as a control setup packet, and the wLength field will be
+ * used to automatically populate the \ref libusb_transfer::length "length"
+ * field of the transfer. Therefore the recommended approach is:
+ * -# Allocate a suitably sized data buffer (including space for control setup)
+ * -# Call libusb_fill_control_setup()
+ * -# If this is a host-to-device transfer with a data stage, put the data
+ * in place after the setup packet
+ * -# Call this function
+ * -# Call libusb_submit_transfer()
+ *
+ * It is also legal to pass a NULL buffer to this function, in which case this
+ * function will not attempt to populate the length field. Remember that you
+ * must then populate the buffer and length fields later.
+ *
+ * \param transfer the transfer to populate
+ * \param dev_handle handle of the device that will handle the transfer
+ * \param buffer data buffer. If provided, this function will interpret the
+ * first 8 bytes as a setup packet and infer the transfer length from that.
+ * \param callback callback function to be invoked on transfer completion
+ * \param user_data user data to pass to callback function
+ * \param timeout timeout for the transfer in milliseconds
+ */
+static inline void libusb_fill_control_transfer(
+ struct libusb_transfer *transfer, libusb_device_handle *dev_handle,
+ unsigned char *buffer, libusb_transfer_cb_fn callback, void *user_data,
+ unsigned int timeout)
+{
+ struct libusb_control_setup *setup = (struct libusb_control_setup *) buffer;
+ transfer->dev_handle = dev_handle;
+ transfer->endpoint = 0;
+ transfer->type = LIBUSB_TRANSFER_TYPE_CONTROL;
+ transfer->timeout = timeout;
+ transfer->buffer = buffer;
+ if (setup)
+ transfer->length = LIBUSB_CONTROL_SETUP_SIZE
+ + libusb_le16_to_cpu(setup->wLength);
+ transfer->user_data = user_data;
+ transfer->callback = callback;
+}
+
+/** \ingroup asyncio
+ * Helper function to populate the required \ref libusb_transfer fields
+ * for a bulk transfer.
+ *
+ * \param transfer the transfer to populate
+ * \param dev_handle handle of the device that will handle the transfer
+ * \param endpoint address of the endpoint where this transfer will be sent
+ * \param buffer data buffer
+ * \param length length of data buffer
+ * \param callback callback function to be invoked on transfer completion
+ * \param user_data user data to pass to callback function
+ * \param timeout timeout for the transfer in milliseconds
+ */
+static inline void libusb_fill_bulk_transfer(struct libusb_transfer *transfer,
+ libusb_device_handle *dev_handle, unsigned char endpoint,
+ unsigned char *buffer, int length, libusb_transfer_cb_fn callback,
+ void *user_data, unsigned int timeout)
+{
+ transfer->dev_handle = dev_handle;
+ transfer->endpoint = endpoint;
+ transfer->type = LIBUSB_TRANSFER_TYPE_BULK;
+ transfer->timeout = timeout;
+ transfer->buffer = buffer;
+ transfer->length = length;
+ transfer->user_data = user_data;
+ transfer->callback = callback;
+}
+
+/** \ingroup asyncio
+ * Helper function to populate the required \ref libusb_transfer fields
+ * for an interrupt transfer.
+ *
+ * \param transfer the transfer to populate
+ * \param dev_handle handle of the device that will handle the transfer
+ * \param endpoint address of the endpoint where this transfer will be sent
+ * \param buffer data buffer
+ * \param length length of data buffer
+ * \param callback callback function to be invoked on transfer completion
+ * \param user_data user data to pass to callback function
+ * \param timeout timeout for the transfer in milliseconds
+ */
+static inline void libusb_fill_interrupt_transfer(
+ struct libusb_transfer *transfer, libusb_device_handle *dev_handle,
+ unsigned char endpoint, unsigned char *buffer, int length,
+ libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout)
+{
+ transfer->dev_handle = dev_handle;
+ transfer->endpoint = endpoint;
+ transfer->type = LIBUSB_TRANSFER_TYPE_INTERRUPT;
+ transfer->timeout = timeout;
+ transfer->buffer = buffer;
+ transfer->length = length;
+ transfer->user_data = user_data;
+ transfer->callback = callback;
+}
+
+/** \ingroup asyncio
+ * Helper function to populate the required \ref libusb_transfer fields
+ * for an isochronous transfer.
+ *
+ * \param transfer the transfer to populate
+ * \param dev_handle handle of the device that will handle the transfer
+ * \param endpoint address of the endpoint where this transfer will be sent
+ * \param buffer data buffer
+ * \param length length of data buffer
+ * \param num_iso_packets the number of isochronous packets
+ * \param callback callback function to be invoked on transfer completion
+ * \param user_data user data to pass to callback function
+ * \param timeout timeout for the transfer in milliseconds
+ */
+static inline void libusb_fill_iso_transfer(struct libusb_transfer *transfer,
+ libusb_device_handle *dev_handle, unsigned char endpoint,
+ unsigned char *buffer, int length, int num_iso_packets,
+ libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout)
+{
+ transfer->dev_handle = dev_handle;
+ transfer->endpoint = endpoint;
+ transfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS;
+ transfer->timeout = timeout;
+ transfer->buffer = buffer;
+ transfer->length = length;
+ transfer->num_iso_packets = num_iso_packets;
+ transfer->user_data = user_data;
+ transfer->callback = callback;
+}
+
+/** \ingroup asyncio
+ * Convenience function to set the length of all packets in an isochronous
+ * transfer, based on the num_iso_packets field in the transfer structure.
+ *
+ * \param transfer a transfer
+ * \param length the length to set in each isochronous packet descriptor
+ * \see libusb_get_max_packet_size()
+ */
+static inline void libusb_set_iso_packet_lengths(
+ struct libusb_transfer *transfer, unsigned int length)
+{
+ int i;
+ for (i = 0; i < transfer->num_iso_packets; i++)
+ transfer->iso_packet_desc[i].length = length;
+}
+
+/** \ingroup asyncio
+ * Convenience function to locate the position of an isochronous packet
+ * within the buffer of an isochronous transfer.
+ *
+ * This is a thorough function which loops through all preceding packets,
+ * accumulating their lengths to find the position of the specified packet.
+ * Typically you will assign equal lengths to each packet in the transfer,
+ * and hence the above method is sub-optimal. You may wish to use
+ * libusb_get_iso_packet_buffer_simple() instead.
+ *
+ * \param transfer a transfer
+ * \param packet the packet to return the address of
+ * \returns the base address of the packet buffer inside the transfer buffer,
+ * or NULL if the packet does not exist.
+ * \see libusb_get_iso_packet_buffer_simple()
+ */
+static inline unsigned char *libusb_get_iso_packet_buffer(
+ struct libusb_transfer *transfer, unsigned int packet)
+{
+ int i;
+ size_t offset = 0;
+ int _packet;
+
+ /* oops..slight bug in the API. packet is an unsigned int, but we use
+ * signed integers almost everywhere else. range-check and convert to
+ * signed to avoid compiler warnings. FIXME for libusb-2. */
+ if (packet > INT_MAX)
+ return NULL;
+ _packet = packet;
+
+ if (_packet >= transfer->num_iso_packets)
+ return NULL;
+
+ for (i = 0; i < _packet; i++)
+ offset += transfer->iso_packet_desc[i].length;
+
+ return transfer->buffer + offset;
+}
+
+/** \ingroup asyncio
+ * Convenience function to locate the position of an isochronous packet
+ * within the buffer of an isochronous transfer, for transfers where each
+ * packet is of identical size.
+ *
+ * This function relies on the assumption that every packet within the transfer
+ * is of identical size to the first packet. Calculating the location of
+ * the packet buffer is then just a simple calculation:
+ * <tt>buffer + (packet_size * packet)</tt>
+ *
+ * Do not use this function on transfers other than those that have identical
+ * packet lengths for each packet.
+ *
+ * \param transfer a transfer
+ * \param packet the packet to return the address of
+ * \returns the base address of the packet buffer inside the transfer buffer,
+ * or NULL if the packet does not exist.
+ * \see libusb_get_iso_packet_buffer()
+ */
+static inline unsigned char *libusb_get_iso_packet_buffer_simple(
+ struct libusb_transfer *transfer, unsigned int packet)
+{
+ int _packet;
+
+ /* oops..slight bug in the API. packet is an unsigned int, but we use
+ * signed integers almost everywhere else. range-check and convert to
+ * signed to avoid compiler warnings. FIXME for libusb-2. */
+ if (packet > INT_MAX)
+ return NULL;
+ _packet = packet;
+
+ if (_packet >= transfer->num_iso_packets)
+ return NULL;
+
+ return transfer->buffer + (transfer->iso_packet_desc[0].length * _packet);
+}
+
+/* sync I/O */
+
+int LIBUSB_CALL libusb_control_transfer(libusb_device_handle *dev_handle,
+ uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
+ unsigned char *data, uint16_t wLength, unsigned int timeout);
+
+int LIBUSB_CALL libusb_bulk_transfer(libusb_device_handle *dev_handle,
+ unsigned char endpoint, unsigned char *data, int length,
+ int *actual_length, unsigned int timeout);
+
+int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle,
+ unsigned char endpoint, unsigned char *data, int length,
+ int *actual_length, unsigned int timeout);
+
+/** \ingroup desc
+ * Retrieve a descriptor from the default control pipe.
+ * This is a convenience function which formulates the appropriate control
+ * message to retrieve the descriptor.
+ *
+ * \param dev a device handle
+ * \param desc_type the descriptor type, see \ref libusb_descriptor_type
+ * \param desc_index the index of the descriptor to retrieve
+ * \param data output buffer for descriptor
+ * \param length size of data buffer
+ * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure
+ */
+static inline int libusb_get_descriptor(libusb_device_handle *dev,
+ uint8_t desc_type, uint8_t desc_index, unsigned char *data, int length)
+{
+ return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN,
+ LIBUSB_REQUEST_GET_DESCRIPTOR, (desc_type << 8) | desc_index, 0, data,
+ (uint16_t) length, 1000);
+}
+
+/** \ingroup desc
+ * Retrieve a descriptor from a device.
+ * This is a convenience function which formulates the appropriate control
+ * message to retrieve the descriptor. The string returned is Unicode, as
+ * detailed in the USB specifications.
+ *
+ * \param dev a device handle
+ * \param desc_index the index of the descriptor to retrieve
+ * \param langid the language ID for the string descriptor
+ * \param data output buffer for descriptor
+ * \param length size of data buffer
+ * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure
+ * \see libusb_get_string_descriptor_ascii()
+ */
+static inline int libusb_get_string_descriptor(libusb_device_handle *dev,
+ uint8_t desc_index, uint16_t langid, unsigned char *data, int length)
+{
+ return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN,
+ LIBUSB_REQUEST_GET_DESCRIPTOR, (uint16_t)((LIBUSB_DT_STRING << 8) | desc_index),
+ langid, data, (uint16_t) length, 1000);
+}
+
+int LIBUSB_CALL libusb_get_string_descriptor_ascii(libusb_device_handle *dev,
+ uint8_t desc_index, unsigned char *data, int length);
+
+/* polling and timeouts */
+
+int LIBUSB_CALL libusb_try_lock_events(libusb_context *ctx);
+void LIBUSB_CALL libusb_lock_events(libusb_context *ctx);
+void LIBUSB_CALL libusb_unlock_events(libusb_context *ctx);
+int LIBUSB_CALL libusb_event_handling_ok(libusb_context *ctx);
+int LIBUSB_CALL libusb_event_handler_active(libusb_context *ctx);
+void LIBUSB_CALL libusb_lock_event_waiters(libusb_context *ctx);
+void LIBUSB_CALL libusb_unlock_event_waiters(libusb_context *ctx);
+int LIBUSB_CALL libusb_wait_for_event(libusb_context *ctx, struct timeval *tv);
+
+int LIBUSB_CALL libusb_handle_events_timeout(libusb_context *ctx,
+ struct timeval *tv);
+int LIBUSB_CALL libusb_handle_events_timeout_completed(libusb_context *ctx,
+ struct timeval *tv, int *completed);
+int LIBUSB_CALL libusb_handle_events(libusb_context *ctx);
+int LIBUSB_CALL libusb_handle_events_completed(libusb_context *ctx, int *completed);
+int LIBUSB_CALL libusb_handle_events_locked(libusb_context *ctx,
+ struct timeval *tv);
+int LIBUSB_CALL libusb_pollfds_handle_timeouts(libusb_context *ctx);
+int LIBUSB_CALL libusb_get_next_timeout(libusb_context *ctx,
+ struct timeval *tv);
+
+/** \ingroup poll
+ * File descriptor for polling
+ */
+struct libusb_pollfd {
+ /** Numeric file descriptor */
+ int fd;
+
+ /** Event flags to poll for from <poll.h>. POLLIN indicates that you
+ * should monitor this file descriptor for becoming ready to read from,
+ * and POLLOUT indicates that you should monitor this file descriptor for
+ * nonblocking write readiness. */
+ short events;
+};
+
+/** \ingroup poll
+ * Callback function, invoked when a new file descriptor should be added
+ * to the set of file descriptors monitored for events.
+ * \param fd the new file descriptor
+ * \param events events to monitor for, see \ref libusb_pollfd for a
+ * description
+ * \param user_data User data pointer specified in
+ * libusb_set_pollfd_notifiers() call
+ * \see libusb_set_pollfd_notifiers()
+ */
+typedef void (LIBUSB_CALL *libusb_pollfd_added_cb)(int fd, short events,
+ void *user_data);
+
+/** \ingroup poll
+ * Callback function, invoked when a file descriptor should be removed from
+ * the set of file descriptors being monitored for events. After returning
+ * from this callback, do not use that file descriptor again.
+ * \param fd the file descriptor to stop monitoring
+ * \param user_data User data pointer specified in
+ * libusb_set_pollfd_notifiers() call
+ * \see libusb_set_pollfd_notifiers()
+ */
+typedef void (LIBUSB_CALL *libusb_pollfd_removed_cb)(int fd, void *user_data);
+
+const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds(
+ libusb_context *ctx);
+void LIBUSB_CALL libusb_set_pollfd_notifiers(libusb_context *ctx,
+ libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb,
+ void *user_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: instr/drsctrl/libusb-1.0.lib
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/instr/drsctrl/libusb-1.0.lib
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: instr/drsctrl/musbstd.c
===================================================================
--- instr/drsctrl/musbstd.c (nonexistent)
+++ instr/drsctrl/musbstd.c (revision 195)
@@ -0,0 +1,700 @@
+/********************************************************************\
+
+ Name: musbstd.c
+ Created by: Konstantin Olchanski, Stefan Ritt
+
+ Contents: Midas USB access
+
+ $Id$
+
+\********************************************************************/
+
+#include <stdio.h>
+#include <assert.h>
+#include "musbstd.h"
+
+#ifdef _MSC_VER // Windows includes
+
+#include <windows.h>
+#include <conio.h>
+#include <winioctl.h>
+
+#include <setupapi.h>
+#include <initguid.h> /* Required for GUID definition */
+
+// link with SetupAPI.Lib.
+#pragma comment (lib, "setupapi.lib")
+
+// disable "deprecated" warning
+#pragma warning( disable: 4996)
+
+// {CBEB3FB1-AE9F-471c-9016-9B6AC6DCD323}
+DEFINE_GUID(GUID_CLASS_MSCB_BULK, 0xcbeb3fb1, 0xae9f, 0x471c, 0x90, 0x16, 0x9b, 0x6a, 0xc6, 0xdc, 0xd3, 0x23);
+
+#elif defined(OS_DARWIN)
+
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <fcntl.h>
+
+#include <assert.h>
+#include <mach/mach.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOCFPlugIn.h>
+#include <IOKit/usb/IOUSBLib.h>
+
+#elif defined(OS_LINUX) // Linux includes
+
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#endif
+
+#ifdef HAVE_LIBUSB
+#include <errno.h>
+#include "usb.h"
+#endif
+
+#ifdef HAVE_LIBUSB10
+#include <errno.h>
+#include <libusb-1.0/libusb.h>
+#endif
+
+#if !defined(HAVE_LIBUSB) && !defined(HAVE_LIBUSB10)
+#ifdef OS_DARWIN
+
+IOReturn darwin_configure_device(MUSB_INTERFACE* musb)
+{
+ IOReturn status;
+ io_iterator_t iter;
+ io_service_t service;
+ IOCFPlugInInterface **plugin;
+ SInt32 score;
+ IOUSBInterfaceInterface **uinterface;
+ UInt8 numend;
+
+ IOUSBDeviceInterface **device = (IOUSBDeviceInterface **)musb->device;
+
+ status = (*device)->SetConfiguration(device, musb->usb_configuration);
+ assert(status == kIOReturnSuccess);
+
+ IOUSBFindInterfaceRequest request;
+
+ request.bInterfaceClass = kIOUSBFindInterfaceDontCare;
+ request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
+ request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
+ request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
+
+ status = (*device)->CreateInterfaceIterator(device, &request, &iter);
+ assert(status == kIOReturnSuccess);
+
+ while ((service = IOIteratorNext(iter))) {
+ int i;
+ status =
+ IOCreatePlugInInterfaceForService(service, kIOUSBInterfaceUserClientTypeID,
+ kIOCFPlugInInterfaceID, &plugin, &score);
+ assert(status == kIOReturnSuccess);
+
+ status =
+ (*plugin)->QueryInterface(plugin, CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID),
+ (void *) &uinterface);
+ assert(status == kIOReturnSuccess);
+
+
+ status = (*uinterface)->USBInterfaceOpen(uinterface);
+ fprintf(stderr, "musb_open: USBInterfaceOpen status 0x%x\n", status);
+ assert(status == kIOReturnSuccess);
+
+ status = (*uinterface)->GetNumEndpoints(uinterface, &numend);
+ assert(status == kIOReturnSuccess);
+
+ fprintf(stderr, "musb_open: endpoints: %d\n", numend);
+
+ for (i=1; i<=numend; i++) {
+ status = (*uinterface)->GetPipeStatus(uinterface, i);
+ fprintf(stderr, "musb_open: pipe %d status: 0x%x\n", i, status);
+
+#if 0
+ status = (*uinterface)->ClearPipeStall(uinterface, i);
+ fprintf(stderr, "musb_open: pipe %d ClearPipeStall() status: 0x%x\n", i, status);
+ status = (*uinterface)->ResetPipe(uinterface, i);
+ fprintf(stderr, "musb_open: pipe %d ResetPipe() status: 0x%x\n", i, status);
+ status = (*uinterface)->AbortPipe(uinterface, i);
+ fprintf(stderr, "musb_open: pipe %d AbortPipe() status: 0x%x\n", i, status);
+#endif
+ }
+
+ musb->interface = uinterface;
+ return kIOReturnSuccess;
+ }
+
+ assert(!"Should never be reached!");
+ return -1;
+}
+
+#endif
+
+#endif
+
+int musb_open(MUSB_INTERFACE **musb_interface, int vendor, int product, int instance, int configuration, int usbinterface)
+{
+#if defined(HAVE_LIBUSB)
+
+ struct usb_bus *bus;
+ struct usb_device *dev;
+ int count = 0;
+
+ usb_init();
+ usb_find_busses();
+ usb_find_devices();
+ usb_set_debug(3);
+
+ for (bus = usb_get_busses(); bus; bus = bus->next)
+ for (dev = bus->devices; dev; dev = dev->next)
+ if (dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product) {
+ if (count == instance) {
+ int status;
+ usb_dev_handle *udev;
+
+ udev = usb_open(dev);
+ if (!udev) {
+ fprintf(stderr, "musb_open: usb_open() error\n");
+ return MUSB_ACCESS_ERROR;
+ }
+
+ status = usb_set_configuration(udev, configuration);
+ if (status < 0) {
+ fprintf(stderr, "musb_open: usb_set_configuration() error %d (%s)\n", status,
+ strerror(-status));
+ fprintf(stderr,
+ "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it: please check permissions on \"/proc/bus/usb/%s/%s\" and \"/dev/bus/usb/%s/%s\"\n",
+ vendor, product, instance, bus->dirname, dev->filename, bus->dirname, dev->filename);
+ return MUSB_ACCESS_ERROR;
+ }
+
+ /* see if we have write access */
+ status = usb_claim_interface(udev, usbinterface);
+ if (status < 0) {
+ fprintf(stderr, "musb_open: usb_claim_interface() error %d (%s)\n", status,
+ strerror(-status));
+
+#ifdef _MSC_VER
+ fprintf(stderr,
+ "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it:\nDevice is probably used by another program\n",
+ vendor, product, instance);
+#else
+ fprintf(stderr,
+ "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it: please check permissions on \"/proc/bus/usb/%s/%s\"\n",
+ vendor, product, instance, bus->dirname, dev->filename);
+#endif
+
+ return MUSB_ACCESS_ERROR;
+ }
+
+ *musb_interface = (MUSB_INTERFACE*)calloc(1, sizeof(MUSB_INTERFACE));
+ (*musb_interface)->dev = udev;
+ (*musb_interface)->usb_configuration = configuration;
+ (*musb_interface)->usb_interface = usbinterface;
+ return MUSB_SUCCESS;
+ }
+
+ count++;
+ }
+
+ return MUSB_NOT_FOUND;
+
+#elif defined(HAVE_LIBUSB10)
+
+ static int first_call = 1;
+
+ libusb_device **dev_list;
+ libusb_device_handle *dev;
+ struct libusb_device_descriptor desc;
+
+ int status, i, n;
+ int count = 0;
+
+ if (first_call) {
+ first_call = 0;
+ libusb_init(NULL);
+ // libusb_set_debug(NULL, 3);
+ }
+
+ n = libusb_get_device_list(NULL, &dev_list);
+
+ for (i=0 ; i<n ; i++) {
+ status = libusb_get_device_descriptor(dev_list[i], &desc);
+ if (desc.idVendor == vendor && desc.idProduct == product) {
+ if (count == instance) {
+ status = libusb_open(dev_list[i], &dev);
+ if (status < 0) {
+ fprintf(stderr, "musb_open: libusb_open() error %d\n", status);
+ return MUSB_ACCESS_ERROR;
+ }
+
+ status = libusb_set_configuration(dev, configuration);
+ if (status < 0) {
+ fprintf(stderr, "musb_open: usb_set_configuration() error %d\n", status);
+ fprintf(stderr,
+ "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it: please check permissions on \"/proc/bus/usb/%d/%d\" and \"/dev/bus/usb/%d/%d\"\n",
+ vendor, product, instance, libusb_get_bus_number(dev_list[i]), libusb_get_device_address(dev_list[i]), libusb_get_bus_number(dev_list[i]), libusb_get_device_address(dev_list[i]));
+ return MUSB_ACCESS_ERROR;
+ }
+
+ /* see if we have write access */
+ status = libusb_claim_interface(dev, usbinterface);
+ if (status < 0) {
+ fprintf(stderr, "musb_open: libusb_claim_interface() error %d\n", status);
+
+#ifdef _MSC_VER
+ fprintf(stderr,
+ "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it:\nDevice is probably used by another program\n",
+ vendor, product, instance);
+#else
+ fprintf(stderr,
+ "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it: please check permissions on \"/proc/bus/usb/%d/%d\"\n",
+ vendor, product, instance, libusb_get_bus_number(dev_list[i]), libusb_get_device_address(dev_list[i]));
+#endif
+
+ return MUSB_ACCESS_ERROR;
+ }
+
+ *musb_interface = (MUSB_INTERFACE*)calloc(1, sizeof(MUSB_INTERFACE));
+ (*musb_interface)->dev = dev;
+ (*musb_interface)->usb_configuration = configuration;
+ (*musb_interface)->usb_interface = usbinterface;
+ return MUSB_SUCCESS;
+
+ }
+ count++;
+ }
+ }
+
+ libusb_free_device_list(dev_list, 1);
+
+ return MUSB_NOT_FOUND;
+
+#elif defined(OS_DARWIN)
+
+ kern_return_t status;
+ io_iterator_t iter;
+ io_service_t service;
+ IOCFPlugInInterface **plugin;
+ SInt32 score;
+ IOUSBDeviceInterface **device;
+ UInt16 xvendor, xproduct;
+ int count = 0;
+
+ *musb_interface = calloc(1, sizeof(MUSB_INTERFACE));
+
+ status = IORegistryCreateIterator(kIOMasterPortDefault, kIOUSBPlane, kIORegistryIterateRecursively, &iter);
+ assert(status == kIOReturnSuccess);
+
+ while ((service = IOIteratorNext(iter))) {
+ status =
+ IOCreatePlugInInterfaceForService(service, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID,
+ &plugin, &score);
+ assert(status == kIOReturnSuccess);
+
+ status = IOObjectRelease(service);
+ assert(status == kIOReturnSuccess);
+
+ status =
+ (*plugin)->QueryInterface(plugin, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (void *) &device);
+ assert(status == kIOReturnSuccess);
+
+ status = (*plugin)->Release(plugin);
+
+ status = (*device)->GetDeviceVendor(device, &xvendor);
+ assert(status == kIOReturnSuccess);
+ status = (*device)->GetDeviceProduct(device, &xproduct);
+ assert(status == kIOReturnSuccess);
+
+ //fprintf(stderr, "musb_open: Found USB device: vendor 0x%04x, product 0x%04x\n", xvendor, xproduct);
+
+ if (xvendor == vendor && xproduct == product) {
+ if (count == instance) {
+
+ fprintf(stderr, "musb_open: Found USB device: vendor 0x%04x, product 0x%04x, instance %d\n", xvendor, xproduct, instance);
+
+ status = (*device)->USBDeviceOpen(device);
+ fprintf(stderr, "musb_open: USBDeviceOpen status 0x%x\n", status);
+
+ assert(status == kIOReturnSuccess);
+
+ (*musb_interface)->usb_configuration = configuration;
+ (*musb_interface)->usb_interface = usbinterface;
+ (*musb_interface)->device = (void*)device;
+ (*musb_interface)->interface = NULL;
+
+ status = darwin_configure_device(*musb_interface);
+
+ if (status == kIOReturnSuccess)
+ return MUSB_SUCCESS;
+
+ fprintf(stderr, "musb_open: USB device exists, but configuration fails!");
+ return MUSB_NOT_FOUND;
+ }
+
+ count++;
+ }
+
+ (*device)->Release(device);
+ }
+
+ return MUSB_NOT_FOUND;
+#elif defined(_MSC_VER)
+ GUID guid;
+ HDEVINFO hDevInfoList;
+ SP_DEVICE_INTERFACE_DATA deviceInfoData;
+ PSP_DEVICE_INTERFACE_DETAIL_DATA functionClassDeviceData;
+ ULONG predictedLength, requiredLength;
+ int status;
+ char device_name[256], str[256];
+
+ *musb_interface = (MUSB_INTERFACE *)calloc(1, sizeof(MUSB_INTERFACE));
+
+ guid = GUID_CLASS_MSCB_BULK;
+
+ // Retrieve device list for GUID that has been specified.
+ hDevInfoList = SetupDiGetClassDevs(&guid, NULL, NULL, (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
+
+ status = FALSE;
+ if (hDevInfoList != NULL) {
+
+ // Clear data structure
+ memset(&deviceInfoData, 0, sizeof(deviceInfoData));
+ deviceInfoData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+
+ // retrieves a context structure for a device interface of a device information set.
+ if (SetupDiEnumDeviceInterfaces(hDevInfoList, 0, &guid, instance, &deviceInfoData)) {
+ // Must get the detailed information in two steps
+ // First get the length of the detailed information and allocate the buffer
+ // retrieves detailed information about a specified device interface.
+ functionClassDeviceData = NULL;
+
+ predictedLength = requiredLength = 0;
+
+ SetupDiGetDeviceInterfaceDetail(hDevInfoList, &deviceInfoData, NULL, // Not yet allocated
+ 0, // Set output buffer length to zero
+ &requiredLength, // Find out memory requirement
+ NULL);
+
+ predictedLength = requiredLength;
+ functionClassDeviceData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) malloc(predictedLength);
+ functionClassDeviceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
+
+ // Second, get the detailed information
+ if (SetupDiGetDeviceInterfaceDetail(hDevInfoList,
+ &deviceInfoData, functionClassDeviceData,
+ predictedLength, &requiredLength, NULL)) {
+
+ // Save the device name for subsequent pipe open calls
+ strcpy(device_name, functionClassDeviceData->DevicePath);
+ free(functionClassDeviceData);
+
+ // Signal device found
+ status = TRUE;
+ } else
+ free(functionClassDeviceData);
+ }
+ }
+ // SetupDiDestroyDeviceInfoList() destroys a device information set
+ // and frees all associated memory.
+ SetupDiDestroyDeviceInfoList(hDevInfoList);
+
+ if (status) {
+
+ // Get the read handle
+ sprintf(str, "%s\\PIPE00", device_name);
+ (*musb_interface)->rhandle = CreateFile(str,
+ GENERIC_WRITE | GENERIC_READ,
+ FILE_SHARE_WRITE | FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+
+ if ((*musb_interface)->rhandle == INVALID_HANDLE_VALUE)
+ return MUSB_ACCESS_ERROR;
+
+ // Get the write handle
+ sprintf(str, "%s\\PIPE01", device_name);
+ (*musb_interface)->whandle = CreateFile(str,
+ GENERIC_WRITE | GENERIC_READ,
+ FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+
+ if ((*musb_interface)->whandle == INVALID_HANDLE_VALUE)
+ return MUSB_ACCESS_ERROR;
+
+ return MUSB_SUCCESS;
+ }
+
+ return MUSB_NOT_FOUND;
+#endif
+}
+
+int musb_set_altinterface(MUSB_INTERFACE *musb_interface, int index)
+{
+#if defined (HAVE_LIBUSB)
+ int status;
+
+ status = usb_set_altinterface(musb_interface->dev, index);
+ if (status < 0)
+ fprintf(stderr, "musb_set_altinterface: usb_set_altinterface() error %d\n", status);
+
+ return status;
+#else
+ return -1;
+#endif
+}
+
+int musb_close(MUSB_INTERFACE *musb_interface)
+{
+#if defined(HAVE_LIBUSB)
+
+ int status;
+ status = usb_release_interface(musb_interface->dev, musb_interface->usb_interface);
+ if (status < 0)
+ fprintf(stderr, "musb_close: usb_release_interface() error %d\n", status);
+
+#ifdef OS_LINUX // linux wants a reset, otherwise the device cannot be accessed next time
+ musb_reset(musb_interface);
+#endif
+
+ status = usb_close(musb_interface->dev);
+ if (status < 0)
+ fprintf(stderr, "musb_close: usb_close() error %d\n", status);
+
+#elif defined(HAVE_LIBUSB10)
+
+ int status;
+ status = libusb_release_interface(musb_interface->dev, musb_interface->usb_interface);
+ if (status < 0)
+ fprintf(stderr, "musb_close: libusb_release_interface() error %d\n", status);
+
+#ifdef OS_LINUX // linux wants a reset, otherwise the device cannot be accessed next time
+ musb_reset(musb_interface);
+#endif
+
+ libusb_close(musb_interface->dev);
+
+#elif defined(OS_DARWIN)
+
+ IOReturn status;
+ IOUSBInterfaceInterface **interface = (IOUSBInterfaceInterface **)musb_interface->interface;
+
+ status = (*interface)->USBInterfaceClose(interface);
+ if (status != kIOReturnSuccess)
+ fprintf(stderr, "musb_close: USBInterfaceClose() status %d 0x%x\n", status, status);
+
+ status = (*interface)->Release(interface);
+ if (status != kIOReturnSuccess)
+ fprintf(stderr, "musb_close: USB Interface Release() status %d 0x%x\n", status, status);
+
+ IOUSBDeviceInterface **device = (IOUSBDeviceInterface**)musb_interface->device;
+ status = (*device)->USBDeviceClose(device);
+ if (status != kIOReturnSuccess)
+ fprintf(stderr, "musb_close: USBDeviceClose() status %d 0x%x\n", status, status);
+
+ status = (*device)->Release(device);
+ if (status != kIOReturnSuccess)
+ fprintf(stderr, "musb_close: USB Device Release() status %d 0x%x\n", status, status);
+
+#elif defined(_MSC_VER)
+
+ CloseHandle(musb_interface->rhandle);
+ CloseHandle(musb_interface->whandle);
+
+#else
+ assert(!"musb_close() is not implemented");
+#endif
+
+ /* free memory allocated in musb_open() */
+ free(musb_interface);
+ return 0;
+}
+
+int musb_write(MUSB_INTERFACE *musb_interface, int endpoint, const void *buf, int count, int timeout)
+{
+ int n_written;
+
+#if defined(HAVE_LIBUSB)
+ n_written = usb_bulk_write(musb_interface->dev, endpoint, (char*)buf, count, timeout);
+ if (n_written != count) {
+ fprintf(stderr, "musb_write: requested %d, wrote %d, errno %d (%s)\n", count, n_written, errno, strerror(errno));
+ }
+#elif defined(HAVE_LIBUSB10)
+ int status = libusb_bulk_transfer(musb_interface->dev, endpoint, (unsigned char*)buf, count, &n_written, timeout);
+ if (n_written != count) {
+ fprintf(stderr, "musb_write: requested %d, wrote %d, errno %d (%s)\n", count, n_written, status, strerror(status));
+ }
+#elif defined(OS_DARWIN)
+ IOReturn status;
+ IOUSBInterfaceInterface182 **interface = (IOUSBInterfaceInterface182 **)musb_interface->interface;
+ status = (*interface)->WritePipeTO(interface, endpoint, buf, count, 0, timeout);
+ if (status != 0) {
+ fprintf(stderr, "musb_write: WritePipe() status %d 0x%x\n", status, status);
+ return -1;
+ }
+ n_written = count;
+#elif defined(_MSC_VER)
+ WriteFile(musb_interface->whandle, buf, count, &n_written, NULL);
+#endif
+
+ //fprintf(stderr, "musb_write(ep %d, %d bytes) (%s) returns %d\n", endpoint, count, buf, n_written);
+
+ return n_written;
+}
+
+int musb_read(MUSB_INTERFACE *musb_interface, int endpoint, void *buf, int count, int timeout)
+{
+ int n_read = 0;
+
+#if defined(HAVE_LIBUSB)
+
+ n_read = usb_bulk_read(musb_interface->dev, endpoint | 0x80, (char*)buf, count, timeout);
+ /* errors should be handled in upper layer ....
+ if (n_read <= 0) {
+ fprintf(stderr, "musb_read: requested %d, read %d, errno %d (%s)\n", count, n_read, errno, strerror(errno));
+ }
+ */
+
+#elif defined(HAVE_LIBUSB10)
+
+ libusb_bulk_transfer(musb_interface->dev, endpoint | 0x80, (unsigned char*)buf, count, &n_read, timeout);
+ /* errors should be handled in upper layer ....
+ if (n_read <= 0) {
+ fprintf(stderr, "musb_read: requested %d, read %d, errno %d (%s)\n", count, n_read, status, strerror(status));
+ }
+ */
+
+#elif defined(OS_DARWIN)
+
+ UInt32 xcount = count;
+ IOReturn status;
+ IOUSBInterfaceInterface182 **interface = (IOUSBInterfaceInterface182 **)musb_interface->interface;
+
+ status = (*interface)->ReadPipeTO(interface, endpoint, buf, &xcount, 0, timeout);
+ if (status != kIOReturnSuccess) {
+ fprintf(stderr, "musb_read: requested %d, read %d, ReadPipe() status %d 0x%x (%s)\n", count, n_read, status, status, strerror(status));
+ return -1;
+ }
+
+ n_read = xcount;
+
+#elif defined(_MSC_VER)
+
+ OVERLAPPED overlapped;
+ int status;
+
+ memset(&overlapped, 0, sizeof(overlapped));
+ overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ n_read = 0;
+
+ status = ReadFile(musb_interface->rhandle, buf, count, &n_read, &overlapped);
+
+ if (!status) {
+
+ status = GetLastError();
+ if (status != ERROR_IO_PENDING)
+ return 0;
+
+ /* wait for completion with timeout */
+ status = WaitForSingleObject(overlapped.hEvent, timeout);
+ if (status == WAIT_TIMEOUT)
+ CancelIo(musb_interface->rhandle);
+ else
+ GetOverlappedResult(musb_interface->rhandle, &overlapped, &n_read, FALSE);
+ }
+
+ CloseHandle(overlapped.hEvent);
+
+#endif
+
+ //fprintf(stderr, "musb_read(ep %d, %d bytes) returns %d (%s)\n", endpoint, count, n_read, buf);
+
+ return n_read;
+}
+
+int musb_reset(MUSB_INTERFACE *musb_interface)
+{
+#if defined(HAVE_LIBUSB)
+
+ /* Causes re-enumeration: After calling usb_reset, the device will need
+ to re-enumerate and thusly, requires you to find the new device and
+ open a new handle. The handle used to call usb_reset will no longer work */
+
+ int status;
+ status = usb_reset(musb_interface->dev);
+ if (status < 0)
+ fprintf(stderr, "musb_reset: usb_reset() status %d\n", status);
+
+#elif defined(HAVE_LIBUSB10)
+
+ int status;
+ status = libusb_reset_device(musb_interface->dev);
+ if (status < 0)
+ fprintf(stderr, "musb_reset: usb_reset() status %d\n", status);
+
+#elif defined(OS_DARWIN)
+
+ IOReturn status;
+ IOUSBDeviceInterface **device = (IOUSBDeviceInterface**)musb_interface->device;
+
+ status = (*device)->ResetDevice(device);
+ fprintf(stderr, "musb_reset: ResetDevice() status 0x%x\n", status);
+
+ status = darwin_configure_device(musb_interface);
+ assert(status == kIOReturnSuccess);
+
+#elif defined(_MSC_VER)
+
+#define IOCTL_BULKUSB_RESET_DEVICE CTL_CODE(FILE_DEVICE_UNKNOWN, \
+ 1, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+#define IOCTL_BULKUSB_RESET_PIPE CTL_CODE(FILE_DEVICE_UNKNOWN, \
+ 2, \
+ METHOD_BUFFERED, \
+ FILE_ANY_ACCESS)
+
+ int status, n_bytes;
+
+ status = DeviceIoControl(musb_interface->rhandle,
+ IOCTL_BULKUSB_RESET_DEVICE,
+ NULL, 0, NULL, 0, &n_bytes, NULL);
+ status = DeviceIoControl(musb_interface->whandle,
+ IOCTL_BULKUSB_RESET_DEVICE,
+ NULL, 0, NULL, 0, &n_bytes, NULL);
+ status = DeviceIoControl(musb_interface->rhandle,
+ IOCTL_BULKUSB_RESET_PIPE,
+ NULL, 0, NULL, 0, &n_bytes, NULL);
+ status = DeviceIoControl(musb_interface->whandle,
+ IOCTL_BULKUSB_RESET_PIPE,
+ NULL, 0, NULL, 0, &n_bytes, NULL);
+ return status;
+
+#endif
+ return 0;
+}
+
+int musb_get_device(MUSB_INTERFACE *usb_interface)
+{
+#ifdef HAVE_LIBUSB
+ struct usb_device_descriptor d;
+ usb_get_descriptor(usb_interface->dev, USB_DT_DEVICE, 0, &d, sizeof(d));
+ return d.bcdDevice;
+#elif HAVE_LIBUSB10
+ struct libusb_device_descriptor d;
+ libusb_get_descriptor(usb_interface->dev, LIBUSB_DT_DEVICE, 0, (unsigned char *)&d, sizeof(d));
+ return d.bcdDevice;
+#else
+ return 0;
+#endif
+}
+
+/* end */
Index: instr/drsctrl/musbstd.h
===================================================================
--- instr/drsctrl/musbstd.h (nonexistent)
+++ instr/drsctrl/musbstd.h (revision 195)
@@ -0,0 +1,95 @@
+/********************************************************************\
+
+ Name: musbstd.h
+ Created by: Konstantin Olchanski, Stefan Ritt
+
+ Contents: Midas USB access
+
+ $Id$
+
+\********************************************************************/
+
+#ifndef MUSBSTD_H
+#define MUSBSTD_H
+
+#if defined(HAVE_LIBUSB)
+
+#include "usb.h"
+
+typedef struct {
+ usb_dev_handle *dev;
+ int usb_configuration;
+ int usb_interface;
+ int usb_type;
+} MUSB_INTERFACE;
+
+#elif defined(HAVE_LIBUSB10)
+
+#include <libusb-1.0/libusb.h>
+
+typedef struct {
+ libusb_device_handle *dev;
+ int usb_configuration;
+ int usb_interface;
+ int usb_type;
+} MUSB_INTERFACE;
+
+#elif defined(_MSC_VER)
+
+#include <windows.h>
+
+typedef struct {
+ HANDLE rhandle;
+ HANDLE whandle;
+ int usb_type;
+} MUSB_INTERFACE;
+
+#elif defined(OS_DARWIN)
+
+typedef struct {
+ void *device;
+ void *interface;
+ int usb_configuration;
+ int usb_interface;
+ int usb_type;
+} MUSB_INTERFACE;
+
+#else
+#error Do not know how to access USB devices
+#endif
+
+/*---- status codes ------------------------------------------------*/
+
+#define MUSB_SUCCESS 1
+#define MUSB_NOT_FOUND 2
+#define MUSB_INVALID_PARAM 3
+#define MUSB_NO_MEM 4
+#define MUSB_ACCESS_ERROR 5
+
+/* make functions callable from a C++ program */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* make functions under WinNT dll exportable */
+#ifndef EXPRT
+#if defined(_MSC_VER) && defined(_USRDLL)
+#define EXPRT __declspec(dllexport)
+#else
+#define EXPRT
+#endif
+#endif
+
+int EXPRT musb_open(MUSB_INTERFACE **musb_interface, int vendor, int product, int instance, int configuration, int usbinterface);
+int EXPRT musb_close(MUSB_INTERFACE *musb_interface);
+int EXPRT musb_write(MUSB_INTERFACE *musb_interface,int endpoint,const void *buf,int count,int timeout_ms);
+int EXPRT musb_read(MUSB_INTERFACE *musb_interface,int endpoint,void *buf,int count,int timeout_ms);
+int EXPRT musb_reset(MUSB_INTERFACE *musb_interface);
+int EXPRT musb_set_altinterface(MUSB_INTERFACE *musb_interface, int index);
+int EXPRT musb_get_device(MUSB_INTERFACE *musb_interface);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MUSBSTD_H
Index: instr/drsctrl/musbstd.obj
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/instr/drsctrl/musbstd.obj
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: instr/drsctrl/mxml.c
===================================================================
--- instr/drsctrl/mxml.c (nonexistent)
+++ instr/drsctrl/mxml.c (revision 195)
@@ -0,0 +1,2366 @@
+/********************************************************************\
+
+ Name: mxml.c
+ Created by: Stefan Ritt
+ Copyright 2000 + Stefan Ritt
+
+ Contents: Midas XML Library
+
+ This is a simple implementation of XML functions for writing and
+ reading XML files. For writing an XML file from scratch, following
+ functions can be used:
+
+ writer = mxml_open_file(file_name);
+ mxml_start_element(writer, name);
+ mxml_write_attribute(writer, name, value);
+ mxml_write_value(writer, value);
+ mxml_end_element(writer);
+ ...
+ mxml_close_file(writer);
+
+ To read an XML file, the function
+
+ tree = mxml_parse_file(file_name, error, sizeof(error));
+
+ is used. It parses the complete XML file and stores it in a
+ hierarchical tree in memory. Nodes in that tree can be searched
+ for with
+
+ mxml_find_node(tree, xml_path);
+
+ or
+
+ mxml_find_nodes(tree, xml_path, &nodelist);
+
+ which support a subset of the XPath specification. Another set of
+ functions is availabe to retrieve attributes and values from nodes
+ in the tree and for manipulating nodes, like replacing, adding and
+ deleting nodes.
+
+
+ This file is part of MIDAS XML Library.
+
+ MIDAS XML Library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MIDAS XML Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MIDAS XML Library. If not, see <http://www.gnu.org/licenses/>.
+
+\********************************************************************/
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+
+#ifdef _MSC_VER
+
+#include <windows.h>
+#include <io.h>
+#include <time.h>
+
+#pragma warning( disable: 4996) /* disable "deprecated" warning */
+
+#else
+
+#define TRUE 1
+#define FALSE 0
+
+#ifndef O_TEXT
+#define O_TEXT 0
+#define O_BINARY 0
+#endif
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <errno.h>
+#ifndef OS_VXWORKS
+#include <sys/time.h>
+#endif
+#include <time.h>
+
+#endif
+
+#include "mxml.h"
+#ifndef HAVE_STRLCPY
+#include "strlcpy.h"
+#endif
+
+#define XML_INDENT " "
+
+#if defined(__GNUC__) && !defined(__MAKECINT__)
+# define MXML_GNUC_PRINTF( format_idx, arg_idx ) \
+ __attribute__((format (printf, format_idx, arg_idx)))
+# define MXML_GNUC_SCANF( format_idx, arg_idx ) \
+ __attribute__((format (scanf, format_idx, arg_idx)))
+# define MXML_GNUC_FORMAT( arg_idx ) \
+ __attribute__((format_arg (arg_idx)))
+#else
+# define MXML_GNUC_PRINTF( format_idx, arg_idx )
+# define MXML_GNUC_SCANF( format_idx, arg_idx )
+# define MXML_GNUC_FORMAT( arg_idx )
+#endif
+
+static int mxml_suppress_date_flag = 0; /* suppress writing date at the top of file. */
+
+/* local prototypes */
+static PMXML_NODE read_error(PMXML_NODE root, const char *file_name, int line_number, char *error, int error_size, int *error_line, const char *format, ...) MXML_GNUC_PRINTF(7, 8);
+static void mxml_encode(char *src, int size, int translate);
+static void mxml_decode(char *str);
+static int mxml_write_subtree(MXML_WRITER *writer, PMXML_NODE tree, int indent);
+static int mxml_write_line(MXML_WRITER *writer, const char *line);
+static int mxml_start_element1(MXML_WRITER *writer, const char *name, int indent);
+static int mxml_add_resultnode(PMXML_NODE node, const char *xml_path, PMXML_NODE **nodelist, int *found);
+static int mxml_find_nodes1(PMXML_NODE tree, const char *xml_path, PMXML_NODE **nodelist, int *found);
+static void *mxml_malloc(size_t size);
+static void *mxml_realloc(void *p, size_t size);
+static void mxml_free(void *p);
+static void mxml_deallocate(void);
+
+/*------------------------------------------------------------------*/
+
+static char *_encode_buffer = NULL;
+static char *_data_enc = NULL;
+
+/*------------------------------------------------------------------*/
+
+void *mxml_malloc(size_t size)
+{
+ return malloc(size);
+}
+
+/*------------------------------------------------------------------*/
+
+void *mxml_realloc(void *p, size_t size)
+{
+ return realloc(p, size);
+}
+
+/*------------------------------------------------------------------*/
+
+void mxml_free(void *p)
+{
+ free(p);
+}
+
+/*------------------------------------------------------------------*/
+
+void mxml_deallocate(void)
+{
+ if (_encode_buffer != NULL) {
+ mxml_free(_encode_buffer);
+ _encode_buffer = NULL;
+ }
+ if (_data_enc != NULL) {
+ mxml_free(_data_enc);
+ _data_enc = NULL;
+ }
+}
+
+/*------------------------------------------------------------------*/
+
+int mxml_write_line(MXML_WRITER *writer, const char *line)
+{
+ int len;
+
+ len = (int)strlen(line);
+
+ if (writer->buffer) {
+ if (writer->buffer_len + len >= writer->buffer_size) {
+ writer->buffer_size += 10000;
+ writer->buffer = (char *)mxml_realloc(writer->buffer, writer->buffer_size);
+ }
+ strcpy(writer->buffer + writer->buffer_len, line);
+ writer->buffer_len += len;
+ return len;
+ } else {
+ return (int)write(writer->fh, line, len);
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * open a memory buffer and write XML header
+ */
+MXML_WRITER *mxml_open_buffer(void)
+{
+ char str[256], line[1000];
+ time_t now;
+ MXML_WRITER *writer;
+
+ writer = (MXML_WRITER *)mxml_malloc(sizeof(MXML_WRITER));
+ memset(writer, 0, sizeof(MXML_WRITER));
+ writer->translate = 1;
+
+ writer->buffer_size = 10000;
+ writer->buffer = (char *)mxml_malloc(10000);
+ writer->buffer[0] = 0;
+ writer->buffer_len = 0;
+
+ /* write XML header */
+ strcpy(line, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
+ mxml_write_line(writer, line);
+ time(&now);
+ strcpy(str, ctime(&now));
+ str[24] = 0;
+ sprintf(line, "<!-- created by MXML on %s -->\n", str);
+ if (mxml_suppress_date_flag == 0)
+ mxml_write_line(writer, line);
+
+ /* initialize stack */
+ writer->level = 0;
+ writer->element_is_open = 0;
+
+ return writer;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * suppress writing date at the top of file.
+ */
+void mxml_suppress_date(int suppress)
+{
+ mxml_suppress_date_flag = suppress;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * open a file and write XML header
+ */
+MXML_WRITER *mxml_open_file(const char *file_name)
+{
+ char str[256], line[1000];
+ time_t now;
+ MXML_WRITER *writer;
+
+ writer = (MXML_WRITER *)mxml_malloc(sizeof(MXML_WRITER));
+ memset(writer, 0, sizeof(MXML_WRITER));
+ writer->translate = 1;
+
+ writer->fh = open(file_name, O_RDWR | O_CREAT | O_TRUNC | O_TEXT, 0644);
+
+ if (writer->fh == -1) {
+ sprintf(line, "Unable to open file \"%s\": ", file_name);
+ perror(line);
+ mxml_free(writer);
+ return NULL;
+ }
+
+ /* write XML header */
+ strcpy(line, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
+ mxml_write_line(writer, line);
+ time(&now);
+ strcpy(str, ctime(&now));
+ str[24] = 0;
+ sprintf(line, "<!-- created by MXML on %s -->\n", str);
+ if (mxml_suppress_date_flag == 0)
+ mxml_write_line(writer, line);
+
+ /* initialize stack */
+ writer->level = 0;
+ writer->element_is_open = 0;
+
+ return writer;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * convert '<' '>' '&' '"' ''' into &xx;
+ */
+void mxml_encode(char *src, int size, int translate)
+{
+ char *ps, *pd;
+ static int buffer_size = 1000;
+
+ assert(size);
+
+ if (_encode_buffer == NULL) {
+ _encode_buffer = (char *) mxml_malloc(buffer_size);
+ atexit(mxml_deallocate);
+ }
+
+ if (size > buffer_size) {
+ _encode_buffer = (char *) mxml_realloc(_encode_buffer, size*2);
+ buffer_size = size;
+ }
+
+ pd = _encode_buffer;
+ for (ps = src ; *ps && (size_t)pd - (size_t)_encode_buffer < (size_t)(size-10) ; ps++) {
+
+ if (translate) { /* tranlate "<", ">", "&", """, "'" */
+ switch (*ps) {
+ case '<':
+ strcpy(pd, "&lt;");
+ pd += 4;
+ break;
+ case '>':
+ strcpy(pd, "&gt;");
+ pd += 4;
+ break;
+ case '&':
+ strcpy(pd, "&amp;");
+ pd += 5;
+ break;
+ case '\"':
+ strcpy(pd, "&quot;");
+ pd += 6;
+ break;
+ case '\'':
+ strcpy(pd, "&apos;");
+ pd += 6;
+ break;
+ default:
+ *pd++ = *ps;
+ }
+ } else {
+ switch (*ps) { /* translate only illegal XML characters "<" and "&" */
+ case '<':
+ strcpy(pd, "&lt;");
+ pd += 4;
+ break;
+ case '&':
+ strcpy(pd, "&amp;");
+ pd += 5;
+ break;
+ default:
+ *pd++ = *ps;
+ }
+ }
+ }
+ *pd = 0;
+
+ strlcpy(src, _encode_buffer, size);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * reverse of mxml_encode, strip leading or trailing '"'
+ */
+void mxml_decode(char *str)
+{
+ char *p;
+
+ p = str;
+ while ((p = strchr(p, '&')) != NULL) {
+ if (strncmp(p, "&lt;", 4) == 0) {
+ *(p++) = '<';
+ memmove(p, p+3, strlen(p+3) + 1);
+ }
+ else if (strncmp(p, "&gt;", 4) == 0) {
+ *(p++) = '>';
+ memmove(p, p+3, strlen(p+3) + 1);
+ }
+ else if (strncmp(p, "&amp;", 5) == 0) {
+ *(p++) = '&';
+ memmove(p, p+4, strlen(p+4) + 1);
+ }
+ else if (strncmp(p, "&quot;", 6) == 0) {
+ *(p++) = '\"';
+ memmove(p, p+5, strlen(p+5) + 1);
+ }
+ else if (strncmp(p, "&apos;", 6) == 0) {
+ *(p++) = '\'';
+ memmove(p, p+5, strlen(p+5) + 1);
+ }
+ else {
+ p++; // skip unknown entity
+ }
+ }
+/* if (str[0] == '\"' && str[strlen(str)-1] == '\"') {
+ memmove(str, str+1, strlen(str+1) + 1);
+ str[strlen(str)-1] = 0;
+ }*/
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * set translation of <,>,",',&, on/off in writer
+ */
+int mxml_set_translate(MXML_WRITER *writer, int flag)
+{
+ int old_flag;
+
+ old_flag = writer->translate;
+ writer->translate = flag;
+ return old_flag;
+}
+/*------------------------------------------------------------------*/
+
+/**
+ * start a new XML element, must be followed by mxml_end_elemnt
+ */
+int mxml_start_element1(MXML_WRITER *writer, const char *name, int indent)
+{
+ int i;
+ char line[1000], name_enc[1000];
+
+ if (writer->element_is_open) {
+ mxml_write_line(writer, ">\n");
+ writer->element_is_open = FALSE;
+ }
+
+ line[0] = 0;
+ if (indent)
+ for (i=0 ; i<writer->level ; i++)
+ strlcat(line, XML_INDENT, sizeof(line));
+ strlcat(line, "<", sizeof(line));
+ strlcpy(name_enc, name, sizeof(name_enc));
+ mxml_encode(name_enc, sizeof(name_enc), writer->translate);
+ strlcat(line, name_enc, sizeof(line));
+
+ /* put element on stack */
+ if (writer->level == 0)
+ writer->stack = (char **)mxml_malloc(sizeof(char *));
+ else
+ writer->stack = (char **)mxml_realloc(writer->stack, sizeof(char *)*(writer->level+1));
+
+ writer->stack[writer->level] = (char *) mxml_malloc(strlen(name_enc)+1);
+ strcpy(writer->stack[writer->level], name_enc);
+ writer->level++;
+ writer->element_is_open = TRUE;
+ writer->data_was_written = FALSE;
+
+ return mxml_write_line(writer, line) == (int)strlen(line);
+}
+
+/*------------------------------------------------------------------*/
+
+int mxml_start_element(MXML_WRITER *writer, const char *name)
+{
+ return mxml_start_element1(writer, name, TRUE);
+}
+
+/*------------------------------------------------------------------*/
+
+int mxml_start_element_noindent(MXML_WRITER *writer, const char *name)
+{
+ return mxml_start_element1(writer, name, FALSE);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * close an open XML element
+ */
+int mxml_end_element(MXML_WRITER *writer)
+{
+ int i;
+ char line[1000];
+
+ if (writer->level == 0)
+ return 0;
+
+ writer->level--;
+
+ if (writer->element_is_open) {
+ writer->element_is_open = FALSE;
+ mxml_free(writer->stack[writer->level]);
+ if (writer->level == 0)
+ mxml_free(writer->stack);
+ strcpy(line, "/>\n");
+ return mxml_write_line(writer, line) == (int)strlen(line);
+ }
+
+ line[0] = 0;
+ if (!writer->data_was_written) {
+ for (i=0 ; i<writer->level ; i++)
+ strlcat(line, XML_INDENT, sizeof(line));
+ }
+
+ strlcat(line, "</", sizeof(line));
+ strlcat(line, writer->stack[writer->level], sizeof(line));
+ mxml_free(writer->stack[writer->level]);
+ if (writer->level == 0)
+ mxml_free(writer->stack);
+ strlcat(line, ">\n", sizeof(line));
+ writer->data_was_written = FALSE;
+
+ return mxml_write_line(writer, line) == (int)strlen(line);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * write an attribute to the currently open XML element
+ */
+int mxml_write_attribute(MXML_WRITER *writer, const char *name, const char *value)
+{
+ char name_enc[4096], val_enc[4096], line[8192];
+
+ if (!writer->element_is_open)
+ return FALSE;
+
+ strcpy(name_enc, name);
+ mxml_encode(name_enc, sizeof(name_enc), writer->translate);
+ strcpy(val_enc, value);
+ mxml_encode(val_enc, sizeof(val_enc), writer->translate);
+
+ sprintf(line, " %s=\"%s\"", name_enc, val_enc);
+
+ return mxml_write_line(writer, line) == (int)strlen(line);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * write value of an XML element, like <[name]>[value]</[name]>
+ */
+int mxml_write_value(MXML_WRITER *writer, const char *data)
+{
+ static int data_size = 0;
+
+ if (!writer->element_is_open)
+ return FALSE;
+
+ if (mxml_write_line(writer, ">") != 1)
+ return FALSE;
+ writer->element_is_open = FALSE;
+ writer->data_was_written = TRUE;
+
+ if (data_size == 0) {
+ _data_enc = (char *)mxml_malloc(1000);
+ data_size = 1000;
+ } else if ((int)strlen(data)*2+1000 > data_size) {
+ data_size = 1000+(int)strlen(data)*2;
+ _data_enc = (char *)mxml_realloc(_data_enc, data_size);
+ }
+
+ strcpy(_data_enc, data);
+ mxml_encode(_data_enc, data_size, writer->translate);
+ return mxml_write_line(writer, _data_enc) == (int)strlen(_data_enc);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * write empty line
+ */
+int mxml_write_empty_line(MXML_WRITER *writer)
+{
+ if (writer->element_is_open) {
+ mxml_write_line(writer, ">\n");
+ writer->element_is_open = FALSE;
+ }
+
+ if (mxml_write_line(writer, "\n") != 1)
+ return FALSE;
+
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * write a comment to an XML file, enclosed in "<!--" and "-->"
+ */
+int mxml_write_comment(MXML_WRITER *writer, const char *string)
+{
+ int i;
+ char line[1000];
+
+ if (writer->element_is_open) {
+ mxml_write_line(writer, ">\n");
+ writer->element_is_open = FALSE;
+ }
+
+ line[0] = 0;
+ for (i=0 ; i<writer->level ; i++)
+ strlcat(line, XML_INDENT, sizeof(line));
+
+ strlcat(line, "<!-- ", sizeof(line));
+ strlcat(line, string, sizeof(line));
+ strlcat(line, " -->\n", sizeof(line));
+ if (mxml_write_line(writer, line) != (int)strlen(line))
+ return FALSE;
+
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * shortcut to write an element with a value but without attribute
+ */
+int mxml_write_element(MXML_WRITER *writer, const char *name, const char *value)
+{
+ int i;
+
+ i = mxml_start_element(writer, name);
+ i += mxml_write_value(writer, value);
+ i += mxml_end_element(writer);
+ return i;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * close a file opened with mxml_open_writer
+ */
+char *mxml_close_buffer(MXML_WRITER *writer)
+{
+ int i;
+ char *p;
+
+ if (writer->element_is_open) {
+ writer->element_is_open = FALSE;
+ if (mxml_write_line(writer, ">\n") != 2)
+ return NULL;
+ }
+
+ /* close remaining open levels */
+ for (i = 0 ; i<writer->level ; i++)
+ mxml_end_element(writer);
+
+ p = writer->buffer;
+ mxml_free(writer);
+ return p;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * close a file opened with mxml_open_writer
+ */
+int mxml_close_file(MXML_WRITER *writer)
+{
+ int i;
+
+ if (writer->element_is_open) {
+ writer->element_is_open = FALSE;
+ if (mxml_write_line(writer, ">\n") != 2)
+ return 0;
+ }
+
+ /* close remaining open levels */
+ for (i = 0 ; i<writer->level ; i++)
+ mxml_end_element(writer);
+
+ close(writer->fh);
+ mxml_free(writer);
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * create root node of an XML tree
+ */
+PMXML_NODE mxml_create_root_node(void)
+{
+ PMXML_NODE root;
+
+ root = (PMXML_NODE)calloc(sizeof(MXML_NODE), 1);
+ strcpy(root->name, "root");
+ root->node_type = DOCUMENT_NODE;
+
+ return root;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * add a subnode (child) to an existing parent node as a specific position
+ */
+PMXML_NODE mxml_add_special_node_at(PMXML_NODE parent, int node_type, const char *node_name, const char *value, int idx)
+{
+ PMXML_NODE pnode, pchild;
+ int i, j;
+
+ assert(parent);
+ if (parent->n_children == 0)
+ parent->child = (PMXML_NODE)mxml_malloc(sizeof(MXML_NODE));
+ else
+ parent->child = (PMXML_NODE)mxml_realloc(parent->child, sizeof(MXML_NODE)*(parent->n_children+1));
+ assert(parent->child);
+
+ /* move following nodes one down */
+ if (idx < parent->n_children)
+ for (i=parent->n_children ; i > idx ; i--)
+ memcpy(&parent->child[i], &parent->child[i-1], sizeof(MXML_NODE));
+
+ /* correct parent pointer for children */
+ for (i=0 ; i<parent->n_children ; i++) {
+ pchild = parent->child+i;
+ for (j=0 ; j<pchild->n_children ; j++)
+ pchild->child[j].parent = pchild;
+ }
+
+ /* initialize new node */
+ pnode = &parent->child[idx];
+ memset(pnode, 0, sizeof(MXML_NODE));
+ strlcpy(pnode->name, node_name, sizeof(pnode->name));
+ pnode->node_type = node_type;
+ pnode->parent = parent;
+
+ parent->n_children++;
+
+ if (value && *value) {
+ pnode->value = (char *)mxml_malloc(strlen(value)+1);
+ assert(pnode->value);
+ strcpy(pnode->value, value);
+ }
+
+ return pnode;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * add a subnode (child) to an existing parent node at the end
+ */
+PMXML_NODE mxml_add_special_node(PMXML_NODE parent, int node_type, const char *node_name, const char *value)
+{
+ return mxml_add_special_node_at(parent, node_type, node_name, value, parent->n_children);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * write value of an XML element, like <[name]>[value]</[name]>
+ */
+PMXML_NODE mxml_add_node(PMXML_NODE parent, const char *node_name, const char *value)
+{
+ return mxml_add_special_node_at(parent, ELEMENT_NODE, node_name, value, parent->n_children);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * add a subnode (child) to an existing parent node at the end
+ */
+PMXML_NODE mxml_add_node_at(PMXML_NODE parent, const char *node_name, const char *value, int idx)
+{
+ return mxml_add_special_node_at(parent, ELEMENT_NODE, node_name, value, idx);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * add a whole node tree to an existing parent node at a specific position
+ */
+int mxml_add_tree_at(PMXML_NODE parent, PMXML_NODE tree, int idx)
+{
+ PMXML_NODE pchild;
+ int i, j, k;
+
+ assert(parent);
+ assert(tree);
+ if (parent->n_children == 0)
+ parent->child = (PMXML_NODE)mxml_malloc(sizeof(MXML_NODE));
+ else {
+ pchild = parent->child;
+ parent->child = (PMXML_NODE)mxml_realloc(parent->child, sizeof(MXML_NODE)*(parent->n_children+1));
+
+ if (parent->child != pchild) {
+ /* correct parent pointer for children */
+ for (i=0 ; i<parent->n_children ; i++) {
+ pchild = parent->child+i;
+ for (j=0 ; j<pchild->n_children ; j++)
+ pchild->child[j].parent = pchild;
+ }
+ }
+ }
+ assert(parent->child);
+
+ if (idx < parent->n_children)
+ for (i=parent->n_children ; i > idx ; i--) {
+ /* move following nodes one down */
+ memcpy(&parent->child[i], &parent->child[i-1], sizeof(MXML_NODE));
+
+ /* correct parent pointer for children */
+ for (j=0 ; j<parent->n_children ; j++) {
+ pchild = parent->child+j;
+ for (k=0 ; k<pchild->n_children ; k++)
+ pchild->child[k].parent = pchild;
+ }
+ }
+
+ /* initialize new node */
+ memcpy(parent->child+idx, tree, sizeof(MXML_NODE));
+ parent->n_children++;
+ parent->child[idx].parent = parent;
+
+ /* correct parent pointer for children */
+ for (i=0 ; i<parent->n_children ; i++) {
+ pchild = parent->child+i;
+ for (j=0 ; j<pchild->n_children ; j++)
+ pchild->child[j].parent = pchild;
+ }
+
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * add a whole node tree to an existing parent node at the end
+ */
+int mxml_add_tree(PMXML_NODE parent, PMXML_NODE tree)
+{
+ return mxml_add_tree_at(parent, tree, parent->n_children);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * add an attribute to an existing node
+ */
+int mxml_add_attribute(PMXML_NODE pnode, const char *attrib_name, const char *attrib_value)
+{
+ if (pnode->n_attributes == 0) {
+ pnode->attribute_name = (char*)mxml_malloc(MXML_NAME_LENGTH);
+ pnode->attribute_value = (char**)mxml_malloc(sizeof(char *));
+ } else {
+ pnode->attribute_name = (char*)mxml_realloc(pnode->attribute_name, MXML_NAME_LENGTH*(pnode->n_attributes+1));
+ pnode->attribute_value = (char**)mxml_realloc(pnode->attribute_value, sizeof(char *)*(pnode->n_attributes+1));
+ }
+
+ strlcpy(pnode->attribute_name+pnode->n_attributes*MXML_NAME_LENGTH, attrib_name, MXML_NAME_LENGTH);
+ pnode->attribute_value[pnode->n_attributes] = (char *)mxml_malloc(strlen(attrib_value)+1);
+ strcpy(pnode->attribute_value[pnode->n_attributes], attrib_value);
+ pnode->n_attributes++;
+
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * return number of subnodes (children) of a node
+ */
+int mxml_get_number_of_children(PMXML_NODE pnode)
+{
+ assert(pnode);
+ return pnode->n_children;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * return number of subnodes (children) of a node
+ */
+PMXML_NODE mxml_subnode(PMXML_NODE pnode, int idx)
+{
+ assert(pnode);
+ if (idx < pnode->n_children)
+ return &pnode->child[idx];
+ return NULL;
+}
+
+/*------------------------------------------------------------------*/
+
+
+int mxml_find_nodes1(PMXML_NODE tree, const char *xml_path, PMXML_NODE **nodelist, int *found);
+
+int mxml_add_resultnode(PMXML_NODE node, const char *xml_path, PMXML_NODE **nodelist, int *found)
+{
+ /* if at end of path, add this node */
+ if (*xml_path == 0) {
+ if (*found == 0)
+ *nodelist = (PMXML_NODE *)mxml_malloc(sizeof(PMXML_NODE));
+ else
+ *nodelist = (PMXML_NODE *)mxml_realloc(*nodelist, sizeof(PMXML_NODE)*(*found + 1));
+
+ (*nodelist)[*found] = node;
+ (*found)++;
+ } else {
+ /* if not at end of path, branch into subtree */
+ return mxml_find_nodes1(node, xml_path+1, nodelist, found);
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ Return list of XML nodes with a subset of XPATH specifications.
+ Following elemets are possible
+
+ /<node>/<node>/..../<node> Find a node in the tree hierarchy
+ /<node>[idx] Find child #[idx] of node (index starts from 1)
+ /<node>[idx]/<node> Find subnode of the above
+ /<node>[<subnode>=<value>] Find a node which has a specific subnode
+ /<node>[<subnode>=<value>]/<node> Find subnode of the above
+ /<node>[@<attrib>=<value>]/<node> Find a node which has a specific attribute
+*/
+int mxml_find_nodes1(PMXML_NODE tree, const char *xml_path, PMXML_NODE **nodelist, int *found)
+{
+ PMXML_NODE pnode;
+ const char *p1,*p2;
+ char *p3, node_name[256], condition[256];
+ char cond_name[MXML_MAX_CONDITION][256], cond_value[MXML_MAX_CONDITION][256];
+ int cond_type[MXML_MAX_CONDITION];
+ int i, j, k, idx, num_cond;
+ int cond_satisfied,cond_index;
+ size_t len;
+
+ p1 = xml_path;
+ pnode = tree;
+
+ /* skip leading '/' */
+ if (*p1 && *p1 == '/')
+ p1++;
+
+ do {
+ p2 = p1;
+ while (*p2 && *p2 != '/' && *p2 != '[')
+ p2++;
+ len = (size_t)p2 - (size_t)p1;
+ if (len >= sizeof(node_name))
+ return 0;
+
+ memcpy(node_name, p1, len);
+ node_name[len] = 0;
+ idx = 0;
+ num_cond = 0;
+ while (*p2 == '[') {
+ cond_name[num_cond][0] = cond_value[num_cond][0] = cond_type[num_cond] = 0;
+ p2++;
+ if (isdigit(*p2)) {
+ /* evaluate [idx] */
+ idx = atoi(p2);
+ p2 = strchr(p2, ']');
+ if (p2 == NULL)
+ return 0;
+ p2++;
+ } else {
+ /* evaluate [<@attrib>/<subnode>=<value>] */
+ while (*p2 && isspace((unsigned char)*p2))
+ p2++;
+ strlcpy(condition, p2, sizeof(condition));
+ if (strchr(condition, ']'))
+ *strchr(condition, ']') = 0;
+ else
+ return 0;
+ p2 = strchr(p2, ']')+1;
+ if ((p3 = strchr(condition, '=')) != NULL) {
+ if (condition[0] == '@') {
+ cond_type[num_cond] = 1;
+ strlcpy(cond_name[num_cond], &condition[1], sizeof(cond_name[num_cond]));
+ } else {
+ strlcpy(cond_name[num_cond], condition, sizeof(cond_name[num_cond]));
+ }
+
+ *strchr(cond_name[num_cond], '=') = 0;
+ while (cond_name[num_cond][0] && isspace(cond_name[num_cond][strlen(cond_name[num_cond])-1]))
+ cond_name[num_cond][strlen(cond_name[num_cond])-1] = 0;
+
+ p3++;
+ while (*p3 && isspace(*p3))
+ p3++;
+ if (*p3 == '\"') {
+ strlcpy(cond_value[num_cond], p3+1, sizeof(cond_value[num_cond]));
+ while (cond_value[num_cond][0] && isspace(cond_value[num_cond][strlen(cond_value[num_cond])-1]))
+ cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0;
+ if (cond_value[num_cond][0] && cond_value[num_cond][strlen(cond_value[num_cond])-1] == '\"')
+ cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0;
+ } else if (*p3 == '\'') {
+ strlcpy(cond_value[num_cond], p3+1, sizeof(cond_value[num_cond]));
+ while (cond_value[num_cond][0] && isspace(cond_value[num_cond][strlen(cond_value[num_cond])-1]))
+ cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0;
+ if (cond_value[num_cond][0] && cond_value[num_cond][strlen(cond_value[num_cond])-1] == '\'')
+ cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0;
+ } else {
+ strlcpy(cond_value[num_cond], p3, sizeof(cond_value[num_cond]));
+ while (cond_value[num_cond][0] && isspace(cond_value[num_cond][strlen(cond_value[num_cond])-1]))
+ cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0;
+ }
+ num_cond++;
+ }
+ }
+ }
+
+ cond_index = 0;
+ for (i=j=0 ; i<pnode->n_children ; i++) {
+ if (num_cond) {
+ cond_satisfied = 0;
+ for (k=0;k<num_cond;k++) {
+ if (cond_type[k]) {
+ /* search node with attribute */
+ if (strcmp(pnode->child[i].name, node_name) == 0)
+ if (mxml_get_attribute(pnode->child+i, cond_name[k]) &&
+ strcmp(mxml_get_attribute(pnode->child+i, cond_name[k]), cond_value[k]) == 0)
+ cond_satisfied++;
+ }
+ else {
+ /* search subnode */
+ for (j=0 ; j<pnode->child[i].n_children ; j++)
+ if (strcmp(pnode->child[i].child[j].name, cond_name[k]) == 0)
+ if (strcmp(pnode->child[i].child[j].value, cond_value[k]) == 0)
+ cond_satisfied++;
+ }
+ }
+ if (cond_satisfied==num_cond) {
+ cond_index++;
+ if (idx == 0 || cond_index == idx) {
+ if (!mxml_add_resultnode(pnode->child+i, p2, nodelist, found))
+ return 0;
+ }
+ }
+ } else {
+ if (strcmp(pnode->child[i].name, node_name) == 0)
+ if (idx == 0 || ++j == idx)
+ if (!mxml_add_resultnode(pnode->child+i, p2, nodelist, found))
+ return 0;
+ }
+ }
+
+ if (i == pnode->n_children)
+ return 1;
+
+ pnode = &pnode->child[i];
+ p1 = p2;
+ if (*p1 == '/')
+ p1++;
+
+ } while (*p2);
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int mxml_find_nodes(PMXML_NODE tree, const char *xml_path, PMXML_NODE **nodelist)
+{
+ int status, found = 0;
+
+ status = mxml_find_nodes1(tree, xml_path, nodelist, &found);
+
+ if (status == 0)
+ return -1;
+
+ return found;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * Search for a specific XML node with a subset of XPATH specifications.
+ * Return first found node. For syntax see mxml_find_nodes()
+ */
+PMXML_NODE mxml_find_node(PMXML_NODE tree, const char *xml_path)
+{
+ PMXML_NODE *node, pnode;
+ int n;
+
+ n = mxml_find_nodes(tree, xml_path, &node);
+ if (n > 0) {
+ pnode = node[0];
+ mxml_free(node);
+ } else
+ pnode = NULL;
+
+ return pnode;
+}
+
+/*------------------------------------------------------------------*/
+
+PMXML_NODE mxml_get_parent(PMXML_NODE pnode)
+{
+ assert(pnode);
+ return pnode->parent;
+}
+
+/*------------------------------------------------------------------*/
+
+char *mxml_get_name(PMXML_NODE pnode)
+{
+ assert(pnode);
+ return pnode->name;
+}
+
+/*------------------------------------------------------------------*/
+
+char *mxml_get_value(PMXML_NODE pnode)
+{
+ assert(pnode);
+ return pnode->value;
+}
+
+/*------------------------------------------------------------------*/
+
+int mxml_get_line_number_start(PMXML_NODE pnode)
+{
+ assert(pnode);
+ return pnode->line_number_start;
+}
+
+/*------------------------------------------------------------------*/
+
+int mxml_get_line_number_end(PMXML_NODE pnode)
+{
+ assert(pnode);
+ return pnode->line_number_end;
+}
+
+/*------------------------------------------------------------------*/
+
+char *mxml_get_attribute(PMXML_NODE pnode, const char *name)
+{
+ int i;
+
+ assert(pnode);
+ for (i=0 ; i<pnode->n_attributes ; i++)
+ if (strcmp(pnode->attribute_name+i*MXML_NAME_LENGTH, name) == 0)
+ return pnode->attribute_value[i];
+
+ return NULL;
+}
+
+/*------------------------------------------------------------------*/
+
+int mxml_replace_node_name(PMXML_NODE pnode, const char *name)
+{
+ strlcpy(pnode->name, name, sizeof(pnode->name));
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+int mxml_replace_node_value(PMXML_NODE pnode, const char *value)
+{
+ if (pnode->value)
+ pnode->value = (char *)mxml_realloc(pnode->value, strlen(value)+1);
+ else if (value)
+ pnode->value = (char *)mxml_malloc(strlen(value)+1);
+ else
+ pnode->value = NULL;
+
+ if (value)
+ strcpy(pnode->value, value);
+
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ replace value os a subnode, like
+
+ <parent>
+ <child>value</child>
+ </parent>
+
+ if pnode=parent, and "name"="child", then "value" gets replaced
+*/
+int mxml_replace_subvalue(PMXML_NODE pnode, const char *name, const char *value)
+{
+ int i;
+
+ for (i=0 ; i<pnode->n_children ; i++)
+ if (strcmp(pnode->child[i].name, name) == 0)
+ break;
+
+ if (i == pnode->n_children)
+ return FALSE;
+
+ return mxml_replace_node_value(&pnode->child[i], value);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * change the name of an attribute, keep its value
+ */
+int mxml_replace_attribute_name(PMXML_NODE pnode, const char *old_name, const char *new_name)
+{
+ int i;
+
+ for (i=0 ; i<pnode->n_attributes ; i++)
+ if (strcmp(pnode->attribute_name+i*MXML_NAME_LENGTH, old_name) == 0)
+ break;
+
+ if (i == pnode->n_attributes)
+ return FALSE;
+
+ strlcpy(pnode->attribute_name+i*MXML_NAME_LENGTH, new_name, MXML_NAME_LENGTH);
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * change the value of an attribute
+ */
+int mxml_replace_attribute_value(PMXML_NODE pnode, const char *attrib_name, const char *attrib_value)
+{
+ int i;
+
+ for (i=0 ; i<pnode->n_attributes ; i++)
+ if (strcmp(pnode->attribute_name+i*MXML_NAME_LENGTH, attrib_name) == 0)
+ break;
+
+ if (i == pnode->n_attributes)
+ return FALSE;
+
+ pnode->attribute_value[i] = (char *)mxml_realloc(pnode->attribute_value[i], strlen(attrib_value)+1);
+ strcpy(pnode->attribute_value[i], attrib_value);
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * free memory of a node and remove it from the parent's child list
+ */
+int mxml_delete_node(PMXML_NODE pnode)
+{
+ PMXML_NODE parent;
+ int i, j;
+
+ /* remove node from parent's list */
+ parent = pnode->parent;
+
+ if (parent) {
+ for (i=0 ; i<parent->n_children ; i++)
+ if (&parent->child[i] == pnode)
+ break;
+
+ /* free allocated node memory recursively */
+ mxml_free_tree(pnode);
+
+ if (i < parent->n_children) {
+ for (j=i ; j<parent->n_children-1 ; j++)
+ memcpy(&parent->child[j], &parent->child[j+1], sizeof(MXML_NODE));
+ parent->n_children--;
+ if (parent->n_children)
+ parent->child = (PMXML_NODE)mxml_realloc(parent->child, sizeof(MXML_NODE)*(parent->n_children));
+ else
+ mxml_free(parent->child);
+ }
+ } else
+ mxml_free_tree(pnode);
+
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+int mxml_delete_attribute(PMXML_NODE pnode, const char *attrib_name)
+{
+ int i, j;
+
+ for (i=0 ; i<pnode->n_attributes ; i++)
+ if (strcmp(pnode->attribute_name+i*MXML_NAME_LENGTH, attrib_name) == 0)
+ break;
+
+ if (i == pnode->n_attributes)
+ return FALSE;
+
+ mxml_free(pnode->attribute_value[i]);
+ for (j=i ; j<pnode->n_attributes-1 ; j++) {
+ strcpy(pnode->attribute_name+j*MXML_NAME_LENGTH, pnode->attribute_name+(j+1)*MXML_NAME_LENGTH);
+ pnode->attribute_value[j] = pnode->attribute_value[j+1];
+ }
+
+ if (pnode->n_attributes > 0) {
+ pnode->attribute_name = (char *)mxml_realloc(pnode->attribute_name, MXML_NAME_LENGTH*(pnode->n_attributes-1));
+ pnode->attribute_value = (char **)mxml_realloc(pnode->attribute_value, sizeof(char *)*(pnode->n_attributes-1));
+ } else {
+ mxml_free(pnode->attribute_name);
+ mxml_free(pnode->attribute_value);
+ }
+
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+#define HERE root, file_name, line_number, error, error_size, error_line
+
+/**
+ * used inside mxml_parse_file for reporting errors
+ */
+PMXML_NODE read_error(PMXML_NODE root, const char *file_name, int line_number, char *error, int error_size, int *error_line, const char *format, ...)
+{
+ char *msg, str[1000];
+ va_list argptr;
+
+ if (file_name && file_name[0])
+ sprintf(str, "XML read error in file \"%s\", line %d: ", file_name, line_number);
+ else
+ sprintf(str, "XML read error, line %d: ", line_number);
+ msg = (char *)mxml_malloc(error_size);
+ if (error)
+ strlcpy(error, str, error_size);
+
+ va_start(argptr, format);
+ vsprintf(str, (char *) format, argptr);
+ va_end(argptr);
+
+ if (error)
+ strlcat(error, str, error_size);
+ if (error_line)
+ *error_line = line_number;
+
+ mxml_free(msg);
+ mxml_free_tree(root);
+
+ return NULL;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * Parse a XML buffer and convert it into a tree of MXML_NODE's.
+ * Return NULL in case of an error, return error description.
+ * Optional file_name is used for error reporting if called from mxml_parse_file()
+ */
+PMXML_NODE mxml_parse_buffer(const char *buf, char *error, int error_size, int *error_line)
+{
+ char node_name[256], attrib_name[256], attrib_value[1000], quote;
+ const char *p, *pv;
+ int i,j, line_number;
+ PMXML_NODE root, ptree, pnew;
+ int end_element;
+ size_t len;
+ char *file_name = NULL; /* dummy for 'HERE' */
+
+ p = buf;
+ line_number = 1;
+
+ root = mxml_create_root_node();
+ ptree = root;
+
+ /* parse file contents */
+ do {
+ if (*p == '<') {
+
+ end_element = FALSE;
+
+ /* found new element */
+ p++;
+ while (*p && isspace(*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p)
+ return read_error(HERE, "Unexpected end of file");
+
+ if (strncmp(p, "!--", 3) == 0) {
+
+ /* found comment */
+
+ pnew = mxml_add_special_node(ptree, COMMENT_NODE, "Comment", NULL);
+ pnew->line_number_start = line_number;
+ pv = p+3;
+ while (*pv == ' ')
+ pv++;
+
+ p += 3;
+ if (strstr(p, "-->") == NULL)
+ return read_error(HERE, "Unterminated comment");
+
+ while (strncmp(p, "-->", 3) != 0) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+
+ len = (size_t)p - (size_t)pv;
+ pnew->value = (char *)mxml_malloc(len+1);
+ memcpy(pnew->value, pv, len);
+ pnew->value[len] = 0;
+ pnew->line_number_end = line_number;
+ mxml_decode(pnew->value);
+
+ p += 3;
+
+ } else if (*p == '?') {
+
+ /* found ?...? element */
+ pnew = mxml_add_special_node(ptree, PROCESSING_INSTRUCTION_NODE, "PI", NULL);
+ pnew->line_number_start = line_number;
+ pv = p+1;
+
+ p++;
+ if (strstr(p, "?>") == NULL)
+ return read_error(HERE, "Unterminated ?...? element");
+
+ while (strncmp(p, "?>", 2) != 0) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+
+ len = (size_t)p - (size_t)pv;
+ pnew->value = (char *)mxml_malloc(len+1);
+ memcpy(pnew->value, pv, len);
+ pnew->value[len] = 0;
+ pnew->line_number_end = line_number;
+ mxml_decode(pnew->value);
+
+ p += 2;
+
+ } else if (strncmp(p, "!DOCTYPE", 8) == 0 ) {
+
+ /* found !DOCTYPE element , skip it */
+ p += 8;
+ if (strstr(p, ">") == NULL)
+ return read_error(HERE, "Unterminated !DOCTYPE element");
+
+ j = 0;
+ while (*p && (*p != '>' || j > 0)) {
+ if (*p == '\n')
+ line_number++;
+ else if (*p == '<')
+ j++;
+ else if (*p == '>')
+ j--;
+ p++;
+ }
+ if (!*p)
+ return read_error(HERE, "Unexpected end of file");
+
+ p++;
+
+ } else {
+
+ /* found normal element */
+ if (*p == '/') {
+ end_element = TRUE;
+ p++;
+ while (*p && isspace((unsigned char)*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p)
+ return read_error(HERE, "Unexpected end of file");
+ }
+
+ /* extract node name */
+ i = 0;
+ node_name[i] = 0;
+ while (*p && !isspace((unsigned char)*p) && *p != '/' && *p != '>' && *p != '<')
+ node_name[i++] = *p++;
+ node_name[i] = 0;
+ if (!*p)
+ return read_error(HERE, "Unexpected end of file");
+ if (*p == '<')
+ return read_error(HERE, "Unexpected \'<\' inside element \"%s\"", node_name);
+
+ mxml_decode(node_name);
+
+ if (end_element) {
+
+ if (!ptree)
+ return read_error(HERE, "Found unexpected </%s>", node_name);
+
+ /* close previously opened element */
+ if (strcmp(ptree->name, node_name) != 0)
+ return read_error(HERE, "Found </%s>, expected </%s>", node_name, ptree->name);
+ ptree->line_number_end = line_number;
+
+ /* go up one level on the tree */
+ ptree = ptree->parent;
+
+ } else {
+
+ if (ptree == NULL)
+ return read_error(HERE, "Unexpected second top level node");
+
+ /* allocate new element structure in parent tree */
+ pnew = mxml_add_node(ptree, node_name, NULL);
+ pnew->line_number_start = line_number;
+ pnew->line_number_end = line_number;
+
+ while (*p && isspace((unsigned char)*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p)
+ return read_error(HERE, "Unexpected end of file");
+
+ while (*p != '>' && *p != '/') {
+
+ /* found attribute */
+ pv = p;
+ while (*pv && !isspace((unsigned char)*pv) && *pv != '=' && *pv != '<' && *pv != '>')
+ pv++;
+ if (!*pv)
+ return read_error(HERE, "Unexpected end of file");
+ if (*pv == '<' || *pv == '>')
+ return read_error(HERE, "Unexpected \'%c\' inside element \"%s\"", *pv, node_name);
+
+ /* extract attribute name */
+ len = (size_t)pv - (size_t)p;
+ if (len > sizeof(attrib_name)-1)
+ len = sizeof(attrib_name)-1;
+ memcpy(attrib_name, p, len);
+ attrib_name[len] = 0;
+ mxml_decode(attrib_name);
+
+ p = pv;
+ while (*p && isspace((unsigned char)*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p)
+ return read_error(HERE, "Unexpected end of file");
+ if (*p != '=')
+ return read_error(HERE, "Expect \"=\" here");
+
+ p++;
+ while (*p && isspace((unsigned char)*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p)
+ return read_error(HERE, "Unexpected end of file");
+ if (*p != '\"' && *p != '\'')
+ return read_error(HERE, "Expect \" or \' here");
+ quote = *p;
+ p++;
+
+ /* extract attribute value */
+ pv = p;
+ while (*pv && *pv != quote)
+ pv++;
+ if (!*pv)
+ return read_error(HERE, "Unexpected end of file");
+
+ len = (size_t)pv - (size_t)p;
+ if (len > sizeof(attrib_value)-1)
+ len = sizeof(attrib_value)-1;
+ memcpy(attrib_value, p, len);
+ attrib_value[len] = 0;
+ mxml_decode(attrib_value);
+
+ /* add attribute to current node */
+ mxml_add_attribute(pnew, attrib_name, attrib_value);
+
+ p = pv+1;
+ while (*p && isspace((unsigned char)*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p)
+ return read_error(HERE, "Unexpected end of file");
+ }
+
+ if (*p == '/') {
+
+ /* found empty node, like <node/>, just skip closing bracket */
+ p++;
+
+ while (*p && isspace((unsigned char)*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p)
+ return read_error(HERE, "Unexpected end of file");
+ if (*p != '>')
+ return read_error(HERE, "Expected \">\" after \"/\"");
+ p++;
+ }
+
+ if (*p == '>') {
+
+ p++;
+
+ /* check if we have sub-element or value */
+ pv = p;
+ while (*pv && isspace((unsigned char)*pv)) {
+ if (*pv == '\n')
+ line_number++;
+ pv++;
+ }
+ if (!*pv)
+ return read_error(HERE, "Unexpected end of file");
+
+ if (*pv == '<' && *(pv+1) != '/') {
+
+ /* start new subtree */
+ ptree = pnew;
+ p = pv;
+
+ } else {
+
+ /* extract value */
+ while (*pv && *pv != '<') {
+ if (*pv == '\n')
+ line_number++;
+ pv++;
+ }
+ if (!*pv)
+ return read_error(HERE, "Unexpected end of file");
+
+ len = (size_t)pv - (size_t)p;
+ pnew->value = (char *)mxml_malloc(len+1);
+ memcpy(pnew->value, p, len);
+ pnew->value[len] = 0;
+ mxml_decode(pnew->value);
+ p = pv;
+
+ ptree = pnew;
+ }
+ }
+ }
+ }
+ }
+
+ /* go to next element */
+ while (*p && *p != '<') {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ } while (*p);
+
+ return root;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * parse !ENTYTY entries of XML files and replace with references.
+ * Return 0 in case of no errors, return error description.
+ * Optional file_name is used for error reporting if called from mxml_parse_file()
+ */
+int mxml_parse_entity(char **buf, const char *file_name, char *error, int error_size, int *error_line)
+{
+ char *p;
+ char *pv;
+ char delimiter;
+ int i, j, k, line_number, status;
+ char *replacement;
+ char entity_name[MXML_MAX_ENTITY][256];
+ char entity_reference_name[MXML_MAX_ENTITY][256];
+ char *entity_value[MXML_MAX_ENTITY];
+ int entity_type[MXML_MAX_ENTITY]; /* internal or external */
+ int entity_line_number[MXML_MAX_ENTITY];
+ int nentity;
+ int fh, length, len;
+ char *buffer;
+ int ip; /* counter for entity value */
+ char directoryname[FILENAME_MAX];
+ char filename[FILENAME_MAX];
+ int entity_value_length[MXML_MAX_ENTITY];
+ int entity_name_length[MXML_MAX_ENTITY];
+
+ PMXML_NODE root = mxml_create_root_node(); /* dummy for 'HERE' */
+
+ for (ip = 0; ip < MXML_MAX_ENTITY; ip++)
+ entity_value[ip] = NULL;
+
+ line_number = 1;
+ nentity = -1;
+ status = 0;
+
+ if (!buf || !(*buf) || !strlen(*buf))
+ return 0;
+
+ strcpy(directoryname, file_name);
+ mxml_dirname(directoryname);
+
+ /* copy string to temporary space */
+ buffer = (char *) mxml_malloc(strlen(*buf) + 1);
+ if (buffer == NULL) {
+ read_error(HERE, "Cannot allocate memory.");
+ status = 1;
+ goto error;
+ }
+ strcpy(buffer, *buf);
+
+ p = strstr(buffer, "!DOCTYPE");
+ if (p == NULL) { /* no entities */
+ status = 0;
+ goto error;
+ }
+
+ pv = strstr(p, "[");
+ if (pv == NULL) { /* no entities */
+ status = 1;
+ goto error;
+ }
+
+ p = pv + 1;
+
+ /* search !ENTITY */
+ do {
+ if (*p == ']')
+ break;
+
+ if (*p == '<') {
+
+ /* found new entity */
+ p++;
+ while (*p && isspace((unsigned char)*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p) {
+ read_error(HERE, "Unexpected end of file");
+ status = 1;
+ goto error;
+ }
+
+ if (strncmp(p, "!--", 3) == 0) {
+ /* found comment */
+ p += 3;
+ if (strstr(p, "-->") == NULL) {
+ read_error(HERE, "Unterminated comment");
+ status = 1;
+ goto error;
+ }
+
+ while (strncmp(p, "-->", 3) != 0) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ p += 3;
+ }
+
+ else if (strncmp(p, "!ENTITY", 7) == 0) {
+ /* found entity */
+ nentity++;
+ if (nentity >= MXML_MAX_ENTITY) {
+ read_error(HERE, "Too much entities");
+ status = 1;
+ goto error;
+ }
+
+ entity_line_number[nentity] = line_number;
+
+ pv = p + 7;
+ while (*pv == ' ')
+ pv++;
+
+ /* extract entity name */
+ p = pv;
+
+ while (*p && isspace((unsigned char)*p) && *p != '<' && *p != '>') {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p) {
+ read_error(HERE, "Unexpected end of file");
+ status = 1;
+ goto error;
+ }
+ if (*p == '<' || *p == '>') {
+ read_error(HERE, "Unexpected \'%c\' inside !ENTITY", *p);
+ status = 1;
+ goto error;
+ }
+
+ pv = p;
+ while (*pv && !isspace((unsigned char)*pv) && *pv != '<' && *pv != '>')
+ pv++;
+
+ if (!*pv) {
+ read_error(HERE, "Unexpected end of file");
+ status = 1;
+ goto error;
+ }
+ if (*pv == '<' || *pv == '>') {
+ read_error(HERE, "Unexpected \'%c\' inside entity \"%s\"", *pv, &entity_name[nentity][1]);
+ status = 1;
+ goto error;
+ }
+
+ entity_name[nentity][0] = '&';
+ i = 1;
+ entity_name[nentity][i] = 0;
+ while (*p && !isspace((unsigned char)*p) && *p != '/' && *p != '>' && *p != '<' && i < 253)
+ entity_name[nentity][i++] = *p++;
+ entity_name[nentity][i++] = ';';
+ entity_name[nentity][i] = 0;
+
+ if (!*p) {
+ read_error(HERE, "Unexpected end of file");
+ status = 1;
+ goto error;
+ }
+ if (*p == '<') {
+ read_error(HERE, "Unexpected \'<\' inside entity \"%s\"", &entity_name[nentity][1]);
+ status = 1;
+ goto error;
+ }
+
+ /* extract replacement or SYSTEM */
+ while (*p && isspace((unsigned char)*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p) {
+ read_error(HERE, "Unexpected end of file");
+ status = 1;
+ goto error;
+ }
+ if (*p == '>') {
+ read_error(HERE, "Unexpected \'>\' inside entity \"%s\"", &entity_name[nentity][1]);
+ status = 1;
+ goto error;
+ }
+
+ /* check if SYSTEM */
+ if (strncmp(p, "SYSTEM", 6) == 0) {
+ entity_type[nentity] = EXTERNAL_ENTITY;
+ p += 6;
+ } else {
+ entity_type[nentity] = INTERNAL_ENTITY;
+ }
+
+ /* extract replacement */
+ while (*p && isspace((unsigned char)*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p) {
+ read_error(HERE, "Unexpected end of file");
+ status = 1;
+ goto error;
+ }
+ if (*p == '>') {
+ read_error(HERE, "Unexpected \'>\' inside entity \"%s\"", &entity_name[nentity][1]);
+ status = 1;
+ goto error;
+ }
+
+ if (*p != '\"' && *p != '\'') {
+ read_error(HERE, "Replacement was not found for entity \"%s\"", &entity_name[nentity][1]);
+ status = 1;
+ goto error;
+ }
+ delimiter = *p;
+ p++;
+ if (!*p) {
+ read_error(HERE, "Unexpected end of file");
+ status = 1;
+ goto error;
+ }
+ pv = p;
+ while (*pv && *pv != delimiter)
+ pv++;
+
+ if (!*pv) {
+ read_error(HERE, "Unexpected end of file");
+ status = 1;
+ goto error;
+ }
+ if (*pv == '<') {
+ read_error(HERE, "Unexpected \'%c\' inside entity \"%s\"", *pv, &entity_name[nentity][1]);
+ status = 1;
+ goto error;
+ }
+
+ len = (int)((size_t) pv - (size_t) p);
+ replacement = (char *) mxml_malloc(len + 1);
+ if (replacement == NULL) {
+ read_error(HERE, "Cannot allocate memory.");
+ status = 1;
+ goto error;
+ }
+
+ memcpy(replacement, p, len);
+ replacement[len] = 0;
+ mxml_decode(replacement);
+
+ if (entity_type[nentity] == EXTERNAL_ENTITY) {
+ strcpy(entity_reference_name[nentity], replacement);
+ } else {
+ entity_value[nentity] = (char *) mxml_malloc(strlen(replacement));
+ if (entity_value[nentity] == NULL) {
+ read_error(HERE, "Cannot allocate memory.");
+ status = 1;
+ goto error;
+ }
+ strcpy(entity_value[nentity], replacement);
+ }
+ mxml_free(replacement);
+
+ p = pv;
+ while (*p && isspace((unsigned char)*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p) {
+ read_error(HERE, "Unexpected end of file");
+ status = 1;
+ goto error;
+ }
+ }
+ }
+
+ /* go to next element */
+ while (*p && *p != '<') {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ } while (*p);
+ nentity++;
+
+ /* read external file */
+ for (i = 0; i < nentity; i++) {
+ if (entity_type[i] == EXTERNAL_ENTITY) {
+ if ( entity_reference_name[i][0] == DIR_SEPARATOR ) /* absolute path */
+ strcpy(filename, entity_reference_name[i]);
+ else /* relative path */
+ sprintf(filename, "%s%c%s", directoryname, DIR_SEPARATOR, entity_reference_name[i]);
+ fh = open(filename, O_RDONLY | O_TEXT, 0644);
+
+ if (fh == -1) {
+ line_number = entity_line_number[i];
+ read_error(HERE, "%s is missing", entity_reference_name[i]);
+ status = 1;
+ goto error;
+ } else {
+ length = (int)lseek(fh, 0, SEEK_END);
+ lseek(fh, 0, SEEK_SET);
+ if (length == 0) {
+ entity_value[i] = (char *) mxml_malloc(1);
+ if (entity_value[i] == NULL) {
+ read_error(HERE, "Cannot allocate memory.");
+ close(fh);
+ status = 1;
+ goto error;
+ }
+ entity_value[i][0] = 0;
+ } else {
+ entity_value[i] = (char *) mxml_malloc(length);
+ if (entity_value[i] == NULL) {
+ read_error(HERE, "Cannot allocate memory.");
+ close(fh);
+ status = 1;
+ goto error;
+ }
+
+ /* read complete file at once */
+ length = (int)read(fh, entity_value[i], length);
+ entity_value[i][length - 1] = 0;
+ close(fh);
+
+ /* recursive parse */
+ if (mxml_parse_entity(&entity_value[i], filename, error, error_size, error_line) != 0) {
+ status = 1;
+ goto error;
+ }
+ }
+ }
+ }
+ }
+
+ /* count length of output string */
+ length = (int)strlen(buffer);
+ for (i = 0; i < nentity; i++) {
+ p = buffer;
+ entity_value_length[i] = (int)strlen(entity_value[i]);
+ entity_name_length[i] = (int)strlen(entity_name[i]);
+ while (1) {
+ pv = strstr(p, entity_name[i]);
+ if (pv) {
+ length += entity_value_length[i] - entity_name_length[i];
+ p = pv + 1;
+ } else {
+ break;
+ }
+ }
+ }
+
+ /* re-allocate memory */
+ *buf = (char *) mxml_realloc(*buf, length + 1);
+ if (*buf == NULL) {
+ read_error(HERE, "Cannot allocate memory.");
+ status = 1;
+ goto error;
+ }
+
+ /* replace entities */
+ p = buffer;
+ pv = *buf;
+ do {
+ if (*p == '&') {
+ /* found entity */
+ for (j = 0; j < nentity; j++) {
+ if (strncmp(p, entity_name[j], entity_name_length[j]) == 0) {
+ for (k = 0; k < (int) entity_value_length[j]; k++)
+ *pv++ = entity_value[j][k];
+ p += entity_name_length[j];
+ break;
+ }
+ }
+ }
+ *pv++ = *p++;
+ } while (*p);
+ *pv = 0;
+
+error:
+
+ if (buffer != NULL)
+ mxml_free(buffer);
+ for (ip = 0; ip < MXML_MAX_ENTITY; ip++)
+ if (entity_value[ip] != NULL)
+ mxml_free(entity_value[ip]);
+
+ return status;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * parse a XML file and convert it into a tree of MXML_NODE's.
+ * Return NULL in case of an error, return error description
+ */
+PMXML_NODE mxml_parse_file(const char *file_name, char *error, int error_size, int *error_line)
+{
+ char *buf, line[1000];
+ int fh, length;
+ PMXML_NODE root;
+
+ if (error)
+ error[0] = 0;
+
+ fh = open(file_name, O_RDONLY | O_TEXT, 0644);
+
+ if (fh == -1) {
+ sprintf(line, "Unable to open file \"%s\": ", file_name);
+ strlcat(line, strerror(errno), sizeof(line));
+ strlcpy(error, line, error_size);
+ return NULL;
+ }
+
+ length = (int)lseek(fh, 0, SEEK_END);
+ lseek(fh, 0, SEEK_SET);
+ buf = (char *)mxml_malloc(length+1);
+ if (buf == NULL) {
+ close(fh);
+ sprintf(line, "Cannot allocate buffer: ");
+ strlcat(line, strerror(errno), sizeof(line));
+ strlcpy(error, line, error_size);
+ return NULL;
+ }
+
+ /* read complete file at once */
+ length = (int)read(fh, buf, length);
+ buf[length] = 0;
+ close(fh);
+
+ if (mxml_parse_entity(&buf, file_name, error, error_size, error_line) != 0) {
+ mxml_free(buf);
+ return NULL;
+ }
+
+ root = mxml_parse_buffer(buf, error, error_size, error_line);
+
+ mxml_free(buf);
+
+ return root;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * write complete subtree recursively into file opened with mxml_open_document()
+ */
+int mxml_write_subtree(MXML_WRITER *writer, PMXML_NODE tree, int indent)
+{
+ int i;
+
+ mxml_start_element1(writer, tree->name, indent);
+ for (i=0 ; i<tree->n_attributes ; i++)
+ if (!mxml_write_attribute(writer, tree->attribute_name+i*MXML_NAME_LENGTH, tree->attribute_value[i]))
+ return FALSE;
+
+ if (tree->value)
+ if (!mxml_write_value(writer, tree->value))
+ return FALSE;
+
+ for (i=0 ; i<tree->n_children ; i++)
+ if (!mxml_write_subtree(writer, &tree->child[i], (tree->value == NULL) || i > 0))
+ return FALSE;
+
+ return mxml_end_element(writer);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * write a complete XML tree to a file
+ */
+int mxml_write_tree(const char *file_name, PMXML_NODE tree)
+{
+ MXML_WRITER *writer;
+ int i;
+
+ assert(tree);
+ writer = mxml_open_file(file_name);
+ if (!writer)
+ return FALSE;
+
+ for (i=0 ; i<tree->n_children ; i++)
+ if (tree->child[i].node_type == ELEMENT_NODE) /* skip PI and comments */
+ if (!mxml_write_subtree(writer, &tree->child[i], TRUE))
+ return FALSE;
+
+ if (!mxml_close_file(writer))
+ return FALSE;
+
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+PMXML_NODE mxml_clone_tree(PMXML_NODE tree)
+{
+ PMXML_NODE clone;
+ int i;
+
+ clone = (PMXML_NODE)calloc(sizeof(MXML_NODE), 1);
+
+ /* copy name, node_type, n_attributes and n_children */
+ memcpy(clone, tree, sizeof(MXML_NODE));
+
+ clone->value = NULL;
+ mxml_replace_node_value(clone, tree->value);
+
+ clone->attribute_name = NULL;
+ clone->attribute_value = NULL;
+ for (i=0 ; i<tree->n_attributes ; i++)
+ mxml_add_attribute(clone, tree->attribute_name+i*MXML_NAME_LENGTH, tree->attribute_value[i]);
+
+ clone->child = NULL;
+ clone->n_children = 0;
+ for (i=0 ; i<tree->n_children ; i++)
+ mxml_add_tree(clone, mxml_clone_tree(mxml_subnode(tree, i)));
+
+ return clone;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * print XML tree for debugging
+ */
+void mxml_debug_tree(PMXML_NODE tree, int level)
+{
+ int i, j;
+
+ for (i=0 ; i<level ; i++)
+ printf(" ");
+ printf("Name: %s\n", tree->name);
+ for (i=0 ; i<level ; i++)
+ printf(" ");
+ printf("Valu: %s\n", tree->value);
+ for (i=0 ; i<level ; i++)
+ printf(" ");
+ printf("Type: %d\n", tree->node_type);
+ for (i=0 ; i<level ; i++)
+ printf(" ");
+ printf("Lin1: %d\n", tree->line_number_start);
+ for (i=0 ; i<level ; i++)
+ printf(" ");
+ printf("Lin2: %d\n", tree->line_number_end);
+
+ for (j=0 ; j<tree->n_attributes ; j++) {
+ for (i=0 ; i<level ; i++)
+ printf(" ");
+ printf("%s: %s\n", tree->attribute_name+j*MXML_NAME_LENGTH,
+ tree->attribute_value[j]);
+ }
+
+ for (i=0 ; i<level ; i++)
+ printf(" ");
+ printf("Addr: %08zX\n", (size_t)tree);
+ for (i=0 ; i<level ; i++)
+ printf(" ");
+ printf("Prnt: %08zX\n", (size_t)tree->parent);
+ for (i=0 ; i<level ; i++)
+ printf(" ");
+ printf("NCld: %d\n", tree->n_children);
+
+ for (i=0 ; i<tree->n_children ; i++)
+ mxml_debug_tree(tree->child+i, level+1);
+
+ if (level == 0)
+ printf("\n");
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * free memory of XML tree, must be called after any
+ * mxml_create_root_node() or mxml_parse_file()
+ */
+void mxml_free_tree(PMXML_NODE tree)
+{
+ int i;
+
+ /* first free children recursively */
+ for (i=0 ; i<tree->n_children ; i++)
+ mxml_free_tree(&tree->child[i]);
+ if (tree->n_children)
+ mxml_free(tree->child);
+
+ /* now free dynamic data */
+ for (i=0 ; i<tree->n_attributes ; i++)
+ mxml_free(tree->attribute_value[i]);
+
+ if (tree->n_attributes) {
+ mxml_free(tree->attribute_name);
+ mxml_free(tree->attribute_value);
+ }
+
+ if (tree->value)
+ mxml_free(tree->value);
+
+ /* if we are the root node, free it */
+ if (tree->parent == NULL)
+ mxml_free(tree);
+}
+
+/*------------------------------------------------------------------*/
+
+/*
+void mxml_test()
+{
+ char err[256];
+ PMXML_NODE tree, tree2, node;
+
+ tree = mxml_parse_file("c:\\tmp\\test.xml", err, sizeof(err));
+ tree2 = mxml_clone_tree(tree);
+
+ printf("Orig:\n");
+ mxml_debug_tree(tree, 0);
+
+ printf("\nClone:\n");
+ mxml_debug_tree(tree2, 0);
+
+ printf("\nCombined:\n");
+ node = mxml_find_node(tree2, "cddb");
+ mxml_add_tree(tree, node);
+ mxml_debug_tree(tree, 0);
+
+ mxml_free_tree(tree);
+}
+*/
+
+/*------------------------------------------------------------------*/
+ /**
+ mxml_basename deletes any prefix ending with the last slash '/' character
+ present in path. mxml_dirname deletes the filename portion, beginning with
+ the last slash '/' character to the end of path. Followings are examples
+ from these functions
+
+ path dirname basename
+ "/" "/" ""
+ "." "." "."
+ "" "" ""
+ "/test.txt" "/" "test.txt"
+ "path/to/test.txt" "path/to" "test.txt"
+ "test.txt "." "test.txt"
+
+ Under Windows, '\\' and ':' are recognized ad separator too.
+ */
+
+void mxml_basename(char *path)
+{
+ char str[FILENAME_MAX];
+ char *p;
+ char *name;
+
+ if (path) {
+ strcpy(str, path);
+ p = str;
+ name = str;
+ while (1) {
+ if (*p == 0)
+ break;
+ if (*p == '/'
+#ifdef _MSC_VER
+ || *p == ':' || *p == '\\'
+#endif
+ )
+ name = p + 1;
+ p++;
+ }
+ strcpy(path, name);
+ }
+
+ return;
+}
+
+void mxml_dirname(char *path)
+{
+ char *p;
+#ifdef _MSC_VER
+ char *pv;
+#endif
+
+ if (!path || strlen(path) == 0)
+ return;
+
+ p = strrchr(path, '/');
+#ifdef _MSC_VER
+ pv = strrchr(path, ':');
+ if (pv > p)
+ p = pv;
+ pv = strrchr(path, '\\');
+ if (pv > p)
+ p = pv;
+#endif
+
+ if (p == 0) /* current directory */
+ strcpy(path, ".");
+ else if (p == path) /* root directory */
+ sprintf(path, "%c", *p);
+ else
+ *p = 0;
+
+ return;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * Retieve node at a certain line number
+ */
+PMXML_NODE mxml_get_node_at_line(PMXML_NODE tree, int line_number)
+{
+ int i;
+ PMXML_NODE pn;
+
+ if (tree->line_number_start == line_number)
+ return tree;
+
+ for (i=0 ; i<tree->n_children ; i++) {
+ pn = mxml_get_node_at_line(&tree->child[i], line_number);
+ if (pn)
+ return pn;
+ }
+
+ return NULL;
+}
+
Index: instr/drsctrl/mxml.h
===================================================================
--- instr/drsctrl/mxml.h (nonexistent)
+++ instr/drsctrl/mxml.h (revision 195)
@@ -0,0 +1,156 @@
+/********************************************************************\
+
+ Name: mxml.h
+ Created by: Stefan Ritt
+ Copyright 2000 + Stefan Ritt
+
+ Contents: Header file for mxml.c
+
+ This file is part of MIDAS XML Library.
+
+ MIDAS XML Library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MIDAS XML Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MIDAS XML Library. If not, see <http://www.gnu.org/licenses/>.
+
+\********************************************************************/
+
+/*------------------------------------------------------------------*/
+
+#ifndef _MXML_H_
+#define _MXML_H_
+
+#define MXML_NAME_LENGTH 64
+
+#define ELEMENT_NODE 1
+#define TEXT_NODE 2
+#define PROCESSING_INSTRUCTION_NODE 3
+#define COMMENT_NODE 4
+#define DOCUMENT_NODE 5
+
+#define INTERNAL_ENTITY 0
+#define EXTERNAL_ENTITY 1
+#define MXML_MAX_ENTITY 500
+
+#define MXML_MAX_CONDITION 10
+
+#ifdef _MSC_VER
+#define DIR_SEPARATOR '\\'
+#else
+#define DIR_SEPARATOR '/'
+#endif
+
+typedef struct {
+ int fh;
+ char *buffer;
+ int buffer_size;
+ int buffer_len;
+ int level;
+ int element_is_open;
+ int data_was_written;
+ char **stack;
+ int translate;
+} MXML_WRITER;
+
+typedef struct mxml_struct *PMXML_NODE;
+
+typedef struct mxml_struct {
+ char name[MXML_NAME_LENGTH]; // name of element <[name]>[value]</[name]>
+ int node_type; // type of node XXX_NODE
+ char *value; // value of element
+ int n_attributes; // list of attributes
+ char *attribute_name;
+ char **attribute_value;
+ int line_number_start; // first line number in XML file, starting from 1
+ int line_number_end; // last line number in XML file, starting from 1
+ PMXML_NODE parent; // pointer to parent element
+ int n_children; // list of children
+ PMXML_NODE child;
+} MXML_NODE;
+
+/*------------------------------------------------------------------*/
+
+/* make functions callable from a C++ program */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef EXPRT
+#if defined(EXPORT_DLL)
+#define EXPRT __declspec(dllexport)
+#else
+#define EXPRT
+#endif
+#endif
+
+void mxml_suppress_date(int suppress);
+MXML_WRITER *mxml_open_file(const char *file_name);
+MXML_WRITER *mxml_open_buffer(void);
+int mxml_set_translate(MXML_WRITER *writer, int flag);
+int mxml_start_element(MXML_WRITER *writer, const char *name);
+int mxml_start_element_noindent(MXML_WRITER *writer, const char *name);
+int mxml_end_element(MXML_WRITER *writer);
+int mxml_write_comment(MXML_WRITER *writer, const char *string);
+int mxml_write_element(MXML_WRITER *writer, const char *name, const char *value);
+int mxml_write_attribute(MXML_WRITER *writer, const char *name, const char *value);
+int mxml_write_value(MXML_WRITER *writer, const char *value);
+int mxml_write_empty_line(MXML_WRITER *writer);
+char *mxml_close_buffer(MXML_WRITER *writer);
+int mxml_close_file(MXML_WRITER *writer);
+
+int mxml_get_number_of_children(PMXML_NODE pnode);
+PMXML_NODE mxml_get_parent(PMXML_NODE pnode);
+PMXML_NODE mxml_subnode(PMXML_NODE pnode, int idx);
+PMXML_NODE mxml_find_node(PMXML_NODE tree, const char *xml_path);
+int mxml_find_nodes(PMXML_NODE tree, const char *xml_path, PMXML_NODE **nodelist);
+char *mxml_get_name(PMXML_NODE pnode);
+char *mxml_get_value(PMXML_NODE pnode);
+int mxml_get_line_number_start(PMXML_NODE pnode);
+int mxml_get_line_number_end(PMXML_NODE pnode);
+PMXML_NODE mxml_get_node_at_line(PMXML_NODE tree, int linenumber);
+char *mxml_get_attribute(PMXML_NODE pnode, const char *name);
+
+int mxml_add_attribute(PMXML_NODE pnode, const char *attrib_name, const char *attrib_value);
+PMXML_NODE mxml_add_special_node(PMXML_NODE parent, int node_type, const char *node_name, const char *value);
+PMXML_NODE mxml_add_special_node_at(PMXML_NODE parent, int node_type, const char *node_name, const char *value, int idx);
+PMXML_NODE mxml_add_node(PMXML_NODE parent, const char *node_name, const char *value);
+PMXML_NODE mxml_add_node_at(PMXML_NODE parent, const char *node_name, const char *value, int idx);
+
+PMXML_NODE mxml_clone_tree(PMXML_NODE tree);
+int mxml_add_tree(PMXML_NODE parent, PMXML_NODE tree);
+int mxml_add_tree_at(PMXML_NODE parent, PMXML_NODE tree, int idx);
+
+int mxml_replace_node_name(PMXML_NODE pnode, const char *new_name);
+int mxml_replace_node_value(PMXML_NODE pnode, const char *value);
+int mxml_replace_subvalue(PMXML_NODE pnode, const char *name, const char *value);
+int mxml_replace_attribute_name(PMXML_NODE pnode, const char *old_name, const char *new_name);
+int mxml_replace_attribute_value(PMXML_NODE pnode, const char *attrib_name, const char *attrib_value);
+
+int mxml_delete_node(PMXML_NODE pnode);
+int mxml_delete_attribute(PMXML_NODE, const char *attrib_name);
+
+PMXML_NODE mxml_create_root_node(void);
+PMXML_NODE mxml_parse_file(const char *file_name, char *error, int error_size, int *error_line);
+PMXML_NODE mxml_parse_buffer(const char *buffer, char *error, int error_size, int *error_line);
+int mxml_parse_entity(char **buf, const char* file_name, char *error, int error_size, int *error_line);
+int mxml_write_tree(const char *file_name, PMXML_NODE tree);
+void mxml_debug_tree(PMXML_NODE tree, int level);
+void mxml_free_tree(PMXML_NODE tree);
+
+void mxml_dirname(char* path);
+void mxml_basename(char *path);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MXML_H_ */
+/*------------------------------------------------------------------*/
Index: instr/drsctrl/mxml.obj
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/instr/drsctrl/mxml.obj
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: instr/drsctrl/rb.cpp
===================================================================
--- instr/drsctrl/rb.cpp (nonexistent)
+++ instr/drsctrl/rb.cpp (revision 195)
@@ -0,0 +1,387 @@
+/********************************************************************\
+
+ Name: rb.c
+ Created by: Stefan Ritt
+
+ $Id: rb.cpp 21437 2014-07-30 14:13:29Z ritt $
+
+\********************************************************************/
+
+#include <stdio.h>
+#ifdef OS_DARWIN
+#include <sys/malloc.h>
+#else
+#include <malloc.h>
+#endif
+#include <string.h>
+#include <assert.h>
+
+#include "rb.h"
+
+/********************************************************************\
+* *
+* Ring buffer functions *
+* *
+* Provide an inter-thread buffer scheme for handling front-end *
+* events. This code allows concurrent data acquisition, calibration *
+* and network transfer on a multi-CPU machine. One thread reads *
+* out the data, passes it vis the ring buffer functions *
+* to another thread running on the other CPU, which can then *
+* calibrate and/or send the data over the network. *
+* *
+\********************************************************************/
+
+typedef struct {
+ unsigned char *buffer;
+ unsigned int size;
+ unsigned int max_event_size;
+ unsigned char *rp;
+ unsigned char *wp;
+ unsigned char *ep;
+} RING_BUFFER;
+
+#define MAX_RING_BUFFER 100
+RING_BUFFER rb[MAX_RING_BUFFER];
+
+volatile int _rb_nonblocking = 0;
+
+extern void ss_sleep(int ms);
+
+int rb_set_nonblocking()
+/********************************************************************\
+
+ Routine: rb_set_nonblocking
+
+ Purpose: Set all rb_get_xx to nonblocking. Needed in multi-thread
+ environments for stopping all theads without deadlock
+
+ Input:
+ NONE
+
+ Output:
+ NONE
+
+ Function value:
+ RB_SUCCESS Successful completion
+
+\********************************************************************/
+{
+ _rb_nonblocking = 1;
+
+ return RB_SUCCESS;
+}
+
+int rb_create(int size, int max_event_size, int *handle)
+/********************************************************************\
+
+ Routine: rb_create
+
+ Purpose: Create a ring buffer with a given size
+
+ Input:
+ int size Size of ring buffer, must be larger than
+ 2*max_event_size
+ int max_event_size Maximum event size to be placed into
+ ring buffer
+ Output:
+ int *handle Handle to ring buffer
+
+ Function value:
+ DB_SUCCESS Successful completion
+ DB_NO_MEMORY Maximum number of ring buffers exceeded
+ DB_INVALID_PARAM Invalid event size specified
+
+\********************************************************************/
+{
+ int i;
+
+ for (i = 0; i < MAX_RING_BUFFER; i++)
+ if (rb[i].buffer == NULL)
+ break;
+
+ if (i == MAX_RING_BUFFER)
+ return RB_NO_MEMORY;
+
+ if (size < max_event_size * 2)
+ return RB_INVALID_PARAM;
+
+ memset(&rb[i], 0, sizeof(RING_BUFFER));
+ rb[i].buffer = (unsigned char *) malloc(size);
+ assert(rb[i].buffer);
+ rb[i].size = size;
+ rb[i].max_event_size = max_event_size;
+ rb[i].rp = rb[i].buffer;
+ rb[i].wp = rb[i].buffer;
+ rb[i].ep = rb[i].buffer;
+
+ *handle = i + 1;
+
+ return RB_SUCCESS;
+}
+
+int rb_delete(int handle)
+/********************************************************************\
+
+ Routine: rb_delete
+
+ Purpose: Delete a ring buffer
+
+ Input:
+ none
+ Output:
+ int handle Handle to ring buffer
+
+ Function value:
+ DB_SUCCESS Successful completion
+
+\********************************************************************/
+{
+ if (handle < 0 || handle >= MAX_RING_BUFFER || rb[handle - 1].buffer == NULL)
+ return RB_INVALID_HANDLE;
+
+ free(rb[handle - 1].buffer);
+ memset(&rb[handle - 1], 0, sizeof(RING_BUFFER));
+
+ return RB_SUCCESS;
+}
+
+int rb_get_wp(int handle, void **p, int millisec)
+/********************************************************************\
+
+Routine: rb_get_wp
+
+ Purpose: Retrieve write pointer where new data can be written
+
+ Input:
+ int handle Ring buffer handle
+ int millisec Optional timeout in milliseconds if
+ buffer is full. Zero to not wait at
+ all (non-blocking)
+
+ Output:
+ char **p Write pointer
+
+ Function value:
+ DB_SUCCESS Successful completion
+
+\********************************************************************/
+{
+ int h, i;
+ unsigned char *rp;
+
+ if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL)
+ return RB_INVALID_HANDLE;
+
+ h = handle - 1;
+
+ for (i = 0; i <= millisec / 10; i++) {
+
+ rp = rb[h].rp; // keep local copy, rb[h].rp might be changed by other thread
+
+ /* check if enough size for wp >= rp without wrap-around */
+ if (rb[h].wp >= rp
+ && rb[h].wp + rb[h].max_event_size <= rb[h].buffer + rb[h].size - rb[h].max_event_size) {
+ *p = rb[h].wp;
+ return RB_SUCCESS;
+ }
+
+ /* check if enough size for wp >= rp with wrap-around */
+ if (rb[h].wp >= rp && rb[h].wp + rb[h].max_event_size > rb[h].buffer + rb[h].size - rb[h].max_event_size && rb[h].rp > rb[h].buffer) { // next increment of wp wraps around, so need space at beginning
+ *p = rb[h].wp;
+ return RB_SUCCESS;
+ }
+
+ /* check if enough size for wp < rp */
+ if (rb[h].wp < rp && rb[h].wp + rb[h].max_event_size < rp) {
+ *p = rb[h].wp;
+ return RB_SUCCESS;
+ }
+
+ if (millisec == 0)
+ return RB_TIMEOUT;
+
+ if (_rb_nonblocking)
+ return RB_TIMEOUT;
+
+ /* wait one time slice */
+ ss_sleep(10);
+ }
+
+ return RB_TIMEOUT;
+}
+
+int rb_increment_wp(int handle, int size)
+/********************************************************************\
+
+ Routine: rb_increment_wp
+
+ Purpose: Increment current write pointer, making the data at
+ the write pointer available to the receiving thread
+
+ Input:
+ int handle Ring buffer handle
+ int size Number of bytes placed at the WP
+
+ Output:
+ NONE
+
+ Function value:
+ RB_SUCCESS Successful completion
+ RB_INVALID_PARAM Event size too large or invalid handle
+\********************************************************************/
+{
+ int h;
+ unsigned char *new_wp;
+
+ if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL)
+ return RB_INVALID_HANDLE;
+
+ h = handle - 1;
+
+ if ((unsigned int) size > rb[h].max_event_size)
+ return RB_INVALID_PARAM;
+
+ new_wp = rb[h].wp + size;
+
+ /* wrap around wp if not enough space */
+ if (new_wp > rb[h].buffer + rb[h].size - rb[h].max_event_size) {
+ rb[h].ep = new_wp;
+ new_wp = rb[h].buffer;
+ assert(rb[h].rp != rb[h].buffer);
+ }
+
+ rb[h].wp = new_wp;
+
+ return RB_SUCCESS;
+}
+
+int rb_get_rp(int handle, void **p, int millisec)
+/********************************************************************\
+
+ Routine: rb_get_rp
+
+ Purpose: Obtain the current read pointer at which new data is
+ available with optional timeout
+
+ Input:
+ int handle Ring buffer handle
+ int millisec Optional timeout in milliseconds if
+ buffer is full. Zero to not wait at
+ all (non-blocking)
+
+ Output:
+ char **p Address of pointer pointing to newly
+ available data. If p == NULL, only
+ return status.
+
+ Function value:
+ RB_SUCCESS Successful completion
+
+\********************************************************************/
+{
+ int i, h;
+
+ if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL)
+ return RB_INVALID_HANDLE;
+
+ h = handle - 1;
+
+ for (i = 0; i <= millisec / 10; i++) {
+
+ if (rb[h].wp != rb[h].rp) {
+ if (p != NULL)
+ *p = rb[handle - 1].rp;
+ return RB_SUCCESS;
+ }
+
+ if (millisec == 0)
+ return RB_TIMEOUT;
+
+ if (_rb_nonblocking)
+ return RB_TIMEOUT;
+
+ /* wait one time slice */
+ ss_sleep(10);
+ }
+
+ return RB_TIMEOUT;
+}
+
+int rb_increment_rp(int handle, int size)
+/********************************************************************\
+
+ Routine: rb_increment_rp
+
+ Purpose: Increment current read pointer, freeing up space for
+ the writing thread.
+
+ Input:
+ int handle Ring buffer handle
+ int size Number of bytes to free up at current
+ read pointer
+
+ Output:
+ NONE
+
+ Function value:
+ RB_SUCCESS Successful completion
+ RB_INVALID_PARAM Event size too large or invalid handle
+
+\********************************************************************/
+{
+ int h;
+
+ unsigned char *new_rp;
+
+ if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL)
+ return RB_INVALID_HANDLE;
+
+ h = handle - 1;
+
+ if ((unsigned int) size > rb[h].max_event_size)
+ return RB_INVALID_PARAM;
+
+ new_rp = rb[h].rp + size;
+
+ /* wrap around if not enough space left */
+ if (new_rp + rb[h].max_event_size > rb[h].buffer + rb[h].size)
+ new_rp = rb[h].buffer;
+
+ rb[handle - 1].rp = new_rp;
+
+ return RB_SUCCESS;
+}
+
+int rb_get_buffer_level(int handle, int *n_bytes)
+/********************************************************************\
+
+ Routine: rb_get_buffer_level
+
+ Purpose: Return number of bytes in a ring buffer
+
+ Input:
+ int handle Handle of the buffer to get the info
+
+ Output:
+ int *n_bytes Number of bytes in buffer
+
+ Function value:
+ RB_SUCCESS Successful completion
+ RB_INVALID_HANDLE Buffer handle is invalid
+
+\********************************************************************/
+{
+ int h;
+
+ if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL)
+ return RB_INVALID_HANDLE;
+
+ h = handle - 1;
+
+ if (rb[h].wp >= rb[h].rp)
+ *n_bytes = rb[h].wp - rb[h].rp;
+ else
+ *n_bytes = rb[h].ep - rb[h].rp + rb[h].wp - rb[h].buffer;
+
+ return RB_SUCCESS;
+}
Index: instr/drsctrl/rb.h
===================================================================
--- instr/drsctrl/rb.h (nonexistent)
+++ instr/drsctrl/rb.h (revision 195)
@@ -0,0 +1,28 @@
+/********************************************************************\
+
+ Name: rb.h
+ Created by: Stefan Ritt
+
+ Contents: Function declarations and constants for ring buffer
+ routines
+
+ $Id: rb.h 17217 2011-02-25 15:31:29Z ritt $
+
+\********************************************************************/
+
+#define RB_SUCCESS 1
+#define RB_NO_MEMORY 2
+#define RB_INVALID_PARAM 3
+#define RB_INVALID_HANDLE 4
+#define RB_TIMEOUT 5
+
+#define POINTER_T unsigned int
+
+int rb_set_nonblocking();
+int rb_create(int size, int max_event_size, int *ring_buffer_handle);
+int rb_delete(int ring_buffer_handle);
+int rb_get_wp(int handle, void **p, int millisec);
+int rb_increment_wp(int handle, int size);
+int rb_get_rp(int handle, void **p, int millisec);
+int rb_increment_rp(int handle, int size);
+int rb_get_buffer_level(int handle, int * n_bytes);
Index: instr/drsctrl/read_binary.cpp
===================================================================
--- instr/drsctrl/read_binary.cpp (nonexistent)
+++ instr/drsctrl/read_binary.cpp (revision 195)
@@ -0,0 +1,250 @@
+/*
+ Name: read_binary.cpp
+ Created by: Stefan Ritt <stefan.ritt@psi.ch>
+ Date: July 30th, 2014
+
+ Purpose: Example file to read binary data saved by DRSOsc.
+
+ Compile and run it with:
+
+ gcc -o read_binary read_binary.cpp
+
+ ./read_binary <filename>
+
+ This program assumes that a pulse from a signal generator is split
+ and fed into channels #1 and #2. It then calculates the time difference
+ between these two pulses to show the performance of the DRS board
+ for time measurements.
+
+ $Id: read_binary.cpp 22321 2016-08-25 12:26:12Z ritt $
+*/
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <math.h>
+
+typedef struct {
+ char tag[3];
+ char version;
+} FHEADER;
+
+typedef struct {
+ char time_header[4];
+} THEADER;
+
+typedef struct {
+ char bn[2];
+ unsigned short board_serial_number;
+} BHEADER;
+
+typedef struct {
+ char event_header[4];
+ unsigned int event_serial_number;
+ unsigned short year;
+ unsigned short month;
+ unsigned short day;
+ unsigned short hour;
+ unsigned short minute;
+ unsigned short second;
+ unsigned short millisecond;
+ unsigned short range;
+} EHEADER;
+
+typedef struct {
+ char tc[2];
+ unsigned short trigger_cell;
+} TCHEADER;
+
+typedef struct {
+ char c[1];
+ char cn[3];
+} CHEADER;
+
+/*-----------------------------------------------------------------------------*/
+
+int main(int argc, const char * argv[])
+{
+ FHEADER fh;
+ THEADER th;
+ BHEADER bh;
+ EHEADER eh;
+ TCHEADER tch;
+ CHEADER ch;
+
+ unsigned int scaler;
+ unsigned short voltage[1024];
+ double waveform[16][4][1024], time[16][4][1024];
+ float bin_width[16][4][1024];
+ int i, j, b, chn, n, chn_index, n_boards;
+ double t1, t2, dt;
+ char filename[256];
+
+ int ndt;
+ double threshold, sumdt, sumdt2;
+
+ if (argc > 1)
+ strcpy(filename, argv[1]);
+ else {
+ printf("Usage: read_binary <filename>\n");
+ return 0;
+ }
+
+ // open the binary waveform file
+ FILE *f = fopen(filename, "rb");
+ if (f == NULL) {
+ printf("Cannot find file \'%s\'\n", filename);
+ return 0;
+ }
+
+ // read file header
+ fread(&fh, sizeof(fh), 1, f);
+ if (fh.tag[0] != 'D' || fh.tag[1] != 'R' || fh.tag[2] != 'S') {
+ printf("Found invalid file header in file \'%s\', aborting.\n", filename);
+ return 0;
+ }
+
+ if (fh.version != '2') {
+ printf("Found invalid file version \'%c\' in file \'%s\', should be \'2\', aborting.\n", fh.version, filename);
+ return 0;
+ }
+
+ // read time header
+ fread(&th, sizeof(th), 1, f);
+ if (memcmp(th.time_header, "TIME", 4) != 0) {
+ printf("Invalid time header in file \'%s\', aborting.\n", filename);
+ return 0;
+ }
+
+ for (b = 0 ; ; b++) {
+ // read board header
+ fread(&bh, sizeof(bh), 1, f);
+ if (memcmp(bh.bn, "B#", 2) != 0) {
+ // probably event header found
+ fseek(f, -4, SEEK_CUR);
+ break;
+ }
+
+ printf("Found data for board #%d\n", bh.board_serial_number);
+
+ // read time bin widths
+ memset(bin_width[b], sizeof(bin_width[0]), 0);
+ for (chn=0 ; chn<5 ; chn++) {
+ fread(&ch, sizeof(ch), 1, f);
+ if (ch.c[0] != 'C') {
+ // event header found
+ fseek(f, -4, SEEK_CUR);
+ break;
+ }
+ i = ch.cn[2] - '0' - 1;
+ printf("Found timing calibration for channel #%d\n", i+1);
+ fread(&bin_width[b][i][0], sizeof(float), 1024, f);
+ // fix for 2048 bin mode: double channel
+ if (bin_width[b][i][1023] > 10 || bin_width[b][i][1023] < 0.01) {
+ for (j=0 ; j<512 ; j++)
+ bin_width[b][i][j+512] = bin_width[b][i][j];
+ }
+ }
+ }
+ n_boards = b;
+
+ // initialize statistics
+ ndt = 0;
+ sumdt = sumdt2 = 0;
+
+ // loop over all events in the data file
+ for (n=0 ; ; n++) {
+ // read event header
+ i = (int)fread(&eh, sizeof(eh), 1, f);
+ if (i < 1)
+ break;
+
+ printf("Found event #%d %d %d\n", eh.event_serial_number, eh.second, eh.millisecond);
+
+ // loop over all boards in data file
+ for (b=0 ; b<n_boards ; b++) {
+
+ // read board header
+ fread(&bh, sizeof(bh), 1, f);
+ if (memcmp(bh.bn, "B#", 2) != 0) {
+ printf("Invalid board header in file \'%s\', aborting.\n", filename);
+ return 0;
+ }
+
+ // read trigger cell
+ fread(&tch, sizeof(tch), 1, f);
+ if (memcmp(tch.tc, "T#", 2) != 0) {
+ printf("Invalid trigger cell header in file \'%s\', aborting.\n", filename);
+ return 0;
+ }
+
+ if (n_boards > 1)
+ printf("Found data for board #%d\n", bh.board_serial_number);
+
+ // reach channel data
+ for (chn=0 ; chn<4 ; chn++) {
+
+ // read channel header
+ fread(&ch, sizeof(ch), 1, f);
+ if (ch.c[0] != 'C') {
+ // event header found
+ fseek(f, -4, SEEK_CUR);
+ break;
+ }
+ chn_index = ch.cn[2] - '0' - 1;
+ fread(&scaler, sizeof(int), 1, f);
+ fread(voltage, sizeof(short), 1024, f);
+
+ for (i=0 ; i<1024 ; i++) {
+ // convert data to volts
+ waveform[b][chn_index][i] = (voltage[i] / 65536. + eh.range/1000.0 - 0.5);
+
+ // calculate time for this cell
+ for (j=0,time[b][chn_index][i]=0 ; j<i ; j++)
+ time[b][chn_index][i] += bin_width[b][chn_index][(j+tch.trigger_cell) % 1024];
+ }
+ }
+
+ // align cell #0 of all channels
+ t1 = time[b][0][(1024-tch.trigger_cell) % 1024];
+ for (chn=1 ; chn<4 ; chn++) {
+ t2 = time[b][chn][(1024-tch.trigger_cell) % 1024];
+ dt = t1 - t2;
+ for (i=0 ; i<1024 ; i++)
+ time[b][chn][i] += dt;
+ }
+
+ t1 = t2 = 0;
+ threshold = 0.3;
+
+ // find peak in channel 1 above threshold
+ for (i=0 ; i<1022 ; i++)
+ if (waveform[b][0][i] < threshold && waveform[b][0][i+1] >= threshold) {
+ t1 = (threshold-waveform[b][0][i])/(waveform[b][0][i+1]-waveform[b][0][i])*(time[b][0][i+1]-time[b][0][i])+time[b][0][i];
+ break;
+ }
+
+ // find peak in channel 2 above threshold
+ for (i=0 ; i<1022 ; i++)
+ if (waveform[b][1][i] < threshold && waveform[b][1][i+1] >= threshold) {
+ t2 = (threshold-waveform[b][1][i])/(waveform[b][1][i+1]-waveform[b][1][i])*(time[b][1][i+1]-time[b][1][i])+time[b][1][i];
+ break;
+ }
+
+ // calculate distance of peaks with statistics
+ if (t1 > 0 && t2 > 0) {
+ ndt++;
+ dt = t2 - t1;
+ sumdt += dt;
+ sumdt2 += dt*dt;
+ }
+ }
+ }
+
+ // print statistics
+ printf("dT = %1.3lfns +- %1.1lfps\n", sumdt/ndt, 1000*sqrt(1.0/(ndt-1)*(sumdt2-1.0/ndt*sumdt*sumdt)));
+
+ return 1;
+}
+
Index: instr/drsctrl/readdata.cpp
===================================================================
--- instr/drsctrl/readdata.cpp (nonexistent)
+++ instr/drsctrl/readdata.cpp (revision 195)
@@ -0,0 +1 @@
+
Index: instr/drsctrl/startroot.bat
===================================================================
--- instr/drsctrl/startroot.bat (nonexistent)
+++ instr/drsctrl/startroot.bat (revision 195)
@@ -0,0 +1 @@
+cmd.exe /k thisroot.bat
Index: instr/drsctrl/strlcpy.c
===================================================================
--- instr/drsctrl/strlcpy.c (nonexistent)
+++ instr/drsctrl/strlcpy.c (revision 195)
@@ -0,0 +1,101 @@
+/********************************************************************\
+
+ Name: strlcpy.c
+ Created by: Stefan Ritt
+ Copyright 2000 + Stefan Ritt
+
+ Contents: Contains strlcpy and strlcat which are versions of
+ strcpy and strcat, but which avoid buffer overflows
+
+
+ This file is part of MIDAS XML Library.
+
+ MIDAS XML Library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MIDAS XML Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MIDAS XML Library. If not, see <http://www.gnu.org/licenses/>.
+
+\********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include "strlcpy.h"
+
+/*
+* Copy src to string dst of size siz. At most siz-1 characters
+* will be copied. Always NUL terminates (unless size == 0).
+* Returns strlen(src); if retval >= siz, truncation occurred.
+*/
+#ifndef STRLCPY_DEFINED
+
+size_t strlcpy(char *dst, const char *src, size_t size)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = size;
+
+ /* Copy as many bytes as will fit */
+ if (n != 0 && --n != 0) {
+ do {
+ if ((*d++ = *s++) == 0)
+ break;
+ } while (--n != 0);
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src */
+ if (n == 0) {
+ if (size != 0)
+ *d = '\0'; /* NUL-terminate dst */
+ while (*s++);
+ }
+
+ return (s - src - 1); /* count does not include NUL */
+}
+
+/*-------------------------------------------------------------------*/
+
+/*
+* Appends src to string dst of size siz (unlike strncat, siz is the
+* full size of dst, not space left). At most siz-1 characters
+* will be copied. Always NUL terminates (unless size <= strlen(dst)).
+* Returns strlen(src) + MIN(size, strlen(initial dst)).
+* If retval >= size, truncation occurred.
+*/
+size_t strlcat(char *dst, const char *src, size_t size)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = size;
+ size_t dlen;
+
+ /* Find the end of dst and adjust bytes left but don't go past end */
+ while (n-- != 0 && *d != '\0')
+ d++;
+ dlen = d - dst;
+ n = size - dlen;
+
+ if (n == 0)
+ return (dlen + strlen(s));
+ while (*s != '\0') {
+ if (n != 1) {
+ *d++ = *s;
+ n--;
+ }
+ s++;
+ }
+ *d = '\0';
+
+ return (dlen + (s - src)); /* count does not include NUL */
+}
+
+/*-------------------------------------------------------------------*/
+
+#endif // STRLCPY_DEFINED
Index: instr/drsctrl/strlcpy.h
===================================================================
--- instr/drsctrl/strlcpy.h (nonexistent)
+++ instr/drsctrl/strlcpy.h (revision 195)
@@ -0,0 +1,55 @@
+/********************************************************************\
+
+ Name: strlcpy.h
+ Created by: Stefan Ritt
+ Copyright 2000 + Stefan Ritt
+
+ Contents: Header file for strlcpy.c
+
+ This file is part of MIDAS XML Library.
+
+ MIDAS XML Library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MIDAS XML Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MIDAS XML Library. If not, see <http://www.gnu.org/licenses/>.
+
+\********************************************************************/
+
+#ifndef _STRLCPY_H_
+#define _STRLCPY_H_
+
+// some version of gcc have a built-in strlcpy
+#ifdef strlcpy
+#define STRLCPY_DEFINED
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef EXPRT
+#if defined(EXPORT_DLL)
+#define EXPRT __declspec(dllexport)
+#else
+#define EXPRT
+#endif
+#endif
+
+#ifndef STRLCPY_DEFINED
+size_t EXPRT strlcpy(char *dst, const char *src, size_t size);
+size_t EXPRT strlcat(char *dst, const char *src, size_t size);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_STRLCPY_H_ */
Index: instr/drsctrl/strlcpy.obj
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/instr/drsctrl/strlcpy.obj
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: instr/drsctrl/thisroot.bat
===================================================================
--- instr/drsctrl/thisroot.bat (nonexistent)
+++ instr/drsctrl/thisroot.bat (revision 195)
@@ -0,0 +1,25 @@
+@echo off
+set MPATH=%~dp0
+rem set MPATH=%CD%
+
+cd "\"
+FOR /D %%x in ("Program Files*") do (
+ cd /D %%x
+ if exist "Microsoft SDKs\Windows\v7.1A\Include" set INCLUDE=%INCLUDE%;%CD%%%x\Microsoft SDKs\Windows\v7.1A\Include
+ For /D %%G in ("Microsoft Visual Studio*") do set VC=%%x\%%G
+ cd "\"
+)
+
+echo call "%VC%\VC\vcvarsall.bat" x86
+call "%VC%\VC\vcvarsall.bat" x86
+
+
+cd "\"
+FOR /D %%G IN ("root*") DO SET ROOTSYS=c:\%%G
+
+echo ROOTSYS= "%ROOTSYS%"
+echo INCLUDE="%INCLUDE%"
+
+echo Visual C Development environment
+echo nmake -f Makefile.win32
+cd /D "%MPATH%"
\ No newline at end of file
Index: instr/drsctrl/timer.c
===================================================================
--- instr/drsctrl/timer.c (nonexistent)
+++ instr/drsctrl/timer.c (revision 195)
@@ -0,0 +1,142 @@
+/*
+***************************************************************************
+*
+* Author: Teunis van Beelen
+*
+* Copyright (C) 2010, 2011, 2012 Teunis van Beelen
+*
+* teuniz@gmail.com
+*
+***************************************************************************
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation version 2 of the License.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+***************************************************************************
+*
+* This version of GPL is at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+*
+***************************************************************************
+*/
+
+
+
+#include "timer.h"
+
+
+
+void (*timer_func_handler_pntr)(void);
+
+
+#ifdef __linux__
+
+void timer_handler(int);
+
+struct itimerval timervalue;
+
+struct sigaction new_handler, old_handler;
+
+void timer_sig_handler(int);
+
+
+
+int start_timer(int mSec, void (*timer_func_handler)(void))
+{
+ timer_func_handler_pntr = timer_func_handler;
+
+ timervalue.it_interval.tv_sec = mSec / 1000;
+ timervalue.it_interval.tv_usec = (mSec % 1000) * 1000;
+ timervalue.it_value.tv_sec = mSec / 1000;
+ timervalue.it_value.tv_usec = (mSec % 1000) * 1000;
+ if(setitimer(ITIMER_REAL, &timervalue, NULL))
+ {
+ printf("\nsetitimer() error\n");
+ return(1);
+ }
+
+ new_handler.sa_handler = &timer_sig_handler;
+ new_handler.sa_flags = SA_NOMASK;
+ if(sigaction(SIGALRM, &new_handler, &old_handler))
+ {
+ printf("\nsigaction() error\n");
+ return(1);
+ }
+
+ return(0);
+}
+
+
+void timer_sig_handler(int arg)
+{
+ timer_func_handler_pntr();
+}
+
+
+void stop_timer(void)
+{
+ timervalue.it_interval.tv_sec = 0;
+ timervalue.it_interval.tv_usec = 0;
+ timervalue.it_value.tv_sec = 0;
+ timervalue.it_value.tv_usec = 0;
+ setitimer(ITIMER_REAL, &timervalue, NULL);
+
+ sigaction(SIGALRM, &old_handler, NULL);
+}
+
+#else
+
+HANDLE win_timer;
+
+VOID CALLBACK timer_sig_handler(PVOID, BOOLEAN);
+
+
+int start_timer(int mSec, void (*timer_func_handler)(void))
+{
+ timer_func_handler_pntr = timer_func_handler;
+
+ if(CreateTimerQueueTimer(&win_timer, NULL, (WAITORTIMERCALLBACK)timer_sig_handler, NULL, mSec, mSec, WT_EXECUTEINTIMERTHREAD) == 0)
+ {
+ printf("\nCreateTimerQueueTimer() error\n");
+ return(1);
+ }
+
+ return(0);
+}
+
+
+VOID CALLBACK timer_sig_handler(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
+{
+ timer_func_handler_pntr();
+}
+
+
+void stop_timer(void)
+{
+ DeleteTimerQueueTimer(NULL, win_timer, NULL);
+ CloseHandle(win_timer);
+}
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: instr/drsctrl/timer.h
===================================================================
--- instr/drsctrl/timer.h (nonexistent)
+++ instr/drsctrl/timer.h (revision 195)
@@ -0,0 +1,78 @@
+/*
+***************************************************************************
+*
+* Author: Teunis van Beelen
+*
+* Copyright (C) 2010, 2011, 2012 Teunis van Beelen
+*
+* teuniz@gmail.com
+*
+***************************************************************************
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation version 2 of the License.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+***************************************************************************
+*
+* This version of GPL is at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+*
+***************************************************************************
+*/
+
+
+
+#include <stdio.h>
+
+#ifdef __linux__
+
+#include <sys/time.h>
+#include <signal.h>
+
+#else
+
+/* this code only works on win2000, XP, Vista, 7 and up */
+/* win95, win98 and ME are not supported */
+/* WINVER must have value 0x500 or higher */
+#ifndef WINVER
+#define WINVER 0x500
+#endif
+
+#if WINVER < 0x500
+#error "WINVER is < 0x500, cannot compile for old windows versions"
+#endif
+
+#include <windows.h>
+
+#endif
+
+
+#ifndef timer_INCLUDED
+#define timer_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+int start_timer(int, void (*)(void));
+
+void stop_timer(void);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
+
+
Index: instr/drsctrl/timer.obj
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/instr/drsctrl/timer.obj
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property