root/experimental/components/DigitalModem/trunk/DigitalModem/src/DigitalModem.cpp @ 4746

Revision 4746, 5.4 KB (checked in by jgaeddert, 6 years ago)

fixing ModulateSequence method in DigitalModem, adding autotests

  • Property svn:eol-style set to native
Line 
1/****************************************************************************
2
3Copyright 2007 Virginia Polytechnic Institute and State University
4
5This file is part of the OSSIE Demodulator.
6
7OSSIE Demodulator is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12OSSIE Demodulator is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with OSSIE Demodulator; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
21****************************************************************************/
22
23
24#include <iostream>
25#include "DigitalModem.h"
26#include <math.h>
27
28using namespace SigProc;
29
30
31// Default constructor
32DigitalModem::DigitalModem()
33{
34    SetModulationScheme( BPSK );
35}
36
37// Destructor
38DigitalModem::~DigitalModem()
39{
40}
41
42// Set modulation scheme
43void DigitalModem::SetModulationScheme( SigProc::ModulationScheme _ms )
44{
45    switch ( _ms ) {
46    case BPSK:
47        Demodulate = &DemodulateBPSK;
48        Modulate = &ModulateBPSK;
49        bitsPerSymbol = 1;
50        differentialMode = false;
51        break;
52    case QPSK:
53        Demodulate = &DemodulateQPSK;
54        Modulate = &ModulateQPSK;
55        bitsPerSymbol = 2;
56        differentialMode = false;
57        break;
58    case PSK8:
59        Demodulate = &Demodulate8PSK;
60        Modulate = &Modulate8PSK;
61        bitsPerSymbol = 3;
62        differentialMode = false;
63        break;
64    case QAM16:
65        Demodulate = &Demodulate16QAM;
66        Modulate = &Modulate16QAM;
67        bitsPerSymbol = 4;
68        differentialMode = false;
69        break;
70    case PAM4:
71        Demodulate = &Demodulate4PAM;
72        Modulate = &Modulate4PAM;
73        bitsPerSymbol = 2;
74        differentialMode = false;
75        break;
76    case DBPSK:
77        state_i = 0;
78        state_q = 0;
79        Demodulate = &DemodulateBPSK;
80        Modulate = &ModulateBPSK;
81        bitsPerSymbol = 1;
82        differentialMode = true;
83        break;
84    case DQPSK:
85        state_i = 0;
86        state_q = 0;
87        Demodulate = &DemodulateQPSK;
88        Modulate = &ModulateQPSK;
89        bitsPerSymbol = 2;
90        differentialMode = true;
91        break;
92    case DPSK8:
93        state_i = 0;
94        state_q = 0;
95        Demodulate = &Demodulate8PSK;
96        Modulate = &Modulate8PSK;
97        bitsPerSymbol = 3;
98        differentialMode = true;
99        break;
100    default:
101        std::cerr << "ERROR: DigitalModem::SetModulationScheme(): "
102                  << "unknown mod. scheme " << _ms << std::endl;
103        std::cerr << "  => Using BPSK instead" << std::endl;
104        SetModulationScheme( BPSK );
105        //throw 0;
106    }
107   
108    mod_scheme = _ms;
109}
110
111// Modulates sequence of bits
112void DigitalModem::ModulateSequence(
113        char * bits_in,
114        unsigned int N_in,
115        short * I_out,
116        short * Q_out)
117{
118    unsigned short s;
119    unsigned int j(0);
120   
121    if ( differentialMode ) {
122        ///\todo implement differential PSK modulation
123        std::cerr << "ERROR: DigitalModem::DemodulateSequence(): "
124                  << "differential mode not yet supported!" << std::endl;
125        throw 0;
126    } else {
127        for (unsigned int i=0; j<N_in; i++) {
128            ConvertBitsToSymbol(bits_in+j, s);
129            Modulate(s, I_out[i], Q_out[i]);
130            j += bitsPerSymbol;
131        }
132    }
133       
134}
135
136
137//
138void DigitalModem::DemodulateSequence(
139        short * I_in,
140        short * Q_in,
141        unsigned int N_in,
142        char * bits_out)
143{
144    short s;
145    unsigned int j(0);
146
147    // If QAM or PAM correct for amplitude
148    if ( mod_scheme == QAM16 || mod_scheme == PAM4 ) {
149        ScaleSignalAmplitude(I_in, Q_in, N_in, TARGET_SIGNAL_ENERGY);
150    }
151
152    if ( differentialMode ) {
153        ///\todo implement differential PSK demodulation
154        std::cerr << "ERROR: DigitalModem::DemodulateSequence(): "
155                  << "differential mode not yet supported!" << std::endl;
156        throw 0;
157    } else {
158        for (unsigned int i=0; i<N_in; i++) {
159            Demodulate(I_in[i], Q_in[i], s);
160            ConvertSymbolToBits(s, bits_out+j);
161            j += bitsPerSymbol;
162        }
163    }
164}
165
166
167//
168void DigitalModem::ScaleSignalAmplitude(
169    short * I_in,
170    short * Q_in,
171    unsigned int N_in,
172    unsigned int targetEnergy)
173{
174    unsigned int i;
175    float energy(0.0f), scalingFactor;
176    for (i=0; i<N_in; i++) {
177        energy += float(I_in[i])*float(I_in[i]);
178        energy += float(Q_in[i])*float(Q_in[i]);
179    }
180    energy /= float(N_in);
181
182    scalingFactor = float(targetEnergy)/sqrtf(energy);
183
184    for (i=0; i<N_in; i++) {
185        I_in[i] = short( I_in[i]*scalingFactor );
186        Q_in[i] = short( Q_in[i]*scalingFactor );
187    }
188}
189
190
191// Converts symbol to bit sequence
192void DigitalModem::ConvertSymbolToBits(unsigned short s, char * bitsOut)
193{
194    for (unsigned int i=0; i<bitsPerSymbol; i++) {
195        bitsOut[bitsPerSymbol-i-1] = ( s & 0x01 ) ? BIT1 : BIT0;
196        s >>= 1;
197    }
198}
199
200
201// Converts bit sequence to symbol
202void DigitalModem::ConvertBitsToSymbol(char * bitsIn, unsigned short &s)
203{
204    s = 0;
205   
206    for (unsigned int i=0; i<bitsPerSymbol; i++) {
207        s <<= 1;
208        s |= (bitsIn[i] > 0) ? 1 : 0;
209    }
210}
211
212
Note: See TracBrowser for help on using the browser.