CSharp (C#) Streaming Ain/Aout Function Generator

The example below demonstrates how to stream analog data out the analog output pins while at the same time reading it back in. To keep the program simple, an array is created that contains a waveform and this waveform is continuously written to the output buffer without change. In a more sophisticated program the array data would be changing on each write. To use this program you must have a device that supports hardware analog output scanning at rates of at lest 50,000 per second. At the beginning of the program where the constants are defined there is a section of tested devices. Uncomment the device you have and comment the current device which is the USB-1408FS-Plus.

The example program writes the data to a text file that is compatible with the DASYLab ReadFile module and Excel. To visually verify the data, I found the easiest method was to read the file in with DASYLab and display it in a strip chart. Connect the outputs to the inputs using wire and run the program to generate the data file. Run the attached DASYLab 13.0 test worksheet to see the data. The worksheet will not only display data but will also measure the frequency. If you change the example program's block size and sample rate you must also change it in the DASYLab worksheet in the Read module ASCII Options. If you don't have DASYLab there is 30 day evaluation available on the MCC web site.

The program uses the MccDaq.dll .net assembly API. To be able to access this API, in your project add a reference to it. Adding the reference is usually accomplished by right clicking the Project [under the Project Explorer] and selecting Add Reference. On the .NET page find and select the MccDaq component. My complete Visual Studio 9.0 project is attached to this article further down.

Disclaimer:
The attached Code or Example is provided As Is. It has not been tested or validated as a product, for use in a deployed application or system, or for use in hazardous environments. You assume all risks for use of the Code or Example.

using System;
using MccDaq;
using System.IO;
using System.Linq;

namespace Ain_Aout_Continous
{
    class Program
    {
        public const int iBLOCKSIZE = 4096;     //input block size
        public const int oBLOCKSIZE = 2048;     //output block size

        public const int iFREQ = 5000;          //input sample rate
        public const int oFREQ = 50000;         //output update rate

        public const int FIRSTCHANNEL = 0;
        public const int LASTCHANNEL = 1;

        public const int iCHANCOUNT = LASTCHANNEL - FIRSTCHANNEL +1;        //input channel count
        public const int oCHANCOUNT = LASTCHANNEL - FIRSTCHANNEL + 1;       //output channel count
        
        public const int iBUFFERSIZE = iBLOCKSIZE * iCHANCOUNT; //input buffer size
        public const int oBUFFERSIZE = oBLOCKSIZE * oCHANCOUNT; //output buffer size

        public const int iHALFBUFFSIZE = iBUFFERSIZE / 2;
        public const int oHALFBUFFSIZE = oBUFFERSIZE / 2;
        
 //The following devices have been tried...Uncomment yours
//public const string DEVICE = "PCI-DAS6052"; 
//public const int RESOLUTION = 65535; public const ScanOptions ExtraOpts = ScanOptions.BurstMode | ScanOptions.BlockIo;

//public const string DEVICE = "USB-1608GX-2AO"; 
//public const int RESOLUTION = 65535; public const ScanOptions ExtraOpts = ScanOptions.BurstMode | ScanOptions.BlockIo;

//public const string DEVICE = "USB-1616HS-4"; 
//public const int RESOLUTION = 65535; public const ScanOptions ExtraOpts = ScanOptions.BlockIo;

//public const string DEVICE = "USB-1616HS-2"; 
//public const int RESOLUTION = 65535; public const ScanOptions ExtraOpts = ScanOptions.BlockIo;

//public const string DEVICE = "USB-2527"; 
//public const int RESOLUTION = 65535; public const ScanOptions ExtraOpts = ScanOptions.BlockIo;

//public const string DEVICE = "USB-1208HS-4AO"; 
//public const int RESOLUTION = 4096; public const ScanOptions ExtraOpts = ScanOptions.BurstMode|ScanOptions.BlockIo;

public const string DEVICE = "USB-1408FS-Plus"; 
public const int RESOLUTION = 4096; public const ScanOptions ExtraOpts = ScanOptions.BlockIo;

//public const string DEVICE = "USB-1208FS-Plus"; 
//public const int RESOLUTION = 4096; public const ScanOptions ExtraOpts = ScanOptions.BlockIo;

        public static StreamWriter fStream;
        public static IntPtr OutBuf;
        public static IntPtr buffer;
        public static bool inLower;
        public static bool outLower;
        public static ushort[] inArray;
        public static ushort[] outArray;
     
        public static MccBoard daq;

        public static MccDaq.ErrorInfo RetVal;
        // *********************************************************************************************************
        // *********************************************************************************************************
        // *********************************************************************************************************

        static void Main(string[] args)
        {

            MccDaq.ErrorInfo RetVal;
            int BoardNum = 0;
            int iRate = iFREQ; //input rate
            int oRate = oFREQ; //output rate
            inLower = true;
            outLower = true;
            Console.WriteLine("Connecting to {0}",DEVICE);
            BoardNum = GetBoardNum(DEVICE);

            if (BoardNum == -1)
            {
                Console.WriteLine("No {0} detected!", DEVICE);
                WaitForKey();
                return;
            }
            else
            { ///////// BEGIN PROGRAM ///////////
                daq = new MccDaq.MccBoard(BoardNum);

                //create the driver buffers
                OutBuf = MccService.WinBufAllocEx(oBUFFERSIZE);
                buffer = MccService.ScaledWinBufAllocEx(iBUFFERSIZE);
                Console.WriteLine("{0} Connected",DEVICE);

                if ((OutBuf == IntPtr.Zero) || (buffer == IntPtr.Zero))
                {
                    Console.WriteLine("Insufficient Memory");
                    WaitForKey();
                    return;
                }

                
                //create the user output buffer.
                outArray = new ushort[oBUFFERSIZE];
                //create the waveforms
                for(int i=0;i<oCHANCOUNT;i++)
                    GetWaveForm(3, i, outArray); //start with sine wave

                //write the user data to the driver buffer
                MccService.WinArrayToBuf(outArray, OutBuf, 0, oBUFFERSIZE);
                //start the waveforms 
                RetVal = daq.AOutScan(  FIRSTCHANNEL,
                                        LASTCHANNEL,
                                        oBUFFERSIZE,
                                        ref oRate,
                                        Range.Bip10Volts,
                                        OutBuf,
                                        ScanOptions.Background | ScanOptions.Continuous
                                      );
                if (IsError("AOutScan",RetVal) == 1) return;


                short[] chArray = new short[iCHANCOUNT]; //configuration array for channel numbers
                for(short i=0; i<iCHANCOUNT;i++)
                    chArray[0] = i;


 

                fStream = new StreamWriter(@"C:\Users\Public\Documents\DataFile.asc");
                CreateFileHeaders(chArray); //writes basic info to the beginning of the file
                System.ConsoleKeyInfo cki;
                WaitForKey();
 
                //begin analog input
                RetVal = daq.AInScan(FIRSTCHANNEL,
                                        LASTCHANNEL,
                                        iBUFFERSIZE,
                                        ref iRate,
                                        Range.Bip10Volts,
                                        buffer,
                                        ScanOptions.Background | ScanOptions.Continuous | ExtraOpts
                                    );
                if (IsError("AInScan", RetVal) == 1) return; bool exit = false;
                
                //do loop to switch waveforms and read/write data
                do
                {
                    if (Console.KeyAvailable)
                    {
                        cki = Console.ReadKey(true);
                        switch (cki.Key)
                        {
                            case ConsoleKey.D1: 
                            case ConsoleKey.NumPad1:
                                if ((cki.Modifiers & ConsoleModifiers.Alt) != 0)
                                    GetWaveForm(1, 1, outArray);
                                else
                                    GetWaveForm(1,0,outArray);

                                break;
                            case ConsoleKey.D2:
                            case ConsoleKey.NumPad2:
                                if ((cki.Modifiers & ConsoleModifiers.Alt) != 0)
                                    GetWaveForm(2, 1, outArray);
                                else
                                    GetWaveForm(2, 0, outArray);
                                break;
                            case ConsoleKey.D3:
                            case ConsoleKey.NumPad3:
                                if ((cki.Modifiers & ConsoleModifiers.Alt) != 0)
                                    GetWaveForm(3, 1, outArray);
                                else
                                    GetWaveForm(3, 0, outArray);
                                break;
                            case ConsoleKey.D4:
                            case ConsoleKey.NumPad4:
                                if ((cki.Modifiers & ConsoleModifiers.Alt) != 0)
                                    GetWaveForm(4, 1, outArray);
                                else
                                    GetWaveForm(4, 0, outArray);
                                break;
                            case ConsoleKey.D5:
                            case ConsoleKey.NumPad5:
                                if ((cki.Modifiers & ConsoleModifiers.Alt) != 0)
                                    GetWaveForm(5, 1, outArray);
                                else
                                    GetWaveForm(5, 0, outArray);
                                break;
                            case ConsoleKey.D6:
                            case ConsoleKey.NumPad6:
                                if ((cki.Modifiers & ConsoleModifiers.Alt) != 0)
                                    GetWaveForm(6, 1, outArray);
                                else
                                    GetWaveForm(6, 0, outArray);
                                break;
                            case ConsoleKey.Spacebar:
                                exit = true;
                                break;

                        }
                    }
                    if(ReadInputBuffer()==1) return;
                    if(WriteOutputBuffer()==1) return;

                   
                } while (!exit);

                //flush buffered data out to disk
                fStream.Flush();
                //close file
                fStream.Close();

                //stop the  acquisition
                RetVal = daq.StopBackground(FunctionType.AiFunction);
                RetVal = daq.StopBackground(FunctionType.AoFunction);

                //free up memory
                MccService.WinBufFreeEx(buffer);
                MccService.WinBufFreeEx(OutBuf);

                return;
            }
        }

Attachments
ReadDataFile.DSB
AIn_Aout_Continous_Waveform_Generator.zip