def MPSK_gray_encode_bb(N_symb,Ns,M=<NUM_LIT:4>,pulse='<STR_LIT>',alpha=<NUM_LIT>,ext_data=None):
<EOL>bin2gray1 = [<NUM_LIT:0>,<NUM_LIT:1>]<EOL>bin2gray2 = [<NUM_LIT:0>,<NUM_LIT:1>,<NUM_LIT:3>,<NUM_LIT:2>]<EOL>bin2gray3 = [<NUM_LIT:0>,<NUM_LIT:1>,<NUM_LIT:3>,<NUM_LIT:2>,<NUM_LIT:7>,<NUM_LIT:6>,<NUM_LIT:4>,<NUM_LIT:5>] <EOL>bin2gray4 = [<NUM_LIT:0>,<NUM_LIT:1>,<NUM_LIT:3>,<NUM_LIT:2>,<NUM_LIT:7>,<NUM_LIT:6>,<NUM_LIT:4>,<NUM_LIT:5>,<NUM_LIT:15>,<NUM_LIT>,<NUM_LIT:12>,<NUM_LIT>,<NUM_LIT:8>,<NUM_LIT:9>,<NUM_LIT:11>,<NUM_LIT:10>]<EOL>bin2gray5 = [<NUM_LIT:0>,<NUM_LIT:1>,<NUM_LIT:3>,<NUM_LIT:2>,<NUM_LIT:7>,<NUM_LIT:6>,<NUM_LIT:4>,<NUM_LIT:5>,<NUM_LIT:15>,<NUM_LIT>,<NUM_LIT:12>,<NUM_LIT>,<NUM_LIT:8>,<NUM_LIT:9>,<NUM_LIT:11>,<NUM_LIT:10>,<NUM_LIT>,<NUM_LIT:30>,<EOL><NUM_LIT>,<NUM_LIT>,<NUM_LIT>,<NUM_LIT>,<NUM_LIT>,<NUM_LIT>,<NUM_LIT:16>,<NUM_LIT>,<NUM_LIT>,<NUM_LIT>,<NUM_LIT>,<NUM_LIT>,<NUM_LIT:20>,<NUM_LIT>]<EOL>N_word = int(np.log2(M))<EOL>if N_symb == None:<EOL><INDENT>N_symb = int(np.floor(len(ext_data)/N_word))<EOL>data = ext_data[:N_symb*N_word]<EOL><DEDENT>else:<EOL><INDENT>data = np.random.randint(<NUM_LIT:0>,<NUM_LIT:2>,size=int(np.log2(M))*N_symb)<EOL><DEDENT>x_IQ = np.zeros(N_symb,dtype=np.complex128)<EOL>bin_wgts = <NUM_LIT:2>**np.arange(N_word-<NUM_LIT:1>,-<NUM_LIT:1>,-<NUM_LIT:1>)<EOL>if M == <NUM_LIT:2>: <EOL><INDENT>x_IQ = <NUM_LIT:2>*data - <NUM_LIT:1><EOL><DEDENT>elif M == <NUM_LIT:4>: <EOL><INDENT>for k in range(N_symb):<EOL><INDENT>word_phase = data[k*N_word:(k+<NUM_LIT:1>)*N_word]<EOL>x_phase = <NUM_LIT:2>*np.pi*bin2gray2[np.dot(word_phase,bin_wgts)]/M + np.pi/M<EOL>x_IQ[k] = np.exp(<NUM_LIT>*x_phase)<EOL><DEDENT><DEDENT>elif M == <NUM_LIT:8>:<EOL><INDENT>for k in range(N_symb):<EOL><INDENT>word_phase = data[k*N_word:(k+<NUM_LIT:1>)*N_word]<EOL>x_phase = <NUM_LIT:2>*np.pi*bin2gray3[np.dot(word_phase,bin_wgts)]/M<EOL>x_IQ[k] = np.exp(<NUM_LIT>*x_phase)<EOL><DEDENT><DEDENT>elif M == <NUM_LIT:16>:<EOL><INDENT>for k in range(N_symb):<EOL><INDENT>word_phase = data[k*N_word:(k+<NUM_LIT:1>)*N_word]<EOL>x_phase = <NUM_LIT:2>*np.pi*bin2gray4[np.dot(word_phase,bin_wgts)]/M<EOL>x_IQ[k] = np.exp(<NUM_LIT>*x_phase)<EOL><DEDENT><DEDENT>elif M == <NUM_LIT:32>:<EOL><INDENT>for k in range(N_symb):<EOL><INDENT>word_phase = data[k*N_word:(k+<NUM_LIT:1>)*N_word]<EOL>x_phase = <NUM_LIT:2>*np.pi*bin2gray5[np.dot(word_phase,bin_wgts)]/M<EOL>x_IQ[k] = np.exp(<NUM_LIT>*x_phase)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')        <EOL><DEDENT>if Ns > <NUM_LIT:1>:<EOL><INDENT>if pulse.lower() == '<STR_LIT:src>':<EOL><INDENT>b = sqrt_rc_imp(Ns,alpha,<NUM_LIT:6>)<EOL><DEDENT>elif pulse.lower() == '<STR_LIT>':<EOL><INDENT>b = rc_imp(Ns,alpha,<NUM_LIT:6>)    <EOL><DEDENT>elif pulse.lower() == '<STR_LIT>':<EOL><INDENT>b = np.ones(int(Ns)) <EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>x = signal.lfilter(b,<NUM_LIT:1>,upsample(x_IQ,Ns))<EOL>b = b/sum(b)<EOL>return x, b, data<EOL><DEDENT>else:<EOL><INDENT>return x_IQ, <NUM_LIT:1>, data<EOL><DEDENT>
MPSK_gray_bb: A gray code mapped MPSK complex baseband transmitter 
x,b,tx_data = MPSK_gray_bb(K,Ns,M)

//////////// Inputs //////////////////////////////////////////////////
  N_symb = the number of symbols to process
      Ns = number of samples per symbol
       M = modulation order: 2, 4, 8, 16 MPSK
   alpha = squareroot raised cosine excess bandwidth factor.
           Can range over 0 < alpha < 1.
   pulse = 'rect', 'src', or 'rc'
//////////// Outputs /////////////////////////////////////////////////
       x = complex baseband digital modulation
       b = transmitter shaping filter, rectangle or SRC
 tx_data = xI+1j*xQ = inphase symbol sequence + 
           1j*quadrature symbol sequence

Mark Wickert November 2018