Subversion Repositories f9daq

Rev

Blame | Last modification | View Log | RSS feed

// NativeExportsConsumerApp.cpp : Defines the entry point for the console application.
//
#include <utility.h>
#include <stdlib.h>
#include <stdio.h>
#include "AitMduManager.h"
#include "AitMduManager_DEF.h"

//Unhandled Exception: System.Runtime.InteropServices.MarshalDirectiveException:
//Cannot marshal 'return value': Invalid managed/unmanaged type combination.
#ifdef _CVI_
#include <ansi_c.h>

#define AddMessageI(x) AddMessage("%s %d\n", #x, x);
#define AddMessageF(x) AddMessage("%s %f\n", #x, x);
#define AddMessageX(x) AddMessage("%s 0x%x\n", #x, x);
#define AddMessageS(x) AddMessage("%s %s\n", #x, x);  

int sprintf_s(const char *dest, int len, const char *format, ...) {
        va_list aptr;
        int ret;


        va_start(aptr, format);
        ret = vsnprintf(dest, len, format, aptr);
        va_end(aptr);
        return(ret);
}


#endif

typedef unsigned short ushort;
typedef unsigned int uint;
#ifdef __cplusplus
extern "C"
{
#endif
        __declspec(dllimport) void NE_Rainbow();
#ifdef __cplusplus
}
#endif

#ifndef _CVI_

#ifdef _DEBUG
#pragma comment(lib, "../NativeExports/bin/Debug/NativeExports.lib")
#else
#pragma comment(lib, "../NativeExports/bin/Release/NativeExports.lib")
#endif

#endif

                //private MduManager SD4;
                uint deviceId = 0;
        int deviceIndex = -1;
        int adcBufferLen;
        ushort *adcBuffer;
        int histograms[4][0xFFF];
        int histogramtotal[0xFFF * 4];

        int histogramTotalEvents = 0;

        const double MONADC_SCALE = 65535.0;     // 16-bit monitor ADC
        const double DAC_SCALE = 65535.0;      // 16-bit DAC
        const double MONADC_VRANGE = 2.5;      // 2.5V ADC voltage range
        const double DISCR_OFFSETRANGE = 250.0;    // +/- 250mV discriminator offset range
        const double DISCR_THRESHOLDRANGE = 1000.0;  // 0-1000mV discriminator threshold range
        const double HV_IRANGE = 5.0;        // 0-5.0mA HV current monitor range
        const double HV_VRANGE = 80.0;       // 0-80V HV voltage control range
        const int INTEGRATOR_LSB = 10;       // 10ns integrator time resolution
        const double RAMPRATESCALE = 61036.0;    // Ramp rate register setting = (rate in V/s) / RAMPRATESCALE
        const char statusNoDevice[0xFF] = "No Device Connected";
        const char statusReconfig[0xFF] = "Reconfiguring Device ... ";
        const char statusReset[0xFF] = "Resetting Device ... ";
        const char statusReconnect[0xFF] = "Reconnecting Device ... ";
        const char statusDone[0xFF] = "Done";


        const int CHANNELS = 4;      // 4-Channel DAQ
        const int ADCMAX = 4096;   // 12-bit ADC

        bool addTimeStamp = false;    // updated by ReadRegisters
        bool addEventCount = false;   // updated by ReadRegisters
        bool addChannelNum = false;   // updated by ReadRegisters

        int TIMESTAMP_LSB = 10;     // 10ns time stamp resolution



        void Sleep(int musec) {
      Delay(musec/1000.);
        }

        /*
                void AddMessage( const char * message)
                {
                  printf("%s\n", message);
                }
                */


        int AddMessage(const char *format, ...) {
                va_list aptr;
                int ret;

                char strbuf[0xFF];

                va_start(aptr, format);
                ret = vsprintf(strbuf, format, aptr);
                va_end(aptr);
                //  SetCtrlVal(p1h,P1_STDIO,strbuf);

                printf("%s", strbuf);

                return(ret);
        }


        //----------------------------------------
        // Utilities
        //----------------------------------------
        ushort SetBit(ushort data, int bitIndex, bool bitValue) {
                if (bitValue == true)
                        return (ushort)(data | (1 << bitIndex));
                else
                        return (ushort)(data & ~(1 << bitIndex));
        }

        bool GetBit(int data, int bitIndex) {
                return (data & (1 << bitIndex)) != 0;
        }

        ushort ReadSD4Register(int reg) {
                return SD4_Read(deviceId, reg);
        }

        uint ReadSD4Register32(int addrHi, int addrLo) {
                uint dataHi = (uint)SD4_Read(deviceId, addrHi);
                uint dataLo = (uint)SD4_Read(deviceId, addrLo);
                return (dataHi << 16) | dataLo;
        }

        void WriteSD4Register(int address, ushort data) {
                SD4_Write(deviceId, address, data);
        }

        void WriteSD4Register32(int addrHi, int addrLo, uint data) {
                WriteSD4Register(addrHi, (ushort)(data >> 16));
                WriteSD4Register(addrLo, (ushort)data);
        }


        void ReadModifyWrite(int reg, int bitIndex, bool bitValue) {
                ushort regData = ReadSD4Register(reg);
                regData = SetBit(regData, bitIndex, bitValue);
                WriteSD4Register(reg, regData);
        }

        double LimitSetting(double value, double min, double max) {
                double limited = value;
                if (limited > max) limited = max;
                if (limited < min) limited = min;
                return limited;
        }



        int ReadAdcBuffer()
{
        //if (adcBuffer == NULL)
        //      return -1;
        int bytes = 0;
        //printf("In\n%d\n%d\n%d\n", deviceId, ADDR_BUFFER, adcBufferLen);
        adcBuffer = SD4_ReadUShortArray(deviceId, ADDR_BUFFER, adcBufferLen, &bytes);
        return bytes/2;
}
int ReadAdcByteBuffer()
{
        if (adcBuffer == NULL)
                return -1;
        int bytes = 0;
        char * byteBuffer = SD4_ReadByteArray(deviceId, ADDR_BUFFER, adcBufferLen * 2, &bytes);
        int byteIndex = 0;
        int words = bytes / 2;
        ushort dataword = 0;
        for (int i = 0; i < words; i++)
        {
                dataword = (ushort)(byteBuffer[byteIndex++] << 8);
                adcBuffer[i] = (ushort)(dataword | byteBuffer[byteIndex++]);
        }
        return words;
}





        //----------------------------------------
        // Monitor ADC
        //----------------------------------------

        double GetVoltage(int reg) {
                return ReadSD4Register(reg) * MONADC_VRANGE / MONADC_SCALE;
        }

        double GetDetectorTemperature() {
                // Temperature = 500mV + 1mV per degree C
                return (GetVoltage(ADDR_BASE_TEMPERATURE) - 0.5) / 0.01;
        }

        double GetHvVoltage(int reg) {
                return GetVoltage(reg) / MONADC_VRANGE * HV_VRANGE;
        }

        double GetHvCurrentInUa() {
                // 2.5V ADC input voltage = 5000 microamps
                return GetVoltage(ADDR_HV_IMON) * 2000.0;
        }

        double GetVoltage75(int reg) {
                // 2.5V ADC input voltage = 7.5V monitor voltage
                return GetVoltage(reg) * 3.0;
        }



        //----------------------------------------
        // Discriminator, Sum
        //----------------------------------------

        void SetSumGain(int gain) {
                ushort csrDetector = ReadSD4Register(ADDR_CSR_DETECTOR);
                bool g1 = GetBit(gain, 0);
                bool g2 = GetBit(gain, 1);
                bool g3 = GetBit(gain, 2);
                bool g4 = GetBit(gain, 3);
                csrDetector = SetBit(csrDetector, BIT_CSR_DET_SUMGAIN1, g1);
                csrDetector = SetBit(csrDetector, BIT_CSR_DET_SUMGAIN2, g2);
                csrDetector = SetBit(csrDetector, BIT_CSR_DET_SUMGAIN3, g3);
                csrDetector = SetBit(csrDetector, BIT_CSR_DET_SUMGAIN4, g4);
                WriteSD4Register(ADDR_CSR_DETECTOR, (ushort)csrDetector);
        }

        void SetSumCoupling(bool acCoupling) {
                ReadModifyWrite(ADDR_CSR_DETECTOR, BIT_CSR_DET_SUMCOUPLING, acCoupling);
        }

        void SetThreshold(double thresholdInMillivolts) {
                thresholdInMillivolts = LimitSetting(thresholdInMillivolts, -DISCR_THRESHOLDRANGE, DISCR_THRESHOLDRANGE);
                WriteSD4Register(ADDR_DISCR_THRESHOLD, (ushort)(thresholdInMillivolts * DAC_SCALE / DISCR_THRESHOLDRANGE));
        }

        double GetThreshold() {
                return ReadSD4Register(ADDR_DISCR_THRESHOLD) / DAC_SCALE * DISCR_THRESHOLDRANGE;
        }

        double GetSumOffsetInMv() {
                // Sum offsets are with respect to the positive sum output polarity.
                return (ReadSD4Register(ADDR_DISCR_OFFSET) / DAC_SCALE * (DISCR_OFFSETRANGE * 2)) - DISCR_OFFSETRANGE;
        }

        void SetSumOffset(double milliVolts) {
                // Sum offsets are with respect to the positive sum output polarity.
                // Actual output offset is multiplied by the selectable gain stage.
                WriteSD4Register(ADDR_DISCR_OFFSET, (ushort)((milliVolts + DISCR_OFFSETRANGE) * DAC_SCALE / (DISCR_OFFSETRANGE * 2)));
        }



        //----------------------------------------
        // Trigger
        //----------------------------------------

        void SetTriggerInterval(int triggerInterval) {
                WriteSD4Register32(ADDR_TG_INTERVALHI, ADDR_TG_INTERVALLO, (uint)(triggerInterval / INTEGRATOR_LSB));
        }

        void SetTriggerBurst(int triggerBurst) {
                WriteSD4Register32(ADDR_TG_COUNTHI, ADDR_TG_COUNTLO, (uint)triggerBurst);
        }

        void EnableTrigger(int bitIndex) {
                WriteSD4Register(ADDR_CSR_TRIGGER, SetBit(0, bitIndex, true));
        }

        void DisableTriggers() {
                WriteSD4Register(ADDR_CSR_TRIGGER, 0);
        }

        void SetDeadTime(int deadTimeInNs) {
                WriteSD4Register(ADDR_DEADTIME, (ushort)(deadTimeInNs / INTEGRATOR_LSB));
        }



        //----------------------------------------
        // Integrators, ADCs
        //----------------------------------------

        void SetIntegrationTime(int integrationTime) {
                WriteSD4Register(ADDR_ITIME, (ushort)(integrationTime / INTEGRATOR_LSB));
        }

        int GetIntegrationTime() {
                return ReadSD4Register(ADDR_ITIME) * INTEGRATOR_LSB;
        }

        void SetAdcCoupling(bool acCoupling) {
                ReadModifyWrite(ADDR_CSR_DETECTOR, BIT_CSR_DET_ADCCOUPLING, acCoupling);
        }

        void ResetAdc(bool reset) {
                ushort cmd = 0;
                cmd = SetBit(cmd, BIT_CSR_MAIN_ADCRESET, reset);
                WriteSD4Register(ADDR_CSR_MAIN, cmd);
        }

        double GetAdcOffsetInMv(int reg) {
                // ADC offset polarity is with respect to the positive ADC polarity (integrator output), not the main negative input signal polarity.
                // Actual output offset is multiplied by the selectable gain stage.
                return DISCR_OFFSETRANGE - (ReadSD4Register(reg) / DAC_SCALE * (DISCR_OFFSETRANGE * 2));
        }

        void SetAdcOffset(int reg, double milliVolts) {
                // ADC offset polarity is with respect to the positive ADC polarity (integrator output), not the main negative input signal polarity.
                // Actual output offset is multiplied by the selectable gain stage.
                WriteSD4Register(reg, (ushort)((DISCR_OFFSETRANGE - milliVolts) * DAC_SCALE / (DISCR_OFFSETRANGE * 2)));
        }



        //----------------------------------------
        // Event ID
        //----------------------------------------

        void AddEventCount(bool addEventCount) {
                ReadModifyWrite(ADDR_EVENTID, BIT_EVENTID_COUNT, addEventCount);
        }

        void AddTimeStamp(bool addTimeStamp) {
                ReadModifyWrite(ADDR_EVENTID, BIT_EVENTID_TIME, addTimeStamp);
        }

        void AddChannelNumber(bool addChannelNumber) {
                ReadModifyWrite(ADDR_EVENTID, BIT_EVENTID_CHNUM, addChannelNumber);
        }



        //----------------------------------------
        // Detector VA
        //----------------------------------------

        void SetDetectorVaOn(bool on) {
                ReadModifyWrite(ADDR_CSR_DETECTOR, BIT_CSR_DET_VAENABLE, on);
        }

        void SetDetectorVaHiRange(bool range) {
                ReadModifyWrite(ADDR_CSR_DETECTOR, BIT_CSR_DET_VAHIRNG, range);
        }



        //----------------------------------------
        // High Voltage
        //----------------------------------------

        void SetHvCurrentLimit(double milliamps) {
                milliamps = LimitSetting(milliamps, 0, HV_IRANGE);
                WriteSD4Register(ADDR_HV_ILIMIT, (ushort)(milliamps * DAC_SCALE / HV_IRANGE));
        }

        void SetHvVoltage(int reg, double volts) {
                volts = LimitSetting(volts, 0, HV_VRANGE);
                WriteSD4Register(reg, (ushort)(volts * DAC_SCALE / HV_VRANGE));
        }

        double GetHvIlimitSetting() {
                return ReadSD4Register(ADDR_HV_ILIMIT) / DAC_SCALE * HV_IRANGE;
        }

        double GetHvVoltageSetting() {
                return ReadSD4Register(ADDR_HV_CTRL) / DAC_SCALE * HV_VRANGE;
        }

        void SetHvOn(bool hvOn) {
                ReadModifyWrite(ADDR_CSR_DETECTOR, BIT_CSR_DET_HVENABLE, hvOn);
        }

        void SetMaximumHvSetting(double volts) {
                SetHvVoltage(ADDR_HV_MAX, volts);
        }

        void CycleHvReset() {
                // CAUTION: Holding HV in reset will force it to ignore the current limit
                ReadModifyWrite(ADDR_CSR_DETECTOR, BIT_CSR_DET_HVRESET, true);
                ReadModifyWrite(ADDR_CSR_DETECTOR, BIT_CSR_DET_HVRESET, false);
        }

        void SetRampRate(double voltsPerSecond) {
                WriteSD4Register(ADDR_HV_RAMPRATE, (ushort)(RAMPRATESCALE / voltsPerSecond));
        }

        double GetRampRate() {
                return RAMPRATESCALE / (ReadSD4Register(ADDR_HV_RAMPRATE) + 1);
        }

        void SetAdcGain(int gain) {
                ushort csrDetector = ReadSD4Register(ADDR_CSR_DETECTOR);
                bool g1 = GetBit(gain, 0);
                bool g2 = GetBit(gain, 1);
                csrDetector = SetBit(csrDetector, BIT_CSR_DET_ADCGAIN1, g1);
                csrDetector = SetBit(csrDetector, BIT_CSR_DET_ADCGAIN2, g2);
                WriteSD4Register(ADDR_CSR_DETECTOR, (ushort)csrDetector);
        }

        void SetAdcOffsets(int offsetInMv) {
                //nudOffset1.Value = offsetInMv;
                //nudOffset2.Value = offsetInMv;
                //nudOffset3.Value = offsetInMv;
                //nudOffset4.Value = offsetInMv;
                SetAdcOffset(ADDR_OFFSET1, offsetInMv);
                SetAdcOffset(ADDR_OFFSET2, offsetInMv);
                SetAdcOffset(ADDR_OFFSET3, offsetInMv);
                SetAdcOffset(ADDR_OFFSET4, offsetInMv);
        }

        void QuickSetupContinuous() {
                // Set ADC reset
                ResetAdc(true);

                // Clear ADC reset
                ResetAdc(false);

                // Set trigger dead time to 200ns
                SetDeadTime(200);

                // Set event ID
                AddTimeStamp(true);
                AddEventCount(true);
                AddChannelNumber(true);

                // Enable detector amplifier voltage
                SetDetectorVaHiRange(false);
                SetDetectorVaOn(true);

                /*
                // Set HV current limit
                double iLimit = 2.5;
                nudHvIlimit.Value = (decimal)iLimit;
                SetHvCurrentLimit(iLimit);

                // Reset any HV faults
                CycleHvReset();

                // Enable bias voltage
                SetHvOn(false);
                SetHvOn(true);

                // Set bias voltage
                double hvVoltage = 30.0;
                nudHvVoltage.Value = (decimal)hvVoltage;
                SetHvVoltage(ADDR_HV_CTRL, hvVoltage);
                */


                // Set integration time
                int integrationTime = 350;
                //nudIntegrationTime.Value = integrationTime;
                SetIntegrationTime(integrationTime);

                // Set discriminator threshold
                int threshold = 50;
                //nudThreshold.Value = threshold;
                SetThreshold(threshold);

                // Set sum coupling
                SetSumCoupling(true);

                // Set sum gain
                int sumGain = 3;
                //nudSumGain.Value = sumGain;
                SetSumGain(sumGain);

                // Set sum offset
                int offset = 0;
                //nudSumOffset.Value = offset;
                SetSumOffset(offset);

                // Set ADC coupling
                SetAdcCoupling(false);

                // Set ADC gains
                int gain = 1;
                //nudAdcGain.Value = gain;
                SetAdcGain(gain);

                // Set all ADC offsets
                SetAdcOffsets(5);

                // Set internal trigger interval
                int triggerInterval = 1000;
                //nudTriggerInterval.Value = triggerInterval;
                SetTriggerInterval(triggerInterval);

                // Enable continuous trigger
                EnableTrigger(BIT_CSR_TRIG_CONTINUOUS);

                // Begin continuous acquisition
                //nudEventsPerAcquisition.Value = 50000;
                //cbAcquireContinuous.Checked = true;

                // Update histogram offsets
                //SetAllHistogramOffsets(0);
        }


        void QuickSetupDiscriminator() {
                // Set ADC reset
                ResetAdc(true);

                // Clear ADC reset
                ResetAdc(false);

                // Set trigger dead time to 300ns
                SetDeadTime(500);

                // Set event ID
                AddTimeStamp(true);
                AddEventCount(true);
                AddChannelNumber(true);

                // Enable detector amplifier voltage
                SetDetectorVaHiRange(true);
                SetDetectorVaOn(true);

                // Set HV current limit
                double iLimit = 2.5;
                //nudHvIlimit.Value = (decimal)iLimit;
                SetHvCurrentLimit(iLimit);

                // Reset any HV faults
                CycleHvReset();

                // Enable bias voltage
                SetHvOn(false);
                SetHvOn(true);

                // Set bias voltage
                double hvVoltage = 28.0;
                //nudHvVoltage.Value = (decimal)hvVoltage;
                SetHvVoltage(ADDR_HV_CTRL, hvVoltage);

                // Set integration time
                int integrationTime = 350;
                //nudIntegrationTime.Value = integrationTime;
                SetIntegrationTime(integrationTime);

                // Set discriminator threshold
                int threshold = 50;
                //nudThreshold.Value = threshold;
                SetThreshold(threshold);

                // Set sum coupling
                SetSumCoupling(true);

                // Set sum gain
                int sumGain = 3;
                //nudSumGain.Value = sumGain;
                SetSumGain(sumGain);

                // Set sum offset
                int offset = 0;
                //nudSumOffset.Value = offset;
                SetSumOffset(offset);

                // Set ADC coupling
                SetAdcCoupling(false);

                // Set ADC gains
                int gain = 1;
                //nudAdcGain.Value = gain;
                SetAdcGain(gain);

                // Set all ADC offsets
                SetAdcOffsets(5);

                // Clear histograms
                //ClearHistograms();

                // Enable discriminator trigger
                EnableTrigger(BIT_CSR_TRIG_DISCR);

                // Begin continuous acquisition
                //nudEventsPerAcquisition.Value = 1000;
                //cbAcquireContinuous.Checked = true;

                // Update histogram offsets
                //SetAllHistogramOffsets(0);
        }

        void QuickSetupTriggerOff() {
                //cbAcquireContinuous.Checked = false;
                DisableTriggers();
                SetHvOn(false);
                SetDetectorVaOn(false);
        }

        void ReadRegisters() {
                if (deviceIndex < 0)
                        return;

                // Voltages
                double lHvImon = GetHvCurrentInUa();
                double HvVmon = GetHvVoltage(ADDR_HV_VMON);
                double HvVmax = GetHvVoltage(ADDR_HV_MAX);
                double lDetPva = GetVoltage75(ADDR_BASE_PVA);
                double lDetNva = GetVoltage75(ADDR_BASE_NVA);
                double lPva = GetVoltage75(ADDR_MAIN_PVA);
                double lNva = GetVoltage75(ADDR_MAIN_NVA);
                double l12V = GetVoltage(ADDR_MAIN_P12);
                double l33V = GetVoltage75(ADDR_MAIN_P33);
                double l50V = GetVoltage75(ADDR_MAIN_P50);
                double Temperature = GetDetectorTemperature();
                double lRampRate = GetRampRate();


                AddMessageF(lHvImon);
                AddMessageF(HvVmon);
                AddMessageF(HvVmax);
                AddMessageF(lDetPva);
                AddMessageF(lDetNva);
                AddMessageF(lPva);
                AddMessageF(lNva);
                AddMessageF(l12V);
                AddMessageF(l33V);
                AddMessageF(l50V);
                AddMessageF(Temperature);
                AddMessageF(lRampRate);





                // Integration time
                int lItime = GetIntegrationTime();

                // Buffer memory used
                int lBufferWords = ReadSD4Register(ADDR_BUFFERWORDS);

                // Offsets
                double  lOffset1 = GetAdcOffsetInMv(ADDR_OFFSET1);
                double  lOffset2 = GetAdcOffsetInMv(ADDR_OFFSET2);
                double  lOffset3 = GetAdcOffsetInMv(ADDR_OFFSET3);
                double  lOffset4 = GetAdcOffsetInMv(ADDR_OFFSET4);
                double  lSumOffset = GetSumOffsetInMv();

                // Main CSR
                int csrMain = ReadSD4Register(ADDR_CSR_MAIN);
                int lPvaStatus = GetBit(csrMain, BIT_CSR_MAIN_PVA);
                int lNvaStatus = GetBit(csrMain, BIT_CSR_MAIN_NVA);
                int l12vStatus = GetBit(csrMain, BIT_CSR_MAIN_P12);
                int l33vStatus = GetBit(csrMain, BIT_CSR_MAIN_P33);
                int l5vStatus = GetBit(csrMain, BIT_CSR_MAIN_P50);


                AddMessageF(lOffset1);
                AddMessageF(lOffset2);
                AddMessageF(lOffset3);
                AddMessageF(lOffset4);
                AddMessageF(lSumOffset);
                AddMessageX(csrMain);
                AddMessageX(lNvaStatus);
                AddMessageX(lNvaStatus);
                AddMessageX(l12vStatus);
                AddMessageX(l33vStatus);
                AddMessageX(l5vStatus);

                AddMessageI(lBufferWords);
                AddMessageI(lItime);

                // Trigger CSR
                // Assumes only one trigger source is active
                char lTriggerSource[0xFF]="";
                int csrTrigger = ReadSD4Register(ADDR_CSR_TRIGGER);
                if (GetBit(csrTrigger, BIT_CSR_TRIG_CONTINUOUS))
                        sprintf_s(lTriggerSource, 0xFF, "CONTINUOUS");
                else if (GetBit(csrTrigger, BIT_CSR_TRIG_BURST))
                        sprintf_s(lTriggerSource, 0xFF, "BURST");
                else if (GetBit(csrTrigger, BIT_CSR_TRIG_DISCR))
                        sprintf_s(lTriggerSource, 0xFF, "DISCRIMINATOR");
                else if (GetBit(csrTrigger, BIT_CSR_TRIG_EXTERNAL))
                        sprintf_s(lTriggerSource, 0xFF, "EXTERNAL");
                else
                        sprintf_s(lTriggerSource, 0xFF, "OFF");

                // Event ID CSR
                int csrEventId = ReadSD4Register(ADDR_EVENTID);
                addTimeStamp = GetBit(csrEventId, BIT_EVENTID_TIME);
                addEventCount = GetBit(csrEventId, BIT_EVENTID_COUNT);
                addChannelNum = GetBit(csrEventId, BIT_EVENTID_CHNUM);
                //lTimeStamp.Text = addTimeStamp ? "+" : "";
                //lEventCount.Text = addEventCount ? "+" : "";
                //lChannelNum.Text = addChannelNum ? "+" : "";
                AddMessageS(lTriggerSource);
                AddMessageI(addTimeStamp);
                AddMessageI(addEventCount);
                AddMessageI(addEventCount);
                       
                // Trigger generator
                int lTriggerInterval = ReadSD4Register32(ADDR_TG_INTERVALHI, ADDR_TG_INTERVALLO) * 10;
                int lTrigCount = ReadSD4Register32(ADDR_TG_COUNTHI, ADDR_TG_COUNTLO);
                ushort dum = 0;
                WriteSD4Register(ADDR_TC_COUNTLO, dum);    // latch counters by writing to any counter register
                int lTriggers = ReadSD4Register32(ADDR_TC_COUNTHI, ADDR_TC_COUNTLO);
                int lTriggerRate = ReadSD4Register32(ADDR_TC_RATEHI, ADDR_TC_RATELO);
                int lAdcConversions = ReadSD4Register32(ADDR_CONV_COUNTHI, ADDR_CONV_COUNTLO);
                double lThreshold = GetThreshold();
                double lHvIlimit = GetHvIlimitSetting();
                double lHvVoltage = GetHvVoltageSetting();


                AddMessageI(lTriggerInterval);
                AddMessageI(lTrigCount);
                AddMessageI(lTriggers);
                AddMessageI(lTriggerRate);
                AddMessageI(lAdcConversions);
                AddMessageF(lThreshold);
                AddMessageF(lHvIlimit);
                AddMessageF(lHvVoltage);



                // Detector CSR
                int csrDetector = ReadSD4Register(ADDR_CSR_DETECTOR);
                int lHvEnabled = GetBit(csrDetector, BIT_CSR_DET_HVENABLE);
                int lHvOn = GetBit(csrDetector, BIT_CSR_DET_HVGOOD);
                int lSumCoupling = GetBit(csrDetector, BIT_CSR_DET_SUMCOUPLING);
                int lSumGain =
                        ((GetBit(csrDetector, BIT_CSR_DET_SUMGAIN4) ? 1 : 0) << 3) |
                        ((GetBit(csrDetector, BIT_CSR_DET_SUMGAIN3) ? 1 : 0) << 2) |
                        ((GetBit(csrDetector, BIT_CSR_DET_SUMGAIN2) ? 1 : 0) << 1) |
                        ((GetBit(csrDetector, BIT_CSR_DET_SUMGAIN1) ? 1 : 0) << 0);
                int lAdcCoupling = GetBit(csrDetector, BIT_CSR_DET_ADCCOUPLING);
                int lAdcGain = ((GetBit(csrDetector, BIT_CSR_DET_ADCGAIN2) ? 1 : 0) << 1) |
                        ((GetBit(csrDetector, BIT_CSR_DET_ADCGAIN1) ? 1 : 0) << 0);
                int lAmpEnabled = GetBit(csrDetector, BIT_CSR_DET_VAENABLE);
                int lAmpLevel = GetBit(csrDetector, BIT_CSR_DET_VAHIRNG);
                int lDetPvaStatus = GetBit(csrDetector, BIT_CSR_DET_PVAGOOD);
                int lDetNvaStatus = GetBit(csrDetector, BIT_CSR_DET_NVAGOOD);
                int lTemperatureOn = GetBit(csrDetector, BIT_CSR_DET_TEMPVALID);
    AddMessageI(lHvEnabled);
    AddMessageI(lHvOn);
    AddMessageI(lSumCoupling);
    AddMessageI(lSumGain);
    AddMessageI(lAdcCoupling);
    AddMessageI(lAdcGain );
    AddMessageI(lAmpEnabled);
    AddMessageI(lAmpLevel);
    AddMessageI(lDetPvaStatus );
    AddMessageI(lDetNvaStatus);
    AddMessageI(lTemperatureOn);
   
        }



        //----------------------------------------
        // Message list
        //----------------------------------------




        //----------------------------------------
        // MDU Events
        //----------------------------------------
        /*
        private void AitDeviceAttached(object sender, EventArgs e)
        {
         MduManager.DeviceChangedEventArgs aitEventArgs = e as MduManager.DeviceChangedEventArgs;
         AddMessage(String.Format("Attached : Index={0}, ID={1:X8}", aitEventArgs.DeviceIndex, aitEventArgs.DeviceId));
         UpdateDeviceList();
        }

        private void AitDeviceRemoved(object sender, EventArgs e)
        {
         MduManager.DeviceChangedEventArgs aitEventArgs = e as MduManager.DeviceChangedEventArgs;
         AddMessage(String.Format("Removed : Index={0}, ID={1:X8}", aitEventArgs.DeviceIndex, aitEventArgs.DeviceId));
         UpdateDeviceList();
        }

        */


        //----------------------------------------
        // Device Control
        //----------------------------------------

        void GetDeviceId() {
                deviceIndex = 0;
                deviceId = 1;
                /*
                if (tscbDeviceList.SelectedIndex >= 0)
                {
                 deviceIndex = 0; // tscbDeviceList.SelectedIndex;
                 deviceId = 1;  //UInt32.Parse((string)tscbDeviceList.SelectedItem, System.Globalization.NumberStyles.HexNumber);
                }
                else
                {
                 deviceIndex = -1;
                 deviceId = 0;
                }
                */

        }

        int UpdateDeviceList()
{
       
        deviceIndex = -1;
        deviceId = 0;
        int deviceCount = 0;
        uint * devIds = SD4_GetDeviceList(&deviceCount);
        for (int i = 0; i < deviceCount; i++) {
                printf("Device %d = 0x%8x\t", i, devIds[i]);
                deviceId = devIds[i];
                deviceIndex =     i;
        }
        return deviceCount;
}


        void ResetDevice() {
                if (deviceIndex >= 0) {
                        AddMessage(statusReset);
                        SD4_ResetFpga(deviceIndex);
                        Sleep(500);
                        UpdateDeviceList();
                        AddMessage(statusReset);
                        AddMessage(statusDone);
                }
                else
                        AddMessage(statusNoDevice);
        }

        void ReconnectDevice() {
                if (deviceIndex >= 0) {
                        AddMessage(statusReconnect);
                        SD4_Reconnect(deviceIndex);
                        Sleep(500);
                        AddMessage(statusReconnect);
                        AddMessage(statusDone);
                }
                else
                        AddMessage(statusNoDevice);
        }

        void ReconfigureDevice() {
                if (deviceIndex >= 0) {
                        AddMessage(statusReconfig);
                        SD4_Reconfigure(deviceIndex);
                        Sleep(500);
                        SD4_ResetFpga(deviceIndex);
                        UpdateDeviceList();
                        AddMessage(statusReconfig);
                        AddMessage(statusDone);
                }
                else
                        AddMessage(statusNoDevice);
        }

        //----------------------------------------
        // Initialize Device Connection
        //----------------------------------------

        void InitializeConnection() {
    int ndevices = 0;
          unsigned int * devlist = SD4_FindDevices(&ndevices);
        printf("Found %d devices\t", ndevices);
        //SD4.DeviceAttached += new EventHandler(AitDeviceAttached);
        //SD4.DeviceRemoved += new EventHandler(AitDeviceRemoved);
        //tscbDeviceList.SelectedIndexChanged += new EventHandler(tscbDeviceList_SelectedIndexChanged);
          printf("Updated devices %d\n", UpdateDeviceList());
 
 
               

                // Set above the maximum bias voltage to prevent accidental over-bias.
                        // For example for 30V bias, set to 32V. For 70V bias, set to 72V
                SetMaximumHvSetting(32.0);

                // Set TTL port to 0
                WriteSD4Register(ADDR_TTLPORT, 0);

                // Set HV ramp rate to 20 V/s
                SetRampRate(20);

                // 1 second register scan interval
                //SetupTimer(1.0);

        }


        int GetAdcEventSize() {
                int eventSize = CHANNELS;
                if (addTimeStamp == true)
                        eventSize += 3;   // 3 16-bit words for time stamp
                if (addEventCount == true)
                        eventSize += 2;   // 2 16-bit words for event count
                return eventSize;
        }

        int GetEventPosition(int eventNum) {
                int adcBoardEventSize = GetAdcEventSize();
                return adcBoardEventSize * eventNum;
        }

        ushort ExtractAdcData(int eventNum, int channel) {
                int index = GetEventPosition(eventNum) + channel;
                return adcBuffer[index];
        }

        long ExtractTimeStamp(int eventNum) {
                int index = GetEventPosition(eventNum) + CHANNELS;
                long timestamp = 0;
                for (int i = 0; i < 3; i++)
                        timestamp = (timestamp << 16) | adcBuffer[index++];
                return timestamp;
        }

        int ExtractEventCount(int eventNum) {
                int offset = 0;
                if (addTimeStamp == true)
                        offset += 3;
                int index = GetEventPosition(eventNum) + CHANNELS + offset;
                int eventCount = adcBuffer[index];
                eventCount = (eventCount << 16) | adcBuffer[index + 1];
                return eventCount;
        }

        void ShowEvent(int eventNumber) {
                if (eventNumber < 1)
                        return;
                eventNumber--;
                char lAdcTimeStamp[0xFF]="";
                char lAdcAbsTimeStamp[0xFF]="";
                char lAdcEventCount[0xFF]="";
                //tbAdcData.Clear();
                int eventPosition = GetEventPosition(eventNumber);
                for (int channel = 0; channel < CHANNELS; channel++) {
                        int data = ExtractAdcData(eventNumber, channel);
                        AddMessage("AdcData event %d channel:%d  data:%d\n", eventNumber, channel + 1, data);
                }
                if (addTimeStamp == true) {
                        long reference = ExtractTimeStamp(0);
                        long timeStamp = ExtractTimeStamp(eventNumber);
                        sprintf_s(lAdcTimeStamp, 0xFF, "%d", ((timeStamp - reference) * TIMESTAMP_LSB));
                        sprintf_s(lAdcAbsTimeStamp, 0xFF, "%d", (timeStamp * TIMESTAMP_LSB));
                }
                else {
                        sprintf_s(lAdcTimeStamp, 0xFF, "%s", "----");
                        sprintf_s(lAdcAbsTimeStamp, 0xFF, "%s", "----");
                }
                if (addEventCount == true) {
                        sprintf_s(lAdcEventCount, 0xFF, "%d", ExtractEventCount(eventNumber));
                }
                else {
                        sprintf_s(lAdcEventCount, 0xFF, "%s", "----");
                }
                //SetTextboxToTop(tbAdcData);
        }

int BlockTransferTime() {
  return SD4_BlockTransferTime();
}  
        void InitInterface(int events) {
                adcBufferLen = GetAdcEventSize() * events;
                //adcBuffer = (ushort *)malloc(sizeof(ushort) * adcBufferLen);
    /*
                for (int i = 0; i < 0xFFF; i++) {
                        for (int j = 0; j < 4; j++) histograms[j][i] = 0;
                }
                for (int i = 0; i < 4 * 0xFFF; i++) {
                        histogramtotal[i] = 0;
                }
    */

                histogramTotalEvents = 0;
        }

        int Acquire(int events) {
                //InitializeConnection();
                // Acquire
                InitInterface(events);
                //int wordsAcquired = ReadAdcByteBuffer();    //  use only to test byte buffer read operation
                int wordsAcquired = ReadAdcBuffer();
                if (wordsAcquired != adcBufferLen) {
                        char msg[0xFF];
                        AddMessage("ERROR: Timeout with possible data loss (%d/%d words received; Block Error = %d)\n", wordsAcquired, adcBufferLen, SD4_BlockError());
      return 0;
                }

               
   
                /*
                lTransferRate.Text = String.Format("{0:f2}", transferRate);
                lAcquisitionSize.Text = String.Format("{0:f2}", blocksize / 1e6);   // block size in MB
                lAcquisitionTime.Text = String.Format("{0:f2}", microseconds / 1e6);
                */

                return events;
        }

        void GetStatistics(int events) {
                ushort rawAdcData = 0;
                ushort adcData = 0;
                int channelReceived = 0;
                int channelExpected = 0;
                bool includeSaturated = 0; // cbIncludeSaturated.Checked;
                ushort max[CHANNELS];
                ushort min[CHANNELS];
                ushort average[CHANNELS];
                int  total[CHANNELS];
                for (int i = 0; i < CHANNELS; i++) {
                        min[i] = 0xFFFF;
                        max[i] = 0;
                        total[i] = 0;
                }
                for (int eventNum = 0; eventNum < events; eventNum++) {

                        int sum = 0;
                        for (int channel = 0; channel < CHANNELS; channel++) {
                                rawAdcData = ExtractAdcData(eventNum, channel);
                                if (addChannelNum == true) {
                                        channelReceived = (rawAdcData >> 12) & 0xF;
                                        channelExpected = (channel & 0xF);
                                        if (channelReceived != channelExpected) {

                                                AddMessage("ERROR in Event %d : Expected channel %d, received %d -ANALYSIS STOPPED", eventNum, channelExpected, channelReceived);

                                                //EnableRegisterScanTimer(true);
                                                return;
                                        }
                                }
                                adcData = (ushort)(rawAdcData & 0x0FFF);    // remove channel number
                                if ((includeSaturated == true) || ((includeSaturated == false) && (adcData < (ADCMAX - 2))))
                                        histograms[channel][adcData]++;
                                total[channel] = total[channel] + adcData;
                                if (adcData > max[channel])
                                        max[channel] = adcData;
                                else if (adcData < min[channel])
                                        min[channel] = adcData;

                                sum += adcData;
                        }
                        histogramtotal[sum]++;
                        histogramTotalEvents++;
                }
                //tbAdcStatistics.Clear();
                for (int channel = 0; channel < CHANNELS; channel++) {
                        average[channel] = (ushort)(total[channel] / events);

                        AddMessage(" {channel:%d}  : {min:0x%d}  {max:0x%d}  {max-min:%d}  {average:%d}\n", channel + 1, min[channel], max[channel], max[channel] - min[channel], average[channel]);
                        //if (channel < (CHANNELS - 1))
                        //    tbAdcStatistics.AppendText(Environment.NewLine);

                }
                //SetTextboxToTop(tbAdcStatistics);
        }

        void SetupAcquisition(int neve) {
                //EnableRegisterScanTimer(false);
                //nudEventSelect.Minimum = 0;
                //nudEventSelect.Maximum = 0;
                int eventsAcquired = Acquire(neve);
                if (eventsAcquired < 1){
      printf("Acquired events %d\n", eventsAcquired);
                        return;
    }  
                GetStatistics(eventsAcquired);
                ShowEvent(1);
                //ShowHistograms();
                //nudEventSelect.Minimum = 1;
                //nudEventSelect.Maximum = eventsAcquired;
                //EnableRegisterScanTimer(true);
        }





        int _tmain(int argc, char **argv) {


                int events = 1000;

                InitInterface(events);
                SetupAcquisition(1);

                //NE_Rainbow();
                printf("xxx\n");
                //NE_Call(9);
                int b = 9;
                int k = 0;//NE_Func(b);
                printf("yyy %d %d\n", b, k);
                return 0;
        }