📄 tcm.cpp
字号:
//---------------------------------------------------------------------------
#pragma hdrstop
#include "TCM.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
TCM::TCM()
{
//y3 y2 y1 y0
qam16map[0][0][0][0]=12;
qam16map[1][0][0][0]=6;
qam16map[0][1][0][0]=4;
qam16map[1][1][0][0]=14;
qam16map[0][0][1][0]=9;
qam16map[1][0][1][0]=3;
qam16map[0][1][1][0]=1;
qam16map[1][1][1][0]=11;
qam16map[0][0][0][1]=13;
qam16map[1][0][0][1]=7;
qam16map[0][1][0][1]=5;
qam16map[1][1][0][1]=15;
qam16map[0][0][1][1]=8;
qam16map[1][0][1][1]=2;
qam16map[0][1][1][1]=0;
qam16map[1][1][1][1]=10;
//y5 y4 y3 y2 y1 y0
qam64map[0][0][0][0][0][0]=10;
qam64map[0][0][1][0][0][0]=14;
qam64map[0][1][0][0][0][0]=24;
qam64map[0][1][1][0][0][0]=28;
qam64map[1][0][0][0][0][0]=42;
qam64map[1][0][1][0][0][0]=46;
qam64map[1][1][0][0][0][0]=56;
qam64map[1][1][1][0][0][0]=60;
qam64map[0][0][0][1][0][0]=8;
qam64map[0][0][1][1][0][0]=12;
qam64map[0][1][0][1][0][0]=26;
qam64map[0][1][1][1][0][0]=30;
qam64map[1][0][0][1][0][0]=40;
qam64map[1][0][1][1][0][0]=44;
qam64map[1][1][0][1][0][0]=58;
qam64map[1][1][1][1][0][0]=62;
qam64map[0][0][0][0][1][0]=3;
qam64map[0][0][1][0][1][0]=7;
qam64map[0][1][0][0][1][0]=17;
qam64map[0][1][1][0][1][0]=21;
qam64map[1][0][0][0][1][0]=35;
qam64map[1][0][1][0][1][0]=39;
qam64map[1][1][0][0][1][0]=49;
qam64map[1][1][1][0][1][0]=53;
qam64map[0][0][0][1][1][0]=1;
qam64map[0][0][1][1][1][0]=5;
qam64map[0][1][0][1][1][0]=19;
qam64map[0][1][1][1][1][0]=23;
qam64map[1][0][0][1][1][0]=33;
qam64map[1][0][1][1][1][0]=37;
qam64map[1][1][0][1][1][0]=51;
qam64map[1][1][1][1][1][0]=55;
qam64map[0][0][0][0][0][1]=11;
qam64map[0][0][1][0][0][1]=15;
qam64map[0][1][0][0][0][1]=25;
qam64map[0][1][1][0][0][1]=29;
qam64map[1][0][0][0][0][1]=43;
qam64map[1][0][1][0][0][1]=47;
qam64map[1][1][0][0][0][1]=57;
qam64map[1][1][1][0][0][1]=61;
qam64map[0][0][0][1][0][1]=9;
qam64map[0][0][1][1][0][1]=13;
qam64map[0][1][0][1][0][1]=27;
qam64map[0][1][1][1][0][1]=31;
qam64map[1][0][0][1][0][1]=41;
qam64map[1][0][1][1][0][1]=45;
qam64map[1][1][0][1][0][1]=59;
qam64map[1][1][1][1][0][1]=63;
qam64map[0][0][0][0][1][1]=2;
qam64map[0][0][1][0][1][1]=6;
qam64map[0][1][0][0][1][1]=16;
qam64map[0][1][1][0][1][1]=20;
qam64map[1][0][0][0][1][1]=34;
qam64map[1][0][1][0][1][1]=38;
qam64map[1][1][0][0][1][1]=48;
qam64map[1][1][1][0][1][1]=52;
qam64map[0][0][0][1][1][1]=0;
qam64map[0][0][1][1][1][1]=4;
qam64map[0][1][0][1][1][1]=18;
qam64map[0][1][1][1][1][1]=22;
qam64map[1][0][0][1][1][1]=32;
qam64map[1][0][1][1][1][1]=36;
qam64map[1][1][0][1][1][1]=50;
qam64map[1][1][1][1][1][1]=54;
//decoder
DemodSettingsHaveChanged(CH_ANYTHING);
ModSettingsHaveChanged(CH_ANYTHING);
gSettings.ModMajorAddCallBackNotificationFuction(ModSettingsHaveChanged);
gSettings.DemodMajorAddCallBackNotificationFuction(DemodSettingsHaveChanged);
}
int __fastcall TCM::Encode(int Value)
{
int result;
int tr1,tr2,tr3;
switch (gSettings.ModMajor.ConstalationSize)
{
case 64:
result=qam64map[((Value&16)>>4)][((Value&8)>>3)][((Value&4)>>2)][((Value&2)>>1)][(Value&1)][r1];
tr3=r1;
tr2=((Value&1)+r3)%2;
tr1=(((Value&2)>>1)+r2)%2;
r3=tr3;
r2=tr2;
r1=tr1;
break;
case 16:
result=qam16map[((Value&4)>>2)][((Value&2)>>1)][(Value&1)][r1];
tr3=r1;
tr2=((Value&1)+r3)%2;
tr1=(((Value&2)>>1)+r2)%2;
r3=tr3;
r2=tr2;
r1=tr1;
break;
}
return result;
}
int __fastcall TCM::Decode(PtComplex r)
{
int i,k;
PtComplex tptdif;
double dis;
double tsdis;
double t;
//autorotate
if(autorotate)
{
if(autorotatescoreptr==-1)
{
autorotatescore[0]=0;autorotatescore[1]=0;
autorotatescore[2]=0;autorotatescore[3]=0;
autorotatescoreptr=0;Rotation=0;
autorotateybufptr=0;
ResetMetrics();
}
if(autorotatescoreptr==0)
{
autorotateybuf[autorotateybufptr].re=r.re;
autorotateybuf[autorotateybufptr].im=r.im;
}
else
{
r.re=autorotateybuf[autorotateybufptr].re;
r.im=autorotateybuf[autorotateybufptr].im;
}
autorotateybufptr++;
if(autorotateybufptr>=autorotateybufsize)
{
autorotateybufptr=0;
autorotatescoreptr++;
Rotation=autorotatescoreptr;
ResetMetrics();
}
if(autorotatescoreptr>=4)
{
autorotate=false;
double min=autorotatescore[0];
autorotatescoreptr=0;
for(i=1;i<4;i++)
{
if(autorotatescore[i]<min)
{
min=autorotatescore[i];
autorotatescoreptr=i;
}
}
Rotation=autorotatescoreptr;
autorotatescoreptr=-1;
}
}
//rotate
Rotate(&r);
//update branch metrics
for(i=0;i<8;i++)Bm[i]=10000000000; //ie infinity
for(i=0;i<(gSettings.DemodMajor.CMapQAMAmpsSize);i++)
{
tptdif.re=r.re-gSettings.DemodMajor.CMapQAMAmps[i];
dx[i]=tptdif.re*tptdif.re;
tptdif.im=r.im-gSettings.DemodMajor.CMapQAMAmps[i];
dy[i]=tptdif.im*tptdif.im;
}
double tdis=10000000;
for(i=0;i<(gSettings.DemodMajor.ConstalationSize);i++)
{
dis=dx[Split[i].re]+dy[Split[i].im];
if(dis<tdis)
{
tentitivepoint.re=gSettings.DemodMajor.CMapQAMAmps[Split[i].re];
tentitivepoint.im=gSettings.DemodMajor.CMapQAMAmps[Split[i].im];
tdis=dis;
}
if(dis<Bm[S[i]])
{
Bm[S[i]]=dis;
Hd[S[i]]=L[i];
}
}
//end update branch metrics
//path metric update
for(k=0;k<8;k++)
{
tPm[k]=1000000000;
for(i=0;i<4;i++)
{
t=Bm[BranchWeCameBy[k][i]]+Pm[FromState[k][i]];
if(t<tPm[k])
{
tPm[k]=t;
TrackState[k][ptr]=FromState[k][i];
TrackHd[k][ptr]=Hd[BranchWeCameBy[k][i]];
}
}
}
ptr++;ptr%=10;
winner=0;
for(k=0;k<8;k++)
{
Pm[k]=tPm[k];
if(Pm[k]<Pm[winner])
{
winner=k;
}
}
t=Pm[winner];
for(k=0;k<8;k++)
{
Pm[k]-=t;
}
//end path metric update
//trackback routine
int him=winner;
int sptr=ptr;ptr--;if(ptr<0)ptr+=10;
for(i=1;i<9;i++)
{
him=TrackState[him][ptr];
ptr--;if(ptr<0)ptr+=10;
}
int branch=R[TrackState[him][ptr]][him];
int data=(((branch&6)>>1)&3)+(((TrackHd[him][ptr])<<2)&28); //works for 16 and 64
ptr=sptr;
//end trackback routine
//autorotate
if((autorotate)&&(autorotatescoreptr>=0))
{
autorotatescore[autorotatescoreptr]+=t;
}
//10 april test
tcmmsesum+=t;
tcmmseptr++;
if(tcmmseptr>=10000)
{
tcmmseptr=0;
tcmmse=tcmmsesum;
tcmmsesum=0;
}
//10 end
return data;
}
void __fastcall TCM::ResetMetrics()
{
for(int i=0;i<8;i++)
{
Bm[i]=0;
Pm[i]=0;
Hd[i]=0;
for(int k=0;k<10;k++)
{
TrackState[i][k]=0;
TrackHd[i][k]=0;
}
}
winner=0;ptr=0;
r1=0;r2=0;r3=0;
}
__fastcall TCM::~TCM()
{
gSettings.ModMajorRemoveCallBackNotificationFunction(ModSettingsHaveChanged);
gSettings.DemodMajorRemoveCallBackNotificationFunction(DemodSettingsHaveChanged);
if(autorotateybuf)delete [] autorotateybuf;
}
void __fastcall TCM::Rotate(PtComplex *r)
{
PtComplex tmp;
//introduce errors to test tcm
/*int i=rand()%10;
if(i==0)
{
int j=rand()%50-25;
(*r).re+=((float)j)/100;
j=rand()%50-25;
(*r).im+=((float)j)/100;
}*/
switch (Rotation)
{
case 0:
tmp.re=(*r).re;
tmp.im=(*r).im;
break;
case 1:
tmp.re=-(*r).im;
tmp.im=(*r).re;
break;
case 2:
tmp.re=-(*r).re;
tmp.im=-(*r).im;
break;
case 3:
tmp.re=(*r).im;
tmp.im=-(*r).re;
break;
}
(*r).re=tmp.re;
(*r).im=tmp.im;
}
void __fastcall TCM::SetMSELow()
{
tcmmseptr=0;
tcmmse=0;
tcmmsesum=0;
}
void __fastcall TCM::DemodSettingsHaveChanged(NotificationEventType WhatHasChanged)
{
//load R relation between states;
int i,j,k,tr1,tr2,tr3;
for(i=0;i<8;i++){for(j=0;j<8;j++){R[i][j]=-1;}}
for(i=0;i<8;i++)
{
for(j=0;j<4;j++)
{
r1=(i&1);
r2=((i&2)>>1);
r3=((i&4)>>2);
tr1=(((j&2)>>1)+r2)%2;
tr2=((j&1)+r3)%2;
tr3=r1;
R[i][((tr3<<2)&4)|((tr2<<1)&2)|(tr1&1)]=((j<<1)&6)|(r1);
}
}
//load S[i] the branch that symbol i belongins to
switch (gSettings.DemodMajor.ConstalationSize)
{
case 64:
for(i=0;i<64;i++)
{
S[qam64map[(i&32)>>5][(i&16)>>4][(i&8)>>3][(i&4)>>2][(i&2)>>1][i&1]]=i&7;
}
break;
case 16:
for(i=0;i<16;i++)
{
S[qam16map[(i&8)>>3][(i&4)>>2][(i&2)>>1][i&1]]=i&7;
}
break;
}
//load L[i] the unencoded data that symbol i refers to
switch (gSettings.DemodMajor.ConstalationSize)
{
case 64:
for(i=0;i<64;i++)
{
L[qam64map[(i&32)>>5][(i&16)>>4][(i&8)>>3][(i&4)>>2][(i&2)>>1][i&1]]=(i&56)>>3;
}
break;
case 16:
for(i=0;i<16;i++)
{
L[qam16map[(i&8)>>3][(i&4)>>2][(i&2)>>1][i&1]]=(i&8)>>3;
}
break;
}
//load FromState & BranchWeCameBy
for(k=0;k<8;k++)
{
i=0;
for(j=0;j<8;j++)
{
if(R[j][k]>=0)
{
FromState[k][i]=j;
BranchWeCameBy[k][i]=R[j][k];
i++;
if(i>=4) break;
}
}
}
//load splitter
switch (gSettings.DemodMajor.ConstalationSize)
{
case 64:
for(i=0;i<64;i++)
{
Split[i].re=(i&7);
Split[i].im=((i&56)>>3);
}
break;
case 16:
for(i=0;i<16;i++)
{
Split[i].re=(i&3);
Split[i].im=((i&12)>>2);
}
break;
}
for(i=0;i<8;i++)
{
Bm[i]=0;
Pm[i]=0;
Hd[i]=0;
for(int k=0;k<10;k++)
{
TrackState[i][k]=0;
TrackHd[i][k]=0;
}
}
winner=0;ptr=0;
r1=0;r2=0;r3=0;
autorotate=false;
autorotateybufptr=0;
autorotateybufsize=100;
autorotateybuf=0;
autorotateybuf=new PtComplex[autorotateybufsize];
autorotatescoreptr=-1;
Rotation=0;
SetMSELow();
}
void __fastcall TCM::ModSettingsHaveChanged(NotificationEventType WhatHasChanged)
{
r1=0;r2=0;r3=0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -