using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; // for callback using AIOUSBNet; // the namespace exposes the AIOUSB Class interface namespace ConsoleApplication1 { class Program { // Global static persistent pointer to callback function defined in Net wrapper dll: public static AIOUSB.ADCallback myCallBack; // AD specifics: const int Channels = 16; // Num channels we will be using: public const int numAnalogInputs = 16; // default 16 // Struct for AI Board Config: public struct TUSBAI1616Config { public TUSBAI1616Config(int size) { ChannelRange = new byte[size]; CalibMode = 0; TrigMode = 0; StartStopCH = 0; Oversample = 0; } public byte[] ChannelRange; public byte CalibMode; public byte TrigMode; public byte StartStopCH; public byte Oversample; } // Struct for Configuration must pass number of channels for array size: public TUSBAI1616Config Config = new TUSBAI1616Config(numAnalogInputs); // Method that matches delegate signature: // Note: BuffSize returned is actually number of bytes so array of UInt16's lenghth should actually be 1/2 BuffSize public static void ADCallbackReport(IntPtr pBuf, UInt32 BufSize, UInt32 Flags, UInt32 Context) { // Copy pBuff into an Int16 array then convert to UInt16 // This is required due to CLR restraints on IntPtr and Marshal.Copy() for unmanaged code array pointers int BuffLen = ((int)BufSize / 2); // proper length of the buffer in 16 bit elements based on retuned number of 8 bit bytes Int16[] array = new Int16[BuffLen]; // array for buff Int16 copy UInt16[] ChannelCounts = new UInt16[BuffLen]; // buffer for all final UInt16 count data Marshal.Copy(pBuf, array, 0, (array.Length)); for (int i = 0; i < BuffLen; ++i) { ChannelCounts[i] = (UInt16)array[i]; // convert Int16 to UInt16 //ChannelCounts[i] = Convert.ToUInt16(array[i]); } /* // Alternate byte method: int BuffLen = ((int)BufSize / 2); // proper length of the buffer in 16 bit elements based on retuned number of 8 bit bytes byte[] arrayB = new byte[BufSize]; // array for buff byte copy UInt16[] ChannelCounts = new UInt16[BuffLen]; // buffer for all final UInt16 count data Marshal.Copy(pBuf, arrayB, 0, (arrayB.Length)); for (int i = 0; i < BuffLen; ++i) { // Could do this: ChannelCounts[i] = BitConverter.ToUInt16( arrayB, (i * 2) ); } */ // Converting counts to volts: // We will need to safely get the settings used form the Form UI controls: byte RangeCode; int ChannelsDisplayed = 16; double Volts = 0; //We're going to use the range code to convert to volts. RangeCode = 1; // default to 1 +-10 volts for testing full range //Because the display can be slow, and this is called from a worker //thread, we just load each channel's last reading for display. Any //direct processing of the data, like a Fourier transform, would go //here instead. UInt16 Counts; Console.Clear(); for (int i = 0; i < ChannelsDisplayed; i++) { Counts = ChannelCounts[i]; // raw counts Volts = (double)(Counts) / (double)(0xFFFF); //"Volts" now holds a value from 0 to 1. if ((RangeCode & 0x01) != 0) //Bit 0(mask 01 hex) indicates bipolar. { Volts = Volts * 2 - 1; //"Volts" now holds a value from -1 to +1. } if ((RangeCode & 0x02) == 0) //Bit 1(mask 02 hex) indicates x2 gain. { Volts *= 2; } if ((RangeCode & 0x04) == 0) //Bit 2(mask 04 hex) indicates x5 gain. { Volts *= 5; } string strVolts; string strFormat = "Ch: {0,2:D2} Volts: {1,8:F3} \r\n"; strVolts = String.Format(strFormat, i, Volts); Console.Write(strVolts); } Console.WriteLine("\n Callback Running... Press any key to stop callback and continue..."); } static void Main(string[] args) { // Instantiate delegate with named method: myCallBack = new AIOUSB.ADCallback(ADCallbackReport); double Hz = 0; UInt32 BlockIndex = 0; UInt32 DeviceIndex = AIOUSB.diOnly; UInt32 Status; bool bCal = true; //Stop the counter, in case it was running. AIOUSB.CTR_StartOutputFreq(DeviceIndex, BlockIndex, out Hz); // Temp array for ADC_SetConfig() dll calls: byte[] configArray = new byte[20]; // Init all config values: // Temp copy struct to array for dll call: for (int i = 0; i < numAnalogInputs; i++) { configArray[i] = 1; // range code default to 1 +-10 volts for testing full range } configArray[16] = 0; //Take actual data, not internal calibration sources. configArray[17] = 0x05; //Scan selected channels each counter rising edge. //configArray[18] = 0xF0; //Scan selected channels. configArray[19] = 0; //No oversample. UInt32 ConfigBufSizeTemp = 20; AIOUSB.ADC_SetConfig(DeviceIndex, configArray, out ConfigBufSizeTemp); configArray[18] = 0xF0; //Select all 16 channels, from 0 to 15. // Config again: configArray[18] = 0xF0; //Select all 16 channels, from 0 to 15. AIOUSB.ADC_SetConfig(DeviceIndex, configArray, out ConfigBufSizeTemp); if (bCal) { Status = AIOUSB.ADC_SetCal(DeviceIndex, ":1TO1:"); //Status = AIOUSB.ADC_SetCal(DeviceIndex, ":AUTO:"); //Status = AIOUSB.ADC_SetCal(DeviceIndex, "NONE"); if (Status != 0) //ERROR_SUCCESS ) { Console.WriteLine("Calibration Error!"); return; } } //Since we've put it in scan mode, this is 1kHz per channel, or 16kHz total. Hz = 1000; AIOUSB.CTR_StartOutputFreq(DeviceIndex, 0, out Hz); Status = AIOUSB.ADC_BulkContinuousCallbackStart(DeviceIndex, 1024, 64, 0, myCallBack); Console.WriteLine("Callback Started... Press any key to stop callback and continue..."); Console.ReadKey(true); UInt32 EndStatus, IOStatus; EndStatus = AIOUSB.ADC_BulkContinuousEnd(DeviceIndex, out IOStatus); Console.WriteLine("\n Callback Stopped... Press any key to Exit Console App\n"); Console.ReadKey(true); } } }