You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

208 lines
9.1 KiB
Python

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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):
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": ["外同步", "内同步"],
"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来存储显示文本
# 存储映射关系
self.sync_mode_mapping = {"外同步": 0, "内同步": 1}
self.reverse_sync_mode_mapping = {0: "外同步", 1: "内同步"}
combobox = ttk.Combobox(parent, textvariable=var,
values=list(self.sync_mode_mapping.keys()), state="readonly", width=10)
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, "外同步")
self.sync_mode_var.set(sync_mode_text)
self.pt_internal_period_var.set(config.pt_internal_period)
print("全局参数读取成功")
except Exception as e:
print(f"解析全局参数失败: {e}")
self.show_error("解析全局参数失败")
def on_set_response(self, header, body):
"""处理设置响应"""
self.show_info("全局参数设置成功")