blob: 089981731a969b204684d7609b80853a8f3a0feb [file] [log] [blame]
Roman Khassraf059bab92015-05-20 12:49:46 +02001/*
Roman Khassrafd71e6582015-06-02 08:49:12 +02002* Copyright 2008, 2009, 2014 Free Software Foundation, Inc.
3* Copyright 2014 Range Networks, Inc.
Roman Khassraf059bab92015-05-20 12:49:46 +02004*
Roman Khassrafd71e6582015-06-02 08:49:12 +02005* This software is distributed under the terms of the GNU Affero Public License.
Roman Khassraf059bab92015-05-20 12:49:46 +02006* See the COPYING file in the main directory for details.
Roman Khassrafd71e6582015-06-02 08:49:12 +02007*
8* This use of this software may be subject to additional restrictions.
9* See the LEGAL file in the main directory for details.
Roman Khassraf059bab92015-05-20 12:49:46 +020010
Roman Khassrafd71e6582015-06-02 08:49:12 +020011 This program is free software: you can redistribute it and/or modify
12 it under the terms of the GNU Affero General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
Roman Khassraf059bab92015-05-20 12:49:46 +020015
Roman Khassrafd71e6582015-06-02 08:49:12 +020016 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU Affero General Public License for more details.
Roman Khassraf059bab92015-05-20 12:49:46 +020020
Roman Khassrafd71e6582015-06-02 08:49:12 +020021 You should have received a copy of the GNU Affero General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
Roman Khassraf059bab92015-05-20 12:49:46 +020023
24*/
25
26
Roman Khassrafd71e6582015-06-02 08:49:12 +020027#ifndef BITVECTORS_H
28#define BITVECTORS_H
Roman Khassraf059bab92015-05-20 12:49:46 +020029
30#include "Vector.h"
31#include <stdint.h>
Roman Khassrafd71e6582015-06-02 08:49:12 +020032#include <stdio.h>
Roman Khassraf059bab92015-05-20 12:49:46 +020033
34
35class BitVector;
36class SoftVector;
37
38
39
Roman Khassrafd71e6582015-06-02 08:49:12 +020040
Roman Khassraf059bab92015-05-20 12:49:46 +020041/** Shift-register (LFSR) generator. */
42class Generator {
43
44 private:
45
46 uint64_t mCoeff; ///< polynomial coefficients. LSB is zero exponent.
47 uint64_t mState; ///< shift register state. LSB is most recent.
48 uint64_t mMask; ///< mask for reading state
49 unsigned mLen; ///< number of bits used in shift register
50 unsigned mLen_1; ///< mLen - 1
51
52 public:
53
54 Generator(uint64_t wCoeff, unsigned wLen)
55 :mCoeff(wCoeff),mState(0),
56 mMask((1ULL<<wLen)-1),
57 mLen(wLen),mLen_1(wLen-1)
58 { assert(wLen<64); }
59
60 void clear() { mState=0; }
61
62 /**@name Accessors */
63 //@{
64 uint64_t state() const { return mState & mMask; }
65 unsigned size() const { return mLen; }
66 //@}
67
68 /**
69 Calculate one bit of a syndrome.
70 This is in the .h for inlining.
71 */
72 void syndromeShift(unsigned inBit)
73 {
74 const unsigned fb = (mState>>(mLen_1)) & 0x01;
75 mState = (mState<<1) ^ (inBit & 0x01);
76 if (fb) mState ^= mCoeff;
77 }
78
79 /**
80 Update the generator state by one cycle.
81 This is in the .h for inlining.
82 */
83 void encoderShift(unsigned inBit)
84 {
85 const unsigned fb = ((mState>>(mLen_1)) ^ inBit) & 0x01;
86 mState <<= 1;
87 if (fb) mState ^= mCoeff;
88 }
89
90
91};
92
93
94
95
96/** Parity (CRC-type) generator and checker based on a Generator. */
97class Parity : public Generator {
98
99 protected:
100
101 unsigned mCodewordSize;
102
103 public:
104
105 Parity(uint64_t wCoefficients, unsigned wParitySize, unsigned wCodewordSize)
106 :Generator(wCoefficients, wParitySize),
107 mCodewordSize(wCodewordSize)
108 { }
109
110 /** Compute the parity word and write it into the target segment. */
111 void writeParityWord(const BitVector& data, BitVector& parityWordTarget, bool invert=true);
112
113 /** Compute the syndrome of a received sequence. */
114 uint64_t syndrome(const BitVector& receivedCodeword);
115};
116
117
Roman Khassrafd71e6582015-06-02 08:49:12 +0200118// (pat) Nov 2013. I rationalized the behavior of BitVector and added assertions to core dump code
119// that relied on the bad aspects of the original behavior. See comments at VectorBase.
120class BitVector : public VectorBase<char>
121{
Roman Khassraf059bab92015-05-20 12:49:46 +0200122 public:
Roman Khassraf059bab92015-05-20 12:49:46 +0200123 /**@name Constructors. */
124 //@{
125
126 /**@name Casts of Vector constructors. */
Roman Khassrafd71e6582015-06-02 08:49:12 +0200127 BitVector(VectorDataType wData, char* wStart, char* wEnd) : VectorBase<char>(wData, wStart, wEnd) {}
128
129 // The one and only copy-constructor.
130 BitVector(const BitVector&other) : VectorBase<char>() {
131 VECTORDEBUG("BitVector(%p)",(void*)&other);
132 if (other.getData()) {
133 this->clone(other);
134 } else {
135 this->makeAlias(other);
136 }
137 }
138
139 // (pat) Removed default value for len and added 'explicit'. Please do not remove 'explicit';
140 // it prevents auto-conversion of int to BitVector in constructors.
141 // Previous code was often ambiguous, especially for L3Frame and descendent constructors, leading to latent bugs.
142 explicit BitVector(size_t len) { this->vInit(len); }
143 BitVector() { this->vInit(0); }
144
145 /** Build a BitVector by concatenation. */
146 BitVector(const BitVector& other1, const BitVector& other2) : VectorBase<char>()
147 {
148 assert(this->getData() == 0);
149 this->vConcat(other1,other2);
150 }
Roman Khassraf059bab92015-05-20 12:49:46 +0200151
152 /** Construct from a string of "0" and "1". */
Roman Khassrafd71e6582015-06-02 08:49:12 +0200153 // (pat) Characters that are not '0' or '1' map to '0'.
Roman Khassraf059bab92015-05-20 12:49:46 +0200154 BitVector(const char* valString);
155 //@}
156
Roman Khassraf059bab92015-05-20 12:49:46 +0200157 /**@name Casts and overrides of Vector operators. */
158 //@{
Roman Khassrafd71e6582015-06-02 08:49:12 +0200159 // (pat) Please DO NOT add a const anywhere in this method. Use cloneSegment instead.
Roman Khassraf059bab92015-05-20 12:49:46 +0200160 BitVector segment(size_t start, size_t span)
161 {
Roman Khassrafd71e6582015-06-02 08:49:12 +0200162 char* wStart = this->begin() + start;
Roman Khassraf059bab92015-05-20 12:49:46 +0200163 char* wEnd = wStart + span;
Roman Khassrafd71e6582015-06-02 08:49:12 +0200164 assert(wEnd<=this->end());
165#if BITVECTOR_REFCNTS
166 return BitVector(mData,wStart,wEnd);
167#else
Roman Khassraf059bab92015-05-20 12:49:46 +0200168 return BitVector(NULL,wStart,wEnd);
Roman Khassrafd71e6582015-06-02 08:49:12 +0200169#endif
Roman Khassraf059bab92015-05-20 12:49:46 +0200170 }
171
Roman Khassrafd71e6582015-06-02 08:49:12 +0200172 // (pat) Historically the BitVector segment method had const and non-const versions with different behavior.
173 // I changed the name of the const version to cloneSegment and replaced all uses throughout OpenBTS.
174 const BitVector cloneSegment(size_t start, size_t span) const
175 {
176 BitVector seg = const_cast<BitVector*>(this)->segment(start,span);
177 // (pat) We are depending on the Return Value Optimization not to invoke the copy-constructor on the result,
178 // which would result in its immediate destruction while we are still using it.
179 BitVector result;
180 result.clone(seg);
181 return result;
182 }
Roman Khassraf059bab92015-05-20 12:49:46 +0200183
Roman Khassrafd71e6582015-06-02 08:49:12 +0200184 BitVector alias() const {
185 return const_cast<BitVector*>(this)->segment(0,size());
186 }
Roman Khassraf059bab92015-05-20 12:49:46 +0200187
188 BitVector head(size_t span) { return segment(0,span); }
Roman Khassraf059bab92015-05-20 12:49:46 +0200189 BitVector tail(size_t start) { return segment(start,size()-start); }
Roman Khassrafd71e6582015-06-02 08:49:12 +0200190
191 // (pat) Please do NOT put the const version of head and tail back in, because historically they were messed up.
192 // Use cloneSegment instead.
193 //const BitVector head(size_t span) const { return segment(0,span); }
194 //const BitVector tail(size_t start) const { return segment(start,size()-start); }
Roman Khassraf059bab92015-05-20 12:49:46 +0200195 //@}
196
197
198 void zero() { fill(0); }
199
200 /**@name FEC operations. */
201 //@{
202 /** Calculate the syndrome of the vector with the given Generator. */
203 uint64_t syndrome(Generator& gen) const;
204 /** Calculate the parity word for the vector with the given Generator. */
205 uint64_t parity(Generator& gen) const;
Roman Khassraf059bab92015-05-20 12:49:46 +0200206 //@}
207
208
209 /** Invert 0<->1. */
210 void invert();
211
212 /**@name Byte-wise operations. */
213 //@{
214 /** Reverse an 8-bit vector. */
215 void reverse8();
216 /** Reverse groups of 8 within the vector (byte reversal). */
217 void LSB8MSB();
218 //@}
219
220 /**@name Serialization and deserialization. */
221 //@{
222 uint64_t peekField(size_t readIndex, unsigned length) const;
Roman Khassrafd71e6582015-06-02 08:49:12 +0200223 uint64_t peekFieldReversed(size_t readIndex, unsigned length) const;
Roman Khassraf059bab92015-05-20 12:49:46 +0200224 uint64_t readField(size_t& readIndex, unsigned length) const;
Roman Khassrafd71e6582015-06-02 08:49:12 +0200225 uint64_t readFieldReversed(size_t& readIndex, unsigned length) const;
Roman Khassraf059bab92015-05-20 12:49:46 +0200226 void fillField(size_t writeIndex, uint64_t value, unsigned length);
Roman Khassrafd71e6582015-06-02 08:49:12 +0200227 void fillFieldReversed(size_t writeIndex, uint64_t value, unsigned length);
Roman Khassraf059bab92015-05-20 12:49:46 +0200228 void writeField(size_t& writeIndex, uint64_t value, unsigned length);
Roman Khassrafd71e6582015-06-02 08:49:12 +0200229 void writeFieldReversed(size_t& writeIndex, uint64_t value, unsigned length);
230 void write0(size_t& writeIndex) { writeField(writeIndex,0,1); }
231 void write1(size_t& writeIndex) { writeField(writeIndex,1,1); }
232
Roman Khassraf059bab92015-05-20 12:49:46 +0200233 //@}
234
235 /** Sum of bits. */
236 unsigned sum() const;
237
238 /** Reorder bits, dest[i] = this[map[i]]. */
239 void map(const unsigned *map, size_t mapSize, BitVector& dest) const;
240
241 /** Reorder bits, dest[map[i]] = this[i]. */
242 void unmap(const unsigned *map, size_t mapSize, BitVector& dest) const;
243
244 /** Pack into a char array. */
245 void pack(unsigned char*) const;
Roman Khassrafd38206c2015-06-07 16:26:29 +0200246
247 /* Roman: This is here for debugging */
248 void pack2(unsigned char*) const;
249
Roman Khassrafd71e6582015-06-02 08:49:12 +0200250 // Same as pack but return a string.
251 std::string packToString() const;
Roman Khassraf059bab92015-05-20 12:49:46 +0200252
Roman Khassrafd71e6582015-06-02 08:49:12 +0200253 /** Unpack from a char array. */
Roman Khassraf059bab92015-05-20 12:49:46 +0200254 void unpack(const unsigned char*);
255
Roman Khassrafd71e6582015-06-02 08:49:12 +0200256 /** Make a hexdump string. */
257 void hex(std::ostream&) const;
258 std::string hexstr() const;
259
260 /** Unpack from a hexdump string.
261 * @returns true on success, false on error. */
262 bool unhex(const char*);
263
264 // For this method, 'other' should have been run through the copy-constructor already
265 // (unless it was newly created, ie foo.dup(L2Frame(...)), in which case we are screwed anyway)
266 // so the call to makeAlias is redundant.
267 // This only works if other is already an alias.
268 void dup(BitVector other) { assert(!this->getData()); makeAlias(other); assert(this->mStart == other.mStart); }
269 void dup(BitVector &other) { makeAlias(other); assert(this->mStart == other.mStart); }
270
271#if 0
272 void operator=(const BitVector& other) {
273 printf("BitVector::operator=\n");
274 assert(0);
275 //this->dup(other);
276 }
277#endif
278
279 bool operator==(const BitVector &other) const;
280
281 /** Copy to dst, not including those indexed in puncture. */
282 void copyPunctured(BitVector &dst, const unsigned *puncture, const size_t plth);
283
284 /** Index a single bit. */
285 // (pat) Cant have too many ways to do this, I guess.
286 bool bit(size_t index) const
287 {
288 // We put this code in .h for fast inlining.
289 const char *dp = this->begin()+index;
290 assert(dp<this->end());
291 return (*dp) & 0x01;
292 }
293
294 char& operator[](size_t index)
295 {
296 assert(this->mStart+index<this->mEnd);
297 return this->mStart[index];
298 }
299
300 const char& operator[](size_t index) const
301 {
302 assert(this->mStart+index<this->mEnd);
303 return this->mStart[index];
304 }
305
306 /** Set a bit */
307 void settfb(size_t index, int value)
308 {
309 char *dp = this->mStart+index;
310 assert(dp<this->mEnd);
311 *dp = value;
312 }
313
314 typedef char* iterator;
315 typedef const char* const_iterator;
Roman Khassraf059bab92015-05-20 12:49:46 +0200316};
317
Roman Khassrafd71e6582015-06-02 08:49:12 +0200318// (pat) BitVector2 was an intermediate step in fixing BitVector but is no longer needed.
319#define BitVector2 BitVector
Roman Khassraf059bab92015-05-20 12:49:46 +0200320
321
322std::ostream& operator<<(std::ostream&, const BitVector&);
323
324
325
326
327
328
329/**
330 The SoftVector class is used to represent a soft-decision signal.
331 Values 0..1 represent probabilities that a bit is "true".
332 */
333class SoftVector: public Vector<float> {
334
335 public:
336
337 /** Build a SoftVector of a given length. */
338 SoftVector(size_t wSize=0):Vector<float>(wSize) {}
339
340 /** Construct a SoftVector from a C string of "0", "1", and "X". */
341 SoftVector(const char* valString);
Roman Khassrafd71e6582015-06-02 08:49:12 +0200342
Roman Khassraf059bab92015-05-20 12:49:46 +0200343 /** Construct a SoftVector from a BitVector. */
344 SoftVector(const BitVector& source);
345
346 /**
347 Wrap a SoftVector around a block of floats.
348 The block will be delete[]ed upon desctuction.
349 */
350 SoftVector(float *wData, unsigned length)
351 :Vector<float>(wData,length)
352 {}
353
354 SoftVector(float* wData, float* wStart, float* wEnd)
355 :Vector<float>(wData,wStart,wEnd)
356 { }
357
358 /**
359 Casting from a Vector<float>.
360 Note that this is NOT pass-by-reference.
361 */
362 SoftVector(Vector<float> source)
363 :Vector<float>(source)
364 {}
365
366
367 /**@name Casts and overrides of Vector operators. */
368 //@{
369 SoftVector segment(size_t start, size_t span)
370 {
371 float* wStart = mStart + start;
372 float* wEnd = wStart + span;
373 assert(wEnd<=mEnd);
374 return SoftVector(NULL,wStart,wEnd);
375 }
376
377 SoftVector alias()
378 { return segment(0,size()); }
379
380 const SoftVector segment(size_t start, size_t span) const
381 { return (SoftVector)(Vector<float>::segment(start,span)); }
382
383 SoftVector head(size_t span) { return segment(0,span); }
384 const SoftVector head(size_t span) const { return segment(0,span); }
385 SoftVector tail(size_t start) { return segment(start,size()-start); }
386 const SoftVector tail(size_t start) const { return segment(start,size()-start); }
387 //@}
388
Roman Khassrafd71e6582015-06-02 08:49:12 +0200389 // (pat) How good is the SoftVector in the sense of the bits being solid?
390 // Result of 1 is perfect and 0 means all the bits were 0.5
391 // If plow is non-NULL, also return the lowest energy bit.
392 float getEnergy(float *low=0) const;
393 float getSNR() const;
Roman Khassraf059bab92015-05-20 12:49:46 +0200394
395 /** Fill with "unknown" values. */
396 void unknown() { fill(0.5F); }
397
398 /** Return a hard bit value from a given index by slicing. */
399 bool bit(size_t index) const
400 {
401 const float *dp = mStart+index;
402 assert(dp<mEnd);
403 return (*dp)>0.5F;
404 }
405
406 /** Slice the whole signal into bits. */
407 BitVector sliced() const;
408
Roman Khassrafd71e6582015-06-02 08:49:12 +0200409 /** Copy to dst, adding in 0.5 for those indexed in puncture. */
410 void copyUnPunctured(SoftVector &dst, const unsigned *puncture, const size_t plth);
411
412 /** Return a soft bit. */
413 float softbit(size_t index) const
414 {
415 const float *dp = mStart+index;
416 assert(dp<mEnd);
417 return *dp;
418 }
419
420 /** Set a soft bit */
421 void settfb(size_t index, float value)
422 {
423 float *dp = mStart+index;
424 assert(dp<mEnd);
425 *dp = value;
426 }
Roman Khassraf059bab92015-05-20 12:49:46 +0200427};
428
429
430
431std::ostream& operator<<(std::ostream&, const SoftVector&);
432
433
434
435
Roman Khassraf059bab92015-05-20 12:49:46 +0200436#endif
437// vim: ts=4 sw=4