|
|
|
|
|
import inspect
|
|
|
|
|
|
import os.path
|
|
|
|
|
|
import tkinter as tk
|
|
|
|
|
|
from tkinter import ttk
|
|
|
|
|
|
from .base_page import BasePage
|
|
|
|
|
|
from protocol import DbgGlobalConfig
|
|
|
|
|
|
from config import Cmd
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class GlobalParamsPage(BasePage):
|
|
|
|
|
|
def __init__(self, parent, tcp_client):
|
|
|
|
|
|
# 先定义同步模式映射关系
|
|
|
|
|
|
self.sync_mode_mapping = {
|
|
|
|
|
|
"PT外同步,B码外同步": 0,
|
|
|
|
|
|
"PT内同步,B码外同步": 1,
|
|
|
|
|
|
"PT外同步,B码内同步": 2,
|
|
|
|
|
|
"PT内同步,B码内同步": 3
|
|
|
|
|
|
}
|
|
|
|
|
|
self.reverse_sync_mode_mapping = {v: k for k, v in self.sync_mode_mapping.items()}
|
|
|
|
|
|
|
|
|
|
|
|
# 然后调用父类的__init__
|
|
|
|
|
|
super().__init__(parent, tcp_client, "全局参数")
|
|
|
|
|
|
|
|
|
|
|
|
# 配置样式
|
|
|
|
|
|
self.configure_styles()
|
|
|
|
|
|
|
|
|
|
|
|
# 注册回调
|
|
|
|
|
|
tcp_client.register_callback(Cmd.GLOBAL_PARAM_GET, self.on_data_received)
|
|
|
|
|
|
tcp_client.register_callback(Cmd.GLOBAL_PARAM_SET, self.on_set_response)
|
|
|
|
|
|
|
|
|
|
|
|
# self.create_widgets()
|
|
|
|
|
|
|
|
|
|
|
|
def configure_styles(self):
|
|
|
|
|
|
"""配置界面样式"""
|
|
|
|
|
|
style = ttk.Style()
|
|
|
|
|
|
style.configure('Readonly.TEntry',
|
|
|
|
|
|
fieldbackground='#f0f0f0',
|
|
|
|
|
|
foreground='#666666')
|
|
|
|
|
|
|
|
|
|
|
|
def create_widgets(self):
|
|
|
|
|
|
"""创建界面控件"""
|
|
|
|
|
|
print(f"file:{os.path.basename(__file__)} func:{inspect.currentframe().f_code.co_name}")
|
|
|
|
|
|
super().create_widgets()
|
|
|
|
|
|
|
|
|
|
|
|
# 创建主框架
|
|
|
|
|
|
main_frame = ttk.Frame(self)
|
|
|
|
|
|
main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
|
|
|
|
|
|
|
|
|
|
|
|
# 创建两列
|
|
|
|
|
|
left_frame = ttk.Frame(main_frame)
|
|
|
|
|
|
left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 5))
|
|
|
|
|
|
|
|
|
|
|
|
right_frame = ttk.Frame(main_frame)
|
|
|
|
|
|
right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=(5, 0))
|
|
|
|
|
|
|
|
|
|
|
|
# 定义所有字段
|
|
|
|
|
|
self.fields = [
|
|
|
|
|
|
# 左列
|
|
|
|
|
|
{"label": "采样频率", "attr": "sample_frequency", "type": "spin", "args": (1, 1000), "unit": "MHz",
|
|
|
|
|
|
"readonly": False},
|
|
|
|
|
|
{"label": "触发采样长度", "attr": "trigger_sample_numbers", "type": "spin", "args": (1, 10000),
|
|
|
|
|
|
"unit": "us", "readonly": False},
|
|
|
|
|
|
{"label": "预触发百分比", "attr": "pre_trigger_percent", "type": "spin", "args": (0, 100), "unit": "%",
|
|
|
|
|
|
"readonly": False},
|
|
|
|
|
|
{"label": "触发电平", "attr": "trigLevel", "type": "spin", "args": (0, 5000), "unit": "mv",
|
|
|
|
|
|
"readonly": False},
|
|
|
|
|
|
{"label": "趋势上升周期", "attr": "trend_up_period", "type": "spin", "args": (1, 1000), "unit": "",
|
|
|
|
|
|
"readonly": False},
|
|
|
|
|
|
|
|
|
|
|
|
# 右列
|
|
|
|
|
|
{"label": "心跳包周期", "attr": "heartbeat_period", "type": "spin", "args": (1, 3600), "unit": "s",
|
|
|
|
|
|
"readonly": False},
|
|
|
|
|
|
{"label": "通道使能掩码", "attr": "ch_en_mask", "type": "hex_entry", "unit": "", "readonly": False},
|
|
|
|
|
|
{"label": "同步模式", "attr": "sync_mode", "type": "combo",
|
|
|
|
|
|
"options": list(self.sync_mode_mapping.keys()), # 使用映射的键作为选项
|
|
|
|
|
|
"readonly": False},
|
|
|
|
|
|
{"label": "内同步频率", "attr": "pt_internal_period", "type": "spin", "args": (40, 300), "unit": "",
|
|
|
|
|
|
"readonly": False},
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
# 创建字段控件
|
|
|
|
|
|
self.create_field_controls(left_frame, self.fields[:5]) # 左列前5个
|
|
|
|
|
|
self.create_field_controls(right_frame, self.fields[5:]) # 右列后4个
|
|
|
|
|
|
|
|
|
|
|
|
# 创建按钮
|
|
|
|
|
|
self.create_buttons()
|
|
|
|
|
|
|
|
|
|
|
|
def create_field_controls(self, parent, fields):
|
|
|
|
|
|
"""创建字段控件"""
|
|
|
|
|
|
for i, field in enumerate(fields):
|
|
|
|
|
|
# 创建标签
|
|
|
|
|
|
label_text = field["label"] + ":"
|
|
|
|
|
|
if "unit" in field and field["unit"]:
|
|
|
|
|
|
label_text += f" ({field['unit']})"
|
|
|
|
|
|
ttk.Label(parent, text=label_text).grid(
|
|
|
|
|
|
row=i, column=0, sticky='e', padx=2, pady=2)
|
|
|
|
|
|
|
|
|
|
|
|
# 创建输入控件
|
|
|
|
|
|
if field["type"] == "spin":
|
|
|
|
|
|
var = tk.IntVar()
|
|
|
|
|
|
spinbox = ttk.Spinbox(parent, from_=field["args"][0], to=field["args"][1],
|
|
|
|
|
|
textvariable=var, width=12)
|
|
|
|
|
|
spinbox.grid(row=i, column=1, sticky='w', padx=2, pady=2)
|
|
|
|
|
|
if field["readonly"]:
|
|
|
|
|
|
spinbox.configure(state='readonly', style='Readonly.TEntry')
|
|
|
|
|
|
|
|
|
|
|
|
elif field["type"] == "hex_entry":
|
|
|
|
|
|
var = tk.StringVar()
|
|
|
|
|
|
entry = ttk.Entry(parent, textvariable=var, width=12)
|
|
|
|
|
|
entry.grid(row=i, column=1, sticky='w', padx=2, pady=2)
|
|
|
|
|
|
if field["readonly"]:
|
|
|
|
|
|
entry.configure(state='readonly', style='Readonly.TEntry')
|
|
|
|
|
|
|
|
|
|
|
|
elif field["type"] == "combo":
|
|
|
|
|
|
var = tk.StringVar() # 使用StringVar存储显示文本
|
|
|
|
|
|
combobox = ttk.Combobox(parent, textvariable=var,
|
|
|
|
|
|
values=field["options"], state="readonly", width=15) # 增加宽度以适应更长的文本
|
|
|
|
|
|
combobox.grid(row=i, column=1, sticky='w', padx=2, pady=2)
|
|
|
|
|
|
|
|
|
|
|
|
else: # entry
|
|
|
|
|
|
var = tk.StringVar()
|
|
|
|
|
|
entry = ttk.Entry(parent, textvariable=var, width=15)
|
|
|
|
|
|
entry.grid(row=i, column=1, sticky='w', padx=2, pady=2)
|
|
|
|
|
|
if field["readonly"]:
|
|
|
|
|
|
entry.configure(state='readonly', style='Readonly.TEntry')
|
|
|
|
|
|
|
|
|
|
|
|
# 存储变量引用
|
|
|
|
|
|
setattr(self, f"{field['attr']}_var", var)
|
|
|
|
|
|
|
|
|
|
|
|
def create_buttons(self):
|
|
|
|
|
|
"""创建按钮"""
|
|
|
|
|
|
btn_frame = ttk.Frame(self)
|
|
|
|
|
|
btn_frame.pack(pady=10)
|
|
|
|
|
|
|
|
|
|
|
|
ttk.Button(btn_frame, text="读取", command=self.read_data, width=10).pack(side=tk.LEFT, padx=5)
|
|
|
|
|
|
ttk.Button(btn_frame, text="设置", command=self.set_data, width=10).pack(side=tk.LEFT, padx=5)
|
|
|
|
|
|
|
|
|
|
|
|
def read_data(self):
|
|
|
|
|
|
"""读取全局参数"""
|
|
|
|
|
|
print(f"发送命令: {Cmd.GLOBAL_PARAM_GET}")
|
|
|
|
|
|
if not self.tcp_client.connected:
|
|
|
|
|
|
self.show_error("未连接设备")
|
|
|
|
|
|
return
|
|
|
|
|
|
self.tcp_client.send_packet(Cmd.GLOBAL_PARAM_GET)
|
|
|
|
|
|
|
|
|
|
|
|
def set_data(self):
|
|
|
|
|
|
"""设置全局参数"""
|
|
|
|
|
|
if not self.tcp_client.connected:
|
|
|
|
|
|
self.show_error("未连接设备")
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
config = DbgGlobalConfig()
|
|
|
|
|
|
|
|
|
|
|
|
# 设置字段值
|
|
|
|
|
|
config.sample_frequency = self.sample_frequency_var.get()
|
|
|
|
|
|
config.trigger_sample_numbers = self.trigger_sample_numbers_var.get()
|
|
|
|
|
|
config.pre_trigger_percent = self.pre_trigger_percent_var.get()
|
|
|
|
|
|
config.trigLevel = self.trigLevel_var.get()
|
|
|
|
|
|
config.trend_up_period = self.trend_up_period_var.get()
|
|
|
|
|
|
config.heartbeat_period = self.heartbeat_period_var.get()
|
|
|
|
|
|
|
|
|
|
|
|
# 通道使能掩码(16进制转整数)
|
|
|
|
|
|
ch_en_mask_str = self.ch_en_mask_var.get().strip()
|
|
|
|
|
|
if ch_en_mask_str.startswith(('0x', '0X')):
|
|
|
|
|
|
ch_en_mask_str = ch_en_mask_str[2:]
|
|
|
|
|
|
config.ch_en_mask = int(ch_en_mask_str, 16) if ch_en_mask_str else 0
|
|
|
|
|
|
|
|
|
|
|
|
# 同步模式:将文本转换为对应的数字值
|
|
|
|
|
|
sync_mode_text = self.sync_mode_var.get()
|
|
|
|
|
|
config.sync_mode = self.sync_mode_mapping.get(sync_mode_text, 0)
|
|
|
|
|
|
|
|
|
|
|
|
config.pt_internal_period = self.pt_internal_period_var.get()
|
|
|
|
|
|
|
|
|
|
|
|
self.tcp_client.send_packet(Cmd.GLOBAL_PARAM_SET, config.to_bytes())
|
|
|
|
|
|
|
|
|
|
|
|
except ValueError as e:
|
|
|
|
|
|
self.show_error(f"参数格式错误: {e}")
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
self.show_error(f"设置失败: {e}")
|
|
|
|
|
|
|
|
|
|
|
|
def on_data_received(self, header, body):
|
|
|
|
|
|
"""处理接收到的数据"""
|
|
|
|
|
|
print(f"file:{os.path.basename(__file__)} func:{inspect.currentframe().f_code.co_name}")
|
|
|
|
|
|
print(f"收到数据: 命令={header.cmd}, 数据长度={len(body)}")
|
|
|
|
|
|
try:
|
|
|
|
|
|
config = DbgGlobalConfig.from_bytes(body)
|
|
|
|
|
|
print(f"解析成功: sample_frequency={config.sample_frequency}, trigger_sample_numbers={config.trigger_sample_numbers}")
|
|
|
|
|
|
|
|
|
|
|
|
# 更新界面字段
|
|
|
|
|
|
self.sample_frequency_var.set(config.sample_frequency)
|
|
|
|
|
|
self.trigger_sample_numbers_var.set(config.trigger_sample_numbers)
|
|
|
|
|
|
self.pre_trigger_percent_var.set(config.pre_trigger_percent)
|
|
|
|
|
|
self.trigLevel_var.set(config.trigLevel)
|
|
|
|
|
|
self.trend_up_period_var.set(config.trend_up_period)
|
|
|
|
|
|
self.heartbeat_period_var.set(config.heartbeat_period)
|
|
|
|
|
|
|
|
|
|
|
|
# 通道使能掩码显示为16进制
|
|
|
|
|
|
self.ch_en_mask_var.set(f"0x{config.ch_en_mask:02X}")
|
|
|
|
|
|
|
|
|
|
|
|
# 同步模式:将数字值转换为对应的文本显示
|
|
|
|
|
|
sync_mode_text = self.reverse_sync_mode_mapping.get(config.sync_mode, "PT外同步,B码外同步")
|
|
|
|
|
|
self.sync_mode_var.set(sync_mode_text)
|
|
|
|
|
|
|
|
|
|
|
|
self.pt_internal_period_var.set(config.pt_internal_period)
|
|
|
|
|
|
|
|
|
|
|
|
print(f"同步模式设置: {config.sync_mode} -> {sync_mode_text}")
|
|
|
|
|
|
print("全局参数读取成功")
|
|
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"解析全局参数失败: {e}")
|
|
|
|
|
|
self.show_error("解析全局参数失败")
|
|
|
|
|
|
|
|
|
|
|
|
def on_set_response(self, header, body):
|
|
|
|
|
|
"""处理设置响应"""
|
|
|
|
|
|
self.show_info("全局参数设置成功")
|