kopia lustrzana https://github.com/xdsopl/qsstv
351 wiersze
6.8 KiB
C++
351 wiersze
6.8 KiB
C++
#include "sstvtx.h"
|
|
#include "appglobal.h"
|
|
#include "configparams.h"
|
|
#include "soundbase.h"
|
|
#include "cw.h"
|
|
#include "dispatcher.h"
|
|
#include "synthes.h"
|
|
#include "modes/modes.h"
|
|
#include "txfunctions.h"
|
|
|
|
|
|
|
|
sstvTx::sstvTx()
|
|
{
|
|
currentMode=0;
|
|
oldMode=NOTVALID;
|
|
}
|
|
sstvTx::~sstvTx()
|
|
{
|
|
if(currentMode) delete currentMode;
|
|
}
|
|
|
|
void sstvTx::init()
|
|
{
|
|
sampleCounter=0;
|
|
}
|
|
|
|
|
|
|
|
|
|
void sstvTx::sendPreamble()
|
|
{
|
|
addToLog("txFunc:sendPreamble",LOGTXFUNC);
|
|
|
|
synthesPtr->sendTone(0.1,1900.,0,true);
|
|
synthesPtr->sendTone(0.1,1500.,0,true);
|
|
synthesPtr->sendTone(0.1,1900.,0,true);
|
|
synthesPtr->sendTone(0.1,1500.,0,true);
|
|
synthesPtr->sendTone(0.1,2300.,0,true);
|
|
synthesPtr->sendTone(0.1,1500.,0,true);
|
|
synthesPtr->sendTone(0.1,2300.,0,true);
|
|
synthesPtr->sendTone(0.1,1500.,0,true);
|
|
synthesPtr->sendTone(0.3,1900.,0,true);
|
|
synthesPtr->sendTone(0.01,1200.,0,true);
|
|
synthesPtr->sendTone(0.3,1900.,0,true);
|
|
}
|
|
|
|
|
|
|
|
void sstvTx::sendVIS()
|
|
{
|
|
int i,l;
|
|
int t=txSSTVParam.VISCode;
|
|
addToLog("txFunc:sendVis",LOGTXFUNC);
|
|
if(currentMode->isNarrow())
|
|
{
|
|
l=24;
|
|
synthesPtr->sendTone(0.300,1900,0,true);
|
|
synthesPtr->sendTone(0.100,2100,0,true);
|
|
synthesPtr->sendTone(0.022,1900,0,true); // startbit
|
|
for (i=0;i<l;i++)
|
|
{
|
|
if((t&1)==1) synthesPtr->sendTone(0.022,1900,0,true);
|
|
else synthesPtr->sendTone(0.022,2100,0,true);
|
|
t>>=1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((t&0xFF)==0x23) l=16;
|
|
else l=8;
|
|
synthesPtr->sendTone(0.030,1200,0,true); // startbit
|
|
for (i=0;i<l;i++)
|
|
{
|
|
if((t&1)==1) synthesPtr->sendTone(0.030,1100,0,true);
|
|
else synthesPtr->sendTone(0.030,1300,0,true);
|
|
t>>=1;
|
|
}
|
|
synthesPtr->sendTone(0.030,1200,0,true); // stopbit
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool sstvTx::create(esstvMode m,DSPFLOAT clock)
|
|
{
|
|
if((oldMode==m) && (currentMode!=NULL))
|
|
{
|
|
currentMode->init(clock);
|
|
return true;
|
|
}
|
|
oldMode=m;
|
|
if(currentMode) delete currentMode;
|
|
currentMode=0;
|
|
switch (m)
|
|
{
|
|
case M1:
|
|
case M2:
|
|
currentMode=new modeGBR(m,TXSTRIPE,true,false);
|
|
break;
|
|
case S1:
|
|
case S2:
|
|
case SDX:
|
|
currentMode=new modeGBR2(m,TXSTRIPE,true,false);
|
|
break;
|
|
case R36:
|
|
currentMode=new modeRobot1(m,TXSTRIPE,true,false);
|
|
break;
|
|
case R24:
|
|
case R72:
|
|
case MR73:
|
|
case MR90:
|
|
case MR115:
|
|
case MR140:
|
|
case MR175:
|
|
case ML180:
|
|
case ML240:
|
|
case ML280:
|
|
case ML320:
|
|
currentMode=new modeRobot2(m,TXSTRIPE,true,false);
|
|
break;
|
|
case SC2_60:
|
|
case SC2_120:
|
|
case SC2_180:
|
|
case P3:
|
|
case P5:
|
|
case P7:
|
|
case MC110N:
|
|
case MC140N:
|
|
case MC180N:
|
|
currentMode=new modeRGB(m,TXSTRIPE,true,false);
|
|
break;
|
|
case FAX480:
|
|
case BW8:
|
|
case BW12:
|
|
currentMode=new modeBW(m,TXSTRIPE,true,false);
|
|
break;
|
|
case AVT24:
|
|
case AVT90:
|
|
case AVT94:
|
|
currentMode=new modeAVT(m,TXSTRIPE,true,false);
|
|
break;
|
|
case PD50:
|
|
case PD90:
|
|
case PD120:
|
|
case PD160:
|
|
case PD180:
|
|
case PD240:
|
|
case PD290:
|
|
case MP73:
|
|
case MP115:
|
|
case MP140:
|
|
case MP175:
|
|
currentMode=new modePD(m,TXSTRIPE,true,false);
|
|
break;
|
|
|
|
case MP73N:
|
|
case MP110N:
|
|
case MP140N:
|
|
currentMode=new modePD(m,TXSTRIPE,true,true);
|
|
break;
|
|
default:
|
|
m=NOTVALID;
|
|
break;
|
|
}
|
|
if (m!=NOTVALID)
|
|
{
|
|
initializeSSTVParametersIndex(m,true);
|
|
QString s=getSSTVModeNameLong(m);
|
|
addToLog("create: create TX mode",LOGTXFUNC);
|
|
currentMode->init(clock);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
double sstvTx::FSKIDTime()
|
|
{
|
|
double tim;
|
|
double charTime=0.022*6;
|
|
tim=(myCallsign.size()+3)*charTime;
|
|
tim+=0.422;
|
|
return tim;
|
|
}
|
|
|
|
double sstvTx::calcTxTime(int overheadTime)
|
|
{
|
|
double tim=0;
|
|
// tim= soundIOPtr->getPlaybackStartupTime();
|
|
tim+=SILENCEDELAY;
|
|
initializeSSTVParametersIndex(sstvModeIndexTx,true);
|
|
int t=txSSTVParam.VISCode;
|
|
tim+=1.41; //preamble;
|
|
if ((t&0xFF)==0x23) tim+=18.*0.03;
|
|
else tim+=10.*0.03;
|
|
tim+=txSSTVParam.imageTime;
|
|
|
|
// if(enableCW)
|
|
if(useCW)
|
|
{
|
|
tim+=0.5 ;//CW silence gap
|
|
initCW(cwText);
|
|
tim+=getCWDuration();
|
|
tim+=0.3; // trailer;
|
|
}
|
|
else
|
|
{
|
|
tim+=FSKIDTime();
|
|
}
|
|
tim+=overheadTime;
|
|
return tim;
|
|
}
|
|
|
|
bool sstvTx::sendImage(imageViewer *ivPtr)
|
|
{
|
|
modeBase::eModeBase mb;
|
|
if(useVOX) synthesPtr->sendTone(1.,1700.,0,false);
|
|
if(txSSTVParam.mode==FAX480)
|
|
{
|
|
for (int i=0;i<1220;i++)
|
|
{
|
|
synthesPtr->sendTone(0.00205,1500,0,true);
|
|
synthesPtr->sendTone(0.00205,2300,0,true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sendPreamble();
|
|
sendVIS();
|
|
}
|
|
addToLog("txFunc: sendImage",LOGTXFUNC);
|
|
mb=currentMode->transmitImage(ivPtr);
|
|
if(mb==modeBase::MBABORTED) return false;
|
|
else return true;
|
|
}
|
|
|
|
void sstvTx::applyTemplate(QString templateFilename,bool useTemplate,imageViewer *ivPtr)
|
|
{
|
|
create(sstvModeIndexTx,txClock);
|
|
|
|
ivPtr->setParam(templateFilename,useTemplate, txSSTVParam.numberOfPixels,txSSTVParam.numberOfDisplayLines);
|
|
}
|
|
|
|
void sstvTx::abort()
|
|
{
|
|
if(currentMode)
|
|
{
|
|
currentMode->abort();
|
|
}
|
|
}
|
|
|
|
|
|
bool sstvTx::aborted()
|
|
{
|
|
if(currentMode) return currentMode->aborted();
|
|
else return true;
|
|
|
|
}
|
|
|
|
void sstvTx::createTestPattern(imageViewer *ivPtr,etpSelect sel)
|
|
{
|
|
int i,j;
|
|
QRgb *pixelPtr;
|
|
int nb=txSSTVParam.numberOfPixels;
|
|
int nl=txSSTVParam.numberOfDisplayLines;
|
|
ivPtr->clear();
|
|
ivPtr->createImage(QSize(nb,nl),imageBackGroundColor,false);
|
|
switch (sel)
|
|
{
|
|
case TPRASTER:
|
|
for(i=0;i<nl;i++)
|
|
{
|
|
pixelPtr=ivPtr->getScanLineAddress(i);
|
|
if(i<2)
|
|
{
|
|
int val=0;;
|
|
for(j=0;j<nb;j++) pixelPtr[j]=qRgb(val,val,val);
|
|
}
|
|
else if(i>=(nl-2))
|
|
{
|
|
{
|
|
int val=0;;
|
|
for(j=0;j<nb;j++) pixelPtr[j]=qRgb(val,val,val);
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
for(j=0;j<nb/4;j++)
|
|
{
|
|
int val=(j%2)*255;
|
|
pixelPtr[j]=qRgb(val,val,val);
|
|
}
|
|
for(;j<nb/2;j++)
|
|
{
|
|
int val=((j/2)%2)*255;
|
|
pixelPtr[j]=qRgb(val,val,val);
|
|
}
|
|
for(;j<3*nb/4;j++)
|
|
{
|
|
int val=0;
|
|
pixelPtr[j]=qRgb(val,val,val);
|
|
}
|
|
for(;j<nb;j++)
|
|
{
|
|
int val=255;
|
|
pixelPtr[j]=qRgb(val,val,val);
|
|
}
|
|
|
|
}
|
|
}
|
|
break;
|
|
case TPWHITE:
|
|
for(i=0;i<nl;i++)
|
|
{
|
|
pixelPtr=ivPtr->getScanLineAddress(i);
|
|
for(j=0;j<nb;j++)
|
|
{
|
|
int val=255;
|
|
pixelPtr[j]=qRgb(val,val,val);
|
|
}
|
|
}
|
|
break;
|
|
case TPBLACK:
|
|
for(i=0;i<nl;i++)
|
|
{
|
|
pixelPtr=ivPtr->getScanLineAddress(i);
|
|
for(j=0;j<nb;j++)
|
|
{
|
|
int val=0;
|
|
pixelPtr[j]=qRgb(val,val,val);
|
|
}
|
|
}
|
|
break;
|
|
case TPGRAY:
|
|
for(i=0;i<nl;i++)
|
|
{
|
|
pixelPtr=ivPtr->getScanLineAddress(i);
|
|
for(j=0;j<nb;j++)
|
|
{
|
|
int val=128;
|
|
pixelPtr[j]=qRgb(val,val,val);
|
|
}
|
|
}
|
|
break;
|
|
|
|
}
|
|
ivPtr->setValidImage(true);
|
|
ivPtr->displayImage();
|
|
}
|