GNU Radio Manual and C++ API Reference  v3.9.2.0-89-gb7c7001e
The Free & Open Software Radio Ecosystem
lfsr.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2008,2010,2012 Free Software Foundation, Inc.
4  *
5  * This file is part of GNU Radio
6  *
7  * SPDX-License-Identifier: GPL-3.0-or-later
8  *
9  */
10 
11 #ifndef INCLUDED_DIGITAL_LFSR_H
12 #define INCLUDED_DIGITAL_LFSR_H
13 
14 #include <gnuradio/digital/api.h>
15 #include <stdint.h>
16 #include <cstdint>
17 #include <stdexcept>
18 
19 namespace gr {
20 namespace digital {
21 
22 /*!
23  * \brief Fibonacci Linear Feedback Shift Register using specified
24  * polynomial mask
25  * \ingroup misc
26  *
27  * \details
28  * Generates a maximal length pseudo-random sequence of length
29  * 2^degree-1
30  *
31  * Constructor: digital::lfsr(int mask, int seed, int reg_len);
32  *
33  * \param mask - polynomial coefficients representing the
34  * locations of feedback taps from a shift register
35  * which are xor'ed together to form the new high
36  * order bit.
37  *
38  * Some common masks might be:
39  * x^4 + x^3 + x^0 = 0x19
40  * x^5 + x^3 + x^0 = 0x29
41  * x^6 + x^5 + x^0 = 0x61
42  *
43  * \param seed - the initialization vector placed into the
44  * register during initialization. Low order bit
45  * corresponds to x^0 coefficient -- the first to be
46  * shifted as output.
47  *
48  * \param reg_len - specifies the length of the feedback shift
49  * register to be used. During each iteration, the
50  * register is rightshifted one and the new bit is
51  * placed in bit reg_len. reg_len should generally be
52  * at least order(mask) + 1
53  *
54  *
55  * see http://en.wikipedia.org/wiki/Linear_feedback_shift_register
56  * for more explanation.
57  *
58  * next_bit() - Standard LFSR operation
59  *
60  * Perform one cycle of the LFSR. The output bit is taken from
61  * the shift register LSB. The shift register MSB is assigned from
62  * the modulo 2 sum of the masked shift register.
63  *
64  * next_bit_scramble(unsigned char input) - Scramble an input stream
65  *
66  * Perform one cycle of the LFSR. The output bit is taken from
67  * the shift register LSB. The shift register MSB is assigned from
68  * the modulo 2 sum of the masked shift register and the input LSB.
69  *
70  * next_bit_descramble(unsigned char input) - Descramble an input stream
71  *
72  * Perform one cycle of the LFSR. The output bit is taken from
73  * the modulo 2 sum of the masked shift register and the input LSB.
74  * The shift register MSB is assigned from the LSB of the input.
75  *
76  * See http://en.wikipedia.org/wiki/Scrambler for operation of these
77  * last two functions (see multiplicative scrambler.)
78  */
79 class lfsr
80 {
81 private:
82  uint32_t d_shift_register;
83  uint32_t d_mask;
84  uint32_t d_seed;
85  uint32_t d_shift_register_length; // less than 32
86 
87  static uint32_t popCount(uint32_t x)
88  {
89  uint32_t r = x - ((x >> 1) & 033333333333) - ((x >> 2) & 011111111111);
90  return ((r + (r >> 3)) & 030707070707) % 63;
91  }
92 
93 public:
94  lfsr(uint32_t mask, uint32_t seed, uint32_t reg_len)
95  : d_shift_register(seed),
96  d_mask(mask),
97  d_seed(seed),
98  d_shift_register_length(reg_len)
99  {
100  if (reg_len > 31)
101  throw std::invalid_argument("reg_len must be <= 31");
102  }
103 
104  unsigned char next_bit()
105  {
106  unsigned char output = d_shift_register & 1;
107  unsigned char newbit = popCount(d_shift_register & d_mask) % 2;
108  d_shift_register =
109  ((d_shift_register >> 1) | (newbit << d_shift_register_length));
110  return output;
111  }
112 
113  unsigned char next_bit_scramble(unsigned char input)
114  {
115  unsigned char output = d_shift_register & 1;
116  unsigned char newbit = (popCount(d_shift_register & d_mask) % 2) ^ (input & 1);
117  d_shift_register =
118  ((d_shift_register >> 1) | (newbit << d_shift_register_length));
119  return output;
120  }
121 
122  unsigned char next_bit_descramble(unsigned char input)
123  {
124  unsigned char output = (popCount(d_shift_register & d_mask) % 2) ^ (input & 1);
125  unsigned char newbit = input & 1;
126  d_shift_register =
127  ((d_shift_register >> 1) | (newbit << d_shift_register_length));
128  return output;
129  }
130 
131  /*!
132  * Reset shift register to initial seed value
133  */
134  void reset() { d_shift_register = d_seed; }
135 
136  /*!
137  * Rotate the register through x number of bits
138  * where we are just throwing away the results to get queued up correctly
139  */
140  void pre_shift(int num)
141  {
142  for (int i = 0; i < num; i++) {
143  next_bit();
144  }
145  }
146 
147  int mask() const { return d_mask; }
148 };
149 
150 } /* namespace digital */
151 } /* namespace gr */
152 
153 #endif /* INCLUDED_DIGITAL_LFSR_H */
Fibonacci Linear Feedback Shift Register using specified polynomial mask.
Definition: lfsr.h:80
lfsr(uint32_t mask, uint32_t seed, uint32_t reg_len)
Definition: lfsr.h:94
void pre_shift(int num)
Definition: lfsr.h:140
void reset()
Definition: lfsr.h:134
int mask() const
Definition: lfsr.h:147
unsigned char next_bit_descramble(unsigned char input)
Definition: lfsr.h:122
unsigned char next_bit()
Definition: lfsr.h:104
unsigned char next_bit_scramble(unsigned char input)
Definition: lfsr.h:113
GNU Radio logging wrapper for log4cpp library (C++ port of log4j)
Definition: basic_block.h:29