1f71252c5SXianjun Jiao# 2f71252c5SXianjun Jiao# openwifi side info receive and display program 3f71252c5SXianjun Jiao# Xianjun jiao. [email protected]; [email protected] 4f71252c5SXianjun Jiao# 5f71252c5SXianjun Jiaoimport os 6f71252c5SXianjun Jiaoimport sys 7f71252c5SXianjun Jiaoimport socket 8f71252c5SXianjun Jiaoimport numpy as np 9f71252c5SXianjun Jiaoimport matplotlib.pyplot as plt 10f71252c5SXianjun Jiao 11f71252c5SXianjun Jiaodef display_iq(iq_capture, agc_gain, rssi_half_db): 12f71252c5SXianjun Jiao 13f71252c5SXianjun Jiao fig_iq_capture = plt.figure(0) 14f71252c5SXianjun Jiao fig_iq_capture.clf() 15f71252c5SXianjun Jiao plt.xlabel("sample") 16f71252c5SXianjun Jiao plt.ylabel("I/Q") 17f71252c5SXianjun Jiao plt.title("I (blue) and Q (red) capture") 18f71252c5SXianjun Jiao plt.plot(iq_capture.real, 'b') 19f71252c5SXianjun Jiao plt.plot(iq_capture.imag, 'r') 20f71252c5SXianjun Jiao plt.ylim(-32767, 32767) 219fde3bffSthavinga fig_iq_capture.canvas.flush_events() 22f71252c5SXianjun Jiao 23f71252c5SXianjun Jiao agc_gain_lock = np.copy(agc_gain) 24f71252c5SXianjun Jiao agc_gain_lock[agc_gain>127] = 80 # agc lock 25f71252c5SXianjun Jiao agc_gain_lock[agc_gain<=127] = 0 # agc not lock 26f71252c5SXianjun Jiao 27f71252c5SXianjun Jiao agc_gain_value = np.copy(agc_gain) 28f71252c5SXianjun Jiao agc_gain_value[agc_gain>127] = agc_gain[agc_gain>127] - 128 29f71252c5SXianjun Jiao 30f71252c5SXianjun Jiao fig_agc_gain = plt.figure(1) 31f71252c5SXianjun Jiao fig_agc_gain.clf() 32f71252c5SXianjun Jiao plt.xlabel("sample") 33f71252c5SXianjun Jiao plt.ylabel("gain/lock") 34f71252c5SXianjun Jiao plt.title("AGC gain (blue) and lock status (red)") 35f71252c5SXianjun Jiao plt.plot(agc_gain_value, 'b') 36f71252c5SXianjun Jiao plt.plot(agc_gain_lock, 'r') 37f71252c5SXianjun Jiao plt.ylim(0, 82) 389fde3bffSthavinga fig_agc_gain.canvas.flush_events() 39f71252c5SXianjun Jiao 40f71252c5SXianjun Jiao fig_rssi_half_db = plt.figure(2) 41f71252c5SXianjun Jiao fig_rssi_half_db.clf() 42f71252c5SXianjun Jiao plt.xlabel("sample") 43f71252c5SXianjun Jiao plt.ylabel("dB") 44f71252c5SXianjun Jiao plt.title("RSSI half dB (uncalibrated)") 45f71252c5SXianjun Jiao plt.plot(rssi_half_db) 46f71252c5SXianjun Jiao plt.ylim(100, 270) 479fde3bffSthavinga fig_rssi_half_db.canvas.flush_events() 48f71252c5SXianjun Jiao 49f71252c5SXianjun Jiaodef parse_iq(iq, iq_len): 50f71252c5SXianjun Jiao # print(len(iq), iq_len) 51f71252c5SXianjun Jiao num_dma_symbol_per_trans = 1 + iq_len 52f71252c5SXianjun Jiao num_int16_per_trans = num_dma_symbol_per_trans*4 # 64bit per dma symbol 53f71252c5SXianjun Jiao num_trans = round(len(iq)/num_int16_per_trans) 54f71252c5SXianjun Jiao # print(len(iq), iq.dtype, num_trans) 55f71252c5SXianjun Jiao iq = iq.reshape([num_trans, num_int16_per_trans]) 56f71252c5SXianjun Jiao 57f71252c5SXianjun Jiao timestamp = iq[:,0] + pow(2,16)*iq[:,1] + pow(2,32)*iq[:,2] + pow(2,48)*iq[:,3] 58*e556af35SXianjun Jiao iq_capture = np.int16(iq[:,4::4]) + np.int16(iq[:,5::4])*1j 59f71252c5SXianjun Jiao agc_gain = iq[:,6::4] 60f71252c5SXianjun Jiao rssi_half_db = iq[:,7::4] 61f71252c5SXianjun Jiao # print(num_trans, iq_len, iq_capture.shape, agc_gain.shape, rssi_half_db.shape) 62f71252c5SXianjun Jiao 63f71252c5SXianjun Jiao iq_capture = iq_capture.reshape([num_trans*iq_len,]) 64f71252c5SXianjun Jiao agc_gain = agc_gain.reshape([num_trans*iq_len,]) 65f71252c5SXianjun Jiao rssi_half_db = rssi_half_db.reshape([num_trans*iq_len,]) 66f71252c5SXianjun Jiao 67f71252c5SXianjun Jiao return timestamp, iq_capture, agc_gain, rssi_half_db 68f71252c5SXianjun Jiao 69f71252c5SXianjun JiaoUDP_IP = "192.168.10.1" #Local IP to listen 70f71252c5SXianjun JiaoUDP_PORT = 4000 #Local port to listen 71f71252c5SXianjun Jiao 72f71252c5SXianjun Jiaosock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP 73f71252c5SXianjun Jiaosock.bind((UDP_IP, UDP_PORT)) 74a4eb2001SXianjun Jiaosock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 464) # for low latency. 464 is the minimum udp length in our case (CSI only) 75f71252c5SXianjun Jiao 76f71252c5SXianjun Jiao# align with side_ch_control.v and all related user space, remote files 77f71252c5SXianjun JiaoMAX_NUM_DMA_SYMBOL = 8192 78f71252c5SXianjun Jiao 79f71252c5SXianjun Jiaoif len(sys.argv)<2: 80f71252c5SXianjun Jiao print("Assume iq_len = 8187! (Max UDP 65507 bytes; (65507/8)-1 = 8187)") 81f71252c5SXianjun Jiao iq_len = 8187 82f71252c5SXianjun Jiaoelse: 83f71252c5SXianjun Jiao iq_len = int(sys.argv[1]) 84f71252c5SXianjun Jiao print(iq_len) 85f71252c5SXianjun Jiao # print(type(num_eq)) 86f71252c5SXianjun Jiao 87f71252c5SXianjun Jiaoif iq_len>8187: 88f71252c5SXianjun Jiao iq_len = 8187 89f71252c5SXianjun Jiao print('Limit iq_len to 8187! (Max UDP 65507 bytes; (65507/8)-1 = 8187)') 90f71252c5SXianjun Jiao 91f71252c5SXianjun Jiaonum_dma_symbol_per_trans = 1 + iq_len 92f71252c5SXianjun Jiaonum_byte_per_trans = 8*num_dma_symbol_per_trans 93f71252c5SXianjun Jiao 94f71252c5SXianjun Jiaoif os.path.exists("iq.txt"): 95f71252c5SXianjun Jiao os.remove("iq.txt") 96f71252c5SXianjun Jiaoiq_fd=open('iq.txt','a') 97f71252c5SXianjun Jiao 989fde3bffSthavingaplt.ion() 999fde3bffSthavinga 100f71252c5SXianjun Jiaowhile True: 101f71252c5SXianjun Jiao try: 102f71252c5SXianjun Jiao data, addr = sock.recvfrom(MAX_NUM_DMA_SYMBOL*8) # buffer size 103f71252c5SXianjun Jiao # print(addr) 104f71252c5SXianjun Jiao test_residual = len(data)%num_byte_per_trans 105f71252c5SXianjun Jiao # print(len(data)/8, num_dma_symbol_per_trans, test_residual) 106f71252c5SXianjun Jiao if (test_residual != 0): 107f71252c5SXianjun Jiao print("Abnormal length") 108f71252c5SXianjun Jiao 109*e556af35SXianjun Jiao iq = np.frombuffer(data, dtype='uint16') 110f71252c5SXianjun Jiao np.savetxt(iq_fd, iq) 111f71252c5SXianjun Jiao 112f71252c5SXianjun Jiao timestamp, iq_capture, agc_gain, rssi_half_db = parse_iq(iq, iq_len) 113f71252c5SXianjun Jiao print(timestamp) 114f71252c5SXianjun Jiao display_iq(iq_capture, agc_gain, rssi_half_db) 115f71252c5SXianjun Jiao 116f71252c5SXianjun Jiao except KeyboardInterrupt: 117f71252c5SXianjun Jiao print('User quit') 118f71252c5SXianjun Jiao break 119f71252c5SXianjun Jiao 120f71252c5SXianjun Jiaoprint('close()') 1219fde3bffSthavingaiq_fd.close() 122f71252c5SXianjun Jiaosock.close() 123