1 /*+============================================================================
  2 |
  3 | LEGAL
  4 |
  5 |     PN Version 1.0 - A Program for generating pseudonoise sequences.
  6 |     Copyright (C) 1986-2024 by Sean Erik O'Connor.  All Rights Reserved.
  7 |
  8 |     This program is free software: you can redistribute it and/or modify
  9 |     it under the terms of the GNU General Public License as published by
 10 |     the Free Software Foundation, either version 3 of the License, or
 11 |     (at your option) any later version.
 12 |
 13 |     This program is distributed in the hope that it will be useful,
 14 |     but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16 |     GNU General Public License for more details.
 17 |
 18 |     You should have received a copy of the GNU General Public License
 19 |     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 20 |     
 21 |     The author's address is seanerikoconnor!AT!gmail!DOT!com
 22 |     with !DOT! replaced by . and the !AT! replaced by @
 23 |
 24 +============================================================================*/
 25 
 26 #include <stdio.h>
 27 
 28 char * legalNotice =
 29 {
 30     "\n"
 31     "PN Version 1.0 - A Program for generating pseudonoise sequences.\n"
 32     "Copyright (C) 1986-2024 by Sean Erik O'Connor.  All Rights Reserved.\n"
 33     "\n"
 34     "PN comes with ABSOLUTELY NO WARRANTY; for details see the\n"
 35     "GNU General Public License.  This is free software, and you are welcome\n"
 36     "to redistribute it under certain conditions; see the GNU General Public License\n"
 37     "for details.\n\n"
 38 }  ;
 39 
 40 int pn( void ) ;
 41 
 42 /* Print out values of a sample binary PN sequence. */
 43 
 44 int main( int argc, char * argv[] )
 45 {
 46     int i ;
 47 
 48     /*  Show the legal notice first.  */
 49     printf(  "%s", legalNotice )  ;
 50 
 51     /* Print out PN sequence values. */
 52     for (i = 1 ;  i <= 15 ;  ++i)
 53     {
 54         printf( "pn %3d = %3d\n", i, pn() ) ;
 55     }
 56 
 57     return 0 ;
 58 }
 59 
 60 
 61 /* Compute the bits of a binary PN sequence. */
 62 
 63 int pn( void )
 64 {
 65     static unsigned int shiftRegister = 1 ;   /* Initial state of shift register, */
 66                                               /* a  = 1, a  = ... = a  = 0        */
 67                                               /*  0       1          3            */
 68 
 69     unsigned int m        = 4 ;               /* Period of PN sequence = 2^m - 1 = 15   */
 70 
 71     unsigned int primPoly = 0x13 ;            /* Primitive polynomial coefficients,     */
 72                                               /* x^4 + x + 1 = 10011 (binary) = 13 hex  */
 73 
 74     unsigned int mask     = (1 << (m-1)) ;    /* Selects the mth bit.                   */
 75 
 76     unsigned int multiplier =
 77                  (primPoly ^ (1 << m)) ;      /* Feedback multiplier, corresponding to   */
 78                                               /* the taps f ... f on the shift register, */
 79                                               /*           3     0                       */
 80                                               /* equal to the primitive polynomial       */
 81                                               /* coefficients with highest degree term   */
 82                                               /* omitted.                                */
 83 
 84     unsigned int feedback ; /* Feedback bit.                  */
 85     unsigned int bit ;      /* Bit 0 or 1 of the PN sequence. */
 86     unsigned int product ;  /* Bitwise product.               */
 87     unsigned int i ;
 88 
 89     product = shiftRegister & multiplier ;   /* Modulo 2 multiplication of feedback */
 90                                              /* taps times shift register contents  */
 91                                              /* in parallel.                        */
 92 
 93     /* Sum up the product bits modulo 2 to get the feedback bit. */
 94     for (i = 1, feedback = 0 ;  i <= m ;  ++i)
 95     {
 96         feedback ^= (1 & product) ;         /* Add first bit of the product into  */
 97                                             /* the running sum of the feedback.   */
 98 
 99         product >>= 1 ;                     /* Shift to expose next bit of the product. */
100     }
101 
102     bit = shiftRegister & 1 ;               /* Save the zeroth (PN sequence) bit of */
103                                             /* of the shift register.               */
104 
105     shiftRegister >>= 1 ;                   /* Shift the shift register contents.   */
106 
107     if (feedback)                           /* Add feedback (if any) to the shift register */
108     {                                       /* contents.                                   */
109         shiftRegister ^= mask ;
110     }
111 
112     return( bit ) ;                         /* Return the PN sequence bit. */
113 }