root/SigProc/trunk/SigProc/fec_conv.cpp @ 4766

Revision 4766, 13.5 KB (checked in by jgaeddert, 6 years ago)

moving math.h includes to SigProc?.h, adding section for trigonometric functions, implementing arctan and autotests

Line 
1/****************************************************************************
2Copyright 2005,2006 Virginia Polytechnic Institute and State University
3
4This file is part of the OSSIE Signal Processing Library.
5
6OSSIE Signal Processing Library is free software; you can redistribute it
7and/or modify it under the terms of the GNU General Public License as
8published by the Free Software Foundation; either version 2 of the License,
9or (at your option) any later version.
10
11OSSIE Signal Processing Library is distributed in the hope that it will be
12useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License along
17with OSSIE Signal Processing Library; if not, write to the Free Software
18Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20
21****************************************************************************/
22
23#include "SigProc.h"
24
25namespace SigProc {
26
27//----------------------------Trellis Entry-------------------------------------
28TrellisEntry::TrellisEntry()
29{
30    previousState=0;
31    symbolNo=0;
32    distance=-1;
33}
34
35TrellisEntry::~TrellisEntry()
36{
37
38
39}
40
41//----------------------------trellisTable--------------------------------------
42
43trellisTable::trellisTable(
44    unsigned int * generatorPolynomials,
45    unsigned short int k_in,
46    unsigned short int n_in,
47    unsigned short K_in)
48{
49    //Build trellis table
50    trellisTable::k=k_in;
51    trellisTable::n=n_in;
52    trellisTable::K=K_in;
53
54    //std::cout<<"Constructor, generatorPolynomials:";
55   // for (int i=0;i<n;i++){
56
57     //   std::cout<<generatorPolynomials[i]<<" ";
58    //}
59    //std::cout<<std::endl;
60
61    //std::cout<<"Input bits:"<<k<<" Contraint Length:"<<K<<std::endl;
62    trellisTable::nextState=NULL;
63    trellisTable::output=NULL;
64    trellisTable::GenerateTrellisTable(generatorPolynomials);
65}
66
67trellisTable::~trellisTable()
68{
69    //Deallocate memory
70    if (trellisTable::nextState!=NULL){
71        for (unsigned int i = 0; i < trellisTable::numberOfTrellisStates; i++){
72            delete []trellisTable::nextState[i];
73        }
74        delete []trellisTable::nextState;
75    }
76
77    if (trellisTable::output!=NULL){
78        for (unsigned int i = 0; i < trellisTable::numberOfTrellisStates; i++){
79            delete []trellisTable::output[i];
80        }
81        delete []trellisTable::output;
82    }
83}
84
85
86void trellisTable::GenerateTrellisTable(unsigned int * generatorPolynomials)
87{
88    numberOfTrellisStates=int(pow(2,(k*(K-1))));
89    numberOfInputStates=int(pow(2,k));
90
91    //std::cout<<"NumberOfTrellisStates="<<numberOfTrellisStates<<std::endl;
92    //std::cout<<"numberOfInputStates="<<numberOfInputStates<<std::endl;
93
94    nextState = new unsigned int *[numberOfTrellisStates];
95
96    for (unsigned int i = 0; i < numberOfTrellisStates; i++){
97        nextState[i] = new unsigned int[numberOfInputStates];
98    }
99
100
101    output = new unsigned int *[numberOfTrellisStates];
102    for (unsigned int i = 0; i < numberOfTrellisStates; i++){
103        output[i] = new unsigned int[numberOfInputStates];
104    }
105
106    unsigned int ENCregister=0, tempOut=0;
107
108    for (unsigned int tstate=0;tstate<numberOfTrellisStates;tstate++){
109        //std::cout<<tstate<<":";
110        for (unsigned short int inputIdx=0;inputIdx<numberOfInputStates;inputIdx++){
111
112            ENCregister=inputIdx*numberOfTrellisStates+tstate;
113            nextState[tstate][inputIdx]=(unsigned int)floor(ENCregister/pow(2,k));
114            tempOut=0;
115
116            for (unsigned short int bitNo=0;bitNo<n;bitNo++){
117                // std::cout<<"\nBitNo:"<<bitNo<<" ENCregister:"<<ENCregister<<" g:"<<generatorPolynomials[bitNo]<<" &:"<<(ENCregister&generatorPolynomials[bitNo])
118                //      <<"power:"<<(unsigned short int)pow(2,n-bitNo-1)<<"tempOut:"<<tempOut<<"\n";
119                // std::cout<<"Mod2add:"<<Modulo2BitWiseAdd((ENCregister&generatorPolynomials[bitNo])*(unsigned short int)pow(2,n-bitNo-1))<<"\n";
120
121                tempOut+=Modulo2BitWiseAdd(ENCregister&generatorPolynomials[bitNo])* (unsigned short int)pow(2,n-bitNo-1);
122            }
123            output[tstate][inputIdx]=tempOut;
124            //std::cout<<output[tstate][inputIdx]<<" ("<<nextState[tstate][inputIdx]<<") ";
125
126
127        }
128        //std::cout<<std::endl;
129    }
130}
131
132unsigned short int trellisTable::Modulo2BitWiseAdd(unsigned short int inputNumber)
133{
134    //std::cout<<"IN:"<<inputNumber;
135    unsigned int tempOut=0;
136    tempOut=inputNumber % 2;
137    inputNumber>>=1;
138
139    while (inputNumber>0){
140        tempOut^=inputNumber % 2;
141        inputNumber>>=1;
142    }
143    // std::cout<<" Out:"<<tempOut<<" ";
144    return tempOut;
145}
146
147
148//-------------------------------fec_conv--------------------------------------
149
150void fec_conv::SetTrellisTable(trellisTable *theTrellisTableIn)
151{
152    theTrellisTable=theTrellisTableIn;
153}
154
155void fec_conv::Dec2Bin(unsigned int decNumber,unsigned short int * outputData,unsigned short int numberOfBits)
156{
157    unsigned short int i;
158    for (i=numberOfBits;i>0;i--){
159        outputData[i-1]=decNumber % 2;
160
161        if (decNumber>0) decNumber>>=1;
162    }
163}
164
165fec_conv_encoder::fec_conv_encoder()
166{
167    currentState=0;
168}
169
170fec_conv_encoder::~fec_conv_encoder()
171{
172
173}
174
175void fec_conv_encoder::ResetState()
176{
177    currentState=0;
178}
179
180unsigned int fec_conv_encoder::GetState()
181{
182    return currentState;
183}
184
185void fec_conv_encoder::Encode(unsigned short int * inputData,unsigned short int * outputData)
186{
187    unsigned int inbits=0,tmp=0,outbits=0;
188
189    for (unsigned short int i=0;i<theTrellisTable->k;i++)    {
190        tmp=inputData[i];
191        //std::cout<<"inputData:"<<tmp<<"\n";
192        tmp<<=theTrellisTable->k-i-1;
193        //std::cout<<"temp"<<tmp<<"\n";
194        inbits+=tmp;
195    }
196   
197    if (inbits>(unsigned int)(theTrellisTable->numberOfInputStates-1)){
198        std::cout<<"ERROR:fec_conv_encoder::Encode inbits>numberOfInputStates-1";
199        std::cout<<"inbits:"<<inbits<<" numberOfInputStates:"<<theTrellisTable->numberOfInputStates;
200        throw 0;
201    };
202
203    //std::cout<<"state:"<<currentState<<" inbits:"<<inbits<<" outbits:"<<outbits<<"\n";
204    outbits=theTrellisTable->output[currentState][inbits];
205
206    currentState=theTrellisTable->nextState[currentState][inbits];
207    Dec2Bin(outbits,outputData,theTrellisTable->n);
208
209}
210
211//------------------------------Decoder-----------------------------------------
212fec_conv_decoder::fec_conv_decoder()
213{
214    tracedBackSymbols=NULL;
215    theTrellis=NULL;
216    decodedSymbolIndex=0;
217    currentTrellisIndex=0;
218    mode=0;
219}
220
221fec_conv_decoder::~fec_conv_decoder()
222{
223    if (tracedBackSymbols!=NULL) delete  []tracedBackSymbols;
224
225    if (theTrellis!=NULL){
226        for (unsigned int i = 0; i < theTrellisTable->numberOfTrellisStates; i++){
227            delete []theTrellis[i];
228        };
229       
230        delete []theTrellis;
231    }
232
233};
234void fec_conv_decoder::SetMode(unsigned short int mode)
235{
236    fec_conv_decoder::mode=mode;
237};
238
239void fec_conv_decoder::Reset()
240{
241    decodedSymbolIndex=0;
242    currentTrellisIndex=0;
243     for (unsigned int i=0;i<theTrellisTable->numberOfTrellisStates;i++)
244        for (unsigned int j=0;j<=noOfSymbols2TraceBack;j++){
245            theTrellis[i][j].previousState=0;
246            theTrellis[i][j].symbolNo=0;
247            theTrellis[i][j].distance=(signed int)-1;
248        }
249    theTrellis[0][0].distance=0;
250};
251
252void fec_conv_decoder::SetNoOfSymbols2TraceBack(unsigned int traceBackLength){
253    //std::cout<<theTrellis;
254
255    if (fec_conv_decoder::noOfSymbols2TraceBack!=traceBackLength){
256         fec_conv_decoder::noOfSymbols2TraceBack=traceBackLength;
257        if (theTrellis!=NULL){
258            for (unsigned int i = 0; i < theTrellisTable->numberOfTrellisStates; i++){
259                delete []theTrellis[i];
260            };
261            delete []theTrellis;
262            theTrellis=NULL;
263        }
264        //std::cout<<theTrellis;
265        //int dummy;
266        //std::cin>>dummy;
267
268   
269
270        theTrellis= new TrellisEntry*[theTrellisTable->numberOfTrellisStates];
271        for (unsigned int i = 0; i < theTrellisTable->numberOfTrellisStates; i++){
272         theTrellis[i] =new TrellisEntry[noOfSymbols2TraceBack+1];
273        };
274
275        if (tracedBackSymbols!=NULL){
276            delete []tracedBackSymbols;
277            tracedBackSymbols=NULL;
278        };
279    tracedBackSymbols = new unsigned int [noOfSymbols2TraceBack];
280
281    }
282/*
283    currentTrellisIndex=0;
284    for (unsigned int i=0;i<theTrellisTable->numberOfTrellisStates;i++)
285        for (unsigned int j=0;j<=noOfSymbols2TraceBack;j++){
286            theTrellis[i][j].previousState=0;
287            theTrellis[i][j].symbolNo=0;
288            theTrellis[i][j].distance=(signed int)-1;
289        }
290    theTrellis[0][0].distance=0;
291*/
292    fec_conv_decoder::Reset();
293}
294
295void fec_conv_decoder::Symbol2Decode(unsigned short int * inputData)
296{
297
298    unsigned int inbits=0,tmp=0,newState=0;
299    unsigned short int symbol;
300    signed int distance;
301
302   // inbits=0;
303    for (unsigned short int i=0;i<theTrellisTable->n;i++){
304        tmp=inputData[i];
305        //std::cout<<"inputData:"<<tmp<<"\n";
306        tmp<<=theTrellisTable->n-i-1;
307        //std::cout<<"temp"<<tmp<<"\n";
308        inbits+=tmp;
309    }
310
311   
312    //std::cout<<"inbits:"<<inbits<<"\n";
313    currentTrellisIndex++;
314
315    if (currentTrellisIndex>noOfSymbols2TraceBack){
316         std::cout<<"ERROR:fec_conv_decoder::Symbol2Decode currentTrellisIndex>Traceback length";
317        throw 0;
318    };
319
320     if (inbits>(unsigned int)(pow(2.0,(float)theTrellisTable->n)-1)){
321        std::cout<<"ERROR:fec_conv_decoder::Symbol2Decode inbits>2^n-1\n";
322        std::cout<<"inbits:"<<inbits<<"   2^n-1: "<<(unsigned int)pow(2.0,(float)theTrellisTable->n)-1
323            <<"n="<<theTrellisTable->n<<"\n";
324        throw 0;
325    };
326
327    //std::cout<<"currentTrellisIndex:"<<currentTrellisIndex<<"\n";
328    for (unsigned int tstate=0;tstate<theTrellisTable->numberOfTrellisStates;tstate++){
329        if (theTrellis[tstate][currentTrellisIndex-1].distance!=-1){
330            for (unsigned short int inputBits=0;inputBits<theTrellisTable->numberOfInputStates;inputBits++){
331                newState=theTrellisTable->nextState[tstate][inputBits];
332                symbol=theTrellisTable->output[tstate][inputBits];
333
334                distance=CalculateDistance(inbits,symbol)+theTrellis[tstate][currentTrellisIndex-1].distance; //Have to calculate;
335                if ((theTrellis[newState][currentTrellisIndex].distance==-1)||
336                        ((distance<theTrellis[newState][currentTrellisIndex].distance))||
337                        (theTrellis[newState][currentTrellisIndex].distance<0)){
338                    theTrellis[newState][currentTrellisIndex].distance=distance;
339                    theTrellis[newState][currentTrellisIndex].previousState=tstate;
340                    theTrellis[newState][currentTrellisIndex].symbolNo=inputBits;
341                };
342            };
343        }
344        else{
345        };
346
347    }
348
349    /*
350        for (unsigned int tstate=0;tstate<numberOfTrellisStates;tstate++)
351        {
352                    std::cout<<"["<<tstate<<"]["<<currentTrellisIndex<<"].previousState:"
353                       <<theTrellis[tstate][currentTrellisIndex].previousState<<".distance:"
354                        <<theTrellis[tstate][currentTrellisIndex].distance<<".symbol:"<<
355                        theTrellis[tstate][currentTrellisIndex].symbolNo<<"\n";
356        };
357    */
358};
359
360signed int fec_conv_decoder::CalculateDistance(unsigned short int inBits, unsigned short int symbol)
361{
362    unsigned short int tmp;
363    signed int distance=0;
364    tmp=inBits^symbol;
365
366    while (tmp>0){
367        distance+=(signed int)(tmp % 2);
368        tmp>>=1;
369    };
370    return distance;
371
372}
373
374void fec_conv_decoder::TraceBackTrellis(){
375    //std::cout<<"cTi:"<<currentTrellisIndex<<"; cS:"<<currentState<<";";
376    unsigned int currentState;
377    signed int minDistance=9999;
378    unsigned int minDistState=0;
379
380    if (currentTrellisIndex==noOfSymbols2TraceBack){
381        if (mode==1){
382            currentState=0;
383        } else{
384            for (unsigned int tstate=0;tstate<theTrellisTable->numberOfTrellisStates;tstate++)
385                if ((theTrellis[tstate][currentTrellisIndex].distance!=-1)
386                        &&(theTrellis[tstate][currentTrellisIndex].distance<minDistance)){
387                    minDistance=theTrellis[tstate][currentTrellisIndex].distance;
388                    minDistState=tstate;
389                };
390
391            currentState=minDistState;
392        }
393       // std::cout<<"\nMinDistance:"<<minDistance<<" minDistState:"<<minDistState<<"\n";
394
395
396        unsigned short int symbol;
397        while (currentTrellisIndex>0)
398        {
399            symbol=theTrellis[currentState][currentTrellisIndex].symbolNo;
400            currentState=theTrellis[currentState][currentTrellisIndex].previousState;
401            currentTrellisIndex--;
402            //Dec2Bin(symbol,outputData,k);
403            tracedBackSymbols[currentTrellisIndex]=symbol;
404            // std::cout<<"\nsymbol:"<<symbol<<"outputData"<<outputData[0]<<"\n";
405        }
406
407        decodedSymbolIndex=0;
408    }
409}
410
411void fec_conv_decoder::GetDecodedSymbol(unsigned short int * outputData)
412{
413    if (currentTrellisIndex==0){
414
415        if (decodedSymbolIndex<noOfSymbols2TraceBack){
416            Dec2Bin(tracedBackSymbols[decodedSymbolIndex],
417            outputData,
418            theTrellisTable->k);
419        } else {
420        std::cout<<"ERROR: fec_conv_decoder::GetDecodedSymbol attempt to get more symbols of what is available\n";
421        throw 0;
422   
423        }
424       
425        decodedSymbolIndex++;
426       
427    } else {
428        std::cout<<"ERROR: fec_conv_decoder::GetDecodedSymbol trellis wasnt traced back properly\n";
429        throw 0;
430    }
431}
432
433
434
435} // namespace SigProc
436
Note: See TracBrowser for help on using the browser.