xref: /openwifi/user_space/side_ch_ctl_src/iq_capture.py (revision e556af35c696ecef552192823e107caf37eb6af9)
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