import numpy as np defqam_constellation(M,normalize=False): """ M must be 2^k ,where k is an even integer gray mapping param: - M: the size of qam set - normalize: normalize the average energy qam symbols unit return: 1-D numpy array """ assert np.log2(M).is_integer() m = int(np.sqrt(M)) x = np.zeros(m,np.int32) # gray mapping binding to natural number y = np.zeros(m,np.int32) # mappping natural number to gray code in octal natural2gray = lambda x: x ^ (x >> 1) x[natural2gray(np.arange(0, m))] = np.arange(0, 2*m,2) -m+1 y[natural2gray(np.arange(0, m))] = np.arange(0, 2*m,2) -m+1
constellation = np.zeros((m, m), dtype=np.cfloat) for i inrange(m): for j inrange(m): constellation[i][j] = (x[i]+1j* y[j]) if normalize: return constellation.flatten()/(np.linalg.norm(constellation)/m) else: return constellation.flatten()
defpsk_constellation(M): """ gray mapping param: - M: the size of psk set - normalize: normalize the average energy qam symbols unit return: 1-D numpy array """ phase = np.arange(0, M) * 2 * np.pi / M constellation = np.zeros(M, dtype=np.cfloat) natural2gray = lambda x: x ^ (x >> 1) constellation[natural2gray(np.arange(0, M))] = np.exp(1j * phase) return constellation
defmapping(data, constellation): """ param: - data: binary data in 1-D numpy array - constellation: 1-D numpy array return: 1-D numpy array """ M = len(constellation) assert np.log2(M).is_integer() assertlen(data) % np.log2(M) == 0 data = data.reshape(-1, int(np.log2(M))) mask = np.array([2**i for i inrange(int(np.log2(M))-1, -1, -1)]) # [8,4,2,1] index = np.sum(data * mask, axis=1) # left first return constellation[index]