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