/// <summary> /// Get fundamental information about the device. /// </summary> /// <exception cref="RtlSdrLibraryExecutionException"></exception> private static DeviceInfo GetDeviceInfo(uint deviceIndex) { // Create buffers, where the results will be stored. var serialBuffer = new StringBuilder(256); var manufacturerBuffer = new StringBuilder(256); var productBuffer = new StringBuilder(256); // Get the device name. var nameBufferPtr = RtlSdrLibraryWrapper.rtlsdr_get_device_name(deviceIndex); var nameBuffer = Marshal.PtrToStringUTF8(nameBufferPtr); // Get the other data of the device. var returnCode = RtlSdrLibraryWrapper.rtlsdr_get_device_usb_strings(deviceIndex, manufacturerBuffer, productBuffer, serialBuffer); if (returnCode != 0) { throw new RtlSdrLibraryExecutionException( "Problem happened during reading USB strings of the device. " + $"Error code: {returnCode}, device index: {deviceIndex}."); } // If everything is good, fill the device info. return(new DeviceInfo(deviceIndex, serialBuffer.ToString(), manufacturerBuffer.ToString(), productBuffer.ToString(), nameBuffer)); }
/// <summary> /// Stop reading samples from the device. /// </summary> public void StopReadSamplesAsync() { // Check the worker thread. if (_asyncWorker == null) { return; } // Cancel the reading with the native function. var returnCode = RtlSdrLibraryWrapper.rtlsdr_cancel_async(_devicePointer); // If we did not get 0, there is an error. if (returnCode != 0) { throw new RtlSdrLibraryExecutionException( "Problem happened during stopping asynchronous data reading. " + $"Error code: {returnCode}, device index: {DeviceInfo.Index}."); } // Stop the worker thread. if (_asyncWorker.ThreadState == ThreadState.Running) { _asyncWorker.Join(); } // Release the worker. _asyncWorker = null; // Empty the buffer. _asyncBuffer = null; }
/// <summary> /// Read samples (I/Q) from the device. /// </summary> /// <param name="requestedSamples">Amount of requested samples.</param> /// <returns>I/Q data from the device as an IqData list.</returns> /// <exception cref="RtlSdrLibraryExecutionException"></exception> public List <IQData> ReadSamples(int requestedSamples) { // I/Q data means 2 bytes. var requestedBytes = requestedSamples * 2; // Initialize the buffer. var buffer = new byte[requestedBytes]; var bufferPinned = GCHandle.Alloc(buffer, GCHandleType.Pinned); var bufferPointer = bufferPinned.AddrOfPinnedObject(); // Read the ubytes from the device. var returnCode = RtlSdrLibraryWrapper.rtlsdr_read_sync(_devicePointer, bufferPointer, requestedBytes, out var receivedBytes); // Overflow happened. if (returnCode == -8) { throw new RtlSdrLibraryExecutionException( "Problem happened during reading bytes from the device (overflow, device provided more data). " + $"Error code: {returnCode}, requested bytes: {requestedBytes}, device index: {DeviceInfo.Index}."); } // Error happened during reading the data. if (returnCode != 0) { throw new RtlSdrLibraryExecutionException( "Problem happened during reading bytes from the device. " + $"Error code: {returnCode}, requested bytes: {requestedBytes}, device index: {DeviceInfo.Index}."); } // Amount of the received bytes is different than the requested. if (receivedBytes != requestedBytes) { throw new RtlSdrLibraryExecutionException( "Problem happened during reading bytes from the device. " + $"Error code: {returnCode}, requested bytes: {requestedBytes}, " + $"received bytes: {receivedBytes}, device index: {DeviceInfo.Index}."); } // Release the memory object. bufferPinned.Free(); // Convert byte array to IqData list. var iqData = new List <IQData>(); for (var i = 0; i < buffer.Length; i += 2) { iqData.Add(new IQData(buffer[i], buffer[i + 1])); } // Return the IqData list. return(iqData); }
/// <summary> /// Get fundamental information about all the devices on the system. /// </summary> /// <returns></returns> /// <exception cref="RtlSdrDeviceException"></exception> private static Dictionary <uint, DeviceInfo> GetAllDeviceInfo() { // Check the number of the devices on the system. var deviceCount = RtlSdrLibraryWrapper.rtlsdr_get_device_count(); // If there is no device on the system, throw an exception. if (deviceCount == 0) { throw new RtlSdrDeviceException("There is no supported RTL-SDR device on the system."); } // Create the list, which will contain the devices. var devices = new Dictionary <uint, DeviceInfo>(); // Iterate the devices. for (uint i = 0; i < deviceCount; i++) { // If everything is good, add the device to the list. devices.Add(i, GetDeviceInfo(i)); } // Return the list. return(devices); }
/// <summary> /// Create an instance of managed RTL-SDR device. /// </summary> /// <param name="deviceInfo">Fundamental information of the device.</param> internal RtlSdrManagedDevice(DeviceInfo deviceInfo) { // Store the index number of the device. _deviceIndex = deviceInfo.Index; // Get the other data of the device. var returnCode = RtlSdrLibraryWrapper.rtlsdr_open(out _devicePointer, _deviceIndex); // The index doesn't exists on the system. if (returnCode == -1) { throw new RtlSdrLibraryExecutionException( "RTL-SDR device cannot be found with the given index. " + $"Error code: {returnCode}, device index: {_deviceIndex}."); } // The device is already managed. if (returnCode == -6) { throw new RtlSdrLibraryExecutionException( "The RTL-SDR device is already managed (opened). " + $"Error code: {returnCode}, device index: {_deviceIndex}."); } // Other error was happened. if (returnCode != 0) { throw new RtlSdrLibraryExecutionException( "Problem happened during reading opening the RTL-SDR device. " + $"Error code: {returnCode}, device index: {_deviceIndex}."); } // Set the device context. _deviceContext = GCHandle.Alloc(this); // Set the tuner gain mode to automatic. // The initialization is necessary, to be sure that it will happen once. TunerGainMode = TunerGainModes.AGC; // Set the AGC mode to disabled. // The initialization is necessary, to be sure that it will happen once. AGCMode = AGCModes.Disabled; // Set the test mode to disabled. // The initialization is necessary, to be sure that it will happen once. TestMode = TestModes.Disabled; // Set the bandwidth selection mode to automatic. // The initialization is necessary, to be sure that it will happen once. TunerBandwidthSelectionMode = TunerBandwidthSelectionModes.Automatic; // Set the default value of maximum async I/Q buffer. // The initialization is necessary, to be sure that it will happen once. MaxAsyncBufferSize = AsyncDefaultReadLength * 4; // Set the default value of behavior when the buffer is full. // The initialization is necessary, to be sure that it will happen once. DropSamplesOnFullBuffer = false; // Run GetDeviceInfo to put fundamental data of device to the cache. DeviceInfo = deviceInfo; }
/// <summary> /// Worker method to asynchronously read data from the RTL-SDR device. /// </summary> /// <exception cref="RtlSdrLibraryExecutionException"></exception> private void SamplesAsyncReader(object readLength) { // Read from device. RtlSdrLibraryWrapper.rtlsdr_read_async(_devicePointer, _asyncCallback, (IntPtr)_deviceContext, 0, (uint)readLength); }