/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_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_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_TRG_DELAY, 2); |
reg = (reg & 0xFF) | (ticks << 8); |
Write(T_CTRL, REG_TRG_DELAY, ®, 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, ®, 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: drsctrl/LinkDef.h |
=================================================================== |
--- drsctrl/LinkDef.h (nonexistent) |
+++ 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: drsctrl/Makefile |
=================================================================== |
--- drsctrl/Makefile (nonexistent) |
+++ 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: drsctrl/XGetopt.cpp |
=================================================================== |
--- drsctrl/XGetopt.cpp (nonexistent) |
+++ 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: drsctrl/XGetopt.h |
=================================================================== |
--- drsctrl/XGetopt.h (nonexistent) |
+++ 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: drsctrl/XGetopt.obj |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/drsctrl/XGetopt.obj |
---|
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: drsctrl/averager.cpp |
=================================================================== |
--- drsctrl/averager.cpp (nonexistent) |
+++ 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: drsctrl/averager.h |
=================================================================== |
--- drsctrl/averager.h (nonexistent) |
+++ 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: drsctrl/averager.obj |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/drsctrl/averager.obj |
---|
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: drsctrl/daq.h |
=================================================================== |
--- drsctrl/daq.h (nonexistent) |
+++ 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: drsctrl/drs.h |
=================================================================== |
--- drsctrl/drs.h (nonexistent) |
+++ 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: drsctrl/drs4.c |
=================================================================== |
--- drsctrl/drs4.c (nonexistent) |
+++ 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: drsctrl/drs4.cws |
=================================================================== |
--- drsctrl/drs4.cws (nonexistent) |
+++ 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: drsctrl/drs4.exe |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/drsctrl/drs4.exe |
---|
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: drsctrl/drs4.h |
=================================================================== |
--- drsctrl/drs4.h (nonexistent) |
+++ 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: drsctrl/drs4.prj |
=================================================================== |
--- drsctrl/drs4.prj (nonexistent) |
+++ 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: drsctrl/drs4.uir |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/drsctrl/drs4.uir |
---|
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: drsctrl/drscl.cpp |
=================================================================== |
--- drsctrl/drscl.cpp (nonexistent) |
+++ 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: drsctrl/drscl.exe |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/drsctrl/drscl.exe |
---|
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: drsctrl/drscl.obj |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/drsctrl/drscl.obj |
---|
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: drsctrl/drsread.c |
=================================================================== |
--- drsctrl/drsread.c (nonexistent) |
+++ 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: drsctrl/drsread.cpp |
=================================================================== |
--- drsctrl/drsread.cpp (nonexistent) |
+++ 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: drsctrl/drsread.dll |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/drsctrl/drsread.dll |
---|
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: drsctrl/drsread.exe |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/drsctrl/drsread.exe |
---|
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: drsctrl/drsread.exp |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/drsctrl/drsread.exp |
---|
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: drsctrl/drsread.h |
=================================================================== |
--- drsctrl/drsread.h (nonexistent) |
+++ 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: drsctrl/drsread.lib |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/drsctrl/drsread.lib |
---|
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: drsctrl/drsread.obj |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/drsctrl/drsread.obj |
---|
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: drsctrl/getopt.h |
=================================================================== |
--- drsctrl/getopt.h (nonexistent) |
+++ 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: drsctrl/getopt_long.c |
=================================================================== |
--- drsctrl/getopt_long.c (nonexistent) |
+++ 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: drsctrl/getopt_long.obj |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/drsctrl/getopt_long.obj |
---|
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: drsctrl/gettimeofday.c |
=================================================================== |
--- drsctrl/gettimeofday.c (nonexistent) |
+++ 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: drsctrl/gettimeofday.h |
=================================================================== |
--- drsctrl/gettimeofday.h (nonexistent) |
+++ 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: drsctrl/gettimeofday.obj |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/drsctrl/gettimeofday.obj |
---|
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: drsctrl/gui.cpp |
=================================================================== |
--- drsctrl/gui.cpp (nonexistent) |
+++ 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: drsctrl/libusb-1.0/libusb.h |
=================================================================== |
--- drsctrl/libusb-1.0/libusb.h (nonexistent) |
+++ 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: drsctrl/libusb-1.0.lib |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/drsctrl/libusb-1.0.lib |
---|
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: drsctrl/musbstd.c |
=================================================================== |
--- drsctrl/musbstd.c (nonexistent) |
+++ 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: drsctrl/musbstd.h |
=================================================================== |
--- drsctrl/musbstd.h (nonexistent) |
+++ 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: drsctrl/musbstd.obj |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/drsctrl/musbstd.obj |
---|
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: drsctrl/mxml.c |
=================================================================== |
--- drsctrl/mxml.c (nonexistent) |
+++ 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, "<"); |
+ pd += 4; |
+ break; |
+ case '>': |
+ strcpy(pd, ">"); |
+ pd += 4; |
+ break; |
+ case '&': |
+ strcpy(pd, "&"); |
+ pd += 5; |
+ break; |
+ case '\"': |
+ strcpy(pd, """); |
+ pd += 6; |
+ break; |
+ case '\'': |
+ strcpy(pd, "'"); |
+ pd += 6; |
+ break; |
+ default: |
+ *pd++ = *ps; |
+ } |
+ } else { |
+ switch (*ps) { /* translate only illegal XML characters "<" and "&" */ |
+ case '<': |
+ strcpy(pd, "<"); |
+ pd += 4; |
+ break; |
+ case '&': |
+ strcpy(pd, "&"); |
+ 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, "<", 4) == 0) { |
+ *(p++) = '<'; |
+ memmove(p, p+3, strlen(p+3) + 1); |
+ } |
+ else if (strncmp(p, ">", 4) == 0) { |
+ *(p++) = '>'; |
+ memmove(p, p+3, strlen(p+3) + 1); |
+ } |
+ else if (strncmp(p, "&", 5) == 0) { |
+ *(p++) = '&'; |
+ memmove(p, p+4, strlen(p+4) + 1); |
+ } |
+ else if (strncmp(p, """, 6) == 0) { |
+ *(p++) = '\"'; |
+ memmove(p, p+5, strlen(p+5) + 1); |
+ } |
+ else if (strncmp(p, "'", 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: drsctrl/mxml.h |
=================================================================== |
--- drsctrl/mxml.h (nonexistent) |
+++ 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: drsctrl/mxml.obj |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/drsctrl/mxml.obj |
---|
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: drsctrl/rb.cpp |
=================================================================== |
--- drsctrl/rb.cpp (nonexistent) |
+++ 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: drsctrl/rb.h |
=================================================================== |
--- drsctrl/rb.h (nonexistent) |
+++ 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: drsctrl/read_binary.cpp |
=================================================================== |
--- drsctrl/read_binary.cpp (nonexistent) |
+++ 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: drsctrl/readdata.cpp |
=================================================================== |
--- drsctrl/readdata.cpp (nonexistent) |
+++ drsctrl/readdata.cpp (revision 195) |
@@ -0,0 +1 @@ |
+ |
Index: drsctrl/startroot.bat |
=================================================================== |
--- drsctrl/startroot.bat (nonexistent) |
+++ drsctrl/startroot.bat (revision 195) |
@@ -0,0 +1 @@ |
+cmd.exe /k thisroot.bat |
Index: drsctrl/strlcpy.c |
=================================================================== |
--- drsctrl/strlcpy.c (nonexistent) |
+++ 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: drsctrl/strlcpy.h |
=================================================================== |
--- drsctrl/strlcpy.h (nonexistent) |
+++ 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: drsctrl/strlcpy.obj |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/drsctrl/strlcpy.obj |
---|
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: drsctrl/thisroot.bat |
=================================================================== |
--- drsctrl/thisroot.bat (nonexistent) |
+++ 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: drsctrl/timer.c |
=================================================================== |
--- drsctrl/timer.c (nonexistent) |
+++ 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: drsctrl/timer.h |
=================================================================== |
--- drsctrl/timer.h (nonexistent) |
+++ 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: drsctrl/timer.obj |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/drsctrl/timer.obj |
---|
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |