Working multidecoder using relative positioning in the frame buffer
This commit is contained in:
parent
862e827ddf
commit
bd357ed4c4
15
commons.h
15
commons.h
@ -2,7 +2,7 @@
|
||||
#define COMMONS_H
|
||||
|
||||
#define NSMAX 6827
|
||||
#define NTMAX 30
|
||||
#define NTMAX 60
|
||||
|
||||
#define RX_SAMPLE_RATE 12000
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#define JS8_DECODER_E2S 0 // decode every 2 seconds instead of at the half symbol stop
|
||||
|
||||
#define JS8_NUM_SYMBOLS 79
|
||||
#define JS8_ENABLE_JS8A 1
|
||||
#define JS8_ENABLE_JS8B 1
|
||||
#define JS8_ENABLE_JS8C 1
|
||||
#define JS8_ENABLE_JS8D 0
|
||||
@ -75,7 +76,6 @@ extern struct dec_data {
|
||||
float ss[184*NSMAX]; // symbol spectra
|
||||
float savg[NSMAX];
|
||||
float sred[5760];
|
||||
short int d1[NTMAX*RX_SAMPLE_RATE]; // sample frame buffer for decoding (copied from d2 for the frame period)
|
||||
short int d2[NTMAX*RX_SAMPLE_RATE]; // sample frame buffer for sample collection
|
||||
struct
|
||||
{
|
||||
@ -93,10 +93,17 @@ extern struct dec_data {
|
||||
int nfb; //High decode limit (Hz)
|
||||
int ntol; //+/- decoding range around fQSO (Hz)
|
||||
int kin; // number of frames written to d2
|
||||
int kpos; // starting position of decode
|
||||
int kout; // number of frames for decode
|
||||
int kposA; // starting position of decode for submode A
|
||||
int kposB; // starting position of decode for submode B
|
||||
int kposC; // starting position of decode for submode C
|
||||
int kposD; // starting position of decode for submode D
|
||||
int kszA; // number of frames for decode for submode A
|
||||
int kszB; // number of frames for decode for submode B
|
||||
int kszC; // number of frames for decode for submode C
|
||||
int kszD; // number of frames for decode for submode D
|
||||
int nzhsym; // half symbol stop index
|
||||
int nsubmode;
|
||||
int nsubmodes;
|
||||
bool nagain;
|
||||
int ndepth;
|
||||
bool lft8apon;
|
||||
|
@ -1,4 +1,4 @@
|
||||
integer, parameter :: NTMAX=30
|
||||
integer, parameter :: NTMAX=60
|
||||
integer, parameter :: NMAX=NTMAX*12000 !Total sample intervals (one minute)
|
||||
integer, parameter :: NDMAX=NTMAX*1500 !Sample intervals at 1500 Hz rate
|
||||
integer, parameter :: NSMAX=6827 !Max length of saved spectra
|
||||
|
@ -1,4 +1,4 @@
|
||||
subroutine multimode_decoder(ss,id1,params,nfsample)
|
||||
subroutine multimode_decoder(ss,id2,params,nfsample)
|
||||
|
||||
!$ use omp_lib
|
||||
use prog_args
|
||||
@ -28,8 +28,9 @@ subroutine multimode_decoder(ss,id1,params,nfsample)
|
||||
end type counting_js8d_decoder
|
||||
|
||||
real ss(184,NSMAX)
|
||||
logical baddata,newdat65,newdat9,single_decode,bVHF,bad0,newdat
|
||||
integer*2 id1(NTMAX*12000)
|
||||
logical baddata,newdat65,newdat9,single_decode,bVHF,bad0,newdat,trydecode
|
||||
integer*2 id0(NTMAX*12000)
|
||||
integer*2 id2(NTMAX*12000)
|
||||
type(params_block) :: params
|
||||
character(len=20) :: datetime
|
||||
character(len=12) :: mycall, hiscall
|
||||
@ -78,60 +79,92 @@ subroutine multimode_decoder(ss,id1,params,nfsample)
|
||||
endif
|
||||
endif
|
||||
|
||||
if(params%nmode.eq.8 .and. params%nsubmode.eq.4) then
|
||||
trydecode=.false.
|
||||
|
||||
if(params%nmode.eq.8 .and. (params%nsubmode.eq.4 .or. iand(params%nsubmodes, 8).eq.8)) then
|
||||
! We're in JS8 mode D
|
||||
call timer('decjs8d ',0)
|
||||
newdat=params%newdat
|
||||
call my_js8d%decode(js8d_decoded,id1,params%nQSOProgress,params%nfqso, &
|
||||
trydecode=.true.
|
||||
|
||||
! copy the relevant frames for decoding
|
||||
pos = params%kposD
|
||||
sz = params%kszD
|
||||
id0=0
|
||||
id0(1:sz+1)=id2(pos+1:pos+sz+1)
|
||||
|
||||
call my_js8d%decode(js8d_decoded,id0,params%nQSOProgress,params%nfqso, &
|
||||
params%nftx,newdat,params%nutc,params%nfa,params%nfb, &
|
||||
params%nexp_decode,params%ndepth,logical(params%nagain), &
|
||||
logical(params%lft8apon),logical(params%lapcqonly),params%napwid, &
|
||||
mycall,mygrid,hiscall,hisgrid)
|
||||
call timer('decjs8d ',1)
|
||||
go to 800
|
||||
endif
|
||||
|
||||
if(params%nmode.eq.8 .and. params%nsubmode.eq.2) then
|
||||
if(params%nmode.eq.8 .and. (params%nsubmode.eq.2 .or. iand(params%nsubmodes, 4).eq.4)) then
|
||||
! We're in JS8 mode C
|
||||
call timer('decjs8c ',0)
|
||||
newdat=params%newdat
|
||||
call my_js8c%decode(js8c_decoded,id1,params%nQSOProgress,params%nfqso, &
|
||||
trydecode=.true.
|
||||
|
||||
! copy the relevant frames for decoding
|
||||
pos = params%kposC
|
||||
sz = params%kszC
|
||||
id0=0
|
||||
id0(1:sz+1)=id2(pos+1:pos+sz+1)
|
||||
|
||||
call my_js8c%decode(js8c_decoded,id0,params%nQSOProgress,params%nfqso, &
|
||||
params%nftx,newdat,params%nutc,params%nfa,params%nfb, &
|
||||
params%nexp_decode,params%ndepth,logical(params%nagain), &
|
||||
logical(params%lft8apon),logical(params%lapcqonly),params%napwid, &
|
||||
mycall,mygrid,hiscall,hisgrid)
|
||||
call timer('decjs8c ',1)
|
||||
go to 800
|
||||
endif
|
||||
|
||||
if(params%nmode.eq.8 .and. params%nsubmode.eq.1) then
|
||||
if(params%nmode.eq.8 .and. (params%nsubmode.eq.1 .or. iand(params%nsubmodes, 2).eq.2)) then
|
||||
! We're in JS8 mode B
|
||||
call timer('decjs8b ',0)
|
||||
newdat=params%newdat
|
||||
call my_js8b%decode(js8b_decoded,id1,params%nQSOProgress,params%nfqso, &
|
||||
trydecode=.true.
|
||||
|
||||
! copy the relevant frames for decoding
|
||||
pos = params%kposB
|
||||
sz = params%kszB
|
||||
id0=0
|
||||
id0(1:sz+1)=id2(pos+1:pos+sz+1)
|
||||
|
||||
call my_js8b%decode(js8b_decoded,id0,params%nQSOProgress,params%nfqso, &
|
||||
params%nftx,newdat,params%nutc,params%nfa,params%nfb, &
|
||||
params%nexp_decode,params%ndepth,logical(params%nagain), &
|
||||
logical(params%lft8apon),logical(params%lapcqonly),params%napwid, &
|
||||
mycall,mygrid,hiscall,hisgrid)
|
||||
call timer('decjs8b ',1)
|
||||
go to 800
|
||||
endif
|
||||
|
||||
if(params%nmode.eq.8 .and. params%nsubmode.eq.0) then
|
||||
if(params%nmode.eq.8 .and. (params%nsubmode.eq.0 .or. iand(params%nsubmodes, 1).eq.1)) then
|
||||
! We're in JS8 mode A
|
||||
call timer('decjs8a ',0)
|
||||
newdat=params%newdat
|
||||
call my_js8a%decode(js8a_decoded,id1,params%nQSOProgress,params%nfqso, &
|
||||
trydecode=.true.
|
||||
|
||||
! copy the relevant frames for decoding
|
||||
pos = params%kposA
|
||||
sz = params%kszA
|
||||
id0=0
|
||||
id0(1:sz+1)=id2(pos+1:pos+sz+1)
|
||||
|
||||
call my_js8a%decode(js8a_decoded,id0,params%nQSOProgress,params%nfqso, &
|
||||
params%nftx,newdat,params%nutc,params%nfa,params%nfb, &
|
||||
params%nexp_decode,params%ndepth,logical(params%nagain), &
|
||||
logical(params%lft8apon),logical(params%lapcqonly),params%napwid, &
|
||||
mycall,mygrid,hiscall,hisgrid)
|
||||
call timer('decjs8a ',1)
|
||||
go to 800
|
||||
endif
|
||||
|
||||
rms=sqrt(dot_product(float(id1(300000:310000)), &
|
||||
float(id1(300000:310000)))/10000.0)
|
||||
if(trydecode) go to 800
|
||||
|
||||
rms=sqrt(dot_product(float(id2(300000:310000)), &
|
||||
float(id2(300000:310000)))/10000.0)
|
||||
if(rms.lt.2.0) go to 800
|
||||
|
||||
! Zap data at start that might come from T/R switching transient?
|
||||
@ -142,7 +175,7 @@ subroutine multimode_decoder(ss,id1,params,nfsample)
|
||||
sq=0.
|
||||
do n=1,nadd
|
||||
k=k+1
|
||||
sq=sq + float(id1(k))**2
|
||||
sq=sq + float(id2(k))**2
|
||||
enddo
|
||||
rms=sqrt(sq/nadd)
|
||||
if(rms.gt.10000.0) then
|
||||
@ -153,11 +186,11 @@ subroutine multimode_decoder(ss,id1,params,nfsample)
|
||||
enddo
|
||||
if(bad0) then
|
||||
nz=min(NTMAX*12000,kbad+100)
|
||||
! id1(1:nz)=0 ! temporarily disabled as it can breaak the JT9 decoder, maybe others
|
||||
! id2(1:nz)=0 ! temporarily disabled as it can breaak the JT9 decoder, maybe others
|
||||
endif
|
||||
|
||||
npts65=52*12000
|
||||
if(baddata(id1,npts65)) then
|
||||
if(baddata(id2,npts65)) then
|
||||
nsynced=0
|
||||
ndecoded=0
|
||||
go to 800
|
||||
|
@ -297,6 +297,10 @@ program jt9
|
||||
datetime="2013-Apr-16 15:13" !### Temp
|
||||
shared_data%params%datetime=transfer(datetime,shared_data%params%datetime)
|
||||
if(mode.eq.9 .and. fsplit.ne.2700) shared_data%params%nfa=fsplit
|
||||
shared_data%params%kszA=NMAX-1
|
||||
shared_data%params%kszB=NMAX-1
|
||||
shared_data%params%kszC=NMAX-1
|
||||
shared_data%params%kszD=NMAX-1
|
||||
call multimode_decoder(shared_data%ss,shared_data%id2,shared_data%params,nfsample)
|
||||
enddo
|
||||
|
||||
|
@ -61,7 +61,7 @@ subroutine jt9a()
|
||||
local_params=shared_data%params !save a copy because wsjtx carries on accessing
|
||||
call flush(6)
|
||||
call timer('decoder ',0)
|
||||
call multimode_decoder(shared_data%ss,shared_data%id1,local_params,12000)
|
||||
call multimode_decoder(shared_data%ss,shared_data%id2,local_params,12000)
|
||||
call timer('decoder ',1)
|
||||
|
||||
100 inquire(file=trim(temp_dir)//'/.lock',exist=fileExists)
|
||||
|
@ -19,10 +19,17 @@
|
||||
integer(c_int) :: nfb
|
||||
integer(c_int) :: ntol
|
||||
integer(c_int) :: kin
|
||||
integer(c_int) :: kpos
|
||||
integer(c_int) :: kout
|
||||
integer(c_int) :: kposA
|
||||
integer(c_int) :: kposB
|
||||
integer(c_int) :: kposC
|
||||
integer(c_int) :: kposD
|
||||
integer(c_int) :: kszA
|
||||
integer(c_int) :: kszB
|
||||
integer(c_int) :: kszC
|
||||
integer(c_int) :: kszD
|
||||
integer(c_int) :: nzhsym
|
||||
integer(c_int) :: nsubmode
|
||||
integer(c_int) :: nsubmodes
|
||||
logical(c_bool) :: nagain
|
||||
integer(c_int) :: ndepth
|
||||
logical(c_bool) :: lft8apon
|
||||
@ -54,7 +61,6 @@
|
||||
real(c_float) :: ss(184,NSMAX)
|
||||
real(c_float) :: savg(NSMAX)
|
||||
real(c_float) :: sred(5760)
|
||||
integer(c_short) :: id1(NMAX)
|
||||
integer(c_short) :: id2(NMAX)
|
||||
type(params_block) :: params
|
||||
end type dec_data
|
||||
|
@ -1015,6 +1015,9 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
if(pProcessed) *pProcessed = true;
|
||||
});
|
||||
ui->modeButton->installEventFilter(mbmp);
|
||||
if(!JS8_ENABLE_JS8A){
|
||||
ui->actionModeJS8Normal->setVisible(false);
|
||||
}
|
||||
if(!JS8_ENABLE_JS8B){
|
||||
ui->actionModeJS8Fast->setVisible(false);
|
||||
}
|
||||
@ -2480,7 +2483,7 @@ int MainWindow::computeStop(int submode, int period){
|
||||
case Varicode::JS8CallNormal: symbolSamples = JS8A_SYMBOL_SAMPLES; /* threshold = 1.00 */ ; break;
|
||||
case Varicode::JS8CallFast: symbolSamples = JS8B_SYMBOL_SAMPLES; /* threshold = 1.08 */ ; break;
|
||||
case Varicode::JS8CallTurbo: symbolSamples = JS8C_SYMBOL_SAMPLES; /* threshold = 0.50 */ ; break;
|
||||
case Varicode::JS8CallUltra: symbolSamples = JS8D_SYMBOL_SAMPLES; /* threshold = 0.00 */ ; break;
|
||||
case Varicode::JS8CallUltra: symbolSamples = JS8D_SYMBOL_SAMPLES; threshold = 0.00; break;
|
||||
}
|
||||
stop = qFloor(float(symbolSamples*JS8_NUM_SYMBOLS + threshold*RX_SAMPLE_RATE)/(float)m_nsps*2.0);
|
||||
#endif
|
||||
@ -2580,6 +2583,14 @@ void MainWindow::dataSink(qint64 frames)
|
||||
dec_data.params.nagain=0;
|
||||
dec_data.params.nzhsym=m_ihsym;
|
||||
|
||||
// only decode once per second
|
||||
static int lastn = -1;
|
||||
int n = m_detector->secondInPeriod();
|
||||
if(n == lastn){
|
||||
return;
|
||||
}
|
||||
lastn = n;
|
||||
|
||||
decode();
|
||||
}
|
||||
|
||||
@ -3845,7 +3856,7 @@ void MainWindow::decode(){
|
||||
qint32 submode = m_nSubMode;
|
||||
qint32 period = m_TRperiod;
|
||||
|
||||
bool ready = decodeReady(submode, period);
|
||||
bool ready = decodeReady(submode, period, &submode, &period);
|
||||
if(!ready){
|
||||
return;
|
||||
}
|
||||
@ -3854,28 +3865,80 @@ void MainWindow::decode(){
|
||||
decodePrepareSaveAudio(submode, period);
|
||||
}
|
||||
|
||||
bool MainWindow::decodeReady(int submode, int period){
|
||||
bool MainWindow::decodeReady(int submode, int period, int *pSubmode, int *pPeriod){
|
||||
if(period == 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
#if JS8_RING_BUFFER
|
||||
qint32 cycle = computeCurrentCycle(period);
|
||||
qint32 cycleSampleStart = computeCycleStartForDecode(cycle, period);
|
||||
qint32 framesNeeded = computeFramesNeededForDecode(submode, period);
|
||||
int k = dec_data.params.kin;
|
||||
|
||||
static int lastCycle = -1;
|
||||
if(cycle < lastCycle){
|
||||
lastCycle = -1;
|
||||
qint32 cycleSampleStartA = computeCycleStartForDecode(computeCurrentCycle(JS8A_TX_SECONDS), JS8A_TX_SECONDS);
|
||||
qint32 framesNeededA = computeFramesNeededForDecode(Varicode::JS8CallNormal, JS8A_TX_SECONDS);
|
||||
bool couldDecodeA = k >= cycleSampleStartA + framesNeededA;
|
||||
|
||||
qint32 cycleSampleStartB = computeCycleStartForDecode(computeCurrentCycle(JS8B_TX_SECONDS), JS8B_TX_SECONDS);
|
||||
qint32 framesNeededB = computeFramesNeededForDecode(Varicode::JS8CallFast, JS8B_TX_SECONDS);
|
||||
bool couldDecodeB = k >= cycleSampleStartB + framesNeededB;
|
||||
|
||||
qint32 cycleSampleStartC = computeCycleStartForDecode(computeCurrentCycle(JS8C_TX_SECONDS), JS8C_TX_SECONDS);
|
||||
qint32 framesNeededC = computeFramesNeededForDecode(Varicode::JS8CallTurbo, JS8C_TX_SECONDS);
|
||||
bool couldDecodeC = k >= cycleSampleStartC + framesNeededC;
|
||||
|
||||
#if JS8_ENABLE_JS8D
|
||||
qint32 cycleSampleStartD = computeCycleStartForDecode(computeCurrentCycle(JS8D_TX_SECONDS), JS8D_TX_SECONDS);
|
||||
qint32 framesNeededD = computeFramesNeededForDecode(Varicode::JS8CallUltra, JS8D_TX_SECONDS);
|
||||
bool couldDecodeD = k >= cycleSampleStartD + framesNeededD;
|
||||
#else
|
||||
qint32 cycleSampleStartD = 0;
|
||||
qint32 framesNeededD = 0;
|
||||
bool couldDecodeD = false;
|
||||
#endif
|
||||
|
||||
// set the params for starting positions and sizes for decode
|
||||
dec_data.params.kposA = cycleSampleStartA;
|
||||
dec_data.params.kposB = cycleSampleStartB;
|
||||
dec_data.params.kposC = cycleSampleStartC;
|
||||
dec_data.params.kposD = cycleSampleStartD;
|
||||
dec_data.params.kszA = qMax(framesNeededA, k-cycleSampleStartA);
|
||||
dec_data.params.kszB = qMax(framesNeededB, k-cycleSampleStartB);
|
||||
dec_data.params.kszC = qMax(framesNeededC, k-cycleSampleStartC);
|
||||
dec_data.params.kszD = qMax(framesNeededD, k-cycleSampleStartD);
|
||||
dec_data.params.nsubmodes = 0;
|
||||
|
||||
int decodes = int(couldDecodeA) + int(couldDecodeB) + int(couldDecodeC) + int(couldDecodeD);
|
||||
|
||||
if(couldDecodeD){
|
||||
qDebug() << "could decode D from" << cycleSampleStartD << "to" << cycleSampleStartD + framesNeededD;
|
||||
submode = Varicode::JS8CallUltra;
|
||||
period = JS8D_TX_SECONDS;
|
||||
dec_data.params.nsubmodes |= (Varicode::JS8CallUltra << 1);
|
||||
}
|
||||
if(couldDecodeC){
|
||||
qDebug() << "could decode C from" << cycleSampleStartC << "to" << cycleSampleStartC + framesNeededC;
|
||||
submode = Varicode::JS8CallTurbo;
|
||||
period = JS8C_TX_SECONDS;
|
||||
dec_data.params.nsubmodes |= (Varicode::JS8CallTurbo << 1);
|
||||
}
|
||||
if(couldDecodeB){
|
||||
qDebug() << "could decode B from" << cycleSampleStartB << "to" << cycleSampleStartB + framesNeededB;
|
||||
submode = Varicode::JS8CallFast;
|
||||
period = JS8B_TX_SECONDS;
|
||||
dec_data.params.nsubmodes |= (Varicode::JS8CallFast << 1);
|
||||
}
|
||||
if(couldDecodeA){
|
||||
qDebug() << "could decode A from" << cycleSampleStartA << "to" << cycleSampleStartA + framesNeededA;
|
||||
submode = Varicode::JS8CallNormal;
|
||||
period = JS8A_TX_SECONDS;
|
||||
dec_data.params.nsubmodes |= (Varicode::JS8CallNormal + 1);
|
||||
}
|
||||
|
||||
int k = dec_data.params.kin;
|
||||
if(!m_diskData && (cycle == lastCycle || k < cycleSampleStart + framesNeeded)){
|
||||
if(pSubmode) *pSubmode=submode;
|
||||
if(pPeriod) *pPeriod=period;
|
||||
|
||||
if(!m_diskData && decodes == 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
qDebug() << "cycle" << cycle << "start" << cycleSampleStart << "k" << k << "needed" << framesNeeded;
|
||||
lastCycle = cycle;
|
||||
#endif
|
||||
|
||||
#if JS8_DECODER_E2S
|
||||
@ -4011,6 +4074,7 @@ bool MainWindow::decodeReady(int submode, int period){
|
||||
strncpy(dec_data.params.hiscall,(hisCall + " ").toLatin1 ().constData (), 12);
|
||||
strncpy(dec_data.params.hisgrid,(hisGrid + " ").toLatin1 ().constData (), 6);
|
||||
|
||||
#if JS8_TWO_BUFFERS
|
||||
#if JS8_RING_BUFFER
|
||||
// clear out d1
|
||||
memset(dec_data.d1, 0, sizeof(dec_data.d1));
|
||||
@ -4047,6 +4111,7 @@ bool MainWindow::decodeReady(int submode, int period){
|
||||
qDebug() << "try decode from" << 0 << "to" << dec_data.params.kin;
|
||||
memset(dec_data.d1, 0, sizeof(dec_data.d1));
|
||||
memcpy(dec_data.d1, dec_data.d2, sizeof(dec_data.d2));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return true;
|
||||
@ -7066,7 +7131,8 @@ void MainWindow::on_actionJS8_triggered()
|
||||
m_wideGraph->setPeriod(m_TRperiod, m_nsps);
|
||||
m_modulator->setTRPeriod(m_TRperiod); // TODO - not thread safe
|
||||
#if JS8_RING_BUFFER
|
||||
m_detector->setTRPeriod(NTMAX); // TODO - not thread safe
|
||||
Q_ASSERT(NTMAX == 60);
|
||||
m_detector->setTRPeriod(NTMAX / 2); // TODO - not thread safe
|
||||
#else
|
||||
m_detector->setTRPeriod(m_TRperiod); // TODO - not thread safe
|
||||
#endif
|
||||
|
@ -230,7 +230,7 @@ private slots:
|
||||
void on_actionCopyright_Notice_triggered();
|
||||
void on_DecodeButton_clicked (bool);
|
||||
void decode();
|
||||
bool decodeReady(int submode, int period);
|
||||
bool decodeReady(int submode, int period, int *pSubmode, int *pPeriod);
|
||||
void decodeStart(int submode, int period);
|
||||
void decodePrepareSaveAudio(int submode, int period);
|
||||
void decodeBusy(bool b);
|
||||
|
Loading…
Reference in New Issue
Block a user