Exemple #1
0
        //----------------------------------------------------------------------------
        //
        // Function    :  Acquire data
        //
        // Description :  Acquire data from board, optionally saving data to file.
        //
        //----------------------------------------------------------------------------

        static public unsafe bool AcquireData(IntPtr boardHandle)
        {
            // There are no pre-trigger samples in NPT mode
            UInt32 preTriggerSamples = 0;

            // TODO: Select the number of post-trigger samples per record
            UInt32 postTriggerSamples = 2048;

            // TODO: Specify the number of records per DMA buffer
            UInt32 recordsPerBuffer      = 10;
            UInt32 buffersPerAcquisition = 10;

            UInt32 channelMask = AlazarAPI.CHANNEL_A | AlazarAPI.CHANNEL_B;

            // TODO: Select if you wish to save the sample data to a file
            bool saveData = false;

            // Calculate the number of enabled channels from the channel mask
            UInt32 channelCount = 0;

            switch (channelMask)
            {
            case AlazarAPI.CHANNEL_A:
            case AlazarAPI.CHANNEL_B:
                channelCount = 1;
                break;

            case AlazarAPI.CHANNEL_A | AlazarAPI.CHANNEL_B:
                channelCount = 2;
                break;

            default:
                Console.WriteLine("Error: Invalid channel mask -- {0}", channelMask);
                return(false);
            }

            // Get the sample size in bits, and the on-board memory size in samples per channel

            Byte   bitsPerSample;
            UInt32 maxSamplesPerChannel;
            UInt32 retCode = AlazarAPI.AlazarGetChannelInfo(boardHandle, &maxSamplesPerChannel, &bitsPerSample);

            if (retCode != AlazarAPI.ApiSuccess)
            {
                Console.WriteLine("Error: AlazarGetChannelInfo failed -- " +
                                  AlazarAPI.AlazarErrorToText(retCode));
                return(false);
            }

            // Calculate the size of each DMA buffer in bytes

            UInt32 bytesPerSample   = ((UInt32)bitsPerSample + 7) / 8;
            UInt32 samplesPerRecord = preTriggerSamples + postTriggerSamples;
            UInt32 bytesPerRecord   = (bytesPerSample * samplesPerRecord);
            UInt32 bytesPerBuffer   = bytesPerRecord * recordsPerBuffer * channelCount;

            FileStream fileStream = null;
            bool       success    = true;

            try
            {
                // Create a data file if required

                if (saveData)
                {
                    fileStream = File.Create(@"data.bin");
                }

                // Allocate memory for sample buffer

                byte[] buffer = new byte[bytesPerBuffer];

                // Cast byte array to short array

                ByteToShortArray byteToShortArray = new ByteToShortArray();
                byteToShortArray.bytes = buffer;

                fixed(short *pBuffer = byteToShortArray.shorts)
                {
                    // Configure the record size

                    retCode =
                        AlazarAPI.AlazarSetRecordSize(
                            boardHandle,
                            preTriggerSamples,
                            postTriggerSamples
                            );
                    if (retCode != AlazarAPI.ApiSuccess)
                    {
                        throw new System.Exception("Error: AlazarSetRecordSize failed -- " + AlazarAPI.AlazarErrorToText(retCode));
                    }

                    // Configure the board to make an NPT AutoDMA acquisition

                    UInt32 recordsPerAcquisition = recordsPerBuffer * buffersPerAcquisition;

                    retCode =
                        AlazarAPI.AlazarBeforeAsyncRead(
                            boardHandle,
                            channelMask,
                            -(int)preTriggerSamples,
                            samplesPerRecord,
                            recordsPerBuffer,
                            recordsPerAcquisition,
                            AlazarAPI.ADMA_EXTERNAL_STARTCAPTURE | AlazarAPI.ADMA_NPT | AlazarAPI.ADMA_ALLOC_BUFFERS
                            );
                    if (retCode != AlazarAPI.ApiSuccess)
                    {
                        throw new System.Exception("Error: AlazarBeforeAsyncRead failed -- " + AlazarAPI.AlazarErrorToText(retCode));
                    }

                    // Arm the board to begin the acquisition

                    retCode = AlazarAPI.AlazarStartCapture(boardHandle);
                    if (retCode != AlazarAPI.ApiSuccess)
                    {
                        throw new System.Exception("Error: AlazarStartCapture failed -- " +
                                                   AlazarAPI.AlazarErrorToText(retCode));
                    }

                    // Wait for each buffer to be filled, then process the buffer

                    Console.WriteLine("Capturing {0} buffers ... press any key to abort",
                                      buffersPerAcquisition);

                    int startTickCount = System.Environment.TickCount;

                    UInt32 buffersCompleted = 0;
                    Int64  bytesTransferred = 0;

                    bool done = false;

                    while (!done)
                    {
                        // TODO: Set a buffer timeout that is longer than the time
                        //       required to capture all the records in one buffer.

                        UInt32 timeout_ms = 5000;

                        // Wait for a buffer to be filled by the board.

                        retCode = AlazarAPI.AlazarWaitNextAsyncBufferComplete(boardHandle, pBuffer, bytesPerBuffer, timeout_ms);
                        if (retCode == AlazarAPI.ApiSuccess)
                        {
                            // This buffer is full, but there are more buffers in the acquisition.
                        }
                        else if (retCode == AlazarAPI.ApiTransferComplete)
                        {
                            // This buffer is full, and it's the last buffer of the acqusition.
                            done = true;
                        }
                        else
                        {
                            throw new System.Exception("Error: AlazarWaitNextAsyncBufferComplete failed -- " +
                                                       AlazarAPI.AlazarErrorToText(retCode));
                        }

                        buffersCompleted++;
                        bytesTransferred += bytesPerBuffer;

                        // TODO: Process sample data in this buffer.

                        // NOTE:
                        //
                        // While you are processing this buffer, the board is already
                        // filling the next available buffer(s).
                        //
                        // You MUST finish processing this buffer and post it back to the
                        // board before the board fills all of the available DMA buffers,
                        // and its on-board memory.
                        //
                        // Samples are arranged in the buffer as follows: S0A, S0B, ..., S1A, S1B, ...
                        // with SXY the sample number X of channel Y.
                        //
                        // Sample code are stored as 8-bit values.
                        //
                        // Sample codes are unsigned by default. As a result:
                        // - a sample code of 0x00 represents a negative full scale
                        // input signal.
                        // - a sample code of 0x80 represents a ~0V signal.
                        // - a sample code of 0xFF represents a positive full scale
                        // input signal.

                        if (saveData)
                        {
                            IntPtr pvBuffer = (IntPtr)pBuffer;
                            for (int channel = 0; (channel < channelCount) && (success == true); channel++)
                            {
                                for (UInt32 record = 0; (record < recordsPerBuffer) && (success == true);
                                     record++)
                                {
                                    // Get input range from ID
                                    double inputRange_volts =
                                        InputRangeIdToVolts(InputRangeIds[channel]);

                                    // AlazarTech boards are calibrated as follows
                                    double codeZero  = (1 << (bitsPerSample - 1)) - 0.5;
                                    double codeRange = (1 << (bitsPerSample - 1)) - 0.5;

                                    // Convert sample values to volts and write to file
                                    for (UInt32 sample = 0;
                                         (sample < samplesPerRecord) && (success == true); sample++)
                                    {
                                        // Convert code to volts
                                        double volts          = 0.0;
                                        int    sampleBitShift =
                                            (int)(8 * bytesPerSample - bitsPerSample + 0.5);
                                        UInt16 sampleValue = ((UInt16 *)pvBuffer)[channel * recordsPerBuffer * samplesPerRecord
                                                                                  + record * samplesPerRecord
                                                                                  + sample];
                                        UInt16 sampleCode = (UInt16)(sampleValue >> sampleBitShift);
                                        volts = inputRange_volts *
                                                ((double)(sampleCode - codeZero) / codeRange);

                                        // write value in volts to file
                                        fileStream.Write(BitConverter.GetBytes(volts), 0, 8);
                                    }
                                }
                            }
                        }
                        // If a key was pressed, exit the acquisition loop
                        if (Console.KeyAvailable == true)
                        {
                            Console.WriteLine("Aborted...");
                            done = true;
                        }

                        if (buffersCompleted >= buffersPerAcquisition)
                        {
                            done = true;
                        }

                        // Display progress
                        Console.Write("Completed {0} buffers\r", buffersCompleted);
                    }
                    // Display results

                    double transferTime_sec = ((double)(System.Environment.TickCount - startTickCount)) / 1000;

                    Console.WriteLine("Capture completed in {0:N3} sec", transferTime_sec);

                    UInt32 recordsTransferred = recordsPerBuffer * buffersCompleted;

                    double buffersPerSec;
                    double bytesPerSec;
                    double recordsPerSec;

                    if (transferTime_sec > 0)
                    {
                        buffersPerSec = buffersCompleted / transferTime_sec;
                        bytesPerSec   = bytesTransferred / transferTime_sec;
                        recordsPerSec = recordsTransferred / transferTime_sec;
                    }
                    else
                    {
                        buffersPerSec = 0;
                        bytesPerSec   = 0;
                        recordsPerSec = 0;
                    }

                    Console.WriteLine("Captured {0} buffers ({1:G4} buffers per sec)", buffersCompleted, buffersPerSec);
                    Console.WriteLine("Captured {0} records ({1:G4} records per sec)", recordsTransferred, recordsPerSec);
                    Console.WriteLine("Transferred {0} bytes ({1:G4} bytes per sec)", bytesTransferred, bytesPerSec);
                }
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.ToString());
                success = false;
            }
            finally
            {
                // Close the data file
                if (fileStream != null)
                {
                    fileStream.Close();
                }

                // Abort the acquisition
                retCode = AlazarAPI.AlazarAbortAsyncRead(boardHandle);
                if (retCode != AlazarAPI.ApiSuccess)
                {
                    Console.WriteLine("Error: AlazarAbortAsyncRead failed -- " +
                                      AlazarAPI.AlazarErrorToText(retCode));
                }
            }

            return(success);
        }
Exemple #2
0
        //----------------------------------------------------------------------------
        //
        // Function    :  Acquire data
        //
        // Description :  Acquire data from board, optionally saving data to file.
        //
        //----------------------------------------------------------------------------

        static public unsafe bool AcquireData(IntPtr boardHandle)
        {
            // TODO: Select the total acquisition length in seconds

            double acquisitionLength_sec = 1;

            UInt32 samplesPerBuffer = 204800;

            UInt32 channelMask = AlazarAPI.CHANNEL_A;

            // TODO: Select if you wish to save the sample data to a file
            bool saveData = false;

            // Calculate the number of enabled channels from the channel mask
            UInt32 channelCount = 0;

            switch (channelMask)
            {
            case AlazarAPI.CHANNEL_A:
            case AlazarAPI.CHANNEL_B:
                channelCount = 1;
                break;

            case AlazarAPI.CHANNEL_A | AlazarAPI.CHANNEL_B:
                channelCount = 2;
                break;

            default:
                Console.WriteLine("Error: Invalid channel mask -- {0}", channelMask);
                return(false);
            }

            // Get the sample size in bits, and the on-board memory size in samples per channel

            Byte   bitsPerSample;
            UInt32 maxSamplesPerChannel;
            UInt32 retCode = AlazarAPI.AlazarGetChannelInfo(boardHandle, &maxSamplesPerChannel, &bitsPerSample);

            if (retCode != AlazarAPI.ApiSuccess)
            {
                Console.WriteLine("Error: AlazarGetChannelInfo failed -- " +
                                  AlazarAPI.AlazarErrorToText(retCode));
                return(false);
            }

            // Calculate the size of each DMA buffer in bytes

            UInt32 bytesPerSample = ((UInt32)bitsPerSample + 7) / 8;
            UInt32 bytesPerBuffer = bytesPerSample * samplesPerBuffer * channelCount;

            // Calculate the number of buffers in the acquisition

            Int64 samplesPerAcquisition =
                (Int64)(samplesPerSec * acquisitionLength_sec + 0.5);
            UInt32 buffersPerAcquisition = (UInt32)(
                (samplesPerAcquisition + samplesPerBuffer - 1) / samplesPerBuffer);

            FileStream fileStream = null;
            bool       success    = true;

            try
            {
                // Create a data file if required

                if (saveData)
                {
                    fileStream = File.Create(@"data.bin");
                }

                // Allocate memory for sample buffer

                byte[] buffer = new byte[bytesPerBuffer];

                // Cast byte array to short array

                ByteToShortArray byteToShortArray = new ByteToShortArray();
                byteToShortArray.bytes = buffer;

                fixed(short *pBuffer = byteToShortArray.shorts)
                {
                    retCode =
                        AlazarAPI.AlazarBeforeAsyncRead(boardHandle,
                                                        channelMask,
                                                        0,           // Must be 0
                                                        samplesPerBuffer,
                                                        1,           // Must be 1
                                                        0x7FFFFFFF,  // Ignored. Behave as if infinite
                                                        AlazarAPI.ADMA_EXTERNAL_STARTCAPTURE | AlazarAPI.ADMA_CONTINUOUS_MODE | AlazarAPI.ADMA_FIFO_ONLY_STREAMING | AlazarAPI.ADMA_ALLOC_BUFFERS);
                    if (retCode != AlazarAPI.ApiSuccess)
                    {
                        throw new System.Exception("Error: AlazarBeforeAsyncRead failed -- " + AlazarAPI.AlazarErrorToText(retCode));
                    }

                    // Arm the board to begin the acquisition

                    retCode = AlazarAPI.AlazarStartCapture(boardHandle);
                    if (retCode != AlazarAPI.ApiSuccess)
                    {
                        throw new System.Exception("Error: AlazarStartCapture failed -- " +
                                                   AlazarAPI.AlazarErrorToText(retCode));
                    }

                    // Wait for each buffer to be filled, then process the buffer

                    Console.WriteLine("Capturing {0} buffers ... press any key to abort",
                                      buffersPerAcquisition);

                    int startTickCount = System.Environment.TickCount;

                    UInt32 buffersCompleted = 0;
                    Int64  bytesTransferred = 0;

                    bool done = false;

                    while (!done)
                    {
                        // TODO: Set a buffer timeout that is longer than the time
                        //       required to capture all the records in one buffer.

                        UInt32 timeout_ms = 5000;

                        // Wait for a buffer to be filled by the board.

                        retCode = AlazarAPI.AlazarWaitNextAsyncBufferComplete(boardHandle, pBuffer, bytesPerBuffer, timeout_ms);
                        if (retCode == AlazarAPI.ApiSuccess)
                        {
                            // This buffer is full, but there are more buffers in the acquisition.
                        }
                        else if (retCode == AlazarAPI.ApiTransferComplete)
                        {
                            // This buffer is full, and it's the last buffer of the acqusition.
                            done = true;
                        }
                        else
                        {
                            throw new System.Exception("Error: AlazarWaitNextAsyncBufferComplete failed -- " +
                                                       AlazarAPI.AlazarErrorToText(retCode));
                        }

                        buffersCompleted++;
                        bytesTransferred += bytesPerBuffer;

                        // TODO: Process sample data in this buffer.

                        // NOTE:
                        //
                        // While you are processing this buffer, the board is already
                        // filling the next available buffer(s).
                        //
                        // You MUST finish processing this buffer and post it back to the
                        // board before the board fills all of the available DMA buffers,
                        // and its on-board memory.
                        //
                        // Samples are arranged in the buffer as follows: S0A, S0B, ..., S1A, S1B, ...
                        // with SXY the sample number X of channel Y.
                        //
                        // A 12-bit sample code is stored in the most significant bits
                        // of
                        // in each 16-bit sample value.
                        //
                        // Sample codes are unsigned by default. As a result:
                        // - a sample code of 0x0000 represents a negative full scale
                        // input signal.
                        // - a sample code of 0x8000 represents a ~0V signal.
                        // - a sample code of 0xFFFF represents a positive full scale
                        // input signal.
                        if (saveData)
                        {
                            // Write record to file
                            fileStream.Write(buffer, 0, (int)bytesPerBuffer);
                        }
                        // If a key was pressed, exit the acquisition loop
                        if (Console.KeyAvailable == true)
                        {
                            Console.WriteLine("Aborted...");
                            done = true;
                        }

                        if (buffersCompleted >= buffersPerAcquisition)
                        {
                            done = true;
                        }

                        // Display progress
                        Console.Write("Completed {0} buffers\r", buffersCompleted);
                    }
                    // Display results

                    double transferTime_sec = ((double)(System.Environment.TickCount - startTickCount)) / 1000;

                    Console.WriteLine("Capture completed in {0:N3} sec", transferTime_sec);

                    double buffersPerSec;
                    double bytesPerSec;

                    if (transferTime_sec > 0)
                    {
                        buffersPerSec = buffersCompleted / transferTime_sec;
                        bytesPerSec   = bytesTransferred / transferTime_sec;
                    }
                    else
                    {
                        buffersPerSec = 0;
                        bytesPerSec   = 0;
                    }

                    Console.WriteLine("Captured {0} buffers ({1:G4} buffers per sec)", buffersCompleted, buffersPerSec);
                    Console.WriteLine("Transferred {0} bytes ({1:G4} bytes per sec)", bytesTransferred, bytesPerSec);
                }
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.ToString());
                success = false;
            }
            finally
            {
                // Close the data file
                if (fileStream != null)
                {
                    fileStream.Close();
                }

                // Abort the acquisition
                retCode = AlazarAPI.AlazarAbortAsyncRead(boardHandle);
                if (retCode != AlazarAPI.ApiSuccess)
                {
                    Console.WriteLine("Error: AlazarAbortAsyncRead failed -- " +
                                      AlazarAPI.AlazarErrorToText(retCode));
                }
            }

            return(success);
        }
Exemple #3
0
        //----------------------------------------------------------------------------
        //
        // Function    :  Acquire data
        //
        // Description :  Acquire data from board, optionally saving data to file.
        //
        //----------------------------------------------------------------------------

        static public unsafe bool AcquireData(IntPtr boardHandle)
        {
            // TODO: Select the number of pre-trigger samples per record

            UInt32 preTriggerSamples = 1024;

            // TODO: Select the number of post-trigger samples per record

            UInt32 postTriggerSamples = 1024;

            // TODO: Specify the number of records to acquire to on-board memory

            UInt32 recordsPerCapture = 100;

            // TODO: Select the amount of time, in seconds, to wait for the
            //       acquisiton to complete to on-board memory.

            int timeout_ms = 10 * 1000;


            // TODO: Select which channels to capture (A, B, or both)

            UInt32 channelMask = AlazarAPI.CHANNEL_A | AlazarAPI.CHANNEL_B;

            // TODO: Select if you wish to save the sample data to a file

            bool saveData = false;

            // Calculate the number of enabled channels from the channel mask

            UInt32 channelCount = 0;

            switch (channelMask)
            {
            case AlazarAPI.CHANNEL_A:
            case AlazarAPI.CHANNEL_B:
                channelCount = 1;
                break;

            case AlazarAPI.CHANNEL_A | AlazarAPI.CHANNEL_B:
                channelCount = 2;
                break;

            default:
                Console.WriteLine("Error: Invalid channel mask -- {0}", channelMask);
                return(false);
            }

            // Get the sample size in bits, and the on-board memory size in samples per channel

            Byte   bitsPerSample;
            UInt32 maxSamplesPerChannel;
            UInt32 retCode = AlazarAPI.AlazarGetChannelInfo(boardHandle, &maxSamplesPerChannel, &bitsPerSample);

            if (retCode != AlazarAPI.ApiSuccess)
            {
                Console.WriteLine("Error: AlazarGetChannelInfo failed -- " +
                                  AlazarAPI.AlazarErrorToText(retCode));
                return(false);
            }

            // Calculate the size of each DMA buffer in bytes

            UInt32 bytesPerSample   = ((UInt32)bitsPerSample + 7) / 8;
            UInt32 samplesPerRecord = preTriggerSamples + postTriggerSamples;
            UInt32 bytesPerRecord   = bytesPerSample * samplesPerRecord;

            // Calculate the size of a record buffer in bytes
            // Note that the buffer must be at least 16 samples larger than the transfer size

            UInt32 bytesPerBuffer = bytesPerSample * (samplesPerRecord + 0);

            // Configure the record size

            retCode =
                AlazarAPI.AlazarSetRecordSize(
                    boardHandle,
                    preTriggerSamples,
                    postTriggerSamples
                    );
            if (retCode != AlazarAPI.ApiSuccess)
            {
                Console.WriteLine("Error: AlazarSetRecordSize failed -- " + AlazarAPI.AlazarErrorToText(retCode));
                return(false);
            }

            // Configure the number of records in the acquisition

            retCode = AlazarAPI.AlazarSetRecordCount(boardHandle, recordsPerCapture);
            if (retCode != AlazarAPI.ApiSuccess)
            {
                Console.WriteLine("Error: AlazarSetRecordCount failed -- " + AlazarAPI.AlazarErrorToText(retCode));
                return(false);
            }

            // Arm the board to wait for a trigger event to begin the acquisition

            retCode = AlazarAPI.AlazarStartCapture(boardHandle);
            if (retCode != AlazarAPI.ApiSuccess)
            {
                Console.WriteLine("Error: AlazarStartCapture failed -- " + AlazarAPI.AlazarErrorToText(retCode));
                return(false);
            }

            // Wait for the board to capture all records to on-board memory

            Console.WriteLine("Capturing {0} record ... press any key to abort",
                              recordsPerCapture);

            int startTickCount   = System.Environment.TickCount;
            int timeoutTickCount = startTickCount + timeout_ms;

            bool success = true;

            while (AlazarAPI.AlazarBusy(boardHandle) != 0 && success == true)
            {
                if (System.Environment.TickCount > timeoutTickCount)
                {
                    Console.WriteLine("Error: Capture timeout after {0} ms", timeout_ms);
                    success = false;
                }
                else if (System.Console.KeyAvailable == true)
                {
                    Console.WriteLine("Acquisition aborted");
                    success = false;
                }
                else
                {
                    System.Threading.Thread.Sleep(10);
                }
            }

            if (!success)
            {
                // Abort the acquisition
                retCode = AlazarAPI.AlazarAbortCapture(boardHandle);
                if (retCode != AlazarAPI.ApiSuccess)
                {
                    Console.WriteLine("Error: AlazarAbortCapture failed -- " + AlazarAPI.AlazarErrorToText(retCode));
                }
                return(false);
            }

            // The board captured all records to on-board memory

            double captureTime_sec = ((double)(System.Environment.TickCount - startTickCount)) / 1000;

            double recordsPerSec;

            if (captureTime_sec > 0)
            {
                recordsPerSec = recordsPerCapture / captureTime_sec;
            }
            else
            {
                recordsPerSec = 0;
            }

            Console.WriteLine("Captured {0} records in {1:N3} sec ({2:N3} records / sec)",
                              recordsPerCapture, captureTime_sec, recordsPerSec);

            FileStream fs = null;

            startTickCount = System.Environment.TickCount;
            UInt64 bytesTransferred = 0;

            try
            {
                // Create a data file if required

                if (saveData)
                {
                    fs = File.Create(@"data.bin");
                }

                // Allocate memory for one record

                byte[] buffer = new byte[bytesPerBuffer + 16];

                // Cast byte array to short array

                ByteToShortArray byteToShortArray = new ByteToShortArray();
                byteToShortArray.bytes = buffer;

                fixed(short *pBuffer = byteToShortArray.shorts)
                {
                    // Transfer the records from on-board memory to our buffer

                    Console.WriteLine("Transferring {0} records ... press any key to cancel", recordsPerCapture);

                    UInt32 record;

                    for (record = 0; record < recordsPerCapture; record++)
                    {
                        for (int channel = 0; channel < channelCount; channel++)
                        {
                            // Find the current channel Id

                            UInt32 channelId;
                            if (channelCount == 1)
                            {
                                if ((channelMask & AlazarAPI.CHANNEL_A) != 0)
                                {
                                    channelId = AlazarAPI.CHANNEL_A;
                                }
                                else
                                {
                                    channelId = AlazarAPI.CHANNEL_B;
                                }
                            }
                            else
                            {
                                if (channel == 0)
                                {
                                    channelId = AlazarAPI.CHANNEL_A;
                                }
                                else
                                {
                                    channelId = AlazarAPI.CHANNEL_B;
                                }
                            }

                            // Transfer one full record from on-board memory to our buffer

                            retCode =
                                AlazarAPI.AlazarRead(
                                    boardHandle,
                                    channelId,
                                    pBuffer,
                                    (int)bytesPerSample,
                                    (int)record + 1,
                                    -((int)preTriggerSamples),
                                    samplesPerRecord
                                    );
                            if (retCode != AlazarAPI.ApiSuccess)
                            {
                                throw new System.Exception("Error: AlazarRead record  -- " +
                                                           AlazarAPI.AlazarErrorToText(retCode));
                            }

                            bytesTransferred += bytesPerRecord;

                            // TODO: Process record here.
                            //
                            // A 12-bit sample code is stored in the most significant bits
                            // of
                            // in each 16-bit sample value.
                            //
                            // Sample codes are unsigned by default. As a result:
                            // - a sample code of 0x0000 represents a negative full scale
                            // input signal.
                            // - a sample code of 0x8000 represents a ~0V signal.
                            // - a sample code of 0xFFFF represents a positive full scale
                            // input signal.
                            if (saveData)
                            {
                                // Write record to file
                                fs.Write(buffer, 0, (int)bytesPerRecord);
                            }
                        }

                        // If a key was pressed, then stop processing records.

                        if (Console.KeyAvailable == true)
                        {
                            throw new System.Exception("Error: Transfer aborted");
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.ToString());
                success = false;
            }
            finally
            {
                // Close the data file
                if (fs != null)
                {
                    fs.Close();
                }
            }

            // Display results

            double transferTime_sec = ((double)(System.Environment.TickCount - startTickCount)) / 1000;

            double bytesPerSec;

            if (transferTime_sec > 0)
            {
                bytesPerSec = bytesTransferred / transferTime_sec;
            }
            else
            {
                bytesPerSec = 0;
            }

            Console.WriteLine("Transferred {0} bytes ({1:G4} bytes per sec)", bytesTransferred, bytesPerSec);

            return(success);
        }