Logo Search packages:      
Sourcecode: qsstv version File versions  Download package

sstvrx.cpp

#include "sstvrx.h"
#include <qstatusbar.h>
#include <qdir.h>
#include <qfile.h>
#include <qcombobox.h>
#include <qcheckbox.h>
#include <qspinbox.h>
#include "sstvtx.h"
#include "qsstvglobal.h"
#include "ledbar.h"
#include "recorder.h"
#include "filefunc.h"
#include "thumbwindow.h"
#include "repeater.h"
#include "dirdialog.h"
#include "imageframe.h"
#include <math.h>
#include "ftp.h"



#define THRESHOLDON 4
#define THRESHOLDOFF 8
#define SYNCBW 250

//#define DEBUGSSTVRX

sstvRX::sstvRX(QWidget *p ,const char *n, WFlags f):rxWindow(p,n,f),rxtxCommon()
{

#ifdef  DEBUGQSSTV
      deb= new debugger();
      connect(dsp, SIGNAL(signalEndOfInput()),this,SLOT(slotStopDump()));
#endif
      sensitivityCBox->setCurrentItem(syncDetectSensitivity);
      VISButton->setChecked(buseVIS);
      autosaveBtn->setChecked(bautoSave);
  dxBtn->setChecked(bDX);
  eraseBtn->setChecked(bautoErase);
  repeaterBtn->setChecked(brepeater);
      filterMode->setCurrentItem(idefaultFilter);
      postFilterMode->setCurrentItem(idefaultPostFilter);
      connect(canvas,SIGNAL(mouseLeftButtonPressed(QMouseEvent *)),SLOT(slotLeftMouseBtn(QMouseEvent *)));
      connect (tx,SIGNAL(signalTXEnd()),SLOT(slotTXEnd()));
      faxRunning=FALSE;
      initReceive();
//    slotStart();
}


sstvRX::~sstvRX()
{
      delete timer;
}

void sstvRX::slotStart()
{

#ifdef DEBUGSSTVRX
            debug("rx slotStart");
#endif
      tx->slotStop();
      if (lineCounter>20)
            {
                  endOfImage();
            }
      reset(); // in case we are already running
      //start receiving data
      dsp->initDSP(isamplingrate); //must be done before dsp starts filtering
      initReceive();
      dsp->startReceive();
      faxTools->setEnabled(FALSE);
      leds->setGreenLed(TRUE);
      timer->start(0,TRUE);
}

void sstvRX::initReceive()
{
#ifdef DEBUGSSTVRX
            debug("rx initReceive");
#endif
      initAllCounters();
      if (timer) delete timer;
      timer= new QTimer(this);
//    dsp->setSpectrumDisplayPointer(specDisplay);
      dsp->setFFTDisplayPointer(fftDisplay);
      if (modeSSTVFAXRX==SSTV)
            {
                  faxRunning=FALSE;
                  buildLayoutSSTV();
                  connect( timer, SIGNAL(timeout()),this,SLOT(slotSSTVDecode()));
                  switchSyncDetect(TRUE); //must be done before dsp starts filtering
                  currentMode=999; // set to invalid
                  if ((brepeater)&&(!brepGetPicture))
            {
                  permText->setText("Waiting for toneburst");
                  gotoState(REPTONE);
            }
      else
            {
                  permText->setText("Waiting for image");
            }
            }
      else
            {
                  sampleSum=0; pcounter=0;
                  connect( timer, SIGNAL(timeout()),this,SLOT(slotFAXDecode()));
                  //calculate the lineTime
                  lineTime=60./lpmSpinBox->value();
                  faxInversePolarity=invPolCheckBox->isChecked();
                  //calculate aspectratio
                  // The aspectratio is given by the ioc
                  // ioc is defined as total line length multiplied by
                  // the number of lines per unitlength divided by PI
                  // from there we calculate the number of pixels per line
                  // lpu*ll/PI=ioc
                  // lpu=ioc*PI/ll
                  // we take lpu=1 (this is the case for square pixels
                  // then ll= 288*3.1419 = 905
                  // lpu=204
                  pixelsPerLine=(unsigned int)(iocSpinBox->value()*M_PI+.5);
                  buildLayoutFAX(pixelsPerLine,linesSpinBox->value());
                  time1PerPixel=lineTime/pixelsPerLine;
                  videoBuffer0=canvas->getLineAddress(lineCounter);
                  switchSyncDetect(FALSE);
                  buildLUT();
                  if(faxRunning)
                        {
                              permText->setText("Receiving Image");
                              faxState=FAXFORCE;
                        }
                  else
                        {
                              permText->setText("Waiting for FAX start");
                              faxState=FAXIDLE;
                        }
            }
}

void sstvRX::reset()
{
      leds->setRedLed(TRUE);
      timer->stop();
      dsp->stop();
      dumpActive=FALSE;
      faxTools->setEnabled(TRUE);
}

void sstvRX::slotStop()
{
      reset();
      faxRunning=FALSE;
}

void sstvRX::slotTXEnd()
{
      if(brepeater) return;
      slotStart();
}

void sstvRX::slotSSTVFAX(int i)
{
      modeSSTVFAXRX= i;
      reset();
      faxRunning=FALSE;
      initReceive(); // to update the layout
}

void sstvRX::slotTop()
{
      lineCounter=0;
  slotResync();
}



void sstvRX::slotResync()
{
      resyncFlag=TRUE;
#ifdef DEBUGSSTVRX
      debug("resync sc=%lu",imageSampleCounter);
#endif
}




void sstvRX::slotVisButton(bool b)
{
 buseVIS=b;
 gotoState(STARTPIC);
}


void sstvRX::gotoState(eTxRxState s)
{
      
      armFrequencyDetection();
      stateSampleCounter=0;
      if(state!=s)
            {
#ifdef DEBUGSSTVRX
            debug("changing to state: %s lineCounter=%u sc=%lu ssc=%lu",stateString[s],lineCounter,
                                          imageSampleCounter,stateSampleCounter);
#endif
            }
      state=s;    
}


void sstvRX::slotSSTVDecode()
{
      int i;
      int r,g,b;
      char temp[50];
      do
            {
            switch(state)
                  {
                        case STARTPIC:
                              {
                                    bincomingImage=FALSE;
                                    switchSyncDetect(TRUE);
                                    imageSampleCounter=0;
                                    lineCounter=0;
                              if (buseVIS)
                                    {
                                          leds->setYellowLed(TRUE);
                                          statusBar()->message("VIS Code Detection");
                                          gotoState(F1900A);
                                    }
                              else
                                    {
                                          initAnalyseSync();
                                    }
                              }
                        break;
                        case F1900A:
                              {
                                    // First 1900Hz signal
                                    visCode=0;
                        visBits=0;
                        if ((freqResult=waitForTonePulse(1900.,500,0.03))!=FDETECTWAIT)
                                    {
                                    if (freqResult==FDETECTOK)
                                          {
                                                            gotoState(VISSTART);
                                          }
                                    else
                                          {
                                                            gotoState(F1900A); //force arm frequency
                                          }
                                    }
                        }
                    break;
                        case VISSTART:
                              {
                                    if((freqResult=measureFrequency(.03))!=FDETECTWAIT)
                              {
                                                if ((averageFrequency<1300) && (averageFrequency>1100))
                                                {
                                                gotoState(VISDATA);
                                                }
                                                else
                                                {     
                                                gotoState(F1900A); //continue waiting
                                                }
                              }
                              }
                        break;
                  
                        case VISDATA:
                              {
                        if((freqResult=measureFrequency(.03))!=FDETECTWAIT)
                              {
                                                if (averageFrequency>1500)
                                                {
#ifdef DEBUGSSTVRX      
                                                debug("false vis %f",averageFrequency);
#endif                                          
                                                gotoState(STARTPIC);
                                                break;
                                                }
                                                else
                                                {
                                                visCode=visCode>>1;
                                                if (averageFrequency<1200)
                                                      {
                                                                        visCode+=0x100;
                                                      }
                                                    if (++visBits>=9)
                                                      {
                                                                        visCode&=0xff;
                                                                        int tcode=lookupModeCode(visCode);
                                                                        if (tcode<NUMBEROFRXMODES)
                                                                        {
                                                                        changeMode(tcode);
                                                                        gotoState(VISSTOP);
                                                                        break;
                                                                        }
                                                                        else
                                                                        {
                                                                        sprintf(temp,"Unknown Mode %x",visCode);
                                                                        permText->setText(temp);                  
                                                                        gotoState(STARTPIC);
                                                                        break;
                                                                        }
                                                                  }
                                                }
                                                gotoState(VISDATA);
                                          }
                  }                       
                        break;
                        case VISSTOP:
                              {
                                    leds->setGreenLed(TRUE);
                              
                        if((freqResult=waitForEndTone(1200.,SYNCBW))!=FDETECTWAIT)
                              {
                                    switchSyncDetect(FALSE);
                                    if(sstvparam.colorScheme!=GBR2)
                                          {
                                                calculateTiming();
                                                reposition((int)(hsTime*fRXsamplingrate));
                                          }
                                                gotoState(PHASET0);
                                                imageSampleCounter=0;
                                    }
                              }
                        break;
                        case HUNT:
                              {
                              
                                    if((freqResult=waitForTonePulse(1200.,SYNCBW,0.0025))!=FDETECTWAIT)
                              {
                                                if(freqResult==FDETECTOK)
                                                {
                                                      leds->toggleYellowLed();
                                                      shiftSyncArray();
                                                syncArray[AUTODETLEN-1].syncDuration=pulseDuration;
                                                syncArray[AUTODETLEN-1].readPointer=dsp->getReadPtr();
                                                if(analyseSync())
                                                      {
                                                            // we got a valid sync series, analyseSync changes the state
                                                            syncDisplay->setData(syncArray[AUTODETLEN-syncDetectCounter-1].readPointer);
                                                            syncDisplay->draw();
                                                            break;
                                                      }
                                          }
                                    gotoState(HUNT); // to rearm freq. detection
                                    
                                          }
                  }
                  break;
                  case PHASET0: // start of a new line
                        {
                              if (resyncFlag)
                              {
                                                initAnalyseSync(); // will switch to HUNT mode
                                                break;
                              }
                                    if (lineCounter<(sstvparam.numberOfLines-1))
                              {
                                                calculateTiming();
                                                if (lineCounter>0)
                                                      {
#ifdef DEBUGSSTVRX                                                            
                                                            debug("display draw ptr %d", dsp->getReadPtr());
#endif
                                                            syncDisplay->draw(); // realy the sync from the previous line
                                                      }
                                                gotoState(getNextState(state));
                              }
                        else
                              {
                                                endOfImage();
                              }
                        }
                  break;
                  case PHASET1: //get sync
                        {
                              
                        if ((freqResult=measureFrequencyEndTime(hsTime))!=FDETECTWAIT)
                                    {
#ifdef DEBUGSSTVRX                                                            
                                    debug("display sync ptr %d", dsp->getReadPtr());
#endif
                                          syncDisplay->setData(dsp->getReadPtr());
                                        float af=averageFrequency;
                                          if ((af>1850.)&&(af<1950.)&&(!bDX))
                                        {
                                                            if (lineCounter>20)
                                                            {
#ifdef DEBUGSSTVRX                                                            
                                                                  debug("restart on 1900 Hz");
#endif
                                                                  endOfImage();
                                                            }
                                                            gotoState(STARTPIC);
                                          }
                                    else
                                          {
                                                            gotoState(getNextState(state));
                                          }
                                    }
                  }
                        break;
                        case PHASET2: //get backporch       
                              {
                        if ((freqResult=measureFrequencyEndTime(bpTime))!=FDETECTWAIT)
                              {
                                                gotoState(getNextState(state));
                              }
                        }
                  break;
                        case PHASET3: // Get RED  Line
                        {
                        nextSubline(REDLINE);    // will switch to next state
                        }
                        break;
                        case PHASET4: // Get GREEN Line
                        {
                        nextSubline(GREENLINE); // will switch to next state
                  }
                  break;
                        case PHASET5: // Get BLUE Line
                        {
                        nextSubline(BLUELINE);  // will switch to next state
              }
                  break;
                        case PHASET6:
                        case PHASET7:
                        {
                            if((freqResult=calcPixel(time1PerPixel))!=FDETECTWAIT)
                          {
                                                gotoState(getNextState(state));
                              }
                        }                 
                        break;
                        case PHASET8: // get a complete line
                        {
                            if((freqResult=calcPixel(time2PerPixel))!=FDETECTWAIT)
                          {
                                                gotoState(getNextState(state));
                              }
                        }
                  break;
                        case PHASET9:
                              {
                                    if((freqResult=measureFrequencyEndTime(f1Time))!=FDETECTWAIT)
                                          {
                                                if ((sstvparam.colorScheme==XYZOE)&&((lineCounter&1)==0))
                                                      {
                                                if ((averageFrequency>2000)&&(averageFrequency<2300))
                                                            {
                                                            robotResync=TRUE;
#ifdef DEBUGSSTVRX
                                                            debug("robot resync");
#endif
                                                            }
                                          }
                                                gotoState(getNextState(state));
                                          }
                              }
                        break;
                        case PHASETA:
                              {
                                    if((freqResult=measureFrequencyEndTime(f2Time))!=FDETECTWAIT)
                                          {
                                                gotoState(getNextState(state));
                                          }
                              }
                        break;
                        case PHASETB:
                              {
                                    if((freqResult=measureFrequencyEndTime(f3Time))!=FDETECTWAIT)
                                          {
                                                gotoState(getNextState(state));
                                          }
                              }
                        break;
                        case PHASETC:
                              {
                                    if((freqResult=measureFrequencyEndTime(f4Time))!=FDETECTWAIT)
                                          {
                                                gotoState(getNextState(state));
                                          }
                              }
                        break;                        
                        case PHASETD:
                              {
                                    if((freqResult=measureFrequencyEndTime(f5Time))!=FDETECTWAIT)
                                          {
                                                gotoState(getNextState(state));
                                          }
                              }
                        break;
                        case PHASETE:
                        {
                        if((freqResult=measureFrequencyEndTime(fpTime))!=FDETECTWAIT)
                              {
                                                gotoState(getNextState(state));
                              }
                        }
                  break;
                        case NEXTRGB:
                        {
                        for (i=0;i<sstvparam.numberOfPixels;i++)
                              {
                                                videoBuffer1[i]=qRgb(pixbuf0[i],pixbuf1[i],pixbuf2[i]);
                                                 // videoBuffer1[i]=qRgb(255,255,255);
                              }
                        canvas->showLine(sstvparam.numberOfPixels,lineCounter);
                        lineCounter++;
                        gotoState(getNextState(state));
                        }
                  break;
                        case NEXTXYZOE:
                        {
                            if((lineCounter&1)==1)
                          {
                                                for (i=0;i<sstvparam.numberOfPixels;i++)
                                                {
                                                r=(100*pixbuf0[i]+140*pixbuf1[i]-17850)/100;
                                                b=(100*pixbuf0[i]+178*pixbuf3[i]-22695)/100;
                                                g=(100*pixbuf0[i]- 71*pixbuf1[i]-33*pixbuf3[i]+13260)/100;
                                                r=(r>255 ? 255 : r);
                                                r=(r<0 ? 0 : r);
                                                b=(b>255 ? 255 : b);
                                                b=(b<0 ? 0 : b);
                                                g=(g>255 ? 255 : g);
                                                g=(g<0 ? 0 : g);
                                                videoBuffer0[i]=qRgb(r,g,b);
                                                r=(100*pixbuf2[i]+140*pixbuf1[i]-17850)/100;
                                                b=(100*pixbuf2[i]+178*pixbuf3[i]-22695)/100;
                                                g=(100*pixbuf2[i]- 71*pixbuf1[i]-33*pixbuf3[i]+13260)/100;
                                                r=(r>255 ? 255 : r);
                                                r=(r<0 ? 0 : r);
                                                b=(b>255 ? 255 : b);
                                                b=(b<0 ? 0 : b);
                                                g=(g>255 ? 255 : g);
                                                g=(g<0 ? 0 : g);
                                                videoBuffer1[i]=qRgb(r,g,b);
                                                }
                                                canvas->showLine(sstvparam.numberOfPixels,lineCounter-1);
                                                canvas->showLine(sstvparam.numberOfPixels,lineCounter);
                              }
                              if(!robotResync)
                                    {
                                     lineCounter++;
                                    }
                              else
                                    {
                                          robotResync=FALSE;
                                    }
                              gotoState(getNextState(state));
                        }
                        break;

                  case NEXTXYZOE2:
                  {
                  for (i=0;i<sstvparam.numberOfPixels;i++)
                        {
                                          r=(100*pixbuf0[i]+140*pixbuf1[i]-17850)/100;
                                          b=(100*pixbuf0[i]+178*pixbuf2[i]-22695)/100;
                                          g=(100*pixbuf0[i]- 71*pixbuf1[i]-33*pixbuf2[i]+13260)/100;
                                          r=(r>255 ? 255 : r);
                                          r=(r<0 ? 0 : r);
                                          b=(b>255 ? 255 : b);
                                          b=(b<0 ? 0 : b);
                                          g=(g>255 ? 255 : g);
                                          g=(g<0 ? 0 : g);
                                          videoBuffer1[i]=qRgb(r,g,b);
                        }
                  canvas->showLine(sstvparam.numberOfPixels,lineCounter);
                  lineCounter++;
                  gotoState(getNextState(state));
            }
                  break;
                  case REPTONE:
                  {
                  if ((freqResult=waitForTonePulse(1750.,100,0.6))!=FDETECTWAIT)
                        {
                                          if (freqResult==FDETECTOK)
                                          {
                                          permText->setText("Waiting for start of image");
                                          rep->slotSendAck();
                                          freqResult=FDETECTWAIT; //leave loop
                                          slotStop();
                                          }
                                          else
                                          {
                                          gotoState(REPTONE); // force arm freq det.
                                          }
                        }
                  }
            break;                        
                  default:
#ifdef DEBUGSSTVRX
                        debug(" faulty rx state %s",stateString[state]);
#endif
            gotoState(STARTPIC);
                  break;
                  }
            }
      while (freqResult!=FDETECTWAIT);
      vu->setProgress(dsp->getVolume());
      timer->start(250,TRUE);
}



void sstvRX::changeMode(uint tcode)
{
  char temp[50];
  if(currentMode!=tcode)
    {
      currentMode=tcode;
      initializeTable(tcode);
      buildLayoutSSTV();
    }
  if ((bautoErase)&&(!resyncFlag))
    {
      slotErase();
    }
      sprintf(temp,"%s",sstvparam.name);
#ifdef DEBUGSSTVRX
      debug(" mode changed to %s",sstvparam.name);
#endif
  permText->setText(temp);
}

void sstvRX::armFrequencyDetection()
{
  detectState=DETECTSTART;
  threshold=0;
  threshold_end=THRESHOLDOFF;
  detectedSamples=0;
  pulseDuration=0;
  averageFrequency=0;
  stateSampleCounter=0;
  frequencyError=0;
}

// detect a tone pulse


efreqReturn sstvRX::waitForEndTone(float freq,float bandwidth)
{
  float fUpper,fLower;
  fLower=freq-bandwidth;
  fUpper=freq+bandwidth;

  while(getData())
    {
      pulseDuration+=(1./fRXsamplingrate);
      if((sample>fLower)&&(sample<fUpper))
                        {
                        threshold_end=(threshold_end<THRESHOLDOFF ? ++threshold_end:THRESHOLDOFF);
                        averageFrequency+=sample;
                        detectedSamples++;
                        }
      else
                        {
                        threshold_end=(threshold_end>0 ? --threshold_end :0);
                        }
      if (threshold_end==0)
                        {
                        averageFrequency/=detectedSamples;
                        reposition(THRESHOLDOFF);
                        return FDETECTOK;
                        }
    }
  return FDETECTWAIT;
}





efreqReturn sstvRX::waitForTonePulse(float freq,float bandwidth,float minimumDuration)
{
  float fUpper,fLower;
  fLower=freq-bandwidth;
  fUpper=freq+bandwidth;

  if(minimumDuration==0)
    {
      return FDETECTOK;
    }
  while(getData())
    {
      pulseDuration+=(1./fRXsamplingrate);
      if((sample<fUpper)&&(sample>fLower))
                        {
                        threshold=(threshold<THRESHOLDOFF ? ++threshold:THRESHOLDOFF);
                        averageFrequency+=sample;
                        detectedSamples++;
                        }
      else
                        {
                              threshold=(threshold>0 ? --threshold :0);
                        }
                  switch (detectState)
                        {
                              case DETECTSTART:
                              {
                                  if (threshold>=THRESHOLDON)
                                    {
                                                      pulseDuration=THRESHOLDON/fRXsamplingrate;
                                                      detectState=DETECTED;
                                                      threshold=THRESHOLDOFF;
                                    }
                              }
                              break;
                              case DETECTED:
                              {
                              if (threshold==0)
                                    {
                                                      averageFrequency/=detectedSamples;
                                                      pulseDuration-=(THRESHOLDOFF/fRXsamplingrate);
                                                      if(pulseDuration>=minimumDuration)
                                                      {
                                                            reposition(THRESHOLDOFF);
                                                      return FDETECTOK;
                                                      }
                                                      else
                                                      {
                                                            return FDETECTFAILED;
                                                      }
                                    }
                              }
                              break;
                        }
    }
  return FDETECTWAIT;
}




efreqReturn sstvRX::measureFrequency(float duration,float delay)
{
      // we will just skip the delay at the beginning and the end of the pulse
      float a;
  if (duration==0)
    {
     return FDETECTOK;
    }
  while(getData())
    {
      pulseDuration+=(1/fRXsamplingrate);
      if((pulseDuration>=delay)&&(pulseDuration<=duration-delay))
            {
                  averageFrequency+=sample;
                  detectedSamples++;
                        a=averageFrequency/detectedSamples-sample;
                        frequencyError+=(a*a);
            }
                  if (pulseDuration>=duration)
                        {
                              averageFrequency/=detectedSamples;
                              frequencyError/=detectedSamples;
                        return FDETECTOK;
                        }
    }
  return FDETECTWAIT;
}

bool sstvRX::testAverageFrequency(float freq,float error)
{
      if ((freq<(averageFrequency-error))|| (freq>(averageFrequency+error)))
            {
                  return FALSE;
            }
      if(frequencyError>(error*error))
            {
                  return FALSE;
            }
      return TRUE;
}

/** measure the frequency until end time is reached */

efreqReturn sstvRX::measureFrequencyEndTime(double endTime)
{

  while(((((double)imageSampleCounter))/(double)fRXsamplingrate)<endTime)
    {
      if(!getData())
                        {
                        return FDETECTWAIT;
                        }
      pulseDuration+=(1/fRXsamplingrate);
      averageFrequency+=sample;
      detectedSamples++;
    }
  averageFrequency/=detectedSamples;
  return FDETECTOK;
}


void sstvRX::initAnalyseSync()
{
      int i;
      for(i=0;i<AUTODETLEN;i++)
            {
                  syncArray[i].readPointer=0;
                  syncArray[i].syncDuration=0;
            }
      syncDetectCounter=0;
      switchSyncDetect(TRUE);
      statusBar()->message("Hunting");
      leds->setRedLed(TRUE);
      gotoState(HUNT);
}

bool sstvRX::analyseSync()
{
      // analyze the syncarray to find to correct sync and mode
      float pd0=0;
      float pd1=0;
      float pd2=0;
      float tlineTime=0;
      float tlineTime1=0;
      float tlineTime2=0;
      unsigned short diffrp1,diffrp2;
      bool verticalSyncFlag=FALSE;
      int tc;
      bool valid=FALSE;
      diffrp1=syncArray[AUTODETLEN-2].readPointer-syncArray[AUTODETLEN -3].readPointer;
      diffrp2=syncArray[AUTODETLEN-1].readPointer-syncArray[AUTODETLEN -2].readPointer;
      pd0=syncArray[AUTODETLEN-3].syncDuration;
      pd1=syncArray[AUTODETLEN-2].syncDuration;
      pd2=syncArray[AUTODETLEN-1].syncDuration;
      if((pd0>0.27)&&(pd0<0.35))
            {
                  verticalSyncFlag=TRUE;
            }
      tlineTime1=diffrp1/fRXsamplingrate;
      tlineTime2=diffrp2/fRXsamplingrate;
#ifdef DEBUGSSTVRX
      debug("pd = %f, %f, %f tl1= %f, tl2= %f freq:=%f samplecount=%lu",
            pd0,pd1,pd2,tlineTime1,tlineTime2,averageFrequency,sampleCounter);
#endif
      if ((tlineTime1>0.12)&&(tlineTime2>0.12))
            {
                  if (((tlineTime1-tlineTime2)<0.01)&&((tlineTime1-tlineTime2)>-0.01))
                        {
                              tlineTime=(tlineTime1+tlineTime2)/2;
                              valid=TRUE;
                        }
                  else if(((tlineTime1-tlineTime2/2)<0.01)&&((tlineTime1-tlineTime2/2)>-0.01))
                        {
                              tlineTime=(tlineTime1+tlineTime2)/3;
                              valid=TRUE;
                        }
                  else if(((tlineTime1/2-tlineTime2)<0.01)&&((tlineTime1/2-tlineTime2)>-0.01))
                        {
                              tlineTime=(tlineTime1+tlineTime2)/3;
                              valid=TRUE;
                        }
            }
      if (!valid)
        {
            syncDetectCounter=0;
                  return FALSE;
            }
      
      if((tc=modeLookup(tlineTime))==-1)
            {
#ifdef DEBUGSSTVRX
                  debug("errorreject");
#endif
                  return FALSE;
            }
      syncDetectCounter++;
      if(syncDetectCounter<(unsigned int)(3-syncDetectSensitivity))
            {
                  return FALSE;
            }
      syncWidth=(pd1+pd2)/2;
      if(verticalSyncFlag)
      {
                  syncWidth=(pd1+pd2)/2;
            resyncFlag=FALSE; //must be before changemode to allow erase
            changeMode(tc);
            lineCounter=0;
#ifdef DEBUGSSTVRX
            debug("rp %u sa %u ts %u",dsp->getReadPtr(),syncArray[AUTODETLEN-2-syncDetectCounter].readPointer,(unsigned short int)( sstvparam.hs.t*fRXsamplingrate));
#endif
            reposition(dsp->getReadPtr()-syncArray[AUTODETLEN-2-syncDetectCounter].readPointer
                        +(unsigned short int)( sstvparam.hs.t*fRXsamplingrate));
#ifdef DEBUGSSTVRX
            debug("rp %u",dsp->getReadPtr());   
            debug("rpv=%d",syncArray[AUTODETLEN-2-syncDetectCounter].readPointer);
#endif
            imageSampleCounter=0;
      }
      else
      {
            syncWidth=(pd0+pd1+pd2)/3;
            changeMode(tc);
            resyncFlag=FALSE; //must be after changemode to avoid erase
            if(sstvparam.colorScheme!=GBR2) //all modes start with a syncpulse except Scottie 1 & 2
                  {
#ifdef DEBUGSSTVRX
                  debug("non-scottie mode in analysesync");
                  debug("rp %u sa %u ts %u",dsp->getReadPtr(),syncArray[0].readPointer,(unsigned short int)( sstvparam.hs.t*fRXsamplingrate));
#endif
                        reposition(dsp->getReadPtr()-syncArray[AUTODETLEN-1-syncDetectCounter].readPointer
                        +(unsigned short int)( sstvparam.hs.t*fRXsamplingrate));
#ifdef DEBUGSSTVRX
                        debug("rp %u",dsp->getReadPtr());   
#endif                  
                  }
            else
                  {
#ifdef DEBUGSSTVRX
                        debug("scottie mode in analysesync");
#endif
                        double ltime=(sstvparam.imageTime)/sstvparam.numberOfLines
                              -sstvparam.f1.t-sstvparam.f2.t
                              -sstvparam.fp.t-sstvparam.hs.t
                              -sstvparam.bp.t;
                        double ttime=2*ltime/3 +sstvparam.hs.t+sstvparam.fp.t
                                                            +sstvparam.f1.t+sstvparam.f2.t;
                        unsigned short int tsamples=(unsigned short int) (ttime*fRXsamplingrate);
#ifdef DEBUGSSTVRX
                        debug("rp %u sa %u ts %u",dsp->getReadPtr(),syncArray[AUTODETLEN-1-syncDetectCounter].readPointer,tsamples);
#endif
                        reposition(dsp->getReadPtr()-syncArray[AUTODETLEN-1-syncDetectCounter].readPointer+tsamples);
#ifdef DEBUGSSTVRX
                        debug("rp %u",dsp->getReadPtr());               
#endif
                  }
            imageSampleCounter=(unsigned int)((sstvparam.imageTime*((double)lineCounter)/sstvparam.numberOfLines)*fRXsamplingrate);
            }
      leds->setGreenLed(TRUE);
      statusBar()->message("Receiving");
      switchSyncDetect(FALSE);
      gotoState(PHASET0); // start with a new line
      return TRUE;
}
            


void sstvRX::shiftSyncArray()
{
      int i;
      for(i=1;i<AUTODETLEN;i++)
            {
        syncArray[i-1]=syncArray[i];
            }
}


void sstvRX::endOfImage()
{
  char strtemp[100];
  int intdate,inttime;
  QFile fn;
  QDir stemp;
  QFileInfo t;
  QTime tim=QTime::currentTime();
  QDate dat = QDate::currentDate();
  intdate=dat.year()*10000+dat.month()*100+dat.day();
  inttime=tim.hour()*100+tim.minute();
  stemp.setPath(configFile.readOption("ImageRxDir"));
  if(bautoSave)
    {
      if (modeSSTVFAXRX==SSTV)
            {
                  sprintf(strtemp,"%s_%d_%d",getMode(currentMode),intdate,inttime);
            }
      else
            {
                  sprintf(strtemp,"%s_%d_%d","fax_",intdate,inttime);
            }
    }
  else
    {
      sprintf(strtemp,"tmp_%d_%d",tw->getRow(),tw->getColumn());
    }
  t.setFile(stemp,strtemp);
  changeExtension(t,configFile.readOption("ImageFormat"),TRUE);
  canvas->save(t.filePath());
  tw->add(t.filePath());
  lineCounter=0; // to avoid restart through slotStart()
  if(brepeater)
    {
      rep->slotSendPicture(currentMode);
      gotoState(REPTONE);
    }
  else if (bftp)
      {
            // send image to an ftp server
            QString h(configFile.readOption("FTPHost"));
                  QString u(configFile.readOption("FTPUser"));
                  QString p(configFile.readOption("FTPPassword"));
                  QString r(configFile.readOption("FTPRemDirectory"));
                  ftpPtr= new ftp(h,u,p);
            ftpPtr->upload(t.filePath(),configFile.readOption("FTPFilename"),r);
      }
  else
    {
      gotoState(STARTPIC);
    }
}




void sstvRX::nextSubline(uint line)
{
  pixelCounter=0;
  tempColor=0;
  tempColorCounter=1;
  videoBuffer1=canvas->getLineAddress(lineCounter%sstvparam.numberOfLines);
  switch(sstvparam.colorScheme)
    {
      case GBR:
                  case GBR2:
                  case RGB:
            {
                              if (line==REDLINE)
                              {
                              buf=pixbuf0;
                              }
                              else if (line==GREENLINE)
                              {
                              buf=pixbuf1;
                        }
                              else
                              {
                              buf=pixbuf2;
                        }
                        }
                  break;
                  case XYZOE:
            {
                              if (line==REDLINE)
                              {
                                    if((lineCounter&1)==0)
                              {
                                                      buf=pixbuf0;
                                    }
                              else
                                    {
                                                      videoBuffer0=canvas->getLineAddress((lineCounter-1)%sstvparam.numberOfLines);
                                                      buf=pixbuf2;
                                                }
                                    }
                              else
                              {
                              if((lineCounter&1)==0)
                                    {
                                                      buf=pixbuf1;
                                    }
                              else
                                    {
                                                      buf=pixbuf3;
                                    }
                              }
                  }
            break;
                  case XYZOE2:
            {
                              if (line==REDLINE)
                              {
                              buf=pixbuf0;
                              }     
                              else if (line==GREENLINE)
                              {
                              buf=pixbuf1;
                                    }
                              else
                              {
                              buf=pixbuf2;
                              }
            }
                  break;
    }
      gotoState(getNextState(state));
}



efreqReturn sstvRX::calcPixel(double timePerPixel)
{
  uint color;
  while (pixelCounter<sstvparam.numberOfPixels)
    {
      if(!getData())
                        {
                        return FDETECTWAIT;
                        }
      if(!bDX)
                        {
                        if  ((sample<(1200+SYNCBW))&&(sample>(1200-SYNCBW)))
                        {
                              syncInPixel++;
                              if (((float)syncInPixel/fRXsamplingrate)>sstvparam.hs.t)
                                                {
#ifdef DEBUGSSTVRX
                                                  debug("sync in video found");
#endif                                                
                                                }
                        }
                        else
                        {
                              syncInPixel=(syncInPixel>0 ? --syncInPixel : 0);
                        }
                        }
                  
      sample=(sample<1500 ? 1500 : sample);
      sample=(sample>=2300 ? 2300-2300/10000 : sample);
      color=(uint)(((sample-1500)*255)/(2300-1500));
      if (((double)pixelCounter*timePerPixel) < (((double)stateSampleCounter/(double)fRXsamplingrate)))
                        {     
                        buf[pixelCounter]=(unsigned char)((color+tempColor)/tempColorCounter);
                        //  buf[pixelCounter]=(unsigned char)(color);
                        pixelCounter++;
                        tempColor=0;
                        tempColorCounter=1;
                        }
      else
                        {
                        tempColor+=color;
                        tempColorCounter++;
                        }
    }
  return FDETECTOK;
}



void sstvRX::switchSyncDetect(bool t)
{
      // dynamically switch the center frequency
      if(t)
            {
#ifdef DEBUGSSTVRX
                  debug("switching to sync detect");
#endif
                  bincomingImage=FALSE;
                  dsp->computeSineTable(isamplingrate,1600,1);
                  dsp->setFilter(F800);  // smal bandwidth
                  dsp->setPostFilter(MEDIUM);
            }
      else
            {
#ifdef DEBUGSSTVRX
      debug("switching to video detect");
#endif
                  bincomingImage=TRUE;
                  dsp->computeSineTable(isamplingrate,1900,19);
                  dsp->setPostFilter(selectedPostFilter);
                  dsp->setFilter(selectedFilter);
            }
}

void sstvRX::slotFilterChange(int fil)
{
      idefaultFilter=fil;
      selectedFilter=(enum efilterType)fil;
      if(bincomingImage==TRUE) // avoid changing settings during sync detect
            {
                  dsp->setFilter(selectedFilter); //allow on the fly change of the filter
            }
}

void sstvRX::slotPostFilterChange(int fil)
{
      idefaultPostFilter=fil;
      selectedPostFilter=(enum epostFilterType)fil;
      if(bincomingImage==TRUE) // avoid changing settings during sync detect
            {
                  dsp->setPostFilter(selectedPostFilter); //allow on the fly change of the filter
            }
}



void sstvRX::slotLeftMouseBtn(QMouseEvent *e)
{
      if (modeSSTVFAXRX==SSTV)
            {
                  slotZoom();
            }
      else
            {
#ifdef DEBUGSSTVRX            
                  debug("mous x=%d lpc=%u line=%u",e->x(),linePixelCounter,lineCounter);
#endif
                  canvas->rotate(e->x(),lineCounter);
                  pixelCounter-=(uint)(e->x()*time1PerPixel*(double)fRXsamplingrate);
                  imageSampleCounter-=(uint)(e->x()*time1PerPixel*(double)fRXsamplingrate);
                  if(linePixelCounter<(uint)e->x())
                        {
                              linePixelCounter+=pixelsPerLine-e->x();
                              lineCounter--;

                        }
                  else
                        {
                              linePixelCounter-=e->x();
                        }
#ifdef DEBUGSSTVRX            
                  debug("new  x=%d lpc=%u line=%u",e->x(),linePixelCounter,lineCounter);
#endif                        
                  canvas->showLine(pixelsPerLine,0,lineCounter+1);
            }
}




void sstvRX::slotDump()
{
#ifdef  DEBUGQSSTV
      //reading from file
      QString fn;
  dirDialog dd(0,0,TRUE);
  slotStop();
  fn=dd.openFileName(configFile.readOption("SoundDir"),"*.raw");
  if(!fn.isNull())
    {
                  dsp->enableDump(fn,NULL);
                  if(deb->openForWrite(fn))
                        {
                              dsp->initDSP(isamplingrate);
                              initReceive();
                              dsp->startReceive();
                              timer->start(0,TRUE);
                              dumpActive=TRUE;
                        }
                  else
                        {
                              dsp->disableDump();
                              slotStart();
                        }
    }
#endif
}



void sstvRX::slotStopDump()
{
#ifdef  DEBUGQSSTV
      deb->stop();
      dumpActive=FALSE;
      dsp->disableDump();
#endif
}


void sstvRX::slotPlot()
{
#ifdef  DEBUGQSSTV
#endif
}

void sstvRX::slotRecord()
{
#ifdef  DEBUGQSSTV
      slotStop();
  recorder stf(this,"Recording");
  stf.saveFile();
#endif
}










Generated by  Doxygen 1.6.0   Back to index