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