Parcourir la source

update wave loader in SDR service

Vyacheslav V il y a 6 jours
Parent
commit
108882cdc0
5 fichiers modifiés avec 146 ajouts et 66 suppressions
  1. 30 8
      sdr-tcp/client-gui.py
  2. 13 0
      sdr-tcp/events.json
  3. 66 58
      sdr-tcp/server-simulator.py
  4. BIN
      sdr-tcp/sinc_wave.bin
  5. 37 0
      sdr-tcp/wavegen.py

+ 30 - 8
sdr-tcp/client-gui.py

@@ -100,11 +100,11 @@ class SDRClient(QMainWindow):
         except Exception as e:
             print(f"Failed to connect to server: {e}")
             QMessageBox.critical(self, "Connection Error", f"Failed to connect to server: {e}")
-            self.sock = None
 
     def disconnect_from_server(self):
         if self.sock:
             self.sock.close()
+            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
             QMessageBox.information(self, "Disconnected", "Successfully disconnected from SDR server")
             print("Disconnected from SDR server")
 
@@ -116,7 +116,7 @@ class SDRClient(QMainWindow):
         add_event_dialog.setWindowTitle("Add Event")
         layout = QFormLayout()
 
-        labels = ["Start Time (ticks)", "Duration (ticks)", "Waveform Type", "time_front_rf_ttl (ticks)", "time_back_rf_ttl (ticks)", "time_front_adc_ttl (ticks)", "time_back_adc_ttl (ticks)", "time_start_rf (ticks)", "time_end_rf (ticks)", "rf_freq (Hz)"]
+        labels = ["Start Time (ticks)", "Duration (ticks)", "Waveform Type", "time_front_rf_ttl (ticks)", "time_back_rf_ttl (ticks)", "time_front_adc_ttl (ticks)", "time_back_adc_ttl (ticks)", "time_start_rf (ticks)", "time_end_rf (ticks)", "rf_freq (Hz)", "phase_offset"]
         self.event_inputs = {}
         for label in labels:
             if label == "Waveform Type":
@@ -155,7 +155,8 @@ class SDRClient(QMainWindow):
                 "time_back_adc_trigger": int(self.event_inputs["time_back_adc_ttl (ticks)"].text()),
                 "rf_start": int(self.event_inputs["time_start_rf (ticks)"].text()),
                 "rf_end": int(self.event_inputs["time_end_rf (ticks)"].text()),
-                "carrier_freq": float(self.event_inputs["rf_freq (Hz)"].text())
+                "carrier_freq": float(self.event_inputs["rf_freq (Hz)"].text()),
+                "phase_offset": int(self.event_inputs["phase_offset"].text())
             }
             msg = msgpack.packb(msg, use_bin_type=True)
             self.sock.sendall(msg)
@@ -192,7 +193,8 @@ class SDRClient(QMainWindow):
                         "time_back_adc_trigger": event_data["time_back_adc_trigger"],
                         "rf_start": event_data["rf_start"],
                         "rf_end": event_data["rf_end"],
-                        "carrier_freq": event_data["carrier_freq"]
+                        "carrier_freq": event_data["carrier_freq"],
+                        "phase_offser": event_data["phase_offset"]
                     }
                     packed_msg = msgpack.packb(msg, use_bin_type=True)
                     self.sock.sendall(packed_msg)
@@ -204,7 +206,6 @@ class SDRClient(QMainWindow):
                         raise Exception(f"Server error: {unpacked_resp['message']}")
                 print("Event list loaded successfully")
                 QMessageBox.information(self, "Success", "Event list loaded successfully")
-                self.add_event_dialog.close()
             except Exception as e:
                 print(f"Failed to load event list: {e}")
                 QMessageBox.critical(self, "Error", f"Failed to load event list: {e}")
@@ -249,14 +250,22 @@ class SDRClient(QMainWindow):
             "magic": 0xAA,
             "cmd": 0x20,
             "wavetype": name,
+            "packet_length": 512,  # Define packet length for sending waveform data
             "total_length": 0,  # Placeholder, will be updated after loading the waveform data
             "total_packets": 0,  # Placeholder, will be updated after loading the waveform data
         }
 
+        data = b''
         with open(file_path, 'rb') as f:
             # Load rows point from .bin file (first 2 bytes is Q-point, next 2 bytes is I-point)
-            total_wavedata_q = np.fromfile(f, dtype=np.int16, count=-1, offset=0)
-            total_wavedata_i = np.fromfile(f, dtype=np.int16, count=-1, offset=2)
+            data = f.read()
+
+        total_wavedata_q = np.array([], dtype=np.int16)
+        total_wavedata_i = np.array([], dtype=np.int16)
+        for i in range(len(data) // 4):
+            total_wavedata_q = np.append(total_wavedata_q, np.frombuffer(data, dtype=np.int16, count=1, offset=4*i))
+            total_wavedata_i = np.append(total_wavedata_i, np.frombuffer(data, dtype=np.int16, count=1, offset=4*i+2))
+
         if len(total_wavedata_q) != len(total_wavedata_i):
             QMessageBox.warning(self, "Input Error", "In-phase and quadrature wave data must have the same length")
             return
@@ -280,8 +289,10 @@ class SDRClient(QMainWindow):
             QMessageBox.critical(self, "Error", f"Failed to send waveform header: {e}")
             return
         
+        print(f"Total packets to send: {header_msg["total_packets"]}")
         try:
             for i in range(header_msg["total_packets"]):
+                print(f"Sending packet {i}")
                 packet_length = min(512, len(total_wavedata_q) - i * 512)
                 start_idx = i * 512
                 end_idx = min((i + 1) * 512, len(total_wavedata_q))
@@ -303,12 +314,16 @@ class SDRClient(QMainWindow):
                 if resp["cmd"] != 0xFE or resp["code"] != 0x00000002:
                     raise Exception(f"Server error: {resp['message']}")
                 self.sock.sendall(b"ACK") # Send ACK to server to indicate ready for next packet
+                print(f"Packet {i} sended!")
+            print("All packets sent!")
             raw_resp = self.sock.recv(4096)
             if not raw_resp:
                 raise Exception("No response from server after sending all packets")
             resp = msgpack.unpackb(raw_resp, raw=False)
             if resp["cmd"] != 0xFE or resp["code"] != 0x00000003:
                 raise Exception(f"Server error after sending all packets: {resp['message']}")
+            self.sock.sendall(b'ACK')
+            print("All packets sent!")
         except Exception as e:
             print(f"Failed to send waveform data: {e}")
             QMessageBox.critical(self, "Error", f"Failed to send waveform data: {e}")
@@ -323,7 +338,7 @@ class SDRClient(QMainWindow):
         msg = {
             "magic": 0xAA,
             "cmd": 0x30,
-            "interpolation_method": "linear"  # Placeholder, can be extended to allow user selection of interpolation method
+            "interpolation_method": "cubic"  # Placeholder, can be extended to allow user selection of interpolation method
         }
         try:
             packed_msg = msgpack.packb(msg, use_bin_type=True)
@@ -383,6 +398,13 @@ class SDRClient(QMainWindow):
         self.plot_canvas.draw()
 
     def receive_sim_data(self):
+        self.channel_data = {
+            'time': np.array([], dtype=np.int64),
+            'channel_g': np.array([], dtype=np.int16),
+            'channel_rf': np.array([], dtype=np.int16),
+            'channel_adc_ttl': np.array([], dtype=np.int16),
+            'channel_rf_ttl': np.array([], dtype=np.int16)
+        }
         msg = {
             "magic": 0xAA,
             "cmd": 0x40

+ 13 - 0
sdr-tcp/events.json

@@ -0,0 +1,13 @@
+[{
+    "time": 1000,
+    "duration": 50000,
+    "wave": "sinc",
+    "time_front_rf_trigger": 40000,
+    "time_back_rf_trigger": 1000,
+    "time_front_adc_trigger": 40000,
+    "time_back_adc_trigger": 1000,
+    "rf_start": 2000,
+    "rf_end": 39000,
+    "carrier_freq": 3000000,
+    "phase_offset": 0
+}]

+ 66 - 58
sdr-tcp/server-simulator.py

@@ -3,6 +3,7 @@ import scipy.interpolate as interp
 import msgpack
 import json
 import socket
+import time as tm
 
 class ServerSimulator:
     def __init__(self):
@@ -71,29 +72,33 @@ class ServerSimulator:
 
 
     def acceptCommand(self):
-        rawdata = self.conn.recv(4096)
-        
-        # Check if data is received
-        if not rawdata:
-            return False
-        
-        # Unpack data using msgpack
-        self.data = msgpack.unpackb(rawdata, raw=False)
-        if self.data["magic"] != self.magic:
-            print("Invalid magic byte")
-            self.errCode = 0x00000051 # Invalid magic byte
-            self.conn.sendall(self.getErrorMsg(self.errCode, "Invalid magic byte"))
-            return False
-        if self.data["cmd"] not in self.cmd_dict.keys():
-            print("Invalid command")
-            self.errCode = 0x00000052 # Invalid command
-            self.conn.sendall(self.getErrorMsg(self.errCode, "Invalid command"))
-            return False
-        print(f"Received command: {self.data['cmd']}")
+        try:
+            rawdata = self.conn.recv(4096)
+            
+            # Check if data is received
+            if not rawdata:
+                return 2
+            
+            # Unpack data using msgpack
+            self.data = msgpack.unpackb(rawdata, raw=False)
+            if self.data["magic"] != self.magic:
+                print("Invalid magic byte")
+                self.errCode = 0x00000051 # Invalid magic byte
+                self.conn.sendall(self.getErrorMsg(self.errCode, "Invalid magic byte"))
+                return 2
+            if self.data["cmd"] not in self.cmd_dict.keys():
+                print("Invalid command")
+                self.errCode = 0x00000052 # Invalid command
+                self.conn.sendall(self.getErrorMsg(self.errCode, "Invalid command"))
+                return 2
+            print(f"Received command: {self.data['cmd']}")
 
-        # Process command
-        self.cmd = self.data["cmd"]
-        self.cmd_dict[self.cmd](self.data)
+            # Process command
+            self.cmd = self.data["cmd"]
+            self.cmd_dict[self.cmd](self.data)
+        except Exception as e:
+            print(f"Exception: {e}")
+            return False
 
         return True
 
@@ -102,7 +107,7 @@ class ServerSimulator:
             print("Missing event parameters")
             self.errCode = 0x00000001 # Missing parameters
             self.conn.sendall(self.getErrorMsg(self.errCode, "Missing event parameters"))
-            return False
+            return 2
         
         event = {
             "start_time": data["time"],
@@ -115,63 +120,64 @@ class ServerSimulator:
             "rf_end": data["rf_end"],
             "time_front_adc_trigger": data["time_front_adc_trigger"],
             "time_back_adc_trigger": data["time_back_adc_trigger"],
+            "phase_offset": data["phase_offset"]
         }
 
         if event["start_time"] < self.time:
             print("Event start time is in the past")
             self.errCode = 0x00000002 # Event in the past
             self.conn.sendall(self.getErrorMsg(self.errCode, "Event start time is in the past"))
-            return False
+            return 2
         if event["time_front_rf_trigger"] < 0 or event["time_back_rf_trigger"] < 0 or event["rf_start"] < 0 or event["rf_end"] < 0:
             print("RF trigger times and delays must be non-negative")
             self.errCode = 0x00000003 # Negative times
             self.conn.sendall(self.getErrorMsg(self.errCode, "RF trigger times and delays must be non-negative"))
-            return False
+            return 2
         if event["time_front_adc_trigger"] < 0 or event["time_back_adc_trigger"] < 0:
             print("ADC trigger times must be non-negative")
             self.errCode = 0x00000004 # Negative times
             self.conn.sendall(self.getErrorMsg(self.errCode, "ADC trigger times must be non-negative"))
-            return False
+            return 2
         if event["time_front_rf_trigger"] > event["duration"] or event["time_back_rf_trigger"] > event["duration"]:
             print("RF trigger times must be within event duration")
             self.errCode = 0x00000005 # RF trigger times out of bounds
             self.conn.sendall(self.getErrorMsg(self.errCode, "RF trigger times must be within event duration"))
-            return False
+            return 2
         if event["rf_start"] > event["duration"] or event["rf_end"] > event["duration"]:
             print("RF start and end times must be within event duration")
             self.errCode = 0x00000006 # RF start/end times out of bounds
             self.conn.sendall(self.getErrorMsg(self.errCode, "RF start and end times must be within event duration"))
-            return False
+            return 2
         if event["time_front_adc_trigger"] > event["duration"] or event["time_back_adc_trigger"] > event["duration"]:
             print("ADC trigger times must be within event duration")
             self.errCode = 0x00000007 # ADC trigger times out of bounds
             self.conn.sendall(self.getErrorMsg(self.errCode, "ADC trigger times must be within event duration"))
-            return False
+            return 2
         if event["time_front_rf_trigger"] < event["time_back_rf_trigger"]:
             print("RF triggers and delays overlap")
             self.errCode = 0x00000008 # RF triggers overlap
             self.conn.sendall(self.getErrorMsg(self.errCode, "RF triggers and delays overlap"))
-            return False
+            return 2
         if event["time_front_adc_trigger"] < event["time_back_adc_trigger"]:
             print("ADC triggers overlap")
             self.errCode = 0x00000009 # ADC triggers overlap
             self.conn.sendall(self.getErrorMsg(self.errCode, "ADC triggers overlap"))
-            return False
+            return 2
         if event["rf_start"] > event["rf_end"]:
             print("RF start and end times overlap")
             self.errCode = 0x0000000A # RF start/end times overlap
             self.conn.sendall(self.getErrorMsg(self.errCode, "RF start and end times overlap"))
-            return False
+            return 2
         if event["rf_start"] < event["time_back_rf_trigger"] or event["rf_end"] > event["time_front_rf_trigger"]:
             print("RF start and end times must be within RF trigger times")
             self.errCode = 0x0000000B # RF start/end times outside triggers
             self.conn.sendall(self.getErrorMsg(self.errCode, "RF start and end times must be within RF trigger times"))
-            return False
+            return 2
         if event["rf_end"] - event["rf_start"] < len(self.rfwaves[event["wave"]]):
             print("RF pulse duration must be at least as long as the wave length")
             self.errCode = 0x0000000C # Insufficient RF pulse duration
             self.conn.sendall(self.getErrorMsg(self.errCode, "RF pulse duration must be at least as long as the wave length"))
-            return False
+            return 2
         self.events.append(event)
         self.time = event["start_time"] + event["duration"]
         print(f"Added event: {event}")
@@ -179,11 +185,11 @@ class ServerSimulator:
         return True
 
     def getRfwaveTable(self, data):
-        if not all (k in data for k in ("wavetype", "total_length", "total_packets", "packet_index", "packet_length")):
+        if not all (k in data for k in ("wavetype", "total_length", "total_packets", "packet_length")):
             print("Missing RF wave parameters")
             self.errCode = 0x0000000F # Missing parameters
             self.conn.sendall(self.getErrorMsg(self.errCode, "Missing RF wave parameters"))
-            return False
+            return 2
         wavetype = data["wavetype"]
         total_length = data["total_length"]
         total_packets = data["total_packets"]
@@ -194,27 +200,28 @@ class ServerSimulator:
         self.conn.sendall(self.getStatusMsg(0x00000001, f"Ready to receive RF wave data packets"))
 
         for i in range(total_packets):
-            rawdata = self.sock.recv(4096)
+            print(f"Send packet {i}...")
+            rawdata = self.conn.recv(4096)
             if not rawdata:
                 print("No data received for RF wave packet")
-                return False
+                return 2
             
             packet_data = msgpack.unpackb(rawdata, raw=False)
             if packet_data["magic"] != self.magic:
                 print("Invalid magic byte in RF wave packet")
                 self.errCode = 0x00000014 # Invalid magic byte
                 self.conn.sendall(self.getErrorMsg(self.errCode, "Invalid magic byte in RF wave packet"))
-                return False
+                return 2
             if packet_data["cmd"] != 0x2C:
                 print("Invalid command in RF wave packet")
                 self.errCode = 0x00000013 # Invalid command
                 self.conn.sendall(self.getErrorMsg(self.errCode, "Invalid command in RF wave packet"))
-                return False
+                return 2
             if "wavedata_q" not in packet_data or "wavedata_i" not in packet_data:
                 print("Missing wave data in RF wave packet")
                 self.errCode = 0x00000010 # Missing wave data
                 self.conn.sendall(self.getErrorMsg(self.errCode, "Missing wave data in RF wave packet"))
-                return False
+                return 2
             
             wave_q = np.frombuffer(packet_data["wavedata_q"], dtype=np.int16)
             wave_i = np.frombuffer(packet_data["wavedata_i"], dtype=np.int16)
@@ -223,23 +230,24 @@ class ServerSimulator:
                 print("In-phase and quadrature wave data must have the same length in RF wave packet")
                 self.errCode = 0x00000012 # Mismatched wave data lengths
                 self.conn.sendall(self.getErrorMsg(self.errCode, "In-phase and quadrature wave data must have the same length in RF wave packet"))
-                return False
+                return 2
             total_wave_q = np.concatenate([total_wave_q, wave_q])
             total_wave_i = np.concatenate([total_wave_i, wave_i])
 
             print(f"Received RF wave packet {i+1}/{total_packets} with length {len(wave_q)}")
             self.conn.sendall(self.getStatusMsg(0x00000002, f"Received RF wave packet {i+1}/{total_packets} with length {len(wave_q)}"))
             self.conn.recv(1024) # Wait for ACK before receiving next packet
-            return True
+            print("ACK recieved!")
 
         if len(total_wave_q) != total_length or len(total_wave_i) != total_length:
             print("Total wave data length does not match expected length")
             self.errCode = 0x00000011 # Total length mismatch
             self.conn.sendall(self.getErrorMsg(self.errCode, "Total wave data length does not match expected length"))
-            return False
-        self.rfwaves.append({data["wavetype"]: (total_wave_q, total_wave_i)})
+            return 2
+        self.rfwaves[data["wavetype"]] = (total_wave_q, total_wave_i)
         print(f"RF wave '{wavetype}' received successfully with total length {total_length}")
         self.conn.sendall(self.getStatusMsg(0x00000003, f"RF wave '{wavetype}' received successfully with total length {total_length}"))
+        self.conn.recv(1024)
         return True
     
     def runEventList(self, data):
@@ -281,20 +289,20 @@ class ServerSimulator:
             interp_wave_q = np.zeros(rf_pulse_length, dtype=np.int16)
             interp_wave_i = np.zeros(rf_pulse_length, dtype=np.int16)
             if data["interpolation_method"] == "linear":
-                interp_func_q = interp.interp1d(np.linspace(0, rf_wave_length, rf_wave_length), rf_wave_q, kind='linear', fill_value="extrapolate")
-                interp_func_i = interp.interp1d(np.linspace(0, rf_wave_length, rf_wave_length), rf_wave_i, kind='linear', fill_value="extrapolate")
-                interp_wave_q = interp_func_q(rf_time).astype(np.int16)
-                interp_wave_i = interp_func_i(rf_time).astype(np.int16)
+                interp_func_q = interp.interp1d(np.linspace(0, rf_wave_length, rf_wave_length), rf_wave_q, kind='linear')
+                interp_func_i = interp.interp1d(np.linspace(0, rf_wave_length, rf_wave_length), rf_wave_i, kind='linear')
+                interp_wave_q = interp_func_q(rf_time * (rf_wave_length / rf_pulse_length)).astype(np.int16)
+                interp_wave_i = interp_func_i(rf_time * (rf_wave_length / rf_pulse_length)).astype(np.int16)
             elif data["interpolation_method"] == "nearest":
-                interp_func_q = interp.interp1d(np.linspace(0, rf_wave_length, rf_wave_length), rf_wave_q, kind='nearest', fill_value="extrapolate")
-                interp_func_i = interp.interp1d(np.linspace(0, rf_wave_length, rf_wave_length), rf_wave_i, kind='nearest', fill_value="extrapolate")
-                interp_wave_q = interp_func_q(rf_time).astype(np.int16)
-                interp_wave_i = interp_func_i(rf_time).astype(np.int16)
+                interp_func_q = interp.interp1d(np.linspace(0, rf_wave_length, rf_wave_length), rf_wave_q, kind='nearest')
+                interp_func_i = interp.interp1d(np.linspace(0, rf_wave_length, rf_wave_length), rf_wave_i, kind='nearest')
+                interp_wave_q = interp_func_q(rf_time * (rf_wave_length / rf_pulse_length)).astype(np.int16)
+                interp_wave_i = interp_func_i(rf_time * (rf_wave_length / rf_pulse_length)).astype(np.int16)
             elif data["interpolation_method"] == "cubic":
-                interp_func_q = interp.interp1d(np.linspace(0, rf_wave_length, rf_wave_length), rf_wave_q, kind='cubic', fill_value="extrapolate")
-                interp_func_i = interp.interp1d(np.linspace(0, rf_wave_length, rf_wave_length), rf_wave_i, kind='cubic', fill_value="extrapolate")
-                interp_wave_q = interp_func_q(rf_time).astype(np.int16)
-                interp_wave_i = interp_func_i(rf_time).astype(np.int16)
+                interp_func_q = interp.interp1d(np.linspace(0, rf_wave_length, rf_wave_length), rf_wave_q, kind='cubic')
+                interp_func_i = interp.interp1d(np.linspace(0, rf_wave_length, rf_wave_length), rf_wave_i, kind='cubic')
+                interp_wave_q = interp_func_q(rf_time * (rf_wave_length / rf_pulse_length)).astype(np.int16)
+                interp_wave_i = interp_func_i(rf_time * (rf_wave_length / rf_pulse_length)).astype(np.int16)
 
             channel_rf[event["start_time"]+event["rf_start"]:event["start_time"]+event["rf_end"]+1] = np.floor((interp_wave_q * np.sin(2 * np.pi * event["carrier_freq"] * rf_time * 8e-9) - interp_wave_i * np.cos(2 * np.pi * event["carrier_freq"] * rf_time * 8e-9)) / np.sqrt(2)).astype(np.int16)
             channel_rf_ttl[event["start_time"]+event["time_back_rf_trigger"]:event["start_time"]+event["time_front_rf_trigger"]+1] = np.int16(1 * np.floor(3.3 / 5 * 32767))
@@ -354,7 +362,7 @@ class ServerSimulator:
             print("Missing frequency parameter")
             self.errCode = 0x00000020 # Missing parameter
             self.conn.sendall(self.getErrorMsg(self.errCode, "Missing frequency parameter"))
-            return False
+            return 2
         self.freq = data["frequency"]
         self.conn.sendall(self.getStatusMsg(0x00000071, f"Frequency set to {self.freq} Hz"))
         return True

BIN
sdr-tcp/sinc_wave.bin


+ 37 - 0
sdr-tcp/wavegen.py

@@ -0,0 +1,37 @@
+import numpy as np
+import matplotlib.pyplot as plt
+
+def main():
+    # Parameters
+    samples = 512
+    x = np.linspace(-2, 2, samples)
+    # Generate a sinc wave
+    sinc_wave = np.sinc(x)
+    # Normalize to 16-bit range
+    sinc_wave = sinc_wave / np.max(np.abs(sinc_wave)) * 32767
+    imaginary_part = np.zeros(samples)
+    # Save to a file
+    with open('sinc_wave.bin', 'wb') as f:
+        for i in range(samples):
+            f.write(np.int16(sinc_wave[i]).tobytes())
+            f.write(np.int16(imaginary_part[i]).tobytes())
+
+    data = b''
+    with open('sinc_wave.bin', 'rb') as f:
+        data = f.read()
+    
+    print(len(data))
+    wave_q = np.array([], dtype=np.int16)
+    wave_i = np.array([], dtype=np.int16)
+
+    for i in range(len(data) // 4):
+        wave_q = np.append(wave_q, np.frombuffer(data, dtype=np.int16, count=1, offset=4*i))
+        wave_i = np.append(wave_i, np.frombuffer(data, dtype=np.int16, count=1, offset=4*i+2))
+
+    plt.plot(x, wave_q)
+    plt.plot(x, wave_i)
+    plt.show()
+
+if __name__ == "__main__":
+    main()
+