/*************************************************************************** |FILENAME| - description ------------------- begin : |DATE| copyright : (C) |YEAR| by |AUTHOR| email : |EMAIL| ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * ***************************************************************************/ #include "crxdisplay.h" #include #include #include #include #include #include #include #include #include #include #include "crecording.h" #include "crxchannel.h" #include "crxwindow.h" #include "csquelch.h" #include "ctrigger.h" #include "frequencyselect.h" #include "input.h" #include "textinput.h" #include "waveinput.h" #include "csound.h" #include "fircoeffs.h" #include "parameter.h" #include "color.h" extern Parameter settings; MyTabBar::MyTabBar(QWidget *parent, const char *name): QTabBar(parent,name) { Farbe=0; } MyTabBar::~MyTabBar() { } void MyTabBar::paintLabel ( QPainter *p,const QRect & br, QTab * t, bool has_focus ) const { QStyle::SFlags flags = QStyle::Style_Default; if (isEnabled() && t->isEnabled()) flags |= QStyle::Style_Enabled; if (has_focus) flags |= QStyle::Style_HasFocus; QColorGroup Cg=colorGroup(); if (Farbe > 0) { int position=t->identifier(); if ( position >= 0 && position < Farbe->size() ) Cg.setColor(QColorGroup::Foreground, Farbe->at(position)); } style().drawControl( QStyle::CE_TabBarLabel, p, this, br, Cg, flags, QStyleOption(t) ); } void MyTabBar::setColorList(std::vector *c) { Farbe=c; } /* * Constructs a CRxDisplay which is a child of 'parent', with the * name 'name'.' */ CRxDisplay::CRxDisplay( QWidget* parent, const char* name ) : QFrame( parent, name ) { setFrameShape( QFrame::WinPanel ); setFrameShadow( QFrame::Sunken ); RxFreq = new FrequencySelect( this, "RxFreq" , Wide); RxFreq->setTitle("Rx Freq / AFC"); RxFreq->setFunctionText("Narrow"); Recording = new CRecording( this, "Recording" ); Trigger = new CTrigger( this, "Trigger" ); Squelch = new CSquelch( this, "Squelch" ); RxHeader = new MyTabBar( this); RxHeader->setShape(QTabBar::RoundedAbove); Clear= new QPushButton(this,"RxClear"); Clear->setText("Clear"); QTab *Tab = new QTab("Rx 1"); Sound=0; dec2fir = new double[DEC2_LPFIR_LENGTH]; int ID=RxHeader->addTab(Tab); RxChannel = new CRxChannel(ID,this); settings.ChannelChain=RxChannel; settings.ActChannel=RxChannel; Squelch->setSquelchState(RxChannel->getSquelchState()); languageChange(); // Connect Signals and Slots RxTimer= new QTimer(this); connect(RxTimer,SIGNAL(timeout()),this,SLOT(process_rxdata())); connect(RxFreq,SIGNAL(FrequencyChanged(double)),this,SLOT(setRxFrequency(double))); connect(RxHeader,SIGNAL(selected(int)),this,SLOT(changeActiveRxWindow(int))); // connect(RxFreq,SIGNAL(toggleAFC(bool)),this,SLOT(setAFC(bool))); connect(Trigger->Activate,SIGNAL(clicked()),this,SLOT(trigger())); connect(Trigger->TriggerText,SIGNAL(returnPressed()),this,SLOT(trigger())); connect(RxChannel,SIGNAL(Triggered(int)),RxHeader,SLOT(setCurrentTab(int))); connect ( Clear, SIGNAL( clicked() ),this, SLOT(clearRxWindow())); trigger(); // We should ensure that the triggertext is stored; // Creating Variables for the fft // plan=rfftw_create_plan(BUF_SIZE/2,FFTW_REAL_TO_COMPLEX,FFTW_ESTIMATE); plan=fftw_plan_r2r_1d(BUF_SIZE/2,outbuf,output,FFTW_R2HC ,FFTW_PATIENT ); } /* * Destroys the object and frees any allocated resources */ CRxDisplay::~CRxDisplay() { // no need to delete child widgets, Qt does it all for us } /* * Sets the strings of the subwidgets using the current * language. */ void CRxDisplay::languageChange() { setCaption( tr( "RxDisplay" ) ); } void CRxDisplay::calculateSizeofComponents() { /** in percent of whole widget **/ /** RX Part **/ #define RXPARTWIDTH 64 /** Squelch **/ #define SQUELCHWIDTH 10 /** General Width **/ #define GENERALWIDTH 18 /** Recording **/ #define RECORDHEIGHT 25 /** Trigger **/ #define TRIGGERHEIGHT 33 /** RxFrequency (Height) **/ #define RXFREQHEIGHT 70 /** Left and Right Margin **/ #define LEFTANDRIGHTMARGIN 1 /** Top and Bottom Margin **/ #define TOPANDBOTTOMMARGIN 5 /** Inner distance **/ #define distance 1 /** Tab height **/ #define TABHEIGHT 10 int xpos,ypos,width,height,innerheight,innerwidth; width=this->width(); height=this->height(); xpos=width*LEFTANDRIGHTMARGIN/100; /**Recording **/ ypos=height*TOPANDBOTTOMMARGIN/100; innerwidth=width*GENERALWIDTH/100; innerheight=height*RECORDHEIGHT/100; Recording->setGeometry(xpos,ypos,innerwidth,innerheight); ypos=ypos+innerheight+height*distance/100; /** Trigger **/ innerheight=height*TRIGGERHEIGHT/100; Trigger->setGeometry(xpos,ypos,innerwidth,innerheight); /** RXFrequency **/ ypos=ypos+innerheight+height*distance/100; RxFreq->setGeometry(xpos,ypos,innerwidth,innerheight); /**SQuelch **/ xpos=xpos+innerwidth+width*distance/100; ypos=height*TOPANDBOTTOMMARGIN/100;; innerheight=height-2*ypos; innerwidth=width*SQUELCHWIDTH/100; Squelch->setGeometry(xpos,ypos,innerwidth,innerheight); /** RxWindowTabBar **/ xpos=xpos+innerwidth+width*distance/100; innerwidth=width-xpos-width*LEFTANDRIGHTMARGIN/100; innerheight=height*TABHEIGHT/100; RxHeader->setGeometry(xpos,ypos,innerwidth,innerheight); Clear->setGeometry(width-width*LEFTANDRIGHTMARGIN/100-100,ypos,100,innerheight); ypos=ypos+innerheight; innerheight=height-innerheight-height*TOPANDBOTTOMMARGIN/100; settings.ActChannel->setGeometry(xpos,ypos,innerwidth,innerheight); } void CRxDisplay::resizeEvent( QResizeEvent * ) { calculateSizeofComponents(); } bool CRxDisplay::start_process_loop() { int time; QString errorstring; if ( Sound == 0 ) { if (settings.DemoMode) { if (settings.DemoTypeNumber == 0) Sound = new WaveInput(-1); else Sound = new TextInput(-1); } else Sound = new CSound(settings.serial); } if ( Sound <= 0 ) return false; m_pDec2InPtr=dec2fir; for (int i=0; i open_Device_read(&errorstring)) { if(settings.DemoMode) time= 100; // In Demomode we should get realistic Timing, but for testing it should go quicker; else time =160; RxTimer->start(time,false); // Every 371 ms we shoud get BUF_SIZE samples in DemoMode // Or we poll the soundcard } else //Something went wrong in Opening Input File { if (settings.DemoMode) QMessageBox::information(0,"LinPsk",errorstring); else QMessageBox::critical(0,"LinPsk",errorstring); if ( Sound != 0 ) delete Sound; Sound = 0; return false; } return true; } void CRxDisplay::ProcDec2Fir(double *pIn, double *pOut,int BlockSize) { /** Decimate by 2 FIR filter on 'BlockSize' samples. pIn == pointer to input array of double's (can be same buffer as pOut ) pOut == pointer to output array of double's Blocksize == number of samples to process This Procdeure is taken from WinPSK by Moe Wheatley **/ int i,j; double acc; const double* Kptr; double* Firptr; double* Qptr; double* Inptr; Inptr = m_pDec2InPtr; //use automatic copies of member variables Qptr = dec2fir; // for better speed. j = 0; for( i = 0; i= Qptr+DEC2_LPFIR_LENGTH ) //deal with wraparound Firptr = Qptr; } pOut[j++] = acc; //save output sample } } m_pDec2InPtr = Inptr; // save position in circular delay line } void CRxDisplay::process_rxdata() { bool overload; if (Sound->getSamples(inbuf,BUF_SIZE) == 0) return; // No sample available, try later overload=false; ProcDec2Fir( inbuf, outbuf , BUF_SIZE); // 2uS per sample RxFreq->setFrequency( (unsigned int) settings.ActChannel->getRxFrequency()); Squelch->setSquelchLevel(settings.ActChannel->getSquelchValue()); settings.ActChannel->setThreshold(Squelch->getThreshold()); settings.ActChannel->setSquelch(Squelch->getSquelchState()); settings.ActChannel->setAfcMode(RxFreq->getAfcMode()); for(CRxChannel * p=RxChannel;p != 0;p=p->getNextChannel() ) if ( (p->getModulationType() != RTTY) && (p->getModulationType() != MFSK16) ) { p->processInput(outbuf,output); } else p->processInput(inbuf,output); /** Update RxFreq for the active Channel **/ emit new_IMD(settings.ActChannel->getIMD()); // Calculate FFT and start Ploting // First look for overload int N=BUF_SIZE/2; for(int i=0; i 0.77) overload=true; // Apply Hamming to Data outbuf[i] *=(0.54-0.46*cos((i*PI2)/N)); } if( !overload) for(int i=N;i 0.77 ) { overload=true; break; } fftw_execute(plan); //Calculate power spectrum for(int i=1;iaddTab(Tab); p=new CRxChannel(ID,this,Modulation,Frequency); connect(p,SIGNAL(Triggered(int)),this,SLOT(changeActiveRxWindow(int))); RxChannel->insertChannel(p); RxHeader->setCurrentTab(ID); RxHeader->repaint(); trigger(); // We should ensure that the triggertext is stored; } void CRxDisplay::setRxFrequency(double freq) { settings.ActChannel->setRxFrequency(freq); } void CRxDisplay::changeActiveRxWindow(int ID) { if (settings.ActChannel != 0 ) { settings.ActChannel->hide(); settings.ActChannel->setQsoData(settings.QslData); // Save actual Data to Channel settings.ActChannel->setAfcMode(RxFreq->getAfcMode()); if (settings.ActChannel->getChannel(ID) != 0 ) settings.ActChannel=settings.ActChannel->getChannel(ID); settings.QslData = settings.ActChannel->getQsoData(); RxFreq->setAfcDisplayMode(settings.ActChannel->AfcProperties()); RxFreq->setAfcMode(settings.ActChannel->getAfcMode()); RxFreq->setFrequency((unsigned int) settings.ActChannel->getRxFrequency()); Squelch->setSquelchState(settings.ActChannel->getSquelchState()); Squelch->setThreshold(settings.ActChannel->getThreshold()); Trigger->Activate->setChecked(settings.ActChannel->RxWindow->getTriggerStatus()); Trigger->TriggerText->setText(settings.ActChannel->RxWindow->getTriggerText()); Recording->Record->setChecked(settings.ActChannel->RxWindow->getRecordingState()); calculateSizeofComponents(); settings.ActChannel->show(); emit newActiveChannel(); RxHeader->setCurrentTab(ID); } } void CRxDisplay::stop_process_loop() { RxTimer->stop(); if (Sound != 0) { Sound->close_Device(); delete Sound; } Sound = 0 ; } void CRxDisplay::trigger() { settings.ActChannel->RxWindow->activateTrigger(Trigger->TriggerText->text()); if (!Trigger->Activate->isOn() ) settings.ActChannel->RxWindow->deactivateTrigger(); } void CRxDisplay::setColorList(std::vector *c) { RxHeader->setColorList(c); } void CRxDisplay::clearRxWindow() { settings.ActChannel->clearRxWindow(); }