Пример #1
0
 //==============================================================================================
 /// <summary>
 /// Synchronizes access to the bulk in ready buffers queue
 /// </summary>
 /// <param name="bulkInBuffer">The buffer to queue</param>
 /// <param name="queueAction">The actions to take (enqueue or dequeue)</param>
 /// <returns>The buffer that was dequeued</returns>
 //==============================================================================================
 internal BulkInBuffer QueueBulkInReadyBuffers(BulkInBuffer bulkInBuffer, QueueAction queueAction)
 {
     lock (m_bulkInReadyBuffersLock)
     {
         if (queueAction == QueueAction.Enqueue)
         {
             m_bulkInReadyBuffers.Enqueue(bulkInBuffer);
             return null;
         }
         else
         {
             if (m_bulkInReadyBuffers.Count > 0)
             {
                 return m_bulkInReadyBuffers.Dequeue();
             }
             else
             {
                 return null;
             }
         }
     }
 }
Пример #2
0
 //==============================================================================================
 /// <summary>
 /// Virtual method for a USB Bulk IN request
 /// </summary>
 /// <param name="buffer">The buffer to receive the data</param>
 /// <param name="bytesReceived">The number of actual bytes received</param>
 /// <returns>The result</returns>
 //==============================================================================================
 internal abstract ErrorCodes UsbBulkInRequest(ref BulkInBuffer buffer, ref uint bytesReceived);
Пример #3
0
 //==============================================================================================
 /// <summary>
 /// Synchronizes access to the bulk in completed buffers queue
 /// </summary>
 /// <param name="bulkInBuffer">The buffer to queue</param>
 /// <param name="queueAction">The actions to take (enqueue or dequeue)</param>
 /// <returns>The buffer that was dequeued</returns>
 //==============================================================================================
 internal BulkInBuffer QueueBulkInCompletedBuffers(BulkInBuffer bulkInBuffer, QueueAction queueAction)
 {
     lock (m_bulkInCompletedBuffersLock)
     {
         try
         {
             if (queueAction == QueueAction.Enqueue)
             {
                 m_bulkInCompletedBuffers.Enqueue(bulkInBuffer);
                 return null;
             }
             else
             {
                 if (m_bulkInCompletedBuffers.Count > 0)
                 {
                     return m_bulkInCompletedBuffers.Dequeue();
                 }
                 else
                 {
                     return null;
                 }
             }
         }
         catch (Exception ex)
         {
             System.Diagnostics.Debug.Assert(false, ex.Message);
             return null;
         }
     }
 }
Пример #4
0
        //==============================================================================================
        /// <summary>
        /// Virtual method for a USB Bulk IN request
        /// </summary>
        /// <param name="buffer">The buffer to receive the data</param>
        /// <param name="bytesRequested">The number of bytes to requested</param>
        /// <param name="bytesReceived">The number of actual bytes received</param>
        /// <returns>The result</returns>
        //==============================================================================================
        internal override ErrorCodes UsbBulkInRequest(ref BulkInBuffer buffer, ref uint bytesReceived)
        {
            ErrorCodes result;
            BulkInBuffer bulkInBuffer = null;

            do
            {
                result = m_inputScanErrorCode;

                if (result != ErrorCodes.NoErrors)
                    break;

                bulkInBuffer = QueueBulkInCompletedBuffers(null, QueueAction.Dequeue);

                if (bulkInBuffer == null)
                    Thread.Sleep(1);

            } while (bulkInBuffer == null && !m_stopInputTransfers);

            if (bulkInBuffer != null)
            {
                buffer = bulkInBuffer;
                bytesReceived = (uint)bulkInBuffer.Length;
            }
            else
            {
                buffer = null;
                bytesReceived = 0;
            }

            return result;
        }
Пример #5
0
        //=============================================================================================================
        /// <summary>
        /// Sets up parameters for bulk in transfers
        /// </summary>
        /// <param name="scanRate">The device scan rate</param>
        /// <param name="totalNumberOfBytes">The total number of bytes to transfer</param>
        /// <param name="transferSize">The number of bytes in each transfer request</param>
        //=============================================================================================================
        internal override void PrepareInputTransfers(double scanRate, int totalNumberOfBytes, int transferSize)
        {
            m_errorCode = ErrorCodes.NoErrors;

            m_expectedInputTransferIndex = 0;

            m_totalNumberOfInputBytesRequested = totalNumberOfBytes;

            m_completedBulkInRequestBuffers.Clear();
            
            //For the 1208FS/1408FS, packets get mixed up at high rates in SINGLEIO mode. So,
            // only allow 1 packet to be in process
            int maxWorkingInputRequests = (transferSize==2 ? 2 : 8);
            if (m_criticalParams.InputSampleMode == SampleMode.Finite)
            {
                m_numberOfWorkingInputRequests = Math.Min(maxWorkingInputRequests, Math.Max(1, totalNumberOfBytes / transferSize));

                m_numberOfQueuedInputRequests = Math.Max(1, m_numberOfWorkingInputRequests / 2);
            }
            else
            {
               m_numberOfWorkingInputRequests = maxWorkingInputRequests;
               m_numberOfQueuedInputRequests =  Math.Max(1,maxWorkingInputRequests/2);
            }

            if (m_criticalParams.InputTransferMode == TransferMode.SingleIO)
            {
                int byteRatio = m_criticalParams.DataInXferSize;

                    // for single io mode at higher rates the packets could get out of order between the kernel driver
                    // and user mode so only use one request buffer...
                m_numberOfWorkingInputRequests = 1;
                m_numberOfQueuedInputRequests = 1;

                m_totalNumberOfInputRequests = totalNumberOfBytes / (byteRatio * m_criticalParams.NumberOfSamplesForSingleIO);
            }
            else
            {
                if (totalNumberOfBytes <= transferSize)
                    m_totalNumberOfInputRequests = 1;
                else
                    m_totalNumberOfInputRequests = (int)Math.Ceiling((double)totalNumberOfBytes / (double)transferSize);
            }

            // the device will send a zero-length packet after the last data packet if
            // the number of bytes is a multiple of the packet size so add an extra request (or is it the transfer size)
            //if ((totalNumberOfBytes % m_criticalParams.InputPacketSize == 0) || 
            //    (m_criticalParams.InputTransferMode == TransferMode.SingleIO && m_criticalParams.Requires0LengthPacketForSingleIO))
            //{
            //    m_totalNumberOfInputRequests++;

            //    if (m_numberOfWorkingInputRequests == 1)// && m_criticalParams.NumberOfSamplesForSingleIO > 1)
            //        m_numberOfWorkingInputRequests++;
            //}

            m_stopInputTransfers = false;

            int numberOfBulkInCopyBuffers = 50;

            // empty the bulkInReadyBuffers queue
            while (m_bulkInReadyBuffers.Count > 0)
            {
                BulkInBuffer buffer = m_bulkInReadyBuffers.Dequeue();
                new WeakReference(buffer, false);
                buffer = null;
            }

            // empty the bulkInCompletedBuffers queue
            while (m_bulkInCompletedBuffers.Count > 0)
            {
                BulkInBuffer buffer = m_bulkInCompletedBuffers.Dequeue();
                new WeakReference(buffer, false);
                buffer = null;
            }
            
            //GC.Collect();

            for (int i = 0; i < numberOfBulkInCopyBuffers; i++)
            {
                QueueBulkInReadyBuffers(new BulkInBuffer(transferSize), QueueAction.Enqueue);
            }

                // create the holding queue base on the number of working requests...
            m_holdingBuffer = new BulkInBuffer[m_numberOfWorkingInputRequests];

            for (int i = 0; i < m_numberOfWorkingInputRequests; i++)
            {
                    // initialize to null...
                m_holdingBuffer[i] = null;
            }

            m_temporaryBuffer = new List<BulkInBuffer>();

                // create the bulk in request objects that will be used in the transfers...
            CreateBulkInputRequestObjects(transferSize);

                // reset the sumbitted and completed counts...
            m_numberOfInputRequestsSubmitted = 0;
            m_numberOfInputRequestsCompleted = 0;

                // queue bulk in requests - at this point the device has not yet started..
            QueueBulkInRequests(scanRate);
        }
Пример #6
0
 //=============================================================================================================
 /// <summary>
 /// Virtual method for a USB Bulk IN request
 /// </summary>
 /// <param name="buffer">The buffer to receive the data</param>
 /// <param name="bytesRequested">The number of bytes to requested</param>
 /// <param name="bytesReceived">The number of actual bytes received</param>
 /// <returns>The result</returns>
 //=============================================================================================================
 internal override ErrorCodes UsbBulkInRequest(ref BulkInBuffer buffer, ref uint bytesReceived)
 {
     System.Diagnostics.Debug.Assert(false, "UsbBulkInRequest must be implemented in a derived class");
     buffer = null;
     bytesReceived = 0;
     return ErrorCodes.MethodRequiresImplementation;
 }
Пример #7
0
        //====================================================================
        /// <summary>
        /// Processes bulk read requests for input scan on a separate thread
        /// This method will copy bulk in request buffers to an internal
        /// managed buffer or an extenral unmanaged buffer
        /// </summary>
        //====================================================================
        protected void ProcessInputScanThread()
        {
            System.Diagnostics.Debug.Assert(m_criticalParams.BulkInXferSize != 0);

            bool usingInternalBuffer = true;

            //if (m_onAcquisitionArmedCallbackControl != null)
            //    m_onAcquisitionArmedCallback = new CallbackDelegate(m_onAcquisitionArmedCallbackControl.NotifyApplication);

            if (m_onDataAvailableCallbackControl != null)
                m_onDataAvailableCallback = new CallbackDelegate(m_onDataAvailableCallbackControl.NotifyApplication);

            if (m_onInputScanCompleteCallbackControl != null)
                m_onInputScanCompleteCallback = new CallbackDelegate(m_onInputScanCompleteCallbackControl.NotifyApplication);

            if (m_onInputScanErrorCallbackControl != null)
                m_onInputScanErrorCallback = new CallbackDelegate(m_onInputScanErrorCallbackControl.NotifyApplication);

            int triggerRearmByteCount = 0;
            int readBufferLength;
            int callbackCount = 0;
            int rearmTriggerCount = 0;

            m_availableSamplesForCallbackSinceStartOfScan = 0;
            m_terminateCallbacks = false;

            m_totalBytesReceived = 0;

            if (m_onDataAvailableCallbackControl != null || m_onInputScanErrorCallbackControl != null || m_onInputScanCompleteCallbackControl != null)
            {
                TerminateCallbacks = false;

                    // the other callback controls may be instantiated but this may not be...
                if (m_onDataAvailableCallbackControl != null)
                {
                    m_onDataAvailableCallbackControl.Abort = false;
                }
                    // start the callback thread...
                m_callbackThread = new Thread(new ThreadStart(ProcessCallbackThread));
                m_callbackThread.Name = "[DAQFlex]: InputScanCallbackThread";
                m_callbackThread.Start();
            }

            unsafe
            {
                if (m_externalReadBuffer != null)
                    usingInternalBuffer = false;
            }

            // get the buffer size that the platform interop object calculates from the scan rate
            int optimalBufferSize = m_criticalParams.BulkInXferSize;

            int channelCount = m_criticalParams.AiChannelCount;

            m_totalBytesToRead = channelCount * (m_criticalParams.DataInXferSize * m_criticalParams.InputScanSamples);

            if (m_criticalParams.InputSampleMode == SampleMode.Continuous && !m_inputBufferSizeOverride)
                m_internalReadBuffer = new byte[2 * m_totalBytesToRead];

            if (usingInternalBuffer)
                readBufferLength = m_internalReadBuffer.Length;
            else
                readBufferLength = m_externalReadBufferSize;

            if (m_totalBytesToRead < optimalBufferSize)
            {
                optimalBufferSize = m_totalBytesToRead;
                m_criticalParams.BulkInXferSize = optimalBufferSize;
            }

            // give the device an opportunity to do device-specific stuff before starting
            m_daqDevice.BeginInputScan();

            if (m_criticalParams.InputTransferMode == TransferMode.SingleIO)
            {
                // single sample only
                optimalBufferSize = m_criticalParams.DataInXferSize * m_criticalParams.NumberOfSamplesForSingleIO;
                m_criticalParams.BulkInXferSize = optimalBufferSize;
            }

            if (m_onDataAvailableCallbackControl != null)
            {
                    // update the bulk transfer size so it closely matches the number of call back samples...
                optimalBufferSize = GetOptimalInputBufferSize(m_criticalParams.InputScanRate);
            }

            // the platform interop object will allocate and return the bulk read buffer
            m_bulkReadBuffer = null;

            //// give the device an opportunity to do device-specific stuff before starting
            //m_daqDevice.BeginInputScan();

            // this will queue one or more bulk in requests if the interop object supports asynchronous I/O
            m_platformInterop.PrepareInputTransfers(m_criticalParams.InputScanRate,
                                                    m_totalBytesToRead,
                                                    optimalBufferSize);

            //// were ready to send the start command so raise the acqusition armed event
            //if (m_onAcquisitionArmedCallbackControl != null && m_onAcquisitionArmedCallbackControl.Created)
            //{
            //    AcquisitionInfo acquisitionInfo = new AcquisitionInfo();
            //    acquisitionInfo.AiQueueEnabled = m_criticalParams.AiQueueEnabled;
            //    acquisitionInfo.AiScans = (optimalBufferSize / channelCount / sizeof(double));
            //    acquisitionInfo.InputScanRate = m_criticalParams.InputScanRate;
            //    acquisitionInfo.IsAiDataCalibrated = m_criticalParams.CalibrateAiData;

            //    if (m_onAcquisitionArmedCallbackControl.ExecuteOnUIThread)
            //    {
            //        m_acquisitionArmedCallbackParam[0] = acquisitionInfo;
            //        m_onAcquisitionArmedCallbackControl.BeginInvoke(m_onAcquisitionArmedCallback, m_acquisitionArmedCallbackParam);
            //    }
            //    else
            //    {
            //        m_acquisitionArmedCallbackParam[0] = acquisitionInfo;
            //        m_onAcquisitionArmedCallbackControl.NotifyApplication((int)m_acquisitionArmedCallbackParam[0]);
            //    }

            //}

            // this will start the device scan
            TransmitDeferredInputMessages();

            int numberOfBulkTransfersToExecute;
            uint bytesReceivedInCurrentTransfer = 0;
            uint totalBytesTransfered = 0;
            uint bytesToTransfer = 0;
            int deltaBytes = 0;

            while (ContinueProcessingInputScan(m_inputScanErrorCode))
            {
                bytesReceivedInCurrentTransfer = 0;
                totalBytesTransfered = 0;
                bytesToTransfer = 0;

                m_inputScanStatus = ScanState.Running;

                // if the bulk read buffer length is greater than the max transfer size, then we'll need multiple transfers
                numberOfBulkTransfersToExecute = (int)Math.Ceiling((double)optimalBufferSize / (double)m_platformInterop.MaxTransferSize);

                for (int i = 0; i < numberOfBulkTransfersToExecute; i++)
                {
                    // calculate the number of bytes to process in this transfer
                    if (m_criticalParams.InputTransferMode == TransferMode.SingleIO)
                        bytesToTransfer = (uint)(m_criticalParams.DataInXferSize * m_criticalParams.NumberOfSamplesForSingleIO);
                    else
                        bytesToTransfer = (uint)Math.Min(optimalBufferSize, (m_totalBytesToRead - (int)totalBytesTransfered));

                    // if the input scan is finite then check if this is the last transfer
                    if (m_criticalParams.InputSampleMode == SampleMode.Finite)
                    {
                        if (m_lastInputScanWriteIndex + bytesToTransfer > readBufferLength)
                            bytesToTransfer = (uint)(readBufferLength - m_lastInputScanWriteIndex) - 1;
                    }

                    //*********************************************************************************************************
                    // Read the data on the bulk in pipe
                    //*********************************************************************************************************
                    m_inputScanErrorCode = m_platformInterop.UsbBulkInRequest(ref m_bulkReadBuffer, ref bytesReceivedInCurrentTransfer);

                    // update the total number of bytes received
                    m_totalBytesReceived += (ulong)bytesReceivedInCurrentTransfer;

                    // m_bulkInReadBuffer could be null if the input scan was stopped with the Stop command

                    if (m_inputScanErrorCode == (int)ErrorCodes.NoErrors && m_bulkReadBuffer != null)
                    {
                        // update the total number of bytes transfered so far
                        totalBytesTransfered += bytesReceivedInCurrentTransfer;

                        try
                        {
                            if (m_criticalParams.DeltaRearmInputSamples > 0)
                            {
                                triggerRearmByteCount += (int)bytesToTransfer;

                                if (triggerRearmByteCount >= (m_criticalParams.DataInXferSize * channelCount * m_criticalParams.AdjustedRearmSamplesPerTrigger))
                                {
                                    rearmTriggerCount++;
                                    bytesToTransfer -= (uint)(m_criticalParams.DataInXferSize * channelCount * m_criticalParams.DeltaRearmInputSamples);
                                    m_totalBytesReceived -= (ulong)(m_criticalParams.DataInXferSize * channelCount * m_criticalParams.DeltaRearmInputSamples);
                                    triggerRearmByteCount = 0;
                                }
                            }

                            // upate the number of samples acquired so far per channel
                            lock (m_inputScanCountLock)
                            {
                                m_inputScanCount = (m_totalBytesReceived / (ulong)m_criticalParams.DataInXferSize) / (ulong)channelCount;

                                if (m_criticalParams.InputScanOverwrite)
                                {
                                    deltaBytes = m_criticalParams.DataInXferSize * (int)(m_inputScanCount - m_inputSamplesReadPerChannel);

                                    if (deltaBytes > readBufferLength)
                                    {
                                        m_inputScanErrorCode = ErrorCodes.InputBufferOverrun;
                                        continue;
                                    }
                                }
                            }

                            if (m_criticalParams.InputTransferMode == TransferMode.SingleIO)
                                callbackCount += ((int)bytesReceivedInCurrentTransfer / m_criticalParams.DataInXferSize) / m_criticalParams.NumberOfSamplesForSingleIO;
                            else
                                callbackCount += ((int)bytesReceivedInCurrentTransfer / m_criticalParams.DataInXferSize) / channelCount;

                            if (usingInternalBuffer)
                            {
                                int bytesToCopyOnFirstPass;
                                int bytesToCopyOnSecondPass;

                                if (m_lastInputScanWriteIndex + bytesToTransfer >= readBufferLength)
                                {
                                    // two passes are required since the current input scan write index
                                    // wrapped around to the beginning of the internal read buffer
                                    bytesToCopyOnFirstPass = readBufferLength - (m_lastInputScanWriteIndex + 1);
                                    bytesToCopyOnSecondPass = (int)bytesToTransfer - bytesToCopyOnFirstPass;
                                    m_inputBufferFilled = true;
                                }
                                else
                                {
                                    // only one pass is required since the current input scan write index
                                    // did not wrap around
                                    bytesToCopyOnFirstPass = (int)bytesToTransfer;
                                    bytesToCopyOnSecondPass = 0;
                                }

                                CopyToInternalReadBuffer(m_bulkReadBuffer.Data,
                                                         m_internalReadBuffer,
                                                         bytesToCopyOnFirstPass,
                                                         bytesToCopyOnSecondPass);
                            }
                            else
                            {
                                unsafe
                                {
                                    CopyToExternalReadBuffer(m_bulkReadBuffer.Data,
                                                             m_externalReadBuffer,
                                                             readBufferLength,
                                                             bytesToTransfer);
                                }
                            }

                            // calculate current index (some devices in SINGLEIO mode only transfer one channel per packet and the second calculation will always return 0)
                            if (m_criticalParams.InputTransferMode == TransferMode.SingleIO)
                                m_inputScanIndex = (long)Math.Max(0, (m_inputScanCount % (ulong)(readBufferLength / m_criticalParams.DataInXferSize)) - 1);
                            else
                                m_inputScanIndex = (long)Math.Max(0, (m_inputScanCount % (ulong)(readBufferLength / m_criticalParams.DataInXferSize)) - (ulong)channelCount);

                            // add the m_bulkReadBuffer to the ready buffers queue so it may be reused
                            m_platformInterop.QueueBulkInReadyBuffers(m_bulkReadBuffer, QueueAction.Enqueue);
                        }
                        catch (Exception ex)
                        {
                            System.Diagnostics.Debug.Assert(false, ex.Message);
                            m_inputScanErrorCode = ErrorCodes.UnknownError;
                        }

                        //*****************************************************************************************
                        // OnDataAvailable callback
                        //*****************************************************************************************
                        if (m_inputScanErrorCode == ErrorCodes.NoErrors)
                        {
                            if (m_onDataAvailableCallbackControl != null && m_onDataAvailableCallbackControl.Created)
                            {
                                if (m_criticalParams.InputSampleMode == SampleMode.Finite)
                                {
                                    if (m_totalBytesReceived >= (ulong)m_totalBytesToRead && m_totalBytesReceived > 0)
                                        TerminateCallbacks = true;
                                }
                            }
                        }
                    }
                }

                //*****************************************************************************************
                // OnInputScanError callback
                //*****************************************************************************************
                if (m_inputScanErrorCode != ErrorCodes.NoErrors)
                {
                    m_callbackInfoQueue.Clear();
                    TerminateCallbacks = true;
                }

                Thread.Sleep(0);
            }

            while (!m_platformInterop.InputScanComplete())
                Thread.Sleep(0);

            DebugLogger.WriteLine("Input scan complete");
            DebugLogger.StopWatch.Stop();
            //DebugLogger.DumpDebugInfo();

            if (m_inputScanErrorCode == ErrorCodes.DataOverrun)
                m_inputScanStatus = ScanState.Overrun;
            else
                m_inputScanStatus = ScanState.Idle;

            m_inputScanComplete = true;
            m_inputScanStarted = false;

                // give the device an opportunity to do device-specific stuff before stopping
                // THIS MUST BE DONE AFTER m_inputScanStatus HAS BEEN SET
            m_daqDevice.EndInputScan();

            if (m_callbackThread != null)
            {
                    // was a stop message sent?...
                if (m_stopInputScan)
                {
                        // Does the callback thread know to terminate?...
                    if (!TerminateCallbacks)
                    {
                            // Let it know...
                        TerminateCallbacks = true;
                    }
                }
            }

            m_errorCode = m_inputScanErrorCode;

                // set the DaqDevice's pending error so that it can handle it on the next message sent...
            if (m_errorCode != ErrorCodes.NoErrors && m_errorCode != ErrorCodes.DataOverrun)
            {
                m_daqDevice.SetPendingInputScanError(m_errorCode);
            }
        }