|
|
@@ -7,10 +7,12 @@ import socket
|
|
|
class ServerSimulator:
|
|
|
def __init__(self):
|
|
|
self.events = []
|
|
|
- self.rfwaves = []
|
|
|
+ self.rfwaves = {"default": (np.ones(512, dtype=np.int16) * np.floor(3.3 / 5 * 32767), np.zeros(512, dtype=np.int16))} # Default RF wave is a 100-sample pulse at max amplitude
|
|
|
self.time = 0
|
|
|
#Socket parameters
|
|
|
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
|
+ self.sock.bind(('127.0.0.1', 5003))
|
|
|
+ self.sock.listen()
|
|
|
self.conn = 0
|
|
|
self.magic = 0xAA
|
|
|
self.cmd = 0x00
|
|
|
@@ -18,6 +20,13 @@ class ServerSimulator:
|
|
|
self.simview = {}
|
|
|
#Simulation parameters
|
|
|
self.level = 20000
|
|
|
+ self.simview = {
|
|
|
+ "time": np.array([], dtype=np.int64),
|
|
|
+ "channel_g": np.array([], dtype=np.int16),
|
|
|
+ "channel_rf_ttl": np.array([], dtype=np.int16),
|
|
|
+ "channel_adc_ttl": np.array([], dtype=np.int16),
|
|
|
+ "channel_rf": np.array([], dtype=np.int16)
|
|
|
+ }
|
|
|
#32bit Codes
|
|
|
self.errCode = 0x00000000
|
|
|
self.statCode = 0x00000000
|
|
|
@@ -32,15 +41,15 @@ class ServerSimulator:
|
|
|
0x00: self.disconnect
|
|
|
}
|
|
|
|
|
|
- def connect(self, host, port):
|
|
|
- self.sock.bind((host, port))
|
|
|
- self.sock.listen(1)
|
|
|
- self.conn, addr = self.sock.accept()
|
|
|
- print(f"New connection from {addr}")
|
|
|
+ def connect(self):
|
|
|
+ self.conn, self.addr = self.sock.accept()
|
|
|
+ print(f"New connection from {self.addr}")
|
|
|
return True
|
|
|
|
|
|
def disconnect(self):
|
|
|
self.conn.close()
|
|
|
+ print(f"Connection with {self.addr} closed")
|
|
|
+ return True
|
|
|
|
|
|
def getErrorMsg(self, errCode, errString):
|
|
|
error = {
|
|
|
@@ -62,7 +71,7 @@ class ServerSimulator:
|
|
|
|
|
|
|
|
|
def acceptCommand(self):
|
|
|
- rawdata = self.sock.recv(4096)
|
|
|
+ rawdata = self.conn.recv(4096)
|
|
|
|
|
|
# Check if data is received
|
|
|
if not rawdata:
|
|
|
@@ -89,7 +98,7 @@ class ServerSimulator:
|
|
|
return True
|
|
|
|
|
|
def addEvent(self, data):
|
|
|
- if not all (k in data for k in ("time", "duration", "wave", "time_front_rf_trigger", "time_back_rf", "rf_start", "rf_end", "time_adc_trigger", "time_back_adc")):
|
|
|
+ if not all (k in data for k in ("time", "duration", "wave", "time_front_rf_trigger", "time_back_rf_trigger", "rf_start", "rf_end", "time_front_adc_trigger", "time_back_adc_trigger")):
|
|
|
print("Missing event parameters")
|
|
|
self.errCode = 0x00000001 # Missing parameters
|
|
|
self.conn.sendall(self.getErrorMsg(self.errCode, "Missing event parameters"))
|
|
|
@@ -101,11 +110,11 @@ class ServerSimulator:
|
|
|
"wave": data["wave"],
|
|
|
"carrier_freq": data["carrier_freq"],
|
|
|
"time_front_rf_trigger": data["time_front_rf_trigger"],
|
|
|
- "time_back_rf_trigger": data["time_back_rf"],
|
|
|
+ "time_back_rf_trigger": data["time_back_rf_trigger"],
|
|
|
"rf_start": data["rf_start"],
|
|
|
"rf_end": data["rf_end"],
|
|
|
- "time_front_adc_trigger": data["time_adc_trigger"],
|
|
|
- "time_back_adc_trigger": data["time_back_adc"],
|
|
|
+ "time_front_adc_trigger": data["time_front_adc_trigger"],
|
|
|
+ "time_back_adc_trigger": data["time_back_adc_trigger"],
|
|
|
}
|
|
|
|
|
|
if event["start_time"] < self.time:
|
|
|
@@ -113,9 +122,6 @@ class ServerSimulator:
|
|
|
self.errCode = 0x00000002 # Event in the past
|
|
|
self.conn.sendall(self.getErrorMsg(self.errCode, "Event start time is in the past"))
|
|
|
return False
|
|
|
-
|
|
|
- self.time = event["start_time"] + event["duration"]
|
|
|
-
|
|
|
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
|
|
|
@@ -151,12 +157,12 @@ class ServerSimulator:
|
|
|
self.errCode = 0x00000009 # ADC triggers overlap
|
|
|
self.conn.sendall(self.getErrorMsg(self.errCode, "ADC triggers overlap"))
|
|
|
return False
|
|
|
- if event["rf_start"] < event["rf_end"]:
|
|
|
+ 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
|
|
|
- if event["rf_start"] < event["time_front_rf_trigger"] or event["rf_end"] > event["time_back_rf_trigger"]:
|
|
|
+ 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"))
|
|
|
@@ -167,6 +173,7 @@ class ServerSimulator:
|
|
|
self.conn.sendall(self.getErrorMsg(self.errCode, "RF pulse duration must be at least as long as the wave length"))
|
|
|
return False
|
|
|
self.events.append(event)
|
|
|
+ self.time = event["start_time"] + event["duration"]
|
|
|
print(f"Added event: {event}")
|
|
|
self.conn.sendall(self.getStatusMsg(0x00000010, "Event added successfully"))
|
|
|
return True
|
|
|
@@ -209,8 +216,8 @@ class ServerSimulator:
|
|
|
self.conn.sendall(self.getErrorMsg(self.errCode, "Missing wave data in RF wave packet"))
|
|
|
return False
|
|
|
|
|
|
- wave_q = packet_data["wavedata_q"]
|
|
|
- wave_i = packet_data["wavedata_i"]
|
|
|
+ wave_q = np.frombuffer(packet_data["wavedata_q"], dtype=np.int16)
|
|
|
+ wave_i = np.frombuffer(packet_data["wavedata_i"], dtype=np.int16)
|
|
|
|
|
|
if len(wave_q) != len(wave_i):
|
|
|
print("In-phase and quadrature wave data must have the same length in RF wave packet")
|
|
|
@@ -237,10 +244,12 @@ class ServerSimulator:
|
|
|
|
|
|
def runEventList(self, data):
|
|
|
time_linspace = np.linspace(0, self.time, self.time+1)
|
|
|
- channel_g = np.ones(self.time, dtype=np.int16) * np.floor(3.3 / 5 * 32767)
|
|
|
- channel_rf_ttl = np.zeros(self.time, dtype=np.int16)
|
|
|
- channel_adc_ttl = np.zeros(self.time, dtype=np.int16)
|
|
|
- channel_rf = np.zeros(self.time, dtype=np.int16)
|
|
|
+ self.simview["time"] = time_linspace.astype(np.int64)
|
|
|
+
|
|
|
+ channel_g = np.ones(self.time+1, dtype=np.int16) * np.floor(3.3 / 5 * 32767).astype(np.int16)
|
|
|
+ channel_rf_ttl = np.zeros(self.time+1, dtype=np.int16)
|
|
|
+ channel_adc_ttl = np.zeros(self.time+1, dtype=np.int16)
|
|
|
+ channel_rf = np.zeros(self.time+1, dtype=np.int16)
|
|
|
|
|
|
for event in self.events:
|
|
|
print(f"Running event: {event}")
|
|
|
@@ -249,8 +258,8 @@ class ServerSimulator:
|
|
|
rf_wave_i = self.rfwaves[event["wave"]][1]
|
|
|
|
|
|
rf_pulse_length = event["rf_end"] - event["rf_start"]
|
|
|
- rf_trigger_length = event["time_back_rf_trigger"] - event["time_front_rf_trigger"]
|
|
|
- adc_trigger_length = event["time_back_adc_trigger"] - event["time_front_adc_trigger"]
|
|
|
+ rf_trigger_length = -event["time_back_rf_trigger"] + event["time_front_rf_trigger"]
|
|
|
+ adc_trigger_length = -event["time_back_adc_trigger"] + event["time_front_adc_trigger"]
|
|
|
|
|
|
rf_wave_length = len(rf_wave_q)
|
|
|
|
|
|
@@ -260,6 +269,7 @@ class ServerSimulator:
|
|
|
rf_trigger_time = np.linspace(0, rf_trigger_length, rf_trigger_length+1)
|
|
|
adc_trigger_time = np.linspace(0, adc_trigger_length, adc_trigger_length+1)
|
|
|
event_time = np.linspace(0, event_length, event_length+1)
|
|
|
+ print(f"RF pulse length: {rf_pulse_length}, RF trigger length: {rf_trigger_length}, ADC trigger length: {adc_trigger_length}, Event length: {event_length}")
|
|
|
|
|
|
if rf_pulse_length < rf_wave_length:
|
|
|
print("RF pulse length is shorter than RF wave length, cannot run event")
|
|
|
@@ -271,47 +281,47 @@ 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')
|
|
|
- interp_func_i = interp.interp1d(np.linspace(0, rf_wave_length, rf_wave_length), rf_wave_i, kind='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)
|
|
|
elif data["interpolation_method"] == "nearest":
|
|
|
- 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_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)
|
|
|
elif data["interpolation_method"] == "cubic":
|
|
|
- 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_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)
|
|
|
|
|
|
- channel_rf[event["rf_start"]:event["rf_end"]+1] = np.floor((interp_wave_q * np.cos(2 * np.pi * event["carrier_freq"] * rf_time * 8e-9) - interp_wave_i * np.sin(2 * np.pi * event["carrier_freq"] * rf_time * 8e-9)) / np.sqrt(2)).astype(np.int16)
|
|
|
- channel_rf_ttl[event["time_front_rf_trigger"]:event["time_back_rf_trigger"]+1] = 1
|
|
|
- channel_adc_ttl[event["time_front_adc_trigger"]:event["time_back_adc_trigger"]+1] = 1
|
|
|
+ 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))
|
|
|
+ channel_adc_ttl[event["start_time"]+event["time_back_adc_trigger"]:event["start_time"]+event["time_front_adc_trigger"]+1] = np.int16(1 * np.floor(3.3 / 5 * 32767))
|
|
|
channel_g[event["start_time"]:(event["start_time"]+event["duration"]+1)] = 0
|
|
|
|
|
|
- self.simview = {
|
|
|
- "time": time_linspace,
|
|
|
- "channel_g": channel_g,
|
|
|
- "channel_rf_ttl": channel_rf_ttl,
|
|
|
- "channel_adc_ttl": channel_adc_ttl,
|
|
|
- "channel_rf": channel_rf
|
|
|
- }
|
|
|
+ self.simview["channel_g"] = channel_g
|
|
|
+ self.simview["channel_rf_ttl"] = channel_rf_ttl
|
|
|
+ self.simview["channel_adc_ttl"] = channel_adc_ttl
|
|
|
+ self.simview["channel_rf"] = channel_rf
|
|
|
+ print(f"Simulation data: time length {len(self.simview['time'])}, channel_g length {len(self.simview['channel_g'])}, channel_rf_ttl length {len(self.simview['channel_rf_ttl'])}, channel_adc_ttl length {len(self.simview['channel_adc_ttl'])}, channel_rf length {len(self.simview['channel_rf'])}")
|
|
|
self.conn.sendall(self.getStatusMsg(0x00000032, "Event list simulation complete"))
|
|
|
return True
|
|
|
|
|
|
def sendSimViewData(self, data):
|
|
|
data_length = len(self.simview["time"])
|
|
|
- channels = ["channel_g", "channel_rf_ttl", "channel_adc_ttl", "channel_rf"]
|
|
|
- packet_size = 1024
|
|
|
- total_packets = (data_length * len(channels) * 2) // packet_size + 1
|
|
|
+ channels = ["channel_g", "channel_rf_ttl", "channel_adc_ttl", "channel_rf", "time"]
|
|
|
+ packet_size = 512
|
|
|
+ total_packets = (data_length * len(channels)) // packet_size + 1
|
|
|
packet_index = 0
|
|
|
self.conn.sendall(self.getStatusMsg(0x00000043, f"Ready to send simulation data in {total_packets} packets with size {packet_size} bytes"))
|
|
|
+ self.conn.recv(4096) # ACK
|
|
|
+ print(f"Starting to send simulation data: total length {data_length}, total packets {total_packets}")
|
|
|
for channel in channels:
|
|
|
- channel_data = self.simview[channel].tobytes()
|
|
|
+ channel_data = self.simview[channel]
|
|
|
for i in range(0, len(channel_data), packet_size):
|
|
|
- packet_num += 1
|
|
|
+ packet_index += 1
|
|
|
packet_data = None
|
|
|
if i + packet_size > len(channel_data):
|
|
|
packet_data = channel_data[i:]
|
|
|
@@ -323,22 +333,19 @@ class ServerSimulator:
|
|
|
"channel": channel,
|
|
|
"total_packets": total_packets,
|
|
|
"packet_index": packet_index,
|
|
|
- "data": packet_data
|
|
|
+ "data": packet_data.tobytes(),
|
|
|
+ "data_length": len(packet_data)
|
|
|
}
|
|
|
+ print(f"Sending packet {packet_index}/{total_packets} for channel '{channel}' with data length {len(packet_data)}")
|
|
|
self.conn.sendall(msgpack.packb(packet_msg, use_bin_type=True))
|
|
|
- rawdata = self.conn.recv(1024) # Wait for ACK
|
|
|
- ack_data = msgpack.unpackb(rawdata, raw=False)
|
|
|
- if ack_data["magic"] != self.magic or ack_data["cmd"] != 0x41 or ack_data["code"] != packet_index:
|
|
|
- print(f"Invalid ACK for packet {packet_index}")
|
|
|
- self.errCode = 0x00000045 # Invalid ACK
|
|
|
- self.conn.sendall(self.getErrorMsg(self.errCode, f"Invalid ACK for packet {packet_index}"))
|
|
|
- return False
|
|
|
+ self.conn.recv(4096) # Wait for ACK
|
|
|
print("Simulation data sent successfully")
|
|
|
self.conn.sendall(self.getStatusMsg(0x00000044, "All simulation data packets sent"))
|
|
|
return True
|
|
|
|
|
|
def clearEventList(self, data):
|
|
|
self.events = []
|
|
|
+ self.time = 0
|
|
|
self.conn.sendall(self.getStatusMsg(0x00000064, "Event list cleared"))
|
|
|
return True
|
|
|
|
|
|
@@ -354,6 +361,6 @@ class ServerSimulator:
|
|
|
|
|
|
server = ServerSimulator()
|
|
|
|
|
|
-while server.connect('127.0.0.1', 5003):
|
|
|
+while server.connect():
|
|
|
while server.acceptCommand():
|
|
|
pass
|