//---------------------------------------------------------------------------- // // 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 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); 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); }
//---------------------------------------------------------------------------- // // Function : Acquire data // // Description : Acquire data from board, optionally saving data to file. // //---------------------------------------------------------------------------- static public unsafe bool AcquireData(IntPtr boardHandle, IntPtr fftHandle, UInt32 recordLength_samples) { UInt32 retCode; // TODO: Specify the number of records per DMA buffer UInt32 recordsPerBuffer = 10; // TODO: Specify the total number of buffers to capture UInt32 buffersPerAcquisition = 10; // Acquiring from a single channel UInt32 channelMask = AlazarAPI.CHANNEL_A; // TODO: Select if you wish to save the sample data to a file bool saveData = false; // TODO: Select the FFT output format AlazarAPI.FFT_OUTPUT_FORMAT outputFormat = AlazarAPI.FFT_OUTPUT_FORMAT.FFT_OUTPUT_FORMAT_U16_LOG; // TODO: Select the presence of NPT footers AlazarAPI.FFT_FOOTER footer = AlazarAPI.FFT_FOOTER.FFT_FOOTER_NONE; // Get the sample size in bits, and the on-board memory size in samples per channel Byte bitsPerSample; UInt32 maxSamplesPerChannel; retCode = AlazarAPI.AlazarGetChannelInfo( boardHandle, &maxSamplesPerChannel, &bitsPerSample ); if (retCode != AlazarAPI.ApiSuccess) { Console.WriteLine("Error: AlazarGetChannelInfo failed -- " + AlazarAPI.AlazarErrorToText(retCode)); return(false); } FileStream fileStream = null; bool success = true; try { // Create a data file if required if (saveData) { fileStream = File.Create(@"data.bin"); } // Configure the FFT UInt32 fftLength_samples = 1; while (fftLength_samples < recordLength_samples) { fftLength_samples *= 2; } UInt32 bytesPerOutputRecord; retCode = AlazarAPI.AlazarFFTSetup( fftHandle, (UInt16)channelMask, recordLength_samples, fftLength_samples, (UInt32)outputFormat, (UInt32)footer, 0, &bytesPerOutputRecord ); if (retCode != AlazarAPI.ApiSuccess) { throw new System.Exception("Error: AlazarFFTSetup failed -- " + AlazarAPI.AlazarErrorToText(retCode)); } UInt32 bytesPerBuffer = bytesPerOutputRecord * recordsPerBuffer; // 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 board to make an NPT_onFPGA_FFT acquisition UInt32 recordsPerAcquisition = recordsPerBuffer * buffersPerAcquisition; UInt32 admaFlags = AlazarAPI.ADMA_EXTERNAL_STARTCAPTURE | AlazarAPI.ADMA_NPT | AlazarAPI.ADMA_DSP | AlazarAPI.ADMA_FIFO_ONLY_STREAMING | AlazarAPI.ADMA_ALLOC_BUFFERS; retCode = AlazarAPI.AlazarBeforeAsyncRead( boardHandle, channelMask, 0, bytesPerOutputRecord, recordsPerBuffer, 0x7FFFFFFF, admaFlags ); 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). // 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); 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); }