/cvi/instr/drsctrl/drsread.lib |
Cannot display: file marked as a binary type.
|
svn:mime-type = application/octet-stream |
Property changes: |
Deleted: svn:mime-type |
## -1 +0,0 ## |
-application/octet-stream |
\ No newline at end of property |
Index: instr/drsctrl/drs4.c |
=================================================================== |
--- instr/drsctrl/drs4.c (revision 196) |
+++ instr/drsctrl/drs4.c (nonexistent) |
@@ -1,216 +0,0 @@ |
-#include <utility.h> |
-#include <ansi_c.h> |
-#include <cvirte.h> |
-#include <userint.h> |
-#include "drs4.h" |
-#include "drsread.h" |
- |
-static int daq_on; |
-static int ph, plothandle; |
-static int tfID; |
-static int controlID; |
- |
-#define MAX_THREADS 10 |
- |
-static CmtThreadPoolHandle poolHandle = 0; |
- |
-int main (int argc, char *argv[]) { |
- if (InitCVIRTE (0, argv, 0) == 0) |
- return -1; /* out of memory */ |
- if ((ph = LoadPanel (0, "drs4.uir", PANEL)) < 0) |
- return -1; |
- SetStdioPort (CVI_STDIO_WINDOW); |
- SetSleepPolicy(VAL_SLEEP_MORE); |
- CmtNewThreadPool (MAX_THREADS, &poolHandle); |
- |
- DisplayPanel (ph); |
- RunUserInterface (); |
- DiscardPanel (ph); |
- CmtDiscardThreadPool (poolHandle); |
- return 0; |
-} |
- |
- |
- |
- |
- |
-static void start_timer (double tout) { |
- SetCtrlAttribute (ph, PANEL_TIMER, ATTR_INTERVAL, tout); |
- SetCtrlAttribute (ph, PANEL_TIMER, ATTR_ENABLED, 1); |
-} |
- |
-static void stop_timer ( void ) { |
- SetCtrlAttribute (ph, PANEL_TIMER, ATTR_ENABLED, 0); |
- DRSSetTimeout(); |
-} |
- |
- |
- |
- |
-void CVICALLBACK EndOfThread ( CmtThreadPoolHandle poolhandle, |
- CmtThreadFunctionID functionID, unsigned int event, |
- int value, void *callbackData ) { |
- |
- daq_on=0; |
- //SetDimming(0); |
- printf("End of Thread \n"); |
- return ; |
- |
-} |
- |
- |
-int CVICALLBACK daq(void *functionData) { |
- |
- |
- int neve; |
- char filename[0xff]; |
- char smask[0xff]; |
- unsigned long mask; |
- int frequency; |
- double trgdelay; |
- double trglevel; |
- int trgtype; |
- int trgchannel; |
- int trgpolarity; |
- int verbose; |
- double range; |
- |
- |
- GetCtrlVal(ph, PANEL_FILENAME, filename ); |
- GetCtrlVal(ph, PANEL_MASK, smask ); |
- mask = strtoul (smask,NULL,0); |
- GetCtrlVal(ph,PANEL_NEVE, &neve); |
- |
- GetCtrlVal(ph,PANEL_FREQUENCY, &frequency); |
- GetCtrlVal(ph,PANEL_TRGDELAY, &trgdelay); |
- GetCtrlVal(ph,PANEL_TRGCHANNEL, &trgchannel); |
- GetCtrlVal(ph,PANEL_TRGTYPE, &trgtype); |
- GetCtrlVal(ph,PANEL_TRGLEVEL, &trglevel); |
- GetCtrlVal(ph,PANEL_TRGPOLARITY, &trgpolarity); |
- GetCtrlVal(ph,PANEL_RANGE, &range); |
- GetCtrlVal(ph,PANEL_DEBUG, &verbose); |
- |
- printf("mask=0x%x\n",mask); |
- |
- DRSSetMask( (unsigned char)( mask & 0xF ) ); |
- |
- DRSSetFrequency( frequency ); |
- DRSSetTriggerPolarity(trgpolarity); |
- DRSSetTriggerLevel(trglevel); |
- DRSSetRange ( range ); |
- DRSSetTriggerType( trgtype ); |
- DRSSetTriggerChannel(trgchannel ); |
- |
- FILE *fp=fopen(filename,"wb"); |
- |
- |
- static unsigned char *buffer; |
- |
- int buffer_size = 0; |
-const int nBoards=1; |
-const int waveDepth=1024; |
-if (buffer_size == 0) { |
- buffer_size = 4 + nBoards * (4 + 4*(4+waveDepth*4)); |
- buffer_size += 24 + nBoards * (8 + 4*(4+waveDepth*2)); |
- buffer = (unsigned char *)malloc(buffer_size); |
-} |
- |
-time_t t,told, tstart; |
- |
-if (!DRSInit()){ |
- time(&tstart); |
- told=tstart; |
- int i=0; |
- for (i=0; i<neve; i++) { |
- start_timer(1);// 1 s timeout |
- int retval = DRSRead(0); |
- stop_timer(); |
- int nb = ( retval == 0 && fp ) ? DRSToBuffer( buffer , i ) : 0; |
- SetCtrlVal(ph,PANEL_CEVE,i); |
- if (retval) i--; |
- if (!daq_on) break; |
- time(&t); |
- if (t!=told ) { |
- printf("%d events in %2.2f min (%d s) %s",i+1, (double)(t-tstart)/60.,(t-tstart), ctime(&t)); |
- |
- } |
- told=t; |
-// Save data |
- if (nb>0 && fp) fwrite(buffer, 1,nb ,fp); |
-// Plot Data |
- for (int k=0;k<4;k++){ |
- if (! (mask & ( 0x1<<k )) ) continue; |
- float *t=DRSGetTime(k); |
- float *x=DRSGetWave(k); |
- |
- if (!k){ |
- if (plothandle) DeleteGraphPlot (ph, PANEL_GRAPH, plothandle, VAL_DELAYED_DRAW); |
- plothandle = PlotXY (ph, PANEL_GRAPH, t, x, 1024, VAL_FLOAT, VAL_FLOAT, VAL_THIN_LINE, VAL_NO_POINT, VAL_SOLID, 1, VAL_BLUE); |
- } |
- |
- |
- for (int i=0 ; i<1024 ; i++) { |
- if (verbose) printf("[%d] %d. x= %3.2f y=%3.2f\n", k, i, t[i], x[i] ); |
- //h[k]->Fill( t[i], x[i]*1e-3); |
- } |
- } |
- } |
- time(&t); |
- printf("%d events in %2.2f min (%d s) %s",i+1, (double)(t-tstart)/60.,t-tstart, ctime(&t)); |
- |
- DRSEnd(); |
-} |
- |
-if (fp) fclose(fp); |
- |
-free(buffer); |
- |
- return 0; |
- |
-} |
- |
-int CVICALLBACK StartCB (int panel, int control, int event, |
- void *callbackData, int eventData1, int eventData2) { |
- ThreadFunctionPtr mythread = NULL; |
- switch (event) { |
- |
- case EVENT_COMMIT: |
- |
- mythread = daq; |
- if (mythread!=NULL) { |
- printf("New Thread panel=%d button=%d\n", panel, control); |
- |
- // SetDimming(1); |
- controlID= control; |
- daq_on=1; |
- CmtScheduleThreadPoolFunctionAdv (poolHandle, mythread, &controlID, |
- DEFAULT_THREAD_PRIORITY, |
- EndOfThread, |
- EVENT_TP_THREAD_FUNCTION_END, |
- NULL, RUN_IN_SCHEDULED_THREAD, |
- &tfID); |
- } |
- break; |
- } |
- return 0; |
-} |
- |
-int CVICALLBACK StopCB (int panel, int control, int event, |
- void *callbackData, int eventData1, int eventData2) { |
- switch (event) { |
- case EVENT_COMMIT: |
- daq_on=0; |
- break; |
- } |
- return 0; |
-} |
- |
-int CVICALLBACK ExitCB (int panel, int control, int event, |
- void *callbackData, int eventData1, int eventData2) { |
- switch (event) { |
- case EVENT_COMMIT: |
- QuitUserInterface (0); |
- break; |
- } |
- return 0; |
-} |
Index: instr/drsctrl/read_binary.cpp |
=================================================================== |
--- instr/drsctrl/read_binary.cpp (revision 196) |
+++ instr/drsctrl/read_binary.cpp (nonexistent) |
@@ -1,250 +0,0 @@ |
-/* |
- Name: read_binary.cpp |
- Created by: Stefan Ritt <stefan.ritt@psi.ch> |
- Date: July 30th, 2014 |
- |
- Purpose: Example file to read binary data saved by DRSOsc. |
- |
- Compile and run it with: |
- |
- gcc -o read_binary read_binary.cpp |
- |
- ./read_binary <filename> |
- |
- This program assumes that a pulse from a signal generator is split |
- and fed into channels #1 and #2. It then calculates the time difference |
- between these two pulses to show the performance of the DRS board |
- for time measurements. |
- |
- $Id: read_binary.cpp 22321 2016-08-25 12:26:12Z ritt $ |
-*/ |
- |
-#include <stdio.h> |
-#include <fcntl.h> |
-#include <unistd.h> |
-#include <string.h> |
-#include <math.h> |
- |
-typedef struct { |
- char tag[3]; |
- char version; |
-} FHEADER; |
- |
-typedef struct { |
- char time_header[4]; |
-} THEADER; |
- |
-typedef struct { |
- char bn[2]; |
- unsigned short board_serial_number; |
-} BHEADER; |
- |
-typedef struct { |
- char event_header[4]; |
- unsigned int event_serial_number; |
- unsigned short year; |
- unsigned short month; |
- unsigned short day; |
- unsigned short hour; |
- unsigned short minute; |
- unsigned short second; |
- unsigned short millisecond; |
- unsigned short range; |
-} EHEADER; |
- |
-typedef struct { |
- char tc[2]; |
- unsigned short trigger_cell; |
-} TCHEADER; |
- |
-typedef struct { |
- char c[1]; |
- char cn[3]; |
-} CHEADER; |
- |
-/*-----------------------------------------------------------------------------*/ |
- |
-int main(int argc, const char * argv[]) |
-{ |
- FHEADER fh; |
- THEADER th; |
- BHEADER bh; |
- EHEADER eh; |
- TCHEADER tch; |
- CHEADER ch; |
- |
- unsigned int scaler; |
- unsigned short voltage[1024]; |
- double waveform[16][4][1024], time[16][4][1024]; |
- float bin_width[16][4][1024]; |
- int i, j, b, chn, n, chn_index, n_boards; |
- double t1, t2, dt; |
- char filename[256]; |
- |
- int ndt; |
- double threshold, sumdt, sumdt2; |
- |
- if (argc > 1) |
- strcpy(filename, argv[1]); |
- else { |
- printf("Usage: read_binary <filename>\n"); |
- return 0; |
- } |
- |
- // open the binary waveform file |
- FILE *f = fopen(filename, "rb"); |
- if (f == NULL) { |
- printf("Cannot find file \'%s\'\n", filename); |
- return 0; |
- } |
- |
- // read file header |
- fread(&fh, sizeof(fh), 1, f); |
- if (fh.tag[0] != 'D' || fh.tag[1] != 'R' || fh.tag[2] != 'S') { |
- printf("Found invalid file header in file \'%s\', aborting.\n", filename); |
- return 0; |
- } |
- |
- if (fh.version != '2') { |
- printf("Found invalid file version \'%c\' in file \'%s\', should be \'2\', aborting.\n", fh.version, filename); |
- return 0; |
- } |
- |
- // read time header |
- fread(&th, sizeof(th), 1, f); |
- if (memcmp(th.time_header, "TIME", 4) != 0) { |
- printf("Invalid time header in file \'%s\', aborting.\n", filename); |
- return 0; |
- } |
- |
- for (b = 0 ; ; b++) { |
- // read board header |
- fread(&bh, sizeof(bh), 1, f); |
- if (memcmp(bh.bn, "B#", 2) != 0) { |
- // probably event header found |
- fseek(f, -4, SEEK_CUR); |
- break; |
- } |
- |
- printf("Found data for board #%d\n", bh.board_serial_number); |
- |
- // read time bin widths |
- memset(bin_width[b], sizeof(bin_width[0]), 0); |
- for (chn=0 ; chn<5 ; chn++) { |
- fread(&ch, sizeof(ch), 1, f); |
- if (ch.c[0] != 'C') { |
- // event header found |
- fseek(f, -4, SEEK_CUR); |
- break; |
- } |
- i = ch.cn[2] - '0' - 1; |
- printf("Found timing calibration for channel #%d\n", i+1); |
- fread(&bin_width[b][i][0], sizeof(float), 1024, f); |
- // fix for 2048 bin mode: double channel |
- if (bin_width[b][i][1023] > 10 || bin_width[b][i][1023] < 0.01) { |
- for (j=0 ; j<512 ; j++) |
- bin_width[b][i][j+512] = bin_width[b][i][j]; |
- } |
- } |
- } |
- n_boards = b; |
- |
- // initialize statistics |
- ndt = 0; |
- sumdt = sumdt2 = 0; |
- |
- // loop over all events in the data file |
- for (n=0 ; ; n++) { |
- // read event header |
- i = (int)fread(&eh, sizeof(eh), 1, f); |
- if (i < 1) |
- break; |
- |
- printf("Found event #%d %d %d\n", eh.event_serial_number, eh.second, eh.millisecond); |
- |
- // loop over all boards in data file |
- for (b=0 ; b<n_boards ; b++) { |
- |
- // read board header |
- fread(&bh, sizeof(bh), 1, f); |
- if (memcmp(bh.bn, "B#", 2) != 0) { |
- printf("Invalid board header in file \'%s\', aborting.\n", filename); |
- return 0; |
- } |
- |
- // read trigger cell |
- fread(&tch, sizeof(tch), 1, f); |
- if (memcmp(tch.tc, "T#", 2) != 0) { |
- printf("Invalid trigger cell header in file \'%s\', aborting.\n", filename); |
- return 0; |
- } |
- |
- if (n_boards > 1) |
- printf("Found data for board #%d\n", bh.board_serial_number); |
- |
- // reach channel data |
- for (chn=0 ; chn<4 ; chn++) { |
- |
- // read channel header |
- fread(&ch, sizeof(ch), 1, f); |
- if (ch.c[0] != 'C') { |
- // event header found |
- fseek(f, -4, SEEK_CUR); |
- break; |
- } |
- chn_index = ch.cn[2] - '0' - 1; |
- fread(&scaler, sizeof(int), 1, f); |
- fread(voltage, sizeof(short), 1024, f); |
- |
- for (i=0 ; i<1024 ; i++) { |
- // convert data to volts |
- waveform[b][chn_index][i] = (voltage[i] / 65536. + eh.range/1000.0 - 0.5); |
- |
- // calculate time for this cell |
- for (j=0,time[b][chn_index][i]=0 ; j<i ; j++) |
- time[b][chn_index][i] += bin_width[b][chn_index][(j+tch.trigger_cell) % 1024]; |
- } |
- } |
- |
- // align cell #0 of all channels |
- t1 = time[b][0][(1024-tch.trigger_cell) % 1024]; |
- for (chn=1 ; chn<4 ; chn++) { |
- t2 = time[b][chn][(1024-tch.trigger_cell) % 1024]; |
- dt = t1 - t2; |
- for (i=0 ; i<1024 ; i++) |
- time[b][chn][i] += dt; |
- } |
- |
- t1 = t2 = 0; |
- threshold = 0.3; |
- |
- // find peak in channel 1 above threshold |
- for (i=0 ; i<1022 ; i++) |
- if (waveform[b][0][i] < threshold && waveform[b][0][i+1] >= threshold) { |
- t1 = (threshold-waveform[b][0][i])/(waveform[b][0][i+1]-waveform[b][0][i])*(time[b][0][i+1]-time[b][0][i])+time[b][0][i]; |
- break; |
- } |
- |
- // find peak in channel 2 above threshold |
- for (i=0 ; i<1022 ; i++) |
- if (waveform[b][1][i] < threshold && waveform[b][1][i+1] >= threshold) { |
- t2 = (threshold-waveform[b][1][i])/(waveform[b][1][i+1]-waveform[b][1][i])*(time[b][1][i+1]-time[b][1][i])+time[b][1][i]; |
- break; |
- } |
- |
- // calculate distance of peaks with statistics |
- if (t1 > 0 && t2 > 0) { |
- ndt++; |
- dt = t2 - t1; |
- sumdt += dt; |
- sumdt2 += dt*dt; |
- } |
- } |
- } |
- |
- // print statistics |
- printf("dT = %1.3lfns +- %1.1lfps\n", sumdt/ndt, 1000*sqrt(1.0/(ndt-1)*(sumdt2-1.0/ndt*sumdt*sumdt))); |
- |
- return 1; |
-} |
- |
Index: instr/drsctrl/LinkDef.h |
=================================================================== |
--- instr/drsctrl/LinkDef.h (revision 196) |
+++ instr/drsctrl/LinkDef.h (nonexistent) |
@@ -1,7 +0,0 @@ |
-#ifdef __CINT__ |
- |
-#pragma link off all globals; |
-#pragma link off all classes; |
-#pragma link C++ function TimerOut; |
- |
-#endif |
Index: instr/drsctrl/drs4.h |
=================================================================== |
--- instr/drsctrl/drs4.h (revision 196) |
+++ instr/drsctrl/drs4.h (nonexistent) |
@@ -1,55 +0,0 @@ |
-/**************************************************************************/ |
-/* LabWindows/CVI User Interface Resource (UIR) Include File */ |
-/* */ |
-/* WARNING: Do not add to, delete from, or otherwise modify the contents */ |
-/* of this include file. */ |
-/**************************************************************************/ |
- |
-#include <userint.h> |
- |
-#ifdef __cplusplus |
- extern "C" { |
-#endif |
- |
- /* Panels and Controls: */ |
- |
-#define PANEL 1 |
-#define PANEL_Exit 2 /* control type: command, callback function: ExitCB */ |
-#define PANEL_STOP 3 /* control type: command, callback function: StopCB */ |
-#define PANEL_START 4 /* control type: command, callback function: StartCB */ |
-#define PANEL_TRGTYPE 5 /* control type: numeric, callback function: (none) */ |
-#define PANEL_TRGLEVEL 6 /* control type: numeric, callback function: (none) */ |
-#define PANEL_TRGDELAY 7 /* control type: numeric, callback function: (none) */ |
-#define PANEL_RANGE 8 /* control type: numeric, callback function: (none) */ |
-#define PANEL_TRGCHANNEL 9 /* control type: numeric, callback function: (none) */ |
-#define PANEL_CEVE 10 /* control type: numeric, callback function: (none) */ |
-#define PANEL_NEVE 11 /* control type: numeric, callback function: (none) */ |
-#define PANEL_FREQUENCY 12 /* control type: numeric, callback function: (none) */ |
-#define PANEL_TRGPOLARITY 13 /* control type: binary, callback function: (none) */ |
-#define PANEL_MASK 14 /* control type: string, callback function: (none) */ |
-#define PANEL_FILENAME 15 /* control type: string, callback function: (none) */ |
-#define PANEL_GRAPH 16 /* control type: graph, callback function: (none) */ |
-#define PANEL_DEBUG 17 /* control type: radioButton, callback function: (none) */ |
-#define PANEL_TIMER 18 /* control type: timer, callback function: (none) */ |
- |
- |
- /* Control Arrays: */ |
- |
- /* (no control arrays in the resource file) */ |
- |
- |
- /* Menu Bars, Menus, and Menu Items: */ |
- |
- /* (no menu bars in the resource file) */ |
- |
- |
- /* Callback Prototypes: */ |
- |
-int CVICALLBACK ExitCB(int panel, int control, int event, void *callbackData, int eventData1, int eventData2); |
-int CVICALLBACK StartCB(int panel, int control, int event, void *callbackData, int eventData1, int eventData2); |
-int CVICALLBACK StopCB(int panel, int control, int event, void *callbackData, int eventData1, int eventData2); |
- |
- |
-#ifdef __cplusplus |
- } |
-#endif |
Index: instr/drsctrl/drsread.c |
=================================================================== |
--- instr/drsctrl/drsread.c (revision 196) |
+++ instr/drsctrl/drsread.c (nonexistent) |
@@ -1,283 +0,0 @@ |
-#include <windows.h> |
-#include <drsread.h> |
- |
-/* The two macros below are used as error return codes */ |
-/* in case the DLL does not load, or is missing one or */ |
-/* more functions, respectively. You must define them */ |
-/* to whatever values are meaningful for your DLL. */ |
-#define kFailedToLoadDLLError ??? |
-#define kCouldNotFindFunction ??? |
- |
-static HINSTANCE DLLHandle; |
- |
-/* Declare the variables that hold the addresses of the function */ |
-/* pointers. */ |
-static void (__cdecl *DRSSetMask_Ptr)(int mask); |
-static void (__cdecl *DRSSetTriggerType_Ptr)(int type); |
-static void (__cdecl *DRSSetFrequency_Ptr)(int freq); |
-static void (__cdecl *DRSSetRange_Ptr)(double range); |
-static void (__cdecl *DRSSetTriggerChannel_Ptr)(int channel); |
-static void (__cdecl *DRSSetTriggerDelay_Ptr)(double delay); |
-static void (__cdecl *DRSSetTriggerLevel_Ptr)(double level); |
-static void (__cdecl *DRSSetTriggerPolarity_Ptr)(int polarity); |
-static float *(__cdecl *DRSGetTime_Ptr)(int ch); |
-static float *(__cdecl *DRSGetWave_Ptr)(int ch); |
-static int (__cdecl *DRSInit_Ptr)(); |
-static int (__cdecl *DRSRead_Ptr)(int drstimer); |
-static int (__cdecl *DRSEnd_Ptr)(); |
-static int (__cdecl *DRSToBuffer_Ptr)(unsigned char *p, int m_evSerial); |
-static int (__cdecl *DRSIsTimeout_Ptr)(); |
-static void (__cdecl *DRSSetTimeout_Ptr)(); |
-static void (__cdecl *DRSSigInt_Ptr)(int k); |
- |
- |
-/* Load the DLL and get the addresses of the functions */ |
-static int LoadDLLIfNeeded(void) |
-{ |
- if (DLLHandle) |
- return 0; |
- |
- DLLHandle = LoadLibrary("drsread.dll"); |
- if (DLLHandle == NULL) { |
- return kFailedToLoadDLLError; |
- } |
- |
- if (!(DRSSetMask_Ptr = (void*) GetProcAddress(DLLHandle, "DRSSetMask"))) |
- goto FunctionNotFoundError; |
- |
- if (!(DRSSetTriggerType_Ptr = (void*) GetProcAddress(DLLHandle, |
- "DRSSetTriggerType"))) |
- goto FunctionNotFoundError; |
- |
- if (!(DRSSetFrequency_Ptr = (void*) GetProcAddress(DLLHandle, |
- "DRSSetFrequency"))) |
- goto FunctionNotFoundError; |
- |
- if (!(DRSSetRange_Ptr = (void*) GetProcAddress(DLLHandle, "DRSSetRange"))) |
- goto FunctionNotFoundError; |
- |
- if (!(DRSSetTriggerChannel_Ptr = (void*) GetProcAddress(DLLHandle, |
- "DRSSetTriggerChannel"))) |
- goto FunctionNotFoundError; |
- |
- if (!(DRSSetTriggerDelay_Ptr = (void*) GetProcAddress(DLLHandle, |
- "DRSSetTriggerDelay"))) |
- goto FunctionNotFoundError; |
- |
- if (!(DRSSetTriggerLevel_Ptr = (void*) GetProcAddress(DLLHandle, |
- "DRSSetTriggerLevel"))) |
- goto FunctionNotFoundError; |
- |
- if (!(DRSSetTriggerPolarity_Ptr = (void*) GetProcAddress(DLLHandle, |
- "DRSSetTriggerPolarity"))) |
- goto FunctionNotFoundError; |
- |
- if (!(DRSGetTime_Ptr = (void*) GetProcAddress(DLLHandle, "DRSGetTime"))) |
- goto FunctionNotFoundError; |
- |
- if (!(DRSGetWave_Ptr = (void*) GetProcAddress(DLLHandle, "DRSGetWave"))) |
- goto FunctionNotFoundError; |
- |
- if (!(DRSInit_Ptr = (void*) GetProcAddress(DLLHandle, "DRSInit"))) |
- goto FunctionNotFoundError; |
- |
- if (!(DRSRead_Ptr = (void*) GetProcAddress(DLLHandle, "DRSRead"))) |
- goto FunctionNotFoundError; |
- |
- if (!(DRSEnd_Ptr = (void*) GetProcAddress(DLLHandle, "DRSEnd"))) |
- goto FunctionNotFoundError; |
- |
- if (!(DRSToBuffer_Ptr = (void*) GetProcAddress(DLLHandle, "DRSToBuffer"))) |
- goto FunctionNotFoundError; |
- |
- if (!(DRSIsTimeout_Ptr = (void*) GetProcAddress(DLLHandle, "DRSIsTimeout"))) |
- goto FunctionNotFoundError; |
- |
- if (!(DRSSetTimeout_Ptr = (void*) GetProcAddress(DLLHandle, "DRSSetTimeout"))) |
- goto FunctionNotFoundError; |
- |
- if (!(DRSSigInt_Ptr = (void*) GetProcAddress(DLLHandle, "DRSSigInt"))) |
- goto FunctionNotFoundError; |
- |
- return 0; |
- |
-FunctionNotFoundError: |
- FreeLibrary(DLLHandle); |
- DLLHandle = 0; |
- return kCouldNotFindFunction; |
-} |
- |
- |
-/* Glue Code for each of the DLL functions */ |
- |
- |
- |
-void DRSSetMask(int mask) |
-{ |
- int dllLoadError; |
- |
- if (dllLoadError = LoadDLLIfNeeded()) |
- return; |
- (*DRSSetMask_Ptr)(mask); |
-} |
- |
- |
-void DRSSetTriggerType(int type) |
-{ |
- int dllLoadError; |
- |
- if (dllLoadError = LoadDLLIfNeeded()) |
- return; |
- (*DRSSetTriggerType_Ptr)(type); |
-} |
- |
- |
-void DRSSetFrequency(int freq) |
-{ |
- int dllLoadError; |
- |
- if (dllLoadError = LoadDLLIfNeeded()) |
- return; |
- (*DRSSetFrequency_Ptr)(freq); |
-} |
- |
- |
-void DRSSetRange(double range) |
-{ |
- int dllLoadError; |
- |
- if (dllLoadError = LoadDLLIfNeeded()) |
- return; |
- (*DRSSetRange_Ptr)(range); |
-} |
- |
- |
-void DRSSetTriggerChannel(int channel) |
-{ |
- int dllLoadError; |
- |
- if (dllLoadError = LoadDLLIfNeeded()) |
- return; |
- (*DRSSetTriggerChannel_Ptr)(channel); |
-} |
- |
- |
-void DRSSetTriggerDelay(double delay) |
-{ |
- int dllLoadError; |
- |
- if (dllLoadError = LoadDLLIfNeeded()) |
- return; |
- (*DRSSetTriggerDelay_Ptr)(delay); |
-} |
- |
- |
-void DRSSetTriggerLevel(double level) |
-{ |
- int dllLoadError; |
- |
- if (dllLoadError = LoadDLLIfNeeded()) |
- return; |
- (*DRSSetTriggerLevel_Ptr)(level); |
-} |
- |
- |
-void DRSSetTriggerPolarity(int polarity) |
-{ |
- int dllLoadError; |
- |
- if (dllLoadError = LoadDLLIfNeeded()) |
- return; |
- (*DRSSetTriggerPolarity_Ptr)(polarity); |
-} |
- |
- |
-float *DRSGetTime(int ch) |
-{ |
- int dllLoadError; |
- |
- if (dllLoadError = LoadDLLIfNeeded()) |
- return ???; |
- return (*DRSGetTime_Ptr)(ch); |
-} |
- |
- |
-float *DRSGetWave(int ch) |
-{ |
- int dllLoadError; |
- |
- if (dllLoadError = LoadDLLIfNeeded()) |
- return ???; |
- return (*DRSGetWave_Ptr)(ch); |
-} |
- |
- |
-int DRSInit() |
-{ |
- int dllLoadError; |
- |
- if (dllLoadError = LoadDLLIfNeeded()) |
- return dllLoadError; |
- return (*DRSInit_Ptr)(); |
-} |
- |
- |
-int DRSRead(int drstimer) |
-{ |
- int dllLoadError; |
- |
- if (dllLoadError = LoadDLLIfNeeded()) |
- return dllLoadError; |
- return (*DRSRead_Ptr)(drstimer); |
-} |
- |
- |
-int DRSEnd() |
-{ |
- int dllLoadError; |
- |
- if (dllLoadError = LoadDLLIfNeeded()) |
- return dllLoadError; |
- return (*DRSEnd_Ptr)(); |
-} |
- |
- |
-int DRSToBuffer(unsigned char *p, int m_evSerial) |
-{ |
- int dllLoadError; |
- |
- if (dllLoadError = LoadDLLIfNeeded()) |
- return dllLoadError; |
- return (*DRSToBuffer_Ptr)(p, m_evSerial); |
-} |
- |
- |
-int DRSIsTimeout() |
-{ |
- int dllLoadError; |
- |
- if (dllLoadError = LoadDLLIfNeeded()) |
- return dllLoadError; |
- return (*DRSIsTimeout_Ptr)(); |
-} |
- |
- |
-void DRSSetTimeout() |
-{ |
- int dllLoadError; |
- |
- if (dllLoadError = LoadDLLIfNeeded()) |
- return; |
- (*DRSSetTimeout_Ptr)(); |
-} |
- |
- |
-void DRSSigInt(int k) |
-{ |
- int dllLoadError; |
- |
- if (dllLoadError = LoadDLLIfNeeded()) |
- return; |
- (*DRSSigInt_Ptr)(k); |
-} |
- |
Index: instr/drsctrl/gui.cpp |
=================================================================== |
--- instr/drsctrl/gui.cpp (revision 196) |
+++ instr/drsctrl/gui.cpp (nonexistent) |
@@ -1,503 +0,0 @@ |
-// By ROOT version 5.17/02 on 2008-03-13 06:46:41 |
- |
-#ifndef ROOT_TGDockableFrame |
-#include "TGDockableFrame.h" |
-#endif |
-#ifndef ROOT_TGMenu |
-#include "TGMenu.h" |
-#endif |
-#ifndef ROOT_TGMdiDecorFrame |
-#include "TGMdiDecorFrame.h" |
-#endif |
-#ifndef ROOT_TG3DLine |
-#include "TG3DLine.h" |
-#endif |
-#ifndef ROOT_TGMdiFrame |
-#include "TGMdiFrame.h" |
-#endif |
-#ifndef ROOT_TGMdiMainFrame |
-#include "TGMdiMainFrame.h" |
-#endif |
-//#ifndef ROOT_TGuiBldHintsButton |
-//#include "TGuiBldHintsButton.h" |
-//#endif |
-#ifndef ROOT_TGMdiMenu |
-#include "TGMdiMenu.h" |
-#endif |
-#ifndef ROOT_TGListBox |
-#include "TGListBox.h" |
-#endif |
-#ifndef ROOT_TGNumberEntry |
-#include "TGNumberEntry.h" |
-#endif |
-#ifndef ROOT_TGScrollBar |
-#include "TGScrollBar.h" |
-#endif |
-//#ifndef ROOT_TGuiBldHintsEditor |
-//#include "TGuiBldHintsEditor.h" |
-//#endif |
-#ifndef ROOT_TRootBrowser |
-#include "TRootBrowser.h" |
-#endif |
-#ifndef ROOT_TGFrame |
-#include "TGFrame.h" |
-#endif |
-#ifndef ROOT_TGFileDialog |
-#include "TGFileDialog.h" |
-#endif |
-#ifndef ROOT_TGShutter |
-#include "TGShutter.h" |
-#endif |
-#ifndef ROOT_TGButtonGroup |
-#include "TGButtonGroup.h" |
-#endif |
-#ifndef ROOT_TGCanvas |
-#include "TGCanvas.h" |
-#endif |
-#ifndef ROOT_TGFSContainer |
-#include "TGFSContainer.h" |
-#endif |
-#ifndef ROOT_TGButton |
-#include "TGButton.h" |
-#endif |
-//#ifndef ROOT_TGuiBldEditor |
-//#include "TGuiBldEditor.h" |
-//#endif |
-#ifndef ROOT_TGTextEdit |
-#include "TGTextEdit.h" |
-#endif |
-#ifndef ROOT_TGFSComboBox |
-#include "TGFSComboBox.h" |
-#endif |
-#ifndef ROOT_TGLabel |
-#include "TGLabel.h" |
-#endif |
-#ifndef ROOT_TGView |
-#include "TGView.h" |
-#endif |
-//#ifndef ROOT_TRootGuiBuilder |
-//#include "TRootGuiBuilder.h" |
-//#endif |
-#ifndef ROOT_TGTab |
-#include "TGTab.h" |
-#endif |
-#ifndef ROOT_TGListView |
-#include "TGListView.h" |
-#endif |
-#ifndef ROOT_TGSplitter |
-#include "TGSplitter.h" |
-#endif |
-#ifndef ROOT_TGStatusBar |
-#include "TGStatusBar.h" |
-#endif |
-#ifndef ROOT_TGListTree |
-#include "TGListTree.h" |
-#endif |
-#ifndef ROOT_TGToolTip |
-#include "TGToolTip.h" |
-#endif |
-#ifndef ROOT_TGToolBar |
-#include "TGToolBar.h" |
-#endif |
-#ifndef ROOT_TRootEmbeddedCanvas |
-#include "TRootEmbeddedCanvas.h" |
-#endif |
-#ifndef ROOT_TCanvas |
-#include "TCanvas.h" |
-#endif |
-//#ifndef ROOT_TGuiBldDragManager |
-//#include "TGuiBldDragManager.h" |
-//#endif |
- |
-#include "Riostream.h" |
-#include "TThread.h" |
-#include "TApplication.h" |
-#include "TROOT.h" |
-#include "TGraph.h" |
-#include "TH1F.h" |
-//#include "daq.h" |
- |
-TGTextButton *gTextButton[10]; |
-TCanvas *fCanvas; |
-TGMainFrame *fMain; |
-TGTextEntry *gFilename; |
-TGNumberEntry *gCh; |
- |
-TGTextEntry *gTimeDisplay; |
-TGCheckButton *gDebugButton; |
- |
- |
- |
- TGNumberEntry *gMaxEve; |
-TGNumberEntry *gNeve; |
-TGNumberEntry *gMask; |
-TGNumberEntry *gRange; |
-TGNumberEntry *gSoftwareTrigger; |
-TGNumberEntry *gTriggerChannel; |
-TGNumberEntry *gSamplingFrequency; |
-TGNumberEntry *gTriggerDelay; |
- |
- |
- |
- |
- |
-const char gParNames[30][30]={"Events:","EventNo:","Channel Mask:","Range:", "SwTrg", "TriggerChannel:","Sampling Freq.:","TRG Delay:" }; |
- |
-TGNumberFormat::EStyle gParStyle[10] = { |
-TGNumberFormat::kNESInteger , |
-TGNumberFormat::kNESInteger, |
-TGNumberFormat::kNESInteger , |
-TGNumberFormat::kNESReal, |
-TGNumberFormat::kNESInteger, |
-TGNumberFormat::kNESInteger, |
-TGNumberFormat::kNESInteger, |
-TGNumberFormat::kNESReal |
-}; |
-TGNumberEntry *gParameters[10]; |
- |
- |
- |
-TRootEmbeddedCanvas *gCanvas; |
-#define MAXCH 32 |
-TH1F* gHisto[MAXCH]; |
-//daq * gDaq; |
-#define WINDOW_NAME "Praktikum IV MAPMT PET" |
-//---------------------------------------------------- |
-int UIRDimming(int state){ |
- switch (state) { |
- case 0: |
- gTextButton[0]->SetEnabled(0); |
- gTextButton[1]->SetEnabled(1); |
- gTextButton[2]->SetEnabled(0); |
- |
- break; |
- |
- case 1: |
- gTextButton[0]->SetEnabled(0); |
- gTextButton[1]->SetEnabled(0); |
- gTextButton[2]->SetEnabled(1); |
- |
- break; |
- |
- case 2: |
- gTextButton[0]->SetEnabled(1); |
- gTextButton[1]->SetEnabled(1); |
- gTextButton[2]->SetEnabled(0); |
- break; |
- |
- default: |
- break; |
- } |
- return 0; |
-} |
- |
-int fDebug; |
-void GetDebug(){ |
- if ( gDebugButton->IsOn() ) fDebug=1; |
- else fDebug=0; |
-} |
- |
-int GetTime(char *x){ |
- time_t rawtime; |
- struct tm * timeinfo; |
- time ( &rawtime ); |
- timeinfo = localtime ( &rawtime ); |
- sprintf(x,"%s",asctime (timeinfo)); |
- int len=strlen(x); |
- if (len) x[len-1]=0; |
- return 0; |
-} |
-void MyTimer(){ |
- char cmd[100]; |
- GetTime(cmd); |
- if (gTimeDisplay) gTimeDisplay->SetText(cmd); |
- /* Canvas ni thread safe |
- if (gCanvas){ |
- gCanvas->GetCanvas()->Modified(); |
- gCanvas->GetCanvas()->Update(); |
- } |
- */ |
-} |
- |
-//---------------------------------------------------- |
-// thread function |
-int gStop=0; |
-#define BSIZE 10000 |
-unsigned int gBuf[BSIZE]; |
-void *MyThread(void *ptr) |
-{ |
- TThread::Printf("Start of MyThread %x \n" ,(int *)ptr); |
- |
- // odpremo datoteko za pisanje |
- char fname[128]; |
- sprintf(fname,"%s.dat",gFilename->GetText()); |
- FILE *fp=fopen(fname,"w"); |
- int neve = (int) gMaxEve->GetNumber(); |
- int hdr[4]={1}; |
- |
- //if (gDaq) gDaq->fStop=0; |
- // zajem zeljenega kolicine podatkov |
- for (int n=0;n<neve;n++){ |
- int nb=0; |
- /* |
- if (!gDaq) break; |
- nb = gDaq->event(gBuf,BSIZE); |
- if (gDaq->fStop) break; |
- */ |
- if (nb<0){ |
- n--; |
- continue; |
- } |
- |
- // zapis v datoteko |
- hdr[1]=nb+4*sizeof(int); |
- hdr[2]=time(NULL); |
- hdr[3]=n; |
- |
- fwrite(hdr, sizeof(int),4 , fp); |
- fwrite(gBuf, sizeof(int),nb, fp); |
- // napolni histograme |
- //***************** |
- unsigned int *data= gBuf; |
- int evsize=0; |
- int events=0; |
- int ib=1,count=0; |
- events = data[0]; |
- evsize = data[1]&0xffff; |
- if (evsize<2){ |
- n--; |
- continue; |
- } |
- const unsigned int END_MARKER=0xFAF5; |
- if (fDebug) printf("nb=%d Event:%d events=%d EvSize:%d\n",nb, n, events, evsize); |
- for (int i=0;i<evsize;i++) { |
- //if (fDebug) printf("%d\t%08x\n", ib, data[ib]); |
- |
- if (data[ib]== END_MARKER) break; |
- if (ib%2==0) { |
- unsigned short word1 =data[ib ]&0xFFFF; |
- unsigned short word2 =data[ib+1]&0xFFFF; |
- unsigned short tdc = word1; |
- unsigned short ch = (word2 >> 1 ) &0x1F; |
- unsigned short edge = word2 & 0x1; |
- unsigned short q = (word2 >> 8) &0x1; |
- unsigned short x = (word2 >> 9) &0x1; |
- TThread::Lock(); |
- if (edge && ch < MAXCH) gHisto[ch]->Fill(tdc); |
- TThread::UnLock(); |
- if (fDebug) TThread::Printf("%d. [ch=%2d] edge=%d data=%d q=%d x=%d\n",count,ch,edge,tdc, q, x); |
- |
- count++; |
- } |
- ib++; |
- } |
- if (data[evsize+1]!=END_MARKER) printf("Error! END_MARKER not found\n"); |
-//***************** |
- |
- |
- |
- |
- |
- gNeve->SetNumber(n); |
- } |
- fclose(fp); |
- UIRDimming(2); |
- TThread::Printf("End of MyThread neve=%d\n",neve); |
- return 0; |
-} |
- |
- |
-int save2ascii(){ |
- if (!gHisto[0]) return 0; |
- char fname[128]; |
- sprintf(fname,"%s.txt",gFilename->GetText()); |
- FILE *fp= fopen(fname, "w"); |
- fprintf(fp, "%s\n",WINDOW_NAME); |
- char cmd[128]; |
- GetTime(cmd); |
- fprintf(fp, "Shranjeno: %s\n\n", cmd ); |
- fprintf(fp, "Kanal hid=") ; |
- for (int j=0;j<MAXCH;j++) fprintf(fp, "%d\t",j); |
- fprintf(fp, "\n-------------------------------------------------\n"); |
- for (int i=0;i<gHisto[0]->GetNbinsX();i++){ |
- fprintf(fp, "%d\t",i); |
- for (int j=0;j<MAXCH;j++) fprintf(fp, "%d\t",(int) gHisto[j]->GetBinContent(i+1)); |
- fprintf(fp, "\n"); |
- } |
- fclose(fp); |
- printf("Rezultati meritev so zapisani v datoteki %s\n",fname); |
- return 0; |
- } |
- |
-void MyEventHandler(int i){ |
- static TTimer * tmr = new TTimer(1000, kFALSE); |
- UIRDimming(i); |
- TThread *fThread; |
- switch (i) { |
- case 0: // Init |
- //gDaq->init(); |
- break; |
- case 1: // Start |
- fThread = new TThread(MyThread,(void*)0); |
- fThread->Run(); |
- tmr->SetCommand("MyTimer()"); |
- tmr->TurnOn(); |
- tmr->Start(1000, kFALSE); // 1 second single-shot |
- break; |
- case 2: // Stop |
- //gDaq->fStop=1; |
- tmr->Stop(); |
- tmr->TurnOff(); |
- break; |
- case 3: // ReDraw |
- gCanvas->GetCanvas()->Modified(); |
- gCanvas->GetCanvas()->Update(); |
- break; |
- case 4: // Clear |
- for (int j=0;j<MAXCH;j++) if (gHisto[j]) gHisto[j]->Reset(); |
- break; |
- case 5: // Save |
- save2ascii(); |
- break; |
- case 6: // Print |
- gCanvas->GetCanvas()->SaveAs("zivljenjski_cas_mionov.pdf"); |
- break; |
- case 7: // exit |
- gApplication->Terminate(0); |
- break; |
- } |
- |
-} |
- |
-int Redraw(long val=0){ |
- unsigned int ch= (unsigned int)(gCh->GetNumber()); |
- if (ch<MAXCH && gHisto[ch]) { |
- gCanvas->GetCanvas()->cd(); |
- gHisto[ch]->Draw(); |
- gCanvas->GetCanvas()->Modified(); |
- gCanvas->GetCanvas()->Update(); |
- } else { |
- if (gCh->GetNumber()>=MAXCH) gCh->SetNumber(MAXCH-1); |
- if (gCh->GetNumber()< 0) gCh->SetNumber(0); |
- } |
- return 0; |
-} |
-//---------------------------------------------------- |
- |
-int gui(){ |
- |
- for (int i=0;i<MAXCH;i++){ |
- char hname[50]; |
- sprintf(hname,"TDC Ch. %d;TDC;N",i); |
- char hn[50]; |
- sprintf(hn,"ch%d",i); |
- gHisto[i] = new TH1F(hn,hname,128,-0.5,1024*8-0.5); |
- } |
- //gDaq= new daq(); |
- fMain = new TGMainFrame(0,800,800); |
- TGHorizontalFrame *fH=new TGHorizontalFrame(fMain,800,400); |
- //------------------------------------------------------------ |
- TGLayoutHints *f0= new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2); |
- TGLayoutHints *layout2= new TGLayoutHints(kLHintsLeft | kLHintsTop,20,20,20,20); |
- // gumbi |
- |
- int nbut=8; |
- const char *names[10]={"Init","Start","Stop","Refresh","Clear","Export to ASCII", "Print" , "Exit"}; |
- for (int i=0;i<nbut;i++){ |
- |
- gTextButton[i]= new TGTextButton(fH, names[i]); |
- gTextButton[i]->SetTextJustify(36); |
- gTextButton[i]->SetMargins(0,0,0,0); |
- gTextButton[i]->SetWrapLength(-1); |
- gTextButton[i]->ChangeOptions(gTextButton[i]->GetOptions() | kFixedWidth); // | kFixedSize |
- gTextButton[i]->Resize(100,gTextButton[i]->GetDefaultHeight()); |
- |
- fH->AddFrame(gTextButton[i], f0); |
- char cmd[50]; |
- sprintf(cmd,"MyEventHandler(=%d)",i); |
- TQObject::Connect(gTextButton[i],"Clicked()",0,0,cmd); |
- } |
- |
- gDebugButton = new TGCheckButton( fH,"Debug"); |
- gDebugButton->Resize(50,22); |
- TQObject::Connect(gDebugButton,"Clicked()", 0, 0 , "GetDebug()"); |
- gDebugButton->SetState(kButtonDown); |
- fH->AddFrame(gDebugButton, f0); |
- |
- fMain->AddFrame(fH , f0); |
- |
- TGHorizontalFrame *fH1=new TGHorizontalFrame(fMain,800,400); |
- //--------------------------------------------------------- |
- // ura |
- TGLabel *lab1; |
- fH=new TGHorizontalFrame(fH1,800,200); |
- lab1 = new TGLabel( fH ,"Ura:"); |
- fH->AddFrame(lab1, f0); |
- gTimeDisplay = new TGTextEntry( fH,""); |
- gTimeDisplay->Resize(200,22); |
- fH->AddFrame(gTimeDisplay, f0); |
- fH1->AddFrame(fH , f0); |
- //--------------------------------------------------------- |
- // inputi |
- fH=new TGHorizontalFrame(fH1,800,200); |
- lab1 = new TGLabel( fH ,"Filename:"); |
- fH->AddFrame(lab1, f0); |
- gFilename = new TGTextEntry( fH,"tmp"); |
- gFilename->Resize(200,22); |
- fH->AddFrame(gFilename, f0); |
- fH1->AddFrame(fH , f0); |
- //--------------------------------------------------------- |
- fH=new TGHorizontalFrame(fH1,800,200); |
- lab1 = new TGLabel( fH ,"Events:"); |
- fH->AddFrame(lab1, f0); |
- gMaxEve = new TGNumberEntry( fH,10000); |
- gMaxEve->Resize(100,22); |
- fH->AddFrame(gMaxEve, f0); |
- fH1->AddFrame(fH , f0); |
- //--------------------------------------------------------- |
- fH=new TGHorizontalFrame(fH1,800,200); |
- lab1 = new TGLabel( fH ,"Event no:"); |
- fH->AddFrame(lab1, f0); |
- gNeve = new TGNumberEntry( fH,0); |
- gNeve->Resize(100,22); |
- fH->AddFrame(gNeve, f0); |
- fH1->AddFrame(fH , f0); |
- //--------------------------------------------------------- |
- fMain->AddFrame(fH1 , f0); |
- TGVerticalFrame *fV=new TGVerticalFrame(fMain,800,200); |
- nbut = 8; |
- for (int i=0;i<nbut;i++){ |
- fH=new TGHorizontalFrame(fV,800,200); |
- lab1 = new TGLabel( fH ,gParNames[i]); |
- lab1->Resize(100,22); |
- fH->AddFrame(lab1, f0); |
- gParameters[i] = new TGNumberEntry( fH,0,5,i, gParStyle[i] ); |
- gParameters[i]->Resize(100,22); |
- fH->AddFrame(gParameters[i] , f0); |
- fV->AddFrame(fH , f0); |
- } |
- fMain->AddFrame(fV , f0); |
- //--------------------------------------------------------- |
- // canvas |
- fH=new TGHorizontalFrame(fMain,800,200); |
- gCanvas = new TRootEmbeddedCanvas ("gCanvas",fH,800,400); |
- fH->AddFrame(gCanvas, f0); |
- fMain->AddFrame(fH , f0); |
- //------------------------------------------------------------ |
- fH=new TGHorizontalFrame(fMain,800,200); |
- lab1 = new TGLabel( fH ,"Ch. Number(0..3):"); |
- fH->AddFrame(lab1, f0); |
- gCh = new TGNumberEntry( fH,0); |
- fH->AddFrame(gCh, f0); |
- TQObject::Connect(gCh,"ValueSet(Long_t)",0,0,"Redraw(Long_t )"); |
- |
- fMain->AddFrame(fH , f0); |
- //------------------------------------------------------------ |
- fMain->SetWindowName(WINDOW_NAME); |
- fMain->MapSubwindows(); |
- fMain->Resize(fMain->GetDefaultSize()); |
- fMain->MapWindow(); |
- Redraw(); |
- GetDebug(); |
- return 0; |
-} |
Index: instr/drsctrl/startroot.bat |
=================================================================== |
--- instr/drsctrl/startroot.bat (revision 196) |
+++ instr/drsctrl/startroot.bat (nonexistent) |
@@ -1 +0,0 @@ |
-cmd.exe /k thisroot.bat |
Index: instr/drsctrl/drs4.cws |
=================================================================== |
--- instr/drsctrl/drs4.cws (revision 196) |
+++ instr/drsctrl/drs4.cws (nonexistent) |
@@ -1,232 +0,0 @@ |
-[Workspace Header] |
-Version = 1302 |
-Pathname = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.cws" |
-CVI Dir = "/c/program files (x86)/national instruments/cvi2013" |
-CVI Shared Dir = "/C/Program Files (x86)/National Instruments/Shared/CVI" |
-CVI Pub Local Dir = "/C/ProgramData/National Instruments/CVI2013" |
-CVI Pub Global Dir = "/C/ProgramData/National Instruments/CVI" |
-IVI Standard Root Dir = "/C/Program Files (x86)/IVI Foundation/IVI" |
-IVI Standard Root 64-bit Dir = "/C/Program Files/IVI Foundation/IVI" |
-VXIplug&play Framework Dir = "/C/Program Files (x86)/IVI Foundation/VISA/winnt" |
-VXIplug&play Framework 64-bit Dir = "/C/Program Files/IVI Foundation/VISA/win64" |
-Number of Projects = 1 |
-Active Project = 1 |
-Project 0001 = "drs4.prj" |
-Drag Bar Left = 360 |
-Window Top = 277 |
-Window Left = 205 |
-Window Bottom = 1617 |
-Window Right = 2435 |
-Maximized = False |
-Maximized Children = True |
-Max32 Number Of Errors = 20 |
-Track Include File Dependencies = True |
-Prompt For Missing Includes = True |
-Stop On First Error File = False |
-Bring Up Err Win At Start = True |
-Bring Up Err Win For Errors = False |
-Save Changes Before Running = "Always" |
-Save Changes Before Compiling = "Always" |
-Hide Windows = False |
-Break At First Statement = False |
-Sort Type = "File Name" |
-Number of Opened Files = 8 |
-Window Confinement Region Enabled = True |
-MainColumnWidth = 343 |
-FileDateColumnWidth = 70 |
-FileSizeColumnWidth = 70 |
- |
-[Project Header 0001] |
-Version = 1302 |
-Don't Update DistKit = False |
-Platform Code = 4 |
-Build Configuration = "Debug" |
-Warn User If Debugging Release = 1 |
-Batch Build Release = False |
-Batch Build Debug = False |
- |
-[File 0001] |
-Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.c" |
-File Type = "CSource" |
-Disk Date = 3566382302 |
-In Projects = "1," |
-Window Top = 522 |
-Window Left = 247 |
-Window Z-Order = 1 |
-Source Window State = "1,147,148,148,0,0,0,0,0,229,0,2,0,2,0,67,14,0,26,2,349,683,1,0," |
- |
-[File 0002] |
-Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.uir" |
-File Type = "User Interface Resource" |
-Disk Date = 3566382690 |
-In Projects = "1," |
-Window Top = 132 |
-Window Left = 49 |
-Window Height = 349 |
-Window Width = 811 |
-Window Z-Order = 2 |
- |
-[File 0003] |
-Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.h" |
-File Type = "Include" |
-Disk Date = 3566380515 |
-In Projects = "" |
-Window Top = 67 |
-Window Left = 16 |
-Window Z-Order = 6 |
-Source Window State = "1,0,0,0,0,0,0,0,0,96,0,0,0,0,0,25,0,0,0,0,349,811,1,0," |
- |
-[File 0004] |
-Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drsread.h" |
-File Type = "Include" |
-Disk Date = 3566381442 |
-In Projects = "" |
-Window Top = 197 |
-Window Left = 82 |
-Window Z-Order = 5 |
-Source Window State = "1,0,0,0,0,0,0,0,0,96,0,0,0,0,0,25,0,0,31,70,349,811,1,0," |
- |
-[File 0005] |
-Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drsread.c" |
-File Type = "CSource" |
-Disk Date = 3566381600 |
-In Projects = "" |
-Window Top = 262 |
-Window Left = 115 |
-Window Z-Order = 4 |
-Source Window State = "1,0,0,0,0,0,0,0,0,96,0,0,0,0,0,25,0,0,30,26,349,811,1,0," |
- |
-[File 0006] |
-Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drsread.lib" |
-File Type = "Library" |
-Disk Date = 3566381587 |
-In Projects = "1," |
- |
-[File 0007] |
-Path = "/c/Users/rok/Documents/rok/lab/praktikum/mioni/mioni.c" |
-File Type = "CSource" |
-Disk Date = 3564730349 |
-In Projects = "" |
-Window Top = 132 |
-Window Left = 49 |
-Window Z-Order = 8 |
-Source Window State = "1,26,26,26,0,25,25,0,3,96,0,0,0,0,0,25,0,0,26,0,349,811,1,0," |
- |
-[File 0008] |
-Path = "/c/home/git/arich/daq/sa02_daq/cvi/sa02_CVI.c" |
-File Type = "CSource" |
-Disk Date = 3559701358 |
-In Projects = "" |
-Window Top = 197 |
-Window Left = 82 |
-Window Z-Order = 3 |
-Source Window State = "1,362,370,362,7,60,7,0,3,96,0,0,0,0,0,25,330,0,370,60,349,811,1,0," |
- |
-[File 0009] |
-Path = "/c/home/git/arich/daq/sa02_daq/sa02lib.c" |
-File Type = "CSource" |
-Disk Date = 3559701358 |
-In Projects = "" |
-Window Top = 262 |
-Window Left = 115 |
-Window Z-Order = 7 |
-Source Window State = "1,240,240,240,1,21,21,0,3,96,0,0,0,0,0,25,213,0,240,1,349,811,1,0," |
- |
-[Tab Order] |
-Tab 0001 = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.uir" |
-Tab 0002 = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.c" |
-Tab 0003 = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drsread.c" |
-Tab 0004 = "/c/Users/rok/Documents/rok/lab/praktikum/mioni/mioni.c" |
-Tab 0005 = "/c/home/git/arich/daq/sa02_daq/cvi/sa02_CVI.c" |
-Tab 0006 = "/c/home/git/arich/daq/sa02_daq/sa02lib.c" |
-Tab 0007 = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.h" |
-Tab 0008 = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drsread.h" |
- |
-[Default Build Config 0001 Debug] |
-Generate Browse Info = False |
-Enable Uninitialized Locals Runtime Warning = True |
-Batch Build = False |
-Profile = "Disabled" |
-Debugging Level = "Standard" |
-Execution Trace = "Disabled" |
-Command Line Args = "" |
-Working Directory = "" |
-Environment Options = "" |
-External Process Path = "" |
- |
-[Default Build Config 0001 Release] |
-Generate Browse Info = False |
-Enable Uninitialized Locals Runtime Warning = True |
-Batch Build = False |
-Profile = "Disabled" |
-Debugging Level = "Standard" |
-Execution Trace = "Disabled" |
-Command Line Args = "" |
-Working Directory = "" |
-Environment Options = "" |
-External Process Path = "" |
- |
-[Default Build Config 0001 Debug64] |
-Generate Browse Info = False |
-Enable Uninitialized Locals Runtime Warning = True |
-Batch Build = False |
-Profile = "Disabled" |
-Debugging Level = "Standard" |
-Execution Trace = "Disabled" |
-Command Line Args = "" |
-Working Directory = "" |
-Environment Options = "" |
-External Process Path = "" |
- |
-[Default Build Config 0001 Release64] |
-Generate Browse Info = False |
-Enable Uninitialized Locals Runtime Warning = True |
-Batch Build = False |
-Profile = "Disabled" |
-Debugging Level = "Standard" |
-Execution Trace = "Disabled" |
-Command Line Args = "" |
-Working Directory = "" |
-Environment Options = "" |
-External Process Path = "" |
- |
-[Build Dependencies 0001] |
-Number of Dependencies = 0 |
- |
-[Build Options 0001] |
-Generate Browse Info = False |
-Enable Uninitialized Locals Runtime Warning = True |
-Execution Trace = "Disabled" |
-Profile = "Disabled" |
-Debugging Level = "Standard" |
-Break On Library Errors = True |
-Break On First Chance Exceptions = False |
- |
-[Execution Target 0001] |
-Execution Target Address = "Local desktop computer" |
-Execution Target Port = 0 |
-Execution Target Type = 0 |
- |
-[SCC Options 0001] |
-Use global settings = True |
-SCC Provider = "" |
-SCC Project = "" |
-Local Path = "" |
-Auxiliary Path = "" |
-Perform Same Action For .h File As For .uir File = "Ask" |
-Perform Same Action For .cds File As For .prj File = "Ask" |
-Username = "" |
-Comment = "" |
-Use Default Username = False |
-Use Default Comment = False |
-Suppress CVI Error Messages = False |
-Always show confirmation dialog = True |
- |
-[DLL Debugging Support 0001] |
-External Process Path = "" |
- |
-[Command Line Args 0001] |
-Command Line Args = "" |
-Working Directory = "" |
-Environment Options = "" |
- |
Index: instr/drsctrl/DRS.cpp |
=================================================================== |
--- instr/drsctrl/DRS.cpp (revision 196) |
+++ instr/drsctrl/DRS.cpp (nonexistent) |
@@ -1,7733 +0,0 @@ |
-/******************************************************************** |
- |
- 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; |
- } |
-} |
Index: instr/drsctrl/drsread.h |
=================================================================== |
--- instr/drsctrl/drsread.h (revision 196) |
+++ instr/drsctrl/drsread.h (nonexistent) |
@@ -1,31 +0,0 @@ |
-#ifndef _DRSREAD_H_ |
-#define _DRSREAD_H_ |
-#ifdef DLLMAIN |
-#define DLLEXPORT extern "C" __declspec(dllexport) |
-#else |
-//#define DLLEXPORT __declspec(dllimport) |
-#define DLLEXPORT |
-#endif |
- |
-DLLEXPORT void DRSSetMask(int mask); |
-DLLEXPORT void DRSSetTriggerType(int type); |
-DLLEXPORT void DRSSetFrequency(int freq); |
-DLLEXPORT void DRSSetRange(double range); |
-DLLEXPORT void DRSSetTriggerChannel(int channel); |
-DLLEXPORT void DRSSetTriggerDelay(double delay); |
-DLLEXPORT void DRSSetTriggerLevel(double level); |
-DLLEXPORT void DRSSetTriggerPolarity(int polarity); |
- |
-DLLEXPORT float * DRSGetTime(int ch); |
-DLLEXPORT float * DRSGetWave(int ch); |
- |
-DLLEXPORT int DRSInit(); |
-DLLEXPORT int DRSRead( int drstimer); |
-DLLEXPORT int DRSEnd(); |
-DLLEXPORT int DRSToBuffer( unsigned char *p, int m_evSerial ); |
- |
-DLLEXPORT int DRSIsTimeout(); |
-DLLEXPORT void DRSSetTimeout ( void ); |
- |
-DLLEXPORT void DRSSigInt ( int k ); |
-#endif |
Index: instr/drsctrl/drs4.uir |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/instr/drsctrl/drs4.uir |
Property changes: |
Deleted: svn:mime-type |
## -1 +0,0 ## |
-application/octet-stream |
\ No newline at end of property |
Index: instr/drsctrl/XGetopt.cpp |
=================================================================== |
--- instr/drsctrl/XGetopt.cpp (revision 196) |
+++ instr/drsctrl/XGetopt.cpp (nonexistent) |
@@ -1,225 +0,0 @@ |
-// XGetopt.cpp Version 1.2 |
-// |
-// Author: Hans Dietrich |
-// hdietrich2@hotmail.com |
-// |
-// Description: |
-// XGetopt.cpp implements getopt(), a function to parse command lines. |
-// |
-// History |
-// Version 1.2 - 2003 May 17 |
-// - Added Unicode support |
-// |
-// Version 1.1 - 2002 March 10 |
-// - Added example to XGetopt.cpp module header |
-// |
-// This software is released into the public domain. |
-// You are free to use it in any way you like. |
-// |
-// This software is provided "as is" with no expressed |
-// or implied warranty. I accept no liability for any |
-// damage or loss of business that this software may cause. |
-// |
-/////////////////////////////////////////////////////////////////////////////// |
- |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// if you are using precompiled headers then include this line: |
-//#include "stdafx.h" |
-/////////////////////////////////////////////////////////////////////////////// |
- |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// if you are not using precompiled headers then include these lines: |
-#include <windows.h> |
-#include <stdio.h> |
-#include <tchar.h> |
-/////////////////////////////////////////////////////////////////////////////// |
- |
- |
-#include "XGetopt.h" |
- |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// |
-// X G e t o p t . c p p |
-// |
-// |
-// NAME |
-// getopt -- parse command line options |
-// |
-// SYNOPSIS |
-// int getopt(int argc, TCHAR *argv[], TCHAR *optstring) |
-// |
-// extern TCHAR *optarg; |
-// extern int optind; |
-// |
-// DESCRIPTION |
-// The getopt() function parses the command line arguments. Its |
-// arguments argc and argv are the argument count and array as |
-// passed into the application on program invocation. In the case |
-// of Visual C++ programs, argc and argv are available via the |
-// variables __argc and __argv (double underscores), respectively. |
-// getopt returns the next option letter in argv that matches a |
-// letter in optstring. (Note: Unicode programs should use |
-// __targv instead of __argv. Also, all character and string |
-// literals should be enclosed in _T( ) ). |
-// |
-// optstring is a string of recognized option letters; if a letter |
-// is followed by a colon, the option is expected to have an argument |
-// that may or may not be separated from it by white space. optarg |
-// is set to point to the start of the option argument on return from |
-// getopt. |
-// |
-// Option letters may be combined, e.g., "-ab" is equivalent to |
-// "-a -b". Option letters are case sensitive. |
-// |
-// getopt places in the external variable optind the argv index |
-// of the next argument to be processed. optind is initialized |
-// to 0 before the first call to getopt. |
-// |
-// When all options have been processed (i.e., up to the first |
-// non-option argument), getopt returns EOF, optarg will point |
-// to the argument, and optind will be set to the argv index of |
-// the argument. If there are no non-option arguments, optarg |
-// will be set to NULL. |
-// |
-// The special option "--" may be used to delimit the end of the |
-// options; EOF will be returned, and "--" (and everything after it) |
-// will be skipped. |
-// |
-// RETURN VALUE |
-// For option letters contained in the string optstring, getopt |
-// will return the option letter. getopt returns a question mark (?) |
-// when it encounters an option letter not included in optstring. |
-// EOF is returned when processing is finished. |
-// |
-// BUGS |
-// 1) Long options are not supported. |
-// 2) The GNU double-colon extension is not supported. |
-// 3) The environment variable POSIXLY_CORRECT is not supported. |
-// 4) The + syntax is not supported. |
-// 5) The automatic permutation of arguments is not supported. |
-// 6) This implementation of getopt() returns EOF if an error is |
-// encountered, instead of -1 as the latest standard requires. |
-// |
-// EXAMPLE |
-// BOOL CMyApp::ProcessCommandLine(int argc, TCHAR *argv[]) |
-// { |
-// int c; |
-// |
-// while ((c = getopt(argc, argv, _T("aBn:"))) != EOF) |
-// { |
-// switch (c) |
-// { |
-// case _T('a'): |
-// TRACE(_T("option a\n")); |
-// // |
-// // set some flag here |
-// // |
-// break; |
-// |
-// case _T('B'): |
-// TRACE( _T("option B\n")); |
-// // |
-// // set some other flag here |
-// // |
-// break; |
-// |
-// case _T('n'): |
-// TRACE(_T("option n: value=%d\n"), atoi(optarg)); |
-// // |
-// // do something with value here |
-// // |
-// break; |
-// |
-// case _T('?'): |
-// TRACE(_T("ERROR: illegal option %s\n"), argv[optind-1]); |
-// return FALSE; |
-// break; |
-// |
-// default: |
-// TRACE(_T("WARNING: no handler for option %c\n"), c); |
-// return FALSE; |
-// break; |
-// } |
-// } |
-// // |
-// // check for non-option args here |
-// // |
-// return TRUE; |
-// } |
-// |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-//TCHAR *optarg; // global argument pointer |
-char *optarg; // global argument pointer |
-int optind = 0; // global argv index |
- |
-//int getopt(int argc, TCHAR *argv[], TCHAR *optstring) |
-int getopt(int argc, char *argv[], char *optstring) |
-{ |
- //static TCHAR *next = NULL; |
- static char *next = NULL; |
- if (optind == 0) |
- next = NULL; |
- |
- optarg = NULL; |
- |
- if (next == NULL || *next == _T('\0')) |
- { |
- if (optind == 0) |
- optind++; |
- |
- if (optind >= argc || argv[optind][0] != _T('-') || argv[optind][1] == _T('\0')) |
- { |
- optarg = NULL; |
- if (optind < argc) |
- optarg = argv[optind]; |
- return EOF; |
- } |
- |
- if (strcmp( argv[optind], _T("--")) == 0) |
- { |
- optind++; |
- optarg = NULL; |
- if (optind < argc) |
- optarg = argv[optind]; |
- return EOF; |
- } |
- |
- next = argv[optind]; |
- next++; // skip past - |
- optind++; |
- } |
- |
- //TCHAR c = *next++; |
- //TCHAR *cp = _tcschr(optstring, c); |
- char c = *next++; |
- //char *cp = _tcschr(optstring, c); |
- char *cp =strchr(optstring, c); |
- |
- if (cp == NULL || c == _T(':')) |
- return _T('?'); |
- |
- cp++; |
- if (*cp == _T(':')) |
- { |
- if (*next != _T('\0')) |
- { |
- optarg = next; |
- next = NULL; |
- } |
- else if (optind < argc) |
- { |
- optarg = argv[optind]; |
- optind++; |
- } |
- else |
- { |
- return _T('?'); |
- } |
- } |
- |
- return c; |
-} |
Index: instr/drsctrl/libusb-1.0/libusb.h |
=================================================================== |
--- instr/drsctrl/libusb-1.0/libusb.h (revision 196) |
+++ instr/drsctrl/libusb-1.0/libusb.h (nonexistent) |
@@ -1,1443 +0,0 @@ |
-/* |
- * Public libusb header file |
- * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org> |
- * Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com> |
- * |
- * This library is free software; you can redistribute it and/or |
- * modify it under the terms of the GNU Lesser General Public |
- * License as published by the Free Software Foundation; either |
- * version 2.1 of the License, or (at your option) any later version. |
- * |
- * This library is distributed in the hope that it will be useful, |
- * but WITHOUT ANY WARRANTY; without even the implied warranty of |
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
- * Lesser General Public License for more details. |
- * |
- * You should have received a copy of the GNU Lesser General Public |
- * License along with this library; if not, write to the Free Software |
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
- */ |
- |
-#ifndef LIBUSB_H |
-#define LIBUSB_H |
- |
-#ifdef _MSC_VER |
-/* on MS environments, the inline keyword is available in C++ only */ |
-#define inline __inline |
-/* ssize_t is also not available (copy/paste from MinGW) */ |
-#ifndef _SSIZE_T_DEFINED |
-#define _SSIZE_T_DEFINED |
-#undef ssize_t |
-#ifdef _WIN64 |
- typedef __int64 ssize_t; |
-#else |
- typedef int ssize_t; |
-#endif /* _WIN64 */ |
-#endif /* _SSIZE_T_DEFINED */ |
-#endif /* _MSC_VER */ |
- |
-/* stdint.h is also not usually available on MS */ |
-#if defined(_MSC_VER) && (_MSC_VER < 1600) && (!defined(_STDINT)) && (!defined(_STDINT_H)) |
-typedef unsigned __int8 uint8_t; |
-typedef unsigned __int16 uint16_t; |
-typedef unsigned __int32 uint32_t; |
-#else |
-#include <stdint.h> |
-#endif |
- |
-#include <sys/types.h> |
-#include <time.h> |
-#include <limits.h> |
- |
-#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__) |
-#include <sys/time.h> |
-#endif |
- |
-/* 'interface' might be defined as a macro on Windows, so we need to |
- * undefine it so as not to break the current libusb API, because |
- * libusb_config_descriptor has an 'interface' member |
- * As this can be problematic if you include windows.h after libusb.h |
- * in your sources, we force windows.h to be included first. */ |
-#if defined(_WIN32) || defined(__CYGWIN__) |
-#include <windows.h> |
-#if defined(interface) |
-#undef interface |
-#endif |
-#endif |
- |
-/** \def LIBUSB_CALL |
- * \ingroup misc |
- * libusb's Windows calling convention. |
- * |
- * Under Windows, the selection of available compilers and configurations |
- * means that, unlike other platforms, there is not <em>one true calling |
- * convention</em> (calling convention: the manner in which parameters are |
- * passed to funcions in the generated assembly code). |
- * |
- * Matching the Windows API itself, libusb uses the WINAPI convention (which |
- * translates to the <tt>stdcall</tt> convention) and guarantees that the |
- * library is compiled in this way. The public header file also includes |
- * appropriate annotations so that your own software will use the right |
- * convention, even if another convention is being used by default within |
- * your codebase. |
- * |
- * The one consideration that you must apply in your software is to mark |
- * all functions which you use as libusb callbacks with this LIBUSB_CALL |
- * annotation, so that they too get compiled for the correct calling |
- * convention. |
- * |
- * On non-Windows operating systems, this macro is defined as nothing. This |
- * means that you can apply it to your code without worrying about |
- * cross-platform compatibility. |
- */ |
-/* LIBUSB_CALL must be defined on both definition and declaration of libusb |
- * functions. You'd think that declaration would be enough, but cygwin will |
- * complain about conflicting types unless both are marked this way. |
- * The placement of this macro is important too; it must appear after the |
- * return type, before the function name. See internal documentation for |
- * API_EXPORTED. |
- */ |
-#if defined(_WIN32) || defined(__CYGWIN__) |
-#define LIBUSB_CALL WINAPI |
-#else |
-#define LIBUSB_CALL |
-#endif |
- |
-#ifdef __cplusplus |
-extern "C" { |
-#endif |
- |
-/** \def libusb_cpu_to_le16 |
- * \ingroup misc |
- * Convert a 16-bit value from host-endian to little-endian format. On |
- * little endian systems, this function does nothing. On big endian systems, |
- * the bytes are swapped. |
- * \param x the host-endian value to convert |
- * \returns the value in little-endian byte order |
- */ |
-static inline uint16_t libusb_cpu_to_le16(const uint16_t x) |
-{ |
- union { |
- uint8_t b8[2]; |
- uint16_t b16; |
- } _tmp; |
- _tmp.b8[1] = x >> 8; |
- _tmp.b8[0] = x & 0xff; |
- return _tmp.b16; |
-} |
- |
-/** \def libusb_le16_to_cpu |
- * \ingroup misc |
- * Convert a 16-bit value from little-endian to host-endian format. On |
- * little endian systems, this function does nothing. On big endian systems, |
- * the bytes are swapped. |
- * \param x the little-endian value to convert |
- * \returns the value in host-endian byte order |
- */ |
-#define libusb_le16_to_cpu libusb_cpu_to_le16 |
- |
-/* standard USB stuff */ |
- |
-/** \ingroup desc |
- * Device and/or Interface Class codes */ |
-enum libusb_class_code { |
- /** In the context of a \ref libusb_device_descriptor "device descriptor", |
- * this bDeviceClass value indicates that each interface specifies its |
- * own class information and all interfaces operate independently. |
- */ |
- LIBUSB_CLASS_PER_INTERFACE = 0, |
- |
- /** Audio class */ |
- LIBUSB_CLASS_AUDIO = 1, |
- |
- /** Communications class */ |
- LIBUSB_CLASS_COMM = 2, |
- |
- /** Human Interface Device class */ |
- LIBUSB_CLASS_HID = 3, |
- |
- /** Physical */ |
- LIBUSB_CLASS_PHYSICAL = 5, |
- |
- /** Printer class */ |
- LIBUSB_CLASS_PRINTER = 7, |
- |
- /** Image class */ |
- LIBUSB_CLASS_PTP = 6, /* legacy name from libusb-0.1 usb.h */ |
- LIBUSB_CLASS_IMAGE = 6, |
- |
- /** Mass storage class */ |
- LIBUSB_CLASS_MASS_STORAGE = 8, |
- |
- /** Hub class */ |
- LIBUSB_CLASS_HUB = 9, |
- |
- /** Data class */ |
- LIBUSB_CLASS_DATA = 10, |
- |
- /** Smart Card */ |
- LIBUSB_CLASS_SMART_CARD = 0x0b, |
- |
- /** Content Security */ |
- LIBUSB_CLASS_CONTENT_SECURITY = 0x0d, |
- |
- /** Video */ |
- LIBUSB_CLASS_VIDEO = 0x0e, |
- |
- /** Personal Healthcare */ |
- LIBUSB_CLASS_PERSONAL_HEALTHCARE = 0x0f, |
- |
- /** Diagnostic Device */ |
- LIBUSB_CLASS_DIAGNOSTIC_DEVICE = 0xdc, |
- |
- /** Wireless class */ |
- LIBUSB_CLASS_WIRELESS = 0xe0, |
- |
- /** Application class */ |
- LIBUSB_CLASS_APPLICATION = 0xfe, |
- |
- /** Class is vendor-specific */ |
- LIBUSB_CLASS_VENDOR_SPEC = 0xff |
-}; |
- |
-/** \ingroup desc |
- * Descriptor types as defined by the USB specification. */ |
-enum libusb_descriptor_type { |
- /** Device descriptor. See libusb_device_descriptor. */ |
- LIBUSB_DT_DEVICE = 0x01, |
- |
- /** Configuration descriptor. See libusb_config_descriptor. */ |
- LIBUSB_DT_CONFIG = 0x02, |
- |
- /** String descriptor */ |
- LIBUSB_DT_STRING = 0x03, |
- |
- /** Interface descriptor. See libusb_interface_descriptor. */ |
- LIBUSB_DT_INTERFACE = 0x04, |
- |
- /** Endpoint descriptor. See libusb_endpoint_descriptor. */ |
- LIBUSB_DT_ENDPOINT = 0x05, |
- |
- /** HID descriptor */ |
- LIBUSB_DT_HID = 0x21, |
- |
- /** HID report descriptor */ |
- LIBUSB_DT_REPORT = 0x22, |
- |
- /** Physical descriptor */ |
- LIBUSB_DT_PHYSICAL = 0x23, |
- |
- /** Hub descriptor */ |
- LIBUSB_DT_HUB = 0x29, |
-}; |
- |
-/* Descriptor sizes per descriptor type */ |
-#define LIBUSB_DT_DEVICE_SIZE 18 |
-#define LIBUSB_DT_CONFIG_SIZE 9 |
-#define LIBUSB_DT_INTERFACE_SIZE 9 |
-#define LIBUSB_DT_ENDPOINT_SIZE 7 |
-#define LIBUSB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ |
-#define LIBUSB_DT_HUB_NONVAR_SIZE 7 |
- |
-#define LIBUSB_ENDPOINT_ADDRESS_MASK 0x0f /* in bEndpointAddress */ |
-#define LIBUSB_ENDPOINT_DIR_MASK 0x80 |
- |
-/** \ingroup desc |
- * Endpoint direction. Values for bit 7 of the |
- * \ref libusb_endpoint_descriptor::bEndpointAddress "endpoint address" scheme. |
- */ |
-enum libusb_endpoint_direction { |
- /** In: device-to-host */ |
- LIBUSB_ENDPOINT_IN = 0x80, |
- |
- /** Out: host-to-device */ |
- LIBUSB_ENDPOINT_OUT = 0x00 |
-}; |
- |
-#define LIBUSB_TRANSFER_TYPE_MASK 0x03 /* in bmAttributes */ |
- |
-/** \ingroup desc |
- * Endpoint transfer type. Values for bits 0:1 of the |
- * \ref libusb_endpoint_descriptor::bmAttributes "endpoint attributes" field. |
- */ |
-enum libusb_transfer_type { |
- /** Control endpoint */ |
- LIBUSB_TRANSFER_TYPE_CONTROL = 0, |
- |
- /** Isochronous endpoint */ |
- LIBUSB_TRANSFER_TYPE_ISOCHRONOUS = 1, |
- |
- /** Bulk endpoint */ |
- LIBUSB_TRANSFER_TYPE_BULK = 2, |
- |
- /** Interrupt endpoint */ |
- LIBUSB_TRANSFER_TYPE_INTERRUPT = 3 |
-}; |
- |
-/** \ingroup misc |
- * Standard requests, as defined in table 9-3 of the USB2 specifications */ |
-enum libusb_standard_request { |
- /** Request status of the specific recipient */ |
- LIBUSB_REQUEST_GET_STATUS = 0x00, |
- |
- /** Clear or disable a specific feature */ |
- LIBUSB_REQUEST_CLEAR_FEATURE = 0x01, |
- |
- /* 0x02 is reserved */ |
- |
- /** Set or enable a specific feature */ |
- LIBUSB_REQUEST_SET_FEATURE = 0x03, |
- |
- /* 0x04 is reserved */ |
- |
- /** Set device address for all future accesses */ |
- LIBUSB_REQUEST_SET_ADDRESS = 0x05, |
- |
- /** Get the specified descriptor */ |
- LIBUSB_REQUEST_GET_DESCRIPTOR = 0x06, |
- |
- /** Used to update existing descriptors or add new descriptors */ |
- LIBUSB_REQUEST_SET_DESCRIPTOR = 0x07, |
- |
- /** Get the current device configuration value */ |
- LIBUSB_REQUEST_GET_CONFIGURATION = 0x08, |
- |
- /** Set device configuration */ |
- LIBUSB_REQUEST_SET_CONFIGURATION = 0x09, |
- |
- /** Return the selected alternate setting for the specified interface */ |
- LIBUSB_REQUEST_GET_INTERFACE = 0x0A, |
- |
- /** Select an alternate interface for the specified interface */ |
- LIBUSB_REQUEST_SET_INTERFACE = 0x0B, |
- |
- /** Set then report an endpoint's synchronization frame */ |
- LIBUSB_REQUEST_SYNCH_FRAME = 0x0C, |
-}; |
- |
-/** \ingroup misc |
- * Request type bits of the |
- * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control |
- * transfers. */ |
-enum libusb_request_type { |
- /** Standard */ |
- LIBUSB_REQUEST_TYPE_STANDARD = (0x00 << 5), |
- |
- /** Class */ |
- LIBUSB_REQUEST_TYPE_CLASS = (0x01 << 5), |
- |
- /** Vendor */ |
- LIBUSB_REQUEST_TYPE_VENDOR = (0x02 << 5), |
- |
- /** Reserved */ |
- LIBUSB_REQUEST_TYPE_RESERVED = (0x03 << 5) |
-}; |
- |
-/** \ingroup misc |
- * Recipient bits of the |
- * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control |
- * transfers. Values 4 through 31 are reserved. */ |
-enum libusb_request_recipient { |
- /** Device */ |
- LIBUSB_RECIPIENT_DEVICE = 0x00, |
- |
- /** Interface */ |
- LIBUSB_RECIPIENT_INTERFACE = 0x01, |
- |
- /** Endpoint */ |
- LIBUSB_RECIPIENT_ENDPOINT = 0x02, |
- |
- /** Other */ |
- LIBUSB_RECIPIENT_OTHER = 0x03, |
-}; |
- |
-#define LIBUSB_ISO_SYNC_TYPE_MASK 0x0C |
- |
-/** \ingroup desc |
- * Synchronization type for isochronous endpoints. Values for bits 2:3 of the |
- * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in |
- * libusb_endpoint_descriptor. |
- */ |
-enum libusb_iso_sync_type { |
- /** No synchronization */ |
- LIBUSB_ISO_SYNC_TYPE_NONE = 0, |
- |
- /** Asynchronous */ |
- LIBUSB_ISO_SYNC_TYPE_ASYNC = 1, |
- |
- /** Adaptive */ |
- LIBUSB_ISO_SYNC_TYPE_ADAPTIVE = 2, |
- |
- /** Synchronous */ |
- LIBUSB_ISO_SYNC_TYPE_SYNC = 3 |
-}; |
- |
-#define LIBUSB_ISO_USAGE_TYPE_MASK 0x30 |
- |
-/** \ingroup desc |
- * Usage type for isochronous endpoints. Values for bits 4:5 of the |
- * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in |
- * libusb_endpoint_descriptor. |
- */ |
-enum libusb_iso_usage_type { |
- /** Data endpoint */ |
- LIBUSB_ISO_USAGE_TYPE_DATA = 0, |
- |
- /** Feedback endpoint */ |
- LIBUSB_ISO_USAGE_TYPE_FEEDBACK = 1, |
- |
- /** Implicit feedback Data endpoint */ |
- LIBUSB_ISO_USAGE_TYPE_IMPLICIT = 2, |
-}; |
- |
-/** \ingroup desc |
- * A structure representing the standard USB device descriptor. This |
- * descriptor is documented in section 9.6.1 of the USB 2.0 specification. |
- * All multiple-byte fields are represented in host-endian format. |
- */ |
-struct libusb_device_descriptor { |
- /** Size of this descriptor (in bytes) */ |
- uint8_t bLength; |
- |
- /** Descriptor type. Will have value |
- * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE LIBUSB_DT_DEVICE in this |
- * context. */ |
- uint8_t bDescriptorType; |
- |
- /** USB specification release number in binary-coded decimal. A value of |
- * 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1, etc. */ |
- uint16_t bcdUSB; |
- |
- /** USB-IF class code for the device. See \ref libusb_class_code. */ |
- uint8_t bDeviceClass; |
- |
- /** USB-IF subclass code for the device, qualified by the bDeviceClass |
- * value */ |
- uint8_t bDeviceSubClass; |
- |
- /** USB-IF protocol code for the device, qualified by the bDeviceClass and |
- * bDeviceSubClass values */ |
- uint8_t bDeviceProtocol; |
- |
- /** Maximum packet size for endpoint 0 */ |
- uint8_t bMaxPacketSize0; |
- |
- /** USB-IF vendor ID */ |
- uint16_t idVendor; |
- |
- /** USB-IF product ID */ |
- uint16_t idProduct; |
- |
- /** Device release number in binary-coded decimal */ |
- uint16_t bcdDevice; |
- |
- /** Index of string descriptor describing manufacturer */ |
- uint8_t iManufacturer; |
- |
- /** Index of string descriptor describing product */ |
- uint8_t iProduct; |
- |
- /** Index of string descriptor containing device serial number */ |
- uint8_t iSerialNumber; |
- |
- /** Number of possible configurations */ |
- uint8_t bNumConfigurations; |
-}; |
- |
-/** \ingroup desc |
- * A structure representing the standard USB endpoint descriptor. This |
- * descriptor is documented in section 9.6.3 of the USB 2.0 specification. |
- * All multiple-byte fields are represented in host-endian format. |
- */ |
-struct libusb_endpoint_descriptor { |
- /** Size of this descriptor (in bytes) */ |
- uint8_t bLength; |
- |
- /** Descriptor type. Will have value |
- * \ref libusb_descriptor_type::LIBUSB_DT_ENDPOINT LIBUSB_DT_ENDPOINT in |
- * this context. */ |
- uint8_t bDescriptorType; |
- |
- /** The address of the endpoint described by this descriptor. Bits 0:3 are |
- * the endpoint number. Bits 4:6 are reserved. Bit 7 indicates direction, |
- * see \ref libusb_endpoint_direction. |
- */ |
- uint8_t bEndpointAddress; |
- |
- /** Attributes which apply to the endpoint when it is configured using |
- * the bConfigurationValue. Bits 0:1 determine the transfer type and |
- * correspond to \ref libusb_transfer_type. Bits 2:3 are only used for |
- * isochronous endpoints and correspond to \ref libusb_iso_sync_type. |
- * Bits 4:5 are also only used for isochronous endpoints and correspond to |
- * \ref libusb_iso_usage_type. Bits 6:7 are reserved. |
- */ |
- uint8_t bmAttributes; |
- |
- /** Maximum packet size this endpoint is capable of sending/receiving. */ |
- uint16_t wMaxPacketSize; |
- |
- /** Interval for polling endpoint for data transfers. */ |
- uint8_t bInterval; |
- |
- /** For audio devices only: the rate at which synchronization feedback |
- * is provided. */ |
- uint8_t bRefresh; |
- |
- /** For audio devices only: the address if the synch endpoint */ |
- uint8_t bSynchAddress; |
- |
- /** Extra descriptors. If libusb encounters unknown endpoint descriptors, |
- * it will store them here, should you wish to parse them. */ |
- const unsigned char *extra; |
- |
- /** Length of the extra descriptors, in bytes. */ |
- int extra_length; |
-}; |
- |
-/** \ingroup desc |
- * A structure representing the standard USB interface descriptor. This |
- * descriptor is documented in section 9.6.5 of the USB 2.0 specification. |
- * All multiple-byte fields are represented in host-endian format. |
- */ |
-struct libusb_interface_descriptor { |
- /** Size of this descriptor (in bytes) */ |
- uint8_t bLength; |
- |
- /** Descriptor type. Will have value |
- * \ref libusb_descriptor_type::LIBUSB_DT_INTERFACE LIBUSB_DT_INTERFACE |
- * in this context. */ |
- uint8_t bDescriptorType; |
- |
- /** Number of this interface */ |
- uint8_t bInterfaceNumber; |
- |
- /** Value used to select this alternate setting for this interface */ |
- uint8_t bAlternateSetting; |
- |
- /** Number of endpoints used by this interface (excluding the control |
- * endpoint). */ |
- uint8_t bNumEndpoints; |
- |
- /** USB-IF class code for this interface. See \ref libusb_class_code. */ |
- uint8_t bInterfaceClass; |
- |
- /** USB-IF subclass code for this interface, qualified by the |
- * bInterfaceClass value */ |
- uint8_t bInterfaceSubClass; |
- |
- /** USB-IF protocol code for this interface, qualified by the |
- * bInterfaceClass and bInterfaceSubClass values */ |
- uint8_t bInterfaceProtocol; |
- |
- /** Index of string descriptor describing this interface */ |
- uint8_t iInterface; |
- |
- /** Array of endpoint descriptors. This length of this array is determined |
- * by the bNumEndpoints field. */ |
- const struct libusb_endpoint_descriptor *endpoint; |
- |
- /** Extra descriptors. If libusb encounters unknown interface descriptors, |
- * it will store them here, should you wish to parse them. */ |
- const unsigned char *extra; |
- |
- /** Length of the extra descriptors, in bytes. */ |
- int extra_length; |
-}; |
- |
-/** \ingroup desc |
- * A collection of alternate settings for a particular USB interface. |
- */ |
-struct libusb_interface { |
- /** Array of interface descriptors. The length of this array is determined |
- * by the num_altsetting field. */ |
- const struct libusb_interface_descriptor *altsetting; |
- |
- /** The number of alternate settings that belong to this interface */ |
- int num_altsetting; |
-}; |
- |
-/** \ingroup desc |
- * A structure representing the standard USB configuration descriptor. This |
- * descriptor is documented in section 9.6.3 of the USB 2.0 specification. |
- * All multiple-byte fields are represented in host-endian format. |
- */ |
-struct libusb_config_descriptor { |
- /** Size of this descriptor (in bytes) */ |
- uint8_t bLength; |
- |
- /** Descriptor type. Will have value |
- * \ref libusb_descriptor_type::LIBUSB_DT_CONFIG LIBUSB_DT_CONFIG |
- * in this context. */ |
- uint8_t bDescriptorType; |
- |
- /** Total length of data returned for this configuration */ |
- uint16_t wTotalLength; |
- |
- /** Number of interfaces supported by this configuration */ |
- uint8_t bNumInterfaces; |
- |
- /** Identifier value for this configuration */ |
- uint8_t bConfigurationValue; |
- |
- /** Index of string descriptor describing this configuration */ |
- uint8_t iConfiguration; |
- |
- /** Configuration characteristics */ |
- uint8_t bmAttributes; |
- |
- /** Maximum power consumption of the USB device from this bus in this |
- * configuration when the device is fully opreation. Expressed in units |
- * of 2 mA. */ |
- uint8_t MaxPower; |
- |
- /** Array of interfaces supported by this configuration. The length of |
- * this array is determined by the bNumInterfaces field. */ |
- const struct libusb_interface *interface; |
- |
- /** Extra descriptors. If libusb encounters unknown configuration |
- * descriptors, it will store them here, should you wish to parse them. */ |
- const unsigned char *extra; |
- |
- /** Length of the extra descriptors, in bytes. */ |
- int extra_length; |
-}; |
- |
-/** \ingroup asyncio |
- * Setup packet for control transfers. */ |
-struct libusb_control_setup { |
- /** Request type. Bits 0:4 determine recipient, see |
- * \ref libusb_request_recipient. Bits 5:6 determine type, see |
- * \ref libusb_request_type. Bit 7 determines data transfer direction, see |
- * \ref libusb_endpoint_direction. |
- */ |
- uint8_t bmRequestType; |
- |
- /** Request. If the type bits of bmRequestType are equal to |
- * \ref libusb_request_type::LIBUSB_REQUEST_TYPE_STANDARD |
- * "LIBUSB_REQUEST_TYPE_STANDARD" then this field refers to |
- * \ref libusb_standard_request. For other cases, use of this field is |
- * application-specific. */ |
- uint8_t bRequest; |
- |
- /** Value. Varies according to request */ |
- uint16_t wValue; |
- |
- /** Index. Varies according to request, typically used to pass an index |
- * or offset */ |
- uint16_t wIndex; |
- |
- /** Number of bytes to transfer */ |
- uint16_t wLength; |
-}; |
- |
-#define LIBUSB_CONTROL_SETUP_SIZE (sizeof(struct libusb_control_setup)) |
- |
-/* libusb */ |
- |
-struct libusb_context; |
-struct libusb_device; |
-struct libusb_device_handle; |
- |
-/** \ingroup lib |
- * Structure representing the libusb version. |
- */ |
-struct libusb_version { |
- /** Library major version. */ |
- const uint16_t major; |
- |
- /** Library minor version. */ |
- const uint16_t minor; |
- |
- /** Library micro version. */ |
- const uint16_t micro; |
- |
- /** Library nano version. This field is only nonzero on Windows. */ |
- const uint16_t nano; |
- |
- /** Library release candidate suffix string, e.g. "-rc4". */ |
- const char *rc; |
- |
- /** Output of `git describe --tags` at library build time. */ |
- const char *describe; |
-}; |
- |
-/** \ingroup lib |
- * Structure representing a libusb session. The concept of individual libusb |
- * sessions allows for your program to use two libraries (or dynamically |
- * load two modules) which both independently use libusb. This will prevent |
- * interference between the individual libusb users - for example |
- * libusb_set_debug() will not affect the other user of the library, and |
- * libusb_exit() will not destroy resources that the other user is still |
- * using. |
- * |
- * Sessions are created by libusb_init() and destroyed through libusb_exit(). |
- * If your application is guaranteed to only ever include a single libusb |
- * user (i.e. you), you do not have to worry about contexts: pass NULL in |
- * every function call where a context is required. The default context |
- * will be used. |
- * |
- * For more information, see \ref contexts. |
- */ |
-typedef struct libusb_context libusb_context; |
- |
-/** \ingroup dev |
- * Structure representing a USB device detected on the system. This is an |
- * opaque type for which you are only ever provided with a pointer, usually |
- * originating from libusb_get_device_list(). |
- * |
- * Certain operations can be performed on a device, but in order to do any |
- * I/O you will have to first obtain a device handle using libusb_open(). |
- * |
- * Devices are reference counted with libusb_device_ref() and |
- * libusb_device_unref(), and are freed when the reference count reaches 0. |
- * New devices presented by libusb_get_device_list() have a reference count of |
- * 1, and libusb_free_device_list() can optionally decrease the reference count |
- * on all devices in the list. libusb_open() adds another reference which is |
- * later destroyed by libusb_close(). |
- */ |
-typedef struct libusb_device libusb_device; |
- |
- |
-/** \ingroup dev |
- * Structure representing a handle on a USB device. This is an opaque type for |
- * which you are only ever provided with a pointer, usually originating from |
- * libusb_open(). |
- * |
- * A device handle is used to perform I/O and other operations. When finished |
- * with a device handle, you should call libusb_close(). |
- */ |
-typedef struct libusb_device_handle libusb_device_handle; |
- |
-/** \ingroup dev |
- * Speed codes. Indicates the speed at which the device is operating. |
- */ |
-enum libusb_speed { |
- /** The OS doesn't report or know the device speed. */ |
- LIBUSB_SPEED_UNKNOWN = 0, |
- |
- /** The device is operating at low speed (1.5MBit/s). */ |
- LIBUSB_SPEED_LOW = 1, |
- |
- /** The device is operating at full speed (12MBit/s). */ |
- LIBUSB_SPEED_FULL = 2, |
- |
- /** The device is operating at high speed (480MBit/s). */ |
- LIBUSB_SPEED_HIGH = 3, |
- |
- /** The device is operating at super speed (5000MBit/s). */ |
- LIBUSB_SPEED_SUPER = 4, |
-}; |
- |
-/** \ingroup misc |
- * Error codes. Most libusb functions return 0 on success or one of these |
- * codes on failure. |
- * You can call \ref libusb_error_name() to retrieve a string representation |
- * of an error code. |
- */ |
-enum libusb_error { |
- /** Success (no error) */ |
- LIBUSB_SUCCESS = 0, |
- |
- /** Input/output error */ |
- LIBUSB_ERROR_IO = -1, |
- |
- /** Invalid parameter */ |
- LIBUSB_ERROR_INVALID_PARAM = -2, |
- |
- /** Access denied (insufficient permissions) */ |
- LIBUSB_ERROR_ACCESS = -3, |
- |
- /** No such device (it may have been disconnected) */ |
- LIBUSB_ERROR_NO_DEVICE = -4, |
- |
- /** Entity not found */ |
- LIBUSB_ERROR_NOT_FOUND = -5, |
- |
- /** Resource busy */ |
- LIBUSB_ERROR_BUSY = -6, |
- |
- /** Operation timed out */ |
- LIBUSB_ERROR_TIMEOUT = -7, |
- |
- /** Overflow */ |
- LIBUSB_ERROR_OVERFLOW = -8, |
- |
- /** Pipe error */ |
- LIBUSB_ERROR_PIPE = -9, |
- |
- /** System call interrupted (perhaps due to signal) */ |
- LIBUSB_ERROR_INTERRUPTED = -10, |
- |
- /** Insufficient memory */ |
- LIBUSB_ERROR_NO_MEM = -11, |
- |
- /** Operation not supported or unimplemented on this platform */ |
- LIBUSB_ERROR_NOT_SUPPORTED = -12, |
- |
- /* NB! Remember to update libusb_error_name() |
- when adding new error codes here. */ |
- |
- /** Other error */ |
- LIBUSB_ERROR_OTHER = -99, |
-}; |
- |
-/** \ingroup asyncio |
- * Transfer status codes */ |
-enum libusb_transfer_status { |
- /** Transfer completed without error. Note that this does not indicate |
- * that the entire amount of requested data was transferred. */ |
- LIBUSB_TRANSFER_COMPLETED, |
- |
- /** Transfer failed */ |
- LIBUSB_TRANSFER_ERROR, |
- |
- /** Transfer timed out */ |
- LIBUSB_TRANSFER_TIMED_OUT, |
- |
- /** Transfer was cancelled */ |
- LIBUSB_TRANSFER_CANCELLED, |
- |
- /** For bulk/interrupt endpoints: halt condition detected (endpoint |
- * stalled). For control endpoints: control request not supported. */ |
- LIBUSB_TRANSFER_STALL, |
- |
- /** Device was disconnected */ |
- LIBUSB_TRANSFER_NO_DEVICE, |
- |
- /** Device sent more data than requested */ |
- LIBUSB_TRANSFER_OVERFLOW, |
-}; |
- |
-/** \ingroup asyncio |
- * libusb_transfer.flags values */ |
-enum libusb_transfer_flags { |
- /** Report short frames as errors */ |
- LIBUSB_TRANSFER_SHORT_NOT_OK = 1<<0, |
- |
- /** Automatically free() transfer buffer during libusb_free_transfer() */ |
- LIBUSB_TRANSFER_FREE_BUFFER = 1<<1, |
- |
- /** Automatically call libusb_free_transfer() after callback returns. |
- * If this flag is set, it is illegal to call libusb_free_transfer() |
- * from your transfer callback, as this will result in a double-free |
- * when this flag is acted upon. */ |
- LIBUSB_TRANSFER_FREE_TRANSFER = 1<<2, |
- |
- /** Terminate transfers that are a multiple of the endpoint's |
- * wMaxPacketSize with an extra zero length packet. This is useful |
- * when a device protocol mandates that each logical request is |
- * terminated by an incomplete packet (i.e. the logical requests are |
- * not separated by other means). |
- * |
- * This flag only affects host-to-device transfers to bulk and interrupt |
- * endpoints. In other situations, it is ignored. |
- * |
- * This flag only affects transfers with a length that is a multiple of |
- * the endpoint's wMaxPacketSize. On transfers of other lengths, this |
- * flag has no effect. Therefore, if you are working with a device that |
- * needs a ZLP whenever the end of the logical request falls on a packet |
- * boundary, then it is sensible to set this flag on <em>every</em> |
- * transfer (you do not have to worry about only setting it on transfers |
- * that end on the boundary). |
- * |
- * This flag is currently only supported on Linux. |
- * On other systems, libusb_submit_transfer() will return |
- * LIBUSB_ERROR_NOT_SUPPORTED for every transfer where this flag is set. |
- * |
- * Available since libusb-1.0.9. |
- */ |
- LIBUSB_TRANSFER_ADD_ZERO_PACKET = 1 << 3, |
-}; |
- |
-/** \ingroup asyncio |
- * Isochronous packet descriptor. */ |
-struct libusb_iso_packet_descriptor { |
- /** Length of data to request in this packet */ |
- unsigned int length; |
- |
- /** Amount of data that was actually transferred */ |
- unsigned int actual_length; |
- |
- /** Status code for this packet */ |
- enum libusb_transfer_status status; |
-}; |
- |
-struct libusb_transfer; |
- |
-/** \ingroup asyncio |
- * Asynchronous transfer callback function type. When submitting asynchronous |
- * transfers, you pass a pointer to a callback function of this type via the |
- * \ref libusb_transfer::callback "callback" member of the libusb_transfer |
- * structure. libusb will call this function later, when the transfer has |
- * completed or failed. See \ref asyncio for more information. |
- * \param transfer The libusb_transfer struct the callback function is being |
- * notified about. |
- */ |
-typedef void (LIBUSB_CALL *libusb_transfer_cb_fn)(struct libusb_transfer *transfer); |
- |
-/** \ingroup asyncio |
- * The generic USB transfer structure. The user populates this structure and |
- * then submits it in order to request a transfer. After the transfer has |
- * completed, the library populates the transfer with the results and passes |
- * it back to the user. |
- */ |
-struct libusb_transfer { |
- /** Handle of the device that this transfer will be submitted to */ |
- libusb_device_handle *dev_handle; |
- |
- /** A bitwise OR combination of \ref libusb_transfer_flags. */ |
- uint8_t flags; |
- |
- /** Address of the endpoint where this transfer will be sent. */ |
- unsigned char endpoint; |
- |
- /** Type of the endpoint from \ref libusb_transfer_type */ |
- unsigned char type; |
- |
- /** Timeout for this transfer in millseconds. A value of 0 indicates no |
- * timeout. */ |
- unsigned int timeout; |
- |
- /** The status of the transfer. Read-only, and only for use within |
- * transfer callback function. |
- * |
- * If this is an isochronous transfer, this field may read COMPLETED even |
- * if there were errors in the frames. Use the |
- * \ref libusb_iso_packet_descriptor::status "status" field in each packet |
- * to determine if errors occurred. */ |
- enum libusb_transfer_status status; |
- |
- /** Length of the data buffer */ |
- int length; |
- |
- /** Actual length of data that was transferred. Read-only, and only for |
- * use within transfer callback function. Not valid for isochronous |
- * endpoint transfers. */ |
- int actual_length; |
- |
- /** Callback function. This will be invoked when the transfer completes, |
- * fails, or is cancelled. */ |
- libusb_transfer_cb_fn callback; |
- |
- /** User context data to pass to the callback function. */ |
- void *user_data; |
- |
- /** Data buffer */ |
- unsigned char *buffer; |
- |
- /** Number of isochronous packets. Only used for I/O with isochronous |
- * endpoints. */ |
- int num_iso_packets; |
- |
- /** Isochronous packet descriptors, for isochronous transfers only. */ |
- struct libusb_iso_packet_descriptor iso_packet_desc |
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) |
- [] /* valid C99 code */ |
-#else |
- [0] /* non-standard, but usually working code */ |
-#endif |
- ; |
-}; |
- |
-/** \ingroup misc |
- * Capabilities supported by this instance of libusb. Test if the loaded |
- * library supports a given capability by calling |
- * \ref libusb_has_capability(). |
- */ |
-enum libusb_capability { |
- /** The libusb_has_capability() API is available. */ |
- LIBUSB_CAP_HAS_CAPABILITY = 0, |
-}; |
- |
-int LIBUSB_CALL libusb_init(libusb_context **ctx); |
-void LIBUSB_CALL libusb_exit(libusb_context *ctx); |
-void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level); |
-const struct libusb_version * LIBUSB_CALL libusb_get_version(void); |
-int LIBUSB_CALL libusb_has_capability(uint32_t capability); |
-const char * LIBUSB_CALL libusb_error_name(int errcode); |
- |
-ssize_t LIBUSB_CALL libusb_get_device_list(libusb_context *ctx, |
- libusb_device ***list); |
-void LIBUSB_CALL libusb_free_device_list(libusb_device **list, |
- int unref_devices); |
-libusb_device * LIBUSB_CALL libusb_ref_device(libusb_device *dev); |
-void LIBUSB_CALL libusb_unref_device(libusb_device *dev); |
- |
-int LIBUSB_CALL libusb_get_configuration(libusb_device_handle *dev, |
- int *config); |
-int LIBUSB_CALL libusb_get_device_descriptor(libusb_device *dev, |
- struct libusb_device_descriptor *desc); |
-int LIBUSB_CALL libusb_get_active_config_descriptor(libusb_device *dev, |
- struct libusb_config_descriptor **config); |
-int LIBUSB_CALL libusb_get_config_descriptor(libusb_device *dev, |
- uint8_t config_index, struct libusb_config_descriptor **config); |
-int LIBUSB_CALL libusb_get_config_descriptor_by_value(libusb_device *dev, |
- uint8_t bConfigurationValue, struct libusb_config_descriptor **config); |
-void LIBUSB_CALL libusb_free_config_descriptor( |
- struct libusb_config_descriptor *config); |
-uint8_t LIBUSB_CALL libusb_get_bus_number(libusb_device *dev); |
-uint8_t LIBUSB_CALL libusb_get_device_address(libusb_device *dev); |
-int LIBUSB_CALL libusb_get_device_speed(libusb_device *dev); |
-int LIBUSB_CALL libusb_get_max_packet_size(libusb_device *dev, |
- unsigned char endpoint); |
-int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev, |
- unsigned char endpoint); |
- |
-int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **handle); |
-void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle); |
-libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle); |
- |
-int LIBUSB_CALL libusb_set_configuration(libusb_device_handle *dev, |
- int configuration); |
-int LIBUSB_CALL libusb_claim_interface(libusb_device_handle *dev, |
- int interface_number); |
-int LIBUSB_CALL libusb_release_interface(libusb_device_handle *dev, |
- int interface_number); |
- |
-libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid( |
- libusb_context *ctx, uint16_t vendor_id, uint16_t product_id); |
- |
-int LIBUSB_CALL libusb_set_interface_alt_setting(libusb_device_handle *dev, |
- int interface_number, int alternate_setting); |
-int LIBUSB_CALL libusb_clear_halt(libusb_device_handle *dev, |
- unsigned char endpoint); |
-int LIBUSB_CALL libusb_reset_device(libusb_device_handle *dev); |
- |
-int LIBUSB_CALL libusb_kernel_driver_active(libusb_device_handle *dev, |
- int interface_number); |
-int LIBUSB_CALL libusb_detach_kernel_driver(libusb_device_handle *dev, |
- int interface_number); |
-int LIBUSB_CALL libusb_attach_kernel_driver(libusb_device_handle *dev, |
- int interface_number); |
- |
-/* async I/O */ |
- |
-/** \ingroup asyncio |
- * Get the data section of a control transfer. This convenience function is here |
- * to remind you that the data does not start until 8 bytes into the actual |
- * buffer, as the setup packet comes first. |
- * |
- * Calling this function only makes sense from a transfer callback function, |
- * or situations where you have already allocated a suitably sized buffer at |
- * transfer->buffer. |
- * |
- * \param transfer a transfer |
- * \returns pointer to the first byte of the data section |
- */ |
-static inline unsigned char *libusb_control_transfer_get_data( |
- struct libusb_transfer *transfer) |
-{ |
- return transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; |
-} |
- |
-/** \ingroup asyncio |
- * Get the control setup packet of a control transfer. This convenience |
- * function is here to remind you that the control setup occupies the first |
- * 8 bytes of the transfer data buffer. |
- * |
- * Calling this function only makes sense from a transfer callback function, |
- * or situations where you have already allocated a suitably sized buffer at |
- * transfer->buffer. |
- * |
- * \param transfer a transfer |
- * \returns a casted pointer to the start of the transfer data buffer |
- */ |
-static inline struct libusb_control_setup *libusb_control_transfer_get_setup( |
- struct libusb_transfer *transfer) |
-{ |
- return (struct libusb_control_setup *) transfer->buffer; |
-} |
- |
-/** \ingroup asyncio |
- * Helper function to populate the setup packet (first 8 bytes of the data |
- * buffer) for a control transfer. The wIndex, wValue and wLength values should |
- * be given in host-endian byte order. |
- * |
- * \param buffer buffer to output the setup packet into |
- * \param bmRequestType see the |
- * \ref libusb_control_setup::bmRequestType "bmRequestType" field of |
- * \ref libusb_control_setup |
- * \param bRequest see the |
- * \ref libusb_control_setup::bRequest "bRequest" field of |
- * \ref libusb_control_setup |
- * \param wValue see the |
- * \ref libusb_control_setup::wValue "wValue" field of |
- * \ref libusb_control_setup |
- * \param wIndex see the |
- * \ref libusb_control_setup::wIndex "wIndex" field of |
- * \ref libusb_control_setup |
- * \param wLength see the |
- * \ref libusb_control_setup::wLength "wLength" field of |
- * \ref libusb_control_setup |
- */ |
-static inline void libusb_fill_control_setup(unsigned char *buffer, |
- uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, |
- uint16_t wLength) |
-{ |
- struct libusb_control_setup *setup = (struct libusb_control_setup *) buffer; |
- setup->bmRequestType = bmRequestType; |
- setup->bRequest = bRequest; |
- setup->wValue = libusb_cpu_to_le16(wValue); |
- setup->wIndex = libusb_cpu_to_le16(wIndex); |
- setup->wLength = libusb_cpu_to_le16(wLength); |
-} |
- |
-struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(int iso_packets); |
-int LIBUSB_CALL libusb_submit_transfer(struct libusb_transfer *transfer); |
-int LIBUSB_CALL libusb_cancel_transfer(struct libusb_transfer *transfer); |
-void LIBUSB_CALL libusb_free_transfer(struct libusb_transfer *transfer); |
- |
-/** \ingroup asyncio |
- * Helper function to populate the required \ref libusb_transfer fields |
- * for a control transfer. |
- * |
- * If you pass a transfer buffer to this function, the first 8 bytes will |
- * be interpreted as a control setup packet, and the wLength field will be |
- * used to automatically populate the \ref libusb_transfer::length "length" |
- * field of the transfer. Therefore the recommended approach is: |
- * -# Allocate a suitably sized data buffer (including space for control setup) |
- * -# Call libusb_fill_control_setup() |
- * -# If this is a host-to-device transfer with a data stage, put the data |
- * in place after the setup packet |
- * -# Call this function |
- * -# Call libusb_submit_transfer() |
- * |
- * It is also legal to pass a NULL buffer to this function, in which case this |
- * function will not attempt to populate the length field. Remember that you |
- * must then populate the buffer and length fields later. |
- * |
- * \param transfer the transfer to populate |
- * \param dev_handle handle of the device that will handle the transfer |
- * \param buffer data buffer. If provided, this function will interpret the |
- * first 8 bytes as a setup packet and infer the transfer length from that. |
- * \param callback callback function to be invoked on transfer completion |
- * \param user_data user data to pass to callback function |
- * \param timeout timeout for the transfer in milliseconds |
- */ |
-static inline void libusb_fill_control_transfer( |
- struct libusb_transfer *transfer, libusb_device_handle *dev_handle, |
- unsigned char *buffer, libusb_transfer_cb_fn callback, void *user_data, |
- unsigned int timeout) |
-{ |
- struct libusb_control_setup *setup = (struct libusb_control_setup *) buffer; |
- transfer->dev_handle = dev_handle; |
- transfer->endpoint = 0; |
- transfer->type = LIBUSB_TRANSFER_TYPE_CONTROL; |
- transfer->timeout = timeout; |
- transfer->buffer = buffer; |
- if (setup) |
- transfer->length = LIBUSB_CONTROL_SETUP_SIZE |
- + libusb_le16_to_cpu(setup->wLength); |
- transfer->user_data = user_data; |
- transfer->callback = callback; |
-} |
- |
-/** \ingroup asyncio |
- * Helper function to populate the required \ref libusb_transfer fields |
- * for a bulk transfer. |
- * |
- * \param transfer the transfer to populate |
- * \param dev_handle handle of the device that will handle the transfer |
- * \param endpoint address of the endpoint where this transfer will be sent |
- * \param buffer data buffer |
- * \param length length of data buffer |
- * \param callback callback function to be invoked on transfer completion |
- * \param user_data user data to pass to callback function |
- * \param timeout timeout for the transfer in milliseconds |
- */ |
-static inline void libusb_fill_bulk_transfer(struct libusb_transfer *transfer, |
- libusb_device_handle *dev_handle, unsigned char endpoint, |
- unsigned char *buffer, int length, libusb_transfer_cb_fn callback, |
- void *user_data, unsigned int timeout) |
-{ |
- transfer->dev_handle = dev_handle; |
- transfer->endpoint = endpoint; |
- transfer->type = LIBUSB_TRANSFER_TYPE_BULK; |
- transfer->timeout = timeout; |
- transfer->buffer = buffer; |
- transfer->length = length; |
- transfer->user_data = user_data; |
- transfer->callback = callback; |
-} |
- |
-/** \ingroup asyncio |
- * Helper function to populate the required \ref libusb_transfer fields |
- * for an interrupt transfer. |
- * |
- * \param transfer the transfer to populate |
- * \param dev_handle handle of the device that will handle the transfer |
- * \param endpoint address of the endpoint where this transfer will be sent |
- * \param buffer data buffer |
- * \param length length of data buffer |
- * \param callback callback function to be invoked on transfer completion |
- * \param user_data user data to pass to callback function |
- * \param timeout timeout for the transfer in milliseconds |
- */ |
-static inline void libusb_fill_interrupt_transfer( |
- struct libusb_transfer *transfer, libusb_device_handle *dev_handle, |
- unsigned char endpoint, unsigned char *buffer, int length, |
- libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) |
-{ |
- transfer->dev_handle = dev_handle; |
- transfer->endpoint = endpoint; |
- transfer->type = LIBUSB_TRANSFER_TYPE_INTERRUPT; |
- transfer->timeout = timeout; |
- transfer->buffer = buffer; |
- transfer->length = length; |
- transfer->user_data = user_data; |
- transfer->callback = callback; |
-} |
- |
-/** \ingroup asyncio |
- * Helper function to populate the required \ref libusb_transfer fields |
- * for an isochronous transfer. |
- * |
- * \param transfer the transfer to populate |
- * \param dev_handle handle of the device that will handle the transfer |
- * \param endpoint address of the endpoint where this transfer will be sent |
- * \param buffer data buffer |
- * \param length length of data buffer |
- * \param num_iso_packets the number of isochronous packets |
- * \param callback callback function to be invoked on transfer completion |
- * \param user_data user data to pass to callback function |
- * \param timeout timeout for the transfer in milliseconds |
- */ |
-static inline void libusb_fill_iso_transfer(struct libusb_transfer *transfer, |
- libusb_device_handle *dev_handle, unsigned char endpoint, |
- unsigned char *buffer, int length, int num_iso_packets, |
- libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) |
-{ |
- transfer->dev_handle = dev_handle; |
- transfer->endpoint = endpoint; |
- transfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS; |
- transfer->timeout = timeout; |
- transfer->buffer = buffer; |
- transfer->length = length; |
- transfer->num_iso_packets = num_iso_packets; |
- transfer->user_data = user_data; |
- transfer->callback = callback; |
-} |
- |
-/** \ingroup asyncio |
- * Convenience function to set the length of all packets in an isochronous |
- * transfer, based on the num_iso_packets field in the transfer structure. |
- * |
- * \param transfer a transfer |
- * \param length the length to set in each isochronous packet descriptor |
- * \see libusb_get_max_packet_size() |
- */ |
-static inline void libusb_set_iso_packet_lengths( |
- struct libusb_transfer *transfer, unsigned int length) |
-{ |
- int i; |
- for (i = 0; i < transfer->num_iso_packets; i++) |
- transfer->iso_packet_desc[i].length = length; |
-} |
- |
-/** \ingroup asyncio |
- * Convenience function to locate the position of an isochronous packet |
- * within the buffer of an isochronous transfer. |
- * |
- * This is a thorough function which loops through all preceding packets, |
- * accumulating their lengths to find the position of the specified packet. |
- * Typically you will assign equal lengths to each packet in the transfer, |
- * and hence the above method is sub-optimal. You may wish to use |
- * libusb_get_iso_packet_buffer_simple() instead. |
- * |
- * \param transfer a transfer |
- * \param packet the packet to return the address of |
- * \returns the base address of the packet buffer inside the transfer buffer, |
- * or NULL if the packet does not exist. |
- * \see libusb_get_iso_packet_buffer_simple() |
- */ |
-static inline unsigned char *libusb_get_iso_packet_buffer( |
- struct libusb_transfer *transfer, unsigned int packet) |
-{ |
- int i; |
- size_t offset = 0; |
- int _packet; |
- |
- /* oops..slight bug in the API. packet is an unsigned int, but we use |
- * signed integers almost everywhere else. range-check and convert to |
- * signed to avoid compiler warnings. FIXME for libusb-2. */ |
- if (packet > INT_MAX) |
- return NULL; |
- _packet = packet; |
- |
- if (_packet >= transfer->num_iso_packets) |
- return NULL; |
- |
- for (i = 0; i < _packet; i++) |
- offset += transfer->iso_packet_desc[i].length; |
- |
- return transfer->buffer + offset; |
-} |
- |
-/** \ingroup asyncio |
- * Convenience function to locate the position of an isochronous packet |
- * within the buffer of an isochronous transfer, for transfers where each |
- * packet is of identical size. |
- * |
- * This function relies on the assumption that every packet within the transfer |
- * is of identical size to the first packet. Calculating the location of |
- * the packet buffer is then just a simple calculation: |
- * <tt>buffer + (packet_size * packet)</tt> |
- * |
- * Do not use this function on transfers other than those that have identical |
- * packet lengths for each packet. |
- * |
- * \param transfer a transfer |
- * \param packet the packet to return the address of |
- * \returns the base address of the packet buffer inside the transfer buffer, |
- * or NULL if the packet does not exist. |
- * \see libusb_get_iso_packet_buffer() |
- */ |
-static inline unsigned char *libusb_get_iso_packet_buffer_simple( |
- struct libusb_transfer *transfer, unsigned int packet) |
-{ |
- int _packet; |
- |
- /* oops..slight bug in the API. packet is an unsigned int, but we use |
- * signed integers almost everywhere else. range-check and convert to |
- * signed to avoid compiler warnings. FIXME for libusb-2. */ |
- if (packet > INT_MAX) |
- return NULL; |
- _packet = packet; |
- |
- if (_packet >= transfer->num_iso_packets) |
- return NULL; |
- |
- return transfer->buffer + (transfer->iso_packet_desc[0].length * _packet); |
-} |
- |
-/* sync I/O */ |
- |
-int LIBUSB_CALL libusb_control_transfer(libusb_device_handle *dev_handle, |
- uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, |
- unsigned char *data, uint16_t wLength, unsigned int timeout); |
- |
-int LIBUSB_CALL libusb_bulk_transfer(libusb_device_handle *dev_handle, |
- unsigned char endpoint, unsigned char *data, int length, |
- int *actual_length, unsigned int timeout); |
- |
-int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle, |
- unsigned char endpoint, unsigned char *data, int length, |
- int *actual_length, unsigned int timeout); |
- |
-/** \ingroup desc |
- * Retrieve a descriptor from the default control pipe. |
- * This is a convenience function which formulates the appropriate control |
- * message to retrieve the descriptor. |
- * |
- * \param dev a device handle |
- * \param desc_type the descriptor type, see \ref libusb_descriptor_type |
- * \param desc_index the index of the descriptor to retrieve |
- * \param data output buffer for descriptor |
- * \param length size of data buffer |
- * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure |
- */ |
-static inline int libusb_get_descriptor(libusb_device_handle *dev, |
- uint8_t desc_type, uint8_t desc_index, unsigned char *data, int length) |
-{ |
- return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN, |
- LIBUSB_REQUEST_GET_DESCRIPTOR, (desc_type << 8) | desc_index, 0, data, |
- (uint16_t) length, 1000); |
-} |
- |
-/** \ingroup desc |
- * Retrieve a descriptor from a device. |
- * This is a convenience function which formulates the appropriate control |
- * message to retrieve the descriptor. The string returned is Unicode, as |
- * detailed in the USB specifications. |
- * |
- * \param dev a device handle |
- * \param desc_index the index of the descriptor to retrieve |
- * \param langid the language ID for the string descriptor |
- * \param data output buffer for descriptor |
- * \param length size of data buffer |
- * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure |
- * \see libusb_get_string_descriptor_ascii() |
- */ |
-static inline int libusb_get_string_descriptor(libusb_device_handle *dev, |
- uint8_t desc_index, uint16_t langid, unsigned char *data, int length) |
-{ |
- return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN, |
- LIBUSB_REQUEST_GET_DESCRIPTOR, (uint16_t)((LIBUSB_DT_STRING << 8) | desc_index), |
- langid, data, (uint16_t) length, 1000); |
-} |
- |
-int LIBUSB_CALL libusb_get_string_descriptor_ascii(libusb_device_handle *dev, |
- uint8_t desc_index, unsigned char *data, int length); |
- |
-/* polling and timeouts */ |
- |
-int LIBUSB_CALL libusb_try_lock_events(libusb_context *ctx); |
-void LIBUSB_CALL libusb_lock_events(libusb_context *ctx); |
-void LIBUSB_CALL libusb_unlock_events(libusb_context *ctx); |
-int LIBUSB_CALL libusb_event_handling_ok(libusb_context *ctx); |
-int LIBUSB_CALL libusb_event_handler_active(libusb_context *ctx); |
-void LIBUSB_CALL libusb_lock_event_waiters(libusb_context *ctx); |
-void LIBUSB_CALL libusb_unlock_event_waiters(libusb_context *ctx); |
-int LIBUSB_CALL libusb_wait_for_event(libusb_context *ctx, struct timeval *tv); |
- |
-int LIBUSB_CALL libusb_handle_events_timeout(libusb_context *ctx, |
- struct timeval *tv); |
-int LIBUSB_CALL libusb_handle_events_timeout_completed(libusb_context *ctx, |
- struct timeval *tv, int *completed); |
-int LIBUSB_CALL libusb_handle_events(libusb_context *ctx); |
-int LIBUSB_CALL libusb_handle_events_completed(libusb_context *ctx, int *completed); |
-int LIBUSB_CALL libusb_handle_events_locked(libusb_context *ctx, |
- struct timeval *tv); |
-int LIBUSB_CALL libusb_pollfds_handle_timeouts(libusb_context *ctx); |
-int LIBUSB_CALL libusb_get_next_timeout(libusb_context *ctx, |
- struct timeval *tv); |
- |
-/** \ingroup poll |
- * File descriptor for polling |
- */ |
-struct libusb_pollfd { |
- /** Numeric file descriptor */ |
- int fd; |
- |
- /** Event flags to poll for from <poll.h>. POLLIN indicates that you |
- * should monitor this file descriptor for becoming ready to read from, |
- * and POLLOUT indicates that you should monitor this file descriptor for |
- * nonblocking write readiness. */ |
- short events; |
-}; |
- |
-/** \ingroup poll |
- * Callback function, invoked when a new file descriptor should be added |
- * to the set of file descriptors monitored for events. |
- * \param fd the new file descriptor |
- * \param events events to monitor for, see \ref libusb_pollfd for a |
- * description |
- * \param user_data User data pointer specified in |
- * libusb_set_pollfd_notifiers() call |
- * \see libusb_set_pollfd_notifiers() |
- */ |
-typedef void (LIBUSB_CALL *libusb_pollfd_added_cb)(int fd, short events, |
- void *user_data); |
- |
-/** \ingroup poll |
- * Callback function, invoked when a file descriptor should be removed from |
- * the set of file descriptors being monitored for events. After returning |
- * from this callback, do not use that file descriptor again. |
- * \param fd the file descriptor to stop monitoring |
- * \param user_data User data pointer specified in |
- * libusb_set_pollfd_notifiers() call |
- * \see libusb_set_pollfd_notifiers() |
- */ |
-typedef void (LIBUSB_CALL *libusb_pollfd_removed_cb)(int fd, void *user_data); |
- |
-const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds( |
- libusb_context *ctx); |
-void LIBUSB_CALL libusb_set_pollfd_notifiers(libusb_context *ctx, |
- libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, |
- void *user_data); |
- |
-#ifdef __cplusplus |
-} |
-#endif |
- |
-#endif |
Index: instr/drsctrl/averager.cpp |
=================================================================== |
--- instr/drsctrl/averager.cpp (revision 196) |
+++ instr/drsctrl/averager.cpp (nonexistent) |
@@ -1,214 +0,0 @@ |
-/********************************************************************\ |
- |
- Name: averager.cpp |
- Created by: Stefan Ritt |
- |
- Contents: Robust averager |
- |
- $Id: averager.cpp 21210 2013-12-12 11:36:59Z ritt $ |
- |
-\********************************************************************/ |
- |
-#include <stdio.h> |
-#include <stdlib.h> |
-#include <string.h> |
-#include <math.h> |
-#include <assert.h> |
- |
-#include "averager.h" |
- |
-/*----------------------------------------------------------------*/ |
- |
-Averager::Averager(int nx, int ny, int nz, int dim) |
-{ |
- fNx = nx; |
- fNy = ny; |
- fNz = nz; |
- fDim = dim; |
- |
- int size = sizeof(float)*nx*ny*nz * dim; |
- fArray = (float *)malloc(size); |
- assert(fArray); |
- memset(fArray, 0, size); |
- size = sizeof(float)*nx*ny*nz; |
- fN = (unsigned short *)malloc(size); |
- assert(fN); |
- memset(fN, 0, size); |
-} |
- |
-/*----------------------------------------------------------------*/ |
- |
-Averager::~Averager() |
-{ |
- if (fN) |
- free(fN); |
- if (fArray) |
- free(fArray); |
- fN = NULL; |
- fArray = NULL; |
-} |
- |
-/*----------------------------------------------------------------*/ |
- |
-void Averager::Add(int x, int y, int z, float value) |
-{ |
- assert(x < fNx); |
- assert(y < fNy); |
- assert(z < fNz); |
- |
- int nIndex = (x*fNy + y)*fNz + z; |
- if (fN[nIndex] == fDim - 1) // check if array full |
- return; |
- |
- int aIndex = ((x*fNy + y)*fNz + z) * fDim + fN[nIndex]; |
- fN[nIndex]++; |
- fArray[aIndex] = value; |
-} |
- |
-/*----------------------------------------------------------------*/ |
- |
-void Averager::Reset() |
-{ |
- int size = sizeof(float)*fNx*fNy*fNz * fDim; |
- memset(fArray, 0, size); |
- size = sizeof(float)*fNx*fNy*fNz; |
- memset(fN, 0, size); |
-} |
- |
-/*----------------------------------------------------------------*/ |
- |
-int compar(const void *a, const void *b); |
- |
-int compar(const void *a, const void *b) |
-{ |
- if (*((float *)a) == *((float *)b)) |
- return 0; |
- |
- return (*((float *)a) < *((float *)b)) ? -1 : 1; |
-} |
- |
-double Averager::Average(int x, int y, int z) |
-{ |
- assert(x < fNx); |
- assert(y < fNy); |
- assert(z < fNz); |
- |
- double a = 0; |
- |
- int nIndex = (x*fNy + y)*fNz + z; |
- int aIndex = ((x*fNy + y)*fNz + z) * fDim; |
- |
- for (int i=0 ; i<fN[nIndex] ; i++) |
- a += fArray[aIndex + i]; |
- |
- if (fN[nIndex] > 0) |
- a /= fN[nIndex]; |
- |
- return a; |
-} |
- |
-/*----------------------------------------------------------------*/ |
- |
-double Averager::Median(int x, int y, int z) |
-{ |
- assert(x < fNx); |
- assert(y < fNy); |
- assert(z < fNz); |
- |
- double m = 0; |
- |
- int nIndex = (x*fNy + y)*fNz + z; |
- int aIndex = ((x*fNy + y)*fNz + z) * fDim; |
- |
- qsort(&fArray[aIndex], fN[nIndex], sizeof(float), compar); |
- m = fArray[aIndex + fN[nIndex]/2]; |
- |
- return m; |
-} |
- |
-/*----------------------------------------------------------------*/ |
- |
-double Averager::RobustAverage(double range, int x, int y, int z) |
-{ |
- assert(x < fNx); |
- assert(y < fNy); |
- assert(z < fNz); |
- |
- double ra = 0; |
- int n = 0; |
- double m = Median(x, y, z); |
- |
- int nIndex = (x*fNy + y)*fNz + z; |
- int aIndex = ((x*fNy + y)*fNz + z) * fDim; |
- |
- for (int i=0 ; i<fN[nIndex] ; i++) { |
- if (fArray[aIndex + i] > m - range && fArray[aIndex + i] < m + range) { |
- ra += fArray[aIndex + i]; |
- n++; |
- } |
- } |
- |
- if (n > 0) |
- ra /= n; |
- |
- //if (y == 0 && z == 7 && fN[nIndex] > 10) |
- // printf("%d %lf %lf %lf\n", fN[nIndex], a, m, ra); |
- |
- return ra; |
-} |
- |
-/*----------------------------------------------------------------*/ |
- |
-int Averager::SaveNormalizedDistribution(const char *filename, int x, float range) |
-{ |
- assert(x < fNx); |
- FILE *f = fopen(filename, "wt"); |
- |
- if (!f) |
- return 0; |
- |
- fprintf(f, "X, Y, Z, Min, Max, Ave, Sigma\n"); |
- |
- for (int y=0 ; y<fNy ; y++) |
- for (int z=0 ; z<fNz ; z++) { |
- |
- int nIndex = (x*fNy + y)*fNz + z; |
- int aIndex = ((x*fNy + y)*fNz + z) * fDim; |
- |
- if (fN[nIndex] > 1) { |
- fprintf(f, "%d,%d, %d, ", x, y, z); |
- |
- double s = 0; |
- double s2 = 0; |
- double min = 0; |
- double max = 0; |
- int n = fN[nIndex]; |
- double m = Median(x, y, z); |
- |
- for (int i=0 ; i<n ; i++) { |
- double v = fArray[aIndex + i] - m; |
- s += v; |
- s2 += v*v; |
- if (v < min) |
- min = v; |
- if (v > max) |
- max = v; |
- } |
- double sigma = sqrt((n * s2 - s * s) / (n * (n-1))); |
- double average = s / n; |
- |
- fprintf(f, "%3.1lf, %3.1lf, %3.1lf, %3.3lf, ", min, max, average, sigma); |
- |
- if (min < -range || max > range) { |
- for (int i=0 ; i<n ; i++) |
- fprintf(f, "%3.1lf,", fArray[aIndex + i] - m); |
- } |
- |
- fprintf(f, "\n"); |
- } |
- } |
- |
- fclose(f); |
- return 1; |
-} |
- |
Index: instr/drsctrl/drs.h |
=================================================================== |
--- instr/drsctrl/drs.h (revision 196) |
+++ instr/drsctrl/drs.h (nonexistent) |
@@ -1,950 +0,0 @@ |
-/******************************************************************** |
- DRS.h, S.Ritt, M. Schneebeli - PSI |
- |
- $Id: DRS.h 21309 2014-04-11 14:51:29Z ritt $ |
- |
-********************************************************************/ |
-#ifndef DRS_H |
-#define DRS_H |
-#include <stdio.h> |
-#include <string.h> |
-#include "averager.h" |
- |
-#ifdef HAVE_LIBUSB |
-# ifndef HAVE_USB |
-# define HAVE_USB |
-# endif |
-#endif |
- |
-#ifdef HAVE_USB |
-# include "musbstd.h" |
-#endif // HAVE_USB |
- |
-#ifdef HAVE_VME |
-# include <mvmestd.h> |
-#endif // HAVE_VME |
- |
-/* disable "deprecated" warning */ |
-#ifdef _MSC_VER |
-#pragma warning(disable: 4996) |
-#endif |
- |
-#ifndef NULL |
-#define NULL 0 |
-#endif |
- |
-int drs_kbhit(); |
-unsigned int millitime(); |
- |
-/* transport mode */ |
-#define TR_VME 1 |
-#define TR_USB 2 |
-#define TR_USB2 3 |
- |
-/* address types */ |
-#ifndef T_CTRL |
-#define T_CTRL 1 |
-#define T_STATUS 2 |
-#define T_RAM 3 |
-#define T_FIFO 4 |
-#endif |
- |
-/*---- Register addresses ------------------------------------------*/ |
- |
-#define REG_CTRL 0x00000 /* 32 bit control reg */ |
-#define REG_DAC_OFS 0x00004 |
-#define REG_DAC0 0x00004 |
-#define REG_DAC1 0x00006 |
-#define REG_DAC2 0x00008 |
-#define REG_DAC3 0x0000A |
-#define REG_DAC4 0x0000C |
-#define REG_DAC5 0x0000E |
-#define REG_DAC6 0x00010 |
-#define REG_DAC7 0x00012 |
-#define REG_CHANNEL_CONFIG 0x00014 // low byte |
-#define REG_CONFIG 0x00014 // high byte |
-#define REG_CHANNEL_MODE 0x00016 |
-#define REG_ADCCLK_PHASE 0x00016 |
-#define REG_FREQ_SET_HI 0x00018 // DRS2 |
-#define REG_FREQ_SET_LO 0x0001A // DRS2 |
-#define REG_TRG_DELAY 0x00018 // DRS4 |
-#define REG_FREQ_SET 0x0001A // DRS4 |
-#define REG_TRIG_DELAY 0x0001C |
-#define REG_LMK_MSB 0x0001C // DRS4 Mezz |
-#define REG_CALIB_TIMING 0x0001E // DRS2 |
-#define REG_EEPROM_PAGE_EVAL 0x0001E // DRS4 Eval |
-#define REG_EEPROM_PAGE_MEZZ 0x0001A // DRS4 Mezz |
-#define REG_TRG_CONFIG 0x0001C // DRS4 Eval4 |
-#define REG_LMK_LSB 0x0001E // DRS4 Mezz |
-#define REG_WARMUP 0x00020 // DRS4 Mezz |
-#define REG_COOLDOWN 0x00022 // DRS4 Mezz |
-#define REG_READ_POINTER 0x00026 // DRS4 Mezz |
- |
-#define REG_MAGIC 0x00000 |
-#define REG_BOARD_TYPE 0x00002 |
-#define REG_STATUS 0x00004 |
-#define REG_RDAC_OFS 0x0000E |
-#define REG_RDAC0 0x00008 |
-#define REG_STOP_CELL0 0x00008 |
-#define REG_RDAC1 0x0000A |
-#define REG_STOP_CELL1 0x0000A |
-#define REG_RDAC2 0x0000C |
-#define REG_STOP_CELL2 0x0000C |
-#define REG_RDAC3 0x0000E |
-#define REG_STOP_CELL3 0x0000E |
-#define REG_RDAC4 0x00000 |
-#define REG_RDAC5 0x00002 |
-#define REG_STOP_WSR0 0x00010 |
-#define REG_STOP_WSR1 0x00011 |
-#define REG_STOP_WSR2 0x00012 |
-#define REG_STOP_WSR3 0x00013 |
-#define REG_RDAC6 0x00014 |
-#define REG_RDAC7 0x00016 |
-#define REG_EVENTS_IN_FIFO 0x00018 |
-#define REG_EVENT_COUNT 0x0001A |
-#define REG_FREQ1 0x0001C |
-#define REG_FREQ2 0x0001E |
-#define REG_WRITE_POINTER 0x0001E |
-#define REG_TEMPERATURE 0x00020 |
-#define REG_TRIGGER_BUS 0x00022 |
-#define REG_SERIAL_BOARD 0x00024 |
-#define REG_VERSION_FW 0x00026 |
-#define REG_SCALER0 0x00028 |
-#define REG_SCALER1 0x0002C |
-#define REG_SCALER2 0x00030 |
-#define REG_SCALER3 0x00034 |
-#define REG_SCALER4 0x00038 |
-#define REG_SCALER5 0x0003C |
- |
-/*---- Control register bit definitions ----------------------------*/ |
- |
-#define BIT_START_TRIG (1<<0) // write a "1" to start domino wave |
-#define BIT_REINIT_TRIG (1<<1) // write a "1" to stop & reset DRS |
-#define BIT_SOFT_TRIG (1<<2) // write a "1" to stop and read data to RAM |
-#define BIT_EEPROM_WRITE_TRIG (1<<3) // write a "1" to write into serial EEPROM |
-#define BIT_EEPROM_READ_TRIG (1<<4) // write a "1" to read from serial EEPROM |
-#define BIT_MULTI_BUFFER (1<<16) // Use multi buffering when "1" |
-#define BIT_DMODE (1<<17) // (*DRS2*) 0: single shot, 1: circular |
-#define BIT_ADC_ACTIVE (1<<17) // (*DRS4*) 0: stop ADC when running, 1: ADC always clocked |
-#define BIT_LED (1<<18) // 1=on, 0=blink during readout |
-#define BIT_TCAL_EN (1<<19) // switch on (1) / off (0) for 33 MHz calib signal |
-#define BIT_TCAL_SOURCE (1<<20) |
-#define BIT_REFCLK_SOURCE (1<<20) |
-#define BIT_FREQ_AUTO_ADJ (1<<21) // DRS2/3 |
-#define BIT_TRANSP_MODE (1<<21) // DRS4 |
-#define BIT_ENABLE_TRIGGER1 (1<<22) // External LEMO/FP/TRBUS trigger |
-#define BIT_LONG_START_PULSE (1<<23) // (*DRS2*) 0:short start pulse (>0.8GHz), 1:long start pulse (<0.8GHz) |
-#define BIT_READOUT_MODE (1<<23) // (*DRS3*,*DRS4*) 0:start from first bin, 1:start from domino stop |
-#define BIT_DELAYED_START (1<<24) // DRS2: start domino wave 400ns after soft trigger, used for waveform |
- // generator startup |
-#define BIT_NEG_TRIGGER (1<<24) // DRS4: use high-to-low trigger if set |
-#define BIT_ACAL_EN (1<<25) // connect DRS to inputs (0) or to DAC6 (1) |
-#define BIT_TRIGGER_DELAYED (1<<26) // select delayed trigger from trigger bus |
-#define BIT_ADCCLK_INVERT (1<<26) // invert ADC clock |
-#define BIT_REFCLK_EXT (1<<26) // use external MMCX CLKIN refclk |
-#define BIT_DACTIVE (1<<27) // keep domino wave running during readout |
-#define BIT_STANDBY_MODE (1<<28) // put chip in standby mode |
-#define BIT_TR_SOURCE1 (1<<29) // trigger source selection bits |
-#define BIT_DECIMATION (1<<29) // drop all odd samples (DRS4 mezz.) |
-#define BIT_TR_SOURCE2 (1<<30) // trigger source selection bits |
-#define BIT_ENABLE_TRIGGER2 (1<<31) // analog threshold (internal) trigger |
- |
-/* DRS4 configuration register bit definitions */ |
-#define BIT_CONFIG_DMODE (1<<8) // 0: single shot, 1: circular |
-#define BIT_CONFIG_PLLEN (1<<9) // write a "1" to enable the internal PLL |
-#define BIT_CONFIG_WSRLOOP (1<<10) // write a "1" to connect WSROUT to WSRIN internally |
- |
-/*---- Status register bit definitions -----------------------------*/ |
- |
-#define BIT_RUNNING (1<<0) // one if domino wave running or readout in progress |
-#define BIT_NEW_FREQ1 (1<<1) // one if new frequency measurement available |
-#define BIT_NEW_FREQ2 (1<<2) |
-#define BIT_PLL_LOCKED0 (1<<1) // 1 if PLL has locked (DRS4 evaluation board only) |
-#define BIT_PLL_LOCKED1 (1<<2) // 1 if PLL DRS4 B has locked (DRS4 mezzanine board only) |
-#define BIT_PLL_LOCKED2 (1<<3) // 1 if PLL DRS4 C has locked (DRS4 mezzanine board only) |
-#define BIT_PLL_LOCKED3 (1<<4) // 1 if PLL DRS4 D has locked (DRS4 mezzanine board only) |
-#define BIT_SERIAL_BUSY (1<<5) // 1 if EEPROM operation in progress |
-#define BIT_LMK_LOCKED (1<<6) // 1 if PLL of LMK chip has locked (DRS4 mezzanine board only) |
-#define BIT_2048_MODE (1<<7) // 1 if 2048-bin mode has been soldered |
- |
-enum DRSBoardConstants { |
- kNumberOfChannelsMax = 10, |
- kNumberOfCalibChannelsV3 = 10, |
- kNumberOfCalibChannelsV4 = 8, |
- kNumberOfBins = 1024, |
- kNumberOfChipsMax = 4, |
- kFrequencyCacheSize = 10, |
- kBSplineOrder = 4, |
- kPreCaliculatedBSplines = 1000, |
- kPreCaliculatedBSplineGroups = 5, |
- kNumberOfADCBins = 4096, |
- kBSplineXMinOffset = 20, |
- kMaxNumberOfClockCycles = 100, |
-}; |
- |
-enum DRSErrorCodes { |
- kSuccess = 0, |
- kInvalidTriggerSignal = -1, |
- kWrongChannelOrChip = -2, |
- kInvalidTransport = -3, |
- kZeroSuppression = -4, |
- kWaveNotAvailable = -5 |
-}; |
- |
-/*---- callback class ----*/ |
- |
-class DRSCallback |
-{ |
-public: |
- virtual void Progress(int value) = 0; |
- virtual ~DRSCallback() {}; |
-}; |
- |
-/*------------------------*/ |
- |
-class DRSBoard; |
- |
-class ResponseCalibration { |
-protected: |
- |
- class CalibrationData { |
- public: |
- class CalibrationDataChannel { |
- public: |
- unsigned char fLimitGroup[kNumberOfBins]; //! |
- float fMin[kNumberOfBins]; //! |
- float fRange[kNumberOfBins]; //! |
- short fOffset[kNumberOfBins]; //! |
- short fGain[kNumberOfBins]; //! |
- unsigned short fOffsetADC[kNumberOfBins]; //! |
- short *fData[kNumberOfBins]; //! |
- unsigned char *fLookUp[kNumberOfBins]; //! |
- unsigned short fLookUpOffset[kNumberOfBins]; //! |
- unsigned char fNumberOfLookUpPoints[kNumberOfBins]; //! |
- float *fTempData; //! |
- |
- private: |
- CalibrationDataChannel(const CalibrationDataChannel &c); // not implemented |
- CalibrationDataChannel &operator=(const CalibrationDataChannel &rhs); // not implemented |
- |
- public: |
- CalibrationDataChannel(int numberOfGridPoints) |
- :fTempData(new float[numberOfGridPoints]) { |
- int i; |
- for (i = 0; i < kNumberOfBins; i++) { |
- fData[i] = new short[numberOfGridPoints]; |
- } |
- memset(fLimitGroup, 0, sizeof(fLimitGroup)); |
- memset(fMin, 0, sizeof(fMin)); |
- memset(fRange, 0, sizeof(fRange)); |
- memset(fOffset, 0, sizeof(fOffset)); |
- memset(fGain, 0, sizeof(fGain)); |
- memset(fOffsetADC, 0, sizeof(fOffsetADC)); |
- memset(fLookUp, 0, sizeof(fLookUp)); |
- memset(fLookUpOffset, 0, sizeof(fLookUpOffset)); |
- memset(fNumberOfLookUpPoints, 0, sizeof(fNumberOfLookUpPoints)); |
- } |
- ~CalibrationDataChannel() { |
- int i; |
- delete fTempData; |
- for (i = 0; i < kNumberOfBins; i++) { |
- delete fData[i]; |
- delete fLookUp[i]; |
- } |
- } |
- }; |
- |
- bool fRead; //! |
- CalibrationDataChannel *fChannel[10]; //! |
- unsigned char fNumberOfGridPoints; //! |
- int fHasOffsetCalibration; //! |
- float fStartTemperature; //! |
- float fEndTemperature; //! |
- int *fBSplineOffsetLookUp[kNumberOfADCBins]; //! |
- float **fBSplineLookUp[kNumberOfADCBins]; //! |
- float fMin; //! |
- float fMax; //! |
- unsigned char fNumberOfLimitGroups; //! |
- static float fIntRevers[2 * kBSplineOrder - 2]; |
- |
- private: |
- CalibrationData(const CalibrationData &c); // not implemented |
- CalibrationData &operator=(const CalibrationData &rhs); // not implemented |
- |
- public: |
- CalibrationData(int numberOfGridPoints); |
- ~CalibrationData(); |
- static int CalculateBSpline(int nGrid, float value, float *bsplines); |
- void PreCalculateBSpline(); |
- void DeletePreCalculatedBSpline(); |
- }; |
- |
- // General Fields |
- DRSBoard *fBoard; |
- |
- double fPrecision; |
- |
- // Fields for creating the Calibration |
- bool fInitialized; |
- bool fRecorded; |
- bool fFitted; |
- bool fOffset; |
- bool fCalibrationValid[2]; |
- |
- int fNumberOfPointsLowVolt; |
- int fNumberOfPoints; |
- int fNumberOfMode2Bins; |
- int fNumberOfSamples; |
- int fNumberOfGridPoints; |
- int fNumberOfXConstPoints; |
- int fNumberOfXConstGridPoints; |
- double fTriggerFrequency; |
- int fShowStatistics; |
- FILE *fCalibFile; |
- |
- int fCurrentLowVoltPoint; |
- int fCurrentPoint; |
- int fCurrentSample; |
- int fCurrentFitChannel; |
- int fCurrentFitBin; |
- |
- float *fResponseX[10][kNumberOfBins]; |
- float *fResponseY; |
- unsigned short **fWaveFormMode3[10]; |
- unsigned short **fWaveFormMode2[10]; |
- short **fWaveFormOffset[10]; |
- unsigned short **fWaveFormOffsetADC[10]; |
- unsigned short *fSamples; |
- int *fSampleUsed; |
- |
- float *fPntX[2]; |
- float *fPntY[2]; |
- float *fUValues[2]; |
- float *fRes[kNumberOfBins]; |
- float *fResX[kNumberOfBins]; |
- |
- double *fXXFit; |
- double *fYYFit; |
- double *fWWFit; |
- double *fYYFitRes; |
- double *fYYSave; |
- double *fXXSave; |
- double fGainMin; |
- double fGainMax; |
- |
- float **fStatisticsApprox; |
- float **fStatisticsApproxExt; |
- |
- // Fields for applying the Calibration |
- CalibrationData *fCalibrationData[kNumberOfChipsMax]; |
- |
-private: |
- ResponseCalibration(const ResponseCalibration &c); // not implemented |
- ResponseCalibration &operator=(const ResponseCalibration &rhs); // not implemented |
- |
-public: |
- ResponseCalibration(DRSBoard* board); |
- ~ResponseCalibration(); |
- |
- void SetCalibrationParameters(int numberOfPointsLowVolt, int numberOfPoints, int numberOfMode2Bins, |
- int numberOfSamples, int numberOfGridPoints, int numberOfXConstPoints, |
- int numberOfXConstGridPoints, double triggerFrequency, int showStatistics = 0); |
- void ResetCalibration(); |
- bool RecordCalibrationPoints(int chipNumber); |
- bool RecordCalibrationPointsV3(int chipNumber); |
- bool RecordCalibrationPointsV4(int chipNumber); |
- bool FitCalibrationPoints(int chipNumber); |
- bool FitCalibrationPointsV3(int chipNumber); |
- bool FitCalibrationPointsV4(int chipNumber); |
- bool OffsetCalibration(int chipNumber); |
- bool OffsetCalibrationV3(int chipNumber); |
- bool OffsetCalibrationV4(int chipNumber); |
- double GetTemperature(unsigned int chipIndex); |
- |
- bool WriteCalibration(unsigned int chipIndex); |
- bool WriteCalibrationV3(unsigned int chipIndex); |
- bool WriteCalibrationV4(unsigned int chipIndex); |
- bool ReadCalibration(unsigned int chipIndex); |
- bool ReadCalibrationV3(unsigned int chipIndex); |
- bool ReadCalibrationV4(unsigned int chipIndex); |
- bool Calibrate(unsigned int chipIndex, unsigned int channel, unsigned short *adcWaveform, short *uWaveform, |
- int triggerCell, float threshold, bool offsetCalib); |
- bool SubtractADCOffset(unsigned int chipIndex, unsigned int channel, unsigned short *adcWaveform, |
- unsigned short *adcCalibratedWaveform, unsigned short newBaseLevel); |
- bool IsRead(int chipIndex) const { return fCalibrationValid[chipIndex]; } |
- double GetPrecision() const { return fPrecision; }; |
- |
- double GetOffsetAt(int chip,int chn,int bin) const { return fCalibrationData[chip]->fChannel[chn]->fOffset[bin]; }; |
- double GetGainAt(int chip,int chn,int bin) const { return fCalibrationData[chip]->fChannel[chn]->fGain[bin]; }; |
- double GetMeasPointXAt(int ip) const { return fXXSave[ip]; }; |
- double GetMeasPointYAt(int ip) const { return fYYSave[ip]; }; |
- |
-protected: |
- void InitFields(int numberOfPointsLowVolt, int numberOfPoints, int numberOfMode2Bins, int numberOfSamples, |
- int numberOfGridPoints, int numberOfXConstPoints, int numberOfXConstGridPoints, |
- double triggerFrequency, int showStatistics); |
- void DeleteFields(); |
- void CalibrationTrigger(int mode, double voltage); |
- void CalibrationStart(double voltage); |
- |
- static float GetValue(float *coefficients, float u, int n); |
- static int Approx(float *p, float *uu, int np, int nu, float *coef); |
- static void LeastSquaresAccumulation(float **matrix, int nb, int *ip, int *ir, int mt, int jt); |
- static int LeastSquaresSolving(float **matrix, int nb, int ip, int ir, float *x, int n); |
- static void Housholder(int lpivot, int l1, int m, float **u, int iU1, int iU2, float *up, float **c, int iC1, |
- int iC2, int ice, int ncv); |
- |
- static int MakeDir(const char *path); |
- static void Average(int method,float *samples,int numberOfSamples,float &mean,float &error,float sigmaBoundary); |
-}; |
- |
- |
-class DRSBoard { |
-protected: |
- class TimeData { |
- public: |
- class FrequencyData { |
- public: |
- int fFrequency; |
- double fBin[kNumberOfBins]; |
- }; |
- |
- enum { |
- kMaxNumberOfFrequencies = 4000 |
- }; |
- int fChip; |
- int fNumberOfFrequencies; |
- FrequencyData *fFrequency[kMaxNumberOfFrequencies]; |
- |
- private: |
- TimeData(const TimeData &c); // not implemented |
- TimeData &operator=(const TimeData &rhs); // not implemented |
- |
- public: |
- TimeData() |
- :fChip(0) |
- ,fNumberOfFrequencies(0) { |
- } |
- ~TimeData() { |
- int i; |
- for (i = 0; i < fNumberOfFrequencies; i++) { |
- delete fFrequency[i]; |
- } |
- } |
- }; |
- |
-public: |
- // DAC channels (CMC Version 1 : DAC_COFSA,DAC_COFSB,DAC_DRA,DAC_DSA,DAC_TLEVEL,DAC_ACALIB,DAC_DSB,DAC_DRB) |
- unsigned int fDAC_COFSA; |
- unsigned int fDAC_COFSB; |
- unsigned int fDAC_DRA; |
- unsigned int fDAC_DSA; |
- unsigned int fDAC_TLEVEL; |
- unsigned int fDAC_ACALIB; |
- unsigned int fDAC_DSB; |
- unsigned int fDAC_DRB; |
- // DAC channels (CMC Version 2+3 : DAC_COFS,DAC_DSA,DAC_DSB,DAC_TLEVEL,DAC_ADCOFS,DAC_CLKOFS,DAC_ACALIB) |
- unsigned int fDAC_COFS; |
- unsigned int fDAC_ADCOFS; |
- unsigned int fDAC_CLKOFS; |
- // DAC channels (CMC Version 4 : DAC_ROFS_1,DAC_DSA,DAC_DSB,DAC_ROFS_2,DAC_ADCOFS,DAC_ACALIB,DAC_INOFS,DAC_BIAS) |
- unsigned int fDAC_ROFS_1; |
- unsigned int fDAC_ROFS_2; |
- unsigned int fDAC_INOFS; |
- unsigned int fDAC_BIAS; |
- // DAC channels (USB EVAL1 (fBoardType 5) : DAC_ROFS_1,DAC_CMOFS,DAC_CALN,DAC_CALP,DAC_BIAS,DAC_TLEVEL,DAC_ONOFS) |
- // DAC channels (USB EVAL3 (fBoardType 7) : DAC_ROFS_1,DAC_CMOFS,DAC_CALN,DAC_CALP,DAC_BIAS,DAC_TLEVEL,DAC_ONOFS) |
- unsigned int fDAC_CMOFS; |
- unsigned int fDAC_CALN; |
- unsigned int fDAC_CALP; |
- unsigned int fDAC_ONOFS; |
- // DAC channels (DRS4 MEZZ1 (fBoardType 6) : DAC_ONOFS,DAC_CMOFSP,DAC_CALN,DAC_CALP,DAC_BIAS,DAC_CMOFSN,DAC_ROFS_1) |
- unsigned int fDAC_CMOFSP; |
- unsigned int fDAC_CMOFSN; |
- // DAC channels (DRS4 EVAL4 (fBoardType 8) : DAC_ONOFS,DAC_TLEVEL4,DAC_CALN,DAC_CALP,DAC_BIAS,DAC_TLEVEL1,DAC_TLEVEL2,DAC_TLEVEL3) |
- unsigned int fDAC_TLEVEL1; |
- unsigned int fDAC_TLEVEL2; |
- unsigned int fDAC_TLEVEL3; |
- unsigned int fDAC_TLEVEL4; |
- |
-protected: |
- // Fields for DRS |
- int fDRSType; |
- int fBoardType; |
- int fNumberOfChips; |
- int fNumberOfChannels; |
- int fRequiredFirmwareVersion; |
- int fFirmwareVersion; |
- int fBoardSerialNumber; |
- int fHasMultiBuffer; |
- unsigned int fTransport; |
- unsigned int fCtrlBits; |
- int fNumberOfReadoutChannels; |
- int fReadoutChannelConfig; |
- int fADCClkPhase; |
- bool fADCClkInvert; |
- double fExternalClockFrequency; |
-#ifdef HAVE_USB |
- MUSB_INTERFACE *fUsbInterface; |
-#endif |
-#ifdef HAVE_VME |
- MVME_INTERFACE *fVmeInterface; |
- mvme_addr_t fBaseAddress; |
-#endif |
- int fSlotNumber; |
- double fNominalFrequency; |
- double fTrueFrequency; |
- double fTCALFrequency; |
- double fRefClock; |
- int fMultiBuffer; |
- int fDominoMode; |
- int fDominoActive; |
- int fADCActive; |
- int fChannelConfig; |
- int fChannelCascading; |
- int fChannelDepth; |
- int fWSRLoop; |
- int fReadoutMode; |
- unsigned short fReadPointer; |
- int fNMultiBuffer; |
- int fTriggerEnable1; |
- int fTriggerEnable2; |
- int fTriggerSource; |
- int fTriggerDelay; |
- double fTriggerDelayNs; |
- int fSyncDelay; |
- int fDelayedStart; |
- int fTranspMode; |
- int fDecimation; |
- unsigned short fStopCell[4]; |
- unsigned char fStopWSR[4]; |
- unsigned short fTriggerBus; |
- double fROFS; |
- double fRange; |
- double fCommonMode; |
- int fAcalMode; |
- int fbkAcalMode; |
- double fAcalVolt; |
- double fbkAcalVolt; |
- int fTcalFreq; |
- int fbkTcalFreq; |
- int fTcalLevel; |
- int fbkTcalLevel; |
- int fTcalPhase; |
- int fTcalSource; |
- int fRefclk; |
- |
- unsigned char fWaveforms[kNumberOfChipsMax * kNumberOfChannelsMax * 2 * kNumberOfBins]; |
- |
- // Fields for Calibration |
- int fMaxChips; |
- char fCalibDirectory[1000]; |
- |
- // Fields for Response Calibration old method |
- ResponseCalibration *fResponseCalibration; |
- |
- // Fields for Calibration new method |
- bool fVoltageCalibrationValid; |
- double fCellCalibratedRange; |
- double fCellCalibratedTemperature; |
- unsigned short fCellOffset[kNumberOfChipsMax * kNumberOfChannelsMax][kNumberOfBins]; |
- unsigned short fCellOffset2[kNumberOfChipsMax * kNumberOfChannelsMax][kNumberOfBins]; |
- double fCellGain[kNumberOfChipsMax * kNumberOfChannelsMax][kNumberOfBins]; |
- |
- double fTimingCalibratedFrequency; |
- double fCellDT[kNumberOfChipsMax][kNumberOfChannelsMax][kNumberOfBins]; |
- |
- // Fields for Time Calibration |
- TimeData **fTimeData; |
- int fNumberOfTimeData; |
- |
- // General debugging flag |
- int fDebug; |
- |
- // Fields for wave transfer |
- bool fWaveTransferred[kNumberOfChipsMax * kNumberOfChannelsMax]; |
- |
- // Waveform Rotation |
- int fTriggerStartBin; // Start Bin of the trigger |
- |
-private: |
- DRSBoard(const DRSBoard &c); // not implemented |
- DRSBoard &operator=(const DRSBoard &rhs); // not implemented |
- |
-public: |
- // Public Methods |
-#ifdef HAVE_USB |
- DRSBoard(MUSB_INTERFACE * musb_interface, int usb_slot); |
-#endif |
-#ifdef HAVE_VME |
- DRSBoard(MVME_INTERFACE * mvme_interface, mvme_addr_t base_address, int slot_number); |
- |
- MVME_INTERFACE *GetVMEInterface() const { return fVmeInterface; }; |
-#endif |
- ~DRSBoard(); |
- |
- int SetBoardSerialNumber(unsigned short serialNumber); |
- int GetBoardSerialNumber() const { return fBoardSerialNumber; } |
- int HasMultiBuffer() const { return fHasMultiBuffer; } |
- int GetFirmwareVersion() const { return fFirmwareVersion; } |
- int GetRequiredFirmwareVersion() const { return fRequiredFirmwareVersion; } |
- int GetDRSType() const { return fDRSType; } |
- int GetBoardType() const { return fBoardType; } |
- int GetNumberOfChips() const { return fNumberOfChips; } |
- // channel : Flash ADC index |
- // readout channel : VME readout index |
- // input : Input on board |
- int GetNumberOfChannels() const { return fNumberOfChannels; } |
- int GetChannelDepth() const { return fChannelDepth; } |
- int GetChannelCascading() const { return fChannelCascading; } |
- inline int GetNumberOfReadoutChannels() const; |
- inline int GetWaveformBufferSize() const; |
- inline int GetNumberOfInputs() const; |
- inline int GetNumberOfCalibInputs() const; |
- inline int GetClockChannel() const; |
- inline int GetTriggerChannel() const; |
- inline int GetClockInput() const { return Channel2Input(GetClockChannel()); } |
- inline int GetTriggerInput() const { return fDRSType < 4 ? Channel2Input(GetTriggerChannel()) : -1; } |
- inline int Channel2Input(int channel) const; |
- inline int Channel2ReadoutChannel(int channel) const; |
- inline int Input2Channel(int input, int ind = 0) const; |
- inline int Input2ReadoutChannel(int input, int ind = 0) const; |
- inline int ReadoutChannel2Channel(int readout) const; |
- inline int ReadoutChannel2Input(int readout) const; |
- |
- inline bool IsCalibChannel(int ch) const; |
- inline bool IsCalibInput(int input) const; |
- int GetSlotNumber() const { return fSlotNumber; } |
- int InitFPGA(void); |
- int Write(int type, unsigned int addr, void *data, int size); |
- int Read(int type, void *data, unsigned int addr, int size); |
- int GetTransport() const { return fTransport; } |
- void RegisterTest(void); |
- int RAMTest(int flag); |
- int ChipTest(); |
- unsigned int GetCtrlReg(void); |
- unsigned short GetConfigReg(void); |
- unsigned int GetStatusReg(void); |
- void SetLED(int state); |
- int SetChannelConfig(int firstChannel, int lastChannel, int nConfigChannels); |
- void SetADCClkPhase(int phase, bool invert); |
- void SetWarmup(unsigned int ticks); |
- void SetCooldown(unsigned int ticks); |
- int GetReadoutChannelConfig() { return fReadoutChannelConfig; } |
- void SetNumberOfChannels(int nChannels); |
- int EnableTrigger(int flag1, int flag2); |
- int GetTriggerEnable(int i) { return i?fTriggerEnable2:fTriggerEnable1; } |
- int SetDelayedTrigger(int flag); |
- int SetTriggerDelayPercent(int delay); |
- int SetTriggerDelayNs(int delay); |
- int GetTriggerDelay() { return fTriggerDelay; } |
- double GetTriggerDelayNs() { return fTriggerDelayNs; } |
- int SetSyncDelay(int ticks); |
- int SetTriggerLevel(double value); |
- int SetIndividualTriggerLevel(int channel, double voltage); |
- int SetTriggerPolarity(bool negative); |
- int SetTriggerSource(int source); |
- int GetTriggerSource() { return fTriggerSource; } |
- int SetDelayedStart(int flag); |
- int SetTranspMode(int flag); |
- int SetStandbyMode(int flag); |
- int SetDecimation(int flag); |
- int GetDecimation() { return fDecimation; } |
- int IsBusy(void); |
- int IsEventAvailable(void); |
- int IsPLLLocked(void); |
- int IsLMKLocked(void); |
- int IsNewFreq(unsigned char chipIndex); |
- int SetDAC(unsigned char channel, double value); |
- int ReadDAC(unsigned char channel, double *value); |
- int GetRegulationDAC(double *value); |
- int StartDomino(); |
- int StartClearCycle(); |
- int FinishClearCycle(); |
- int Reinit(); |
- int Init(); |
- void SetDebug(int debug) { fDebug = debug; } |
- int Debug() { return fDebug; } |
- int SetDominoMode(unsigned char mode); |
- int SetDominoActive(unsigned char mode); |
- int SetReadoutMode(unsigned char mode); |
- int SoftTrigger(void); |
- int ReadFrequency(unsigned char chipIndex, double *f); |
- int SetFrequency(double freq, bool wait); |
- double VoltToFreq(double volt); |
- double FreqToVolt(double freq); |
- double GetNominalFrequency() const { return fNominalFrequency; } |
- double GetTrueFrequency(); |
- int RegulateFrequency(double freq); |
- int SetExternalClockFrequency(double frequencyMHz); |
- double GetExternalClockFrequency(); |
- int SetMultiBuffer(int flag); |
- int IsMultiBuffer() { return fMultiBuffer; } |
- void ResetMultiBuffer(void); |
- int GetMultiBufferRP(void); |
- int SetMultiBufferRP(unsigned short rp); |
- int GetMultiBufferWP(void); |
- void IncrementMultiBufferRP(void); |
- void SetVoltageOffset(double offset1, double offset2); |
- int SetInputRange(double center); |
- double GetInputRange(void) { return fRange; } |
- double GetCalibratedInputRange(void) { return fCellCalibratedRange; } |
- double GetCalibratedTemperature(void) { return fCellCalibratedTemperature; } |
- double GetCalibratedFrequency(void) { return fTimingCalibratedFrequency; } |
- int TransferWaves(int numberOfChannels = kNumberOfChipsMax * kNumberOfChannelsMax); |
- int TransferWaves(unsigned char *p, int numberOfChannels = kNumberOfChipsMax * kNumberOfChannelsMax); |
- int TransferWaves(int firstChannel, int lastChannel); |
- int TransferWaves(unsigned char *p, int firstChannel, int lastChannel); |
- int DecodeWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel, |
- unsigned short *waveform); |
- int DecodeWave(unsigned int chipIndex, unsigned char channel, unsigned short *waveform); |
- int GetWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel, short *waveform, |
- bool responseCalib = false, int triggerCell = -1, int wsr = -1, bool adjustToClock = false, |
- float threshold = 0, bool offsetCalib = true); |
- int GetWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel, float *waveform, |
- bool responseCalib = false, int triggerCell = -1, int wsr = -1, bool adjustToClock = false, |
- float threshold = 0, bool offsetCalib = true); |
- int GetWave(unsigned int chipIndex, unsigned char channel, short *waveform, bool responseCalib = false, |
- int triggerCell = -1, int wsr = -1, bool adjustToClock = false, float threshold = 0, bool offsetCalib = true); |
- int GetWave(unsigned int chipIndex, unsigned char channel, float *waveform, bool responseCalib, |
- int triggerCell = -1, int wsr = -1, bool adjustToClock = false, float threshold = 0, bool offsetCalib = true); |
- int GetWave(unsigned int chipIndex, unsigned char channel, float *waveform); |
- int GetRawWave(unsigned int chipIndex, unsigned char channel, unsigned short *waveform, bool adjustToClock = false); |
- int GetRawWave(unsigned char *waveforms,unsigned int chipIndex, unsigned char channel, |
- unsigned short *waveform, bool adjustToClock = false); |
- bool IsTimingCalibrationValid(void); |
- bool IsVoltageCalibrationValid(void) { return fVoltageCalibrationValid; } |
- int GetTime(unsigned int chipIndex, int channelIndex, double freq, int tc, float *time, bool tcalibrated=true, bool rotated=true); |
- int GetTime(unsigned int chipIndex, int channelIndex, int tc, float *time, bool tcalibrated=true, bool rotated=true); |
- int GetTimeCalibration(unsigned int chipIndex, int channelIndex, int mode, float *time, bool force=false); |
- int GetTriggerCell(unsigned int chipIndex); |
- int GetStopCell(unsigned int chipIndex); |
- unsigned char GetStopWSR(unsigned int chipIndex); |
- int GetTriggerCell(unsigned char *waveforms,unsigned int chipIndex); |
- void TestDAC(int channel); |
- void MeasureSpeed(); |
- void InteractSpeed(); |
- void MonitorFrequency(); |
- int TestShift(int n); |
- int EnableAcal(int mode, double voltage); |
- int GetAcalMode() { return fAcalMode; } |
- double GetAcalVolt() { return fAcalVolt; } |
- int EnableTcal(int freq, int level=0, int phase=0); |
- int SelectClockSource(int source); |
- int SetRefclk(int source); |
- int GetRefclk() { return fRefclk; } |
- int GetTcalFreq() { return fTcalFreq; } |
- int GetTcalLevel() { return fTcalLevel; } |
- int GetTcalPhase() { return fTcalPhase; } |
- int GetTcalSource() { return fTcalSource; } |
- int SetCalibVoltage(double value); |
- int SetCalibTiming(int t1, int t2); |
- double GetTemperature(); |
- int Is2048ModeCapable(); |
- int GetTriggerBus(); |
- unsigned int GetScaler(int channel); |
- int ReadEEPROM(unsigned short page, void *buffer, int size); |
- int WriteEEPROM(unsigned short page, void *buffer, int size); |
- bool HasCorrectFirmware(); |
- int ConfigureLMK(double sampFreq, bool freqChange, int calFreq, int calPhase); |
- |
- bool InitTimeCalibration(unsigned int chipIndex); |
- void SetCalibrationDirectory(const char *calibrationDirectoryPath); |
- void GetCalibrationDirectory(char *calibrationDirectoryPath); |
- |
- ResponseCalibration *GetResponseCalibration() const { return fResponseCalibration; } |
- |
- double GetPrecision() const { return fResponseCalibration ? fResponseCalibration->GetPrecision() : 0.1; } |
- int CalibrateWaveform(unsigned int chipIndex, unsigned char channel, unsigned short *adcWaveform, |
- short *waveform, bool responseCalib, int triggerCell, bool adjustToClock, |
- float threshold, bool offsetCalib); |
- |
- static void LinearRegression(double *x, double *y, int n, double *a, double *b); |
- |
- void ReadSingleWaveform(int nChips, int nChan, |
- unsigned short wfu[kNumberOfChipsMax][kNumberOfChannelsMax][kNumberOfBins], bool rotated); |
- int AverageWaveforms(DRSCallback *pcb, int chipIndex, int nChan, int prog1, int prog2, unsigned short *awf, int n, bool rotated); |
- int RobustAverageWaveforms(DRSCallback *pcb, int chipIndex, int nChan, int prog1, int prog2, unsigned short *awf, int n, bool rotated); |
- int CalibrateVolt(DRSCallback *pcb); |
- int AnalyzePeriod(Averager *ave, int iIter, int nIter, int channel, float wf[kNumberOfBins], int tCell, double cellDV[kNumberOfBins], double cellDT[kNumberOfBins]); |
- int AnalyzeSlope(Averager *ave, int iIter, int nIter, int channel, float wf[kNumberOfBins], int tCell, double cellDV[kNumberOfBins], double cellDT[kNumberOfBins]); |
- int CalibrateTiming(DRSCallback *pcb); |
- static void RemoveSymmetricSpikes(short **wf, int nwf, |
- short diffThreshold, int spikeWidth, |
- short maxPeakToPeak, short spikeVoltage, |
- int nTimeRegionThreshold); |
-protected: |
- // Protected Methods |
- void ConstructBoard(); |
- void ReadSerialNumber(); |
- void ReadCalibration(void); |
- |
- TimeData *GetTimeCalibration(unsigned int chipIndex, bool reinit = false); |
- |
- int GetStretchedTime(float *time, float *measurement, int numberOfMeasurements, float period); |
-}; |
- |
-int DRSBoard::GetNumberOfReadoutChannels() const |
-{ |
- return (fDRSType == 4 && fReadoutChannelConfig == 4) ? 5 : fNumberOfChannels; |
-} |
- |
-int DRSBoard::GetWaveformBufferSize() const |
-{ |
- int nbin=0; |
- if (fDRSType < 4) { |
- nbin = fNumberOfChips * fNumberOfChannels * kNumberOfBins; |
- } else { |
- if (fBoardType == 6) { |
- if (fDecimation) { |
- nbin = fNumberOfChips * (4 * kNumberOfBins + kNumberOfBins / 2); |
- } else { |
- nbin = fNumberOfChips * 5 * kNumberOfBins; |
- } |
- } else if (fBoardType == 7 || fBoardType == 8 || fBoardType == 9) |
- nbin = fNumberOfChips * fNumberOfChannels * kNumberOfBins; |
- } |
- return nbin * static_cast<int>(sizeof(short int)); |
-} |
- |
-int DRSBoard::GetNumberOfInputs() const |
-{ |
- // return number of input channels excluding clock and trigger channels. |
- if (fDRSType < 4) { |
- return fNumberOfChannels - 2; |
- } else { |
- return fNumberOfChannels / 2; |
- } |
-} |
-int DRSBoard::GetNumberOfCalibInputs() const |
-{ |
- return (fDRSType < 4) ? 2 : 1; |
-} |
-int DRSBoard::GetClockChannel() const |
-{ |
- return fDRSType < 4 ? 9 : 8; |
-} |
-int DRSBoard::GetTriggerChannel() const |
-{ |
- return fDRSType < 4 ? 8 : -1; |
-} |
- |
-int DRSBoard::Channel2Input(int channel) const |
-{ |
- return (fDRSType < 4) ? channel : channel / 2; |
-} |
-int DRSBoard::Channel2ReadoutChannel(int channel) const |
-{ |
- if (fDRSType < 4) { |
- return channel; |
- } else { |
- if (fReadoutChannelConfig == 4) { |
- return channel / 2; |
- } else { |
- return channel; |
- } |
- } |
-} |
-int DRSBoard::Input2Channel(int input, int ind) const |
-{ |
- if (fChannelCascading == 1) { |
- return (fDRSType < 4) ? input : (input * 2 + ind); |
- } else { |
- if (input == 4) { // clock |
- return 8; |
- } else { |
- return input; |
- } |
- } |
-} |
-int DRSBoard::Input2ReadoutChannel(int input, int ind) const |
-{ |
- if (fDRSType < 4) { |
- return input; |
- } else { |
- if (fReadoutChannelConfig == 4) { |
- return input; |
- } else { |
- return (input * 2 + ind); |
- } |
- } |
-} |
-int DRSBoard::ReadoutChannel2Channel(int readout) const |
-{ |
- if (fDRSType < 4) { |
- return readout; |
- } else { |
- if (fReadoutChannelConfig == 4) { |
- return readout * 2; |
- } else { |
- return readout; |
- } |
- } |
-} |
-int DRSBoard::ReadoutChannel2Input(int readout) const |
-{ |
- if (fDRSType < 4) { |
- return readout; |
- } else { |
- if (fReadoutChannelConfig == 4) { |
- return readout; |
- } else { |
- return readout / 2; |
- } |
- } |
-} |
-bool DRSBoard::IsCalibChannel(int ch) const |
-{ |
- // return if it is clock or trigger channel |
- if (fDRSType < 4) |
- return ch == GetClockChannel() || ch == GetTriggerChannel(); |
- else |
- return ch == GetClockChannel(); |
-} |
-bool DRSBoard::IsCalibInput(int input) const |
-{ |
- // return if it is clock or trigger channel |
- int ch = Input2Channel(input); |
- if (fDRSType < 4) |
- return ch == GetClockChannel() || ch == GetTriggerChannel(); |
- else |
- return ch == GetClockChannel(); |
-} |
- |
-class DRS { |
-protected: |
- // constants |
- enum { |
- kMaxNumberOfBoards = 40 |
- }; |
- |
-protected: |
- DRSBoard *fBoard[kMaxNumberOfBoards]; |
- int fNumberOfBoards; |
- char fError[256]; |
-#ifdef HAVE_VME |
- MVME_INTERFACE *fVmeInterface; |
-#endif |
- |
-private: |
- DRS(const DRS &c); // not implemented |
- DRS &operator=(const DRS &rhs); // not implemented |
- |
-public: |
- // Public Methods |
- DRS(); |
- ~DRS(); |
- |
- DRSBoard *GetBoard(int i) { return fBoard[i]; } |
- void SetBoard(int i, DRSBoard *b); |
- DRSBoard **GetBoards() { return fBoard; } |
- int GetNumberOfBoards() const { return fNumberOfBoards; } |
- bool GetError(char *str, int size); |
- void SortBoards(); |
- |
-#ifdef HAVE_VME |
- MVME_INTERFACE *GetVMEInterface() const { return fVmeInterface; }; |
-#endif |
-}; |
- |
-#endif // DRS_H |
Index: instr/drsctrl/thisroot.bat |
=================================================================== |
--- instr/drsctrl/thisroot.bat (revision 196) |
+++ instr/drsctrl/thisroot.bat (nonexistent) |
@@ -1,25 +0,0 @@ |
-@echo off |
-set MPATH=%~dp0 |
-rem set MPATH=%CD% |
- |
-cd "\" |
-FOR /D %%x in ("Program Files*") do ( |
- cd /D %%x |
- if exist "Microsoft SDKs\Windows\v7.1A\Include" set INCLUDE=%INCLUDE%;%CD%%%x\Microsoft SDKs\Windows\v7.1A\Include |
- For /D %%G in ("Microsoft Visual Studio*") do set VC=%%x\%%G |
- cd "\" |
-) |
- |
-echo call "%VC%\VC\vcvarsall.bat" x86 |
-call "%VC%\VC\vcvarsall.bat" x86 |
- |
- |
-cd "\" |
-FOR /D %%G IN ("root*") DO SET ROOTSYS=c:\%%G |
- |
-echo ROOTSYS= "%ROOTSYS%" |
-echo INCLUDE="%INCLUDE%" |
- |
-echo Visual C Development environment |
-echo nmake -f Makefile.win32 |
-cd /D "%MPATH%" |
\ No newline at end of file |
Index: instr/drsctrl/strlcpy.c |
=================================================================== |
--- instr/drsctrl/strlcpy.c (revision 196) |
+++ instr/drsctrl/strlcpy.c (nonexistent) |
@@ -1,101 +0,0 @@ |
-/********************************************************************\ |
- |
- Name: strlcpy.c |
- Created by: Stefan Ritt |
- Copyright 2000 + Stefan Ritt |
- |
- Contents: Contains strlcpy and strlcat which are versions of |
- strcpy and strcat, but which avoid buffer overflows |
- |
- |
- This file is part of MIDAS XML Library. |
- |
- MIDAS XML Library is free software: you can redistribute it and/or modify |
- it under the terms of the GNU General Public License as published by |
- the Free Software Foundation, either version 3 of the License, or |
- (at your option) any later version. |
- |
- MIDAS XML Library is distributed in the hope that it will be useful, |
- but WITHOUT ANY WARRANTY; without even the implied warranty of |
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
- GNU General Public License for more details. |
- |
- You should have received a copy of the GNU General Public License |
- along with MIDAS XML Library. If not, see <http://www.gnu.org/licenses/>. |
- |
-\********************************************************************/ |
- |
-#include <stdio.h> |
-#include <string.h> |
-#include "strlcpy.h" |
- |
-/* |
-* Copy src to string dst of size siz. At most siz-1 characters |
-* will be copied. Always NUL terminates (unless size == 0). |
-* Returns strlen(src); if retval >= siz, truncation occurred. |
-*/ |
-#ifndef STRLCPY_DEFINED |
- |
-size_t strlcpy(char *dst, const char *src, size_t size) |
-{ |
- char *d = dst; |
- const char *s = src; |
- size_t n = size; |
- |
- /* Copy as many bytes as will fit */ |
- if (n != 0 && --n != 0) { |
- do { |
- if ((*d++ = *s++) == 0) |
- break; |
- } while (--n != 0); |
- } |
- |
- /* Not enough room in dst, add NUL and traverse rest of src */ |
- if (n == 0) { |
- if (size != 0) |
- *d = '\0'; /* NUL-terminate dst */ |
- while (*s++); |
- } |
- |
- return (s - src - 1); /* count does not include NUL */ |
-} |
- |
-/*-------------------------------------------------------------------*/ |
- |
-/* |
-* Appends src to string dst of size siz (unlike strncat, siz is the |
-* full size of dst, not space left). At most siz-1 characters |
-* will be copied. Always NUL terminates (unless size <= strlen(dst)). |
-* Returns strlen(src) + MIN(size, strlen(initial dst)). |
-* If retval >= size, truncation occurred. |
-*/ |
-size_t strlcat(char *dst, const char *src, size_t size) |
-{ |
- char *d = dst; |
- const char *s = src; |
- size_t n = size; |
- size_t dlen; |
- |
- /* Find the end of dst and adjust bytes left but don't go past end */ |
- while (n-- != 0 && *d != '\0') |
- d++; |
- dlen = d - dst; |
- n = size - dlen; |
- |
- if (n == 0) |
- return (dlen + strlen(s)); |
- while (*s != '\0') { |
- if (n != 1) { |
- *d++ = *s; |
- n--; |
- } |
- s++; |
- } |
- *d = '\0'; |
- |
- return (dlen + (s - src)); /* count does not include NUL */ |
-} |
- |
-/*-------------------------------------------------------------------*/ |
- |
-#endif // STRLCPY_DEFINED |
Index: instr/drsctrl/libusb-1.0.lib |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/instr/drsctrl/libusb-1.0.lib |
Property changes: |
Deleted: svn:mime-type |
## -1 +0,0 ## |
-application/octet-stream |
\ No newline at end of property |
Index: instr/drsctrl/rb.cpp |
=================================================================== |
--- instr/drsctrl/rb.cpp (revision 196) |
+++ instr/drsctrl/rb.cpp (nonexistent) |
@@ -1,387 +0,0 @@ |
-/********************************************************************\ |
- |
- Name: rb.c |
- Created by: Stefan Ritt |
- |
- $Id: rb.cpp 21437 2014-07-30 14:13:29Z ritt $ |
- |
-\********************************************************************/ |
- |
-#include <stdio.h> |
-#ifdef OS_DARWIN |
-#include <sys/malloc.h> |
-#else |
-#include <malloc.h> |
-#endif |
-#include <string.h> |
-#include <assert.h> |
- |
-#include "rb.h" |
- |
-/********************************************************************\ |
-* * |
-* Ring buffer functions * |
-* * |
-* Provide an inter-thread buffer scheme for handling front-end * |
-* events. This code allows concurrent data acquisition, calibration * |
-* and network transfer on a multi-CPU machine. One thread reads * |
-* out the data, passes it vis the ring buffer functions * |
-* to another thread running on the other CPU, which can then * |
-* calibrate and/or send the data over the network. * |
-* * |
-\********************************************************************/ |
- |
-typedef struct { |
- unsigned char *buffer; |
- unsigned int size; |
- unsigned int max_event_size; |
- unsigned char *rp; |
- unsigned char *wp; |
- unsigned char *ep; |
-} RING_BUFFER; |
- |
-#define MAX_RING_BUFFER 100 |
-RING_BUFFER rb[MAX_RING_BUFFER]; |
- |
-volatile int _rb_nonblocking = 0; |
- |
-extern void ss_sleep(int ms); |
- |
-int rb_set_nonblocking() |
-/********************************************************************\ |
- |
- Routine: rb_set_nonblocking |
- |
- Purpose: Set all rb_get_xx to nonblocking. Needed in multi-thread |
- environments for stopping all theads without deadlock |
- |
- Input: |
- NONE |
- |
- Output: |
- NONE |
- |
- Function value: |
- RB_SUCCESS Successful completion |
- |
-\********************************************************************/ |
-{ |
- _rb_nonblocking = 1; |
- |
- return RB_SUCCESS; |
-} |
- |
-int rb_create(int size, int max_event_size, int *handle) |
-/********************************************************************\ |
- |
- Routine: rb_create |
- |
- Purpose: Create a ring buffer with a given size |
- |
- Input: |
- int size Size of ring buffer, must be larger than |
- 2*max_event_size |
- int max_event_size Maximum event size to be placed into |
- ring buffer |
- Output: |
- int *handle Handle to ring buffer |
- |
- Function value: |
- DB_SUCCESS Successful completion |
- DB_NO_MEMORY Maximum number of ring buffers exceeded |
- DB_INVALID_PARAM Invalid event size specified |
- |
-\********************************************************************/ |
-{ |
- int i; |
- |
- for (i = 0; i < MAX_RING_BUFFER; i++) |
- if (rb[i].buffer == NULL) |
- break; |
- |
- if (i == MAX_RING_BUFFER) |
- return RB_NO_MEMORY; |
- |
- if (size < max_event_size * 2) |
- return RB_INVALID_PARAM; |
- |
- memset(&rb[i], 0, sizeof(RING_BUFFER)); |
- rb[i].buffer = (unsigned char *) malloc(size); |
- assert(rb[i].buffer); |
- rb[i].size = size; |
- rb[i].max_event_size = max_event_size; |
- rb[i].rp = rb[i].buffer; |
- rb[i].wp = rb[i].buffer; |
- rb[i].ep = rb[i].buffer; |
- |
- *handle = i + 1; |
- |
- return RB_SUCCESS; |
-} |
- |
-int rb_delete(int handle) |
-/********************************************************************\ |
- |
- Routine: rb_delete |
- |
- Purpose: Delete a ring buffer |
- |
- Input: |
- none |
- Output: |
- int handle Handle to ring buffer |
- |
- Function value: |
- DB_SUCCESS Successful completion |
- |
-\********************************************************************/ |
-{ |
- if (handle < 0 || handle >= MAX_RING_BUFFER || rb[handle - 1].buffer == NULL) |
- return RB_INVALID_HANDLE; |
- |
- free(rb[handle - 1].buffer); |
- memset(&rb[handle - 1], 0, sizeof(RING_BUFFER)); |
- |
- return RB_SUCCESS; |
-} |
- |
-int rb_get_wp(int handle, void **p, int millisec) |
-/********************************************************************\ |
- |
-Routine: rb_get_wp |
- |
- Purpose: Retrieve write pointer where new data can be written |
- |
- Input: |
- int handle Ring buffer handle |
- int millisec Optional timeout in milliseconds if |
- buffer is full. Zero to not wait at |
- all (non-blocking) |
- |
- Output: |
- char **p Write pointer |
- |
- Function value: |
- DB_SUCCESS Successful completion |
- |
-\********************************************************************/ |
-{ |
- int h, i; |
- unsigned char *rp; |
- |
- if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL) |
- return RB_INVALID_HANDLE; |
- |
- h = handle - 1; |
- |
- for (i = 0; i <= millisec / 10; i++) { |
- |
- rp = rb[h].rp; // keep local copy, rb[h].rp might be changed by other thread |
- |
- /* check if enough size for wp >= rp without wrap-around */ |
- if (rb[h].wp >= rp |
- && rb[h].wp + rb[h].max_event_size <= rb[h].buffer + rb[h].size - rb[h].max_event_size) { |
- *p = rb[h].wp; |
- return RB_SUCCESS; |
- } |
- |
- /* check if enough size for wp >= rp with wrap-around */ |
- if (rb[h].wp >= rp && rb[h].wp + rb[h].max_event_size > rb[h].buffer + rb[h].size - rb[h].max_event_size && rb[h].rp > rb[h].buffer) { // next increment of wp wraps around, so need space at beginning |
- *p = rb[h].wp; |
- return RB_SUCCESS; |
- } |
- |
- /* check if enough size for wp < rp */ |
- if (rb[h].wp < rp && rb[h].wp + rb[h].max_event_size < rp) { |
- *p = rb[h].wp; |
- return RB_SUCCESS; |
- } |
- |
- if (millisec == 0) |
- return RB_TIMEOUT; |
- |
- if (_rb_nonblocking) |
- return RB_TIMEOUT; |
- |
- /* wait one time slice */ |
- ss_sleep(10); |
- } |
- |
- return RB_TIMEOUT; |
-} |
- |
-int rb_increment_wp(int handle, int size) |
-/********************************************************************\ |
- |
- Routine: rb_increment_wp |
- |
- Purpose: Increment current write pointer, making the data at |
- the write pointer available to the receiving thread |
- |
- Input: |
- int handle Ring buffer handle |
- int size Number of bytes placed at the WP |
- |
- Output: |
- NONE |
- |
- Function value: |
- RB_SUCCESS Successful completion |
- RB_INVALID_PARAM Event size too large or invalid handle |
-\********************************************************************/ |
-{ |
- int h; |
- unsigned char *new_wp; |
- |
- if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL) |
- return RB_INVALID_HANDLE; |
- |
- h = handle - 1; |
- |
- if ((unsigned int) size > rb[h].max_event_size) |
- return RB_INVALID_PARAM; |
- |
- new_wp = rb[h].wp + size; |
- |
- /* wrap around wp if not enough space */ |
- if (new_wp > rb[h].buffer + rb[h].size - rb[h].max_event_size) { |
- rb[h].ep = new_wp; |
- new_wp = rb[h].buffer; |
- assert(rb[h].rp != rb[h].buffer); |
- } |
- |
- rb[h].wp = new_wp; |
- |
- return RB_SUCCESS; |
-} |
- |
-int rb_get_rp(int handle, void **p, int millisec) |
-/********************************************************************\ |
- |
- Routine: rb_get_rp |
- |
- Purpose: Obtain the current read pointer at which new data is |
- available with optional timeout |
- |
- Input: |
- int handle Ring buffer handle |
- int millisec Optional timeout in milliseconds if |
- buffer is full. Zero to not wait at |
- all (non-blocking) |
- |
- Output: |
- char **p Address of pointer pointing to newly |
- available data. If p == NULL, only |
- return status. |
- |
- Function value: |
- RB_SUCCESS Successful completion |
- |
-\********************************************************************/ |
-{ |
- int i, h; |
- |
- if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL) |
- return RB_INVALID_HANDLE; |
- |
- h = handle - 1; |
- |
- for (i = 0; i <= millisec / 10; i++) { |
- |
- if (rb[h].wp != rb[h].rp) { |
- if (p != NULL) |
- *p = rb[handle - 1].rp; |
- return RB_SUCCESS; |
- } |
- |
- if (millisec == 0) |
- return RB_TIMEOUT; |
- |
- if (_rb_nonblocking) |
- return RB_TIMEOUT; |
- |
- /* wait one time slice */ |
- ss_sleep(10); |
- } |
- |
- return RB_TIMEOUT; |
-} |
- |
-int rb_increment_rp(int handle, int size) |
-/********************************************************************\ |
- |
- Routine: rb_increment_rp |
- |
- Purpose: Increment current read pointer, freeing up space for |
- the writing thread. |
- |
- Input: |
- int handle Ring buffer handle |
- int size Number of bytes to free up at current |
- read pointer |
- |
- Output: |
- NONE |
- |
- Function value: |
- RB_SUCCESS Successful completion |
- RB_INVALID_PARAM Event size too large or invalid handle |
- |
-\********************************************************************/ |
-{ |
- int h; |
- |
- unsigned char *new_rp; |
- |
- if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL) |
- return RB_INVALID_HANDLE; |
- |
- h = handle - 1; |
- |
- if ((unsigned int) size > rb[h].max_event_size) |
- return RB_INVALID_PARAM; |
- |
- new_rp = rb[h].rp + size; |
- |
- /* wrap around if not enough space left */ |
- if (new_rp + rb[h].max_event_size > rb[h].buffer + rb[h].size) |
- new_rp = rb[h].buffer; |
- |
- rb[handle - 1].rp = new_rp; |
- |
- return RB_SUCCESS; |
-} |
- |
-int rb_get_buffer_level(int handle, int *n_bytes) |
-/********************************************************************\ |
- |
- Routine: rb_get_buffer_level |
- |
- Purpose: Return number of bytes in a ring buffer |
- |
- Input: |
- int handle Handle of the buffer to get the info |
- |
- Output: |
- int *n_bytes Number of bytes in buffer |
- |
- Function value: |
- RB_SUCCESS Successful completion |
- RB_INVALID_HANDLE Buffer handle is invalid |
- |
-\********************************************************************/ |
-{ |
- int h; |
- |
- if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL) |
- return RB_INVALID_HANDLE; |
- |
- h = handle - 1; |
- |
- if (rb[h].wp >= rb[h].rp) |
- *n_bytes = rb[h].wp - rb[h].rp; |
- else |
- *n_bytes = rb[h].ep - rb[h].rp + rb[h].wp - rb[h].buffer; |
- |
- return RB_SUCCESS; |
-} |
Index: instr/drsctrl/readdata.cpp |
=================================================================== |
--- instr/drsctrl/readdata.cpp (revision 196) |
+++ instr/drsctrl/readdata.cpp (nonexistent) |
@@ -1 +0,0 @@ |
- |
Index: instr/drsctrl/strlcpy.h |
=================================================================== |
--- instr/drsctrl/strlcpy.h (revision 196) |
+++ instr/drsctrl/strlcpy.h (nonexistent) |
@@ -1,55 +0,0 @@ |
-/********************************************************************\ |
- |
- Name: strlcpy.h |
- Created by: Stefan Ritt |
- Copyright 2000 + Stefan Ritt |
- |
- Contents: Header file for strlcpy.c |
- |
- This file is part of MIDAS XML Library. |
- |
- MIDAS XML Library is free software: you can redistribute it and/or modify |
- it under the terms of the GNU General Public License as published by |
- the Free Software Foundation, either version 3 of the License, or |
- (at your option) any later version. |
- |
- MIDAS XML Library is distributed in the hope that it will be useful, |
- but WITHOUT ANY WARRANTY; without even the implied warranty of |
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
- GNU General Public License for more details. |
- |
- You should have received a copy of the GNU General Public License |
- along with MIDAS XML Library. If not, see <http://www.gnu.org/licenses/>. |
- |
-\********************************************************************/ |
- |
-#ifndef _STRLCPY_H_ |
-#define _STRLCPY_H_ |
- |
-// some version of gcc have a built-in strlcpy |
-#ifdef strlcpy |
-#define STRLCPY_DEFINED |
-#endif |
- |
-#ifdef __cplusplus |
-extern "C" { |
-#endif |
- |
-#ifndef EXPRT |
-#if defined(EXPORT_DLL) |
-#define EXPRT __declspec(dllexport) |
-#else |
-#define EXPRT |
-#endif |
-#endif |
- |
-#ifndef STRLCPY_DEFINED |
-size_t EXPRT strlcpy(char *dst, const char *src, size_t size); |
-size_t EXPRT strlcat(char *dst, const char *src, size_t size); |
-#endif |
- |
-#ifdef __cplusplus |
-} |
-#endif |
- |
-#endif /*_STRLCPY_H_ */ |
Index: instr/drsctrl/drscl.cpp |
=================================================================== |
--- instr/drsctrl/drscl.cpp (revision 196) |
+++ instr/drsctrl/drscl.cpp (nonexistent) |
@@ -1,1647 +0,0 @@ |
-/********************************************************************\ |
- |
- Name: drscl.cpp |
- Created by: Stefan Ritt |
- |
- Contents: Command line interface to DRS chip via USB and VME |
- |
- $Id: drscl.cpp 21435 2014-07-30 13:02:31Z ritt $ |
- |
-\********************************************************************/ |
- |
-#include <math.h> |
- |
-#ifdef _MSC_VER |
- |
-#include <windows.h> |
-#include <conio.h> |
-#include <io.h> |
-#include <direct.h> |
- |
-#define DIR_SEPARATOR '\\' |
- |
-#elif defined(OS_LINUX) || defined(OS_DARWIN) |
- |
-#define O_BINARY 0 |
- |
-#include <unistd.h> |
-#include <ctype.h> |
-#include <sys/ioctl.h> |
-#include <errno.h> |
- |
-#define DIR_SEPARATOR '/' |
- |
-#endif |
- |
-#include <stdio.h> |
-#include <string.h> |
-#include <stdlib.h> |
-#include <fcntl.h> |
-#include <time.h> |
-#include <sys/stat.h> |
-#include <assert.h> |
- |
-#include "strlcpy.h" |
-#include "DRS.h" |
-#ifdef HAVE_VME |
-#include "ace.h" |
-#endif |
- |
-const char *drscl_svn_revision = "$Id: drscl.cpp 21435 2014-07-30 13:02:31Z ritt $"; |
- |
-void print_help(); |
-void clear_screen(); |
-int match(const char *str, const char *cmd); |
-void cmd_loop(); |
- |
-#if defined(OS_LINUX) || defined(OS_DARWIN) |
-#define getch() getchar() |
-#define Sleep(x) usleep(x*1000) |
-#endif |
- |
-#ifdef _MSC_VER |
-#include <conio.h> |
-#define drs_kbhit() kbhit() |
-#endif |
- |
-void print_help() |
-{ |
- puts("Available commands:\n"); |
- puts("active <0|1> Set domino active mode on (1) or off (0)"); |
- puts("board <i>|<i1> <i2>|all Address individual board/range/all boards"); |
- puts("calib [dir] Response Calibration. Use dir=\"area\" for MEG"); |
- puts("chn [n] Set number of channels: 8, 4, 2, 1"); |
- puts("ct Chip Test"); |
- puts("del <0|1> Switch delayed start on/off"); |
- puts("dir Show CF directory"); |
- puts("dmode <0|1> Set Domino mode 0=single, 1=cont."); |
- puts("et EEPROM test"); |
- puts("exit Exit program"); |
- puts("freq <ghz> [0|1] Set frequency of board [without/with] regulation"); |
- puts("info Show information about board"); |
- puts("init Initialize board"); |
- puts("led <0|1> Turn LED on (1) or off (0)"); |
- puts("lock [0|1] Display lock status [without/with] restart"); |
- puts("multi [0|1] Turn multi-buffer mode on/off"); |
- puts("offset <voltage> Set offset voltage"); |
- puts("phase <value> [0|1] Set ADC clock phase and inversion"); |
- puts("quit Exit program"); |
- puts("ram Test speed to FPGA RAM"); |
- puts("range <center> Change input range to <center>+=0.5V"); |
- puts("read <chn> [0|1] [file] Read waveform to [file], chn=0..19 [with] calibration"); |
- puts("refclk [0|1] Use FPGA ref. clk (0) or ext. P2 ref. clk (1)"); |
- puts("reg Register test"); |
- puts("serial <number> Set serial number of board"); |
- puts("scan Scan for boards"); |
- puts("standby <0|1> Turn standby mode on (1) or off (0)"); |
- puts("start Start domino wave"); |
- puts("stop Issue soft trigger"); |
- puts("tcout [file] [idx_offset] Print time calibration of DRS4, or write it onto [file]"); |
- puts("tcs <0|1> Timing calibration signal on (1) or off (0)"); |
- puts("tcalib [freq] Timing Calibration"); |
- puts("tlevel <voltage> Set trigger level in Volts"); |
- puts("trans <0|1> Set transparent mode on (1) or off (0)"); |
- puts("trig <0|1> Hardware trigger on (1) or off (0)"); |
- puts("upload <file> Upload ACE file to CF"); |
- puts("volt off|<voltage> Turn calibration voltage on/off"); |
- |
- puts(""); |
-} |
- |
-/*------------------------------------------------------------------*/ |
- |
-void clear_screen() |
-{ |
-#ifdef _MSC_VER |
- |
- HANDLE hConsole; |
- COORD coordScreen = { 0, 0 }; /* here's where we'll home the cursor */ |
- BOOL bSuccess; |
- DWORD cCharsWritten; |
- CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */ |
- DWORD dwConSize; /* number of character cells in the current buffer */ |
- |
- hConsole = GetStdHandle(STD_OUTPUT_HANDLE); |
- |
- /* get the number of character cells in the current buffer */ |
- bSuccess = GetConsoleScreenBufferInfo(hConsole, &csbi); |
- dwConSize = csbi.dwSize.X * csbi.dwSize.Y; |
- |
- /* fill the entire screen with blanks */ |
- bSuccess = FillConsoleOutputCharacter(hConsole, (TCHAR) ' ', dwConSize, coordScreen, &cCharsWritten); |
- |
- /* put the cursor at (0, 0) */ |
- bSuccess = SetConsoleCursorPosition(hConsole, coordScreen); |
- return; |
- |
-#else |
- printf("\033[2J"); |
-#endif |
-} |
- |
-/*------------------------------------------------------------------*/ |
- |
-int match(const char *str, const char *cmd) |
-{ |
- int i; |
- |
- if (str[0] == '\r' || str[0] == '\n') |
- return 0; |
- |
- for (i = 0; i < (int) strlen(str); i++) { |
- if (toupper(str[i]) != toupper(cmd[i]) && str[i] != '\r' && str[i] != '\n') |
- return 0; |
- } |
- |
- return 1; |
-} |
- |
-/*------------------------------------------------------------------*/ |
- |
-class ProgressBar : public DRSCallback |
-{ |
-public: |
- void Progress(int prog); |
-}; |
- |
-void ProgressBar::Progress(int prog) |
-{ |
- if (prog == 0) |
- printf("[--------------------------------------------------]\r"); |
- printf("["); |
- for (int i=0 ; i<prog/2 ; i++) |
- printf("="); |
- printf("\r"); |
- fflush(stdout); |
-} |
- |
-/*------------------------------------------------------------------*/ |
- |
-void cmd_loop() |
-{ |
- int i, j, idx, i_start, i_end, nparam, calib, status, debug, cascading, |
- ext_refclk; |
- char str[256], dir[256], line[256], file_name[256], param[10][100], *pc; |
- double freq, triggerfreq, range; |
- FILE *f = NULL; |
- DRS *drs; |
- DRSBoard *b; |
-#ifdef HAVE_VME |
- ACE ace; |
-#endif |
- static char bar[] = {'\\', '|', '/', '-'}; |
- |
- /* do initial scan */ |
- drs = new DRS(); |
- if (drs->GetError(str, sizeof(str))) |
- printf("%s", str); |
- |
- for (i=0 ; i<drs->GetNumberOfBoards() ; i++) { |
- b = drs->GetBoard(i); |
-#ifdef HAVE_VME |
- if (b->GetTransport() != 1) |
- printf("Found DRS%d board %2d on USB, serial #%04d, firmware revision %5d\n", |
- b->GetDRSType(), i, b->GetBoardSerialNumber(), b->GetFirmwareVersion()); |
-#else |
- printf("Found DRS%d board %2d on USB, serial #%04d, firmware revision %5d\n", |
- b->GetDRSType(), i, b->GetBoardSerialNumber(), b->GetFirmwareVersion()); |
-#endif |
- } |
- |
- if (drs->GetNumberOfBoards()) { |
- i_start = 0; |
- i_end = 1; |
- b = drs->GetBoard(0); |
- } |
- else { |
- printf("No DRS Boards found\n"); |
- i_start = i_end = 0; |
- b = NULL; |
- } |
- |
- puts(""); |
- |
- do { |
- /* print prompt */ |
- if (i_start == i_end-1) |
- printf("B%d> ", i_start); |
- else if (i_start == 0 && i_end == 0) |
- printf("> "); |
- else |
- printf("B%d-%d> ", i_start, i_end-1); |
- memset(line, 0, sizeof(line)); |
- fgets(line, sizeof(line), stdin); |
- /* strip \r\n */ |
- while (strpbrk(line,"\n\r")) |
- *strpbrk(line,"\n\r") = 0; |
- |
- /* analyze line */ |
- nparam = 0; |
- pc = line; |
- while (*pc == ' ') |
- pc++; |
- |
- memset(param, 0, sizeof(param)); |
- do { |
- if (*pc == '"') { |
- pc++; |
- for (i = 0; *pc && *pc != '"'; i++) |
- param[nparam][i] = *pc++; |
- if (*pc) |
- pc++; |
- } else if (*pc == '\'') { |
- pc++; |
- for (i = 0; *pc && *pc != '\''; i++) |
- param[nparam][i] = *pc++; |
- if (*pc) |
- pc++; |
- } else if (*pc == '`') { |
- pc++; |
- for (i = 0; *pc && *pc != '`'; i++) |
- param[nparam][i] = *pc++; |
- if (*pc) |
- pc++; |
- } else |
- for (i = 0; *pc && *pc != ' '; i++) |
- param[nparam][i] = *pc++; |
- param[nparam][i] = 0; |
- while (*pc == ' ' || *pc == '\r' || *pc == '\n') |
- pc++; |
- nparam++; |
- } while (*pc); |
- |
- if (param[0][0] == 0) { |
- } |
- |
- /* help ---------- */ |
- else if ((param[0][0] == 'h' && param[0][1] == 'e') || param[0][0] == '?') |
- print_help(); |
- |
- /* scan ---------- */ |
- else if (match(param[0], "scan")) { |
- j = 0; |
- |
- do { |
- delete drs; |
- drs = new DRS(); |
- |
- for (i=0 ; i<drs->GetNumberOfBoards() ; i++) { |
- b = drs->GetBoard(i); |
-#ifdef HAVE_VME |
- if (b->GetTransport() != 1) |
- printf("Found DRS%d board %2d on USB, serial #%04d, firmware revision %5d\n", |
- b->GetDRSType(), i, b->GetBoardSerialNumber(), b->GetFirmwareVersion()); |
-#else |
- printf("Found DRS%d board %2d on USB, serial #%04d, firmware revision %5d\n", |
- b->GetDRSType(), i, b->GetBoardSerialNumber(), b->GetFirmwareVersion()); |
-#endif |
- } |
- |
- if (drs_kbhit()) |
- break; |
- |
- if (param[1][0] == 'r') { |
- printf("%c\r", bar[j]); |
- fflush(stdout); |
- j = (j+1) % 4; |
- Sleep(1000); |
- } |
- |
- } while (param[1][0] == 'r'); |
- |
- while (drs_kbhit()) |
- getch(); |
- |
- if (drs->GetNumberOfBoards()) { |
- i_start = 0; |
- i_end = 1; |
- b = drs->GetBoard(0); |
- } else { |
- printf("No DRS Boards found\n"); |
- i_start = i_end = 0; |
- b = NULL; |
- } |
- } |
- |
- /* address board ---------- */ |
- else if (match(param[0], "board")) { |
- if (param[1][0] == 'a') { |
- i_start = 0; |
- i_end = drs->GetNumberOfBoards(); |
- b = drs->GetBoard(0); |
- } else if (param[2][0] && atoi(param[2]) > 0 && atoi(param[2]) < drs->GetNumberOfBoards()) { |
- i_start = atoi(param[1]); |
- i_end = atoi(param[2]) + 1; |
- b = drs->GetBoard(i_start); |
- } else if (atoi(param[1]) >= 0 && atoi(param[1]) < drs->GetNumberOfBoards()) { |
- i_start = atoi(param[1]); |
- i_end = i_start + 1; |
- b = drs->GetBoard(i_start); |
- } else |
- printf("Board #%d does not exist\n", atoi(param[1])); |
- } |
- |
- /* info ---------- */ |
- else if (match(param[0], "info")) { |
- for (idx=i_start ; idx<i_end ; idx++) { |
- b = drs->GetBoard(idx); |
- printf("==============================\n"); |
- printf("Mezz. Board index: %d\n", idx); |
-#ifdef HAVE_VME |
- if (b->GetTransport() == TR_VME) { |
- printf("Slot: %d", (b->GetSlotNumber() >> 1)+2); |
- if ((b->GetSlotNumber() & 1) == 0) |
- printf(" upper\n"); |
- else |
- printf(" lower\n"); |
- } |
-#endif |
- printf("DRS type: DRS%d\n", b->GetDRSType()); |
- printf("Board type: %d\n", b->GetBoardType()); |
- printf("Serial number: %04d\n", b->GetBoardSerialNumber()); |
- printf("Firmware revision: %d\n", b->GetFirmwareVersion()); |
- printf("Temperature: %1.1lf C\n", b->GetTemperature()); |
- if (b->GetDRSType() == 4) { |
- printf("Input range: %1.2lgV...%1.2lgV\n", |
- b->GetInputRange()-0.5, b->GetInputRange()+0.5); |
- printf("Calibrated range: %1.2lgV...%1.2lgV\n", b->GetCalibratedInputRange()-0.5, |
- b->GetCalibratedInputRange()+0.5); |
- printf("Calibrated frequency: %1.3lf GHz\n", b->GetCalibratedFrequency()); |
- |
- if (b->GetTransport() == TR_VME) { |
- printf("Multi Buffer WP: %d\n", b->GetMultiBufferWP()); |
- printf("Multi Buffer RP: %d\n", b->GetMultiBufferRP()); |
- } |
- } |
- |
- printf("Status reg.: %08X\n", b->GetStatusReg()); |
- if (b->GetStatusReg() & BIT_RUNNING) |
- puts(" Domino wave running"); |
- if (b->GetDRSType() == 4) { |
- if (b->GetBoardType() == 5) { |
- if (b->GetStatusReg() & BIT_PLL_LOCKED0) |
- puts(" PLL locked"); |
- } else if (b->GetBoardType() == 6) { |
- i = 0; |
- if (b->GetStatusReg() & BIT_PLL_LOCKED0) i++; |
- if (b->GetStatusReg() & BIT_PLL_LOCKED1) i++; |
- if (b->GetStatusReg() & BIT_PLL_LOCKED2) i++; |
- if (b->GetStatusReg() & BIT_PLL_LOCKED3) i++; |
- if (i == 4) |
- puts(" All PLLs locked"); |
- else if (i == 0) |
- puts(" No PLL locked"); |
- else |
- printf(" %d PLLs locked\n", i); |
- if (b->GetStatusReg() & BIT_LMK_LOCKED) |
- puts(" LMK PLL locked"); |
- } |
- } else { |
- if (b->GetStatusReg() & BIT_NEW_FREQ1) |
- puts(" New Freq1 ready"); |
- if (b->GetStatusReg() & BIT_NEW_FREQ2) |
- puts(" New Freq2 ready"); |
- } |
- |
- printf("Control reg.: %08X\n", b->GetCtrlReg()); |
- if (b->GetCtrlReg() & BIT_MULTI_BUFFER) |
- puts(" Multi-buffering enabled"); |
- if (b->GetDRSType() == 4) { |
- if (b->GetConfigReg() & BIT_CONFIG_DMODE) |
- puts(" DMODE circular"); |
- else |
- puts(" DMODE single shot"); |
- } else { |
- if (b->GetCtrlReg() & BIT_DMODE) |
- puts(" DMODE circular"); |
- else |
- puts(" DMODE single shot"); |
- } |
- if (b->GetCtrlReg() & BIT_LED) |
- puts(" LED"); |
- if (b->GetCtrlReg() & BIT_TCAL_EN) |
- puts(" TCAL enabled"); |
- if (b->GetDRSType() == 4) { |
- if (b->GetCtrlReg() & BIT_TRANSP_MODE) |
- puts(" TRANSP_MODE enabled"); |
- } else { |
- if (b->GetCtrlReg() & BIT_FREQ_AUTO_ADJ) |
- puts(" FREQ_AUTO_ADJ enabled"); |
- } |
- if (b->GetCtrlReg() & BIT_ENABLE_TRIGGER1) |
- puts(" Hardware trigger enabled"); |
- if (b->GetDRSType() == 4) { |
- if (b->GetCtrlReg() & BIT_READOUT_MODE) |
- puts(" Readout from stop"); |
- if (b->GetCtrlReg() & BIT_ENABLE_TRIGGER2) |
- puts(" Internal trigger enabled"); |
- } else { |
- if (b->GetCtrlReg() & BIT_LONG_START_PULSE) |
- puts(" LONG_START_PULSE"); |
- } |
- if (b->GetCtrlReg() & BIT_DELAYED_START) |
- puts(" DELAYED_START"); |
- if (b->GetCtrlReg() & BIT_ACAL_EN) |
- puts(" ACAL enabled"); |
- if (b->GetDRSType() < 4) |
- if (b->GetCtrlReg() & BIT_TRIGGER_DELAYED) |
- puts(" DELAYED_TRIGGER selected"); |
- if (b->GetBoardType() != 5) |
- printf("Trigger bus: %08X\n", b->GetTriggerBus()); |
- if (b->GetDRSType() == 4) { |
- if (b->GetRefclk() == 1) { |
- if (b->IsPLLLocked() && b->IsLMKLocked()) { |
- b->ReadFrequency(0, &freq); |
- printf("Frequency: %1.3lf GHz\n", freq); |
- } else { |
- if (!b->IsPLLLocked()) |
- printf("Frequency: PLL not locked\n"); |
- else |
- printf("Frequency: LMK chip not locked\n"); |
- } |
- } else { |
- if (b->IsPLLLocked()) { |
- b->ReadFrequency(0, &freq); |
- printf("Frequency: %1.3lf GHz\n", freq); |
- } else { |
- printf("Frequency: PLL not locked\n"); |
- } |
- } |
- } else { |
- if (b->IsBusy()) { |
- b->ReadFrequency(0, &freq); |
- printf("Frequency0: %1.4lf GHz\n", freq); |
- b->ReadFrequency(1, &freq); |
- printf("Frequency1: %1.4lf GHz\n", freq); |
- } else |
- puts("Domino wave stopped"); |
- } |
- } |
- } |
- |
- /* init ---------- */ |
- else if (match(param[0], "init")) { |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- b->Init(); |
- } |
- } |
- |
- /* set led ---------- */ |
- else if (match(param[0], "led")) { |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- if (atoi(param[1])) |
- b->SetLED(1); |
- else |
- b->SetLED(0); |
- } |
- } |
- |
- /* set multi buffer mode ---------- */ |
- else if (match(param[0], "multi")) { |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- if (atoi(param[1])) |
- b->SetMultiBuffer(1); |
- else |
- b->SetMultiBuffer(0); |
- } |
- } |
- |
- /* lock status ---------- */ |
- else if (match(param[0], "lock")) { |
- int slot, found, restart; |
- |
- restart = atoi(param[1]); |
- |
- // select external reference clock |
- for (i=0 ; i<drs->GetNumberOfBoards() ; i++) { |
- b = drs->GetBoard(i); |
- b->SetRefclk(1); |
- b->SetFrequency(b->GetNominalFrequency(), true); |
- } |
- |
- // loop until keyboard hit |
- do { |
- clear_screen(); |
- printf(" 1 1 1 1 1 1 1 1 1 1 2 2\n"); |
- printf("2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\n\n"); |
- |
- // upper slots |
- for (slot = 2 ; slot<22 ; slot++) { |
- found = 0; |
- for (i=0 ; i<drs->GetNumberOfBoards() ; i++) { |
- b = drs->GetBoard(i); |
- if ((b->GetSlotNumber() & 1) == 0 && (b->GetSlotNumber() >> 1)+2 == slot) { |
- found = 1; |
- if (b->IsLMKLocked()) |
- printf("O "); |
- else |
- printf("- "); |
- } |
- } |
- if (!found) |
- printf(" "); |
- } |
- printf("\n"); |
- |
- // lower slots |
- for (slot = 2 ; slot<22 ; slot++) { |
- found = 0; |
- for (i=0 ; i<drs->GetNumberOfBoards() ; i++) { |
- b = drs->GetBoard(i); |
- if ((b->GetSlotNumber() & 1) == 1 && (b->GetSlotNumber() >> 1)+2 == slot) { |
- found = 1; |
- if (b->IsLMKLocked()) |
- printf("O "); |
- else |
- printf("- "); |
- } |
- } |
- if (!found) |
- printf(" "); |
- } |
- printf("\n"); |
- |
- if (restart) { |
- for (i=0 ; i<drs->GetNumberOfBoards() ; i++) { |
- b = drs->GetBoard(i); |
- b->SetFrequency(b->GetNominalFrequency(), true); |
- } |
- } |
- |
- Sleep(300); |
- |
- } while (!drs_kbhit()); |
- puts(""); |
- while (drs_kbhit()) |
- getch(); |
- } |
- |
- /* start domino wave ---------- */ |
- else if (match(param[0], "start")) { |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- b->StartDomino(); |
- b->ReadFrequency(0, &freq); |
- for (j=0 ; j<10 ; j++) |
- if (b->GetDRSType() != 4 || b->IsPLLLocked()) |
- break; |
- if (j == 10) |
- printf("Domino wave started but PLL did not lock!\n"); |
- else |
- printf("Domino wave started at %1.3lf GHz\n", freq); |
- } |
- } |
- |
- /* issue soft trigger ---------- */ |
- else if (match(param[0], "stop")) { |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- b->SoftTrigger(); |
- } |
- } |
- |
- /* set serial ---------- */ |
- else if (match(param[0], "serial")) { |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- if (param[1][0] == 0) { |
- printf("Serial number: "); |
- fgets(str, sizeof(str), stdin); |
- } else |
- strlcpy(str, param[1], sizeof(str)); |
- |
- if (!b->SetBoardSerialNumber(atoi(str))) |
- printf("Board EEPROM is write protected\n"); |
- else |
- printf("Serial number successfully changed\n"); |
- } |
- } |
- |
- /* eeprom test ---------- */ |
- else if (match(param[0], "et")) { |
- unsigned short buf[16384]; |
- unsigned short rbuf[16384]; |
- int n_error; |
- |
- do { |
- for (i=0 ; i<16384 ; i++) |
- buf[i] = rand(); |
- b->WriteEEPROM(1, buf, sizeof(buf)); |
- memset(rbuf, 0, sizeof(rbuf)); |
- b->Write(T_RAM, 0, rbuf, sizeof(rbuf)); |
- b->ReadEEPROM(1, rbuf, sizeof(rbuf)); |
- for (i=n_error=0 ; i<16384 ; i++) |
- if (buf[i] != rbuf[i]) { |
- printf("%04X %04X - %04X\n", i, buf[i], rbuf[i]); |
- n_error++; |
- } |
- |
- printf("32 kb written, %d errors\n", n_error); |
- } while (!drs_kbhit()); |
- |
- while (drs_kbhit()) |
- getch(); |
- } |
- |
- /* set frequency ---------- */ |
- else if (match(param[0], "freq")) { |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- if (param[1][0] == 0) { |
- printf("Frequency: "); |
- fgets(str, sizeof(str), stdin); |
- } else |
- strlcpy(str, param[1], sizeof(str)); |
- |
- b->SetDebug(1); |
- |
- if (param[2][0] && atoi(param[2])) |
- b->RegulateFrequency(atof(str)); |
- else |
- b->SetFrequency(atof(str), true); |
- } |
- } |
- |
- /* set calibration voltage ---------- */ |
- else if (match(param[0], "volt")) { |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- if (param[1][0] == 0) { |
- printf("Voltage or \"off\": "); |
- fgets(str, sizeof(str), stdin); |
- } else |
- strlcpy(str, param[1], sizeof(str)); |
- |
- if (str[0] == 'o') { |
- b->EnableAcal(0, 0); |
- puts("Calibration voltage turned off"); |
- } else { |
- b->EnableAcal(1, atof(str)); |
- printf("Voltage set to %1.3lf Volt\n", atof(str)); |
- } |
- } |
- } |
- |
- /* set channel configuration ---------- */ |
- else if (match(param[0], "chn")) { |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- if (param[1][0] == 0) { |
- printf("Number of channels (8,4,2,1): "); |
- fgets(str, sizeof(str), stdin); |
- } else |
- strlcpy(str, param[1], sizeof(str)); |
- |
- if (b->SetChannelConfig(0, 8, atoi(str))) |
- printf("DRS4 configured for %d channels\n", atoi(str)); |
- } |
- } |
- |
- /* set trigger level ---------- */ |
- else if (match(param[0], "tlevel")) { |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- if (param[1][0] == 0) { |
- printf("Voltage: "); |
- fgets(str, sizeof(str), stdin); |
- } else |
- strlcpy(str, param[1], sizeof(str)); |
- |
- b->SetTriggerLevel(atof(str)); |
- printf("Trigger level set to %1.3lf Volt\n", atof(str)); |
- } |
- } |
- |
- /* trigger on/off ---------- */ |
- else if (match(param[0], "trig")) { |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- b->EnableTrigger(atoi(param[1]), 0); |
- if (atoi(param[1]) == 1) { |
- puts("Hardware fast trigger is on"); |
- } else if (atoi(param[1]) == 2) { |
- puts("Hardware slow trigger is on"); |
- } else { |
- puts("Hardware trigger is off"); |
- } |
- } |
- } |
- |
- /* timing calibration signal on/off ---------- */ |
- else if (match(param[0], "tcs")) { |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- b->EnableTcal(atoi(param[1]), 0, 0); |
- b->SelectClockSource(0); |
- if (atoi(param[1])) |
- puts("Timing calibration signal is on"); |
- else |
- puts("Timing calibration signal is off"); |
- } |
- } |
- |
- /* timing calibration signal on/off ---------- */ |
- else if (match(param[0], "refclk")) { |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- b->SetRefclk(atoi(param[1])); |
- // re-set frequency since LMK configuration needs to be changed |
- b->SetFrequency(b->GetNominalFrequency(), true); |
- if (atoi(param[1])) |
- puts("Refclock set to external through P2"); |
- else |
- puts("Refclock set to internal (FPGA)"); |
- } |
- } |
- |
- /* domino mode 0/1 ---------- */ |
- else if (match(param[0], "dmode")) { |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- if (atoi(param[1]) == 1) { |
- b->SetDominoMode(1); |
- puts("Domino mode switched to cyclic"); |
- } else { |
- b->SetDominoMode(0); |
- puts("Domino mode switched to single shot"); |
- } |
- } |
- } |
- |
- /* active mode 0/1 ---------- */ |
- else if (match(param[0], "active")) { |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- if (atoi(param[1]) == 1) { |
- b->SetDominoActive(1); |
- puts("Domino wave active during readout"); |
- } else { |
- b->SetDominoMode(0); |
- puts("Domino wave stopped during readout"); |
- } |
- } |
- } |
- |
- /* delayed start on/off ---------- */ |
- else if (match(param[0], "del")) { |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- if (b->GetDRSType() == 4) |
- puts("Delayed start not possible for DRS4"); |
- else { |
- if (atoi(param[1]) == 1) { |
- b->SetDelayedStart(1); |
- puts("Delayed start is on"); |
- } else { |
- b->SetDelayedStart(0); |
- puts("Delayed start is off"); |
- } |
- } |
- } |
- } |
- |
- /* transparent mode on/off ---------- */ |
- else if (match(param[0], "trans")) { |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- if (b->GetDRSType() != 4) |
- puts("Transparen mode only possible for DRS4"); |
- else { |
- if (atoi(param[1]) == 1) { |
- b->SetTranspMode(1); |
- puts("Transparent mode is on"); |
- } else { |
- b->SetTranspMode(0); |
- puts("Transparent mode is off"); |
- } |
- } |
- } |
- } |
- |
- /* standby mode on/off ---------- */ |
- else if (match(param[0], "standby")) { |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- if (b->GetDRSType() != 4) |
- puts("Standby mode only possible for DRS4"); |
- else { |
- if (atoi(param[1]) == 1) { |
- b->SetStandbyMode(1); |
- puts("Standby mode is on"); |
- } else { |
- b->SetStandbyMode(0); |
- puts("Standby mode is off"); |
- } |
- } |
- } |
- } |
- |
- /* offset ---------- */ |
- else if (match(param[0], "offset")) { |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- b->SetVoltageOffset(atof(param[1]), atof(param[2])); |
- } |
- } |
- |
- /* phase ---------- */ |
- else if (match(param[0], "phase")) { |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- b->SetADCClkPhase(atoi(param[1]), atoi(param[2]) > 0); |
- } |
- } |
- |
- /* directory ---------- */ |
- else if (match(param[0], "dir")) { |
- |
-#ifdef HAVE_VME |
-#ifdef CF_VIA_USB |
- { |
- if (param[2][0]) |
- i = atoi(param[2]); |
- else |
- i = 1; |
- printf("Physical drive %d:\n", i); |
- |
- if (ace_init(NULL, i, &ace) != ACE_SUCCESS) { |
- printf("Cannot access ACE on physical drive %d\n", i); |
- } else { |
-#else |
- for (i=i_start ; i<i_end ; i++) { |
- |
- /* do only once per VME board */ |
- if (i_end - i_start > 1 && (i % 2) == 1) |
- continue; |
- |
- b = drs->GetBoard(i); |
- |
- printf("VME slot %2d: ", (b->GetSlotNumber() >> 1) + 2); |
- |
- if (ace_init(b->GetVMEInterface(), (b->GetSlotNumber() >> 1)+2, &ace) != ACE_SUCCESS) { |
- printf("Cannot access ACE in slot %d\n", (b->GetSlotNumber() >> 1)+2); |
- } else { |
-#endif |
- ace_dir(&ace); |
- } |
- } |
-#else |
- printf("No VME support compiled into drscl\n"); |
-#endif // HAVE_VME |
- } |
- |
- /* upload ---------- */ |
- else if (match(param[0], "upload")) { |
- |
-#ifdef HAVE_VME |
-#ifdef CF_VIA_USB |
- { |
- if (param[2][0]) |
- i = atoi(param[2]); |
- else |
- i = 1; |
- printf("Physical drive %d:\n", i); |
- |
- if (ace_init(NULL, i, &ace) != ACE_SUCCESS) { |
- printf("Cannot access ACE on physical drive %d\n", i); |
- } else { |
-#else |
- |
- /* use SVN file as default */ |
- if (param[1][0] == 0) { |
-#ifdef _MSC_VER |
- if (b->GetDRSType() == 4) |
- strcpy(str, "c:\\meg\\online\\VPC\\drs4\\2vp30\\cflash\\drs4\\rev0\\rev0.ace"); |
- else if (b->GetDRSType() == 3) |
- strcpy(str, "c:\\meg\\online\\VPC\\drs3\\2vp30\\cflash\\drs3\\rev0\\rev0.ace"); |
- else |
- strcpy(str, "c:\\meg\\online\\VPC\\drs2\\2vp30\\cflash\\drs2\\rev0\\rev0.ace"); |
-#else |
- if (b->GetDRSType() == 4) |
- strcpy(str, "/home/meg/meg/online/VPC/drs4/2vp30/cflash/drs4/rev0/rev0.ace"); |
- else if (b->GetDRSType() == 3) |
- strcpy(str, "/home/meg/meg/online/VPC/drs3/2vp30/cflash/drs3/rev0/rev0.ace"); |
- else |
- strcpy(str, "/home/meg/meg/online/VPC/drs2/2vp30/cflash/drs2/rev0/rev0.ace"); |
-#endif |
- printf("Enter filename or hit return for \n%s\n", str); |
- fgets(line, sizeof(line), stdin); |
- if (line[0] == '\r' || line[0] == '\n') |
- strcpy(file_name, str); |
- else |
- strcpy(file_name, line); |
- strcpy(param[1], str); |
- } else |
- strcpy(file_name, param[1]); |
- |
- for (i=i_start ; i<i_end ; i++) { |
- |
- /* do only once per VME board */ |
- if (i_end - i_start > 1 && (i % 2) == 1) |
- continue; |
- |
- b = drs->GetBoard(i); |
- |
- if (b->GetTransport() == TR_USB) { |
- printf("Cannot upload to USB board.\n"); |
- } else { |
- printf("VME slot %d:\n", (b->GetSlotNumber() >> 1)+2); |
- if (ace_init(b->GetVMEInterface(), (b->GetSlotNumber() >> 1)+2, &ace) != ACE_SUCCESS) { |
- printf("Cannot access ACE in slot %d\n", (b->GetSlotNumber() >> 1)+2); |
- } else { |
-#endif |
- status = ace_upload(&ace, file_name); |
- } |
- } |
- } |
- printf("\nPlease issue a power cycle to activate new firmware\n"); |
-#else |
- printf("No VME support compiled into drscl\n"); |
-#endif // HAVE_VME |
- } |
- |
- /* download ---------- */ |
- else if (match(param[0], "download")) { |
- |
-#ifdef HAVE_VME |
- b = drs->GetBoard(i_start); |
- |
- if (b->GetTransport() == TR_USB) { |
- printf("Cannot upload to USB board.\n"); |
- } else { |
- printf("VME slot %d:\n", (b->GetSlotNumber() >> 1)+2); |
- if (ace_init(b->GetVMEInterface(), (b->GetSlotNumber() >> 1)+2, &ace) != ACE_SUCCESS) { |
- printf("Cannot access ACE in slot %d\n", (b->GetSlotNumber() >> 1)+2); |
- } else { |
- strcpy(str, "rev0.ace"); |
- if (param[1][0] == 0) { |
- printf("Enter filename or hit return for \n%s\n", str); |
- fgets(line, sizeof(line), stdin); |
- if (line[0] == '\r' || line[0] == '\n') |
- strcpy(file_name, str); |
- else |
- strcpy(file_name, line); |
- strcpy(param[1], str); |
- } else |
- strcpy(file_name, param[1]); |
- |
- if (strchr(file_name, '\r')) |
- *strchr(file_name, '\r') = 0; |
- if (strchr(file_name, '\n')) |
- *strchr(file_name, '\n') = 0; |
- |
- status = ace_download(&ace, file_name); |
- } |
- } |
-#else |
- printf("No VME support compiled into drscl\n"); |
-#endif // HAVE_VME |
- } |
- |
- /* calibration ---------- */ |
- else if (match(param[0], "calib")) { |
- debug = strcmp(param[1], "debug") == 0 || strcmp(param[2], "debug") == 0 || strcmp(param[3], "debug") == 0; |
- if (param[1][0]) { |
- strlcpy(dir, param[1], sizeof(str)); |
- } else |
- getcwd(dir, sizeof(dir)); |
- |
- while (dir[strlen(dir)-1] == '\n' || dir[strlen(dir)-1] == '\r') |
- dir[strlen(dir)-1] = 0; |
- |
- b = drs->GetBoard(i_start); |
- |
- printf("\n Enter calibration frequency [GHz]: "); |
- fgets(line, sizeof(line), stdin); |
- freq = atof(line); |
- |
- if (b->GetDRSType() == 2) { |
- printf(" Enter the expected trigger frequency [Hz]: "); |
- fgets(line, sizeof(line), stdin); |
- triggerfreq = atof(line); |
- } else |
- triggerfreq = 0; |
- |
- ext_refclk = 0; |
- if (b->GetBoardType() == 6) { |
- printf("Use [e]xternal or [i]nternal reference clock: "); |
- fgets(line, sizeof(line), stdin); |
- ext_refclk = line[0] == 'e'; |
- } |
- |
- if (b->GetDRSType() == 4) { |
- printf(" Enter range [V]: "); |
- fgets(line, sizeof(line), stdin); |
- range = atof(line); |
- |
- printf(" Enter mode [1]024 or [2]048 bin mode: "); |
- fgets(line, sizeof(line), stdin); |
- cascading = atoi(line); |
- } else { |
- range = 0; |
- cascading = 0; |
- } |
- |
- if (b->GetDRSType() == 4) { |
- printf("\nPlease make sure that no input signal are present then hit any key\r"); |
- fflush(stdout); |
- while (!drs_kbhit()); |
- printf(" \r"); |
- while (drs_kbhit()) |
- getchar(); |
- } |
- |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- if (b->GetTransport() == TR_VME) |
- printf("Creating Calibration of Board in VME slot %2d %s, serial #%04d\n", |
- (b->GetSlotNumber() >> 1)+2, ((b->GetSlotNumber() & 1) == 0) ? "upper" : "lower", |
- b->GetBoardSerialNumber()); |
- else |
- printf("Creating Calibration of Board on USB, serial #%04d\n", |
- b->GetBoardSerialNumber()); |
- if (b->GetDRSType() == 4) { |
- ProgressBar p; |
- if (b->GetTransport() == TR_VME) { |
- if (cascading == 2) |
- b->SetChannelConfig(7, 8, 4); // 7 means read all 9 channels per chip |
- else |
- b->SetChannelConfig(7, 8, 8); |
- } else { |
- if (cascading == 2) |
- b->SetChannelConfig(0, 8, 4); |
- else |
- b->SetChannelConfig(0, 8, 8); |
- } |
- |
- b->SetRefclk(ext_refclk); |
- b->SetFrequency(freq, true); |
- b->SetInputRange(range); |
- b->CalibrateVolt(&p); |
- } else { |
- b->SetDebug(debug); |
- b->Init(); |
- b->SetFrequency(freq, true); |
- b->SoftTrigger(); |
- |
- if (b->GetDRSType() == 3) |
- b->GetResponseCalibration()->SetCalibrationParameters(1,11,0,20,0,0,0,0,0); |
- else |
- b->GetResponseCalibration()->SetCalibrationParameters(1,36,110,20,19,40,15,triggerfreq,0); |
- if (!strcmp(dir,"lab")) |
- b->SetCalibrationDirectory("C:/experiment/calibrations"); |
- else if (!strcmp(dir,"area")) |
- b->SetCalibrationDirectory("/home/meg/meg/online/calibrations"); |
- else |
- b->SetCalibrationDirectory(dir); |
- for (j=0;j<2;j++) { |
- b->GetResponseCalibration()->ResetCalibration(); |
- while (!b->GetResponseCalibration()->RecordCalibrationPoints(j)) {} |
- while (!b->GetResponseCalibration()->FitCalibrationPoints(j)) {} |
- while (!b->GetResponseCalibration()->OffsetCalibration(j)) {} |
- if (!b->GetResponseCalibration()->WriteCalibration(j)) |
- break; |
- } |
- } |
- } |
- } |
- |
- /* timing calibration ---------- */ |
- else if (match(param[0], "tcalib")) { |
- |
- freq = 0; |
- if (param[1][0]) |
- freq = atof(param[1]); |
- |
- if (freq == 0) { |
- printf("Enter calibration frequency [GHz]: "); |
- fgets(line, sizeof(line), stdin); |
- freq = atof(line); |
- } |
- |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- if (b->GetDRSType() < 4) |
- printf("Timing calibration not possivle for DRS2 or DRS3\n"); |
- else if (b->GetFirmwareVersion() < 13279) |
- printf("Firmware revision 13279 or later required for timing calibration\n"); |
- else if (b->GetDRSType() == 4) { |
- printf("Creating Timing Calibration of Board #%d\n", b->GetBoardSerialNumber()); |
- ProgressBar p; |
- b->SetFrequency(freq, true); |
- status = b->CalibrateTiming(&p); |
- if (!status) |
- printf("Error performing timing calibration, please check waveforms\n"); |
- printf("\n"); |
- } |
- } |
- } |
- |
- /* tcout ---------- */ |
- else if (match(param[0], "tcout")) { |
- float time[1024]; |
- int chip; |
- int k; |
- int idx = 0; |
- int first_board = i_start; |
- int last_board = i_end; |
- |
- file_name[0] = 0; |
- strcpy(file_name, param[1]); |
- if (file_name[0]) { |
- f = fopen(file_name, "wt"); |
- if (f == NULL) { |
- printf("Cannot open file \"%s\"\n", file_name); |
- } else { |
- first_board = 0; |
- last_board = drs->GetNumberOfBoards(); |
- } |
- idx += atoi(param[2]); |
- } else |
- f = NULL; |
- |
- if (f) { |
- fprintf(f, "-- Replace %%%% with correct id\n"); |
- } |
- for (i=first_board ; i<last_board ; i++) { |
- b = drs->GetBoard(i); |
- if (b->GetDRSType() >= 4) { |
- for (chip = 0; chip < b->GetNumberOfChips(); chip++) { |
- b->GetTime(chip, 0, b->GetTriggerCell(0), time, true, false); |
- if (f) { |
- fprintf(f, "INSERT INTO MEGDRSTimeCalibration VALUES(%%%%,%d,%d", idx, |
- static_cast<int>(b->GetNominalFrequency() * 10 + 0.5) * 100); |
- for (j=0 ; j<1024 ; j++) |
- fprintf(f, ",%g", time[j] * 1e-9); |
- fprintf(f, ",%d,%d", b->GetBoardSerialNumber(), chip); |
- fprintf(f, ",%g);\n", 1 / (b->GetNominalFrequency() * 1e9) * 1024); |
- idx++; |
- } else { |
- printf("Board %d\n", b->GetBoardSerialNumber()); |
- for (j=0 ; j<128 ; j++) { |
- printf("%4d: ", j*8); |
- for (k=0 ; k<7 ; k++) |
- printf("%6.1lf ", time[j*8+k]); |
- printf("%6.1lf\n", time[j*8+k]); |
- } |
- printf("n"); |
- } |
- } |
- } else { |
- // DRS2 or DRS3 |
- idx += 2; |
- } |
- } |
- if (f) { |
- fclose(f); |
- printf("Data successfully written to \"%s\"\n", file_name); |
- } |
- } |
- |
- /* read */ |
- else if (match(param[0], "read")) { |
- float waveform[2048]; |
- short swaveform[2048]; |
- calib = 0; |
- |
- file_name[0] = 0; |
- if (param[1][0]) { |
- idx = atoi(param[1]); |
- calib = atoi(param[2]); |
- if (strlen(param[2]) > 2) |
- strcpy(file_name, param[2]); |
- else |
- strcpy(file_name, param[3]); |
- } else { |
- printf("Enter channel number (0..19): "); |
- fgets(line, sizeof(line), stdin); |
- idx = atoi(line); |
- } |
- |
- if (idx<0 || idx>19) |
- printf("Channel number must be between 0 and 19\n"); |
- else { |
- b = drs->GetBoard(i_start); |
- if (!b->IsEventAvailable()) |
- printf("Error: Domino wave is running, please issue a \"stop\" first\n"); |
- else { |
- if (calib == 1) { |
- if (b->GetDRSType() == 4) { |
- if (!b->IsVoltageCalibrationValid()) { |
- printf("Calibration not valid for board #%d\n", b->GetBoardSerialNumber()); |
- calib = 0; |
- } |
- |
- } else { |
-#ifdef _MSC_VER |
- b->SetCalibrationDirectory("C:/experiment/calibrations"); |
-#else |
- b->SetCalibrationDirectory("/home/meg/meg/online/calibrations"); |
-#endif |
- if (!b->GetResponseCalibration()->IsRead(0)) |
- if (!b->GetResponseCalibration()->ReadCalibration(0)) |
- calib = 0; |
- if (!b->GetResponseCalibration()->IsRead(1)) |
- if (!b->GetResponseCalibration()->ReadCalibration(1)) |
- calib = 0; |
- } |
- } |
- |
- status = b->TransferWaves(idx, idx); |
- if (file_name[0]) { |
- f = fopen(file_name, "wt"); |
- if (f == NULL) |
- printf("Cannot open file \"%s\"\n", file_name); |
- } else |
- f = NULL; |
- |
- if (calib) { |
- status = b->GetWave(idx/b->GetNumberOfChannels(), idx%b->GetNumberOfChannels(), waveform, |
- true, b->GetTriggerCell(idx/b->GetNumberOfChannels()), b->GetStopWSR(idx/b->GetNumberOfChannels())); |
- if (status == 0) { |
- if (f) |
- for (i=0 ; i<b->GetChannelDepth() ; i++) |
- fprintf(f, "%6.1lf\n", waveform[i]); |
- else { |
- for (i=0 ; i<b->GetChannelDepth()/8 ; i++) { |
- printf("%4d: ", i*8); |
- for (j=0 ; j<7 ; j++) |
- printf("%6.1lf ", waveform[i*8+j]); |
- printf("%6.1lf\n", waveform[i*8+j]); |
- } |
- } |
- } |
- } else { |
- status = b->GetWave(idx/b->GetNumberOfChannels(), idx%b->GetNumberOfChannels(), swaveform, 0, 0); |
- if (status == 0) { |
- if (f) |
- for (i=0 ; i<b->GetChannelDepth() ; i++) |
- fprintf(f, "%4d\n", swaveform[i]); |
- else { |
- for (i=0 ; i<b->GetChannelDepth()/16 ; i++) { |
- for (j=0 ; j<15 ; j++) |
- printf("%4d ", swaveform[i*16+j] >> 4); |
- printf("%4d\n", swaveform[i*16+j] >> 4); |
- } |
- } |
- } |
- } |
- } |
- } |
- |
- if (f) { |
- fclose(f); |
- printf("Data successfully written to \"%s\"\n", file_name); |
- } |
- } |
- |
- /* register test ---------- */ |
- else if (match(param[0], "reg")) { |
- b->RegisterTest(); |
- } |
- |
- /* RAM test */ |
- else if (match(param[0], "ram")) { |
- if (param[1][0] == 0) |
- b->RAMTest(3); |
- else |
- b->RAMTest(atoi(param[1])); |
- } |
- |
- /* Change input range */ |
- else if (match(param[0], "range")) { |
- for (i=i_start ; i<i_end ; i++) { |
- b = drs->GetBoard(i); |
- if (param[1][0] == 0) { |
- printf("Input range: "); |
- fgets(str, sizeof(str), stdin); |
- } else |
- strlcpy(str, param[1], sizeof(str)); |
- |
- b->SetInputRange(atof(str)); |
- printf("Range set to %1.2lg V ... %1.2lg V\n", atof(str)-0.5, atof(str)+0.5); |
- } |
- } |
- |
- /* Chip Test */ |
- else if (match(param[0], "ct")) { |
- if (drs->GetNumberOfBoards() == 0) |
- puts("No DRS board found"); |
- else { |
- puts("Press 'q' to quit, any other key to repeat test.\n"); |
- do { |
- if (b->ChipTest()) |
- puts("Chip test successfully finished"); |
- else |
- puts("\007Chip Error!"); |
- |
- b->SetStandbyMode(1); |
- for (i=0 ; i<8 ; i++) |
- b->SetDAC(i, 0); |
- i = getch(); |
- b->SetStandbyMode(0); |
- } while (i != 'q'); |
- } |
- } |
- |
- /* calib0 for speed vs. temperature calibration */ |
- else if (match(param[0], "c0")) { |
- |
- double volt, freq; |
- |
- b->Init(); |
- b->SetFrequency(5, true); |
- b->EnableAcal(0, 0); |
- b->SetDominoMode(1); |
- |
- for (volt=2.5 ; volt > 0 ; volt -= 0.05) { |
- printf("%4.1lf - %5.3lf ", b->GetTemperature(), volt); |
- b->SetDAC(1, volt); |
- b->SetDAC(2, volt); |
- Sleep(100); |
- b->ReadFrequency(0, &freq); |
- |
- printf("%5.3lf\n", freq); |
- |
- if (drs_kbhit()) |
- break; |
- } |
- |
- while (drs_kbhit()) |
- getch(); |
- |
- b->Init(); // reset voltage offset |
- } |
- |
- /* calib1 */ |
- else if (match(param[0], "c1")) { |
- |
- short swaveform[1024]; |
- double volt; |
- double av[1024]; |
- int k; |
- |
- b->Init(); |
- b->SetFrequency(5, true); |
- b->SetDominoMode(1); |
- b->SetDominoActive(1); |
- b->SetReadoutMode(1); |
- |
- for (volt=-0.5 ; volt <= 0.5001 ; volt += 0.02) { |
- printf("%4.1lf - %6.0lf ", b->GetTemperature(), 1000*volt); |
- b->EnableAcal(1, volt); |
- b->StartDomino(); |
- Sleep(100); |
- |
- memset(av, 0, sizeof(av)); |
- |
- for (j=0 ; j<100 ; j++) { |
- for (i=0 ; i<10 ; i++) |
- b->IsBusy(); |
- b->SoftTrigger(); |
- while (b->IsBusy()); |
- b->StartDomino(); |
- b->TransferWaves(b->GetNumberOfChannels()*b->GetNumberOfChips()); |
- i = b->GetTriggerCell(0); |
- b->GetWave(0, 0, swaveform, false, i, 1); |
- |
- for (k=0 ; k<1024 ; k++) |
- av[k] += swaveform[k]; |
- |
- if (drs_kbhit()) |
- break; |
- } |
- |
- for (k=0 ; k<1024 ; k++) |
- av[k] /= j; |
- |
- for (k=0 ; k<5 ; k++) |
- printf("%10.2lf ", 1000*(av[k]/65536-0.5)); |
- printf("\n"); |
- |
- if (drs_kbhit()) |
- break; |
- } |
- // keep chip "warm" |
- b->StartDomino(); |
- } |
- |
- /* test0 */ |
- else if (match(param[0], "t0")) { |
- b->Init(); |
- b->SetDominoMode(1); |
- b->SetDominoActive(1); |
- b->SetReadoutMode(1); |
- b->SetFrequency(0.8, true); |
- b->EnableTrigger(1, 0); |
- b->SetTriggerLevel(1); |
- b->SetChannelConfig(0, 8, 4); |
- |
- do { |
- b->StartDomino(); |
- while (b->IsBusy()) |
- if (drs_kbhit()) |
- break; |
- |
- b->TransferWaves(); |
- |
- if (b->GetBoardType() == 5) { |
- printf("%04d(0x%03X) - %3d\n", b->GetTriggerCell(0), b->GetTriggerCell(0), |
- b->GetStopWSR(0)); |
- } else { |
- printf("%04d %04d %04d %04d - %3d %3d %3d\n", |
- b->GetTriggerCell(0), |
- b->GetTriggerCell(1), |
- b->GetTriggerCell(2), |
- b->GetTriggerCell(3), |
- b->GetTriggerCell(1)-b->GetTriggerCell(0), |
- b->GetTriggerCell(2)-b->GetTriggerCell(0), |
- b->GetTriggerCell(3)-b->GetTriggerCell(0)); |
- } |
- Sleep(300); |
- } while (!drs_kbhit()); |
- |
- while (drs_kbhit()) |
- getch(); |
- } |
- |
- /* test1 simple start/stop loop */ |
- else if (match(param[0], "t1")) { |
- time_t t1, t2; |
- |
- b->SetDebug(1); |
- b->Init(); |
- b->SetFrequency(5, true); |
- b->SetDominoMode(1); |
- b->SetReadoutMode(0); |
- b->SetTranspMode(0); |
- b->SetDominoActive(1); |
- b->EnableAcal(1, 0.5); |
- b->EnableTcal(1); |
- time(&t1); |
- do { |
- time(&t2); |
- } while (t1 == t2); |
- i=0; |
- t1 = t2; |
- do { |
- b->StartDomino(); |
- b->SoftTrigger(); |
- b->TransferWaves(); |
- i++; |
- time(&t2); |
- if (t2 > t1) { |
- printf("%d events/sec\n", i); |
- i = 0; |
- t1 = t2; |
- } |
- } while (!drs_kbhit()); |
- |
- while (drs_kbhit()) |
- getch(); |
- } |
- |
- /* test2 readout from stop position */ |
- else if (match(param[0], "t2")) { |
- short sw[1024]; |
- double volt = 0.5; |
- |
- b->Init(); |
- b->SetNumberOfChannels(10); |
- b->SetChannelConfig(0, 9, 12); |
- b->SetFrequency(2, true); |
- b->EnableTcal(1); |
- b->SetReadoutMode(0); |
- b->SetDominoActive(0); |
- b->SetDominoMode(1); |
- b->SetCalibTiming(0, 0); |
- b->StartDomino(); |
- b->EnableAcal(1, 0.5); |
- if (!b->GetResponseCalibration()->IsRead(0)) |
- if (!b->GetResponseCalibration()->ReadCalibration(0)) |
- printf("cannot read calibration\n"); |
- |
- do { |
- //volt += 0.25; |
- if (volt > 1) |
- volt = 0; |
- b->SoftTrigger(); |
- while (b->IsBusy()); |
- b->StartDomino(); |
- b->EnableAcal(1, volt); |
- b->TransferWaves(); |
- |
- b->GetWave(0, 1, sw, 0, 0); |
- printf("%d ", sw[100]); |
- b->GetWave(0, 1, sw, 1, 0); |
- printf("%1.4lf\n", sw[100]/4096.0); |
- } while (!drs_kbhit()); |
- while (drs_kbhit()) getch(); |
- } |
- |
- /* DAC Loop */ |
- else if (match(param[0], "t3")) { |
- double volt; |
- do { |
- for (volt=2.5 ; volt > 0 ; volt -= 0.05) { |
- |
- printf("%4.1lf - %5.3lf\n", b->GetTemperature(), volt); |
- b->SetDAC(0, volt); |
- b->SetDAC(1, 2.5-volt); |
- Sleep(100); |
- if (drs_kbhit()) |
- break; |
- } |
- } while (!drs_kbhit()); |
- |
- while (drs_kbhit()) |
- getch(); |
- } |
- |
- /* noise measurement */ |
- else if (match(param[0], "t4")) { |
- int i, n; |
- short sw[1024]; |
- double ofs[1024], sx, sxx, avg, stdev, enob; |
- |
- b->Init(); |
- b->SetFrequency(2, true); |
- b->EnableTcal(0); |
- b->SetDominoMode(1); |
- b->StartDomino(); |
- b->EnableAcal(1, 0.5); |
- Sleep(100); |
- b->SoftTrigger(); |
- while (b->IsBusy()); |
- b->StartDomino(); |
- Sleep(100); |
- memset(ofs, 0, sizeof(ofs)); |
- |
- for (i=0 ; i<10 ; i++) { |
- b->SoftTrigger(); |
- while (b->IsBusy()); |
- b->StartDomino(); |
- b->TransferWaves(1); |
- b->GetWave(0, 0, sw, 0, 0); |
- sx = sxx = 0; |
- for (n=0 ; n<1024 ; n++) { |
- ofs[n] += sw[n]; |
- } |
- } |
- |
- for (n=0 ; n<1024 ; n++) |
- ofs[n] /= i; |
- |
- for (i=0 ; i<10 ; i++) { |
- b->SoftTrigger(); |
- while (b->IsBusy()); |
- b->StartDomino(); |
- b->TransferWaves(1); |
- b->GetWave(0, 0, sw, 0, 0); |
- |
- sx = sxx = 0; |
- for (n=10 ; n<1014 ; n++) { |
- sx += (sw[n]-ofs[n])/4096.0; |
- sxx += (sw[n]-ofs[n])/4096.0*(sw[n]-ofs[n])/4096.0; |
- } |
- |
- if (i>5) |
- Sleep(5000); |
- |
- avg = sx / n; |
- stdev = sqrt((sxx-sx*sx/n)/(n-1)); |
- enob = log(1/stdev)/log(2.); |
- printf("avg=%1.4lf sd=%1.4lf ENOB=%1.1lf\n", avg, stdev, enob); |
- }; |
- } |
- |
- /* exit/quit ---------- */ |
- else if (match(param[0], "exit") || match(param[0], "quit")) |
- break; |
- |
- else { |
- if (strchr(param[0], '\r')) |
- *strchr(param[0], '\r') = 0; |
- if (strchr(param[0], '\n')) |
- *strchr(param[0], '\n') = 0; |
- printf("Unknon command \"%s\"\n", param[0]); |
- } |
- |
- } while (1); |
- |
- delete drs; |
-} |
- |
-/*------------------------------------------------------------------*/ |
- |
-int main() |
-{ |
- printf("DRS command line tool, Revision %d\n", atoi(drscl_svn_revision+15)); |
- printf("Type 'help' for a list of available commands.\n\n"); |
- |
- cmd_loop(); |
- return 1; |
-} |
Index: instr/drsctrl/getopt.h |
=================================================================== |
--- instr/drsctrl/getopt.h (revision 196) |
+++ instr/drsctrl/getopt.h (nonexistent) |
@@ -1,74 +0,0 @@ |
- |
-/*- |
- * Copyright (c) 2000 The NetBSD Foundation, Inc. |
- * All rights reserved. |
- * |
- * This code is derived from software contributed to The NetBSD Foundation |
- * by Dieter Baron and Thomas Klausner. |
- * |
- * Redistribution and use in source and binary forms, with or without |
- * modification, are permitted provided that the following conditions |
- * are met: |
- * 1. Redistributions of source code must retain the above copyright |
- * notice, this list of conditions and the following disclaimer. |
- * 2. Redistributions in binary form must reproduce the above copyright |
- * notice, this list of conditions and the following disclaimer in the |
- * documentation and/or other materials provided with the distribution. |
- * |
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
- * POSSIBILITY OF SUCH DAMAGE. |
- * |
- * $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ |
- */ |
- |
-#ifndef _GETOPT_H_ |
-#define _GETOPT_H_ |
- |
-/* |
- * Gnu like getopt_long() and BSD4.4 getsubopt()/optreset extensions |
- */ |
-#define no_argument 0 |
-#define required_argument 1 |
-#define optional_argument 2 |
- |
-#ifdef __cplusplus |
-extern "C" { |
-#endif |
- |
-struct option { |
- /* name of long option */ |
- const char *name; |
- /* |
- * one of no_argument, required_argument, and optional_argument: |
- * whether option takes an argument |
- */ |
- int has_arg; |
- /* if not NULL, set *flag to val when option found */ |
- int *flag; |
- /* if flag not NULL, value to set *flag to; else return value */ |
- int val; |
-}; |
- |
-int getopt_long(int, char * const *, const char *, |
- const struct option *, int *); |
- |
-extern int optreset; |
-extern char *optarg; |
-extern int opterr; |
-extern int optind; |
-extern int optopt; |
- |
-#ifdef __cplusplus |
-}; |
-#endif |
- |
-#endif /* !_GETOPT_H_ */ |
Index: instr/drsctrl/daq.h |
=================================================================== |
--- instr/drsctrl/daq.h (revision 196) |
+++ instr/drsctrl/daq.h (nonexistent) |
@@ -1,18 +0,0 @@ |
-#ifndef _daq_h_ |
-#define _daq_h_ |
- |
-#define BUFF_L 2048 |
-class daq { |
-public: |
- unsigned long stackwrite[BUFF_L],stackdata[10000],stackdump[27000]; |
-int debug; |
-int fStop; |
-int event(unsigned int *, int); |
-int init(); |
-int connect(); |
-int disconnect(); |
-daq(); |
-~daq(); |
-}; |
- |
-#endif |
Index: instr/drsctrl/drsread.dll |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/instr/drsctrl/drsread.dll |
Property changes: |
Deleted: svn:mime-type |
## -1 +0,0 ## |
-application/octet-stream |
\ No newline at end of property |
Index: instr/drsctrl/mxml.c |
=================================================================== |
--- instr/drsctrl/mxml.c (revision 196) |
+++ instr/drsctrl/mxml.c (nonexistent) |
@@ -1,2366 +0,0 @@ |
-/********************************************************************\ |
- |
- 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: instr/drsctrl/timer.c |
=================================================================== |
--- instr/drsctrl/timer.c (revision 196) |
+++ instr/drsctrl/timer.c (nonexistent) |
@@ -1,142 +0,0 @@ |
-/* |
-*************************************************************************** |
-* |
-* Author: Teunis van Beelen |
-* |
-* Copyright (C) 2010, 2011, 2012 Teunis van Beelen |
-* |
-* teuniz@gmail.com |
-* |
-*************************************************************************** |
-* |
-* This program is free software; you can redistribute it and/or modify |
-* it under the terms of the GNU General Public License as published by |
-* the Free Software Foundation version 2 of the License. |
-* |
-* This program is distributed in the hope that it will be useful, |
-* but WITHOUT ANY WARRANTY; without even the implied warranty of |
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
-* GNU General Public License for more details. |
-* |
-* You should have received a copy of the GNU General Public License along |
-* with this program; if not, write to the Free Software Foundation, Inc., |
-* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
-* |
-*************************************************************************** |
-* |
-* This version of GPL is at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt |
-* |
-*************************************************************************** |
-*/ |
- |
- |
- |
-#include "timer.h" |
- |
- |
- |
-void (*timer_func_handler_pntr)(void); |
- |
- |
-#ifdef __linux__ |
- |
-void timer_handler(int); |
- |
-struct itimerval timervalue; |
- |
-struct sigaction new_handler, old_handler; |
- |
-void timer_sig_handler(int); |
- |
- |
- |
-int start_timer(int mSec, void (*timer_func_handler)(void)) |
-{ |
- timer_func_handler_pntr = timer_func_handler; |
- |
- timervalue.it_interval.tv_sec = mSec / 1000; |
- timervalue.it_interval.tv_usec = (mSec % 1000) * 1000; |
- timervalue.it_value.tv_sec = mSec / 1000; |
- timervalue.it_value.tv_usec = (mSec % 1000) * 1000; |
- if(setitimer(ITIMER_REAL, &timervalue, NULL)) |
- { |
- printf("\nsetitimer() error\n"); |
- return(1); |
- } |
- |
- new_handler.sa_handler = &timer_sig_handler; |
- new_handler.sa_flags = SA_NOMASK; |
- if(sigaction(SIGALRM, &new_handler, &old_handler)) |
- { |
- printf("\nsigaction() error\n"); |
- return(1); |
- } |
- |
- return(0); |
-} |
- |
- |
-void timer_sig_handler(int arg) |
-{ |
- timer_func_handler_pntr(); |
-} |
- |
- |
-void stop_timer(void) |
-{ |
- timervalue.it_interval.tv_sec = 0; |
- timervalue.it_interval.tv_usec = 0; |
- timervalue.it_value.tv_sec = 0; |
- timervalue.it_value.tv_usec = 0; |
- setitimer(ITIMER_REAL, &timervalue, NULL); |
- |
- sigaction(SIGALRM, &old_handler, NULL); |
-} |
- |
-#else |
- |
-HANDLE win_timer; |
- |
-VOID CALLBACK timer_sig_handler(PVOID, BOOLEAN); |
- |
- |
-int start_timer(int mSec, void (*timer_func_handler)(void)) |
-{ |
- timer_func_handler_pntr = timer_func_handler; |
- |
- if(CreateTimerQueueTimer(&win_timer, NULL, (WAITORTIMERCALLBACK)timer_sig_handler, NULL, mSec, mSec, WT_EXECUTEINTIMERTHREAD) == 0) |
- { |
- printf("\nCreateTimerQueueTimer() error\n"); |
- return(1); |
- } |
- |
- return(0); |
-} |
- |
- |
-VOID CALLBACK timer_sig_handler(PVOID lpParameter, BOOLEAN TimerOrWaitFired) |
-{ |
- timer_func_handler_pntr(); |
-} |
- |
- |
-void stop_timer(void) |
-{ |
- DeleteTimerQueueTimer(NULL, win_timer, NULL); |
- CloseHandle(win_timer); |
-} |
- |
-#endif |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Index: instr/drs/DRS.cpp |
=================================================================== |
--- instr/drs/DRS.cpp (nonexistent) |
+++ instr/drs/DRS.cpp (revision 197) |
@@ -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; |
+ } |
+} |
Index: instr/drs/LinkDef.h |
=================================================================== |
--- instr/drs/LinkDef.h (nonexistent) |
+++ instr/drs/LinkDef.h (revision 197) |
@@ -0,0 +1,7 @@ |
+#ifdef __CINT__ |
+ |
+#pragma link off all globals; |
+#pragma link off all classes; |
+#pragma link C++ function TimerOut; |
+ |
+#endif |
Index: instr/drs/Makefile |
=================================================================== |
--- instr/drs/Makefile (nonexistent) |
+++ instr/drs/Makefile (revision 197) |
@@ -0,0 +1,208 @@ |
+#cmd.exe /k ""C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"" x86 |
+#set INCLUDE=%INCLUDE%;"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include" |
+#set ROOTSYS=C:\root_v5.34.34 |
+# |
+#nmake -f Makefile.win32 |
+# |
+#set INCLUDE=%INCLUDE%;C:\Program Files\Microsoft SDKs\Windows\v7.1A\Include |
+!if "$(CFG)" == "" |
+!if ([findstr /c:"--build=debug" $(ROOTSYS)\bin\root-config > nul ] == 0) |
+CFG = Win32 Debug |
+!if ([findstr /c:"--disable-winrtdebug" $(ROOTSYS)\bin\root-config > nul ] == 0) |
+RUNTIME = Release |
+!else |
+RUNTIME = Debug |
+!endif |
+!message No configuration specified: Defaulting to Win32 Debug |
+!message With $(RUNTIME) Runtime DLL (Taken from ROOT config). |
+!message . |
+!else |
+CFG = Win32 Release |
+RUNTIME = Release |
+!message No configuration specified: Defaulting to Win32 Release |
+!message With $(RUNTIME) Runtime DLL (Taken from ROOT config). |
+!message . |
+!endif |
+!else |
+!if "$(CFG)" == "Win32 Release" |
+RUNTIME = Release |
+!elseif "$(CFG)" == "Win32 Debug" |
+RUNTIME = Debug |
+!endif |
+!endif |
+ |
+!if "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" |
+!message Invalid configuration "$(CFG)" specified. |
+!message You can specify a configuration when running NMAKE |
+!message by defining the macro CFG on the command line. For example: |
+!message |
+!message NMAKE /f "Makefile.msc" CFG="Win32 Debug" |
+!message |
+!message Possible choices for configuration are: |
+!message |
+!message "Win32 Release" (based on "Win32 (x86) Dynamic Library") |
+!message "Win32 Debug" (based on "Win32 (x86) Dynamic Library") |
+!message |
+!error An invalid configuration is specified. |
+!endif |
+!message ROOTSYS = "$(ROOTSYS)/include" |
+ |
+ObjSuf = obj |
+SrcSuf = c |
+SrcSuf1 = cpp |
+ExeSuf = .exe |
+DllSuf = dll |
+OutPutOpt = -out: |
+ |
+ |
+## VS2012 (VC11): configure subsystem version |
+## See: https://blogs.msdn.com/b/vcblog/archive/2012/10/08/10357555.aspx |
+## (APPVER used in win32.mak to set subsystem version) |
+!if ([nmake /? 2>&1 | findstr /c:"Version 14\." > nul ] == 0) |
+APPVER = 5.01 |
+!endif |
+ |
+# Win32 system with Microsoft Visual C/C++ |
+!include <win32.mak> |
+CC = $(cc) |
+CXX = $(cc) |
+CXXFLAGS = -nologo -EHsc -GR -DWIN32 -W3 -D_WINDOWS -DMAIN -DDLLMAIN -DHAVE_USB -DHAVE_LIBUSB10 -D_XKEYCHECK_H -DMYDLL_API\ |
+ -DVISUAL_CPLUSPLUS -I$(ROOTSYS)/include -Icvi -I. \ |
+ -wd4244 |
+#-FIw32pragma.h |
+LD = $(link) |
+ |
+!if "$(CFG)" == "Win32 Release" |
+CXXOPT = -O2 -arch:SSE2 -MD |
+LDOPT = -opt:ref |
+!elseif "$(CFG)" == "Win32 Debug" |
+!if "$(RUNTIME)" == "Debug" |
+CXXOPT = -Z7 -MDd |
+!else |
+CXXOPT = -Z7 -O2 -arch:SSE2 -MD |
+!endif |
+LDOPT = -debug |
+!endif |
+ |
+# Check if nmake version is 8.xx or 9.xx |
+!if ([nmake /? 2>&1 | findstr /c:"Version 8\." > nul ] == 0) || \ |
+ ([nmake /? 2>&1 | findstr /c:"Version 9\." > nul ] == 0) |
+MT_EXE = mt -nologo -manifest $@.manifest -outputresource:$@;1 |
+MT_DLL = mt -nologo -manifest $@.manifest -outputresource:$@;2 |
+EXTRAFLAGS = -D_CRT_SECURE_NO_DEPRECATE |
+!else if ([nmake /? 2>&1 | findstr /c:"Version 12\." > nul ] == 0) |
+MT_EXE = |
+MT_DLL = |
+EXTRAFLAGS = |
+!else if ([nmake /? 2>&1 | findstr /c:"Version 10\." > nul ] == 0) |
+EXTRAFLAGS = -D_CRT_SECURE_NO_DEPRECATE |
+!else if ([nmake /? 2>&1 | findstr /c:"Version 14\." > nul ] == 0) |
+EXTRAFLAGS = -D_CRT_SECURE_NO_DEPRECATE |
+!else |
+MT_EXE = |
+MT_DLL = |
+EXTRAFLAGS = -G5 |
+!endif |
+ |
+LDFLAGS1 = $(LDOPT) $(conlflags) -nologo -include:_G__cpp_setupG__Hist \ |
+ -include:_G__cpp_setupG__Graf -include:_G__cpp_setupG__G3D \ |
+ -include:_G__cpp_setupG__GPad -include:_G__cpp_setupG__Tree \ |
+ -include:_G__cpp_setupG__Rint -include:_G__cpp_setupG__PostScript \ |
+ -include:_G__cpp_setupG__Matrix -include:_G__cpp_setupG__Physics |
+ |
+LDFLAGS1 = $(LDOPT) $(conlflags) -nologo |
+ |
+SOFLAGS = $(dlllflags:-pdb:none=) |
+ROOTLIBS = $(ROOTSYS)\lib\libCore.lib \ |
+ $(ROOTSYS)\lib\libCint.lib $(ROOTSYS)\lib\libHist.lib \ |
+ $(ROOTSYS)\lib\libGraf.lib $(ROOTSYS)\lib\libGraf3d.lib \ |
+ $(ROOTSYS)\lib\libGpad.lib $(ROOTSYS)\lib\libTree.lib \ |
+ $(ROOTSYS)\lib\libRint.lib $(ROOTSYS)\lib\libPostscript.lib \ |
+ $(ROOTSYS)\lib\libMatrix.lib $(ROOTSYS)\lib\libPhysics.lib \ |
+ $(ROOTSYS)\lib\libNet.lib $(ROOTSYS)\lib\libRIO.lib \ |
+ $(ROOTSYS)\lib\libMathCore.lib |
+LIBS = libusb-1.0.lib |
+GLIBS = $(LIBS) $(ROOTSYS)\lib\libGui.lib $(ROOTSYS)\lib\libGraf.lib \ |
+ $(ROOTSYS)\lib\libGpad.lib |
+LIBSALL = libusb-1.0.lib |
+ |
+ |
+ |
+ |
+#------------------------------------------------------------------------------ |
+MYAPP = drscl$(ExeSuf) |
+MYAPPS = drscl.$(SrcSuf1) musbstd.$(SrcSuf) mxml.$(SrcSuf) strlcpy.$(SrcSuf) DRS.$(SrcSuf1) averager.$(SrcSuf1) |
+ |
+MYAPPO = drscl.$(ObjSuf) musbstd.$(ObjSuf) mxml.$(ObjSuf) strlcpy.$(ObjSuf) DRS.$(ObjSuf) averager.$(ObjSuf) |
+ |
+MYREADO = musbstd.$(ObjSuf) mxml.$(ObjSuf) DRS.$(ObjSuf) averager.$(ObjSuf) drsread.$(ObjSuf) XGetopt.$(ObjSuf) getopt_long.$(ObjSuf) timer.$(ObjSuf) gettimeofday.$(ObjSuf) |
+ |
+OBJS = $(MYAPPO) |
+PROGRAMS = $(MYAPP) |
+ |
+#------------------------------------------------------------------------------ |
+ |
+!message LDFLAGS = "$(LDFLAGS)" |
+!message MYAPP = "$(MYAPP)" |
+!message MYAPPO = "$(MYAPPO)" |
+!message PROGRAMS = "$(PROGRAMS)" |
+ |
+ |
+all: $(PROGRAMS) drsread.exe drsread.dll |
+ |
+ |
+ |
+RootShowerDict.$(SrcSuf): MyParticle.h MyDetector.h MyEvent.h RSLinkDef.h |
+ @echo "Generating dictionary $@..." |
+ @rootcint -f $@ -c MyParticle.h MyDetector.h MyEvent.h RSLinkDef.h |
+ |
+#------------------------------------------------------------------------------ |
+ |
+clean: |
+ @del *.obj *Dict.* *.def *.exp *.d *.log .def *.pdb *.ilk *.manifest |
+ |
+distclean: clean |
+ @del *.exe *.root *.ps *.lib *.dll |
+ |
+$(MYAPP): $(MYAPPO) |
+ @echo "Compiling $@ " |
+ $(LD) $(LDFLAGS) /SUBSYSTEM:CONSOLE \ |
+ $(MYAPPO) $(LIBSALL) $(OutPutOpt)$@ |
+ @echo "$@ done" |
+ |
+drscl.$(ObjSuf): drscl.$(SrcSuf1) |
+ @echo "Compiling drs $@ " |
+ $(CXX) $(CXXFLAGS) $(EXTRAFLAGS) $(CXXOPT) -c drscl.$(SrcSuf1) |
+ |
+drsread.exe: $(MYREADO) |
+ @echo "Compiling $@ " |
+ $(LD) $(LDFLAGS) /SUBSYSTEM:CONSOLE \ |
+ $(MYREADO) $(LIBSALL) $(ROOTLIBS) $(OutPutOpt)$@ |
+ @echo "$@ done" |
+ |
+drsread.dll: $(MYREADO) |
+ @echo "DLL library $@ " |
+ $(LD) /DLL $(MYREADO) $(LIBSALL) $(ROOTLIBS) /OUT:drsread.dll |
+ @echo "$@ done" |
+ |
+ |
+drsreadDict.cpp: drsread.h LinkDef.h |
+ rootcint -f drsreadDict.cpp -c drsread.h LinkDef.h |
+ |
+drsread.$(ObjSuf): drsread.$(SrcSuf1) |
+ @echo "Compiling drsread $@ " |
+ $(CXX) $(CXXFLAGS) $(EXTRAFLAGS) $(CXXOPT) -c drsread.$(SrcSuf1) |
+ |
+drsread.$(ObjSuf): drsread.$(SrcSuf1) |
+ @echo "Compiling drsread $@ " |
+ $(CXX) $(CXXFLAGS) $(EXTRAFLAGS) $(CXXOPT) -c drsread.$(SrcSuf1) |
+ |
+ |
+.$(SrcSuf1).$(ObjSuf): |
+ @echo "Compiling object $@ " |
+ $(CXX) $(CXXFLAGS) $(EXTRAFLAGS) $(CXXOPT) -c $< |
+ |
+.c.$(ObjSuf): |
+ @echo "Compiling object $@ " |
+ $(CXX) $(CXXFLAGS) $(EXTRAFLAGS) $(CXXOPT) -c $< |
+ |
Index: instr/drs/XGetopt.cpp |
=================================================================== |
--- instr/drs/XGetopt.cpp (nonexistent) |
+++ instr/drs/XGetopt.cpp (revision 197) |
@@ -0,0 +1,225 @@ |
+// XGetopt.cpp Version 1.2 |
+// |
+// Author: Hans Dietrich |
+// hdietrich2@hotmail.com |
+// |
+// Description: |
+// XGetopt.cpp implements getopt(), a function to parse command lines. |
+// |
+// History |
+// Version 1.2 - 2003 May 17 |
+// - Added Unicode support |
+// |
+// Version 1.1 - 2002 March 10 |
+// - Added example to XGetopt.cpp module header |
+// |
+// This software is released into the public domain. |
+// You are free to use it in any way you like. |
+// |
+// This software is provided "as is" with no expressed |
+// or implied warranty. I accept no liability for any |
+// damage or loss of business that this software may cause. |
+// |
+/////////////////////////////////////////////////////////////////////////////// |
+ |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+// if you are using precompiled headers then include this line: |
+//#include "stdafx.h" |
+/////////////////////////////////////////////////////////////////////////////// |
+ |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+// if you are not using precompiled headers then include these lines: |
+#include <windows.h> |
+#include <stdio.h> |
+#include <tchar.h> |
+/////////////////////////////////////////////////////////////////////////////// |
+ |
+ |
+#include "XGetopt.h" |
+ |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+// |
+// X G e t o p t . c p p |
+// |
+// |
+// NAME |
+// getopt -- parse command line options |
+// |
+// SYNOPSIS |
+// int getopt(int argc, TCHAR *argv[], TCHAR *optstring) |
+// |
+// extern TCHAR *optarg; |
+// extern int optind; |
+// |
+// DESCRIPTION |
+// The getopt() function parses the command line arguments. Its |
+// arguments argc and argv are the argument count and array as |
+// passed into the application on program invocation. In the case |
+// of Visual C++ programs, argc and argv are available via the |
+// variables __argc and __argv (double underscores), respectively. |
+// getopt returns the next option letter in argv that matches a |
+// letter in optstring. (Note: Unicode programs should use |
+// __targv instead of __argv. Also, all character and string |
+// literals should be enclosed in _T( ) ). |
+// |
+// optstring is a string of recognized option letters; if a letter |
+// is followed by a colon, the option is expected to have an argument |
+// that may or may not be separated from it by white space. optarg |
+// is set to point to the start of the option argument on return from |
+// getopt. |
+// |
+// Option letters may be combined, e.g., "-ab" is equivalent to |
+// "-a -b". Option letters are case sensitive. |
+// |
+// getopt places in the external variable optind the argv index |
+// of the next argument to be processed. optind is initialized |
+// to 0 before the first call to getopt. |
+// |
+// When all options have been processed (i.e., up to the first |
+// non-option argument), getopt returns EOF, optarg will point |
+// to the argument, and optind will be set to the argv index of |
+// the argument. If there are no non-option arguments, optarg |
+// will be set to NULL. |
+// |
+// The special option "--" may be used to delimit the end of the |
+// options; EOF will be returned, and "--" (and everything after it) |
+// will be skipped. |
+// |
+// RETURN VALUE |
+// For option letters contained in the string optstring, getopt |
+// will return the option letter. getopt returns a question mark (?) |
+// when it encounters an option letter not included in optstring. |
+// EOF is returned when processing is finished. |
+// |
+// BUGS |
+// 1) Long options are not supported. |
+// 2) The GNU double-colon extension is not supported. |
+// 3) The environment variable POSIXLY_CORRECT is not supported. |
+// 4) The + syntax is not supported. |
+// 5) The automatic permutation of arguments is not supported. |
+// 6) This implementation of getopt() returns EOF if an error is |
+// encountered, instead of -1 as the latest standard requires. |
+// |
+// EXAMPLE |
+// BOOL CMyApp::ProcessCommandLine(int argc, TCHAR *argv[]) |
+// { |
+// int c; |
+// |
+// while ((c = getopt(argc, argv, _T("aBn:"))) != EOF) |
+// { |
+// switch (c) |
+// { |
+// case _T('a'): |
+// TRACE(_T("option a\n")); |
+// // |
+// // set some flag here |
+// // |
+// break; |
+// |
+// case _T('B'): |
+// TRACE( _T("option B\n")); |
+// // |
+// // set some other flag here |
+// // |
+// break; |
+// |
+// case _T('n'): |
+// TRACE(_T("option n: value=%d\n"), atoi(optarg)); |
+// // |
+// // do something with value here |
+// // |
+// break; |
+// |
+// case _T('?'): |
+// TRACE(_T("ERROR: illegal option %s\n"), argv[optind-1]); |
+// return FALSE; |
+// break; |
+// |
+// default: |
+// TRACE(_T("WARNING: no handler for option %c\n"), c); |
+// return FALSE; |
+// break; |
+// } |
+// } |
+// // |
+// // check for non-option args here |
+// // |
+// return TRUE; |
+// } |
+// |
+/////////////////////////////////////////////////////////////////////////////// |
+ |
+//TCHAR *optarg; // global argument pointer |
+char *optarg; // global argument pointer |
+int optind = 0; // global argv index |
+ |
+//int getopt(int argc, TCHAR *argv[], TCHAR *optstring) |
+int getopt(int argc, char *argv[], char *optstring) |
+{ |
+ //static TCHAR *next = NULL; |
+ static char *next = NULL; |
+ if (optind == 0) |
+ next = NULL; |
+ |
+ optarg = NULL; |
+ |
+ if (next == NULL || *next == _T('\0')) |
+ { |
+ if (optind == 0) |
+ optind++; |
+ |
+ if (optind >= argc || argv[optind][0] != _T('-') || argv[optind][1] == _T('\0')) |
+ { |
+ optarg = NULL; |
+ if (optind < argc) |
+ optarg = argv[optind]; |
+ return EOF; |
+ } |
+ |
+ if (strcmp( argv[optind], _T("--")) == 0) |
+ { |
+ optind++; |
+ optarg = NULL; |
+ if (optind < argc) |
+ optarg = argv[optind]; |
+ return EOF; |
+ } |
+ |
+ next = argv[optind]; |
+ next++; // skip past - |
+ optind++; |
+ } |
+ |
+ //TCHAR c = *next++; |
+ //TCHAR *cp = _tcschr(optstring, c); |
+ char c = *next++; |
+ //char *cp = _tcschr(optstring, c); |
+ char *cp =strchr(optstring, c); |
+ |
+ if (cp == NULL || c == _T(':')) |
+ return _T('?'); |
+ |
+ cp++; |
+ if (*cp == _T(':')) |
+ { |
+ if (*next != _T('\0')) |
+ { |
+ optarg = next; |
+ next = NULL; |
+ } |
+ else if (optind < argc) |
+ { |
+ optarg = argv[optind]; |
+ optind++; |
+ } |
+ else |
+ { |
+ return _T('?'); |
+ } |
+ } |
+ |
+ return c; |
+} |
Index: instr/drs/XGetopt.h |
=================================================================== |
--- instr/drs/XGetopt.h (nonexistent) |
+++ instr/drs/XGetopt.h (revision 197) |
@@ -0,0 +1,25 @@ |
+// XGetopt.h Version 1.2 |
+// |
+// Author: Hans Dietrich |
+// hdietrich2@hotmail.com |
+// |
+// This software is released into the public domain. |
+// You are free to use it in any way you like. |
+// |
+// This software is provided "as is" with no expressed |
+// or implied warranty. I accept no liability for any |
+// damage or loss of business that this software may cause. |
+// |
+/////////////////////////////////////////////////////////////////////////////// |
+ |
+#ifndef XGETOPT_H |
+#define XGETOPT_H |
+ |
+extern int optind, opterr; |
+//extern TCHAR *optarg; |
+extern char *optarg; |
+ |
+//int getopt(int argc, TCHAR *argv[], TCHAR *optstring); |
+int getopt(int argc, char *argv[], char *optstring); |
+ |
+#endif //XGETOPT_H |
Index: instr/drs/averager.cpp |
=================================================================== |
--- instr/drs/averager.cpp (nonexistent) |
+++ instr/drs/averager.cpp (revision 197) |
@@ -0,0 +1,214 @@ |
+/********************************************************************\ |
+ |
+ Name: averager.cpp |
+ Created by: Stefan Ritt |
+ |
+ Contents: Robust averager |
+ |
+ $Id: averager.cpp 21210 2013-12-12 11:36:59Z ritt $ |
+ |
+\********************************************************************/ |
+ |
+#include <stdio.h> |
+#include <stdlib.h> |
+#include <string.h> |
+#include <math.h> |
+#include <assert.h> |
+ |
+#include "averager.h" |
+ |
+/*----------------------------------------------------------------*/ |
+ |
+Averager::Averager(int nx, int ny, int nz, int dim) |
+{ |
+ fNx = nx; |
+ fNy = ny; |
+ fNz = nz; |
+ fDim = dim; |
+ |
+ int size = sizeof(float)*nx*ny*nz * dim; |
+ fArray = (float *)malloc(size); |
+ assert(fArray); |
+ memset(fArray, 0, size); |
+ size = sizeof(float)*nx*ny*nz; |
+ fN = (unsigned short *)malloc(size); |
+ assert(fN); |
+ memset(fN, 0, size); |
+} |
+ |
+/*----------------------------------------------------------------*/ |
+ |
+Averager::~Averager() |
+{ |
+ if (fN) |
+ free(fN); |
+ if (fArray) |
+ free(fArray); |
+ fN = NULL; |
+ fArray = NULL; |
+} |
+ |
+/*----------------------------------------------------------------*/ |
+ |
+void Averager::Add(int x, int y, int z, float value) |
+{ |
+ assert(x < fNx); |
+ assert(y < fNy); |
+ assert(z < fNz); |
+ |
+ int nIndex = (x*fNy + y)*fNz + z; |
+ if (fN[nIndex] == fDim - 1) // check if array full |
+ return; |
+ |
+ int aIndex = ((x*fNy + y)*fNz + z) * fDim + fN[nIndex]; |
+ fN[nIndex]++; |
+ fArray[aIndex] = value; |
+} |
+ |
+/*----------------------------------------------------------------*/ |
+ |
+void Averager::Reset() |
+{ |
+ int size = sizeof(float)*fNx*fNy*fNz * fDim; |
+ memset(fArray, 0, size); |
+ size = sizeof(float)*fNx*fNy*fNz; |
+ memset(fN, 0, size); |
+} |
+ |
+/*----------------------------------------------------------------*/ |
+ |
+int compar(const void *a, const void *b); |
+ |
+int compar(const void *a, const void *b) |
+{ |
+ if (*((float *)a) == *((float *)b)) |
+ return 0; |
+ |
+ return (*((float *)a) < *((float *)b)) ? -1 : 1; |
+} |
+ |
+double Averager::Average(int x, int y, int z) |
+{ |
+ assert(x < fNx); |
+ assert(y < fNy); |
+ assert(z < fNz); |
+ |
+ double a = 0; |
+ |
+ int nIndex = (x*fNy + y)*fNz + z; |
+ int aIndex = ((x*fNy + y)*fNz + z) * fDim; |
+ |
+ for (int i=0 ; i<fN[nIndex] ; i++) |
+ a += fArray[aIndex + i]; |
+ |
+ if (fN[nIndex] > 0) |
+ a /= fN[nIndex]; |
+ |
+ return a; |
+} |
+ |
+/*----------------------------------------------------------------*/ |
+ |
+double Averager::Median(int x, int y, int z) |
+{ |
+ assert(x < fNx); |
+ assert(y < fNy); |
+ assert(z < fNz); |
+ |
+ double m = 0; |
+ |
+ int nIndex = (x*fNy + y)*fNz + z; |
+ int aIndex = ((x*fNy + y)*fNz + z) * fDim; |
+ |
+ qsort(&fArray[aIndex], fN[nIndex], sizeof(float), compar); |
+ m = fArray[aIndex + fN[nIndex]/2]; |
+ |
+ return m; |
+} |
+ |
+/*----------------------------------------------------------------*/ |
+ |
+double Averager::RobustAverage(double range, int x, int y, int z) |
+{ |
+ assert(x < fNx); |
+ assert(y < fNy); |
+ assert(z < fNz); |
+ |
+ double ra = 0; |
+ int n = 0; |
+ double m = Median(x, y, z); |
+ |
+ int nIndex = (x*fNy + y)*fNz + z; |
+ int aIndex = ((x*fNy + y)*fNz + z) * fDim; |
+ |
+ for (int i=0 ; i<fN[nIndex] ; i++) { |
+ if (fArray[aIndex + i] > m - range && fArray[aIndex + i] < m + range) { |
+ ra += fArray[aIndex + i]; |
+ n++; |
+ } |
+ } |
+ |
+ if (n > 0) |
+ ra /= n; |
+ |
+ //if (y == 0 && z == 7 && fN[nIndex] > 10) |
+ // printf("%d %lf %lf %lf\n", fN[nIndex], a, m, ra); |
+ |
+ return ra; |
+} |
+ |
+/*----------------------------------------------------------------*/ |
+ |
+int Averager::SaveNormalizedDistribution(const char *filename, int x, float range) |
+{ |
+ assert(x < fNx); |
+ FILE *f = fopen(filename, "wt"); |
+ |
+ if (!f) |
+ return 0; |
+ |
+ fprintf(f, "X, Y, Z, Min, Max, Ave, Sigma\n"); |
+ |
+ for (int y=0 ; y<fNy ; y++) |
+ for (int z=0 ; z<fNz ; z++) { |
+ |
+ int nIndex = (x*fNy + y)*fNz + z; |
+ int aIndex = ((x*fNy + y)*fNz + z) * fDim; |
+ |
+ if (fN[nIndex] > 1) { |
+ fprintf(f, "%d,%d, %d, ", x, y, z); |
+ |
+ double s = 0; |
+ double s2 = 0; |
+ double min = 0; |
+ double max = 0; |
+ int n = fN[nIndex]; |
+ double m = Median(x, y, z); |
+ |
+ for (int i=0 ; i<n ; i++) { |
+ double v = fArray[aIndex + i] - m; |
+ s += v; |
+ s2 += v*v; |
+ if (v < min) |
+ min = v; |
+ if (v > max) |
+ max = v; |
+ } |
+ double sigma = sqrt((n * s2 - s * s) / (n * (n-1))); |
+ double average = s / n; |
+ |
+ fprintf(f, "%3.1lf, %3.1lf, %3.1lf, %3.3lf, ", min, max, average, sigma); |
+ |
+ if (min < -range || max > range) { |
+ for (int i=0 ; i<n ; i++) |
+ fprintf(f, "%3.1lf,", fArray[aIndex + i] - m); |
+ } |
+ |
+ fprintf(f, "\n"); |
+ } |
+ } |
+ |
+ fclose(f); |
+ return 1; |
+} |
+ |
Index: instr/drs/averager.h |
=================================================================== |
--- instr/drs/averager.h (nonexistent) |
+++ instr/drs/averager.h (revision 197) |
@@ -0,0 +1,28 @@ |
+/********************************************************************\ |
+ |
+ Name: averager.h |
+ Created by: Stefan Ritt |
+ |
+ Contents: Robust averager |
+ |
+ $Id: averager.h 21220 2013-12-20 13:47:43Z ritt $ |
+ |
+\********************************************************************/ |
+ |
+class Averager { |
+ int fNx, fNy, fNz, fDim; |
+ float *fArray; |
+ unsigned short *fN; |
+ |
+public: |
+ Averager(int nx, int ny, int nz, int dim); |
+ ~Averager(); |
+ |
+ void Add(int x, int y, int z, float value); |
+ void Reset(); |
+ double Average(int x, int y, int z); |
+ double Median(int x, int y, int z); |
+ double RobustAverage(double range, int x, int y, int z); |
+ int SaveNormalizedDistribution(const char *filename, int x, float range); |
+ |
+}; |
Index: instr/drs/daq.h |
=================================================================== |
--- instr/drs/daq.h (nonexistent) |
+++ instr/drs/daq.h (revision 197) |
@@ -0,0 +1,18 @@ |
+#ifndef _daq_h_ |
+#define _daq_h_ |
+ |
+#define BUFF_L 2048 |
+class daq { |
+public: |
+ unsigned long stackwrite[BUFF_L],stackdata[10000],stackdump[27000]; |
+int debug; |
+int fStop; |
+int event(unsigned int *, int); |
+int init(); |
+int connect(); |
+int disconnect(); |
+daq(); |
+~daq(); |
+}; |
+ |
+#endif |
Index: instr/drs/drs.h |
=================================================================== |
--- instr/drs/drs.h (nonexistent) |
+++ instr/drs/drs.h (revision 197) |
@@ -0,0 +1,950 @@ |
+/******************************************************************** |
+ DRS.h, S.Ritt, M. Schneebeli - PSI |
+ |
+ $Id: DRS.h 21309 2014-04-11 14:51:29Z ritt $ |
+ |
+********************************************************************/ |
+#ifndef DRS_H |
+#define DRS_H |
+#include <stdio.h> |
+#include <string.h> |
+#include "averager.h" |
+ |
+#ifdef HAVE_LIBUSB |
+# ifndef HAVE_USB |
+# define HAVE_USB |
+# endif |
+#endif |
+ |
+#ifdef HAVE_USB |
+# include "musbstd.h" |
+#endif // HAVE_USB |
+ |
+#ifdef HAVE_VME |
+# include <mvmestd.h> |
+#endif // HAVE_VME |
+ |
+/* disable "deprecated" warning */ |
+#ifdef _MSC_VER |
+#pragma warning(disable: 4996) |
+#endif |
+ |
+#ifndef NULL |
+#define NULL 0 |
+#endif |
+ |
+int drs_kbhit(); |
+unsigned int millitime(); |
+ |
+/* transport mode */ |
+#define TR_VME 1 |
+#define TR_USB 2 |
+#define TR_USB2 3 |
+ |
+/* address types */ |
+#ifndef T_CTRL |
+#define T_CTRL 1 |
+#define T_STATUS 2 |
+#define T_RAM 3 |
+#define T_FIFO 4 |
+#endif |
+ |
+/*---- Register addresses ------------------------------------------*/ |
+ |
+#define REG_CTRL 0x00000 /* 32 bit control reg */ |
+#define REG_DAC_OFS 0x00004 |
+#define REG_DAC0 0x00004 |
+#define REG_DAC1 0x00006 |
+#define REG_DAC2 0x00008 |
+#define REG_DAC3 0x0000A |
+#define REG_DAC4 0x0000C |
+#define REG_DAC5 0x0000E |
+#define REG_DAC6 0x00010 |
+#define REG_DAC7 0x00012 |
+#define REG_CHANNEL_CONFIG 0x00014 // low byte |
+#define REG_CONFIG 0x00014 // high byte |
+#define REG_CHANNEL_MODE 0x00016 |
+#define REG_ADCCLK_PHASE 0x00016 |
+#define REG_FREQ_SET_HI 0x00018 // DRS2 |
+#define REG_FREQ_SET_LO 0x0001A // DRS2 |
+#define REG_TRG_DELAY 0x00018 // DRS4 |
+#define REG_FREQ_SET 0x0001A // DRS4 |
+#define REG_TRIG_DELAY 0x0001C |
+#define REG_LMK_MSB 0x0001C // DRS4 Mezz |
+#define REG_CALIB_TIMING 0x0001E // DRS2 |
+#define REG_EEPROM_PAGE_EVAL 0x0001E // DRS4 Eval |
+#define REG_EEPROM_PAGE_MEZZ 0x0001A // DRS4 Mezz |
+#define REG_TRG_CONFIG 0x0001C // DRS4 Eval4 |
+#define REG_LMK_LSB 0x0001E // DRS4 Mezz |
+#define REG_WARMUP 0x00020 // DRS4 Mezz |
+#define REG_COOLDOWN 0x00022 // DRS4 Mezz |
+#define REG_READ_POINTER 0x00026 // DRS4 Mezz |
+ |
+#define REG_MAGIC 0x00000 |
+#define REG_BOARD_TYPE 0x00002 |
+#define REG_STATUS 0x00004 |
+#define REG_RDAC_OFS 0x0000E |
+#define REG_RDAC0 0x00008 |
+#define REG_STOP_CELL0 0x00008 |
+#define REG_RDAC1 0x0000A |
+#define REG_STOP_CELL1 0x0000A |
+#define REG_RDAC2 0x0000C |
+#define REG_STOP_CELL2 0x0000C |
+#define REG_RDAC3 0x0000E |
+#define REG_STOP_CELL3 0x0000E |
+#define REG_RDAC4 0x00000 |
+#define REG_RDAC5 0x00002 |
+#define REG_STOP_WSR0 0x00010 |
+#define REG_STOP_WSR1 0x00011 |
+#define REG_STOP_WSR2 0x00012 |
+#define REG_STOP_WSR3 0x00013 |
+#define REG_RDAC6 0x00014 |
+#define REG_RDAC7 0x00016 |
+#define REG_EVENTS_IN_FIFO 0x00018 |
+#define REG_EVENT_COUNT 0x0001A |
+#define REG_FREQ1 0x0001C |
+#define REG_FREQ2 0x0001E |
+#define REG_WRITE_POINTER 0x0001E |
+#define REG_TEMPERATURE 0x00020 |
+#define REG_TRIGGER_BUS 0x00022 |
+#define REG_SERIAL_BOARD 0x00024 |
+#define REG_VERSION_FW 0x00026 |
+#define REG_SCALER0 0x00028 |
+#define REG_SCALER1 0x0002C |
+#define REG_SCALER2 0x00030 |
+#define REG_SCALER3 0x00034 |
+#define REG_SCALER4 0x00038 |
+#define REG_SCALER5 0x0003C |
+ |
+/*---- Control register bit definitions ----------------------------*/ |
+ |
+#define BIT_START_TRIG (1<<0) // write a "1" to start domino wave |
+#define BIT_REINIT_TRIG (1<<1) // write a "1" to stop & reset DRS |
+#define BIT_SOFT_TRIG (1<<2) // write a "1" to stop and read data to RAM |
+#define BIT_EEPROM_WRITE_TRIG (1<<3) // write a "1" to write into serial EEPROM |
+#define BIT_EEPROM_READ_TRIG (1<<4) // write a "1" to read from serial EEPROM |
+#define BIT_MULTI_BUFFER (1<<16) // Use multi buffering when "1" |
+#define BIT_DMODE (1<<17) // (*DRS2*) 0: single shot, 1: circular |
+#define BIT_ADC_ACTIVE (1<<17) // (*DRS4*) 0: stop ADC when running, 1: ADC always clocked |
+#define BIT_LED (1<<18) // 1=on, 0=blink during readout |
+#define BIT_TCAL_EN (1<<19) // switch on (1) / off (0) for 33 MHz calib signal |
+#define BIT_TCAL_SOURCE (1<<20) |
+#define BIT_REFCLK_SOURCE (1<<20) |
+#define BIT_FREQ_AUTO_ADJ (1<<21) // DRS2/3 |
+#define BIT_TRANSP_MODE (1<<21) // DRS4 |
+#define BIT_ENABLE_TRIGGER1 (1<<22) // External LEMO/FP/TRBUS trigger |
+#define BIT_LONG_START_PULSE (1<<23) // (*DRS2*) 0:short start pulse (>0.8GHz), 1:long start pulse (<0.8GHz) |
+#define BIT_READOUT_MODE (1<<23) // (*DRS3*,*DRS4*) 0:start from first bin, 1:start from domino stop |
+#define BIT_DELAYED_START (1<<24) // DRS2: start domino wave 400ns after soft trigger, used for waveform |
+ // generator startup |
+#define BIT_NEG_TRIGGER (1<<24) // DRS4: use high-to-low trigger if set |
+#define BIT_ACAL_EN (1<<25) // connect DRS to inputs (0) or to DAC6 (1) |
+#define BIT_TRIGGER_DELAYED (1<<26) // select delayed trigger from trigger bus |
+#define BIT_ADCCLK_INVERT (1<<26) // invert ADC clock |
+#define BIT_REFCLK_EXT (1<<26) // use external MMCX CLKIN refclk |
+#define BIT_DACTIVE (1<<27) // keep domino wave running during readout |
+#define BIT_STANDBY_MODE (1<<28) // put chip in standby mode |
+#define BIT_TR_SOURCE1 (1<<29) // trigger source selection bits |
+#define BIT_DECIMATION (1<<29) // drop all odd samples (DRS4 mezz.) |
+#define BIT_TR_SOURCE2 (1<<30) // trigger source selection bits |
+#define BIT_ENABLE_TRIGGER2 (1<<31) // analog threshold (internal) trigger |
+ |
+/* DRS4 configuration register bit definitions */ |
+#define BIT_CONFIG_DMODE (1<<8) // 0: single shot, 1: circular |
+#define BIT_CONFIG_PLLEN (1<<9) // write a "1" to enable the internal PLL |
+#define BIT_CONFIG_WSRLOOP (1<<10) // write a "1" to connect WSROUT to WSRIN internally |
+ |
+/*---- Status register bit definitions -----------------------------*/ |
+ |
+#define BIT_RUNNING (1<<0) // one if domino wave running or readout in progress |
+#define BIT_NEW_FREQ1 (1<<1) // one if new frequency measurement available |
+#define BIT_NEW_FREQ2 (1<<2) |
+#define BIT_PLL_LOCKED0 (1<<1) // 1 if PLL has locked (DRS4 evaluation board only) |
+#define BIT_PLL_LOCKED1 (1<<2) // 1 if PLL DRS4 B has locked (DRS4 mezzanine board only) |
+#define BIT_PLL_LOCKED2 (1<<3) // 1 if PLL DRS4 C has locked (DRS4 mezzanine board only) |
+#define BIT_PLL_LOCKED3 (1<<4) // 1 if PLL DRS4 D has locked (DRS4 mezzanine board only) |
+#define BIT_SERIAL_BUSY (1<<5) // 1 if EEPROM operation in progress |
+#define BIT_LMK_LOCKED (1<<6) // 1 if PLL of LMK chip has locked (DRS4 mezzanine board only) |
+#define BIT_2048_MODE (1<<7) // 1 if 2048-bin mode has been soldered |
+ |
+enum DRSBoardConstants { |
+ kNumberOfChannelsMax = 10, |
+ kNumberOfCalibChannelsV3 = 10, |
+ kNumberOfCalibChannelsV4 = 8, |
+ kNumberOfBins = 1024, |
+ kNumberOfChipsMax = 4, |
+ kFrequencyCacheSize = 10, |
+ kBSplineOrder = 4, |
+ kPreCaliculatedBSplines = 1000, |
+ kPreCaliculatedBSplineGroups = 5, |
+ kNumberOfADCBins = 4096, |
+ kBSplineXMinOffset = 20, |
+ kMaxNumberOfClockCycles = 100, |
+}; |
+ |
+enum DRSErrorCodes { |
+ kSuccess = 0, |
+ kInvalidTriggerSignal = -1, |
+ kWrongChannelOrChip = -2, |
+ kInvalidTransport = -3, |
+ kZeroSuppression = -4, |
+ kWaveNotAvailable = -5 |
+}; |
+ |
+/*---- callback class ----*/ |
+ |
+class DRSCallback |
+{ |
+public: |
+ virtual void Progress(int value) = 0; |
+ virtual ~DRSCallback() {}; |
+}; |
+ |
+/*------------------------*/ |
+ |
+class DRSBoard; |
+ |
+class ResponseCalibration { |
+protected: |
+ |
+ class CalibrationData { |
+ public: |
+ class CalibrationDataChannel { |
+ public: |
+ unsigned char fLimitGroup[kNumberOfBins]; //! |
+ float fMin[kNumberOfBins]; //! |
+ float fRange[kNumberOfBins]; //! |
+ short fOffset[kNumberOfBins]; //! |
+ short fGain[kNumberOfBins]; //! |
+ unsigned short fOffsetADC[kNumberOfBins]; //! |
+ short *fData[kNumberOfBins]; //! |
+ unsigned char *fLookUp[kNumberOfBins]; //! |
+ unsigned short fLookUpOffset[kNumberOfBins]; //! |
+ unsigned char fNumberOfLookUpPoints[kNumberOfBins]; //! |
+ float *fTempData; //! |
+ |
+ private: |
+ CalibrationDataChannel(const CalibrationDataChannel &c); // not implemented |
+ CalibrationDataChannel &operator=(const CalibrationDataChannel &rhs); // not implemented |
+ |
+ public: |
+ CalibrationDataChannel(int numberOfGridPoints) |
+ :fTempData(new float[numberOfGridPoints]) { |
+ int i; |
+ for (i = 0; i < kNumberOfBins; i++) { |
+ fData[i] = new short[numberOfGridPoints]; |
+ } |
+ memset(fLimitGroup, 0, sizeof(fLimitGroup)); |
+ memset(fMin, 0, sizeof(fMin)); |
+ memset(fRange, 0, sizeof(fRange)); |
+ memset(fOffset, 0, sizeof(fOffset)); |
+ memset(fGain, 0, sizeof(fGain)); |
+ memset(fOffsetADC, 0, sizeof(fOffsetADC)); |
+ memset(fLookUp, 0, sizeof(fLookUp)); |
+ memset(fLookUpOffset, 0, sizeof(fLookUpOffset)); |
+ memset(fNumberOfLookUpPoints, 0, sizeof(fNumberOfLookUpPoints)); |
+ } |
+ ~CalibrationDataChannel() { |
+ int i; |
+ delete fTempData; |
+ for (i = 0; i < kNumberOfBins; i++) { |
+ delete fData[i]; |
+ delete fLookUp[i]; |
+ } |
+ } |
+ }; |
+ |
+ bool fRead; //! |
+ CalibrationDataChannel *fChannel[10]; //! |
+ unsigned char fNumberOfGridPoints; //! |
+ int fHasOffsetCalibration; //! |
+ float fStartTemperature; //! |
+ float fEndTemperature; //! |
+ int *fBSplineOffsetLookUp[kNumberOfADCBins]; //! |
+ float **fBSplineLookUp[kNumberOfADCBins]; //! |
+ float fMin; //! |
+ float fMax; //! |
+ unsigned char fNumberOfLimitGroups; //! |
+ static float fIntRevers[2 * kBSplineOrder - 2]; |
+ |
+ private: |
+ CalibrationData(const CalibrationData &c); // not implemented |
+ CalibrationData &operator=(const CalibrationData &rhs); // not implemented |
+ |
+ public: |
+ CalibrationData(int numberOfGridPoints); |
+ ~CalibrationData(); |
+ static int CalculateBSpline(int nGrid, float value, float *bsplines); |
+ void PreCalculateBSpline(); |
+ void DeletePreCalculatedBSpline(); |
+ }; |
+ |
+ // General Fields |
+ DRSBoard *fBoard; |
+ |
+ double fPrecision; |
+ |
+ // Fields for creating the Calibration |
+ bool fInitialized; |
+ bool fRecorded; |
+ bool fFitted; |
+ bool fOffset; |
+ bool fCalibrationValid[2]; |
+ |
+ int fNumberOfPointsLowVolt; |
+ int fNumberOfPoints; |
+ int fNumberOfMode2Bins; |
+ int fNumberOfSamples; |
+ int fNumberOfGridPoints; |
+ int fNumberOfXConstPoints; |
+ int fNumberOfXConstGridPoints; |
+ double fTriggerFrequency; |
+ int fShowStatistics; |
+ FILE *fCalibFile; |
+ |
+ int fCurrentLowVoltPoint; |
+ int fCurrentPoint; |
+ int fCurrentSample; |
+ int fCurrentFitChannel; |
+ int fCurrentFitBin; |
+ |
+ float *fResponseX[10][kNumberOfBins]; |
+ float *fResponseY; |
+ unsigned short **fWaveFormMode3[10]; |
+ unsigned short **fWaveFormMode2[10]; |
+ short **fWaveFormOffset[10]; |
+ unsigned short **fWaveFormOffsetADC[10]; |
+ unsigned short *fSamples; |
+ int *fSampleUsed; |
+ |
+ float *fPntX[2]; |
+ float *fPntY[2]; |
+ float *fUValues[2]; |
+ float *fRes[kNumberOfBins]; |
+ float *fResX[kNumberOfBins]; |
+ |
+ double *fXXFit; |
+ double *fYYFit; |
+ double *fWWFit; |
+ double *fYYFitRes; |
+ double *fYYSave; |
+ double *fXXSave; |
+ double fGainMin; |
+ double fGainMax; |
+ |
+ float **fStatisticsApprox; |
+ float **fStatisticsApproxExt; |
+ |
+ // Fields for applying the Calibration |
+ CalibrationData *fCalibrationData[kNumberOfChipsMax]; |
+ |
+private: |
+ ResponseCalibration(const ResponseCalibration &c); // not implemented |
+ ResponseCalibration &operator=(const ResponseCalibration &rhs); // not implemented |
+ |
+public: |
+ ResponseCalibration(DRSBoard* board); |
+ ~ResponseCalibration(); |
+ |
+ void SetCalibrationParameters(int numberOfPointsLowVolt, int numberOfPoints, int numberOfMode2Bins, |
+ int numberOfSamples, int numberOfGridPoints, int numberOfXConstPoints, |
+ int numberOfXConstGridPoints, double triggerFrequency, int showStatistics = 0); |
+ void ResetCalibration(); |
+ bool RecordCalibrationPoints(int chipNumber); |
+ bool RecordCalibrationPointsV3(int chipNumber); |
+ bool RecordCalibrationPointsV4(int chipNumber); |
+ bool FitCalibrationPoints(int chipNumber); |
+ bool FitCalibrationPointsV3(int chipNumber); |
+ bool FitCalibrationPointsV4(int chipNumber); |
+ bool OffsetCalibration(int chipNumber); |
+ bool OffsetCalibrationV3(int chipNumber); |
+ bool OffsetCalibrationV4(int chipNumber); |
+ double GetTemperature(unsigned int chipIndex); |
+ |
+ bool WriteCalibration(unsigned int chipIndex); |
+ bool WriteCalibrationV3(unsigned int chipIndex); |
+ bool WriteCalibrationV4(unsigned int chipIndex); |
+ bool ReadCalibration(unsigned int chipIndex); |
+ bool ReadCalibrationV3(unsigned int chipIndex); |
+ bool ReadCalibrationV4(unsigned int chipIndex); |
+ bool Calibrate(unsigned int chipIndex, unsigned int channel, unsigned short *adcWaveform, short *uWaveform, |
+ int triggerCell, float threshold, bool offsetCalib); |
+ bool SubtractADCOffset(unsigned int chipIndex, unsigned int channel, unsigned short *adcWaveform, |
+ unsigned short *adcCalibratedWaveform, unsigned short newBaseLevel); |
+ bool IsRead(int chipIndex) const { return fCalibrationValid[chipIndex]; } |
+ double GetPrecision() const { return fPrecision; }; |
+ |
+ double GetOffsetAt(int chip,int chn,int bin) const { return fCalibrationData[chip]->fChannel[chn]->fOffset[bin]; }; |
+ double GetGainAt(int chip,int chn,int bin) const { return fCalibrationData[chip]->fChannel[chn]->fGain[bin]; }; |
+ double GetMeasPointXAt(int ip) const { return fXXSave[ip]; }; |
+ double GetMeasPointYAt(int ip) const { return fYYSave[ip]; }; |
+ |
+protected: |
+ void InitFields(int numberOfPointsLowVolt, int numberOfPoints, int numberOfMode2Bins, int numberOfSamples, |
+ int numberOfGridPoints, int numberOfXConstPoints, int numberOfXConstGridPoints, |
+ double triggerFrequency, int showStatistics); |
+ void DeleteFields(); |
+ void CalibrationTrigger(int mode, double voltage); |
+ void CalibrationStart(double voltage); |
+ |
+ static float GetValue(float *coefficients, float u, int n); |
+ static int Approx(float *p, float *uu, int np, int nu, float *coef); |
+ static void LeastSquaresAccumulation(float **matrix, int nb, int *ip, int *ir, int mt, int jt); |
+ static int LeastSquaresSolving(float **matrix, int nb, int ip, int ir, float *x, int n); |
+ static void Housholder(int lpivot, int l1, int m, float **u, int iU1, int iU2, float *up, float **c, int iC1, |
+ int iC2, int ice, int ncv); |
+ |
+ static int MakeDir(const char *path); |
+ static void Average(int method,float *samples,int numberOfSamples,float &mean,float &error,float sigmaBoundary); |
+}; |
+ |
+ |
+class DRSBoard { |
+protected: |
+ class TimeData { |
+ public: |
+ class FrequencyData { |
+ public: |
+ int fFrequency; |
+ double fBin[kNumberOfBins]; |
+ }; |
+ |
+ enum { |
+ kMaxNumberOfFrequencies = 4000 |
+ }; |
+ int fChip; |
+ int fNumberOfFrequencies; |
+ FrequencyData *fFrequency[kMaxNumberOfFrequencies]; |
+ |
+ private: |
+ TimeData(const TimeData &c); // not implemented |
+ TimeData &operator=(const TimeData &rhs); // not implemented |
+ |
+ public: |
+ TimeData() |
+ :fChip(0) |
+ ,fNumberOfFrequencies(0) { |
+ } |
+ ~TimeData() { |
+ int i; |
+ for (i = 0; i < fNumberOfFrequencies; i++) { |
+ delete fFrequency[i]; |
+ } |
+ } |
+ }; |
+ |
+public: |
+ // DAC channels (CMC Version 1 : DAC_COFSA,DAC_COFSB,DAC_DRA,DAC_DSA,DAC_TLEVEL,DAC_ACALIB,DAC_DSB,DAC_DRB) |
+ unsigned int fDAC_COFSA; |
+ unsigned int fDAC_COFSB; |
+ unsigned int fDAC_DRA; |
+ unsigned int fDAC_DSA; |
+ unsigned int fDAC_TLEVEL; |
+ unsigned int fDAC_ACALIB; |
+ unsigned int fDAC_DSB; |
+ unsigned int fDAC_DRB; |
+ // DAC channels (CMC Version 2+3 : DAC_COFS,DAC_DSA,DAC_DSB,DAC_TLEVEL,DAC_ADCOFS,DAC_CLKOFS,DAC_ACALIB) |
+ unsigned int fDAC_COFS; |
+ unsigned int fDAC_ADCOFS; |
+ unsigned int fDAC_CLKOFS; |
+ // DAC channels (CMC Version 4 : DAC_ROFS_1,DAC_DSA,DAC_DSB,DAC_ROFS_2,DAC_ADCOFS,DAC_ACALIB,DAC_INOFS,DAC_BIAS) |
+ unsigned int fDAC_ROFS_1; |
+ unsigned int fDAC_ROFS_2; |
+ unsigned int fDAC_INOFS; |
+ unsigned int fDAC_BIAS; |
+ // DAC channels (USB EVAL1 (fBoardType 5) : DAC_ROFS_1,DAC_CMOFS,DAC_CALN,DAC_CALP,DAC_BIAS,DAC_TLEVEL,DAC_ONOFS) |
+ // DAC channels (USB EVAL3 (fBoardType 7) : DAC_ROFS_1,DAC_CMOFS,DAC_CALN,DAC_CALP,DAC_BIAS,DAC_TLEVEL,DAC_ONOFS) |
+ unsigned int fDAC_CMOFS; |
+ unsigned int fDAC_CALN; |
+ unsigned int fDAC_CALP; |
+ unsigned int fDAC_ONOFS; |
+ // DAC channels (DRS4 MEZZ1 (fBoardType 6) : DAC_ONOFS,DAC_CMOFSP,DAC_CALN,DAC_CALP,DAC_BIAS,DAC_CMOFSN,DAC_ROFS_1) |
+ unsigned int fDAC_CMOFSP; |
+ unsigned int fDAC_CMOFSN; |
+ // DAC channels (DRS4 EVAL4 (fBoardType 8) : DAC_ONOFS,DAC_TLEVEL4,DAC_CALN,DAC_CALP,DAC_BIAS,DAC_TLEVEL1,DAC_TLEVEL2,DAC_TLEVEL3) |
+ unsigned int fDAC_TLEVEL1; |
+ unsigned int fDAC_TLEVEL2; |
+ unsigned int fDAC_TLEVEL3; |
+ unsigned int fDAC_TLEVEL4; |
+ |
+protected: |
+ // Fields for DRS |
+ int fDRSType; |
+ int fBoardType; |
+ int fNumberOfChips; |
+ int fNumberOfChannels; |
+ int fRequiredFirmwareVersion; |
+ int fFirmwareVersion; |
+ int fBoardSerialNumber; |
+ int fHasMultiBuffer; |
+ unsigned int fTransport; |
+ unsigned int fCtrlBits; |
+ int fNumberOfReadoutChannels; |
+ int fReadoutChannelConfig; |
+ int fADCClkPhase; |
+ bool fADCClkInvert; |
+ double fExternalClockFrequency; |
+#ifdef HAVE_USB |
+ MUSB_INTERFACE *fUsbInterface; |
+#endif |
+#ifdef HAVE_VME |
+ MVME_INTERFACE *fVmeInterface; |
+ mvme_addr_t fBaseAddress; |
+#endif |
+ int fSlotNumber; |
+ double fNominalFrequency; |
+ double fTrueFrequency; |
+ double fTCALFrequency; |
+ double fRefClock; |
+ int fMultiBuffer; |
+ int fDominoMode; |
+ int fDominoActive; |
+ int fADCActive; |
+ int fChannelConfig; |
+ int fChannelCascading; |
+ int fChannelDepth; |
+ int fWSRLoop; |
+ int fReadoutMode; |
+ unsigned short fReadPointer; |
+ int fNMultiBuffer; |
+ int fTriggerEnable1; |
+ int fTriggerEnable2; |
+ int fTriggerSource; |
+ int fTriggerDelay; |
+ double fTriggerDelayNs; |
+ int fSyncDelay; |
+ int fDelayedStart; |
+ int fTranspMode; |
+ int fDecimation; |
+ unsigned short fStopCell[4]; |
+ unsigned char fStopWSR[4]; |
+ unsigned short fTriggerBus; |
+ double fROFS; |
+ double fRange; |
+ double fCommonMode; |
+ int fAcalMode; |
+ int fbkAcalMode; |
+ double fAcalVolt; |
+ double fbkAcalVolt; |
+ int fTcalFreq; |
+ int fbkTcalFreq; |
+ int fTcalLevel; |
+ int fbkTcalLevel; |
+ int fTcalPhase; |
+ int fTcalSource; |
+ int fRefclk; |
+ |
+ unsigned char fWaveforms[kNumberOfChipsMax * kNumberOfChannelsMax * 2 * kNumberOfBins]; |
+ |
+ // Fields for Calibration |
+ int fMaxChips; |
+ char fCalibDirectory[1000]; |
+ |
+ // Fields for Response Calibration old method |
+ ResponseCalibration *fResponseCalibration; |
+ |
+ // Fields for Calibration new method |
+ bool fVoltageCalibrationValid; |
+ double fCellCalibratedRange; |
+ double fCellCalibratedTemperature; |
+ unsigned short fCellOffset[kNumberOfChipsMax * kNumberOfChannelsMax][kNumberOfBins]; |
+ unsigned short fCellOffset2[kNumberOfChipsMax * kNumberOfChannelsMax][kNumberOfBins]; |
+ double fCellGain[kNumberOfChipsMax * kNumberOfChannelsMax][kNumberOfBins]; |
+ |
+ double fTimingCalibratedFrequency; |
+ double fCellDT[kNumberOfChipsMax][kNumberOfChannelsMax][kNumberOfBins]; |
+ |
+ // Fields for Time Calibration |
+ TimeData **fTimeData; |
+ int fNumberOfTimeData; |
+ |
+ // General debugging flag |
+ int fDebug; |
+ |
+ // Fields for wave transfer |
+ bool fWaveTransferred[kNumberOfChipsMax * kNumberOfChannelsMax]; |
+ |
+ // Waveform Rotation |
+ int fTriggerStartBin; // Start Bin of the trigger |
+ |
+private: |
+ DRSBoard(const DRSBoard &c); // not implemented |
+ DRSBoard &operator=(const DRSBoard &rhs); // not implemented |
+ |
+public: |
+ // Public Methods |
+#ifdef HAVE_USB |
+ DRSBoard(MUSB_INTERFACE * musb_interface, int usb_slot); |
+#endif |
+#ifdef HAVE_VME |
+ DRSBoard(MVME_INTERFACE * mvme_interface, mvme_addr_t base_address, int slot_number); |
+ |
+ MVME_INTERFACE *GetVMEInterface() const { return fVmeInterface; }; |
+#endif |
+ ~DRSBoard(); |
+ |
+ int SetBoardSerialNumber(unsigned short serialNumber); |
+ int GetBoardSerialNumber() const { return fBoardSerialNumber; } |
+ int HasMultiBuffer() const { return fHasMultiBuffer; } |
+ int GetFirmwareVersion() const { return fFirmwareVersion; } |
+ int GetRequiredFirmwareVersion() const { return fRequiredFirmwareVersion; } |
+ int GetDRSType() const { return fDRSType; } |
+ int GetBoardType() const { return fBoardType; } |
+ int GetNumberOfChips() const { return fNumberOfChips; } |
+ // channel : Flash ADC index |
+ // readout channel : VME readout index |
+ // input : Input on board |
+ int GetNumberOfChannels() const { return fNumberOfChannels; } |
+ int GetChannelDepth() const { return fChannelDepth; } |
+ int GetChannelCascading() const { return fChannelCascading; } |
+ inline int GetNumberOfReadoutChannels() const; |
+ inline int GetWaveformBufferSize() const; |
+ inline int GetNumberOfInputs() const; |
+ inline int GetNumberOfCalibInputs() const; |
+ inline int GetClockChannel() const; |
+ inline int GetTriggerChannel() const; |
+ inline int GetClockInput() const { return Channel2Input(GetClockChannel()); } |
+ inline int GetTriggerInput() const { return fDRSType < 4 ? Channel2Input(GetTriggerChannel()) : -1; } |
+ inline int Channel2Input(int channel) const; |
+ inline int Channel2ReadoutChannel(int channel) const; |
+ inline int Input2Channel(int input, int ind = 0) const; |
+ inline int Input2ReadoutChannel(int input, int ind = 0) const; |
+ inline int ReadoutChannel2Channel(int readout) const; |
+ inline int ReadoutChannel2Input(int readout) const; |
+ |
+ inline bool IsCalibChannel(int ch) const; |
+ inline bool IsCalibInput(int input) const; |
+ int GetSlotNumber() const { return fSlotNumber; } |
+ int InitFPGA(void); |
+ int Write(int type, unsigned int addr, void *data, int size); |
+ int Read(int type, void *data, unsigned int addr, int size); |
+ int GetTransport() const { return fTransport; } |
+ void RegisterTest(void); |
+ int RAMTest(int flag); |
+ int ChipTest(); |
+ unsigned int GetCtrlReg(void); |
+ unsigned short GetConfigReg(void); |
+ unsigned int GetStatusReg(void); |
+ void SetLED(int state); |
+ int SetChannelConfig(int firstChannel, int lastChannel, int nConfigChannels); |
+ void SetADCClkPhase(int phase, bool invert); |
+ void SetWarmup(unsigned int ticks); |
+ void SetCooldown(unsigned int ticks); |
+ int GetReadoutChannelConfig() { return fReadoutChannelConfig; } |
+ void SetNumberOfChannels(int nChannels); |
+ int EnableTrigger(int flag1, int flag2); |
+ int GetTriggerEnable(int i) { return i?fTriggerEnable2:fTriggerEnable1; } |
+ int SetDelayedTrigger(int flag); |
+ int SetTriggerDelayPercent(int delay); |
+ int SetTriggerDelayNs(int delay); |
+ int GetTriggerDelay() { return fTriggerDelay; } |
+ double GetTriggerDelayNs() { return fTriggerDelayNs; } |
+ int SetSyncDelay(int ticks); |
+ int SetTriggerLevel(double value); |
+ int SetIndividualTriggerLevel(int channel, double voltage); |
+ int SetTriggerPolarity(bool negative); |
+ int SetTriggerSource(int source); |
+ int GetTriggerSource() { return fTriggerSource; } |
+ int SetDelayedStart(int flag); |
+ int SetTranspMode(int flag); |
+ int SetStandbyMode(int flag); |
+ int SetDecimation(int flag); |
+ int GetDecimation() { return fDecimation; } |
+ int IsBusy(void); |
+ int IsEventAvailable(void); |
+ int IsPLLLocked(void); |
+ int IsLMKLocked(void); |
+ int IsNewFreq(unsigned char chipIndex); |
+ int SetDAC(unsigned char channel, double value); |
+ int ReadDAC(unsigned char channel, double *value); |
+ int GetRegulationDAC(double *value); |
+ int StartDomino(); |
+ int StartClearCycle(); |
+ int FinishClearCycle(); |
+ int Reinit(); |
+ int Init(); |
+ void SetDebug(int debug) { fDebug = debug; } |
+ int Debug() { return fDebug; } |
+ int SetDominoMode(unsigned char mode); |
+ int SetDominoActive(unsigned char mode); |
+ int SetReadoutMode(unsigned char mode); |
+ int SoftTrigger(void); |
+ int ReadFrequency(unsigned char chipIndex, double *f); |
+ int SetFrequency(double freq, bool wait); |
+ double VoltToFreq(double volt); |
+ double FreqToVolt(double freq); |
+ double GetNominalFrequency() const { return fNominalFrequency; } |
+ double GetTrueFrequency(); |
+ int RegulateFrequency(double freq); |
+ int SetExternalClockFrequency(double frequencyMHz); |
+ double GetExternalClockFrequency(); |
+ int SetMultiBuffer(int flag); |
+ int IsMultiBuffer() { return fMultiBuffer; } |
+ void ResetMultiBuffer(void); |
+ int GetMultiBufferRP(void); |
+ int SetMultiBufferRP(unsigned short rp); |
+ int GetMultiBufferWP(void); |
+ void IncrementMultiBufferRP(void); |
+ void SetVoltageOffset(double offset1, double offset2); |
+ int SetInputRange(double center); |
+ double GetInputRange(void) { return fRange; } |
+ double GetCalibratedInputRange(void) { return fCellCalibratedRange; } |
+ double GetCalibratedTemperature(void) { return fCellCalibratedTemperature; } |
+ double GetCalibratedFrequency(void) { return fTimingCalibratedFrequency; } |
+ int TransferWaves(int numberOfChannels = kNumberOfChipsMax * kNumberOfChannelsMax); |
+ int TransferWaves(unsigned char *p, int numberOfChannels = kNumberOfChipsMax * kNumberOfChannelsMax); |
+ int TransferWaves(int firstChannel, int lastChannel); |
+ int TransferWaves(unsigned char *p, int firstChannel, int lastChannel); |
+ int DecodeWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel, |
+ unsigned short *waveform); |
+ int DecodeWave(unsigned int chipIndex, unsigned char channel, unsigned short *waveform); |
+ int GetWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel, short *waveform, |
+ bool responseCalib = false, int triggerCell = -1, int wsr = -1, bool adjustToClock = false, |
+ float threshold = 0, bool offsetCalib = true); |
+ int GetWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel, float *waveform, |
+ bool responseCalib = false, int triggerCell = -1, int wsr = -1, bool adjustToClock = false, |
+ float threshold = 0, bool offsetCalib = true); |
+ int GetWave(unsigned int chipIndex, unsigned char channel, short *waveform, bool responseCalib = false, |
+ int triggerCell = -1, int wsr = -1, bool adjustToClock = false, float threshold = 0, bool offsetCalib = true); |
+ int GetWave(unsigned int chipIndex, unsigned char channel, float *waveform, bool responseCalib, |
+ int triggerCell = -1, int wsr = -1, bool adjustToClock = false, float threshold = 0, bool offsetCalib = true); |
+ int GetWave(unsigned int chipIndex, unsigned char channel, float *waveform); |
+ int GetRawWave(unsigned int chipIndex, unsigned char channel, unsigned short *waveform, bool adjustToClock = false); |
+ int GetRawWave(unsigned char *waveforms,unsigned int chipIndex, unsigned char channel, |
+ unsigned short *waveform, bool adjustToClock = false); |
+ bool IsTimingCalibrationValid(void); |
+ bool IsVoltageCalibrationValid(void) { return fVoltageCalibrationValid; } |
+ int GetTime(unsigned int chipIndex, int channelIndex, double freq, int tc, float *time, bool tcalibrated=true, bool rotated=true); |
+ int GetTime(unsigned int chipIndex, int channelIndex, int tc, float *time, bool tcalibrated=true, bool rotated=true); |
+ int GetTimeCalibration(unsigned int chipIndex, int channelIndex, int mode, float *time, bool force=false); |
+ int GetTriggerCell(unsigned int chipIndex); |
+ int GetStopCell(unsigned int chipIndex); |
+ unsigned char GetStopWSR(unsigned int chipIndex); |
+ int GetTriggerCell(unsigned char *waveforms,unsigned int chipIndex); |
+ void TestDAC(int channel); |
+ void MeasureSpeed(); |
+ void InteractSpeed(); |
+ void MonitorFrequency(); |
+ int TestShift(int n); |
+ int EnableAcal(int mode, double voltage); |
+ int GetAcalMode() { return fAcalMode; } |
+ double GetAcalVolt() { return fAcalVolt; } |
+ int EnableTcal(int freq, int level=0, int phase=0); |
+ int SelectClockSource(int source); |
+ int SetRefclk(int source); |
+ int GetRefclk() { return fRefclk; } |
+ int GetTcalFreq() { return fTcalFreq; } |
+ int GetTcalLevel() { return fTcalLevel; } |
+ int GetTcalPhase() { return fTcalPhase; } |
+ int GetTcalSource() { return fTcalSource; } |
+ int SetCalibVoltage(double value); |
+ int SetCalibTiming(int t1, int t2); |
+ double GetTemperature(); |
+ int Is2048ModeCapable(); |
+ int GetTriggerBus(); |
+ unsigned int GetScaler(int channel); |
+ int ReadEEPROM(unsigned short page, void *buffer, int size); |
+ int WriteEEPROM(unsigned short page, void *buffer, int size); |
+ bool HasCorrectFirmware(); |
+ int ConfigureLMK(double sampFreq, bool freqChange, int calFreq, int calPhase); |
+ |
+ bool InitTimeCalibration(unsigned int chipIndex); |
+ void SetCalibrationDirectory(const char *calibrationDirectoryPath); |
+ void GetCalibrationDirectory(char *calibrationDirectoryPath); |
+ |
+ ResponseCalibration *GetResponseCalibration() const { return fResponseCalibration; } |
+ |
+ double GetPrecision() const { return fResponseCalibration ? fResponseCalibration->GetPrecision() : 0.1; } |
+ int CalibrateWaveform(unsigned int chipIndex, unsigned char channel, unsigned short *adcWaveform, |
+ short *waveform, bool responseCalib, int triggerCell, bool adjustToClock, |
+ float threshold, bool offsetCalib); |
+ |
+ static void LinearRegression(double *x, double *y, int n, double *a, double *b); |
+ |
+ void ReadSingleWaveform(int nChips, int nChan, |
+ unsigned short wfu[kNumberOfChipsMax][kNumberOfChannelsMax][kNumberOfBins], bool rotated); |
+ int AverageWaveforms(DRSCallback *pcb, int chipIndex, int nChan, int prog1, int prog2, unsigned short *awf, int n, bool rotated); |
+ int RobustAverageWaveforms(DRSCallback *pcb, int chipIndex, int nChan, int prog1, int prog2, unsigned short *awf, int n, bool rotated); |
+ int CalibrateVolt(DRSCallback *pcb); |
+ int AnalyzePeriod(Averager *ave, int iIter, int nIter, int channel, float wf[kNumberOfBins], int tCell, double cellDV[kNumberOfBins], double cellDT[kNumberOfBins]); |
+ int AnalyzeSlope(Averager *ave, int iIter, int nIter, int channel, float wf[kNumberOfBins], int tCell, double cellDV[kNumberOfBins], double cellDT[kNumberOfBins]); |
+ int CalibrateTiming(DRSCallback *pcb); |
+ static void RemoveSymmetricSpikes(short **wf, int nwf, |
+ short diffThreshold, int spikeWidth, |
+ short maxPeakToPeak, short spikeVoltage, |
+ int nTimeRegionThreshold); |
+protected: |
+ // Protected Methods |
+ void ConstructBoard(); |
+ void ReadSerialNumber(); |
+ void ReadCalibration(void); |
+ |
+ TimeData *GetTimeCalibration(unsigned int chipIndex, bool reinit = false); |
+ |
+ int GetStretchedTime(float *time, float *measurement, int numberOfMeasurements, float period); |
+}; |
+ |
+int DRSBoard::GetNumberOfReadoutChannels() const |
+{ |
+ return (fDRSType == 4 && fReadoutChannelConfig == 4) ? 5 : fNumberOfChannels; |
+} |
+ |
+int DRSBoard::GetWaveformBufferSize() const |
+{ |
+ int nbin=0; |
+ if (fDRSType < 4) { |
+ nbin = fNumberOfChips * fNumberOfChannels * kNumberOfBins; |
+ } else { |
+ if (fBoardType == 6) { |
+ if (fDecimation) { |
+ nbin = fNumberOfChips * (4 * kNumberOfBins + kNumberOfBins / 2); |
+ } else { |
+ nbin = fNumberOfChips * 5 * kNumberOfBins; |
+ } |
+ } else if (fBoardType == 7 || fBoardType == 8 || fBoardType == 9) |
+ nbin = fNumberOfChips * fNumberOfChannels * kNumberOfBins; |
+ } |
+ return nbin * static_cast<int>(sizeof(short int)); |
+} |
+ |
+int DRSBoard::GetNumberOfInputs() const |
+{ |
+ // return number of input channels excluding clock and trigger channels. |
+ if (fDRSType < 4) { |
+ return fNumberOfChannels - 2; |
+ } else { |
+ return fNumberOfChannels / 2; |
+ } |
+} |
+int DRSBoard::GetNumberOfCalibInputs() const |
+{ |
+ return (fDRSType < 4) ? 2 : 1; |
+} |
+int DRSBoard::GetClockChannel() const |
+{ |
+ return fDRSType < 4 ? 9 : 8; |
+} |
+int DRSBoard::GetTriggerChannel() const |
+{ |
+ return fDRSType < 4 ? 8 : -1; |
+} |
+ |
+int DRSBoard::Channel2Input(int channel) const |
+{ |
+ return (fDRSType < 4) ? channel : channel / 2; |
+} |
+int DRSBoard::Channel2ReadoutChannel(int channel) const |
+{ |
+ if (fDRSType < 4) { |
+ return channel; |
+ } else { |
+ if (fReadoutChannelConfig == 4) { |
+ return channel / 2; |
+ } else { |
+ return channel; |
+ } |
+ } |
+} |
+int DRSBoard::Input2Channel(int input, int ind) const |
+{ |
+ if (fChannelCascading == 1) { |
+ return (fDRSType < 4) ? input : (input * 2 + ind); |
+ } else { |
+ if (input == 4) { // clock |
+ return 8; |
+ } else { |
+ return input; |
+ } |
+ } |
+} |
+int DRSBoard::Input2ReadoutChannel(int input, int ind) const |
+{ |
+ if (fDRSType < 4) { |
+ return input; |
+ } else { |
+ if (fReadoutChannelConfig == 4) { |
+ return input; |
+ } else { |
+ return (input * 2 + ind); |
+ } |
+ } |
+} |
+int DRSBoard::ReadoutChannel2Channel(int readout) const |
+{ |
+ if (fDRSType < 4) { |
+ return readout; |
+ } else { |
+ if (fReadoutChannelConfig == 4) { |
+ return readout * 2; |
+ } else { |
+ return readout; |
+ } |
+ } |
+} |
+int DRSBoard::ReadoutChannel2Input(int readout) const |
+{ |
+ if (fDRSType < 4) { |
+ return readout; |
+ } else { |
+ if (fReadoutChannelConfig == 4) { |
+ return readout; |
+ } else { |
+ return readout / 2; |
+ } |
+ } |
+} |
+bool DRSBoard::IsCalibChannel(int ch) const |
+{ |
+ // return if it is clock or trigger channel |
+ if (fDRSType < 4) |
+ return ch == GetClockChannel() || ch == GetTriggerChannel(); |
+ else |
+ return ch == GetClockChannel(); |
+} |
+bool DRSBoard::IsCalibInput(int input) const |
+{ |
+ // return if it is clock or trigger channel |
+ int ch = Input2Channel(input); |
+ if (fDRSType < 4) |
+ return ch == GetClockChannel() || ch == GetTriggerChannel(); |
+ else |
+ return ch == GetClockChannel(); |
+} |
+ |
+class DRS { |
+protected: |
+ // constants |
+ enum { |
+ kMaxNumberOfBoards = 40 |
+ }; |
+ |
+protected: |
+ DRSBoard *fBoard[kMaxNumberOfBoards]; |
+ int fNumberOfBoards; |
+ char fError[256]; |
+#ifdef HAVE_VME |
+ MVME_INTERFACE *fVmeInterface; |
+#endif |
+ |
+private: |
+ DRS(const DRS &c); // not implemented |
+ DRS &operator=(const DRS &rhs); // not implemented |
+ |
+public: |
+ // Public Methods |
+ DRS(); |
+ ~DRS(); |
+ |
+ DRSBoard *GetBoard(int i) { return fBoard[i]; } |
+ void SetBoard(int i, DRSBoard *b); |
+ DRSBoard **GetBoards() { return fBoard; } |
+ int GetNumberOfBoards() const { return fNumberOfBoards; } |
+ bool GetError(char *str, int size); |
+ void SortBoards(); |
+ |
+#ifdef HAVE_VME |
+ MVME_INTERFACE *GetVMEInterface() const { return fVmeInterface; }; |
+#endif |
+}; |
+ |
+#endif // DRS_H |
Index: instr/drs/drs4.c |
=================================================================== |
--- instr/drs/drs4.c (nonexistent) |
+++ instr/drs/drs4.c (revision 197) |
@@ -0,0 +1,216 @@ |
+#include <utility.h> |
+#include <ansi_c.h> |
+#include <cvirte.h> |
+#include <userint.h> |
+#include "drs4.h" |
+#include "drsread.h" |
+ |
+static int daq_on; |
+static int ph, plothandle; |
+static int tfID; |
+static int controlID; |
+ |
+#define MAX_THREADS 10 |
+ |
+static CmtThreadPoolHandle poolHandle = 0; |
+ |
+int main (int argc, char *argv[]) { |
+ if (InitCVIRTE (0, argv, 0) == 0) |
+ return -1; /* out of memory */ |
+ if ((ph = LoadPanel (0, "drs4.uir", PANEL)) < 0) |
+ return -1; |
+ SetStdioPort (CVI_STDIO_WINDOW); |
+ SetSleepPolicy(VAL_SLEEP_MORE); |
+ CmtNewThreadPool (MAX_THREADS, &poolHandle); |
+ |
+ DisplayPanel (ph); |
+ RunUserInterface (); |
+ DiscardPanel (ph); |
+ CmtDiscardThreadPool (poolHandle); |
+ return 0; |
+} |
+ |
+ |
+ |
+ |
+ |
+static void start_timer (double tout) { |
+ SetCtrlAttribute (ph, PANEL_TIMER, ATTR_INTERVAL, tout); |
+ SetCtrlAttribute (ph, PANEL_TIMER, ATTR_ENABLED, 1); |
+} |
+ |
+static void stop_timer ( void ) { |
+ SetCtrlAttribute (ph, PANEL_TIMER, ATTR_ENABLED, 0); |
+ DRSSetTimeout(); |
+} |
+ |
+ |
+ |
+ |
+void CVICALLBACK EndOfThread ( CmtThreadPoolHandle poolhandle, |
+ CmtThreadFunctionID functionID, unsigned int event, |
+ int value, void *callbackData ) { |
+ |
+ daq_on=0; |
+ //SetDimming(0); |
+ printf("End of Thread \n"); |
+ return ; |
+ |
+} |
+ |
+ |
+int CVICALLBACK daq(void *functionData) { |
+ |
+ |
+ int neve; |
+ char filename[0xff]; |
+ char smask[0xff]; |
+ unsigned long mask; |
+ int frequency; |
+ double trgdelay; |
+ double trglevel; |
+ int trgtype; |
+ int trgchannel; |
+ int trgpolarity; |
+ int verbose; |
+ double range; |
+ |
+ |
+ GetCtrlVal(ph, PANEL_FILENAME, filename ); |
+ GetCtrlVal(ph, PANEL_MASK, smask ); |
+ mask = strtoul (smask,NULL,0); |
+ GetCtrlVal(ph,PANEL_NEVE, &neve); |
+ |
+ GetCtrlVal(ph,PANEL_FREQUENCY, &frequency); |
+ GetCtrlVal(ph,PANEL_TRGDELAY, &trgdelay); |
+ GetCtrlVal(ph,PANEL_TRGCHANNEL, &trgchannel); |
+ GetCtrlVal(ph,PANEL_TRGTYPE, &trgtype); |
+ GetCtrlVal(ph,PANEL_TRGLEVEL, &trglevel); |
+ GetCtrlVal(ph,PANEL_TRGPOLARITY, &trgpolarity); |
+ GetCtrlVal(ph,PANEL_RANGE, &range); |
+ GetCtrlVal(ph,PANEL_DEBUG, &verbose); |
+ |
+ printf("mask=0x%x\n",mask); |
+ |
+ DRSSetMask( (unsigned char)( mask & 0xF ) ); |
+ |
+ DRSSetFrequency( frequency ); |
+ DRSSetTriggerPolarity(trgpolarity); |
+ DRSSetTriggerLevel(trglevel); |
+ DRSSetRange ( range ); |
+ DRSSetTriggerType( trgtype ); |
+ DRSSetTriggerChannel(trgchannel ); |
+ |
+ FILE *fp=fopen(filename,"wb"); |
+ |
+ |
+ static unsigned char *buffer; |
+ |
+ int buffer_size = 0; |
+const int nBoards=1; |
+const int waveDepth=1024; |
+if (buffer_size == 0) { |
+ buffer_size = 4 + nBoards * (4 + 4*(4+waveDepth*4)); |
+ buffer_size += 24 + nBoards * (8 + 4*(4+waveDepth*2)); |
+ buffer = (unsigned char *)malloc(buffer_size); |
+} |
+ |
+time_t t,told, tstart; |
+ |
+if (!DRSInit()){ |
+ time(&tstart); |
+ told=tstart; |
+ int i=0; |
+ for (i=0; i<neve; i++) { |
+ start_timer(1);// 1 s timeout |
+ int retval = DRSRead(0); |
+ stop_timer(); |
+ int nb = ( retval == 0 && fp ) ? DRSToBuffer( buffer , i ) : 0; |
+ SetCtrlVal(ph,PANEL_CEVE,i); |
+ if (retval) i--; |
+ if (!daq_on) break; |
+ time(&t); |
+ if (t!=told ) { |
+ printf("%d events in %2.2f min (%d s) %s",i+1, (double)(t-tstart)/60.,(t-tstart), ctime(&t)); |
+ |
+ } |
+ told=t; |
+// Save data |
+ if (nb>0 && fp) fwrite(buffer, 1,nb ,fp); |
+// Plot Data |
+ for (int k=0;k<4;k++){ |
+ if (! (mask & ( 0x1<<k )) ) continue; |
+ float *t=DRSGetTime(k); |
+ float *x=DRSGetWave(k); |
+ |
+ if (!k){ |
+ if (plothandle) DeleteGraphPlot (ph, PANEL_GRAPH, plothandle, VAL_DELAYED_DRAW); |
+ plothandle = PlotXY (ph, PANEL_GRAPH, t, x, 1024, VAL_FLOAT, VAL_FLOAT, VAL_THIN_LINE, VAL_NO_POINT, VAL_SOLID, 1, VAL_BLUE); |
+ } |
+ |
+ |
+ for (int i=0 ; i<1024 ; i++) { |
+ if (verbose) printf("[%d] %d. x= %3.2f y=%3.2f\n", k, i, t[i], x[i] ); |
+ //h[k]->Fill( t[i], x[i]*1e-3); |
+ } |
+ } |
+ } |
+ time(&t); |
+ printf("%d events in %2.2f min (%d s) %s",i+1, (double)(t-tstart)/60.,t-tstart, ctime(&t)); |
+ |
+ DRSEnd(); |
+} |
+ |
+if (fp) fclose(fp); |
+ |
+free(buffer); |
+ |
+ return 0; |
+ |
+} |
+ |
+int CVICALLBACK StartCB (int panel, int control, int event, |
+ void *callbackData, int eventData1, int eventData2) { |
+ ThreadFunctionPtr mythread = NULL; |
+ switch (event) { |
+ |
+ case EVENT_COMMIT: |
+ |
+ mythread = daq; |
+ if (mythread!=NULL) { |
+ printf("New Thread panel=%d button=%d\n", panel, control); |
+ |
+ // SetDimming(1); |
+ controlID= control; |
+ daq_on=1; |
+ CmtScheduleThreadPoolFunctionAdv (poolHandle, mythread, &controlID, |
+ DEFAULT_THREAD_PRIORITY, |
+ EndOfThread, |
+ EVENT_TP_THREAD_FUNCTION_END, |
+ NULL, RUN_IN_SCHEDULED_THREAD, |
+ &tfID); |
+ } |
+ break; |
+ } |
+ return 0; |
+} |
+ |
+int CVICALLBACK StopCB (int panel, int control, int event, |
+ void *callbackData, int eventData1, int eventData2) { |
+ switch (event) { |
+ case EVENT_COMMIT: |
+ daq_on=0; |
+ break; |
+ } |
+ return 0; |
+} |
+ |
+int CVICALLBACK ExitCB (int panel, int control, int event, |
+ void *callbackData, int eventData1, int eventData2) { |
+ switch (event) { |
+ case EVENT_COMMIT: |
+ QuitUserInterface (0); |
+ break; |
+ } |
+ return 0; |
+} |
Index: instr/drs/drs4.cws |
=================================================================== |
--- instr/drs/drs4.cws (nonexistent) |
+++ instr/drs/drs4.cws (revision 197) |
@@ -0,0 +1,232 @@ |
+[Workspace Header] |
+Version = 1302 |
+Pathname = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.cws" |
+CVI Dir = "/c/program files (x86)/national instruments/cvi2013" |
+CVI Shared Dir = "/C/Program Files (x86)/National Instruments/Shared/CVI" |
+CVI Pub Local Dir = "/C/ProgramData/National Instruments/CVI2013" |
+CVI Pub Global Dir = "/C/ProgramData/National Instruments/CVI" |
+IVI Standard Root Dir = "/C/Program Files (x86)/IVI Foundation/IVI" |
+IVI Standard Root 64-bit Dir = "/C/Program Files/IVI Foundation/IVI" |
+VXIplug&play Framework Dir = "/C/Program Files (x86)/IVI Foundation/VISA/winnt" |
+VXIplug&play Framework 64-bit Dir = "/C/Program Files/IVI Foundation/VISA/win64" |
+Number of Projects = 1 |
+Active Project = 1 |
+Project 0001 = "drs4.prj" |
+Drag Bar Left = 360 |
+Window Top = 277 |
+Window Left = 205 |
+Window Bottom = 1617 |
+Window Right = 2435 |
+Maximized = False |
+Maximized Children = True |
+Max32 Number Of Errors = 20 |
+Track Include File Dependencies = True |
+Prompt For Missing Includes = True |
+Stop On First Error File = False |
+Bring Up Err Win At Start = True |
+Bring Up Err Win For Errors = False |
+Save Changes Before Running = "Always" |
+Save Changes Before Compiling = "Always" |
+Hide Windows = False |
+Break At First Statement = False |
+Sort Type = "File Name" |
+Number of Opened Files = 8 |
+Window Confinement Region Enabled = True |
+MainColumnWidth = 343 |
+FileDateColumnWidth = 70 |
+FileSizeColumnWidth = 70 |
+ |
+[Project Header 0001] |
+Version = 1302 |
+Don't Update DistKit = False |
+Platform Code = 4 |
+Build Configuration = "Debug" |
+Warn User If Debugging Release = 1 |
+Batch Build Release = False |
+Batch Build Debug = False |
+ |
+[File 0001] |
+Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.c" |
+File Type = "CSource" |
+Disk Date = 3566382302 |
+In Projects = "1," |
+Window Top = 522 |
+Window Left = 247 |
+Window Z-Order = 1 |
+Source Window State = "1,147,148,148,0,0,0,0,0,229,0,2,0,2,0,67,14,0,26,2,349,683,1,0," |
+ |
+[File 0002] |
+Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.uir" |
+File Type = "User Interface Resource" |
+Disk Date = 3566382690 |
+In Projects = "1," |
+Window Top = 132 |
+Window Left = 49 |
+Window Height = 349 |
+Window Width = 811 |
+Window Z-Order = 2 |
+ |
+[File 0003] |
+Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.h" |
+File Type = "Include" |
+Disk Date = 3566380515 |
+In Projects = "" |
+Window Top = 67 |
+Window Left = 16 |
+Window Z-Order = 6 |
+Source Window State = "1,0,0,0,0,0,0,0,0,96,0,0,0,0,0,25,0,0,0,0,349,811,1,0," |
+ |
+[File 0004] |
+Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drsread.h" |
+File Type = "Include" |
+Disk Date = 3566381442 |
+In Projects = "" |
+Window Top = 197 |
+Window Left = 82 |
+Window Z-Order = 5 |
+Source Window State = "1,0,0,0,0,0,0,0,0,96,0,0,0,0,0,25,0,0,31,70,349,811,1,0," |
+ |
+[File 0005] |
+Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drsread.c" |
+File Type = "CSource" |
+Disk Date = 3566381600 |
+In Projects = "" |
+Window Top = 262 |
+Window Left = 115 |
+Window Z-Order = 4 |
+Source Window State = "1,0,0,0,0,0,0,0,0,96,0,0,0,0,0,25,0,0,30,26,349,811,1,0," |
+ |
+[File 0006] |
+Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drsread.lib" |
+File Type = "Library" |
+Disk Date = 3566381587 |
+In Projects = "1," |
+ |
+[File 0007] |
+Path = "/c/Users/rok/Documents/rok/lab/praktikum/mioni/mioni.c" |
+File Type = "CSource" |
+Disk Date = 3564730349 |
+In Projects = "" |
+Window Top = 132 |
+Window Left = 49 |
+Window Z-Order = 8 |
+Source Window State = "1,26,26,26,0,25,25,0,3,96,0,0,0,0,0,25,0,0,26,0,349,811,1,0," |
+ |
+[File 0008] |
+Path = "/c/home/git/arich/daq/sa02_daq/cvi/sa02_CVI.c" |
+File Type = "CSource" |
+Disk Date = 3559701358 |
+In Projects = "" |
+Window Top = 197 |
+Window Left = 82 |
+Window Z-Order = 3 |
+Source Window State = "1,362,370,362,7,60,7,0,3,96,0,0,0,0,0,25,330,0,370,60,349,811,1,0," |
+ |
+[File 0009] |
+Path = "/c/home/git/arich/daq/sa02_daq/sa02lib.c" |
+File Type = "CSource" |
+Disk Date = 3559701358 |
+In Projects = "" |
+Window Top = 262 |
+Window Left = 115 |
+Window Z-Order = 7 |
+Source Window State = "1,240,240,240,1,21,21,0,3,96,0,0,0,0,0,25,213,0,240,1,349,811,1,0," |
+ |
+[Tab Order] |
+Tab 0001 = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.uir" |
+Tab 0002 = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.c" |
+Tab 0003 = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drsread.c" |
+Tab 0004 = "/c/Users/rok/Documents/rok/lab/praktikum/mioni/mioni.c" |
+Tab 0005 = "/c/home/git/arich/daq/sa02_daq/cvi/sa02_CVI.c" |
+Tab 0006 = "/c/home/git/arich/daq/sa02_daq/sa02lib.c" |
+Tab 0007 = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.h" |
+Tab 0008 = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drsread.h" |
+ |
+[Default Build Config 0001 Debug] |
+Generate Browse Info = False |
+Enable Uninitialized Locals Runtime Warning = True |
+Batch Build = False |
+Profile = "Disabled" |
+Debugging Level = "Standard" |
+Execution Trace = "Disabled" |
+Command Line Args = "" |
+Working Directory = "" |
+Environment Options = "" |
+External Process Path = "" |
+ |
+[Default Build Config 0001 Release] |
+Generate Browse Info = False |
+Enable Uninitialized Locals Runtime Warning = True |
+Batch Build = False |
+Profile = "Disabled" |
+Debugging Level = "Standard" |
+Execution Trace = "Disabled" |
+Command Line Args = "" |
+Working Directory = "" |
+Environment Options = "" |
+External Process Path = "" |
+ |
+[Default Build Config 0001 Debug64] |
+Generate Browse Info = False |
+Enable Uninitialized Locals Runtime Warning = True |
+Batch Build = False |
+Profile = "Disabled" |
+Debugging Level = "Standard" |
+Execution Trace = "Disabled" |
+Command Line Args = "" |
+Working Directory = "" |
+Environment Options = "" |
+External Process Path = "" |
+ |
+[Default Build Config 0001 Release64] |
+Generate Browse Info = False |
+Enable Uninitialized Locals Runtime Warning = True |
+Batch Build = False |
+Profile = "Disabled" |
+Debugging Level = "Standard" |
+Execution Trace = "Disabled" |
+Command Line Args = "" |
+Working Directory = "" |
+Environment Options = "" |
+External Process Path = "" |
+ |
+[Build Dependencies 0001] |
+Number of Dependencies = 0 |
+ |
+[Build Options 0001] |
+Generate Browse Info = False |
+Enable Uninitialized Locals Runtime Warning = True |
+Execution Trace = "Disabled" |
+Profile = "Disabled" |
+Debugging Level = "Standard" |
+Break On Library Errors = True |
+Break On First Chance Exceptions = False |
+ |
+[Execution Target 0001] |
+Execution Target Address = "Local desktop computer" |
+Execution Target Port = 0 |
+Execution Target Type = 0 |
+ |
+[SCC Options 0001] |
+Use global settings = True |
+SCC Provider = "" |
+SCC Project = "" |
+Local Path = "" |
+Auxiliary Path = "" |
+Perform Same Action For .h File As For .uir File = "Ask" |
+Perform Same Action For .cds File As For .prj File = "Ask" |
+Username = "" |
+Comment = "" |
+Use Default Username = False |
+Use Default Comment = False |
+Suppress CVI Error Messages = False |
+Always show confirmation dialog = True |
+ |
+[DLL Debugging Support 0001] |
+External Process Path = "" |
+ |
+[Command Line Args 0001] |
+Command Line Args = "" |
+Working Directory = "" |
+Environment Options = "" |
+ |
Index: instr/drs/drs4.h |
=================================================================== |
--- instr/drs/drs4.h (nonexistent) |
+++ instr/drs/drs4.h (revision 197) |
@@ -0,0 +1,55 @@ |
+/**************************************************************************/ |
+/* LabWindows/CVI User Interface Resource (UIR) Include File */ |
+/* */ |
+/* WARNING: Do not add to, delete from, or otherwise modify the contents */ |
+/* of this include file. */ |
+/**************************************************************************/ |
+ |
+#include <userint.h> |
+ |
+#ifdef __cplusplus |
+ extern "C" { |
+#endif |
+ |
+ /* Panels and Controls: */ |
+ |
+#define PANEL 1 |
+#define PANEL_Exit 2 /* control type: command, callback function: ExitCB */ |
+#define PANEL_STOP 3 /* control type: command, callback function: StopCB */ |
+#define PANEL_START 4 /* control type: command, callback function: StartCB */ |
+#define PANEL_TRGTYPE 5 /* control type: numeric, callback function: (none) */ |
+#define PANEL_TRGLEVEL 6 /* control type: numeric, callback function: (none) */ |
+#define PANEL_TRGDELAY 7 /* control type: numeric, callback function: (none) */ |
+#define PANEL_RANGE 8 /* control type: numeric, callback function: (none) */ |
+#define PANEL_TRGCHANNEL 9 /* control type: numeric, callback function: (none) */ |
+#define PANEL_CEVE 10 /* control type: numeric, callback function: (none) */ |
+#define PANEL_NEVE 11 /* control type: numeric, callback function: (none) */ |
+#define PANEL_FREQUENCY 12 /* control type: numeric, callback function: (none) */ |
+#define PANEL_TRGPOLARITY 13 /* control type: binary, callback function: (none) */ |
+#define PANEL_MASK 14 /* control type: string, callback function: (none) */ |
+#define PANEL_FILENAME 15 /* control type: string, callback function: (none) */ |
+#define PANEL_GRAPH 16 /* control type: graph, callback function: (none) */ |
+#define PANEL_DEBUG 17 /* control type: radioButton, callback function: (none) */ |
+#define PANEL_TIMER 18 /* control type: timer, callback function: (none) */ |
+ |
+ |
+ /* Control Arrays: */ |
+ |
+ /* (no control arrays in the resource file) */ |
+ |
+ |
+ /* Menu Bars, Menus, and Menu Items: */ |
+ |
+ /* (no menu bars in the resource file) */ |
+ |
+ |
+ /* Callback Prototypes: */ |
+ |
+int CVICALLBACK ExitCB(int panel, int control, int event, void *callbackData, int eventData1, int eventData2); |
+int CVICALLBACK StartCB(int panel, int control, int event, void *callbackData, int eventData1, int eventData2); |
+int CVICALLBACK StopCB(int panel, int control, int event, void *callbackData, int eventData1, int eventData2); |
+ |
+ |
+#ifdef __cplusplus |
+ } |
+#endif |
Index: instr/drs/drs4.prj |
=================================================================== |
--- instr/drs/drs4.prj (nonexistent) |
+++ instr/drs/drs4.prj (revision 197) |
@@ -0,0 +1,432 @@ |
+[Project Header] |
+Version = 1302 |
+Pathname = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.prj" |
+CVI Dir = "/c/program files (x86)/national instruments/cvi2013" |
+CVI Shared Dir = "/C/Program Files (x86)/National Instruments/Shared/CVI" |
+CVI Pub Local Dir = "/C/ProgramData/National Instruments/CVI2013" |
+CVI Pub Global Dir = "/C/ProgramData/National Instruments/CVI" |
+IVI Standard Root Dir = "/C/Program Files (x86)/IVI Foundation/IVI" |
+VXIplug&play Framework Dir = "/C/Program Files (x86)/IVI Foundation/VISA/winnt" |
+IVI Standard Root 64-bit Dir = "/C/Program Files/IVI Foundation/IVI" |
+VXIplug&play Framework 64-bit Dir = "/C/Program Files/IVI Foundation/VISA/win64" |
+Number of Files = 3 |
+Target Type = "Executable" |
+Flags = 2064 |
+Copied From Locked InstrDrv Directory = False |
+Copied from VXIPNP Directory = False |
+Locked InstrDrv Name = "" |
+Don't Display Deploy InstrDrv Dialog = False |
+ |
+[Folders] |
+Include Files Folder Not Added Yet = True |
+Instrument Files Folder Not Added Yet = True |
+Folder 0 = "User Interface Files" |
+FolderEx 0 = "User Interface Files" |
+Folder 1 = "Source Files" |
+FolderEx 1 = "Source Files" |
+Folder 2 = "Library Files" |
+FolderEx 2 = "Library Files" |
+ |
+[File 0001] |
+File Type = "User Interface Resource" |
+Res Id = 1 |
+Path Is Rel = True |
+Path Rel To = "Project" |
+Path Rel Path = "drs4.uir" |
+Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.uir" |
+Exclude = False |
+Project Flags = 0 |
+Folder = "User Interface Files" |
+Folder Id = 0 |
+ |
+[File 0002] |
+File Type = "CSource" |
+Res Id = 2 |
+Path Is Rel = True |
+Path Rel To = "Project" |
+Path Rel Path = "drs4.c" |
+Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.c" |
+Exclude = False |
+Compile Into Object File = False |
+Project Flags = 0 |
+Folder = "Source Files" |
+Folder Id = 1 |
+ |
+[File 0003] |
+File Type = "Library" |
+Res Id = 3 |
+Path Is Rel = True |
+Path Rel To = "Project" |
+Path Rel Path = "drsread.lib" |
+Path = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drsread.lib" |
+Exclude = False |
+Project Flags = 0 |
+Folder = "Library Files" |
+Folder Id = 2 |
+ |
+[Custom Build Configs] |
+Num Custom Build Configs = 0 |
+ |
+[Default Build Config Debug] |
+Config Name = "Debug" |
+Is 64-Bit = False |
+Is Release = False |
+Default Calling Convention = "cdecl" |
+Optimization Level = "Optimize for speed (level 2)" |
+Require Prototypes = True |
+Show Warning IDs in Build Output = False |
+Selected Warning Level = "None" |
+Warning List None = "4,9,84,105,106,107,108,109,110,111" |
+Warning List Common = "" |
+Warning List Extended = "" |
+Warning List All = "" |
+Warning Mode = 0 |
+Enable Unreferenced Identifiers Warning = False |
+Enable Pointer Mismatch Warning = False |
+Enable Unreachable Code Warning = False |
+Enable Assignment In Conditional Warning = False |
+Uninitialized Locals Compile Warning = "Aggressive" |
+Require Return Values = True |
+Enable C99 Extensions = False |
+Enable OpenMP Extensions = False |
+Stack Size = 250000 |
+Stack Reserve = 1048576 |
+Stack Commit = 4096 |
+Image Base Address = 4194304 |
+Image Base Address x64 = 4194304 |
+Compiler Defines = "/DWIN32_LEAN_AND_MEAN" |
+Sign = False |
+Sign Store = "" |
+Sign Certificate = "" |
+Sign Timestamp URL = "" |
+Sign URL = "" |
+Manifest Embed = False |
+Icon File Is Rel = False |
+Icon File = "" |
+Application Title = "" |
+Use IVI Subdirectories for Import Libraries = False |
+Use VXIPNP Subdirectories for Import Libraries = False |
+Use Dflt Import Lib Base Name = True |
+Where to Copy DLL = "Do not copy" |
+Custom Directory to Copy DLL Is Rel = False |
+Custom Directory to Copy DLL = "" |
+Generate Source Documentation = "None" |
+Runtime Support = "Full Runtime Support" |
+Runtime Binding = "Shared" |
+Embed Project .UIRs = False |
+Generate Map File = False |
+Embed Timestamp = True |
+Create Console Application = False |
+Using LoadExternalModule = False |
+DLL Exports = "Include File Symbols" |
+Register ActiveX Server = False |
+Numeric File Version = "1,0,0,0" |
+Numeric Prod Version = "1,0,0,0" |
+Comments = "" |
+Comments Ex = "" |
+Company Name = "" |
+Company Name Ex = "%company" |
+File Description = "drs4 (Debug x86)" |
+File Description Ex = "%application (%rel_dbg %arch)" |
+File Version = "1.0" |
+File Version Ex = "%f1.%f2" |
+Internal Name = "drs4" |
+Internal Name Ex = "%basename" |
+Legal Copyright = "Copyright © 2017" |
+Legal Copyright Ex = "Copyright © %company %Y" |
+Legal Trademarks = "" |
+Legal Trademarks Ex = "" |
+Original Filename = "drs4.exe" |
+Original Filename Ex = "%filename" |
+Private Build = "" |
+Private Build Ex = "" |
+Product Name = " drs4" |
+Product Name Ex = "%company %application" |
+Product Version = "1.0" |
+Product Version Ex = "%p1.%p2" |
+Special Build = "" |
+Special Build Ex = "" |
+Add Type Lib To DLL = False |
+Include Type Lib Help Links = False |
+TLB Help Style = "HLP" |
+Type Lib FP File Is Rel = False |
+Type Lib FP File = "" |
+ |
+[Default Build Config Release] |
+Config Name = "Release" |
+Is 64-Bit = False |
+Is Release = True |
+Default Calling Convention = "cdecl" |
+Optimization Level = "Optimize for speed (level 2)" |
+Require Prototypes = True |
+Show Warning IDs in Build Output = False |
+Selected Warning Level = "None" |
+Warning List None = "4,9,84,105,106,107,108,109,110,111" |
+Warning List Common = "" |
+Warning List Extended = "" |
+Warning List All = "" |
+Warning Mode = 0 |
+Enable Unreferenced Identifiers Warning = False |
+Enable Pointer Mismatch Warning = False |
+Enable Unreachable Code Warning = False |
+Enable Assignment In Conditional Warning = False |
+Uninitialized Locals Compile Warning = "Aggressive" |
+Require Return Values = True |
+Enable C99 Extensions = False |
+Enable OpenMP Extensions = False |
+Stack Size = 250000 |
+Stack Reserve = 1048576 |
+Stack Commit = 4096 |
+Image Base Address = 4194304 |
+Image Base Address x64 = 4194304 |
+Compiler Defines = "/DWIN32_LEAN_AND_MEAN" |
+Sign = False |
+Sign Store = "" |
+Sign Certificate = "" |
+Sign Timestamp URL = "" |
+Sign URL = "" |
+Manifest Embed = False |
+Icon File Is Rel = False |
+Icon File = "" |
+Application Title = "" |
+Use IVI Subdirectories for Import Libraries = False |
+Use VXIPNP Subdirectories for Import Libraries = False |
+Use Dflt Import Lib Base Name = True |
+Where to Copy DLL = "Do not copy" |
+Custom Directory to Copy DLL Is Rel = False |
+Custom Directory to Copy DLL = "" |
+Generate Source Documentation = "None" |
+Runtime Support = "Full Runtime Support" |
+Runtime Binding = "Shared" |
+Embed Project .UIRs = False |
+Generate Map File = False |
+Embed Timestamp = True |
+Create Console Application = False |
+Using LoadExternalModule = False |
+DLL Exports = "Include File Symbols" |
+Register ActiveX Server = False |
+Add Type Lib To DLL = False |
+Include Type Lib Help Links = False |
+TLB Help Style = "HLP" |
+Type Lib FP File Is Rel = False |
+Type Lib FP File = "" |
+ |
+[Default Build Config Debug64] |
+Config Name = "Debug64" |
+Is 64-Bit = True |
+Is Release = False |
+Default Calling Convention = "cdecl" |
+Optimization Level = "Optimize for speed (level 2)" |
+Require Prototypes = True |
+Show Warning IDs in Build Output = False |
+Selected Warning Level = "None" |
+Warning List None = "4,9,84,105,106,107,108,109,110,111" |
+Warning List Common = "" |
+Warning List Extended = "" |
+Warning List All = "" |
+Warning Mode = 0 |
+Enable Unreferenced Identifiers Warning = False |
+Enable Pointer Mismatch Warning = False |
+Enable Unreachable Code Warning = False |
+Enable Assignment In Conditional Warning = False |
+Uninitialized Locals Compile Warning = "Aggressive" |
+Require Return Values = True |
+Enable C99 Extensions = False |
+Enable OpenMP Extensions = False |
+Stack Size = 250000 |
+Stack Reserve = 1048576 |
+Stack Commit = 4096 |
+Image Base Address = 4194304 |
+Image Base Address x64 = 4194304 |
+Compiler Defines = "/DWIN32_LEAN_AND_MEAN" |
+Sign = False |
+Sign Store = "" |
+Sign Certificate = "" |
+Sign Timestamp URL = "" |
+Sign URL = "" |
+Manifest Embed = False |
+Icon File Is Rel = False |
+Icon File = "" |
+Application Title = "" |
+Use IVI Subdirectories for Import Libraries = False |
+Use VXIPNP Subdirectories for Import Libraries = False |
+Use Dflt Import Lib Base Name = True |
+Where to Copy DLL = "Do not copy" |
+Custom Directory to Copy DLL Is Rel = False |
+Custom Directory to Copy DLL = "" |
+Generate Source Documentation = "None" |
+Runtime Support = "Full Runtime Support" |
+Runtime Binding = "Shared" |
+Embed Project .UIRs = False |
+Generate Map File = False |
+Embed Timestamp = True |
+Create Console Application = False |
+Using LoadExternalModule = False |
+DLL Exports = "Include File Symbols" |
+Register ActiveX Server = False |
+Add Type Lib To DLL = False |
+Include Type Lib Help Links = False |
+TLB Help Style = "HLP" |
+Type Lib FP File Is Rel = False |
+Type Lib FP File = "" |
+ |
+[Default Build Config Release64] |
+Config Name = "Release64" |
+Is 64-Bit = True |
+Is Release = True |
+Default Calling Convention = "cdecl" |
+Optimization Level = "Optimize for speed (level 2)" |
+Require Prototypes = True |
+Show Warning IDs in Build Output = False |
+Selected Warning Level = "None" |
+Warning List None = "4,9,84,105,106,107,108,109,110,111" |
+Warning List Common = "" |
+Warning List Extended = "" |
+Warning List All = "" |
+Warning Mode = 0 |
+Enable Unreferenced Identifiers Warning = False |
+Enable Pointer Mismatch Warning = False |
+Enable Unreachable Code Warning = False |
+Enable Assignment In Conditional Warning = False |
+Uninitialized Locals Compile Warning = "Aggressive" |
+Require Return Values = True |
+Enable C99 Extensions = False |
+Enable OpenMP Extensions = False |
+Stack Size = 250000 |
+Stack Reserve = 1048576 |
+Stack Commit = 4096 |
+Image Base Address = 4194304 |
+Image Base Address x64 = 4194304 |
+Compiler Defines = "/DWIN32_LEAN_AND_MEAN" |
+Sign = False |
+Sign Store = "" |
+Sign Certificate = "" |
+Sign Timestamp URL = "" |
+Sign URL = "" |
+Manifest Embed = False |
+Icon File Is Rel = False |
+Icon File = "" |
+Application Title = "" |
+Use IVI Subdirectories for Import Libraries = False |
+Use VXIPNP Subdirectories for Import Libraries = False |
+Use Dflt Import Lib Base Name = True |
+Where to Copy DLL = "Do not copy" |
+Custom Directory to Copy DLL Is Rel = False |
+Custom Directory to Copy DLL = "" |
+Generate Source Documentation = "None" |
+Runtime Support = "Full Runtime Support" |
+Runtime Binding = "Shared" |
+Embed Project .UIRs = False |
+Generate Map File = False |
+Embed Timestamp = True |
+Create Console Application = False |
+Using LoadExternalModule = False |
+DLL Exports = "Include File Symbols" |
+Register ActiveX Server = False |
+Add Type Lib To DLL = False |
+Include Type Lib Help Links = False |
+TLB Help Style = "HLP" |
+Type Lib FP File Is Rel = False |
+Type Lib FP File = "" |
+ |
+[Compiler Options] |
+Default Calling Convention = "cdecl" |
+Require Prototypes = True |
+Require Return Values = True |
+Enable Pointer Mismatch Warning = False |
+Enable Unreachable Code Warning = False |
+Enable Unreferenced Identifiers Warning = False |
+Enable Assignment In Conditional Warning = False |
+O Option Compatible With 5.0 = False |
+Enable C99 Extensions = False |
+Uninitialized Locals Compile Warning = "Aggressive" |
+Precompile Prefix Header = False |
+Prefix Header File = "" |
+ |
+[Run Options] |
+Stack Size = 250000 |
+Stack Commit = 4096 |
+Image Base Address = 4194304 |
+Image Base Address x64 = 4194304 |
+ |
+[Compiler Defines] |
+Compiler Defines = "/DWIN32_LEAN_AND_MEAN" |
+ |
+[Create Executable] |
+Executable File_Debug Is Rel = True |
+Executable File_Debug Rel To = "Project" |
+Executable File_Debug Rel Path = "drs4.exe" |
+Executable File_Debug = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.exe" |
+Executable File_Release Is Rel = True |
+Executable File_Release Rel To = "Project" |
+Executable File_Release Rel Path = "drs4.exe" |
+Executable File_Release = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.exe" |
+Executable File_Debug64 Is Rel = True |
+Executable File_Debug64 Rel To = "Project" |
+Executable File_Debug64 Rel Path = "drs4.exe" |
+Executable File_Debug64 = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.exe" |
+Executable File_Release64 Is Rel = True |
+Executable File_Release64 Rel To = "Project" |
+Executable File_Release64 Rel Path = "drs4.exe" |
+Executable File_Release64 = "/c/Users/rok/Documents/rok/lab/drs/drsctrl/drs4.exe" |
+Icon File Is Rel = False |
+Icon File = "" |
+Application Title = "" |
+DLL Exports = "Include File Symbols" |
+Use IVI Subdirectories for Import Libraries = False |
+Use VXIPNP Subdirectories for Import Libraries = False |
+Use Dflt Import Lib Base Name = True |
+Where to Copy DLL = "Do not copy" |
+Custom Directory to Copy DLL Is Rel = False |
+Custom Directory to Copy DLL = "" |
+Generate Source Documentation = "None" |
+Add Type Lib To DLL = False |
+Include Type Lib Help Links = False |
+TLB Help Style = "HLP" |
+Type Lib FP File Is Rel = False |
+Type Lib FP File = "" |
+Type Lib Guid = "" |
+Runtime Support = "Full Runtime Support" |
+Instrument Driver Support Only = False |
+Embed Project .UIRs = False |
+Generate Map File = False |
+ |
+[External Compiler Support] |
+UIR Callbacks File Option = 0 |
+Using LoadExternalModule = False |
+Create Project Symbols File = True |
+UIR Callbacks Obj File Is Rel = False |
+UIR Callbacks Obj File = "" |
+Project Symbols H File Is Rel = False |
+Project Symbols H File = "" |
+Project Symbols Obj File Is Rel = False |
+Project Symbols Obj File = "" |
+ |
+[ActiveX Server Options] |
+Specification File Is Rel = False |
+Specification File = "" |
+Source File Is Rel = False |
+Source File = "" |
+Include File Is Rel = False |
+Include File = "" |
+IDL File Is Rel = False |
+IDL File = "" |
+Register ActiveX Server = False |
+ |
+[Signing Info] |
+Sign = False |
+Sign Debug Build = False |
+Store = "" |
+Certificate = "" |
+Timestamp URL = "" |
+URL = "" |
+ |
+[Manifest Info] |
+Embed = False |
+ |
+[tpcSection] |
+tpcEnabled = 0 |
+tpcOverrideEnvironment = 0 |
+tpcEnabled x64 = 0 |
+tpcOverrideEnvironment x64 = 0 |
+ |
Index: instr/drs/drs4.uir |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/instr/drs/drs4.uir |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: instr/drs/drscl.cpp |
=================================================================== |
--- instr/drs/drscl.cpp (nonexistent) |
+++ instr/drs/drscl.cpp (revision 197) |
@@ -0,0 +1,1647 @@ |
+/********************************************************************\ |
+ |
+ Name: drscl.cpp |
+ Created by: Stefan Ritt |
+ |
+ Contents: Command line interface to DRS chip via USB and VME |
+ |
+ $Id: drscl.cpp 21435 2014-07-30 13:02:31Z ritt $ |
+ |
+\********************************************************************/ |
+ |
+#include <math.h> |
+ |
+#ifdef _MSC_VER |
+ |
+#include <windows.h> |
+#include <conio.h> |
+#include <io.h> |
+#include <direct.h> |
+ |
+#define DIR_SEPARATOR '\\' |
+ |
+#elif defined(OS_LINUX) || defined(OS_DARWIN) |
+ |
+#define O_BINARY 0 |
+ |
+#include <unistd.h> |
+#include <ctype.h> |
+#include <sys/ioctl.h> |
+#include <errno.h> |
+ |
+#define DIR_SEPARATOR '/' |
+ |
+#endif |
+ |
+#include <stdio.h> |
+#include <string.h> |
+#include <stdlib.h> |
+#include <fcntl.h> |
+#include <time.h> |
+#include <sys/stat.h> |
+#include <assert.h> |
+ |
+#include "strlcpy.h" |
+#include "DRS.h" |
+#ifdef HAVE_VME |
+#include "ace.h" |
+#endif |
+ |
+const char *drscl_svn_revision = "$Id: drscl.cpp 21435 2014-07-30 13:02:31Z ritt $"; |
+ |
+void print_help(); |
+void clear_screen(); |
+int match(const char *str, const char *cmd); |
+void cmd_loop(); |
+ |
+#if defined(OS_LINUX) || defined(OS_DARWIN) |
+#define getch() getchar() |
+#define Sleep(x) usleep(x*1000) |
+#endif |
+ |
+#ifdef _MSC_VER |
+#include <conio.h> |
+#define drs_kbhit() kbhit() |
+#endif |
+ |
+void print_help() |
+{ |
+ puts("Available commands:\n"); |
+ puts("active <0|1> Set domino active mode on (1) or off (0)"); |
+ puts("board <i>|<i1> <i2>|all Address individual board/range/all boards"); |
+ puts("calib [dir] Response Calibration. Use dir=\"area\" for MEG"); |
+ puts("chn [n] Set number of channels: 8, 4, 2, 1"); |
+ puts("ct Chip Test"); |
+ puts("del <0|1> Switch delayed start on/off"); |
+ puts("dir Show CF directory"); |
+ puts("dmode <0|1> Set Domino mode 0=single, 1=cont."); |
+ puts("et EEPROM test"); |
+ puts("exit Exit program"); |
+ puts("freq <ghz> [0|1] Set frequency of board [without/with] regulation"); |
+ puts("info Show information about board"); |
+ puts("init Initialize board"); |
+ puts("led <0|1> Turn LED on (1) or off (0)"); |
+ puts("lock [0|1] Display lock status [without/with] restart"); |
+ puts("multi [0|1] Turn multi-buffer mode on/off"); |
+ puts("offset <voltage> Set offset voltage"); |
+ puts("phase <value> [0|1] Set ADC clock phase and inversion"); |
+ puts("quit Exit program"); |
+ puts("ram Test speed to FPGA RAM"); |
+ puts("range <center> Change input range to <center>+=0.5V"); |
+ puts("read <chn> [0|1] [file] Read waveform to [file], chn=0..19 [with] calibration"); |
+ puts("refclk [0|1] Use FPGA ref. clk (0) or ext. P2 ref. clk (1)"); |
+ puts("reg Register test"); |
+ puts("serial <number> Set serial number of board"); |
+ puts("scan Scan for boards"); |
+ puts("standby <0|1> Turn standby mode on (1) or off (0)"); |
+ puts("start Start domino wave"); |
+ puts("stop Issue soft trigger"); |
+ puts("tcout [file] [idx_offset] Print time calibration of DRS4, or write it onto [file]"); |
+ puts("tcs <0|1> Timing calibration signal on (1) or off (0)"); |
+ puts("tcalib [freq] Timing Calibration"); |
+ puts("tlevel <voltage> Set trigger level in Volts"); |
+ puts("trans <0|1> Set transparent mode on (1) or off (0)"); |
+ puts("trig <0|1> Hardware trigger on (1) or off (0)"); |
+ puts("upload <file> Upload ACE file to CF"); |
+ puts("volt off|<voltage> Turn calibration voltage on/off"); |
+ |
+ puts(""); |
+} |
+ |
+/*------------------------------------------------------------------*/ |
+ |
+void clear_screen() |
+{ |
+#ifdef _MSC_VER |
+ |
+ HANDLE hConsole; |
+ COORD coordScreen = { 0, 0 }; /* here's where we'll home the cursor */ |
+ BOOL bSuccess; |
+ DWORD cCharsWritten; |
+ CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */ |
+ DWORD dwConSize; /* number of character cells in the current buffer */ |
+ |
+ hConsole = GetStdHandle(STD_OUTPUT_HANDLE); |
+ |
+ /* get the number of character cells in the current buffer */ |
+ bSuccess = GetConsoleScreenBufferInfo(hConsole, &csbi); |
+ dwConSize = csbi.dwSize.X * csbi.dwSize.Y; |
+ |
+ /* fill the entire screen with blanks */ |
+ bSuccess = FillConsoleOutputCharacter(hConsole, (TCHAR) ' ', dwConSize, coordScreen, &cCharsWritten); |
+ |
+ /* put the cursor at (0, 0) */ |
+ bSuccess = SetConsoleCursorPosition(hConsole, coordScreen); |
+ return; |
+ |
+#else |
+ printf("\033[2J"); |
+#endif |
+} |
+ |
+/*------------------------------------------------------------------*/ |
+ |
+int match(const char *str, const char *cmd) |
+{ |
+ int i; |
+ |
+ if (str[0] == '\r' || str[0] == '\n') |
+ return 0; |
+ |
+ for (i = 0; i < (int) strlen(str); i++) { |
+ if (toupper(str[i]) != toupper(cmd[i]) && str[i] != '\r' && str[i] != '\n') |
+ return 0; |
+ } |
+ |
+ return 1; |
+} |
+ |
+/*------------------------------------------------------------------*/ |
+ |
+class ProgressBar : public DRSCallback |
+{ |
+public: |
+ void Progress(int prog); |
+}; |
+ |
+void ProgressBar::Progress(int prog) |
+{ |
+ if (prog == 0) |
+ printf("[--------------------------------------------------]\r"); |
+ printf("["); |
+ for (int i=0 ; i<prog/2 ; i++) |
+ printf("="); |
+ printf("\r"); |
+ fflush(stdout); |
+} |
+ |
+/*------------------------------------------------------------------*/ |
+ |
+void cmd_loop() |
+{ |
+ int i, j, idx, i_start, i_end, nparam, calib, status, debug, cascading, |
+ ext_refclk; |
+ char str[256], dir[256], line[256], file_name[256], param[10][100], *pc; |
+ double freq, triggerfreq, range; |
+ FILE *f = NULL; |
+ DRS *drs; |
+ DRSBoard *b; |
+#ifdef HAVE_VME |
+ ACE ace; |
+#endif |
+ static char bar[] = {'\\', '|', '/', '-'}; |
+ |
+ /* do initial scan */ |
+ drs = new DRS(); |
+ if (drs->GetError(str, sizeof(str))) |
+ printf("%s", str); |
+ |
+ for (i=0 ; i<drs->GetNumberOfBoards() ; i++) { |
+ b = drs->GetBoard(i); |
+#ifdef HAVE_VME |
+ if (b->GetTransport() != 1) |
+ printf("Found DRS%d board %2d on USB, serial #%04d, firmware revision %5d\n", |
+ b->GetDRSType(), i, b->GetBoardSerialNumber(), b->GetFirmwareVersion()); |
+#else |
+ printf("Found DRS%d board %2d on USB, serial #%04d, firmware revision %5d\n", |
+ b->GetDRSType(), i, b->GetBoardSerialNumber(), b->GetFirmwareVersion()); |
+#endif |
+ } |
+ |
+ if (drs->GetNumberOfBoards()) { |
+ i_start = 0; |
+ i_end = 1; |
+ b = drs->GetBoard(0); |
+ } |
+ else { |
+ printf("No DRS Boards found\n"); |
+ i_start = i_end = 0; |
+ b = NULL; |
+ } |
+ |
+ puts(""); |
+ |
+ do { |
+ /* print prompt */ |
+ if (i_start == i_end-1) |
+ printf("B%d> ", i_start); |
+ else if (i_start == 0 && i_end == 0) |
+ printf("> "); |
+ else |
+ printf("B%d-%d> ", i_start, i_end-1); |
+ memset(line, 0, sizeof(line)); |
+ fgets(line, sizeof(line), stdin); |
+ /* strip \r\n */ |
+ while (strpbrk(line,"\n\r")) |
+ *strpbrk(line,"\n\r") = 0; |
+ |
+ /* analyze line */ |
+ nparam = 0; |
+ pc = line; |
+ while (*pc == ' ') |
+ pc++; |
+ |
+ memset(param, 0, sizeof(param)); |
+ do { |
+ if (*pc == '"') { |
+ pc++; |
+ for (i = 0; *pc && *pc != '"'; i++) |
+ param[nparam][i] = *pc++; |
+ if (*pc) |
+ pc++; |
+ } else if (*pc == '\'') { |
+ pc++; |
+ for (i = 0; *pc && *pc != '\''; i++) |
+ param[nparam][i] = *pc++; |
+ if (*pc) |
+ pc++; |
+ } else if (*pc == '`') { |
+ pc++; |
+ for (i = 0; *pc && *pc != '`'; i++) |
+ param[nparam][i] = *pc++; |
+ if (*pc) |
+ pc++; |
+ } else |
+ for (i = 0; *pc && *pc != ' '; i++) |
+ param[nparam][i] = *pc++; |
+ param[nparam][i] = 0; |
+ while (*pc == ' ' || *pc == '\r' || *pc == '\n') |
+ pc++; |
+ nparam++; |
+ } while (*pc); |
+ |
+ if (param[0][0] == 0) { |
+ } |
+ |
+ /* help ---------- */ |
+ else if ((param[0][0] == 'h' && param[0][1] == 'e') || param[0][0] == '?') |
+ print_help(); |
+ |
+ /* scan ---------- */ |
+ else if (match(param[0], "scan")) { |
+ j = 0; |
+ |
+ do { |
+ delete drs; |
+ drs = new DRS(); |
+ |
+ for (i=0 ; i<drs->GetNumberOfBoards() ; i++) { |
+ b = drs->GetBoard(i); |
+#ifdef HAVE_VME |
+ if (b->GetTransport() != 1) |
+ printf("Found DRS%d board %2d on USB, serial #%04d, firmware revision %5d\n", |
+ b->GetDRSType(), i, b->GetBoardSerialNumber(), b->GetFirmwareVersion()); |
+#else |
+ printf("Found DRS%d board %2d on USB, serial #%04d, firmware revision %5d\n", |
+ b->GetDRSType(), i, b->GetBoardSerialNumber(), b->GetFirmwareVersion()); |
+#endif |
+ } |
+ |
+ if (drs_kbhit()) |
+ break; |
+ |
+ if (param[1][0] == 'r') { |
+ printf("%c\r", bar[j]); |
+ fflush(stdout); |
+ j = (j+1) % 4; |
+ Sleep(1000); |
+ } |
+ |
+ } while (param[1][0] == 'r'); |
+ |
+ while (drs_kbhit()) |
+ getch(); |
+ |
+ if (drs->GetNumberOfBoards()) { |
+ i_start = 0; |
+ i_end = 1; |
+ b = drs->GetBoard(0); |
+ } else { |
+ printf("No DRS Boards found\n"); |
+ i_start = i_end = 0; |
+ b = NULL; |
+ } |
+ } |
+ |
+ /* address board ---------- */ |
+ else if (match(param[0], "board")) { |
+ if (param[1][0] == 'a') { |
+ i_start = 0; |
+ i_end = drs->GetNumberOfBoards(); |
+ b = drs->GetBoard(0); |
+ } else if (param[2][0] && atoi(param[2]) > 0 && atoi(param[2]) < drs->GetNumberOfBoards()) { |
+ i_start = atoi(param[1]); |
+ i_end = atoi(param[2]) + 1; |
+ b = drs->GetBoard(i_start); |
+ } else if (atoi(param[1]) >= 0 && atoi(param[1]) < drs->GetNumberOfBoards()) { |
+ i_start = atoi(param[1]); |
+ i_end = i_start + 1; |
+ b = drs->GetBoard(i_start); |
+ } else |
+ printf("Board #%d does not exist\n", atoi(param[1])); |
+ } |
+ |
+ /* info ---------- */ |
+ else if (match(param[0], "info")) { |
+ for (idx=i_start ; idx<i_end ; idx++) { |
+ b = drs->GetBoard(idx); |
+ printf("==============================\n"); |
+ printf("Mezz. Board index: %d\n", idx); |
+#ifdef HAVE_VME |
+ if (b->GetTransport() == TR_VME) { |
+ printf("Slot: %d", (b->GetSlotNumber() >> 1)+2); |
+ if ((b->GetSlotNumber() & 1) == 0) |
+ printf(" upper\n"); |
+ else |
+ printf(" lower\n"); |
+ } |
+#endif |
+ printf("DRS type: DRS%d\n", b->GetDRSType()); |
+ printf("Board type: %d\n", b->GetBoardType()); |
+ printf("Serial number: %04d\n", b->GetBoardSerialNumber()); |
+ printf("Firmware revision: %d\n", b->GetFirmwareVersion()); |
+ printf("Temperature: %1.1lf C\n", b->GetTemperature()); |
+ if (b->GetDRSType() == 4) { |
+ printf("Input range: %1.2lgV...%1.2lgV\n", |
+ b->GetInputRange()-0.5, b->GetInputRange()+0.5); |
+ printf("Calibrated range: %1.2lgV...%1.2lgV\n", b->GetCalibratedInputRange()-0.5, |
+ b->GetCalibratedInputRange()+0.5); |
+ printf("Calibrated frequency: %1.3lf GHz\n", b->GetCalibratedFrequency()); |
+ |
+ if (b->GetTransport() == TR_VME) { |
+ printf("Multi Buffer WP: %d\n", b->GetMultiBufferWP()); |
+ printf("Multi Buffer RP: %d\n", b->GetMultiBufferRP()); |
+ } |
+ } |
+ |
+ printf("Status reg.: %08X\n", b->GetStatusReg()); |
+ if (b->GetStatusReg() & BIT_RUNNING) |
+ puts(" Domino wave running"); |
+ if (b->GetDRSType() == 4) { |
+ if (b->GetBoardType() == 5) { |
+ if (b->GetStatusReg() & BIT_PLL_LOCKED0) |
+ puts(" PLL locked"); |
+ } else if (b->GetBoardType() == 6) { |
+ i = 0; |
+ if (b->GetStatusReg() & BIT_PLL_LOCKED0) i++; |
+ if (b->GetStatusReg() & BIT_PLL_LOCKED1) i++; |
+ if (b->GetStatusReg() & BIT_PLL_LOCKED2) i++; |
+ if (b->GetStatusReg() & BIT_PLL_LOCKED3) i++; |
+ if (i == 4) |
+ puts(" All PLLs locked"); |
+ else if (i == 0) |
+ puts(" No PLL locked"); |
+ else |
+ printf(" %d PLLs locked\n", i); |
+ if (b->GetStatusReg() & BIT_LMK_LOCKED) |
+ puts(" LMK PLL locked"); |
+ } |
+ } else { |
+ if (b->GetStatusReg() & BIT_NEW_FREQ1) |
+ puts(" New Freq1 ready"); |
+ if (b->GetStatusReg() & BIT_NEW_FREQ2) |
+ puts(" New Freq2 ready"); |
+ } |
+ |
+ printf("Control reg.: %08X\n", b->GetCtrlReg()); |
+ if (b->GetCtrlReg() & BIT_MULTI_BUFFER) |
+ puts(" Multi-buffering enabled"); |
+ if (b->GetDRSType() == 4) { |
+ if (b->GetConfigReg() & BIT_CONFIG_DMODE) |
+ puts(" DMODE circular"); |
+ else |
+ puts(" DMODE single shot"); |
+ } else { |
+ if (b->GetCtrlReg() & BIT_DMODE) |
+ puts(" DMODE circular"); |
+ else |
+ puts(" DMODE single shot"); |
+ } |
+ if (b->GetCtrlReg() & BIT_LED) |
+ puts(" LED"); |
+ if (b->GetCtrlReg() & BIT_TCAL_EN) |
+ puts(" TCAL enabled"); |
+ if (b->GetDRSType() == 4) { |
+ if (b->GetCtrlReg() & BIT_TRANSP_MODE) |
+ puts(" TRANSP_MODE enabled"); |
+ } else { |
+ if (b->GetCtrlReg() & BIT_FREQ_AUTO_ADJ) |
+ puts(" FREQ_AUTO_ADJ enabled"); |
+ } |
+ if (b->GetCtrlReg() & BIT_ENABLE_TRIGGER1) |
+ puts(" Hardware trigger enabled"); |
+ if (b->GetDRSType() == 4) { |
+ if (b->GetCtrlReg() & BIT_READOUT_MODE) |
+ puts(" Readout from stop"); |
+ if (b->GetCtrlReg() & BIT_ENABLE_TRIGGER2) |
+ puts(" Internal trigger enabled"); |
+ } else { |
+ if (b->GetCtrlReg() & BIT_LONG_START_PULSE) |
+ puts(" LONG_START_PULSE"); |
+ } |
+ if (b->GetCtrlReg() & BIT_DELAYED_START) |
+ puts(" DELAYED_START"); |
+ if (b->GetCtrlReg() & BIT_ACAL_EN) |
+ puts(" ACAL enabled"); |
+ if (b->GetDRSType() < 4) |
+ if (b->GetCtrlReg() & BIT_TRIGGER_DELAYED) |
+ puts(" DELAYED_TRIGGER selected"); |
+ if (b->GetBoardType() != 5) |
+ printf("Trigger bus: %08X\n", b->GetTriggerBus()); |
+ if (b->GetDRSType() == 4) { |
+ if (b->GetRefclk() == 1) { |
+ if (b->IsPLLLocked() && b->IsLMKLocked()) { |
+ b->ReadFrequency(0, &freq); |
+ printf("Frequency: %1.3lf GHz\n", freq); |
+ } else { |
+ if (!b->IsPLLLocked()) |
+ printf("Frequency: PLL not locked\n"); |
+ else |
+ printf("Frequency: LMK chip not locked\n"); |
+ } |
+ } else { |
+ if (b->IsPLLLocked()) { |
+ b->ReadFrequency(0, &freq); |
+ printf("Frequency: %1.3lf GHz\n", freq); |
+ } else { |
+ printf("Frequency: PLL not locked\n"); |
+ } |
+ } |
+ } else { |
+ if (b->IsBusy()) { |
+ b->ReadFrequency(0, &freq); |
+ printf("Frequency0: %1.4lf GHz\n", freq); |
+ b->ReadFrequency(1, &freq); |
+ printf("Frequency1: %1.4lf GHz\n", freq); |
+ } else |
+ puts("Domino wave stopped"); |
+ } |
+ } |
+ } |
+ |
+ /* init ---------- */ |
+ else if (match(param[0], "init")) { |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ b->Init(); |
+ } |
+ } |
+ |
+ /* set led ---------- */ |
+ else if (match(param[0], "led")) { |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ if (atoi(param[1])) |
+ b->SetLED(1); |
+ else |
+ b->SetLED(0); |
+ } |
+ } |
+ |
+ /* set multi buffer mode ---------- */ |
+ else if (match(param[0], "multi")) { |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ if (atoi(param[1])) |
+ b->SetMultiBuffer(1); |
+ else |
+ b->SetMultiBuffer(0); |
+ } |
+ } |
+ |
+ /* lock status ---------- */ |
+ else if (match(param[0], "lock")) { |
+ int slot, found, restart; |
+ |
+ restart = atoi(param[1]); |
+ |
+ // select external reference clock |
+ for (i=0 ; i<drs->GetNumberOfBoards() ; i++) { |
+ b = drs->GetBoard(i); |
+ b->SetRefclk(1); |
+ b->SetFrequency(b->GetNominalFrequency(), true); |
+ } |
+ |
+ // loop until keyboard hit |
+ do { |
+ clear_screen(); |
+ printf(" 1 1 1 1 1 1 1 1 1 1 2 2\n"); |
+ printf("2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\n\n"); |
+ |
+ // upper slots |
+ for (slot = 2 ; slot<22 ; slot++) { |
+ found = 0; |
+ for (i=0 ; i<drs->GetNumberOfBoards() ; i++) { |
+ b = drs->GetBoard(i); |
+ if ((b->GetSlotNumber() & 1) == 0 && (b->GetSlotNumber() >> 1)+2 == slot) { |
+ found = 1; |
+ if (b->IsLMKLocked()) |
+ printf("O "); |
+ else |
+ printf("- "); |
+ } |
+ } |
+ if (!found) |
+ printf(" "); |
+ } |
+ printf("\n"); |
+ |
+ // lower slots |
+ for (slot = 2 ; slot<22 ; slot++) { |
+ found = 0; |
+ for (i=0 ; i<drs->GetNumberOfBoards() ; i++) { |
+ b = drs->GetBoard(i); |
+ if ((b->GetSlotNumber() & 1) == 1 && (b->GetSlotNumber() >> 1)+2 == slot) { |
+ found = 1; |
+ if (b->IsLMKLocked()) |
+ printf("O "); |
+ else |
+ printf("- "); |
+ } |
+ } |
+ if (!found) |
+ printf(" "); |
+ } |
+ printf("\n"); |
+ |
+ if (restart) { |
+ for (i=0 ; i<drs->GetNumberOfBoards() ; i++) { |
+ b = drs->GetBoard(i); |
+ b->SetFrequency(b->GetNominalFrequency(), true); |
+ } |
+ } |
+ |
+ Sleep(300); |
+ |
+ } while (!drs_kbhit()); |
+ puts(""); |
+ while (drs_kbhit()) |
+ getch(); |
+ } |
+ |
+ /* start domino wave ---------- */ |
+ else if (match(param[0], "start")) { |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ b->StartDomino(); |
+ b->ReadFrequency(0, &freq); |
+ for (j=0 ; j<10 ; j++) |
+ if (b->GetDRSType() != 4 || b->IsPLLLocked()) |
+ break; |
+ if (j == 10) |
+ printf("Domino wave started but PLL did not lock!\n"); |
+ else |
+ printf("Domino wave started at %1.3lf GHz\n", freq); |
+ } |
+ } |
+ |
+ /* issue soft trigger ---------- */ |
+ else if (match(param[0], "stop")) { |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ b->SoftTrigger(); |
+ } |
+ } |
+ |
+ /* set serial ---------- */ |
+ else if (match(param[0], "serial")) { |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ if (param[1][0] == 0) { |
+ printf("Serial number: "); |
+ fgets(str, sizeof(str), stdin); |
+ } else |
+ strlcpy(str, param[1], sizeof(str)); |
+ |
+ if (!b->SetBoardSerialNumber(atoi(str))) |
+ printf("Board EEPROM is write protected\n"); |
+ else |
+ printf("Serial number successfully changed\n"); |
+ } |
+ } |
+ |
+ /* eeprom test ---------- */ |
+ else if (match(param[0], "et")) { |
+ unsigned short buf[16384]; |
+ unsigned short rbuf[16384]; |
+ int n_error; |
+ |
+ do { |
+ for (i=0 ; i<16384 ; i++) |
+ buf[i] = rand(); |
+ b->WriteEEPROM(1, buf, sizeof(buf)); |
+ memset(rbuf, 0, sizeof(rbuf)); |
+ b->Write(T_RAM, 0, rbuf, sizeof(rbuf)); |
+ b->ReadEEPROM(1, rbuf, sizeof(rbuf)); |
+ for (i=n_error=0 ; i<16384 ; i++) |
+ if (buf[i] != rbuf[i]) { |
+ printf("%04X %04X - %04X\n", i, buf[i], rbuf[i]); |
+ n_error++; |
+ } |
+ |
+ printf("32 kb written, %d errors\n", n_error); |
+ } while (!drs_kbhit()); |
+ |
+ while (drs_kbhit()) |
+ getch(); |
+ } |
+ |
+ /* set frequency ---------- */ |
+ else if (match(param[0], "freq")) { |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ if (param[1][0] == 0) { |
+ printf("Frequency: "); |
+ fgets(str, sizeof(str), stdin); |
+ } else |
+ strlcpy(str, param[1], sizeof(str)); |
+ |
+ b->SetDebug(1); |
+ |
+ if (param[2][0] && atoi(param[2])) |
+ b->RegulateFrequency(atof(str)); |
+ else |
+ b->SetFrequency(atof(str), true); |
+ } |
+ } |
+ |
+ /* set calibration voltage ---------- */ |
+ else if (match(param[0], "volt")) { |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ if (param[1][0] == 0) { |
+ printf("Voltage or \"off\": "); |
+ fgets(str, sizeof(str), stdin); |
+ } else |
+ strlcpy(str, param[1], sizeof(str)); |
+ |
+ if (str[0] == 'o') { |
+ b->EnableAcal(0, 0); |
+ puts("Calibration voltage turned off"); |
+ } else { |
+ b->EnableAcal(1, atof(str)); |
+ printf("Voltage set to %1.3lf Volt\n", atof(str)); |
+ } |
+ } |
+ } |
+ |
+ /* set channel configuration ---------- */ |
+ else if (match(param[0], "chn")) { |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ if (param[1][0] == 0) { |
+ printf("Number of channels (8,4,2,1): "); |
+ fgets(str, sizeof(str), stdin); |
+ } else |
+ strlcpy(str, param[1], sizeof(str)); |
+ |
+ if (b->SetChannelConfig(0, 8, atoi(str))) |
+ printf("DRS4 configured for %d channels\n", atoi(str)); |
+ } |
+ } |
+ |
+ /* set trigger level ---------- */ |
+ else if (match(param[0], "tlevel")) { |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ if (param[1][0] == 0) { |
+ printf("Voltage: "); |
+ fgets(str, sizeof(str), stdin); |
+ } else |
+ strlcpy(str, param[1], sizeof(str)); |
+ |
+ b->SetTriggerLevel(atof(str)); |
+ printf("Trigger level set to %1.3lf Volt\n", atof(str)); |
+ } |
+ } |
+ |
+ /* trigger on/off ---------- */ |
+ else if (match(param[0], "trig")) { |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ b->EnableTrigger(atoi(param[1]), 0); |
+ if (atoi(param[1]) == 1) { |
+ puts("Hardware fast trigger is on"); |
+ } else if (atoi(param[1]) == 2) { |
+ puts("Hardware slow trigger is on"); |
+ } else { |
+ puts("Hardware trigger is off"); |
+ } |
+ } |
+ } |
+ |
+ /* timing calibration signal on/off ---------- */ |
+ else if (match(param[0], "tcs")) { |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ b->EnableTcal(atoi(param[1]), 0, 0); |
+ b->SelectClockSource(0); |
+ if (atoi(param[1])) |
+ puts("Timing calibration signal is on"); |
+ else |
+ puts("Timing calibration signal is off"); |
+ } |
+ } |
+ |
+ /* timing calibration signal on/off ---------- */ |
+ else if (match(param[0], "refclk")) { |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ b->SetRefclk(atoi(param[1])); |
+ // re-set frequency since LMK configuration needs to be changed |
+ b->SetFrequency(b->GetNominalFrequency(), true); |
+ if (atoi(param[1])) |
+ puts("Refclock set to external through P2"); |
+ else |
+ puts("Refclock set to internal (FPGA)"); |
+ } |
+ } |
+ |
+ /* domino mode 0/1 ---------- */ |
+ else if (match(param[0], "dmode")) { |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ if (atoi(param[1]) == 1) { |
+ b->SetDominoMode(1); |
+ puts("Domino mode switched to cyclic"); |
+ } else { |
+ b->SetDominoMode(0); |
+ puts("Domino mode switched to single shot"); |
+ } |
+ } |
+ } |
+ |
+ /* active mode 0/1 ---------- */ |
+ else if (match(param[0], "active")) { |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ if (atoi(param[1]) == 1) { |
+ b->SetDominoActive(1); |
+ puts("Domino wave active during readout"); |
+ } else { |
+ b->SetDominoMode(0); |
+ puts("Domino wave stopped during readout"); |
+ } |
+ } |
+ } |
+ |
+ /* delayed start on/off ---------- */ |
+ else if (match(param[0], "del")) { |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ if (b->GetDRSType() == 4) |
+ puts("Delayed start not possible for DRS4"); |
+ else { |
+ if (atoi(param[1]) == 1) { |
+ b->SetDelayedStart(1); |
+ puts("Delayed start is on"); |
+ } else { |
+ b->SetDelayedStart(0); |
+ puts("Delayed start is off"); |
+ } |
+ } |
+ } |
+ } |
+ |
+ /* transparent mode on/off ---------- */ |
+ else if (match(param[0], "trans")) { |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ if (b->GetDRSType() != 4) |
+ puts("Transparen mode only possible for DRS4"); |
+ else { |
+ if (atoi(param[1]) == 1) { |
+ b->SetTranspMode(1); |
+ puts("Transparent mode is on"); |
+ } else { |
+ b->SetTranspMode(0); |
+ puts("Transparent mode is off"); |
+ } |
+ } |
+ } |
+ } |
+ |
+ /* standby mode on/off ---------- */ |
+ else if (match(param[0], "standby")) { |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ if (b->GetDRSType() != 4) |
+ puts("Standby mode only possible for DRS4"); |
+ else { |
+ if (atoi(param[1]) == 1) { |
+ b->SetStandbyMode(1); |
+ puts("Standby mode is on"); |
+ } else { |
+ b->SetStandbyMode(0); |
+ puts("Standby mode is off"); |
+ } |
+ } |
+ } |
+ } |
+ |
+ /* offset ---------- */ |
+ else if (match(param[0], "offset")) { |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ b->SetVoltageOffset(atof(param[1]), atof(param[2])); |
+ } |
+ } |
+ |
+ /* phase ---------- */ |
+ else if (match(param[0], "phase")) { |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ b->SetADCClkPhase(atoi(param[1]), atoi(param[2]) > 0); |
+ } |
+ } |
+ |
+ /* directory ---------- */ |
+ else if (match(param[0], "dir")) { |
+ |
+#ifdef HAVE_VME |
+#ifdef CF_VIA_USB |
+ { |
+ if (param[2][0]) |
+ i = atoi(param[2]); |
+ else |
+ i = 1; |
+ printf("Physical drive %d:\n", i); |
+ |
+ if (ace_init(NULL, i, &ace) != ACE_SUCCESS) { |
+ printf("Cannot access ACE on physical drive %d\n", i); |
+ } else { |
+#else |
+ for (i=i_start ; i<i_end ; i++) { |
+ |
+ /* do only once per VME board */ |
+ if (i_end - i_start > 1 && (i % 2) == 1) |
+ continue; |
+ |
+ b = drs->GetBoard(i); |
+ |
+ printf("VME slot %2d: ", (b->GetSlotNumber() >> 1) + 2); |
+ |
+ if (ace_init(b->GetVMEInterface(), (b->GetSlotNumber() >> 1)+2, &ace) != ACE_SUCCESS) { |
+ printf("Cannot access ACE in slot %d\n", (b->GetSlotNumber() >> 1)+2); |
+ } else { |
+#endif |
+ ace_dir(&ace); |
+ } |
+ } |
+#else |
+ printf("No VME support compiled into drscl\n"); |
+#endif // HAVE_VME |
+ } |
+ |
+ /* upload ---------- */ |
+ else if (match(param[0], "upload")) { |
+ |
+#ifdef HAVE_VME |
+#ifdef CF_VIA_USB |
+ { |
+ if (param[2][0]) |
+ i = atoi(param[2]); |
+ else |
+ i = 1; |
+ printf("Physical drive %d:\n", i); |
+ |
+ if (ace_init(NULL, i, &ace) != ACE_SUCCESS) { |
+ printf("Cannot access ACE on physical drive %d\n", i); |
+ } else { |
+#else |
+ |
+ /* use SVN file as default */ |
+ if (param[1][0] == 0) { |
+#ifdef _MSC_VER |
+ if (b->GetDRSType() == 4) |
+ strcpy(str, "c:\\meg\\online\\VPC\\drs4\\2vp30\\cflash\\drs4\\rev0\\rev0.ace"); |
+ else if (b->GetDRSType() == 3) |
+ strcpy(str, "c:\\meg\\online\\VPC\\drs3\\2vp30\\cflash\\drs3\\rev0\\rev0.ace"); |
+ else |
+ strcpy(str, "c:\\meg\\online\\VPC\\drs2\\2vp30\\cflash\\drs2\\rev0\\rev0.ace"); |
+#else |
+ if (b->GetDRSType() == 4) |
+ strcpy(str, "/home/meg/meg/online/VPC/drs4/2vp30/cflash/drs4/rev0/rev0.ace"); |
+ else if (b->GetDRSType() == 3) |
+ strcpy(str, "/home/meg/meg/online/VPC/drs3/2vp30/cflash/drs3/rev0/rev0.ace"); |
+ else |
+ strcpy(str, "/home/meg/meg/online/VPC/drs2/2vp30/cflash/drs2/rev0/rev0.ace"); |
+#endif |
+ printf("Enter filename or hit return for \n%s\n", str); |
+ fgets(line, sizeof(line), stdin); |
+ if (line[0] == '\r' || line[0] == '\n') |
+ strcpy(file_name, str); |
+ else |
+ strcpy(file_name, line); |
+ strcpy(param[1], str); |
+ } else |
+ strcpy(file_name, param[1]); |
+ |
+ for (i=i_start ; i<i_end ; i++) { |
+ |
+ /* do only once per VME board */ |
+ if (i_end - i_start > 1 && (i % 2) == 1) |
+ continue; |
+ |
+ b = drs->GetBoard(i); |
+ |
+ if (b->GetTransport() == TR_USB) { |
+ printf("Cannot upload to USB board.\n"); |
+ } else { |
+ printf("VME slot %d:\n", (b->GetSlotNumber() >> 1)+2); |
+ if (ace_init(b->GetVMEInterface(), (b->GetSlotNumber() >> 1)+2, &ace) != ACE_SUCCESS) { |
+ printf("Cannot access ACE in slot %d\n", (b->GetSlotNumber() >> 1)+2); |
+ } else { |
+#endif |
+ status = ace_upload(&ace, file_name); |
+ } |
+ } |
+ } |
+ printf("\nPlease issue a power cycle to activate new firmware\n"); |
+#else |
+ printf("No VME support compiled into drscl\n"); |
+#endif // HAVE_VME |
+ } |
+ |
+ /* download ---------- */ |
+ else if (match(param[0], "download")) { |
+ |
+#ifdef HAVE_VME |
+ b = drs->GetBoard(i_start); |
+ |
+ if (b->GetTransport() == TR_USB) { |
+ printf("Cannot upload to USB board.\n"); |
+ } else { |
+ printf("VME slot %d:\n", (b->GetSlotNumber() >> 1)+2); |
+ if (ace_init(b->GetVMEInterface(), (b->GetSlotNumber() >> 1)+2, &ace) != ACE_SUCCESS) { |
+ printf("Cannot access ACE in slot %d\n", (b->GetSlotNumber() >> 1)+2); |
+ } else { |
+ strcpy(str, "rev0.ace"); |
+ if (param[1][0] == 0) { |
+ printf("Enter filename or hit return for \n%s\n", str); |
+ fgets(line, sizeof(line), stdin); |
+ if (line[0] == '\r' || line[0] == '\n') |
+ strcpy(file_name, str); |
+ else |
+ strcpy(file_name, line); |
+ strcpy(param[1], str); |
+ } else |
+ strcpy(file_name, param[1]); |
+ |
+ if (strchr(file_name, '\r')) |
+ *strchr(file_name, '\r') = 0; |
+ if (strchr(file_name, '\n')) |
+ *strchr(file_name, '\n') = 0; |
+ |
+ status = ace_download(&ace, file_name); |
+ } |
+ } |
+#else |
+ printf("No VME support compiled into drscl\n"); |
+#endif // HAVE_VME |
+ } |
+ |
+ /* calibration ---------- */ |
+ else if (match(param[0], "calib")) { |
+ debug = strcmp(param[1], "debug") == 0 || strcmp(param[2], "debug") == 0 || strcmp(param[3], "debug") == 0; |
+ if (param[1][0]) { |
+ strlcpy(dir, param[1], sizeof(str)); |
+ } else |
+ getcwd(dir, sizeof(dir)); |
+ |
+ while (dir[strlen(dir)-1] == '\n' || dir[strlen(dir)-1] == '\r') |
+ dir[strlen(dir)-1] = 0; |
+ |
+ b = drs->GetBoard(i_start); |
+ |
+ printf("\n Enter calibration frequency [GHz]: "); |
+ fgets(line, sizeof(line), stdin); |
+ freq = atof(line); |
+ |
+ if (b->GetDRSType() == 2) { |
+ printf(" Enter the expected trigger frequency [Hz]: "); |
+ fgets(line, sizeof(line), stdin); |
+ triggerfreq = atof(line); |
+ } else |
+ triggerfreq = 0; |
+ |
+ ext_refclk = 0; |
+ if (b->GetBoardType() == 6) { |
+ printf("Use [e]xternal or [i]nternal reference clock: "); |
+ fgets(line, sizeof(line), stdin); |
+ ext_refclk = line[0] == 'e'; |
+ } |
+ |
+ if (b->GetDRSType() == 4) { |
+ printf(" Enter range [V]: "); |
+ fgets(line, sizeof(line), stdin); |
+ range = atof(line); |
+ |
+ printf(" Enter mode [1]024 or [2]048 bin mode: "); |
+ fgets(line, sizeof(line), stdin); |
+ cascading = atoi(line); |
+ } else { |
+ range = 0; |
+ cascading = 0; |
+ } |
+ |
+ if (b->GetDRSType() == 4) { |
+ printf("\nPlease make sure that no input signal are present then hit any key\r"); |
+ fflush(stdout); |
+ while (!drs_kbhit()); |
+ printf(" \r"); |
+ while (drs_kbhit()) |
+ getchar(); |
+ } |
+ |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ if (b->GetTransport() == TR_VME) |
+ printf("Creating Calibration of Board in VME slot %2d %s, serial #%04d\n", |
+ (b->GetSlotNumber() >> 1)+2, ((b->GetSlotNumber() & 1) == 0) ? "upper" : "lower", |
+ b->GetBoardSerialNumber()); |
+ else |
+ printf("Creating Calibration of Board on USB, serial #%04d\n", |
+ b->GetBoardSerialNumber()); |
+ if (b->GetDRSType() == 4) { |
+ ProgressBar p; |
+ if (b->GetTransport() == TR_VME) { |
+ if (cascading == 2) |
+ b->SetChannelConfig(7, 8, 4); // 7 means read all 9 channels per chip |
+ else |
+ b->SetChannelConfig(7, 8, 8); |
+ } else { |
+ if (cascading == 2) |
+ b->SetChannelConfig(0, 8, 4); |
+ else |
+ b->SetChannelConfig(0, 8, 8); |
+ } |
+ |
+ b->SetRefclk(ext_refclk); |
+ b->SetFrequency(freq, true); |
+ b->SetInputRange(range); |
+ b->CalibrateVolt(&p); |
+ } else { |
+ b->SetDebug(debug); |
+ b->Init(); |
+ b->SetFrequency(freq, true); |
+ b->SoftTrigger(); |
+ |
+ if (b->GetDRSType() == 3) |
+ b->GetResponseCalibration()->SetCalibrationParameters(1,11,0,20,0,0,0,0,0); |
+ else |
+ b->GetResponseCalibration()->SetCalibrationParameters(1,36,110,20,19,40,15,triggerfreq,0); |
+ if (!strcmp(dir,"lab")) |
+ b->SetCalibrationDirectory("C:/experiment/calibrations"); |
+ else if (!strcmp(dir,"area")) |
+ b->SetCalibrationDirectory("/home/meg/meg/online/calibrations"); |
+ else |
+ b->SetCalibrationDirectory(dir); |
+ for (j=0;j<2;j++) { |
+ b->GetResponseCalibration()->ResetCalibration(); |
+ while (!b->GetResponseCalibration()->RecordCalibrationPoints(j)) {} |
+ while (!b->GetResponseCalibration()->FitCalibrationPoints(j)) {} |
+ while (!b->GetResponseCalibration()->OffsetCalibration(j)) {} |
+ if (!b->GetResponseCalibration()->WriteCalibration(j)) |
+ break; |
+ } |
+ } |
+ } |
+ } |
+ |
+ /* timing calibration ---------- */ |
+ else if (match(param[0], "tcalib")) { |
+ |
+ freq = 0; |
+ if (param[1][0]) |
+ freq = atof(param[1]); |
+ |
+ if (freq == 0) { |
+ printf("Enter calibration frequency [GHz]: "); |
+ fgets(line, sizeof(line), stdin); |
+ freq = atof(line); |
+ } |
+ |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ if (b->GetDRSType() < 4) |
+ printf("Timing calibration not possivle for DRS2 or DRS3\n"); |
+ else if (b->GetFirmwareVersion() < 13279) |
+ printf("Firmware revision 13279 or later required for timing calibration\n"); |
+ else if (b->GetDRSType() == 4) { |
+ printf("Creating Timing Calibration of Board #%d\n", b->GetBoardSerialNumber()); |
+ ProgressBar p; |
+ b->SetFrequency(freq, true); |
+ status = b->CalibrateTiming(&p); |
+ if (!status) |
+ printf("Error performing timing calibration, please check waveforms\n"); |
+ printf("\n"); |
+ } |
+ } |
+ } |
+ |
+ /* tcout ---------- */ |
+ else if (match(param[0], "tcout")) { |
+ float time[1024]; |
+ int chip; |
+ int k; |
+ int idx = 0; |
+ int first_board = i_start; |
+ int last_board = i_end; |
+ |
+ file_name[0] = 0; |
+ strcpy(file_name, param[1]); |
+ if (file_name[0]) { |
+ f = fopen(file_name, "wt"); |
+ if (f == NULL) { |
+ printf("Cannot open file \"%s\"\n", file_name); |
+ } else { |
+ first_board = 0; |
+ last_board = drs->GetNumberOfBoards(); |
+ } |
+ idx += atoi(param[2]); |
+ } else |
+ f = NULL; |
+ |
+ if (f) { |
+ fprintf(f, "-- Replace %%%% with correct id\n"); |
+ } |
+ for (i=first_board ; i<last_board ; i++) { |
+ b = drs->GetBoard(i); |
+ if (b->GetDRSType() >= 4) { |
+ for (chip = 0; chip < b->GetNumberOfChips(); chip++) { |
+ b->GetTime(chip, 0, b->GetTriggerCell(0), time, true, false); |
+ if (f) { |
+ fprintf(f, "INSERT INTO MEGDRSTimeCalibration VALUES(%%%%,%d,%d", idx, |
+ static_cast<int>(b->GetNominalFrequency() * 10 + 0.5) * 100); |
+ for (j=0 ; j<1024 ; j++) |
+ fprintf(f, ",%g", time[j] * 1e-9); |
+ fprintf(f, ",%d,%d", b->GetBoardSerialNumber(), chip); |
+ fprintf(f, ",%g);\n", 1 / (b->GetNominalFrequency() * 1e9) * 1024); |
+ idx++; |
+ } else { |
+ printf("Board %d\n", b->GetBoardSerialNumber()); |
+ for (j=0 ; j<128 ; j++) { |
+ printf("%4d: ", j*8); |
+ for (k=0 ; k<7 ; k++) |
+ printf("%6.1lf ", time[j*8+k]); |
+ printf("%6.1lf\n", time[j*8+k]); |
+ } |
+ printf("n"); |
+ } |
+ } |
+ } else { |
+ // DRS2 or DRS3 |
+ idx += 2; |
+ } |
+ } |
+ if (f) { |
+ fclose(f); |
+ printf("Data successfully written to \"%s\"\n", file_name); |
+ } |
+ } |
+ |
+ /* read */ |
+ else if (match(param[0], "read")) { |
+ float waveform[2048]; |
+ short swaveform[2048]; |
+ calib = 0; |
+ |
+ file_name[0] = 0; |
+ if (param[1][0]) { |
+ idx = atoi(param[1]); |
+ calib = atoi(param[2]); |
+ if (strlen(param[2]) > 2) |
+ strcpy(file_name, param[2]); |
+ else |
+ strcpy(file_name, param[3]); |
+ } else { |
+ printf("Enter channel number (0..19): "); |
+ fgets(line, sizeof(line), stdin); |
+ idx = atoi(line); |
+ } |
+ |
+ if (idx<0 || idx>19) |
+ printf("Channel number must be between 0 and 19\n"); |
+ else { |
+ b = drs->GetBoard(i_start); |
+ if (!b->IsEventAvailable()) |
+ printf("Error: Domino wave is running, please issue a \"stop\" first\n"); |
+ else { |
+ if (calib == 1) { |
+ if (b->GetDRSType() == 4) { |
+ if (!b->IsVoltageCalibrationValid()) { |
+ printf("Calibration not valid for board #%d\n", b->GetBoardSerialNumber()); |
+ calib = 0; |
+ } |
+ |
+ } else { |
+#ifdef _MSC_VER |
+ b->SetCalibrationDirectory("C:/experiment/calibrations"); |
+#else |
+ b->SetCalibrationDirectory("/home/meg/meg/online/calibrations"); |
+#endif |
+ if (!b->GetResponseCalibration()->IsRead(0)) |
+ if (!b->GetResponseCalibration()->ReadCalibration(0)) |
+ calib = 0; |
+ if (!b->GetResponseCalibration()->IsRead(1)) |
+ if (!b->GetResponseCalibration()->ReadCalibration(1)) |
+ calib = 0; |
+ } |
+ } |
+ |
+ status = b->TransferWaves(idx, idx); |
+ if (file_name[0]) { |
+ f = fopen(file_name, "wt"); |
+ if (f == NULL) |
+ printf("Cannot open file \"%s\"\n", file_name); |
+ } else |
+ f = NULL; |
+ |
+ if (calib) { |
+ status = b->GetWave(idx/b->GetNumberOfChannels(), idx%b->GetNumberOfChannels(), waveform, |
+ true, b->GetTriggerCell(idx/b->GetNumberOfChannels()), b->GetStopWSR(idx/b->GetNumberOfChannels())); |
+ if (status == 0) { |
+ if (f) |
+ for (i=0 ; i<b->GetChannelDepth() ; i++) |
+ fprintf(f, "%6.1lf\n", waveform[i]); |
+ else { |
+ for (i=0 ; i<b->GetChannelDepth()/8 ; i++) { |
+ printf("%4d: ", i*8); |
+ for (j=0 ; j<7 ; j++) |
+ printf("%6.1lf ", waveform[i*8+j]); |
+ printf("%6.1lf\n", waveform[i*8+j]); |
+ } |
+ } |
+ } |
+ } else { |
+ status = b->GetWave(idx/b->GetNumberOfChannels(), idx%b->GetNumberOfChannels(), swaveform, 0, 0); |
+ if (status == 0) { |
+ if (f) |
+ for (i=0 ; i<b->GetChannelDepth() ; i++) |
+ fprintf(f, "%4d\n", swaveform[i]); |
+ else { |
+ for (i=0 ; i<b->GetChannelDepth()/16 ; i++) { |
+ for (j=0 ; j<15 ; j++) |
+ printf("%4d ", swaveform[i*16+j] >> 4); |
+ printf("%4d\n", swaveform[i*16+j] >> 4); |
+ } |
+ } |
+ } |
+ } |
+ } |
+ } |
+ |
+ if (f) { |
+ fclose(f); |
+ printf("Data successfully written to \"%s\"\n", file_name); |
+ } |
+ } |
+ |
+ /* register test ---------- */ |
+ else if (match(param[0], "reg")) { |
+ b->RegisterTest(); |
+ } |
+ |
+ /* RAM test */ |
+ else if (match(param[0], "ram")) { |
+ if (param[1][0] == 0) |
+ b->RAMTest(3); |
+ else |
+ b->RAMTest(atoi(param[1])); |
+ } |
+ |
+ /* Change input range */ |
+ else if (match(param[0], "range")) { |
+ for (i=i_start ; i<i_end ; i++) { |
+ b = drs->GetBoard(i); |
+ if (param[1][0] == 0) { |
+ printf("Input range: "); |
+ fgets(str, sizeof(str), stdin); |
+ } else |
+ strlcpy(str, param[1], sizeof(str)); |
+ |
+ b->SetInputRange(atof(str)); |
+ printf("Range set to %1.2lg V ... %1.2lg V\n", atof(str)-0.5, atof(str)+0.5); |
+ } |
+ } |
+ |
+ /* Chip Test */ |
+ else if (match(param[0], "ct")) { |
+ if (drs->GetNumberOfBoards() == 0) |
+ puts("No DRS board found"); |
+ else { |
+ puts("Press 'q' to quit, any other key to repeat test.\n"); |
+ do { |
+ if (b->ChipTest()) |
+ puts("Chip test successfully finished"); |
+ else |
+ puts("\007Chip Error!"); |
+ |
+ b->SetStandbyMode(1); |
+ for (i=0 ; i<8 ; i++) |
+ b->SetDAC(i, 0); |
+ i = getch(); |
+ b->SetStandbyMode(0); |
+ } while (i != 'q'); |
+ } |
+ } |
+ |
+ /* calib0 for speed vs. temperature calibration */ |
+ else if (match(param[0], "c0")) { |
+ |
+ double volt, freq; |
+ |
+ b->Init(); |
+ b->SetFrequency(5, true); |
+ b->EnableAcal(0, 0); |
+ b->SetDominoMode(1); |
+ |
+ for (volt=2.5 ; volt > 0 ; volt -= 0.05) { |
+ printf("%4.1lf - %5.3lf ", b->GetTemperature(), volt); |
+ b->SetDAC(1, volt); |
+ b->SetDAC(2, volt); |
+ Sleep(100); |
+ b->ReadFrequency(0, &freq); |
+ |
+ printf("%5.3lf\n", freq); |
+ |
+ if (drs_kbhit()) |
+ break; |
+ } |
+ |
+ while (drs_kbhit()) |
+ getch(); |
+ |
+ b->Init(); // reset voltage offset |
+ } |
+ |
+ /* calib1 */ |
+ else if (match(param[0], "c1")) { |
+ |
+ short swaveform[1024]; |
+ double volt; |
+ double av[1024]; |
+ int k; |
+ |
+ b->Init(); |
+ b->SetFrequency(5, true); |
+ b->SetDominoMode(1); |
+ b->SetDominoActive(1); |
+ b->SetReadoutMode(1); |
+ |
+ for (volt=-0.5 ; volt <= 0.5001 ; volt += 0.02) { |
+ printf("%4.1lf - %6.0lf ", b->GetTemperature(), 1000*volt); |
+ b->EnableAcal(1, volt); |
+ b->StartDomino(); |
+ Sleep(100); |
+ |
+ memset(av, 0, sizeof(av)); |
+ |
+ for (j=0 ; j<100 ; j++) { |
+ for (i=0 ; i<10 ; i++) |
+ b->IsBusy(); |
+ b->SoftTrigger(); |
+ while (b->IsBusy()); |
+ b->StartDomino(); |
+ b->TransferWaves(b->GetNumberOfChannels()*b->GetNumberOfChips()); |
+ i = b->GetTriggerCell(0); |
+ b->GetWave(0, 0, swaveform, false, i, 1); |
+ |
+ for (k=0 ; k<1024 ; k++) |
+ av[k] += swaveform[k]; |
+ |
+ if (drs_kbhit()) |
+ break; |
+ } |
+ |
+ for (k=0 ; k<1024 ; k++) |
+ av[k] /= j; |
+ |
+ for (k=0 ; k<5 ; k++) |
+ printf("%10.2lf ", 1000*(av[k]/65536-0.5)); |
+ printf("\n"); |
+ |
+ if (drs_kbhit()) |
+ break; |
+ } |
+ // keep chip "warm" |
+ b->StartDomino(); |
+ } |
+ |
+ /* test0 */ |
+ else if (match(param[0], "t0")) { |
+ b->Init(); |
+ b->SetDominoMode(1); |
+ b->SetDominoActive(1); |
+ b->SetReadoutMode(1); |
+ b->SetFrequency(0.8, true); |
+ b->EnableTrigger(1, 0); |
+ b->SetTriggerLevel(1); |
+ b->SetChannelConfig(0, 8, 4); |
+ |
+ do { |
+ b->StartDomino(); |
+ while (b->IsBusy()) |
+ if (drs_kbhit()) |
+ break; |
+ |
+ b->TransferWaves(); |
+ |
+ if (b->GetBoardType() == 5) { |
+ printf("%04d(0x%03X) - %3d\n", b->GetTriggerCell(0), b->GetTriggerCell(0), |
+ b->GetStopWSR(0)); |
+ } else { |
+ printf("%04d %04d %04d %04d - %3d %3d %3d\n", |
+ b->GetTriggerCell(0), |
+ b->GetTriggerCell(1), |
+ b->GetTriggerCell(2), |
+ b->GetTriggerCell(3), |
+ b->GetTriggerCell(1)-b->GetTriggerCell(0), |
+ b->GetTriggerCell(2)-b->GetTriggerCell(0), |
+ b->GetTriggerCell(3)-b->GetTriggerCell(0)); |
+ } |
+ Sleep(300); |
+ } while (!drs_kbhit()); |
+ |
+ while (drs_kbhit()) |
+ getch(); |
+ } |
+ |
+ /* test1 simple start/stop loop */ |
+ else if (match(param[0], "t1")) { |
+ time_t t1, t2; |
+ |
+ b->SetDebug(1); |
+ b->Init(); |
+ b->SetFrequency(5, true); |
+ b->SetDominoMode(1); |
+ b->SetReadoutMode(0); |
+ b->SetTranspMode(0); |
+ b->SetDominoActive(1); |
+ b->EnableAcal(1, 0.5); |
+ b->EnableTcal(1); |
+ time(&t1); |
+ do { |
+ time(&t2); |
+ } while (t1 == t2); |
+ i=0; |
+ t1 = t2; |
+ do { |
+ b->StartDomino(); |
+ b->SoftTrigger(); |
+ b->TransferWaves(); |
+ i++; |
+ time(&t2); |
+ if (t2 > t1) { |
+ printf("%d events/sec\n", i); |
+ i = 0; |
+ t1 = t2; |
+ } |
+ } while (!drs_kbhit()); |
+ |
+ while (drs_kbhit()) |
+ getch(); |
+ } |
+ |
+ /* test2 readout from stop position */ |
+ else if (match(param[0], "t2")) { |
+ short sw[1024]; |
+ double volt = 0.5; |
+ |
+ b->Init(); |
+ b->SetNumberOfChannels(10); |
+ b->SetChannelConfig(0, 9, 12); |
+ b->SetFrequency(2, true); |
+ b->EnableTcal(1); |
+ b->SetReadoutMode(0); |
+ b->SetDominoActive(0); |
+ b->SetDominoMode(1); |
+ b->SetCalibTiming(0, 0); |
+ b->StartDomino(); |
+ b->EnableAcal(1, 0.5); |
+ if (!b->GetResponseCalibration()->IsRead(0)) |
+ if (!b->GetResponseCalibration()->ReadCalibration(0)) |
+ printf("cannot read calibration\n"); |
+ |
+ do { |
+ //volt += 0.25; |
+ if (volt > 1) |
+ volt = 0; |
+ b->SoftTrigger(); |
+ while (b->IsBusy()); |
+ b->StartDomino(); |
+ b->EnableAcal(1, volt); |
+ b->TransferWaves(); |
+ |
+ b->GetWave(0, 1, sw, 0, 0); |
+ printf("%d ", sw[100]); |
+ b->GetWave(0, 1, sw, 1, 0); |
+ printf("%1.4lf\n", sw[100]/4096.0); |
+ } while (!drs_kbhit()); |
+ while (drs_kbhit()) getch(); |
+ } |
+ |
+ /* DAC Loop */ |
+ else if (match(param[0], "t3")) { |
+ double volt; |
+ do { |
+ for (volt=2.5 ; volt > 0 ; volt -= 0.05) { |
+ |
+ printf("%4.1lf - %5.3lf\n", b->GetTemperature(), volt); |
+ b->SetDAC(0, volt); |
+ b->SetDAC(1, 2.5-volt); |
+ Sleep(100); |
+ if (drs_kbhit()) |
+ break; |
+ } |
+ } while (!drs_kbhit()); |
+ |
+ while (drs_kbhit()) |
+ getch(); |
+ } |
+ |
+ /* noise measurement */ |
+ else if (match(param[0], "t4")) { |
+ int i, n; |
+ short sw[1024]; |
+ double ofs[1024], sx, sxx, avg, stdev, enob; |
+ |
+ b->Init(); |
+ b->SetFrequency(2, true); |
+ b->EnableTcal(0); |
+ b->SetDominoMode(1); |
+ b->StartDomino(); |
+ b->EnableAcal(1, 0.5); |
+ Sleep(100); |
+ b->SoftTrigger(); |
+ while (b->IsBusy()); |
+ b->StartDomino(); |
+ Sleep(100); |
+ memset(ofs, 0, sizeof(ofs)); |
+ |
+ for (i=0 ; i<10 ; i++) { |
+ b->SoftTrigger(); |
+ while (b->IsBusy()); |
+ b->StartDomino(); |
+ b->TransferWaves(1); |
+ b->GetWave(0, 0, sw, 0, 0); |
+ sx = sxx = 0; |
+ for (n=0 ; n<1024 ; n++) { |
+ ofs[n] += sw[n]; |
+ } |
+ } |
+ |
+ for (n=0 ; n<1024 ; n++) |
+ ofs[n] /= i; |
+ |
+ for (i=0 ; i<10 ; i++) { |
+ b->SoftTrigger(); |
+ while (b->IsBusy()); |
+ b->StartDomino(); |
+ b->TransferWaves(1); |
+ b->GetWave(0, 0, sw, 0, 0); |
+ |
+ sx = sxx = 0; |
+ for (n=10 ; n<1014 ; n++) { |
+ sx += (sw[n]-ofs[n])/4096.0; |
+ sxx += (sw[n]-ofs[n])/4096.0*(sw[n]-ofs[n])/4096.0; |
+ } |
+ |
+ if (i>5) |
+ Sleep(5000); |
+ |
+ avg = sx / n; |
+ stdev = sqrt((sxx-sx*sx/n)/(n-1)); |
+ enob = log(1/stdev)/log(2.); |
+ printf("avg=%1.4lf sd=%1.4lf ENOB=%1.1lf\n", avg, stdev, enob); |
+ }; |
+ } |
+ |
+ /* exit/quit ---------- */ |
+ else if (match(param[0], "exit") || match(param[0], "quit")) |
+ break; |
+ |
+ else { |
+ if (strchr(param[0], '\r')) |
+ *strchr(param[0], '\r') = 0; |
+ if (strchr(param[0], '\n')) |
+ *strchr(param[0], '\n') = 0; |
+ printf("Unknon command \"%s\"\n", param[0]); |
+ } |
+ |
+ } while (1); |
+ |
+ delete drs; |
+} |
+ |
+/*------------------------------------------------------------------*/ |
+ |
+int main() |
+{ |
+ printf("DRS command line tool, Revision %d\n", atoi(drscl_svn_revision+15)); |
+ printf("Type 'help' for a list of available commands.\n\n"); |
+ |
+ cmd_loop(); |
+ return 1; |
+} |
Index: instr/drs/drsread.c |
=================================================================== |
--- instr/drs/drsread.c (nonexistent) |
+++ instr/drs/drsread.c (revision 197) |
@@ -0,0 +1,283 @@ |
+#include <windows.h> |
+#include <drsread.h> |
+ |
+/* The two macros below are used as error return codes */ |
+/* in case the DLL does not load, or is missing one or */ |
+/* more functions, respectively. You must define them */ |
+/* to whatever values are meaningful for your DLL. */ |
+#define kFailedToLoadDLLError ??? |
+#define kCouldNotFindFunction ??? |
+ |
+static HINSTANCE DLLHandle; |
+ |
+/* Declare the variables that hold the addresses of the function */ |
+/* pointers. */ |
+static void (__cdecl *DRSSetMask_Ptr)(int mask); |
+static void (__cdecl *DRSSetTriggerType_Ptr)(int type); |
+static void (__cdecl *DRSSetFrequency_Ptr)(int freq); |
+static void (__cdecl *DRSSetRange_Ptr)(double range); |
+static void (__cdecl *DRSSetTriggerChannel_Ptr)(int channel); |
+static void (__cdecl *DRSSetTriggerDelay_Ptr)(double delay); |
+static void (__cdecl *DRSSetTriggerLevel_Ptr)(double level); |
+static void (__cdecl *DRSSetTriggerPolarity_Ptr)(int polarity); |
+static float *(__cdecl *DRSGetTime_Ptr)(int ch); |
+static float *(__cdecl *DRSGetWave_Ptr)(int ch); |
+static int (__cdecl *DRSInit_Ptr)(); |
+static int (__cdecl *DRSRead_Ptr)(int drstimer); |
+static int (__cdecl *DRSEnd_Ptr)(); |
+static int (__cdecl *DRSToBuffer_Ptr)(unsigned char *p, int m_evSerial); |
+static int (__cdecl *DRSIsTimeout_Ptr)(); |
+static void (__cdecl *DRSSetTimeout_Ptr)(); |
+static void (__cdecl *DRSSigInt_Ptr)(int k); |
+ |
+ |
+/* Load the DLL and get the addresses of the functions */ |
+static int LoadDLLIfNeeded(void) |
+{ |
+ if (DLLHandle) |
+ return 0; |
+ |
+ DLLHandle = LoadLibrary("drsread.dll"); |
+ if (DLLHandle == NULL) { |
+ return kFailedToLoadDLLError; |
+ } |
+ |
+ if (!(DRSSetMask_Ptr = (void*) GetProcAddress(DLLHandle, "DRSSetMask"))) |
+ goto FunctionNotFoundError; |
+ |
+ if (!(DRSSetTriggerType_Ptr = (void*) GetProcAddress(DLLHandle, |
+ "DRSSetTriggerType"))) |
+ goto FunctionNotFoundError; |
+ |
+ if (!(DRSSetFrequency_Ptr = (void*) GetProcAddress(DLLHandle, |
+ "DRSSetFrequency"))) |
+ goto FunctionNotFoundError; |
+ |
+ if (!(DRSSetRange_Ptr = (void*) GetProcAddress(DLLHandle, "DRSSetRange"))) |
+ goto FunctionNotFoundError; |
+ |
+ if (!(DRSSetTriggerChannel_Ptr = (void*) GetProcAddress(DLLHandle, |
+ "DRSSetTriggerChannel"))) |
+ goto FunctionNotFoundError; |
+ |
+ if (!(DRSSetTriggerDelay_Ptr = (void*) GetProcAddress(DLLHandle, |
+ "DRSSetTriggerDelay"))) |
+ goto FunctionNotFoundError; |
+ |
+ if (!(DRSSetTriggerLevel_Ptr = (void*) GetProcAddress(DLLHandle, |
+ "DRSSetTriggerLevel"))) |
+ goto FunctionNotFoundError; |
+ |
+ if (!(DRSSetTriggerPolarity_Ptr = (void*) GetProcAddress(DLLHandle, |
+ "DRSSetTriggerPolarity"))) |
+ goto FunctionNotFoundError; |
+ |
+ if (!(DRSGetTime_Ptr = (void*) GetProcAddress(DLLHandle, "DRSGetTime"))) |
+ goto FunctionNotFoundError; |
+ |
+ if (!(DRSGetWave_Ptr = (void*) GetProcAddress(DLLHandle, "DRSGetWave"))) |
+ goto FunctionNotFoundError; |
+ |
+ if (!(DRSInit_Ptr = (void*) GetProcAddress(DLLHandle, "DRSInit"))) |
+ goto FunctionNotFoundError; |
+ |
+ if (!(DRSRead_Ptr = (void*) GetProcAddress(DLLHandle, "DRSRead"))) |
+ goto FunctionNotFoundError; |
+ |
+ if (!(DRSEnd_Ptr = (void*) GetProcAddress(DLLHandle, "DRSEnd"))) |
+ goto FunctionNotFoundError; |
+ |
+ if (!(DRSToBuffer_Ptr = (void*) GetProcAddress(DLLHandle, "DRSToBuffer"))) |
+ goto FunctionNotFoundError; |
+ |
+ if (!(DRSIsTimeout_Ptr = (void*) GetProcAddress(DLLHandle, "DRSIsTimeout"))) |
+ goto FunctionNotFoundError; |
+ |
+ if (!(DRSSetTimeout_Ptr = (void*) GetProcAddress(DLLHandle, "DRSSetTimeout"))) |
+ goto FunctionNotFoundError; |
+ |
+ if (!(DRSSigInt_Ptr = (void*) GetProcAddress(DLLHandle, "DRSSigInt"))) |
+ goto FunctionNotFoundError; |
+ |
+ return 0; |
+ |
+FunctionNotFoundError: |
+ FreeLibrary(DLLHandle); |
+ DLLHandle = 0; |
+ return kCouldNotFindFunction; |
+} |
+ |
+ |
+/* Glue Code for each of the DLL functions */ |
+ |
+ |
+ |
+void DRSSetMask(int mask) |
+{ |
+ int dllLoadError; |
+ |
+ if (dllLoadError = LoadDLLIfNeeded()) |
+ return; |
+ (*DRSSetMask_Ptr)(mask); |
+} |
+ |
+ |
+void DRSSetTriggerType(int type) |
+{ |
+ int dllLoadError; |
+ |
+ if (dllLoadError = LoadDLLIfNeeded()) |
+ return; |
+ (*DRSSetTriggerType_Ptr)(type); |
+} |
+ |
+ |
+void DRSSetFrequency(int freq) |
+{ |
+ int dllLoadError; |
+ |
+ if (dllLoadError = LoadDLLIfNeeded()) |
+ return; |
+ (*DRSSetFrequency_Ptr)(freq); |
+} |
+ |
+ |
+void DRSSetRange(double range) |
+{ |
+ int dllLoadError; |
+ |
+ if (dllLoadError = LoadDLLIfNeeded()) |
+ return; |
+ (*DRSSetRange_Ptr)(range); |
+} |
+ |
+ |
+void DRSSetTriggerChannel(int channel) |
+{ |
+ int dllLoadError; |
+ |
+ if (dllLoadError = LoadDLLIfNeeded()) |
+ return; |
+ (*DRSSetTriggerChannel_Ptr)(channel); |
+} |
+ |
+ |
+void DRSSetTriggerDelay(double delay) |
+{ |
+ int dllLoadError; |
+ |
+ if (dllLoadError = LoadDLLIfNeeded()) |
+ return; |
+ (*DRSSetTriggerDelay_Ptr)(delay); |
+} |
+ |
+ |
+void DRSSetTriggerLevel(double level) |
+{ |
+ int dllLoadError; |
+ |
+ if (dllLoadError = LoadDLLIfNeeded()) |
+ return; |
+ (*DRSSetTriggerLevel_Ptr)(level); |
+} |
+ |
+ |
+void DRSSetTriggerPolarity(int polarity) |
+{ |
+ int dllLoadError; |
+ |
+ if (dllLoadError = LoadDLLIfNeeded()) |
+ return; |
+ (*DRSSetTriggerPolarity_Ptr)(polarity); |
+} |
+ |
+ |
+float *DRSGetTime(int ch) |
+{ |
+ int dllLoadError; |
+ |
+ if (dllLoadError = LoadDLLIfNeeded()) |
+ return ???; |
+ return (*DRSGetTime_Ptr)(ch); |
+} |
+ |
+ |
+float *DRSGetWave(int ch) |
+{ |
+ int dllLoadError; |
+ |
+ if (dllLoadError = LoadDLLIfNeeded()) |
+ return ???; |
+ return (*DRSGetWave_Ptr)(ch); |
+} |
+ |
+ |
+int DRSInit() |
+{ |
+ int dllLoadError; |
+ |
+ if (dllLoadError = LoadDLLIfNeeded()) |
+ return dllLoadError; |
+ return (*DRSInit_Ptr)(); |
+} |
+ |
+ |
+int DRSRead(int drstimer) |
+{ |
+ int dllLoadError; |
+ |
+ if (dllLoadError = LoadDLLIfNeeded()) |
+ return dllLoadError; |
+ return (*DRSRead_Ptr)(drstimer); |
+} |
+ |
+ |
+int DRSEnd() |
+{ |
+ int dllLoadError; |
+ |
+ if (dllLoadError = LoadDLLIfNeeded()) |
+ return dllLoadError; |
+ return (*DRSEnd_Ptr)(); |
+} |
+ |
+ |
+int DRSToBuffer(unsigned char *p, int m_evSerial) |
+{ |
+ int dllLoadError; |
+ |
+ if (dllLoadError = LoadDLLIfNeeded()) |
+ return dllLoadError; |
+ return (*DRSToBuffer_Ptr)(p, m_evSerial); |
+} |
+ |
+ |
+int DRSIsTimeout() |
+{ |
+ int dllLoadError; |
+ |
+ if (dllLoadError = LoadDLLIfNeeded()) |
+ return dllLoadError; |
+ return (*DRSIsTimeout_Ptr)(); |
+} |
+ |
+ |
+void DRSSetTimeout() |
+{ |
+ int dllLoadError; |
+ |
+ if (dllLoadError = LoadDLLIfNeeded()) |
+ return; |
+ (*DRSSetTimeout_Ptr)(); |
+} |
+ |
+ |
+void DRSSigInt(int k) |
+{ |
+ int dllLoadError; |
+ |
+ if (dllLoadError = LoadDLLIfNeeded()) |
+ return; |
+ (*DRSSigInt_Ptr)(k); |
+} |
+ |
Index: instr/drs/drsread.cpp |
=================================================================== |
--- instr/drs/drsread.cpp (nonexistent) |
+++ instr/drs/drsread.cpp (revision 197) |
@@ -0,0 +1,620 @@ |
+/********************************************************************\ |
+ |
+ Name: drsread.cpp |
+ Created by: Rok Pestotnik |
+ |
+ Contents: Simple example application to read out a DRS4 |
+ evaluation board and save into the data file |
+ Interface dll for LabWindows CVI |
+ |
+\********************************************************************/ |
+#ifdef DLLMAIN |
+#define DLLEXPORT __declspec(dllexport) |
+#else |
+#define DLLEXPORT |
+#endif |
+ |
+ |
+#include <stdio.h> |
+#include <string.h> |
+#include <stdlib.h> |
+ |
+#include <math.h> |
+#include <time.h> |
+#include <signal.h> |
+ |
+#include <TFile.h> |
+#include <TH2F.h> |
+#include <TCanvas.h> |
+//#include <TApplication.h> |
+ |
+#ifdef _MSC_VER |
+ |
+#include "gettimeofday.h" |
+#include "timer.h" |
+ |
+#define DIR_SEPARATOR '\\' |
+ |
+#elif defined(OS_LINUX) || defined(OS_DARWIN) |
+ |
+#define O_BINARY 0 |
+#include <unistd.h> |
+#include <ctype.h> |
+#include <sys/ioctl.h> |
+#include <errno.h> |
+#define DIR_SEPARATOR '/' |
+#endif |
+ |
+#include "DRS.h" |
+#include "drsread.h" |
+ |
+ |
+/*------------------------------------------------------------------*/ |
+class drssettings { |
+ static drssettings *s_instance; |
+public: |
+ drssettings(){ |
+ mask = 0xF; |
+ range = 0; |
+ trigger_type = 1; |
+ sampling_frequency = 5; |
+ trigger_delay = 0; |
+ trigger_channel=0; |
+ trigger_polarity=false; |
+ trigger_level=0.05; |
+ |
+ }; |
+ ~drssettings(){}; |
+ static drssettings *instance() |
+ { |
+ if (!s_instance) |
+ s_instance = new drssettings; |
+ return s_instance; |
+ }; |
+ |
+ |
+ unsigned char mask; |
+ double range; |
+ int trigger_type; // 0 software, 1 fast hardware, 2 slow hardware |
+ int trigger_channel; |
+ int sampling_frequency; |
+ double trigger_delay; |
+ double trigger_level; |
+ bool trigger_polarity; |
+}; |
+drssettings *drssettings::s_instance = 0; |
+drssettings *DRSParameters; |
+DLLEXPORT void DRSSetMask(int mask){ drssettings::instance()->mask;}; |
+DLLEXPORT void DRSSetTriggerType(int type){ drssettings::instance()->trigger_type = type;}; |
+DLLEXPORT void DRSSetFrequency(int freq){ drssettings::instance()->sampling_frequency = freq;}; |
+DLLEXPORT void DRSSetRange(double range){ drssettings::instance()->range = range;}; |
+DLLEXPORT void DRSSetTriggerChannel(int channel){ drssettings::instance()->trigger_channel = channel;}; |
+DLLEXPORT void DRSSetTriggerDelay(double delay){ drssettings::instance()->trigger_delay = delay;}; |
+DLLEXPORT void DRSSetTriggerLevel(double level){ drssettings::instance()->trigger_level = level;}; |
+DLLEXPORT void DRSSetTriggerPolarity(int polarity){ drssettings::instance()->trigger_polarity = (polarity==1);}; |
+ |
+ |
+static int DRSTimeout; |
+ |
+DLLEXPORT int DRSIsTimeout() |
+{ |
+ return DRSTimeout; |
+} |
+ |
+DLLEXPORT void DRSSetTimeout ( void ) |
+{ |
+ DRSTimeout=1; |
+ printf("->>> Timer Out !!!\n"); |
+} |
+ |
+static DRS *drs=NULL; |
+ |
+DLLEXPORT int DRSInit() |
+{ |
+ |
+ DRSBoard *b; |
+ /* do drsinitial scan */ |
+ drs = new DRS(); |
+ if (!drs) return -1; |
+ DRSParameters = drssettings::instance(); |
+ |
+ /* show any found board(s) */ |
+ for (int i=0 ; i<drs->GetNumberOfBoards() ; i++) { |
+ b = drs->GetBoard(i); |
+ printf("Found DRS4 evaluation board, serial #%d, firmware revision %d\n", |
+ b->GetBoardSerialNumber(), b->GetFirmwareVersion()); |
+ } |
+ |
+ /* exit if no board found */ |
+ int nBoards = drs->GetNumberOfBoards(); |
+ if (nBoards == 0) { |
+ printf("No DRS4 evaluation board found\n"); |
+ return -2; |
+ } |
+ |
+ /* continue working with first board only */ |
+ b = drs->GetBoard(0); |
+ |
+ /* drsinitialize board */ |
+ b->Init(); |
+ |
+ /* set sampling frequency default 5 */ |
+ b->SetFrequency(DRSParameters->sampling_frequency, true); |
+ |
+ /* enable transparent mode needed for analog trigger */ |
+ b->SetTranspMode(1); |
+ |
+ /* set input range to -0.5V ... +0.5V -> range=0 */ |
+ b->SetInputRange(DRSParameters->range); |
+ |
+ /* use following line to set range to 0..1V */ |
+ //b->SetInputRange(0.5); |
+ |
+ /* use following line to turn on the internal 100 MHz clock connected to all channels */ |
+ //b->EnableTcal(1); |
+ |
+ /* kaj je to .... |
+ // Set domino mode |
+ // mode == 0: single sweep |
+ // mode == 1: run continously -- default |
+ b->SetDominoMode(1); |
+ // Set domino activity |
+ // mode == 0: stop during readout |
+ // mode == 1: keep domino wave running -- default |
+ // |
+ b->SetDominoActive(1); |
+ |
+ // Set readout mode |
+ // mode == 0: start from first bin -- default |
+ // mode == 1: start from domino stop |
+ // |
+ b->SetReadoutMode(1); |
+ */ |
+ |
+ /* use following lines to enable hardware trigger on CH1 at 50 mV positive edge */ |
+ printf("Board Type:%d\n",b->GetBoardType() ); |
+ if (b->GetBoardType() >= 8) { // Evaluaiton Board V4&5 |
+ |
+ b->EnableTrigger(DRSParameters->trigger_type, 0); // enable hardware trigger - 1 fast trigger, 2 slow trigger, 0 disable hw trigger |
+ b->SetTriggerSource(1<<DRSParameters->trigger_channel); // set CH1 as source // simple or of single channel |
+ } else if (b->GetBoardType() == 7) { // Evaluation Board V3 |
+ b->EnableTrigger(0, 1); // lemo off, analog trigger on |
+ b->SetTriggerSource(0); // use CH1 as source |
+ } |
+ b->SetTriggerLevel(DRSParameters->trigger_level); // 0.05 V |
+ b->SetTriggerPolarity(DRSParameters->trigger_polarity); // positive edge |
+ |
+ /* use following lines to set individual trigger elvels */ |
+ //b->SetIndividualTriggerLevel(1, 0.1); |
+ //b->SetIndividualTriggerLevel(2, 0.2); |
+ //b->SetIndividualTriggerLevel(3, 0.3); |
+ //b->SetIndividualTriggerLevel(4, 0.4); |
+ //b->SetTriggerSource(15); |
+ |
+ b->SetTriggerDelayNs( DRSParameters->trigger_delay); // zero ns trigger delay |
+ |
+ /* use following lines to enable the external trigger */ |
+ //if (b->GetBoardType() == 8) { // Evaluaiton Board V4 |
+ // b->EnableTrigger(1, 0); // enable hardware trigger |
+ // b->SetTriggerSource(1<<4); // set external trigger as source |
+ //} else { // Evaluation Board V3 |
+ // b->EnableTrigger(1, 0); // lemo on, analog trigger off |
+ // } |
+ |
+ return 0; |
+ |
+ |
+} |
+ |
+static float DRSTimeArray[8][1024]; |
+static float DRSWaveArray[8][1024]; |
+ |
+DLLEXPORT float * DRSGetTime(int ch){ return DRSTimeArray[ch];} |
+DLLEXPORT float * DRSGetWave(int ch){ return DRSWaveArray[ch];} |
+ |
+DLLEXPORT int DRSRead( int DRStimer) |
+{ |
+ |
+ DRSBoard *b = drs->GetBoard(0); |
+ |
+ |
+ |
+ /* wait for trigger */ |
+ |
+ |
+ int tout=1000; /* timeout in mili seconds */ |
+ DRSTimeout=0; |
+ |
+ if (DRStimer) start_timer(tout, &DRSSetTimeout); |
+ |
+ /* start board (activate domino wave) */ |
+ b->StartDomino(); |
+ |
+ if (!DRSParameters->trigger_type) b->SoftTrigger(); |
+ |
+ while (b->IsBusy()){ |
+ |
+ if (DRSTimeout) { |
+ printf("Waiting for Trigger.. at line %d\n", __LINE__); |
+ |
+ if (DRStimer) stop_timer(); |
+ |
+ return -1; |
+ } |
+ }; |
+ |
+ |
+ if (DRStimer) stop_timer(); |
+ |
+ |
+ |
+ /* read all waveforms */ |
+ b->TransferWaves(0, 8); |
+ |
+ |
+ for (int k=0;k<4;k++){ |
+ if (! (DRSParameters->mask & ( 0x1<<k )) ) continue; |
+ /* Note: On the evaluation board input #1 is connected to channel 0 and 1 of |
+ the DRS chip, input #2 is connected to channel 2 and 3 and so on. So to |
+ get the input #2 we have to read DRS channel #2, not #1. */ |
+ |
+ /* read time (X) array of k-th channel in ns and waveform (Y) array of k-th channel in mV */ |
+ b->GetTime(0, 2*k, b->GetTriggerCell(DRSParameters->trigger_channel), DRSTimeArray[k]); |
+ b->GetWave(0, 2*k, DRSWaveArray[k]); |
+ |
+ |
+ } |
+ |
+ return 0; |
+} |
+ |
+DLLEXPORT int DRSEnd(){ |
+ |
+ /* delete DRS object -> close USB connection */ |
+ if (drs) delete drs; |
+ drs = NULL; |
+ return 0; |
+} |
+ |
+ |
+ |
+DLLEXPORT int DRSToBuffer( unsigned char *p, int m_evSerial ) |
+{ |
+ |
+ unsigned short d; |
+ float t; |
+ unsigned char *p0 = p; |
+ |
+ int m_nBoards = drs->GetNumberOfBoards(); |
+ int m_waveDepth = 1024 ;// 2048 |
+ int m_inputRange = drs->GetBoard(0)->GetInputRange(); |
+ time_t rawtime; |
+ time ( &rawtime ); |
+ struct tm m_evTimestamp; |
+ m_evTimestamp = *(localtime ( &rawtime )); |
+ struct timeval mtime; |
+ gettimeofday(&mtime, NULL); |
+ |
+ if (m_evSerial == 0) { |
+ // time calibration header |
+ memcpy(p, "TIME", 4); |
+ p += 4; |
+ |
+ for (int b=0 ; b<m_nBoards ; b++) { |
+ // store board serial number |
+ sprintf((char *)p, "B#"); |
+ p += 2; |
+ *(unsigned short *)p = drs->GetBoard(b)->GetBoardSerialNumber(); |
+ p += sizeof(unsigned short); |
+ |
+ for (int i=0 ; i<4 ; i++) { |
+ if (DRSParameters->mask & (0x1<<i)) { |
+ sprintf((char *)p, "C%03d", i+1); |
+ p += 4; |
+ float tcal[2048]; |
+ drs->GetBoard(b)->GetTimeCalibration(0, i*2, 0, tcal, 0); |
+ for (int j=0 ; j<m_waveDepth ; j++) { |
+ // save binary time as 32-bit float value |
+ if (m_waveDepth == 2048) { |
+ t = (tcal[j]+tcal[j+1])/2; |
+ j++; |
+ } else |
+ t = tcal[j]; |
+ *(float *)p = t; |
+ p += sizeof(float); |
+ } |
+ } |
+ } |
+ } |
+ } |
+ |
+ |
+ |
+ memcpy(p, "EHDR", 4); |
+ p += 4; |
+ *(int *)p = m_evSerial; |
+ p += sizeof(int); |
+ *(unsigned short *)p = m_evTimestamp.tm_year; |
+ p += sizeof(unsigned short); |
+ *(unsigned short *)p = m_evTimestamp.tm_mon; |
+ p += sizeof(unsigned short); |
+ *(unsigned short *)p = m_evTimestamp.tm_mday; |
+ p += sizeof(unsigned short); |
+ *(unsigned short *)p = m_evTimestamp.tm_hour; |
+ p += sizeof(unsigned short); |
+ *(unsigned short *)p = m_evTimestamp.tm_min; |
+ p += sizeof(unsigned short); |
+ *(unsigned short *)p = m_evTimestamp.tm_sec; |
+ p += sizeof(unsigned short); |
+ *(unsigned short *)p = mtime.tv_usec/1000; |
+ p += sizeof(unsigned short); |
+ *(unsigned short *)p = (unsigned short)(m_inputRange * 1000); // range |
+ p += sizeof(unsigned short); |
+ |
+ int b=0; // only for board 0 |
+ |
+ // store board serial number |
+ sprintf((char *)p, "B#"); |
+ p += 2; |
+ *(unsigned short *)p = drs->GetBoard(b)->GetBoardSerialNumber(); |
+ p += sizeof(unsigned short); |
+ |
+ // store trigger cell |
+ sprintf((char *)p, "T#"); |
+ p += 2; |
+ *(unsigned short *)p = drs->GetBoard(b)->GetTriggerCell(DRSParameters->trigger_channel); |
+ p += sizeof(unsigned short); |
+ |
+ for (int i=0 ; i<4 ; i++) { |
+ if (DRSParameters->mask & (0x1<<i)) { |
+ sprintf((char *)p, "C%03d", i+1); |
+ p += 4; |
+ for (int j=0 ; j<m_waveDepth ; j++) { |
+ // save binary date as 16-bit value: |
+ // 0 = -0.5V, 65535 = +0.5V for range 0 |
+ // 0 = -0.05V, 65535 = +0.95V for range 0.45 |
+ if (m_waveDepth == 2048) { |
+ // in cascaded mode, save 1024 values as averages of the 2048 values |
+ d = (unsigned short)(((DRSWaveArray[i][j]+DRSWaveArray[i][j+1])/2000.0 - m_inputRange + 0.5) * 65535); |
+ *(unsigned short *)p = d; |
+ p += sizeof(unsigned short); |
+ j++; |
+ } else { |
+ d = (unsigned short)((DRSWaveArray[i][j]/1000.0 - m_inputRange + 0.5) * 65535); |
+ *(unsigned short *)p = d; |
+ p += sizeof(unsigned short); |
+ } |
+ } |
+ } |
+ } |
+ |
+ return (p-p0); // return number of bytes |
+} |
+ |
+ |
+ |
+#ifdef MAIN |
+ |
+ |
+ |
+#include "XGetopt.h" |
+#include "getopt.h" |
+ |
+TH2F *h[4]; |
+ |
+typedef struct { |
+ char recid[4]; |
+ unsigned int posx, posy, posz; |
+ unsigned int iposx, iposy, iposz; |
+} POSREC; |
+ |
+ |
+int help() { |
+ printf ("*********************************************************************************:\n"); |
+ printf ("Usage: Read of the DRS4 PSI board and dump of the waveforms in the file:\n\n"); |
+ printf ("Arguments: \n"); |
+ printf ("-v verbosity \n"); |
+ printf ("-a output rootfile \n"); |
+ printf ("-o output filename \n"); |
+ printf ("-r output root filename \n"); |
+ printf ("-n number of events\n"); |
+ printf ("-m channel bit mask\n"); |
+ printf ("-h trigger type (0 software, 1 fast hardware, 2 slow hardware)\n"); |
+ printf ("-d trigger delay in ns\n"); |
+ printf ("-f sampling frequency\n"); |
+ printf ("-t trigger channel\n"); |
+ printf ("-l trigger level\n"); |
+ printf ("-p trigger polarity (0 positive\n"); |
+ printf ("*********************************************************************************:\n"); |
+ printf ("Examples:\n\n"); |
+ |
+ return 0; |
+} |
+ |
+ |
+ |
+char filename[0xFF]=""; |
+char rootfile[0xFF]=""; |
+int neve = 0; |
+int verbose = 0; |
+ |
+void Init(int argc, char **argv){ |
+ DRSParameters = drssettings::instance(); |
+ char c; |
+ |
+ extern char *optarg; |
+ extern int optind; |
+ extern int optopt; |
+ while ((c = getopt (argc, argv, "a:o:v:m:n:f:d:r:h:t:p:l:")) != -1){ |
+ |
+ switch (c) |
+ { |
+ |
+ case 'a': |
+ sprintf(rootfile,"%s", optarg ); |
+ break; // root output |
+ |
+ case 'o': |
+ sprintf(filename,"%s", optarg ); |
+ break; // output |
+ |
+ case 'v': |
+ verbose = atoi(optarg); |
+ break; // verbosity |
+ case 'm':{ |
+ unsigned long ul = strtoul (optarg,NULL,0); |
+ DRSSetMask( (unsigned char)( ul & 0xF ) ) ; |
+ break; |
+ } // channel mask |
+ case 'n': |
+ neve = atoi (optarg); |
+ break; // number of events or number of scan points |
+ |
+ case 'f': |
+ DRSSetFrequency( atoi (optarg) ); |
+ break; // sampling frequency |
+ |
+ case 'd': |
+ DRSSetTriggerDelay( atof (optarg) ); |
+ break; // trigger delay |
+ case 'p': |
+ DRSSetTriggerPolarity( atoi (optarg)); |
+ break; // trigger polarity |
+ case 'l': |
+ DRSSetTriggerLevel(atoi (optarg)); |
+ break; // trigger level |
+ |
+ |
+ case 'r': |
+ DRSSetRange ( atof (optarg) ); |
+ break; // range |
+ case 'h': |
+ DRSSetTriggerType( atoi (optarg) ); |
+ break; // send sotware trigger before reading out the dat |
+ case 't': |
+ DRSSetTriggerChannel( atoi(optarg) ); |
+ break; // trigger channel |
+ |
+ |
+ case '?': |
+ if (optopt == 'c') |
+ fprintf (stderr, "Option -%c requires an argument.\n", optopt); |
+ else if (isprint (optopt)) |
+ fprintf (stderr, "Unknown option `-%c'.\n", optopt); |
+ else |
+ fprintf (stderr, |
+ "Unknown option character `\\x%x'.\n", |
+ optopt); |
+ abort (); |
+ default: |
+ abort (); |
+ } |
+ } |
+ //for (int i=optind; i<argc; i++) data = strtoul (argv[i],NULL,0); |
+ |
+} |
+ |
+int ctrl_c=0; |
+DLLEXPORT void DRSSigInt ( int ) |
+{ |
+ ctrl_c = 1; |
+ printf("->>> CTRL+c !!!\n"); |
+} |
+ |
+//#ifdef __CINT__ |
+int main(int argc, char **argv){ |
+//#else |
+//int drsread(int argc, char **argv){ |
+//#endif |
+ |
+ if (signal (SIGINT, DRSSigInt) == SIG_ERR) { |
+ perror ("sigignore"); |
+ } |
+ |
+ |
+Init(argc, argv); |
+if (argc==1) { help(); return 0; } |
+ |
+FILE *fp=NULL; |
+if (strlen(filename)>0) { |
+ if (verbose) printf("Data in the file:%s\n", filename); |
+ fp=fopen(filename,"wb"); |
+} |
+ |
+TFile *rfile= NULL; |
+if (strlen(rootfile)>0) { |
+ if (verbose) printf("Data in the file:%s\n", rootfile); |
+ rfile = new TFile(rootfile,"RECREATE"); |
+} |
+ |
+ |
+TCanvas *c = new TCanvas(); c->Divide(2,2); |
+c->Draw(); |
+for (int i=0;i<4;i++){ |
+ if (! (DRSParameters->mask & ( 0x1<<i )) ) continue; |
+ char name[0xff]; |
+ sprintf(name,"h%d",i); |
+ h[i]=new TH2F(name,name,1024,0,204,1024,-0.6+DRSParameters->range,0.6+DRSParameters->range); |
+ c->cd(i+1); h[i]->Draw("colz"); |
+ |
+} |
+ |
+ |
+ |
+//--------------------------------------- |
+static unsigned char *buffer; |
+static int buffer_size = 0; |
+const int nBoards=1; |
+const int waveDepth=1024; |
+if (buffer_size == 0) { |
+ buffer_size = 4 + nBoards * (4 + 4*(4+waveDepth*4)); |
+ buffer_size += 24 + nBoards * (8 + 4*(4+waveDepth*2)); |
+ buffer = (unsigned char *)malloc(buffer_size); |
+} |
+ |
+time_t t,told, tstart; |
+if (!DRSInit()){ |
+ time(&tstart); |
+ told=tstart; |
+ int i=0; |
+ for (i=0; i<neve; i++) { |
+ int nb = (DRSRead(1) == 0 && fp ) ? DRSToBuffer( buffer , i ) : 0; |
+ |
+ if (DRSTimeout) i--; |
+ if (ctrl_c) break; |
+ time(&t); |
+ if (t!=told ) { |
+ printf("%d events in %2.2f min (%d s) %s",i+1, (double)(t-tstart)/60.,int(t-tstart), ctime(&t)); |
+ c->Modified(); c->Update(); |
+ } |
+ told=t; |
+// Save data |
+ if (nb>0 && fp) fwrite(buffer, 1,nb ,fp); |
+// Plot Data |
+ for (int k=0;k<4;k++){ |
+ if (! (DRSParameters->mask & ( 0x1<<k )) ) continue; |
+ float *t=DRSGetTime(k); |
+ float *x=DRSGetWave(k); |
+ for (int i=0 ; i<1024 ; i++) { |
+ if (verbose) printf("[%d] %d. x= %3.2f y=%3.2f\n", k, i, t[i], x[i] ); |
+ h[k]->Fill( t[i], x[i]*1e-3); |
+ } |
+ } |
+ } |
+ time(&t); |
+ printf("%d events in %2.2f min (%d s) %s",i+1, (double)(t-tstart)/60.,int(t-tstart), ctime(&t)); |
+ |
+ DRSEnd(); |
+} |
+//--------------------------------------- |
+if (rfile !=NULL) rfile->Write(); |
+if (fp) fclose(fp); |
+if (c) c->SaveAs("drsread.pdf"); |
+// TApplication* theApp = new TApplication("App", NULL, NULL); |
+// theApp->Run(); |
+ |
+ |
+ |
+} |
+ |
+#endif |
\ No newline at end of file |
Index: instr/drs/drsread.dll |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/instr/drs/drsread.dll |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: instr/drs/drsread.h |
=================================================================== |
--- instr/drs/drsread.h (nonexistent) |
+++ instr/drs/drsread.h (revision 197) |
@@ -0,0 +1,31 @@ |
+#ifndef _DRSREAD_H_ |
+#define _DRSREAD_H_ |
+#ifdef DLLMAIN |
+#define DLLEXPORT extern "C" __declspec(dllexport) |
+#else |
+//#define DLLEXPORT __declspec(dllimport) |
+#define DLLEXPORT |
+#endif |
+ |
+DLLEXPORT void DRSSetMask(int mask); |
+DLLEXPORT void DRSSetTriggerType(int type); |
+DLLEXPORT void DRSSetFrequency(int freq); |
+DLLEXPORT void DRSSetRange(double range); |
+DLLEXPORT void DRSSetTriggerChannel(int channel); |
+DLLEXPORT void DRSSetTriggerDelay(double delay); |
+DLLEXPORT void DRSSetTriggerLevel(double level); |
+DLLEXPORT void DRSSetTriggerPolarity(int polarity); |
+ |
+DLLEXPORT float * DRSGetTime(int ch); |
+DLLEXPORT float * DRSGetWave(int ch); |
+ |
+DLLEXPORT int DRSInit(); |
+DLLEXPORT int DRSRead( int drstimer); |
+DLLEXPORT int DRSEnd(); |
+DLLEXPORT int DRSToBuffer( unsigned char *p, int m_evSerial ); |
+ |
+DLLEXPORT int DRSIsTimeout(); |
+DLLEXPORT void DRSSetTimeout ( void ); |
+ |
+DLLEXPORT void DRSSigInt ( int k ); |
+#endif |
Index: instr/drs/drsread.lib |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/instr/drs/drsread.lib |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: instr/drs/getopt.h |
=================================================================== |
--- instr/drs/getopt.h (nonexistent) |
+++ instr/drs/getopt.h (revision 197) |
@@ -0,0 +1,74 @@ |
+ |
+/*- |
+ * Copyright (c) 2000 The NetBSD Foundation, Inc. |
+ * All rights reserved. |
+ * |
+ * This code is derived from software contributed to The NetBSD Foundation |
+ * by Dieter Baron and Thomas Klausner. |
+ * |
+ * Redistribution and use in source and binary forms, with or without |
+ * modification, are permitted provided that the following conditions |
+ * are met: |
+ * 1. Redistributions of source code must retain the above copyright |
+ * notice, this list of conditions and the following disclaimer. |
+ * 2. Redistributions in binary form must reproduce the above copyright |
+ * notice, this list of conditions and the following disclaimer in the |
+ * documentation and/or other materials provided with the distribution. |
+ * |
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
+ * POSSIBILITY OF SUCH DAMAGE. |
+ * |
+ * $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ |
+ */ |
+ |
+#ifndef _GETOPT_H_ |
+#define _GETOPT_H_ |
+ |
+/* |
+ * Gnu like getopt_long() and BSD4.4 getsubopt()/optreset extensions |
+ */ |
+#define no_argument 0 |
+#define required_argument 1 |
+#define optional_argument 2 |
+ |
+#ifdef __cplusplus |
+extern "C" { |
+#endif |
+ |
+struct option { |
+ /* name of long option */ |
+ const char *name; |
+ /* |
+ * one of no_argument, required_argument, and optional_argument: |
+ * whether option takes an argument |
+ */ |
+ int has_arg; |
+ /* if not NULL, set *flag to val when option found */ |
+ int *flag; |
+ /* if flag not NULL, value to set *flag to; else return value */ |
+ int val; |
+}; |
+ |
+int getopt_long(int, char * const *, const char *, |
+ const struct option *, int *); |
+ |
+extern int optreset; |
+extern char *optarg; |
+extern int opterr; |
+extern int optind; |
+extern int optopt; |
+ |
+#ifdef __cplusplus |
+}; |
+#endif |
+ |
+#endif /* !_GETOPT_H_ */ |
Index: instr/drs/getopt_long.c |
=================================================================== |
--- instr/drs/getopt_long.c (nonexistent) |
+++ instr/drs/getopt_long.c (revision 197) |
@@ -0,0 +1,466 @@ |
+ |
+/*- |
+ * Copyright (c) 2000 The NetBSD Foundation, Inc. |
+ * All rights reserved. |
+ * |
+ * This code is derived from software contributed to The NetBSD Foundation |
+ * by Dieter Baron and Thomas Klausner. |
+ * |
+ * Redistribution and use in source and binary forms, with or without |
+ * modification, are permitted provided that the following conditions |
+ * are met: |
+ * 1. Redistributions of source code must retain the above copyright |
+ * notice, this list of conditions and the following disclaimer. |
+ * 2. Redistributions in binary form must reproduce the above copyright |
+ * notice, this list of conditions and the following disclaimer in the |
+ * documentation and/or other materials provided with the distribution. |
+ * |
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
+ * POSSIBILITY OF SUCH DAMAGE. |
+ * |
+ * $NetBSD: getopt_long.c,v 1.3 2008/04/29 05:46:09 martin Exp $ |
+ */ |
+ |
+#include <assert.h> |
+#include <errno.h> |
+#include <stdarg.h> |
+#include <stdio.h> |
+#include <stdlib.h> |
+#include <string.h> |
+#include "getopt.h" |
+ |
+#ifndef _DIAGASSERT |
+#define _DIAGASSERT(e) |
+#endif |
+ |
+int opterr = 1; /* if error message should be printed */ |
+int optind = 1; /* index into parent argv vector */ |
+int optopt = '?'; /* character checked for validity */ |
+int optreset; /* reset getopt */ |
+char *optarg; /* argument associated with option */ |
+ |
+ |
+#define IGNORE_FIRST (*options == '-' || *options == '+') |
+#define PRINT_ERROR ((opterr) && ((*options != ':') \ |
+ || (IGNORE_FIRST && options[1] != ':'))) |
+#define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL) |
+#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST) |
+/* XXX: GNU ignores PC if *options == '-' */ |
+#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-') |
+ |
+/* return values */ |
+#define BADCH (int)'?' |
+#define BADARG (int)':' |
+#define INORDER (int)1 |
+ |
+#define EMSG "" |
+ |
+static int getopt_internal(int, char * const *, const char *); |
+static int gcd(int, int); |
+static void permute_args(int, int, int, char * const *); |
+static void xwarnx(const char *, ...); |
+ |
+static char *place = EMSG; /* option letter processing */ |
+ |
+/* XXX: set optreset to 1 rather than these two */ |
+static int nonopt_start = -1; /* first non option argument (for permute) */ |
+static int nonopt_end = -1; /* first option after non options (for permute) */ |
+ |
+/* Error messages */ |
+static const char recargchar[] = "option requires an argument -- %c"; |
+static const char recargstring[] = "option requires an argument -- %s"; |
+static const char ambig[] = "ambiguous option -- %.*s"; |
+static const char noarg[] = "option doesn't take an argument -- %.*s"; |
+static const char illoptchar[] = "illegal option -- %c"; |
+static const char illoptstring[] = "illegal option -- %s"; |
+ |
+static const char *progname; |
+ |
+ |
+/* Replacement for warnx(3) for systems without it. */ |
+static void xwarnx(const char *fmt, ...) { |
+ va_list ap; |
+ |
+ va_start(ap, fmt); |
+ if (progname) |
+ (void) fprintf(stderr, "%s: ", progname); |
+ if (fmt) |
+ (void) vfprintf(stderr, fmt, ap); |
+ (void) fprintf(stderr, "\n"); |
+ va_end(ap); |
+} |
+ |
+/* |
+ * Compute the greatest common divisor of a and b. |
+ */ |
+static int |
+gcd(int a, int b) |
+{ |
+ int c; |
+ |
+ c = a % b; |
+ while (c != 0) { |
+ a = b; |
+ b = c; |
+ c = a % b; |
+ } |
+ |
+ return b; |
+} |
+ |
+/* |
+ * Exchange the block from nonopt_start to nonopt_end with the block |
+ * from nonopt_end to opt_end (keeping the same order of arguments |
+ * in each block). |
+ */ |
+static void |
+permute_args(int nonopt_start, int nonopt_end, int opt_end, char * const *nargv) |
+{ |
+ int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; |
+ char *swap; |
+ |
+ /* |
+ * compute lengths of blocks and number and size of cycles |
+ */ |
+ nnonopts = nonopt_end - nonopt_start; |
+ nopts = opt_end - nonopt_end; |
+ ncycle = gcd(nnonopts, nopts); |
+ cyclelen = (opt_end - nonopt_start) / ncycle; |
+ |
+ for (i = 0; i < ncycle; i++) { |
+ cstart = nonopt_end+i; |
+ pos = cstart; |
+ for (j = 0; j < cyclelen; j++) { |
+ if (pos >= nonopt_end) |
+ pos -= nnonopts; |
+ else |
+ pos += nopts; |
+ swap = nargv[pos]; |
+ /* LINTED const cast */ |
+ ((char **) nargv)[pos] = nargv[cstart]; |
+ /* LINTED const cast */ |
+ ((char **)nargv)[cstart] = swap; |
+ } |
+ } |
+} |
+ |
+/* |
+ * getopt_internal -- |
+ * Parse argc/argv argument vector. Called by user level routines. |
+ * Returns -2 if -- is found (can be long option or end of options marker). |
+ */ |
+static int |
+getopt_internal(int nargc, char * const *nargv, const char *options) |
+{ |
+ char *oli; /* option letter list index */ |
+ int optchar; |
+ |
+ _DIAGASSERT(nargv != NULL); |
+ _DIAGASSERT(options != NULL); |
+ |
+ optarg = NULL; |
+ |
+ /* |
+ * XXX Some programs (like rsyncd) expect to be able to |
+ * XXX re-initialize optind to 0 and have getopt_long(3) |
+ * XXX properly function again. Work around this braindamage. |
+ */ |
+ if (optind == 0) |
+ optind = 1; |
+ |
+ if (optreset) |
+ nonopt_start = nonopt_end = -1; |
+start: |
+ if (optreset || !*place) { /* update scanning pointer */ |
+ optreset = 0; |
+ if (optind >= nargc) { /* end of argument vector */ |
+ place = EMSG; |
+ if (nonopt_end != -1) { |
+ /* do permutation, if we have to */ |
+ permute_args(nonopt_start, nonopt_end, |
+ optind, nargv); |
+ optind -= nonopt_end - nonopt_start; |
+ } |
+ else if (nonopt_start != -1) { |
+ /* |
+ * If we skipped non-options, set optind |
+ * to the first of them. |
+ */ |
+ optind = nonopt_start; |
+ } |
+ nonopt_start = nonopt_end = -1; |
+ return -1; |
+ } |
+ if (*(place = nargv[optind]) != '-') { /* found non-option */ |
+ place = EMSG; |
+ if (IN_ORDER) { |
+ /* |
+ * GNU extension: |
+ * return non-option as argument to option 1 |
+ */ |
+ optarg = nargv[optind++]; |
+ return INORDER; |
+ } |
+ if (!PERMUTE) { |
+ /* |
+ * if no permutation wanted, stop parsing |
+ * at first non-option |
+ */ |
+ return -1; |
+ } |
+ /* do permutation */ |
+ if (nonopt_start == -1) |
+ nonopt_start = optind; |
+ else if (nonopt_end != -1) { |
+ permute_args(nonopt_start, nonopt_end, |
+ optind, nargv); |
+ nonopt_start = optind - |
+ (nonopt_end - nonopt_start); |
+ nonopt_end = -1; |
+ } |
+ optind++; |
+ /* process next argument */ |
+ goto start; |
+ } |
+ if (nonopt_start != -1 && nonopt_end == -1) |
+ nonopt_end = optind; |
+ if (place[1] && *++place == '-') { /* found "--" */ |
+ place++; |
+ return -2; |
+ } |
+ } |
+ if ((optchar = (int)*place++) == (int)':' || |
+ (oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) { |
+ /* option letter unknown or ':' */ |
+ if (!*place) |
+ ++optind; |
+ if (PRINT_ERROR) |
+ xwarnx(illoptchar, optchar); |
+ optopt = optchar; |
+ return BADCH; |
+ } |
+ if (optchar == 'W' && oli[1] == ';') { /* -W long-option */ |
+ /* XXX: what if no long options provided (called by getopt)? */ |
+ if (*place) |
+ return -2; |
+ |
+ if (++optind >= nargc) { /* no arg */ |
+ place = EMSG; |
+ if (PRINT_ERROR) |
+ xwarnx(recargchar, optchar); |
+ optopt = optchar; |
+ /* XXX: GNU returns '?' if options[0] != ':' */ |
+ return BADARG; |
+ } else /* white space */ |
+ place = nargv[optind]; |
+ /* |
+ * Handle -W arg the same as --arg (which causes getopt to |
+ * stop parsing). |
+ */ |
+ return -2; |
+ } |
+ if (*++oli != ':') { /* doesn't take argument */ |
+ if (!*place) |
+ ++optind; |
+ } else { /* takes (optional) argument */ |
+ optarg = NULL; |
+ if (*place) /* no white space */ |
+ optarg = place; |
+ /* XXX: disable test for :: if PC? (GNU doesn't) */ |
+ else if (oli[1] != ':') { /* arg not optional */ |
+ if (++optind >= nargc) { /* no arg */ |
+ place = EMSG; |
+ if (PRINT_ERROR) |
+ xwarnx(recargchar, optchar); |
+ optopt = optchar; |
+ /* XXX: GNU returns '?' if options[0] != ':' */ |
+ return BADARG; |
+ } else |
+ optarg = nargv[optind]; |
+ } |
+ place = EMSG; |
+ ++optind; |
+ } |
+ /* dump back option letter */ |
+ return optchar; |
+} |
+ |
+/* |
+ * getopt -- |
+ * Parse argc/argv argument vector. |
+ * |
+ * [eventually this will replace the real getopt] |
+ */ |
+int |
+getopt(int nargc, char * const *nargv, const char *options) |
+{ |
+ int retval; |
+ |
+ progname = nargv[0]; |
+ |
+ if ((retval = getopt_internal(nargc, nargv, options)) == -2) { |
+ ++optind; |
+ /* |
+ * We found an option (--), so if we skipped non-options, |
+ * we have to permute. |
+ */ |
+ if (nonopt_end != -1) { |
+ permute_args(nonopt_start, nonopt_end, optind, |
+ nargv); |
+ optind -= nonopt_end - nonopt_start; |
+ } |
+ nonopt_start = nonopt_end = -1; |
+ retval = -1; |
+ } |
+ return retval; |
+} |
+ |
+/* |
+ * getopt_long -- |
+ * Parse argc/argv argument vector. |
+ */ |
+int |
+getopt_long(int nargc, |
+ char * const *nargv, |
+ const char *options, |
+ const struct option *long_options, |
+ int *idx) |
+{ |
+ int retval; |
+ |
+ _DIAGASSERT(nargv != NULL); |
+ _DIAGASSERT(options != NULL); |
+ _DIAGASSERT(long_options != NULL); |
+ /* idx may be NULL */ |
+ |
+ progname = nargv[0]; |
+ |
+ if ((retval = getopt_internal(nargc, nargv, options)) == -2) { |
+ char *current_argv, *has_equal; |
+ size_t current_argv_len; |
+ int i, match; |
+ |
+ current_argv = place; |
+ match = -1; |
+ |
+ optind++; |
+ place = EMSG; |
+ |
+ if (*current_argv == '\0') { /* found "--" */ |
+ /* |
+ * We found an option (--), so if we skipped |
+ * non-options, we have to permute. |
+ */ |
+ if (nonopt_end != -1) { |
+ permute_args(nonopt_start, nonopt_end, |
+ optind, nargv); |
+ optind -= nonopt_end - nonopt_start; |
+ } |
+ nonopt_start = nonopt_end = -1; |
+ return -1; |
+ } |
+ if ((has_equal = strchr(current_argv, '=')) != NULL) { |
+ /* argument found (--option=arg) */ |
+ current_argv_len = has_equal - current_argv; |
+ has_equal++; |
+ } else |
+ current_argv_len = strlen(current_argv); |
+ |
+ for (i = 0; long_options[i].name; i++) { |
+ /* find matching long option */ |
+ if (strncmp(current_argv, long_options[i].name, |
+ current_argv_len)) |
+ continue; |
+ |
+ if (strlen(long_options[i].name) == |
+ (unsigned)current_argv_len) { |
+ /* exact match */ |
+ match = i; |
+ break; |
+ } |
+ if (match == -1) /* partial match */ |
+ match = i; |
+ else { |
+ /* ambiguous abbreviation */ |
+ if (PRINT_ERROR) |
+ xwarnx(ambig, (int)current_argv_len, |
+ current_argv); |
+ optopt = 0; |
+ return BADCH; |
+ } |
+ } |
+ if (match != -1) { /* option found */ |
+ if (long_options[match].has_arg == no_argument |
+ && has_equal) { |
+ if (PRINT_ERROR) |
+ xwarnx(noarg, (int)current_argv_len, |
+ current_argv); |
+ /* |
+ * XXX: GNU sets optopt to val regardless of |
+ * flag |
+ */ |
+ if (long_options[match].flag == NULL) |
+ optopt = long_options[match].val; |
+ else |
+ optopt = 0; |
+ /* XXX: GNU returns '?' if options[0] != ':' */ |
+ return BADARG; |
+ } |
+ if (long_options[match].has_arg == required_argument || |
+ long_options[match].has_arg == optional_argument) { |
+ if (has_equal) |
+ optarg = has_equal; |
+ else if (long_options[match].has_arg == |
+ required_argument) { |
+ /* |
+ * optional argument doesn't use |
+ * next nargv |
+ */ |
+ optarg = nargv[optind++]; |
+ } |
+ } |
+ if ((long_options[match].has_arg == required_argument) |
+ && (optarg == NULL)) { |
+ /* |
+ * Missing argument; leading ':' |
+ * indicates no error should be generated |
+ */ |
+ if (PRINT_ERROR) |
+ xwarnx(recargstring, current_argv); |
+ /* |
+ * XXX: GNU sets optopt to val regardless |
+ * of flag |
+ */ |
+ if (long_options[match].flag == NULL) |
+ optopt = long_options[match].val; |
+ else |
+ optopt = 0; |
+ /* XXX: GNU returns '?' if options[0] != ':' */ |
+ --optind; |
+ return BADARG; |
+ } |
+ } else { /* unknown option */ |
+ if (PRINT_ERROR) |
+ xwarnx(illoptstring, current_argv); |
+ optopt = 0; |
+ return BADCH; |
+ } |
+ if (long_options[match].flag) { |
+ *long_options[match].flag = long_options[match].val; |
+ retval = 0; |
+ } else |
+ retval = long_options[match].val; |
+ if (idx) |
+ *idx = match; |
+ } |
+ return retval; |
+} |
Index: instr/drs/gettimeofday.c |
=================================================================== |
--- instr/drs/gettimeofday.c (nonexistent) |
+++ instr/drs/gettimeofday.c (revision 197) |
@@ -0,0 +1,57 @@ |
+/* |
+ * gettimeofday.c |
+ * Win32 gettimeofday() replacement |
+ * |
+ * src/port/gettimeofday.c |
+ * |
+ * Copyright (c) 2003 SRA, Inc. |
+ * Copyright (c) 2003 SKC, Inc. |
+ * |
+ * Permission to use, copy, modify, and distribute this software and |
+ * its documentation for any purpose, without fee, and without a |
+ * written agreement is hereby granted, provided that the above |
+ * copyright notice and this paragraph and the following two |
+ * paragraphs appear in all copies. |
+ * |
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, |
+ * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING |
+ * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS |
+ * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED |
+ * OF THE POSSIBILITY OF SUCH DAMAGE. |
+ * |
+ * THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT |
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+ * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS |
+ * IS" BASIS, AND THE AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, |
+ * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
+ */ |
+ |
+//#include "c.h" |
+#include <windows.h> |
+#include <time.h> |
+ |
+ |
+/* FILETIME of Jan 1 1970 00:00:00. */ |
+static const unsigned __int64 epoch = ((unsigned __int64) 116444736000000000ULL); |
+ |
+/* |
+ * timezone information is stored outside the kernel so tzp isn't used anymore. |
+ * |
+ * Note: this function is not for Win32 high precision timing purpose. See |
+ * elapsed_time(). |
+ */ |
+int gettimeofday(struct timeval * tp, struct timezone * tzp){ |
+ FILETIME file_time; |
+ SYSTEMTIME system_time; |
+ ULARGE_INTEGER ularge; |
+ |
+ GetSystemTime(&system_time); |
+ SystemTimeToFileTime(&system_time, &file_time); |
+ ularge.LowPart = file_time.dwLowDateTime; |
+ ularge.HighPart = file_time.dwHighDateTime; |
+ |
+ tp->tv_sec = (long) ((ularge.QuadPart - epoch) / 10000000L); |
+ tp->tv_usec = (long) (system_time.wMilliseconds * 1000); |
+ |
+ return 0; |
+} |
\ No newline at end of file |
Index: instr/drs/gettimeofday.h |
=================================================================== |
--- instr/drs/gettimeofday.h (nonexistent) |
+++ instr/drs/gettimeofday.h (revision 197) |
@@ -0,0 +1,12 @@ |
+#ifndef _GETTIMEOFDAY_H_ |
+#define _GETTIMEOFDAY_H_ |
+#ifdef __cplusplus |
+extern "C" { |
+#endif |
+ |
+int gettimeofday(struct timeval * tp, struct timezone * tzp); |
+ |
+#ifdef __cplusplus |
+} |
+#endif |
+#endif |
\ No newline at end of file |
Index: instr/drs/gui.cpp |
=================================================================== |
--- instr/drs/gui.cpp (nonexistent) |
+++ instr/drs/gui.cpp (revision 197) |
@@ -0,0 +1,503 @@ |
+// By ROOT version 5.17/02 on 2008-03-13 06:46:41 |
+ |
+#ifndef ROOT_TGDockableFrame |
+#include "TGDockableFrame.h" |
+#endif |
+#ifndef ROOT_TGMenu |
+#include "TGMenu.h" |
+#endif |
+#ifndef ROOT_TGMdiDecorFrame |
+#include "TGMdiDecorFrame.h" |
+#endif |
+#ifndef ROOT_TG3DLine |
+#include "TG3DLine.h" |
+#endif |
+#ifndef ROOT_TGMdiFrame |
+#include "TGMdiFrame.h" |
+#endif |
+#ifndef ROOT_TGMdiMainFrame |
+#include "TGMdiMainFrame.h" |
+#endif |
+//#ifndef ROOT_TGuiBldHintsButton |
+//#include "TGuiBldHintsButton.h" |
+//#endif |
+#ifndef ROOT_TGMdiMenu |
+#include "TGMdiMenu.h" |
+#endif |
+#ifndef ROOT_TGListBox |
+#include "TGListBox.h" |
+#endif |
+#ifndef ROOT_TGNumberEntry |
+#include "TGNumberEntry.h" |
+#endif |
+#ifndef ROOT_TGScrollBar |
+#include "TGScrollBar.h" |
+#endif |
+//#ifndef ROOT_TGuiBldHintsEditor |
+//#include "TGuiBldHintsEditor.h" |
+//#endif |
+#ifndef ROOT_TRootBrowser |
+#include "TRootBrowser.h" |
+#endif |
+#ifndef ROOT_TGFrame |
+#include "TGFrame.h" |
+#endif |
+#ifndef ROOT_TGFileDialog |
+#include "TGFileDialog.h" |
+#endif |
+#ifndef ROOT_TGShutter |
+#include "TGShutter.h" |
+#endif |
+#ifndef ROOT_TGButtonGroup |
+#include "TGButtonGroup.h" |
+#endif |
+#ifndef ROOT_TGCanvas |
+#include "TGCanvas.h" |
+#endif |
+#ifndef ROOT_TGFSContainer |
+#include "TGFSContainer.h" |
+#endif |
+#ifndef ROOT_TGButton |
+#include "TGButton.h" |
+#endif |
+//#ifndef ROOT_TGuiBldEditor |
+//#include "TGuiBldEditor.h" |
+//#endif |
+#ifndef ROOT_TGTextEdit |
+#include "TGTextEdit.h" |
+#endif |
+#ifndef ROOT_TGFSComboBox |
+#include "TGFSComboBox.h" |
+#endif |
+#ifndef ROOT_TGLabel |
+#include "TGLabel.h" |
+#endif |
+#ifndef ROOT_TGView |
+#include "TGView.h" |
+#endif |
+//#ifndef ROOT_TRootGuiBuilder |
+//#include "TRootGuiBuilder.h" |
+//#endif |
+#ifndef ROOT_TGTab |
+#include "TGTab.h" |
+#endif |
+#ifndef ROOT_TGListView |
+#include "TGListView.h" |
+#endif |
+#ifndef ROOT_TGSplitter |
+#include "TGSplitter.h" |
+#endif |
+#ifndef ROOT_TGStatusBar |
+#include "TGStatusBar.h" |
+#endif |
+#ifndef ROOT_TGListTree |
+#include "TGListTree.h" |
+#endif |
+#ifndef ROOT_TGToolTip |
+#include "TGToolTip.h" |
+#endif |
+#ifndef ROOT_TGToolBar |
+#include "TGToolBar.h" |
+#endif |
+#ifndef ROOT_TRootEmbeddedCanvas |
+#include "TRootEmbeddedCanvas.h" |
+#endif |
+#ifndef ROOT_TCanvas |
+#include "TCanvas.h" |
+#endif |
+//#ifndef ROOT_TGuiBldDragManager |
+//#include "TGuiBldDragManager.h" |
+//#endif |
+ |
+#include "Riostream.h" |
+#include "TThread.h" |
+#include "TApplication.h" |
+#include "TROOT.h" |
+#include "TGraph.h" |
+#include "TH1F.h" |
+//#include "daq.h" |
+ |
+TGTextButton *gTextButton[10]; |
+TCanvas *fCanvas; |
+TGMainFrame *fMain; |
+TGTextEntry *gFilename; |
+TGNumberEntry *gCh; |
+ |
+TGTextEntry *gTimeDisplay; |
+TGCheckButton *gDebugButton; |
+ |
+ |
+ |
+ TGNumberEntry *gMaxEve; |
+TGNumberEntry *gNeve; |
+TGNumberEntry *gMask; |
+TGNumberEntry *gRange; |
+TGNumberEntry *gSoftwareTrigger; |
+TGNumberEntry *gTriggerChannel; |
+TGNumberEntry *gSamplingFrequency; |
+TGNumberEntry *gTriggerDelay; |
+ |
+ |
+ |
+ |
+ |
+const char gParNames[30][30]={"Events:","EventNo:","Channel Mask:","Range:", "SwTrg", "TriggerChannel:","Sampling Freq.:","TRG Delay:" }; |
+ |
+TGNumberFormat::EStyle gParStyle[10] = { |
+TGNumberFormat::kNESInteger , |
+TGNumberFormat::kNESInteger, |
+TGNumberFormat::kNESInteger , |
+TGNumberFormat::kNESReal, |
+TGNumberFormat::kNESInteger, |
+TGNumberFormat::kNESInteger, |
+TGNumberFormat::kNESInteger, |
+TGNumberFormat::kNESReal |
+}; |
+TGNumberEntry *gParameters[10]; |
+ |
+ |
+ |
+TRootEmbeddedCanvas *gCanvas; |
+#define MAXCH 32 |
+TH1F* gHisto[MAXCH]; |
+//daq * gDaq; |
+#define WINDOW_NAME "Praktikum IV MAPMT PET" |
+//---------------------------------------------------- |
+int UIRDimming(int state){ |
+ switch (state) { |
+ case 0: |
+ gTextButton[0]->SetEnabled(0); |
+ gTextButton[1]->SetEnabled(1); |
+ gTextButton[2]->SetEnabled(0); |
+ |
+ break; |
+ |
+ case 1: |
+ gTextButton[0]->SetEnabled(0); |
+ gTextButton[1]->SetEnabled(0); |
+ gTextButton[2]->SetEnabled(1); |
+ |
+ break; |
+ |
+ case 2: |
+ gTextButton[0]->SetEnabled(1); |
+ gTextButton[1]->SetEnabled(1); |
+ gTextButton[2]->SetEnabled(0); |
+ break; |
+ |
+ default: |
+ break; |
+ } |
+ return 0; |
+} |
+ |
+int fDebug; |
+void GetDebug(){ |
+ if ( gDebugButton->IsOn() ) fDebug=1; |
+ else fDebug=0; |
+} |
+ |
+int GetTime(char *x){ |
+ time_t rawtime; |
+ struct tm * timeinfo; |
+ time ( &rawtime ); |
+ timeinfo = localtime ( &rawtime ); |
+ sprintf(x,"%s",asctime (timeinfo)); |
+ int len=strlen(x); |
+ if (len) x[len-1]=0; |
+ return 0; |
+} |
+void MyTimer(){ |
+ char cmd[100]; |
+ GetTime(cmd); |
+ if (gTimeDisplay) gTimeDisplay->SetText(cmd); |
+ /* Canvas ni thread safe |
+ if (gCanvas){ |
+ gCanvas->GetCanvas()->Modified(); |
+ gCanvas->GetCanvas()->Update(); |
+ } |
+ */ |
+} |
+ |
+//---------------------------------------------------- |
+// thread function |
+int gStop=0; |
+#define BSIZE 10000 |
+unsigned int gBuf[BSIZE]; |
+void *MyThread(void *ptr) |
+{ |
+ TThread::Printf("Start of MyThread %x \n" ,(int *)ptr); |
+ |
+ // odpremo datoteko za pisanje |
+ char fname[128]; |
+ sprintf(fname,"%s.dat",gFilename->GetText()); |
+ FILE *fp=fopen(fname,"w"); |
+ int neve = (int) gMaxEve->GetNumber(); |
+ int hdr[4]={1}; |
+ |
+ //if (gDaq) gDaq->fStop=0; |
+ // zajem zeljenega kolicine podatkov |
+ for (int n=0;n<neve;n++){ |
+ int nb=0; |
+ /* |
+ if (!gDaq) break; |
+ nb = gDaq->event(gBuf,BSIZE); |
+ if (gDaq->fStop) break; |
+ */ |
+ if (nb<0){ |
+ n--; |
+ continue; |
+ } |
+ |
+ // zapis v datoteko |
+ hdr[1]=nb+4*sizeof(int); |
+ hdr[2]=time(NULL); |
+ hdr[3]=n; |
+ |
+ fwrite(hdr, sizeof(int),4 , fp); |
+ fwrite(gBuf, sizeof(int),nb, fp); |
+ // napolni histograme |
+ //***************** |
+ unsigned int *data= gBuf; |
+ int evsize=0; |
+ int events=0; |
+ int ib=1,count=0; |
+ events = data[0]; |
+ evsize = data[1]&0xffff; |
+ if (evsize<2){ |
+ n--; |
+ continue; |
+ } |
+ const unsigned int END_MARKER=0xFAF5; |
+ if (fDebug) printf("nb=%d Event:%d events=%d EvSize:%d\n",nb, n, events, evsize); |
+ for (int i=0;i<evsize;i++) { |
+ //if (fDebug) printf("%d\t%08x\n", ib, data[ib]); |
+ |
+ if (data[ib]== END_MARKER) break; |
+ if (ib%2==0) { |
+ unsigned short word1 =data[ib ]&0xFFFF; |
+ unsigned short word2 =data[ib+1]&0xFFFF; |
+ unsigned short tdc = word1; |
+ unsigned short ch = (word2 >> 1 ) &0x1F; |
+ unsigned short edge = word2 & 0x1; |
+ unsigned short q = (word2 >> 8) &0x1; |
+ unsigned short x = (word2 >> 9) &0x1; |
+ TThread::Lock(); |
+ if (edge && ch < MAXCH) gHisto[ch]->Fill(tdc); |
+ TThread::UnLock(); |
+ if (fDebug) TThread::Printf("%d. [ch=%2d] edge=%d data=%d q=%d x=%d\n",count,ch,edge,tdc, q, x); |
+ |
+ count++; |
+ } |
+ ib++; |
+ } |
+ if (data[evsize+1]!=END_MARKER) printf("Error! END_MARKER not found\n"); |
+//***************** |
+ |
+ |
+ |
+ |
+ |
+ gNeve->SetNumber(n); |
+ } |
+ fclose(fp); |
+ UIRDimming(2); |
+ TThread::Printf("End of MyThread neve=%d\n",neve); |
+ return 0; |
+} |
+ |
+ |
+int save2ascii(){ |
+ if (!gHisto[0]) return 0; |
+ char fname[128]; |
+ sprintf(fname,"%s.txt",gFilename->GetText()); |
+ FILE *fp= fopen(fname, "w"); |
+ fprintf(fp, "%s\n",WINDOW_NAME); |
+ char cmd[128]; |
+ GetTime(cmd); |
+ fprintf(fp, "Shranjeno: %s\n\n", cmd ); |
+ fprintf(fp, "Kanal hid=") ; |
+ for (int j=0;j<MAXCH;j++) fprintf(fp, "%d\t",j); |
+ fprintf(fp, "\n-------------------------------------------------\n"); |
+ for (int i=0;i<gHisto[0]->GetNbinsX();i++){ |
+ fprintf(fp, "%d\t",i); |
+ for (int j=0;j<MAXCH;j++) fprintf(fp, "%d\t",(int) gHisto[j]->GetBinContent(i+1)); |
+ fprintf(fp, "\n"); |
+ } |
+ fclose(fp); |
+ printf("Rezultati meritev so zapisani v datoteki %s\n",fname); |
+ return 0; |
+ } |
+ |
+void MyEventHandler(int i){ |
+ static TTimer * tmr = new TTimer(1000, kFALSE); |
+ UIRDimming(i); |
+ TThread *fThread; |
+ switch (i) { |
+ case 0: // Init |
+ //gDaq->init(); |
+ break; |
+ case 1: // Start |
+ fThread = new TThread(MyThread,(void*)0); |
+ fThread->Run(); |
+ tmr->SetCommand("MyTimer()"); |
+ tmr->TurnOn(); |
+ tmr->Start(1000, kFALSE); // 1 second single-shot |
+ break; |
+ case 2: // Stop |
+ //gDaq->fStop=1; |
+ tmr->Stop(); |
+ tmr->TurnOff(); |
+ break; |
+ case 3: // ReDraw |
+ gCanvas->GetCanvas()->Modified(); |
+ gCanvas->GetCanvas()->Update(); |
+ break; |
+ case 4: // Clear |
+ for (int j=0;j<MAXCH;j++) if (gHisto[j]) gHisto[j]->Reset(); |
+ break; |
+ case 5: // Save |
+ save2ascii(); |
+ break; |
+ case 6: // Print |
+ gCanvas->GetCanvas()->SaveAs("zivljenjski_cas_mionov.pdf"); |
+ break; |
+ case 7: // exit |
+ gApplication->Terminate(0); |
+ break; |
+ } |
+ |
+} |
+ |
+int Redraw(long val=0){ |
+ unsigned int ch= (unsigned int)(gCh->GetNumber()); |
+ if (ch<MAXCH && gHisto[ch]) { |
+ gCanvas->GetCanvas()->cd(); |
+ gHisto[ch]->Draw(); |
+ gCanvas->GetCanvas()->Modified(); |
+ gCanvas->GetCanvas()->Update(); |
+ } else { |
+ if (gCh->GetNumber()>=MAXCH) gCh->SetNumber(MAXCH-1); |
+ if (gCh->GetNumber()< 0) gCh->SetNumber(0); |
+ } |
+ return 0; |
+} |
+//---------------------------------------------------- |
+ |
+int gui(){ |
+ |
+ for (int i=0;i<MAXCH;i++){ |
+ char hname[50]; |
+ sprintf(hname,"TDC Ch. %d;TDC;N",i); |
+ char hn[50]; |
+ sprintf(hn,"ch%d",i); |
+ gHisto[i] = new TH1F(hn,hname,128,-0.5,1024*8-0.5); |
+ } |
+ //gDaq= new daq(); |
+ fMain = new TGMainFrame(0,800,800); |
+ TGHorizontalFrame *fH=new TGHorizontalFrame(fMain,800,400); |
+ //------------------------------------------------------------ |
+ TGLayoutHints *f0= new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2); |
+ TGLayoutHints *layout2= new TGLayoutHints(kLHintsLeft | kLHintsTop,20,20,20,20); |
+ // gumbi |
+ |
+ int nbut=8; |
+ const char *names[10]={"Init","Start","Stop","Refresh","Clear","Export to ASCII", "Print" , "Exit"}; |
+ for (int i=0;i<nbut;i++){ |
+ |
+ gTextButton[i]= new TGTextButton(fH, names[i]); |
+ gTextButton[i]->SetTextJustify(36); |
+ gTextButton[i]->SetMargins(0,0,0,0); |
+ gTextButton[i]->SetWrapLength(-1); |
+ gTextButton[i]->ChangeOptions(gTextButton[i]->GetOptions() | kFixedWidth); // | kFixedSize |
+ gTextButton[i]->Resize(100,gTextButton[i]->GetDefaultHeight()); |
+ |
+ fH->AddFrame(gTextButton[i], f0); |
+ char cmd[50]; |
+ sprintf(cmd,"MyEventHandler(=%d)",i); |
+ TQObject::Connect(gTextButton[i],"Clicked()",0,0,cmd); |
+ } |
+ |
+ gDebugButton = new TGCheckButton( fH,"Debug"); |
+ gDebugButton->Resize(50,22); |
+ TQObject::Connect(gDebugButton,"Clicked()", 0, 0 , "GetDebug()"); |
+ gDebugButton->SetState(kButtonDown); |
+ fH->AddFrame(gDebugButton, f0); |
+ |
+ fMain->AddFrame(fH , f0); |
+ |
+ TGHorizontalFrame *fH1=new TGHorizontalFrame(fMain,800,400); |
+ //--------------------------------------------------------- |
+ // ura |
+ TGLabel *lab1; |
+ fH=new TGHorizontalFrame(fH1,800,200); |
+ lab1 = new TGLabel( fH ,"Ura:"); |
+ fH->AddFrame(lab1, f0); |
+ gTimeDisplay = new TGTextEntry( fH,""); |
+ gTimeDisplay->Resize(200,22); |
+ fH->AddFrame(gTimeDisplay, f0); |
+ fH1->AddFrame(fH , f0); |
+ //--------------------------------------------------------- |
+ // inputi |
+ fH=new TGHorizontalFrame(fH1,800,200); |
+ lab1 = new TGLabel( fH ,"Filename:"); |
+ fH->AddFrame(lab1, f0); |
+ gFilename = new TGTextEntry( fH,"tmp"); |
+ gFilename->Resize(200,22); |
+ fH->AddFrame(gFilename, f0); |
+ fH1->AddFrame(fH , f0); |
+ //--------------------------------------------------------- |
+ fH=new TGHorizontalFrame(fH1,800,200); |
+ lab1 = new TGLabel( fH ,"Events:"); |
+ fH->AddFrame(lab1, f0); |
+ gMaxEve = new TGNumberEntry( fH,10000); |
+ gMaxEve->Resize(100,22); |
+ fH->AddFrame(gMaxEve, f0); |
+ fH1->AddFrame(fH , f0); |
+ //--------------------------------------------------------- |
+ fH=new TGHorizontalFrame(fH1,800,200); |
+ lab1 = new TGLabel( fH ,"Event no:"); |
+ fH->AddFrame(lab1, f0); |
+ gNeve = new TGNumberEntry( fH,0); |
+ gNeve->Resize(100,22); |
+ fH->AddFrame(gNeve, f0); |
+ fH1->AddFrame(fH , f0); |
+ //--------------------------------------------------------- |
+ fMain->AddFrame(fH1 , f0); |
+ TGVerticalFrame *fV=new TGVerticalFrame(fMain,800,200); |
+ nbut = 8; |
+ for (int i=0;i<nbut;i++){ |
+ fH=new TGHorizontalFrame(fV,800,200); |
+ lab1 = new TGLabel( fH ,gParNames[i]); |
+ lab1->Resize(100,22); |
+ fH->AddFrame(lab1, f0); |
+ gParameters[i] = new TGNumberEntry( fH,0,5,i, gParStyle[i] ); |
+ gParameters[i]->Resize(100,22); |
+ fH->AddFrame(gParameters[i] , f0); |
+ fV->AddFrame(fH , f0); |
+ } |
+ fMain->AddFrame(fV , f0); |
+ //--------------------------------------------------------- |
+ // canvas |
+ fH=new TGHorizontalFrame(fMain,800,200); |
+ gCanvas = new TRootEmbeddedCanvas ("gCanvas",fH,800,400); |
+ fH->AddFrame(gCanvas, f0); |
+ fMain->AddFrame(fH , f0); |
+ //------------------------------------------------------------ |
+ fH=new TGHorizontalFrame(fMain,800,200); |
+ lab1 = new TGLabel( fH ,"Ch. Number(0..3):"); |
+ fH->AddFrame(lab1, f0); |
+ gCh = new TGNumberEntry( fH,0); |
+ fH->AddFrame(gCh, f0); |
+ TQObject::Connect(gCh,"ValueSet(Long_t)",0,0,"Redraw(Long_t )"); |
+ |
+ fMain->AddFrame(fH , f0); |
+ //------------------------------------------------------------ |
+ fMain->SetWindowName(WINDOW_NAME); |
+ fMain->MapSubwindows(); |
+ fMain->Resize(fMain->GetDefaultSize()); |
+ fMain->MapWindow(); |
+ Redraw(); |
+ GetDebug(); |
+ return 0; |
+} |
Index: instr/drs/libusb-1.0/libusb.h |
=================================================================== |
--- instr/drs/libusb-1.0/libusb.h (nonexistent) |
+++ instr/drs/libusb-1.0/libusb.h (revision 197) |
@@ -0,0 +1,1443 @@ |
+/* |
+ * Public libusb header file |
+ * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org> |
+ * Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com> |
+ * |
+ * This library is free software; you can redistribute it and/or |
+ * modify it under the terms of the GNU Lesser General Public |
+ * License as published by the Free Software Foundation; either |
+ * version 2.1 of the License, or (at your option) any later version. |
+ * |
+ * This library is distributed in the hope that it will be useful, |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
+ * Lesser General Public License for more details. |
+ * |
+ * You should have received a copy of the GNU Lesser General Public |
+ * License along with this library; if not, write to the Free Software |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
+ */ |
+ |
+#ifndef LIBUSB_H |
+#define LIBUSB_H |
+ |
+#ifdef _MSC_VER |
+/* on MS environments, the inline keyword is available in C++ only */ |
+#define inline __inline |
+/* ssize_t is also not available (copy/paste from MinGW) */ |
+#ifndef _SSIZE_T_DEFINED |
+#define _SSIZE_T_DEFINED |
+#undef ssize_t |
+#ifdef _WIN64 |
+ typedef __int64 ssize_t; |
+#else |
+ typedef int ssize_t; |
+#endif /* _WIN64 */ |
+#endif /* _SSIZE_T_DEFINED */ |
+#endif /* _MSC_VER */ |
+ |
+/* stdint.h is also not usually available on MS */ |
+#if defined(_MSC_VER) && (_MSC_VER < 1600) && (!defined(_STDINT)) && (!defined(_STDINT_H)) |
+typedef unsigned __int8 uint8_t; |
+typedef unsigned __int16 uint16_t; |
+typedef unsigned __int32 uint32_t; |
+#else |
+#include <stdint.h> |
+#endif |
+ |
+#include <sys/types.h> |
+#include <time.h> |
+#include <limits.h> |
+ |
+#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__) |
+#include <sys/time.h> |
+#endif |
+ |
+/* 'interface' might be defined as a macro on Windows, so we need to |
+ * undefine it so as not to break the current libusb API, because |
+ * libusb_config_descriptor has an 'interface' member |
+ * As this can be problematic if you include windows.h after libusb.h |
+ * in your sources, we force windows.h to be included first. */ |
+#if defined(_WIN32) || defined(__CYGWIN__) |
+#include <windows.h> |
+#if defined(interface) |
+#undef interface |
+#endif |
+#endif |
+ |
+/** \def LIBUSB_CALL |
+ * \ingroup misc |
+ * libusb's Windows calling convention. |
+ * |
+ * Under Windows, the selection of available compilers and configurations |
+ * means that, unlike other platforms, there is not <em>one true calling |
+ * convention</em> (calling convention: the manner in which parameters are |
+ * passed to funcions in the generated assembly code). |
+ * |
+ * Matching the Windows API itself, libusb uses the WINAPI convention (which |
+ * translates to the <tt>stdcall</tt> convention) and guarantees that the |
+ * library is compiled in this way. The public header file also includes |
+ * appropriate annotations so that your own software will use the right |
+ * convention, even if another convention is being used by default within |
+ * your codebase. |
+ * |
+ * The one consideration that you must apply in your software is to mark |
+ * all functions which you use as libusb callbacks with this LIBUSB_CALL |
+ * annotation, so that they too get compiled for the correct calling |
+ * convention. |
+ * |
+ * On non-Windows operating systems, this macro is defined as nothing. This |
+ * means that you can apply it to your code without worrying about |
+ * cross-platform compatibility. |
+ */ |
+/* LIBUSB_CALL must be defined on both definition and declaration of libusb |
+ * functions. You'd think that declaration would be enough, but cygwin will |
+ * complain about conflicting types unless both are marked this way. |
+ * The placement of this macro is important too; it must appear after the |
+ * return type, before the function name. See internal documentation for |
+ * API_EXPORTED. |
+ */ |
+#if defined(_WIN32) || defined(__CYGWIN__) |
+#define LIBUSB_CALL WINAPI |
+#else |
+#define LIBUSB_CALL |
+#endif |
+ |
+#ifdef __cplusplus |
+extern "C" { |
+#endif |
+ |
+/** \def libusb_cpu_to_le16 |
+ * \ingroup misc |
+ * Convert a 16-bit value from host-endian to little-endian format. On |
+ * little endian systems, this function does nothing. On big endian systems, |
+ * the bytes are swapped. |
+ * \param x the host-endian value to convert |
+ * \returns the value in little-endian byte order |
+ */ |
+static inline uint16_t libusb_cpu_to_le16(const uint16_t x) |
+{ |
+ union { |
+ uint8_t b8[2]; |
+ uint16_t b16; |
+ } _tmp; |
+ _tmp.b8[1] = x >> 8; |
+ _tmp.b8[0] = x & 0xff; |
+ return _tmp.b16; |
+} |
+ |
+/** \def libusb_le16_to_cpu |
+ * \ingroup misc |
+ * Convert a 16-bit value from little-endian to host-endian format. On |
+ * little endian systems, this function does nothing. On big endian systems, |
+ * the bytes are swapped. |
+ * \param x the little-endian value to convert |
+ * \returns the value in host-endian byte order |
+ */ |
+#define libusb_le16_to_cpu libusb_cpu_to_le16 |
+ |
+/* standard USB stuff */ |
+ |
+/** \ingroup desc |
+ * Device and/or Interface Class codes */ |
+enum libusb_class_code { |
+ /** In the context of a \ref libusb_device_descriptor "device descriptor", |
+ * this bDeviceClass value indicates that each interface specifies its |
+ * own class information and all interfaces operate independently. |
+ */ |
+ LIBUSB_CLASS_PER_INTERFACE = 0, |
+ |
+ /** Audio class */ |
+ LIBUSB_CLASS_AUDIO = 1, |
+ |
+ /** Communications class */ |
+ LIBUSB_CLASS_COMM = 2, |
+ |
+ /** Human Interface Device class */ |
+ LIBUSB_CLASS_HID = 3, |
+ |
+ /** Physical */ |
+ LIBUSB_CLASS_PHYSICAL = 5, |
+ |
+ /** Printer class */ |
+ LIBUSB_CLASS_PRINTER = 7, |
+ |
+ /** Image class */ |
+ LIBUSB_CLASS_PTP = 6, /* legacy name from libusb-0.1 usb.h */ |
+ LIBUSB_CLASS_IMAGE = 6, |
+ |
+ /** Mass storage class */ |
+ LIBUSB_CLASS_MASS_STORAGE = 8, |
+ |
+ /** Hub class */ |
+ LIBUSB_CLASS_HUB = 9, |
+ |
+ /** Data class */ |
+ LIBUSB_CLASS_DATA = 10, |
+ |
+ /** Smart Card */ |
+ LIBUSB_CLASS_SMART_CARD = 0x0b, |
+ |
+ /** Content Security */ |
+ LIBUSB_CLASS_CONTENT_SECURITY = 0x0d, |
+ |
+ /** Video */ |
+ LIBUSB_CLASS_VIDEO = 0x0e, |
+ |
+ /** Personal Healthcare */ |
+ LIBUSB_CLASS_PERSONAL_HEALTHCARE = 0x0f, |
+ |
+ /** Diagnostic Device */ |
+ LIBUSB_CLASS_DIAGNOSTIC_DEVICE = 0xdc, |
+ |
+ /** Wireless class */ |
+ LIBUSB_CLASS_WIRELESS = 0xe0, |
+ |
+ /** Application class */ |
+ LIBUSB_CLASS_APPLICATION = 0xfe, |
+ |
+ /** Class is vendor-specific */ |
+ LIBUSB_CLASS_VENDOR_SPEC = 0xff |
+}; |
+ |
+/** \ingroup desc |
+ * Descriptor types as defined by the USB specification. */ |
+enum libusb_descriptor_type { |
+ /** Device descriptor. See libusb_device_descriptor. */ |
+ LIBUSB_DT_DEVICE = 0x01, |
+ |
+ /** Configuration descriptor. See libusb_config_descriptor. */ |
+ LIBUSB_DT_CONFIG = 0x02, |
+ |
+ /** String descriptor */ |
+ LIBUSB_DT_STRING = 0x03, |
+ |
+ /** Interface descriptor. See libusb_interface_descriptor. */ |
+ LIBUSB_DT_INTERFACE = 0x04, |
+ |
+ /** Endpoint descriptor. See libusb_endpoint_descriptor. */ |
+ LIBUSB_DT_ENDPOINT = 0x05, |
+ |
+ /** HID descriptor */ |
+ LIBUSB_DT_HID = 0x21, |
+ |
+ /** HID report descriptor */ |
+ LIBUSB_DT_REPORT = 0x22, |
+ |
+ /** Physical descriptor */ |
+ LIBUSB_DT_PHYSICAL = 0x23, |
+ |
+ /** Hub descriptor */ |
+ LIBUSB_DT_HUB = 0x29, |
+}; |
+ |
+/* Descriptor sizes per descriptor type */ |
+#define LIBUSB_DT_DEVICE_SIZE 18 |
+#define LIBUSB_DT_CONFIG_SIZE 9 |
+#define LIBUSB_DT_INTERFACE_SIZE 9 |
+#define LIBUSB_DT_ENDPOINT_SIZE 7 |
+#define LIBUSB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ |
+#define LIBUSB_DT_HUB_NONVAR_SIZE 7 |
+ |
+#define LIBUSB_ENDPOINT_ADDRESS_MASK 0x0f /* in bEndpointAddress */ |
+#define LIBUSB_ENDPOINT_DIR_MASK 0x80 |
+ |
+/** \ingroup desc |
+ * Endpoint direction. Values for bit 7 of the |
+ * \ref libusb_endpoint_descriptor::bEndpointAddress "endpoint address" scheme. |
+ */ |
+enum libusb_endpoint_direction { |
+ /** In: device-to-host */ |
+ LIBUSB_ENDPOINT_IN = 0x80, |
+ |
+ /** Out: host-to-device */ |
+ LIBUSB_ENDPOINT_OUT = 0x00 |
+}; |
+ |
+#define LIBUSB_TRANSFER_TYPE_MASK 0x03 /* in bmAttributes */ |
+ |
+/** \ingroup desc |
+ * Endpoint transfer type. Values for bits 0:1 of the |
+ * \ref libusb_endpoint_descriptor::bmAttributes "endpoint attributes" field. |
+ */ |
+enum libusb_transfer_type { |
+ /** Control endpoint */ |
+ LIBUSB_TRANSFER_TYPE_CONTROL = 0, |
+ |
+ /** Isochronous endpoint */ |
+ LIBUSB_TRANSFER_TYPE_ISOCHRONOUS = 1, |
+ |
+ /** Bulk endpoint */ |
+ LIBUSB_TRANSFER_TYPE_BULK = 2, |
+ |
+ /** Interrupt endpoint */ |
+ LIBUSB_TRANSFER_TYPE_INTERRUPT = 3 |
+}; |
+ |
+/** \ingroup misc |
+ * Standard requests, as defined in table 9-3 of the USB2 specifications */ |
+enum libusb_standard_request { |
+ /** Request status of the specific recipient */ |
+ LIBUSB_REQUEST_GET_STATUS = 0x00, |
+ |
+ /** Clear or disable a specific feature */ |
+ LIBUSB_REQUEST_CLEAR_FEATURE = 0x01, |
+ |
+ /* 0x02 is reserved */ |
+ |
+ /** Set or enable a specific feature */ |
+ LIBUSB_REQUEST_SET_FEATURE = 0x03, |
+ |
+ /* 0x04 is reserved */ |
+ |
+ /** Set device address for all future accesses */ |
+ LIBUSB_REQUEST_SET_ADDRESS = 0x05, |
+ |
+ /** Get the specified descriptor */ |
+ LIBUSB_REQUEST_GET_DESCRIPTOR = 0x06, |
+ |
+ /** Used to update existing descriptors or add new descriptors */ |
+ LIBUSB_REQUEST_SET_DESCRIPTOR = 0x07, |
+ |
+ /** Get the current device configuration value */ |
+ LIBUSB_REQUEST_GET_CONFIGURATION = 0x08, |
+ |
+ /** Set device configuration */ |
+ LIBUSB_REQUEST_SET_CONFIGURATION = 0x09, |
+ |
+ /** Return the selected alternate setting for the specified interface */ |
+ LIBUSB_REQUEST_GET_INTERFACE = 0x0A, |
+ |
+ /** Select an alternate interface for the specified interface */ |
+ LIBUSB_REQUEST_SET_INTERFACE = 0x0B, |
+ |
+ /** Set then report an endpoint's synchronization frame */ |
+ LIBUSB_REQUEST_SYNCH_FRAME = 0x0C, |
+}; |
+ |
+/** \ingroup misc |
+ * Request type bits of the |
+ * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control |
+ * transfers. */ |
+enum libusb_request_type { |
+ /** Standard */ |
+ LIBUSB_REQUEST_TYPE_STANDARD = (0x00 << 5), |
+ |
+ /** Class */ |
+ LIBUSB_REQUEST_TYPE_CLASS = (0x01 << 5), |
+ |
+ /** Vendor */ |
+ LIBUSB_REQUEST_TYPE_VENDOR = (0x02 << 5), |
+ |
+ /** Reserved */ |
+ LIBUSB_REQUEST_TYPE_RESERVED = (0x03 << 5) |
+}; |
+ |
+/** \ingroup misc |
+ * Recipient bits of the |
+ * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control |
+ * transfers. Values 4 through 31 are reserved. */ |
+enum libusb_request_recipient { |
+ /** Device */ |
+ LIBUSB_RECIPIENT_DEVICE = 0x00, |
+ |
+ /** Interface */ |
+ LIBUSB_RECIPIENT_INTERFACE = 0x01, |
+ |
+ /** Endpoint */ |
+ LIBUSB_RECIPIENT_ENDPOINT = 0x02, |
+ |
+ /** Other */ |
+ LIBUSB_RECIPIENT_OTHER = 0x03, |
+}; |
+ |
+#define LIBUSB_ISO_SYNC_TYPE_MASK 0x0C |
+ |
+/** \ingroup desc |
+ * Synchronization type for isochronous endpoints. Values for bits 2:3 of the |
+ * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in |
+ * libusb_endpoint_descriptor. |
+ */ |
+enum libusb_iso_sync_type { |
+ /** No synchronization */ |
+ LIBUSB_ISO_SYNC_TYPE_NONE = 0, |
+ |
+ /** Asynchronous */ |
+ LIBUSB_ISO_SYNC_TYPE_ASYNC = 1, |
+ |
+ /** Adaptive */ |
+ LIBUSB_ISO_SYNC_TYPE_ADAPTIVE = 2, |
+ |
+ /** Synchronous */ |
+ LIBUSB_ISO_SYNC_TYPE_SYNC = 3 |
+}; |
+ |
+#define LIBUSB_ISO_USAGE_TYPE_MASK 0x30 |
+ |
+/** \ingroup desc |
+ * Usage type for isochronous endpoints. Values for bits 4:5 of the |
+ * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in |
+ * libusb_endpoint_descriptor. |
+ */ |
+enum libusb_iso_usage_type { |
+ /** Data endpoint */ |
+ LIBUSB_ISO_USAGE_TYPE_DATA = 0, |
+ |
+ /** Feedback endpoint */ |
+ LIBUSB_ISO_USAGE_TYPE_FEEDBACK = 1, |
+ |
+ /** Implicit feedback Data endpoint */ |
+ LIBUSB_ISO_USAGE_TYPE_IMPLICIT = 2, |
+}; |
+ |
+/** \ingroup desc |
+ * A structure representing the standard USB device descriptor. This |
+ * descriptor is documented in section 9.6.1 of the USB 2.0 specification. |
+ * All multiple-byte fields are represented in host-endian format. |
+ */ |
+struct libusb_device_descriptor { |
+ /** Size of this descriptor (in bytes) */ |
+ uint8_t bLength; |
+ |
+ /** Descriptor type. Will have value |
+ * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE LIBUSB_DT_DEVICE in this |
+ * context. */ |
+ uint8_t bDescriptorType; |
+ |
+ /** USB specification release number in binary-coded decimal. A value of |
+ * 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1, etc. */ |
+ uint16_t bcdUSB; |
+ |
+ /** USB-IF class code for the device. See \ref libusb_class_code. */ |
+ uint8_t bDeviceClass; |
+ |
+ /** USB-IF subclass code for the device, qualified by the bDeviceClass |
+ * value */ |
+ uint8_t bDeviceSubClass; |
+ |
+ /** USB-IF protocol code for the device, qualified by the bDeviceClass and |
+ * bDeviceSubClass values */ |
+ uint8_t bDeviceProtocol; |
+ |
+ /** Maximum packet size for endpoint 0 */ |
+ uint8_t bMaxPacketSize0; |
+ |
+ /** USB-IF vendor ID */ |
+ uint16_t idVendor; |
+ |
+ /** USB-IF product ID */ |
+ uint16_t idProduct; |
+ |
+ /** Device release number in binary-coded decimal */ |
+ uint16_t bcdDevice; |
+ |
+ /** Index of string descriptor describing manufacturer */ |
+ uint8_t iManufacturer; |
+ |
+ /** Index of string descriptor describing product */ |
+ uint8_t iProduct; |
+ |
+ /** Index of string descriptor containing device serial number */ |
+ uint8_t iSerialNumber; |
+ |
+ /** Number of possible configurations */ |
+ uint8_t bNumConfigurations; |
+}; |
+ |
+/** \ingroup desc |
+ * A structure representing the standard USB endpoint descriptor. This |
+ * descriptor is documented in section 9.6.3 of the USB 2.0 specification. |
+ * All multiple-byte fields are represented in host-endian format. |
+ */ |
+struct libusb_endpoint_descriptor { |
+ /** Size of this descriptor (in bytes) */ |
+ uint8_t bLength; |
+ |
+ /** Descriptor type. Will have value |
+ * \ref libusb_descriptor_type::LIBUSB_DT_ENDPOINT LIBUSB_DT_ENDPOINT in |
+ * this context. */ |
+ uint8_t bDescriptorType; |
+ |
+ /** The address of the endpoint described by this descriptor. Bits 0:3 are |
+ * the endpoint number. Bits 4:6 are reserved. Bit 7 indicates direction, |
+ * see \ref libusb_endpoint_direction. |
+ */ |
+ uint8_t bEndpointAddress; |
+ |
+ /** Attributes which apply to the endpoint when it is configured using |
+ * the bConfigurationValue. Bits 0:1 determine the transfer type and |
+ * correspond to \ref libusb_transfer_type. Bits 2:3 are only used for |
+ * isochronous endpoints and correspond to \ref libusb_iso_sync_type. |
+ * Bits 4:5 are also only used for isochronous endpoints and correspond to |
+ * \ref libusb_iso_usage_type. Bits 6:7 are reserved. |
+ */ |
+ uint8_t bmAttributes; |
+ |
+ /** Maximum packet size this endpoint is capable of sending/receiving. */ |
+ uint16_t wMaxPacketSize; |
+ |
+ /** Interval for polling endpoint for data transfers. */ |
+ uint8_t bInterval; |
+ |
+ /** For audio devices only: the rate at which synchronization feedback |
+ * is provided. */ |
+ uint8_t bRefresh; |
+ |
+ /** For audio devices only: the address if the synch endpoint */ |
+ uint8_t bSynchAddress; |
+ |
+ /** Extra descriptors. If libusb encounters unknown endpoint descriptors, |
+ * it will store them here, should you wish to parse them. */ |
+ const unsigned char *extra; |
+ |
+ /** Length of the extra descriptors, in bytes. */ |
+ int extra_length; |
+}; |
+ |
+/** \ingroup desc |
+ * A structure representing the standard USB interface descriptor. This |
+ * descriptor is documented in section 9.6.5 of the USB 2.0 specification. |
+ * All multiple-byte fields are represented in host-endian format. |
+ */ |
+struct libusb_interface_descriptor { |
+ /** Size of this descriptor (in bytes) */ |
+ uint8_t bLength; |
+ |
+ /** Descriptor type. Will have value |
+ * \ref libusb_descriptor_type::LIBUSB_DT_INTERFACE LIBUSB_DT_INTERFACE |
+ * in this context. */ |
+ uint8_t bDescriptorType; |
+ |
+ /** Number of this interface */ |
+ uint8_t bInterfaceNumber; |
+ |
+ /** Value used to select this alternate setting for this interface */ |
+ uint8_t bAlternateSetting; |
+ |
+ /** Number of endpoints used by this interface (excluding the control |
+ * endpoint). */ |
+ uint8_t bNumEndpoints; |
+ |
+ /** USB-IF class code for this interface. See \ref libusb_class_code. */ |
+ uint8_t bInterfaceClass; |
+ |
+ /** USB-IF subclass code for this interface, qualified by the |
+ * bInterfaceClass value */ |
+ uint8_t bInterfaceSubClass; |
+ |
+ /** USB-IF protocol code for this interface, qualified by the |
+ * bInterfaceClass and bInterfaceSubClass values */ |
+ uint8_t bInterfaceProtocol; |
+ |
+ /** Index of string descriptor describing this interface */ |
+ uint8_t iInterface; |
+ |
+ /** Array of endpoint descriptors. This length of this array is determined |
+ * by the bNumEndpoints field. */ |
+ const struct libusb_endpoint_descriptor *endpoint; |
+ |
+ /** Extra descriptors. If libusb encounters unknown interface descriptors, |
+ * it will store them here, should you wish to parse them. */ |
+ const unsigned char *extra; |
+ |
+ /** Length of the extra descriptors, in bytes. */ |
+ int extra_length; |
+}; |
+ |
+/** \ingroup desc |
+ * A collection of alternate settings for a particular USB interface. |
+ */ |
+struct libusb_interface { |
+ /** Array of interface descriptors. The length of this array is determined |
+ * by the num_altsetting field. */ |
+ const struct libusb_interface_descriptor *altsetting; |
+ |
+ /** The number of alternate settings that belong to this interface */ |
+ int num_altsetting; |
+}; |
+ |
+/** \ingroup desc |
+ * A structure representing the standard USB configuration descriptor. This |
+ * descriptor is documented in section 9.6.3 of the USB 2.0 specification. |
+ * All multiple-byte fields are represented in host-endian format. |
+ */ |
+struct libusb_config_descriptor { |
+ /** Size of this descriptor (in bytes) */ |
+ uint8_t bLength; |
+ |
+ /** Descriptor type. Will have value |
+ * \ref libusb_descriptor_type::LIBUSB_DT_CONFIG LIBUSB_DT_CONFIG |
+ * in this context. */ |
+ uint8_t bDescriptorType; |
+ |
+ /** Total length of data returned for this configuration */ |
+ uint16_t wTotalLength; |
+ |
+ /** Number of interfaces supported by this configuration */ |
+ uint8_t bNumInterfaces; |
+ |
+ /** Identifier value for this configuration */ |
+ uint8_t bConfigurationValue; |
+ |
+ /** Index of string descriptor describing this configuration */ |
+ uint8_t iConfiguration; |
+ |
+ /** Configuration characteristics */ |
+ uint8_t bmAttributes; |
+ |
+ /** Maximum power consumption of the USB device from this bus in this |
+ * configuration when the device is fully opreation. Expressed in units |
+ * of 2 mA. */ |
+ uint8_t MaxPower; |
+ |
+ /** Array of interfaces supported by this configuration. The length of |
+ * this array is determined by the bNumInterfaces field. */ |
+ const struct libusb_interface *interface; |
+ |
+ /** Extra descriptors. If libusb encounters unknown configuration |
+ * descriptors, it will store them here, should you wish to parse them. */ |
+ const unsigned char *extra; |
+ |
+ /** Length of the extra descriptors, in bytes. */ |
+ int extra_length; |
+}; |
+ |
+/** \ingroup asyncio |
+ * Setup packet for control transfers. */ |
+struct libusb_control_setup { |
+ /** Request type. Bits 0:4 determine recipient, see |
+ * \ref libusb_request_recipient. Bits 5:6 determine type, see |
+ * \ref libusb_request_type. Bit 7 determines data transfer direction, see |
+ * \ref libusb_endpoint_direction. |
+ */ |
+ uint8_t bmRequestType; |
+ |
+ /** Request. If the type bits of bmRequestType are equal to |
+ * \ref libusb_request_type::LIBUSB_REQUEST_TYPE_STANDARD |
+ * "LIBUSB_REQUEST_TYPE_STANDARD" then this field refers to |
+ * \ref libusb_standard_request. For other cases, use of this field is |
+ * application-specific. */ |
+ uint8_t bRequest; |
+ |
+ /** Value. Varies according to request */ |
+ uint16_t wValue; |
+ |
+ /** Index. Varies according to request, typically used to pass an index |
+ * or offset */ |
+ uint16_t wIndex; |
+ |
+ /** Number of bytes to transfer */ |
+ uint16_t wLength; |
+}; |
+ |
+#define LIBUSB_CONTROL_SETUP_SIZE (sizeof(struct libusb_control_setup)) |
+ |
+/* libusb */ |
+ |
+struct libusb_context; |
+struct libusb_device; |
+struct libusb_device_handle; |
+ |
+/** \ingroup lib |
+ * Structure representing the libusb version. |
+ */ |
+struct libusb_version { |
+ /** Library major version. */ |
+ const uint16_t major; |
+ |
+ /** Library minor version. */ |
+ const uint16_t minor; |
+ |
+ /** Library micro version. */ |
+ const uint16_t micro; |
+ |
+ /** Library nano version. This field is only nonzero on Windows. */ |
+ const uint16_t nano; |
+ |
+ /** Library release candidate suffix string, e.g. "-rc4". */ |
+ const char *rc; |
+ |
+ /** Output of `git describe --tags` at library build time. */ |
+ const char *describe; |
+}; |
+ |
+/** \ingroup lib |
+ * Structure representing a libusb session. The concept of individual libusb |
+ * sessions allows for your program to use two libraries (or dynamically |
+ * load two modules) which both independently use libusb. This will prevent |
+ * interference between the individual libusb users - for example |
+ * libusb_set_debug() will not affect the other user of the library, and |
+ * libusb_exit() will not destroy resources that the other user is still |
+ * using. |
+ * |
+ * Sessions are created by libusb_init() and destroyed through libusb_exit(). |
+ * If your application is guaranteed to only ever include a single libusb |
+ * user (i.e. you), you do not have to worry about contexts: pass NULL in |
+ * every function call where a context is required. The default context |
+ * will be used. |
+ * |
+ * For more information, see \ref contexts. |
+ */ |
+typedef struct libusb_context libusb_context; |
+ |
+/** \ingroup dev |
+ * Structure representing a USB device detected on the system. This is an |
+ * opaque type for which you are only ever provided with a pointer, usually |
+ * originating from libusb_get_device_list(). |
+ * |
+ * Certain operations can be performed on a device, but in order to do any |
+ * I/O you will have to first obtain a device handle using libusb_open(). |
+ * |
+ * Devices are reference counted with libusb_device_ref() and |
+ * libusb_device_unref(), and are freed when the reference count reaches 0. |
+ * New devices presented by libusb_get_device_list() have a reference count of |
+ * 1, and libusb_free_device_list() can optionally decrease the reference count |
+ * on all devices in the list. libusb_open() adds another reference which is |
+ * later destroyed by libusb_close(). |
+ */ |
+typedef struct libusb_device libusb_device; |
+ |
+ |
+/** \ingroup dev |
+ * Structure representing a handle on a USB device. This is an opaque type for |
+ * which you are only ever provided with a pointer, usually originating from |
+ * libusb_open(). |
+ * |
+ * A device handle is used to perform I/O and other operations. When finished |
+ * with a device handle, you should call libusb_close(). |
+ */ |
+typedef struct libusb_device_handle libusb_device_handle; |
+ |
+/** \ingroup dev |
+ * Speed codes. Indicates the speed at which the device is operating. |
+ */ |
+enum libusb_speed { |
+ /** The OS doesn't report or know the device speed. */ |
+ LIBUSB_SPEED_UNKNOWN = 0, |
+ |
+ /** The device is operating at low speed (1.5MBit/s). */ |
+ LIBUSB_SPEED_LOW = 1, |
+ |
+ /** The device is operating at full speed (12MBit/s). */ |
+ LIBUSB_SPEED_FULL = 2, |
+ |
+ /** The device is operating at high speed (480MBit/s). */ |
+ LIBUSB_SPEED_HIGH = 3, |
+ |
+ /** The device is operating at super speed (5000MBit/s). */ |
+ LIBUSB_SPEED_SUPER = 4, |
+}; |
+ |
+/** \ingroup misc |
+ * Error codes. Most libusb functions return 0 on success or one of these |
+ * codes on failure. |
+ * You can call \ref libusb_error_name() to retrieve a string representation |
+ * of an error code. |
+ */ |
+enum libusb_error { |
+ /** Success (no error) */ |
+ LIBUSB_SUCCESS = 0, |
+ |
+ /** Input/output error */ |
+ LIBUSB_ERROR_IO = -1, |
+ |
+ /** Invalid parameter */ |
+ LIBUSB_ERROR_INVALID_PARAM = -2, |
+ |
+ /** Access denied (insufficient permissions) */ |
+ LIBUSB_ERROR_ACCESS = -3, |
+ |
+ /** No such device (it may have been disconnected) */ |
+ LIBUSB_ERROR_NO_DEVICE = -4, |
+ |
+ /** Entity not found */ |
+ LIBUSB_ERROR_NOT_FOUND = -5, |
+ |
+ /** Resource busy */ |
+ LIBUSB_ERROR_BUSY = -6, |
+ |
+ /** Operation timed out */ |
+ LIBUSB_ERROR_TIMEOUT = -7, |
+ |
+ /** Overflow */ |
+ LIBUSB_ERROR_OVERFLOW = -8, |
+ |
+ /** Pipe error */ |
+ LIBUSB_ERROR_PIPE = -9, |
+ |
+ /** System call interrupted (perhaps due to signal) */ |
+ LIBUSB_ERROR_INTERRUPTED = -10, |
+ |
+ /** Insufficient memory */ |
+ LIBUSB_ERROR_NO_MEM = -11, |
+ |
+ /** Operation not supported or unimplemented on this platform */ |
+ LIBUSB_ERROR_NOT_SUPPORTED = -12, |
+ |
+ /* NB! Remember to update libusb_error_name() |
+ when adding new error codes here. */ |
+ |
+ /** Other error */ |
+ LIBUSB_ERROR_OTHER = -99, |
+}; |
+ |
+/** \ingroup asyncio |
+ * Transfer status codes */ |
+enum libusb_transfer_status { |
+ /** Transfer completed without error. Note that this does not indicate |
+ * that the entire amount of requested data was transferred. */ |
+ LIBUSB_TRANSFER_COMPLETED, |
+ |
+ /** Transfer failed */ |
+ LIBUSB_TRANSFER_ERROR, |
+ |
+ /** Transfer timed out */ |
+ LIBUSB_TRANSFER_TIMED_OUT, |
+ |
+ /** Transfer was cancelled */ |
+ LIBUSB_TRANSFER_CANCELLED, |
+ |
+ /** For bulk/interrupt endpoints: halt condition detected (endpoint |
+ * stalled). For control endpoints: control request not supported. */ |
+ LIBUSB_TRANSFER_STALL, |
+ |
+ /** Device was disconnected */ |
+ LIBUSB_TRANSFER_NO_DEVICE, |
+ |
+ /** Device sent more data than requested */ |
+ LIBUSB_TRANSFER_OVERFLOW, |
+}; |
+ |
+/** \ingroup asyncio |
+ * libusb_transfer.flags values */ |
+enum libusb_transfer_flags { |
+ /** Report short frames as errors */ |
+ LIBUSB_TRANSFER_SHORT_NOT_OK = 1<<0, |
+ |
+ /** Automatically free() transfer buffer during libusb_free_transfer() */ |
+ LIBUSB_TRANSFER_FREE_BUFFER = 1<<1, |
+ |
+ /** Automatically call libusb_free_transfer() after callback returns. |
+ * If this flag is set, it is illegal to call libusb_free_transfer() |
+ * from your transfer callback, as this will result in a double-free |
+ * when this flag is acted upon. */ |
+ LIBUSB_TRANSFER_FREE_TRANSFER = 1<<2, |
+ |
+ /** Terminate transfers that are a multiple of the endpoint's |
+ * wMaxPacketSize with an extra zero length packet. This is useful |
+ * when a device protocol mandates that each logical request is |
+ * terminated by an incomplete packet (i.e. the logical requests are |
+ * not separated by other means). |
+ * |
+ * This flag only affects host-to-device transfers to bulk and interrupt |
+ * endpoints. In other situations, it is ignored. |
+ * |
+ * This flag only affects transfers with a length that is a multiple of |
+ * the endpoint's wMaxPacketSize. On transfers of other lengths, this |
+ * flag has no effect. Therefore, if you are working with a device that |
+ * needs a ZLP whenever the end of the logical request falls on a packet |
+ * boundary, then it is sensible to set this flag on <em>every</em> |
+ * transfer (you do not have to worry about only setting it on transfers |
+ * that end on the boundary). |
+ * |
+ * This flag is currently only supported on Linux. |
+ * On other systems, libusb_submit_transfer() will return |
+ * LIBUSB_ERROR_NOT_SUPPORTED for every transfer where this flag is set. |
+ * |
+ * Available since libusb-1.0.9. |
+ */ |
+ LIBUSB_TRANSFER_ADD_ZERO_PACKET = 1 << 3, |
+}; |
+ |
+/** \ingroup asyncio |
+ * Isochronous packet descriptor. */ |
+struct libusb_iso_packet_descriptor { |
+ /** Length of data to request in this packet */ |
+ unsigned int length; |
+ |
+ /** Amount of data that was actually transferred */ |
+ unsigned int actual_length; |
+ |
+ /** Status code for this packet */ |
+ enum libusb_transfer_status status; |
+}; |
+ |
+struct libusb_transfer; |
+ |
+/** \ingroup asyncio |
+ * Asynchronous transfer callback function type. When submitting asynchronous |
+ * transfers, you pass a pointer to a callback function of this type via the |
+ * \ref libusb_transfer::callback "callback" member of the libusb_transfer |
+ * structure. libusb will call this function later, when the transfer has |
+ * completed or failed. See \ref asyncio for more information. |
+ * \param transfer The libusb_transfer struct the callback function is being |
+ * notified about. |
+ */ |
+typedef void (LIBUSB_CALL *libusb_transfer_cb_fn)(struct libusb_transfer *transfer); |
+ |
+/** \ingroup asyncio |
+ * The generic USB transfer structure. The user populates this structure and |
+ * then submits it in order to request a transfer. After the transfer has |
+ * completed, the library populates the transfer with the results and passes |
+ * it back to the user. |
+ */ |
+struct libusb_transfer { |
+ /** Handle of the device that this transfer will be submitted to */ |
+ libusb_device_handle *dev_handle; |
+ |
+ /** A bitwise OR combination of \ref libusb_transfer_flags. */ |
+ uint8_t flags; |
+ |
+ /** Address of the endpoint where this transfer will be sent. */ |
+ unsigned char endpoint; |
+ |
+ /** Type of the endpoint from \ref libusb_transfer_type */ |
+ unsigned char type; |
+ |
+ /** Timeout for this transfer in millseconds. A value of 0 indicates no |
+ * timeout. */ |
+ unsigned int timeout; |
+ |
+ /** The status of the transfer. Read-only, and only for use within |
+ * transfer callback function. |
+ * |
+ * If this is an isochronous transfer, this field may read COMPLETED even |
+ * if there were errors in the frames. Use the |
+ * \ref libusb_iso_packet_descriptor::status "status" field in each packet |
+ * to determine if errors occurred. */ |
+ enum libusb_transfer_status status; |
+ |
+ /** Length of the data buffer */ |
+ int length; |
+ |
+ /** Actual length of data that was transferred. Read-only, and only for |
+ * use within transfer callback function. Not valid for isochronous |
+ * endpoint transfers. */ |
+ int actual_length; |
+ |
+ /** Callback function. This will be invoked when the transfer completes, |
+ * fails, or is cancelled. */ |
+ libusb_transfer_cb_fn callback; |
+ |
+ /** User context data to pass to the callback function. */ |
+ void *user_data; |
+ |
+ /** Data buffer */ |
+ unsigned char *buffer; |
+ |
+ /** Number of isochronous packets. Only used for I/O with isochronous |
+ * endpoints. */ |
+ int num_iso_packets; |
+ |
+ /** Isochronous packet descriptors, for isochronous transfers only. */ |
+ struct libusb_iso_packet_descriptor iso_packet_desc |
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) |
+ [] /* valid C99 code */ |
+#else |
+ [0] /* non-standard, but usually working code */ |
+#endif |
+ ; |
+}; |
+ |
+/** \ingroup misc |
+ * Capabilities supported by this instance of libusb. Test if the loaded |
+ * library supports a given capability by calling |
+ * \ref libusb_has_capability(). |
+ */ |
+enum libusb_capability { |
+ /** The libusb_has_capability() API is available. */ |
+ LIBUSB_CAP_HAS_CAPABILITY = 0, |
+}; |
+ |
+int LIBUSB_CALL libusb_init(libusb_context **ctx); |
+void LIBUSB_CALL libusb_exit(libusb_context *ctx); |
+void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level); |
+const struct libusb_version * LIBUSB_CALL libusb_get_version(void); |
+int LIBUSB_CALL libusb_has_capability(uint32_t capability); |
+const char * LIBUSB_CALL libusb_error_name(int errcode); |
+ |
+ssize_t LIBUSB_CALL libusb_get_device_list(libusb_context *ctx, |
+ libusb_device ***list); |
+void LIBUSB_CALL libusb_free_device_list(libusb_device **list, |
+ int unref_devices); |
+libusb_device * LIBUSB_CALL libusb_ref_device(libusb_device *dev); |
+void LIBUSB_CALL libusb_unref_device(libusb_device *dev); |
+ |
+int LIBUSB_CALL libusb_get_configuration(libusb_device_handle *dev, |
+ int *config); |
+int LIBUSB_CALL libusb_get_device_descriptor(libusb_device *dev, |
+ struct libusb_device_descriptor *desc); |
+int LIBUSB_CALL libusb_get_active_config_descriptor(libusb_device *dev, |
+ struct libusb_config_descriptor **config); |
+int LIBUSB_CALL libusb_get_config_descriptor(libusb_device *dev, |
+ uint8_t config_index, struct libusb_config_descriptor **config); |
+int LIBUSB_CALL libusb_get_config_descriptor_by_value(libusb_device *dev, |
+ uint8_t bConfigurationValue, struct libusb_config_descriptor **config); |
+void LIBUSB_CALL libusb_free_config_descriptor( |
+ struct libusb_config_descriptor *config); |
+uint8_t LIBUSB_CALL libusb_get_bus_number(libusb_device *dev); |
+uint8_t LIBUSB_CALL libusb_get_device_address(libusb_device *dev); |
+int LIBUSB_CALL libusb_get_device_speed(libusb_device *dev); |
+int LIBUSB_CALL libusb_get_max_packet_size(libusb_device *dev, |
+ unsigned char endpoint); |
+int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev, |
+ unsigned char endpoint); |
+ |
+int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **handle); |
+void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle); |
+libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle); |
+ |
+int LIBUSB_CALL libusb_set_configuration(libusb_device_handle *dev, |
+ int configuration); |
+int LIBUSB_CALL libusb_claim_interface(libusb_device_handle *dev, |
+ int interface_number); |
+int LIBUSB_CALL libusb_release_interface(libusb_device_handle *dev, |
+ int interface_number); |
+ |
+libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid( |
+ libusb_context *ctx, uint16_t vendor_id, uint16_t product_id); |
+ |
+int LIBUSB_CALL libusb_set_interface_alt_setting(libusb_device_handle *dev, |
+ int interface_number, int alternate_setting); |
+int LIBUSB_CALL libusb_clear_halt(libusb_device_handle *dev, |
+ unsigned char endpoint); |
+int LIBUSB_CALL libusb_reset_device(libusb_device_handle *dev); |
+ |
+int LIBUSB_CALL libusb_kernel_driver_active(libusb_device_handle *dev, |
+ int interface_number); |
+int LIBUSB_CALL libusb_detach_kernel_driver(libusb_device_handle *dev, |
+ int interface_number); |
+int LIBUSB_CALL libusb_attach_kernel_driver(libusb_device_handle *dev, |
+ int interface_number); |
+ |
+/* async I/O */ |
+ |
+/** \ingroup asyncio |
+ * Get the data section of a control transfer. This convenience function is here |
+ * to remind you that the data does not start until 8 bytes into the actual |
+ * buffer, as the setup packet comes first. |
+ * |
+ * Calling this function only makes sense from a transfer callback function, |
+ * or situations where you have already allocated a suitably sized buffer at |
+ * transfer->buffer. |
+ * |
+ * \param transfer a transfer |
+ * \returns pointer to the first byte of the data section |
+ */ |
+static inline unsigned char *libusb_control_transfer_get_data( |
+ struct libusb_transfer *transfer) |
+{ |
+ return transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; |
+} |
+ |
+/** \ingroup asyncio |
+ * Get the control setup packet of a control transfer. This convenience |
+ * function is here to remind you that the control setup occupies the first |
+ * 8 bytes of the transfer data buffer. |
+ * |
+ * Calling this function only makes sense from a transfer callback function, |
+ * or situations where you have already allocated a suitably sized buffer at |
+ * transfer->buffer. |
+ * |
+ * \param transfer a transfer |
+ * \returns a casted pointer to the start of the transfer data buffer |
+ */ |
+static inline struct libusb_control_setup *libusb_control_transfer_get_setup( |
+ struct libusb_transfer *transfer) |
+{ |
+ return (struct libusb_control_setup *) transfer->buffer; |
+} |
+ |
+/** \ingroup asyncio |
+ * Helper function to populate the setup packet (first 8 bytes of the data |
+ * buffer) for a control transfer. The wIndex, wValue and wLength values should |
+ * be given in host-endian byte order. |
+ * |
+ * \param buffer buffer to output the setup packet into |
+ * \param bmRequestType see the |
+ * \ref libusb_control_setup::bmRequestType "bmRequestType" field of |
+ * \ref libusb_control_setup |
+ * \param bRequest see the |
+ * \ref libusb_control_setup::bRequest "bRequest" field of |
+ * \ref libusb_control_setup |
+ * \param wValue see the |
+ * \ref libusb_control_setup::wValue "wValue" field of |
+ * \ref libusb_control_setup |
+ * \param wIndex see the |
+ * \ref libusb_control_setup::wIndex "wIndex" field of |
+ * \ref libusb_control_setup |
+ * \param wLength see the |
+ * \ref libusb_control_setup::wLength "wLength" field of |
+ * \ref libusb_control_setup |
+ */ |
+static inline void libusb_fill_control_setup(unsigned char *buffer, |
+ uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, |
+ uint16_t wLength) |
+{ |
+ struct libusb_control_setup *setup = (struct libusb_control_setup *) buffer; |
+ setup->bmRequestType = bmRequestType; |
+ setup->bRequest = bRequest; |
+ setup->wValue = libusb_cpu_to_le16(wValue); |
+ setup->wIndex = libusb_cpu_to_le16(wIndex); |
+ setup->wLength = libusb_cpu_to_le16(wLength); |
+} |
+ |
+struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(int iso_packets); |
+int LIBUSB_CALL libusb_submit_transfer(struct libusb_transfer *transfer); |
+int LIBUSB_CALL libusb_cancel_transfer(struct libusb_transfer *transfer); |
+void LIBUSB_CALL libusb_free_transfer(struct libusb_transfer *transfer); |
+ |
+/** \ingroup asyncio |
+ * Helper function to populate the required \ref libusb_transfer fields |
+ * for a control transfer. |
+ * |
+ * If you pass a transfer buffer to this function, the first 8 bytes will |
+ * be interpreted as a control setup packet, and the wLength field will be |
+ * used to automatically populate the \ref libusb_transfer::length "length" |
+ * field of the transfer. Therefore the recommended approach is: |
+ * -# Allocate a suitably sized data buffer (including space for control setup) |
+ * -# Call libusb_fill_control_setup() |
+ * -# If this is a host-to-device transfer with a data stage, put the data |
+ * in place after the setup packet |
+ * -# Call this function |
+ * -# Call libusb_submit_transfer() |
+ * |
+ * It is also legal to pass a NULL buffer to this function, in which case this |
+ * function will not attempt to populate the length field. Remember that you |
+ * must then populate the buffer and length fields later. |
+ * |
+ * \param transfer the transfer to populate |
+ * \param dev_handle handle of the device that will handle the transfer |
+ * \param buffer data buffer. If provided, this function will interpret the |
+ * first 8 bytes as a setup packet and infer the transfer length from that. |
+ * \param callback callback function to be invoked on transfer completion |
+ * \param user_data user data to pass to callback function |
+ * \param timeout timeout for the transfer in milliseconds |
+ */ |
+static inline void libusb_fill_control_transfer( |
+ struct libusb_transfer *transfer, libusb_device_handle *dev_handle, |
+ unsigned char *buffer, libusb_transfer_cb_fn callback, void *user_data, |
+ unsigned int timeout) |
+{ |
+ struct libusb_control_setup *setup = (struct libusb_control_setup *) buffer; |
+ transfer->dev_handle = dev_handle; |
+ transfer->endpoint = 0; |
+ transfer->type = LIBUSB_TRANSFER_TYPE_CONTROL; |
+ transfer->timeout = timeout; |
+ transfer->buffer = buffer; |
+ if (setup) |
+ transfer->length = LIBUSB_CONTROL_SETUP_SIZE |
+ + libusb_le16_to_cpu(setup->wLength); |
+ transfer->user_data = user_data; |
+ transfer->callback = callback; |
+} |
+ |
+/** \ingroup asyncio |
+ * Helper function to populate the required \ref libusb_transfer fields |
+ * for a bulk transfer. |
+ * |
+ * \param transfer the transfer to populate |
+ * \param dev_handle handle of the device that will handle the transfer |
+ * \param endpoint address of the endpoint where this transfer will be sent |
+ * \param buffer data buffer |
+ * \param length length of data buffer |
+ * \param callback callback function to be invoked on transfer completion |
+ * \param user_data user data to pass to callback function |
+ * \param timeout timeout for the transfer in milliseconds |
+ */ |
+static inline void libusb_fill_bulk_transfer(struct libusb_transfer *transfer, |
+ libusb_device_handle *dev_handle, unsigned char endpoint, |
+ unsigned char *buffer, int length, libusb_transfer_cb_fn callback, |
+ void *user_data, unsigned int timeout) |
+{ |
+ transfer->dev_handle = dev_handle; |
+ transfer->endpoint = endpoint; |
+ transfer->type = LIBUSB_TRANSFER_TYPE_BULK; |
+ transfer->timeout = timeout; |
+ transfer->buffer = buffer; |
+ transfer->length = length; |
+ transfer->user_data = user_data; |
+ transfer->callback = callback; |
+} |
+ |
+/** \ingroup asyncio |
+ * Helper function to populate the required \ref libusb_transfer fields |
+ * for an interrupt transfer. |
+ * |
+ * \param transfer the transfer to populate |
+ * \param dev_handle handle of the device that will handle the transfer |
+ * \param endpoint address of the endpoint where this transfer will be sent |
+ * \param buffer data buffer |
+ * \param length length of data buffer |
+ * \param callback callback function to be invoked on transfer completion |
+ * \param user_data user data to pass to callback function |
+ * \param timeout timeout for the transfer in milliseconds |
+ */ |
+static inline void libusb_fill_interrupt_transfer( |
+ struct libusb_transfer *transfer, libusb_device_handle *dev_handle, |
+ unsigned char endpoint, unsigned char *buffer, int length, |
+ libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) |
+{ |
+ transfer->dev_handle = dev_handle; |
+ transfer->endpoint = endpoint; |
+ transfer->type = LIBUSB_TRANSFER_TYPE_INTERRUPT; |
+ transfer->timeout = timeout; |
+ transfer->buffer = buffer; |
+ transfer->length = length; |
+ transfer->user_data = user_data; |
+ transfer->callback = callback; |
+} |
+ |
+/** \ingroup asyncio |
+ * Helper function to populate the required \ref libusb_transfer fields |
+ * for an isochronous transfer. |
+ * |
+ * \param transfer the transfer to populate |
+ * \param dev_handle handle of the device that will handle the transfer |
+ * \param endpoint address of the endpoint where this transfer will be sent |
+ * \param buffer data buffer |
+ * \param length length of data buffer |
+ * \param num_iso_packets the number of isochronous packets |
+ * \param callback callback function to be invoked on transfer completion |
+ * \param user_data user data to pass to callback function |
+ * \param timeout timeout for the transfer in milliseconds |
+ */ |
+static inline void libusb_fill_iso_transfer(struct libusb_transfer *transfer, |
+ libusb_device_handle *dev_handle, unsigned char endpoint, |
+ unsigned char *buffer, int length, int num_iso_packets, |
+ libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) |
+{ |
+ transfer->dev_handle = dev_handle; |
+ transfer->endpoint = endpoint; |
+ transfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS; |
+ transfer->timeout = timeout; |
+ transfer->buffer = buffer; |
+ transfer->length = length; |
+ transfer->num_iso_packets = num_iso_packets; |
+ transfer->user_data = user_data; |
+ transfer->callback = callback; |
+} |
+ |
+/** \ingroup asyncio |
+ * Convenience function to set the length of all packets in an isochronous |
+ * transfer, based on the num_iso_packets field in the transfer structure. |
+ * |
+ * \param transfer a transfer |
+ * \param length the length to set in each isochronous packet descriptor |
+ * \see libusb_get_max_packet_size() |
+ */ |
+static inline void libusb_set_iso_packet_lengths( |
+ struct libusb_transfer *transfer, unsigned int length) |
+{ |
+ int i; |
+ for (i = 0; i < transfer->num_iso_packets; i++) |
+ transfer->iso_packet_desc[i].length = length; |
+} |
+ |
+/** \ingroup asyncio |
+ * Convenience function to locate the position of an isochronous packet |
+ * within the buffer of an isochronous transfer. |
+ * |
+ * This is a thorough function which loops through all preceding packets, |
+ * accumulating their lengths to find the position of the specified packet. |
+ * Typically you will assign equal lengths to each packet in the transfer, |
+ * and hence the above method is sub-optimal. You may wish to use |
+ * libusb_get_iso_packet_buffer_simple() instead. |
+ * |
+ * \param transfer a transfer |
+ * \param packet the packet to return the address of |
+ * \returns the base address of the packet buffer inside the transfer buffer, |
+ * or NULL if the packet does not exist. |
+ * \see libusb_get_iso_packet_buffer_simple() |
+ */ |
+static inline unsigned char *libusb_get_iso_packet_buffer( |
+ struct libusb_transfer *transfer, unsigned int packet) |
+{ |
+ int i; |
+ size_t offset = 0; |
+ int _packet; |
+ |
+ /* oops..slight bug in the API. packet is an unsigned int, but we use |
+ * signed integers almost everywhere else. range-check and convert to |
+ * signed to avoid compiler warnings. FIXME for libusb-2. */ |
+ if (packet > INT_MAX) |
+ return NULL; |
+ _packet = packet; |
+ |
+ if (_packet >= transfer->num_iso_packets) |
+ return NULL; |
+ |
+ for (i = 0; i < _packet; i++) |
+ offset += transfer->iso_packet_desc[i].length; |
+ |
+ return transfer->buffer + offset; |
+} |
+ |
+/** \ingroup asyncio |
+ * Convenience function to locate the position of an isochronous packet |
+ * within the buffer of an isochronous transfer, for transfers where each |
+ * packet is of identical size. |
+ * |
+ * This function relies on the assumption that every packet within the transfer |
+ * is of identical size to the first packet. Calculating the location of |
+ * the packet buffer is then just a simple calculation: |
+ * <tt>buffer + (packet_size * packet)</tt> |
+ * |
+ * Do not use this function on transfers other than those that have identical |
+ * packet lengths for each packet. |
+ * |
+ * \param transfer a transfer |
+ * \param packet the packet to return the address of |
+ * \returns the base address of the packet buffer inside the transfer buffer, |
+ * or NULL if the packet does not exist. |
+ * \see libusb_get_iso_packet_buffer() |
+ */ |
+static inline unsigned char *libusb_get_iso_packet_buffer_simple( |
+ struct libusb_transfer *transfer, unsigned int packet) |
+{ |
+ int _packet; |
+ |
+ /* oops..slight bug in the API. packet is an unsigned int, but we use |
+ * signed integers almost everywhere else. range-check and convert to |
+ * signed to avoid compiler warnings. FIXME for libusb-2. */ |
+ if (packet > INT_MAX) |
+ return NULL; |
+ _packet = packet; |
+ |
+ if (_packet >= transfer->num_iso_packets) |
+ return NULL; |
+ |
+ return transfer->buffer + (transfer->iso_packet_desc[0].length * _packet); |
+} |
+ |
+/* sync I/O */ |
+ |
+int LIBUSB_CALL libusb_control_transfer(libusb_device_handle *dev_handle, |
+ uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, |
+ unsigned char *data, uint16_t wLength, unsigned int timeout); |
+ |
+int LIBUSB_CALL libusb_bulk_transfer(libusb_device_handle *dev_handle, |
+ unsigned char endpoint, unsigned char *data, int length, |
+ int *actual_length, unsigned int timeout); |
+ |
+int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle, |
+ unsigned char endpoint, unsigned char *data, int length, |
+ int *actual_length, unsigned int timeout); |
+ |
+/** \ingroup desc |
+ * Retrieve a descriptor from the default control pipe. |
+ * This is a convenience function which formulates the appropriate control |
+ * message to retrieve the descriptor. |
+ * |
+ * \param dev a device handle |
+ * \param desc_type the descriptor type, see \ref libusb_descriptor_type |
+ * \param desc_index the index of the descriptor to retrieve |
+ * \param data output buffer for descriptor |
+ * \param length size of data buffer |
+ * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure |
+ */ |
+static inline int libusb_get_descriptor(libusb_device_handle *dev, |
+ uint8_t desc_type, uint8_t desc_index, unsigned char *data, int length) |
+{ |
+ return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN, |
+ LIBUSB_REQUEST_GET_DESCRIPTOR, (desc_type << 8) | desc_index, 0, data, |
+ (uint16_t) length, 1000); |
+} |
+ |
+/** \ingroup desc |
+ * Retrieve a descriptor from a device. |
+ * This is a convenience function which formulates the appropriate control |
+ * message to retrieve the descriptor. The string returned is Unicode, as |
+ * detailed in the USB specifications. |
+ * |
+ * \param dev a device handle |
+ * \param desc_index the index of the descriptor to retrieve |
+ * \param langid the language ID for the string descriptor |
+ * \param data output buffer for descriptor |
+ * \param length size of data buffer |
+ * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure |
+ * \see libusb_get_string_descriptor_ascii() |
+ */ |
+static inline int libusb_get_string_descriptor(libusb_device_handle *dev, |
+ uint8_t desc_index, uint16_t langid, unsigned char *data, int length) |
+{ |
+ return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN, |
+ LIBUSB_REQUEST_GET_DESCRIPTOR, (uint16_t)((LIBUSB_DT_STRING << 8) | desc_index), |
+ langid, data, (uint16_t) length, 1000); |
+} |
+ |
+int LIBUSB_CALL libusb_get_string_descriptor_ascii(libusb_device_handle *dev, |
+ uint8_t desc_index, unsigned char *data, int length); |
+ |
+/* polling and timeouts */ |
+ |
+int LIBUSB_CALL libusb_try_lock_events(libusb_context *ctx); |
+void LIBUSB_CALL libusb_lock_events(libusb_context *ctx); |
+void LIBUSB_CALL libusb_unlock_events(libusb_context *ctx); |
+int LIBUSB_CALL libusb_event_handling_ok(libusb_context *ctx); |
+int LIBUSB_CALL libusb_event_handler_active(libusb_context *ctx); |
+void LIBUSB_CALL libusb_lock_event_waiters(libusb_context *ctx); |
+void LIBUSB_CALL libusb_unlock_event_waiters(libusb_context *ctx); |
+int LIBUSB_CALL libusb_wait_for_event(libusb_context *ctx, struct timeval *tv); |
+ |
+int LIBUSB_CALL libusb_handle_events_timeout(libusb_context *ctx, |
+ struct timeval *tv); |
+int LIBUSB_CALL libusb_handle_events_timeout_completed(libusb_context *ctx, |
+ struct timeval *tv, int *completed); |
+int LIBUSB_CALL libusb_handle_events(libusb_context *ctx); |
+int LIBUSB_CALL libusb_handle_events_completed(libusb_context *ctx, int *completed); |
+int LIBUSB_CALL libusb_handle_events_locked(libusb_context *ctx, |
+ struct timeval *tv); |
+int LIBUSB_CALL libusb_pollfds_handle_timeouts(libusb_context *ctx); |
+int LIBUSB_CALL libusb_get_next_timeout(libusb_context *ctx, |
+ struct timeval *tv); |
+ |
+/** \ingroup poll |
+ * File descriptor for polling |
+ */ |
+struct libusb_pollfd { |
+ /** Numeric file descriptor */ |
+ int fd; |
+ |
+ /** Event flags to poll for from <poll.h>. POLLIN indicates that you |
+ * should monitor this file descriptor for becoming ready to read from, |
+ * and POLLOUT indicates that you should monitor this file descriptor for |
+ * nonblocking write readiness. */ |
+ short events; |
+}; |
+ |
+/** \ingroup poll |
+ * Callback function, invoked when a new file descriptor should be added |
+ * to the set of file descriptors monitored for events. |
+ * \param fd the new file descriptor |
+ * \param events events to monitor for, see \ref libusb_pollfd for a |
+ * description |
+ * \param user_data User data pointer specified in |
+ * libusb_set_pollfd_notifiers() call |
+ * \see libusb_set_pollfd_notifiers() |
+ */ |
+typedef void (LIBUSB_CALL *libusb_pollfd_added_cb)(int fd, short events, |
+ void *user_data); |
+ |
+/** \ingroup poll |
+ * Callback function, invoked when a file descriptor should be removed from |
+ * the set of file descriptors being monitored for events. After returning |
+ * from this callback, do not use that file descriptor again. |
+ * \param fd the file descriptor to stop monitoring |
+ * \param user_data User data pointer specified in |
+ * libusb_set_pollfd_notifiers() call |
+ * \see libusb_set_pollfd_notifiers() |
+ */ |
+typedef void (LIBUSB_CALL *libusb_pollfd_removed_cb)(int fd, void *user_data); |
+ |
+const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds( |
+ libusb_context *ctx); |
+void LIBUSB_CALL libusb_set_pollfd_notifiers(libusb_context *ctx, |
+ libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, |
+ void *user_data); |
+ |
+#ifdef __cplusplus |
+} |
+#endif |
+ |
+#endif |
Index: instr/drs/libusb-1.0.lib |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/instr/drs/libusb-1.0.lib |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: instr/drs/musbstd.c |
=================================================================== |
--- instr/drs/musbstd.c (nonexistent) |
+++ instr/drs/musbstd.c (revision 197) |
@@ -0,0 +1,700 @@ |
+/********************************************************************\ |
+ |
+ Name: musbstd.c |
+ Created by: Konstantin Olchanski, Stefan Ritt |
+ |
+ Contents: Midas USB access |
+ |
+ $Id$ |
+ |
+\********************************************************************/ |
+ |
+#include <stdio.h> |
+#include <assert.h> |
+#include "musbstd.h" |
+ |
+#ifdef _MSC_VER // Windows includes |
+ |
+#include <windows.h> |
+#include <conio.h> |
+#include <winioctl.h> |
+ |
+#include <setupapi.h> |
+#include <initguid.h> /* Required for GUID definition */ |
+ |
+// link with SetupAPI.Lib. |
+#pragma comment (lib, "setupapi.lib") |
+ |
+// disable "deprecated" warning |
+#pragma warning( disable: 4996) |
+ |
+// {CBEB3FB1-AE9F-471c-9016-9B6AC6DCD323} |
+DEFINE_GUID(GUID_CLASS_MSCB_BULK, 0xcbeb3fb1, 0xae9f, 0x471c, 0x90, 0x16, 0x9b, 0x6a, 0xc6, 0xdc, 0xd3, 0x23); |
+ |
+#elif defined(OS_DARWIN) |
+ |
+#include <unistd.h> |
+#include <string.h> |
+#include <stdlib.h> |
+#include <ctype.h> |
+#include <sys/types.h> |
+#include <sys/ioctl.h> |
+#include <sys/time.h> |
+#include <fcntl.h> |
+ |
+#include <assert.h> |
+#include <mach/mach.h> |
+#include <IOKit/IOKitLib.h> |
+#include <IOKit/IOCFPlugIn.h> |
+#include <IOKit/usb/IOUSBLib.h> |
+ |
+#elif defined(OS_LINUX) // Linux includes |
+ |
+#include <unistd.h> |
+#include <string.h> |
+#include <stdlib.h> |
+ |
+#endif |
+ |
+#ifdef HAVE_LIBUSB |
+#include <errno.h> |
+#include "usb.h" |
+#endif |
+ |
+#ifdef HAVE_LIBUSB10 |
+#include <errno.h> |
+#include <libusb-1.0/libusb.h> |
+#endif |
+ |
+#if !defined(HAVE_LIBUSB) && !defined(HAVE_LIBUSB10) |
+#ifdef OS_DARWIN |
+ |
+IOReturn darwin_configure_device(MUSB_INTERFACE* musb) |
+{ |
+ IOReturn status; |
+ io_iterator_t iter; |
+ io_service_t service; |
+ IOCFPlugInInterface **plugin; |
+ SInt32 score; |
+ IOUSBInterfaceInterface **uinterface; |
+ UInt8 numend; |
+ |
+ IOUSBDeviceInterface **device = (IOUSBDeviceInterface **)musb->device; |
+ |
+ status = (*device)->SetConfiguration(device, musb->usb_configuration); |
+ assert(status == kIOReturnSuccess); |
+ |
+ IOUSBFindInterfaceRequest request; |
+ |
+ request.bInterfaceClass = kIOUSBFindInterfaceDontCare; |
+ request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; |
+ request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; |
+ request.bAlternateSetting = kIOUSBFindInterfaceDontCare; |
+ |
+ status = (*device)->CreateInterfaceIterator(device, &request, &iter); |
+ assert(status == kIOReturnSuccess); |
+ |
+ while ((service = IOIteratorNext(iter))) { |
+ int i; |
+ status = |
+ IOCreatePlugInInterfaceForService(service, kIOUSBInterfaceUserClientTypeID, |
+ kIOCFPlugInInterfaceID, &plugin, &score); |
+ assert(status == kIOReturnSuccess); |
+ |
+ status = |
+ (*plugin)->QueryInterface(plugin, CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), |
+ (void *) &uinterface); |
+ assert(status == kIOReturnSuccess); |
+ |
+ |
+ status = (*uinterface)->USBInterfaceOpen(uinterface); |
+ fprintf(stderr, "musb_open: USBInterfaceOpen status 0x%x\n", status); |
+ assert(status == kIOReturnSuccess); |
+ |
+ status = (*uinterface)->GetNumEndpoints(uinterface, &numend); |
+ assert(status == kIOReturnSuccess); |
+ |
+ fprintf(stderr, "musb_open: endpoints: %d\n", numend); |
+ |
+ for (i=1; i<=numend; i++) { |
+ status = (*uinterface)->GetPipeStatus(uinterface, i); |
+ fprintf(stderr, "musb_open: pipe %d status: 0x%x\n", i, status); |
+ |
+#if 0 |
+ status = (*uinterface)->ClearPipeStall(uinterface, i); |
+ fprintf(stderr, "musb_open: pipe %d ClearPipeStall() status: 0x%x\n", i, status); |
+ status = (*uinterface)->ResetPipe(uinterface, i); |
+ fprintf(stderr, "musb_open: pipe %d ResetPipe() status: 0x%x\n", i, status); |
+ status = (*uinterface)->AbortPipe(uinterface, i); |
+ fprintf(stderr, "musb_open: pipe %d AbortPipe() status: 0x%x\n", i, status); |
+#endif |
+ } |
+ |
+ musb->interface = uinterface; |
+ return kIOReturnSuccess; |
+ } |
+ |
+ assert(!"Should never be reached!"); |
+ return -1; |
+} |
+ |
+#endif |
+ |
+#endif |
+ |
+int musb_open(MUSB_INTERFACE **musb_interface, int vendor, int product, int instance, int configuration, int usbinterface) |
+{ |
+#if defined(HAVE_LIBUSB) |
+ |
+ struct usb_bus *bus; |
+ struct usb_device *dev; |
+ int count = 0; |
+ |
+ usb_init(); |
+ usb_find_busses(); |
+ usb_find_devices(); |
+ usb_set_debug(3); |
+ |
+ for (bus = usb_get_busses(); bus; bus = bus->next) |
+ for (dev = bus->devices; dev; dev = dev->next) |
+ if (dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product) { |
+ if (count == instance) { |
+ int status; |
+ usb_dev_handle *udev; |
+ |
+ udev = usb_open(dev); |
+ if (!udev) { |
+ fprintf(stderr, "musb_open: usb_open() error\n"); |
+ return MUSB_ACCESS_ERROR; |
+ } |
+ |
+ status = usb_set_configuration(udev, configuration); |
+ if (status < 0) { |
+ fprintf(stderr, "musb_open: usb_set_configuration() error %d (%s)\n", status, |
+ strerror(-status)); |
+ fprintf(stderr, |
+ "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it: please check permissions on \"/proc/bus/usb/%s/%s\" and \"/dev/bus/usb/%s/%s\"\n", |
+ vendor, product, instance, bus->dirname, dev->filename, bus->dirname, dev->filename); |
+ return MUSB_ACCESS_ERROR; |
+ } |
+ |
+ /* see if we have write access */ |
+ status = usb_claim_interface(udev, usbinterface); |
+ if (status < 0) { |
+ fprintf(stderr, "musb_open: usb_claim_interface() error %d (%s)\n", status, |
+ strerror(-status)); |
+ |
+#ifdef _MSC_VER |
+ fprintf(stderr, |
+ "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it:\nDevice is probably used by another program\n", |
+ vendor, product, instance); |
+#else |
+ fprintf(stderr, |
+ "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it: please check permissions on \"/proc/bus/usb/%s/%s\"\n", |
+ vendor, product, instance, bus->dirname, dev->filename); |
+#endif |
+ |
+ return MUSB_ACCESS_ERROR; |
+ } |
+ |
+ *musb_interface = (MUSB_INTERFACE*)calloc(1, sizeof(MUSB_INTERFACE)); |
+ (*musb_interface)->dev = udev; |
+ (*musb_interface)->usb_configuration = configuration; |
+ (*musb_interface)->usb_interface = usbinterface; |
+ return MUSB_SUCCESS; |
+ } |
+ |
+ count++; |
+ } |
+ |
+ return MUSB_NOT_FOUND; |
+ |
+#elif defined(HAVE_LIBUSB10) |
+ |
+ static int first_call = 1; |
+ |
+ libusb_device **dev_list; |
+ libusb_device_handle *dev; |
+ struct libusb_device_descriptor desc; |
+ |
+ int status, i, n; |
+ int count = 0; |
+ |
+ if (first_call) { |
+ first_call = 0; |
+ libusb_init(NULL); |
+ // libusb_set_debug(NULL, 3); |
+ } |
+ |
+ n = libusb_get_device_list(NULL, &dev_list); |
+ |
+ for (i=0 ; i<n ; i++) { |
+ status = libusb_get_device_descriptor(dev_list[i], &desc); |
+ if (desc.idVendor == vendor && desc.idProduct == product) { |
+ if (count == instance) { |
+ status = libusb_open(dev_list[i], &dev); |
+ if (status < 0) { |
+ fprintf(stderr, "musb_open: libusb_open() error %d\n", status); |
+ return MUSB_ACCESS_ERROR; |
+ } |
+ |
+ status = libusb_set_configuration(dev, configuration); |
+ if (status < 0) { |
+ fprintf(stderr, "musb_open: usb_set_configuration() error %d\n", status); |
+ fprintf(stderr, |
+ "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it: please check permissions on \"/proc/bus/usb/%d/%d\" and \"/dev/bus/usb/%d/%d\"\n", |
+ vendor, product, instance, libusb_get_bus_number(dev_list[i]), libusb_get_device_address(dev_list[i]), libusb_get_bus_number(dev_list[i]), libusb_get_device_address(dev_list[i])); |
+ return MUSB_ACCESS_ERROR; |
+ } |
+ |
+ /* see if we have write access */ |
+ status = libusb_claim_interface(dev, usbinterface); |
+ if (status < 0) { |
+ fprintf(stderr, "musb_open: libusb_claim_interface() error %d\n", status); |
+ |
+#ifdef _MSC_VER |
+ fprintf(stderr, |
+ "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it:\nDevice is probably used by another program\n", |
+ vendor, product, instance); |
+#else |
+ fprintf(stderr, |
+ "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it: please check permissions on \"/proc/bus/usb/%d/%d\"\n", |
+ vendor, product, instance, libusb_get_bus_number(dev_list[i]), libusb_get_device_address(dev_list[i])); |
+#endif |
+ |
+ return MUSB_ACCESS_ERROR; |
+ } |
+ |
+ *musb_interface = (MUSB_INTERFACE*)calloc(1, sizeof(MUSB_INTERFACE)); |
+ (*musb_interface)->dev = dev; |
+ (*musb_interface)->usb_configuration = configuration; |
+ (*musb_interface)->usb_interface = usbinterface; |
+ return MUSB_SUCCESS; |
+ |
+ } |
+ count++; |
+ } |
+ } |
+ |
+ libusb_free_device_list(dev_list, 1); |
+ |
+ return MUSB_NOT_FOUND; |
+ |
+#elif defined(OS_DARWIN) |
+ |
+ kern_return_t status; |
+ io_iterator_t iter; |
+ io_service_t service; |
+ IOCFPlugInInterface **plugin; |
+ SInt32 score; |
+ IOUSBDeviceInterface **device; |
+ UInt16 xvendor, xproduct; |
+ int count = 0; |
+ |
+ *musb_interface = calloc(1, sizeof(MUSB_INTERFACE)); |
+ |
+ status = IORegistryCreateIterator(kIOMasterPortDefault, kIOUSBPlane, kIORegistryIterateRecursively, &iter); |
+ assert(status == kIOReturnSuccess); |
+ |
+ while ((service = IOIteratorNext(iter))) { |
+ status = |
+ IOCreatePlugInInterfaceForService(service, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, |
+ &plugin, &score); |
+ assert(status == kIOReturnSuccess); |
+ |
+ status = IOObjectRelease(service); |
+ assert(status == kIOReturnSuccess); |
+ |
+ status = |
+ (*plugin)->QueryInterface(plugin, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (void *) &device); |
+ assert(status == kIOReturnSuccess); |
+ |
+ status = (*plugin)->Release(plugin); |
+ |
+ status = (*device)->GetDeviceVendor(device, &xvendor); |
+ assert(status == kIOReturnSuccess); |
+ status = (*device)->GetDeviceProduct(device, &xproduct); |
+ assert(status == kIOReturnSuccess); |
+ |
+ //fprintf(stderr, "musb_open: Found USB device: vendor 0x%04x, product 0x%04x\n", xvendor, xproduct); |
+ |
+ if (xvendor == vendor && xproduct == product) { |
+ if (count == instance) { |
+ |
+ fprintf(stderr, "musb_open: Found USB device: vendor 0x%04x, product 0x%04x, instance %d\n", xvendor, xproduct, instance); |
+ |
+ status = (*device)->USBDeviceOpen(device); |
+ fprintf(stderr, "musb_open: USBDeviceOpen status 0x%x\n", status); |
+ |
+ assert(status == kIOReturnSuccess); |
+ |
+ (*musb_interface)->usb_configuration = configuration; |
+ (*musb_interface)->usb_interface = usbinterface; |
+ (*musb_interface)->device = (void*)device; |
+ (*musb_interface)->interface = NULL; |
+ |
+ status = darwin_configure_device(*musb_interface); |
+ |
+ if (status == kIOReturnSuccess) |
+ return MUSB_SUCCESS; |
+ |
+ fprintf(stderr, "musb_open: USB device exists, but configuration fails!"); |
+ return MUSB_NOT_FOUND; |
+ } |
+ |
+ count++; |
+ } |
+ |
+ (*device)->Release(device); |
+ } |
+ |
+ return MUSB_NOT_FOUND; |
+#elif defined(_MSC_VER) |
+ GUID guid; |
+ HDEVINFO hDevInfoList; |
+ SP_DEVICE_INTERFACE_DATA deviceInfoData; |
+ PSP_DEVICE_INTERFACE_DETAIL_DATA functionClassDeviceData; |
+ ULONG predictedLength, requiredLength; |
+ int status; |
+ char device_name[256], str[256]; |
+ |
+ *musb_interface = (MUSB_INTERFACE *)calloc(1, sizeof(MUSB_INTERFACE)); |
+ |
+ guid = GUID_CLASS_MSCB_BULK; |
+ |
+ // Retrieve device list for GUID that has been specified. |
+ hDevInfoList = SetupDiGetClassDevs(&guid, NULL, NULL, (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)); |
+ |
+ status = FALSE; |
+ if (hDevInfoList != NULL) { |
+ |
+ // Clear data structure |
+ memset(&deviceInfoData, 0, sizeof(deviceInfoData)); |
+ deviceInfoData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); |
+ |
+ // retrieves a context structure for a device interface of a device information set. |
+ if (SetupDiEnumDeviceInterfaces(hDevInfoList, 0, &guid, instance, &deviceInfoData)) { |
+ // Must get the detailed information in two steps |
+ // First get the length of the detailed information and allocate the buffer |
+ // retrieves detailed information about a specified device interface. |
+ functionClassDeviceData = NULL; |
+ |
+ predictedLength = requiredLength = 0; |
+ |
+ SetupDiGetDeviceInterfaceDetail(hDevInfoList, &deviceInfoData, NULL, // Not yet allocated |
+ 0, // Set output buffer length to zero |
+ &requiredLength, // Find out memory requirement |
+ NULL); |
+ |
+ predictedLength = requiredLength; |
+ functionClassDeviceData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) malloc(predictedLength); |
+ functionClassDeviceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); |
+ |
+ // Second, get the detailed information |
+ if (SetupDiGetDeviceInterfaceDetail(hDevInfoList, |
+ &deviceInfoData, functionClassDeviceData, |
+ predictedLength, &requiredLength, NULL)) { |
+ |
+ // Save the device name for subsequent pipe open calls |
+ strcpy(device_name, functionClassDeviceData->DevicePath); |
+ free(functionClassDeviceData); |
+ |
+ // Signal device found |
+ status = TRUE; |
+ } else |
+ free(functionClassDeviceData); |
+ } |
+ } |
+ // SetupDiDestroyDeviceInfoList() destroys a device information set |
+ // and frees all associated memory. |
+ SetupDiDestroyDeviceInfoList(hDevInfoList); |
+ |
+ if (status) { |
+ |
+ // Get the read handle |
+ sprintf(str, "%s\\PIPE00", device_name); |
+ (*musb_interface)->rhandle = CreateFile(str, |
+ GENERIC_WRITE | GENERIC_READ, |
+ FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, |
+ OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); |
+ |
+ if ((*musb_interface)->rhandle == INVALID_HANDLE_VALUE) |
+ return MUSB_ACCESS_ERROR; |
+ |
+ // Get the write handle |
+ sprintf(str, "%s\\PIPE01", device_name); |
+ (*musb_interface)->whandle = CreateFile(str, |
+ GENERIC_WRITE | GENERIC_READ, |
+ FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); |
+ |
+ if ((*musb_interface)->whandle == INVALID_HANDLE_VALUE) |
+ return MUSB_ACCESS_ERROR; |
+ |
+ return MUSB_SUCCESS; |
+ } |
+ |
+ return MUSB_NOT_FOUND; |
+#endif |
+} |
+ |
+int musb_set_altinterface(MUSB_INTERFACE *musb_interface, int index) |
+{ |
+#if defined (HAVE_LIBUSB) |
+ int status; |
+ |
+ status = usb_set_altinterface(musb_interface->dev, index); |
+ if (status < 0) |
+ fprintf(stderr, "musb_set_altinterface: usb_set_altinterface() error %d\n", status); |
+ |
+ return status; |
+#else |
+ return -1; |
+#endif |
+} |
+ |
+int musb_close(MUSB_INTERFACE *musb_interface) |
+{ |
+#if defined(HAVE_LIBUSB) |
+ |
+ int status; |
+ status = usb_release_interface(musb_interface->dev, musb_interface->usb_interface); |
+ if (status < 0) |
+ fprintf(stderr, "musb_close: usb_release_interface() error %d\n", status); |
+ |
+#ifdef OS_LINUX // linux wants a reset, otherwise the device cannot be accessed next time |
+ musb_reset(musb_interface); |
+#endif |
+ |
+ status = usb_close(musb_interface->dev); |
+ if (status < 0) |
+ fprintf(stderr, "musb_close: usb_close() error %d\n", status); |
+ |
+#elif defined(HAVE_LIBUSB10) |
+ |
+ int status; |
+ status = libusb_release_interface(musb_interface->dev, musb_interface->usb_interface); |
+ if (status < 0) |
+ fprintf(stderr, "musb_close: libusb_release_interface() error %d\n", status); |
+ |
+#ifdef OS_LINUX // linux wants a reset, otherwise the device cannot be accessed next time |
+ musb_reset(musb_interface); |
+#endif |
+ |
+ libusb_close(musb_interface->dev); |
+ |
+#elif defined(OS_DARWIN) |
+ |
+ IOReturn status; |
+ IOUSBInterfaceInterface **interface = (IOUSBInterfaceInterface **)musb_interface->interface; |
+ |
+ status = (*interface)->USBInterfaceClose(interface); |
+ if (status != kIOReturnSuccess) |
+ fprintf(stderr, "musb_close: USBInterfaceClose() status %d 0x%x\n", status, status); |
+ |
+ status = (*interface)->Release(interface); |
+ if (status != kIOReturnSuccess) |
+ fprintf(stderr, "musb_close: USB Interface Release() status %d 0x%x\n", status, status); |
+ |
+ IOUSBDeviceInterface **device = (IOUSBDeviceInterface**)musb_interface->device; |
+ status = (*device)->USBDeviceClose(device); |
+ if (status != kIOReturnSuccess) |
+ fprintf(stderr, "musb_close: USBDeviceClose() status %d 0x%x\n", status, status); |
+ |
+ status = (*device)->Release(device); |
+ if (status != kIOReturnSuccess) |
+ fprintf(stderr, "musb_close: USB Device Release() status %d 0x%x\n", status, status); |
+ |
+#elif defined(_MSC_VER) |
+ |
+ CloseHandle(musb_interface->rhandle); |
+ CloseHandle(musb_interface->whandle); |
+ |
+#else |
+ assert(!"musb_close() is not implemented"); |
+#endif |
+ |
+ /* free memory allocated in musb_open() */ |
+ free(musb_interface); |
+ return 0; |
+} |
+ |
+int musb_write(MUSB_INTERFACE *musb_interface, int endpoint, const void *buf, int count, int timeout) |
+{ |
+ int n_written; |
+ |
+#if defined(HAVE_LIBUSB) |
+ n_written = usb_bulk_write(musb_interface->dev, endpoint, (char*)buf, count, timeout); |
+ if (n_written != count) { |
+ fprintf(stderr, "musb_write: requested %d, wrote %d, errno %d (%s)\n", count, n_written, errno, strerror(errno)); |
+ } |
+#elif defined(HAVE_LIBUSB10) |
+ int status = libusb_bulk_transfer(musb_interface->dev, endpoint, (unsigned char*)buf, count, &n_written, timeout); |
+ if (n_written != count) { |
+ fprintf(stderr, "musb_write: requested %d, wrote %d, errno %d (%s)\n", count, n_written, status, strerror(status)); |
+ } |
+#elif defined(OS_DARWIN) |
+ IOReturn status; |
+ IOUSBInterfaceInterface182 **interface = (IOUSBInterfaceInterface182 **)musb_interface->interface; |
+ status = (*interface)->WritePipeTO(interface, endpoint, buf, count, 0, timeout); |
+ if (status != 0) { |
+ fprintf(stderr, "musb_write: WritePipe() status %d 0x%x\n", status, status); |
+ return -1; |
+ } |
+ n_written = count; |
+#elif defined(_MSC_VER) |
+ WriteFile(musb_interface->whandle, buf, count, &n_written, NULL); |
+#endif |
+ |
+ //fprintf(stderr, "musb_write(ep %d, %d bytes) (%s) returns %d\n", endpoint, count, buf, n_written); |
+ |
+ return n_written; |
+} |
+ |
+int musb_read(MUSB_INTERFACE *musb_interface, int endpoint, void *buf, int count, int timeout) |
+{ |
+ int n_read = 0; |
+ |
+#if defined(HAVE_LIBUSB) |
+ |
+ n_read = usb_bulk_read(musb_interface->dev, endpoint | 0x80, (char*)buf, count, timeout); |
+ /* errors should be handled in upper layer .... |
+ if (n_read <= 0) { |
+ fprintf(stderr, "musb_read: requested %d, read %d, errno %d (%s)\n", count, n_read, errno, strerror(errno)); |
+ } |
+ */ |
+ |
+#elif defined(HAVE_LIBUSB10) |
+ |
+ libusb_bulk_transfer(musb_interface->dev, endpoint | 0x80, (unsigned char*)buf, count, &n_read, timeout); |
+ /* errors should be handled in upper layer .... |
+ if (n_read <= 0) { |
+ fprintf(stderr, "musb_read: requested %d, read %d, errno %d (%s)\n", count, n_read, status, strerror(status)); |
+ } |
+ */ |
+ |
+#elif defined(OS_DARWIN) |
+ |
+ UInt32 xcount = count; |
+ IOReturn status; |
+ IOUSBInterfaceInterface182 **interface = (IOUSBInterfaceInterface182 **)musb_interface->interface; |
+ |
+ status = (*interface)->ReadPipeTO(interface, endpoint, buf, &xcount, 0, timeout); |
+ if (status != kIOReturnSuccess) { |
+ fprintf(stderr, "musb_read: requested %d, read %d, ReadPipe() status %d 0x%x (%s)\n", count, n_read, status, status, strerror(status)); |
+ return -1; |
+ } |
+ |
+ n_read = xcount; |
+ |
+#elif defined(_MSC_VER) |
+ |
+ OVERLAPPED overlapped; |
+ int status; |
+ |
+ memset(&overlapped, 0, sizeof(overlapped)); |
+ overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
+ n_read = 0; |
+ |
+ status = ReadFile(musb_interface->rhandle, buf, count, &n_read, &overlapped); |
+ |
+ if (!status) { |
+ |
+ status = GetLastError(); |
+ if (status != ERROR_IO_PENDING) |
+ return 0; |
+ |
+ /* wait for completion with timeout */ |
+ status = WaitForSingleObject(overlapped.hEvent, timeout); |
+ if (status == WAIT_TIMEOUT) |
+ CancelIo(musb_interface->rhandle); |
+ else |
+ GetOverlappedResult(musb_interface->rhandle, &overlapped, &n_read, FALSE); |
+ } |
+ |
+ CloseHandle(overlapped.hEvent); |
+ |
+#endif |
+ |
+ //fprintf(stderr, "musb_read(ep %d, %d bytes) returns %d (%s)\n", endpoint, count, n_read, buf); |
+ |
+ return n_read; |
+} |
+ |
+int musb_reset(MUSB_INTERFACE *musb_interface) |
+{ |
+#if defined(HAVE_LIBUSB) |
+ |
+ /* Causes re-enumeration: After calling usb_reset, the device will need |
+ to re-enumerate and thusly, requires you to find the new device and |
+ open a new handle. The handle used to call usb_reset will no longer work */ |
+ |
+ int status; |
+ status = usb_reset(musb_interface->dev); |
+ if (status < 0) |
+ fprintf(stderr, "musb_reset: usb_reset() status %d\n", status); |
+ |
+#elif defined(HAVE_LIBUSB10) |
+ |
+ int status; |
+ status = libusb_reset_device(musb_interface->dev); |
+ if (status < 0) |
+ fprintf(stderr, "musb_reset: usb_reset() status %d\n", status); |
+ |
+#elif defined(OS_DARWIN) |
+ |
+ IOReturn status; |
+ IOUSBDeviceInterface **device = (IOUSBDeviceInterface**)musb_interface->device; |
+ |
+ status = (*device)->ResetDevice(device); |
+ fprintf(stderr, "musb_reset: ResetDevice() status 0x%x\n", status); |
+ |
+ status = darwin_configure_device(musb_interface); |
+ assert(status == kIOReturnSuccess); |
+ |
+#elif defined(_MSC_VER) |
+ |
+#define IOCTL_BULKUSB_RESET_DEVICE CTL_CODE(FILE_DEVICE_UNKNOWN, \ |
+ 1, \ |
+ METHOD_BUFFERED, \ |
+ FILE_ANY_ACCESS) |
+#define IOCTL_BULKUSB_RESET_PIPE CTL_CODE(FILE_DEVICE_UNKNOWN, \ |
+ 2, \ |
+ METHOD_BUFFERED, \ |
+ FILE_ANY_ACCESS) |
+ |
+ int status, n_bytes; |
+ |
+ status = DeviceIoControl(musb_interface->rhandle, |
+ IOCTL_BULKUSB_RESET_DEVICE, |
+ NULL, 0, NULL, 0, &n_bytes, NULL); |
+ status = DeviceIoControl(musb_interface->whandle, |
+ IOCTL_BULKUSB_RESET_DEVICE, |
+ NULL, 0, NULL, 0, &n_bytes, NULL); |
+ status = DeviceIoControl(musb_interface->rhandle, |
+ IOCTL_BULKUSB_RESET_PIPE, |
+ NULL, 0, NULL, 0, &n_bytes, NULL); |
+ status = DeviceIoControl(musb_interface->whandle, |
+ IOCTL_BULKUSB_RESET_PIPE, |
+ NULL, 0, NULL, 0, &n_bytes, NULL); |
+ return status; |
+ |
+#endif |
+ return 0; |
+} |
+ |
+int musb_get_device(MUSB_INTERFACE *usb_interface) |
+{ |
+#ifdef HAVE_LIBUSB |
+ struct usb_device_descriptor d; |
+ usb_get_descriptor(usb_interface->dev, USB_DT_DEVICE, 0, &d, sizeof(d)); |
+ return d.bcdDevice; |
+#elif HAVE_LIBUSB10 |
+ struct libusb_device_descriptor d; |
+ libusb_get_descriptor(usb_interface->dev, LIBUSB_DT_DEVICE, 0, (unsigned char *)&d, sizeof(d)); |
+ return d.bcdDevice; |
+#else |
+ return 0; |
+#endif |
+} |
+ |
+/* end */ |
Index: instr/drs/musbstd.h |
=================================================================== |
--- instr/drs/musbstd.h (nonexistent) |
+++ instr/drs/musbstd.h (revision 197) |
@@ -0,0 +1,95 @@ |
+/********************************************************************\ |
+ |
+ Name: musbstd.h |
+ Created by: Konstantin Olchanski, Stefan Ritt |
+ |
+ Contents: Midas USB access |
+ |
+ $Id$ |
+ |
+\********************************************************************/ |
+ |
+#ifndef MUSBSTD_H |
+#define MUSBSTD_H |
+ |
+#if defined(HAVE_LIBUSB) |
+ |
+#include "usb.h" |
+ |
+typedef struct { |
+ usb_dev_handle *dev; |
+ int usb_configuration; |
+ int usb_interface; |
+ int usb_type; |
+} MUSB_INTERFACE; |
+ |
+#elif defined(HAVE_LIBUSB10) |
+ |
+#include <libusb-1.0/libusb.h> |
+ |
+typedef struct { |
+ libusb_device_handle *dev; |
+ int usb_configuration; |
+ int usb_interface; |
+ int usb_type; |
+} MUSB_INTERFACE; |
+ |
+#elif defined(_MSC_VER) |
+ |
+#include <windows.h> |
+ |
+typedef struct { |
+ HANDLE rhandle; |
+ HANDLE whandle; |
+ int usb_type; |
+} MUSB_INTERFACE; |
+ |
+#elif defined(OS_DARWIN) |
+ |
+typedef struct { |
+ void *device; |
+ void *interface; |
+ int usb_configuration; |
+ int usb_interface; |
+ int usb_type; |
+} MUSB_INTERFACE; |
+ |
+#else |
+#error Do not know how to access USB devices |
+#endif |
+ |
+/*---- status codes ------------------------------------------------*/ |
+ |
+#define MUSB_SUCCESS 1 |
+#define MUSB_NOT_FOUND 2 |
+#define MUSB_INVALID_PARAM 3 |
+#define MUSB_NO_MEM 4 |
+#define MUSB_ACCESS_ERROR 5 |
+ |
+/* make functions callable from a C++ program */ |
+#ifdef __cplusplus |
+extern "C" { |
+#endif |
+ |
+/* make functions under WinNT dll exportable */ |
+#ifndef EXPRT |
+#if defined(_MSC_VER) && defined(_USRDLL) |
+#define EXPRT __declspec(dllexport) |
+#else |
+#define EXPRT |
+#endif |
+#endif |
+ |
+int EXPRT musb_open(MUSB_INTERFACE **musb_interface, int vendor, int product, int instance, int configuration, int usbinterface); |
+int EXPRT musb_close(MUSB_INTERFACE *musb_interface); |
+int EXPRT musb_write(MUSB_INTERFACE *musb_interface,int endpoint,const void *buf,int count,int timeout_ms); |
+int EXPRT musb_read(MUSB_INTERFACE *musb_interface,int endpoint,void *buf,int count,int timeout_ms); |
+int EXPRT musb_reset(MUSB_INTERFACE *musb_interface); |
+int EXPRT musb_set_altinterface(MUSB_INTERFACE *musb_interface, int index); |
+int EXPRT musb_get_device(MUSB_INTERFACE *musb_interface); |
+ |
+#ifdef __cplusplus |
+} |
+#endif |
+ |
+#endif // MUSBSTD_H |
Index: instr/drs/mxml.c |
=================================================================== |
--- instr/drs/mxml.c (nonexistent) |
+++ instr/drs/mxml.c (revision 197) |
@@ -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: instr/drs/mxml.h |
=================================================================== |
--- instr/drs/mxml.h (nonexistent) |
+++ instr/drs/mxml.h (revision 197) |
@@ -0,0 +1,156 @@ |
+/********************************************************************\ |
+ |
+ Name: mxml.h |
+ Created by: Stefan Ritt |
+ Copyright 2000 + Stefan Ritt |
+ |
+ Contents: Header file for mxml.c |
+ |
+ This file is part of MIDAS XML Library. |
+ |
+ MIDAS XML Library is free software: you can redistribute it and/or modify |
+ it under the terms of the GNU General Public License as published by |
+ the Free Software Foundation, either version 3 of the License, or |
+ (at your option) any later version. |
+ |
+ MIDAS XML Library is distributed in the hope that it will be useful, |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ GNU General Public License for more details. |
+ |
+ You should have received a copy of the GNU General Public License |
+ along with MIDAS XML Library. If not, see <http://www.gnu.org/licenses/>. |
+ |
+\********************************************************************/ |
+ |
+/*------------------------------------------------------------------*/ |
+ |
+#ifndef _MXML_H_ |
+#define _MXML_H_ |
+ |
+#define MXML_NAME_LENGTH 64 |
+ |
+#define ELEMENT_NODE 1 |
+#define TEXT_NODE 2 |
+#define PROCESSING_INSTRUCTION_NODE 3 |
+#define COMMENT_NODE 4 |
+#define DOCUMENT_NODE 5 |
+ |
+#define INTERNAL_ENTITY 0 |
+#define EXTERNAL_ENTITY 1 |
+#define MXML_MAX_ENTITY 500 |
+ |
+#define MXML_MAX_CONDITION 10 |
+ |
+#ifdef _MSC_VER |
+#define DIR_SEPARATOR '\\' |
+#else |
+#define DIR_SEPARATOR '/' |
+#endif |
+ |
+typedef struct { |
+ int fh; |
+ char *buffer; |
+ int buffer_size; |
+ int buffer_len; |
+ int level; |
+ int element_is_open; |
+ int data_was_written; |
+ char **stack; |
+ int translate; |
+} MXML_WRITER; |
+ |
+typedef struct mxml_struct *PMXML_NODE; |
+ |
+typedef struct mxml_struct { |
+ char name[MXML_NAME_LENGTH]; // name of element <[name]>[value]</[name]> |
+ int node_type; // type of node XXX_NODE |
+ char *value; // value of element |
+ int n_attributes; // list of attributes |
+ char *attribute_name; |
+ char **attribute_value; |
+ int line_number_start; // first line number in XML file, starting from 1 |
+ int line_number_end; // last line number in XML file, starting from 1 |
+ PMXML_NODE parent; // pointer to parent element |
+ int n_children; // list of children |
+ PMXML_NODE child; |
+} MXML_NODE; |
+ |
+/*------------------------------------------------------------------*/ |
+ |
+/* make functions callable from a C++ program */ |
+#ifdef __cplusplus |
+extern "C" { |
+#endif |
+ |
+#ifndef EXPRT |
+#if defined(EXPORT_DLL) |
+#define EXPRT __declspec(dllexport) |
+#else |
+#define EXPRT |
+#endif |
+#endif |
+ |
+void mxml_suppress_date(int suppress); |
+MXML_WRITER *mxml_open_file(const char *file_name); |
+MXML_WRITER *mxml_open_buffer(void); |
+int mxml_set_translate(MXML_WRITER *writer, int flag); |
+int mxml_start_element(MXML_WRITER *writer, const char *name); |
+int mxml_start_element_noindent(MXML_WRITER *writer, const char *name); |
+int mxml_end_element(MXML_WRITER *writer); |
+int mxml_write_comment(MXML_WRITER *writer, const char *string); |
+int mxml_write_element(MXML_WRITER *writer, const char *name, const char *value); |
+int mxml_write_attribute(MXML_WRITER *writer, const char *name, const char *value); |
+int mxml_write_value(MXML_WRITER *writer, const char *value); |
+int mxml_write_empty_line(MXML_WRITER *writer); |
+char *mxml_close_buffer(MXML_WRITER *writer); |
+int mxml_close_file(MXML_WRITER *writer); |
+ |
+int mxml_get_number_of_children(PMXML_NODE pnode); |
+PMXML_NODE mxml_get_parent(PMXML_NODE pnode); |
+PMXML_NODE mxml_subnode(PMXML_NODE pnode, int idx); |
+PMXML_NODE mxml_find_node(PMXML_NODE tree, const char *xml_path); |
+int mxml_find_nodes(PMXML_NODE tree, const char *xml_path, PMXML_NODE **nodelist); |
+char *mxml_get_name(PMXML_NODE pnode); |
+char *mxml_get_value(PMXML_NODE pnode); |
+int mxml_get_line_number_start(PMXML_NODE pnode); |
+int mxml_get_line_number_end(PMXML_NODE pnode); |
+PMXML_NODE mxml_get_node_at_line(PMXML_NODE tree, int linenumber); |
+char *mxml_get_attribute(PMXML_NODE pnode, const char *name); |
+ |
+int mxml_add_attribute(PMXML_NODE pnode, const char *attrib_name, const char *attrib_value); |
+PMXML_NODE mxml_add_special_node(PMXML_NODE parent, int node_type, const char *node_name, const char *value); |
+PMXML_NODE mxml_add_special_node_at(PMXML_NODE parent, int node_type, const char *node_name, const char *value, int idx); |
+PMXML_NODE mxml_add_node(PMXML_NODE parent, const char *node_name, const char *value); |
+PMXML_NODE mxml_add_node_at(PMXML_NODE parent, const char *node_name, const char *value, int idx); |
+ |
+PMXML_NODE mxml_clone_tree(PMXML_NODE tree); |
+int mxml_add_tree(PMXML_NODE parent, PMXML_NODE tree); |
+int mxml_add_tree_at(PMXML_NODE parent, PMXML_NODE tree, int idx); |
+ |
+int mxml_replace_node_name(PMXML_NODE pnode, const char *new_name); |
+int mxml_replace_node_value(PMXML_NODE pnode, const char *value); |
+int mxml_replace_subvalue(PMXML_NODE pnode, const char *name, const char *value); |
+int mxml_replace_attribute_name(PMXML_NODE pnode, const char *old_name, const char *new_name); |
+int mxml_replace_attribute_value(PMXML_NODE pnode, const char *attrib_name, const char *attrib_value); |
+ |
+int mxml_delete_node(PMXML_NODE pnode); |
+int mxml_delete_attribute(PMXML_NODE, const char *attrib_name); |
+ |
+PMXML_NODE mxml_create_root_node(void); |
+PMXML_NODE mxml_parse_file(const char *file_name, char *error, int error_size, int *error_line); |
+PMXML_NODE mxml_parse_buffer(const char *buffer, char *error, int error_size, int *error_line); |
+int mxml_parse_entity(char **buf, const char* file_name, char *error, int error_size, int *error_line); |
+int mxml_write_tree(const char *file_name, PMXML_NODE tree); |
+void mxml_debug_tree(PMXML_NODE tree, int level); |
+void mxml_free_tree(PMXML_NODE tree); |
+ |
+void mxml_dirname(char* path); |
+void mxml_basename(char *path); |
+ |
+#ifdef __cplusplus |
+} |
+#endif |
+ |
+#endif /* _MXML_H_ */ |
+/*------------------------------------------------------------------*/ |
Index: instr/drs/rb.cpp |
=================================================================== |
--- instr/drs/rb.cpp (nonexistent) |
+++ instr/drs/rb.cpp (revision 197) |
@@ -0,0 +1,387 @@ |
+/********************************************************************\ |
+ |
+ Name: rb.c |
+ Created by: Stefan Ritt |
+ |
+ $Id: rb.cpp 21437 2014-07-30 14:13:29Z ritt $ |
+ |
+\********************************************************************/ |
+ |
+#include <stdio.h> |
+#ifdef OS_DARWIN |
+#include <sys/malloc.h> |
+#else |
+#include <malloc.h> |
+#endif |
+#include <string.h> |
+#include <assert.h> |
+ |
+#include "rb.h" |
+ |
+/********************************************************************\ |
+* * |
+* Ring buffer functions * |
+* * |
+* Provide an inter-thread buffer scheme for handling front-end * |
+* events. This code allows concurrent data acquisition, calibration * |
+* and network transfer on a multi-CPU machine. One thread reads * |
+* out the data, passes it vis the ring buffer functions * |
+* to another thread running on the other CPU, which can then * |
+* calibrate and/or send the data over the network. * |
+* * |
+\********************************************************************/ |
+ |
+typedef struct { |
+ unsigned char *buffer; |
+ unsigned int size; |
+ unsigned int max_event_size; |
+ unsigned char *rp; |
+ unsigned char *wp; |
+ unsigned char *ep; |
+} RING_BUFFER; |
+ |
+#define MAX_RING_BUFFER 100 |
+RING_BUFFER rb[MAX_RING_BUFFER]; |
+ |
+volatile int _rb_nonblocking = 0; |
+ |
+extern void ss_sleep(int ms); |
+ |
+int rb_set_nonblocking() |
+/********************************************************************\ |
+ |
+ Routine: rb_set_nonblocking |
+ |
+ Purpose: Set all rb_get_xx to nonblocking. Needed in multi-thread |
+ environments for stopping all theads without deadlock |
+ |
+ Input: |
+ NONE |
+ |
+ Output: |
+ NONE |
+ |
+ Function value: |
+ RB_SUCCESS Successful completion |
+ |
+\********************************************************************/ |
+{ |
+ _rb_nonblocking = 1; |
+ |
+ return RB_SUCCESS; |
+} |
+ |
+int rb_create(int size, int max_event_size, int *handle) |
+/********************************************************************\ |
+ |
+ Routine: rb_create |
+ |
+ Purpose: Create a ring buffer with a given size |
+ |
+ Input: |
+ int size Size of ring buffer, must be larger than |
+ 2*max_event_size |
+ int max_event_size Maximum event size to be placed into |
+ ring buffer |
+ Output: |
+ int *handle Handle to ring buffer |
+ |
+ Function value: |
+ DB_SUCCESS Successful completion |
+ DB_NO_MEMORY Maximum number of ring buffers exceeded |
+ DB_INVALID_PARAM Invalid event size specified |
+ |
+\********************************************************************/ |
+{ |
+ int i; |
+ |
+ for (i = 0; i < MAX_RING_BUFFER; i++) |
+ if (rb[i].buffer == NULL) |
+ break; |
+ |
+ if (i == MAX_RING_BUFFER) |
+ return RB_NO_MEMORY; |
+ |
+ if (size < max_event_size * 2) |
+ return RB_INVALID_PARAM; |
+ |
+ memset(&rb[i], 0, sizeof(RING_BUFFER)); |
+ rb[i].buffer = (unsigned char *) malloc(size); |
+ assert(rb[i].buffer); |
+ rb[i].size = size; |
+ rb[i].max_event_size = max_event_size; |
+ rb[i].rp = rb[i].buffer; |
+ rb[i].wp = rb[i].buffer; |
+ rb[i].ep = rb[i].buffer; |
+ |
+ *handle = i + 1; |
+ |
+ return RB_SUCCESS; |
+} |
+ |
+int rb_delete(int handle) |
+/********************************************************************\ |
+ |
+ Routine: rb_delete |
+ |
+ Purpose: Delete a ring buffer |
+ |
+ Input: |
+ none |
+ Output: |
+ int handle Handle to ring buffer |
+ |
+ Function value: |
+ DB_SUCCESS Successful completion |
+ |
+\********************************************************************/ |
+{ |
+ if (handle < 0 || handle >= MAX_RING_BUFFER || rb[handle - 1].buffer == NULL) |
+ return RB_INVALID_HANDLE; |
+ |
+ free(rb[handle - 1].buffer); |
+ memset(&rb[handle - 1], 0, sizeof(RING_BUFFER)); |
+ |
+ return RB_SUCCESS; |
+} |
+ |
+int rb_get_wp(int handle, void **p, int millisec) |
+/********************************************************************\ |
+ |
+Routine: rb_get_wp |
+ |
+ Purpose: Retrieve write pointer where new data can be written |
+ |
+ Input: |
+ int handle Ring buffer handle |
+ int millisec Optional timeout in milliseconds if |
+ buffer is full. Zero to not wait at |
+ all (non-blocking) |
+ |
+ Output: |
+ char **p Write pointer |
+ |
+ Function value: |
+ DB_SUCCESS Successful completion |
+ |
+\********************************************************************/ |
+{ |
+ int h, i; |
+ unsigned char *rp; |
+ |
+ if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL) |
+ return RB_INVALID_HANDLE; |
+ |
+ h = handle - 1; |
+ |
+ for (i = 0; i <= millisec / 10; i++) { |
+ |
+ rp = rb[h].rp; // keep local copy, rb[h].rp might be changed by other thread |
+ |
+ /* check if enough size for wp >= rp without wrap-around */ |
+ if (rb[h].wp >= rp |
+ && rb[h].wp + rb[h].max_event_size <= rb[h].buffer + rb[h].size - rb[h].max_event_size) { |
+ *p = rb[h].wp; |
+ return RB_SUCCESS; |
+ } |
+ |
+ /* check if enough size for wp >= rp with wrap-around */ |
+ if (rb[h].wp >= rp && rb[h].wp + rb[h].max_event_size > rb[h].buffer + rb[h].size - rb[h].max_event_size && rb[h].rp > rb[h].buffer) { // next increment of wp wraps around, so need space at beginning |
+ *p = rb[h].wp; |
+ return RB_SUCCESS; |
+ } |
+ |
+ /* check if enough size for wp < rp */ |
+ if (rb[h].wp < rp && rb[h].wp + rb[h].max_event_size < rp) { |
+ *p = rb[h].wp; |
+ return RB_SUCCESS; |
+ } |
+ |
+ if (millisec == 0) |
+ return RB_TIMEOUT; |
+ |
+ if (_rb_nonblocking) |
+ return RB_TIMEOUT; |
+ |
+ /* wait one time slice */ |
+ ss_sleep(10); |
+ } |
+ |
+ return RB_TIMEOUT; |
+} |
+ |
+int rb_increment_wp(int handle, int size) |
+/********************************************************************\ |
+ |
+ Routine: rb_increment_wp |
+ |
+ Purpose: Increment current write pointer, making the data at |
+ the write pointer available to the receiving thread |
+ |
+ Input: |
+ int handle Ring buffer handle |
+ int size Number of bytes placed at the WP |
+ |
+ Output: |
+ NONE |
+ |
+ Function value: |
+ RB_SUCCESS Successful completion |
+ RB_INVALID_PARAM Event size too large or invalid handle |
+\********************************************************************/ |
+{ |
+ int h; |
+ unsigned char *new_wp; |
+ |
+ if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL) |
+ return RB_INVALID_HANDLE; |
+ |
+ h = handle - 1; |
+ |
+ if ((unsigned int) size > rb[h].max_event_size) |
+ return RB_INVALID_PARAM; |
+ |
+ new_wp = rb[h].wp + size; |
+ |
+ /* wrap around wp if not enough space */ |
+ if (new_wp > rb[h].buffer + rb[h].size - rb[h].max_event_size) { |
+ rb[h].ep = new_wp; |
+ new_wp = rb[h].buffer; |
+ assert(rb[h].rp != rb[h].buffer); |
+ } |
+ |
+ rb[h].wp = new_wp; |
+ |
+ return RB_SUCCESS; |
+} |
+ |
+int rb_get_rp(int handle, void **p, int millisec) |
+/********************************************************************\ |
+ |
+ Routine: rb_get_rp |
+ |
+ Purpose: Obtain the current read pointer at which new data is |
+ available with optional timeout |
+ |
+ Input: |
+ int handle Ring buffer handle |
+ int millisec Optional timeout in milliseconds if |
+ buffer is full. Zero to not wait at |
+ all (non-blocking) |
+ |
+ Output: |
+ char **p Address of pointer pointing to newly |
+ available data. If p == NULL, only |
+ return status. |
+ |
+ Function value: |
+ RB_SUCCESS Successful completion |
+ |
+\********************************************************************/ |
+{ |
+ int i, h; |
+ |
+ if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL) |
+ return RB_INVALID_HANDLE; |
+ |
+ h = handle - 1; |
+ |
+ for (i = 0; i <= millisec / 10; i++) { |
+ |
+ if (rb[h].wp != rb[h].rp) { |
+ if (p != NULL) |
+ *p = rb[handle - 1].rp; |
+ return RB_SUCCESS; |
+ } |
+ |
+ if (millisec == 0) |
+ return RB_TIMEOUT; |
+ |
+ if (_rb_nonblocking) |
+ return RB_TIMEOUT; |
+ |
+ /* wait one time slice */ |
+ ss_sleep(10); |
+ } |
+ |
+ return RB_TIMEOUT; |
+} |
+ |
+int rb_increment_rp(int handle, int size) |
+/********************************************************************\ |
+ |
+ Routine: rb_increment_rp |
+ |
+ Purpose: Increment current read pointer, freeing up space for |
+ the writing thread. |
+ |
+ Input: |
+ int handle Ring buffer handle |
+ int size Number of bytes to free up at current |
+ read pointer |
+ |
+ Output: |
+ NONE |
+ |
+ Function value: |
+ RB_SUCCESS Successful completion |
+ RB_INVALID_PARAM Event size too large or invalid handle |
+ |
+\********************************************************************/ |
+{ |
+ int h; |
+ |
+ unsigned char *new_rp; |
+ |
+ if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL) |
+ return RB_INVALID_HANDLE; |
+ |
+ h = handle - 1; |
+ |
+ if ((unsigned int) size > rb[h].max_event_size) |
+ return RB_INVALID_PARAM; |
+ |
+ new_rp = rb[h].rp + size; |
+ |
+ /* wrap around if not enough space left */ |
+ if (new_rp + rb[h].max_event_size > rb[h].buffer + rb[h].size) |
+ new_rp = rb[h].buffer; |
+ |
+ rb[handle - 1].rp = new_rp; |
+ |
+ return RB_SUCCESS; |
+} |
+ |
+int rb_get_buffer_level(int handle, int *n_bytes) |
+/********************************************************************\ |
+ |
+ Routine: rb_get_buffer_level |
+ |
+ Purpose: Return number of bytes in a ring buffer |
+ |
+ Input: |
+ int handle Handle of the buffer to get the info |
+ |
+ Output: |
+ int *n_bytes Number of bytes in buffer |
+ |
+ Function value: |
+ RB_SUCCESS Successful completion |
+ RB_INVALID_HANDLE Buffer handle is invalid |
+ |
+\********************************************************************/ |
+{ |
+ int h; |
+ |
+ if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL) |
+ return RB_INVALID_HANDLE; |
+ |
+ h = handle - 1; |
+ |
+ if (rb[h].wp >= rb[h].rp) |
+ *n_bytes = rb[h].wp - rb[h].rp; |
+ else |
+ *n_bytes = rb[h].ep - rb[h].rp + rb[h].wp - rb[h].buffer; |
+ |
+ return RB_SUCCESS; |
+} |
Index: instr/drs/rb.h |
=================================================================== |
--- instr/drs/rb.h (nonexistent) |
+++ instr/drs/rb.h (revision 197) |
@@ -0,0 +1,28 @@ |
+/********************************************************************\ |
+ |
+ Name: rb.h |
+ Created by: Stefan Ritt |
+ |
+ Contents: Function declarations and constants for ring buffer |
+ routines |
+ |
+ $Id: rb.h 17217 2011-02-25 15:31:29Z ritt $ |
+ |
+\********************************************************************/ |
+ |
+#define RB_SUCCESS 1 |
+#define RB_NO_MEMORY 2 |
+#define RB_INVALID_PARAM 3 |
+#define RB_INVALID_HANDLE 4 |
+#define RB_TIMEOUT 5 |
+ |
+#define POINTER_T unsigned int |
+ |
+int rb_set_nonblocking(); |
+int rb_create(int size, int max_event_size, int *ring_buffer_handle); |
+int rb_delete(int ring_buffer_handle); |
+int rb_get_wp(int handle, void **p, int millisec); |
+int rb_increment_wp(int handle, int size); |
+int rb_get_rp(int handle, void **p, int millisec); |
+int rb_increment_rp(int handle, int size); |
+int rb_get_buffer_level(int handle, int * n_bytes); |
Index: instr/drs/read_binary.cpp |
=================================================================== |
--- instr/drs/read_binary.cpp (nonexistent) |
+++ instr/drs/read_binary.cpp (revision 197) |
@@ -0,0 +1,250 @@ |
+/* |
+ Name: read_binary.cpp |
+ Created by: Stefan Ritt <stefan.ritt@psi.ch> |
+ Date: July 30th, 2014 |
+ |
+ Purpose: Example file to read binary data saved by DRSOsc. |
+ |
+ Compile and run it with: |
+ |
+ gcc -o read_binary read_binary.cpp |
+ |
+ ./read_binary <filename> |
+ |
+ This program assumes that a pulse from a signal generator is split |
+ and fed into channels #1 and #2. It then calculates the time difference |
+ between these two pulses to show the performance of the DRS board |
+ for time measurements. |
+ |
+ $Id: read_binary.cpp 22321 2016-08-25 12:26:12Z ritt $ |
+*/ |
+ |
+#include <stdio.h> |
+#include <fcntl.h> |
+#include <unistd.h> |
+#include <string.h> |
+#include <math.h> |
+ |
+typedef struct { |
+ char tag[3]; |
+ char version; |
+} FHEADER; |
+ |
+typedef struct { |
+ char time_header[4]; |
+} THEADER; |
+ |
+typedef struct { |
+ char bn[2]; |
+ unsigned short board_serial_number; |
+} BHEADER; |
+ |
+typedef struct { |
+ char event_header[4]; |
+ unsigned int event_serial_number; |
+ unsigned short year; |
+ unsigned short month; |
+ unsigned short day; |
+ unsigned short hour; |
+ unsigned short minute; |
+ unsigned short second; |
+ unsigned short millisecond; |
+ unsigned short range; |
+} EHEADER; |
+ |
+typedef struct { |
+ char tc[2]; |
+ unsigned short trigger_cell; |
+} TCHEADER; |
+ |
+typedef struct { |
+ char c[1]; |
+ char cn[3]; |
+} CHEADER; |
+ |
+/*-----------------------------------------------------------------------------*/ |
+ |
+int main(int argc, const char * argv[]) |
+{ |
+ FHEADER fh; |
+ THEADER th; |
+ BHEADER bh; |
+ EHEADER eh; |
+ TCHEADER tch; |
+ CHEADER ch; |
+ |
+ unsigned int scaler; |
+ unsigned short voltage[1024]; |
+ double waveform[16][4][1024], time[16][4][1024]; |
+ float bin_width[16][4][1024]; |
+ int i, j, b, chn, n, chn_index, n_boards; |
+ double t1, t2, dt; |
+ char filename[256]; |
+ |
+ int ndt; |
+ double threshold, sumdt, sumdt2; |
+ |
+ if (argc > 1) |
+ strcpy(filename, argv[1]); |
+ else { |
+ printf("Usage: read_binary <filename>\n"); |
+ return 0; |
+ } |
+ |
+ // open the binary waveform file |
+ FILE *f = fopen(filename, "rb"); |
+ if (f == NULL) { |
+ printf("Cannot find file \'%s\'\n", filename); |
+ return 0; |
+ } |
+ |
+ // read file header |
+ fread(&fh, sizeof(fh), 1, f); |
+ if (fh.tag[0] != 'D' || fh.tag[1] != 'R' || fh.tag[2] != 'S') { |
+ printf("Found invalid file header in file \'%s\', aborting.\n", filename); |
+ return 0; |
+ } |
+ |
+ if (fh.version != '2') { |
+ printf("Found invalid file version \'%c\' in file \'%s\', should be \'2\', aborting.\n", fh.version, filename); |
+ return 0; |
+ } |
+ |
+ // read time header |
+ fread(&th, sizeof(th), 1, f); |
+ if (memcmp(th.time_header, "TIME", 4) != 0) { |
+ printf("Invalid time header in file \'%s\', aborting.\n", filename); |
+ return 0; |
+ } |
+ |
+ for (b = 0 ; ; b++) { |
+ // read board header |
+ fread(&bh, sizeof(bh), 1, f); |
+ if (memcmp(bh.bn, "B#", 2) != 0) { |
+ // probably event header found |
+ fseek(f, -4, SEEK_CUR); |
+ break; |
+ } |
+ |
+ printf("Found data for board #%d\n", bh.board_serial_number); |
+ |
+ // read time bin widths |
+ memset(bin_width[b], sizeof(bin_width[0]), 0); |
+ for (chn=0 ; chn<5 ; chn++) { |
+ fread(&ch, sizeof(ch), 1, f); |
+ if (ch.c[0] != 'C') { |
+ // event header found |
+ fseek(f, -4, SEEK_CUR); |
+ break; |
+ } |
+ i = ch.cn[2] - '0' - 1; |
+ printf("Found timing calibration for channel #%d\n", i+1); |
+ fread(&bin_width[b][i][0], sizeof(float), 1024, f); |
+ // fix for 2048 bin mode: double channel |
+ if (bin_width[b][i][1023] > 10 || bin_width[b][i][1023] < 0.01) { |
+ for (j=0 ; j<512 ; j++) |
+ bin_width[b][i][j+512] = bin_width[b][i][j]; |
+ } |
+ } |
+ } |
+ n_boards = b; |
+ |
+ // initialize statistics |
+ ndt = 0; |
+ sumdt = sumdt2 = 0; |
+ |
+ // loop over all events in the data file |
+ for (n=0 ; ; n++) { |
+ // read event header |
+ i = (int)fread(&eh, sizeof(eh), 1, f); |
+ if (i < 1) |
+ break; |
+ |
+ printf("Found event #%d %d %d\n", eh.event_serial_number, eh.second, eh.millisecond); |
+ |
+ // loop over all boards in data file |
+ for (b=0 ; b<n_boards ; b++) { |
+ |
+ // read board header |
+ fread(&bh, sizeof(bh), 1, f); |
+ if (memcmp(bh.bn, "B#", 2) != 0) { |
+ printf("Invalid board header in file \'%s\', aborting.\n", filename); |
+ return 0; |
+ } |
+ |
+ // read trigger cell |
+ fread(&tch, sizeof(tch), 1, f); |
+ if (memcmp(tch.tc, "T#", 2) != 0) { |
+ printf("Invalid trigger cell header in file \'%s\', aborting.\n", filename); |
+ return 0; |
+ } |
+ |
+ if (n_boards > 1) |
+ printf("Found data for board #%d\n", bh.board_serial_number); |
+ |
+ // reach channel data |
+ for (chn=0 ; chn<4 ; chn++) { |
+ |
+ // read channel header |
+ fread(&ch, sizeof(ch), 1, f); |
+ if (ch.c[0] != 'C') { |
+ // event header found |
+ fseek(f, -4, SEEK_CUR); |
+ break; |
+ } |
+ chn_index = ch.cn[2] - '0' - 1; |
+ fread(&scaler, sizeof(int), 1, f); |
+ fread(voltage, sizeof(short), 1024, f); |
+ |
+ for (i=0 ; i<1024 ; i++) { |
+ // convert data to volts |
+ waveform[b][chn_index][i] = (voltage[i] / 65536. + eh.range/1000.0 - 0.5); |
+ |
+ // calculate time for this cell |
+ for (j=0,time[b][chn_index][i]=0 ; j<i ; j++) |
+ time[b][chn_index][i] += bin_width[b][chn_index][(j+tch.trigger_cell) % 1024]; |
+ } |
+ } |
+ |
+ // align cell #0 of all channels |
+ t1 = time[b][0][(1024-tch.trigger_cell) % 1024]; |
+ for (chn=1 ; chn<4 ; chn++) { |
+ t2 = time[b][chn][(1024-tch.trigger_cell) % 1024]; |
+ dt = t1 - t2; |
+ for (i=0 ; i<1024 ; i++) |
+ time[b][chn][i] += dt; |
+ } |
+ |
+ t1 = t2 = 0; |
+ threshold = 0.3; |
+ |
+ // find peak in channel 1 above threshold |
+ for (i=0 ; i<1022 ; i++) |
+ if (waveform[b][0][i] < threshold && waveform[b][0][i+1] >= threshold) { |
+ t1 = (threshold-waveform[b][0][i])/(waveform[b][0][i+1]-waveform[b][0][i])*(time[b][0][i+1]-time[b][0][i])+time[b][0][i]; |
+ break; |
+ } |
+ |
+ // find peak in channel 2 above threshold |
+ for (i=0 ; i<1022 ; i++) |
+ if (waveform[b][1][i] < threshold && waveform[b][1][i+1] >= threshold) { |
+ t2 = (threshold-waveform[b][1][i])/(waveform[b][1][i+1]-waveform[b][1][i])*(time[b][1][i+1]-time[b][1][i])+time[b][1][i]; |
+ break; |
+ } |
+ |
+ // calculate distance of peaks with statistics |
+ if (t1 > 0 && t2 > 0) { |
+ ndt++; |
+ dt = t2 - t1; |
+ sumdt += dt; |
+ sumdt2 += dt*dt; |
+ } |
+ } |
+ } |
+ |
+ // print statistics |
+ printf("dT = %1.3lfns +- %1.1lfps\n", sumdt/ndt, 1000*sqrt(1.0/(ndt-1)*(sumdt2-1.0/ndt*sumdt*sumdt))); |
+ |
+ return 1; |
+} |
+ |
Index: instr/drs/readdata.cpp |
=================================================================== |
--- instr/drs/readdata.cpp (nonexistent) |
+++ instr/drs/readdata.cpp (revision 197) |
@@ -0,0 +1 @@ |
+ |
Index: instr/drs/startroot.bat |
=================================================================== |
--- instr/drs/startroot.bat (nonexistent) |
+++ instr/drs/startroot.bat (revision 197) |
@@ -0,0 +1 @@ |
+cmd.exe /k thisroot.bat |
Index: instr/drs/strlcpy.c |
=================================================================== |
--- instr/drs/strlcpy.c (nonexistent) |
+++ instr/drs/strlcpy.c (revision 197) |
@@ -0,0 +1,101 @@ |
+/********************************************************************\ |
+ |
+ Name: strlcpy.c |
+ Created by: Stefan Ritt |
+ Copyright 2000 + Stefan Ritt |
+ |
+ Contents: Contains strlcpy and strlcat which are versions of |
+ strcpy and strcat, but which avoid buffer overflows |
+ |
+ |
+ This file is part of MIDAS XML Library. |
+ |
+ MIDAS XML Library is free software: you can redistribute it and/or modify |
+ it under the terms of the GNU General Public License as published by |
+ the Free Software Foundation, either version 3 of the License, or |
+ (at your option) any later version. |
+ |
+ MIDAS XML Library is distributed in the hope that it will be useful, |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ GNU General Public License for more details. |
+ |
+ You should have received a copy of the GNU General Public License |
+ along with MIDAS XML Library. If not, see <http://www.gnu.org/licenses/>. |
+ |
+\********************************************************************/ |
+ |
+#include <stdio.h> |
+#include <string.h> |
+#include "strlcpy.h" |
+ |
+/* |
+* Copy src to string dst of size siz. At most siz-1 characters |
+* will be copied. Always NUL terminates (unless size == 0). |
+* Returns strlen(src); if retval >= siz, truncation occurred. |
+*/ |
+#ifndef STRLCPY_DEFINED |
+ |
+size_t strlcpy(char *dst, const char *src, size_t size) |
+{ |
+ char *d = dst; |
+ const char *s = src; |
+ size_t n = size; |
+ |
+ /* Copy as many bytes as will fit */ |
+ if (n != 0 && --n != 0) { |
+ do { |
+ if ((*d++ = *s++) == 0) |
+ break; |
+ } while (--n != 0); |
+ } |
+ |
+ /* Not enough room in dst, add NUL and traverse rest of src */ |
+ if (n == 0) { |
+ if (size != 0) |
+ *d = '\0'; /* NUL-terminate dst */ |
+ while (*s++); |
+ } |
+ |
+ return (s - src - 1); /* count does not include NUL */ |
+} |
+ |
+/*-------------------------------------------------------------------*/ |
+ |
+/* |
+* Appends src to string dst of size siz (unlike strncat, siz is the |
+* full size of dst, not space left). At most siz-1 characters |
+* will be copied. Always NUL terminates (unless size <= strlen(dst)). |
+* Returns strlen(src) + MIN(size, strlen(initial dst)). |
+* If retval >= size, truncation occurred. |
+*/ |
+size_t strlcat(char *dst, const char *src, size_t size) |
+{ |
+ char *d = dst; |
+ const char *s = src; |
+ size_t n = size; |
+ size_t dlen; |
+ |
+ /* Find the end of dst and adjust bytes left but don't go past end */ |
+ while (n-- != 0 && *d != '\0') |
+ d++; |
+ dlen = d - dst; |
+ n = size - dlen; |
+ |
+ if (n == 0) |
+ return (dlen + strlen(s)); |
+ while (*s != '\0') { |
+ if (n != 1) { |
+ *d++ = *s; |
+ n--; |
+ } |
+ s++; |
+ } |
+ *d = '\0'; |
+ |
+ return (dlen + (s - src)); /* count does not include NUL */ |
+} |
+ |
+/*-------------------------------------------------------------------*/ |
+ |
+#endif // STRLCPY_DEFINED |
Index: instr/drs/strlcpy.h |
=================================================================== |
--- instr/drs/strlcpy.h (nonexistent) |
+++ instr/drs/strlcpy.h (revision 197) |
@@ -0,0 +1,55 @@ |
+/********************************************************************\ |
+ |
+ Name: strlcpy.h |
+ Created by: Stefan Ritt |
+ Copyright 2000 + Stefan Ritt |
+ |
+ Contents: Header file for strlcpy.c |
+ |
+ This file is part of MIDAS XML Library. |
+ |
+ MIDAS XML Library is free software: you can redistribute it and/or modify |
+ it under the terms of the GNU General Public License as published by |
+ the Free Software Foundation, either version 3 of the License, or |
+ (at your option) any later version. |
+ |
+ MIDAS XML Library is distributed in the hope that it will be useful, |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ GNU General Public License for more details. |
+ |
+ You should have received a copy of the GNU General Public License |
+ along with MIDAS XML Library. If not, see <http://www.gnu.org/licenses/>. |
+ |
+\********************************************************************/ |
+ |
+#ifndef _STRLCPY_H_ |
+#define _STRLCPY_H_ |
+ |
+// some version of gcc have a built-in strlcpy |
+#ifdef strlcpy |
+#define STRLCPY_DEFINED |
+#endif |
+ |
+#ifdef __cplusplus |
+extern "C" { |
+#endif |
+ |
+#ifndef EXPRT |
+#if defined(EXPORT_DLL) |
+#define EXPRT __declspec(dllexport) |
+#else |
+#define EXPRT |
+#endif |
+#endif |
+ |
+#ifndef STRLCPY_DEFINED |
+size_t EXPRT strlcpy(char *dst, const char *src, size_t size); |
+size_t EXPRT strlcat(char *dst, const char *src, size_t size); |
+#endif |
+ |
+#ifdef __cplusplus |
+} |
+#endif |
+ |
+#endif /*_STRLCPY_H_ */ |
Index: instr/drs/thisroot.bat |
=================================================================== |
--- instr/drs/thisroot.bat (nonexistent) |
+++ instr/drs/thisroot.bat (revision 197) |
@@ -0,0 +1,25 @@ |
+@echo off |
+set MPATH=%~dp0 |
+rem set MPATH=%CD% |
+ |
+cd "\" |
+FOR /D %%x in ("Program Files*") do ( |
+ cd /D %%x |
+ if exist "Microsoft SDKs\Windows\v7.1A\Include" set INCLUDE=%INCLUDE%;%CD%%%x\Microsoft SDKs\Windows\v7.1A\Include |
+ For /D %%G in ("Microsoft Visual Studio*") do set VC=%%x\%%G |
+ cd "\" |
+) |
+ |
+echo call "%VC%\VC\vcvarsall.bat" x86 |
+call "%VC%\VC\vcvarsall.bat" x86 |
+ |
+ |
+cd "\" |
+FOR /D %%G IN ("root*") DO SET ROOTSYS=c:\%%G |
+ |
+echo ROOTSYS= "%ROOTSYS%" |
+echo INCLUDE="%INCLUDE%" |
+ |
+echo Visual C Development environment |
+echo nmake -f Makefile.win32 |
+cd /D "%MPATH%" |
\ No newline at end of file |
Index: instr/drs/timer.c |
=================================================================== |
--- instr/drs/timer.c (nonexistent) |
+++ instr/drs/timer.c (revision 197) |
@@ -0,0 +1,142 @@ |
+/* |
+*************************************************************************** |
+* |
+* Author: Teunis van Beelen |
+* |
+* Copyright (C) 2010, 2011, 2012 Teunis van Beelen |
+* |
+* teuniz@gmail.com |
+* |
+*************************************************************************** |
+* |
+* This program is free software; you can redistribute it and/or modify |
+* it under the terms of the GNU General Public License as published by |
+* the Free Software Foundation version 2 of the License. |
+* |
+* This program is distributed in the hope that it will be useful, |
+* but WITHOUT ANY WARRANTY; without even the implied warranty of |
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+* GNU General Public License for more details. |
+* |
+* You should have received a copy of the GNU General Public License along |
+* with this program; if not, write to the Free Software Foundation, Inc., |
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
+* |
+*************************************************************************** |
+* |
+* This version of GPL is at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt |
+* |
+*************************************************************************** |
+*/ |
+ |
+ |
+ |
+#include "timer.h" |
+ |
+ |
+ |
+void (*timer_func_handler_pntr)(void); |
+ |
+ |
+#ifdef __linux__ |
+ |
+void timer_handler(int); |
+ |
+struct itimerval timervalue; |
+ |
+struct sigaction new_handler, old_handler; |
+ |
+void timer_sig_handler(int); |
+ |
+ |
+ |
+int start_timer(int mSec, void (*timer_func_handler)(void)) |
+{ |
+ timer_func_handler_pntr = timer_func_handler; |
+ |
+ timervalue.it_interval.tv_sec = mSec / 1000; |
+ timervalue.it_interval.tv_usec = (mSec % 1000) * 1000; |
+ timervalue.it_value.tv_sec = mSec / 1000; |
+ timervalue.it_value.tv_usec = (mSec % 1000) * 1000; |
+ if(setitimer(ITIMER_REAL, &timervalue, NULL)) |
+ { |
+ printf("\nsetitimer() error\n"); |
+ return(1); |
+ } |
+ |
+ new_handler.sa_handler = &timer_sig_handler; |
+ new_handler.sa_flags = SA_NOMASK; |
+ if(sigaction(SIGALRM, &new_handler, &old_handler)) |
+ { |
+ printf("\nsigaction() error\n"); |
+ return(1); |
+ } |
+ |
+ return(0); |
+} |
+ |
+ |
+void timer_sig_handler(int arg) |
+{ |
+ timer_func_handler_pntr(); |
+} |
+ |
+ |
+void stop_timer(void) |
+{ |
+ timervalue.it_interval.tv_sec = 0; |
+ timervalue.it_interval.tv_usec = 0; |
+ timervalue.it_value.tv_sec = 0; |
+ timervalue.it_value.tv_usec = 0; |
+ setitimer(ITIMER_REAL, &timervalue, NULL); |
+ |
+ sigaction(SIGALRM, &old_handler, NULL); |
+} |
+ |
+#else |
+ |
+HANDLE win_timer; |
+ |
+VOID CALLBACK timer_sig_handler(PVOID, BOOLEAN); |
+ |
+ |
+int start_timer(int mSec, void (*timer_func_handler)(void)) |
+{ |
+ timer_func_handler_pntr = timer_func_handler; |
+ |
+ if(CreateTimerQueueTimer(&win_timer, NULL, (WAITORTIMERCALLBACK)timer_sig_handler, NULL, mSec, mSec, WT_EXECUTEINTIMERTHREAD) == 0) |
+ { |
+ printf("\nCreateTimerQueueTimer() error\n"); |
+ return(1); |
+ } |
+ |
+ return(0); |
+} |
+ |
+ |
+VOID CALLBACK timer_sig_handler(PVOID lpParameter, BOOLEAN TimerOrWaitFired) |
+{ |
+ timer_func_handler_pntr(); |
+} |
+ |
+ |
+void stop_timer(void) |
+{ |
+ DeleteTimerQueueTimer(NULL, win_timer, NULL); |
+ CloseHandle(win_timer); |
+} |
+ |
+#endif |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
Index: instr/drs/timer.h |
=================================================================== |
--- instr/drs/timer.h (nonexistent) |
+++ instr/drs/timer.h (revision 197) |
@@ -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 |
+ |
+ |