/// <summary> /// Generic digital data server for a given 32 bit port. The main data buffer that this class updates /// 'dataBuffer', itself a DigitalEventBuffer object.This method accepts a time range (in seconds referenced to the start of the recording) /// as input and will copy the portion of the current data buffer that is within that range to the user as a /// DigitalEventBuffer object. The EstimateAvailableTimeRange method can be used to get an estimate of a valide range /// to enter for a Read operation. If there is no data in the time range provided, the method returns a null object. /// </summary> /// <param name="sampleFrequencyHz"> Sampling frequency of the DAQ that is feeding this server</param> /// <param name="bufferSizeSec">The requested history of the buffer in seconds</param> /// <param name="numSamplesPerWrite"> How many samples will the DAQ provide when a Write is called?</param> public DigitalEventSrv(double sampleFrequencyHz, double bufferSizeSec, int numSamplesPerWrite) { this.sampleFrequencyHz = sampleFrequencyHz; this.dataBuffer = new DigitalEventBuffer(sampleFrequencyHz); this.numSamplesPerWrite = numSamplesPerWrite; this.bufferSizeInSamples = (int)Math.Ceiling(bufferSizeSec * sampleFrequencyHz); }
/// <summary> /// Write data to the Digital Event Server /// </summary> /// <param name="newData"> A digital event buffer containing the digital events to be added to the buffer.</param> internal void WriteToBuffer(DigitalEventBuffer newData) { lock (lockObj) { // First we must remove the expired samples (we cannot assume these are // in temporal order since for 64 channels, we have to write 2x, once for // each 32 channel recording task) int i = 0; while (i < dataBuffer.SampleBuffer.Count) { // Remove expired data if (dataBuffer.SampleBuffer.ElementAt(i) + (ulong)bufferSizeInSamples < currentSample) { dataBuffer.SampleBuffer.RemoveAt(i); dataBuffer.PortStateBuffer.RemoveAt(i); } } // Add new data dataBuffer.SampleBuffer.AddRange(newData.SampleBuffer); dataBuffer.PortStateBuffer.AddRange(newData.PortStateBuffer); // Update the most current sample read currentSample += (ulong)numSamplesPerWrite; } }
/// <summary> /// Read data from buffer. This method will attempt to retrieve samples within the range /// specified by the input arguements. The object that is returned /// will contain information on the true sample bounds. You can use the EstimateAvailableTimeRange /// method to get a (time-sensitive) estimate for good-arguments for this method. /// </summary> /// <param name="desiredStartIndex">earliest sample, referenced to 0, that should be returned</param> /// <param name="desiredStopIndex">latest sample, referenced to 0, that should be returned</param> /// <returns>DigitalEventBuffer</returns> internal DigitalEventBuffer ReadFromBuffer(ulong desiredStartIndex, ulong desiredStopIndex) { lock (lockObj) { DigitalEventBuffer returnBuffer = new DigitalEventBuffer(dataBuffer.SampleFrequencyHz); // Collect all the data within the desired sample range and add to the returnBuffer // object int i = 0; while (i < dataBuffer.SampleBuffer.Count) { if (dataBuffer.SampleBuffer.ElementAt(i) > desiredStartIndex && dataBuffer.SampleBuffer.ElementAt(i) <= desiredStopIndex) { returnBuffer.SampleBuffer.Add(dataBuffer.SampleBuffer.ElementAt(i)); returnBuffer.PortStateBuffer.Add(dataBuffer.PortStateBuffer.ElementAt(i)); } } // Return the data return returnBuffer; } }