2014-10-27 20:05:40 -04:00
# define OPENGL
2015-02-17 21:26:14 -05:00
# include "CubicSDRDefs.h"
2014-10-27 20:05:40 -04:00
# include "wx/wxprec.h"
# ifndef WX_PRECOMP
# include "wx/wx.h"
# endif
# if !wxUSE_GLCANVAS
# error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library"
# endif
2014-10-27 21:22:29 -04:00
# include "CubicSDR.h"
2015-05-04 19:44:03 -04:00
# include "FrequencyDialog.h"
2014-10-27 20:05:40 -04:00
2015-02-17 21:26:14 -05:00
# ifdef _OSX_APP_
# include "CoreFoundation/CoreFoundation.h"
# endif
2014-10-27 20:05:40 -04:00
IMPLEMENT_APP ( CubicSDR )
2015-07-27 21:45:24 -04:00
CubicSDR : : CubicSDR ( ) : appframe ( NULL ) , m_glContext ( NULL ) , frequency ( 0 ) , offset ( 0 ) , ppm ( 0 ) , snap ( 1 ) , sampleRate ( DEFAULT_SAMPLE_RATE ) , directSamplingMode ( 0 ) ,
2015-07-30 20:36:06 -04:00
sdrThread ( NULL ) , sdrPostThread ( NULL ) , pipeSDRCommand ( NULL ) , pipeSDRIQData ( NULL ) , pipeIQVisualData ( NULL ) , pipeAudioVisualData ( NULL ) , t_SDR ( NULL ) , t_PostSDR ( NULL ) {
2015-07-27 21:45:24 -04:00
}
2014-10-27 20:05:40 -04:00
bool CubicSDR : : OnInit ( ) {
2015-02-17 21:26:14 -05:00
# ifdef _OSX_APP_
CFBundleRef mainBundle = CFBundleGetMainBundle ( ) ;
CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL ( mainBundle ) ;
char path [ PATH_MAX ] ;
if ( ! CFURLGetFileSystemRepresentation ( resourcesURL , TRUE , ( UInt8 * ) path , PATH_MAX ) )
{
// error!
}
CFRelease ( resourcesURL ) ;
chdir ( path ) ;
# endif
2015-04-13 21:18:45 -04:00
2015-04-13 19:58:34 -04:00
if ( ! wxApp : : OnInit ( ) ) {
2014-10-27 20:05:40 -04:00
return false ;
2015-04-13 19:58:34 -04:00
}
2015-04-21 23:19:45 -04:00
wxApp : : SetAppName ( " CubicSDR " ) ;
2015-04-13 19:58:34 -04:00
2015-07-21 00:04:04 -04:00
frequency = wxGetApp ( ) . getConfig ( ) - > getCenterFreq ( ) ;
2015-01-06 00:57:57 -05:00
offset = 0 ;
2015-04-13 21:18:45 -04:00
ppm = 0 ;
2015-05-30 23:14:16 -04:00
directSamplingMode = 0 ;
2014-11-23 19:39:27 -05:00
2015-07-30 19:30:46 -04:00
// Visual Data
2015-07-30 20:36:06 -04:00
pipeIQVisualData = new DemodulatorThreadInputQueue ( ) ;
pipeIQVisualData - > set_max_num_items ( 1 ) ;
2015-08-03 01:38:38 -04:00
spectrumDistributor . setInput ( pipeIQVisualData ) ;
pipeDemodIQVisualData = new DemodulatorThreadInputQueue ( ) ;
2015-08-11 22:11:54 -04:00
pipeDemodIQVisualData - > set_max_num_items ( 1 ) ;
2015-08-03 01:38:38 -04:00
pipeSpectrumIQVisualData = new DemodulatorThreadInputQueue ( ) ;
2015-08-11 22:11:54 -04:00
pipeSpectrumIQVisualData - > set_max_num_items ( 1 ) ;
2015-08-03 01:38:38 -04:00
2015-08-11 00:50:43 -04:00
pipeWaterfallIQVisualData = new DemodulatorThreadInputQueue ( ) ;
2015-08-11 23:52:03 -04:00
pipeWaterfallIQVisualData - > set_max_num_items ( DEFAULT_WATERFALL_LPS ) ;
2015-08-11 00:50:43 -04:00
2015-08-03 01:38:38 -04:00
spectrumDistributor . attachOutput ( pipeDemodIQVisualData ) ;
spectrumDistributor . attachOutput ( pipeSpectrumIQVisualData ) ;
demodSpectrumProcessor . setInput ( pipeDemodIQVisualData ) ;
spectrumProcessor . setInput ( pipeSpectrumIQVisualData ) ;
2015-07-30 19:30:46 -04:00
2015-07-30 20:36:06 -04:00
pipeAudioVisualData = new DemodulatorThreadOutputQueue ( ) ;
pipeAudioVisualData - > set_max_num_items ( 1 ) ;
2015-07-30 19:30:46 -04:00
2015-08-01 11:03:00 -04:00
scopeProcessor . setInput ( pipeAudioVisualData ) ;
2015-07-30 19:30:46 -04:00
// I/Q Data
2015-07-30 20:36:06 -04:00
pipeSDRIQData = new SDRThreadIQDataQueue ;
pipeSDRCommand = new SDRThreadCommandQueue ( ) ;
2015-07-30 19:30:46 -04:00
2015-07-29 22:01:13 -04:00
sdrThread = new SDRThread ( ) ;
2015-07-30 20:36:06 -04:00
sdrThread - > setInputQueue ( " SDRCommandQueue " , pipeSDRCommand ) ;
sdrThread - > setOutputQueue ( " IQDataOutput " , pipeSDRIQData ) ;
2014-11-23 19:39:27 -05:00
2014-11-29 13:58:20 -05:00
sdrPostThread = new SDRPostThread ( ) ;
2015-08-11 20:37:46 -04:00
sdrPostThread - > setNumVisSamples ( BUF_SIZE ) ;
2015-07-30 20:36:06 -04:00
sdrPostThread - > setInputQueue ( " IQDataInput " , pipeSDRIQData ) ;
2015-08-11 00:50:43 -04:00
sdrPostThread - > setOutputQueue ( " IQVisualDataOutput " , pipeIQVisualData ) ;
sdrPostThread - > setOutputQueue ( " IQDataOutput " , pipeWaterfallIQVisualData ) ;
2015-01-12 00:40:43 -05:00
std : : vector < SDRDeviceInfo * > : : iterator devs_i ;
SDRThread : : enumerate_rtl ( & devs ) ;
2015-07-08 18:54:52 -04:00
SDRDeviceInfo * dev = NULL ;
2015-01-12 00:40:43 -05:00
if ( devs . size ( ) > 1 ) {
wxArrayString choices ;
for ( devs_i = devs . begin ( ) ; devs_i ! = devs . end ( ) ; devs_i + + ) {
std : : string devName = ( * devs_i ) - > getName ( ) ;
if ( ( * devs_i ) - > isAvailable ( ) ) {
devName . append ( " : " ) ;
devName . append ( ( * devs_i ) - > getProduct ( ) ) ;
devName . append ( " [ " ) ;
devName . append ( ( * devs_i ) - > getSerial ( ) ) ;
devName . append ( " ] " ) ;
} else {
devName . append ( " (In Use?) " ) ;
}
choices . Add ( devName ) ;
}
2015-07-08 23:32:30 -04:00
int devId = wxGetSingleChoiceIndex ( wxT ( " Devices " ) , wxT ( " Choose Input Device " ) , choices ) ;
if ( devId = = - 1 ) { // User chose to cancel
return false ;
}
2015-07-08 18:54:52 -04:00
dev = devs [ devId ] ;
2015-01-12 00:40:43 -05:00
sdrThread - > setDeviceId ( devId ) ;
2015-07-08 18:54:52 -04:00
} else if ( devs . size ( ) = = 1 ) {
dev = devs [ 0 ] ;
2015-01-12 00:40:43 -05:00
}
2015-07-08 23:32:30 -04:00
if ( ! dev ) {
wxMessageDialog * info ;
info = new wxMessageDialog ( NULL , wxT ( " \x28 \u256F \xB0 \u25A1 \xB0 \uFF09 \u256F \uFE35 \x20 \u253B \u2501 \u253B " ) , wxT ( " RTL-SDR device not found " ) , wxOK | wxICON_ERROR ) ;
info - > ShowModal ( ) ;
return false ;
}
2015-01-12 00:40:43 -05:00
2014-11-30 17:11:29 -05:00
t_PostSDR = new std : : thread ( & SDRPostThread : : threadMain , sdrPostThread ) ;
t_SDR = new std : : thread ( & SDRThread : : threadMain , sdrThread ) ;
2014-11-23 19:39:27 -05:00
2015-05-04 19:44:03 -04:00
appframe = new AppFrame ( ) ;
2015-07-08 18:54:52 -04:00
if ( dev ! = NULL ) {
appframe - > initDeviceParams ( dev - > getDeviceId ( ) ) ;
DeviceConfig * devConfig = wxGetApp ( ) . getConfig ( ) - > getDevice ( dev - > getDeviceId ( ) ) ;
ppm = devConfig - > getPPM ( ) ;
offset = devConfig - > getOffset ( ) ;
directSamplingMode = devConfig - > getDirectSampling ( ) ;
}
2014-10-28 21:39:59 -04:00
2014-12-05 18:20:28 -05:00
# ifdef __APPLE__
2014-12-04 22:25:18 -05:00
int main_policy ;
struct sched_param main_param ;
2014-12-05 20:13:45 -05:00
main_policy = SCHED_RR ;
main_param . sched_priority = sched_get_priority_min ( SCHED_RR ) + 2 ;
2014-12-04 22:25:18 -05:00
pthread_setschedparam ( pthread_self ( ) , main_policy , & main_param ) ;
2014-12-05 18:20:28 -05:00
# endif
2014-12-04 22:25:18 -05:00
2014-10-27 20:05:40 -04:00
return true ;
}
int CubicSDR : : OnExit ( ) {
2015-05-31 12:05:45 -04:00
demodMgr . terminateAll ( ) ;
2014-11-23 19:39:27 -05:00
std : : cout < < " Terminating SDR thread.. " < < std : : endl ;
sdrThread - > terminate ( ) ;
2014-11-30 17:11:29 -05:00
t_SDR - > join ( ) ;
2014-10-27 20:05:40 -04:00
2014-11-30 17:11:29 -05:00
std : : cout < < " Terminating SDR post-processing thread.. " < < std : : endl ;
2014-11-29 13:58:20 -05:00
sdrPostThread - > terminate ( ) ;
2014-11-30 17:11:29 -05:00
t_PostSDR - > join ( ) ;
2014-11-29 13:58:20 -05:00
2014-11-23 19:39:27 -05:00
delete sdrThread ;
2014-11-30 17:11:29 -05:00
delete t_SDR ;
2014-11-23 19:39:27 -05:00
2014-11-29 13:58:20 -05:00
delete sdrPostThread ;
2014-11-30 17:11:29 -05:00
delete t_PostSDR ;
2014-11-29 13:58:20 -05:00
2015-07-30 20:36:06 -04:00
delete pipeSDRCommand ;
2014-11-23 19:39:27 -05:00
2015-07-30 20:36:06 -04:00
delete pipeIQVisualData ;
delete pipeAudioVisualData ;
delete pipeSDRIQData ;
2014-11-29 13:58:20 -05:00
2014-11-23 19:39:27 -05:00
delete m_glContext ;
2014-10-27 20:05:40 -04:00
2015-01-10 21:49:58 -05:00
# ifdef __APPLE__
AudioThread : : deviceCleanup ( ) ;
# endif
2014-10-27 20:05:40 -04:00
return wxApp : : OnExit ( ) ;
}
PrimaryGLContext & CubicSDR : : GetContext ( wxGLCanvas * canvas ) {
PrimaryGLContext * glContext ;
if ( ! m_glContext ) {
2014-11-12 21:55:11 -05:00
m_glContext = new PrimaryGLContext ( canvas , NULL ) ;
2014-10-27 20:05:40 -04:00
}
glContext = m_glContext ;
return * glContext ;
}
2015-07-20 18:39:45 -04:00
void CubicSDR : : OnInitCmdLine ( wxCmdLineParser & parser ) {
parser . SetDesc ( commandLineInfo ) ;
parser . SetSwitchChars ( wxT ( " - " ) ) ;
}
bool CubicSDR : : OnCmdLineParsed ( wxCmdLineParser & parser ) {
wxString * confName = new wxString ;
if ( parser . Found ( " c " , confName ) ) {
if ( confName ) {
config . setConfigName ( confName - > ToStdString ( ) ) ;
}
}
config . load ( ) ;
return true ;
}
2015-01-04 17:11:20 -05:00
void CubicSDR : : setFrequency ( long long freq ) {
2015-01-11 17:08:16 -05:00
if ( freq < sampleRate / 2 ) {
freq = sampleRate / 2 ;
2015-01-04 13:20:31 -05:00
}
2014-11-23 19:39:27 -05:00
frequency = freq ;
SDRThreadCommand command ( SDRThreadCommand : : SDR_THREAD_CMD_TUNE ) ;
2015-01-04 17:11:20 -05:00
command . llong_value = freq ;
2015-07-30 20:36:06 -04:00
pipeSDRCommand - > push ( command ) ;
2014-11-23 19:39:27 -05:00
}
2015-01-06 00:57:57 -05:00
long long CubicSDR : : getOffset ( ) {
return offset ;
}
void CubicSDR : : setOffset ( long long ofs ) {
offset = ofs ;
SDRThreadCommand command ( SDRThreadCommand : : SDR_THREAD_CMD_SET_OFFSET ) ;
command . llong_value = ofs ;
2015-07-30 20:36:06 -04:00
pipeSDRCommand - > push ( command ) ;
2015-07-08 01:07:39 -04:00
SDRDeviceInfo * dev = ( * getDevices ( ) ) [ getDevice ( ) ] ;
config . getDevice ( dev - > getDeviceId ( ) ) - > setOffset ( ofs ) ;
2015-01-06 00:57:57 -05:00
}
2015-05-30 23:14:16 -04:00
void CubicSDR : : setDirectSampling ( int mode ) {
directSamplingMode = mode ;
SDRThreadCommand command ( SDRThreadCommand : : SDR_THREAD_CMD_SET_DIRECT_SAMPLING ) ;
command . llong_value = mode ;
2015-07-30 20:36:06 -04:00
pipeSDRCommand - > push ( command ) ;
2015-07-08 01:07:39 -04:00
SDRDeviceInfo * dev = ( * getDevices ( ) ) [ getDevice ( ) ] ;
config . getDevice ( dev - > getDeviceId ( ) ) - > setDirectSampling ( mode ) ;
2015-05-30 23:14:16 -04:00
}
int CubicSDR : : getDirectSampling ( ) {
return directSamplingMode ;
}
2015-05-31 22:13:14 -04:00
void CubicSDR : : setSwapIQ ( bool swapIQ ) {
sdrPostThread - > setSwapIQ ( swapIQ ) ;
2015-07-08 01:07:39 -04:00
SDRDeviceInfo * dev = ( * getDevices ( ) ) [ getDevice ( ) ] ;
config . getDevice ( dev - > getDeviceId ( ) ) - > setIQSwap ( swapIQ ) ;
2015-05-31 22:13:14 -04:00
}
bool CubicSDR : : getSwapIQ ( ) {
return sdrPostThread - > getSwapIQ ( ) ;
}
2015-01-04 17:11:20 -05:00
long long CubicSDR : : getFrequency ( ) {
2014-11-23 19:39:27 -05:00
return frequency ;
}
2014-12-10 21:22:13 -05:00
2015-08-01 11:03:00 -04:00
ScopeVisualProcessor * CubicSDR : : getScopeProcessor ( ) {
return & scopeProcessor ;
}
2015-08-03 01:38:38 -04:00
SpectrumVisualProcessor * CubicSDR : : getSpectrumProcesor ( ) {
return & spectrumProcessor ;
}
SpectrumVisualProcessor * CubicSDR : : getDemodSpectrumProcesor ( ) {
return & demodSpectrumProcessor ;
}
2015-08-11 00:50:43 -04:00
SpectrumVisualProcessor * CubicSDR : : getWaterfallProcesor ( ) {
return & waterfallProcessor ;
}
2015-08-03 01:38:38 -04:00
VisualDataDistributor < DemodulatorThreadIQData > * CubicSDR : : getSpectrumDistributor ( ) {
return & spectrumDistributor ;
}
2014-12-10 21:22:13 -05:00
DemodulatorThreadOutputQueue * CubicSDR : : getAudioVisualQueue ( ) {
2015-07-30 20:36:06 -04:00
return pipeAudioVisualData ;
2014-12-10 21:22:13 -05:00
}
2014-12-26 16:15:35 -05:00
DemodulatorThreadInputQueue * CubicSDR : : getIQVisualQueue ( ) {
2015-07-30 20:36:06 -04:00
return pipeIQVisualData ;
2014-12-10 21:22:13 -05:00
}
2015-08-11 00:50:43 -04:00
DemodulatorThreadInputQueue * CubicSDR : : getWaterfallVisualQueue ( ) {
return pipeWaterfallIQVisualData ;
}
2014-12-10 21:22:13 -05:00
DemodulatorMgr & CubicSDR : : getDemodMgr ( ) {
return demodMgr ;
}
void CubicSDR : : bindDemodulator ( DemodulatorInstance * demod ) {
if ( ! demod ) {
return ;
}
sdrPostThread - > bindDemodulator ( demod ) ;
}
2015-01-11 17:08:16 -05:00
void CubicSDR : : setSampleRate ( long long rate_in ) {
sampleRate = rate_in ;
SDRThreadCommand command ( SDRThreadCommand : : SDR_THREAD_CMD_SET_SAMPLERATE ) ;
command . llong_value = rate_in ;
2015-07-30 20:36:06 -04:00
pipeSDRCommand - > push ( command ) ;
2015-01-11 17:08:16 -05:00
setFrequency ( frequency ) ;
}
long long CubicSDR : : getSampleRate ( ) {
return sampleRate ;
}
2014-12-10 21:22:13 -05:00
void CubicSDR : : removeDemodulator ( DemodulatorInstance * demod ) {
if ( ! demod ) {
return ;
}
2015-01-22 23:41:33 -05:00
demod - > setActive ( false ) ;
2014-12-10 21:22:13 -05:00
sdrPostThread - > removeDemodulator ( demod ) ;
}
2015-01-12 00:40:43 -05:00
std : : vector < SDRDeviceInfo * > * CubicSDR : : getDevices ( ) {
return & devs ;
}
void CubicSDR : : setDevice ( int deviceId ) {
sdrThread - > setDeviceId ( deviceId ) ;
SDRThreadCommand command ( SDRThreadCommand : : SDR_THREAD_CMD_SET_DEVICE ) ;
command . llong_value = deviceId ;
2015-07-30 20:36:06 -04:00
pipeSDRCommand - > push ( command ) ;
2015-04-13 21:18:45 -04:00
SDRDeviceInfo * dev = ( * getDevices ( ) ) [ deviceId ] ;
2015-07-08 01:07:39 -04:00
DeviceConfig * devConfig = config . getDevice ( dev - > getDeviceId ( ) ) ;
2015-04-13 21:18:45 -04:00
2015-07-08 01:07:39 -04:00
setPPM ( devConfig - > getPPM ( ) ) ;
setDirectSampling ( devConfig - > getDirectSampling ( ) ) ;
setSwapIQ ( devConfig - > getIQSwap ( ) ) ;
setOffset ( devConfig - > getOffset ( ) ) ;
2015-01-12 00:40:43 -05:00
}
2015-01-12 00:51:57 -05:00
int CubicSDR : : getDevice ( ) {
return sdrThread - > getDeviceId ( ) ;
}
2015-04-13 19:58:34 -04:00
AppConfig * CubicSDR : : getConfig ( ) {
return & config ;
}
2015-04-13 21:18:45 -04:00
2015-04-22 22:54:48 -04:00
void CubicSDR : : saveConfig ( ) {
config . save ( ) ;
}
2015-04-13 21:18:45 -04:00
void CubicSDR : : setPPM ( int ppm_in ) {
if ( sdrThread - > getDeviceId ( ) < 0 ) {
return ;
}
ppm = ppm_in ;
SDRThreadCommand command ( SDRThreadCommand : : SDR_THREAD_CMD_SET_PPM ) ;
command . llong_value = ppm ;
2015-07-30 20:36:06 -04:00
pipeSDRCommand - > push ( command ) ;
2015-04-13 21:18:45 -04:00
SDRDeviceInfo * dev = ( * getDevices ( ) ) [ getDevice ( ) ] ;
2015-04-21 23:19:45 -04:00
config . getDevice ( dev - > getDeviceId ( ) ) - > setPPM ( ppm_in ) ;
2015-04-13 21:18:45 -04:00
}
int CubicSDR : : getPPM ( ) {
if ( sdrThread - > getDeviceId ( ) < 0 ) {
return 0 ;
}
SDRDeviceInfo * dev = ( * getDevices ( ) ) [ getDevice ( ) ] ;
SDRThreadCommand command_ppm ( SDRThreadCommand : : SDR_THREAD_CMD_SET_PPM ) ;
2015-04-21 23:19:45 -04:00
ppm = config . getDevice ( dev - > getDeviceId ( ) ) - > getPPM ( ) ;
2015-04-13 21:18:45 -04:00
return ppm ;
}
2015-05-04 19:44:03 -04:00
void CubicSDR : : showFrequencyInput ( ) {
2015-05-10 20:00:48 -04:00
FrequencyDialog fdialog ( appframe , - 1 , demodMgr . getActiveDemodulator ( ) ? _ ( " Set Demodulator Frequency " ) : _ ( " Set Center Frequency " ) , demodMgr . getActiveDemodulator ( ) , wxPoint ( - 100 , - 100 ) , wxSize ( 320 , 75 ) ) ;
2015-05-10 01:39:10 -04:00
fdialog . ShowModal ( ) ;
2015-05-04 19:44:03 -04:00
}
2015-05-10 01:39:10 -04:00
2015-05-10 21:43:03 -04:00
void CubicSDR : : setFrequencySnap ( int snap ) {
if ( snap > 1000000 ) {
snap = 1000000 ;
}
this - > snap = snap ;
}
int CubicSDR : : getFrequencySnap ( ) {
return snap ;
}