blob: 3019c2c16aa9575644839ff61ff136fcf4e82a72 [file] [log] [blame]
Roman Khassraf059bab92015-05-20 12:49:46 +02001/*
2* Copyright 2008 Free Software Foundation, Inc.
3*
4* This software is distributed under the terms of the GNU Public License.
5* See the COPYING file in the main directory for details.
6
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20*/
21
22
23#ifndef FECVECTORS_H
24#define FECVECTORS_H
25
26#include "Vector.h"
27#include <stdint.h>
28
29
30class BitVector;
31class SoftVector;
32
33
34
35/** Shift-register (LFSR) generator. */
36class Generator {
37
38 private:
39
40 uint64_t mCoeff; ///< polynomial coefficients. LSB is zero exponent.
41 uint64_t mState; ///< shift register state. LSB is most recent.
42 uint64_t mMask; ///< mask for reading state
43 unsigned mLen; ///< number of bits used in shift register
44 unsigned mLen_1; ///< mLen - 1
45
46 public:
47
48 Generator(uint64_t wCoeff, unsigned wLen)
49 :mCoeff(wCoeff),mState(0),
50 mMask((1ULL<<wLen)-1),
51 mLen(wLen),mLen_1(wLen-1)
52 { assert(wLen<64); }
53
54 void clear() { mState=0; }
55
56 /**@name Accessors */
57 //@{
58 uint64_t state() const { return mState & mMask; }
59 unsigned size() const { return mLen; }
60 //@}
61
62 /**
63 Calculate one bit of a syndrome.
64 This is in the .h for inlining.
65 */
66 void syndromeShift(unsigned inBit)
67 {
68 const unsigned fb = (mState>>(mLen_1)) & 0x01;
69 mState = (mState<<1) ^ (inBit & 0x01);
70 if (fb) mState ^= mCoeff;
71 }
72
73 /**
74 Update the generator state by one cycle.
75 This is in the .h for inlining.
76 */
77 void encoderShift(unsigned inBit)
78 {
79 const unsigned fb = ((mState>>(mLen_1)) ^ inBit) & 0x01;
80 mState <<= 1;
81 if (fb) mState ^= mCoeff;
82 }
83
84
85};
86
87
88
89
90/** Parity (CRC-type) generator and checker based on a Generator. */
91class Parity : public Generator {
92
93 protected:
94
95 unsigned mCodewordSize;
96
97 public:
98
99 Parity(uint64_t wCoefficients, unsigned wParitySize, unsigned wCodewordSize)
100 :Generator(wCoefficients, wParitySize),
101 mCodewordSize(wCodewordSize)
102 { }
103
104 /** Compute the parity word and write it into the target segment. */
105 void writeParityWord(const BitVector& data, BitVector& parityWordTarget, bool invert=true);
106
107 /** Compute the syndrome of a received sequence. */
108 uint64_t syndrome(const BitVector& receivedCodeword);
109};
110
111
112
113
114/**
115 Class to represent convolutional coders/decoders of rate 1/2, memory length 4.
116 This is the "workhorse" coder for most GSM channels.
117*/
118class ViterbiR2O4 {
119
120 private:
121 /**name Lots of precomputed elements so the compiler can optimize like hell. */
122 //@{
123 /**@name Core values. */
124 //@{
125 static const unsigned mIRate = 2; ///< reciprocal of rate
126 static const unsigned mOrder = 4; ///< memory length of generators
127 //@}
128 /**@name Derived values. */
129 //@{
130 static const unsigned mIStates = 0x01 << mOrder; ///< number of states, number of survivors
131 static const uint32_t mSMask = mIStates-1; ///< survivor mask
132 static const uint32_t mCMask = (mSMask<<1) | 0x01; ///< candidate mask
133 static const uint32_t mOMask = (0x01<<mIRate)-1; ///< ouput mask, all iRate low bits set
134 static const unsigned mNumCands = mIStates*2; ///< number of candidates to generate during branching
135 static const unsigned mDeferral = 6*mOrder; ///< deferral to be used
136 //@}
137 //@}
138
139 /** Precomputed tables. */
140 //@{
141 uint32_t mCoeffs[mIRate]; ///< polynomial for each generator
142 uint32_t mStateTable[mIRate][2*mIStates]; ///< precomputed generator output tables
143 uint32_t mGeneratorTable[2*mIStates]; ///< precomputed coder output table
144 //@}
145
146 public:
147
148 /**
149 A candidate sequence in a Viterbi decoder.
150 The 32-bit state register can support a deferral of 6 with a 4th-order coder.
151 */
152 typedef struct candStruct {
153 uint32_t iState; ///< encoder input associated with this candidate
154 uint32_t oState; ///< encoder output associated with this candidate
155 float cost; ///< cost (metric value), float to support soft inputs
156 } vCand;
157
158 /** Clear a structure. */
159 void clear(vCand& v)
160 {
161 v.iState=0;
162 v.oState=0;
163 v.cost=0;
164 }
165
166
167 private:
168
169 /**@name Survivors and candidates. */
170 //@{
171 vCand mSurvivors[mIStates]; ///< current survivor pool
172 vCand mCandidates[2*mIStates]; ///< current candidate pool
173 //@}
174
175 public:
176
177 unsigned iRate() const { return mIRate; }
178 uint32_t cMask() const { return mCMask; }
179 uint32_t stateTable(unsigned g, unsigned i) const { return mStateTable[g][i]; }
180 unsigned deferral() const { return mDeferral; }
181
182
183 ViterbiR2O4();
184
185 /** Set all cost metrics to zero. */
186 void initializeStates();
187
188 /**
189 Full cycle of the Viterbi algorithm: branch, metrics, prune, select.
190 @return reference to minimum-cost candidate.
191 */
192 const vCand& step(uint32_t inSample, const float *probs, const float *iprobs);
193
194 private:
195
196 /** Branch survivors into new candidates. */
197 void branchCandidates();
198
199 /** Compute cost metrics for soft-inputs. */
200 void getSoftCostMetrics(uint32_t inSample, const float *probs, const float *iprobs);
201
202 /** Select survivors from the candidate set. */
203 void pruneCandidates();
204
205 /** Find the minimum cost survivor. */
206 const vCand& minCost() const;
207
208 /**
209 Precompute the state tables.
210 @param g Generator index 0..((1/rate)-1)
211 */
212 void computeStateTables(unsigned g);
213
214 /**
215 Precompute the generator outputs.
216 mCoeffs must be defined first.
217 */
218 void computeGeneratorTable();
219
220};
221
222
223
224
225class BitVector : public Vector<char> {
226
227
228 public:
229
230 /**@name Constructors. */
231 //@{
232
233 /**@name Casts of Vector constructors. */
234 //@{
235 BitVector(char* wData, char* wStart, char* wEnd)
236 :Vector<char>(wData,wStart,wEnd)
237 { }
238 BitVector(size_t len=0):Vector<char>(len) {}
239 BitVector(const Vector<char>& source):Vector<char>(source) {}
240 BitVector(Vector<char>& source):Vector<char>(source) {}
241 BitVector(const Vector<char>& source1, const Vector<char> source2):Vector<char>(source1,source2) {}
242 //@}
243
244 /** Construct from a string of "0" and "1". */
245 BitVector(const char* valString);
246 //@}
247
248 /** Index a single bit. */
249 bool bit(size_t index) const
250 {
251 // We put this code in .h for fast inlining.
252 const char *dp = mStart+index;
253 assert(dp<mEnd);
254 return (*dp) & 0x01;
255 }
256
257 /**@name Casts and overrides of Vector operators. */
258 //@{
259 BitVector segment(size_t start, size_t span)
260 {
261 char* wStart = mStart + start;
262 char* wEnd = wStart + span;
263 assert(wEnd<=mEnd);
264 return BitVector(NULL,wStart,wEnd);
265 }
266
267 BitVector alias()
268 { return segment(0,size()); }
269
270 const BitVector segment(size_t start, size_t span) const
271 { return (BitVector)(Vector<char>::segment(start,span)); }
272
273 BitVector head(size_t span) { return segment(0,span); }
274 const BitVector head(size_t span) const { return segment(0,span); }
275 BitVector tail(size_t start) { return segment(start,size()-start); }
276 const BitVector tail(size_t start) const { return segment(start,size()-start); }
277 //@}
278
279
280 void zero() { fill(0); }
281
282 /**@name FEC operations. */
283 //@{
284 /** Calculate the syndrome of the vector with the given Generator. */
285 uint64_t syndrome(Generator& gen) const;
286 /** Calculate the parity word for the vector with the given Generator. */
287 uint64_t parity(Generator& gen) const;
288 /** Encode the signal with the GSM rate 1/2 convolutional encoder. */
289 void encode(const ViterbiR2O4& encoder, BitVector& target);
290 //@}
291
292
293 /** Invert 0<->1. */
294 void invert();
295
296 /**@name Byte-wise operations. */
297 //@{
298 /** Reverse an 8-bit vector. */
299 void reverse8();
300 /** Reverse groups of 8 within the vector (byte reversal). */
301 void LSB8MSB();
302 //@}
303
304 /**@name Serialization and deserialization. */
305 //@{
306 uint64_t peekField(size_t readIndex, unsigned length) const;
307 uint64_t readField(size_t& readIndex, unsigned length) const;
308 void fillField(size_t writeIndex, uint64_t value, unsigned length);
309 void writeField(size_t& writeIndex, uint64_t value, unsigned length);
310 //@}
311
312 /** Sum of bits. */
313 unsigned sum() const;
314
315 /** Reorder bits, dest[i] = this[map[i]]. */
316 void map(const unsigned *map, size_t mapSize, BitVector& dest) const;
317
318 /** Reorder bits, dest[map[i]] = this[i]. */
319 void unmap(const unsigned *map, size_t mapSize, BitVector& dest) const;
320
321 /** Pack into a char array. */
322 void pack(unsigned char*) const;
323
324 /** Unopack from a char array. */
325 void unpack(const unsigned char*);
326
327};
328
329
330
331std::ostream& operator<<(std::ostream&, const BitVector&);
332
333
334
335
336
337
338/**
339 The SoftVector class is used to represent a soft-decision signal.
340 Values 0..1 represent probabilities that a bit is "true".
341 */
342class SoftVector: public Vector<float> {
343
344 public:
345
346 /** Build a SoftVector of a given length. */
347 SoftVector(size_t wSize=0):Vector<float>(wSize) {}
348
349 /** Construct a SoftVector from a C string of "0", "1", and "X". */
350 SoftVector(const char* valString);
351
352 /** Construct a SoftVector from a BitVector. */
353 SoftVector(const BitVector& source);
354
355 /**
356 Wrap a SoftVector around a block of floats.
357 The block will be delete[]ed upon desctuction.
358 */
359 SoftVector(float *wData, unsigned length)
360 :Vector<float>(wData,length)
361 {}
362
363 SoftVector(float* wData, float* wStart, float* wEnd)
364 :Vector<float>(wData,wStart,wEnd)
365 { }
366
367 /**
368 Casting from a Vector<float>.
369 Note that this is NOT pass-by-reference.
370 */
371 SoftVector(Vector<float> source)
372 :Vector<float>(source)
373 {}
374
375
376 /**@name Casts and overrides of Vector operators. */
377 //@{
378 SoftVector segment(size_t start, size_t span)
379 {
380 float* wStart = mStart + start;
381 float* wEnd = wStart + span;
382 assert(wEnd<=mEnd);
383 return SoftVector(NULL,wStart,wEnd);
384 }
385
386 SoftVector alias()
387 { return segment(0,size()); }
388
389 const SoftVector segment(size_t start, size_t span) const
390 { return (SoftVector)(Vector<float>::segment(start,span)); }
391
392 SoftVector head(size_t span) { return segment(0,span); }
393 const SoftVector head(size_t span) const { return segment(0,span); }
394 SoftVector tail(size_t start) { return segment(start,size()-start); }
395 const SoftVector tail(size_t start) const { return segment(start,size()-start); }
396 //@}
397
398 /** Decode soft symbols with the GSM rate-1/2 Viterbi decoder. */
399 void decode(ViterbiR2O4 &decoder, BitVector& target) const;
400
401 /** Fill with "unknown" values. */
402 void unknown() { fill(0.5F); }
403
404 /** Return a hard bit value from a given index by slicing. */
405 bool bit(size_t index) const
406 {
407 const float *dp = mStart+index;
408 assert(dp<mEnd);
409 return (*dp)>0.5F;
410 }
411
412 /** Slice the whole signal into bits. */
413 BitVector sliced() const;
414
415};
416
417
418
419std::ostream& operator<<(std::ostream&, const SoftVector&);
420
421
422
423
424
425
426#endif
427// vim: ts=4 sw=4