Subversion Repositories f9daq

Rev

Blame | Last modification | View Log | RSS feed

// NativeExportsConsumerApp.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <string.h>
#include <windows.h>
#include "AitMduManager.h"
#include "AitMduManager_DEF.h"

typedef unsigned short ushort;
typedef unsigned int uint;

extern "C"
{
        DLLIMPORT  void NE_Rainbow();

        DLLIMPORT  int  NE_Func(int a);
        DLLIMPORT  int  NE_Ptr2ByteArray(char *, int len);
        DLLIMPORT  char * NE_ByteArray2Ptr(char *, int *);
        DLLIMPORT  int  NE_Ptr2String(char *, int len);
        DLLIMPORT  int  NE_String2Ptr(char *);
        DLLIMPORT  char * NE_String();
        DLLIMPORT  unsigned int * NE_UInt(int *);
}

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

uint deviceId = 0;
int deviceIndex = -1;
int adcBufferLen;
ushort * adcBuffer;
int histograms[4][0xFFF];
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";

/*
void Sleep(int musec) {

}
*/


//----------------------------------------
// 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;
}
// Equivalent to ReadAdcBuffer() except using byte buffer for acquisition
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 = 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);

        // 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();

        // 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);

        // 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);
        int addTimeStamp = GetBit(csrEventId, BIT_EVENTID_TIME);
        int addEventCount = GetBit(csrEventId, BIT_EVENTID_COUNT);
        int addChannelNum = GetBit(csrEventId, BIT_EVENTID_CHNUM);
        //lTimeStamp.Text = addTimeStamp ? "+" : "";
        //lEventCount.Text = addEventCount ? "+" : "";
        //lChannelNum.Text = addChannelNum ? "+" : "";

        // 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();

        // 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);
}



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

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





//----------------------------------------
// 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
//----------------------------------------

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\n", 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\n", ndevices);
        //SD4.DeviceAttached += new EventHandler(AitDeviceAttached);
        //SD4.DeviceRemoved += new EventHandler(AitDeviceRemoved);
        //tscbDeviceList.SelectedIndexChanged += new EventHandler(tscbDeviceList_SelectedIndexChanged);
        printf("Updated devices %d\n", UpdateDeviceList());
}


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



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);
                printf(" 0:%d  1:%d ", channel + 1, data);
                if (channel < (CHANNELS - 1))
                        printf("\n");
        }
        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 Acquire(int events)
{
        // Acquire
        adcBufferLen = GetAdcEventSize() * events;
        //adcBuffer = new ushort[adcBufferLen];

        //int wordsAcquired = ReadAdcByteBuffer();              //  use only to test byte buffer read operation
        int wordsAcquired = ReadAdcBuffer();
        if (wordsAcquired != adcBufferLen)
        {
                char msg[0xFF];
                sprintf_s(msg, "ERROR: Timeout with possible data loss (%d/%d words received; Block Error = %d)", wordsAcquired, adcBufferLen, SD4_BlockError());
                AddMessage(msg);
                /*
                if (cbAcquireContinuous.Checked == true)
                {
                        cbAcquireContinuous.Checked = false;
                        AddMessage("Acquisition disabled");
                }
                */

        }

        // Update UI
        double blocksize = adcBufferLen * 2.0;
        double microseconds = SD4_BlockTransferTime();
        double transferRate = blocksize / microseconds;
        /*
        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 = new ushort[CHANNELS];
        ushort * min = new ushort[CHANNELS];
        ushort * average = new ushort[CHANNELS];
        int*  total = new int[CHANNELS];
        for (int i = 0; i < CHANNELS; i++)
        {
                min[i] = 0xFFFF;
                max[i] = 0;
                total[i] = 0;
        }
        for (int eventNum = 0; eventNum < events; eventNum++)
        {
                for (int channel = 0; channel < CHANNELS; channel++)
                {
                        rawAdcData = ExtractAdcData(eventNum, channel);
                        if (addChannelNum == true)
                        {
                                channelReceived = (rawAdcData >> 12) & 0xF;
                                channelExpected = (channel & 0xF);
                                if (channelReceived != channelExpected)
                                {
                                        char msg[0xFF];
                                        sprintf_s(msg, "ERROR in Event %d : Expected channel %d, received %d -ANALYSIS STOPPED", eventNum, channelExpected, channelReceived);
                                        AddMessage(msg);
                                        //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;
                }
                histogramTotalEvents++;
        }
        //tbAdcStatistics.Clear();
        for (int channel = 0; channel < CHANNELS; channel++)
        {
                average[channel] = (ushort)(total[channel] / events);
                char msg[0xFF];
                sprintf_s(msg, " {0:%d}  : {1:0x%04x}  {2:0x%04x}  {3:0x%04x}  {4:0x%04x}", channel + 1, min[channel], max[channel], max[channel] - min[channel], average[channel]);
                //if (channel < (CHANNELS - 1))
          //      tbAdcStatistics.AppendText(Environment.NewLine);
                AddMessage(msg);
        }
        //SetTextboxToTop(tbAdcStatistics);
}

void SetupAcquisition(int neve)
{
        //EnableRegisterScanTimer(false);
        //nudEventSelect.Minimum = 0;
        //nudEventSelect.Maximum = 0;
        int eventsAcquired = Acquire(neve);
        if (eventsAcquired < 1)
                return;
        GetStatistics(eventsAcquired);
        ShowEvent(1);
        //ShowHistograms();
        //nudEventSelect.Minimum = 1;
        //nudEventSelect.Maximum = eventsAcquired;
        //EnableRegisterScanTimer(true);
}

int main(int argc, _TCHAR* argv[])
//int _tmain(int argc, _TCHAR* argv[])
{


        NE_Rainbow();
        //-----------------------------------
        char bla[100] = "abcd";
        NE_Ptr2ByteArray(bla, strlen(bla));
        //-----------------------------------
        char data[1000] = { 1,0,0,1,0,0,0,0,1,1,1,1 };
        int len = 0;
        //char *data=NULL;
        int *retval = (int *)NE_ByteArray2Ptr(data, &len);
        int *idata = (int*)data;
        printf("***NE_ByteArray2Ptr %d\n", len);
        for (int i = 0; i < len; i++) printf("%d %d %d\n", i, idata[i], retval[i]);
        printf("\n");
        //-----------------------------------
        char data1[100] = "NE_Ptr2String";
        NE_Ptr2String(data1, strlen(data1));
        //-----------------------------------
        char data2[100] = "abcd";
        int nb = NE_String2Ptr(data2);
        //-----------------------------------

        printf("result = %d %s\n", nb, bla);
        printf("string = %s\n", NE_String());

        //-----------------------------------
        unsigned int *n = NE_UInt(&len);
        printf("NE_UInt size = %d\n", len);
        for (int i = 0; i < len; i++) printf("%d\t", n[i]);
        printf("\n");
        //-----------------------------------

        int events = 1000;
        adcBufferLen = GetAdcEventSize() * events;
        //adcBuffer = new ushort[GetAdcEventSize() * events];
        for (int i = 0; i < 0xFFF; i++) {
                for (int j = 0; j < 4; j++) histograms[j][i] = 0;
        }
        histogramTotalEvents = 0;
        InitializeConnection();
        QuickSetupContinuous();
        ReadRegisters();
        SetupAcquisition(1);

        return 0;
}