SDRSharper/Plugins/SDRSharper.RTLTCP/SDRSharp.RTLTCP/RtlTcpIO.cs

358 lines
6.2 KiB
C#
Raw Normal View History

using SDRSharp.Radio;
using System;
using System.Net.Sockets;
using System.Threading;
using System.Timers;
using System.Windows.Forms;
namespace SDRSharp.RTLTCP
{
public class RtlTcpIO : IFrontendController, IDisposable
{
private const double DEFAULT_SAMPLE_RATE = 2048000.0;
private const long DEFAULT_FREQUENCY = 100000000L;
private const string DEFAULT_HOSTNAME = "192.168.0.11";
private const int DEFAULT_PORT = 1234;
private const byte CMD_SET_FREQ = 1;
private const byte CMD_SET_SAMPLE_RATE = 2;
private const byte CMD_SET_GAIN_MODE = 3;
private const byte CMD_SET_GAIN = 4;
private const byte CMD_SET_FREQ_COR = 5;
public const uint GAIN_MODE_AUTO = 0u;
public const uint GAIN_MODE_MANUAL = 1u;
private const int BUFFER_SIZE = 16384;
private const int MAX_TUNE_RATE = 20;
private RTLTcpSettings _gui;
private volatile SamplesAvailableDelegate _callback;
private Thread _sampleThread;
private long _freq;
private double _sr;
private Socket _s;
private string _host;
private int _port;
private uint _gainMode;
private int _gainVal;
private int _fCor;
private UnsafeBuffer _b;
private bool _tunePlease;
private System.Timers.Timer _retuneTimer = new System.Timers.Timer(50.0);
public string hostName
{
get
{
return this._host;
}
set
{
this._host = value;
}
}
public int port
{
get
{
return this._port;
}
set
{
this._port = value;
}
}
public bool IsSoundCardBased => false;
public string SoundCardHint => string.Empty;
public double Samplerate
{
get
{
return this._sr;
}
set
{
this._sr = value;
this.sendCommand(2, (uint)this._sr);
}
}
public long Frequency
{
get
{
return this._freq;
}
set
{
this._freq = value;
lock (this._retuneTimer)
{
this._tunePlease = true;
}
}
}
public int Gain
{
get
{
return this._gainVal;
}
set
{
this._gainVal = value;
this.sendCommand(4, this._gainVal);
}
}
public uint GainMode
{
get
{
return this._gainMode;
}
set
{
this._gainMode = value;
this.sendCommand(3, this._gainMode);
}
}
public int FreqCorrection
{
get
{
return this._fCor;
}
set
{
this._fCor = value;
this.sendCommand(5, this._fCor);
}
}
private bool sendCommand(byte cmd, byte[] val)
{
if (this._s == null)
{
return false;
}
if (val.Length < 4)
{
return false;
}
byte[] buffer = new byte[5]
{
cmd,
val[3],
val[2],
val[1],
val[0]
};
try
{
this._s.Send(buffer);
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
return false;
}
}
private bool sendCommand(byte cmd, uint val)
{
byte[] bytes = BitConverter.GetBytes(val);
return this.sendCommand(cmd, bytes);
}
private bool sendCommand(byte cmd, int val)
{
byte[] bytes = BitConverter.GetBytes(val);
return this.sendCommand(cmd, bytes);
}
public RtlTcpIO()
{
this._freq = 100000000L;
this._sr = 2048000.0;
this._gainVal = 0;
this._gainMode = 0u;
this._host = "192.168.0.11";
this._port = 1234;
this._retuneTimer.Elapsed += this.retuneNow;
this._retuneTimer.Start();
}
~RtlTcpIO()
{
this.Dispose();
}
public void Dispose()
{
if (this._gui != null)
{
this._gui.Dispose();
this._gui = null;
}
GC.SuppressFinalize(this);
}
public void Open()
{
}
public void Close()
{
if (this._s != null)
{
this._s.Close();
this._s = null;
}
}
public unsafe void Start(SamplesAvailableDelegate callback)
{
lock (this)
{
this._callback = callback;
}
this._s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this._s.Connect(this._host, this._port);
this._sampleThread = new Thread((ThreadStart)delegate
{
this.receiveSamples();
});
this._sampleThread.Start();
this.sendCommand(3, this._gainMode);
this.sendCommand(2, (uint)this._sr);
this.sendCommand(1, (uint)this._freq);
this.sendCommand(5, this._fCor);
}
public unsafe void Stop()
{
lock (this)
{
this._callback = null;
}
this.Close();
if (this._sampleThread != null)
{
this._sampleThread.Join();
}
}
public void ShowSettingGUI(IWin32Window parent)
{
if (this._gui == null || this._gui.IsDisposed)
{
this._gui = new RTLTcpSettings(this);
}
this._gui.Show();
}
public void HideSettingGUI()
{
if (this._gui != null && !this._gui.IsDisposed)
{
this._gui.Hide();
}
}
private unsafe void receiveSamples()
{
byte[] buffer = new byte[17408];
int num = 0;
ulong num2 = 0uL;
DateTime now = DateTime.Now;
while (this._callback != null && this._s != null && this._s.Connected)
{
try
{
int num3 = this._s.Receive(buffer, num, 16384, SocketFlags.None);
num2 = (ulong)((long)num2 + (long)num3);
int num4 = num + num3;
num = num4 % 2;
this.beamUpThemSamples(buffer, num4 - num);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
this.Close();
break;
}
}
DateTime now2 = DateTime.Now;
TimeSpan timeSpan = now2 - now;
double num5 = (double)num2 / timeSpan.TotalSeconds;
double num6 = num5 / 2.0;
Console.WriteLine($"Received {num2} bytes over {timeSpan.TotalSeconds} seconds, which is {num5} bps or {num6} sps");
}
private unsafe void beamUpThemSamples(byte[] buffer, int len)
{
int num = len / 2;
if (this._b == null || this._b.Length < num)
{
this._b = UnsafeBuffer.Create(num, sizeof(Complex));
}
Complex* ptr = (Complex*)(void*)this._b;
for (int i = 0; i < num; i++)
{
ptr[i].Real = (float)(buffer[i * 2 + 1] - 128) * 0.0078125f;
ptr[i].Imag = (float)(buffer[i * 2] - 128) * 0.0078125f;
}
lock (this)
{
if (this._callback != null)
{
this._callback(this, ptr, num);
}
}
}
private void retuneNow(object source, ElapsedEventArgs e)
{
lock (this._retuneTimer)
{
if (this._tunePlease)
{
this.sendCommand(1, (uint)this._freq);
this._tunePlease = false;
}
}
}
}
}