I'm trying to integrate an old RFSpace SDR-IQ radio into an existing C# program. SDR-IQ info: http://www.rfspace.com/RFSPACE/SDR-IQ.html
The SDR-IQ connects to the PC via USB.
I've found a very old ActiveX control that successfully drops onto the C# dialog (after registering the DLL manually). ActiveX control: http://www.moetronix.com/files/sdr14xsdk127.zip
Here is the C# metadata for the control:
namespace AxSDR14XLib
{
[DefaultEvent("StatusChange")]
[DesignTimeVisible(true)]
public class AxSDR14X : AxHost
{
public AxSDR14X();
[DispId(12)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public virtual short BootRevision { get; set; }
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[DispId(1)]
public virtual int ClockFrequency { get; set; }
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[DispId(2)]
public virtual string DeviceName { get; set; }
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[DispId(3)]
public virtual int FirmwareRevision { get; set; }
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[DispId(4)]
public virtual int HFgain { get; set; }
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[DispId(5)]
public virtual int IFfilter { get; set; }
[DispId(10)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public virtual int IFgain { get; set; }
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[DispId(6)]
public virtual int InputSource { get; set; }
[DispId(7)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public virtual int InterfaceVersion { get; set; }
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[DispId(13)]
public virtual double IQOffset { get; set; }
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[DispId(8)]
public virtual int NCOfrequency { get; set; }
[DispId(11)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public virtual int SampleRate { get; set; }
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[DispId(9)]
public virtual string SerialNumber { get; set; }
public event _DSDR14XEvents_DataRdyEventHandler DataRdy;
public event _DSDR14XEvents_StatusChangeEventHandler StatusChange;
public event EventHandler UartDataRdy;
public virtual void AboutBox();
protected override void AttachInterfaces();
public virtual void CloseI2CPort();
public virtual void CloseSpiPort();
public virtual void CloseUartPort();
protected override void CreateSink();
protected override void DetachSink();
public virtual int GetDoubleData(ref double dataArray);
public virtual bool GetFftDoubleData(ref double dataArray);
public virtual bool GetFftScreendata(int plotHeght, int plotWidth, double maxdB, double mindB, int startFreq, int endFreq, ref int plotBuf);
public virtual int GetIntegerData(ref short dataArray);
public virtual int GetLongData(ref int dataArray);
public virtual short GetUartData(ref short uartRxArray);
public virtual void InitControl();
public virtual void OpenI2CPort(short adrWidth);
public virtual void OpenSpiPort(short clkPolarity);
public virtual void OpenUartPort(int baudRate, short parity, bool flowControl);
public virtual void ResetFftAverage();
public virtual void Send6620RawCmd(short address, short d0, short d1, short d2, short d3, short d4);
public virtual void SendI2CData(ref short txDataArray, short numDataItems);
public virtual void SendSpiData(int data32High, int data32Low, short numberBits);
public virtual void SendUartData(ref short uartTxArray, short numDataItems);
public virtual void SetupFFT(int fftPoints, short fftaverages, bool fftInverted);
public virtual void Start(short blocks, short mode);
public virtual void Stop();
}
The control's .InitControl()
and .Start()
methods work correctly. The StatusChange
and DataRdy
events also work. So, the control is successfully communicating with the radio.
The problem comes when I try to get the data out of the control in the DataRdy
event handler via .GetLongData()
.
Despite many hours of googling, no matter what I try, my code just crashes with the error:
The program '[9036] sdriq.vshost.exe: Managed (v4.0.30319)' has exited with code -1073741819 (0xc0000005).
There isn't any further detailed information about the crash in the Exception object.
Here's one example of a call to .GetLongData()
that fails:
private int[] m_SdrData = new int[40000];
private void axSDR14X1_DataRdy(object sender, AxSDR14XLib._DSDR14XEvents_DataRdyEvent e)
{
unsafe
{
var unmanagedArray = (int*)Marshal.AllocHGlobal(m_SdrData.Length * sizeof(int));
int samples = axSDR14X1.GetLongData(ref unmanagedArray[0]);
for (int i = 0; i < m_SdrData.Length; i++) m_SdrData[i] = unmanagedArray[i];
Marshal.FreeHGlobal((IntPtr)unmanagedArray);
}
}
The original author of the control did reply when I wrote to the address in the control's readme: "Yes the dll i wrote along time ago was an activex dll and I don't think uSoft allows passing memory pointers anymore. I don't know C# but I suspect it doesn't allow direct memory pointers either."
So though it's not explicitly stated, I'm 99% sure the control is written in C++.
I'm not very savvy when it comes to calling into C++ from C#. Given the signature of .GetLongData
shown above, I'm looking for help in finding the magical combination of unsafe
, IntPtr
, Marshal.AllocHGlobal
, etc., to get the radio's data from the unmanaged C++ ActiveX control into my managed C# code.
Thanks very much in advance for any help.
User contributions licensed under CC BY-SA 3.0