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