|
Hi,
I have currently also just started to write a C# wrapper for the G313e. Things to consider for the if and audio - Stream callback are (if you don't allready know it anyway): Pin the delegates. Otherwise the app will jump into the void after the first relocation of the delegates due to garbage collection. One more thing is the marshalling of the if/audio data arrays in the callback. If you don't want to get "unsafe", you will most probably marshall them as LPArray. And there you have to give the size statically... Otherwise you will only get an array with rank 1 on the managed side.
Ciao
Roland
|
|
|
|
|
Hello Brov,
First of all can You plase give me your email address so that I can discuss My winradio project with you. ans send you my project to discuss..
I am working on the development of software derfined radio by using Winradio GR-303e receiver similar G313 I beleive the API is the same... 4 both
I am doing coding in C#. I have very serious issues while doing the IF codec straeming (CodecStart that uses delegates) and the G3BlockScan Function.
I hope u have overcome these problems because I am so fed up coz I have to submit this project on 8th of september but I could not mange to do any thing.
can we share our code or some thing..... like that
Please please it is very important for me .
THANKS
o O º(`'·.,(`'·., ☆,.·''),.·'')º O o°
»·'"`»* *☆ t4ure4n ☆* *«·'"`«
°o O º(,.·''(,.·'' ☆`'·.,)`'·.,)º O o°
|
|
|
|
|
sorry for disturbing you again...
I have seen the API for G 303e and G313 e receivers they have diggent APIs... coz the G 313e has its onboard DSP...
Do you have to write code to play the incoming signal or you can listen to it directly by calling API methods.
I have not found any methos i can in G303e API to directly listen to the Radio channel rather it stores the received data in the PCM file and treadds only bloicks no continuous streaming example.
What do you suggest what should I do for this problem
o O º(`'·.,(`'·., ☆,.·''),.·'')º O o°
»·'"`»* *☆ t4ure4n ☆* *«·'"`«
°o O º(,.·''(,.·'' ☆`'·.,)`'·.,)º O o°
|
|
|
|
|
I dont know about the 303e. But the 313e doesn't have an audio plug. All data is delivered to the computer via USB. So, the G313e api does not have any Methods that allow you to play the incoming data directly. But, as you have seen, you can define callbacks to which the received audio and IF data is delivered by the API. In Principal, it is the same concept as recording audio data from a soundcard. There you also use a callback mechanism. Not directly via a Callback, but via events. But the result is the same. When your callback is activated by the winradio api, you are free to do with the received data whatever you want. E.g. redirect the data to your own streaming mechanism that transfers the data to the soundcard so you can listen to it. But to do so, you would have to read a little bit about DirectSound and its mechanisms.
Actually, why i started my project was the need to have direct access to the audio data to do decoding of the one or other digital mode. But as soon as the "virtual soundcard" was released by WiNRADIO the need for a complete own Sysetm has vanished for me, because now i can access the data via the virtual soundcard. I have mostly worked on the interface (in DirectX) so far, but concerning the API i have a nearly complete but untested wrapper class. I'll post the thing here later on if you like.
|
|
|
|
|
Hello bro,
First of all I want to give you my email address so that we can communicate with each other directly. My email address is taurian15581@yahoo.com. Please send me a email on this address.
Let me tell u slightly about the project I am doing with WiNRADiO. I have to develop a “Software Defined Radio” as my MSc Project. I got the Radio receiver WR-G303e through my University. I wanted to develop the software in C#.
I have tried to build the API wrapper class so that I can communicate with the receiver. but I have problems when Using memory pointers and Callbacks. i.e in funtions like CodecStart and G3BlockScan etc. The important 1 is codecstart and its signature is
BOOL __stdcall CodecStart(int hRadio,void __stdcall (*CallbackFunc)(void *),void *CallbackTarget);
The example use can be found under Codec Streaming Example usage in C++[^]
API is @ http://www.winradio.co.uk/home/g303_sdk.htm
Can you please send me your wrapper class or possibly the project you have made for so that I can have look at your code and see want I am doing wrong.
second thing is regarding the listening to the radio. In G303e there is only 1 function for codec streaming it gives IF signal centred @ 12kHz freq... as PCM data.... (I am not sure whether it is audio or not )
You wrote about WiNRADiO Digital Bridge™ Virtual Sound Card but what do I get out it.... will help me in playing the audio signal.
Thanks n hope you will contact me soon
Awaiting your reply
o O º(`'·.,(`'·., ☆,.·''),.·'')º O o°
»·'"`»* *☆ t4ure4n ☆* *«·'"`«
°o O º(,.·''(,.·'' ☆`'·.,)`'·.,)º O o°
|
|
|
|
|
Hi t4urean
Instead of discussing via private email I would prefer discussing this topic here on the board, as there is very little about the WiNRADIO api on the net, and so anyone interested in the api could also find some pieces of information. (Never mind the different alias marius_romanus. It's still me. Have two aliases so I can get the newsletter and stuff automatically at work AND at home ).
>second thing is regarding the listening to the radio. In G303e there is only 1 function for >codec streaming it gives IF signal centred @ 12kHz freq... as PCM data.... (I am not sure >whether it is audio or not )
No! Very basically speaking the tuned signal is downconverted to some "fixed" frequency. This frequency is the IF (Intermediate Frequency). Thus, the IF signal that is delivered to your callback is the raw signal received by the radio. To get the required audio Signal you have to demodulate this signal with respect to the mode the Signal represents. AM, USB, LSB, etc... There are various descriptions of demodulation algorithms on the web.
The WiNRADiO Digital Bridge™ Virtual Sound Card will be of no use for your project. It is intended for the WiNRADIO control software as an alternative output for audio or IF data. So, you do not need a second soundcard but can connect to the virtual soundcard from any application as if it were a real soundcard. (But only if the radio control program that is delivered by WiNRADIO is used).
Now for the api wrapper. As I said, it is nearly complete, but it is COMPLETELY UNTESTED, and furthermore it is for the G313e api ! But it might give you some ideas.
The prototype for the G313e callback is:
public delegate void streamingCallBack([In]IntPtr targetHandle,[In]IntPtr buffer, uint bufSize, uint samplingRate);
The api wrap to set up the G313e streams is this one:
[DllImport("wrg3130api.dll")] private static extern int SetupStreams(int hRadio,streamingCallBack iFHandler,IntPtr iFT, streamingCallBack aSHandler, IntPtr aST);
And the Method with which one can actually set up the streams from the application via the wrapper is:
public bool wrSetupStreams(int hRadio, streamingCallBack iCB, object ifStreamWriter, streamingCallBack aCB, object audioStreamWriter)
Here is the complete wrapper. Good luck and have fun !
using System;
using System.Runtime.InteropServices;
/*
* This is the Interface to the Radio G313e hardware driver dll that is available only in unmanaged code. It is based on the
* C interfaces given in the WiNRADIO api documentation.
*
*/
namespace HardwareController
{
#region The radio modes
// These are the radio modes that can be used with the Method SetMode.Given by WiNRADIO in repply to a request.
public enum RadioModes {CW=0, AM, FMN, FMW, LSB, USB, FMM, FSK, SAM, DAB, FM3, FM6, AMN, DSB, ISB, DRM=128, None, NumberOfDemodulators};
#endregion
#region The structure definitions given in the WiNRADIO api documentation.
// The OLD_RADIO_INFO structure as given in the api documentation.
[ StructLayout( LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi )]
public struct OLD_RADIO_INFO
{
public int bLength; // Specifies the size of the structure, in bytes; it must be filled before calling G3GetInfo
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=9 )]
public char[] szSerNum; // 8 characters long serial number ended by zero - this string may be directly passed to the G3Open function.
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=9 )]
public char[] szProdName; // 8 characters long product name ended by zero
public uint dwMinFreq; // Minimum frequency supported by the receiver
public uint dwMaxFreq; // Maximum frequency supported by the receiver
public byte bNumBands; // Number of band filters on RF input of the receiver; also, number of valid entries in dwBandFreq array
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=16 )]
public uint[] dwBandFreq; // Crossover frequencies between band filters
public uint dwLOfreq; // Local oscillator offset
public byte bNumVcos; // Number of VCOs on PLL board; also, number of valid entries in dwVcoFreq, wVcoDiv and bVcoBits arrays
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=8 )]
public uint[] dwVcoFreq; // Highest frequency for each VCO
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=8 )]
public ushort[] wVcoDiv; // VCO dividers
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=8 )]
public byte[] bVcoBits; // VCO select bits
public uint dwRefClk1; // Reference Clock1 frequency [Hz]
public uint dwRefClk2; // Reference Clock2 frequency [Hz], 0 if not fitted
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=8 )]
public byte[] IF1DAC; // DACs on IF1 module
public void allocateArrays()
{
this.szSerNum=new char[9];
this.szProdName=new char[9];
this.dwBandFreq=new uint[16];
this.dwVcoFreq=new uint[8];
this.wVcoDiv=new ushort[8];
this.bVcoBits=new byte[8];
this.IF1DAC=new byte[8];
}
}
// The RADIO_INFO structure as given in the api documentation
[ StructLayout( LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi )]
public struct RADIO_INFO
{
public int bLength; // Specifies the size of the structure, in bytes; it must be filled before calling G3GetInfo
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=9 )]
public char[] szSerNum; // 8 characters long serial number ended by zero - this string may be directly passed to the G3Open function.
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=9 )]
public char[] szProdName; // 8 characters long product name ended by zero
public uint dwMinFreq; // Minimum frequency supported by the receiver
public uint dwMaxFreq; // Maximum freuqnecy supported by the receiver
public byte bNumBands; // Number of band filters on RF input of the receiver; also, number of valid entries in dwBandFreq array
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=16 )]
public uint[] dwBandFreq; // Crossover frequencies between band filters
public uint dwLOfreq; // Local oscillator offset
public byte bNumVcos; // Number of VCOs on PLL board; also, number of valid entries in dwVcoFreq, wVcoDiv and bVcoBits arrays
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=8 )]
public uint[] dwVcoFreq; // Highest frequency for each VCO
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=8 )]
public ushort[] wVcoDiv; // VCO dividers
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=8 )]
public byte[] bVcoBits; // VCO select bits
public uint dwRefClk1; // Reference Clock1 frequency [Hz]
public uint dwRefClk2; // Reference Clock2 frequency [Hz], 0 if not fitted
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=8 )]
public byte[] IF1DAC; // DACs on IF1 module
public int iAGCstart; // Raw AGC level at low power (-97dBm)
public int iAGCmid; // Raw AGC value 5dB above AGC start
public int iAGCend; // raw AGC value at -30dBm
public int iDropLevel; // The level where AGC starts *10dBm
public int iRSSItop; // The level where raw RSSI value is 0x03FF *10dBm
public int iRSSIref; // Raw RSSI value at -97dBm
public void allocateArrays()
{
this.szSerNum=new char[9];
this.szProdName=new char[9];
this.dwBandFreq=new uint[16];
this.dwVcoFreq=new uint[8];
this.wVcoDiv=new ushort[8];
this.bVcoBits=new byte[8];
this.IF1DAC=new byte[8];
}
}
// The SOFT_AGC structure as given in the api documentation.
[ StructLayout( LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi )]
public struct SOFTAGC_DATA
{
public int bLength; // Length of structure in bytes
public int iRefLevel; // AGC reference level in dB
public uint dwAttackTime; // AGC attack time in ms
public uint dwDecayTime; // AGC decay time in ms
};
#endregion
// The streaming callback "prototypes" for the audio and intermediate frequency data delivery callbacks.
// Target is a GC - Handle to the object to which the data should be written. Via the handle the Object can be retrieved
// in the corresponding C# callback.
public delegate void streamingCallBack([In]IntPtr targetHandle,[In]IntPtr buffer, uint bufSize, uint samplingRate);
///
/// This class encapsulates the WiNRADIO api for the WR-G313i and WR-G313e receivers.
/// Written by Roland Wöhry 2006
///
public class WinradioInterface
{
// All the managed prototypes for the unmanaged winradio api functions. (For description of functions see the WiNRADIO
// api documentation for the WiNRADIO WR-G313i and WR-G313e receivers).
[DllImport("wrg3130api.dll")] private static extern int SetupStreams(int hRadio,streamingCallBack iFHandler,IntPtr iFT, streamingCallBack aSHandler, IntPtr aST);
[DllImport("wrg3130api.dll")] private static extern int G3Open([MarshalAs(UnmanagedType.LPStr)] string ID);
[DllImport("wrg3130api.dll")] private static extern int OpenRadioDevice(int deviceNum);
[DllImport("wrg3130api.dll")] private static extern int CloseRadioDevice(int hRadio);
[DllImport("wrg3130api.dll")] private static extern int G3GetRadioList([In,Out] OLD_RADIO_INFO[] radioInfos, int bufferSize);
// G3GetRadioList2 --> Not yet implemented
[DllImport("wrg3130api.dll")] private static extern int GetSignalStrengthdBm(int hRadio);
[DllImport("wrg3130api.dll")] private static extern int GetRawSignalStrength(int hRadio);
[DllImport("wrg3130api.dll")] private static extern int G3GetLastSSdBm(int hRadio);
[DllImport("wrg3130api.dll")] private static extern int G3GetLastRawSS(int hRadio);
[DllImport("wrg3130api.dll")] private static extern uint G3GetInternalRSSI(int hRadio);
[DllImport("wrg3130api.dll")] private static extern int SetFrequency(int hRadio, uint dwFreq);
[DllImport("wrg3130api.dll")] private static extern int G3SetFreqAsync(int hRadio, uint dwFreq);
[DllImport("wrg3130api.dll")] private static extern int G3WaitFreqAsync(int hRadio);
[DllImport("wrg3130api.dll")] private static extern int SetIF2Frequency(int hRadio, int iFreq);
[DllImport("wrg3130api.dll")] private static extern int SetAtten(int hRadio, int fAtten);
[DllImport("wrg3130api.dll")] private static extern int SetPower(int hRadio, int fPower);
[DllImport("wrg3130api.dll")] private static extern int SetAGC(int hRadio, int iAGC);
[DllImport("wrg3130api.dll")] private static extern int SetIFGain(int hRadio, int iIFGain);
[DllImport("wrg3130api.dll")] private static extern int G3SetRefClock(int hRadio, uint RefClock);
[DllImport("wrg3130api.dll")] private static extern uint GetFrequency(int hRadio);
[DllImport("wrg3130api.dll")] private static extern int GetIF2Frequency(int hRadio);
[DllImport("wrg3130api.dll")] private static extern int GetAtten(int hRadio);
[DllImport("wrg3130api.dll")] private static extern int GetPower(int hRadio);
[DllImport("wrg3130api.dll")] private static extern int GetAGC(int hRadio);
[DllImport("wrg3130api.dll")] private static extern int GetIFGain(int hRadio);
[DllImport("wrg3130api.dll")] private static extern uint G3GetLock(int hRadio, int GetType);
[DllImport("wrg3130api.dll")] private static extern uint G3GetRefClock(int hRadio);
// The following methods are not implemented because they will not be used by the system. The system will implement
// it's own mode of block scanning.
// G3BlockScan --> Not yet implemented
// G3StopBlockScan --> Not yet implemented
// G3PauseBlockScan --> Not yet implemented
// G3ResumeBlockScan --> Not yet implemented
[DllImport("wrg3130api.dll")] private static extern int G3GetInfo(int hRadio, ref RADIO_INFO info);
[DllImport("wrg3130api.dll")] private static extern int G3IsBusy(int hRadio);
// G3GetPath --> Not yet implemented
// G3GetPath2 --> Not yet implemented
[DllImport("wrg3130api.dll")] private static extern int IsDeviceConnected(int hRadio);
// dsp commands are not used by the system, so the corresponding functions are not wrapped.
// dspOpen --> Not yet implemented
// dspClose --> Not yet implemented
// dspReset --> Not yet implemented
// dspBoot --> Not yet implemented
// dspRead --> Not yet implemented
// dspWrite --> Not yet implemented
[DllImport("wrg3130api.dll")] private static extern int SetAdvancedMode(int hRadio,int Advanced,[MarshalAs(UnmanagedType.LPStr)] string CalFilePath);
[DllImport("wrg3130api.dll")] private static extern int SetNotchFilter(int hRadio,int Active,int Freq,uint BW);
[DllImport("wrg3130api.dll")] private static extern int SetNoiseBlanker(int hRadio,int Active,uint Thres);
[DllImport("wrg3130api.dll")] private static extern int SetIFShift(int hRadio,int Shift);
[DllImport("wrg3130api.dll")] private static extern int SetIFBandwidth(int hRadio,uint BW);
[DllImport("wrg3130api.dll")] private static extern int SetPassbandOffset(int hRadio,int PBO);
[DllImport("wrg3130api.dll")] private static extern int SetSoftAGC(int hRadio,ref SOFTAGC_DATA Data);
[DllImport("wrg3130api.dll")] private static extern int SetMode(int hRadio,int Mode);
// Important Should be set together with the IF-Bandwidth.
[DllImport("wrg3130api.dll")] private static extern int SetAudioBandwidth(int hRadio,uint BW);
// Should be set with no AGC
[DllImport("wrg3130api.dll")] private static extern int SetAudioGain(int hRadio,uint Gain);
[DllImport("wrg3130api.dll")] private static extern int SetVolume(int hRadio,uint Volume);
[DllImport("wrg3130api.dll")] private static extern int SetFMAFSquelchLevel(int hRadio,uint Level);
[DllImport("wrg3130api.dll")] private static extern int SetISBAudioChannel(int hRadio,uint Channel);
[DllImport("wrg3130api.dll")] private static extern int SetCWTone(int hRadio,uint Freq);
[DllImport("wrg3130api.dll")] private static extern int GetAdvancedMode(int hRadio);
[DllImport("wrg3130api.dll")] private static extern int GetNotchFilter(int hRadio,ref int Freq,ref uint BW);
[DllImport("wrg3130api.dll")] private static extern int GetNoiseBlanker(int hRadio,ref uint Thres);
[DllImport("wrg3130api.dll")] private static extern int GetIFShift(int hRadio);
[DllImport("wrg3130api.dll")] private static extern int GetIFBandwidth(int hRadio);
[DllImport("wrg3130api.dll")] private static extern int GetPassbandOffset(int hRadio);
[DllImport("wrg3130api.dll")] private static extern int GetSoftAGC(int hRadio,ref SOFTAGC_DATA Data);
[DllImport("wrg3130api.dll")] private static extern int GetMode(int hRadio);
[DllImport("wrg3130api.dll")] private static extern uint GetAudioBandwidth(int hRadio);
[DllImport("wrg3130api.dll")] private static extern uint GetAudioGain(int hRadio);
[DllImport("wrg3130api.dll")] private static extern uint GetVolume(int hRadio);
[DllImport("wrg3130api.dll")] private static extern uint GetFMAFSquelchLevel(int hRadio);
[DllImport("wrg3130api.dll")] private static extern uint GetISBAudioChannel(int hRadio);
[DllImport("wrg3130api.dll")] private static extern uint GetCWTone(int hRadio);
[DllImport("wrg3130api.dll")] private static extern int GetTuneError(int hRadio);
[DllImport("wrg3130api.dll")] private static extern uint GetFrequencyDeviation(int hRadio);
[DllImport("wrg3130api.dll")] private static extern uint GetAMDepth(int hRadio);
// The callback handles for the data given to the if and audio streams. In the callbacks they can be converted into
// the corresponding Objects again. Garbage Collector isn't an issue here as the objects are tunneled through the
// unmanaged code by means of these handles.
GCHandle audioStreamTargetHandle; // The handle to the audio stream target object used in the callback.
GCHandle ifStreamTargetHandle; // The handle to the if stream target object used in the callback.
// This is the only instance of this radio interface in the system.
private static WinradioInterface onlyInstance=null;
// The RadioInterface singleton access
public static WinradioInterface Instance{get{if(onlyInstance==null)onlyInstance=new WinradioInterface(); return onlyInstance;}}
#region The wrapper methods to the WiNRADIO interface
// Function for getting the AM depth for the current transmission. The 0..1 range normal for
// this parameter is returned scaled to 0..1000
public uint wrGetAMDepth(int hRadio)
{
return GetAMDepth(hRadio);
}
// Function for getting the frequency deviation (in Hz) of the currently received transmission.
public uint wrGetFrequencyDeviation(int hRadio)
{
return GetFrequencyDeviation(hRadio);
}
// Function for getting the tuning error while in advanced mode. The resulting value is valid only if the receiver is tuned
// to a transmissions. The returned value must be substracted from the frequency to which the receiver is currently tuned.
public int wrGetTuneError(int hRadio)
{
return GetTuneError(hRadio);
}
// Function for getting the CW tone frequency.
public uint wrGetCWTone(int hRadio)
{
return GetCWTone(hRadio);
}
// Function for getting the currently selected ISB audio channel.
public uint wrGetISBAudioChannel(int hRadio)
{
return GetISBAudioChannel(hRadio);
}
// Function for getting the current FM AF squelch level.
public uint wrGetFMAFSquelchLevel(int hRadio)
{
return GetFMAFSquelchLevel(hRadio);
}
// Function for getting the current audition volume.
public uint wrGetVolume(int hRadio)
{
return GetVolume(hRadio);
}
// Function for getting the current fixed audio gain.
public uint wrGetAudioGain(int hRadio)
{
return GetAudioGain(hRadio);
}
// Function for getting the current audio bandwidth.
public uint wrGetAudioBandwidth(int hRadio)
{
return GetAudioBandwidth(hRadio);
}
// Function for getting the current demodulation mode.
public RadioModes wrGetMode(int hRadio)
{
return (RadioModes)GetMode(hRadio);
}
// Function for retrieving the software AGC parameters.
public bool wrGetSoftAGC(int hRadio,ref SOFTAGC_DATA Data)
{
return intToBool(GetSoftAGC(hRadio, ref Data));
}
// Function for retrieving the pass-band offset value.
public int wrGetPassbandOffset(int hRadio)
{
return GetPassbandOffset(hRadio);
}
// Function for retrieving the IF bandwidth value.
public int wrGetIFBandwidth(int hRadio)
{
return GetIFBandwidth(hRadio);
}
// Function for retrieving the IF shift value
public int wrGetIFShift(int hRadio)
{
return GetIFShift(hRadio);
}
// Function for retrieving the noise blanker settings.
public bool wrGetNoiseBlanker(int hRadio,ref uint Thres)
{
return intToBool(GetNoiseBlanker(hRadio, ref Thres));
}
// Function for retrieving the IF notch filter settings.
public bool wrGetNotchFilter(int hRadio,ref int Freq,ref uint BW)
{
return intToBool(GetNotchFilter(hRadio, ref Freq, ref BW));
}
// Function checking the current status of the advanced mode.
public bool wrGetAdvancedMode(int hRadio)
{
return intToBool(GetAdvancedMode(hRadio));
}
// Function for setting the frequency of the audible tone when receving CW transmissions.
public bool wrSetCWTone(int hRadio,uint Freq)
{
return intToBool(SetCWTone(hRadio, Freq));
}
// Function for specifying the audio channel that should be sent to the audio output when demodulating ISB transmissions.
// 0 stands for Left (LSB) and 1 for Right (USB).
public bool wrSetISBAudioChannel(int hRadio,uint Channel)
{
return intToBool(SetISBAudioChannel(hRadio, Channel));
}
// Function for setting the AF squelch while demodulating FM transmissions. The level corresponds to the minimum noise
// level that will mute the audio output. By specifying a value of 0 the AF squelch is disabled.
public bool wrSetFMAFSquelchLevel(int hRadio,uint Level)
{
return intToBool(SetFMAFSquelchLevel(hRadio, Level));
}
// Function for setting the audition volume. It can be any value between 0 and 31.
public bool wrSetVolume(int hRadio,uint Volume)
{
return intToBool(SetVolume(hRadio, Volume));
}
// Function for setting the fixed audio gain. This value is used to provide a fixed audio amplification when the
// software AGC is disabled.
public bool wrSetAudioGain(int hRadio,uint Gain)
{
return intToBool(SetAudioGain(hRadio, Gain));
}
// Function for setting the final audio bandwidth. For linear modulation types it should be equal to IF bandwidth (LSB, USB)
// or half the IF bandwidth (AM, AMS, DSB, ISB). For exponential modulations (FM) it is transmission dependant. For CW
// there is a special condition as the audio bandwidth should be the minimum between half IF bandwidth and the CW tone
// frequency.
public bool wrSetAudioBandwidth(int hRadio,uint BW)
{
return intToBool(SetAudioBandwidth(hRadio, BW));
}
// Function for selecting the desired demodulation mode. All demodulation modes available in the G313 demodulator
// can be selected here.
public bool wrSetMode(int hRadio,RadioModes Mode)
{
return intToBool(SetMode(hRadio, (int)Mode));
}
// Function for setting the desired AGC behaviour. The AGC is active for as long as the reference level is below 0. The
// attack and decay times are automatically set to 1 if the values passed to the API are 0.
public bool wrSetSoftAGC(int hRadio,ref SOFTAGC_DATA Data)
{
Data.bLength=Marshal.SizeOf(Data);
return intToBool(SetSoftAGC(hRadio, ref Data));
}
// Function for setting the pass-band offset value. Normally it is 0. Accepted values are from -8kHz...+8kHz. It controls
// the amount that the spectrum is shifted before actual demodulation.
public bool wrSetPassbandOffset(int hRadio,int PBO)
{
return intToBool(SetPassbandOffset(hRadio, PBO));
}
// Function for setting the IF bandwidth. Values in the 1Hz...15kHz range are accepted. Through this API call the filters
//that come after the I and Q multipliers are controlled.
public bool wrSetIFBandwidth(int hRadio,uint BW)
{
return intToBool(SetIFBandwidth(hRadio, BW));
}
// Function for setting the IF shift. The specified value is added to the IF2 frequency and provides the actual receiving
// frequency. The resulting value must not exceed the IF hardware filter bandwidth (15kHz for G313), thus the accepted
// values are in the range -7500...+7500.
public bool wrSetIFShift(int hRadio,int Shift)
{
return intToBool(SetIFShift(hRadio, Shift));
}
// Function for configuring the noise blanker. The treshold is given as percentage of the maximum acceptable input signal.
public bool wrSetNoiseBlanker(int hRadio,bool Active,uint Thres)
{
return intToBool(SetNoiseBlanker(hRadio, boolToInt(Active), Thres));
}
// Function for configuring the IF notch filter. The frequency is specified relatively to the IF frequency and is limited to
// the IF hardware filter bandwidth, meaning from -7500 to +7500.
public bool wrSetNotchFilter(int hRadio,bool Active,int Freq,uint BW)
{
return intToBool(SetNotchFilter(hRadio, boolToInt(Active), Freq, BW));
}
// Function for entering/leaving advanced mode. The advanced mode must be activated before any other advanced mode
// function. When the advanced mode is nolonger needed it should be disabled. When activating the advanced mode the
// full path to a calibration data file may be provided if signal strength measurement must be calibrated. If not so,
// the passed pointer should be NULL.
public bool wrSetAdvancedMode(int hRadio,bool Advanced,string CalFilePath)
{
return intToBool(SetAdvancedMode(hRadio, boolToInt(Advanced), CalFilePath));
}
// Checks if the receiver is still connected to the computer. It is significant only for external receivers while the internal ones will always be reported as connected.
public bool wrIsDeviceConnected(int hRadio)
{
return intToBool(IsDeviceConnected(hRadio));
}
// Checks the receiver whether it is ready to accept commands.
public bool wrG3IsBusy(int hRadio)
{
return intToBool(G3IsBusy(hRadio));
}
// Retrieves the RADIO_INFO structure of the receiver.
public bool wrG3GetInfo(int hRadio, ref RADIO_INFO info)
{
info.bLength=Marshal.SizeOf(info);
return intToBool(G3GetInfo(hRadio,ref info));
}
// Retrieves the current reference clock frequency.
public uint wrG3GetRefClock(int hRadio)
{
return G3GetRefClock(hRadio);
}
// Retrieves the PLLs lock status.
public uint wrG3GetLock(int hRadio, int GetType)
{
return G3GetLock(hRadio, GetType);
}
// Retrieves the IFGain value of the receiver.
public int wrGetIFGain(int hRadio)
{
return GetIFGain(hRadio);
}
// The GetAGC function returns current AGC value of radio device.
public int wrGetAGC(int hRadio)
{
return GetAGC(hRadio);
}
// The GetPower function returns whether the receiver's power is on or off.
public bool wrGetPower(int hRadio)
{
return intToBool(GetPower(hRadio));
}
// The GetAtten function returns the RF input attenuator setting.
public bool wrGetAtten(int hRadio)
{
return intToBool(GetAtten(hRadio));
}
// The GetIF2Frequency function retrieves the current IF2 frequency.
public int wrGetIF2Frequency(int hRadio)
{
return GetIF2Frequency(hRadio);
}
// The GetFrequency function retrieves the frequency the receiver is tuned to.
public uint wrGetFrequency(int hRadio)
{
return GetFrequency(hRadio);
}
// Specifies the reference clock frequency and allows switching between internal and external references.
public bool wrG3SetRefClock(int hRadio, uint RefClock)
{
return intToBool(G3SetRefClock(hRadio, RefClock));
}
// Sets IFGain value for the specified receiver.
public bool wrSetIFGain(int hRadio, int iIFGain)
{
return intToBool(SetIFGain(hRadio, iIFGain));
}
// The SetAGC function sets the AGC value for given receiver.
public bool wrSetAGC(int hRadio, int iAGC)
{
return intToBool(SetAGC(hRadio, iAGC));
}
// The SetPower function switches the device's power on or off. This function can be used to power down the receiver
// in portable applications to conserve battery power.
public bool wrSetPower(int hRadio, bool fPower)
{
return intToBool(SetPower(hRadio, boolToInt(fPower)));
}
// The SetAtten function activates or deactivates the RF input attenuator. It is used to prevent overloading of the
// receiver with strong signals.
public bool wrSetAtten(int hRadio, bool fAtten)
{
return intToBool(SetAtten(hRadio, boolToInt(fAtten)));
}
// The SetIF2Frequency function sets the center frequency of the last IF signal.
public bool wrSetIF2Frequency(int hRadio, int iFreq)
{
return intToBool(SetIF2Frequency(hRadio, iFreq));
}
// The G3WaitFreqAsync function waits for the end of a receiver tunning started by a G3SetFreqAsync call.
public bool wrG3WaitFreqAsync(int hRadio)
{
return intToBool(G3WaitFreqAsync(hRadio));
}
//The G3SetFreqAsync function starts the sequence of hardware commands that sets the frequency the device is to be
// tuned to. In order to insure the sequence has been executed and that the hardware is properly tuned,
// G3WaitFreqAsync function must be called.
public bool wrG3SetFreqAsync(int hRadio, uint dwFreq)
{
return intToBool(G3SetFreqAsync(hRadio,dwFreq));
}
// The SetFrequency function sets the frequency the device is to be tuned to.
public bool wrSetFrequency(int hRadio, uint dwFreq)
{
return intToBool(SetFrequency(hRadio, dwFreq));
}
// The G3GetInternalRSSI function returns a combination of the RSSI and AGC values read from the receiver hardware.
public uint wrG3GetInternalRSSI(int hRadio)
{
return G3GetInternalRSSI(hRadio);
}
// The G3GetLastRawSS function returns last measured RAW signal strength value. Useful during block scanning.
public int wrG3GetLastRawSS(int hRadio)
{
return G3GetLastRawSS(hRadio);
}
// The G3GetLastSSdBm function returns the last measured strength of the radio signal in dBm. Useful during block scanning.
public int wrG3GetLastSSdBm(int hRadio)
{
return G3GetLastSSdBm(hRadio);
}
// The GetRawSignalStrength function returns the "raw" signal strength value. This is made available for compatibility with applications which expect the signal strength value to be from 0 (min signal level) to 255 (max signal level). The formula for this is:
// SignalStrength_RAW = 255*(SignalStrength_dBm + 1300)/1000
// This means that -130dBm corresponds to 0 and -30dBm corresponds to 255 of "raw" value.
public int wrGetRadSignalStrength(int hRadio)
{
return GetRawSignalStrength(hRadio);
}
// The GetSignalStrengthdBm function returns the strength of the radio signal in dBm received by the radio device.
public int wrGetSignalStrengthdBm(int hRadio)
{
return GetSignalStrengthdBm(hRadio);
}
// The G3GetRadioList function returns information about all G313 devices that can be opened.
// Do not allocate the arrays within the structs yourself. G3GetRadioList will do the allocation.
public int wrG3GetRadioList(OLD_RADIO_INFO[] radioInfos)
{
int ret=0;
if(radioInfos!=null)
{
for(int i=0; i
|
|
|
|
|
Thanks bro. . . .
I am going to have a look at you code and c If can figure out what I was doing wrong.... Just 1 or two questions b4 I start working with you code.
The block scanning function whose signature is
G3BlockScan
C/C++ declaration
BOOL __stdcall G3BlockScan(int hRadio,DWORD *Freqs, int Count,int StopSquelchRaw,DWORD FeedbackTime,HWND WinHandle,DWORD Msg); Parameters
hRadioHandle to a radio device that was returned by OpenRadioDevice or G3Open.
Freqs The array of frequencies to be scanned.
Count The count of frequencies to be scanned.
StopSquelchRaw The value of the RAW signal strength at which the scanning should stop.
FeedbackTime The time interval in ms after which G3 API sends you scanned data.
WinHandle The window handle to which the scanned data will arrive.
Msg The constant for window mesage that will bring the scanned data.
Return Value If the scan started, the return value is TRUE. Otherwise FALSE is returned.
Remarks
Scanned RAW signal strength values are written back to the Freqs buffer. Each frequency in the Freqs buffer is replaced by appropriate RAW value. Parts of this buffer are sent to the appplication after Feedback time interval expires. The block scanning automatically ends when scanned RAW signal strength value rises StopSquelchRaw parameter. The scanned RAW values are sent using window message Msg to the window procedure of the window handle WinHandle with buffer pointer as WParam and buffer length as LParam.
This function works well with the Synchronous Block Scanning example in C++[^] provided with the SDK.. and returns a value of 256 for every frequency element in the array
but the same function when called in c# gives the error...
I have wrapped this function in C# as follows..
[DllImport("wrg303api.dll")]
public static extern bool G3BlockScan(int hRadio, uint [] Freqs, int Count,int StopSquelchRaw,uint FeedbackTime,IntPtr WinHandle,uint Msg);
Please note that the pointer in the function calls is null (IntPtr.Zero)... coz in the example usage in SDK it is NULL
and the function call is like this .....
..... some code.....
uint[] Freqs = new uint[1001]; ..... some code....
if (!clsApiWrapper.G3BlockScan(radioHandle, Freqs, 1001, 256, 100000, pointer,Msg))
MessageBox.Show("The block scanning failed to start", "WiNRADiO - Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
..... some code ....
But now when I run the app it doesn't change the contents of the array. so I believe I need to pass the reference of the array to the function. And if I change the code like this to pass the reference of the array
[DllImport("wrg303api.dll")]
public static extern bool G3BlockScan(int hRadio, ref uint [] Freqs, int Count,int StopSquelchRaw,uint FeedbackTime,IntPtr WinHandle,uint Msg);
..... some code.....
uint[] Freqs = new uint[1001];
..... some code....
if (!clsApiWrapper.G3BlockScan(radioHandle,ref Freqs, 1001, 256, 100000, pointer,Msg))
MessageBox.Show("The block scanning failed to start", "WiNRADiO - Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
Now when I access the Freqs array after the method call I encounter a strange behaviour.. The size of Freqs array is reduced from 1000 to 1.
I can't figure out what is going wrong.
Please post your opinion on this problem...
Kind Regards
o O º(`'·.,(`'·., ☆,.·''),.·'')º O o°
»·'"`»* *☆ t4ure4n ☆* *«·'"`«
°o O º(,.·''(,.·'' ☆`'·.,)`'·.,)º O o°
|
|
|
|
|
Hi t4urean !
t4urean wrote: Please note that the pointer in the function calls is null (IntPtr.Zero)... coz in the example usage in SDK it is NULL
You have to know that the Documentation says that IntPtr.Zero means "null" in the managed platform, but it is NOT the same as NULL in C/C++ ! Hence, your problem. I cannot find where i read it now, but i definitely read it somewhere some time ago !
Now to the marshalling of arrays: you declared the blockscan method as:
t4urean wrote: [DllImport("wrg303api.dll")]public static extern bool G3BlockScan(int hRadio, ref uint [] Freqs, int Count,int StopSquelchRaw,uint FeedbackTime,IntPtr WinHandle,uint Msg);
Try the following.
-->[In][Out] (If you use ref the size will be defined by the interop as 1).
I'm not what you would call an expert on interop marshalling. But this worked for me once. Maybe there are more performant possibilities of marshalling but currently i do not know of any.
[DllImport("wrg303api.dll")]public static extern bool G3BlockScan(int hRadio, [In][Out] uint [] Freqs, int Count,int StopSquelchRaw,uint FeedbackTime,IntPtr WinHandle,uint Msg);
And call it like this:
t4urean wrote: if (!clsApiWrapper.G3BlockScan(radioHandle, Freqs, 1001, 256, 100000, pointer,Msg))MessageBox.Show("The block scanning failed to start", "WiNRADiO - Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
I hope this helps your problem, Good Luck
marius
|
|
|
|
|
Thanks bro 4 ur prompt replies..
I have used your suggestionregarding replacing ref keyword with [In][Out] and guess what it really did the trick 4 me. Previously I had tried using [In,Out] but id didn’t work now I know what I was doing wrong. Thanks again for that.
Now I have 1 more problem left and then I think that I am done with the API wrapping and I can go for the Dermodulation of the IF signal.
The problem is with function CodecStart Function for starting the IF streaming input from a USB connected external receiver.
This function has a pointer to function called as CallbackFunc so this should be a delegate in c#.. Second Thing is the CallbackTarget pointer which is pointer to the Structure “CallbackContext” and this struture has pointer to the api function declared in it. This function is “CodecRead”. You can c this structure in the example code below..
C/C++ declaration
BOOL __stdcall CodecStart(int hRadio,
void __stdcall (*CallbackFunc)(void *),
void *CallbackTarget); Parameters
hRadio Handle to a radio device
CallbackFunction Application provided function to be called by the API when there is new data received through the IF stream from the receiver
CallbackTarget Argument to be passed to the application defined callback function
Return Value If the function succeeds, the return value is TRUE. Otherwise FALSE is returned.
The example usage of the above function provided in the API is given below..
Remarks The provided callback function is called from a separate thread that waits for codec samples sent by the receiver and code to prevent resources accessing must be included in the application if necessary.
// IF Block Scanning.cpp : Defines the entry point for the console //application.
// I am going to bold the part of code that is of my interest.
#include "stdafx.h"
#include "stdio.h"
#include "windows.h"
// G3 API function type declarations
typedef int (__stdcall *FNCOpenRadioDevice)(int iDeviceNum);
typedef BOOL (__stdcall *FNCCloseRadioDevice)(int hRadio);
typedef BOOL (__stdcall *FNCSetAtten)(int hRadio, BOOL fAtten);
typedef BOOL (__stdcall *FNCSetPower)(int hRadio, BOOL fPower);
typedef BOOL (__stdcall *FNCSetAGC)(int hRadio, int iAGC);
typedef BOOL (__stdcall *FNCCodecStart)(int hRadio,void (__stdcall *CallbackFunc)(void *),void *CallbackTarget);
typedef BOOL (__stdcall *FNCCodecStop)(int hRadio);
typedef unsigned int (__stdcall *FNCCodecRead)(int hRadio,void *Buf,unsigned int Size);
typedef struct
{
int hRadio;
FILE *IFFile;
FNCCodecRead CodecRead;<-------API Function c up last typedef
} CallbackContext;
void __stdcall CodecCallback(void *Target)
{
unsigned int i;
char Buf[4096];
CallbackContext *Ctx=(CallbackContext *)Target;
while ((i=Ctx->CodecRead(Ctx->hRadio,Buf,sizeof(Buf)))!=0)
fwrite(Buf,i,1,Ctx->IFFile);
}
int main(int argc, char* argv[])
{
// load the G3 API library
HMODULE dll=LoadLibraryA("wrg303api.dll");
if (!dll) {puts("WRG303API.DLL not found !"); return 0;}
// link G3 API functions
FNCOpenRadioDevice OpenRadioDevice=(FNCOpenRadioDevice)GetProcAddress(dll,"OpenRadioDevice");
FNCCloseRadioDevice CloseRadioDevice=(FNCCloseRadioDevice)GetProcAddress(dll,"CloseRadioDevice");
FNCSetAtten SetAtten=(FNCSetAtten)GetProcAddress(dll,"SetAtten");
FNCSetPower SetPower=(FNCSetPower)GetProcAddress(dll,"SetPower");
FNCSetAGC SetAGC=(FNCSetAGC)GetProcAddress(dll,"SetAGC");
FNCCodecStart CodecStart=(FNCCodecStart)GetProcAddress(dll,"CodecStart");
FNCCodecStop CodecStop=(FNCCodecStop)GetProcAddress(dll,"CodecStop");
FNCCodecRead CodecRead=(FNCCodecRead)GetProcAddress(dll,"CodecRead");
// open the first available radio
int hRadio=OpenRadioDevice(0);
if (!hRadio) {puts("No WR-G303 device could be opened !");FreeLibrary(dll); return 0;}
// set Power, AGC and Attenuator
if (SetPower(hRadio,TRUE)) puts("The device is turned ON"); else puts("The device failed to turn ON");
if (SetAtten(hRadio,FALSE)) puts("The attenuator is OFF"); else puts("The attenuator failed to turn OFF");
if (SetAGC(hRadio,3)) puts("The AGC is FAST"); else puts("The AGC failed to switch");
FILE *f=fopen("IF2.pcm","wb");
CallbackContext Ctx;
Ctx.hRadio=hRadio;
Ctx.IFFile=f;
Ctx.CodecRead=CodecRead;
if (!CodecStart(hRadio,CodecCallback,&Ctx)) puts("Codec streaming couldn't be started!");
else {
puts("Codec streaming properly started!");
while (!ftell(f) )
{
}
CodecStop(hRadio);
fclose(f); }
// close the device handle
if (CloseRadioDevice(hRadio)) puts("The device is closed properly"); else puts("The device failed to close");
// free the G3 API library
FreeLibrary(dll);
return 0;
}
My Idea the callback Function could be a delegate like this
<cose>public delegate void delegateCallBackFunction(IntPtr Target);</code> and instead of having structure we can have a class... (may be) I don't know If API functions will accept that.
If we can then can we use idea of the "Delegate and Events".. coz we can have have event against the delegate and we can pass data as event arguments but I am sure about having the function pointer in the eventArgument. I am too confused with all this...
Please post any comments you can give
Cheers ..
o O º(`'·.,(`'·., ☆,.·''),.·'')º O o°
»·'"`»* *☆ t4ure4n ☆* *«·'"`«
°o O º(,.·''(,.·'' ☆`'·.,)`'·.,)º O o°
|
|
|
|
|
Hi t4urean
Concerning streaming, the G303 api seems to differ a lot from the G313 api. But lets give it a try:
First of all the target structure is something that you can define freely so you can give all the information you need to your callback class. But that you will shurely allready know. As this is a pointer you should be able to define it as a class. But BEWARE ! When you call the CodecStart function, the pointer would be given to the api. And the address of the object would be locked by the InterOp FOR THE DURATION OF THE CALL to CodecStart. Afterwards the GC is free to move the object around in memory, but the api still got the pointer that was given to CodecStart !!!! So, after the garbage collector possibly moves the object somewhere along prog. execution you would end up having an invalid pointer in the callback... --> Thats one of the problems of some C code asynchronously calling back managed code.
So, the safest way to communicate here to my mind would not be passing the Target object directly, but passing a handle to the target object. This way the GC can move around however suits it, but you never loose your object.
But first of all the import of the codec start function
[DllImport(" -- your dll ---")] private static extern int CodecStart(int hradio,delegateCallbackFunction callback, IntPtr target);
I would declare the callback as: public delegate void delegateCallBackFunction(IntPtr TargetHandle);
Code for invoking the streaming would look something like this (callbackTargetObject is an Instance of your CallbackTarget class):
GCHandle targetHandle = GCHandle.Alloc(callbackTargetObject);<br />
CodecStart(hRadio, yourDelegate, (IntPtr)targetHandle);<br />
<br />
GC.KeepAlive(targetHandle);
Your delegate would look something like this:
yourDelegate(IntPtr target)<br />
{<br />
CallbackTarget yourTargetObject=(CallbackTarget)(((GCHandle)target).Target);<br />
<br />
}
So far so good. One thing i do not yet know is, if delegates are also Objects that can be moved around by the GC. If so, it could be that your streaming works for a little while and suddenly craches because the api jumps into the void as the callback has been relocated. But I dont know. But if so, you could try to pin the delegate. YOu could try to allocate a handle for it and give as the second parameter GCHandleType.Pinned.
Hope that helps. Good Luck !
Marius
|
|
|
|
|
|
I have got Winradio Receiver WR-G303e hardware to develop a software defined radio.
The SDK/API provided works for c/C++, Delphi etc, My question is can I use it to work in c#...
How do I manage to call functions written in C to work in c# .
|
|
|
|
|
You can call the functions/APIs that exported from WinRadio Dll just like Win32 API. See MSDN for how to call Win32 API.
Then you can convert the function signature from C to C#.
Best regards,
A. Riazi
|
|
|
|
|
Hello,
I read your article it was very great. I am working on my MSc project to develop a software defined radio. I was trying to build a radio receiver/tuning part & use Soundcard to capture the signal & manipulate it.
I happened to see WinRadio Website but i was not sure. After I have read your article I am going to use Winradio receiver for my project.
There is one problem that Now i can only get Winradio WR-1550i instead if WR-1000i (can't buy it anymore).
Will it work for me?
Can you please suggest any thing that would help in my project I would be very greatfull.
:->
Regards... t4urean....
|
|
|
|
|
Hi,
Note that this model has an ISA bus not PCI. Maybe your motherboard doesn't support ISA. Check before buy.
Best regards,
A. Riazi
|
|
|
|
|
salam
I want to have a meeting with you, would you please let me have your contact info?
thanks
|
|
|
|
|
I should thanks Rick Parrish for his email. He sent me a link that show his efforts on trunk radio decoder.
You can download his project (source & binary) and add extra functionality to my article source code.
Find Rick's decoder project by clicking here[^]
See his project screen shot here[^].
A. Riazi
|
|
|
|
|
Do you have the code to Rick's trunk decoder? The link does not work anymore.
|
|
|
|
|
One of reviewers asked me for Trunk Radio and unfortunately, I deleted his email. Because of this, I write this message.
WiNRADiO cards are a very well designed recievers. The frequency range of them is 150 kHz to 1.5 GHz (an extended version of these cards can recieve up to 4GHz).
According to company web site, these receivers are intended for cost-effective professional and amateur applications. They are particularly suited for VHF/UHF monitoring. For this reason, they can be used to monitor trunk radio devices.
A. Riazi
|
|
|
|
|