Subversion Repositories f9daq

Compare Revisions

Ignore whitespace Rev 196 → Rev 197

/cvi/instr/drsctrl/gettimeofday.c
File deleted
\ No newline at end of file
/cvi/instr/drsctrl/LinkDef.h
File deleted
/cvi/instr/drsctrl/mxml.h
File deleted
/cvi/instr/drsctrl/drsread.c
File deleted
/cvi/instr/drsctrl/gui.cpp
File deleted
/cvi/instr/drsctrl/drs4.prj
File deleted
/cvi/instr/drsctrl/startroot.bat
File deleted
/cvi/instr/drsctrl/gettimeofday.h
File deleted
\ No newline at end of file
/cvi/instr/drsctrl/DRS.cpp
File deleted
/cvi/instr/drsctrl/drsread.h
File deleted
/cvi/instr/drsctrl/XGetopt.cpp
File deleted
/cvi/instr/drsctrl/Makefile
File deleted
/cvi/instr/drsctrl/drs.h
File deleted
/cvi/instr/drsctrl/strlcpy.c
File deleted
/cvi/instr/drsctrl/averager.h
File deleted
/cvi/instr/drsctrl/strlcpy.h
File deleted
/cvi/instr/drsctrl/drscl.cpp
File deleted
/cvi/instr/drsctrl/rb.h
File deleted
/cvi/instr/drsctrl/daq.h
File deleted
/cvi/instr/drsctrl/drs4.c
File deleted
/cvi/instr/drsctrl/drsread.dll
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/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/drsctrl/getopt_long.c
===================================================================
--- instr/drsctrl/getopt_long.c (revision 196)
+++ instr/drsctrl/getopt_long.c (nonexistent)
@@ -1,466 +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_long.c,v 1.3 2008/04/29 05:46:09 martin Exp $
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "getopt.h"
-
-#ifndef _DIAGASSERT
-#define _DIAGASSERT(e)
-#endif
-
-int opterr = 1; /* if error message should be printed */
-int optind = 1; /* index into parent argv vector */
-int optopt = '?'; /* character checked for validity */
-int optreset; /* reset getopt */
-char *optarg; /* argument associated with option */
-
-
-#define IGNORE_FIRST (*options == '-' || *options == '+')
-#define PRINT_ERROR ((opterr) && ((*options != ':') \
- || (IGNORE_FIRST && options[1] != ':')))
-#define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL)
-#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST)
-/* XXX: GNU ignores PC if *options == '-' */
-#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-')
-
-/* return values */
-#define BADCH (int)'?'
-#define BADARG (int)':'
-#define INORDER (int)1
-
-#define EMSG ""
-
-static int getopt_internal(int, char * const *, const char *);
-static int gcd(int, int);
-static void permute_args(int, int, int, char * const *);
-static void xwarnx(const char *, ...);
-
-static char *place = EMSG; /* option letter processing */
-
-/* XXX: set optreset to 1 rather than these two */
-static int nonopt_start = -1; /* first non option argument (for permute) */
-static int nonopt_end = -1; /* first option after non options (for permute) */
-
-/* Error messages */
-static const char recargchar[] = "option requires an argument -- %c";
-static const char recargstring[] = "option requires an argument -- %s";
-static const char ambig[] = "ambiguous option -- %.*s";
-static const char noarg[] = "option doesn't take an argument -- %.*s";
-static const char illoptchar[] = "illegal option -- %c";
-static const char illoptstring[] = "illegal option -- %s";
-
-static const char *progname;
-
-
-/* Replacement for warnx(3) for systems without it. */
-static void xwarnx(const char *fmt, ...) {
- va_list ap;
-
- va_start(ap, fmt);
- if (progname)
- (void) fprintf(stderr, "%s: ", progname);
- if (fmt)
- (void) vfprintf(stderr, fmt, ap);
- (void) fprintf(stderr, "\n");
- va_end(ap);
-}
-
-/*
- * Compute the greatest common divisor of a and b.
- */
-static int
-gcd(int a, int b)
-{
- int c;
-
- c = a % b;
- while (c != 0) {
- a = b;
- b = c;
- c = a % b;
- }
-
- return b;
-}
-
-/*
- * Exchange the block from nonopt_start to nonopt_end with the block
- * from nonopt_end to opt_end (keeping the same order of arguments
- * in each block).
- */
-static void
-permute_args(int nonopt_start, int nonopt_end, int opt_end, char * const *nargv)
-{
- int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
- char *swap;
-
- /*
- * compute lengths of blocks and number and size of cycles
- */
- nnonopts = nonopt_end - nonopt_start;
- nopts = opt_end - nonopt_end;
- ncycle = gcd(nnonopts, nopts);
- cyclelen = (opt_end - nonopt_start) / ncycle;
-
- for (i = 0; i < ncycle; i++) {
- cstart = nonopt_end+i;
- pos = cstart;
- for (j = 0; j < cyclelen; j++) {
- if (pos >= nonopt_end)
- pos -= nnonopts;
- else
- pos += nopts;
- swap = nargv[pos];
- /* LINTED const cast */
- ((char **) nargv)[pos] = nargv[cstart];
- /* LINTED const cast */
- ((char **)nargv)[cstart] = swap;
- }
- }
-}
-
-/*
- * getopt_internal --
- * Parse argc/argv argument vector. Called by user level routines.
- * Returns -2 if -- is found (can be long option or end of options marker).
- */
-static int
-getopt_internal(int nargc, char * const *nargv, const char *options)
-{
- char *oli; /* option letter list index */
- int optchar;
-
- _DIAGASSERT(nargv != NULL);
- _DIAGASSERT(options != NULL);
-
- optarg = NULL;
-
- /*
- * XXX Some programs (like rsyncd) expect to be able to
- * XXX re-initialize optind to 0 and have getopt_long(3)
- * XXX properly function again. Work around this braindamage.
- */
- if (optind == 0)
- optind = 1;
-
- if (optreset)
- nonopt_start = nonopt_end = -1;
-start:
- if (optreset || !*place) { /* update scanning pointer */
- optreset = 0;
- if (optind >= nargc) { /* end of argument vector */
- place = EMSG;
- if (nonopt_end != -1) {
- /* do permutation, if we have to */
- permute_args(nonopt_start, nonopt_end,
- optind, nargv);
- optind -= nonopt_end - nonopt_start;
- }
- else if (nonopt_start != -1) {
- /*
- * If we skipped non-options, set optind
- * to the first of them.
- */
- optind = nonopt_start;
- }
- nonopt_start = nonopt_end = -1;
- return -1;
- }
- if (*(place = nargv[optind]) != '-') { /* found non-option */
- place = EMSG;
- if (IN_ORDER) {
- /*
- * GNU extension:
- * return non-option as argument to option 1
- */
- optarg = nargv[optind++];
- return INORDER;
- }
- if (!PERMUTE) {
- /*
- * if no permutation wanted, stop parsing
- * at first non-option
- */
- return -1;
- }
- /* do permutation */
- if (nonopt_start == -1)
- nonopt_start = optind;
- else if (nonopt_end != -1) {
- permute_args(nonopt_start, nonopt_end,
- optind, nargv);
- nonopt_start = optind -
- (nonopt_end - nonopt_start);
- nonopt_end = -1;
- }
- optind++;
- /* process next argument */
- goto start;
- }
- if (nonopt_start != -1 && nonopt_end == -1)
- nonopt_end = optind;
- if (place[1] && *++place == '-') { /* found "--" */
- place++;
- return -2;
- }
- }
- if ((optchar = (int)*place++) == (int)':' ||
- (oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) {
- /* option letter unknown or ':' */
- if (!*place)
- ++optind;
- if (PRINT_ERROR)
- xwarnx(illoptchar, optchar);
- optopt = optchar;
- return BADCH;
- }
- if (optchar == 'W' && oli[1] == ';') { /* -W long-option */
- /* XXX: what if no long options provided (called by getopt)? */
- if (*place)
- return -2;
-
- if (++optind >= nargc) { /* no arg */
- place = EMSG;
- if (PRINT_ERROR)
- xwarnx(recargchar, optchar);
- optopt = optchar;
- /* XXX: GNU returns '?' if options[0] != ':' */
- return BADARG;
- } else /* white space */
- place = nargv[optind];
- /*
- * Handle -W arg the same as --arg (which causes getopt to
- * stop parsing).
- */
- return -2;
- }
- if (*++oli != ':') { /* doesn't take argument */
- if (!*place)
- ++optind;
- } else { /* takes (optional) argument */
- optarg = NULL;
- if (*place) /* no white space */
- optarg = place;
- /* XXX: disable test for :: if PC? (GNU doesn't) */
- else if (oli[1] != ':') { /* arg not optional */
- if (++optind >= nargc) { /* no arg */
- place = EMSG;
- if (PRINT_ERROR)
- xwarnx(recargchar, optchar);
- optopt = optchar;
- /* XXX: GNU returns '?' if options[0] != ':' */
- return BADARG;
- } else
- optarg = nargv[optind];
- }
- place = EMSG;
- ++optind;
- }
- /* dump back option letter */
- return optchar;
-}
-
-/*
- * getopt --
- * Parse argc/argv argument vector.
- *
- * [eventually this will replace the real getopt]
- */
-int
-getopt(int nargc, char * const *nargv, const char *options)
-{
- int retval;
-
- progname = nargv[0];
-
- if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
- ++optind;
- /*
- * We found an option (--), so if we skipped non-options,
- * we have to permute.
- */
- if (nonopt_end != -1) {
- permute_args(nonopt_start, nonopt_end, optind,
- nargv);
- optind -= nonopt_end - nonopt_start;
- }
- nonopt_start = nonopt_end = -1;
- retval = -1;
- }
- return retval;
-}
-
-/*
- * getopt_long --
- * Parse argc/argv argument vector.
- */
-int
-getopt_long(int nargc,
- char * const *nargv,
- const char *options,
- const struct option *long_options,
- int *idx)
-{
- int retval;
-
- _DIAGASSERT(nargv != NULL);
- _DIAGASSERT(options != NULL);
- _DIAGASSERT(long_options != NULL);
- /* idx may be NULL */
-
- progname = nargv[0];
-
- if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
- char *current_argv, *has_equal;
- size_t current_argv_len;
- int i, match;
-
- current_argv = place;
- match = -1;
-
- optind++;
- place = EMSG;
-
- if (*current_argv == '\0') { /* found "--" */
- /*
- * We found an option (--), so if we skipped
- * non-options, we have to permute.
- */
- if (nonopt_end != -1) {
- permute_args(nonopt_start, nonopt_end,
- optind, nargv);
- optind -= nonopt_end - nonopt_start;
- }
- nonopt_start = nonopt_end = -1;
- return -1;
- }
- if ((has_equal = strchr(current_argv, '=')) != NULL) {
- /* argument found (--option=arg) */
- current_argv_len = has_equal - current_argv;
- has_equal++;
- } else
- current_argv_len = strlen(current_argv);
-
- for (i = 0; long_options[i].name; i++) {
- /* find matching long option */
- if (strncmp(current_argv, long_options[i].name,
- current_argv_len))
- continue;
-
- if (strlen(long_options[i].name) ==
- (unsigned)current_argv_len) {
- /* exact match */
- match = i;
- break;
- }
- if (match == -1) /* partial match */
- match = i;
- else {
- /* ambiguous abbreviation */
- if (PRINT_ERROR)
- xwarnx(ambig, (int)current_argv_len,
- current_argv);
- optopt = 0;
- return BADCH;
- }
- }
- if (match != -1) { /* option found */
- if (long_options[match].has_arg == no_argument
- && has_equal) {
- if (PRINT_ERROR)
- xwarnx(noarg, (int)current_argv_len,
- current_argv);
- /*
- * XXX: GNU sets optopt to val regardless of
- * flag
- */
- if (long_options[match].flag == NULL)
- optopt = long_options[match].val;
- else
- optopt = 0;
- /* XXX: GNU returns '?' if options[0] != ':' */
- return BADARG;
- }
- if (long_options[match].has_arg == required_argument ||
- long_options[match].has_arg == optional_argument) {
- if (has_equal)
- optarg = has_equal;
- else if (long_options[match].has_arg ==
- required_argument) {
- /*
- * optional argument doesn't use
- * next nargv
- */
- optarg = nargv[optind++];
- }
- }
- if ((long_options[match].has_arg == required_argument)
- && (optarg == NULL)) {
- /*
- * Missing argument; leading ':'
- * indicates no error should be generated
- */
- if (PRINT_ERROR)
- xwarnx(recargstring, current_argv);
- /*
- * XXX: GNU sets optopt to val regardless
- * of flag
- */
- if (long_options[match].flag == NULL)
- optopt = long_options[match].val;
- else
- optopt = 0;
- /* XXX: GNU returns '?' if options[0] != ':' */
- --optind;
- return BADARG;
- }
- } else { /* unknown option */
- if (PRINT_ERROR)
- xwarnx(illoptstring, current_argv);
- optopt = 0;
- return BADCH;
- }
- if (long_options[match].flag) {
- *long_options[match].flag = long_options[match].val;
- retval = 0;
- } else
- retval = long_options[match].val;
- if (idx)
- *idx = match;
- }
- return retval;
-}
Index: instr/drsctrl/musbstd.c
===================================================================
--- instr/drsctrl/musbstd.c (revision 196)
+++ instr/drsctrl/musbstd.c (nonexistent)
@@ -1,700 +0,0 @@
-/********************************************************************\
-
- Name: musbstd.c
- Created by: Konstantin Olchanski, Stefan Ritt
-
- Contents: Midas USB access
-
- $Id$
-
-\********************************************************************/
-
-#include <stdio.h>
-#include <assert.h>
-#include "musbstd.h"
-
-#ifdef _MSC_VER // Windows includes
-
-#include <windows.h>
-#include <conio.h>
-#include <winioctl.h>
-
-#include <setupapi.h>
-#include <initguid.h> /* Required for GUID definition */
-
-// link with SetupAPI.Lib.
-#pragma comment (lib, "setupapi.lib")
-
-// disable "deprecated" warning
-#pragma warning( disable: 4996)
-
-// {CBEB3FB1-AE9F-471c-9016-9B6AC6DCD323}
-DEFINE_GUID(GUID_CLASS_MSCB_BULK, 0xcbeb3fb1, 0xae9f, 0x471c, 0x90, 0x16, 0x9b, 0x6a, 0xc6, 0xdc, 0xd3, 0x23);
-
-#elif defined(OS_DARWIN)
-
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <fcntl.h>
-
-#include <assert.h>
-#include <mach/mach.h>
-#include <IOKit/IOKitLib.h>
-#include <IOKit/IOCFPlugIn.h>
-#include <IOKit/usb/IOUSBLib.h>
-
-#elif defined(OS_LINUX) // Linux includes
-
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-
-#endif
-
-#ifdef HAVE_LIBUSB
-#include <errno.h>
-#include "usb.h"
-#endif
-
-#ifdef HAVE_LIBUSB10
-#include <errno.h>
-#include <libusb-1.0/libusb.h>
-#endif
-
-#if !defined(HAVE_LIBUSB) && !defined(HAVE_LIBUSB10)
-#ifdef OS_DARWIN
-
-IOReturn darwin_configure_device(MUSB_INTERFACE* musb)
-{
- IOReturn status;
- io_iterator_t iter;
- io_service_t service;
- IOCFPlugInInterface **plugin;
- SInt32 score;
- IOUSBInterfaceInterface **uinterface;
- UInt8 numend;
-
- IOUSBDeviceInterface **device = (IOUSBDeviceInterface **)musb->device;
-
- status = (*device)->SetConfiguration(device, musb->usb_configuration);
- assert(status == kIOReturnSuccess);
-
- IOUSBFindInterfaceRequest request;
-
- request.bInterfaceClass = kIOUSBFindInterfaceDontCare;
- request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
- request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
- request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
-
- status = (*device)->CreateInterfaceIterator(device, &request, &iter);
- assert(status == kIOReturnSuccess);
-
- while ((service = IOIteratorNext(iter))) {
- int i;
- status =
- IOCreatePlugInInterfaceForService(service, kIOUSBInterfaceUserClientTypeID,
- kIOCFPlugInInterfaceID, &plugin, &score);
- assert(status == kIOReturnSuccess);
-
- status =
- (*plugin)->QueryInterface(plugin, CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID),
- (void *) &uinterface);
- assert(status == kIOReturnSuccess);
-
-
- status = (*uinterface)->USBInterfaceOpen(uinterface);
- fprintf(stderr, "musb_open: USBInterfaceOpen status 0x%x\n", status);
- assert(status == kIOReturnSuccess);
-
- status = (*uinterface)->GetNumEndpoints(uinterface, &numend);
- assert(status == kIOReturnSuccess);
-
- fprintf(stderr, "musb_open: endpoints: %d\n", numend);
-
- for (i=1; i<=numend; i++) {
- status = (*uinterface)->GetPipeStatus(uinterface, i);
- fprintf(stderr, "musb_open: pipe %d status: 0x%x\n", i, status);
-
-#if 0
- status = (*uinterface)->ClearPipeStall(uinterface, i);
- fprintf(stderr, "musb_open: pipe %d ClearPipeStall() status: 0x%x\n", i, status);
- status = (*uinterface)->ResetPipe(uinterface, i);
- fprintf(stderr, "musb_open: pipe %d ResetPipe() status: 0x%x\n", i, status);
- status = (*uinterface)->AbortPipe(uinterface, i);
- fprintf(stderr, "musb_open: pipe %d AbortPipe() status: 0x%x\n", i, status);
-#endif
- }
-
- musb->interface = uinterface;
- return kIOReturnSuccess;
- }
-
- assert(!"Should never be reached!");
- return -1;
-}
-
-#endif
-
-#endif
-
-int musb_open(MUSB_INTERFACE **musb_interface, int vendor, int product, int instance, int configuration, int usbinterface)
-{
-#if defined(HAVE_LIBUSB)
-
- struct usb_bus *bus;
- struct usb_device *dev;
- int count = 0;
-
- usb_init();
- usb_find_busses();
- usb_find_devices();
- usb_set_debug(3);
-
- for (bus = usb_get_busses(); bus; bus = bus->next)
- for (dev = bus->devices; dev; dev = dev->next)
- if (dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product) {
- if (count == instance) {
- int status;
- usb_dev_handle *udev;
-
- udev = usb_open(dev);
- if (!udev) {
- fprintf(stderr, "musb_open: usb_open() error\n");
- return MUSB_ACCESS_ERROR;
- }
-
- status = usb_set_configuration(udev, configuration);
- if (status < 0) {
- fprintf(stderr, "musb_open: usb_set_configuration() error %d (%s)\n", status,
- strerror(-status));
- fprintf(stderr,
- "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it: please check permissions on \"/proc/bus/usb/%s/%s\" and \"/dev/bus/usb/%s/%s\"\n",
- vendor, product, instance, bus->dirname, dev->filename, bus->dirname, dev->filename);
- return MUSB_ACCESS_ERROR;
- }
-
- /* see if we have write access */
- status = usb_claim_interface(udev, usbinterface);
- if (status < 0) {
- fprintf(stderr, "musb_open: usb_claim_interface() error %d (%s)\n", status,
- strerror(-status));
-
-#ifdef _MSC_VER
- fprintf(stderr,
- "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it:\nDevice is probably used by another program\n",
- vendor, product, instance);
-#else
- fprintf(stderr,
- "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it: please check permissions on \"/proc/bus/usb/%s/%s\"\n",
- vendor, product, instance, bus->dirname, dev->filename);
-#endif
-
- return MUSB_ACCESS_ERROR;
- }
-
- *musb_interface = (MUSB_INTERFACE*)calloc(1, sizeof(MUSB_INTERFACE));
- (*musb_interface)->dev = udev;
- (*musb_interface)->usb_configuration = configuration;
- (*musb_interface)->usb_interface = usbinterface;
- return MUSB_SUCCESS;
- }
-
- count++;
- }
-
- return MUSB_NOT_FOUND;
-
-#elif defined(HAVE_LIBUSB10)
-
- static int first_call = 1;
-
- libusb_device **dev_list;
- libusb_device_handle *dev;
- struct libusb_device_descriptor desc;
-
- int status, i, n;
- int count = 0;
-
- if (first_call) {
- first_call = 0;
- libusb_init(NULL);
- // libusb_set_debug(NULL, 3);
- }
-
- n = libusb_get_device_list(NULL, &dev_list);
-
- for (i=0 ; i<n ; i++) {
- status = libusb_get_device_descriptor(dev_list[i], &desc);
- if (desc.idVendor == vendor && desc.idProduct == product) {
- if (count == instance) {
- status = libusb_open(dev_list[i], &dev);
- if (status < 0) {
- fprintf(stderr, "musb_open: libusb_open() error %d\n", status);
- return MUSB_ACCESS_ERROR;
- }
-
- status = libusb_set_configuration(dev, configuration);
- if (status < 0) {
- fprintf(stderr, "musb_open: usb_set_configuration() error %d\n", status);
- fprintf(stderr,
- "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it: please check permissions on \"/proc/bus/usb/%d/%d\" and \"/dev/bus/usb/%d/%d\"\n",
- vendor, product, instance, libusb_get_bus_number(dev_list[i]), libusb_get_device_address(dev_list[i]), libusb_get_bus_number(dev_list[i]), libusb_get_device_address(dev_list[i]));
- return MUSB_ACCESS_ERROR;
- }
-
- /* see if we have write access */
- status = libusb_claim_interface(dev, usbinterface);
- if (status < 0) {
- fprintf(stderr, "musb_open: libusb_claim_interface() error %d\n", status);
-
-#ifdef _MSC_VER
- fprintf(stderr,
- "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it:\nDevice is probably used by another program\n",
- vendor, product, instance);
-#else
- fprintf(stderr,
- "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it: please check permissions on \"/proc/bus/usb/%d/%d\"\n",
- vendor, product, instance, libusb_get_bus_number(dev_list[i]), libusb_get_device_address(dev_list[i]));
-#endif
-
- return MUSB_ACCESS_ERROR;
- }
-
- *musb_interface = (MUSB_INTERFACE*)calloc(1, sizeof(MUSB_INTERFACE));
- (*musb_interface)->dev = dev;
- (*musb_interface)->usb_configuration = configuration;
- (*musb_interface)->usb_interface = usbinterface;
- return MUSB_SUCCESS;
-
- }
- count++;
- }
- }
-
- libusb_free_device_list(dev_list, 1);
-
- return MUSB_NOT_FOUND;
-
-#elif defined(OS_DARWIN)
-
- kern_return_t status;
- io_iterator_t iter;
- io_service_t service;
- IOCFPlugInInterface **plugin;
- SInt32 score;
- IOUSBDeviceInterface **device;
- UInt16 xvendor, xproduct;
- int count = 0;
-
- *musb_interface = calloc(1, sizeof(MUSB_INTERFACE));
-
- status = IORegistryCreateIterator(kIOMasterPortDefault, kIOUSBPlane, kIORegistryIterateRecursively, &iter);
- assert(status == kIOReturnSuccess);
-
- while ((service = IOIteratorNext(iter))) {
- status =
- IOCreatePlugInInterfaceForService(service, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID,
- &plugin, &score);
- assert(status == kIOReturnSuccess);
-
- status = IOObjectRelease(service);
- assert(status == kIOReturnSuccess);
-
- status =
- (*plugin)->QueryInterface(plugin, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (void *) &device);
- assert(status == kIOReturnSuccess);
-
- status = (*plugin)->Release(plugin);
-
- status = (*device)->GetDeviceVendor(device, &xvendor);
- assert(status == kIOReturnSuccess);
- status = (*device)->GetDeviceProduct(device, &xproduct);
- assert(status == kIOReturnSuccess);
-
- //fprintf(stderr, "musb_open: Found USB device: vendor 0x%04x, product 0x%04x\n", xvendor, xproduct);
-
- if (xvendor == vendor && xproduct == product) {
- if (count == instance) {
-
- fprintf(stderr, "musb_open: Found USB device: vendor 0x%04x, product 0x%04x, instance %d\n", xvendor, xproduct, instance);
-
- status = (*device)->USBDeviceOpen(device);
- fprintf(stderr, "musb_open: USBDeviceOpen status 0x%x\n", status);
-
- assert(status == kIOReturnSuccess);
-
- (*musb_interface)->usb_configuration = configuration;
- (*musb_interface)->usb_interface = usbinterface;
- (*musb_interface)->device = (void*)device;
- (*musb_interface)->interface = NULL;
-
- status = darwin_configure_device(*musb_interface);
-
- if (status == kIOReturnSuccess)
- return MUSB_SUCCESS;
-
- fprintf(stderr, "musb_open: USB device exists, but configuration fails!");
- return MUSB_NOT_FOUND;
- }
-
- count++;
- }
-
- (*device)->Release(device);
- }
-
- return MUSB_NOT_FOUND;
-#elif defined(_MSC_VER)
- GUID guid;
- HDEVINFO hDevInfoList;
- SP_DEVICE_INTERFACE_DATA deviceInfoData;
- PSP_DEVICE_INTERFACE_DETAIL_DATA functionClassDeviceData;
- ULONG predictedLength, requiredLength;
- int status;
- char device_name[256], str[256];
-
- *musb_interface = (MUSB_INTERFACE *)calloc(1, sizeof(MUSB_INTERFACE));
-
- guid = GUID_CLASS_MSCB_BULK;
-
- // Retrieve device list for GUID that has been specified.
- hDevInfoList = SetupDiGetClassDevs(&guid, NULL, NULL, (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
-
- status = FALSE;
- if (hDevInfoList != NULL) {
-
- // Clear data structure
- memset(&deviceInfoData, 0, sizeof(deviceInfoData));
- deviceInfoData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
-
- // retrieves a context structure for a device interface of a device information set.
- if (SetupDiEnumDeviceInterfaces(hDevInfoList, 0, &guid, instance, &deviceInfoData)) {
- // Must get the detailed information in two steps
- // First get the length of the detailed information and allocate the buffer
- // retrieves detailed information about a specified device interface.
- functionClassDeviceData = NULL;
-
- predictedLength = requiredLength = 0;
-
- SetupDiGetDeviceInterfaceDetail(hDevInfoList, &deviceInfoData, NULL, // Not yet allocated
- 0, // Set output buffer length to zero
- &requiredLength, // Find out memory requirement
- NULL);
-
- predictedLength = requiredLength;
- functionClassDeviceData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) malloc(predictedLength);
- functionClassDeviceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
-
- // Second, get the detailed information
- if (SetupDiGetDeviceInterfaceDetail(hDevInfoList,
- &deviceInfoData, functionClassDeviceData,
- predictedLength, &requiredLength, NULL)) {
-
- // Save the device name for subsequent pipe open calls
- strcpy(device_name, functionClassDeviceData->DevicePath);
- free(functionClassDeviceData);
-
- // Signal device found
- status = TRUE;
- } else
- free(functionClassDeviceData);
- }
- }
- // SetupDiDestroyDeviceInfoList() destroys a device information set
- // and frees all associated memory.
- SetupDiDestroyDeviceInfoList(hDevInfoList);
-
- if (status) {
-
- // Get the read handle
- sprintf(str, "%s\\PIPE00", device_name);
- (*musb_interface)->rhandle = CreateFile(str,
- GENERIC_WRITE | GENERIC_READ,
- FILE_SHARE_WRITE | FILE_SHARE_READ, NULL,
- OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
-
- if ((*musb_interface)->rhandle == INVALID_HANDLE_VALUE)
- return MUSB_ACCESS_ERROR;
-
- // Get the write handle
- sprintf(str, "%s\\PIPE01", device_name);
- (*musb_interface)->whandle = CreateFile(str,
- GENERIC_WRITE | GENERIC_READ,
- FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
-
- if ((*musb_interface)->whandle == INVALID_HANDLE_VALUE)
- return MUSB_ACCESS_ERROR;
-
- return MUSB_SUCCESS;
- }
-
- return MUSB_NOT_FOUND;
-#endif
-}
-
-int musb_set_altinterface(MUSB_INTERFACE *musb_interface, int index)
-{
-#if defined (HAVE_LIBUSB)
- int status;
-
- status = usb_set_altinterface(musb_interface->dev, index);
- if (status < 0)
- fprintf(stderr, "musb_set_altinterface: usb_set_altinterface() error %d\n", status);
-
- return status;
-#else
- return -1;
-#endif
-}
-
-int musb_close(MUSB_INTERFACE *musb_interface)
-{
-#if defined(HAVE_LIBUSB)
-
- int status;
- status = usb_release_interface(musb_interface->dev, musb_interface->usb_interface);
- if (status < 0)
- fprintf(stderr, "musb_close: usb_release_interface() error %d\n", status);
-
-#ifdef OS_LINUX // linux wants a reset, otherwise the device cannot be accessed next time
- musb_reset(musb_interface);
-#endif
-
- status = usb_close(musb_interface->dev);
- if (status < 0)
- fprintf(stderr, "musb_close: usb_close() error %d\n", status);
-
-#elif defined(HAVE_LIBUSB10)
-
- int status;
- status = libusb_release_interface(musb_interface->dev, musb_interface->usb_interface);
- if (status < 0)
- fprintf(stderr, "musb_close: libusb_release_interface() error %d\n", status);
-
-#ifdef OS_LINUX // linux wants a reset, otherwise the device cannot be accessed next time
- musb_reset(musb_interface);
-#endif
-
- libusb_close(musb_interface->dev);
-
-#elif defined(OS_DARWIN)
-
- IOReturn status;
- IOUSBInterfaceInterface **interface = (IOUSBInterfaceInterface **)musb_interface->interface;
-
- status = (*interface)->USBInterfaceClose(interface);
- if (status != kIOReturnSuccess)
- fprintf(stderr, "musb_close: USBInterfaceClose() status %d 0x%x\n", status, status);
-
- status = (*interface)->Release(interface);
- if (status != kIOReturnSuccess)
- fprintf(stderr, "musb_close: USB Interface Release() status %d 0x%x\n", status, status);
-
- IOUSBDeviceInterface **device = (IOUSBDeviceInterface**)musb_interface->device;
- status = (*device)->USBDeviceClose(device);
- if (status != kIOReturnSuccess)
- fprintf(stderr, "musb_close: USBDeviceClose() status %d 0x%x\n", status, status);
-
- status = (*device)->Release(device);
- if (status != kIOReturnSuccess)
- fprintf(stderr, "musb_close: USB Device Release() status %d 0x%x\n", status, status);
-
-#elif defined(_MSC_VER)
-
- CloseHandle(musb_interface->rhandle);
- CloseHandle(musb_interface->whandle);
-
-#else
- assert(!"musb_close() is not implemented");
-#endif
-
- /* free memory allocated in musb_open() */
- free(musb_interface);
- return 0;
-}
-
-int musb_write(MUSB_INTERFACE *musb_interface, int endpoint, const void *buf, int count, int timeout)
-{
- int n_written;
-
-#if defined(HAVE_LIBUSB)
- n_written = usb_bulk_write(musb_interface->dev, endpoint, (char*)buf, count, timeout);
- if (n_written != count) {
- fprintf(stderr, "musb_write: requested %d, wrote %d, errno %d (%s)\n", count, n_written, errno, strerror(errno));
- }
-#elif defined(HAVE_LIBUSB10)
- int status = libusb_bulk_transfer(musb_interface->dev, endpoint, (unsigned char*)buf, count, &n_written, timeout);
- if (n_written != count) {
- fprintf(stderr, "musb_write: requested %d, wrote %d, errno %d (%s)\n", count, n_written, status, strerror(status));
- }
-#elif defined(OS_DARWIN)
- IOReturn status;
- IOUSBInterfaceInterface182 **interface = (IOUSBInterfaceInterface182 **)musb_interface->interface;
- status = (*interface)->WritePipeTO(interface, endpoint, buf, count, 0, timeout);
- if (status != 0) {
- fprintf(stderr, "musb_write: WritePipe() status %d 0x%x\n", status, status);
- return -1;
- }
- n_written = count;
-#elif defined(_MSC_VER)
- WriteFile(musb_interface->whandle, buf, count, &n_written, NULL);
-#endif
-
- //fprintf(stderr, "musb_write(ep %d, %d bytes) (%s) returns %d\n", endpoint, count, buf, n_written);
-
- return n_written;
-}
-
-int musb_read(MUSB_INTERFACE *musb_interface, int endpoint, void *buf, int count, int timeout)
-{
- int n_read = 0;
-
-#if defined(HAVE_LIBUSB)
-
- n_read = usb_bulk_read(musb_interface->dev, endpoint | 0x80, (char*)buf, count, timeout);
- /* errors should be handled in upper layer ....
- if (n_read <= 0) {
- fprintf(stderr, "musb_read: requested %d, read %d, errno %d (%s)\n", count, n_read, errno, strerror(errno));
- }
- */
-
-#elif defined(HAVE_LIBUSB10)
-
- libusb_bulk_transfer(musb_interface->dev, endpoint | 0x80, (unsigned char*)buf, count, &n_read, timeout);
- /* errors should be handled in upper layer ....
- if (n_read <= 0) {
- fprintf(stderr, "musb_read: requested %d, read %d, errno %d (%s)\n", count, n_read, status, strerror(status));
- }
- */
-
-#elif defined(OS_DARWIN)
-
- UInt32 xcount = count;
- IOReturn status;
- IOUSBInterfaceInterface182 **interface = (IOUSBInterfaceInterface182 **)musb_interface->interface;
-
- status = (*interface)->ReadPipeTO(interface, endpoint, buf, &xcount, 0, timeout);
- if (status != kIOReturnSuccess) {
- fprintf(stderr, "musb_read: requested %d, read %d, ReadPipe() status %d 0x%x (%s)\n", count, n_read, status, status, strerror(status));
- return -1;
- }
-
- n_read = xcount;
-
-#elif defined(_MSC_VER)
-
- OVERLAPPED overlapped;
- int status;
-
- memset(&overlapped, 0, sizeof(overlapped));
- overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
- n_read = 0;
-
- status = ReadFile(musb_interface->rhandle, buf, count, &n_read, &overlapped);
-
- if (!status) {
-
- status = GetLastError();
- if (status != ERROR_IO_PENDING)
- return 0;
-
- /* wait for completion with timeout */
- status = WaitForSingleObject(overlapped.hEvent, timeout);
- if (status == WAIT_TIMEOUT)
- CancelIo(musb_interface->rhandle);
- else
- GetOverlappedResult(musb_interface->rhandle, &overlapped, &n_read, FALSE);
- }
-
- CloseHandle(overlapped.hEvent);
-
-#endif
-
- //fprintf(stderr, "musb_read(ep %d, %d bytes) returns %d (%s)\n", endpoint, count, n_read, buf);
-
- return n_read;
-}
-
-int musb_reset(MUSB_INTERFACE *musb_interface)
-{
-#if defined(HAVE_LIBUSB)
-
- /* Causes re-enumeration: After calling usb_reset, the device will need
- to re-enumerate and thusly, requires you to find the new device and
- open a new handle. The handle used to call usb_reset will no longer work */
-
- int status;
- status = usb_reset(musb_interface->dev);
- if (status < 0)
- fprintf(stderr, "musb_reset: usb_reset() status %d\n", status);
-
-#elif defined(HAVE_LIBUSB10)
-
- int status;
- status = libusb_reset_device(musb_interface->dev);
- if (status < 0)
- fprintf(stderr, "musb_reset: usb_reset() status %d\n", status);
-
-#elif defined(OS_DARWIN)
-
- IOReturn status;
- IOUSBDeviceInterface **device = (IOUSBDeviceInterface**)musb_interface->device;
-
- status = (*device)->ResetDevice(device);
- fprintf(stderr, "musb_reset: ResetDevice() status 0x%x\n", status);
-
- status = darwin_configure_device(musb_interface);
- assert(status == kIOReturnSuccess);
-
-#elif defined(_MSC_VER)
-
-#define IOCTL_BULKUSB_RESET_DEVICE CTL_CODE(FILE_DEVICE_UNKNOWN, \
- 1, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-#define IOCTL_BULKUSB_RESET_PIPE CTL_CODE(FILE_DEVICE_UNKNOWN, \
- 2, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
- int status, n_bytes;
-
- status = DeviceIoControl(musb_interface->rhandle,
- IOCTL_BULKUSB_RESET_DEVICE,
- NULL, 0, NULL, 0, &n_bytes, NULL);
- status = DeviceIoControl(musb_interface->whandle,
- IOCTL_BULKUSB_RESET_DEVICE,
- NULL, 0, NULL, 0, &n_bytes, NULL);
- status = DeviceIoControl(musb_interface->rhandle,
- IOCTL_BULKUSB_RESET_PIPE,
- NULL, 0, NULL, 0, &n_bytes, NULL);
- status = DeviceIoControl(musb_interface->whandle,
- IOCTL_BULKUSB_RESET_PIPE,
- NULL, 0, NULL, 0, &n_bytes, NULL);
- return status;
-
-#endif
- return 0;
-}
-
-int musb_get_device(MUSB_INTERFACE *usb_interface)
-{
-#ifdef HAVE_LIBUSB
- struct usb_device_descriptor d;
- usb_get_descriptor(usb_interface->dev, USB_DT_DEVICE, 0, &d, sizeof(d));
- return d.bcdDevice;
-#elif HAVE_LIBUSB10
- struct libusb_device_descriptor d;
- libusb_get_descriptor(usb_interface->dev, LIBUSB_DT_DEVICE, 0, (unsigned char *)&d, sizeof(d));
- return d.bcdDevice;
-#else
- return 0;
-#endif
-}
-
-/* end */
Index: instr/drsctrl/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.cpp
===================================================================
--- instr/drsctrl/drsread.cpp (revision 196)
+++ instr/drsctrl/drsread.cpp (nonexistent)
@@ -1,620 +0,0 @@
-/********************************************************************\
-
- Name: drsread.cpp
- Created by: Rok Pestotnik
-
- Contents: Simple example application to read out a DRS4
- evaluation board and save into the data file
- Interface dll for LabWindows CVI
-
-\********************************************************************/
-#ifdef DLLMAIN
-#define DLLEXPORT __declspec(dllexport)
-#else
-#define DLLEXPORT
-#endif
-
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <math.h>
-#include <time.h>
-#include <signal.h>
-
-#include <TFile.h>
-#include <TH2F.h>
-#include <TCanvas.h>
-//#include <TApplication.h>
-
-#ifdef _MSC_VER
-
-#include "gettimeofday.h"
-#include "timer.h"
-
-#define DIR_SEPARATOR '\\'
-
-#elif defined(OS_LINUX) || defined(OS_DARWIN)
-
-#define O_BINARY 0
-#include <unistd.h>
-#include <ctype.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#define DIR_SEPARATOR '/'
-#endif
-
-#include "DRS.h"
-#include "drsread.h"
-
-
-/*------------------------------------------------------------------*/
-class drssettings {
- static drssettings *s_instance;
-public:
- drssettings(){
- mask = 0xF;
- range = 0;
- trigger_type = 1;
- sampling_frequency = 5;
- trigger_delay = 0;
- trigger_channel=0;
- trigger_polarity=false;
- trigger_level=0.05;
-
- };
- ~drssettings(){};
- static drssettings *instance()
- {
- if (!s_instance)
- s_instance = new drssettings;
- return s_instance;
- };
-
-
- unsigned char mask;
- double range;
- int trigger_type; // 0 software, 1 fast hardware, 2 slow hardware
- int trigger_channel;
- int sampling_frequency;
- double trigger_delay;
- double trigger_level;
- bool trigger_polarity;
-};
-drssettings *drssettings::s_instance = 0;
-drssettings *DRSParameters;
-DLLEXPORT void DRSSetMask(int mask){ drssettings::instance()->mask;};
-DLLEXPORT void DRSSetTriggerType(int type){ drssettings::instance()->trigger_type = type;};
-DLLEXPORT void DRSSetFrequency(int freq){ drssettings::instance()->sampling_frequency = freq;};
-DLLEXPORT void DRSSetRange(double range){ drssettings::instance()->range = range;};
-DLLEXPORT void DRSSetTriggerChannel(int channel){ drssettings::instance()->trigger_channel = channel;};
-DLLEXPORT void DRSSetTriggerDelay(double delay){ drssettings::instance()->trigger_delay = delay;};
-DLLEXPORT void DRSSetTriggerLevel(double level){ drssettings::instance()->trigger_level = level;};
-DLLEXPORT void DRSSetTriggerPolarity(int polarity){ drssettings::instance()->trigger_polarity = (polarity==1);};
-
-
-static int DRSTimeout;
-
-DLLEXPORT int DRSIsTimeout()
-{
- return DRSTimeout;
-}
-
-DLLEXPORT void DRSSetTimeout ( void )
-{
- DRSTimeout=1;
- printf("->>> Timer Out !!!\n");
-}
-
-static DRS *drs=NULL;
-
-DLLEXPORT int DRSInit()
-{
-
- DRSBoard *b;
- /* do drsinitial scan */
- drs = new DRS();
- if (!drs) return -1;
- DRSParameters = drssettings::instance();
-
- /* show any found board(s) */
- for (int i=0 ; i<drs->GetNumberOfBoards() ; i++) {
- b = drs->GetBoard(i);
- printf("Found DRS4 evaluation board, serial #%d, firmware revision %d\n",
- b->GetBoardSerialNumber(), b->GetFirmwareVersion());
- }
-
- /* exit if no board found */
- int nBoards = drs->GetNumberOfBoards();
- if (nBoards == 0) {
- printf("No DRS4 evaluation board found\n");
- return -2;
- }
-
- /* continue working with first board only */
- b = drs->GetBoard(0);
-
- /* drsinitialize board */
- b->Init();
-
- /* set sampling frequency default 5 */
- b->SetFrequency(DRSParameters->sampling_frequency, true);
-
- /* enable transparent mode needed for analog trigger */
- b->SetTranspMode(1);
-
- /* set input range to -0.5V ... +0.5V -> range=0 */
- b->SetInputRange(DRSParameters->range);
-
- /* use following line to set range to 0..1V */
- //b->SetInputRange(0.5);
-
- /* use following line to turn on the internal 100 MHz clock connected to all channels */
- //b->EnableTcal(1);
-
- /* kaj je to ....
- // Set domino mode
- // mode == 0: single sweep
- // mode == 1: run continously -- default
- b->SetDominoMode(1);
- // Set domino activity
- // mode == 0: stop during readout
- // mode == 1: keep domino wave running -- default
- //
- b->SetDominoActive(1);
-
- // Set readout mode
- // mode == 0: start from first bin -- default
- // mode == 1: start from domino stop
- //
- b->SetReadoutMode(1);
- */
-
- /* use following lines to enable hardware trigger on CH1 at 50 mV positive edge */
- printf("Board Type:%d\n",b->GetBoardType() );
- if (b->GetBoardType() >= 8) { // Evaluaiton Board V4&5
-
- b->EnableTrigger(DRSParameters->trigger_type, 0); // enable hardware trigger - 1 fast trigger, 2 slow trigger, 0 disable hw trigger
- b->SetTriggerSource(1<<DRSParameters->trigger_channel); // set CH1 as source // simple or of single channel
- } else if (b->GetBoardType() == 7) { // Evaluation Board V3
- b->EnableTrigger(0, 1); // lemo off, analog trigger on
- b->SetTriggerSource(0); // use CH1 as source
- }
- b->SetTriggerLevel(DRSParameters->trigger_level); // 0.05 V
- b->SetTriggerPolarity(DRSParameters->trigger_polarity); // positive edge
-
- /* use following lines to set individual trigger elvels */
- //b->SetIndividualTriggerLevel(1, 0.1);
- //b->SetIndividualTriggerLevel(2, 0.2);
- //b->SetIndividualTriggerLevel(3, 0.3);
- //b->SetIndividualTriggerLevel(4, 0.4);
- //b->SetTriggerSource(15);
-
- b->SetTriggerDelayNs( DRSParameters->trigger_delay); // zero ns trigger delay
-
- /* use following lines to enable the external trigger */
- //if (b->GetBoardType() == 8) { // Evaluaiton Board V4
- // b->EnableTrigger(1, 0); // enable hardware trigger
- // b->SetTriggerSource(1<<4); // set external trigger as source
- //} else { // Evaluation Board V3
- // b->EnableTrigger(1, 0); // lemo on, analog trigger off
- // }
-
- return 0;
-
-
-}
-
-static float DRSTimeArray[8][1024];
-static float DRSWaveArray[8][1024];
-
-DLLEXPORT float * DRSGetTime(int ch){ return DRSTimeArray[ch];}
-DLLEXPORT float * DRSGetWave(int ch){ return DRSWaveArray[ch];}
-
-DLLEXPORT int DRSRead( int DRStimer)
-{
-
- DRSBoard *b = drs->GetBoard(0);
-
-
-
- /* wait for trigger */
-
-
- int tout=1000; /* timeout in mili seconds */
- DRSTimeout=0;
-
- if (DRStimer) start_timer(tout, &DRSSetTimeout);
-
- /* start board (activate domino wave) */
- b->StartDomino();
-
- if (!DRSParameters->trigger_type) b->SoftTrigger();
-
- while (b->IsBusy()){
-
- if (DRSTimeout) {
- printf("Waiting for Trigger.. at line %d\n", __LINE__);
-
- if (DRStimer) stop_timer();
-
- return -1;
- }
- };
-
-
- if (DRStimer) stop_timer();
-
-
-
- /* read all waveforms */
- b->TransferWaves(0, 8);
-
-
- for (int k=0;k<4;k++){
- if (! (DRSParameters->mask & ( 0x1<<k )) ) continue;
- /* Note: On the evaluation board input #1 is connected to channel 0 and 1 of
- the DRS chip, input #2 is connected to channel 2 and 3 and so on. So to
- get the input #2 we have to read DRS channel #2, not #1. */
-
- /* read time (X) array of k-th channel in ns and waveform (Y) array of k-th channel in mV */
- b->GetTime(0, 2*k, b->GetTriggerCell(DRSParameters->trigger_channel), DRSTimeArray[k]);
- b->GetWave(0, 2*k, DRSWaveArray[k]);
-
-
- }
-
- return 0;
-}
-
-DLLEXPORT int DRSEnd(){
-
- /* delete DRS object -> close USB connection */
- if (drs) delete drs;
- drs = NULL;
- return 0;
-}
-
-
-
-DLLEXPORT int DRSToBuffer( unsigned char *p, int m_evSerial )
-{
-
- unsigned short d;
- float t;
- unsigned char *p0 = p;
-
- int m_nBoards = drs->GetNumberOfBoards();
- int m_waveDepth = 1024 ;// 2048
- int m_inputRange = drs->GetBoard(0)->GetInputRange();
- time_t rawtime;
- time ( &rawtime );
- struct tm m_evTimestamp;
- m_evTimestamp = *(localtime ( &rawtime ));
- struct timeval mtime;
- gettimeofday(&mtime, NULL);
-
- if (m_evSerial == 0) {
- // time calibration header
- memcpy(p, "TIME", 4);
- p += 4;
-
- for (int b=0 ; b<m_nBoards ; b++) {
- // store board serial number
- sprintf((char *)p, "B#");
- p += 2;
- *(unsigned short *)p = drs->GetBoard(b)->GetBoardSerialNumber();
- p += sizeof(unsigned short);
-
- for (int i=0 ; i<4 ; i++) {
- if (DRSParameters->mask & (0x1<<i)) {
- sprintf((char *)p, "C%03d", i+1);
- p += 4;
- float tcal[2048];
- drs->GetBoard(b)->GetTimeCalibration(0, i*2, 0, tcal, 0);
- for (int j=0 ; j<m_waveDepth ; j++) {
- // save binary time as 32-bit float value
- if (m_waveDepth == 2048) {
- t = (tcal[j]+tcal[j+1])/2;
- j++;
- } else
- t = tcal[j];
- *(float *)p = t;
- p += sizeof(float);
- }
- }
- }
- }
- }
-
-
-
- memcpy(p, "EHDR", 4);
- p += 4;
- *(int *)p = m_evSerial;
- p += sizeof(int);
- *(unsigned short *)p = m_evTimestamp.tm_year;
- p += sizeof(unsigned short);
- *(unsigned short *)p = m_evTimestamp.tm_mon;
- p += sizeof(unsigned short);
- *(unsigned short *)p = m_evTimestamp.tm_mday;
- p += sizeof(unsigned short);
- *(unsigned short *)p = m_evTimestamp.tm_hour;
- p += sizeof(unsigned short);
- *(unsigned short *)p = m_evTimestamp.tm_min;
- p += sizeof(unsigned short);
- *(unsigned short *)p = m_evTimestamp.tm_sec;
- p += sizeof(unsigned short);
- *(unsigned short *)p = mtime.tv_usec/1000;
- p += sizeof(unsigned short);
- *(unsigned short *)p = (unsigned short)(m_inputRange * 1000); // range
- p += sizeof(unsigned short);
-
- int b=0; // only for board 0
-
- // store board serial number
- sprintf((char *)p, "B#");
- p += 2;
- *(unsigned short *)p = drs->GetBoard(b)->GetBoardSerialNumber();
- p += sizeof(unsigned short);
-
- // store trigger cell
- sprintf((char *)p, "T#");
- p += 2;
- *(unsigned short *)p = drs->GetBoard(b)->GetTriggerCell(DRSParameters->trigger_channel);
- p += sizeof(unsigned short);
-
- for (int i=0 ; i<4 ; i++) {
- if (DRSParameters->mask & (0x1<<i)) {
- sprintf((char *)p, "C%03d", i+1);
- p += 4;
- for (int j=0 ; j<m_waveDepth ; j++) {
- // save binary date as 16-bit value:
- // 0 = -0.5V, 65535 = +0.5V for range 0
- // 0 = -0.05V, 65535 = +0.95V for range 0.45
- if (m_waveDepth == 2048) {
- // in cascaded mode, save 1024 values as averages of the 2048 values
- d = (unsigned short)(((DRSWaveArray[i][j]+DRSWaveArray[i][j+1])/2000.0 - m_inputRange + 0.5) * 65535);
- *(unsigned short *)p = d;
- p += sizeof(unsigned short);
- j++;
- } else {
- d = (unsigned short)((DRSWaveArray[i][j]/1000.0 - m_inputRange + 0.5) * 65535);
- *(unsigned short *)p = d;
- p += sizeof(unsigned short);
- }
- }
- }
- }
-
- return (p-p0); // return number of bytes
-}
-
-
-
-#ifdef MAIN
-
-
-
-#include "XGetopt.h"
-#include "getopt.h"
-
-TH2F *h[4];
-
-typedef struct {
- char recid[4];
- unsigned int posx, posy, posz;
- unsigned int iposx, iposy, iposz;
-} POSREC;
-
-
-int help() {
- printf ("*********************************************************************************:\n");
- printf ("Usage: Read of the DRS4 PSI board and dump of the waveforms in the file:\n\n");
- printf ("Arguments: \n");
- printf ("-v verbosity \n");
- printf ("-a output rootfile \n");
- printf ("-o output filename \n");
- printf ("-r output root filename \n");
- printf ("-n number of events\n");
- printf ("-m channel bit mask\n");
- printf ("-h trigger type (0 software, 1 fast hardware, 2 slow hardware)\n");
- printf ("-d trigger delay in ns\n");
- printf ("-f sampling frequency\n");
- printf ("-t trigger channel\n");
- printf ("-l trigger level\n");
- printf ("-p trigger polarity (0 positive\n");
- printf ("*********************************************************************************:\n");
- printf ("Examples:\n\n");
-
- return 0;
-}
-
-
-
-char filename[0xFF]="";
-char rootfile[0xFF]="";
-int neve = 0;
-int verbose = 0;
-
-void Init(int argc, char **argv){
- DRSParameters = drssettings::instance();
- char c;
-
- extern char *optarg;
- extern int optind;
- extern int optopt;
- while ((c = getopt (argc, argv, "a:o:v:m:n:f:d:r:h:t:p:l:")) != -1){
-
- switch (c)
- {
-
- case 'a':
- sprintf(rootfile,"%s", optarg );
- break; // root output
-
- case 'o':
- sprintf(filename,"%s", optarg );
- break; // output
-
- case 'v':
- verbose = atoi(optarg);
- break; // verbosity
- case 'm':{
- unsigned long ul = strtoul (optarg,NULL,0);
- DRSSetMask( (unsigned char)( ul & 0xF ) ) ;
- break;
- } // channel mask
- case 'n':
- neve = atoi (optarg);
- break; // number of events or number of scan points
-
- case 'f':
- DRSSetFrequency( atoi (optarg) );
- break; // sampling frequency
-
- case 'd':
- DRSSetTriggerDelay( atof (optarg) );
- break; // trigger delay
- case 'p':
- DRSSetTriggerPolarity( atoi (optarg));
- break; // trigger polarity
- case 'l':
- DRSSetTriggerLevel(atoi (optarg));
- break; // trigger level
-
-
- case 'r':
- DRSSetRange ( atof (optarg) );
- break; // range
- case 'h':
- DRSSetTriggerType( atoi (optarg) );
- break; // send sotware trigger before reading out the dat
- case 't':
- DRSSetTriggerChannel( atoi(optarg) );
- break; // trigger channel
-
-
- case '?':
- if (optopt == 'c')
- fprintf (stderr, "Option -%c requires an argument.\n", optopt);
- else if (isprint (optopt))
- fprintf (stderr, "Unknown option `-%c'.\n", optopt);
- else
- fprintf (stderr,
- "Unknown option character `\\x%x'.\n",
- optopt);
- abort ();
- default:
- abort ();
- }
- }
- //for (int i=optind; i<argc; i++) data = strtoul (argv[i],NULL,0);
-
-}
-
-int ctrl_c=0;
-DLLEXPORT void DRSSigInt ( int )
-{
- ctrl_c = 1;
- printf("->>> CTRL+c !!!\n");
-}
-
-//#ifdef __CINT__
-int main(int argc, char **argv){
-//#else
-//int drsread(int argc, char **argv){
-//#endif
-
- if (signal (SIGINT, DRSSigInt) == SIG_ERR) {
- perror ("sigignore");
- }
-
-
-Init(argc, argv);
-if (argc==1) { help(); return 0; }
-
-FILE *fp=NULL;
-if (strlen(filename)>0) {
- if (verbose) printf("Data in the file:%s\n", filename);
- fp=fopen(filename,"wb");
-}
-
-TFile *rfile= NULL;
-if (strlen(rootfile)>0) {
- if (verbose) printf("Data in the file:%s\n", rootfile);
- rfile = new TFile(rootfile,"RECREATE");
-}
-
-
-TCanvas *c = new TCanvas(); c->Divide(2,2);
-c->Draw();
-for (int i=0;i<4;i++){
- if (! (DRSParameters->mask & ( 0x1<<i )) ) continue;
- char name[0xff];
- sprintf(name,"h%d",i);
- h[i]=new TH2F(name,name,1024,0,204,1024,-0.6+DRSParameters->range,0.6+DRSParameters->range);
- c->cd(i+1); h[i]->Draw("colz");
-
-}
-
-
-
-//---------------------------------------
-static unsigned char *buffer;
-static int buffer_size = 0;
-const int nBoards=1;
-const int waveDepth=1024;
-if (buffer_size == 0) {
- buffer_size = 4 + nBoards * (4 + 4*(4+waveDepth*4));
- buffer_size += 24 + nBoards * (8 + 4*(4+waveDepth*2));
- buffer = (unsigned char *)malloc(buffer_size);
-}
-
-time_t t,told, tstart;
-if (!DRSInit()){
- time(&tstart);
- told=tstart;
- int i=0;
- for (i=0; i<neve; i++) {
- int nb = (DRSRead(1) == 0 && fp ) ? DRSToBuffer( buffer , i ) : 0;
-
- if (DRSTimeout) i--;
- if (ctrl_c) break;
- time(&t);
- if (t!=told ) {
- printf("%d events in %2.2f min (%d s) %s",i+1, (double)(t-tstart)/60.,int(t-tstart), ctime(&t));
- c->Modified(); c->Update();
- }
- told=t;
-// Save data
- if (nb>0 && fp) fwrite(buffer, 1,nb ,fp);
-// Plot Data
- for (int k=0;k<4;k++){
- if (! (DRSParameters->mask & ( 0x1<<k )) ) continue;
- float *t=DRSGetTime(k);
- float *x=DRSGetWave(k);
- for (int i=0 ; i<1024 ; i++) {
- if (verbose) printf("[%d] %d. x= %3.2f y=%3.2f\n", k, i, t[i], x[i] );
- h[k]->Fill( t[i], x[i]*1e-3);
- }
- }
- }
- time(&t);
- printf("%d events in %2.2f min (%d s) %s",i+1, (double)(t-tstart)/60.,int(t-tstart), ctime(&t));
-
- DRSEnd();
-}
-//---------------------------------------
-if (rfile !=NULL) rfile->Write();
-if (fp) fclose(fp);
-if (c) c->SaveAs("drsread.pdf");
-// TApplication* theApp = new TApplication("App", NULL, NULL);
-// theApp->Run();
-
-
-
-}
-
-#endif
\ No newline at end of file
Index: instr/drsctrl/timer.h
===================================================================
--- instr/drsctrl/timer.h (revision 196)
+++ instr/drsctrl/timer.h (nonexistent)
@@ -1,78 +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 <stdio.h>
-
-#ifdef __linux__
-
-#include <sys/time.h>
-#include <signal.h>
-
-#else
-
-/* this code only works on win2000, XP, Vista, 7 and up */
-/* win95, win98 and ME are not supported */
-/* WINVER must have value 0x500 or higher */
-#ifndef WINVER
-#define WINVER 0x500
-#endif
-
-#if WINVER < 0x500
-#error "WINVER is < 0x500, cannot compile for old windows versions"
-#endif
-
-#include <windows.h>
-
-#endif
-
-
-#ifndef timer_INCLUDED
-#define timer_INCLUDED
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-int start_timer(int, void (*)(void));
-
-void stop_timer(void);
-
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif
-
-
Index: instr/drsctrl/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/musbstd.h
===================================================================
--- instr/drsctrl/musbstd.h (revision 196)
+++ instr/drsctrl/musbstd.h (nonexistent)
@@ -1,95 +0,0 @@
-/********************************************************************\
-
- Name: musbstd.h
- Created by: Konstantin Olchanski, Stefan Ritt
-
- Contents: Midas USB access
-
- $Id$
-
-\********************************************************************/
-
-#ifndef MUSBSTD_H
-#define MUSBSTD_H
-
-#if defined(HAVE_LIBUSB)
-
-#include "usb.h"
-
-typedef struct {
- usb_dev_handle *dev;
- int usb_configuration;
- int usb_interface;
- int usb_type;
-} MUSB_INTERFACE;
-
-#elif defined(HAVE_LIBUSB10)
-
-#include <libusb-1.0/libusb.h>
-
-typedef struct {
- libusb_device_handle *dev;
- int usb_configuration;
- int usb_interface;
- int usb_type;
-} MUSB_INTERFACE;
-
-#elif defined(_MSC_VER)
-
-#include <windows.h>
-
-typedef struct {
- HANDLE rhandle;
- HANDLE whandle;
- int usb_type;
-} MUSB_INTERFACE;
-
-#elif defined(OS_DARWIN)
-
-typedef struct {
- void *device;
- void *interface;
- int usb_configuration;
- int usb_interface;
- int usb_type;
-} MUSB_INTERFACE;
-
-#else
-#error Do not know how to access USB devices
-#endif
-
-/*---- status codes ------------------------------------------------*/
-
-#define MUSB_SUCCESS 1
-#define MUSB_NOT_FOUND 2
-#define MUSB_INVALID_PARAM 3
-#define MUSB_NO_MEM 4
-#define MUSB_ACCESS_ERROR 5
-
-/* make functions callable from a C++ program */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* make functions under WinNT dll exportable */
-#ifndef EXPRT
-#if defined(_MSC_VER) && defined(_USRDLL)
-#define EXPRT __declspec(dllexport)
-#else
-#define EXPRT
-#endif
-#endif
-
-int EXPRT musb_open(MUSB_INTERFACE **musb_interface, int vendor, int product, int instance, int configuration, int usbinterface);
-int EXPRT musb_close(MUSB_INTERFACE *musb_interface);
-int EXPRT musb_write(MUSB_INTERFACE *musb_interface,int endpoint,const void *buf,int count,int timeout_ms);
-int EXPRT musb_read(MUSB_INTERFACE *musb_interface,int endpoint,void *buf,int count,int timeout_ms);
-int EXPRT musb_reset(MUSB_INTERFACE *musb_interface);
-int EXPRT musb_set_altinterface(MUSB_INTERFACE *musb_interface, int index);
-int EXPRT musb_get_device(MUSB_INTERFACE *musb_interface);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // MUSBSTD_H
Index: instr/drsctrl/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/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/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/XGetopt.h
===================================================================
--- instr/drsctrl/XGetopt.h (revision 196)
+++ instr/drsctrl/XGetopt.h (nonexistent)
@@ -1,25 +0,0 @@
-// XGetopt.h Version 1.2
-//
-// Author: Hans Dietrich
-// hdietrich2@hotmail.com
-//
-// This software is released into the public domain.
-// You are free to use it in any way you like.
-//
-// This software is provided "as is" with no expressed
-// or implied warranty. I accept no liability for any
-// damage or loss of business that this software may cause.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef XGETOPT_H
-#define XGETOPT_H
-
-extern int optind, opterr;
-//extern TCHAR *optarg;
-extern char *optarg;
-
-//int getopt(int argc, TCHAR *argv[], TCHAR *optstring);
-int getopt(int argc, char *argv[], char *optstring);
-
-#endif //XGETOPT_H
Index: instr/drsctrl/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/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/drsread.lib
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/instr/drsctrl/drsread.lib
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, "&lt;");
- pd += 4;
- break;
- case '>':
- strcpy(pd, "&gt;");
- pd += 4;
- break;
- case '&':
- strcpy(pd, "&amp;");
- pd += 5;
- break;
- case '\"':
- strcpy(pd, "&quot;");
- pd += 6;
- break;
- case '\'':
- strcpy(pd, "&apos;");
- pd += 6;
- break;
- default:
- *pd++ = *ps;
- }
- } else {
- switch (*ps) { /* translate only illegal XML characters "<" and "&" */
- case '<':
- strcpy(pd, "&lt;");
- pd += 4;
- break;
- case '&':
- strcpy(pd, "&amp;");
- pd += 5;
- break;
- default:
- *pd++ = *ps;
- }
- }
- }
- *pd = 0;
-
- strlcpy(src, _encode_buffer, size);
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * reverse of mxml_encode, strip leading or trailing '"'
- */
-void mxml_decode(char *str)
-{
- char *p;
-
- p = str;
- while ((p = strchr(p, '&')) != NULL) {
- if (strncmp(p, "&lt;", 4) == 0) {
- *(p++) = '<';
- memmove(p, p+3, strlen(p+3) + 1);
- }
- else if (strncmp(p, "&gt;", 4) == 0) {
- *(p++) = '>';
- memmove(p, p+3, strlen(p+3) + 1);
- }
- else if (strncmp(p, "&amp;", 5) == 0) {
- *(p++) = '&';
- memmove(p, p+4, strlen(p+4) + 1);
- }
- else if (strncmp(p, "&quot;", 6) == 0) {
- *(p++) = '\"';
- memmove(p, p+5, strlen(p+5) + 1);
- }
- else if (strncmp(p, "&apos;", 6) == 0) {
- *(p++) = '\'';
- memmove(p, p+5, strlen(p+5) + 1);
- }
- else {
- p++; // skip unknown entity
- }
- }
-/* if (str[0] == '\"' && str[strlen(str)-1] == '\"') {
- memmove(str, str+1, strlen(str+1) + 1);
- str[strlen(str)-1] = 0;
- }*/
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * set translation of <,>,",',&, on/off in writer
- */
-int mxml_set_translate(MXML_WRITER *writer, int flag)
-{
- int old_flag;
-
- old_flag = writer->translate;
- writer->translate = flag;
- return old_flag;
-}
-/*------------------------------------------------------------------*/
-
-/**
- * start a new XML element, must be followed by mxml_end_elemnt
- */
-int mxml_start_element1(MXML_WRITER *writer, const char *name, int indent)
-{
- int i;
- char line[1000], name_enc[1000];
-
- if (writer->element_is_open) {
- mxml_write_line(writer, ">\n");
- writer->element_is_open = FALSE;
- }
-
- line[0] = 0;
- if (indent)
- for (i=0 ; i<writer->level ; i++)
- strlcat(line, XML_INDENT, sizeof(line));
- strlcat(line, "<", sizeof(line));
- strlcpy(name_enc, name, sizeof(name_enc));
- mxml_encode(name_enc, sizeof(name_enc), writer->translate);
- strlcat(line, name_enc, sizeof(line));
-
- /* put element on stack */
- if (writer->level == 0)
- writer->stack = (char **)mxml_malloc(sizeof(char *));
- else
- writer->stack = (char **)mxml_realloc(writer->stack, sizeof(char *)*(writer->level+1));
-
- writer->stack[writer->level] = (char *) mxml_malloc(strlen(name_enc)+1);
- strcpy(writer->stack[writer->level], name_enc);
- writer->level++;
- writer->element_is_open = TRUE;
- writer->data_was_written = FALSE;
-
- return mxml_write_line(writer, line) == (int)strlen(line);
-}
-
-/*------------------------------------------------------------------*/
-
-int mxml_start_element(MXML_WRITER *writer, const char *name)
-{
- return mxml_start_element1(writer, name, TRUE);
-}
-
-/*------------------------------------------------------------------*/
-
-int mxml_start_element_noindent(MXML_WRITER *writer, const char *name)
-{
- return mxml_start_element1(writer, name, FALSE);
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * close an open XML element
- */
-int mxml_end_element(MXML_WRITER *writer)
-{
- int i;
- char line[1000];
-
- if (writer->level == 0)
- return 0;
-
- writer->level--;
-
- if (writer->element_is_open) {
- writer->element_is_open = FALSE;
- mxml_free(writer->stack[writer->level]);
- if (writer->level == 0)
- mxml_free(writer->stack);
- strcpy(line, "/>\n");
- return mxml_write_line(writer, line) == (int)strlen(line);
- }
-
- line[0] = 0;
- if (!writer->data_was_written) {
- for (i=0 ; i<writer->level ; i++)
- strlcat(line, XML_INDENT, sizeof(line));
- }
-
- strlcat(line, "</", sizeof(line));
- strlcat(line, writer->stack[writer->level], sizeof(line));
- mxml_free(writer->stack[writer->level]);
- if (writer->level == 0)
- mxml_free(writer->stack);
- strlcat(line, ">\n", sizeof(line));
- writer->data_was_written = FALSE;
-
- return mxml_write_line(writer, line) == (int)strlen(line);
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * write an attribute to the currently open XML element
- */
-int mxml_write_attribute(MXML_WRITER *writer, const char *name, const char *value)
-{
- char name_enc[4096], val_enc[4096], line[8192];
-
- if (!writer->element_is_open)
- return FALSE;
-
- strcpy(name_enc, name);
- mxml_encode(name_enc, sizeof(name_enc), writer->translate);
- strcpy(val_enc, value);
- mxml_encode(val_enc, sizeof(val_enc), writer->translate);
-
- sprintf(line, " %s=\"%s\"", name_enc, val_enc);
-
- return mxml_write_line(writer, line) == (int)strlen(line);
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * write value of an XML element, like <[name]>[value]</[name]>
- */
-int mxml_write_value(MXML_WRITER *writer, const char *data)
-{
- static int data_size = 0;
-
- if (!writer->element_is_open)
- return FALSE;
-
- if (mxml_write_line(writer, ">") != 1)
- return FALSE;
- writer->element_is_open = FALSE;
- writer->data_was_written = TRUE;
-
- if (data_size == 0) {
- _data_enc = (char *)mxml_malloc(1000);
- data_size = 1000;
- } else if ((int)strlen(data)*2+1000 > data_size) {
- data_size = 1000+(int)strlen(data)*2;
- _data_enc = (char *)mxml_realloc(_data_enc, data_size);
- }
-
- strcpy(_data_enc, data);
- mxml_encode(_data_enc, data_size, writer->translate);
- return mxml_write_line(writer, _data_enc) == (int)strlen(_data_enc);
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * write empty line
- */
-int mxml_write_empty_line(MXML_WRITER *writer)
-{
- if (writer->element_is_open) {
- mxml_write_line(writer, ">\n");
- writer->element_is_open = FALSE;
- }
-
- if (mxml_write_line(writer, "\n") != 1)
- return FALSE;
-
- return TRUE;
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * write a comment to an XML file, enclosed in "<!--" and "-->"
- */
-int mxml_write_comment(MXML_WRITER *writer, const char *string)
-{
- int i;
- char line[1000];
-
- if (writer->element_is_open) {
- mxml_write_line(writer, ">\n");
- writer->element_is_open = FALSE;
- }
-
- line[0] = 0;
- for (i=0 ; i<writer->level ; i++)
- strlcat(line, XML_INDENT, sizeof(line));
-
- strlcat(line, "<!-- ", sizeof(line));
- strlcat(line, string, sizeof(line));
- strlcat(line, " -->\n", sizeof(line));
- if (mxml_write_line(writer, line) != (int)strlen(line))
- return FALSE;
-
- return TRUE;
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * shortcut to write an element with a value but without attribute
- */
-int mxml_write_element(MXML_WRITER *writer, const char *name, const char *value)
-{
- int i;
-
- i = mxml_start_element(writer, name);
- i += mxml_write_value(writer, value);
- i += mxml_end_element(writer);
- return i;
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * close a file opened with mxml_open_writer
- */
-char *mxml_close_buffer(MXML_WRITER *writer)
-{
- int i;
- char *p;
-
- if (writer->element_is_open) {
- writer->element_is_open = FALSE;
- if (mxml_write_line(writer, ">\n") != 2)
- return NULL;
- }
-
- /* close remaining open levels */
- for (i = 0 ; i<writer->level ; i++)
- mxml_end_element(writer);
-
- p = writer->buffer;
- mxml_free(writer);
- return p;
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * close a file opened with mxml_open_writer
- */
-int mxml_close_file(MXML_WRITER *writer)
-{
- int i;
-
- if (writer->element_is_open) {
- writer->element_is_open = FALSE;
- if (mxml_write_line(writer, ">\n") != 2)
- return 0;
- }
-
- /* close remaining open levels */
- for (i = 0 ; i<writer->level ; i++)
- mxml_end_element(writer);
-
- close(writer->fh);
- mxml_free(writer);
- return 1;
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * create root node of an XML tree
- */
-PMXML_NODE mxml_create_root_node(void)
-{
- PMXML_NODE root;
-
- root = (PMXML_NODE)calloc(sizeof(MXML_NODE), 1);
- strcpy(root->name, "root");
- root->node_type = DOCUMENT_NODE;
-
- return root;
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * add a subnode (child) to an existing parent node as a specific position
- */
-PMXML_NODE mxml_add_special_node_at(PMXML_NODE parent, int node_type, const char *node_name, const char *value, int idx)
-{
- PMXML_NODE pnode, pchild;
- int i, j;
-
- assert(parent);
- if (parent->n_children == 0)
- parent->child = (PMXML_NODE)mxml_malloc(sizeof(MXML_NODE));
- else
- parent->child = (PMXML_NODE)mxml_realloc(parent->child, sizeof(MXML_NODE)*(parent->n_children+1));
- assert(parent->child);
-
- /* move following nodes one down */
- if (idx < parent->n_children)
- for (i=parent->n_children ; i > idx ; i--)
- memcpy(&parent->child[i], &parent->child[i-1], sizeof(MXML_NODE));
-
- /* correct parent pointer for children */
- for (i=0 ; i<parent->n_children ; i++) {
- pchild = parent->child+i;
- for (j=0 ; j<pchild->n_children ; j++)
- pchild->child[j].parent = pchild;
- }
-
- /* initialize new node */
- pnode = &parent->child[idx];
- memset(pnode, 0, sizeof(MXML_NODE));
- strlcpy(pnode->name, node_name, sizeof(pnode->name));
- pnode->node_type = node_type;
- pnode->parent = parent;
-
- parent->n_children++;
-
- if (value && *value) {
- pnode->value = (char *)mxml_malloc(strlen(value)+1);
- assert(pnode->value);
- strcpy(pnode->value, value);
- }
-
- return pnode;
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * add a subnode (child) to an existing parent node at the end
- */
-PMXML_NODE mxml_add_special_node(PMXML_NODE parent, int node_type, const char *node_name, const char *value)
-{
- return mxml_add_special_node_at(parent, node_type, node_name, value, parent->n_children);
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * write value of an XML element, like <[name]>[value]</[name]>
- */
-PMXML_NODE mxml_add_node(PMXML_NODE parent, const char *node_name, const char *value)
-{
- return mxml_add_special_node_at(parent, ELEMENT_NODE, node_name, value, parent->n_children);
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * add a subnode (child) to an existing parent node at the end
- */
-PMXML_NODE mxml_add_node_at(PMXML_NODE parent, const char *node_name, const char *value, int idx)
-{
- return mxml_add_special_node_at(parent, ELEMENT_NODE, node_name, value, idx);
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * add a whole node tree to an existing parent node at a specific position
- */
-int mxml_add_tree_at(PMXML_NODE parent, PMXML_NODE tree, int idx)
-{
- PMXML_NODE pchild;
- int i, j, k;
-
- assert(parent);
- assert(tree);
- if (parent->n_children == 0)
- parent->child = (PMXML_NODE)mxml_malloc(sizeof(MXML_NODE));
- else {
- pchild = parent->child;
- parent->child = (PMXML_NODE)mxml_realloc(parent->child, sizeof(MXML_NODE)*(parent->n_children+1));
-
- if (parent->child != pchild) {
- /* correct parent pointer for children */
- for (i=0 ; i<parent->n_children ; i++) {
- pchild = parent->child+i;
- for (j=0 ; j<pchild->n_children ; j++)
- pchild->child[j].parent = pchild;
- }
- }
- }
- assert(parent->child);
-
- if (idx < parent->n_children)
- for (i=parent->n_children ; i > idx ; i--) {
- /* move following nodes one down */
- memcpy(&parent->child[i], &parent->child[i-1], sizeof(MXML_NODE));
-
- /* correct parent pointer for children */
- for (j=0 ; j<parent->n_children ; j++) {
- pchild = parent->child+j;
- for (k=0 ; k<pchild->n_children ; k++)
- pchild->child[k].parent = pchild;
- }
- }
-
- /* initialize new node */
- memcpy(parent->child+idx, tree, sizeof(MXML_NODE));
- parent->n_children++;
- parent->child[idx].parent = parent;
-
- /* correct parent pointer for children */
- for (i=0 ; i<parent->n_children ; i++) {
- pchild = parent->child+i;
- for (j=0 ; j<pchild->n_children ; j++)
- pchild->child[j].parent = pchild;
- }
-
- return TRUE;
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * add a whole node tree to an existing parent node at the end
- */
-int mxml_add_tree(PMXML_NODE parent, PMXML_NODE tree)
-{
- return mxml_add_tree_at(parent, tree, parent->n_children);
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * add an attribute to an existing node
- */
-int mxml_add_attribute(PMXML_NODE pnode, const char *attrib_name, const char *attrib_value)
-{
- if (pnode->n_attributes == 0) {
- pnode->attribute_name = (char*)mxml_malloc(MXML_NAME_LENGTH);
- pnode->attribute_value = (char**)mxml_malloc(sizeof(char *));
- } else {
- pnode->attribute_name = (char*)mxml_realloc(pnode->attribute_name, MXML_NAME_LENGTH*(pnode->n_attributes+1));
- pnode->attribute_value = (char**)mxml_realloc(pnode->attribute_value, sizeof(char *)*(pnode->n_attributes+1));
- }
-
- strlcpy(pnode->attribute_name+pnode->n_attributes*MXML_NAME_LENGTH, attrib_name, MXML_NAME_LENGTH);
- pnode->attribute_value[pnode->n_attributes] = (char *)mxml_malloc(strlen(attrib_value)+1);
- strcpy(pnode->attribute_value[pnode->n_attributes], attrib_value);
- pnode->n_attributes++;
-
- return TRUE;
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * return number of subnodes (children) of a node
- */
-int mxml_get_number_of_children(PMXML_NODE pnode)
-{
- assert(pnode);
- return pnode->n_children;
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * return number of subnodes (children) of a node
- */
-PMXML_NODE mxml_subnode(PMXML_NODE pnode, int idx)
-{
- assert(pnode);
- if (idx < pnode->n_children)
- return &pnode->child[idx];
- return NULL;
-}
-
-/*------------------------------------------------------------------*/
-
-
-int mxml_find_nodes1(PMXML_NODE tree, const char *xml_path, PMXML_NODE **nodelist, int *found);
-
-int mxml_add_resultnode(PMXML_NODE node, const char *xml_path, PMXML_NODE **nodelist, int *found)
-{
- /* if at end of path, add this node */
- if (*xml_path == 0) {
- if (*found == 0)
- *nodelist = (PMXML_NODE *)mxml_malloc(sizeof(PMXML_NODE));
- else
- *nodelist = (PMXML_NODE *)mxml_realloc(*nodelist, sizeof(PMXML_NODE)*(*found + 1));
-
- (*nodelist)[*found] = node;
- (*found)++;
- } else {
- /* if not at end of path, branch into subtree */
- return mxml_find_nodes1(node, xml_path+1, nodelist, found);
- }
-
- return 1;
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- Return list of XML nodes with a subset of XPATH specifications.
- Following elemets are possible
-
- /<node>/<node>/..../<node> Find a node in the tree hierarchy
- /<node>[idx] Find child #[idx] of node (index starts from 1)
- /<node>[idx]/<node> Find subnode of the above
- /<node>[<subnode>=<value>] Find a node which has a specific subnode
- /<node>[<subnode>=<value>]/<node> Find subnode of the above
- /<node>[@<attrib>=<value>]/<node> Find a node which has a specific attribute
-*/
-int mxml_find_nodes1(PMXML_NODE tree, const char *xml_path, PMXML_NODE **nodelist, int *found)
-{
- PMXML_NODE pnode;
- const char *p1,*p2;
- char *p3, node_name[256], condition[256];
- char cond_name[MXML_MAX_CONDITION][256], cond_value[MXML_MAX_CONDITION][256];
- int cond_type[MXML_MAX_CONDITION];
- int i, j, k, idx, num_cond;
- int cond_satisfied,cond_index;
- size_t len;
-
- p1 = xml_path;
- pnode = tree;
-
- /* skip leading '/' */
- if (*p1 && *p1 == '/')
- p1++;
-
- do {
- p2 = p1;
- while (*p2 && *p2 != '/' && *p2 != '[')
- p2++;
- len = (size_t)p2 - (size_t)p1;
- if (len >= sizeof(node_name))
- return 0;
-
- memcpy(node_name, p1, len);
- node_name[len] = 0;
- idx = 0;
- num_cond = 0;
- while (*p2 == '[') {
- cond_name[num_cond][0] = cond_value[num_cond][0] = cond_type[num_cond] = 0;
- p2++;
- if (isdigit(*p2)) {
- /* evaluate [idx] */
- idx = atoi(p2);
- p2 = strchr(p2, ']');
- if (p2 == NULL)
- return 0;
- p2++;
- } else {
- /* evaluate [<@attrib>/<subnode>=<value>] */
- while (*p2 && isspace((unsigned char)*p2))
- p2++;
- strlcpy(condition, p2, sizeof(condition));
- if (strchr(condition, ']'))
- *strchr(condition, ']') = 0;
- else
- return 0;
- p2 = strchr(p2, ']')+1;
- if ((p3 = strchr(condition, '=')) != NULL) {
- if (condition[0] == '@') {
- cond_type[num_cond] = 1;
- strlcpy(cond_name[num_cond], &condition[1], sizeof(cond_name[num_cond]));
- } else {
- strlcpy(cond_name[num_cond], condition, sizeof(cond_name[num_cond]));
- }
-
- *strchr(cond_name[num_cond], '=') = 0;
- while (cond_name[num_cond][0] && isspace(cond_name[num_cond][strlen(cond_name[num_cond])-1]))
- cond_name[num_cond][strlen(cond_name[num_cond])-1] = 0;
-
- p3++;
- while (*p3 && isspace(*p3))
- p3++;
- if (*p3 == '\"') {
- strlcpy(cond_value[num_cond], p3+1, sizeof(cond_value[num_cond]));
- while (cond_value[num_cond][0] && isspace(cond_value[num_cond][strlen(cond_value[num_cond])-1]))
- cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0;
- if (cond_value[num_cond][0] && cond_value[num_cond][strlen(cond_value[num_cond])-1] == '\"')
- cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0;
- } else if (*p3 == '\'') {
- strlcpy(cond_value[num_cond], p3+1, sizeof(cond_value[num_cond]));
- while (cond_value[num_cond][0] && isspace(cond_value[num_cond][strlen(cond_value[num_cond])-1]))
- cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0;
- if (cond_value[num_cond][0] && cond_value[num_cond][strlen(cond_value[num_cond])-1] == '\'')
- cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0;
- } else {
- strlcpy(cond_value[num_cond], p3, sizeof(cond_value[num_cond]));
- while (cond_value[num_cond][0] && isspace(cond_value[num_cond][strlen(cond_value[num_cond])-1]))
- cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0;
- }
- num_cond++;
- }
- }
- }
-
- cond_index = 0;
- for (i=j=0 ; i<pnode->n_children ; i++) {
- if (num_cond) {
- cond_satisfied = 0;
- for (k=0;k<num_cond;k++) {
- if (cond_type[k]) {
- /* search node with attribute */
- if (strcmp(pnode->child[i].name, node_name) == 0)
- if (mxml_get_attribute(pnode->child+i, cond_name[k]) &&
- strcmp(mxml_get_attribute(pnode->child+i, cond_name[k]), cond_value[k]) == 0)
- cond_satisfied++;
- }
- else {
- /* search subnode */
- for (j=0 ; j<pnode->child[i].n_children ; j++)
- if (strcmp(pnode->child[i].child[j].name, cond_name[k]) == 0)
- if (strcmp(pnode->child[i].child[j].value, cond_value[k]) == 0)
- cond_satisfied++;
- }
- }
- if (cond_satisfied==num_cond) {
- cond_index++;
- if (idx == 0 || cond_index == idx) {
- if (!mxml_add_resultnode(pnode->child+i, p2, nodelist, found))
- return 0;
- }
- }
- } else {
- if (strcmp(pnode->child[i].name, node_name) == 0)
- if (idx == 0 || ++j == idx)
- if (!mxml_add_resultnode(pnode->child+i, p2, nodelist, found))
- return 0;
- }
- }
-
- if (i == pnode->n_children)
- return 1;
-
- pnode = &pnode->child[i];
- p1 = p2;
- if (*p1 == '/')
- p1++;
-
- } while (*p2);
-
- return 1;
-}
-
-/*------------------------------------------------------------------*/
-
-int mxml_find_nodes(PMXML_NODE tree, const char *xml_path, PMXML_NODE **nodelist)
-{
- int status, found = 0;
-
- status = mxml_find_nodes1(tree, xml_path, nodelist, &found);
-
- if (status == 0)
- return -1;
-
- return found;
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * Search for a specific XML node with a subset of XPATH specifications.
- * Return first found node. For syntax see mxml_find_nodes()
- */
-PMXML_NODE mxml_find_node(PMXML_NODE tree, const char *xml_path)
-{
- PMXML_NODE *node, pnode;
- int n;
-
- n = mxml_find_nodes(tree, xml_path, &node);
- if (n > 0) {
- pnode = node[0];
- mxml_free(node);
- } else
- pnode = NULL;
-
- return pnode;
-}
-
-/*------------------------------------------------------------------*/
-
-PMXML_NODE mxml_get_parent(PMXML_NODE pnode)
-{
- assert(pnode);
- return pnode->parent;
-}
-
-/*------------------------------------------------------------------*/
-
-char *mxml_get_name(PMXML_NODE pnode)
-{
- assert(pnode);
- return pnode->name;
-}
-
-/*------------------------------------------------------------------*/
-
-char *mxml_get_value(PMXML_NODE pnode)
-{
- assert(pnode);
- return pnode->value;
-}
-
-/*------------------------------------------------------------------*/
-
-int mxml_get_line_number_start(PMXML_NODE pnode)
-{
- assert(pnode);
- return pnode->line_number_start;
-}
-
-/*------------------------------------------------------------------*/
-
-int mxml_get_line_number_end(PMXML_NODE pnode)
-{
- assert(pnode);
- return pnode->line_number_end;
-}
-
-/*------------------------------------------------------------------*/
-
-char *mxml_get_attribute(PMXML_NODE pnode, const char *name)
-{
- int i;
-
- assert(pnode);
- for (i=0 ; i<pnode->n_attributes ; i++)
- if (strcmp(pnode->attribute_name+i*MXML_NAME_LENGTH, name) == 0)
- return pnode->attribute_value[i];
-
- return NULL;
-}
-
-/*------------------------------------------------------------------*/
-
-int mxml_replace_node_name(PMXML_NODE pnode, const char *name)
-{
- strlcpy(pnode->name, name, sizeof(pnode->name));
- return TRUE;
-}
-
-/*------------------------------------------------------------------*/
-
-int mxml_replace_node_value(PMXML_NODE pnode, const char *value)
-{
- if (pnode->value)
- pnode->value = (char *)mxml_realloc(pnode->value, strlen(value)+1);
- else if (value)
- pnode->value = (char *)mxml_malloc(strlen(value)+1);
- else
- pnode->value = NULL;
-
- if (value)
- strcpy(pnode->value, value);
-
- return TRUE;
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- replace value os a subnode, like
-
- <parent>
- <child>value</child>
- </parent>
-
- if pnode=parent, and "name"="child", then "value" gets replaced
-*/
-int mxml_replace_subvalue(PMXML_NODE pnode, const char *name, const char *value)
-{
- int i;
-
- for (i=0 ; i<pnode->n_children ; i++)
- if (strcmp(pnode->child[i].name, name) == 0)
- break;
-
- if (i == pnode->n_children)
- return FALSE;
-
- return mxml_replace_node_value(&pnode->child[i], value);
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * change the name of an attribute, keep its value
- */
-int mxml_replace_attribute_name(PMXML_NODE pnode, const char *old_name, const char *new_name)
-{
- int i;
-
- for (i=0 ; i<pnode->n_attributes ; i++)
- if (strcmp(pnode->attribute_name+i*MXML_NAME_LENGTH, old_name) == 0)
- break;
-
- if (i == pnode->n_attributes)
- return FALSE;
-
- strlcpy(pnode->attribute_name+i*MXML_NAME_LENGTH, new_name, MXML_NAME_LENGTH);
- return TRUE;
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * change the value of an attribute
- */
-int mxml_replace_attribute_value(PMXML_NODE pnode, const char *attrib_name, const char *attrib_value)
-{
- int i;
-
- for (i=0 ; i<pnode->n_attributes ; i++)
- if (strcmp(pnode->attribute_name+i*MXML_NAME_LENGTH, attrib_name) == 0)
- break;
-
- if (i == pnode->n_attributes)
- return FALSE;
-
- pnode->attribute_value[i] = (char *)mxml_realloc(pnode->attribute_value[i], strlen(attrib_value)+1);
- strcpy(pnode->attribute_value[i], attrib_value);
- return TRUE;
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * free memory of a node and remove it from the parent's child list
- */
-int mxml_delete_node(PMXML_NODE pnode)
-{
- PMXML_NODE parent;
- int i, j;
-
- /* remove node from parent's list */
- parent = pnode->parent;
-
- if (parent) {
- for (i=0 ; i<parent->n_children ; i++)
- if (&parent->child[i] == pnode)
- break;
-
- /* free allocated node memory recursively */
- mxml_free_tree(pnode);
-
- if (i < parent->n_children) {
- for (j=i ; j<parent->n_children-1 ; j++)
- memcpy(&parent->child[j], &parent->child[j+1], sizeof(MXML_NODE));
- parent->n_children--;
- if (parent->n_children)
- parent->child = (PMXML_NODE)mxml_realloc(parent->child, sizeof(MXML_NODE)*(parent->n_children));
- else
- mxml_free(parent->child);
- }
- } else
- mxml_free_tree(pnode);
-
- return TRUE;
-}
-
-/*------------------------------------------------------------------*/
-
-int mxml_delete_attribute(PMXML_NODE pnode, const char *attrib_name)
-{
- int i, j;
-
- for (i=0 ; i<pnode->n_attributes ; i++)
- if (strcmp(pnode->attribute_name+i*MXML_NAME_LENGTH, attrib_name) == 0)
- break;
-
- if (i == pnode->n_attributes)
- return FALSE;
-
- mxml_free(pnode->attribute_value[i]);
- for (j=i ; j<pnode->n_attributes-1 ; j++) {
- strcpy(pnode->attribute_name+j*MXML_NAME_LENGTH, pnode->attribute_name+(j+1)*MXML_NAME_LENGTH);
- pnode->attribute_value[j] = pnode->attribute_value[j+1];
- }
-
- if (pnode->n_attributes > 0) {
- pnode->attribute_name = (char *)mxml_realloc(pnode->attribute_name, MXML_NAME_LENGTH*(pnode->n_attributes-1));
- pnode->attribute_value = (char **)mxml_realloc(pnode->attribute_value, sizeof(char *)*(pnode->n_attributes-1));
- } else {
- mxml_free(pnode->attribute_name);
- mxml_free(pnode->attribute_value);
- }
-
- return TRUE;
-}
-
-/*------------------------------------------------------------------*/
-
-#define HERE root, file_name, line_number, error, error_size, error_line
-
-/**
- * used inside mxml_parse_file for reporting errors
- */
-PMXML_NODE read_error(PMXML_NODE root, const char *file_name, int line_number, char *error, int error_size, int *error_line, const char *format, ...)
-{
- char *msg, str[1000];
- va_list argptr;
-
- if (file_name && file_name[0])
- sprintf(str, "XML read error in file \"%s\", line %d: ", file_name, line_number);
- else
- sprintf(str, "XML read error, line %d: ", line_number);
- msg = (char *)mxml_malloc(error_size);
- if (error)
- strlcpy(error, str, error_size);
-
- va_start(argptr, format);
- vsprintf(str, (char *) format, argptr);
- va_end(argptr);
-
- if (error)
- strlcat(error, str, error_size);
- if (error_line)
- *error_line = line_number;
-
- mxml_free(msg);
- mxml_free_tree(root);
-
- return NULL;
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * Parse a XML buffer and convert it into a tree of MXML_NODE's.
- * Return NULL in case of an error, return error description.
- * Optional file_name is used for error reporting if called from mxml_parse_file()
- */
-PMXML_NODE mxml_parse_buffer(const char *buf, char *error, int error_size, int *error_line)
-{
- char node_name[256], attrib_name[256], attrib_value[1000], quote;
- const char *p, *pv;
- int i,j, line_number;
- PMXML_NODE root, ptree, pnew;
- int end_element;
- size_t len;
- char *file_name = NULL; /* dummy for 'HERE' */
-
- p = buf;
- line_number = 1;
-
- root = mxml_create_root_node();
- ptree = root;
-
- /* parse file contents */
- do {
- if (*p == '<') {
-
- end_element = FALSE;
-
- /* found new element */
- p++;
- while (*p && isspace(*p)) {
- if (*p == '\n')
- line_number++;
- p++;
- }
- if (!*p)
- return read_error(HERE, "Unexpected end of file");
-
- if (strncmp(p, "!--", 3) == 0) {
-
- /* found comment */
-
- pnew = mxml_add_special_node(ptree, COMMENT_NODE, "Comment", NULL);
- pnew->line_number_start = line_number;
- pv = p+3;
- while (*pv == ' ')
- pv++;
-
- p += 3;
- if (strstr(p, "-->") == NULL)
- return read_error(HERE, "Unterminated comment");
-
- while (strncmp(p, "-->", 3) != 0) {
- if (*p == '\n')
- line_number++;
- p++;
- }
-
- len = (size_t)p - (size_t)pv;
- pnew->value = (char *)mxml_malloc(len+1);
- memcpy(pnew->value, pv, len);
- pnew->value[len] = 0;
- pnew->line_number_end = line_number;
- mxml_decode(pnew->value);
-
- p += 3;
-
- } else if (*p == '?') {
-
- /* found ?...? element */
- pnew = mxml_add_special_node(ptree, PROCESSING_INSTRUCTION_NODE, "PI", NULL);
- pnew->line_number_start = line_number;
- pv = p+1;
-
- p++;
- if (strstr(p, "?>") == NULL)
- return read_error(HERE, "Unterminated ?...? element");
-
- while (strncmp(p, "?>", 2) != 0) {
- if (*p == '\n')
- line_number++;
- p++;
- }
-
- len = (size_t)p - (size_t)pv;
- pnew->value = (char *)mxml_malloc(len+1);
- memcpy(pnew->value, pv, len);
- pnew->value[len] = 0;
- pnew->line_number_end = line_number;
- mxml_decode(pnew->value);
-
- p += 2;
-
- } else if (strncmp(p, "!DOCTYPE", 8) == 0 ) {
-
- /* found !DOCTYPE element , skip it */
- p += 8;
- if (strstr(p, ">") == NULL)
- return read_error(HERE, "Unterminated !DOCTYPE element");
-
- j = 0;
- while (*p && (*p != '>' || j > 0)) {
- if (*p == '\n')
- line_number++;
- else if (*p == '<')
- j++;
- else if (*p == '>')
- j--;
- p++;
- }
- if (!*p)
- return read_error(HERE, "Unexpected end of file");
-
- p++;
-
- } else {
-
- /* found normal element */
- if (*p == '/') {
- end_element = TRUE;
- p++;
- while (*p && isspace((unsigned char)*p)) {
- if (*p == '\n')
- line_number++;
- p++;
- }
- if (!*p)
- return read_error(HERE, "Unexpected end of file");
- }
-
- /* extract node name */
- i = 0;
- node_name[i] = 0;
- while (*p && !isspace((unsigned char)*p) && *p != '/' && *p != '>' && *p != '<')
- node_name[i++] = *p++;
- node_name[i] = 0;
- if (!*p)
- return read_error(HERE, "Unexpected end of file");
- if (*p == '<')
- return read_error(HERE, "Unexpected \'<\' inside element \"%s\"", node_name);
-
- mxml_decode(node_name);
-
- if (end_element) {
-
- if (!ptree)
- return read_error(HERE, "Found unexpected </%s>", node_name);
-
- /* close previously opened element */
- if (strcmp(ptree->name, node_name) != 0)
- return read_error(HERE, "Found </%s>, expected </%s>", node_name, ptree->name);
- ptree->line_number_end = line_number;
-
- /* go up one level on the tree */
- ptree = ptree->parent;
-
- } else {
-
- if (ptree == NULL)
- return read_error(HERE, "Unexpected second top level node");
-
- /* allocate new element structure in parent tree */
- pnew = mxml_add_node(ptree, node_name, NULL);
- pnew->line_number_start = line_number;
- pnew->line_number_end = line_number;
-
- while (*p && isspace((unsigned char)*p)) {
- if (*p == '\n')
- line_number++;
- p++;
- }
- if (!*p)
- return read_error(HERE, "Unexpected end of file");
-
- while (*p != '>' && *p != '/') {
-
- /* found attribute */
- pv = p;
- while (*pv && !isspace((unsigned char)*pv) && *pv != '=' && *pv != '<' && *pv != '>')
- pv++;
- if (!*pv)
- return read_error(HERE, "Unexpected end of file");
- if (*pv == '<' || *pv == '>')
- return read_error(HERE, "Unexpected \'%c\' inside element \"%s\"", *pv, node_name);
-
- /* extract attribute name */
- len = (size_t)pv - (size_t)p;
- if (len > sizeof(attrib_name)-1)
- len = sizeof(attrib_name)-1;
- memcpy(attrib_name, p, len);
- attrib_name[len] = 0;
- mxml_decode(attrib_name);
-
- p = pv;
- while (*p && isspace((unsigned char)*p)) {
- if (*p == '\n')
- line_number++;
- p++;
- }
- if (!*p)
- return read_error(HERE, "Unexpected end of file");
- if (*p != '=')
- return read_error(HERE, "Expect \"=\" here");
-
- p++;
- while (*p && isspace((unsigned char)*p)) {
- if (*p == '\n')
- line_number++;
- p++;
- }
- if (!*p)
- return read_error(HERE, "Unexpected end of file");
- if (*p != '\"' && *p != '\'')
- return read_error(HERE, "Expect \" or \' here");
- quote = *p;
- p++;
-
- /* extract attribute value */
- pv = p;
- while (*pv && *pv != quote)
- pv++;
- if (!*pv)
- return read_error(HERE, "Unexpected end of file");
-
- len = (size_t)pv - (size_t)p;
- if (len > sizeof(attrib_value)-1)
- len = sizeof(attrib_value)-1;
- memcpy(attrib_value, p, len);
- attrib_value[len] = 0;
- mxml_decode(attrib_value);
-
- /* add attribute to current node */
- mxml_add_attribute(pnew, attrib_name, attrib_value);
-
- p = pv+1;
- while (*p && isspace((unsigned char)*p)) {
- if (*p == '\n')
- line_number++;
- p++;
- }
- if (!*p)
- return read_error(HERE, "Unexpected end of file");
- }
-
- if (*p == '/') {
-
- /* found empty node, like <node/>, just skip closing bracket */
- p++;
-
- while (*p && isspace((unsigned char)*p)) {
- if (*p == '\n')
- line_number++;
- p++;
- }
- if (!*p)
- return read_error(HERE, "Unexpected end of file");
- if (*p != '>')
- return read_error(HERE, "Expected \">\" after \"/\"");
- p++;
- }
-
- if (*p == '>') {
-
- p++;
-
- /* check if we have sub-element or value */
- pv = p;
- while (*pv && isspace((unsigned char)*pv)) {
- if (*pv == '\n')
- line_number++;
- pv++;
- }
- if (!*pv)
- return read_error(HERE, "Unexpected end of file");
-
- if (*pv == '<' && *(pv+1) != '/') {
-
- /* start new subtree */
- ptree = pnew;
- p = pv;
-
- } else {
-
- /* extract value */
- while (*pv && *pv != '<') {
- if (*pv == '\n')
- line_number++;
- pv++;
- }
- if (!*pv)
- return read_error(HERE, "Unexpected end of file");
-
- len = (size_t)pv - (size_t)p;
- pnew->value = (char *)mxml_malloc(len+1);
- memcpy(pnew->value, p, len);
- pnew->value[len] = 0;
- mxml_decode(pnew->value);
- p = pv;
-
- ptree = pnew;
- }
- }
- }
- }
- }
-
- /* go to next element */
- while (*p && *p != '<') {
- if (*p == '\n')
- line_number++;
- p++;
- }
- } while (*p);
-
- return root;
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * parse !ENTYTY entries of XML files and replace with references.
- * Return 0 in case of no errors, return error description.
- * Optional file_name is used for error reporting if called from mxml_parse_file()
- */
-int mxml_parse_entity(char **buf, const char *file_name, char *error, int error_size, int *error_line)
-{
- char *p;
- char *pv;
- char delimiter;
- int i, j, k, line_number, status;
- char *replacement;
- char entity_name[MXML_MAX_ENTITY][256];
- char entity_reference_name[MXML_MAX_ENTITY][256];
- char *entity_value[MXML_MAX_ENTITY];
- int entity_type[MXML_MAX_ENTITY]; /* internal or external */
- int entity_line_number[MXML_MAX_ENTITY];
- int nentity;
- int fh, length, len;
- char *buffer;
- int ip; /* counter for entity value */
- char directoryname[FILENAME_MAX];
- char filename[FILENAME_MAX];
- int entity_value_length[MXML_MAX_ENTITY];
- int entity_name_length[MXML_MAX_ENTITY];
-
- PMXML_NODE root = mxml_create_root_node(); /* dummy for 'HERE' */
-
- for (ip = 0; ip < MXML_MAX_ENTITY; ip++)
- entity_value[ip] = NULL;
-
- line_number = 1;
- nentity = -1;
- status = 0;
-
- if (!buf || !(*buf) || !strlen(*buf))
- return 0;
-
- strcpy(directoryname, file_name);
- mxml_dirname(directoryname);
-
- /* copy string to temporary space */
- buffer = (char *) mxml_malloc(strlen(*buf) + 1);
- if (buffer == NULL) {
- read_error(HERE, "Cannot allocate memory.");
- status = 1;
- goto error;
- }
- strcpy(buffer, *buf);
-
- p = strstr(buffer, "!DOCTYPE");
- if (p == NULL) { /* no entities */
- status = 0;
- goto error;
- }
-
- pv = strstr(p, "[");
- if (pv == NULL) { /* no entities */
- status = 1;
- goto error;
- }
-
- p = pv + 1;
-
- /* search !ENTITY */
- do {
- if (*p == ']')
- break;
-
- if (*p == '<') {
-
- /* found new entity */
- p++;
- while (*p && isspace((unsigned char)*p)) {
- if (*p == '\n')
- line_number++;
- p++;
- }
- if (!*p) {
- read_error(HERE, "Unexpected end of file");
- status = 1;
- goto error;
- }
-
- if (strncmp(p, "!--", 3) == 0) {
- /* found comment */
- p += 3;
- if (strstr(p, "-->") == NULL) {
- read_error(HERE, "Unterminated comment");
- status = 1;
- goto error;
- }
-
- while (strncmp(p, "-->", 3) != 0) {
- if (*p == '\n')
- line_number++;
- p++;
- }
- p += 3;
- }
-
- else if (strncmp(p, "!ENTITY", 7) == 0) {
- /* found entity */
- nentity++;
- if (nentity >= MXML_MAX_ENTITY) {
- read_error(HERE, "Too much entities");
- status = 1;
- goto error;
- }
-
- entity_line_number[nentity] = line_number;
-
- pv = p + 7;
- while (*pv == ' ')
- pv++;
-
- /* extract entity name */
- p = pv;
-
- while (*p && isspace((unsigned char)*p) && *p != '<' && *p != '>') {
- if (*p == '\n')
- line_number++;
- p++;
- }
- if (!*p) {
- read_error(HERE, "Unexpected end of file");
- status = 1;
- goto error;
- }
- if (*p == '<' || *p == '>') {
- read_error(HERE, "Unexpected \'%c\' inside !ENTITY", *p);
- status = 1;
- goto error;
- }
-
- pv = p;
- while (*pv && !isspace((unsigned char)*pv) && *pv != '<' && *pv != '>')
- pv++;
-
- if (!*pv) {
- read_error(HERE, "Unexpected end of file");
- status = 1;
- goto error;
- }
- if (*pv == '<' || *pv == '>') {
- read_error(HERE, "Unexpected \'%c\' inside entity \"%s\"", *pv, &entity_name[nentity][1]);
- status = 1;
- goto error;
- }
-
- entity_name[nentity][0] = '&';
- i = 1;
- entity_name[nentity][i] = 0;
- while (*p && !isspace((unsigned char)*p) && *p != '/' && *p != '>' && *p != '<' && i < 253)
- entity_name[nentity][i++] = *p++;
- entity_name[nentity][i++] = ';';
- entity_name[nentity][i] = 0;
-
- if (!*p) {
- read_error(HERE, "Unexpected end of file");
- status = 1;
- goto error;
- }
- if (*p == '<') {
- read_error(HERE, "Unexpected \'<\' inside entity \"%s\"", &entity_name[nentity][1]);
- status = 1;
- goto error;
- }
-
- /* extract replacement or SYSTEM */
- while (*p && isspace((unsigned char)*p)) {
- if (*p == '\n')
- line_number++;
- p++;
- }
- if (!*p) {
- read_error(HERE, "Unexpected end of file");
- status = 1;
- goto error;
- }
- if (*p == '>') {
- read_error(HERE, "Unexpected \'>\' inside entity \"%s\"", &entity_name[nentity][1]);
- status = 1;
- goto error;
- }
-
- /* check if SYSTEM */
- if (strncmp(p, "SYSTEM", 6) == 0) {
- entity_type[nentity] = EXTERNAL_ENTITY;
- p += 6;
- } else {
- entity_type[nentity] = INTERNAL_ENTITY;
- }
-
- /* extract replacement */
- while (*p && isspace((unsigned char)*p)) {
- if (*p == '\n')
- line_number++;
- p++;
- }
- if (!*p) {
- read_error(HERE, "Unexpected end of file");
- status = 1;
- goto error;
- }
- if (*p == '>') {
- read_error(HERE, "Unexpected \'>\' inside entity \"%s\"", &entity_name[nentity][1]);
- status = 1;
- goto error;
- }
-
- if (*p != '\"' && *p != '\'') {
- read_error(HERE, "Replacement was not found for entity \"%s\"", &entity_name[nentity][1]);
- status = 1;
- goto error;
- }
- delimiter = *p;
- p++;
- if (!*p) {
- read_error(HERE, "Unexpected end of file");
- status = 1;
- goto error;
- }
- pv = p;
- while (*pv && *pv != delimiter)
- pv++;
-
- if (!*pv) {
- read_error(HERE, "Unexpected end of file");
- status = 1;
- goto error;
- }
- if (*pv == '<') {
- read_error(HERE, "Unexpected \'%c\' inside entity \"%s\"", *pv, &entity_name[nentity][1]);
- status = 1;
- goto error;
- }
-
- len = (int)((size_t) pv - (size_t) p);
- replacement = (char *) mxml_malloc(len + 1);
- if (replacement == NULL) {
- read_error(HERE, "Cannot allocate memory.");
- status = 1;
- goto error;
- }
-
- memcpy(replacement, p, len);
- replacement[len] = 0;
- mxml_decode(replacement);
-
- if (entity_type[nentity] == EXTERNAL_ENTITY) {
- strcpy(entity_reference_name[nentity], replacement);
- } else {
- entity_value[nentity] = (char *) mxml_malloc(strlen(replacement));
- if (entity_value[nentity] == NULL) {
- read_error(HERE, "Cannot allocate memory.");
- status = 1;
- goto error;
- }
- strcpy(entity_value[nentity], replacement);
- }
- mxml_free(replacement);
-
- p = pv;
- while (*p && isspace((unsigned char)*p)) {
- if (*p == '\n')
- line_number++;
- p++;
- }
- if (!*p) {
- read_error(HERE, "Unexpected end of file");
- status = 1;
- goto error;
- }
- }
- }
-
- /* go to next element */
- while (*p && *p != '<') {
- if (*p == '\n')
- line_number++;
- p++;
- }
- } while (*p);
- nentity++;
-
- /* read external file */
- for (i = 0; i < nentity; i++) {
- if (entity_type[i] == EXTERNAL_ENTITY) {
- if ( entity_reference_name[i][0] == DIR_SEPARATOR ) /* absolute path */
- strcpy(filename, entity_reference_name[i]);
- else /* relative path */
- sprintf(filename, "%s%c%s", directoryname, DIR_SEPARATOR, entity_reference_name[i]);
- fh = open(filename, O_RDONLY | O_TEXT, 0644);
-
- if (fh == -1) {
- line_number = entity_line_number[i];
- read_error(HERE, "%s is missing", entity_reference_name[i]);
- status = 1;
- goto error;
- } else {
- length = (int)lseek(fh, 0, SEEK_END);
- lseek(fh, 0, SEEK_SET);
- if (length == 0) {
- entity_value[i] = (char *) mxml_malloc(1);
- if (entity_value[i] == NULL) {
- read_error(HERE, "Cannot allocate memory.");
- close(fh);
- status = 1;
- goto error;
- }
- entity_value[i][0] = 0;
- } else {
- entity_value[i] = (char *) mxml_malloc(length);
- if (entity_value[i] == NULL) {
- read_error(HERE, "Cannot allocate memory.");
- close(fh);
- status = 1;
- goto error;
- }
-
- /* read complete file at once */
- length = (int)read(fh, entity_value[i], length);
- entity_value[i][length - 1] = 0;
- close(fh);
-
- /* recursive parse */
- if (mxml_parse_entity(&entity_value[i], filename, error, error_size, error_line) != 0) {
- status = 1;
- goto error;
- }
- }
- }
- }
- }
-
- /* count length of output string */
- length = (int)strlen(buffer);
- for (i = 0; i < nentity; i++) {
- p = buffer;
- entity_value_length[i] = (int)strlen(entity_value[i]);
- entity_name_length[i] = (int)strlen(entity_name[i]);
- while (1) {
- pv = strstr(p, entity_name[i]);
- if (pv) {
- length += entity_value_length[i] - entity_name_length[i];
- p = pv + 1;
- } else {
- break;
- }
- }
- }
-
- /* re-allocate memory */
- *buf = (char *) mxml_realloc(*buf, length + 1);
- if (*buf == NULL) {
- read_error(HERE, "Cannot allocate memory.");
- status = 1;
- goto error;
- }
-
- /* replace entities */
- p = buffer;
- pv = *buf;
- do {
- if (*p == '&') {
- /* found entity */
- for (j = 0; j < nentity; j++) {
- if (strncmp(p, entity_name[j], entity_name_length[j]) == 0) {
- for (k = 0; k < (int) entity_value_length[j]; k++)
- *pv++ = entity_value[j][k];
- p += entity_name_length[j];
- break;
- }
- }
- }
- *pv++ = *p++;
- } while (*p);
- *pv = 0;
-
-error:
-
- if (buffer != NULL)
- mxml_free(buffer);
- for (ip = 0; ip < MXML_MAX_ENTITY; ip++)
- if (entity_value[ip] != NULL)
- mxml_free(entity_value[ip]);
-
- return status;
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * parse a XML file and convert it into a tree of MXML_NODE's.
- * Return NULL in case of an error, return error description
- */
-PMXML_NODE mxml_parse_file(const char *file_name, char *error, int error_size, int *error_line)
-{
- char *buf, line[1000];
- int fh, length;
- PMXML_NODE root;
-
- if (error)
- error[0] = 0;
-
- fh = open(file_name, O_RDONLY | O_TEXT, 0644);
-
- if (fh == -1) {
- sprintf(line, "Unable to open file \"%s\": ", file_name);
- strlcat(line, strerror(errno), sizeof(line));
- strlcpy(error, line, error_size);
- return NULL;
- }
-
- length = (int)lseek(fh, 0, SEEK_END);
- lseek(fh, 0, SEEK_SET);
- buf = (char *)mxml_malloc(length+1);
- if (buf == NULL) {
- close(fh);
- sprintf(line, "Cannot allocate buffer: ");
- strlcat(line, strerror(errno), sizeof(line));
- strlcpy(error, line, error_size);
- return NULL;
- }
-
- /* read complete file at once */
- length = (int)read(fh, buf, length);
- buf[length] = 0;
- close(fh);
-
- if (mxml_parse_entity(&buf, file_name, error, error_size, error_line) != 0) {
- mxml_free(buf);
- return NULL;
- }
-
- root = mxml_parse_buffer(buf, error, error_size, error_line);
-
- mxml_free(buf);
-
- return root;
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * write complete subtree recursively into file opened with mxml_open_document()
- */
-int mxml_write_subtree(MXML_WRITER *writer, PMXML_NODE tree, int indent)
-{
- int i;
-
- mxml_start_element1(writer, tree->name, indent);
- for (i=0 ; i<tree->n_attributes ; i++)
- if (!mxml_write_attribute(writer, tree->attribute_name+i*MXML_NAME_LENGTH, tree->attribute_value[i]))
- return FALSE;
-
- if (tree->value)
- if (!mxml_write_value(writer, tree->value))
- return FALSE;
-
- for (i=0 ; i<tree->n_children ; i++)
- if (!mxml_write_subtree(writer, &tree->child[i], (tree->value == NULL) || i > 0))
- return FALSE;
-
- return mxml_end_element(writer);
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * write a complete XML tree to a file
- */
-int mxml_write_tree(const char *file_name, PMXML_NODE tree)
-{
- MXML_WRITER *writer;
- int i;
-
- assert(tree);
- writer = mxml_open_file(file_name);
- if (!writer)
- return FALSE;
-
- for (i=0 ; i<tree->n_children ; i++)
- if (tree->child[i].node_type == ELEMENT_NODE) /* skip PI and comments */
- if (!mxml_write_subtree(writer, &tree->child[i], TRUE))
- return FALSE;
-
- if (!mxml_close_file(writer))
- return FALSE;
-
- return TRUE;
-}
-
-/*------------------------------------------------------------------*/
-
-PMXML_NODE mxml_clone_tree(PMXML_NODE tree)
-{
- PMXML_NODE clone;
- int i;
-
- clone = (PMXML_NODE)calloc(sizeof(MXML_NODE), 1);
-
- /* copy name, node_type, n_attributes and n_children */
- memcpy(clone, tree, sizeof(MXML_NODE));
-
- clone->value = NULL;
- mxml_replace_node_value(clone, tree->value);
-
- clone->attribute_name = NULL;
- clone->attribute_value = NULL;
- for (i=0 ; i<tree->n_attributes ; i++)
- mxml_add_attribute(clone, tree->attribute_name+i*MXML_NAME_LENGTH, tree->attribute_value[i]);
-
- clone->child = NULL;
- clone->n_children = 0;
- for (i=0 ; i<tree->n_children ; i++)
- mxml_add_tree(clone, mxml_clone_tree(mxml_subnode(tree, i)));
-
- return clone;
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * print XML tree for debugging
- */
-void mxml_debug_tree(PMXML_NODE tree, int level)
-{
- int i, j;
-
- for (i=0 ; i<level ; i++)
- printf(" ");
- printf("Name: %s\n", tree->name);
- for (i=0 ; i<level ; i++)
- printf(" ");
- printf("Valu: %s\n", tree->value);
- for (i=0 ; i<level ; i++)
- printf(" ");
- printf("Type: %d\n", tree->node_type);
- for (i=0 ; i<level ; i++)
- printf(" ");
- printf("Lin1: %d\n", tree->line_number_start);
- for (i=0 ; i<level ; i++)
- printf(" ");
- printf("Lin2: %d\n", tree->line_number_end);
-
- for (j=0 ; j<tree->n_attributes ; j++) {
- for (i=0 ; i<level ; i++)
- printf(" ");
- printf("%s: %s\n", tree->attribute_name+j*MXML_NAME_LENGTH,
- tree->attribute_value[j]);
- }
-
- for (i=0 ; i<level ; i++)
- printf(" ");
- printf("Addr: %08zX\n", (size_t)tree);
- for (i=0 ; i<level ; i++)
- printf(" ");
- printf("Prnt: %08zX\n", (size_t)tree->parent);
- for (i=0 ; i<level ; i++)
- printf(" ");
- printf("NCld: %d\n", tree->n_children);
-
- for (i=0 ; i<tree->n_children ; i++)
- mxml_debug_tree(tree->child+i, level+1);
-
- if (level == 0)
- printf("\n");
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * free memory of XML tree, must be called after any
- * mxml_create_root_node() or mxml_parse_file()
- */
-void mxml_free_tree(PMXML_NODE tree)
-{
- int i;
-
- /* first free children recursively */
- for (i=0 ; i<tree->n_children ; i++)
- mxml_free_tree(&tree->child[i]);
- if (tree->n_children)
- mxml_free(tree->child);
-
- /* now free dynamic data */
- for (i=0 ; i<tree->n_attributes ; i++)
- mxml_free(tree->attribute_value[i]);
-
- if (tree->n_attributes) {
- mxml_free(tree->attribute_name);
- mxml_free(tree->attribute_value);
- }
-
- if (tree->value)
- mxml_free(tree->value);
-
- /* if we are the root node, free it */
- if (tree->parent == NULL)
- mxml_free(tree);
-}
-
-/*------------------------------------------------------------------*/
-
-/*
-void mxml_test()
-{
- char err[256];
- PMXML_NODE tree, tree2, node;
-
- tree = mxml_parse_file("c:\\tmp\\test.xml", err, sizeof(err));
- tree2 = mxml_clone_tree(tree);
-
- printf("Orig:\n");
- mxml_debug_tree(tree, 0);
-
- printf("\nClone:\n");
- mxml_debug_tree(tree2, 0);
-
- printf("\nCombined:\n");
- node = mxml_find_node(tree2, "cddb");
- mxml_add_tree(tree, node);
- mxml_debug_tree(tree, 0);
-
- mxml_free_tree(tree);
-}
-*/
-
-/*------------------------------------------------------------------*/
- /**
- mxml_basename deletes any prefix ending with the last slash '/' character
- present in path. mxml_dirname deletes the filename portion, beginning with
- the last slash '/' character to the end of path. Followings are examples
- from these functions
-
- path dirname basename
- "/" "/" ""
- "." "." "."
- "" "" ""
- "/test.txt" "/" "test.txt"
- "path/to/test.txt" "path/to" "test.txt"
- "test.txt "." "test.txt"
-
- Under Windows, '\\' and ':' are recognized ad separator too.
- */
-
-void mxml_basename(char *path)
-{
- char str[FILENAME_MAX];
- char *p;
- char *name;
-
- if (path) {
- strcpy(str, path);
- p = str;
- name = str;
- while (1) {
- if (*p == 0)
- break;
- if (*p == '/'
-#ifdef _MSC_VER
- || *p == ':' || *p == '\\'
-#endif
- )
- name = p + 1;
- p++;
- }
- strcpy(path, name);
- }
-
- return;
-}
-
-void mxml_dirname(char *path)
-{
- char *p;
-#ifdef _MSC_VER
- char *pv;
-#endif
-
- if (!path || strlen(path) == 0)
- return;
-
- p = strrchr(path, '/');
-#ifdef _MSC_VER
- pv = strrchr(path, ':');
- if (pv > p)
- p = pv;
- pv = strrchr(path, '\\');
- if (pv > p)
- p = pv;
-#endif
-
- if (p == 0) /* current directory */
- strcpy(path, ".");
- else if (p == path) /* root directory */
- sprintf(path, "%c", *p);
- else
- *p = 0;
-
- return;
-}
-
-/*------------------------------------------------------------------*/
-
-/**
- * Retieve node at a certain line number
- */
-PMXML_NODE mxml_get_node_at_line(PMXML_NODE tree, int line_number)
-{
- int i;
- PMXML_NODE pn;
-
- if (tree->line_number_start == line_number)
- return tree;
-
- for (i=0 ; i<tree->n_children ; i++) {
- pn = mxml_get_node_at_line(&tree->child[i], line_number);
- if (pn)
- return pn;
- }
-
- return NULL;
-}
-
Index: instr/drsctrl/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/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, REG_TRG_DELAY, 2);
+ reg = (reg & 0xFF00) | ticks;
+ Write(T_CTRL, REG_TRG_DELAY, &ticks, 2);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::SetTriggerDelayNs(int delay)
+/* set trigger delay in nanoseconds */
+{
+ short ticks, reg;
+ fTriggerDelayNs = delay;
+
+ if (fBoardType == 5 || fBoardType == 6 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
+
+ // convert delay in ns into ticks
+ if (fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
+ if (fFirmwareVersion >= 17147)
+ ticks = (short int)(delay / LUT_DELAY_S3_8 + 0.5);
+ else
+ ticks = (short int)(delay / LUT_DELAY_S3_4 + 0.5);
+ } else {
+ if (fFirmwareVersion >= 17382)
+ ticks = (short int)(delay / LUT_DELAY_V2_8 + 0.5);
+ else
+ ticks = (short int)(delay / LUT_DELAY_V2_4 + 0.5);
+ }
+
+ if (ticks > 255)
+ ticks = 255;
+ if (ticks < 0)
+ ticks = 0;
+
+ fTriggerDelay = ticks / 255 * 100;
+
+ Read(T_CTRL, &reg, REG_TRG_DELAY, 2);
+ reg = (reg & 0xFF00) | ticks;
+ Write(T_CTRL, REG_TRG_DELAY, &ticks, 2);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::SetSyncDelay(int ticks)
+{
+ short int reg;
+
+ if (fBoardType == 5 || fBoardType == 6 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
+ Read(T_CTRL, &reg, REG_TRG_DELAY, 2);
+ reg = (reg & 0xFF) | (ticks << 8);
+ Write(T_CTRL, REG_TRG_DELAY, &reg, 2);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::SetTriggerSource(int source)
+{
+ short int reg;
+
+ fTriggerSource = source;
+ if (fBoardType == 5 || fBoardType == 7) {
+ // Set trigger source
+ // 0=CH1, 1=CH2, 2=CH3, 3=CH4
+ if (source & 1)
+ fCtrlBits |= BIT_TR_SOURCE1;
+ else
+ fCtrlBits &= ~BIT_TR_SOURCE1;
+ if (source & 2)
+ fCtrlBits |= BIT_TR_SOURCE2;
+ else
+ fCtrlBits &= ~BIT_TR_SOURCE2;
+
+ Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
+ } else if (fBoardType == 8 || fBoardType == 9) {
+ // Set trigger configuration
+ // OR Bit0=CH1, Bit1=CH2, Bit2=CH3, Bit3=CH4, Bit4=EXT
+ // AND Bit8=CH1, Bit9=CH2, Bit10=CH3, Bit11=CH4, Bit12=EXT
+ // TRANSP Bit15
+ reg = (unsigned short) source;
+ Write(T_CTRL, REG_TRG_CONFIG, &reg, 2);
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::SetDelayedStart(int flag)
+{
+ // Enable external trigger
+ fDelayedStart = flag;
+ if (flag)
+ fCtrlBits |= BIT_DELAYED_START;
+ else
+ fCtrlBits &= ~BIT_DELAYED_START;
+
+ Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::SetTranspMode(int flag)
+{
+ // Enable/disable transparent mode
+ fTranspMode = flag;
+ if (flag)
+ fCtrlBits |= BIT_TRANSP_MODE;
+ else
+ fCtrlBits &= ~BIT_TRANSP_MODE;
+
+ Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::SetStandbyMode(int flag)
+{
+ // Enable/disable standby mode
+ fTranspMode = flag;
+ if (flag)
+ fCtrlBits |= BIT_STANDBY_MODE;
+ else
+ fCtrlBits &= ~BIT_STANDBY_MODE;
+
+ Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::SetDecimation(int flag)
+{
+ // Drop every odd sample
+ fDecimation = flag;
+ if (flag)
+ fCtrlBits |= BIT_DECIMATION;
+ else
+ fCtrlBits &= ~BIT_DECIMATION;
+
+ Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
+
+ // Calculate channel depth
+ fChannelDepth = fChannelCascading * (fDecimation ? kNumberOfBins/2 : kNumberOfBins);
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::IsBusy()
+{
+ // Get running flag
+ unsigned int status;
+
+ Read(T_STATUS, &status, REG_STATUS, 4);
+ return (status & BIT_RUNNING) > 0;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::IsEventAvailable()
+{
+ if (!fMultiBuffer)
+ return !IsBusy();
+
+ return GetMultiBufferWP() != fReadPointer;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::IsPLLLocked()
+{
+ // Get running flag
+ unsigned int status;
+
+ Read(T_STATUS, &status, REG_STATUS, 4);
+ if (GetBoardType() == 6)
+ return ((status >> 1) & 0x0F) == 0x0F;
+ return (status & BIT_PLL_LOCKED0) > 0;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::IsLMKLocked()
+{
+ // Get running flag
+ unsigned int status;
+
+ Read(T_STATUS, &status, REG_STATUS, 4);
+ if (GetBoardType() == 6)
+ return (status & BIT_LMK_LOCKED) > 0;
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::IsNewFreq(unsigned char chipIndex)
+{
+ unsigned int status;
+
+ Read(T_STATUS, &status, REG_STATUS, 4);
+ if (chipIndex == 0)
+ return (status & BIT_NEW_FREQ1) > 0;
+ return (status & BIT_NEW_FREQ2) > 0;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::ReadFrequency(unsigned char chipIndex, double *f)
+{
+ if (fDRSType == 4) {
+
+ if (fBoardType == 6) {
+ *f = fNominalFrequency;
+ return 1;
+ }
+
+ unsigned short ticks;
+
+ Read(T_CTRL, &ticks, REG_FREQ_SET, 2);
+ ticks += 2;
+
+ /* convert rounded ticks back to frequency */
+ if (ticks > 2)
+ *f = 1.024 / ticks * fRefClock;
+ else
+ *f = 0;
+ } else {
+ // Read domino sampling frequency
+ unsigned char buffer[2];
+
+ if (chipIndex == 0)
+ Read(T_STATUS, buffer, REG_FREQ1, 2);
+ else
+ Read(T_STATUS, buffer, REG_FREQ2, 2);
+
+ *f = (static_cast < unsigned int >(buffer[1]) << 8) +buffer[0];
+
+ /* convert counts to frequency */
+ if (*f != 0)
+ *f = 1024 * 200 * (32.768E6 * 4) / (*f) / 1E9;
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+double DRSBoard::VoltToFreq(double volt)
+{
+ if (fDRSType == 3) {
+ if (volt <= 1.2001)
+ return (volt - 0.6) / 0.2;
+ else
+ return 0.73 / 0.28 + sqrt((0.73 / 0.28) * (0.73 / 0.28) - 2.2 / 0.14 + volt / 0.14);
+ } else
+ return (volt - 0.5) / 0.2;
+}
+
+/*------------------------------------------------------------------*/
+
+double DRSBoard::FreqToVolt(double freq)
+{
+ if (fDRSType == 3) {
+ if (freq <= 3)
+ return 0.6 + 0.2 * freq;
+ else
+ return 2.2 - 0.73 * freq + 0.14 * freq * freq;
+ } else
+ return 0.55 + 0.25 * freq;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::ConfigureLMK(double sampFreq, bool freqChange, int calFreq, int calPhase)
+{
+ unsigned int data[] = { 0x80000100, // RESET=1
+ 0x0007FF00, // CLKOUT0: EN=1, DIV=FF (=510) MUX=Div&Delay
+ 0x00000101, // CLKOUT1: Disabled
+ 0x0082000B, // R11: DIV4=0
+ 0x028780AD, // R13: VCO settings
+ 0x0830000E, // R14: PLL settings
+ 0xC000000F }; // R15: PLL settings
+
+ /* calculate dividing ratio */
+ int divider, vco_divider, n_counter, r_counter;
+ unsigned int status;
+ double clk, vco;
+
+ if (fTransport == TR_USB2) {
+ /* 30 MHz clock */
+ data[4] = 0x028780AD; // R13 according to CodeLoader 4
+ clk = 30;
+ if (sampFreq < 1) {
+ r_counter = 1;
+ vco_divider = 8;
+ n_counter = 5;
+ } else {
+ r_counter = 1;
+ vco_divider = 5;
+ n_counter = 8;
+ }
+ } else {
+
+ if (fCtrlBits & BIT_REFCLK_SOURCE) {
+ /* 19.44 MHz clock */
+ data[4] = 0x0284C0AD; // R13 according to CodeLoader 4
+ clk = 19.44; // global clock through P2
+
+ r_counter = 2;
+ vco_divider = 8;
+ n_counter = 16;
+ } else {
+ /* 33 MHz clock */
+ data[4] = 0x028840AD; // R13 according to CodeLoader 4
+ clk = 33; // FPGA clock
+
+ r_counter = 2;
+ vco_divider = 8;
+ n_counter = 9;
+ }
+ }
+
+ vco = clk/r_counter*n_counter*vco_divider;
+ divider = (int) ((vco / vco_divider / (sampFreq/2.048) / 2.0) + 0.5);
+
+ /* return exact frequency */
+ fNominalFrequency = vco/vco_divider/(divider*2)*2.048;
+
+ /* return exact timing calibration frequency */
+ fTCALFrequency = vco/vco_divider;
+
+ /* change registers accordingly */
+ data[1] = 0x00070000 | (divider << 8); // R0
+ data[5] = 0x0830000E | (r_counter << 8); // R14
+ data[6] = 0xC000000F | (n_counter << 8) | (vco_divider << 26); // R15
+
+ /* enable TCA output if requested */
+ if (calFreq) {
+ if (calFreq == 1)
+ data[2] = 0x00050001 | ( 1<<8) ; // 148.5 MHz (33 MHz PLL)
+ // 150 MHz (30 MHz PLL)
+ // 155.52 MHz (19.44 MHz PLL)
+ else if (calFreq == 2) {
+ data[2] = 0x00070001 | ( 4<<8); // above values divided by 8
+ fTCALFrequency /= 8;
+ } else if (calFreq == 3) {
+ data[2] = 0x00070001 | (255<<8); // above values divided by 510
+ fTCALFrequency /= 510;
+ }
+ }
+
+ /* set delay to adjsut phase */
+ if (calPhase > 0)
+ data[2] |= (( calPhase & 0x0F) << 4);
+ else if (calPhase < 0)
+ data[1] |= ((-calPhase & 0x0F) << 4);
+
+ if (freqChange) {
+ /* set all registers */
+ for (int i=0 ; i<(int)(sizeof(data)/sizeof(unsigned int)) ; i++) {
+ Write(T_CTRL, REG_LMK_LSB, &data[i], 2);
+ Write(T_CTRL, REG_LMK_MSB, ((char *)&data[i])+2, 2);
+ // poll on serial_busy flag
+ for (int j=0 ; j<100 ; j++) {
+ Read(T_STATUS, &status, REG_STATUS, 4);
+ if ((status & BIT_SERIAL_BUSY) == 0)
+ break;
+ }
+ }
+ } else {
+ /* only enable/disable timing calibration frequency */
+ Write(T_CTRL, REG_LMK_LSB, &data[1], 2);
+ Write(T_CTRL, REG_LMK_MSB, ((char *)&data[1])+2, 2);
+
+ /* poll on serial_busy flag */
+ for (int j=0 ; j<100 ; j++) {
+ Read(T_STATUS, &status, REG_STATUS, 4);
+ if ((status & BIT_SERIAL_BUSY) == 0)
+ break;
+ }
+
+ Write(T_CTRL, REG_LMK_LSB, &data[2], 2);
+ Write(T_CTRL, REG_LMK_MSB, ((char *)&data[2])+2, 2);
+
+ /* poll on serial_busy flag */
+ for (int j=0 ; j<100 ; j++) {
+ Read(T_STATUS, &status, REG_STATUS, 4);
+ if ((status & BIT_SERIAL_BUSY) == 0)
+ break;
+ }
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::SetFrequency(double demand, bool wait)
+{
+ // Set domino sampling frequency
+ double freq, voltage, delta_voltage;
+ unsigned short ticks;
+ int i, index, timeout;
+ int dominoModeSave = fDominoMode;
+ int triggerEnableSave1 = fTriggerEnable1;
+ int triggerEnableSave2 = fTriggerEnable2;
+
+ if (fDRSType == 4) {
+ /* allowed range is 100 MHz to 6 GHz */
+ if (demand > 6 || demand < 0.1)
+ return 0;
+
+ if (fBoardType == 6) {
+ for (i=1 ; i<100 ; i++) {
+ ConfigureLMK(demand, true, fTcalFreq, fTcalPhase);
+ Sleep(10);
+ if (IsLMKLocked())
+ return 1;
+ printf("Re-start LMK in VME slot %2d %s\n",
+ (GetSlotNumber() >> 1)+2, ((GetSlotNumber() & 1) == 0) ? "upper" : "lower");
+ }
+ return 0;
+ }
+
+ /* convert frequency in GHz into ticks counted by reference clock */
+ if (demand == 0)
+ ticks = 0; // turn off frequency generation
+ else
+ ticks = static_cast < unsigned short >(1.024 / demand * fRefClock + 0.5);
+
+ ticks -= 2; // firmware counter need two additional clock cycles
+ Write(T_CTRL, REG_FREQ_SET, &ticks, 2);
+ ticks += 2;
+
+ /* convert rounded ticks back to frequency */
+ if (demand > 0)
+ demand = 1.024 / ticks * fRefClock;
+ fNominalFrequency = demand;
+
+ /* wait for PLL lock if asked */
+ if (wait) {
+ StartDomino();
+ for (i=0 ; i<1000 ; i++)
+ if (GetStatusReg() & BIT_PLL_LOCKED0)
+ break;
+ SoftTrigger();
+ if (i == 1000) {
+ printf("PLL did not lock for frequency %lf\n", demand);
+ return 0;
+ }
+ }
+ } else { // fDRSType == 4
+ SetDominoMode(1);
+ EnableTrigger(0, 0);
+ EnableAcal(0, 0);
+
+ fNominalFrequency = demand;
+
+ /* turn automatic adjustment off */
+ fCtrlBits &= ~BIT_FREQ_AUTO_ADJ;
+
+ /* disable external trigger */
+ fCtrlBits &= ~BIT_ENABLE_TRIGGER1;
+ fCtrlBits &= ~BIT_ENABLE_TRIGGER2;
+
+ /* set start pulse length for future DRSBoard_domino_start() */
+ if (fDRSType == 2) {
+ if (demand < 0.8)
+ fCtrlBits |= BIT_LONG_START_PULSE;
+ else
+ fCtrlBits &= ~BIT_LONG_START_PULSE;
+
+ Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
+ }
+
+ /* stop any running domino wave */
+ Reinit();
+
+ /* estimate DAC setting */
+ voltage = FreqToVolt(demand);
+
+ SetDAC(fDAC_DSA, voltage);
+ SetDAC(fDAC_DSB, voltage);
+
+ /* wait until new DAC value has settled */
+ Sleep(10);
+
+ /* restart domino wave */
+ StartDomino();
+
+ ticks = static_cast < unsigned short >(1024 * 200 * (32.768E6 * 4) / demand / 1E9);
+
+ /* iterate over both DRS chips */
+ for (index = 0; index < 2; index++) {
+
+ /* starting voltage */
+ voltage = FreqToVolt(demand);
+
+ for (i = 0; i < 100; i++) {
+
+ /* wait until measurement finished */
+ for (timeout = 0; timeout < 1000; timeout++)
+ if (IsNewFreq(index))
+ break;
+
+ freq = 0;
+ if (timeout == 1000)
+ break;
+
+ ReadFrequency(index, &freq);
+
+ delta_voltage = FreqToVolt(demand) - FreqToVolt(freq);
+
+ if (fDebug) {
+ if (fabs(freq - demand) < 0.001)
+ printf("CHIP-%d, iter%3d: %1.5lf(%05d) %7.5lf\n", index, i, voltage,
+ static_cast < int >(voltage / 2.5 * 65535 + 0.5), freq);
+ else
+ printf("CHIP-%d, iter%3d: %1.5lf(%05d) %7.5lf %+5d\n", index, i, voltage,
+ static_cast < int >(voltage / 2.5 * 65535 + 0.5), freq,
+ static_cast < int >(delta_voltage / 2.5 * 65535 + 0.5));
+ }
+
+ if (fabs(freq - demand) < 0.001)
+ break;
+
+ voltage += delta_voltage;
+ if (voltage > 2.5)
+ voltage = 2.5;
+ if (voltage < 0)
+ voltage = 0;
+
+ if (freq == 0)
+ break;
+
+ if (index == 0)
+ SetDAC(fDAC_DSA, voltage);
+ else
+ SetDAC(fDAC_DSB, voltage);
+
+ Sleep(10);
+ }
+ if (i == 100 || freq == 0 || timeout == 1000) {
+ printf("Board %d --> Could not set frequency of CHIP-#%d to %1.3f GHz\n", GetBoardSerialNumber(),
+ index, demand);
+ return 0;
+ }
+ }
+
+ SetDominoMode(dominoModeSave);
+ EnableTrigger(triggerEnableSave1, triggerEnableSave2);
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::RegulateFrequency(double demand)
+{
+ // Set frequency regulation
+ unsigned short target, target_hi, target_lo;
+
+ if (demand < 0.42 || demand > 5.2)
+ return 0;
+
+ fNominalFrequency = demand;
+
+ /* first iterate DAC value from host */
+ if (!SetFrequency(demand, true))
+ return 0;
+
+ /* convert frequency in GHz into counts for 200 cycles */
+ target = static_cast < unsigned short >(1024 * 200 * (32.768E6 * 4) / demand / 1E9);
+ target_hi = target + 6;
+ target_lo = target - 6;
+ Write(T_CTRL, REG_FREQ_SET_HI, &target_hi, 2);
+ Write(T_CTRL, REG_FREQ_SET_LO, &target_lo, 2);
+
+ /* turn on regulation */
+ fCtrlBits |= BIT_FREQ_AUTO_ADJ;
+ Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
+
+ /* optional monitoring code ... */
+#if 0
+ do {
+ double freq;
+ unsigned short dac, cnt;
+
+ ReadFrequency(0, &freq);
+
+ if (fBoardType == 1)
+ Read(T_STATUS, &dac, REG_RDAC3, 2);
+ else if (fBoardType == 2 || fBoardType == 3)
+ Read(T_STATUS, &dac, REG_RDAC1, 2);
+
+ Read(T_STATUS, &cnt, REG_FREQ1, 2);
+
+ if (cnt < 65535)
+ printf("%5d %5d %5d %1.5lf\n", dac, target, cnt, freq);
+
+ Sleep(500);
+ } while (1);
+#endif
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+void DRSBoard::RegisterTest()
+{
+ // Register test
+#define N_REG 8
+
+ int i, n, n_err;
+ unsigned int buffer[N_REG], ret[N_REG];
+
+ /* test single register */
+ buffer[0] = 0x12345678;
+ Write(T_CTRL, 0, buffer, 4);
+ memset(ret, 0, sizeof(ret));
+ i = Read(T_CTRL, ret, 0, 4);
+ while (i != 4)
+ printf("Read error single register!\n");
+
+ printf("Reg.0: %08X - %08X\n", buffer[0], ret[0]);
+
+ n_err = 0;
+ for (n = 0; n < 100; n++) {
+ for (i = 0; i < N_REG; i++)
+ buffer[i] = (rand() << 16) | rand();
+ Write(T_CTRL, 0, buffer, sizeof(buffer));
+
+ memset(ret, 0, sizeof(ret));
+ i = Read(T_CTRL, ret, 0, sizeof(ret));
+ while (i != sizeof(ret)) {
+ printf("Read error!\n");
+ return;
+ }
+
+ for (i = 0; i < N_REG; i++) {
+ if (n == 0)
+ printf("Reg.%d: %08X - %08X\n", i, buffer[i], ret[i]);
+ if (buffer[i] != ret[i]) {
+ n_err++;
+ }
+ }
+ }
+
+ printf("Register test: %d errors\n", n_err);
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::RAMTest(int flag)
+{
+#define MAX_N_BYTES 128*1024 // 128 kB
+
+ int i, j, n, bits, n_bytes, n_words, n_dwords;
+ unsigned int buffer[MAX_N_BYTES/4], ret[MAX_N_BYTES/4];
+ time_t now;
+
+ if (fBoardType == 6 && fTransport == TR_VME) {
+ bits = 32;
+ n_bytes = 128*1024; // test full 128 kB
+ n_words = n_bytes/2;
+ n_dwords = n_words/2;
+ } else {
+ bits = 24;
+ n_words = 9*1024;
+ n_bytes = n_words * 2;
+ n_dwords = n_words/2;
+ }
+
+ if (flag & 1) {
+ /* integrety test */
+ printf("Buffer size: %d (%1.1lfk)\n", n_words * 2, n_words * 2 / 1024.0);
+ if (flag & 1) {
+ for (i = 0; i < n_dwords; i++) {
+ if (bits == 24)
+ buffer[i] = (rand() | rand() << 16) & 0x00FFFFFF; // random 24-bit values
+ else
+ buffer[i] = (rand() | rand() << 16); // random 32-bit values
+ }
+
+ Reinit();
+ Write(T_RAM, 0, buffer, n_bytes);
+ memset(ret, 0, n_bytes);
+ Read(T_RAM, ret, 0, n_bytes);
+ Reinit();
+
+ for (i = n = 0; i < n_dwords; i++) {
+ if (buffer[i] != ret[i]) {
+ n++;
+ }
+ if (i < 10)
+ printf("written: %08X read: %08X\n", buffer[i], ret[i]);
+ }
+
+ printf("RAM test: %d errors\n", n);
+ }
+ }
+
+ /* speed test */
+ if (flag & 2) {
+ /* read continously to determine speed */
+ time(&now);
+ while (now == time(NULL));
+ time(&now);
+ i = n = 0;
+ do {
+ memset(ret, 0, n_bytes);
+
+ for (j = 0; j < 10; j++) {
+ Read(T_RAM, ret, 0, n_bytes);
+ i += n_bytes;
+ }
+
+ if (flag & 1) {
+ for (j = 0; j < n_dwords; j++)
+ if (buffer[j] != ret[j])
+ n++;
+ }
+
+ if (now != time(NULL)) {
+ if (flag & 1)
+ printf("%d read/sec, %1.2lf MB/sec, %d errors\n", static_cast < int >(i / n_bytes),
+ i / 1024.0 / 1024.0, n);
+ else
+ printf("%d read/sec, %1.2lf MB/sec\n", static_cast < int >(i / n_bytes),
+ i / 1024.0 / 1024.0);
+ time(&now);
+ i = 0;
+ }
+
+ if (drs_kbhit())
+ break;
+
+ } while (1);
+
+ while (drs_kbhit())
+ getch();
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::ChipTest()
+{
+ int i, j, t;
+ double freq, old_freq, min, max, mean, std;
+ float waveform[1024];
+
+ Init();
+ SetChannelConfig(0, 8, 8);
+ SetDominoMode(1);
+ SetReadoutMode(1);
+ SetDominoActive(1);
+ SetTranspMode(0);
+ EnableTrigger(0, 0);
+ EnableTcal(1, 0);
+ SelectClockSource(0);
+ EnableAcal(1, 0);
+
+ /* test 1 GHz */
+ SetFrequency(1, true);
+ StartDomino();
+ Sleep(100);
+ if (!(GetStatusReg() & BIT_PLL_LOCKED0)) {
+ puts("PLL did not lock at 1 GHz");
+ return 0;
+ }
+
+ /* test up to 6 GHz */
+ for (freq = 5 ; freq < 6 ; freq += 0.1) {
+ SetFrequency(freq, false);
+ Sleep(10);
+ if (!(GetStatusReg() & BIT_PLL_LOCKED0)) {
+ printf("Max. frequency is %1.1lf GHz\n", old_freq);
+ break;
+ }
+ ReadFrequency(0, &old_freq);
+ }
+
+ /* read and check at 0 calibration voltage */
+ SetFrequency(5, true);
+ Sleep(10);
+ SoftTrigger();
+ while (IsBusy());
+ TransferWaves(0, 8);
+
+ for (i=0 ; i<8 ; i++) {
+ t = GetStopCell(0);
+ GetWave(0, i, waveform, false, t, 0, false);
+ for (j=0 ; j<1024; j++)
+ if (waveform[j] < -100 || waveform[j] > 100) {
+ if (j<5) {
+ /* skip this cells */
+ } else {
+ printf("Cell error on channel %d, cell %d: %1.1lf mV instead 0 mV\n", i, j, waveform[j]);
+ return 0;
+ }
+ }
+ }
+
+ /* read and check at +0.5V calibration voltage */
+ EnableAcal(1, 0.5);
+ StartDomino();
+ SoftTrigger();
+ while (IsBusy());
+ TransferWaves(0, 8);
+
+ for (i=0 ; i<8 ; i++) {
+ t = GetStopCell(0);
+ GetWave(0, i, waveform, false, t, 0, false);
+ for (j=0 ; j<1024; j++)
+ if (waveform[j] < 350) {
+ if (j<5) {
+ /* skip this cell */
+ } else {
+ printf("Cell error on channel %d, cell %d: %1.1lf mV instead 400 mV\n", i, j, waveform[j]);
+ return 0;
+ }
+ }
+ }
+
+ /* read and check at -0.5V calibration voltage */
+ EnableAcal(1, -0.5);
+ StartDomino();
+ Sleep(10);
+ SoftTrigger();
+ while (IsBusy());
+ TransferWaves(0, 8);
+
+ for (i=0 ; i<8 ; i++) {
+ t = GetStopCell(0);
+ GetWave(0, i, waveform, false, t, 0, false);
+ for (j=0 ; j<1024; j++)
+ if (waveform[j] > -350) {
+ if (j<5) {
+ /* skip this cell */
+ } else {
+ printf("Cell error on channel %d, cell %d: %1.1lf mV instead -400mV\n", i, j, waveform[j]);
+ return 0;
+ }
+ }
+ }
+
+ /* check clock channel */
+ GetWave(0, 8, waveform, false, 0, 0);
+ min = max = mean = std = 0;
+ for (j=0 ; j<1024 ; j++) {
+ if (waveform[j] > max)
+ max = waveform[j];
+ if (waveform[j] < min)
+ min = waveform[j];
+ mean += waveform[j];
+ }
+ mean /= 1024.0;
+ for (j=0 ; j<1024 ; j++)
+ std += (waveform[j] - mean) * (waveform[j] - mean);
+ std = sqrt(std/1024);
+
+ if (max - min < 400) {
+ printf("Error on clock channel amplitude: %1.1lf mV\n", max-min);
+ return 0;
+ }
+
+ if (std < 100 || std > 300) {
+ printf("Error on clock channel Std: %1.1lf mV\n", std);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+void DRSBoard::SetVoltageOffset(double offset1, double offset2)
+{
+ if (fDRSType == 3) {
+ SetDAC(fDAC_ROFS_1, 0.95 - offset1);
+ SetDAC(fDAC_ROFS_2, 0.95 - offset2);
+ } else if (fDRSType == 2)
+ SetDAC(fDAC_COFS, 0.9 - offset1);
+
+ // let DAC settle
+ Sleep(100);
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::SetInputRange(double center)
+{
+ if (fBoardType == 5 || fBoardType == 6 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
+ // DRS4 USB Evaluation Boards + Mezzanine Board
+
+ // only allow -0.5...0.5 to 0...1.0
+ if (center < 0 || center > 0.5)
+ return 0;
+
+ // remember range
+ fRange = center;
+
+ // correct for sampling cell charge injection
+ center *= 1.125;
+
+ // set readout offset
+ fROFS = 1.6 - center;
+ SetDAC(fDAC_ROFS_1, fROFS);
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::SetExternalClockFrequency(double frequencyMHz)
+{
+ // Set the frequency of the external clock
+ fExternalClockFrequency = frequencyMHz;
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+
+double DRSBoard::GetExternalClockFrequency()
+{
+ // Return the frequency of the external clock
+ return fExternalClockFrequency;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::SetMultiBuffer(int flag)
+{
+ if (fHasMultiBuffer) {
+ // Enable/disable multi-buffering
+ fMultiBuffer = flag;
+ if (flag)
+ fCtrlBits |= BIT_MULTI_BUFFER;
+ else
+ fCtrlBits &= ~BIT_MULTI_BUFFER;
+
+ if (flag) {
+ if (fBoardType == 6)
+ fNMultiBuffer = 3; // 3 buffers for VME board
+ } else
+ fNMultiBuffer = 0;
+
+ Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
+ }
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+void DRSBoard::ResetMultiBuffer(void)
+{
+ Reinit(); // set WP=0
+ fReadPointer = 0;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::GetMultiBufferRP(void)
+{
+ return fReadPointer;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::SetMultiBufferRP(unsigned short rp)
+{
+ if (fHasMultiBuffer) {
+ fReadPointer = rp;
+ Write(T_CTRL, REG_READ_POINTER, &rp, 2);
+ }
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::GetMultiBufferWP(void)
+{
+ unsigned short wp = 0;
+
+ if (fHasMultiBuffer)
+ Read(T_STATUS, &wp, REG_WRITE_POINTER, 2);
+ else
+ wp = 0;
+ return wp;
+}
+
+/*------------------------------------------------------------------*/
+
+void DRSBoard::IncrementMultiBufferRP()
+{
+ if (fHasMultiBuffer && fMultiBuffer)
+ SetMultiBufferRP((fReadPointer + 1) % fNMultiBuffer);
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::TransferWaves(int numberOfChannels)
+{
+ return TransferWaves(fWaveforms, numberOfChannels);
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::TransferWaves(unsigned char *p, int numberOfChannels)
+{
+ return TransferWaves(p, 0, numberOfChannels - 1);
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::TransferWaves(int firstChannel, int lastChannel)
+{
+ int offset;
+
+ if (fTransport == TR_USB)
+ offset = firstChannel * sizeof(short int) * kNumberOfBins;
+ else
+ offset = 0; //in VME and USB2, always start from zero
+
+ return TransferWaves(fWaveforms + offset, firstChannel, lastChannel);
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::TransferWaves(unsigned char *p, int firstChannel, int lastChannel)
+{
+ // Transfer all waveforms at once from VME or USB to location
+ int n, i, offset, n_requested, n_bins;
+ unsigned int dw;
+ unsigned short w;
+ unsigned char *ptr;
+
+ if (lastChannel >= fNumberOfChips * fNumberOfChannels)
+ lastChannel = fNumberOfChips * fNumberOfChannels - 1;
+ if (lastChannel < 0) {
+ printf("Error: Invalid channel index %d\n", lastChannel);
+ return 0;
+ }
+
+ if (firstChannel < 0 || firstChannel > fNumberOfChips * fNumberOfChannels) {
+ printf("Error: Invalid channel index %d\n", firstChannel);
+ return 0;
+ }
+
+ if (fTransport == TR_VME) {
+ /* in VME, always transfer all waveforms, since channels sit 'next' to each other */
+ firstChannel = 0;
+ lastChannel = fNumberOfChips * fNumberOfChannels - 1;
+ if (fReadoutChannelConfig == 4)
+ lastChannel = fNumberOfChips * 5 - 1; // special mode to read only even channels + clock
+ }
+
+ else if (fTransport == TR_USB2) {
+ /* USB2 FPGA contains 9 (Eval) or 10 (Mezz) channels */
+ firstChannel = 0;
+ if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9)
+ lastChannel = 8;
+ else if (fBoardType == 6)
+ lastChannel = 9;
+ }
+
+ else if (fTransport == TR_USB) {
+ /* USB1 FPGA contains only 16 channels */
+ if (lastChannel > 15)
+ lastChannel = 15;
+ }
+
+ n_bins = fDecimation ? kNumberOfBins/2 : kNumberOfBins;
+ n_requested = (lastChannel - firstChannel + 1) * sizeof(short int) * n_bins;
+ offset = firstChannel * sizeof(short int) * n_bins;
+
+ if (fBoardType == 6 && fFirmwareVersion >= 17147)
+ n_requested += 16; // add trailer four chips
+
+ if ((fBoardType == 7 || fBoardType == 8 || fBoardType == 9) && fFirmwareVersion >= 17147)
+ n_requested += 4; // add trailer one chip
+
+ if (fMultiBuffer)
+ offset += n_requested * fReadPointer;
+
+ n = Read(T_RAM, p, offset, n_requested);
+
+ if (fMultiBuffer)
+ IncrementMultiBufferRP();
+
+ if (n != n_requested) {
+ printf("Error: only %d bytes read instead of %d\n", n, n_requested);
+ return n;
+ }
+
+ // read trigger cells
+ if (fDRSType == 4) {
+ if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
+ if ((fBoardType == 7 || fBoardType == 8 || fBoardType == 9) && fFirmwareVersion >= 17147) {
+ // new code reading trailer
+ ptr = p + n_requested - 4;
+ fStopCell[0] = *((unsigned short *)(ptr));
+ fStopWSR[0] = *(ptr + 2);
+ } else {
+ // old code reading status register
+ Read(T_STATUS, fStopCell, REG_STOP_CELL0, 2);
+ Read(T_STATUS, &w, REG_STOP_WSR0, 2);
+ fStopWSR[0] = (w >> 8) & 0xFFFF;
+ }
+ } else {
+
+ if (fBoardType == 6) {
+ // new code reading trailer
+ ptr = p + n_requested - 16;
+ for (i=0 ; i<4 ; i++) {
+ fStopCell[i] = *((unsigned short *)(ptr + i*2));
+ fStopWSR[i] = *(ptr + 8 + i);
+ }
+ fTriggerBus = *((unsigned short *)(ptr + 12));
+ } else {
+ // old code reading registers
+ Read(T_STATUS, &dw, REG_STOP_CELL0, 4);
+ fStopCell[0] = (dw >> 16) & 0xFFFF;
+ fStopCell[1] = (dw >> 0) & 0xFFFF;
+ Read(T_STATUS, &dw, REG_STOP_CELL2, 4);
+ fStopCell[2] = (dw >> 16) & 0xFFFF;
+ fStopCell[3] = (dw >> 0) & 0xFFFF;
+
+ Read(T_STATUS, &dw, REG_STOP_WSR0, 4);
+ fStopWSR[0] = (dw >> 24) & 0xFF;
+ fStopWSR[1] = (dw >> 16) & 0xFF;
+ fStopWSR[2] = (dw >> 8) & 0xFF;
+ fStopWSR[3] = (dw >> 0) & 0xFF;
+
+ Read(T_STATUS, &fTriggerBus, REG_TRIGGER_BUS, 2);
+ }
+ }
+ }
+
+ return n;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::DecodeWave(unsigned int chipIndex, unsigned char channel, unsigned short *waveform)
+{
+ return DecodeWave(fWaveforms, chipIndex, channel, waveform);
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::DecodeWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel,
+ unsigned short *waveform)
+{
+ // Get waveform
+ int i, offset=0, ind, n_bins;
+
+ /* check valid parameters */
+ assert((int)channel < fNumberOfChannels);
+ assert((int)chipIndex < fNumberOfChips);
+
+ /* remap channel */
+ if (fBoardType == 1) {
+ if (channel < 8)
+ channel = 7 - channel;
+ else
+ channel = 16 - channel;
+ } else if (fBoardType == 6) {
+ if (fReadoutChannelConfig == 7) {
+ if (channel < 8)
+ channel = 7-channel;
+ } else if (fReadoutChannelConfig == 4) {
+ if (channel == 8)
+ channel = 4;
+ else
+ channel = 3 - channel/2;
+ } else {
+ channel = channel / 2;
+ if (channel != 4)
+ channel = 3-channel;
+ }
+ } /* else
+ channel = channel; */
+
+ // Read channel
+ if (fTransport == TR_USB) {
+ offset = kNumberOfBins * 2 * (chipIndex * 16 + channel);
+ for (i = 0; i < kNumberOfBins; i++) {
+ // 12-bit data
+ waveform[i] = ((waveforms[i * 2 + 1 + offset] & 0x0f) << 8) + waveforms[i * 2 + offset];
+ }
+ } else if (fTransport == TR_USB2) {
+
+ if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9)
+ // see dpram_map_eval1.xls
+ offset = kNumberOfBins * 2 * (chipIndex * 16 + channel);
+ else if (fBoardType == 6) {
+ // see dpram_map_mezz1.xls mode 0-3
+ offset = (kNumberOfBins * 4) * (channel % 9) + 2 * (chipIndex/2);
+ }
+ for (i = 0; i < kNumberOfBins; i++) {
+ // 16-bit data
+ if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9)
+ waveform[i] = ((waveforms[i * 2 + 1 + offset] & 0xff) << 8) + waveforms[i * 2 + offset];
+ else if (fBoardType == 6)
+ waveform[i] = ((waveforms[i * 4 + 1 + offset] & 0xff) << 8) + waveforms[i * 4 + offset];
+ }
+
+ } else if (fTransport == TR_VME) {
+
+ if (fBoardType == 6) {
+ n_bins = fDecimation ? kNumberOfBins/2 : kNumberOfBins;
+ if (fReadoutChannelConfig == 7) // see dpram_map_mezz1.xls mode 7
+ offset = (n_bins * 4) * (channel % 9 + 9*(chipIndex % 2)) + 2 * (chipIndex/2);
+ else if (fReadoutChannelConfig == 4) // see dpram_map_mezz1.xls mode 4
+ offset = (n_bins * 4) * (channel % 5 + 5*(chipIndex % 2)) + 2 * (chipIndex/2);
+ for (i = 0; i < n_bins; i++)
+ waveform[i] = ((waveforms[i * 4 + 1 + offset] & 0xff) << 8) + waveforms[i * 4 + offset];
+ } else {
+ offset = (kNumberOfBins * 4) * channel;
+ for (i = 0; i < kNumberOfBins; i++) {
+ ind = i * 4 + offset;
+ if (chipIndex == 0)
+ // lower 12 bit
+ waveform[i] = ((waveforms[ind + 1] & 0x0f) << 8) | waveforms[ind];
+ else
+ // upper 12 bit
+ waveform[i] = (waveforms[ind + 2] << 4) | (waveforms[ind + 1] >> 4);
+ }
+ }
+ } else {
+ printf("Error: invalid transport %d\n", fTransport);
+ return kInvalidTransport;
+ }
+ return kSuccess;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::GetWave(unsigned int chipIndex, unsigned char channel, float *waveform)
+{
+ return GetWave(chipIndex, channel, waveform, true, fStopCell[chipIndex], -1, false, 0, true);
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::GetWave(unsigned int chipIndex, unsigned char channel, short *waveform, bool responseCalib,
+ int triggerCell, int wsr, bool adjustToClock, float threshold, bool offsetCalib)
+{
+ return GetWave(fWaveforms, chipIndex, channel, waveform, responseCalib, triggerCell, wsr, adjustToClock,
+ threshold, offsetCalib);
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::GetWave(unsigned int chipIndex, unsigned char channel, float *waveform, bool responseCalib,
+ int triggerCell, int wsr, bool adjustToClock, float threshold, bool offsetCalib)
+{
+ return GetWave(fWaveforms, chipIndex, channel, waveform, responseCalib, triggerCell, wsr, adjustToClock, threshold,
+ offsetCalib);
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::GetWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel,
+ float *waveform, bool responseCalib, int triggerCell, int wsr, bool adjustToClock,
+ float threshold, bool offsetCalib)
+{
+ int ret, i;
+ short waveS[2*kNumberOfBins];
+ ret =
+ GetWave(waveforms, chipIndex, channel, waveS, responseCalib, triggerCell, wsr, adjustToClock, threshold,
+ offsetCalib);
+ if (responseCalib)
+ for (i = 0; i < fChannelDepth ; i++)
+ waveform[i] = static_cast < float >(static_cast <short> (waveS[i]) * GetPrecision());
+ else {
+ for (i = 0; i < fChannelDepth ; i++) {
+ if (fBoardType == 4 || fBoardType == 5 || fBoardType == 6 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
+ waveform[i] = static_cast < float >(waveS[i] * GetPrecision());
+ } else
+ waveform[i] = static_cast < float >(waveS[i]);
+ }
+ }
+ return ret;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::GetWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel,
+ short *waveform, bool responseCalib, int triggerCell, int wsr, bool adjustToClock,
+ float threshold, bool offsetCalib)
+{
+ unsigned short adcWaveform[kNumberOfBins];
+ int i, ret;
+
+ if (fChannelCascading == 1 || channel == 8) {
+ /* single channel configuration */
+ ret = DecodeWave(waveforms, chipIndex, channel, adcWaveform);
+ if (ret != kSuccess)
+ return ret;
+
+ ret = CalibrateWaveform(chipIndex, channel, adcWaveform, waveform, responseCalib,
+ triggerCell, adjustToClock, threshold, offsetCalib);
+
+ return ret;
+ } else if (fChannelCascading == 2) {
+ /* double channel configuration */
+ short wf1[kNumberOfBins];
+ short wf2[kNumberOfBins];
+
+ // first half
+ ret = DecodeWave(waveforms, chipIndex, 2*channel, adcWaveform);
+ if (ret != kSuccess)
+ return ret;
+
+ ret = CalibrateWaveform(chipIndex, 2*channel, adcWaveform, wf1, responseCalib,
+ triggerCell, adjustToClock, threshold, offsetCalib);
+
+ // second half
+ ret = DecodeWave(waveforms, chipIndex, 2*channel+1, adcWaveform);
+ if (ret != kSuccess)
+ return ret;
+
+ ret = CalibrateWaveform(chipIndex, 2*channel+1, adcWaveform, wf2, responseCalib,
+ triggerCell, adjustToClock, threshold, offsetCalib);
+
+
+ // combine two halfs correctly, see 2048_mode.ppt
+ if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
+ if ((wsr == 0 && triggerCell < 767) ||
+ (wsr == 1 && triggerCell >= 767)) {
+ for (i=0 ; i<kNumberOfBins-triggerCell ; i++)
+ waveform[i] = wf1[i];
+ for (; i<kNumberOfBins; i++)
+ waveform[i] = wf2[i];
+ for (i=0 ; i<kNumberOfBins-triggerCell ; i++)
+ waveform[i+kNumberOfBins] = wf2[i];
+ for (; i<kNumberOfBins; i++)
+ waveform[i+kNumberOfBins] = wf1[i];
+ } else {
+ for (i=0 ; i<kNumberOfBins-triggerCell ; i++)
+ waveform[i] = wf2[i];
+ for (; i<kNumberOfBins; i++)
+ waveform[i] = wf1[i];
+ for (i=0 ; i<kNumberOfBins-triggerCell ; i++)
+ waveform[i+kNumberOfBins] = wf1[i];
+ for (; i<kNumberOfBins; i++)
+ waveform[i+kNumberOfBins] = wf2[i];
+ }
+ } else {
+ if (wsr == 1) {
+ if (fDecimation) {
+ for (i=0 ; i<kNumberOfBins/2-triggerCell/2 ; i++)
+ waveform[i] = wf1[i];
+ for (; i<kNumberOfBins/2; i++)
+ waveform[i] = wf2[i];
+ for (i=0 ; i<kNumberOfBins/2-triggerCell/2 ; i++)
+ waveform[i+kNumberOfBins/2] = wf2[i];
+ for (; i<kNumberOfBins/2; i++)
+ waveform[i+kNumberOfBins/2] = wf1[i];
+ } else {
+ for (i=0 ; i<kNumberOfBins-triggerCell ; i++)
+ waveform[i] = wf1[i];
+ for (; i<kNumberOfBins; i++)
+ waveform[i] = wf2[i];
+ for (i=0 ; i<kNumberOfBins-triggerCell ; i++)
+ waveform[i+kNumberOfBins] = wf2[i];
+ for (; i<kNumberOfBins; i++)
+ waveform[i+kNumberOfBins] = wf1[i];
+ }
+ } else {
+ if (fDecimation) {
+ for (i=0 ; i<kNumberOfBins/2-triggerCell/2 ; i++)
+ waveform[i] = wf2[i];
+ for (; i<kNumberOfBins/2; i++)
+ waveform[i] = wf1[i];
+ for (i=0 ; i<kNumberOfBins/2-triggerCell/2 ; i++)
+ waveform[i+kNumberOfBins/2] = wf1[i];
+ for (; i<kNumberOfBins/2; i++)
+ waveform[i+kNumberOfBins/2] = wf2[i];
+ } else {
+ for (i=0 ; i<kNumberOfBins-triggerCell ; i++)
+ waveform[i] = wf2[i];
+ for (; i<kNumberOfBins; i++)
+ waveform[i] = wf1[i];
+ for (i=0 ; i<kNumberOfBins-triggerCell ; i++)
+ waveform[i+kNumberOfBins] = wf1[i];
+ for (; i<kNumberOfBins; i++)
+ waveform[i+kNumberOfBins] = wf2[i];
+ }
+ }
+ }
+
+ return ret;
+ } else
+ assert(!"Not implemented");
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::GetRawWave(unsigned int chipIndex, unsigned char channel, unsigned short *waveform,
+ bool adjustToClock)
+{
+ return GetRawWave(fWaveforms, chipIndex, channel, waveform, adjustToClock);
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::GetRawWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel,
+ unsigned short *waveform, bool adjustToClock)
+{
+ int i, status, tc;
+ unsigned short wf[kNumberOfBins];
+
+ status = DecodeWave(waveforms, chipIndex, channel, wf);
+
+ if (adjustToClock) {
+ tc = GetTriggerCell(chipIndex);
+ for (i = 0 ; i < kNumberOfBins; i++)
+ waveform[(i + tc) % kNumberOfBins] = wf[i];
+ } else {
+ for (i = 0 ; i < kNumberOfBins; i++)
+ waveform[i] = wf[i];
+ }
+
+ return status;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::CalibrateWaveform(unsigned int chipIndex, unsigned char channel, unsigned short *adcWaveform,
+ short *waveform, bool responseCalib,
+ int triggerCell, bool adjustToClock, float threshold, bool offsetCalib)
+{
+ int j, n_bins, skip;
+ double value;
+ short left, right;
+
+ // calibrate waveform
+ if (responseCalib && fVoltageCalibrationValid) {
+ if (GetDRSType() == 4) {
+ // if Mezz though USB2 -> select correct calibration channel
+ if (fBoardType == 6 && (fReadoutChannelConfig == 0 || fReadoutChannelConfig == 2) &&
+ channel != 8)
+ channel++;
+
+ // Channel readout mode #4 -> select correct calibration channel
+ if (fBoardType == 6 && fReadoutChannelConfig == 4 && channel % 2 == 0 && channel != 8)
+ channel++;
+
+ n_bins = fDecimation ? kNumberOfBins/2 : kNumberOfBins;
+ skip = fDecimation ? 2 : 1;
+ for (j = 0; j < n_bins; j++) {
+ value = adcWaveform[j] - fCellOffset[channel+chipIndex*9][(j*skip + triggerCell) % kNumberOfBins];
+ value = value / fCellGain[channel+chipIndex*9][(j*skip + triggerCell) % kNumberOfBins];
+ if (offsetCalib && channel != 8)
+ value = value - fCellOffset2[channel+chipIndex*9][j*skip] + 32768;
+
+ /* convert to units of 0.1 mV */
+ value = value / 65536.0 * 1000 * 10;
+
+ /* apply clipping */
+ if (channel != 8) {
+ if (adcWaveform[j] >= 0xFFF0 || value > (fRange * 1000 + 500) * 10)
+ value = (fRange * 1000 + 500) * 10;
+ if (adcWaveform[j] < 0x0010 || value < (fRange * 1000 - 500) * 10)
+ value = (fRange * 1000 - 500) * 10;
+ }
+
+ if (adjustToClock)
+ waveform[(j + triggerCell) % kNumberOfBins] = (short) (value + 0.5);
+ else
+ waveform[j] = (short) (value + 0.5);
+ }
+
+ // check for stuck pixels and replace by average of neighbors
+ for (j = 0 ; j < n_bins; j++) {
+ if (adjustToClock) {
+ if (fCellOffset[channel+chipIndex*9][j*skip] == 0) {
+ left = waveform[(j-1+kNumberOfBins) % kNumberOfBins];
+ right = waveform[(j+1) % kNumberOfBins];
+ waveform[j] = (short) ((left+right)/2);
+ }
+ } else {
+ if (fCellOffset[channel+chipIndex*9][(j*skip + triggerCell) % kNumberOfBins] == 0) {
+ left = waveform[(j-1+kNumberOfBins) % kNumberOfBins];
+ right = waveform[(j+1) % kNumberOfBins];
+ waveform[j] = (short) ((left+right)/2);
+ }
+ }
+ }
+
+ } else {
+ if (!fResponseCalibration->
+ Calibrate(chipIndex, channel % 10, adcWaveform, waveform, triggerCell, threshold, offsetCalib))
+ return kZeroSuppression; // return immediately if below threshold
+ }
+ } else {
+ if (GetDRSType() == 4) {
+ // if Mezz though USB2 -> select correct calibration channel
+ if (fBoardType == 6 && (fReadoutChannelConfig == 0 || fReadoutChannelConfig == 2) &&
+ channel != 8)
+ channel++;
+ for (j = 0 ; j < kNumberOfBins; j++) {
+ value = adcWaveform[j];
+
+ /* convert to units of 0.1 mV */
+ value = (value - 32768) / 65536.0 * 1000 * 10;
+
+ /* correct for range */
+ value += fRange * 1000 * 10;
+
+ if (adjustToClock)
+ waveform[(j + triggerCell) % kNumberOfBins] = (short) (value + 0.5);
+ else
+ waveform[j] = (short) (value + 0.5);
+ }
+ } else {
+ for (j = 0; j < kNumberOfBins; j++) {
+ if (adjustToClock) {
+ // rotate waveform such that waveform[0] corresponds to bin #0 on the chip
+ waveform[j] = adcWaveform[(kNumberOfBins-triggerCell+j) % kNumberOfBins];
+ } else {
+ waveform[j] = adcWaveform[j];
+ }
+ }
+ }
+ }
+
+ // fix bad cells for single turn mode
+ if (GetDRSType() == 2) {
+ if (fDominoMode == 0 && triggerCell == -1) {
+ waveform[0] = 2 * waveform[1] - waveform[2];
+ short m1 = (waveform[kNumberOfBins - 5] + waveform[kNumberOfBins - 6]) / 2;
+ short m2 = (waveform[kNumberOfBins - 6] + waveform[kNumberOfBins - 7]) / 2;
+ waveform[kNumberOfBins - 4] = m1 - 1 * (m2 - m1);
+ waveform[kNumberOfBins - 3] = m1 - 2 * (m2 - m1);
+ waveform[kNumberOfBins - 2] = m1 - 3 * (m2 - m1);
+ waveform[kNumberOfBins - 1] = m1 - 4 * (m2 - m1);
+ }
+ }
+
+ return kSuccess;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::GetStretchedTime(float *time, float *measurement, int numberOfMeasurements, float period)
+{
+ int j;
+ if (*time >= measurement[numberOfMeasurements - 1]) {
+ *time -= measurement[numberOfMeasurements - 1];
+ return 1;
+ }
+ if (*time < measurement[0]) {
+ *time = *time - measurement[0] - (numberOfMeasurements - 1) * period / 2;
+ return 1;
+ }
+ for (j = 0; j < numberOfMeasurements - 1; j++) {
+ if (*time > measurement[j] && *time <= measurement[j + 1]) {
+ *time =
+ (period / 2) / (measurement[j + 1] - measurement[j]) * (*time - measurement[j + 1]) -
+ (numberOfMeasurements - 2 - j) * period / 2;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::GetTriggerCell(unsigned int chipIndex)
+{
+ if (fDRSType == 4)
+ return GetStopCell(chipIndex);
+
+ return GetTriggerCell(fWaveforms, chipIndex);
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::GetTriggerCell(unsigned char *waveforms, unsigned int chipIndex)
+{
+ int j, triggerCell;
+ bool calib;
+ unsigned short baseLevel = 1000;
+ unsigned short triggerChannel[1024];
+
+ if (fDRSType == 4)
+ return GetStopCell(chipIndex);
+
+ GetRawWave(waveforms, chipIndex, 8, triggerChannel);
+ calib = fResponseCalibration->SubtractADCOffset(chipIndex, 8, triggerChannel, triggerChannel, baseLevel);
+
+ triggerCell = -1;
+ for (j = 0; j < kNumberOfBins; j++) {
+ if (calib) {
+ if (triggerChannel[j] <= baseLevel + 200
+ && triggerChannel[(j + 1) % kNumberOfBins] > baseLevel + 200) {
+ triggerCell = j;
+ break;
+ }
+ } else {
+ if (fDRSType == 3) {
+ if (triggerChannel[j] <= 2000 && triggerChannel[(j + 1) % kNumberOfBins] > 2000) {
+ triggerCell = j;
+ break;
+ }
+ } else {
+ if (triggerChannel[j] >= 2000 && triggerChannel[(j + 1) % kNumberOfBins] < 2000) {
+ triggerCell = j;
+ break;
+ }
+ }
+ }
+ }
+ if (triggerCell == -1) {
+ return kInvalidTriggerSignal;
+ }
+ fStopCell[0] = triggerCell;
+ return triggerCell;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::GetStopCell(unsigned int chipIndex)
+{
+ return fStopCell[chipIndex];
+}
+
+/*------------------------------------------------------------------*/
+
+unsigned char DRSBoard::GetStopWSR(unsigned int chipIndex)
+{
+ return fStopWSR[chipIndex];
+}
+
+/*------------------------------------------------------------------*/
+
+void DRSBoard::TestDAC(int channel)
+{
+ // Test DAC
+ int status;
+
+ do {
+ status = SetDAC(channel, 0);
+ Sleep(1000);
+ status = SetDAC(channel, 0.5);
+ Sleep(1000);
+ status = SetDAC(channel, 1);
+ Sleep(1000);
+ status = SetDAC(channel, 1.5);
+ Sleep(1000);
+ status = SetDAC(channel, 2);
+ Sleep(1000);
+ status = SetDAC(channel, 2.5);
+ Sleep(1000);
+ } while (status);
+}
+
+/*------------------------------------------------------------------*/
+
+void DRSBoard::MeasureSpeed()
+{
+ // Measure domino sampling speed
+ FILE *f;
+ double vdr, vds, freq;
+
+ f = fopen("speed.txt", "wt");
+ fprintf(f, "\t");
+ printf("\t");
+ for (vdr = 0.5; vdr <= 2.501; vdr += 0.05) {
+ fprintf(f, "%1.2lf\t", vdr);
+ printf("%1.2lf\t", vdr);
+ }
+ fprintf(f, "\n");
+ printf("\n");
+
+ for (vds = 0.5; vds <= 2.501; vds += 0.05) {
+ fprintf(f, "%1.2lf\t", vds);
+ printf("%1.2lf\t", vds);
+
+ SetDAC(fDAC_DSA, vds);
+ StartDomino();
+ Sleep(1000);
+ ReadFrequency(0, &freq);
+
+ fprintf(f, "%1.3lf\t", freq);
+ printf("%1.3lf\t", freq);
+
+ fprintf(f, "\n");
+ printf("\n");
+ fflush(f);
+ }
+}
+
+/*------------------------------------------------------------------*/
+
+void DRSBoard::InteractSpeed()
+{
+ int status, i;
+ double freq, vds;
+
+ do {
+ printf("DS: ");
+ scanf("%lf", &vds);
+ if (vds == 0)
+ break;
+
+ SetDAC(fDAC_DSA, vds);
+ SetDAC(fDAC_DSB, vds);
+
+ StartDomino();
+ for (i = 0; i < 4; i++) {
+ Sleep(1000);
+
+ status = ReadFrequency(0, &freq);
+ if (!status)
+ break;
+ printf("%1.6lf GHz\n", freq);
+ }
+
+ /* turn BOARD_LED off */
+ SetLED(0);
+
+ } while (1);
+}
+
+/*------------------------------------------------------------------*/
+
+void DRSBoard::MonitorFrequency()
+{
+ // Monitor domino sampling frequency
+ int status;
+ unsigned int data;
+ double freq, dac;
+ FILE *f;
+ time_t now;
+ char str[256];
+
+ f = fopen("DRSBoard.log", "w");
+
+ do {
+ Sleep(1000);
+
+ status = ReadFrequency(0, &freq);
+ if (!status)
+ break;
+
+ data = 0;
+ if (fBoardType == 1)
+ Read(T_STATUS, &data, REG_RDAC3, 2);
+ else if (fBoardType == 2 || fBoardType == 3)
+ Read(T_STATUS, &data, REG_RDAC1, 2);
+
+ dac = data / 65536.0 * 2.5;
+ printf("%1.6lf GHz, %1.4lf V\n", freq, dac);
+ time(&now);
+ strcpy(str, ctime(&now) + 11);
+ str[8] = 0;
+
+ fprintf(f, "%s %1.6lf GHz, %1.4lf V\n", str, freq, dac);
+ fflush(f);
+
+ } while (!drs_kbhit());
+
+ fclose(f);
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::TestShift(int n)
+{
+ // Test shift register
+ unsigned char buffer[3];
+
+ memset(buffer, 0, sizeof(buffer));
+
+#if 0
+ buffer[0] = CMD_TESTSHIFT;
+ buffer[1] = n;
+
+ status = msend_usb(buffer, 2);
+ if (status != 2)
+ return status;
+
+ status = mrecv_usb(buffer, sizeof(buffer));
+ if (status != 1)
+ return status;
+#endif
+
+ if (buffer[0] == 1)
+ printf("Shift register %c works correctly\n", 'A' + n);
+ else if (buffer[0] == 2)
+ printf("SROUT%c does hot go high after reset\n", 'A' + n);
+ else if (buffer[0] == 3)
+ printf("SROUT%c does hot go low after 1024 clocks\n", 'A' + n);
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+unsigned int DRSBoard::GetCtrlReg()
+{
+ unsigned int status;
+
+ Read(T_CTRL, &status, REG_CTRL, 4);
+ return status;
+}
+
+/*------------------------------------------------------------------*/
+
+unsigned short DRSBoard::GetConfigReg()
+{
+ unsigned short status;
+
+ Read(T_CTRL, &status, REG_CONFIG, 2);
+ return status;
+}
+
+/*------------------------------------------------------------------*/
+
+unsigned int DRSBoard::GetStatusReg()
+{
+ unsigned int status;
+
+ Read(T_STATUS, &status, REG_STATUS, 4);
+ return status;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::EnableTcal(int freq, int level, int phase)
+{
+ fTcalFreq = freq;
+ fTcalLevel = level;
+ fTcalPhase = phase;
+
+ if (fBoardType == 6) {
+ ConfigureLMK(fNominalFrequency, false, freq, phase);
+ } else {
+ if (fBoardType == 9) {
+ // Enable clock a switch channel multiplexers
+ if (freq) {
+ fCtrlBits |= (BIT_TCAL_EN | BIT_ACAL_EN);
+ } else
+ fCtrlBits &= ~(BIT_TCAL_EN | BIT_ACAL_EN);
+
+ } else {
+ // Enable clock channel
+ if (freq)
+ fCtrlBits |= BIT_TCAL_EN;
+ else
+ fCtrlBits &= ~(BIT_TCAL_EN | BIT_TCAL_SOURCE);
+
+ // Set output level, needed for gain calibration
+ if (fDRSType == 4) {
+ if (level)
+ fCtrlBits |= BIT_NEG_TRIGGER;
+ else
+ fCtrlBits &= ~BIT_NEG_TRIGGER;
+ }
+ }
+
+ Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::SelectClockSource(int source)
+{
+ fTcalSource = source;
+
+ // Select clock source:
+ // EVAL1: synchronous (0) or asynchronous (1) (2nd quartz)
+ if (fBoardType <= 8) {
+ if (source)
+ fCtrlBits |= BIT_TCAL_SOURCE;
+ else
+ fCtrlBits &= ~BIT_TCAL_SOURCE;
+
+ Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::SetRefclk(int source)
+{
+ // Select reference clock source to internal FPGA (0) or external P2 (1)
+ if (fBoardType == 6) {
+ if (source)
+ fCtrlBits |= BIT_REFCLK_SOURCE;
+ else
+ fCtrlBits &= ~BIT_REFCLK_SOURCE;
+ } else if (fBoardType == 8 || fBoardType == 9) {
+ if (source)
+ fCtrlBits |= BIT_REFCLK_EXT;
+ else
+ fCtrlBits &= ~BIT_REFCLK_EXT;
+ }
+
+ Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
+ fRefclk = source;
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::EnableAcal(int mode, double voltage)
+{
+ double t1, t2;
+
+ fAcalMode = mode;
+ fAcalVolt = voltage;
+
+ if (mode == 0) {
+ /* turn calibration off */
+ SetCalibTiming(0, 0);
+ if (fBoardType == 5 || fBoardType == 6) {
+ /* turn voltages off (50 Ohm analog switch!) */
+ SetDAC(fDAC_CALP, 0);
+ SetDAC(fDAC_CALN, 0);
+ }
+ if (fBoardType == 7 || fBoardType == 8 || fBoardType == 9)
+ SetCalibVoltage(0);
+
+ fCtrlBits &= ~BIT_ACAL_EN;
+ Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
+ } else if (mode == 1) {
+ /* static calibration */
+ SetCalibVoltage(voltage);
+ SetCalibTiming(0, 0);
+ fCtrlBits |= BIT_ACAL_EN;
+ Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
+ } else if (mode == 2) {
+ /* first part calibration:
+ stop domino wave after 1.2 revolutions
+ turn on calibration voltage after 0.1 revolutions */
+
+ /* ensure circulating domino wave */
+ SetDominoMode(1);
+
+ /* set calibration voltage but do not turn it on now */
+ SetCalibVoltage(voltage);
+ fCtrlBits &= ~BIT_ACAL_EN;
+ Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
+
+ /* calculate duration of DENABLE signal as 1.2 revolutions */
+ t1 = 1 / fNominalFrequency * 1024 * 1.2; // ns
+ t1 = static_cast < int >((t1 - 30) / 30 + 1); // 30 ns offset, 30 ns units, rounded up
+ t2 = 1 / fNominalFrequency * 1024 * 0.1; // ns
+ t2 = static_cast < int >((t2 - 30) / 30 + 1); // 30 ns offset, 30 ns units, rounded up
+ SetCalibTiming(static_cast < int >(t1), static_cast < int >(t2));
+
+ } else if (mode == 3) {
+ /* second part calibration:
+ stop domino wave after 1.05 revolutions */
+
+ /* ensure circulating domino wave */
+ SetDominoMode(1);
+
+ /* turn on and let settle calibration voltage */
+ SetCalibVoltage(voltage);
+ fCtrlBits |= BIT_ACAL_EN;
+ Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
+
+ /* calculate duration of DENABLE signal as 1.1 revolutions */
+ t1 = 1 / fNominalFrequency * 1024 * 1.05; // ns
+ t1 = static_cast < int >((t1 - 30) / 30 + 1); // 30 ns offset, 30 ns units, rounded up
+ SetCalibTiming(static_cast < int >(t1), 0);
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::SetCalibTiming(int t_enable, int t_cal)
+{
+ unsigned short d;
+
+ if (fDRSType == 2) {
+ d = t_cal | (t_enable << 8);
+ Write(T_CTRL, REG_CALIB_TIMING, &d, 2);
+ }
+
+ if (fDRSType == 3) {
+ d = t_cal;
+ Write(T_CTRL, REG_CALIB_TIMING, &d, 2);
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::SetCalibVoltage(double value)
+{
+ // Set Calibration Voltage
+ if (fBoardType == 5 || fBoardType == 6 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
+ if (fBoardType == 5)
+ value = value * (1+fNominalFrequency/65); // rough correction factor for input current
+ if (fBoardType == 7 || fBoardType == 8 || fBoardType == 9)
+ value = value * (1+fNominalFrequency/47); // rough correction factor for input current
+ SetDAC(fDAC_CALP, fCommonMode + value / 2);
+ SetDAC(fDAC_CALN, fCommonMode - value / 2);
+ } else
+ SetDAC(fDAC_ACALIB, value);
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::StartClearCycle()
+{
+ /* clear cycle is necessary for DRS4 to reduce noise */
+
+ fbkAcalVolt = fAcalVolt;
+ fbkAcalMode = fAcalMode;
+ fbkTcalFreq = fTcalFreq;
+ fbkTcalLevel = fTcalLevel;
+
+ /* switch all inputs to zero */
+ EnableAcal(1, 0);
+
+ /* start, stop and readout of zero */
+ StartDomino();
+ SoftTrigger();
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::FinishClearCycle()
+{
+ while (IsBusy());
+
+ /* restore old values */
+ EnableAcal(fbkAcalMode, fbkAcalVolt);
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+double DRSBoard::GetTemperature()
+{
+ // Read Out Temperature Sensor
+ unsigned char buffer[2];
+ unsigned short d;
+ double temperature;
+
+ Read(T_STATUS, buffer, REG_TEMPERATURE, 2);
+
+ d = (static_cast < unsigned int >(buffer[1]) << 8) +buffer[0];
+ temperature = ((d >> 3) & 0x0FFF) * 0.0625;
+
+ return temperature;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::Is2048ModeCapable()
+{
+ unsigned int status;
+
+ if (fFirmwareVersion < 21305)
+ return 0;
+
+ // Read pin J44 and return 1 if 2048 mode has been soldered
+ Read(T_STATUS, &status, REG_STATUS, 4);
+ if ((status & BIT_2048_MODE))
+ return 0;
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::GetTriggerBus()
+{
+ unsigned size, d;
+
+ if (fBoardType == 6 && fTransport == TR_VME) {
+ if (fReadoutChannelConfig == 4)
+ size = (20 * sizeof(short int) * (fDecimation ? kNumberOfBins/2 : kNumberOfBins) + 16);
+ else
+ size = (36 * sizeof(short int) * (fDecimation ? kNumberOfBins/2 : kNumberOfBins) + 16);
+
+ Read(T_RAM, &d, size * fReadPointer + size - 16 + 12, 4);
+ fTriggerBus = (unsigned short)d;
+ } else {
+ Read(T_STATUS, &fTriggerBus, REG_TRIGGER_BUS, 2);
+ }
+ return static_cast < int >(fTriggerBus);
+}
+
+
+/*------------------------------------------------------------------*/
+
+unsigned int DRSBoard::GetScaler(int channel)
+{
+ int reg = 0;
+ unsigned d;
+
+ if (fBoardType < 9 || fFirmwareVersion < 21000 || fTransport != TR_USB2)
+ return 0;
+
+ switch (channel ) {
+ case 0: reg = REG_SCALER0; break;
+ case 1: reg = REG_SCALER1; break;
+ case 2: reg = REG_SCALER2; break;
+ case 3: reg = REG_SCALER3; break;
+ case 4: reg = REG_SCALER4; break;
+ case 5: reg = REG_SCALER5; break;
+ }
+
+ Read(T_STATUS, &d, reg, 4);
+
+ return static_cast < unsigned int >(d * 10); // measurement clock is 10 Hz
+}
+
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::SetBoardSerialNumber(unsigned short serialNumber)
+{
+ unsigned char buf[32768];
+
+ unsigned short dac;
+
+ if (fDRSType < 4) {
+ // read current DAC register
+ Read(T_CTRL, &dac, REG_DAC0, 2);
+
+ // put serial in DAC register
+ Write(T_CTRL, REG_DAC0, &serialNumber, 2);
+
+ // execute flash
+ fCtrlBits |= BIT_EEPROM_WRITE_TRIG;
+ Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
+ fCtrlBits &= ~BIT_EEPROM_WRITE_TRIG;
+
+ // wait 6ms per word
+ Sleep(20);
+
+ // write back old DAC registers
+ Write(T_CTRL, REG_DAC0, &dac, 2);
+
+ // read back serial number
+ ReadSerialNumber();
+
+ } else if (fDRSType == 4) {
+ /* merge serial number into eeprom page #0 */
+ ReadEEPROM(0, buf, sizeof(buf));
+ buf[0] = serialNumber & 0xFF;
+ buf[1] = serialNumber >> 8;
+ WriteEEPROM(0, buf, sizeof(buf));
+
+ /* erase DPRAM */
+ memset(buf, 0, sizeof(buf));
+ Write(T_RAM, 0, buf, sizeof(buf));
+
+ /* read back EEPROM */
+ ReadEEPROM(0, buf, sizeof(buf));
+
+ /* check if correctly set */
+ if (((buf[1] << 8) | buf[0]) != serialNumber)
+ return 0;
+
+ fBoardSerialNumber = serialNumber;
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::ReadEEPROM(unsigned short page, void *buffer, int size)
+{
+ int i;
+ unsigned long status;
+ // write eeprom page number
+ if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9)
+ Write(T_CTRL, REG_EEPROM_PAGE_EVAL, &page, 2);
+ else if (fBoardType == 6)
+ Write(T_CTRL, REG_EEPROM_PAGE_MEZZ, &page, 2);
+ else
+ return -1;
+
+ // execute eeprom read
+ fCtrlBits |= BIT_EEPROM_READ_TRIG;
+ Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
+ fCtrlBits &= ~BIT_EEPROM_READ_TRIG;
+
+ // poll on serial_busy flag
+ for (i=0 ; i<100 ; i++) {
+ Read(T_STATUS, &status, REG_STATUS, 4);
+ if ((status & BIT_SERIAL_BUSY) == 0)
+ break;
+ Sleep(10);
+ }
+
+ return Read(T_RAM, buffer, 0, size);
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::WriteEEPROM(unsigned short page, void *buffer, int size)
+{
+ int i;
+ unsigned long status;
+ unsigned char buf[32768];
+
+ // read previous page
+ ReadEEPROM(page, buf, sizeof(buf));
+
+ // combine with new page
+ memcpy(buf, buffer, size);
+
+ // write eeprom page number
+ if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9)
+ Write(T_CTRL, REG_EEPROM_PAGE_EVAL, &page, 2);
+ else if (fBoardType == 6)
+ Write(T_CTRL, REG_EEPROM_PAGE_MEZZ, &page, 2);
+ else
+ return -1;
+
+ // write eeprom page to RAM
+ Write(T_RAM, 0, buf, size);
+
+ // execute eeprom write
+ fCtrlBits |= BIT_EEPROM_WRITE_TRIG;
+ Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
+ fCtrlBits &= ~BIT_EEPROM_WRITE_TRIG;
+
+ // poll on serail_busy flag
+ for (i=0 ; i<500 ; i++) {
+ Read(T_STATUS, &status, REG_STATUS, 4);
+ if ((status & BIT_SERIAL_BUSY) == 0)
+ break;
+ Sleep(10);
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+bool DRSBoard::IsTimingCalibrationValid()
+{
+ return fabs(fNominalFrequency - fTimingCalibratedFrequency) < 0.001;
+}
+
+double DRSBoard::GetTrueFrequency()
+{
+ int i;
+ double f;
+
+ if (IsTimingCalibrationValid()) {
+ /* calculate true frequency */
+ for (i=0,f=0 ; i<1024 ; i++)
+ f += fCellDT[0][0][i];
+ f = 1024.0 / f;
+ } else
+ f = fNominalFrequency;
+
+ return f;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::GetTime(unsigned int chipIndex, int channelIndex, int tc, float *time, bool tcalibrated, bool rotated)
+{
+ int i, scale, iend;
+ double gt0, gt;
+
+ /* for DRS2, please use function below */
+ if (fDRSType < 4)
+ return GetTime(chipIndex, channelIndex, fNominalFrequency, tc, time, tcalibrated, rotated);
+
+ scale = fDecimation ? 2 : 1;
+
+ if (!IsTimingCalibrationValid() || !tcalibrated) {
+ double t0 = tc / fNominalFrequency;
+ for (i = 0; i < fChannelDepth; i++) {
+ if (rotated)
+ time[i] = static_cast < float >(((i*scale+tc) % kNumberOfBins) / fNominalFrequency - t0);
+ else
+ time[i] = static_cast < float >((i*scale) / fNominalFrequency);
+ if (time[i] < 0)
+ time[i] += static_cast < float > (kNumberOfBins / fNominalFrequency);
+ if (i*scale >= kNumberOfBins)
+ time[i] += static_cast < float > (kNumberOfBins / fNominalFrequency);
+ }
+ return 1;
+ }
+
+ time[0] = 0;
+ for (i=1 ; i<fChannelDepth ; i++) {
+ if (rotated)
+ time[i] = time[i-1] + (float)fCellDT[chipIndex][channelIndex][(i-1+tc) % kNumberOfBins];
+ else
+ time[i] = time[i-1] + (float)fCellDT[chipIndex][channelIndex][(i-1) % kNumberOfADCBins];
+ }
+
+ if (channelIndex > 0) {
+ // correct all channels to channel 0 (Daniel's method)
+ iend = tc >= 700 ? 700+1024 : 700;
+ for (i=tc,gt0=0 ; i<iend ; i++)
+ gt0 += fCellDT[chipIndex][0][i % 1024];
+
+ for (i=tc,gt=0 ; i<iend ; i++)
+ gt += fCellDT[chipIndex][channelIndex][i % 1024];
+
+ for (i=0 ; i<fChannelDepth ; i++)
+ time[i] += (float)(gt0 - gt);
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::GetTimeCalibration(unsigned int chipIndex, int channelIndex, int mode, float *time, bool force)
+{
+ int i;
+ float tint;
+
+ /* not implemented for DRS2 */
+ if (fDRSType < 4)
+ return -1;
+
+ if (!force && !IsTimingCalibrationValid()) {
+ for (i = 0; i < kNumberOfBins; i++)
+ time[i] = (float) (1/fNominalFrequency);
+ return 1;
+ }
+
+ if (mode == 0) {
+ /* differential nonlinearity */
+ for (i=0 ; i<kNumberOfBins ; i++)
+ time[i] = static_cast < float > (fCellDT[chipIndex][channelIndex][i]);
+ } else {
+ /* integral nonlinearity */
+ for (i=0,tint=0; i<kNumberOfBins ; i++) {
+ time[i] = static_cast < float > (tint - i/fNominalFrequency);
+ tint += (float)fCellDT[chipIndex][channelIndex][i];
+ }
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::GetTime(unsigned int chipIndex, int channelIndex, double freqGHz, int tc, float *time, bool tcalibrated, bool rotated)
+{
+ /* for DRS4, use function above */
+ if (fDRSType == 4)
+ return GetTime(chipIndex, channelIndex, tc, time, tcalibrated, rotated);
+
+ int i, irot;
+ DRSBoard::TimeData * init;
+ DRSBoard::TimeData::FrequencyData * freq;
+ int frequencyMHz = (int)(freqGHz*1000);
+
+ init = GetTimeCalibration(chipIndex);
+
+ if (init == NULL) {
+ for (i = 0; i < kNumberOfBins; i++)
+ time[i] = static_cast < float >(i / fNominalFrequency);
+ return 1;
+ }
+ freq = NULL;
+ for (i = 0; i < init->fNumberOfFrequencies; i++) {
+ if (init->fFrequency[i]->fFrequency == frequencyMHz) {
+ freq = init->fFrequency[i];
+ break;
+ }
+ }
+ if (freq == NULL) {
+ for (i = 0; i < kNumberOfBins; i++)
+ time[i] = static_cast < float >(i / fNominalFrequency);
+ return 1;
+ }
+ for (i = 0; i < kNumberOfBins; i++) {
+ irot = (fStopCell[chipIndex] + i) % kNumberOfBins;
+ if (fStopCell[chipIndex] + i < kNumberOfBins)
+ time[i] = static_cast < float >((freq->fBin[irot] - freq->fBin[fStopCell[chipIndex]]) / fNominalFrequency);
+ else
+ time[i] =
+ static_cast <
+ float
+ >((freq->fBin[irot] - freq->fBin[fStopCell[chipIndex]] + freq->fBin[kNumberOfBins - 1] - 2 * freq->fBin[0] +
+ freq->fBin[1]) / fNominalFrequency);
+ }
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+bool DRSBoard::InitTimeCalibration(unsigned int chipIndex)
+{
+ return GetTimeCalibration(chipIndex, true) != NULL;
+}
+
+/*------------------------------------------------------------------*/
+
+DRSBoard::TimeData * DRSBoard::GetTimeCalibration(unsigned int chipIndex, bool reinit)
+{
+ int i, l, index;
+ char *cstop;
+ char fileName[500];
+ char error[240];
+ PMXML_NODE node, rootNode, mainNode;
+
+ index = fNumberOfTimeData;
+ for (i = 0; i < fNumberOfTimeData; i++) {
+ if (fTimeData[i]->fChip == static_cast < int >(chipIndex)) {
+ if (!reinit)
+ return fTimeData[i];
+ else {
+ index = i;
+ break;
+ }
+ }
+ }
+
+ fTimeData[index] = new DRSBoard::TimeData();
+ DRSBoard::TimeData * init = fTimeData[index];
+
+ init->fChip = chipIndex;
+
+ for (i = 0; i < init->kMaxNumberOfFrequencies; i++) {
+ if (i <= 499 || (i >= 501 && i <= 999) || (i >= 1001 && i <= 1499) || (i >= 1501 && i <= 1999) ||
+ (i >= 2001 && i <= 2499) || i >= 2501)
+ continue;
+ sprintf(fileName, "%s/board%d/TimeCalib_board%d_chip%d_%dMHz.xml", fCalibDirectory, fBoardSerialNumber,
+ fBoardSerialNumber, chipIndex, i);
+ rootNode = mxml_parse_file(fileName, error, sizeof(error), NULL);
+ if (rootNode == NULL)
+ continue;
+
+ init->fFrequency[init->fNumberOfFrequencies] = new DRSBoard::TimeData::FrequencyData();
+ init->fFrequency[init->fNumberOfFrequencies]->fFrequency = i;
+
+ mainNode = mxml_find_node(rootNode, "/DRSTimeCalibration");
+
+ for (l = 0; l < kNumberOfBins; l++) {
+ node = mxml_subnode(mainNode, l + 2);
+ init->fFrequency[init->fNumberOfFrequencies]->fBin[l] = strtod(mxml_get_value(node), &cstop);
+ }
+ mxml_free_tree(rootNode);
+ init->fNumberOfFrequencies++;
+ }
+ if (init->fNumberOfFrequencies == 0) {
+ printf("Board %d --> Could not find time calibration file\n", GetBoardSerialNumber());
+ }
+
+ if (index == fNumberOfTimeData)
+ fNumberOfTimeData++;
+
+ return fTimeData[index];
+}
+
+/*------------------------------------------------------------------*/
+
+void DRSBoard::SetCalibrationDirectory(const char *calibrationDirectoryPath)
+{
+ strncpy(fCalibDirectory, calibrationDirectoryPath, strlen(calibrationDirectoryPath));
+ fCalibDirectory[strlen(calibrationDirectoryPath)] = 0;
+};
+
+/*------------------------------------------------------------------*/
+
+void DRSBoard::GetCalibrationDirectory(char *calibrationDirectoryPath)
+{
+ strncpy(calibrationDirectoryPath, fCalibDirectory, strlen(fCalibDirectory));
+ calibrationDirectoryPath[strlen(fCalibDirectory)] = 0;
+};
+
+/*------------------------------------------------------------------*/
+
+void DRSBoard::LinearRegression(double *x, double *y, int n, double *a, double *b)
+{
+ int i;
+ double sx, sxx, sy, sxy;
+
+ sx = sxx = sy = sxy = 0;
+ for (i = 0; i < n; i++) {
+ sx += x[i];
+ sxx += x[i] * x[i];
+ sy += y[i];
+ sxy += x[i] * y[i];
+ }
+
+ *a = (n * sxy - sx * sy) / (n * sxx - sx * sx);
+ *b = (sy - *a * sx) / n;
+}
+
+/*------------------------------------------------------------------*/
+
+void DRSBoard::ReadSingleWaveform(int nChip, int nChan,
+ unsigned short wf[kNumberOfChipsMax][kNumberOfChannelsMax][kNumberOfBins],
+ bool rotated)
+{
+ int i, j, k, tc;
+
+ StartDomino();
+ SoftTrigger();
+ while (IsBusy());
+ TransferWaves();
+
+ for (i=0 ; i<nChip ; i++) {
+ tc = GetTriggerCell(i);
+
+ for (j=0 ; j<nChan ; j++) {
+ GetRawWave(i, j, wf[i][j], rotated);
+ if (!rotated) {
+ for (k=0 ; k<kNumberOfBins ; k++) {
+ /* do primary offset calibration */
+ wf[i][j][k] = wf[i][j][k] - fCellOffset[j+i*9][(k + tc) % kNumberOfBins] + 32768;
+ }
+ }
+ }
+ }
+}
+
+static unsigned short swf[kNumberOfChipsMax][kNumberOfChannelsMax][kNumberOfBins];
+static float center[kNumberOfChipsMax][kNumberOfChannelsMax][kNumberOfBins];
+
+int DRSBoard::AverageWaveforms(DRSCallback *pcb, int nChip, int nChan,
+ int prog1, int prog2, unsigned short *awf, int n, bool rotated)
+{
+ int i, j, k, l, prog, old_prog = 0;
+ float cm;
+
+ if (pcb != NULL)
+ pcb->Progress(prog1);
+
+ memset(center, 0, sizeof(center));
+
+ for (i=0 ; i<n; i++) {
+ ReadSingleWaveform(nChip, nChan, swf, rotated);
+
+ for (j=0 ; j<nChip ; j++) {
+ for (k=0 ; k<nChan ; k++) {
+ if (i > 5) {
+ /* calculate and subtract common mode */
+ for (l=0,cm=0 ; l<kNumberOfBins ; l++)
+ cm += swf[j][k][l] - 32768;
+ cm /= kNumberOfBins;
+ for (l=0 ; l<kNumberOfBins ; l++)
+ center[j][k][l] += swf[j][k][l]- cm;
+ }
+ }
+ }
+
+ prog = (int)(((double)i/n)*(prog2-prog1)+prog1);
+ if (prog > old_prog) {
+ old_prog = prog;
+ if (pcb != NULL)
+ pcb->Progress(prog);
+ }
+ }
+
+ for (i=0 ; i<nChip ; i++)
+ for (j=0 ; j<nChan ; j++)
+ for (k=0 ; k<kNumberOfBins ; k++)
+ awf[(i*nChan+j)*kNumberOfBins+k] = (unsigned short)(center[i][j][k]/(n-6) + 0.5);
+
+ return 1;
+}
+
+int DRSBoard::RobustAverageWaveforms(DRSCallback *pcb, int nChip, int nChan,
+ int prog1, int prog2, unsigned short *awf, int n, bool rotated)
+{
+ int i, j, k, l, prog, old_prog = 0;
+
+ if (pcb != NULL)
+ pcb->Progress(prog1);
+
+ Averager *ave = new Averager(nChip, nChan, kNumberOfBins, 200);
+
+ /* fill histograms */
+ for (i=0 ; i<n ; i++) {
+ ReadSingleWaveform(nChip, nChan, swf, rotated);
+ for (j=0 ; j<nChip ; j++)
+ for (k=0 ; k<nChan ; k++)
+ for (l=0 ; l<kNumberOfBins ; l++)
+ ave->Add(j, k, l, swf[j][k][l]);
+
+ /* update progress bar */
+ prog = (int)(((double)(i+10)/(n+10))*(prog2-prog1)+prog1);
+ if (prog > old_prog) {
+ old_prog = prog;
+ if (pcb != NULL)
+ pcb->Progress(prog);
+ }
+ }
+
+ /*
+ FILE *fh = fopen("calib.csv", "wt");
+ for (i=40 ; i<60 ; i++) {
+ for (j=0 ; j<WFH_SIZE ; j++)
+ fprintf(fh, "%d;", wfh[0][0][i][j]);
+ fprintf(fh, "\n");
+ }
+ fclose(fh);
+ */
+
+ for (i=0 ; i<nChip ; i++)
+ for (j=0 ; j<nChan ; j++)
+ for (k=0 ; k<kNumberOfBins ; k++)
+ awf[(i*nChan+j)*kNumberOfBins+k] = (unsigned short)ave->RobustAverage(100, i, j, k);
+
+ ave->SaveNormalizedDistribution("wv.csv", 0, 100);
+
+ /*
+ FILE *fh = fopen("calib.csv", "wt");
+ for (i=40 ; i<60 ; i++) {
+ fprintf(fh, "%d;", icenter[0][0][0] + (i - WFH_SIZE/2)*16);
+ fprintf(fh, "%d;", wfh[0][0][0][i]);
+ if (i == 50)
+ fprintf(fh, "%d;", awf[0]);
+ fprintf(fh, "\n");
+ }
+ fclose(fh);
+ */
+
+ if (pcb != NULL)
+ pcb->Progress(prog2);
+
+ delete ave;
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int idx[4][10] = {
+ { 0, 2, 4, 6, 8, 18, 20, 22, 24, 26 },
+ { 1, 3, 5, 7, 39, 19, 21, 23, 25, 39 },
+ { 9, 11, 13, 15, 17, 27, 29, 31, 33, 35 },
+ { 10, 12, 14, 16, 39, 28, 30, 32, 34, 39 },
+};
+
+#define F1(x) ((int) (84.0/24 * (x)))
+#define F2(x) ((int) (92.0/8 * (x)))
+
+static unsigned short wft[kNumberOfChipsMax*kNumberOfChannelsMax*kNumberOfChipsMax][1024],
+ wf1[kNumberOfChipsMax*kNumberOfChannelsMax*kNumberOfChipsMax][1024],
+ wf2[kNumberOfChipsMax*kNumberOfChannelsMax*kNumberOfChipsMax][1024],
+ wf3[kNumberOfChipsMax*kNumberOfChannelsMax*kNumberOfChipsMax][1024];
+
+int DRSBoard::CalibrateVolt(DRSCallback *pcb)
+{
+int i, j, nChan, timingChan, chip, config, p, clkon, refclk, trg1, trg2, n_stuck, readchn, casc;
+double f, r;
+unsigned short buf[1024*16]; // 32 kB
+
+ f = fNominalFrequency;
+ r = fRange;
+ clkon = (GetCtrlReg() & BIT_TCAL_EN) > 0;
+ refclk = (GetCtrlReg() & BIT_REFCLK_SOURCE) > 0;
+ trg1 = fTriggerEnable1;
+ trg2 = fTriggerEnable2;
+ readchn = fNumberOfReadoutChannels;
+ casc = fChannelCascading;
+
+ Init();
+ fNominalFrequency = f;
+ SetRefclk(refclk);
+ SetFrequency(fNominalFrequency, true);
+ SetDominoMode(1);
+ SetDominoActive(1);
+ SetReadoutMode(1);
+ SetInputRange(r);
+ if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9)
+ SelectClockSource(0);
+ else if (fBoardType == 6)
+ SetRefclk(refclk);
+ EnableTrigger(0, 0);
+ if (readchn == 5)
+ SetChannelConfig(4, 8, 8); // even channel readout mode
+
+ // WSROUT toggling causes some noise, so calibrate that out
+ if (casc == 2) {
+ if (fTransport == TR_USB2)
+ SetChannelConfig(0, 8, 4);
+ else
+ SetChannelConfig(7, 8, 4);
+ }
+
+ StartDomino();
+
+ nChan = 0;
+ timingChan = 0;
+
+ if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
+ if (fBoardType == 9) {
+ nChan = 8;
+ timingChan = -1;
+ } else {
+ nChan = 9;
+ timingChan = 8;
+ }
+
+ /* measure offset */
+ if (fBoardType == 5)
+ EnableAcal(0, 0); // no inputs signal is allowed during calibration!
+ else
+ EnableAcal(1, 0); // disconnect analog inputs
+ EnableTcal(0, 0);
+ Sleep(100);
+ RobustAverageWaveforms(pcb, 1, nChan, 0, 25, wf1[0], 200, true);
+
+ /* measure gain at upper range */
+ EnableAcal(1, fRange+0.4);
+ EnableTcal(0, 1);
+ Sleep(100);
+ RobustAverageWaveforms(pcb, 1, nChan, 25, 50, wf2[0], 200, true);
+
+ } else if (fBoardType == 6) {
+ if (fTransport == TR_USB2) {
+ nChan = 36;
+ timingChan = 8;
+ memset(wf1, 0, sizeof(wf1));
+ memset(wf2, 0, sizeof(wf2));
+ memset(wf3, 0, sizeof(wf3));
+ for (config=p=0 ; config<4 ; config++) {
+ SetChannelConfig(config, 8, 8);
+
+ /* measure offset */
+ EnableAcal(1, 0);
+ EnableTcal(0, 0);
+ Sleep(100);
+ RobustAverageWaveforms(pcb, 0, 10, F1(p), F1(p+1), wft[0], 500, true); p++;
+ for (i=0 ; i<5 ; i++)
+ memcpy(wf1[idx[config][i]], wft[i*2], sizeof(float)*kNumberOfBins);
+ RobustAverageWaveforms(pcb, 2, 10, F1(p), F1(p+1), wft[0], 500, true); p++;
+ for (i=0 ; i<5 ; i++)
+ memcpy(wf1[idx[config][i+5]], wft[i*2], sizeof(float)*kNumberOfBins);
+
+ /* measure gain at +400 mV */
+ EnableAcal(1, 0.4);
+ EnableTcal(0, 0);
+ Sleep(100);
+ RobustAverageWaveforms(pcb, 0, 8, F1(p), F1(p+1), wft[0], 500, true); p++;
+ for (i=0 ; i<4 ; i++)
+ memcpy(wf2[idx[config][i]], wft[i*2], sizeof(float)*kNumberOfBins);
+ RobustAverageWaveforms(pcb, 2, 8, F1(p), F1(p+1), wft[0], 500, true); p++;
+ for (i=0 ; i<4 ; i++)
+ memcpy(wf2[idx[config][i+5]], wft[i*2], sizeof(float)*kNumberOfBins);
+
+ /* measure gain at -400 mV */
+ EnableAcal(1, -0.4);
+ EnableTcal(0, 1);
+ Sleep(100);
+ RobustAverageWaveforms(pcb, 0, 8, F1(p), F1(p+1), wft[0], 500, true); p++;
+ for (i=0 ; i<4 ; i++)
+ memcpy(wf3[idx[config][i]], wft[i], sizeof(float)*kNumberOfBins);
+ RobustAverageWaveforms(pcb, 2, 8, F1(p), F1(p+1), wft[0], 500, true); p++;
+ for (i=0 ; i<4 ; i++)
+ memcpy(wf3[idx[config][i+5]], wft[i], sizeof(float)*kNumberOfBins);
+ }
+ } else {
+ nChan = 36;
+ timingChan = 8;
+
+ /* measure offset */
+ EnableAcal(0, 0); // no inputs signal is allowed during calibration!
+ EnableTcal(0, 0);
+ Sleep(100);
+ RobustAverageWaveforms(pcb, 4, 9, 0, 25, wf1[0], 500, true);
+
+ /* measure gain at upper range */
+ EnableAcal(1, fRange+0.4);
+ EnableTcal(0, 0);
+ Sleep(100);
+ RobustAverageWaveforms(pcb, 4, 9, 25, 50, wf2[0], 500, true);
+ }
+ }
+
+ /* convert offsets and gains to 16-bit values */
+ memset(fCellOffset, 0, sizeof(fCellOffset));
+ n_stuck = 0;
+ for (i=0 ; i<nChan ; i++) {
+ for (j=0 ; j<kNumberOfBins; j++) {
+ if (i % 9 == timingChan) {
+ /* calculate offset and gain for timing channel */
+ if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
+ /* we have a +325mV and a -325mV value */
+ fCellOffset[i][j] = (unsigned short) ((wf1[i][j]+wf2[i][j])/2+0.5);
+ fCellGain[i][j] = (wf2[i][j] - wf1[i][j])/65536.0*1000 / 650.0;
+ } else {
+ /* only have offset */
+ fCellOffset[i][j] = wf1[i][j];
+ fCellGain[i][j] = 1;
+ }
+ } else {
+ /* calculate offset and gain for data channel */
+ fCellOffset[i][j] = wf1[i][j];
+ if (fCellOffset[i][j] < 100) {
+ // mark stuck pixel
+ n_stuck ++;
+ fCellOffset[i][j] = 0;
+ fCellGain[i][j] = 1;
+ } else
+ fCellGain[i][j] = (wf2[i][j] - fCellOffset[i][j])/65536.0*1000 / ((0.4+fRange)*1000);
+ }
+
+ /* check gain */
+ if (fCellGain[i][j] < 0.5 || fCellGain[i][j] > 1.1) {
+ if ((fBoardType == 7 || fBoardType == 8 || fBoardType == 9) && i % 2 == 1) {
+ /* channels are not connected, so don't print error */
+ } else {
+ printf("Gain of %6.3lf for channel %2d, cell %4d out of range 0.5 ... 1.1\n",
+ fCellGain[i][j], i, j);
+ }
+ fCellGain[i][j] = 1;
+ }
+ }
+ }
+
+ /*
+ FILE *fh = fopen("calib.txt", "wt");
+ for (i=0 ; i<nChan ; i++) {
+ fprintf(fh, "CH%02d:", i);
+ for (j=0 ; j<20 ; j++)
+ fprintf(fh, " %5d", fCellOffset[i][j]-32768);
+ fprintf(fh, "\n");
+ }
+ fclose(fh);
+ */
+
+ /* perform secondary calibration */
+ if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8 || fBoardType == 9) {
+ nChan = 9;
+ timingChan = 8;
+
+ /* measure offset */
+ if (fBoardType == 5)
+ EnableAcal(0, 0); // no inputs signal is allowed during calibration!
+ else
+ EnableAcal(1, 0); // disconnect analog inputs
+ EnableTcal(0, 0);
+ Sleep(100);
+ AverageWaveforms(pcb, 1, 9, 50, 90, wf1[0], 500, false);
+ } else if (fBoardType == 6 && fTransport == TR_VME) {
+ nChan = 36;
+ timingChan = 8;
+
+ /* measure offset */
+ EnableAcal(0, 0); // no inputs signal is allowed during calibration!
+ EnableTcal(0, 0);
+ Sleep(100);
+ AverageWaveforms(pcb, 4, 9, 50, 75, wf1[0], 500, false);
+ }
+
+ /* convert offset to 16-bit values */
+ memset(fCellOffset2, 0, sizeof(fCellOffset2));
+ for (i=0 ; i<nChan ; i++)
+ for (j=0 ; j<kNumberOfBins; j++)
+ if (i % 9 != timingChan)
+ fCellOffset2[i][j] = wf1[i][j];
+
+ /*
+ FILE *fh = fopen("calib.txt", "wt");
+ for (i=0 ; i<nChan ; i++) {
+ for (j=0 ; j<kNumberOfBins; j++)
+ fprintf(fh, "%5d: %5d %5d\n", j, fCellOffset2[0][j]-32768, fCellOffset2[1][j]-32768);
+ fprintf(fh, "\n");
+ }
+ fclose(fh);
+ */
+
+ if (fBoardType == 9) {
+ /* write calibration CH0-CH7 to EEPROM page 1 */
+ for (i=0 ; i<8 ; i++)
+ for (j=0 ; j<1024; j++) {
+ buf[(i*1024+j)*2] = fCellOffset[i][j];
+ buf[(i*1024+j)*2+1] = (unsigned short) ((fCellGain[i][j] - 0.7) / 0.4 * 65535);
+ }
+ WriteEEPROM(1, buf, 1024*32);
+ if (pcb != NULL)
+ pcb->Progress(93);
+
+
+ /* write secondary calibration to EEPROM page 2 */
+ ReadEEPROM(2, buf, 1024*32);
+ for (i=0 ; i<8 ; i++)
+ for (j=0 ; j<1024; j++)
+ buf[(i*1024+j)*2] = fCellOffset2[i][j];
+ WriteEEPROM(2, buf, 1024*32);
+ if (pcb != NULL)
+ pcb->Progress(96);
+
+ /* update page # 0 */
+ ReadEEPROM(0, buf, 4096); // 0-0x0FFF
+ /* write calibration method */
+ buf[2] = (buf[2] & 0xFF00) | VCALIB_METHOD;
+ /* write temperature and range */
+ buf[10] = ((unsigned short) (GetTemperature() * 2 + 0.5) << 8) | ((signed char)(fRange * 100));
+ buf[11] = 1; // EEPROM page #1+2
+ WriteEEPROM(0, buf, 4096);
+ fCellCalibratedRange = fRange;
+ if (pcb != NULL)
+ pcb->Progress(100);
+
+
+ } else if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8) {
+ /* write calibration CH0-CH7 to EEPROM page 1 */
+ for (i=0 ; i<8 ; i++)
+ for (j=0 ; j<1024; j++) {
+ buf[(i*1024+j)*2] = fCellOffset[i][j];
+ buf[(i*1024+j)*2+1] = (unsigned short) ((fCellGain[i][j] - 0.7) / 0.4 * 65535);
+ }
+ WriteEEPROM(1, buf, 1024*32);
+
+ /* write calibration CH8 and secondary calibration to EEPROM page 2 */
+ for (j=0 ; j<1024; j++) {
+ buf[j*2] = fCellOffset[8][j];
+ buf[j*2+1] = (unsigned short) ((fCellGain[8][j] - 0.7) / 0.4 * 65535);
+ }
+ for (i=0 ; i<4 ; i++)
+ for (j=0 ; j<1024; j++) {
+ buf[2*1024+(i*1024+j)*2] = fCellOffset2[i*2][j];
+ buf[2*1024+(i*1024+j)*2+1] = fCellOffset2[i*2+1][j];
+ }
+ WriteEEPROM(2, buf, 1024*5*4);
+
+ /* write calibration method and range */
+ ReadEEPROM(0, buf, 2048); // 0-0x0FFF
+ buf[2] = VCALIB_METHOD_V4 | ((signed char)(fRange * 100)) << 8;
+ WriteEEPROM(0, buf, 2048);
+ fCellCalibratedRange = fRange;
+
+ } else if (fBoardType == 6) {
+ for (chip=0 ; chip<4 ; chip++) {
+ /* write calibration of A0 to A7 to EEPROM page 1
+ B0 to B7 to EEPROM page 2 and so on */
+ for (i=0 ; i<8 ; i++)
+ for (j=0 ; j<1024; j++) {
+ buf[(i*1024+j)*2] = fCellOffset[i+chip*9][j];
+ buf[(i*1024+j)*2+1] = (unsigned short) ((fCellGain[i+chip*9][j] - 0.7) / 0.4 * 65535);
+ }
+ WriteEEPROM(1+chip, buf, 1024*32);
+ if (pcb != NULL)
+ pcb->Progress(75+chip*4);
+ }
+
+ /* write calibration A/B/C/D/CLK to EEPROM page 5 */
+ ReadEEPROM(5, buf, 1024*4*4);
+ for (chip=0 ; chip<4 ; chip++) {
+ for (j=0 ; j<1024; j++) {
+ buf[j*2+chip*0x0800] = fCellOffset[8+chip*9][j];
+ buf[j*2+1+chip*0x0800] = (unsigned short) ((fCellGain[8+chip*9][j] - 0.7) / 0.4 * 65535);
+ }
+ }
+ WriteEEPROM(5, buf, 1024*4*4);
+ if (pcb != NULL)
+ pcb->Progress(90);
+
+ /* write secondary calibration to EEPROM page 7 and 8 */
+ for (i=0 ; i<8 ; i++) {
+ for (j=0 ; j<1024; j++) {
+ buf[i*0x800 + j*2] = fCellOffset2[i][j];
+ buf[i*0x800 + j*2+1] = fCellOffset2[i+9][j];
+ }
+ }
+ WriteEEPROM(7, buf, 1024*32);
+ if (pcb != NULL)
+ pcb->Progress(94);
+
+ for (i=0 ; i<8 ; i++) {
+ for (j=0 ; j<1024; j++) {
+ buf[i*0x800 + j*2] = fCellOffset2[i+18][j];
+ buf[i*0x800 + j*2+1] = fCellOffset2[i+27][j];
+ }
+ }
+ WriteEEPROM(8, buf, 1024*32);
+ if (pcb != NULL)
+ pcb->Progress(98);
+
+ /* write calibration method and range */
+ ReadEEPROM(0, buf, 2048); // 0-0x0FFF
+ buf[2] = VCALIB_METHOD | ((signed char)(fRange * 100)) << 8;
+ WriteEEPROM(0, buf, 2048);
+ fCellCalibratedRange = fRange;
+ if (pcb != NULL)
+ pcb->Progress(100);
+ }
+
+ if (n_stuck)
+ printf("\nFound %d stuck pixels on this board\n", n_stuck);
+
+ fVoltageCalibrationValid = true;
+
+ /* remove calibration voltage */
+ EnableAcal(0, 0);
+ EnableTcal(clkon, 0);
+ EnableTrigger(trg1, trg2);
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::AnalyzeSlope(Averager *ave, int iIter, int nIter, int channel, float wf[kNumberOfBins], int tCell,
+ double cellDV[kNumberOfBins], double cellDT[kNumberOfBins])
+{
+ int i;
+ float dv, llim, ulim;
+ double sum, dtCell;
+
+ if (fNominalFrequency > 3) {
+ llim = -100;
+ ulim = 100;
+ } else {
+ llim = -300;
+ ulim = 300;
+ }
+
+ // rising edges ----
+
+ // skip first cells after trigger cell
+ for (i=tCell+5 ; i<tCell+kNumberOfBins-5 ; i++) {
+ // test slope between previous and next cell to allow for negative cell width
+ if (wf[(i+kNumberOfBins-1) % kNumberOfBins] < wf[(i+2) % kNumberOfBins] &&
+ wf[i % kNumberOfBins] > llim &&
+ wf[(i+1) % kNumberOfBins] < ulim) {
+
+ // calculate delta_v
+ dv = wf[(i+1) % kNumberOfBins] - wf[i % kNumberOfBins];
+
+ // average delta_v
+ ave->Add(0, channel, i % kNumberOfBins, dv);
+ }
+ }
+
+ // falling edges ----
+
+ // skip first cells after trigger cell
+ for (i=tCell+5 ; i<tCell+kNumberOfBins-5 ; i++) {
+ // test slope between previous and next cell to allow for negative cell width
+ if (wf[(i+kNumberOfBins-1) % kNumberOfBins] > wf[(i+2) % kNumberOfBins] &&
+ wf[i % kNumberOfBins] < ulim &&
+ wf[(i+1) % kNumberOfBins] > llim) {
+
+ // calcualte delta_v
+ dv = wf[(i+1) % kNumberOfBins] - wf[i % kNumberOfBins];
+
+ ave->Add(0, channel, i % kNumberOfBins, -dv);
+ }
+ }
+
+ // calculate calibration every 100 events
+ if ((iIter + 1) % 100 == 0) {
+ // average over all 1024 dU
+ sum = 0;
+ for (i=0 ; i<kNumberOfBins ; i++) {
+
+ if (fBoardType == 8)
+ cellDV[i] = ave->Median(0, channel, i);
+ else {
+ // use empirically found limits for averaging
+ if (fNominalFrequency >= 4)
+ cellDV[i] = ave->RobustAverage(3, 0, channel, i);
+ else if (fNominalFrequency >= 3)
+ cellDV[i] = ave->RobustAverage(6, 0, channel, i);
+ else
+ cellDV[i] = ave->Median(0, channel, i);
+ }
+
+ sum += cellDV[i];
+ }
+
+ sum /= kNumberOfBins;
+ dtCell = (float)1/fNominalFrequency;
+
+ // here comes the central calculation, dT = dV/average * dt_cell
+ for (i=0 ; i<kNumberOfBins ; i++)
+ cellDT[i] = cellDV[i] / sum * dtCell;
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int DRSBoard::AnalyzePeriod(Averager *ave, int iIter, int nIter, int channel, float wf[kNumberOfBins], int tCell,
+ double cellDV[kNumberOfBins], double cellDT[kNumberOfBins])
+{
+int i, i1, i2, j, nzx, zeroXing[1000], edge, n_correct, nest;
+double damping, zeroLevel, tPeriod, corr, dv, dv_limit, corr_limit;
+
+ /* calculate zero level */
+ for (i=0,zeroLevel=0 ; i<1024 ; i++)
+ zeroLevel += wf[i];
+ zeroLevel /= 1024;
+
+ /* correct for zero common mode */
+ for (i=0 ; i<1024 ; i++)
+ wf[i] -= (float)zeroLevel;
+
+ /* estimate damping factor */
+ if (fBoardType == 9)
+ damping = 0.01;
+ else
+ damping = fNominalFrequency / nIter * 2 ;
+
+ /* estimate number of zero crossings */
+ nest = (int) (1/fNominalFrequency*1024 / (1/fTCALFrequency*1000));
+
+ if (fNominalFrequency >= 4)
+ dv_limit = 4;
+ else if (fNominalFrequency >= 3)
+ dv_limit = 6;
+ else
+ dv_limit = 10000;
+
+ for (edge = 0 ; edge < 2 ; edge ++) {
+
+ /* find edge zero crossing with wrap-around */
+ for (i=tCell+5,nzx=0 ; i<tCell+1023-5 && nzx < (int)(sizeof(zeroXing)/sizeof(int)) ; i++) {
+ dv = fabs(wf[(i+1) % 1024] - wf[i % 1024]);
+
+ if (edge == 0) {
+ if (wf[(i+1) % 1024] < 0 && wf[i % 1024] > 0) { // falling edge
+ if (fBoardType != 9 || fabs(dv-cellDV[i % 1024]) < dv_limit) // only if DV is not more the dv_limit away from average
+ zeroXing[nzx++] = i % 1024;
+ }
+ } else {
+ if (wf[(i+1) % 1024] > 0 && wf[i % 1024] < 0) { // rising edge
+ if (fBoardType != 9 || fabs(dv-cellDV[i % 1024]) < dv_limit)
+ zeroXing[nzx++] = i % 1024;
+ }
+ }
+ }
+
+ /* abort if uncorrect number of edges is found */
+ if (abs(nest - nzx) > nest / 3)
+ return 0;
+
+ for (i=n_correct=0 ; i<nzx-1 ; i++) {
+ i1 = zeroXing[i];
+ i2 = zeroXing[i+1];
+ if (i1 == 1023 || i2 == 1023)
+ continue;
+
+ if (wf[(i1 + 1) % 1024] == 0 || wf[i2 % 1024] == 0)
+ continue;
+
+ /* first partial cell */
+ tPeriod = cellDT[i1]*(1/(1-wf[i1]/wf[(i1 + 1) % 1024]));
+
+ /* full cells between i1 and i2 */
+ if (i2 < i1)
+ i2 += 1024;
+
+ for (j=i1+1 ; j<i2 ; j++)
+ tPeriod += cellDT[j % 1024];
+
+ /* second partial cell */
+ tPeriod += cellDT[i2 % 1024]*(1/(1-wf[(i2+1) % 1024]/wf[i2 % 1024]));
+
+ /* calculate correction to nominal period as a fraction */
+ corr = (1/fTCALFrequency*1000) / tPeriod;
+
+ /* skip very large corrections (noise) */
+ if (fBoardType == 9 && fNominalFrequency >= 2)
+ corr_limit = 0.001;
+ else if (fBoardType == 9)
+ corr_limit = 0.004;
+ else
+ corr_limit = 0.01;
+
+ if (fBoardType == 9 && fabs(1-corr) > corr_limit)
+ continue;
+
+ /* remeber number of valid corrections */
+ n_correct++;
+
+ /* apply damping factor */
+ corr = (corr-1)*damping + 1;
+
+ /* apply from i1 to i2-1 inclusive */
+ if (i1 == i2)
+ continue;
+
+ /* distribute correciton equally into bins inside the region ... */
+ for (j=i1 ; j<=i2 ; j++)
+ cellDT[j % 1024] *= corr;
+
+ /* test correction */
+ tPeriod = cellDT[i1]*(1/(1-wf[i1]/wf[(i1 + 1) % 1024]));
+ for (j=i1+1 ; j<i2 ; j++)
+ tPeriod += cellDT[j % 1024];
+ tPeriod += cellDT[i2]*(1/(1-wf[(i2+1) % 1024]/wf[i2]));
+ }
+
+ if (n_correct < nzx/3)
+ return 0;
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+
+int DRSBoard::CalibrateTiming(DRSCallback *pcb)
+{
+ int index, status, error, tCell, i, j, c, chip, mode, nIterPeriod, nIterSlope, clkon, phase, refclk, trg1, trg2, n_error, channel;
+ double f, range, tTrue, tRounded, dT, t1[8], t2[8], cellDV[kNumberOfChipsMax*kNumberOfChannelsMax][kNumberOfBins];
+ unsigned short buf[1024*16]; // 32 kB
+ float wf[1024];
+ Averager *ave = NULL;
+
+ nIterPeriod = 5000;
+ nIterSlope = 5000;
+ n_error = 0;
+ refclk = 0;
+ f = fNominalFrequency;
+ range = fRange;
+ clkon = (GetCtrlReg() & BIT_TCAL_EN) > 0;
+ if (fBoardType == 6)
+ refclk = (GetCtrlReg() & BIT_REFCLK_SOURCE) > 0;
+ trg1 = fTriggerEnable1;
+ trg2 = fTriggerEnable2;
+
+ Init();
+ fNominalFrequency = f;
+ fTimingCalibratedFrequency = 0;
+ if (fBoardType == 6) // don't set refclk for evaluation boards
+ SetRefclk(refclk);
+ SetFrequency(fNominalFrequency, true);
+ if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8)
+ fTCALFrequency = 132; // 132 MHz for EVAL1, for MEZZ this is set by ConfigureLMK
+ else if (fBoardType == 9)
+ fTCALFrequency = 100;
+ SetDominoMode(1);
+ SetDominoActive(1);
+ SetReadoutMode(1);
+ EnableTrigger(0, 0);
+ if (fBoardType == 5 || fBoardType == 7) {
+ EnableTcal(1, 0, 0);
+ SelectClockSource(1); // 2nd quartz
+ } else if (fBoardType == 8) {
+ nIterSlope = 0;
+ nIterPeriod = 1500;
+ EnableTcal(1, 0, 0);
+ SelectClockSource(1); // 2nd quartz
+ ave = new Averager(1, 1, 1024, 500); // one chip, 1 channel @ 1024 bins
+ } else if (fBoardType == 9) {
+ EnableTcal(1);
+ nIterSlope = 500;
+ nIterPeriod = 500;
+ ave = new Averager(1, 9, 1024, 500); // one chip, 9 channels @ 1024 bins
+ }
+ StartDomino();
+
+ /* initialize time array */
+ for (i=0 ; i<1024 ; i++)
+ for (chip=0 ; chip<4 ; chip++)
+ for (channel = 0 ; channel < 8 ; channel++) {
+ fCellDT[chip][channel][i] = (float)1/fNominalFrequency; // [ns]
+ }
+
+ error = 0;
+
+ for (index = 0 ; index < nIterSlope+nIterPeriod ; index++) {
+ if (index % 10 == 0)
+ if (pcb)
+ pcb->Progress(100*index/(nIterSlope+nIterPeriod));
+
+ if (fTransport == TR_VME) {
+ SoftTrigger();
+ while (IsBusy());
+
+ /* select random phase */
+ phase = (rand() % 30) - 15;
+ if (phase == 0)
+ phase = 15;
+ EnableTcal(1, 0, phase);
+
+ StartDomino();
+ TransferWaves();
+
+ for (chip=0 ; chip<4 ; chip++) {
+ tCell = GetStopCell(chip);
+ GetWave(chip, 8, wf, true, tCell, 0, true);
+ status = AnalyzePeriod(ave, index, nIterPeriod, 0, wf, tCell, cellDV[chip], fCellDT[chip][0]);
+
+ if (!status)
+ n_error++;
+
+ if (n_error > nIterPeriod / 10) {
+ error = 1;
+ break;
+ }
+ }
+ } else {
+ if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8) { // DRS4 Evaluation board: 1 Chip
+ SoftTrigger();
+ while (IsBusy());
+
+ StartDomino();
+ TransferWaves();
+
+ tCell = GetStopCell(0);
+ GetWave(0, 8, wf, true, tCell, 0, true);
+
+ if (index < nIterSlope)
+ status = AnalyzeSlope(ave, index, nIterSlope, 0, wf, tCell, cellDV[0], fCellDT[0][0]);
+ else
+ status = AnalyzePeriod(ave, index, nIterPeriod, 0, wf, tCell, cellDV[0], fCellDT[0][0]);
+
+ if (!status)
+ n_error++;
+
+ if (n_error > nIterPeriod / 10) {
+ error = 1;
+ break;
+ }
+ } else if (fBoardType == 9) { // DRS4 Evaluation board V5: all channels from one chip
+ SoftTrigger();
+ while (IsBusy());
+
+ StartDomino();
+ TransferWaves();
+
+ // calibrate all channels individually
+ for (channel = 0 ; channel < 8 ; channel+=2) {
+ tCell = GetStopCell(0);
+ GetWave(0, channel, wf, true, tCell, 0, true);
+
+ if (index < nIterSlope)
+ status = AnalyzeSlope(ave, index, nIterSlope, channel, wf, tCell, cellDV[channel], fCellDT[0][channel]);
+ else
+ status = AnalyzePeriod(ave, index, nIterPeriod, channel, wf, tCell, cellDV[channel], fCellDT[0][channel]);
+
+ if (!status)
+ n_error++;
+
+ if (n_error > nIterPeriod / 2) {
+ error = 1;
+ break;
+ }
+ }
+ if (!status)
+ break;
+
+ } else { // DRS4 Mezzanine board: 4 Chips
+ for (mode=0 ; mode<2 ; mode++) {
+ SetChannelConfig(mode*2, 8, 8);
+ SoftTrigger();
+ while (IsBusy());
+
+ /* select random phase */
+ phase = (rand() % 30) - 15;
+ if (phase == 0)
+ phase = 15;
+ EnableTcal(1, 0, phase);
+
+ StartDomino();
+ TransferWaves();
+
+ for (chip=0 ; chip<4 ; chip+=2) {
+ tCell = GetStopCell(chip+mode);
+ GetWave(chip+mode, 8, wf, true, tCell, 0, true);
+ status = AnalyzePeriod(ave, index, nIterPeriod, 0, wf, tCell, cellDV[chip+mode], fCellDT[chip+mode][0]);
+
+ if (!status) {
+ error = 1;
+ break;
+ }
+ }
+ if (!status)
+ break;
+
+ }
+ }
+ }
+ }
+
+ if (pcb)
+ pcb->Progress(100);
+
+ // DRS4 Evaluation board V5: copy even channels to odd channels (usually not connected)
+ if (fBoardType == 9) {
+ for (channel = 0 ; channel < 8 ; channel+=2)
+ memcpy(fCellDT[0][channel+1], fCellDT[0][channel], sizeof(unsigned short)*1024);
+ }
+
+ // use following lines to save calibration into an ASCII file
+#if 0
+ FILE *fh;
+
+ fh = fopen("cellt.csv", "wt");
+ if (!fh)
+ printf("Cannot open file \"cellt.csv\"\n");
+ else {
+ fprintf(fh, "index,dt_ch1,dt_ch2,dt_ch3,dt_ch4\n");
+ for (i=0 ; i<1024 ; i++)
+ fprintf(fh, "%4d,%5.3lf,%5.3lf,%5.3lf,%5.3lf\n", i, fCellDT[0][0][i], fCellDT[0][2][i], fCellDT[0][4][i], fCellDT[0][6][i]);
+ fclose(fh);
+ }
+#endif
+
+ if (fBoardType == 5 || fBoardType == 7 || fBoardType == 8) {
+ /* write timing calibration to EEPROM page 0 */
+ ReadEEPROM(0, buf, sizeof(buf));
+ for (i=0,t1[0]=0 ; i<1024; i++)
+ buf[i*2+1] = (unsigned short) (fCellDT[0][0][i] * 10000 + 0.5);
+
+ /* write calibration method and frequency */
+ buf[4] = TCALIB_METHOD_V4;
+ buf[6] = (unsigned short)(fNominalFrequency*1000+0.5);
+
+ fTimingCalibratedFrequency = fNominalFrequency;
+ WriteEEPROM(0, buf, sizeof(buf));
+
+ // copy calibration to all channels
+ for (i=1 ; i<8 ; i++)
+ for (j=0 ; j<1024; j++)
+ fCellDT[0][i][j] = fCellDT[0][0][j];
+
+ } else if (fBoardType == 9) {
+
+ /* write timing calibration to EEPROM page 2 */
+ ReadEEPROM(2, buf, sizeof(buf));
+ for (i=0 ; i<8 ; i++) {
+ tTrue = 0; // true cellT
+ tRounded = 0; // rounded cellT
+ for (j=0 ; j<1024; j++) {
+ tTrue += fCellDT[0][i][j];
+ dT = tTrue - tRounded;
+ // shift by 1 ns to allow negative widths
+ dT = (unsigned short) (dT*10000+1000+0.5);
+ tRounded += (dT - 1000) / 10000.0;
+ buf[(i*1024+j)*2+1] = (unsigned short) dT;
+ }
+ }
+ WriteEEPROM(2, buf, sizeof(buf));
+
+ /* write calibration method and frequency to EEPROM page 0 */
+ ReadEEPROM(0, buf, sizeof(buf));
+ buf[4] = 1; // number of calibrations
+ buf[2] = (TCALIB_METHOD << 8) | (buf[2] & 0xFF); // calibration method
+ float fl = (float) fNominalFrequency;
+ memcpy(&buf[8], &fl, sizeof(float)); // exact freqeuncy
+
+ fTimingCalibratedFrequency = fNominalFrequency;
+ WriteEEPROM(0, buf, sizeof(buf));
+
+ } else {
+
+ /* write timing calibration to EEPROM page 6 */
+ ReadEEPROM(6, buf, sizeof(buf));
+ for (c=0 ; c<4 ; c++)
+ t1[c] = 0;
+ for (i=0 ; i<1024; i++) {
+ for (c=0 ; c<4 ; c++) {
+ t2[c] = fCellDT[0][c][i] - t1[c];
+ t2[c] = (unsigned short) (t2[c] * 10000 + 0.5);
+ t1[c] += t2[c] / 10000.0;
+ }
+ buf[i*2] = (unsigned short) t2[0];
+ buf[i*2+1] = (unsigned short) t2[1];
+ buf[i*2+0x800] = (unsigned short) t2[2];
+ buf[i*2+0x800+1] = (unsigned short) t2[3];
+ }
+ WriteEEPROM(6, buf, sizeof(buf));
+
+ /* write calibration method and frequency */
+ ReadEEPROM(0, buf, 16);
+ buf[4] = TCALIB_METHOD;
+ buf[6] = (unsigned short) (fNominalFrequency * 1000 + 0.5);
+ fTimingCalibratedFrequency = buf[6] / 1000.0;
+ WriteEEPROM(0, buf, 16);
+ }
+
+ if (ave)
+ delete ave;
+
+ /* remove calibration voltage */
+ EnableAcal(0, 0);
+ EnableTcal(clkon, 0);
+ SetInputRange(range);
+ EnableTrigger(trg1, trg2);
+
+ if (error)
+ return 0;
+
+ return 1;
+}
+
+
+/*------------------------------------------------------------------*/
+
+
+void DRSBoard::RemoveSymmetricSpikes(short **wf, int nwf,
+ short diffThreshold, int spikeWidth,
+ short maxPeakToPeak, short spikeVoltage,
+ int nTimeRegionThreshold)
+{
+ // Remove a specific kind of spike on DRS4.
+ // This spike has some features,
+ // - Common on all the channels on a chip
+ // - Constant heigh and width
+ // - Two spikes per channel
+ // - Symmetric to cell #0.
+ //
+ // This is not general purpose spike-removing function.
+ //
+ // wf : Waveform data. cell#0 must be at bin0,
+ // and number of bins must be kNumberOfBins.
+ // nwf : Number of channels which "wf" holds.
+ // diffThreshold : Amplitude threshold to find peak
+ // spikeWidth : Width of spike
+ // maxPeakToPeak : When peak-to-peak is larger than this, the channel
+ // is not used to find spikes.
+ // spikeVoltage : Amplitude of spikes. When it is 0, it is calculated in this function
+ // from voltage difference from neighboring bins.
+ // nTimeRegionThreshold : Requirement of number of time regions having spike at common position.
+ // Total number of time regions is 2*"nwf".
+
+ if (!wf || !nwf || !diffThreshold || !spikeWidth) {
+ return;
+ }
+
+ int ibin, jbin, kbin;
+ double v;
+ int nbin;
+ int iwf;
+ short maximum, minimum;
+ int spikeCount[kNumberOfBins / 2];
+ int spikeCountSum[kNumberOfBins / 2] = {0};
+ bool largePulse[kNumberOfChannelsMax * 2] = {0};
+ const short diffThreshold2 = diffThreshold + diffThreshold;
+
+ const short maxShort = 0xFFFF>>1;
+ const short minShort = -maxShort - 1;
+
+ // search spike
+ for (iwf = 0; iwf < nwf; iwf++) {
+ // first half
+ memset(spikeCount, 0, sizeof(spikeCount));
+ maximum = minShort;
+ minimum = maxShort;
+ for (ibin = 0; ibin < kNumberOfBins / 2; ibin++) {
+ jbin = ibin;
+ maximum = max(maximum, wf[iwf][jbin]);
+ minimum = min(minimum, wf[iwf][jbin]);
+ if (jbin - 1 >= 0 && jbin + spikeWidth < kNumberOfBins) {
+ v = 0;
+ nbin = 0;
+ for (kbin = 0; kbin < spikeWidth; kbin++) {
+ v += wf[iwf][jbin + kbin];
+ nbin++;
+ }
+ if ((nbin == 2 && v - (wf[iwf][jbin - 1] + wf[iwf][jbin + spikeWidth]) > diffThreshold2) ||
+ (nbin != 2 && nbin && v / nbin - (wf[iwf][jbin - 1] + wf[iwf][jbin + spikeWidth]) / 2 > diffThreshold)) {
+ spikeCount[ibin]++;
+ }
+ }
+ }
+ if (maximum != minShort && minimum != maxShort &&
+ (!maxPeakToPeak || maximum - minimum < maxPeakToPeak)) {
+ for (ibin = 0; ibin < kNumberOfBins / 2; ibin++) {
+ spikeCountSum[ibin] += spikeCount[ibin];
+ }
+ largePulse[iwf] = false;
+#if 0 /* this part can be enabled to skip checking other channels */
+ if (maximum != minShort && minimum != maxShort &&
+ maximum - minimum < diffThreshold) {
+ return;
+ }
+#endif
+ } else {
+ largePulse[iwf] = true;
+ }
+
+ // second half
+ memset(spikeCount, 0, sizeof(spikeCount));
+ maximum = minShort;
+ minimum = maxShort;
+ for (ibin = 0; ibin < kNumberOfBins / 2; ibin++) {
+ jbin = kNumberOfBins - 1 - ibin;
+ maximum = max(maximum, wf[iwf][jbin]);
+ minimum = min(minimum, wf[iwf][jbin]);
+ if (jbin + 1 < kNumberOfBins && jbin - spikeWidth >= 0) {
+ v = 0;
+ nbin = 0;
+ for (kbin = 0; kbin < spikeWidth; kbin++) {
+ v += wf[iwf][jbin - kbin];
+ nbin++;
+ }
+ if ((nbin == 2 && v - (wf[iwf][jbin + 1] + wf[iwf][jbin - spikeWidth]) > diffThreshold2) ||
+ (nbin != 2 && nbin && v / nbin - (wf[iwf][jbin + 1] + wf[iwf][jbin - spikeWidth]) / 2 > diffThreshold)) {
+ spikeCount[ibin]++;
+ }
+ }
+ }
+ if (maximum != minShort && minimum != maxShort &&
+ maximum - minimum < maxPeakToPeak) {
+ for (ibin = 0; ibin < kNumberOfBins / 2; ibin++) {
+ spikeCountSum[ibin] += spikeCount[ibin];
+ }
+ largePulse[iwf + nwf] = false;
+#if 0 /* this part can be enabled to skip checking other channels */
+ if (maximum != minShort && minimum != maxShort &&
+ maximum - minimum < diffThreshold) {
+ return;
+ }
+#endif
+ } else {
+ largePulse[iwf + nwf] = true;
+ }
+ }
+
+ // Find common spike
+ int commonSpikeBin = -1;
+ int commonSpikeMax = -1;
+ for (ibin = 0; ibin < kNumberOfBins / 2; ibin++) {
+ if (commonSpikeMax < spikeCountSum[ibin]) {
+ commonSpikeMax = spikeCountSum[ibin];
+ commonSpikeBin = ibin;
+ }
+ }
+
+ if (spikeCountSum[commonSpikeBin] >= nTimeRegionThreshold) {
+ if (spikeVoltage == 0) {
+ // Estimate spike amplitude
+ double baseline = 0;
+ int nBaseline = 0;
+ double peakAmplitude = 0;
+ int nPeakAmplitude = 0;
+ for (iwf = 0; iwf < nwf; iwf++) {
+ // first half
+ if (!largePulse[iwf]) {
+ // baseline
+ if ((jbin = commonSpikeBin - 1) >= 0 && jbin < kNumberOfBins) {
+ baseline += wf[iwf][jbin];
+ nBaseline++;
+ }
+ if ((jbin = commonSpikeBin + spikeWidth + 1) >= 0 && jbin < kNumberOfBins) {
+ baseline += wf[iwf][jbin];
+ nBaseline++;
+ }
+ // spike
+ for (ibin = 0; ibin < spikeWidth; ibin++) {
+ if ((jbin = commonSpikeBin + ibin) >= 0 && jbin < kNumberOfBins) {
+ peakAmplitude += wf[iwf][jbin];
+ nPeakAmplitude++;
+ }
+ }
+ }
+
+ // second half
+ if (!largePulse[iwf + nwf]) {
+ // baseline
+ if ((jbin = kNumberOfBins - 1 - commonSpikeBin + 1) >= 0 && jbin < kNumberOfBins) {
+ baseline += wf[iwf][jbin];
+ nBaseline++;
+ }
+ if ((jbin = kNumberOfBins - 1 - commonSpikeBin - spikeWidth - 1) >= 0 && jbin < kNumberOfBins) {
+ baseline += wf[iwf][jbin];
+ nBaseline++;
+ }
+ // spike
+ for (ibin = 0; ibin < spikeWidth; ibin++) {
+ if ((jbin = kNumberOfBins - 1 - commonSpikeBin - ibin) >= 0 && jbin < kNumberOfBins) {
+ peakAmplitude += wf[iwf][jbin];
+ nPeakAmplitude++;
+ }
+ }
+ }
+ }
+ if (nBaseline && nPeakAmplitude) {
+ baseline /= nBaseline;
+ peakAmplitude /= nPeakAmplitude;
+ spikeVoltage = static_cast<short>(peakAmplitude - baseline);
+ } else {
+ spikeVoltage = 0;
+ }
+ }
+
+ // Remove spike
+ if (spikeVoltage > 0) {
+ for (iwf = 0; iwf < nwf; iwf++) {
+ for (ibin = 0; ibin < spikeWidth; ibin++) {
+ if ((jbin = commonSpikeBin + ibin) >= 0 && jbin < kNumberOfBins) {
+ wf[iwf][jbin] -= spikeVoltage;
+ }
+ if ((jbin = kNumberOfBins - 1 - commonSpikeBin - ibin) >= 0 && jbin < kNumberOfBins) {
+ wf[iwf][jbin] -= spikeVoltage;
+ }
+ }
+ }
+ }
+ }
+}
+
+/*------------------------------------------------------------------*/
+
+void ResponseCalibration::SetCalibrationParameters(int numberOfPointsLowVolt, int numberOfPoints,
+ int numberOfMode2Bins, int numberOfSamples,
+ int numberOfGridPoints, int numberOfXConstPoints,
+ int numberOfXConstGridPoints, double triggerFrequency,
+ int showStatistics)
+{
+ DeleteFields();
+ InitFields(numberOfPointsLowVolt, numberOfPoints, numberOfMode2Bins, numberOfSamples, numberOfGridPoints,
+ numberOfXConstPoints, numberOfXConstGridPoints, triggerFrequency, showStatistics);
+}
+
+/*------------------------------------------------------------------*/
+
+void ResponseCalibration::ResetCalibration()
+{
+ int i;
+ for (i = 0; i < kNumberOfChipsMax; i++)
+ fCalibrationData[i]->fRead = false;
+ fCurrentPoint = 0;
+ fCurrentLowVoltPoint = 0;
+ fCurrentSample = 0;
+ fCurrentFitChannel = 0;
+ fCurrentFitBin = 0;
+ fRecorded = false;
+ fFitted = false;
+ fOffset = false;
+};
+
+/*------------------------------------------------------------------*/
+
+bool ResponseCalibration::WriteCalibration(unsigned int chipIndex)
+{
+ if (!fOffset)
+ return false;
+ if (fBoard->GetDRSType() == 3)
+ return WriteCalibrationV4(chipIndex);
+ else
+ return WriteCalibrationV3(chipIndex);
+}
+
+/*------------------------------------------------------------------*/
+
+bool ResponseCalibration::WriteCalibrationV3(unsigned int chipIndex)
+{
+ if (!fOffset)
+ return false;
+
+ int ii, j, k;
+ char str[1000];
+ char strt[1000];
+ short tempShort;
+ CalibrationData *data = fCalibrationData[chipIndex];
+ CalibrationData::CalibrationDataChannel * chn;
+
+ // Open File
+ fBoard->GetCalibrationDirectory(strt);
+ sprintf(str, "%s/board%d", strt, fBoard->GetBoardSerialNumber());
+ if (MakeDir(str) == -1) {
+ printf("Error: Cannot create directory \"%s\"\n", str);
+ return false;
+ }
+ sprintf(str, "%s/board%d/ResponseCalib_board%d_chip%d_%dMHz.bin", strt, fBoard->GetBoardSerialNumber(),
+ fBoard->GetBoardSerialNumber(), chipIndex, static_cast < int >(fBoard->GetNominalFrequency() * 1000));
+ fCalibFile = fopen(str, "wb");
+ if (fCalibFile == NULL) {
+ printf("Error: Cannot write to file \"%s\"\n", str);
+ return false;
+ }
+ // Write File
+ fwrite(&data->fNumberOfGridPoints, 1, 1, fCalibFile);
+ tempShort = static_cast < short >(data->fStartTemperature) * 10;
+ fwrite(&tempShort, 2, 1, fCalibFile);
+ tempShort = static_cast < short >(data->fEndTemperature) * 10;
+ fwrite(&tempShort, 2, 1, fCalibFile);
+ fwrite(&data->fMin, 4, 1, fCalibFile);
+ fwrite(&data->fMax, 4, 1, fCalibFile);
+ fwrite(&data->fNumberOfLimitGroups, 1, 1, fCalibFile);
+
+ for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
+ chn = data->fChannel[ii];
+ for (j = 0; j < kNumberOfBins; j++) {
+ fwrite(&chn->fLimitGroup[j], 1, 1, fCalibFile);
+ fwrite(&chn->fLookUpOffset[j], 2, 1, fCalibFile);
+ fwrite(&chn->fNumberOfLookUpPoints[j], 1, 1, fCalibFile);
+ for (k = 0; k < chn->fNumberOfLookUpPoints[j]; k++) {
+ fwrite(&chn->fLookUp[j][k], 1, 1, fCalibFile);
+ }
+ for (k = 0; k < data->fNumberOfGridPoints; k++) {
+ fwrite(&chn->fData[j][k], 2, 1, fCalibFile);
+ }
+ fwrite(&chn->fOffsetADC[j], 2, 1, fCalibFile);
+ fwrite(&chn->fOffset[j], 2, 1, fCalibFile);
+ }
+ }
+ fclose(fCalibFile);
+
+ printf("Calibration successfully written to\n\"%s\"\n", str);
+ return true;
+}
+
+/*------------------------------------------------------------------*/
+
+bool ResponseCalibration::WriteCalibrationV4(unsigned int chipIndex)
+{
+ if (!fOffset)
+ return false;
+
+ int ii, j;
+ char str[1000];
+ char strt[1000];
+ CalibrationData *data = fCalibrationData[chipIndex];
+ CalibrationData::CalibrationDataChannel * chn;
+
+ // Open File
+ fBoard->GetCalibrationDirectory(strt);
+ sprintf(str, "%s/board%d", strt, fBoard->GetBoardSerialNumber());
+ if (MakeDir(str) == -1) {
+ printf("Error: Cannot create directory \"%s\"\n", str);
+ return false;
+ }
+ sprintf(str, "%s/board%d/ResponseCalib_board%d_chip%d_%dMHz.bin", strt, fBoard->GetBoardSerialNumber(),
+ fBoard->GetBoardSerialNumber(), chipIndex, static_cast < int >(fBoard->GetNominalFrequency() * 1000));
+ fCalibFile = fopen(str, "wb");
+ if (fCalibFile == NULL) {
+ printf("Error: Cannot write to file \"%s\"\n", str);
+ return false;
+ }
+ // Write File
+ for (ii = 0; ii < kNumberOfCalibChannelsV4; ii++) {
+ chn = data->fChannel[ii];
+ for (j = 0; j < kNumberOfBins; j++) {
+ fwrite(&chn->fOffset[j], 2, 1, fCalibFile);
+ fwrite(&chn->fGain[j], 2, 1, fCalibFile);
+ }
+ }
+ fclose(fCalibFile);
+
+ printf("Calibration successfully written to\n\"%s\"\n", str);
+ return true;
+}
+
+/*------------------------------------------------------------------*/
+
+void ResponseCalibration::CalibrationTrigger(int mode, double voltage)
+{
+ fBoard->Reinit();
+ fBoard->EnableAcal(mode, voltage);
+ fBoard->StartDomino();
+ fBoard->SoftTrigger();
+ while (fBoard->IsBusy()) {
+ }
+}
+
+/*------------------------------------------------------------------*/
+
+void ResponseCalibration::CalibrationStart(double voltage)
+{
+ fBoard->SetDominoMode(1);
+ fBoard->EnableAcal(0, voltage);
+ fBoard->StartDomino();
+ fBoard->IsBusy();
+ fBoard->IsBusy();
+ fBoard->IsBusy();
+}
+
+/*------------------------------------------------------------------*/
+
+bool ResponseCalibration::RecordCalibrationPoints(int chipNumber)
+{
+ if (!fInitialized)
+ return true;
+ if (fBoard->GetDRSType() == 3)
+ return RecordCalibrationPointsV4(chipNumber);
+ else
+ return RecordCalibrationPointsV3(chipNumber);
+}
+
+/*------------------------------------------------------------------*/
+
+bool ResponseCalibration::RecordCalibrationPointsV3(int chipNumber)
+{
+ int j, k, ii;
+ int notdone, nsample;
+ double voltage;
+ float mean;
+ const double minVolt = 0.006;
+ const double xpos[50] =
+ { 0.010, 0.027, 0.052, 0.074, 0.096, 0.117, 0.136, 0.155, 0.173, 0.191, 0.208, 0.226, 0.243, 0.260,
+ 0.277, 0.294, 0.310,
+ 0.325, 0.342, 0.358, 0.374, 0.390, 0.406, 0.422, 0.439, 0.457, 0.477, 0.497, 0.520, 0.546, 0.577, 0.611,
+ 0.656, 0.710,
+ 0.772, 0.842, 0.916,
+ 0.995, 1.075, 1.157, 1.240, 1.323, 1.407, 1.490, 1.575, 1.659, 1.744, 1.829, 1.914, 2.000
+ };
+
+ // Initialisations
+ if (fCurrentLowVoltPoint == 0) {
+ fBoard->SetDAC(fBoard->fDAC_CLKOFS, 0);
+ // Record Temperature
+ fCalibrationData[chipNumber]->fStartTemperature = static_cast < float >(fBoard->GetTemperature());
+ }
+ // Record current Voltage
+ if (fCurrentLowVoltPoint < fNumberOfPointsLowVolt)
+ voltage =
+ (xpos[0] - minVolt) * fCurrentLowVoltPoint / static_cast <
+ double >(fNumberOfPointsLowVolt) + minVolt;
+ else
+ voltage = xpos[fCurrentPoint];
+ fBoard->SetCalibVoltage(voltage);
+ fResponseY[fCurrentPoint + fCurrentLowVoltPoint] = static_cast < float >(voltage) * 1000;
+
+ // Loop Over Number Of Samples For Statistics
+ for (j = 0; j < fNumberOfSamples; j++) {
+ // Read Out Second Part of the Waveform
+ CalibrationTrigger(3, voltage);
+ fBoard->TransferWaves();
+ for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
+ fBoard->GetRawWave(chipNumber, ii, fWaveFormMode3[ii][j]);
+ }
+ // Read Out First Part of the Waveform
+ CalibrationStart(voltage);
+ CalibrationTrigger(2, voltage);
+ fBoard->TransferWaves();
+ for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
+ fBoard->GetRawWave(chipNumber, ii, fWaveFormMode2[ii][j]);
+ }
+ CalibrationStart(voltage);
+ }
+ // Average Sample Points
+ for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
+ for (k = 0; k < kNumberOfBins; k++) {
+ fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] = 0;
+ for (j = 0; j < fNumberOfSamples; j++) {
+ fSampleUsed[j] = 1;
+ if (k < fNumberOfMode2Bins)
+ fSamples[j] = fWaveFormMode2[ii][j][k];
+ else
+ fSamples[j] = fWaveFormMode3[ii][j][k];
+ fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] += fSamples[j];
+ }
+ mean = fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] / fNumberOfSamples;
+ notdone = 1;
+ nsample = fNumberOfSamples;
+ while (notdone) {
+ notdone = 0;
+ for (j = 0; j < fNumberOfSamples; j++) {
+ if (fSampleUsed[j] && abs(static_cast < int >(fSamples[j] - mean)) > 3) {
+ notdone = 1;
+ fSampleUsed[j] = 0;
+ nsample--;
+ fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] -= fSamples[j];
+ mean = fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] / nsample;
+ }
+ }
+ }
+ fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] = mean;
+ }
+ }
+ if (fCurrentLowVoltPoint < fNumberOfPointsLowVolt)
+ fCurrentLowVoltPoint++;
+ else
+ fCurrentPoint++;
+
+ if (fCurrentPoint == fNumberOfPoints) {
+ fCalibrationData[chipNumber]->fEndTemperature = static_cast < float >(fBoard->GetTemperature());
+ fRecorded = true;
+ fFitted = false;
+ fOffset = false;
+ fCalibrationData[chipNumber]->fRead = false;
+ fCalibrationData[chipNumber]->fHasOffsetCalibration = false;
+ fBoard->SetCalibVoltage(0.0);
+ fBoard->EnableAcal(1, 0.0);
+ fBoard->SetDAC(fBoard->fDAC_CLKOFS, 0.0);
+ return true;
+ }
+
+ return false;
+}
+
+/*------------------------------------------------------------------*/
+
+bool ResponseCalibration::RecordCalibrationPointsV4(int chipNumber)
+{
+ int i, j, k, n;
+ double voltage, s, s2, average;
+
+ if (fCurrentPoint == 0) {
+ fBoard->SetDominoMode(1);
+ fBoard->EnableAcal(1, 0);
+ fBoard->SoftTrigger();
+ while (fBoard->IsBusy());
+ fBoard->StartDomino();
+ fCalibrationData[chipNumber]->fStartTemperature = static_cast < float >(fBoard->GetTemperature());
+ }
+ voltage = 1.0 * fCurrentPoint / (static_cast < double >(fNumberOfPoints) - 1) +0.1;
+ fBoard->SetCalibVoltage(voltage);
+ Sleep(10);
+ fBoard->SetCalibVoltage(voltage);
+ Sleep(10);
+
+ // One dummy cycle for unknown reasons
+ fBoard->SoftTrigger();
+ while (fBoard->IsBusy());
+ fBoard->StartDomino();
+ Sleep(50);
+ fBoard->TransferWaves();
+
+ // Loop over number of samples for statistics
+ for (i = 0; i < fNumberOfSamples; i++) {
+ if (fBoard->Debug()) {
+ printf("%02d:%02d\r", fNumberOfPoints - fCurrentPoint, fNumberOfSamples - i);
+ fflush(stdout);
+ }
+
+
+ fBoard->SoftTrigger();
+ while (fBoard->IsBusy());
+ fBoard->StartDomino();
+ Sleep(50);
+ fBoard->TransferWaves();
+ for (j = 0; j < kNumberOfCalibChannelsV4; j++) {
+ fBoard->GetRawWave(chipNumber, j, fWaveFormMode3[j][i]);
+ }
+ }
+
+ // Calculate averages
+ for (i = 0; i < kNumberOfCalibChannelsV4; i++) {
+ for (k = 0; k < kNumberOfBins; k++) {
+ s = s2 = 0;
+
+ for (j = 0; j < fNumberOfSamples; j++) {
+ s += fWaveFormMode3[i][j][k];
+ s2 += fWaveFormMode3[i][j][k] * fWaveFormMode3[i][j][k];
+ }
+ n = fNumberOfSamples;
+ average = s / n;
+
+ fResponseX[i][k][fCurrentPoint] = static_cast < float >(average);
+ }
+ }
+
+ fCurrentPoint++;
+ if (fCurrentPoint == fNumberOfPoints) {
+ fCalibrationData[chipNumber]->fEndTemperature = static_cast < float >(fBoard->GetTemperature());
+ fRecorded = true;
+ return true;
+ }
+
+ return false;
+}
+
+/*------------------------------------------------------------------*/
+
+bool ResponseCalibration::FitCalibrationPoints(int chipNumber)
+{
+ if (!fRecorded || fFitted)
+ return true;
+ if (fBoard->GetDRSType() == 3)
+ return FitCalibrationPointsV4(chipNumber);
+ else
+ return FitCalibrationPointsV3(chipNumber);
+}
+
+/*------------------------------------------------------------------*/
+
+bool ResponseCalibration::FitCalibrationPointsV3(int chipNumber)
+{
+ int i, j, k;
+ float x1, x2, y1, y2;
+ float uu;
+ float yc, yr;
+ float xminExt, xrangeExt;
+ float xmin, xrange;
+ float average, averageError, averageExt, averageErrorExt;
+ unsigned short i0, i1;
+
+ CalibrationData *data = fCalibrationData[chipNumber];
+ CalibrationData::CalibrationDataChannel * chn = data->fChannel[fCurrentFitChannel];
+
+ data->DeletePreCalculatedBSpline();
+
+ if (fCurrentFitBin == 0 && fCurrentFitChannel == 0) {
+ data->fNumberOfLimitGroups = 0;
+ data->fMin = 100000;
+ data->fMax = -100000;
+ for (i = 0; i < kNumberOfCalibChannelsV3; i++) {
+ for (j = 0; j < kNumberOfBins; j++) {
+ if (data->fMin > fResponseX[i][j][fNumberOfPointsLowVolt + fNumberOfPoints - 1])
+ data->fMin = fResponseX[i][j][fNumberOfPointsLowVolt + fNumberOfPoints - 1];
+ if (data->fMax < fResponseX[i][j][fNumberOfPointsLowVolt])
+ data->fMax = fResponseX[i][j][fNumberOfPointsLowVolt];
+ }
+ }
+ }
+ // Low Volt
+ i0 = static_cast < unsigned short >(fResponseX[fCurrentFitChannel][fCurrentFitBin][0]);
+ i1 = static_cast <
+ unsigned short >(fResponseX[fCurrentFitChannel][fCurrentFitBin][fNumberOfPointsLowVolt]) + 1;
+ chn->fLookUpOffset[fCurrentFitBin] = i0;
+ delete chn->fLookUp[fCurrentFitBin];
+ if (i0 - i1 + 1 < 2) {
+ chn->fNumberOfLookUpPoints[fCurrentFitBin] = 2;
+ chn->fLookUp[fCurrentFitBin] = new unsigned char[2];
+ chn->fLookUp[fCurrentFitBin][0] = 0;
+ chn->fLookUp[fCurrentFitBin][1] = 0;
+ } else {
+ chn->fNumberOfLookUpPoints[fCurrentFitBin] = i0 - i1 + 1;
+ chn->fLookUp[fCurrentFitBin] = new unsigned char[i0 - i1 + 1];
+ for (i = 0; i < i0 - i1 + 1; i++) {
+ for (j = 0; j < fNumberOfPointsLowVolt; j++) {
+ if (i0 - i >= fResponseX[fCurrentFitChannel][fCurrentFitBin][j + 1]) {
+ x1 = fResponseX[fCurrentFitChannel][fCurrentFitBin][j];
+ x2 = fResponseX[fCurrentFitChannel][fCurrentFitBin][j + 1];
+ y1 = fResponseY[j];
+ y2 = fResponseY[j + 1];
+ chn->fLookUp[fCurrentFitBin][i] =
+ static_cast < unsigned char >(((y2 - y1) * (i0 - i - x1) / (x2 - x1) + y1) / fPrecision);
+ break;
+ }
+ }
+ }
+ }
+
+ // Copy Points
+ for (i = 0; i < fNumberOfPoints; i++) {
+ fPntX[0][i] = fResponseX[fCurrentFitChannel][fCurrentFitBin][fNumberOfPointsLowVolt + i];
+ fPntY[0][i] = fResponseY[fNumberOfPointsLowVolt + i];
+ }
+ // Fit BSpline
+ for (i = 0; i < fNumberOfPoints; i++) {
+ fUValues[0][i] = static_cast < float >(1 - i / (fNumberOfPoints - 1.));
+ }
+ if (!Approx(fPntX[0], fUValues[0], fNumberOfPoints, fNumberOfGridPoints, fResX[fCurrentFitBin]))
+ return true;
+ if (!Approx(fPntY[0], fUValues[0], fNumberOfPoints, fNumberOfGridPoints, fRes[fCurrentFitBin]))
+ return true;
+
+ // X constant fit
+ for (k = 0; k < fNumberOfXConstPoints - 2; k++) {
+ fPntX[1][k + 1] =
+ GetValue(fResX[fCurrentFitBin],
+ static_cast < float >(1 - k / static_cast < float >(fNumberOfXConstPoints - 3)),
+ fNumberOfGridPoints);
+ fPntY[1][k + 1] =
+ GetValue(fRes[fCurrentFitBin],
+ static_cast < float >(1 - k / static_cast < float >(fNumberOfXConstPoints - 3)),
+ fNumberOfGridPoints);
+ }
+ xmin = fPntX[1][fNumberOfXConstPoints - 2];
+ xrange = fPntX[1][1] - xmin;
+
+ for (i = 0; i < fNumberOfXConstPoints - 2; i++) {
+ fUValues[1][i + 1] = (fPntX[1][i + 1] - xmin) / xrange;
+ }
+
+ if (!Approx
+ (&fPntY[1][1], &fUValues[1][1], fNumberOfXConstPoints - 2, fNumberOfXConstGridPoints, chn->fTempData))
+ return true;
+
+ // error statistics
+ if (fShowStatistics) {
+ for (i = 0; i < fNumberOfPoints; i++) {
+ uu = (fPntX[0][i] - xmin) / xrange;
+ yc = GetValue(chn->fTempData, uu, fNumberOfXConstGridPoints);
+ yr = fPntY[0][i];
+ fStatisticsApprox[i][fCurrentFitBin + fCurrentFitChannel * kNumberOfBins] = yc - yr;
+ }
+ }
+ // Add min and max point
+ chn->fLimitGroup[fCurrentFitBin] = 0;
+ while (xmin - kBSplineXMinOffset > data->fMin + kBSplineXMinOffset * chn->fLimitGroup[fCurrentFitBin]) {
+ chn->fLimitGroup[fCurrentFitBin]++;
+ }
+ if (data->fNumberOfLimitGroups <= chn->fLimitGroup[fCurrentFitBin])
+ data->fNumberOfLimitGroups = chn->fLimitGroup[fCurrentFitBin] + 1;
+ xminExt = data->fMin + kBSplineXMinOffset * chn->fLimitGroup[fCurrentFitBin];
+ xrangeExt = data->fMax - xminExt;
+
+ fPntX[1][0] = data->fMax;
+ uu = (fPntX[1][0] - xmin) / xrange;
+ fPntY[1][0] = GetValue(chn->fTempData, uu, fNumberOfXConstGridPoints);
+
+ fPntX[1][fNumberOfXConstPoints - 1] = xminExt;
+ uu = (fPntX[1][fNumberOfXConstPoints - 1] - xmin) / xrange;
+ fPntY[1][fNumberOfXConstPoints - 1] = GetValue(chn->fTempData, uu, fNumberOfXConstGridPoints);
+
+ for (i = 0; i < fNumberOfXConstPoints; i++) {
+ fUValues[1][i] = (fPntX[1][i] - xminExt) / xrangeExt;
+ }
+
+ if (!Approx(fPntY[1], fUValues[1], fNumberOfXConstPoints, fNumberOfXConstGridPoints, chn->fTempData))
+ return true;
+
+ // error statistics
+ if (fShowStatistics) {
+ for (i = 0; i < fNumberOfPoints; i++) {
+ uu = (fPntX[0][i] - xminExt) / xrangeExt;
+ yc = GetValue(chn->fTempData, uu, fNumberOfXConstGridPoints);
+ yr = fPntY[0][i];
+ fStatisticsApproxExt[i][fCurrentFitBin + fCurrentFitChannel * kNumberOfBins] = yc - yr;
+ }
+ }
+ for (i = 0; i < fNumberOfXConstGridPoints; i++) {
+ chn->fData[fCurrentFitBin][i] = static_cast < short >(chn->fTempData[i] / fPrecision);
+ }
+
+ // write end of file
+ fCurrentFitBin++;
+ if (fCurrentFitBin == kNumberOfBins) {
+ fCurrentFitChannel++;
+ fCurrentFitBin = 0;
+ }
+ if (fCurrentFitChannel == kNumberOfCalibChannelsV3) {
+ if (fShowStatistics) {
+ for (i = 0; i < fNumberOfPoints; i++) {
+ average = 0;
+ averageError = 0;
+ averageExt = 0;
+ averageErrorExt = 0;
+ for (j = 0; j < kNumberOfCalibChannelsV3 * kNumberOfBins; j++) {
+ average += fStatisticsApprox[i][j];
+ averageError += fStatisticsApprox[i][j] * fStatisticsApprox[i][j];
+ averageExt += fStatisticsApproxExt[i][j];
+ averageErrorExt += fStatisticsApproxExt[i][j] * fStatisticsApproxExt[i][j];
+ }
+ average /= kNumberOfCalibChannelsV3 * kNumberOfBins;
+ averageError =
+ sqrt((averageError -
+ average * average / kNumberOfCalibChannelsV3 * kNumberOfBins) /
+ (kNumberOfCalibChannelsV3 * kNumberOfBins - 1));
+ averageExt /= kNumberOfCalibChannelsV3 * kNumberOfBins;
+ averageErrorExt =
+ sqrt((averageErrorExt -
+ averageExt * averageExt / kNumberOfCalibChannelsV3 * kNumberOfBins) /
+ (kNumberOfCalibChannelsV3 * kNumberOfBins - 1));
+ printf("Error at %3.1f V : % 2.3f +- % 2.3f ; % 2.3f +- % 2.3f\n", fPntY[0][i], average,
+ averageError, averageExt, averageErrorExt);
+ }
+ }
+ fFitted = true;
+ fOffset = false;
+ fCalibrationData[chipNumber]->fRead = true;
+ fCalibrationData[chipNumber]->fHasOffsetCalibration = false;
+ data->PreCalculateBSpline();
+ return true;
+ }
+ return false;
+}
+
+/*------------------------------------------------------------------*/
+
+bool ResponseCalibration::FitCalibrationPointsV4(int chipNumber)
+{
+ if (!fRecorded || fFitted)
+ return true;
+ int i;
+ double par[2];
+ static int error;
+
+ CalibrationData *data = fCalibrationData[chipNumber];
+ CalibrationData::CalibrationDataChannel * chn = data->fChannel[fCurrentFitChannel];
+
+ if (fCurrentFitBin == 0 && fCurrentFitChannel == 0) {
+ error = 0;
+ for (i = 0; i < fNumberOfPoints; i++)
+ fWWFit[i] = 1;
+ }
+
+ for (i = 0; i < fNumberOfPoints; i++) {
+ fXXFit[i] = 1.0 * i / (static_cast < double >(fNumberOfPoints) - 1) +0.1;
+ fYYFit[i] = fResponseX[fCurrentFitChannel][fCurrentFitBin][i];
+ if (fCurrentFitBin == 10 && fCurrentFitChannel == 1) {
+ fXXSave[i] = fXXFit[i];
+ fYYSave[i] = fYYFit[i];
+ }
+ }
+
+ // DRSBoard::LinearRegression(fXXFit, fYYFit, fNumberOfPoints, &par[1], &par[0]);
+ // exclude first two points (sometimes are on limit of FADC)
+ DRSBoard::LinearRegression(fXXFit + 2, fYYFit + 2, fNumberOfPoints - 2, &par[1], &par[0]);
+
+ chn->fOffset[fCurrentFitBin] = static_cast < unsigned short >(par[0] + 0.5);
+ chn->fGain[fCurrentFitBin] = static_cast < unsigned short >(par[1] + 0.5);
+
+ // Remember min/max of gain
+ if (fCurrentFitBin == 0 && fCurrentFitChannel == 0)
+ fGainMin = fGainMax = chn->fGain[0];
+ if (chn->fGain[fCurrentFitBin] < fGainMin)
+ fGainMin = chn->fGain[fCurrentFitBin];
+ if (chn->fGain[fCurrentFitBin] > fGainMax)
+ fGainMax = chn->fGain[fCurrentFitBin];
+
+ // abort if outside normal region
+ if (chn->fGain[fCurrentFitBin] / 4096.0 < 0.8 || chn->fGain[fCurrentFitBin] / 4096.0 > 1) {
+ error++;
+
+ if (error < 20)
+ printf("Gain=%1.3lf for bin %d on channel %d on chip %d outside valid region\n",
+ chn->fGain[fCurrentFitBin] / 4096.0, fCurrentFitBin, fCurrentFitChannel, chipNumber);
+ }
+
+ if (fCurrentFitChannel == 1 && fCurrentFitBin == 10) {
+ for (i = 0; i < fNumberOfPoints; i++) {
+ fXXSave[i] = fXXFit[i];
+ fYYSave[i] = (fYYFit[i] - chn->fOffset[10]) / chn->fGain[10] - fXXFit[i];
+ }
+ }
+
+ fCurrentFitBin++;
+ if (fCurrentFitBin == kNumberOfBins) {
+ fCurrentFitChannel++;
+ fCurrentFitBin = 0;
+ }
+ if (fCurrentFitChannel == kNumberOfCalibChannelsV4) {
+
+ if (fBoard->Debug()) {
+ printf("Gain min=%1.3lf max=%1.3lf\n", fGainMin / 4096.0, fGainMax / 4096.0);
+ fflush(stdout);
+ }
+ // allow up to three bad bins
+ if (error > 3) {
+ printf("Aborting calibration!\n");
+ return true;
+ }
+
+ fFitted = true;
+ fOffset = false;
+ fCalibrationData[chipNumber]->fRead = true;
+ fCalibrationData[chipNumber]->fHasOffsetCalibration = false;
+ return true;
+ }
+
+ return false;
+}
+
+unsigned int millitime()
+{
+#ifdef _MSC_VER
+
+ return (int) GetTickCount();
+
+#else
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+
+ return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+#endif
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+
+bool ResponseCalibration::OffsetCalibration(int chipNumber)
+{
+ if (!fFitted || fOffset)
+ return true;
+ if (fBoard->GetDRSType() == 3)
+ return OffsetCalibrationV4(chipNumber);
+ else
+ return OffsetCalibrationV3(chipNumber);
+}
+
+/*------------------------------------------------------------------*/
+
+bool ResponseCalibration::OffsetCalibrationV3(int chipNumber)
+{
+ int k, ii, j;
+ int t1, t2;
+ float mean, error;
+ CalibrationData *data = fCalibrationData[chipNumber];
+ CalibrationData::CalibrationDataChannel * chn;
+
+ if (fCurrentSample == 0) {
+ data->fHasOffsetCalibration = false;
+ fBoard->SetCalibVoltage(0.0);
+ fBoard->EnableAcal(0, 0.0);
+ }
+ // Loop Over Number Of Samples For Statistics
+ t1 = millitime();
+ fBoard->SoftTrigger();
+ while (fBoard->IsBusy()) {
+ }
+ fBoard->TransferWaves();
+ for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
+ fBoard->GetRawWave(chipNumber, ii, fWaveFormOffsetADC[ii][fCurrentSample]);
+ fBoard->CalibrateWaveform(chipNumber, ii, fWaveFormOffsetADC[ii][fCurrentSample],
+ fWaveFormOffset[ii][fCurrentSample], true, false, false, 0, true);
+ }
+ fBoard->StartDomino();
+ fBoard->IsBusy();
+ fBoard->IsBusy();
+ fBoard->IsBusy();
+ t2 = millitime();
+ while (t2 - t1 < (1000 / fTriggerFrequency)) {
+ t2 = millitime();
+ }
+ fCurrentSample++;
+
+ if (fCurrentSample == fNumberOfSamples) {
+ // Average Sample Points
+ float *sample = new float[fNumberOfSamples];
+ for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
+ chn = data->fChannel[ii];
+ for (k = 0; k < kNumberOfBins; k++) {
+ for (j = 0; j < fNumberOfSamples; j++)
+ sample[j] = static_cast < float >(fWaveFormOffset[ii][j][k]);
+ Average(1, sample, fNumberOfSamples, mean, error, 2);
+ chn->fOffset[k] = static_cast < short >(mean);
+ for (j = 0; j < fNumberOfSamples; j++)
+ sample[j] = fWaveFormOffsetADC[ii][j][k];
+ Average(1, sample, fNumberOfSamples, mean, error, 2);
+ chn->fOffsetADC[k] = static_cast < unsigned short >(mean);
+ }
+ }
+ fOffset = true;
+ fCalibrationData[chipNumber]->fHasOffsetCalibration = true;
+ delete[] sample;
+ return true;
+ }
+
+ return false;
+}
+
+/*------------------------------------------------------------------*/
+
+bool ResponseCalibration::OffsetCalibrationV4(int chipNumber)
+{
+ int k, ii, j;
+ float mean, error;
+ CalibrationData *data = fCalibrationData[chipNumber];
+ CalibrationData::CalibrationDataChannel * chn;
+
+ /* switch DRS to input, hope that no real signal occurs */
+ if (fCurrentSample == 0) {
+ data->fHasOffsetCalibration = false;
+ fBoard->SetCalibVoltage(0.0);
+ fBoard->EnableAcal(0, 0.0);
+ /* one dummy trigger for unknown reasons */
+ fBoard->SoftTrigger();
+ while (fBoard->IsBusy());
+ fBoard->StartDomino();
+ Sleep(50);
+ }
+ // Loop Over Number Of Samples For Statistics
+ fBoard->SoftTrigger();
+ while (fBoard->IsBusy());
+ fBoard->TransferWaves();
+ for (ii = 0; ii < kNumberOfCalibChannelsV4; ii++)
+ fBoard->GetRawWave(chipNumber, ii, fWaveFormOffsetADC[ii][fCurrentSample]);
+
+ fBoard->StartDomino();
+ Sleep(50);
+ fCurrentSample++;
+
+ if (fBoard->Debug()) {
+ printf("%02d\r", fNumberOfSamples - fCurrentSample);
+ fflush(stdout);
+ }
+
+ if (fCurrentSample == fNumberOfSamples) {
+ // Average Sample Points
+ float *sample = new float[fNumberOfSamples];
+ for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
+ chn = data->fChannel[ii];
+ for (k = 0; k < kNumberOfBins; k++) {
+ for (j = 0; j < fNumberOfSamples; j++)
+ sample[j] = static_cast < float >(fWaveFormOffsetADC[ii][j][k]);
+ Average(1, sample, fNumberOfSamples, mean, error, 2);
+ chn->fOffset[k] = static_cast < unsigned short >(mean);
+ }
+ }
+ fOffset = true;
+ fCalibrationData[chipNumber]->fHasOffsetCalibration = true;
+ delete[] sample;
+ return true;
+ }
+
+ return false;
+}
+
+/*------------------------------------------------------------------*/
+
+void ResponseCalibration::InitFields(int numberOfPointsLowVolt, int numberOfPoints, int numberOfMode2Bins,
+ int numberOfSamples, int numberOfGridPoints, int numberOfXConstPoints,
+ int numberOfXConstGridPoints, double triggerFrequency,
+ int showStatistics)
+{
+ int ii, j, i;
+ fInitialized = true;
+ fNumberOfPointsLowVolt = numberOfPointsLowVolt;
+ fNumberOfPoints = numberOfPoints;
+ fNumberOfMode2Bins = numberOfMode2Bins;
+ fNumberOfSamples = numberOfSamples;
+ fNumberOfGridPoints = numberOfGridPoints;
+ fNumberOfXConstPoints = numberOfXConstPoints;
+ fNumberOfXConstGridPoints = numberOfXConstGridPoints;
+ fTriggerFrequency = triggerFrequency;
+ fShowStatistics = showStatistics;
+ fCurrentPoint = 0;
+ fCurrentSample = 0;
+ fCurrentFitChannel = 0;
+ fCurrentFitBin = 0;
+ for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
+ for (j = 0; j < kNumberOfBins; j++) {
+ fResponseX[ii][j] = new float[fNumberOfPoints + fNumberOfPointsLowVolt];
+ }
+ }
+ fResponseY = new float[fNumberOfPoints + fNumberOfPointsLowVolt];
+ for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
+ fWaveFormMode3[ii] = new unsigned short *[fNumberOfSamples];
+ fWaveFormMode2[ii] = new unsigned short *[fNumberOfSamples];
+ fWaveFormOffset[ii] = new short *[fNumberOfSamples];
+ fWaveFormOffsetADC[ii] = new unsigned short *[fNumberOfSamples];
+ for (i = 0; i < fNumberOfSamples; i++) {
+ fWaveFormMode3[ii][i] = new unsigned short[kNumberOfBins];
+ fWaveFormMode2[ii][i] = new unsigned short[kNumberOfBins];
+ fWaveFormOffset[ii][i] = new short[kNumberOfBins];
+ fWaveFormOffsetADC[ii][i] = new unsigned short[kNumberOfBins];
+ }
+ }
+ fSamples = new unsigned short[fNumberOfSamples];
+ fSampleUsed = new int[fNumberOfSamples];
+
+ for (j = 0; j < kNumberOfBins; j++) {
+ fRes[j] = new float[fNumberOfGridPoints];
+ fResX[j] = new float[fNumberOfGridPoints];
+ }
+ for (i = 0; i < 2; i++) {
+ fPntX[i] = new float[fNumberOfPoints * (1 - i) + fNumberOfXConstPoints * i];
+ fPntY[i] = new float[fNumberOfPoints * (1 - i) + fNumberOfXConstPoints * i];
+ fUValues[i] = new float[fNumberOfPoints * (1 - i) + fNumberOfXConstPoints * i];
+ }
+ fXXFit = new double[fNumberOfPoints];
+ fYYFit = new double[fNumberOfPoints];
+ fWWFit = new double[fNumberOfPoints];
+ fYYFitRes = new double[fNumberOfPoints];
+ fYYSave = new double[fNumberOfPoints];
+ fXXSave = new double[fNumberOfPoints];
+
+ fStatisticsApprox = new float *[fNumberOfPoints];
+ fStatisticsApproxExt = new float *[fNumberOfPoints];
+ for (i = 0; i < fNumberOfPoints; i++) {
+ fStatisticsApprox[i] = new float[kNumberOfCalibChannelsV3 * kNumberOfBins];
+ fStatisticsApproxExt[i] = new float[kNumberOfCalibChannelsV3 * kNumberOfBins];
+ }
+ for (i = 0; i < kNumberOfChipsMax; i++) {
+ fCalibrationData[i] = new CalibrationData(numberOfXConstGridPoints);
+ }
+}
+
+/*------------------------------------------------------------------*/
+
+void ResponseCalibration::DeleteFields()
+{
+ if (!fInitialized)
+ return;
+ fInitialized = false;
+ int ii, j, i;
+ for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
+ for (j = 0; j < kNumberOfBins; j++) {
+ delete fResponseX[ii][j];
+ }
+ }
+ delete fResponseY;
+ for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
+ for (i = 0; i < fNumberOfSamples; i++) {
+ if (fWaveFormMode3[ii] != NULL)
+ delete fWaveFormMode3[ii][i];
+ if (fWaveFormMode2[ii] != NULL)
+ delete fWaveFormMode2[ii][i];
+ if (fWaveFormOffset[ii] != NULL)
+ delete fWaveFormOffset[ii][i];
+ if (fWaveFormOffsetADC[ii] != NULL)
+ delete fWaveFormOffsetADC[ii][i];
+ }
+ delete fWaveFormMode3[ii];
+ delete fWaveFormMode2[ii];
+ delete fWaveFormOffset[ii];
+ delete fWaveFormOffsetADC[ii];
+ }
+ delete fSamples;
+ delete fSampleUsed;
+
+ for (j = 0; j < kNumberOfBins; j++) {
+ delete fRes[j];
+ delete fResX[j];
+ }
+ for (i = 0; i < 2; i++) {
+ delete fPntX[i];
+ delete fPntY[i];
+ delete fUValues[i];
+ }
+ delete fXXFit;
+ delete fYYFit;
+ delete fWWFit;
+ delete fYYFitRes;
+ delete fYYSave;
+ delete fXXSave;
+
+ for (i = 0; i < fNumberOfPoints; i++) {
+ delete fStatisticsApprox[i];
+ delete fStatisticsApproxExt[i];
+ }
+ delete fStatisticsApprox;
+ delete fStatisticsApproxExt;
+ for (i = 0; i < kNumberOfChipsMax; i++)
+ delete fCalibrationData[i];
+}
+
+/*------------------------------------------------------------------*/
+
+double ResponseCalibration::GetTemperature(unsigned int chipIndex)
+{
+ if (fCalibrationData[chipIndex] == NULL)
+ return 0;
+ if (!fCalibrationData[chipIndex]->fRead)
+ return 0;
+ return (fCalibrationData[chipIndex]->fStartTemperature + fCalibrationData[chipIndex]->fEndTemperature) / 2;
+}
+
+/*------------------------------------------------------------------*/
+
+bool ResponseCalibration::Calibrate(unsigned int chipIndex, unsigned int channel, unsigned short *adcWaveform,
+ short *uWaveform, int triggerCell, float threshold, bool offsetCalib)
+{
+ int i;
+ unsigned int NumberOfCalibChannels;
+ int hasOffset;
+ bool aboveThreshold;
+ float wave, v;
+ int j, irot;
+
+ CalibrationData *data = fCalibrationData[chipIndex];
+ CalibrationData::CalibrationDataChannel * chn;
+
+ if (fBoard->GetDRSType() == 3)
+ NumberOfCalibChannels = kNumberOfCalibChannelsV4;
+ else
+ NumberOfCalibChannels = kNumberOfCalibChannelsV3;
+
+ if (channel >= NumberOfCalibChannels || data == NULL) {
+ for (i = 0; i < kNumberOfBins; i++) {
+ irot = i;
+ if (triggerCell > -1)
+ irot = (triggerCell + i) % kNumberOfBins;
+
+ uWaveform[i] = adcWaveform[irot];
+ }
+ return true;
+ }
+ if (!data->fRead) {
+ for (i = 0; i < kNumberOfBins; i++) {
+ uWaveform[i] = adcWaveform[i];
+ }
+ return true;
+ }
+
+ chn = data->fChannel[channel];
+
+ hasOffset = data->fHasOffsetCalibration;
+ aboveThreshold = (threshold == 0); // if threshold equal zero, always return true
+
+ short offset;
+
+ // Calibrate
+ for (i = 0; i < kNumberOfBins; i++) {
+ if (fBoard->GetDRSType() != 3) {
+ irot = i;
+ if (triggerCell > -1)
+ irot = (triggerCell + i) % kNumberOfBins;
+ offset = offsetCalib ? chn->fOffset[irot] : 0;
+ if (adcWaveform[irot] > chn->fLookUpOffset[irot]) {
+ uWaveform[i] =
+ ((chn->fLookUp[irot][0] - chn->fLookUp[irot][1]) * (adcWaveform[irot] -
+ chn->fLookUpOffset[irot]) +
+ chn->fLookUp[irot][0]);
+ } else if (adcWaveform[irot] <= chn->fLookUpOffset[irot]
+ && adcWaveform[irot] > chn->fLookUpOffset[irot] - chn->fNumberOfLookUpPoints[irot]) {
+ uWaveform[i] = chn->fLookUp[irot][chn->fLookUpOffset[irot] - adcWaveform[irot]];
+ } else {
+ wave = 0;
+ for (j = 0; j < kBSplineOrder; j++) {
+ wave +=
+ chn->fData[irot][data->fBSplineOffsetLookUp[adcWaveform[irot]][chn->fLimitGroup[irot]] + j]
+ * data->fBSplineLookUp[adcWaveform[irot]][chn->fLimitGroup[irot]][j];
+ }
+ uWaveform[i] = static_cast < short >(wave);
+ }
+ // Offset Calibration
+ if (hasOffset)
+ uWaveform[i] -= offset;
+ } else {
+ irot = i;
+ if (triggerCell > -1)
+ irot = (triggerCell + i) % kNumberOfBins;
+#if 0 /* not enabled yet for DRS3 */
+ offset = offsetCalib ? chn->fOffset[irot] : 0;
+#else
+ offset = chn->fOffset[irot];
+#endif
+ v = static_cast < float >(adcWaveform[irot] - offset) / chn->fGain[irot];
+ uWaveform[i] = static_cast < short >(v * 1000 / GetPrecision() + 0.5);
+ }
+
+ // Check for Threshold
+ if (!aboveThreshold) {
+ if (uWaveform[i] >= threshold)
+ aboveThreshold = true;
+ }
+ }
+ return aboveThreshold;
+}
+
+/*------------------------------------------------------------------*/
+
+bool ResponseCalibration::SubtractADCOffset(unsigned int chipIndex, unsigned int channel,
+ unsigned short *adcWaveform,
+ unsigned short *adcCalibratedWaveform,
+ unsigned short newBaseLevel)
+{
+ int i;
+ unsigned int NumberOfCalibChannels;
+ CalibrationData *data = fCalibrationData[chipIndex];
+ CalibrationData::CalibrationDataChannel * chn;
+
+ if (fBoard->GetDRSType() == 3)
+ NumberOfCalibChannels = kNumberOfCalibChannelsV4;
+ else
+ NumberOfCalibChannels = kNumberOfCalibChannelsV3;
+
+ if (channel >= NumberOfCalibChannels || data == NULL)
+ return false;
+ if (!data->fRead || !data->fHasOffsetCalibration)
+ return false;
+
+ chn = data->fChannel[channel];
+ for (i = 0; i < kNumberOfBins; i++)
+ adcCalibratedWaveform[i] = adcWaveform[i] - chn->fOffsetADC[i] + newBaseLevel;
+ return true;
+}
+
+
+/*------------------------------------------------------------------*/
+
+bool ResponseCalibration::ReadCalibration(unsigned int chipIndex)
+{
+ if (fBoard->GetDRSType() == 3)
+ return ReadCalibrationV4(chipIndex);
+ else
+ return ReadCalibrationV3(chipIndex);
+}
+
+/*------------------------------------------------------------------*/
+
+bool ResponseCalibration::ReadCalibrationV3(unsigned int chipIndex)
+{
+ int k, l, m, num;
+ unsigned char ng;
+ short tempShort;
+ char fileName[2000];
+ FILE *fileHandle;
+ char calibDir[1000];
+
+ // Read Response Calibration
+ delete fCalibrationData[chipIndex];
+ fCalibrationData[chipIndex] = NULL;
+
+ fBoard->GetCalibrationDirectory(calibDir);
+ sprintf(fileName, "%s/board%d/ResponseCalib_board%d_chip%d_%dMHz.bin", calibDir,
+ fBoard->GetBoardSerialNumber(), fBoard->GetBoardSerialNumber(), chipIndex,
+ static_cast < int >(fBoard->GetNominalFrequency() * 1000));
+
+ fileHandle = fopen(fileName, "rb");
+ if (fileHandle == NULL) {
+ printf("Board %d --> Could not find response calibration file:\n", fBoard->GetBoardSerialNumber());
+ printf("%s\n", fileName);
+ return false;
+ }
+ // Number Of Grid Points
+ num = fread(&ng, 1, 1, fileHandle);
+ if (num != 1) {
+ printf("Error while reading response calibration file '%s'\n", fileName);
+ printf(" at 'NumberOfGridPoints'.\n");
+ return false;
+ }
+
+ fCalibrationData[chipIndex] = new CalibrationData(ng);
+ CalibrationData *data = fCalibrationData[chipIndex];
+ CalibrationData::CalibrationDataChannel * chn;
+ data->fRead = true;
+ data->fHasOffsetCalibration = 1;
+ data->DeletePreCalculatedBSpline();
+ fCalibrationValid[chipIndex] = true;
+
+ // Start Temperature
+ num = fread(&tempShort, 2, 1, fileHandle);
+ if (num != 1) {
+ printf("Error while reading response calibration file '%s'\n", fileName);
+ printf(" at 'StartTemperature'.\n");
+ return false;
+ }
+ data->fStartTemperature = static_cast < float >(tempShort) / 10;
+ // End Temperature
+ num = fread(&tempShort, 2, 1, fileHandle);
+ if (num != 1) {
+ printf("Error while reading response calibration file '%s'\n", fileName);
+ printf(" at 'EndTemperature'.\n");
+ return false;
+ }
+ data->fEndTemperature = static_cast < float >(tempShort) / 10;
+ if (fBoard->GetDRSType() != 3) {
+ // Min
+ num = fread(&data->fMin, 4, 1, fileHandle);
+ if (num != 1) {
+ printf("Error while reading response calibration file '%s'\n", fileName);
+ printf(" at 'Min'.\n");
+ return false;
+ }
+ // Max
+ num = fread(&data->fMax, 4, 1, fileHandle);
+ if (num != 1) {
+ printf("Error while reading response calibration file '%s'\n", fileName);
+ printf(" at 'Max'.\n");
+ return false;
+ }
+ // Number Of Limit Groups
+ num = fread(&data->fNumberOfLimitGroups, 1, 1, fileHandle);
+ if (num != 1) {
+ printf("Error while reading response calibration file '%s'\n", fileName);
+ printf(" at 'NumberOfLimitGroups'.\n");
+ return false;
+ }
+ }
+ // read channel
+ for (k = 0; k < kNumberOfCalibChannelsV3; k++) {
+ chn = data->fChannel[k];
+ for (l = 0; l < kNumberOfBins; l++) {
+ if (fBoard->GetDRSType() != 3) {
+ // Range Group
+ num = fread(&chn->fLimitGroup[l], 1, 1, fileHandle);
+ if (num != 1) {
+ printf("Error while reading response calibration file '%s'\n", fileName);
+ printf(" at 'RangeGroup' of channel %d bin %d.\n", k, l);
+ return false;
+ }
+ // Look Up Offset
+ num = fread(&chn->fLookUpOffset[l], 2, 1, fileHandle);
+ if (num != 1) {
+ printf("Error while reading response calibration file '%s'\n", fileName);
+ printf(" at 'LookUpOffset' of channel %d bin %d.\n", k, l);
+ return false;
+ }
+ // Number Of Look Up Points
+ num = fread(&chn->fNumberOfLookUpPoints[l], 1, 1, fileHandle);
+ if (num != 1) {
+ printf("Error while reading response calibration file '%s'\n", fileName);
+ printf(" at 'NumberOfLookUpPoints' of channel %d bin %d.\n", k, l);
+ return false;
+ }
+ // Look Up Points
+ delete chn->fLookUp[l];
+ chn->fLookUp[l] = new unsigned char[chn->fNumberOfLookUpPoints[l]];
+ for (m = 0; m < chn->fNumberOfLookUpPoints[l]; m++) {
+ num = fread(&chn->fLookUp[l][m], 1, 1, fileHandle);
+ if (num != 1) {
+ printf("Error while reading response calibration file '%s'\n", fileName);
+ printf(" at 'LookUp %d' of channel %d bin %d.\n", m, k, l);
+ return false;
+ }
+ }
+ // Points
+ for (m = 0; m < data->fNumberOfGridPoints; m++) {
+ num = fread(&chn->fData[l][m], 2, 1, fileHandle);
+ if (num != 1) {
+ printf("Error while reading response calibration file '%s'\n", fileName);
+ printf(" at 'Point %d' of channel %d bin %d.\n", m, k, l);
+ return false;
+ }
+ }
+ // ADC Offset
+ num = fread(&chn->fOffsetADC[l], 2, 1, fileHandle);
+ if (num != 1) {
+ printf("Error while reading response calibration file '%s'\n", fileName);
+ printf(" at 'ADC Offset' of channel %d bin %d.\n", k, l);
+ return false;
+ }
+ }
+ // Offset
+ num = fread(&chn->fOffset[l], 2, 1, fileHandle);
+ if (num != 1) {
+ printf("Error while reading response calibration file '%s'\n", fileName);
+ printf(" at 'Offset' of channel %d bin %d.\n", k, l);
+ return false;
+ }
+ if (fBoard->GetDRSType() == 3) {
+ // Gain
+ num = fread(&chn->fGain[l], 2, 1, fileHandle);
+ if (num != 1) {
+ printf("Error while reading response calibration file '%s'\n", fileName);
+ printf(" at 'Gain' of channel %d bin %d.\n", k, l);
+ return false;
+ }
+ }
+ }
+ }
+ fclose(fileHandle);
+
+ if (fBoard->GetDRSType() != 3) {
+ data->PreCalculateBSpline();
+ }
+
+ return true;
+}
+
+/*------------------------------------------------------------------*/
+
+bool ResponseCalibration::ReadCalibrationV4(unsigned int chipIndex)
+{
+ int k, l, num;
+ char fileName[2000];
+ FILE *fileHandle;
+ char calibDir[1000];
+
+ // Read Response Calibration
+
+ fBoard->GetCalibrationDirectory(calibDir);
+ sprintf(fileName, "%s/board%d/ResponseCalib_board%d_chip%d_%dMHz.bin", calibDir,
+ fBoard->GetBoardSerialNumber(), fBoard->GetBoardSerialNumber(), chipIndex,
+ static_cast < int >(fBoard->GetNominalFrequency() * 1000));
+
+ fileHandle = fopen(fileName, "rb");
+ if (fileHandle == NULL) {
+ printf("Board %d --> Could not find response calibration file:\n", fBoard->GetBoardSerialNumber());
+ printf("%s\n", fileName);
+ return false;
+ }
+
+ if (fInitialized)
+ delete fCalibrationData[chipIndex];
+ fCalibrationData[chipIndex] = new CalibrationData(1);
+ CalibrationData *data = fCalibrationData[chipIndex];
+ CalibrationData::CalibrationDataChannel * chn;
+ data->fRead = true;
+ data->fHasOffsetCalibration = 1;
+ fCalibrationValid[chipIndex] = true;
+ data->fStartTemperature = 0;
+ data->fEndTemperature = 0;
+
+ // read channel
+ for (k = 0; k < kNumberOfCalibChannelsV4; k++) {
+ chn = data->fChannel[k];
+ for (l = 0; l < kNumberOfBins; l++) {
+ // Offset
+ num = fread(&chn->fOffset[l], 2, 1, fileHandle);
+ if (num != 1) {
+ printf("Error while reading response calibration file '%s'\n", fileName);
+ printf(" at 'Offset' of channel %d bin %d.\n", k, l);
+ return false;
+ }
+ if (fBoard->GetDRSType() == 3) {
+ // Gain
+ num = fread(&chn->fGain[l], 2, 1, fileHandle);
+ if (num != 1) {
+ printf("Error while reading response calibration file '%s'\n", fileName);
+ printf(" at 'Gain' of channel %d bin %d.\n", k, l);
+ return false;
+ }
+ }
+ }
+ }
+
+ fclose(fileHandle);
+ return true;
+}
+
+/*------------------------------------------------------------------*/
+
+float ResponseCalibration::GetValue(float *coefficients, float u, int n)
+{
+ int j, ii;
+ float bsplines[4];
+ ii = CalibrationData::CalculateBSpline(n, u, bsplines);
+
+ float s = 0;
+ for (j = 0; j < kBSplineOrder; j++) {
+ s += coefficients[ii + j] * bsplines[j];
+ }
+ return s;
+}
+
+/*------------------------------------------------------------------*/
+
+int ResponseCalibration::Approx(float *p, float *uu, int np, int nu, float *coef)
+{
+ int i, iu, j;
+
+ const int mbloc = 50;
+ int ip = 0;
+ int ir = 0;
+ int mt = 0;
+ int ileft, irow;
+ float bu[kBSplineOrder];
+ float *matrix[kBSplineOrder + 2];
+ for (i = 0; i < kBSplineOrder + 2; i++)
+ matrix[i] = new float[mbloc + nu + 1];
+ for (iu = kBSplineOrder - 1; iu < nu; iu++) {
+ for (i = 0; i < np; i++) {
+ if (1 <= uu[i])
+ ileft = nu - 1;
+ else if (uu[i] < 0)
+ ileft = kBSplineOrder - 2;
+ else
+ ileft = kBSplineOrder - 1 + static_cast < int >(uu[i] * (nu - kBSplineOrder + 1));
+ if (ileft != iu)
+ continue;
+ irow = ir + mt;
+ mt++;
+ CalibrationData::CalculateBSpline(nu, uu[i], bu);
+ for (j = 0; j < kBSplineOrder; j++) {
+ matrix[j][irow] = bu[j];
+ }
+ matrix[kBSplineOrder][irow] = p[i];
+ if (mt < mbloc)
+ continue;
+ LeastSquaresAccumulation(matrix, kBSplineOrder, &ip, &ir, mt, iu - kBSplineOrder + 1);
+ mt = 0;
+ }
+ if (mt == 0)
+ continue;
+ LeastSquaresAccumulation(matrix, kBSplineOrder, &ip, &ir, mt, iu - kBSplineOrder + 1);
+ mt = 0;
+ }
+ if (!LeastSquaresSolving(matrix, kBSplineOrder, ip, ir, coef, nu)) {
+ for (i = 0; i < kBSplineOrder + 2; i++)
+ delete matrix[i];
+ return 0;
+ }
+
+ for (i = 0; i < kBSplineOrder + 2; i++)
+ delete matrix[i];
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+void ResponseCalibration::LeastSquaresAccumulation(float **matrix, int nb, int *ip, int *ir, int mt, int jt)
+{
+ int i, j, l, mu, k, kh;
+ float rho;
+
+ if (mt <= 0)
+ return;
+ if (jt != *ip) {
+ if (jt > (*ir)) {
+ for (i = 0; i < mt; i++) {
+ for (j = 0; j < nb + 1; j++) {
+ matrix[j][jt + mt - i] = matrix[j][(*ir) + mt - i];
+ }
+ }
+ for (i = 0; i < jt - (*ir); i++) {
+ for (j = 0; j < nb + 1; j++) {
+ matrix[j][(*ir) + i] = 0;
+ }
+ }
+ *ir = jt;
+ }
+ mu = min(nb - 1, (*ir) - (*ip) - 1);
+ if (mu != 0) {
+ for (l = 0; l < mu; l++) {
+ k = min(l + 1, jt - (*ip));
+ for (i = l + 1; i < nb; i++) {
+ matrix[i - k][(*ip) + l + 1] = matrix[i][(*ip) + l + 1];
+ }
+ for (i = 0; i < k; i++) {
+ matrix[nb - i - 1][(*ip) + l + 1] = 0;
+ }
+ }
+ }
+ *ip = jt;
+ }
+ kh = min(nb + 1, (*ir) + mt - (*ip));
+
+ for (i = 0; i < kh; i++) {
+ Housholder(i, max(i + 1, (*ir) - (*ip)), (*ir) + mt - (*ip), matrix, i, (*ip), &rho, matrix, i + 1,
+ (*ip), 1, nb - i);
+ }
+
+ *ir = (*ip) + kh;
+ if (kh < nb + 1)
+ return;
+ for (i = 0; i < nb; i++) {
+ matrix[i][(*ir) - 1] = 0;
+ }
+}
+
+/*------------------------------------------------------------------*/
+
+int ResponseCalibration::LeastSquaresSolving(float **matrix, int nb, int ip, int ir, float *x, int n)
+{
+ int i, j, l, ii;
+ float s, rsq;
+ for (j = 0; j < n; j++) {
+ x[j] = matrix[nb][j];
+ }
+ rsq = 0;
+ if (n <= ir - 1) {
+ for (j = n; j < ir; j++) {
+ rsq += pow(matrix[nb][j], 2);
+ }
+ }
+
+ for (ii = 0; ii < n; ii++) {
+ i = n - ii - 1;
+ s = 0;
+ l = max(0, i - ip);
+ if (i != n - 1) {
+ for (j = 1; j < min(n - i, nb); j++) {
+ s += matrix[j + l][i] * x[i + j];
+ }
+ }
+ if (matrix[l][i] == 0) {
+ printf("Error in LeastSquaresSolving.\n");
+ return 0;
+ }
+ x[i] = (x[i] - s) / matrix[l][i];
+ }
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+void ResponseCalibration::Housholder(int lpivot, int l1, int m, float **u, int iU1, int iU2, float *up,
+ float **c, int iC1, int iC2, int ice, int ncv)
+{
+ int i, j, incr;
+ float tol = static_cast < float >(1e-20);
+ float tolb = static_cast < float >(1e-24);
+ float cl, clinv, sm, b;
+
+ if (lpivot < 0 || lpivot >= l1 || l1 > m - 1)
+ return;
+ cl = fabs(u[iU1][iU2 + lpivot]);
+
+ // Construct the transformation
+ for (j = l1 - 1; j < m; j++)
+ cl = max(fabsf(u[iU1][iU2 + j]), cl);
+ if (cl < tol)
+ return;
+ clinv = 1 / cl;
+ sm = pow(u[iU1][iU2 + lpivot] * clinv, 2);
+ for (j = l1; j < m; j++) {
+ sm = sm + pow(u[iU1][iU2 + j] * clinv, 2);
+ }
+ cl *= sqrt(sm);
+ if (u[iU1][iU2 + lpivot] > 0)
+ cl = -cl;
+ *up = u[iU1][iU2 + lpivot] - cl;
+ u[iU1][iU2 + lpivot] = cl;
+
+ if (ncv <= 0)
+ return;
+ b = (*up) * u[iU1][iU2 + lpivot];
+ if (fabs(b) < tolb)
+ return;
+ if (b >= 0)
+ return;
+ b = 1 / b;
+ incr = ice * (l1 - lpivot);
+ for (j = 0; j < ncv; j++) {
+ sm = c[iC1 + j][iC2 + lpivot] * (*up);
+ for (i = l1; i < m; i++) {
+ sm = sm + c[iC1 + j][iC2 + lpivot + incr + (i - l1) * ice] * u[iU1][iU2 + i];
+ }
+ if (sm == 0)
+ continue;
+ sm *= b;
+ c[iC1 + j][iC2 + lpivot] = c[iC1 + j][iC2 + lpivot] + sm * (*up);
+ for (i = l1; i < m; i++) {
+ c[iC1 + j][iC2 + lpivot + incr + (i - l1) * ice] =
+ c[iC1 + j][iC2 + lpivot + incr + (i - l1) * ice] + sm * u[iU1][iU2 + i];
+ }
+ }
+}
+
+/*------------------------------------------------------------------*/
+
+int ResponseCalibration::MakeDir(const char *path)
+{
+ struct stat buf;
+ if (stat(path, &buf)) {
+#ifdef _MSC_VER
+ return mkdir(path);
+#else
+ return mkdir(path, 0711);
+#endif // R__UNIX
+ }
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+
+ResponseCalibration::ResponseCalibration(DRSBoard * board)
+: fBoard(board)
+ , fPrecision(0.1) // mV
+ , fInitialized(false)
+ , fRecorded(false)
+ , fFitted(false)
+ , fOffset(false)
+ , fNumberOfPointsLowVolt(0)
+ , fNumberOfPoints(0)
+ , fNumberOfMode2Bins(0)
+ , fNumberOfSamples(0)
+ , fNumberOfGridPoints(0)
+ , fNumberOfXConstPoints(0)
+ , fNumberOfXConstGridPoints(0)
+ , fTriggerFrequency(0)
+ , fShowStatistics(0)
+ , fCalibFile(0)
+ , fCurrentLowVoltPoint(0)
+ , fCurrentPoint(0)
+ , fCurrentSample(0)
+ , fCurrentFitChannel(0)
+ , fCurrentFitBin(0)
+ , fResponseY(0)
+ , fSamples(0)
+ , fSampleUsed(0)
+ , fXXFit(0)
+ , fYYFit(0)
+ , fWWFit(0)
+ , fYYFitRes(0)
+ , fYYSave(0)
+ , fXXSave(0)
+ , fStatisticsApprox(0)
+ , fStatisticsApproxExt(0)
+{
+ int i;
+ // Initializing the Calibration Class
+ CalibrationData::fIntRevers[0] = 0;
+ for (i = 1; i < 2 * kBSplineOrder - 2; i++) {
+ CalibrationData::fIntRevers[i] = static_cast < float >(1.) / i;
+ }
+ for (i = 0; i < kNumberOfChipsMax; i++) {
+ fCalibrationData[i] = NULL;
+ }
+ // Initializing the Calibration Creation
+ fCalibrationValid[0] = false;
+ fCalibrationValid[1] = false;
+}
+
+/*------------------------------------------------------------------*/
+
+ResponseCalibration::~ResponseCalibration()
+{
+ // Delete the Calibration
+ for (int i=0 ; i<kNumberOfChipsMax ; i++)
+ delete fCalibrationData[i];
+
+ // Deleting the Calibration Creation
+ DeleteFields();
+}
+
+/*------------------------------------------------------------------*/
+
+float ResponseCalibration::CalibrationData::fIntRevers[2 * kBSplineOrder - 2];
+ResponseCalibration::CalibrationData::CalibrationData(int numberOfGridPoints)
+:fRead(false)
+, fNumberOfGridPoints(numberOfGridPoints)
+, fHasOffsetCalibration(0)
+, fStartTemperature(0)
+, fEndTemperature(0)
+, fMin(0)
+, fMax(0)
+, fNumberOfLimitGroups(0)
+{
+ int i;
+ for (i = 0; i < kNumberOfCalibChannelsV3; i++) {
+ fChannel[i] = new CalibrationDataChannel(numberOfGridPoints);
+ }
+ for (i = 0; i < kNumberOfADCBins; i++) {
+ fBSplineOffsetLookUp[i] = NULL;
+ fBSplineLookUp[i] = NULL;
+ }
+};
+
+/*------------------------------------------------------------------*/
+
+void ResponseCalibration::CalibrationData::PreCalculateBSpline()
+{
+ int i, j;
+ float uu;
+ float xmin, xrange;
+ int nk = fNumberOfGridPoints - kBSplineOrder + 1;
+ for (i = 0; i < kNumberOfADCBins; i++) {
+ fBSplineLookUp[i] = new float *[fNumberOfLimitGroups];
+ fBSplineOffsetLookUp[i] = new int[fNumberOfLimitGroups];
+ for (j = 0; j < fNumberOfLimitGroups; j++) {
+ fBSplineLookUp[i][j] = new float[kBSplineOrder];
+ xmin = fMin + j * kBSplineXMinOffset;
+ xrange = fMax - xmin;
+ uu = (i - xmin) / xrange;
+ if (i < xmin) {
+ uu = 0;
+ }
+ if (i - xmin > xrange) {
+ uu = 1;
+ }
+ fBSplineOffsetLookUp[i][j] = static_cast < int >(uu * nk);
+ CalculateBSpline(fNumberOfGridPoints, uu, fBSplineLookUp[i][j]);
+ }
+ }
+}
+
+/*------------------------------------------------------------------*/
+
+void ResponseCalibration::CalibrationData::DeletePreCalculatedBSpline()
+{
+ int i, j;
+ for (i = 0; i < kNumberOfADCBins; i++) {
+ if (fBSplineLookUp[i] != NULL) {
+ for (j = 0; j < fNumberOfLimitGroups; j++)
+ delete fBSplineLookUp[i][j];
+ }
+ delete fBSplineLookUp[i];
+ delete fBSplineOffsetLookUp[i];
+ }
+}
+
+/*------------------------------------------------------------------*/
+
+ResponseCalibration::CalibrationData::~CalibrationData()
+{
+ int i, j;
+ for (i = 0; i < kNumberOfCalibChannelsV3; i++) {
+ delete fChannel[i];
+ }
+ for (i = 0; i < kNumberOfADCBins; i++) {
+ if (fBSplineLookUp[i] != NULL) {
+ for (j = 0; j < fNumberOfLimitGroups; j++) {
+ delete fBSplineLookUp[i][j];
+ }
+ }
+ delete fBSplineLookUp[i];
+ delete fBSplineOffsetLookUp[i];
+ }
+};
+
+/*------------------------------------------------------------------*/
+
+int ResponseCalibration::CalibrationData::CalculateBSpline(int nGrid, float value, float *bsplines)
+{
+ int minimum;
+ int maximum;
+ float xl;
+
+ int nk = nGrid - kBSplineOrder + 1;
+ float vl = value * nk;
+ int ivl = static_cast < int >(vl);
+
+ if (1 <= value) {
+ xl = vl - nk + 1;
+ minimum = 1 - nk;
+ } else if (value < 0) {
+ xl = vl;
+ minimum = 0;
+ } else {
+ xl = vl - ivl;
+ minimum = -ivl;
+ }
+ maximum = nk + minimum;
+
+// printf("xl = %f\n",xl);
+ float vm, vmprev;
+ int jl, ju;
+ int nb = 0;
+
+ bsplines[0] = 1;
+ for (int i = 0; i < kBSplineOrder - 1; i++) {
+ vmprev = 0;
+ for (int j = 0; j < nb + 1; j++) {
+ jl = max(minimum, j - nb);
+ ju = min(maximum, j + 1);
+ vm = bsplines[j] * fIntRevers[ju - jl];
+ bsplines[j] = vm * (ju - xl) + vmprev;
+ vmprev = vm * (xl - jl);
+ }
+ nb++;
+ bsplines[nb] = vmprev;
+ }
+ return -minimum;
+}
+
+/*------------------------------------------------------------------*/
+
+void ResponseCalibration::Average(int method, float *points, int numberOfPoints, float &mean, float &error,
+ float sigmaBoundary)
+{
+ // Methods :
+ // 0 : Average
+ // 1 : Average inside sigmaBoundary*sigma
+ int i;
+ float sum = 0;
+ float sumSquare = 0;
+
+ if (method == 0 || method == 1) {
+ for (i = 0; i < numberOfPoints; i++) {
+ sum += points[i];
+ sumSquare += points[i] * points[i];
+ }
+
+ mean = sum / numberOfPoints;
+ error = sqrt((sumSquare - sum * sum / numberOfPoints) / (numberOfPoints - 1));
+ }
+ if (method == 1) {
+ int numberOfGoodPoints = numberOfPoints;
+ bool found = true;
+ bool *goodSample = new bool[numberOfGoodPoints];
+ for (i = 0; i < numberOfGoodPoints; i++)
+ goodSample[i] = true;
+
+ while (found) {
+ found = false;
+ for (i = 0; i < numberOfPoints; i++) {
+ if (goodSample[i] && fabs(points[i] - mean) > sigmaBoundary * error) {
+ found = true;
+ goodSample[i] = false;
+ numberOfGoodPoints--;
+ sum -= points[i];
+ sumSquare -= points[i] * points[i];
+ mean = sum / numberOfGoodPoints;
+ error = sqrt((sumSquare - sum * sum / numberOfGoodPoints) / (numberOfGoodPoints - 1));
+ }
+ }
+ }
+ delete[] goodSample;
+ }
+}
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, "&lt;");
+ pd += 4;
+ break;
+ case '>':
+ strcpy(pd, "&gt;");
+ pd += 4;
+ break;
+ case '&':
+ strcpy(pd, "&amp;");
+ pd += 5;
+ break;
+ case '\"':
+ strcpy(pd, "&quot;");
+ pd += 6;
+ break;
+ case '\'':
+ strcpy(pd, "&apos;");
+ pd += 6;
+ break;
+ default:
+ *pd++ = *ps;
+ }
+ } else {
+ switch (*ps) { /* translate only illegal XML characters "<" and "&" */
+ case '<':
+ strcpy(pd, "&lt;");
+ pd += 4;
+ break;
+ case '&':
+ strcpy(pd, "&amp;");
+ pd += 5;
+ break;
+ default:
+ *pd++ = *ps;
+ }
+ }
+ }
+ *pd = 0;
+
+ strlcpy(src, _encode_buffer, size);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * reverse of mxml_encode, strip leading or trailing '"'
+ */
+void mxml_decode(char *str)
+{
+ char *p;
+
+ p = str;
+ while ((p = strchr(p, '&')) != NULL) {
+ if (strncmp(p, "&lt;", 4) == 0) {
+ *(p++) = '<';
+ memmove(p, p+3, strlen(p+3) + 1);
+ }
+ else if (strncmp(p, "&gt;", 4) == 0) {
+ *(p++) = '>';
+ memmove(p, p+3, strlen(p+3) + 1);
+ }
+ else if (strncmp(p, "&amp;", 5) == 0) {
+ *(p++) = '&';
+ memmove(p, p+4, strlen(p+4) + 1);
+ }
+ else if (strncmp(p, "&quot;", 6) == 0) {
+ *(p++) = '\"';
+ memmove(p, p+5, strlen(p+5) + 1);
+ }
+ else if (strncmp(p, "&apos;", 6) == 0) {
+ *(p++) = '\'';
+ memmove(p, p+5, strlen(p+5) + 1);
+ }
+ else {
+ p++; // skip unknown entity
+ }
+ }
+/* if (str[0] == '\"' && str[strlen(str)-1] == '\"') {
+ memmove(str, str+1, strlen(str+1) + 1);
+ str[strlen(str)-1] = 0;
+ }*/
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * set translation of <,>,",',&, on/off in writer
+ */
+int mxml_set_translate(MXML_WRITER *writer, int flag)
+{
+ int old_flag;
+
+ old_flag = writer->translate;
+ writer->translate = flag;
+ return old_flag;
+}
+/*------------------------------------------------------------------*/
+
+/**
+ * start a new XML element, must be followed by mxml_end_elemnt
+ */
+int mxml_start_element1(MXML_WRITER *writer, const char *name, int indent)
+{
+ int i;
+ char line[1000], name_enc[1000];
+
+ if (writer->element_is_open) {
+ mxml_write_line(writer, ">\n");
+ writer->element_is_open = FALSE;
+ }
+
+ line[0] = 0;
+ if (indent)
+ for (i=0 ; i<writer->level ; i++)
+ strlcat(line, XML_INDENT, sizeof(line));
+ strlcat(line, "<", sizeof(line));
+ strlcpy(name_enc, name, sizeof(name_enc));
+ mxml_encode(name_enc, sizeof(name_enc), writer->translate);
+ strlcat(line, name_enc, sizeof(line));
+
+ /* put element on stack */
+ if (writer->level == 0)
+ writer->stack = (char **)mxml_malloc(sizeof(char *));
+ else
+ writer->stack = (char **)mxml_realloc(writer->stack, sizeof(char *)*(writer->level+1));
+
+ writer->stack[writer->level] = (char *) mxml_malloc(strlen(name_enc)+1);
+ strcpy(writer->stack[writer->level], name_enc);
+ writer->level++;
+ writer->element_is_open = TRUE;
+ writer->data_was_written = FALSE;
+
+ return mxml_write_line(writer, line) == (int)strlen(line);
+}
+
+/*------------------------------------------------------------------*/
+
+int mxml_start_element(MXML_WRITER *writer, const char *name)
+{
+ return mxml_start_element1(writer, name, TRUE);
+}
+
+/*------------------------------------------------------------------*/
+
+int mxml_start_element_noindent(MXML_WRITER *writer, const char *name)
+{
+ return mxml_start_element1(writer, name, FALSE);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * close an open XML element
+ */
+int mxml_end_element(MXML_WRITER *writer)
+{
+ int i;
+ char line[1000];
+
+ if (writer->level == 0)
+ return 0;
+
+ writer->level--;
+
+ if (writer->element_is_open) {
+ writer->element_is_open = FALSE;
+ mxml_free(writer->stack[writer->level]);
+ if (writer->level == 0)
+ mxml_free(writer->stack);
+ strcpy(line, "/>\n");
+ return mxml_write_line(writer, line) == (int)strlen(line);
+ }
+
+ line[0] = 0;
+ if (!writer->data_was_written) {
+ for (i=0 ; i<writer->level ; i++)
+ strlcat(line, XML_INDENT, sizeof(line));
+ }
+
+ strlcat(line, "</", sizeof(line));
+ strlcat(line, writer->stack[writer->level], sizeof(line));
+ mxml_free(writer->stack[writer->level]);
+ if (writer->level == 0)
+ mxml_free(writer->stack);
+ strlcat(line, ">\n", sizeof(line));
+ writer->data_was_written = FALSE;
+
+ return mxml_write_line(writer, line) == (int)strlen(line);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * write an attribute to the currently open XML element
+ */
+int mxml_write_attribute(MXML_WRITER *writer, const char *name, const char *value)
+{
+ char name_enc[4096], val_enc[4096], line[8192];
+
+ if (!writer->element_is_open)
+ return FALSE;
+
+ strcpy(name_enc, name);
+ mxml_encode(name_enc, sizeof(name_enc), writer->translate);
+ strcpy(val_enc, value);
+ mxml_encode(val_enc, sizeof(val_enc), writer->translate);
+
+ sprintf(line, " %s=\"%s\"", name_enc, val_enc);
+
+ return mxml_write_line(writer, line) == (int)strlen(line);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * write value of an XML element, like <[name]>[value]</[name]>
+ */
+int mxml_write_value(MXML_WRITER *writer, const char *data)
+{
+ static int data_size = 0;
+
+ if (!writer->element_is_open)
+ return FALSE;
+
+ if (mxml_write_line(writer, ">") != 1)
+ return FALSE;
+ writer->element_is_open = FALSE;
+ writer->data_was_written = TRUE;
+
+ if (data_size == 0) {
+ _data_enc = (char *)mxml_malloc(1000);
+ data_size = 1000;
+ } else if ((int)strlen(data)*2+1000 > data_size) {
+ data_size = 1000+(int)strlen(data)*2;
+ _data_enc = (char *)mxml_realloc(_data_enc, data_size);
+ }
+
+ strcpy(_data_enc, data);
+ mxml_encode(_data_enc, data_size, writer->translate);
+ return mxml_write_line(writer, _data_enc) == (int)strlen(_data_enc);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * write empty line
+ */
+int mxml_write_empty_line(MXML_WRITER *writer)
+{
+ if (writer->element_is_open) {
+ mxml_write_line(writer, ">\n");
+ writer->element_is_open = FALSE;
+ }
+
+ if (mxml_write_line(writer, "\n") != 1)
+ return FALSE;
+
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * write a comment to an XML file, enclosed in "<!--" and "-->"
+ */
+int mxml_write_comment(MXML_WRITER *writer, const char *string)
+{
+ int i;
+ char line[1000];
+
+ if (writer->element_is_open) {
+ mxml_write_line(writer, ">\n");
+ writer->element_is_open = FALSE;
+ }
+
+ line[0] = 0;
+ for (i=0 ; i<writer->level ; i++)
+ strlcat(line, XML_INDENT, sizeof(line));
+
+ strlcat(line, "<!-- ", sizeof(line));
+ strlcat(line, string, sizeof(line));
+ strlcat(line, " -->\n", sizeof(line));
+ if (mxml_write_line(writer, line) != (int)strlen(line))
+ return FALSE;
+
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * shortcut to write an element with a value but without attribute
+ */
+int mxml_write_element(MXML_WRITER *writer, const char *name, const char *value)
+{
+ int i;
+
+ i = mxml_start_element(writer, name);
+ i += mxml_write_value(writer, value);
+ i += mxml_end_element(writer);
+ return i;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * close a file opened with mxml_open_writer
+ */
+char *mxml_close_buffer(MXML_WRITER *writer)
+{
+ int i;
+ char *p;
+
+ if (writer->element_is_open) {
+ writer->element_is_open = FALSE;
+ if (mxml_write_line(writer, ">\n") != 2)
+ return NULL;
+ }
+
+ /* close remaining open levels */
+ for (i = 0 ; i<writer->level ; i++)
+ mxml_end_element(writer);
+
+ p = writer->buffer;
+ mxml_free(writer);
+ return p;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * close a file opened with mxml_open_writer
+ */
+int mxml_close_file(MXML_WRITER *writer)
+{
+ int i;
+
+ if (writer->element_is_open) {
+ writer->element_is_open = FALSE;
+ if (mxml_write_line(writer, ">\n") != 2)
+ return 0;
+ }
+
+ /* close remaining open levels */
+ for (i = 0 ; i<writer->level ; i++)
+ mxml_end_element(writer);
+
+ close(writer->fh);
+ mxml_free(writer);
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * create root node of an XML tree
+ */
+PMXML_NODE mxml_create_root_node(void)
+{
+ PMXML_NODE root;
+
+ root = (PMXML_NODE)calloc(sizeof(MXML_NODE), 1);
+ strcpy(root->name, "root");
+ root->node_type = DOCUMENT_NODE;
+
+ return root;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * add a subnode (child) to an existing parent node as a specific position
+ */
+PMXML_NODE mxml_add_special_node_at(PMXML_NODE parent, int node_type, const char *node_name, const char *value, int idx)
+{
+ PMXML_NODE pnode, pchild;
+ int i, j;
+
+ assert(parent);
+ if (parent->n_children == 0)
+ parent->child = (PMXML_NODE)mxml_malloc(sizeof(MXML_NODE));
+ else
+ parent->child = (PMXML_NODE)mxml_realloc(parent->child, sizeof(MXML_NODE)*(parent->n_children+1));
+ assert(parent->child);
+
+ /* move following nodes one down */
+ if (idx < parent->n_children)
+ for (i=parent->n_children ; i > idx ; i--)
+ memcpy(&parent->child[i], &parent->child[i-1], sizeof(MXML_NODE));
+
+ /* correct parent pointer for children */
+ for (i=0 ; i<parent->n_children ; i++) {
+ pchild = parent->child+i;
+ for (j=0 ; j<pchild->n_children ; j++)
+ pchild->child[j].parent = pchild;
+ }
+
+ /* initialize new node */
+ pnode = &parent->child[idx];
+ memset(pnode, 0, sizeof(MXML_NODE));
+ strlcpy(pnode->name, node_name, sizeof(pnode->name));
+ pnode->node_type = node_type;
+ pnode->parent = parent;
+
+ parent->n_children++;
+
+ if (value && *value) {
+ pnode->value = (char *)mxml_malloc(strlen(value)+1);
+ assert(pnode->value);
+ strcpy(pnode->value, value);
+ }
+
+ return pnode;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * add a subnode (child) to an existing parent node at the end
+ */
+PMXML_NODE mxml_add_special_node(PMXML_NODE parent, int node_type, const char *node_name, const char *value)
+{
+ return mxml_add_special_node_at(parent, node_type, node_name, value, parent->n_children);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * write value of an XML element, like <[name]>[value]</[name]>
+ */
+PMXML_NODE mxml_add_node(PMXML_NODE parent, const char *node_name, const char *value)
+{
+ return mxml_add_special_node_at(parent, ELEMENT_NODE, node_name, value, parent->n_children);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * add a subnode (child) to an existing parent node at the end
+ */
+PMXML_NODE mxml_add_node_at(PMXML_NODE parent, const char *node_name, const char *value, int idx)
+{
+ return mxml_add_special_node_at(parent, ELEMENT_NODE, node_name, value, idx);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * add a whole node tree to an existing parent node at a specific position
+ */
+int mxml_add_tree_at(PMXML_NODE parent, PMXML_NODE tree, int idx)
+{
+ PMXML_NODE pchild;
+ int i, j, k;
+
+ assert(parent);
+ assert(tree);
+ if (parent->n_children == 0)
+ parent->child = (PMXML_NODE)mxml_malloc(sizeof(MXML_NODE));
+ else {
+ pchild = parent->child;
+ parent->child = (PMXML_NODE)mxml_realloc(parent->child, sizeof(MXML_NODE)*(parent->n_children+1));
+
+ if (parent->child != pchild) {
+ /* correct parent pointer for children */
+ for (i=0 ; i<parent->n_children ; i++) {
+ pchild = parent->child+i;
+ for (j=0 ; j<pchild->n_children ; j++)
+ pchild->child[j].parent = pchild;
+ }
+ }
+ }
+ assert(parent->child);
+
+ if (idx < parent->n_children)
+ for (i=parent->n_children ; i > idx ; i--) {
+ /* move following nodes one down */
+ memcpy(&parent->child[i], &parent->child[i-1], sizeof(MXML_NODE));
+
+ /* correct parent pointer for children */
+ for (j=0 ; j<parent->n_children ; j++) {
+ pchild = parent->child+j;
+ for (k=0 ; k<pchild->n_children ; k++)
+ pchild->child[k].parent = pchild;
+ }
+ }
+
+ /* initialize new node */
+ memcpy(parent->child+idx, tree, sizeof(MXML_NODE));
+ parent->n_children++;
+ parent->child[idx].parent = parent;
+
+ /* correct parent pointer for children */
+ for (i=0 ; i<parent->n_children ; i++) {
+ pchild = parent->child+i;
+ for (j=0 ; j<pchild->n_children ; j++)
+ pchild->child[j].parent = pchild;
+ }
+
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * add a whole node tree to an existing parent node at the end
+ */
+int mxml_add_tree(PMXML_NODE parent, PMXML_NODE tree)
+{
+ return mxml_add_tree_at(parent, tree, parent->n_children);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * add an attribute to an existing node
+ */
+int mxml_add_attribute(PMXML_NODE pnode, const char *attrib_name, const char *attrib_value)
+{
+ if (pnode->n_attributes == 0) {
+ pnode->attribute_name = (char*)mxml_malloc(MXML_NAME_LENGTH);
+ pnode->attribute_value = (char**)mxml_malloc(sizeof(char *));
+ } else {
+ pnode->attribute_name = (char*)mxml_realloc(pnode->attribute_name, MXML_NAME_LENGTH*(pnode->n_attributes+1));
+ pnode->attribute_value = (char**)mxml_realloc(pnode->attribute_value, sizeof(char *)*(pnode->n_attributes+1));
+ }
+
+ strlcpy(pnode->attribute_name+pnode->n_attributes*MXML_NAME_LENGTH, attrib_name, MXML_NAME_LENGTH);
+ pnode->attribute_value[pnode->n_attributes] = (char *)mxml_malloc(strlen(attrib_value)+1);
+ strcpy(pnode->attribute_value[pnode->n_attributes], attrib_value);
+ pnode->n_attributes++;
+
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * return number of subnodes (children) of a node
+ */
+int mxml_get_number_of_children(PMXML_NODE pnode)
+{
+ assert(pnode);
+ return pnode->n_children;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * return number of subnodes (children) of a node
+ */
+PMXML_NODE mxml_subnode(PMXML_NODE pnode, int idx)
+{
+ assert(pnode);
+ if (idx < pnode->n_children)
+ return &pnode->child[idx];
+ return NULL;
+}
+
+/*------------------------------------------------------------------*/
+
+
+int mxml_find_nodes1(PMXML_NODE tree, const char *xml_path, PMXML_NODE **nodelist, int *found);
+
+int mxml_add_resultnode(PMXML_NODE node, const char *xml_path, PMXML_NODE **nodelist, int *found)
+{
+ /* if at end of path, add this node */
+ if (*xml_path == 0) {
+ if (*found == 0)
+ *nodelist = (PMXML_NODE *)mxml_malloc(sizeof(PMXML_NODE));
+ else
+ *nodelist = (PMXML_NODE *)mxml_realloc(*nodelist, sizeof(PMXML_NODE)*(*found + 1));
+
+ (*nodelist)[*found] = node;
+ (*found)++;
+ } else {
+ /* if not at end of path, branch into subtree */
+ return mxml_find_nodes1(node, xml_path+1, nodelist, found);
+ }
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ Return list of XML nodes with a subset of XPATH specifications.
+ Following elemets are possible
+
+ /<node>/<node>/..../<node> Find a node in the tree hierarchy
+ /<node>[idx] Find child #[idx] of node (index starts from 1)
+ /<node>[idx]/<node> Find subnode of the above
+ /<node>[<subnode>=<value>] Find a node which has a specific subnode
+ /<node>[<subnode>=<value>]/<node> Find subnode of the above
+ /<node>[@<attrib>=<value>]/<node> Find a node which has a specific attribute
+*/
+int mxml_find_nodes1(PMXML_NODE tree, const char *xml_path, PMXML_NODE **nodelist, int *found)
+{
+ PMXML_NODE pnode;
+ const char *p1,*p2;
+ char *p3, node_name[256], condition[256];
+ char cond_name[MXML_MAX_CONDITION][256], cond_value[MXML_MAX_CONDITION][256];
+ int cond_type[MXML_MAX_CONDITION];
+ int i, j, k, idx, num_cond;
+ int cond_satisfied,cond_index;
+ size_t len;
+
+ p1 = xml_path;
+ pnode = tree;
+
+ /* skip leading '/' */
+ if (*p1 && *p1 == '/')
+ p1++;
+
+ do {
+ p2 = p1;
+ while (*p2 && *p2 != '/' && *p2 != '[')
+ p2++;
+ len = (size_t)p2 - (size_t)p1;
+ if (len >= sizeof(node_name))
+ return 0;
+
+ memcpy(node_name, p1, len);
+ node_name[len] = 0;
+ idx = 0;
+ num_cond = 0;
+ while (*p2 == '[') {
+ cond_name[num_cond][0] = cond_value[num_cond][0] = cond_type[num_cond] = 0;
+ p2++;
+ if (isdigit(*p2)) {
+ /* evaluate [idx] */
+ idx = atoi(p2);
+ p2 = strchr(p2, ']');
+ if (p2 == NULL)
+ return 0;
+ p2++;
+ } else {
+ /* evaluate [<@attrib>/<subnode>=<value>] */
+ while (*p2 && isspace((unsigned char)*p2))
+ p2++;
+ strlcpy(condition, p2, sizeof(condition));
+ if (strchr(condition, ']'))
+ *strchr(condition, ']') = 0;
+ else
+ return 0;
+ p2 = strchr(p2, ']')+1;
+ if ((p3 = strchr(condition, '=')) != NULL) {
+ if (condition[0] == '@') {
+ cond_type[num_cond] = 1;
+ strlcpy(cond_name[num_cond], &condition[1], sizeof(cond_name[num_cond]));
+ } else {
+ strlcpy(cond_name[num_cond], condition, sizeof(cond_name[num_cond]));
+ }
+
+ *strchr(cond_name[num_cond], '=') = 0;
+ while (cond_name[num_cond][0] && isspace(cond_name[num_cond][strlen(cond_name[num_cond])-1]))
+ cond_name[num_cond][strlen(cond_name[num_cond])-1] = 0;
+
+ p3++;
+ while (*p3 && isspace(*p3))
+ p3++;
+ if (*p3 == '\"') {
+ strlcpy(cond_value[num_cond], p3+1, sizeof(cond_value[num_cond]));
+ while (cond_value[num_cond][0] && isspace(cond_value[num_cond][strlen(cond_value[num_cond])-1]))
+ cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0;
+ if (cond_value[num_cond][0] && cond_value[num_cond][strlen(cond_value[num_cond])-1] == '\"')
+ cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0;
+ } else if (*p3 == '\'') {
+ strlcpy(cond_value[num_cond], p3+1, sizeof(cond_value[num_cond]));
+ while (cond_value[num_cond][0] && isspace(cond_value[num_cond][strlen(cond_value[num_cond])-1]))
+ cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0;
+ if (cond_value[num_cond][0] && cond_value[num_cond][strlen(cond_value[num_cond])-1] == '\'')
+ cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0;
+ } else {
+ strlcpy(cond_value[num_cond], p3, sizeof(cond_value[num_cond]));
+ while (cond_value[num_cond][0] && isspace(cond_value[num_cond][strlen(cond_value[num_cond])-1]))
+ cond_value[num_cond][strlen(cond_value[num_cond])-1] = 0;
+ }
+ num_cond++;
+ }
+ }
+ }
+
+ cond_index = 0;
+ for (i=j=0 ; i<pnode->n_children ; i++) {
+ if (num_cond) {
+ cond_satisfied = 0;
+ for (k=0;k<num_cond;k++) {
+ if (cond_type[k]) {
+ /* search node with attribute */
+ if (strcmp(pnode->child[i].name, node_name) == 0)
+ if (mxml_get_attribute(pnode->child+i, cond_name[k]) &&
+ strcmp(mxml_get_attribute(pnode->child+i, cond_name[k]), cond_value[k]) == 0)
+ cond_satisfied++;
+ }
+ else {
+ /* search subnode */
+ for (j=0 ; j<pnode->child[i].n_children ; j++)
+ if (strcmp(pnode->child[i].child[j].name, cond_name[k]) == 0)
+ if (strcmp(pnode->child[i].child[j].value, cond_value[k]) == 0)
+ cond_satisfied++;
+ }
+ }
+ if (cond_satisfied==num_cond) {
+ cond_index++;
+ if (idx == 0 || cond_index == idx) {
+ if (!mxml_add_resultnode(pnode->child+i, p2, nodelist, found))
+ return 0;
+ }
+ }
+ } else {
+ if (strcmp(pnode->child[i].name, node_name) == 0)
+ if (idx == 0 || ++j == idx)
+ if (!mxml_add_resultnode(pnode->child+i, p2, nodelist, found))
+ return 0;
+ }
+ }
+
+ if (i == pnode->n_children)
+ return 1;
+
+ pnode = &pnode->child[i];
+ p1 = p2;
+ if (*p1 == '/')
+ p1++;
+
+ } while (*p2);
+
+ return 1;
+}
+
+/*------------------------------------------------------------------*/
+
+int mxml_find_nodes(PMXML_NODE tree, const char *xml_path, PMXML_NODE **nodelist)
+{
+ int status, found = 0;
+
+ status = mxml_find_nodes1(tree, xml_path, nodelist, &found);
+
+ if (status == 0)
+ return -1;
+
+ return found;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * Search for a specific XML node with a subset of XPATH specifications.
+ * Return first found node. For syntax see mxml_find_nodes()
+ */
+PMXML_NODE mxml_find_node(PMXML_NODE tree, const char *xml_path)
+{
+ PMXML_NODE *node, pnode;
+ int n;
+
+ n = mxml_find_nodes(tree, xml_path, &node);
+ if (n > 0) {
+ pnode = node[0];
+ mxml_free(node);
+ } else
+ pnode = NULL;
+
+ return pnode;
+}
+
+/*------------------------------------------------------------------*/
+
+PMXML_NODE mxml_get_parent(PMXML_NODE pnode)
+{
+ assert(pnode);
+ return pnode->parent;
+}
+
+/*------------------------------------------------------------------*/
+
+char *mxml_get_name(PMXML_NODE pnode)
+{
+ assert(pnode);
+ return pnode->name;
+}
+
+/*------------------------------------------------------------------*/
+
+char *mxml_get_value(PMXML_NODE pnode)
+{
+ assert(pnode);
+ return pnode->value;
+}
+
+/*------------------------------------------------------------------*/
+
+int mxml_get_line_number_start(PMXML_NODE pnode)
+{
+ assert(pnode);
+ return pnode->line_number_start;
+}
+
+/*------------------------------------------------------------------*/
+
+int mxml_get_line_number_end(PMXML_NODE pnode)
+{
+ assert(pnode);
+ return pnode->line_number_end;
+}
+
+/*------------------------------------------------------------------*/
+
+char *mxml_get_attribute(PMXML_NODE pnode, const char *name)
+{
+ int i;
+
+ assert(pnode);
+ for (i=0 ; i<pnode->n_attributes ; i++)
+ if (strcmp(pnode->attribute_name+i*MXML_NAME_LENGTH, name) == 0)
+ return pnode->attribute_value[i];
+
+ return NULL;
+}
+
+/*------------------------------------------------------------------*/
+
+int mxml_replace_node_name(PMXML_NODE pnode, const char *name)
+{
+ strlcpy(pnode->name, name, sizeof(pnode->name));
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+int mxml_replace_node_value(PMXML_NODE pnode, const char *value)
+{
+ if (pnode->value)
+ pnode->value = (char *)mxml_realloc(pnode->value, strlen(value)+1);
+ else if (value)
+ pnode->value = (char *)mxml_malloc(strlen(value)+1);
+ else
+ pnode->value = NULL;
+
+ if (value)
+ strcpy(pnode->value, value);
+
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ replace value os a subnode, like
+
+ <parent>
+ <child>value</child>
+ </parent>
+
+ if pnode=parent, and "name"="child", then "value" gets replaced
+*/
+int mxml_replace_subvalue(PMXML_NODE pnode, const char *name, const char *value)
+{
+ int i;
+
+ for (i=0 ; i<pnode->n_children ; i++)
+ if (strcmp(pnode->child[i].name, name) == 0)
+ break;
+
+ if (i == pnode->n_children)
+ return FALSE;
+
+ return mxml_replace_node_value(&pnode->child[i], value);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * change the name of an attribute, keep its value
+ */
+int mxml_replace_attribute_name(PMXML_NODE pnode, const char *old_name, const char *new_name)
+{
+ int i;
+
+ for (i=0 ; i<pnode->n_attributes ; i++)
+ if (strcmp(pnode->attribute_name+i*MXML_NAME_LENGTH, old_name) == 0)
+ break;
+
+ if (i == pnode->n_attributes)
+ return FALSE;
+
+ strlcpy(pnode->attribute_name+i*MXML_NAME_LENGTH, new_name, MXML_NAME_LENGTH);
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * change the value of an attribute
+ */
+int mxml_replace_attribute_value(PMXML_NODE pnode, const char *attrib_name, const char *attrib_value)
+{
+ int i;
+
+ for (i=0 ; i<pnode->n_attributes ; i++)
+ if (strcmp(pnode->attribute_name+i*MXML_NAME_LENGTH, attrib_name) == 0)
+ break;
+
+ if (i == pnode->n_attributes)
+ return FALSE;
+
+ pnode->attribute_value[i] = (char *)mxml_realloc(pnode->attribute_value[i], strlen(attrib_value)+1);
+ strcpy(pnode->attribute_value[i], attrib_value);
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * free memory of a node and remove it from the parent's child list
+ */
+int mxml_delete_node(PMXML_NODE pnode)
+{
+ PMXML_NODE parent;
+ int i, j;
+
+ /* remove node from parent's list */
+ parent = pnode->parent;
+
+ if (parent) {
+ for (i=0 ; i<parent->n_children ; i++)
+ if (&parent->child[i] == pnode)
+ break;
+
+ /* free allocated node memory recursively */
+ mxml_free_tree(pnode);
+
+ if (i < parent->n_children) {
+ for (j=i ; j<parent->n_children-1 ; j++)
+ memcpy(&parent->child[j], &parent->child[j+1], sizeof(MXML_NODE));
+ parent->n_children--;
+ if (parent->n_children)
+ parent->child = (PMXML_NODE)mxml_realloc(parent->child, sizeof(MXML_NODE)*(parent->n_children));
+ else
+ mxml_free(parent->child);
+ }
+ } else
+ mxml_free_tree(pnode);
+
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+int mxml_delete_attribute(PMXML_NODE pnode, const char *attrib_name)
+{
+ int i, j;
+
+ for (i=0 ; i<pnode->n_attributes ; i++)
+ if (strcmp(pnode->attribute_name+i*MXML_NAME_LENGTH, attrib_name) == 0)
+ break;
+
+ if (i == pnode->n_attributes)
+ return FALSE;
+
+ mxml_free(pnode->attribute_value[i]);
+ for (j=i ; j<pnode->n_attributes-1 ; j++) {
+ strcpy(pnode->attribute_name+j*MXML_NAME_LENGTH, pnode->attribute_name+(j+1)*MXML_NAME_LENGTH);
+ pnode->attribute_value[j] = pnode->attribute_value[j+1];
+ }
+
+ if (pnode->n_attributes > 0) {
+ pnode->attribute_name = (char *)mxml_realloc(pnode->attribute_name, MXML_NAME_LENGTH*(pnode->n_attributes-1));
+ pnode->attribute_value = (char **)mxml_realloc(pnode->attribute_value, sizeof(char *)*(pnode->n_attributes-1));
+ } else {
+ mxml_free(pnode->attribute_name);
+ mxml_free(pnode->attribute_value);
+ }
+
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+#define HERE root, file_name, line_number, error, error_size, error_line
+
+/**
+ * used inside mxml_parse_file for reporting errors
+ */
+PMXML_NODE read_error(PMXML_NODE root, const char *file_name, int line_number, char *error, int error_size, int *error_line, const char *format, ...)
+{
+ char *msg, str[1000];
+ va_list argptr;
+
+ if (file_name && file_name[0])
+ sprintf(str, "XML read error in file \"%s\", line %d: ", file_name, line_number);
+ else
+ sprintf(str, "XML read error, line %d: ", line_number);
+ msg = (char *)mxml_malloc(error_size);
+ if (error)
+ strlcpy(error, str, error_size);
+
+ va_start(argptr, format);
+ vsprintf(str, (char *) format, argptr);
+ va_end(argptr);
+
+ if (error)
+ strlcat(error, str, error_size);
+ if (error_line)
+ *error_line = line_number;
+
+ mxml_free(msg);
+ mxml_free_tree(root);
+
+ return NULL;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * Parse a XML buffer and convert it into a tree of MXML_NODE's.
+ * Return NULL in case of an error, return error description.
+ * Optional file_name is used for error reporting if called from mxml_parse_file()
+ */
+PMXML_NODE mxml_parse_buffer(const char *buf, char *error, int error_size, int *error_line)
+{
+ char node_name[256], attrib_name[256], attrib_value[1000], quote;
+ const char *p, *pv;
+ int i,j, line_number;
+ PMXML_NODE root, ptree, pnew;
+ int end_element;
+ size_t len;
+ char *file_name = NULL; /* dummy for 'HERE' */
+
+ p = buf;
+ line_number = 1;
+
+ root = mxml_create_root_node();
+ ptree = root;
+
+ /* parse file contents */
+ do {
+ if (*p == '<') {
+
+ end_element = FALSE;
+
+ /* found new element */
+ p++;
+ while (*p && isspace(*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p)
+ return read_error(HERE, "Unexpected end of file");
+
+ if (strncmp(p, "!--", 3) == 0) {
+
+ /* found comment */
+
+ pnew = mxml_add_special_node(ptree, COMMENT_NODE, "Comment", NULL);
+ pnew->line_number_start = line_number;
+ pv = p+3;
+ while (*pv == ' ')
+ pv++;
+
+ p += 3;
+ if (strstr(p, "-->") == NULL)
+ return read_error(HERE, "Unterminated comment");
+
+ while (strncmp(p, "-->", 3) != 0) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+
+ len = (size_t)p - (size_t)pv;
+ pnew->value = (char *)mxml_malloc(len+1);
+ memcpy(pnew->value, pv, len);
+ pnew->value[len] = 0;
+ pnew->line_number_end = line_number;
+ mxml_decode(pnew->value);
+
+ p += 3;
+
+ } else if (*p == '?') {
+
+ /* found ?...? element */
+ pnew = mxml_add_special_node(ptree, PROCESSING_INSTRUCTION_NODE, "PI", NULL);
+ pnew->line_number_start = line_number;
+ pv = p+1;
+
+ p++;
+ if (strstr(p, "?>") == NULL)
+ return read_error(HERE, "Unterminated ?...? element");
+
+ while (strncmp(p, "?>", 2) != 0) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+
+ len = (size_t)p - (size_t)pv;
+ pnew->value = (char *)mxml_malloc(len+1);
+ memcpy(pnew->value, pv, len);
+ pnew->value[len] = 0;
+ pnew->line_number_end = line_number;
+ mxml_decode(pnew->value);
+
+ p += 2;
+
+ } else if (strncmp(p, "!DOCTYPE", 8) == 0 ) {
+
+ /* found !DOCTYPE element , skip it */
+ p += 8;
+ if (strstr(p, ">") == NULL)
+ return read_error(HERE, "Unterminated !DOCTYPE element");
+
+ j = 0;
+ while (*p && (*p != '>' || j > 0)) {
+ if (*p == '\n')
+ line_number++;
+ else if (*p == '<')
+ j++;
+ else if (*p == '>')
+ j--;
+ p++;
+ }
+ if (!*p)
+ return read_error(HERE, "Unexpected end of file");
+
+ p++;
+
+ } else {
+
+ /* found normal element */
+ if (*p == '/') {
+ end_element = TRUE;
+ p++;
+ while (*p && isspace((unsigned char)*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p)
+ return read_error(HERE, "Unexpected end of file");
+ }
+
+ /* extract node name */
+ i = 0;
+ node_name[i] = 0;
+ while (*p && !isspace((unsigned char)*p) && *p != '/' && *p != '>' && *p != '<')
+ node_name[i++] = *p++;
+ node_name[i] = 0;
+ if (!*p)
+ return read_error(HERE, "Unexpected end of file");
+ if (*p == '<')
+ return read_error(HERE, "Unexpected \'<\' inside element \"%s\"", node_name);
+
+ mxml_decode(node_name);
+
+ if (end_element) {
+
+ if (!ptree)
+ return read_error(HERE, "Found unexpected </%s>", node_name);
+
+ /* close previously opened element */
+ if (strcmp(ptree->name, node_name) != 0)
+ return read_error(HERE, "Found </%s>, expected </%s>", node_name, ptree->name);
+ ptree->line_number_end = line_number;
+
+ /* go up one level on the tree */
+ ptree = ptree->parent;
+
+ } else {
+
+ if (ptree == NULL)
+ return read_error(HERE, "Unexpected second top level node");
+
+ /* allocate new element structure in parent tree */
+ pnew = mxml_add_node(ptree, node_name, NULL);
+ pnew->line_number_start = line_number;
+ pnew->line_number_end = line_number;
+
+ while (*p && isspace((unsigned char)*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p)
+ return read_error(HERE, "Unexpected end of file");
+
+ while (*p != '>' && *p != '/') {
+
+ /* found attribute */
+ pv = p;
+ while (*pv && !isspace((unsigned char)*pv) && *pv != '=' && *pv != '<' && *pv != '>')
+ pv++;
+ if (!*pv)
+ return read_error(HERE, "Unexpected end of file");
+ if (*pv == '<' || *pv == '>')
+ return read_error(HERE, "Unexpected \'%c\' inside element \"%s\"", *pv, node_name);
+
+ /* extract attribute name */
+ len = (size_t)pv - (size_t)p;
+ if (len > sizeof(attrib_name)-1)
+ len = sizeof(attrib_name)-1;
+ memcpy(attrib_name, p, len);
+ attrib_name[len] = 0;
+ mxml_decode(attrib_name);
+
+ p = pv;
+ while (*p && isspace((unsigned char)*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p)
+ return read_error(HERE, "Unexpected end of file");
+ if (*p != '=')
+ return read_error(HERE, "Expect \"=\" here");
+
+ p++;
+ while (*p && isspace((unsigned char)*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p)
+ return read_error(HERE, "Unexpected end of file");
+ if (*p != '\"' && *p != '\'')
+ return read_error(HERE, "Expect \" or \' here");
+ quote = *p;
+ p++;
+
+ /* extract attribute value */
+ pv = p;
+ while (*pv && *pv != quote)
+ pv++;
+ if (!*pv)
+ return read_error(HERE, "Unexpected end of file");
+
+ len = (size_t)pv - (size_t)p;
+ if (len > sizeof(attrib_value)-1)
+ len = sizeof(attrib_value)-1;
+ memcpy(attrib_value, p, len);
+ attrib_value[len] = 0;
+ mxml_decode(attrib_value);
+
+ /* add attribute to current node */
+ mxml_add_attribute(pnew, attrib_name, attrib_value);
+
+ p = pv+1;
+ while (*p && isspace((unsigned char)*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p)
+ return read_error(HERE, "Unexpected end of file");
+ }
+
+ if (*p == '/') {
+
+ /* found empty node, like <node/>, just skip closing bracket */
+ p++;
+
+ while (*p && isspace((unsigned char)*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p)
+ return read_error(HERE, "Unexpected end of file");
+ if (*p != '>')
+ return read_error(HERE, "Expected \">\" after \"/\"");
+ p++;
+ }
+
+ if (*p == '>') {
+
+ p++;
+
+ /* check if we have sub-element or value */
+ pv = p;
+ while (*pv && isspace((unsigned char)*pv)) {
+ if (*pv == '\n')
+ line_number++;
+ pv++;
+ }
+ if (!*pv)
+ return read_error(HERE, "Unexpected end of file");
+
+ if (*pv == '<' && *(pv+1) != '/') {
+
+ /* start new subtree */
+ ptree = pnew;
+ p = pv;
+
+ } else {
+
+ /* extract value */
+ while (*pv && *pv != '<') {
+ if (*pv == '\n')
+ line_number++;
+ pv++;
+ }
+ if (!*pv)
+ return read_error(HERE, "Unexpected end of file");
+
+ len = (size_t)pv - (size_t)p;
+ pnew->value = (char *)mxml_malloc(len+1);
+ memcpy(pnew->value, p, len);
+ pnew->value[len] = 0;
+ mxml_decode(pnew->value);
+ p = pv;
+
+ ptree = pnew;
+ }
+ }
+ }
+ }
+ }
+
+ /* go to next element */
+ while (*p && *p != '<') {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ } while (*p);
+
+ return root;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * parse !ENTYTY entries of XML files and replace with references.
+ * Return 0 in case of no errors, return error description.
+ * Optional file_name is used for error reporting if called from mxml_parse_file()
+ */
+int mxml_parse_entity(char **buf, const char *file_name, char *error, int error_size, int *error_line)
+{
+ char *p;
+ char *pv;
+ char delimiter;
+ int i, j, k, line_number, status;
+ char *replacement;
+ char entity_name[MXML_MAX_ENTITY][256];
+ char entity_reference_name[MXML_MAX_ENTITY][256];
+ char *entity_value[MXML_MAX_ENTITY];
+ int entity_type[MXML_MAX_ENTITY]; /* internal or external */
+ int entity_line_number[MXML_MAX_ENTITY];
+ int nentity;
+ int fh, length, len;
+ char *buffer;
+ int ip; /* counter for entity value */
+ char directoryname[FILENAME_MAX];
+ char filename[FILENAME_MAX];
+ int entity_value_length[MXML_MAX_ENTITY];
+ int entity_name_length[MXML_MAX_ENTITY];
+
+ PMXML_NODE root = mxml_create_root_node(); /* dummy for 'HERE' */
+
+ for (ip = 0; ip < MXML_MAX_ENTITY; ip++)
+ entity_value[ip] = NULL;
+
+ line_number = 1;
+ nentity = -1;
+ status = 0;
+
+ if (!buf || !(*buf) || !strlen(*buf))
+ return 0;
+
+ strcpy(directoryname, file_name);
+ mxml_dirname(directoryname);
+
+ /* copy string to temporary space */
+ buffer = (char *) mxml_malloc(strlen(*buf) + 1);
+ if (buffer == NULL) {
+ read_error(HERE, "Cannot allocate memory.");
+ status = 1;
+ goto error;
+ }
+ strcpy(buffer, *buf);
+
+ p = strstr(buffer, "!DOCTYPE");
+ if (p == NULL) { /* no entities */
+ status = 0;
+ goto error;
+ }
+
+ pv = strstr(p, "[");
+ if (pv == NULL) { /* no entities */
+ status = 1;
+ goto error;
+ }
+
+ p = pv + 1;
+
+ /* search !ENTITY */
+ do {
+ if (*p == ']')
+ break;
+
+ if (*p == '<') {
+
+ /* found new entity */
+ p++;
+ while (*p && isspace((unsigned char)*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p) {
+ read_error(HERE, "Unexpected end of file");
+ status = 1;
+ goto error;
+ }
+
+ if (strncmp(p, "!--", 3) == 0) {
+ /* found comment */
+ p += 3;
+ if (strstr(p, "-->") == NULL) {
+ read_error(HERE, "Unterminated comment");
+ status = 1;
+ goto error;
+ }
+
+ while (strncmp(p, "-->", 3) != 0) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ p += 3;
+ }
+
+ else if (strncmp(p, "!ENTITY", 7) == 0) {
+ /* found entity */
+ nentity++;
+ if (nentity >= MXML_MAX_ENTITY) {
+ read_error(HERE, "Too much entities");
+ status = 1;
+ goto error;
+ }
+
+ entity_line_number[nentity] = line_number;
+
+ pv = p + 7;
+ while (*pv == ' ')
+ pv++;
+
+ /* extract entity name */
+ p = pv;
+
+ while (*p && isspace((unsigned char)*p) && *p != '<' && *p != '>') {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p) {
+ read_error(HERE, "Unexpected end of file");
+ status = 1;
+ goto error;
+ }
+ if (*p == '<' || *p == '>') {
+ read_error(HERE, "Unexpected \'%c\' inside !ENTITY", *p);
+ status = 1;
+ goto error;
+ }
+
+ pv = p;
+ while (*pv && !isspace((unsigned char)*pv) && *pv != '<' && *pv != '>')
+ pv++;
+
+ if (!*pv) {
+ read_error(HERE, "Unexpected end of file");
+ status = 1;
+ goto error;
+ }
+ if (*pv == '<' || *pv == '>') {
+ read_error(HERE, "Unexpected \'%c\' inside entity \"%s\"", *pv, &entity_name[nentity][1]);
+ status = 1;
+ goto error;
+ }
+
+ entity_name[nentity][0] = '&';
+ i = 1;
+ entity_name[nentity][i] = 0;
+ while (*p && !isspace((unsigned char)*p) && *p != '/' && *p != '>' && *p != '<' && i < 253)
+ entity_name[nentity][i++] = *p++;
+ entity_name[nentity][i++] = ';';
+ entity_name[nentity][i] = 0;
+
+ if (!*p) {
+ read_error(HERE, "Unexpected end of file");
+ status = 1;
+ goto error;
+ }
+ if (*p == '<') {
+ read_error(HERE, "Unexpected \'<\' inside entity \"%s\"", &entity_name[nentity][1]);
+ status = 1;
+ goto error;
+ }
+
+ /* extract replacement or SYSTEM */
+ while (*p && isspace((unsigned char)*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p) {
+ read_error(HERE, "Unexpected end of file");
+ status = 1;
+ goto error;
+ }
+ if (*p == '>') {
+ read_error(HERE, "Unexpected \'>\' inside entity \"%s\"", &entity_name[nentity][1]);
+ status = 1;
+ goto error;
+ }
+
+ /* check if SYSTEM */
+ if (strncmp(p, "SYSTEM", 6) == 0) {
+ entity_type[nentity] = EXTERNAL_ENTITY;
+ p += 6;
+ } else {
+ entity_type[nentity] = INTERNAL_ENTITY;
+ }
+
+ /* extract replacement */
+ while (*p && isspace((unsigned char)*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p) {
+ read_error(HERE, "Unexpected end of file");
+ status = 1;
+ goto error;
+ }
+ if (*p == '>') {
+ read_error(HERE, "Unexpected \'>\' inside entity \"%s\"", &entity_name[nentity][1]);
+ status = 1;
+ goto error;
+ }
+
+ if (*p != '\"' && *p != '\'') {
+ read_error(HERE, "Replacement was not found for entity \"%s\"", &entity_name[nentity][1]);
+ status = 1;
+ goto error;
+ }
+ delimiter = *p;
+ p++;
+ if (!*p) {
+ read_error(HERE, "Unexpected end of file");
+ status = 1;
+ goto error;
+ }
+ pv = p;
+ while (*pv && *pv != delimiter)
+ pv++;
+
+ if (!*pv) {
+ read_error(HERE, "Unexpected end of file");
+ status = 1;
+ goto error;
+ }
+ if (*pv == '<') {
+ read_error(HERE, "Unexpected \'%c\' inside entity \"%s\"", *pv, &entity_name[nentity][1]);
+ status = 1;
+ goto error;
+ }
+
+ len = (int)((size_t) pv - (size_t) p);
+ replacement = (char *) mxml_malloc(len + 1);
+ if (replacement == NULL) {
+ read_error(HERE, "Cannot allocate memory.");
+ status = 1;
+ goto error;
+ }
+
+ memcpy(replacement, p, len);
+ replacement[len] = 0;
+ mxml_decode(replacement);
+
+ if (entity_type[nentity] == EXTERNAL_ENTITY) {
+ strcpy(entity_reference_name[nentity], replacement);
+ } else {
+ entity_value[nentity] = (char *) mxml_malloc(strlen(replacement));
+ if (entity_value[nentity] == NULL) {
+ read_error(HERE, "Cannot allocate memory.");
+ status = 1;
+ goto error;
+ }
+ strcpy(entity_value[nentity], replacement);
+ }
+ mxml_free(replacement);
+
+ p = pv;
+ while (*p && isspace((unsigned char)*p)) {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ if (!*p) {
+ read_error(HERE, "Unexpected end of file");
+ status = 1;
+ goto error;
+ }
+ }
+ }
+
+ /* go to next element */
+ while (*p && *p != '<') {
+ if (*p == '\n')
+ line_number++;
+ p++;
+ }
+ } while (*p);
+ nentity++;
+
+ /* read external file */
+ for (i = 0; i < nentity; i++) {
+ if (entity_type[i] == EXTERNAL_ENTITY) {
+ if ( entity_reference_name[i][0] == DIR_SEPARATOR ) /* absolute path */
+ strcpy(filename, entity_reference_name[i]);
+ else /* relative path */
+ sprintf(filename, "%s%c%s", directoryname, DIR_SEPARATOR, entity_reference_name[i]);
+ fh = open(filename, O_RDONLY | O_TEXT, 0644);
+
+ if (fh == -1) {
+ line_number = entity_line_number[i];
+ read_error(HERE, "%s is missing", entity_reference_name[i]);
+ status = 1;
+ goto error;
+ } else {
+ length = (int)lseek(fh, 0, SEEK_END);
+ lseek(fh, 0, SEEK_SET);
+ if (length == 0) {
+ entity_value[i] = (char *) mxml_malloc(1);
+ if (entity_value[i] == NULL) {
+ read_error(HERE, "Cannot allocate memory.");
+ close(fh);
+ status = 1;
+ goto error;
+ }
+ entity_value[i][0] = 0;
+ } else {
+ entity_value[i] = (char *) mxml_malloc(length);
+ if (entity_value[i] == NULL) {
+ read_error(HERE, "Cannot allocate memory.");
+ close(fh);
+ status = 1;
+ goto error;
+ }
+
+ /* read complete file at once */
+ length = (int)read(fh, entity_value[i], length);
+ entity_value[i][length - 1] = 0;
+ close(fh);
+
+ /* recursive parse */
+ if (mxml_parse_entity(&entity_value[i], filename, error, error_size, error_line) != 0) {
+ status = 1;
+ goto error;
+ }
+ }
+ }
+ }
+ }
+
+ /* count length of output string */
+ length = (int)strlen(buffer);
+ for (i = 0; i < nentity; i++) {
+ p = buffer;
+ entity_value_length[i] = (int)strlen(entity_value[i]);
+ entity_name_length[i] = (int)strlen(entity_name[i]);
+ while (1) {
+ pv = strstr(p, entity_name[i]);
+ if (pv) {
+ length += entity_value_length[i] - entity_name_length[i];
+ p = pv + 1;
+ } else {
+ break;
+ }
+ }
+ }
+
+ /* re-allocate memory */
+ *buf = (char *) mxml_realloc(*buf, length + 1);
+ if (*buf == NULL) {
+ read_error(HERE, "Cannot allocate memory.");
+ status = 1;
+ goto error;
+ }
+
+ /* replace entities */
+ p = buffer;
+ pv = *buf;
+ do {
+ if (*p == '&') {
+ /* found entity */
+ for (j = 0; j < nentity; j++) {
+ if (strncmp(p, entity_name[j], entity_name_length[j]) == 0) {
+ for (k = 0; k < (int) entity_value_length[j]; k++)
+ *pv++ = entity_value[j][k];
+ p += entity_name_length[j];
+ break;
+ }
+ }
+ }
+ *pv++ = *p++;
+ } while (*p);
+ *pv = 0;
+
+error:
+
+ if (buffer != NULL)
+ mxml_free(buffer);
+ for (ip = 0; ip < MXML_MAX_ENTITY; ip++)
+ if (entity_value[ip] != NULL)
+ mxml_free(entity_value[ip]);
+
+ return status;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * parse a XML file and convert it into a tree of MXML_NODE's.
+ * Return NULL in case of an error, return error description
+ */
+PMXML_NODE mxml_parse_file(const char *file_name, char *error, int error_size, int *error_line)
+{
+ char *buf, line[1000];
+ int fh, length;
+ PMXML_NODE root;
+
+ if (error)
+ error[0] = 0;
+
+ fh = open(file_name, O_RDONLY | O_TEXT, 0644);
+
+ if (fh == -1) {
+ sprintf(line, "Unable to open file \"%s\": ", file_name);
+ strlcat(line, strerror(errno), sizeof(line));
+ strlcpy(error, line, error_size);
+ return NULL;
+ }
+
+ length = (int)lseek(fh, 0, SEEK_END);
+ lseek(fh, 0, SEEK_SET);
+ buf = (char *)mxml_malloc(length+1);
+ if (buf == NULL) {
+ close(fh);
+ sprintf(line, "Cannot allocate buffer: ");
+ strlcat(line, strerror(errno), sizeof(line));
+ strlcpy(error, line, error_size);
+ return NULL;
+ }
+
+ /* read complete file at once */
+ length = (int)read(fh, buf, length);
+ buf[length] = 0;
+ close(fh);
+
+ if (mxml_parse_entity(&buf, file_name, error, error_size, error_line) != 0) {
+ mxml_free(buf);
+ return NULL;
+ }
+
+ root = mxml_parse_buffer(buf, error, error_size, error_line);
+
+ mxml_free(buf);
+
+ return root;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * write complete subtree recursively into file opened with mxml_open_document()
+ */
+int mxml_write_subtree(MXML_WRITER *writer, PMXML_NODE tree, int indent)
+{
+ int i;
+
+ mxml_start_element1(writer, tree->name, indent);
+ for (i=0 ; i<tree->n_attributes ; i++)
+ if (!mxml_write_attribute(writer, tree->attribute_name+i*MXML_NAME_LENGTH, tree->attribute_value[i]))
+ return FALSE;
+
+ if (tree->value)
+ if (!mxml_write_value(writer, tree->value))
+ return FALSE;
+
+ for (i=0 ; i<tree->n_children ; i++)
+ if (!mxml_write_subtree(writer, &tree->child[i], (tree->value == NULL) || i > 0))
+ return FALSE;
+
+ return mxml_end_element(writer);
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * write a complete XML tree to a file
+ */
+int mxml_write_tree(const char *file_name, PMXML_NODE tree)
+{
+ MXML_WRITER *writer;
+ int i;
+
+ assert(tree);
+ writer = mxml_open_file(file_name);
+ if (!writer)
+ return FALSE;
+
+ for (i=0 ; i<tree->n_children ; i++)
+ if (tree->child[i].node_type == ELEMENT_NODE) /* skip PI and comments */
+ if (!mxml_write_subtree(writer, &tree->child[i], TRUE))
+ return FALSE;
+
+ if (!mxml_close_file(writer))
+ return FALSE;
+
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+
+PMXML_NODE mxml_clone_tree(PMXML_NODE tree)
+{
+ PMXML_NODE clone;
+ int i;
+
+ clone = (PMXML_NODE)calloc(sizeof(MXML_NODE), 1);
+
+ /* copy name, node_type, n_attributes and n_children */
+ memcpy(clone, tree, sizeof(MXML_NODE));
+
+ clone->value = NULL;
+ mxml_replace_node_value(clone, tree->value);
+
+ clone->attribute_name = NULL;
+ clone->attribute_value = NULL;
+ for (i=0 ; i<tree->n_attributes ; i++)
+ mxml_add_attribute(clone, tree->attribute_name+i*MXML_NAME_LENGTH, tree->attribute_value[i]);
+
+ clone->child = NULL;
+ clone->n_children = 0;
+ for (i=0 ; i<tree->n_children ; i++)
+ mxml_add_tree(clone, mxml_clone_tree(mxml_subnode(tree, i)));
+
+ return clone;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * print XML tree for debugging
+ */
+void mxml_debug_tree(PMXML_NODE tree, int level)
+{
+ int i, j;
+
+ for (i=0 ; i<level ; i++)
+ printf(" ");
+ printf("Name: %s\n", tree->name);
+ for (i=0 ; i<level ; i++)
+ printf(" ");
+ printf("Valu: %s\n", tree->value);
+ for (i=0 ; i<level ; i++)
+ printf(" ");
+ printf("Type: %d\n", tree->node_type);
+ for (i=0 ; i<level ; i++)
+ printf(" ");
+ printf("Lin1: %d\n", tree->line_number_start);
+ for (i=0 ; i<level ; i++)
+ printf(" ");
+ printf("Lin2: %d\n", tree->line_number_end);
+
+ for (j=0 ; j<tree->n_attributes ; j++) {
+ for (i=0 ; i<level ; i++)
+ printf(" ");
+ printf("%s: %s\n", tree->attribute_name+j*MXML_NAME_LENGTH,
+ tree->attribute_value[j]);
+ }
+
+ for (i=0 ; i<level ; i++)
+ printf(" ");
+ printf("Addr: %08zX\n", (size_t)tree);
+ for (i=0 ; i<level ; i++)
+ printf(" ");
+ printf("Prnt: %08zX\n", (size_t)tree->parent);
+ for (i=0 ; i<level ; i++)
+ printf(" ");
+ printf("NCld: %d\n", tree->n_children);
+
+ for (i=0 ; i<tree->n_children ; i++)
+ mxml_debug_tree(tree->child+i, level+1);
+
+ if (level == 0)
+ printf("\n");
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * free memory of XML tree, must be called after any
+ * mxml_create_root_node() or mxml_parse_file()
+ */
+void mxml_free_tree(PMXML_NODE tree)
+{
+ int i;
+
+ /* first free children recursively */
+ for (i=0 ; i<tree->n_children ; i++)
+ mxml_free_tree(&tree->child[i]);
+ if (tree->n_children)
+ mxml_free(tree->child);
+
+ /* now free dynamic data */
+ for (i=0 ; i<tree->n_attributes ; i++)
+ mxml_free(tree->attribute_value[i]);
+
+ if (tree->n_attributes) {
+ mxml_free(tree->attribute_name);
+ mxml_free(tree->attribute_value);
+ }
+
+ if (tree->value)
+ mxml_free(tree->value);
+
+ /* if we are the root node, free it */
+ if (tree->parent == NULL)
+ mxml_free(tree);
+}
+
+/*------------------------------------------------------------------*/
+
+/*
+void mxml_test()
+{
+ char err[256];
+ PMXML_NODE tree, tree2, node;
+
+ tree = mxml_parse_file("c:\\tmp\\test.xml", err, sizeof(err));
+ tree2 = mxml_clone_tree(tree);
+
+ printf("Orig:\n");
+ mxml_debug_tree(tree, 0);
+
+ printf("\nClone:\n");
+ mxml_debug_tree(tree2, 0);
+
+ printf("\nCombined:\n");
+ node = mxml_find_node(tree2, "cddb");
+ mxml_add_tree(tree, node);
+ mxml_debug_tree(tree, 0);
+
+ mxml_free_tree(tree);
+}
+*/
+
+/*------------------------------------------------------------------*/
+ /**
+ mxml_basename deletes any prefix ending with the last slash '/' character
+ present in path. mxml_dirname deletes the filename portion, beginning with
+ the last slash '/' character to the end of path. Followings are examples
+ from these functions
+
+ path dirname basename
+ "/" "/" ""
+ "." "." "."
+ "" "" ""
+ "/test.txt" "/" "test.txt"
+ "path/to/test.txt" "path/to" "test.txt"
+ "test.txt "." "test.txt"
+
+ Under Windows, '\\' and ':' are recognized ad separator too.
+ */
+
+void mxml_basename(char *path)
+{
+ char str[FILENAME_MAX];
+ char *p;
+ char *name;
+
+ if (path) {
+ strcpy(str, path);
+ p = str;
+ name = str;
+ while (1) {
+ if (*p == 0)
+ break;
+ if (*p == '/'
+#ifdef _MSC_VER
+ || *p == ':' || *p == '\\'
+#endif
+ )
+ name = p + 1;
+ p++;
+ }
+ strcpy(path, name);
+ }
+
+ return;
+}
+
+void mxml_dirname(char *path)
+{
+ char *p;
+#ifdef _MSC_VER
+ char *pv;
+#endif
+
+ if (!path || strlen(path) == 0)
+ return;
+
+ p = strrchr(path, '/');
+#ifdef _MSC_VER
+ pv = strrchr(path, ':');
+ if (pv > p)
+ p = pv;
+ pv = strrchr(path, '\\');
+ if (pv > p)
+ p = pv;
+#endif
+
+ if (p == 0) /* current directory */
+ strcpy(path, ".");
+ else if (p == path) /* root directory */
+ sprintf(path, "%c", *p);
+ else
+ *p = 0;
+
+ return;
+}
+
+/*------------------------------------------------------------------*/
+
+/**
+ * Retieve node at a certain line number
+ */
+PMXML_NODE mxml_get_node_at_line(PMXML_NODE tree, int line_number)
+{
+ int i;
+ PMXML_NODE pn;
+
+ if (tree->line_number_start == line_number)
+ return tree;
+
+ for (i=0 ; i<tree->n_children ; i++) {
+ pn = mxml_get_node_at_line(&tree->child[i], line_number);
+ if (pn)
+ return pn;
+ }
+
+ return NULL;
+}
+
Index: instr/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
+
+