def QAM_gray_decode(x_hat,M = <NUM_LIT:4>):
<EOL>gray2bin1 = [<NUM_LIT:0>,<NUM_LIT:1>]<EOL>gray2bin2 = [<NUM_LIT:0>,<NUM_LIT:1>,<NUM_LIT:3>,<NUM_LIT:2>]<EOL>gray2bin3 = [<NUM_LIT:0>,<NUM_LIT:1>,<NUM_LIT:3>,<NUM_LIT:2>,<NUM_LIT:6>,<NUM_LIT:7>,<NUM_LIT:5>,<NUM_LIT:4>] <EOL>gray2bin4 = [<NUM_LIT:0>,<NUM_LIT:1>,<NUM_LIT:3>,<NUM_LIT:2>,<NUM_LIT:6>,<NUM_LIT:7>,<NUM_LIT:5>,<NUM_LIT:4>,<NUM_LIT:12>,<NUM_LIT>,<NUM_LIT:15>,<NUM_LIT>,<NUM_LIT:10>,<NUM_LIT:11>,<NUM_LIT:9>,<NUM_LIT:8>]<EOL>x_m = np.sqrt(M)-<NUM_LIT:1><EOL>if M == <NUM_LIT:2>: x_m = <NUM_LIT:1><EOL>N_symb = len(x_hat)<EOL>N_word = int(np.log2(M)/<NUM_LIT:2>)<EOL>x_hat = x_hat/(np.std(x_hat) * np.sqrt(<NUM_LIT:3>/(<NUM_LIT:2>*(M-<NUM_LIT:1>))))<EOL>k_hat_gray = (x_hat + x_m*(<NUM_LIT:1>+<NUM_LIT>))/<NUM_LIT:2><EOL>k_hat_grayI = np.int16(np.clip(np.rint(k_hat_gray.real),<NUM_LIT:0>,x_m))<EOL>k_hat_grayQ = np.int16(np.clip(np.rint(k_hat_gray.imag),<NUM_LIT:0>,x_m))<EOL>data_hat = np.zeros(<NUM_LIT:2>*N_word*N_symb,dtype=int)<EOL>for k in range(N_symb):<EOL><INDENT>if M == <NUM_LIT:2>: <EOL><INDENT>data_hat = k_hat_grayI<EOL><DEDENT>elif M == <NUM_LIT:4>: <EOL><INDENT>data_hat[<NUM_LIT:2>*k*N_word:<NUM_LIT:2>*(k+<NUM_LIT:1>)*N_word]= np.hstack((to_bin(gray2bin1[k_hat_grayI[k]],N_word),<EOL>to_bin(gray2bin1[k_hat_grayQ[k]],N_word)))<EOL><DEDENT>elif M == <NUM_LIT:16>:<EOL><INDENT>data_hat[<NUM_LIT:2>*k*N_word:<NUM_LIT:2>*(k+<NUM_LIT:1>)*N_word]= np.hstack((to_bin(gray2bin2[k_hat_grayI[k]],N_word),<EOL>to_bin(gray2bin2[k_hat_grayQ[k]],N_word)))            <EOL><DEDENT>elif M == <NUM_LIT:64>:<EOL><INDENT>data_hat[<NUM_LIT:2>*k*N_word:<NUM_LIT:2>*(k+<NUM_LIT:1>)*N_word]= np.hstack((to_bin(gray2bin3[k_hat_grayI[k]],N_word),<EOL>to_bin(gray2bin3[k_hat_grayQ[k]],N_word)))            <EOL><DEDENT>elif M == <NUM_LIT>:<EOL><INDENT>data_hat[<NUM_LIT:2>*k*N_word:<NUM_LIT:2>*(k+<NUM_LIT:1>)*N_word]= np.hstack((to_bin(gray2bin4[k_hat_grayI[k]],N_word),<EOL>to_bin(gray2bin4[k_hat_grayQ[k]],N_word)))<EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')  <EOL><DEDENT><DEDENT>return data_hat<EOL>
Decode MQAM IQ symbols to a serial bit stream using
gray2bin decoding

x_hat = symbol spaced samples of the QAM waveform taken at the maximum
        eye opening. Normally this is following the matched filter

Mark Wickert April 2018