⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcm.cpp

📁 QAM module to use in Java with an easy interface and powerful performance
💻 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 + -