11 Commits
24 changed files with 2503 additions and 662 deletions
+217
View File
@@ -0,0 +1,217 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[codz]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py.cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# UV
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
#uv.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
#poetry.toml
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
#pdm.lock
#pdm.toml
.pdm-python
.pdm-build/
# pixi
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
#pixi.lock
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
# in the .venv directory. It is recommended not to include this directory in version control.
.pixi
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# Redis
*.rdb
*.aof
*.pid
# RabbitMQ
mnesia/
rabbitmq/
rabbitmq-data/
# ActiveMQ
activemq-data/
# SageMath parsed files
*.sage.py
# Environments
.env
.envrc
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# Abstra
# Abstra is an AI-powered process automation framework.
# Ignore directories containing user credentials, local state, and settings.
# Learn more at https://abstra.io/docs
.abstra/
# Visual Studio Code
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
# and can be added to the global gitignore or merged into this file. However, if you prefer,
# you could uncomment the following to ignore the entire vscode folder
# .vscode/
# Ruff stuff:
.ruff_cache/
# PyPI configuration file
.pypirc
# Marimo
marimo/_static/
marimo/_lsp/
__marimo__/
# Streamlit
.streamlit/secrets.toml
+46 -25
View File
@@ -39,10 +39,10 @@ class Plugin(Plugin_Base):
"data": "5A 54 E1 EE 00 CF 02 5A FE"
},
{
"caption": "数据发送测试 - 40 Byte",
"caption": "数据发送测试(节点01)",
"icon": "fa5.play-circle",
"data": (
"5A 54 E4 EE 00 00 00 00 02 00 28 "
"5A 54 E4 EE 01 00 00 00 01 28 00 "
"00 01 02 03 04 05 06 07 "
"08 09 0A 0B 0C 0D 0E 0F "
"10 11 12 13 14 15 16 17 "
@@ -51,25 +51,46 @@ class Plugin(Plugin_Base):
"00 08 31 5A FE"
)
},
# {
# "caption": "数据发送测试 - 2",
# "icon": "fa5.play-circle",
# "data": ""
# },
{
"caption": "装订 - 【主 - 0x01】128 kbps,时隙表 0",
"caption": "数据发送测试(节点02)",
"icon": "fa5.play-circle",
"data": "5A 54 E3 EE AA 01 22 00 00 9E 06 5A FE"
"data": (
"5A 54 E4 EE 02 00 00 00 02 28 00 "
"00 01 02 03 04 05 06 07 "
"08 09 0A 0B 0C 0D 0E 0F "
"10 11 12 13 14 15 16 17 "
"18 19 1A 1B 1C 1D 1E 1F "
"20 21 22 23 24 25 26 27 "
"00 0A 31 5A FE"
)
},
{
"caption": "装订 - 【主 - 0x01】512 kbps,时隙表 1",
"caption": "数据发送测试(节点03)",
"icon": "fa5.play-circle",
"data": "5A 54 E3 EE AA 01 33 01 00 B0 06 5A FE"
"data": (
"5A 54 E4 EE 03 00 00 00 03 28 00 "
"00 01 02 03 04 05 06 07 "
"08 09 0A 0B 0C 0D 0E 0F "
"10 11 12 13 14 15 16 17 "
"18 19 1A 1B 1C 1D 1E 1F "
"20 21 22 23 24 25 26 27 "
"00 0C 31 5A FE"
)
},
{
"caption": "装订 - 【主 - 0x01】2 Mbps,时隙表 2",
"caption": "装订 - 【主 - 0x01】128 kbps,时隙表 1",
"icon": "fa5.play-circle",
"data": "5A 54 E3 EE AA 01 44 02 00 C2 06 5A FE"
"data": "5A 54 E3 EE AA 01 22 01 00 9F 06 5A FE"
},
{
"caption": "装订 - 【主 - 0x01】512 kbps,时隙表 2",
"icon": "fa5.play-circle",
"data": "5A 54 E3 EE AA 01 33 02 00 B1 06 5A FE"
},
{
"caption": "装订 - 【主 - 0x01】2 Mbps,时隙表 3",
"icon": "fa5.play-circle",
"data": "5A 54 E3 EE AA 01 44 03 00 C3 06 5A FE"
},
{
"caption": "装订 - 【主 - 0x01】静默",
@@ -77,19 +98,19 @@ class Plugin(Plugin_Base):
"data": "5A 54 E3 EE 55 01 22 00 00 49 06 5A FE"
},
{
"caption": "装订 - 【从 - 0x02】128 kbps,时隙表 0",
"caption": "装订 - 【从 - 0x02】128 kbps,时隙表 1",
"icon": "fa5.play-circle",
"data": "5A 54 E3 EE AA 02 22 00 00 9F 06 5A FE"
"data": "5A 54 E3 EE AA 02 22 01 00 A0 06 5A FE"
},
{
"caption": "装订 - 【从 - 0x02】512 kbps,时隙表 1",
"caption": "装订 - 【从 - 0x02】512 kbps,时隙表 2",
"icon": "fa5.play-circle",
"data": "5A 54 E3 EE AA 02 33 01 00 B1 06 5A FE"
"data": "5A 54 E3 EE AA 02 33 02 00 B2 06 5A FE"
},
{
"caption": "装订 - 【从 - 0x02】2M bps,时隙表 2",
"caption": "装订 - 【从 - 0x02】2M bps,时隙表 3",
"icon": "fa5.play-circle",
"data": "5A 54 E3 EE AA 02 44 02 00 C3 06 5A FE"
"data": "5A 54 E3 EE AA 02 44 03 00 C4 06 5A FE"
},
{
"caption": "装订 - 【从 - 0x02】静默",
@@ -97,19 +118,19 @@ class Plugin(Plugin_Base):
"data": "5A 54 E3 EE 55 02 22 00 00 4A 06 5A FE"
},
{
"caption": "装订 - 【从 - 0x03】128 kbps,时隙表 0",
"caption": "装订 - 【从 - 0x03】128 kbps,时隙表 1",
"icon": "fa5.play-circle",
"data": "5A 54 E3 EE AA 03 22 00 00 A0 06 5A FE"
"data": "5A 54 E3 EE AA 03 22 01 00 A1 06 5A FE"
},
{
"caption": "装订 - 【从 - 0x03】512 kbps,时隙表 1",
"caption": "装订 - 【从 - 0x03】512 kbps,时隙表 2",
"icon": "fa5.play-circle",
"data": "5A 54 E3 EE AA 03 33 01 00 B2 06 5A FE"
"data": "5A 54 E3 EE AA 03 33 02 00 B3 06 5A FE"
},
{
"caption": "装订 - 【从 - 0x03】2 Mbps,时隙表 2",
"caption": "装订 - 【从 - 0x03】2 Mbps,时隙表 3",
"icon": "fa5.play-circle",
"data": "5A 54 E3 EE AA 03 44 02 00 C4 06 5A FE"
"data": "5A 54 E3 EE AA 03 44 03 00 C5 06 5A FE"
},
{
"caption": "装订 - 【从 - 0x03】静默",
+562
View File
@@ -0,0 +1,562 @@
# from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QLabel, QSlider, QLineEdit, QGridLayout, QPushButton, QCheckBox, QHBoxLayout, QInputDialog)
# from PyQt5.QtCore import pyqtSignal
# from PyQt5.QtGui import QDoubleValidator
import os
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QLabel, QSlider, QLineEdit,
QGridLayout, QPushButton, QCheckBox, QHBoxLayout, QInputDialog, QComboBox, QFileDialog)
from PyQt5.QtCore import pyqtSignal, Qt, QTimer
from PyQt5.QtGui import QDoubleValidator, QPixmap
try:
from i18n import _
import utils_ui
import utils
from widgets import EditRemarDialog
except Exception:
from COMTool.i18n import _
from COMTool import utils_ui
from COMTool import utils
from COMTool.widgets import EditRemarDialog
# from .graph_widget_metasenselite import Graph_MetaSenseLite
from .graph_widgets_base import Graph_Widget_Base
import pyqtgraph as pg
from struct import unpack, pack
import time
class Graph_Image(Graph_Widget_Base):
id = "image"
updateSignal = pyqtSignal(bytes)
startTimeoutSignal = pyqtSignal()
stopTimeoutSignal = pyqtSignal()
def __init__(self, parent=None, hintSignal=lambda type, title, msg: None,
rmCallback=lambda widget: None, send=lambda x: None, config=None):
# 初始化配置,默认缩放倍数为10
default = {"scale_factor": 10}
if config:
default.update(config)
super().__init__(parent, hintSignal, rmCallback, send, default, default)
self.image_data = bytearray()
# 从配置获取缩放倍数
self.scale_factor = self.config.get("scale_factor", 10)
layout = QVBoxLayout()
self.setLayout(layout)
self.imageLabel = QLabel("[ Waiting for image... ]")
self.imageLabel.setAlignment(Qt.AlignCenter)
layout.addWidget(self.imageLabel)
self.clearBtn = QPushButton("Clear Image")
self.clearBtn.clicked.connect(self.clear)
layout.addWidget(self.clearBtn)
self.updateSignal.connect(self.update_image)
self.timeoutTimer = QTimer(self)
self.timeoutTimer.setInterval(2000) # 2 seconds timeout
self.timeoutTimer.timeout.connect(self.clear_buffer)
self.startTimeoutSignal.connect(lambda: self.timeoutTimer.start())
self.stopTimeoutSignal.emit()
def clear(self):
self.image_data.clear()
self.imageLabel.clear()
self.imageLabel.setText("[ Cleared ]")
self.stopTimeoutSignal.emit()
def clear_buffer(self):
self.image_data.clear()
self.imageLabel.setText("[ Timeout: buffer cleared ]")
self.stopTimeoutSignal.emit()
def onData(self, data: bytes):
self.stopTimeoutSignal.emit() # Stop any running timer when data is received
self.image_data.extend(data)
# Check for common image signatures
if self._is_complete_jpeg(self.image_data) or \
self._is_complete_png(self.image_data) or \
self._is_complete_bmp(self.image_data):
self.updateSignal.emit(bytes(self.image_data))
self.image_data.clear()
else:
self.startTimeoutSignal.emit() # Restart timer only if not complete
def _is_complete_jpeg(self, data):
return data[:2] == b'\xFF\xD8' and data[-2:] == b'\xFF\xD9'
def _is_complete_png(self, data):
return data[:8] == b'\x89PNG\r\n\x1a\n' and b'IEND' in data[-20:]
def _is_complete_bmp(self, data):
return data[:2] == b'BM' and len(data) >= int.from_bytes(data[2:6], 'little')
def update_image(self, img_bytes: bytes):
pixmap = QPixmap()
if pixmap.loadFromData(img_bytes):
# 使用配置的缩放倍数进行缩放
scaled_width = pixmap.width() * self.scale_factor
scaled_height = pixmap.height() * self.scale_factor
scaled = pixmap.scaled(
scaled_width,
scaled_height,
Qt.KeepAspectRatio,
Qt.SmoothTransformation
)
self.imageLabel.setPixmap(scaled)
else:
self.imageLabel.setText("[ Failed to decode image ]")
class Graph_Plot(Graph_Widget_Base):
updateSignal = pyqtSignal(dict)
id = "plot"
def __init__(self, parent=None, hintSignal=lambda type, title, msg: None, rmCallback=lambda widget: None, send=lambda x: None, config=None):
default = {
"xRange": 10,
"xRangeEnable": True,
"header": "\\xAA\\xCC\\xEE\\xBB",
"binary_protocol": False,
}
super().__init__(parent, hintSignal=hintSignal, rmCallback=rmCallback,
send=send, config=config, defaultConfig=default)
self.headerBytes = utils.str_to_bytes(
self.config["header"], escape=True, encoding="utf-8")
self.layout = QGridLayout()
self.setLayout(self.layout)
self.plotWin = pg.GraphicsLayoutWidget()
self.plotWin.setMinimumHeight(200)
self.default_x = 0;
pg.setConfigOptions(antialias=True)
rmBtn = QPushButton(_("Remove"))
clearBtn = QPushButton(_("Clear"))
rangeLabel = QLabel(_("Range:"))
rangeConf = QLineEdit(str(self.config["xRange"]))
rangeEnable = QCheckBox(_("Enable"))
rangeEnable.setChecked(self.config["xRangeEnable"])
self.binary_protocol = QCheckBox(_("Binary Protocol"))
headerLabel = QLabel(_("Header:"))
headerConf = QLineEdit(self.config["header"])
self.headerBtn = QPushButton(_("Set"))
hint = _("Protocol: header + 1Byte name length + name + 8Bytes x(double) + 8Bytes y(double) + 1Byte sum\n"
"Protocol example code see help")
headerConf.setToolTip(hint)
self.binary_widgets = [headerLabel, headerConf, self.headerBtn]
self.binary_protocol.setToolTip(_('Check this if you want to use binary protocol, or use ASCII protocol(e.g. "$data1,10.0,200.0\\n"), more see help button on the top of window'))
self.show_binary_protocol_widgets(self.config["binary_protocol"])
headerLabel.setToolTip(hint)
self.headerBtn.setToolTip(hint)
validator = QDoubleValidator()
rangeConf.setValidator(validator)
self.layout.addWidget(self.plotWin, 0, 0, 1, 3)
self.layout.addWidget(rmBtn, 1, 0, 1, 1)
self.layout.addWidget(clearBtn, 1, 2, 1, 1)
self.layout.addWidget(rangeLabel, 2, 0, 1, 1)
self.layout.addWidget(rangeConf, 2, 1, 1, 1)
self.layout.addWidget(rangeEnable, 2, 2, 1, 1)
self.layout.addWidget(self.binary_protocol, 3, 0, 1, 1)
self.layout.addWidget(headerLabel, 4, 0, 1, 1)
self.layout.addWidget(headerConf, 4, 1, 1, 1)
self.layout.addWidget(self.headerBtn, 4, 2, 1, 1)
self.resize(600, 400)
self.p = self.plotWin.addPlot(colspan=2)
# self.p.setLabel('bottom', 'x', '')
self.p.addLegend()
self.p.setXRange(0, self.config["xRange"])
self.updateSignal.connect(self.update)
self.curves = {}
self.rawData = b''
self.data = {}
self.builtinColors = [
"#BD4B4B",
"#3BB273",
"#FFFFFA",
"#307473",
"#3C6997",
"#746D75",
"#228CDB",
"#824C71",
"#7768AE",
"#DC6BAD",
"#607d8b",
"#F18701",
"#912F40",
"#414288",
"#ED4D6E",
"#FFD29D",
"#B56576",
"#503B31",
"#93E1D8",
"#596157",
]
self.notUsedColors = self.builtinColors.copy()
self.colors = {
}
rangeConf.textChanged.connect(self.setRange)
rangeEnable.clicked.connect(
lambda: self.setEnableRange(rangeEnable.isChecked()))
self.headerBtn.clicked.connect(
lambda: self.setHeader(headerConf.text()))
rmBtn.clicked.connect(self.remove)
headerConf.textChanged.connect(self.headerChanged)
clearBtn.clicked.connect(self.clear)
self.binary_protocol.clicked.connect(self.en_binary_protocol)
def remove(self):
self.rmCallback(self)
def en_binary_protocol(self):
self.rawData = b''
self.config["binary_protocol"] = self.binary_protocol.isChecked()
self.show_binary_protocol_widgets(self.config["binary_protocol"])
def show_binary_protocol_widgets(self, show=True):
for w in self.binary_widgets:
w.setVisible(show)
def clear(self):
self.data = {}
self.curves = {}
self.notUsedColors = self.builtinColors.copy()
self.colors = {}
self.p.clear()
def setRange(self, text):
if text:
self.config["xRange"] = float(text)
def setEnableRange(self, en):
self.config["xRangeEnable"] = en
def headerChanged(self, text):
if self.config["header"] != text:
self.headerBtn.setText(_("Set") + " *")
else:
self.headerBtn.setText(_("Set"))
def setHeader(self, text):
if text:
try:
textBytes = utils.str_to_bytes(
text, escape=True, encoding="utf-8")
self.config["header"] = text
self.headerBytes = textBytes
self.headerBtn.setText(_("Set"))
except Exception:
self.hintSignal.emit("error", _("Error"), _("Format error"))
def decodeData(self, data: bytes):
'''
@data bytes, protocol:
| header(4B) | line name len(1B) | line name | x(8B) | y(8B) | sum(1B) |
| AA CC EE BB | 1~255 | roll | double | double | uint8 |
@return haveFrame, dict {
"name": {
"x": [],
"y": []
}
}
'''
# append data
self.rawData += data
# find header
header = self.headerBytes
idx = self.rawData.find(header)
if idx < 0:
return False, self.data
self.rawData = self.rawData[idx:]
# check data length
nameLen = unpack("B", self.rawData[len(header): len(header) + 1])[0]
frameLen = len(header) + nameLen + 18 # 5 + nameLen + 16 + 1
if len(self.rawData) < frameLen:
return False, self.data
# get data
frame = self.rawData[:frameLen]
self.rawData = self.rawData[frameLen:]
_sum = frame[-1]
# check sum
if _sum != sum(frame[:frameLen - 1]) % 256:
return True, self.data
name = frame[len(header) + 1: len(header) +
1 + nameLen].decode("utf-8")
x = unpack("d", frame[-17:-9])[0]
y = unpack("d", frame[-9:-1])[0]
if not name in self.data:
self.data[name] = {
"x": [x],
"y": [y]
}
else:
self.data[name]["x"].append(x)
self.data[name]["y"].append(y)
return True, self.data
def decodeDataAscii(self, data: bytes):
'''
@data bytes, protocol:
$[line name],[x],[y]<,checksum>\n
or $[line name],[y]
"$" means start of frame, "," means separator,
checksum is optional, checksum is sum of all bytes in frame except ",checksum".
e.g.
"$roll,2.0\n"
"$roll,1.0,2.0\n"
"$pitch,1.0,2.0\r\n"
"$pitch,1.0,2.0,179\n" , the 179 = sum(ord(c) for c in "$pitch,1.0,2.0") % 256
@return haveFrame, dict {
"name": {
"x": [],
"y": []
}
}
'''
# append data
self.rawData += data
# find header
header = b"$"
end = b"\n"
idx = self.rawData.find(header)
if idx < 0:
return False, self.data
self.rawData = self.rawData[idx:]
# find \n
idx = self.rawData.find(end)
if idx < 0:
return False, self.data
# get data
frame = self.rawData[1:idx] # pitch,1.0,2.0 pitch,1.0,2.0,179
self.rawData = self.rawData[idx + 1:]
items = frame.split(b",")
if len(items) != 2 and len(items) != 3 and len(items) != 4:
print("-- format error, frame item len(%s, should 3 or 4) error: %s" % (len(items), frame))
return False, self.data
try:
if len(items) == 2:
x = float(self.default_x)
y = float(items[1])
self.default_x += 1
else:
x = float(items[1])
y = float(items[2])
except Exception:
print("-- x or y format error, frame: %s" % frame)
return False, self.data
# checksum
if len(items) == 4:
try:
_sum = int(items[3])
except Exception:
print("-- checksum format error({} not int), frame: {}".format(items[3], frame))
return False, self.data
# get last , index
idx = frame.rfind(b",")
if sum(header + frame[:idx]) % 256 != _sum:
print("-- checksum error")
return False, self.data
name = items[0].decode("utf-8")
if not name in self.data:
self.data[name] = {
"x": [x],
"y": [y]
}
else:
self.data[name]["x"].append(x)
self.data[name]["y"].append(y)
return True, self.data
def pickColor(self, name: str):
if name in self.colors:
return self.colors[name]
else:
if not self.notUsedColors:
self.notUsedColors = self.builtinColors.copy()
color = self.notUsedColors.pop(0)
self.colors[name] = color
return color
def update(self, data: dict):
for k, v in data.items():
if not k in self.curves:
print("add curve:", k)
color = self.pickColor(k)
self.colors[k] = color
self.curves[k] = self.p.plot(pen=pg.mkPen(color=color, width=2),
name=k,)
# symbolBrush=color, symbolPen='w', symbol='o', symbolSize=1)
if self.config["xRangeEnable"] and self.config["xRange"] > 0:
self.p.setXRange(
v["x"][-1] - self.config["xRange"], v["x"][-1])
self.curves[k].setData(x=v["x"], y=v["y"])
def onData(self, data: bytes):
while 1:
haveFrame, allData = self.decodeData(data) if self.config["binary_protocol"] else self.decodeDataAscii(data)
if not haveFrame:
break
data = b''
self.updateSignal.emit(allData)
class Graph_Button(Graph_Widget_Base):
class Button(QWidget):
def __init__(self, rmCallback, addCallback, clickCallback, changeCallback,
value=("", "hello", "hello", "fa.circle", [])):
super().__init__()
if not value[0]:
self.id = str(int(time.time() * 1000))
else:
self.id = value[0]
self.rmCallback = rmCallback
self.changeCallback = changeCallback
self.setProperty("class", "graphBtn")
layout = QHBoxLayout()
layoutSetting = QVBoxLayout()
self.setLayout(layout)
self.button = QPushButton(value[2])
self.button.setProperty("class", "bigBtn")
self.value = value[2]
self.icon = value[3]
self.shortcut = value[4]
layout.addLayout(layoutSetting)
layout.addWidget(self.button)
self.addBtn = QPushButton()
self.rmBtn = QPushButton()
self.editBtn = QPushButton()
self.addBtn.setProperty("class", "smallBtn3")
self.rmBtn.setProperty("class", "smallBtn3")
self.editBtn.setProperty("class", "smallBtn3")
utils_ui.setButtonIcon(self.addBtn, "fa.plus")
utils_ui.setButtonIcon(self.rmBtn, "fa.minus")
utils_ui.setButtonIcon(self.editBtn, "fa.edit")
if self.icon:
utils_ui.setButtonIcon(self.button, self.icon)
if self.shortcut:
tip = self.getShortcutTip()
self.button.setToolTip(tip)
layoutSetting.addStretch()
layoutSetting.addWidget(self.rmBtn)
layoutSetting.addWidget(self.addBtn)
layoutSetting.addWidget(self.editBtn)
self.rmBtn.clicked.connect(self.onRm)
self.addBtn.clicked.connect(lambda: addCallback(self))
self.editBtn.clicked.connect(self.editButton)
self.button.clicked.connect(lambda: clickCallback(
self, utils.str_to_bytes(self.value, escape=True, encoding="utf-8")))
def getInfo(self):
return [self.id, self.button.text(), self.value, self.icon, self.shortcut]
def onRm(self):
utils_ui.clearButtonIcon(self.addBtn)
utils_ui.clearButtonIcon(self.rmBtn)
utils_ui.clearButtonIcon(self.editBtn)
utils_ui.clearButtonIcon(self.button)
self.rmCallback(self)
def editButton(self):
ok, remark, value, icon, shortcut = EditRemarDialog(
self.button.text(), self.icon, shortcut=self.shortcut, value=self.value).exec()
if ok:
self.value = value
self.icon = icon
self.shortcut = shortcut
self.button.setText(remark)
if self.shortcut:
tip = self.getShortcutTip()
self.button.setToolTip(tip)
utils_ui.setButtonIcon(self.button, icon)
self.changeCallback(self)
def getShortcutTip(self):
return _("Shortcut") + ": " + "+".join((name for v, name in self.shortcut))
id = "button"
def __init__(self, parent=None, hintSignal=lambda type, title, msg: None, rmCallback=lambda widget: None, send=lambda x: None, config=None):
default = {
"items": []
}
super().__init__(parent, hintSignal, rmCallback, send, config, default)
self.layout = QHBoxLayout()
self.setLayout(self.layout)
if not self.config["items"]:
button = Graph_Button.Button(
self.onRm, self.onAdd, self.onClick, self.onChange)
self.layout.addWidget(button)
self.buttons = [button]
self.config["items"] = [button.getInfo()]
else:
self.buttons = []
for item in self.config["items"]:
button = Graph_Button.Button(
self.onRm, self.onAdd, self.onClick, self.onChange, value=item)
self.layout.addWidget(button)
self.buttons.append(button)
self.pressedKeys = []
def onRm(self, widget):
'''
@widget Graph_Button.Button
'''
item = widget.getInfo()
for item_ in self.config["items"]:
if item_[0] == item[0]: # id
self.config["items"].remove(item_)
break
self.buttons.remove(widget)
widget.setParent(None)
if not self.buttons:
self.rmCallback(self)
def onAdd(self, widget):
'''
@widget Graph_Button.Button
'''
button = Graph_Button.Button(
self.onRm, self.onAdd, self.onClick, self.onChange)
self.layout.addWidget(button)
self.buttons.append(button)
self.config["items"].append(button.getInfo())
def onClick(self, widget, data: bytes):
self.send(data)
def onChange(self, widget):
self.config["items"][self.buttons.index(widget)] = widget.getInfo()
def onKeyPressEvent(self, event):
key = event.key()
self.pressedKeys.append(key)
for uid, name, value, icon, shortcut in self.config["items"]:
if not shortcut:
continue
if len(shortcut) == len(self.pressedKeys):
same = True
for i in range(len(shortcut)):
if shortcut[i][0] != self.pressedKeys[i]:
same = False
break
if same:
value = utils.str_to_bytes(
value, escape=True, encoding="utf-8")
self.send(value)
def onKeyReleaseEvent(self, event):
key = event.key()
if key in self.pressedKeys:
self.pressedKeys.remove(key)
graphWidgets = {
Graph_Plot.id: Graph_Plot,
Graph_Button.id: Graph_Button,
Graph_Image.id: Graph_Image
# Graph_DragTof.id: Graph_DragTof,
# Graph_MetaSenseLite.id: Graph_MetaSenseLite,
}
+898
View File
@@ -0,0 +1,898 @@
'''
@brief This is an example plugin, can receive and send data
@author
@date
@license LGPL-3.0
'''
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QGridLayout,QHBoxLayout, QTextEdit, QPushButton, QLabel, QScrollArea, QSplitter
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtGui import QFont, QTextCursor
from struct import Struct
try:
from PyQt5.QtWidgets import QFrame
import utils_ui
from plugins.base import Plugin_Base
from conn import ConnectionStatus
from i18n import _
from widgets import statusBar
from plugins.graph_widgets import graphWidgets
from PyQt5.QtWidgets import QPushButton, QMenu
from PyQt5.QtWidgets import QComboBox
from PyQt5 import QtCore
except ImportError:
from COMTool import utils_ui
from COMTool.plugins.base import Plugin_Base
from COMTool.i18n import _
from COMTool.conn import ConnectionStatus
from COMTool.widgets import statusBar
from COMTool.plugins.graph_widgets import graphWidgets
class Plugin(Plugin_Base):
id = "hsjl_timer"
name = _("hsjl_timer")
showReceiveDataSignal = pyqtSignal(str)
# 图片1的字节数据(已存在,提取为常量)
IMAGE1_DATA = [
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1F, 0xF3, 0xFF,
0x61, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xAE, 0xCE, 0x1C, 0xE9, 0x00, 0x00,
0x00, 0x75, 0x49, 0x44, 0x41, 0x54, 0x38, 0x4F, 0x63, 0x64, 0xA0, 0x10, 0x30, 0x52, 0xA8, 0x9F,
0x61, 0xD4, 0x00, 0x06, 0xEC, 0x61, 0x20, 0xD0, 0xFE, 0xDA, 0x81, 0x91, 0x85, 0xF9, 0xCD, 0xFB,
0x52, 0xA1, 0x2B, 0xA0, 0x40, 0x06, 0xF1, 0x41, 0xF4, 0x87, 0x4A, 0xD1, 0x03, 0xE8, 0x81, 0x8E,
0x35, 0x10, 0xF9, 0x3A, 0x5F, 0xD7, 0x33, 0xFE, 0xFF, 0x1F, 0xFF, 0x9F, 0xE1, 0x7F, 0x26, 0xE3,
0x7F, 0x46, 0x3E, 0x06, 0x46, 0xC6, 0x55, 0x8C, 0xFF, 0x19, 0x1C, 0x89, 0x36, 0x00, 0x64, 0x0B,
0xC4, 0x10, 0x86, 0x52, 0x06, 0x06, 0x06, 0x6E, 0x86, 0xFF, 0xFF, 0xC3, 0x3E, 0x56, 0x8A, 0xAD,
0xC6, 0x16, 0xE5, 0x78, 0xA3, 0x11, 0x6C, 0xC8, 0xBF, 0xFF, 0xD7, 0x70, 0x69, 0x06, 0x19, 0x38,
0x9A, 0x0E, 0x06, 0x43, 0x18, 0x00, 0x00, 0x4E, 0x62, 0x24, 0x11, 0xDE, 0x82, 0x35, 0xD8, 0x00,
0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82
]
# 图片2的字节数据(新添加)
IMAGE2_DATA = [
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x05, 0x08, 0x06, 0x00, 0x00, 0x00, 0x7C, 0x64, 0x7D,
0x68, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xAE, 0xCE, 0x1C, 0xE9, 0x00, 0x00,
0x00, 0x04, 0x67, 0x41, 0x4D, 0x41, 0x00, 0x00, 0xB1, 0x8F, 0x0B, 0xFC, 0x61, 0x05, 0x00, 0x00,
0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x12, 0x74, 0x00, 0x00, 0x12, 0x74, 0x01, 0xDE,
0x66, 0x1F, 0x78, 0x00, 0x00, 0x00, 0x14, 0x49, 0x44, 0x41, 0x54, 0x18, 0x57, 0x63, 0x50, 0x54,
0x54, 0xF9, 0x4F, 0x0C, 0x1E, 0xFC, 0x0A, 0x55, 0xFE, 0x03, 0x00, 0xAC, 0x06, 0x45, 0xBB, 0xD3,
0x7A, 0x66, 0x86, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82
]
# 在类初始化时添加定时器相关变量(onInit方法中)
def onInit(self, config):
self.image_index = 0 # 图片索引:0-图片1,1-图片2
self.cycle_count = 0 # 循环次数计数
self.send_timer = QtCore.QTimer() # 新增:定时器
self.send_timer.setInterval(1000) # 间隔1秒
self.send_timer.timeout.connect(self.send_next_image) # 绑定定时发送函数
default = {
"version": 1,
"customSendItems": [
{
"caption": "自检项",
"icon": "fa5.play-circle",
"data": "5A 54 E1 EE 00 CF 02 5A FE"
#"data": "5A 54 E1 EE 01 00 00 00 01 15 00 55 00 05 55 57 58 80 00 00 00 00 00 00 00\n\
#00 00 00 01 00 00 00 00 75 17 5A FE "
},
{
"caption": "图片传输",
"icon": "fa5.play-circle",
"data": "5A 54 E4 EE 00 00 00 01 02 00 BB 89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 00 00 00 10 00 00 \n\
00 10 08 06 00 00 00 1F F3 FF 61 00 00 00 01 73 52 47 42 00 AE CE 1C E9 00 00 00 75 49 \n\
44 41 54 38 4F 63 64 A0 10 30 52 A8 9F 61 D4 00 06 EC 61 20 D0 FE DA 81 91 85 F9 CD FB \n\
52 A1 2B A0 40 06 F1 41 F4 87 4A D1 03 E8 81 8E 35 10 F9 3A 5F D7 33 FE FF 1F FF 9F E1 \n\
7F 26 E3 7F 46 3E 06 46 C6 55 8C FF 19 1C 89 36 00 64 0B C4 10 86 52 06 06 06 6E 86 FF \n\
FF C3 3E 56 8A AD C6 16 E5 78 A3 11 6C C8 BF FF D7 70 69 06 19 38 9A 0E 06 43 18 00 00 \n\
4E 62 24 11 DE 82 35 D8 00 00 00 00 49 45 4E 44 AE 42 60 82 00 76 C4 5A FE"
},
{
"caption": "配置发送",
"icon": "fa5.play-circle",
"data": "5A 54 E3 EE AA 03 22 00 00 A0 06 5A FE"
},
]
}
self.config = config
for k in default:
if k not in self.config:
self.config[k] = default[k]
self.config["customSendItems"] = default["customSendItems"]
print("初始化的customSendItems:", self.config["customSendItems"])
def createToggleButton(self):
toggleBtn = QPushButton("开关: Off")
menu = QMenu(toggleBtn)
actionOn = menu.addAction("On")
actionOff = menu.addAction("Off")
def setOn():
toggleBtn.setText("开关: On")
print("开关设为 On")
def setOff():
toggleBtn.setText("开关: Off")
print("开关设为 Off")
actionOn.triggered.connect(setOn)
actionOff.triggered.connect(setOff)
toggleBtn.setMenu(menu)
return toggleBtn
def createIdButton(self):
# 定义ID映射:原始ID -> 显示文本(带标识)
id_display_map = {
"01": "01(主)",
"02": "02(从)",
"03": "03(从)"
}
default_id = "01" # 原始ID默认值
# 按钮显示带标识的文本
toggleBtn = QPushButton(f"id: {id_display_map[default_id]}")
# 存储原始ID(关键:组帧时用这个值)
toggleBtn.setProperty("originalId", default_id)
menu = QMenu(toggleBtn)
def setId(original_id):
# 更新显示文本(带标识)
toggleBtn.setText(f"id: {id_display_map[original_id]}")
# 更新存储的原始ID
toggleBtn.setProperty("originalId", original_id)
print(f"id设为 {original_id}") # 确认原始ID正确
# 菜单显示带标识的文本,但传递原始ID
for original_id, display_text in id_display_map.items():
menu.addAction(display_text).triggered.connect(
lambda checked, id=original_id: setId(id)
)
toggleBtn.setMenu(menu)
return toggleBtn
def createtoIdButton(self):
# 目的节点ID同理处理
id_display_map = {
"01": "01(主)",
"02": "02(从)",
"03": "03(从)"
}
default_id = "01"
toggleBtn = QPushButton(f"目的节点id: {id_display_map[default_id]}")
toggleBtn.setProperty("originalId", default_id) # 存储原始ID
menu = QMenu(toggleBtn)
def setId(original_id):
toggleBtn.setText(f"目的节点id: {id_display_map[original_id]}")
toggleBtn.setProperty("originalId", original_id)
print(f"目的节点id设为 {original_id}")
for original_id, display_text in id_display_map.items():
menu.addAction(display_text).triggered.connect(
lambda checked, id=original_id: setId(id)
)
toggleBtn.setMenu(menu)
return toggleBtn
def createSlotButton(self):
slotBtn = QPushButton("时隙表: 01") # 默认选中01
menu = QMenu(slotBtn)
slotOptions = ["01", "02", "03"]
def setSlot(text):
slotBtn.setText(f"时隙表: {text}")
print(f"时隙表设为 {text}")
for opt in slotOptions:
menu.addAction(opt).triggered.connect(lambda checked, t=opt: setSlot(t))
slotBtn.setMenu(menu)
return slotBtn
def createRateButton(self):
rateBtn = QPushButton("速率: 128kpbs") # 默认选中01
menu = QMenu(rateBtn)
rateOptions = ["128kpbs", "512kpbs", "2Mbps"]
def setRate(text):
rateBtn.setText(f"速率: {text}")
print(f"速率设为 {text}")
for opt in rateOptions:
menu.addAction(opt).triggered.connect(lambda checked, t=opt: setRate(t))
rateBtn.setMenu(menu)
return rateBtn
def buildBindCommand(self, switch_text, id_text, rate_text, slot_text):
"""
switch_text: "开关: On" 或 "开关: Off"
id_text: 形如 "id: 00", 只取后两位字符串
rate_text: "速率: 01" 对应 1/2/3
slot_text: "时隙表: 01" 对应 1/2/3
返回拼接好的指令字符串,如 "5A 54 E3 EE AA 01 22 01 00 ?? ?? 5A FE"
"""
# 头部固定
frame = [0x5A, 0x54, 0xE3, 0xEE]
# 开关字段:On -> 0xAA,Off -> 0x55
if switch_text.endswith("On"):
frame.append(0xAA)
else:
frame.append(0x55)
# ID字段,转为整数
try:
# 直接获取存储的原始ID(如"01")
original_id = self.idButton.property("originalId")
id_val = int(original_id, 16) # 转为16进制整数
except:
id_val = 0x00 # 异常时默认值
frame.append(id_val)
# 速率字段对应映射(参考原来速率的0x22等)
rate_map = {"128kpbs": 0x22, "512kpbs": 0x33, "2Mbps": 0x44}
rate_key = rate_text.split(":")[1].strip()
rate_val = rate_map.get(rate_key, 0x22)
frame.append(rate_val)
# 时隙表,直接转为整数
try:
slot_val = int(slot_text.split(":")[1].strip())
except:
slot_val = 0x00
frame.append(slot_val)
# 后续固定填充和校验(填充字节+校验和+06 5A FE)
frame.append(0x00) # 填充字节
# 校验和计算(从第3字节开始到最后填充前)
checksum = sum(frame[2:]) & 0xFF
frame.append(checksum)
# 结尾
frame.extend([0x06, 0x5A, 0xFE])
# 转成空格分隔的大写16进制字符串
return " ".join(f"{b:02X}" for b in frame)
def buildimageCommand(self, switch_text, toid_text, rate_text, slot_text, image_index=0):
# 头部固定
frame = [0x5A, 0x54, 0xE4, 0xEE]
if image_index == 0:#两个图片的序号不同
frame.append(0x01)
else:
frame.append(0x02)
frame.extend([0x00, 0x00, 0x00])
# ID字段,转为整数
try:
original_toid = self.toidButton.property("originalId")
id_val = int(original_toid, 16)
except:
id_val = 0x01 # 异常时默认值
frame.append(id_val)
# 根据索引选择图片数据
if image_index == 0:
image_data = self.IMAGE1_DATA
else:
image_data = self.IMAGE2_DATA
# 计算图片数据长度(2字节表示,这里使用小端模式)
data_length = len(image_data)
# 拆分长度为高8位和低8位
high_byte = (data_length >> 8) & 0xFF # 高8位
low_byte = data_length & 0xFF # 低8位
frame.extend([low_byte, high_byte]) # 小端模式:低位字节在前,高位字节在后
# 根据索引选择图片数据
if image_index == 0:
frame.extend(self.IMAGE1_DATA)
else:
frame.extend(self.IMAGE2_DATA)
frame.append(0x00) # 填充字节
# 校验和计算(从第3字节开始到最后填充前)
checksum = sum(frame[2:]) & 0xFF
frame.append(checksum)
# 计算数据段长度:从第三个字节(索引2)到dummy byte(当前frame的最后一个字节)
# 长度 = 总字节数 - 前两个字节(因为前两个是帧头,不算数据段)
data_segment_length = len(frame) -4 # len(frame)此时是:2(头) + 数据段内容长度 + 1(dummy)
# 替换固定值0xC4为计算出的长度,再添加后续固定字节
frame.extend([data_segment_length, 0x5A, 0xFE])
# 转成空格分隔的大写16进制字符串
return " ".join(f"{b:02X}" for b in frame)
def send_next_image(self):
if self.cycle_count < 5: # 循环5次
# 读取按钮状态
switch_text = self.toggleButton.text()
id_text = self.idButton.text()
slot_text = self.slotButton.text()
rate_text = self.rateButton.text()
toid_text = self.toidButton.text()
cmd_str = self.buildimageCommand(
switch_text, toid_text, rate_text, slot_text,
self.image_index # 传入当前图片索引
)
print(f"第{self.cycle_count + 1}次发送,图片{self.image_index + 1}: {cmd_str}")
# 实际发送数据
data_bytes = self.parseSendData(
cmd_str,
encoding=self.configGlobal["encoding"],
isHexStr=True
)
if data_bytes:
self.send(data_bytes, callback=self.onSent)
# 切换图片索引(0<->1)
self.image_index = 1 - self.image_index
self.cycle_count += 1
else:
# 循环结束,重置状态
self.send_timer.stop()
self.cycle_count = 0
self.image_index = 0
# 重新启用按钮
self.image_send_btn.setEnabled(True)
print("循环发送完成")
def onWidgetMain(self, parent):
self.mainWidget = QSplitter(Qt.Vertical)
imageContainer = QSplitter(Qt.Horizontal)
self.widgets = []
for i in range(2):
if "image" in graphWidgets:
imageWidgetClass = graphWidgets["image"]
imageWidget = imageWidgetClass(
hintSignal=self.hintSignal,
rmCallback=lambda widget: None,
send=self.sendData,
config={}
)
self.widgets.append(imageWidget)
frame = QFrame()
frame.setFrameShape(QFrame.StyledPanel)
frame.setFrameShadow(QFrame.Raised)
frame.setStyleSheet("QFrame { border: 1px solid #999; border-radius: 6px; margin: 4px; }")
layout = QVBoxLayout()
layout.setContentsMargins(6, 6, 6, 6)
layout.addWidget(imageWidget)
frame.setLayout(layout)
imageContainer.addWidget(frame)
else:
placeholder = QLabel("No graph widget configured")
placeholder.setAlignment(Qt.AlignCenter)
imageContainer.addWidget(placeholder)
self.mainWidget.addWidget(imageContainer)
self.customSendScroll = QScrollArea()
self.customSendScroll.setMinimumHeight(20)
self.customSendScroll.setWidgetResizable(True)
self.customSendScroll.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.customSendScroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
sendItemsWrapper = QWidget()
self.customSendScroll.setWidget(sendItemsWrapper)
sendItemsOuterWrapper = QWidget()
sendItemsOuterWrapper.setProperty("class", "scrollbar2")
layout0 = QVBoxLayout()
layout0.setContentsMargins(0, 8, 0, 0)
sendItemsOuterWrapper.setLayout(layout0)
layout0.addWidget(self.customSendScroll)
sendItemsLayoutWrapper = QVBoxLayout()
sendItemsLayoutWrapper.setContentsMargins(0, 0, 0, 0)
sendItemsWrapper.setLayout(sendItemsLayoutWrapper)
self.customItems = QWidget()
self.customSendItemsLayout = QGridLayout()
self.customSendItemsLayout.setContentsMargins(8, 4, 8, 4)
self.customItems.setLayout(self.customSendItemsLayout)
sendItemsLayoutWrapper.addWidget(self.customItems)
sendItemsLayoutWrapper.addStretch(0)
self.mainWidget.addWidget(sendItemsOuterWrapper)
# 网络状态标签初始化
self.networkStatusLabel = QLabel("节点状态: 未知")
self.networkStatusLabel.setAlignment(Qt.AlignLeft)
self.networkStatusLabel.setFont(QFont("Arial", 10))
self.networkPhaseLabel = QLabel("天线温度: 未知")
self.networkPhaseLabel.setAlignment(Qt.AlignLeft)
self.networkPhaseLabel.setFont(QFont("Arial", 10))
self.networktemLabel = QLabel("电压状态: 未知")
self.networktemLabel.setAlignment(Qt.AlignLeft)
self.networktemLabel.setFont(QFont("Arial", 10))
self.networkvoltageLabel = QLabel("fgpa温度: 未知")
self.networkvoltageLabel.setAlignment(Qt.AlignLeft)
self.networkvoltageLabel.setFont(QFont("Arial", 10))
# 设置主窗口比例
self.mainWidget.setStretchFactor(0, 6) # 图像区域
self.mainWidget.setStretchFactor(1, 4) # 自定义发送区域
return self.mainWidget
def clearLayout(self, layout):
while layout.count():
item = layout.takeAt(0)
widget = item.widget()
if widget:
widget.setParent(None)
def createSendItemWidget(self, item):
caption = item["caption"]
itemWidget = QWidget()
layout = QHBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
itemWidget.setLayout(layout)
send = QPushButton("")
label = QLabel(caption)
icon = item.get("icon", "fa.send")
utils_ui.setButtonIcon(send, icon)
send.setProperty("class", "smallBtn")
def sendCustomData():
self.sendCustomItem(item)
send.clicked.connect(sendCustomData)
layout.addWidget(label)
layout.addWidget(send)
return itemWidget
def onUiInitDone(self):
# 清空旧布局
self.clearLayout(self.customSendItemsLayout)
# 创建“开关”、“ID”、“时隙表”、“速率”按钮,供“总控”使用
self.toggleButton = self.createToggleButton()
self.customSendItemsLayout.addWidget(self.toggleButton, 1, 0, 1, 2)
self.idButton = self.createIdButton()
self.customSendItemsLayout.addWidget(self.idButton, 0, 1)
self.slotButton = self.createSlotButton()
self.customSendItemsLayout.addWidget(self.slotButton, 0, 2)
self.rateButton = self.createRateButton()
self.customSendItemsLayout.addWidget(self.rateButton, 0, 0)
self.toidButton = self.createtoIdButton()
self.customSendItemsLayout.addWidget(self.toidButton, 0, 3)
# 第一行固定插入“自检”、“图片传输”、“总控”
for item in self.config["customSendItems"]:
if item["caption"] == "自检项":
print("找到自检项,准备添加到(0,0)") # 新增
w = self.createSendItemWidget(item)
self.customSendItemsLayout.addWidget(w, 3, 0, 1, 2)
elif item["caption"] == "图片传输":
totalControlWidget = QWidget()
layout = QHBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
totalControlWidget.setLayout(layout)
sendBtn = QPushButton("")
self.image_send_btn = sendBtn
label = QLabel("图片传输")
utils_ui.setButtonIcon(sendBtn, item.get("icon", "fa.send"))
sendBtn.setProperty("class", "smallBtn")
# 初始化定时器(确保只初始化一次)
self.send_timer = QtCore.QTimer()
def start_image_cycle():
# 禁用按钮防止重复触发
sendBtn.setEnabled(False)
# 重置计数和索引
self.cycle_count = 0 # 总循环次数(每次循环包含图片1+图片2)
self.image_index = 0 # 当前图片索引(0:图片1,1:图片2)
# 新增:根据当前速率设置定时器间隔
# 1. 定义速率与间隔的映射关系(单位:毫秒)
rate_interval_map = {
"128kpbs": 1500, # 128kpbs对应1.5秒
"512kpbs": 1000, # 256kpbs对应1秒
"2Mbps": 500 # 2Mbps对应0.5秒
}
# 2. 获取当前选中的速率
rate_text = self.rateButton.text() # 格式为"速率: xxx"
rate_key = rate_text.split(":")[1].strip() # 提取"128kpbs"等关键部分
# 3. 获取对应的间隔时间(默认1秒)
interval = rate_interval_map.get(rate_key, 1000)
# 4. 启动定时器(使用动态计算的间隔)
self.send_timer.start(interval)
# 定义循环发送逻辑
def send_image_cycle():
# 读取按钮状态
switch_text = self.toggleButton.text()
id_text = self.idButton.text()
slot_text = self.slotButton.text()
rate_text = self.rateButton.text()
toid_text = self.toidButton.text()
# 构建当前图片指令
cmd_str = self.buildimageCommand(
switch_text, toid_text, rate_text, slot_text, self.image_index
)
print(f"第{self.cycle_count + 1}次循环,图片{self.image_index + 1}: {cmd_str}")
# 发送数据
data_bytes = self.parseSendData(
cmd_str,
encoding=self.configGlobal["encoding"],
isHexStr=True
)
if data_bytes:
self.send(data_bytes, callback=self.onSent)
# 切换图片索引(0<->1)
self.image_index = 1 - self.image_index
# 当图片索引回到0时,代表完成一次完整循环(图片1+图片2)
if self.image_index == 0:
self.cycle_count += 1
# 达到5次循环则停止
if self.cycle_count >= 5:
self.send_timer.stop()
sendBtn.setEnabled(True) # 恢复按钮可用
print("循环发送完成")
# 绑定定时器触发事件
self.send_timer.timeout.connect(send_image_cycle)
# 绑定按钮点击事件(启动循环)
sendBtn.clicked.connect(start_image_cycle)
layout.addWidget(label)
layout.addWidget(sendBtn)
self.customSendItemsLayout.addWidget(totalControlWidget, 3, 2, 1, 2 )
elif item["caption"] == "配置发送":
totalControlWidget = QWidget()
layout = QHBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
totalControlWidget.setLayout(layout)
sendBtn = QPushButton("")
label = QLabel("配置发送")
utils_ui.setButtonIcon(sendBtn, item.get("icon", "fa.send"))
sendBtn.setProperty("class", "smallBtn")
def sendTotalControl():
# 读取4个按钮当前文本
switch_text = self.toggleButton.text()
id_text = self.idButton.text()
slot_text = self.slotButton.text()
rate_text = self.rateButton.text()
# 动态构造指令字符串S
cmd_str = self.buildBindCommand(switch_text, id_text, rate_text, slot_text)
print(f"配置发送: {cmd_str}")
data_bytes = self.parseSendData(cmd_str,
encoding=self.configGlobal["encoding"],
isHexStr=True)
if data_bytes:
self.send(data_bytes, callback=self.onSent)
sendBtn.clicked.connect(sendTotalControl)
layout.addWidget(label)
layout.addWidget(sendBtn)
self.customSendItemsLayout.addWidget(totalControlWidget, 1, 2, 1, 2)
# 第三行放4个状态标签
self.customSendItemsLayout.addWidget(self.networkStatusLabel, 2, 0)
self.customSendItemsLayout.addWidget(self.networkPhaseLabel, 2, 1)
self.customSendItemsLayout.addWidget(self.networkvoltageLabel, 2, 2)
self.customSendItemsLayout.addWidget(self.networktemLabel, 2, 3)
def insertSendItem(self, item = None, load = False):
caption = item["caption"]
itemWidget = QWidget()
layout = QHBoxLayout()
layout.setContentsMargins(0,0,0,0)
itemWidget.setLayout(layout)
send = QPushButton("")
label = QLabel(caption)
if (not "icon" in item) or not item["icon"]:
item["icon"] = "fa.send"
utils_ui.setButtonIcon(send, item["icon"])
send.setProperty("class", "smallBtn")
def sendCustomData(idx):
self.sendCustomItem(self.config["customSendItems"][idx])
send.clicked.connect(lambda: sendCustomData(self.customSendItemsLayout.indexOf(itemWidget)))
layout.addWidget(label)
layout.addWidget(send)
count = self.customSendItemsLayout.count()
row = count // 4 # 每 4 个换行
col = count % 4
self.customSendItemsLayout.addWidget(itemWidget,row,col)
if not load:
self.config["customSendItems"].append(item)
return item
def onReceived(self, data: bytes):
print('>')
print(data)
self.statusBar.addRx(len(data)) # 确保self在此处有定义(类成员)
# 新增:判断数据类型并获取二进制帧数据
binary_data = None
try:
# 尝试解码为十六进制字符串(处理第一种格式)
hex_str = data.decode('utf-8')
# 清理空格和换行
cleaned_hex = hex_str.replace(' ', '').replace('\n', '').replace('\r', '')
# 验证是否为有效的十六进制字符
if all(c in '0123456789ABCDEFabcdef' for c in cleaned_hex):
binary_data = bytes.fromhex(cleaned_hex)
print(f"转换后的二进制数据长度: {len(binary_data)} 字节")
else:
# 不是纯十六进制字符串,视为原始二进制数据
binary_data = data
except UnicodeDecodeError:
# 解码失败,说明是原始二进制数据(处理第二种格式)
binary_data = data
print(f"直接使用原始二进制数据,长度: {len(binary_data)} 字节")
except ValueError as e:
print(f"十六进制转换失败: {e}")
return
if not binary_data:
print("无有效二进制数据")
return
# 第二步:对二进制帧数据解析指令
try:
# 帧头为0x5A54(即b'ZT'),前2字节为帧头,第3字节为cmd_id
if len(binary_data) >= 3 and binary_data[:2] == b'\x5A\x54':
cmd_id = binary_data[2]
print(f"收到指令: cmd_id=0x{cmd_id:02X}")
if cmd_id == 0xE5: # 图像测试回令
result = self.evalimageTestRsp(binary_data)
self.showReceiveDataSignal.emit(result)
return
elif cmd_id == 0xE1: # 自检回令
result = self.evalSelfTestRsp(binary_data)
self.showReceiveDataSignal.emit(result)
return
else:
print("未匹配帧头(5A54),进入PNG解析逻辑")
except Exception as e:
print(f"指令解析失败: {e}")
# 第三步:PNG解析逻辑
if not hasattr(self, "png_buffer"):
self.png_buffer = bytearray()
self.png_buffer.extend(binary_data) # 使用处理后的二进制数据累积
png_start = self.png_buffer.find(b'\x89PNG\r\n\x1a\n')
print(f"png_start: {png_start}")
if png_start != -1:
png_candidate = self.png_buffer[png_start:]
iend_pos = png_candidate.rfind(b'IEND\xae\x42\x60\x82')
if iend_pos != -1:
complete_png = png_candidate[:iend_pos + 8]
for widget in self.widgets:
widget.onData(complete_png)
self.png_buffer.clear()
else:
pass
else:
# 超过一定长度仍未找到PNG头则清空,避免内存溢出
if len(self.png_buffer) > 1024 * 1024: # 1MB阈值
self.png_buffer.clear()
def printFrame(self, data: bytes):
ret = ''
for i in range(len(data)):
ret += f'{data[i]:02X}'
ret += '\n' if i%16 == 15 else ' '
ret += '\n'
return ret
def evalSelfTestRsp(self, data: bytes):
print('“”“”“”“”“”“”“”“”“”“”“”“')
try:
# 1. 先解析头部获取数据长度和图片类型标识
header_struct = Struct("<2s B B") # 前11字节结构
header_data = header_struct.unpack(data[:4])
frame_head, cmd_id, node_type= header_data
print(data)
print(header_data)
img_flag = data[7:8] # 第八个字节
print('m')
# 3. 动态构建完整结构体
struct_format = f"<2s B B BBBBbbb 2B 2B 2B BBbBB 3s B B B 2s"
full_struct = Struct(struct_format)
print('km')
# 计算结构体要求的总长度
required_len = 30 # 头部11 + 数据段data_len + 尾部5
print(f"预期长度: {required_len}, 实际数据长度: {len(data)}")
payload = full_struct.unpack(data)
print('lm')
except Exception as e:
print('x')
return f"\n### evalselfTestRsp:: Failed to unpack data (data length {len(data)} byte).\n错误信息: {str(e)}"
ret = "----------- 自检回令 -----------\n"
ret += f"节点编号: 0x{payload[-2]:02X}\n"
ret += "节点状态: "
if payload[3] == 0xAA:
ret += f"正常 (0x{payload[3]:02X})\n"
network_status='正常'
elif payload[6] == 0x55:
ret += f"异常 (0x{payload[3]:02X})\n"
network_status='异常'
else:
ret += f"【未知错误】(0x{payload[3]:02X})\n"
network_status='未知错误'
hwOffset = 4
ret += f"FPGA 电压监测: {bin(payload[hwOffset+0])[2:].zfill(8)}\n"
ret += f"时钟锁定状态: {bin(payload[hwOffset+1])[2:].zfill(8)}\n"
ret += f"AD 锁定状态: {bin(payload[hwOffset+2])[2:].zfill(8)}\n"
ret += f"AD 温度 1: {payload[hwOffset+3]:>4d}\n"
ret += f"AD 温度 2: {payload[hwOffset+4]:>4d}\n"
ret += f"FPGA 温度: {payload[hwOffset+5]:>4d}\n"
ret += f"天线-1 工作 PLL: {(payload[hwOffset+6] >> 15) & 0x01:>1d}\n"
ret += f"天线-1 工作频率: {(payload[hwOffset+6] & 0x7FFF)+3700:>4d}\n"
print(payload[3])
ret += f"天线-2 工作 PLL: {(payload[hwOffset+7] >> 15) & 0x01:>1d}\n"
ret += f"天线-2 工作频率: {(payload[hwOffset+7] & 0x7FFF)+3700:>4d}\n"
print(payload[3])
ret += f"天线-3 工作 PLL: {(payload[hwOffset+8] >> 15) & 0x01:>1d}\n"
ret += f"天线-3 工作频率: {(payload[hwOffset+8] & 0x7FFF)+3700:>4d}\n"
print(payload[3])
ret += f"天线 PLL 锁定状态: {bin(payload[hwOffset+9])[2:].zfill(8)}\n"
print(payload[3])
ret += f"天线工作模式: {bin(payload[hwOffset+10])[2:].zfill(8)}\n"
ret += f"天线温度: {payload[hwOffset+11]:>4d}\n"
print(payload[3])
ret += "--------------------------------\n"
print(payload[3])
print(network_status)
phase=payload[14]
temp=payload[9]
voltage=payload[4]
self.networkStatusLabel.setText(f"节点状态: {network_status}")
self.networkPhaseLabel.setText(f"天线温度: {phase}")
self.networkvoltageLabel.setText(f"电压状态: {voltage}")
self.networktemLabel.setText(f"fgpa温度: {temp}")
return ret + '\n' + self.printFrame(data)
def evalimageTestRsp(self, data: bytes):
print('“”“”“”“”“”“”“”“”“”“”“”“')
try:
# 1. 先解析头部获取数据长度和图片类型标识
header_struct = Struct("<2s B B I B H") # 前11字节结构
header_data = header_struct.unpack(data[:11])
frame_head, cmd_id, node_type, data_id, from_id, data_len = header_data
print(data)
print(header_data)
print(data_len)
# 2. 获取第八个字节的图片类型标识(01/02)
img_flag = data[7:8] # 第八个字节
print('m')
# 3. 动态构建完整结构体
struct_format = f"<2s B B I B H {data_len}s B B B 2s"
full_struct = Struct(struct_format)
print('km')
# 计算结构体要求的总长度
required_len = 11 + data_len + 5 # 头部11 + 数据段data_len + 尾部5
print(f"预期长度: {required_len}, 实际数据长度: {len(data)}")
payload = full_struct.unpack(data)
print('lm')
except Exception as e:
print('x')
return f"\n### evalimageTestRsp:: Failed to unpack data (data length {len(data)} byte).\n错误信息: {str(e)}"
ret = "----------- 图像测试回令 -----------\n"
# 字段索引对应(保留原始变量名)
frame_head = payload[0] # bytes: 2 字节帧头
cmd_id = payload[1] # int: 1 字节指令
node_type = payload[2] # int: 1 字节节点类型
data_id = payload[3] # int: 4 字节数据 ID
from_id = payload[4] # int: 1 字节源节点 ID
data_len = payload[5] # int: 2 字节数据长度
image_data = payload[6] # bytes: 动态长度
padding = payload[7] # int: 1 字节填充
checksum = payload[8] # int: 1 字节校验和
data_len2 = payload[9] # int: 1 字节数据段长度
frame_tail = payload[10] # bytes: 2 字节帧尾
# 格式化输出(保留原始输出格式)
ret += f"帧头: {frame_head.hex().upper()} (ascii: {frame_head.decode(errors='ignore')})\n"
ret += f"指令: 0x{cmd_id:02X}\n"
ret += f"节点类型: 0x{node_type:02X}\n"
ret += f"数据 ID: 0x{data_id:08X}\n"
ret += f"源节点 ID: {from_id}\n"
ret += f"数据长度字段: {data_len} 字节\n"
ret += f"数据段实际长度: {len(image_data)} 字节\n"
ret += f"填充字节: 0x{padding:02X}\n"
ret += f"校验和: 0x{checksum:02X}\n"
ret += f"数据段长度: {data_len2} (十六进制: 0x{data_len2:02X})\n"
ret += f"帧尾: {frame_tail.hex().upper()}\n"
print('&&&&&')
# 图像显示逻辑(添加缩放倍数控制)
# 1. 手动设置缩放倍数(可根据需要修改,例如放大2倍)
# 图像显示逻辑(修正后)
if from_id == 0x01 or from_id == 0x02:
# 图像通道 A → 左侧图像控件
if len(self.widgets) >= 1 and isinstance(self.widgets[0], graphWidgets["image"]):
# 仅传递图像数据,缩放倍数已在控件初始化时通过config设置
self.widgets[0].onData(image_data)
else:
self.showReceiveDataSignal.emit("\n### No valid image widget found (A1)\n")
elif from_id == 0x03:
# 图像通道 B → 右侧图像控件
if len(self.widgets) >= 2 and isinstance(self.widgets[1], graphWidgets["image"]):
# 仅传递图像数据
self.widgets[1].onData(image_data)
else:
self.showReceiveDataSignal.emit("\n### No valid image widget found (A2)\n")
print(from_id)
print('+')
ret += "------------------------------------\n"
return ret + '\n' + self.printFrame(data)
print(from_id)
print('+')
ret += "------------------------------------\n"
return ret + '\n' + self.printFrame(data)
def onSent(self, ok, msg, length, path):
if ok:
self.statusBar.addTx(length)
else:
self.hintSignal.emit("error", _("Error"), _("Send data failed!") + " " + msg)
def sendCustomItem(self, item):
data = item["data"]
dateBytes = self.parseSendData(data, encoding = self.configGlobal["encoding"], isHexStr = True)
if dateBytes:
self.send(dateBytes, callback=self.onSent)
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -1535,10 +1535,10 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
status = ad9361_reg_write(dev, 0x0105, 0x3A); // ADC Large Overload Threshold
status = ad9361_reg_write(dev, 0x0107, 0x2B); // Small LMT Overload Threshold
status = ad9361_reg_write(dev, 0x0108, 0x31); // Large LMT Overload Threshold
status = ad9361_reg_write(dev, 0x0109, 0x00); // Rx1 Full/LMT Gain Index
status = ad9361_reg_write(dev, 0x0109, 0x28); // Rx1 Full/LMT Gain Index
status = ad9361_reg_write(dev, 0x010A, 0x58); // Rx1 LPF Gain Index
status = ad9361_reg_write(dev, 0x010B, 0x00); // Rx1 Digital Gain Index
status = ad9361_reg_write(dev, 0x010C, 0x00); // Rx2 Full/LMT Gain Index
status = ad9361_reg_write(dev, 0x010C, 0x28); // Rx2 Full/LMT Gain Index
status = ad9361_reg_write(dev, 0x010D, 0x18); // Rx2 LPF Gain Index
status = ad9361_reg_write(dev, 0x010E, 0x00); // Rx2 Digital Gain Index
status = ad9361_reg_write(dev, 0x0114, 0x30); // Low Power Threshold
+4 -4
View File
@@ -259,10 +259,10 @@ int32_t Hardware_Init(void)
// Status = ad9361_reg_read(ad9361_1_reg_inst, 0x0002, &rd_back);
// Status = ad9361_reg_read(ad9361_2_reg_inst, 0x0002, &rd_back);
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0109, 0x00); // Rx Gain
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x010C, 0x00); // Rx Gain
Status = ad9361_reg_write(ad9361_2_reg_inst, 0x0109, 0x00); // Rx Gain
Status = ad9361_reg_write(ad9361_2_reg_inst, 0x010C, 0x00); // Rx Gain
// Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0109, 0x00); // Rx Gain
// Status = ad9361_reg_write(ad9361_1_reg_inst, 0x010C, 0x00); // Rx Gain
// Status = ad9361_reg_write(ad9361_2_reg_inst, 0x0109, 0x00); // Rx Gain
// Status = ad9361_reg_write(ad9361_2_reg_inst, 0x010C, 0x00); // Rx Gain
#endif
#ifdef AD9653
+40 -16
View File
@@ -77,8 +77,10 @@ struct callback_desc apptimer_callback_desc = {
// .myType = L2_NODE_HEAD,
// .clustId = 1U,
// .myId = 1U,
// .headId = 1U,
// .netScale = 10U,
// .headId = L2_HEAD_ID,
// .netScale = L2_NET_SCALE,
// .initTable = initRoutTable,
// .normalTable = normalRoutTable1,
// .serviceRate = L2_SVC_512K,
// .phyInstPtr = NULL, // physical layer reference
// .tmcInstPtr = NULL
@@ -88,8 +90,10 @@ L2_CONFIG linkConfig = {
.myType = L2_NODE_MEMBER,
.clustId = 1U,
.myId = 2U,
.headId = 1U,
.netScale = 10U,
.headId = L2_HEAD_ID,
.netScale = L2_NET_SCALE,
.initTable = initRoutTable,
.normalTable = normalRoutTable1,
.serviceRate = L2_SVC_512K,
.phyInstPtr = NULL, // physical layer reference
.tmcInstPtr = NULL
@@ -128,8 +132,8 @@ static SYSBUS_CONFIG sysbusConfig = {
};
static SYSMON_CONFIG sysmonConfig = {
.sendQueueMax = 32U,
.recvQueueMax = 32U
.sendQueueMax = 16U,
.recvQueueMax = 16U
};
/*********************** Driver Instance Definitions **************************/
@@ -198,6 +202,7 @@ int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr)
XScuGic_CPUWriteReg((XScuGic *)(xil_dev->instance), XSCUGIC_EOI_OFFSET, intrState);
/* Initialize physical layer interrupt. */
// Set interrupt trigger level
Status = irq_trigger_level_set(descPtr, PHY_INTR_ID, IRQ_EDGE_RISING);
if (Status != SUCCESS)
{
@@ -220,6 +225,7 @@ int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr)
}
/* Initialize linklayer layer interrupt. */
// Set interrupt trigger level
Status = irq_trigger_level_set(descPtr, PERIODIC_5MS_INTR_ID, IRQ_EDGE_RISING);
if (Status != SUCCESS)
{
@@ -242,17 +248,18 @@ int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr)
}
/* Initialize system bus interrupt. */
// Set interrupt trigger level
Status = irq_trigger_level_set(descPtr, SYSBUS_TX_INTR_ID, IRQ_EDGE_RISING);
if (Status != SUCCESS)
{
DBG_ERROR("PHY_INTR trigger level set FAILED, ErrorCode: %" PRId32 ".\n", Status);
DBG_ERROR("SYSBUS_TX_INTR trigger level set FAILED, ErrorCode: %" PRId32 ".\n", Status);
return Status;
}
// Set interrupt priority
Status = irq_set_priority(descPtr, SYSBUS_TX_INTR_ID, 0x10);
if (Status != SUCCESS)
{
DBG_ERROR("PHY_INTR priority level set FAILED, ErrorCode: %" PRId32 ".\n", Status);
DBG_ERROR("SYSBUS_TX_INTR priority level set FAILED, ErrorCode: %" PRId32 ".\n", Status);
return Status;
}
@@ -260,20 +267,22 @@ int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr)
Status = irq_register_callback(descPtr, SYSBUS_TX_INTR_ID, &sysbus_tx_callback_desc);
if (Status != SUCCESS)
{
DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status);
DBG_ERROR("SYSBUS_TX_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status);
return Status;
}
// Set interrupt trigger level
Status = irq_trigger_level_set(descPtr, SYSBUS_RX_INTR_ID, IRQ_EDGE_RISING);
if (Status != SUCCESS)
{
DBG_ERROR("PHY_INTR trigger level set FAILED, ErrorCode: %" PRId32 ".\n", Status);
DBG_ERROR("SYSBUS_RX_INTR trigger level set FAILED, ErrorCode: %" PRId32 ".\n", Status);
return Status;
}
// Set interrupt priority
Status = irq_set_priority(descPtr, SYSBUS_RX_INTR_ID, 0x18);
if (Status != SUCCESS)
{
DBG_ERROR("PHY_INTR priority level set FAILED, ErrorCode: %" PRId32 ".\n", Status);
DBG_ERROR("SYSBUS_RX_INTR priority level set FAILED, ErrorCode: %" PRId32 ".\n", Status);
return Status;
}
@@ -281,7 +290,7 @@ int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr)
Status = irq_register_callback(descPtr, SYSBUS_RX_INTR_ID, &sysbus_rx_callback_desc);
if (Status != SUCCESS)
{
DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status);
DBG_ERROR("SYSBUS_RX_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status);
return Status;
}
@@ -290,7 +299,7 @@ int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr)
Status = irq_register_callback(descPtr, APPTIMER_INTR_ID, &apptimer_callback_desc);
if (Status != SUCCESS)
{
DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status);
DBG_ERROR("APPTIMER_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status);
return Status;
}
@@ -418,9 +427,24 @@ void AppTimer_IntrHandler(void *context)
{
Phy_UpdateLogging(phyInstPtr);
}
/*
* Read the new Control/Status Register content.
*/
uint32_t ControlStatusReg;
ControlStatusReg = XTmrCtr_ReadReg(((XTmrCtr *)xdesc->instance)->BaseAddress,
0, XTC_TCSR_OFFSET);
/*
* Acknowledge the interrupt by clearing the
* interrupt bit in the timer control status
* register, this is done after calling the
* handler so the application could call
* IsExpired, the interrupt is cleared by
* writing a 1 to the interrupt bit of the
* register without changing any of the other
* bits
*/
XTmrCtr_WriteReg(((XTmrCtr *)xdesc->instance)->BaseAddress, 0,
XTC_TCSR_OFFSET, XTC_CSR_INT_OCCURED_MASK);
XTC_TCSR_OFFSET, ControlStatusReg | XTC_CSR_INT_OCCURED_MASK);
}
#else
#error No timer implementation!
@@ -542,7 +566,7 @@ int main(void)
}
// Start System Monitor logging.
timer_start(logTmPtr);
Status = timer_start(logTmPtr);
DBG_PRINT("Physical started...\n");
Phy_Start(phyInstPtr);
+9 -9
View File
@@ -28,7 +28,7 @@
#include "circ_queue.h"
#include "../time_ctrl/time_ctrl.h"
#ifndef EMULATION
#include "../config/app_config.h"
#include "../../config/app_config.h"
#endif
/************************** Constant Definitions *****************************/
#define NET_START_TIME_INFTY UINT32_MAX
@@ -601,8 +601,8 @@ int32_t Linklayer_Init(L2_INST **instPtr, const L2_CONFIG *config)
(*instPtr)->tor.last = L2_TOR_SUSPEND;
(*instPtr)->tor.curr = L2_TOR_SUSPEND;
(*instPtr)->tor.next = L2_TOR_SUSPEND;
(*instPtr)->rtneConfig.rtneTable = initTable;
(*instPtr)->rtneConfig.rtnePrd = ARRAY_SIZE(initTable);
(*instPtr)->rtneConfig.rtneTable = (*instPtr)->config.initTable;
(*instPtr)->rtneConfig.rtnePrd = ARRAY_SIZE(initRoutTable);
(*instPtr)->mainState = L2_INIT_STATE;
(*instPtr)->nextState = L2_INIT_STATE;
(*instPtr)->myInfo.nodeId = config->myId;
@@ -698,8 +698,8 @@ int32_t Linklayer_Reconfig(L2_INST *instPtr, const L2_CONFIG *config)
instPtr->tor.last = L2_TOR_SUSPEND;
instPtr->tor.curr = L2_TOR_SUSPEND;
instPtr->tor.next = L2_TOR_SUSPEND;
instPtr->rtneConfig.rtneTable = initTable;
instPtr->rtneConfig.rtnePrd = ARRAY_SIZE(initTable);
instPtr->rtneConfig.rtneTable = instPtr->config.initTable;
instPtr->rtneConfig.rtnePrd = ARRAY_SIZE(initRoutTable);
instPtr->mainState = L2_INIT_STATE;
instPtr->nextState = L2_INIT_STATE;
instPtr->myInfo.nodeId = config->myId;
@@ -883,14 +883,14 @@ int32_t Linklayer_EventHandler(L2_INST *instPtr, const L2_EVENT *l2Event)
// Reset scan net FMS for next scan process.
L2_Scan_Reset(instPtr->scanFSM);
UpdateMainSate(instPtr, L2_INIT_STATE);
// instPtr->rtneConfig.rtneTable = initTable;
// instPtr->rtneConfig.rtnePrd = ARRAY_SIZE(initTable);
instPtr->rtneConfig.rtneTable = instPtr->config.initTable;
instPtr->rtneConfig.rtnePrd = ARRAY_SIZE(initRoutTable);
}
else if (instPtr->nextState == L2_NORMAL_STATE)
{
UpdateMainSate(instPtr, L2_NORMAL_STATE);
// instPtr->rtneConfig.rtneTable = normalTable0;
// instPtr->rtneConfig.rtnePrd = ARRAY_SIZE(normalTable0);
instPtr->rtneConfig.rtneTable = instPtr->config.normalTable;
instPtr->rtneConfig.rtnePrd = ARRAY_SIZE(normalRoutTable1);
}
else
{
+8 -4
View File
@@ -45,6 +45,8 @@ typedef struct
uint8_t headId; ///< head node id
uint8_t netScale; ///< net scale
L2_SVC_RATE serviceRate; ///< service data rate
L2_RTNE_TABLE_ENTRY **initTable;
L2_RTNE_TABLE_ENTRY **normalTable;
PHY_INST *phyInstPtr; ///< pointer to system physical layer instance
TMC_INST *tmcInstPtr; ///< pointer to system timer controller layer instance
} L2_CONFIG;
@@ -93,6 +95,8 @@ typedef struct
int64_t timeDev; ///< last time deviation estimation result
uint32_t reconnectCnt; ///< reconnect trial count
uint32_t txValidMsgCnt; ///< non-default tx message count
uint32_t rxValidMsgCnt; ///< non-default rx message count
L2_MSG_RECORD rxLog;
L2_MSG_RECORD txLog;
} L2_LOG;
@@ -129,10 +133,10 @@ typedef struct
} L2_INST;
/************************** Variable Definitions *****************************/
extern L2_RTNE_TABLE_ENTRY *initTable[L2_INIT_RTNE_PERIOD];
extern L2_RTNE_TABLE_ENTRY *normalTable0[L2_INIT_RTNE_PERIOD];
extern L2_RTNE_TABLE_ENTRY *normalTable1[L2_INIT_RTNE_PERIOD];
extern L2_RTNE_TABLE_ENTRY *normalTable2[L2_INIT_RTNE_PERIOD];
extern L2_RTNE_TABLE_ENTRY *initRoutTable[L2_INIT_RTNE_PERIOD];
extern L2_RTNE_TABLE_ENTRY *normalRoutTable1[L2_INIT_RTNE_PERIOD];
extern L2_RTNE_TABLE_ENTRY *normalRoutTable2[L2_INIT_RTNE_PERIOD];
extern L2_RTNE_TABLE_ENTRY *normalRoutTable3[L2_INIT_RTNE_PERIOD];
/************************** Function Prototypes ******************************/
/**
* @defgroup LinkLayer_Main
+4 -3
View File
@@ -25,7 +25,7 @@
#include "geometry/quaternion.h"
#include "../phy_layer/phy_layer.h"
#ifndef EMULATION
#include "../config/app_config.h"
#include "../../config/app_config.h"
#endif
/************************** Constant Definitions *****************************/
/**
@@ -37,8 +37,9 @@
#define L2_BROADCAST_ID2 0xF2
#define L2_BROADCAST_ID3 0xF4
#define L2_UNICAST_ID 0xF0
#define L2_NONE_ID 0
#define L2_HEAD_ID 0x01
#define L2_NONE_ID 0U
#define L2_HEAD_ID 1U
#define L2_NET_SCALE 10U
// Routine configure
#define L2_INIT_RTNE_PERIOD 1
+4 -4
View File
@@ -853,22 +853,22 @@ L2_RTNE_TABLE_ENTRY tab3Mng3Svc[L2_SLOTS_PER_FRAME] =
{L2_SLOT_IDLE, 0x00, 0x00, 0x00}
};
L2_RTNE_TABLE_ENTRY *initTable[L2_INIT_RTNE_PERIOD] =
L2_RTNE_TABLE_ENTRY *initRoutTable[L2_INIT_RTNE_PERIOD] =
{
tab10Mng10Svc
};
L2_RTNE_TABLE_ENTRY *normalTable0[L2_INIT_RTNE_PERIOD] =
L2_RTNE_TABLE_ENTRY *normalRoutTable1[L2_INIT_RTNE_PERIOD] =
{
tab10Mng10Svc
};
L2_RTNE_TABLE_ENTRY *normalTable1[L2_INIT_RTNE_PERIOD] =
L2_RTNE_TABLE_ENTRY *normalRoutTable2[L2_INIT_RTNE_PERIOD] =
{
tab10Mng3Svc
};
L2_RTNE_TABLE_ENTRY *normalTable2[L2_INIT_RTNE_PERIOD] =
L2_RTNE_TABLE_ENTRY *normalRoutTable3[L2_INIT_RTNE_PERIOD] =
{
tab3Mng3Svc
};
+17 -7
View File
@@ -256,6 +256,7 @@ int32_t L2_Scan_PktHandler(L2_INST *instPtr, uint8_t *msg)
recvPayload->dataLen = message->dataLen;
memcpy(recvPayload->data, message->data, message->dataLen);
SysMonitor_GenRecvRsp(recvPayload);
free(recvPayload);
}
// Logging...
@@ -276,7 +277,7 @@ int32_t L2_Scan_PktHandler(L2_INST *instPtr, uint8_t *msg)
L2_MSG_ACK *message = (L2_MSG_ACK *)msg;
size_t msgLen = sizeof(L2_MSG_ACK);
size_t dataLen = L2_PAYLOAD_LEN_ACK;
size_t maxDataLen = L2_PAYLOAD_LEN_ACK;
// Update node status.
uint8_t nodeId = message->common.src;
@@ -326,12 +327,21 @@ int32_t L2_Scan_PktHandler(L2_INST *instPtr, uint8_t *msg)
}
// Get data payload & upload
SYSBUS_SVC_PLD recvPayload;
recvPayload.dataId = message->dataId;
recvPayload.nodeId = message->common.src;
recvPayload.dataLen = message->dataLen;
memcpy(recvPayload.data, message->data, dataLen);
SysMonitor_GenRecvRsp(&recvPayload);
if (message->dataId != DATA_ID_NONE)
{
if (message->dataLen > maxDataLen)
{
DBG_ERROR("Payload length" PRIu16 " out of range.\n", message->dataLen);
return EIGNORE;
}
SYSBUS_SVC_PLD *recvPayload = calloc(1, sizeof(SYSBUS_SVC_PLD));
recvPayload->dataId = message->dataId;
recvPayload->nodeId = message->common.src;
recvPayload->dataLen = message->dataLen;
memcpy(recvPayload->data, message->data, message->dataLen);
SysMonitor_GenRecvRsp(recvPayload);
free(recvPayload);
}
// Logging...
instPtr->log.rxLog.dataId = message->dataId;
+19 -7
View File
@@ -29,7 +29,7 @@
#include "common.h"
#include "circ_queue.h"
#ifndef EMULATION
#include "../config/app_config.h"
#include "../../config/app_config.h"
#endif
/************************** Constant Definitions *****************************/
/***************** Macros (Inline Functions) Definitions *********************/
@@ -201,7 +201,7 @@ static int32_t Service_Packing128K(L2_INST *instPtr, L2_FRAME_TYPE type, uint8_t
{
// Packing extra payload
SYSBUS_SVC_PLD *sendPayload;
SysMonitor_GetSendPayload(&sendPayload);
SysMonitor_GetSendPayload(&sendPayload, dstId);
if(sendPayload == NULL)
{
message->common.dst = L2_NONE_ID;
@@ -211,13 +211,14 @@ static int32_t Service_Packing128K(L2_INST *instPtr, L2_FRAME_TYPE type, uint8_t
}
else
{
// message->common.dst = sendPayload->nodeId;
message->dataId = sendPayload->dataId;
message->dataLen = sendPayload->dataLen;
memset(message->data, 0xAA, maxDataLen);
memcpy(message->data, sendPayload->data, (sendPayload->dataLen > maxDataLen) ?
maxDataLen : sendPayload->dataLen);
free(sendPayload);
// logging
instPtr->log.txValidMsgCnt++;
}
}
else
@@ -279,7 +280,7 @@ static int32_t Service_Packing512K(L2_INST *instPtr, L2_FRAME_TYPE type, uint8_t
// Pack extra payload
SYSBUS_SVC_PLD *sendPayload;
SysMonitor_GetSendPayload(&sendPayload);
SysMonitor_GetSendPayload(&sendPayload, dstId);
if(sendPayload == NULL)
{
message->common.dst = L2_NONE_ID;
@@ -289,13 +290,14 @@ static int32_t Service_Packing512K(L2_INST *instPtr, L2_FRAME_TYPE type, uint8_t
}
else
{
// message->common.dst = sendPayload->nodeId;
message->dataId = sendPayload->dataId;
message->dataLen = sendPayload->dataLen;
memset(message->data, 0xAA, maxDataLen);
memcpy(message->data, sendPayload->data, (sendPayload->dataLen > maxDataLen) ?
maxDataLen : sendPayload->dataLen);
free(sendPayload);
// logging
instPtr->log.txValidMsgCnt++;
}
// Append CRC
@@ -349,7 +351,7 @@ static int32_t Service_Packing2M(L2_INST *instPtr, L2_FRAME_TYPE type, uint8_t d
// Packing extra payload
SYSBUS_SVC_PLD *sendPayload;
SysMonitor_GetSendPayload(&sendPayload);
SysMonitor_GetSendPayload(&sendPayload, dstId);
if(sendPayload == NULL)
{
message->common.dst = L2_NONE_ID;
@@ -359,13 +361,14 @@ static int32_t Service_Packing2M(L2_INST *instPtr, L2_FRAME_TYPE type, uint8_t d
}
else
{
// message->common.dst = sendPayload->nodeId;
message->dataId = sendPayload->dataId;
message->dataLen = sendPayload->dataLen;
memset(message->data, 0xAA, maxDataLen);
memcpy(message->data, sendPayload->data, (sendPayload->dataLen > maxDataLen) ?
maxDataLen : sendPayload->dataLen);
free(sendPayload);
// logging
instPtr->log.txValidMsgCnt++;
}
// Append CRC
@@ -541,6 +544,9 @@ static int32_t Service_PktHandler128K(L2_INST *instPtr, uint8_t *msg)
recvPayload->dataLen = message->dataLen;
memcpy(recvPayload->data, message->data, message->dataLen);
SysMonitor_GenRecvRsp(recvPayload);
free(recvPayload);
// logging
instPtr->log.rxValidMsgCnt++;
}
// Logging...
@@ -629,6 +635,9 @@ static int32_t Service_PktHandler512K(L2_INST *instPtr, uint8_t *msg)
recvPayload->dataLen = message->dataLen;
memcpy(recvPayload->data, message->data, message->dataLen);
SysMonitor_GenRecvRsp(recvPayload);
free(recvPayload);
// logging
instPtr->log.rxValidMsgCnt++;
}
// Logging...
@@ -717,6 +726,9 @@ static int32_t Service_PktHandler2M(L2_INST *instPtr, uint8_t *msg)
recvPayload->dataLen = message->dataLen;
memcpy(recvPayload->data, message->data, message->dataLen);
SysMonitor_GenRecvRsp(recvPayload);
free(recvPayload);
// logging
instPtr->log.rxValidMsgCnt++;
}
// Logging...
+5 -5
View File
@@ -292,11 +292,11 @@ const uint8_t hopPattern_512KBPS_4MS[L1_FRAME_512KBPS_4MS_HOPS] =
const uint8_t hopPattern_2MBPS_4MS[L1_FRAME_2MBPS_4MS_HOPS] =
{
16U, 17U, 18U, 19U, 20U, 21U, 20U, 20U,
20U, 20U, 20U, 20U, 20U, 20U, 20U, 20U,
20U, 20U, 20U, 20U, 20U, 20U, 20U, 20U,
20U, 20U, 20U, 20U, 20U, 20U, 20U, 20U,
20U, 20U, 20U, 20U, 20U, 20U,
16U, 17U, 18U, 19U, 20U, 21U, 10U, 10U,
10U, 10U, 10U, 10U, 10U, 10U, 10U, 10U,
10U, 10U, 10U, 10U, 10U, 10U, 10U, 10U,
10U, 10U, 10U, 10U, 10U, 10U, 10U, 10U,
10U, 10U, 10U, 10U, 10U, 10U,
};
/** @} PhysicalLayer_AntennaConfig_Constants*/
+51 -6
View File
@@ -696,6 +696,7 @@ int32_t Phy_SetupNextSlot(PHY_INST *instPtr, PHY_TOR_TYPE txrxMode,
ASSERT(instPtr != NULL);
int32_t Status;
uint32_t phyModeCtrl, hopNum;
uint16_t txMultifactor; // physical layer tx power digital attenuation
const uint8_t *hopPattern;
// Implement a ping-pong flow, offset always is 0 or half of buffer depth.
instPtr->antConfigOffset = (L1_ANTCONFIG_MAX_LEN >> 1) - instPtr->antConfigOffset;
@@ -717,34 +718,71 @@ int32_t Phy_SetupNextSlot(PHY_INST *instPtr, PHY_TOR_TYPE txrxMode,
}
switch (frameType)
{
#ifdef HSJL_GE
case L1_FRAME_ADV_24MS:
phyModeCtrl |= PHY_MODE_CTRL_FRAME_ADV_24MS;
hopNum = L1_FRAME_ADV_24MS_HOPS;
hopPattern = hopPattern_ADV_24MS;
txMultifactor = 0x1f00; // -12dB
break;
case L1_FRAME_ACK_8MS:
phyModeCtrl |= PHY_MODE_CTRL_FRAME_ACK_8MS;
hopNum = L1_FRAME_ACK_8MS_HOPS;
hopPattern = hopPattern_ACK_8MS;
txMultifactor = 0x1f00; // -12dB
break;
case L1_FRAME_128KBPS_4MS:
phyModeCtrl |= PHY_MODE_CTRL_FRAME_128KBPS_4MS;
hopNum = L1_FRAME_128KBPS_4MS_HOPS;
hopPattern = hopPattern_128KBPS_4MS;
txMultifactor = 0x2000; // -15dB
break;
case L1_FRAME_512KBPS_4MS:
phyModeCtrl |= PHY_MODE_CTRL_FRAME_512KBPS_4MS;
hopNum = L1_FRAME_512KBPS_4MS_HOPS;
hopPattern = hopPattern_512KBPS_4MS;
txMultifactor = 0x2000; // -12dB
break;
case L1_FRAME_2MBPS_4MS:
phyModeCtrl |= PHY_MODE_CTRL_FRAME_2MBPS_4MS;
hopNum = L1_FRAME_2MBPS_4MS_HOPS;
hopPattern = hopPattern_2MBPS_4MS;
txMultifactor = 0x7000; // -6dB, baseline
break;
#else
case L1_FRAME_ADV_24MS:
phyModeCtrl |= PHY_MODE_CTRL_FRAME_ADV_24MS;
hopNum = L1_FRAME_ADV_24MS_HOPS;
hopPattern = hopPattern_ADV_24MS;
txMultifactor = 0x0A00; // -12dB
break;
case L1_FRAME_ACK_8MS:
phyModeCtrl |= PHY_MODE_CTRL_FRAME_ACK_8MS;
hopNum = L1_FRAME_ACK_8MS_HOPS;
hopPattern = hopPattern_ACK_8MS;
txMultifactor = 0x0A00; // -12dB
break;
case L1_FRAME_128KBPS_4MS:
phyModeCtrl |= PHY_MODE_CTRL_FRAME_128KBPS_4MS;
hopNum = L1_FRAME_128KBPS_4MS_HOPS;
hopPattern = hopPattern_128KBPS_4MS;
txMultifactor = 0x0F00; // -15dB
break;
case L1_FRAME_512KBPS_4MS:
phyModeCtrl |= PHY_MODE_CTRL_FRAME_512KBPS_4MS;
hopNum = L1_FRAME_512KBPS_4MS_HOPS;
hopPattern = hopPattern_512KBPS_4MS;
txMultifactor = 0x1000; // -12dB
break;
case L1_FRAME_2MBPS_4MS:
phyModeCtrl |= PHY_MODE_CTRL_FRAME_2MBPS_4MS;
hopNum = L1_FRAME_2MBPS_4MS_HOPS;
hopPattern = hopPattern_2MBPS_4MS;
txMultifactor = 0x2000; // -6dB, baseline
break;
#endif
default:
return EPARAM;
break;
}
// Set frame configs
@@ -794,6 +832,9 @@ int32_t Phy_SetupNextSlot(PHY_INST *instPtr, PHY_TOR_TYPE txrxMode,
}
}
// Set tx multifactor
PhyWrite(instPtr, TX_MULFAC, txMultifactor);
// Trigger physical configuration.
// Indicate physical layer that all the configurations were done.
PhyWrite(instPtr, SLOT_CMD, SLOT_CMD_KEY);
@@ -1026,9 +1067,10 @@ void Phy_RefreshHwSate(PHY_INST *instPtr)
instPtr->hwSate.spFpgaTemp = (evalData > TEMPERATURE_MAX)
? INT8_MAX
: ((evalData < TEMPERATURE_MIN) ? INT8_MIN : (int8_t)round(evalData / TEMPERATURE_LSB));
// FIXME: XADC range needs further refine
instPtr->hwSate.spFpgaVolt = (VOLT_PS_OK | VOLT_PSAUX_OK | VOLT_DDR_OK | VOLT_PL_OK | VOLT_PLAUX_OK | VOLT_BRAM_OK);
instPtr->hwSate.isSpOk = (instPtr->hwSate.spFpgaVolt == (VOLT_PS_OK | VOLT_PSAUX_OK | VOLT_DDR_OK | VOLT_PL_OK | VOLT_PLAUX_OK | VOLT_BRAM_OK))
&& (instPtr->hwSate.spClkState == (CLK_SP_PLL1_LOCK | CLK_SP_PLL2_LOCK))
&& (instPtr->hwSate.spAdLockState == (CLK_AD0_BBPLL_LOCK | CLK_AD0_RFPLL_LOCK | CLK_AD1_BBPLL_LOCK | CLK_AD1_RFPLL_LOCK));
&& (instPtr->hwSate.spClkState == (CLK_SP_PLL1_LOCK | CLK_SP_PLL2_LOCK));
#else
double evalData;
instPtr->hwSate.isSpOk = true;
@@ -1106,9 +1148,12 @@ void Phy_RefreshHwSate(PHY_INST *instPtr)
// -- Update FPGA Chip temperature, unit 1 deg
rawData = XAdcPs_GetAdcData(&(instPtr->hwXadc), XADCPS_CH_TEMP);
evalData = XAdcPs_RawToTemperature(rawData);
instPtr->hwSate.spFpgaTemp = (evalData > TEMPERATURE_MAX)
? INT8_MAX
: ((evalData < TEMPERATURE_MIN) ? INT8_MIN : (int8_t)round(evalData / TEMPERATURE_LSB));
// instPtr->hwSate.spFpgaTemp = (evalData > TEMPERATURE_MAX)
// ? INT8_MAX
// : ((evalData < TEMPERATURE_MIN) ? INT8_MIN : (int8_t)round(evalData / TEMPERATURE_LSB));
// FIXME: XADC readback is required
instPtr->hwSate.spFpgaTemp = ((instPtr->hwSate.spAdTemp_0 - 5) + (instPtr->hwSate.spAdTemp_1 - 7)) / 2;
instPtr->hwSate.spFpgaVolt = (VOLT_PS_OK | VOLT_PSAUX_OK | VOLT_DDR_OK | VOLT_PL_OK | VOLT_PLAUX_OK | VOLT_BRAM_OK);
instPtr->hwSate.isSpOk = (instPtr->hwSate.spFpgaVolt == (VOLT_PS_OK | VOLT_PSAUX_OK | VOLT_DDR_OK | VOLT_PL_OK | VOLT_PLAUX_OK | VOLT_BRAM_OK))
&& (instPtr->hwSate.spClkState == (CLK_SP_PLL1_LOCK | CLK_SP_PLL2_LOCK))
&& (instPtr->hwSate.spAdLockState == (CLK_AD0_BBPLL_LOCK | CLK_AD0_RFPLL_LOCK | CLK_AD1_BBPLL_LOCK | CLK_AD1_RFPLL_LOCK));
+1 -1
View File
@@ -24,7 +24,7 @@
#include "common.h"
#ifndef EMULATION
#include "xbram.h"
#include "../config/app_config.h"
#include "../../config/app_config.h"
#ifdef HSJL_GE // Zynq MPSoC (Zynq UltraScale+)
#include "xsysmon.h"
#else
+9 -1
View File
@@ -207,7 +207,7 @@
/**
* Register: TM_TARGET_L
*/
#define TM_TARGET_L 0x00000064U
#define TM_TARGET_L 0x00000034U
#define TM_TARGET_L_SHIFT 0
#define TM_TARGET_L_WIDTH 32
#define TM_TARGET_L_MASK 0xFFFFFFFFU
@@ -260,6 +260,14 @@
#define ANT_SELECT_INDEX_WIDTH 32
#define ANT_SELECT_INDEX_MASK 0xFFFFFFFFU
/**
* Register: TX_MULFAC
*/
#define TX_MULFAC 0x00000048U
#define TX_MULFAC_SHIFT 0
#define TX_MULFAC_WIDTH 16
#define TX_MULFAC_MASK 0x0000FFFFU
/**
* Register: ANT_STATUS_1
*/
+63 -66
View File
@@ -27,6 +27,9 @@
#include "common.h"
#include "error.h"
#include "circ_queue.h"
// TODO: better approach?
#include "../networking/link_layer/link_layer.h"
#include "../networking/phy_layer/phy_layer.h"
/**
* @addtogroup SystemBus_Protocol_Routine
@@ -175,8 +178,8 @@ typedef struct
typedef struct
{
SYSMON_CONFIG config; ///< system monitor initialization parameters
CIRC_QUEUE *sendQueue; ///< send queue
CIRC_QUEUE *recvQueue; ///< receive queue
CIRC_QUEUE *sendQueue[L2_NET_SCALE]; ///< send queue
CIRC_QUEUE *recvQueue[L2_NET_SCALE]; ///< receive queue
PINGPONG sysInfoCtrl;
SYSINFO sysInfo[2];
PINGPONG linkLogCtrl;
@@ -196,8 +199,6 @@ static int32_t SystemBus_GenRemoteTestRsp(SYSBUS *instPtr, uint8_t *msg);
/**************************** Type Definitions *******************************/
/************************** Variable Definitions *****************************/
// TODO: better approach?
#include "../networking/link_layer/link_layer.h"
#include "../networking/phy_layer/phy_layer.h"
extern L2_INST *linkInstPtr;
extern L2_CONFIG linkConfig;
extern SYSBUS *sysbusDescPtr;
@@ -339,6 +340,45 @@ static int32_t SystemBus_SystemConfig(SYSBUS *instPtr, uint8_t *msg)
}
}
// Routing table selection
if (msg[WD_RTNE_CMD] != instPtr->sysbusLog.lastConfig[3])
{
switch (msg[WD_RTNE_CMD])
{
case 1:
{
reconfig |= (linkConfig.initTable != normalRoutTable1);
reconfig |= (linkConfig.normalTable != normalRoutTable1);
linkConfig.initTable = normalRoutTable1;
linkConfig.normalTable = normalRoutTable1;
break;
}
case 2:
{
reconfig |= (linkConfig.initTable != normalRoutTable2);
reconfig |= (linkConfig.normalTable != normalRoutTable2);
linkConfig.initTable = normalRoutTable2;
linkConfig.normalTable = normalRoutTable2;
break;
}
case 3:
{
reconfig |= (linkConfig.initTable != normalRoutTable3);
reconfig |= (linkConfig.normalTable != normalRoutTable3);
linkConfig.initTable = normalRoutTable3;
linkConfig.normalTable = normalRoutTable3;
break;
}
default:
{
// Ignore current command
DBG_ERROR("Unexpected config command 0x%02X:0x%02X",
WD_RTNE_CMD, msg[WD_RTNE_CMD]);
return EIGNORE;
}
}
}
// Enable control
if (msg[WD_EN_CMD] == EN_CMD_ENABLE)
{
@@ -368,58 +408,6 @@ static int32_t SystemBus_SystemConfig(SYSBUS *instPtr, uint8_t *msg)
return EIGNORE;
}
// Routing table selection
if (msg[WD_RTNE_CMD] != instPtr->sysbusLog.lastConfig[3])
{
L2_RTNE_CONFIG newRtneConfig;
switch (msg[WD_RTNE_CMD])
{
case 0:
{
newRtneConfig.rtneTable = normalTable0;
newRtneConfig.rtnePrd = ARRAY_SIZE(normalTable0);
L2_EVENT l2Event =
{
.event = L2_ROUTINE_UPDATE,
.msg = &newRtneConfig
};
AssertL2Event(linkInstPtr, &l2Event);
break;
}
case 1:
{
newRtneConfig.rtneTable = normalTable1;
newRtneConfig.rtnePrd = ARRAY_SIZE(normalTable1);
L2_EVENT l2Event =
{
.event = L2_ROUTINE_UPDATE,
.msg = &newRtneConfig
};
AssertL2Event(linkInstPtr, &l2Event);
break;
}
case 2:
{
newRtneConfig.rtneTable = normalTable2;
newRtneConfig.rtnePrd = ARRAY_SIZE(normalTable2);
L2_EVENT l2Event =
{
.event = L2_ROUTINE_UPDATE,
.msg = &newRtneConfig
};
AssertL2Event(linkInstPtr, &l2Event);
break;
}
default:
{
// Ignore current command
DBG_ERROR("Unexpected config command 0x%02X:0x%02X",
WD_RTNE_CMD, msg[WD_RTNE_CMD]);
return EIGNORE;
}
}
}
instPtr->sysbusLog.lastConfig[0] = msg[WD_EN_CMD];
instPtr->sysbusLog.lastConfig[1] = msg[WD_ID_CMD];
instPtr->sysbusLog.lastConfig[2] = msg[WD_RATE_CMD];
@@ -467,7 +455,7 @@ int32_t SystemBus_GenRecvRsp(SYSBUS *instPtr, SYSBUS_SVC_PLD *payload)
return ENOMEM;
}
sysbusRsp->len = payload->dataLen + RECV_DATA_LEN_OFFSET;
sysbusRsp->len = payload->dataLen + RECV_DATA_OFFSET;
sysbusRsp->data[WD_CMD] = CMD_RECV_DATA;
sysbusRsp->data[WD_PRD] = MY_PRD_ID;
@@ -780,25 +768,28 @@ int32_t SysMonitor_Init(SYSMON_CONFIG *config)
}
memcpy(&(sysMonitorInst->config), config, sizeof(SYSMON_CONFIG));
sysMonitorInst->sendQueue = NULL;
sysMonitorInst->recvQueue = NULL;
memset(&(sysMonitorInst->sysInfoCtrl), BUFF_NONE, sizeof(PINGPONG));
memset(&(sysMonitorInst->linkLogCtrl), BUFF_NONE, sizeof(PINGPONG));
memset(&(sysMonitorInst->phyLogCtrl), BUFF_NONE, sizeof(PINGPONG));
memset(&(sysMonitorInst->hwStateCtrl), BUFF_NONE, sizeof(PINGPONG));
if (CircQueueCreate(&(sysMonitorInst->sendQueue),
for (uint8_t ii = 0; ii < L2_NET_SCALE; ii++)
{
sysMonitorInst->sendQueue[ii] = NULL;
sysMonitorInst->recvQueue[ii] = NULL;
if (CircQueueCreate(&(sysMonitorInst->sendQueue[ii]),
sysMonitorInst->config.sendQueueMax) == false)
{
SysMonitor_Destroy();
return ENOMEM;
}
if (CircQueueCreate(&(sysMonitorInst->recvQueue),
if (CircQueueCreate(&(sysMonitorInst->recvQueue[ii]),
sysMonitorInst->config.recvQueueMax) == false)
{
SysMonitor_Destroy();
return ENOMEM;
}
}
return SUCCESS;
}
@@ -874,6 +865,11 @@ int32_t SysMonitor_UpdateSendPayload(SYSBUS_SVC_PLD *payload)
DBG_ERROR("Payload length %d exceeds valid range.", payload->dataLen);
return EPARAM;
}
if (payload->nodeId < L2_NODE_NONE || payload->nodeId > L2_NET_SCALE)
{
DBG_ERROR("Node ID %d exceeds valid range.", payload->nodeId);
return EPARAM;
}
// push message into send queue
SYSBUS_SVC_PLD *payloadCopy = malloc(sizeof(SYSBUS_SVC_PLD));
@@ -883,7 +879,8 @@ int32_t SysMonitor_UpdateSendPayload(SYSBUS_SVC_PLD *payload)
return ENOMEM;
}
memcpy(payloadCopy, payload, sizeof(SYSBUS_SVC_PLD));
if (CircQueuePush(sysMonitorInst->sendQueue, (void *)payloadCopy) == false)
// valid id starts from 0x01
if (CircQueuePush(sysMonitorInst->sendQueue[payload->nodeId-1], (void *)payloadCopy) == false)
{
DBG_WARNING("SystemMonitor::SEND Queue overflowed!\n");
free(payloadCopy);
@@ -898,12 +895,13 @@ int32_t SysMonitor_UpdateSendPayload(SYSBUS_SVC_PLD *payload)
*
* @param payload
*/
void SysMonitor_GetSendPayload(SYSBUS_SVC_PLD **payload)
void SysMonitor_GetSendPayload(SYSBUS_SVC_PLD **payload, uint8_t dstId)
{
ASSERT(sysMonitorInst != NULL);
ASSERT(payload != NULL);
if (CircQueuePop(sysMonitorInst->sendQueue, (void **)payload) == false)
// valid id starts from 0x01
if (CircQueuePop(sysMonitorInst->sendQueue[dstId-1], (void **)payload) == false)
{
*payload = NULL;
DBG_INFO("SystemMonitor::Empty sendQueue, nothing need sent.\n");
@@ -917,8 +915,7 @@ void SysMonitor_GetSendPayload(SYSBUS_SVC_PLD **payload)
*/
int32_t SysMonitor_GenRecvRsp(SYSBUS_SVC_PLD *payload)
{
ASSERT(sysMonitorInst != NULL);
ASSERT(sysbusDescPtr != NULL);
ASSERT(payload != NULL);
int32_t Status;
if (payload->dataId == DATA_ID_NONE || payload->dataLen > SYSBUS_PLD_MAX)
+12 -2
View File
@@ -61,6 +61,15 @@
#define VOLT_ANT_NIL_OK BIT(4)
#define ANT_STATE_OK BIT(6)
#ifdef HSJL_GE
// Xilinx Recommended
#define IS_PS_VALID(x) (x <= 0.892 && x >= 0.808)
#define IS_PSAUX_VALID(x) (x <= 1.89 && x >= 1.71)
#define IS_DDR_VALID(x) (x <= 1.89 && x >= 1.14)
#define IS_PL_VALID(x) (x <= 0.892 && x >= 0.808)
#define IS_PLAUX_VALID(x) (x <= 1.89 && x >= 1.71)
#define IS_BRAM_VALID(x) (x <= 0.892 && x >= 0.808)
#else
// Xilinx Recommended
// #define IS_PS_VALID(x) (x <= 1.05 && x >= 0.95)
// #define IS_PSAUX_VALID(x) (x <= 1.89 && x >= 1.71)
@@ -74,6 +83,7 @@
#define IS_PL_VALID(x) (x <= 1.1 && (x) >= 0.9)
#define IS_PLAUX_VALID(x) ((x) <= 2.0 && (x) >= 1.6)
#define IS_BRAM_VALID(x) ((x) <= 1.1 && (x) >= 0.9)
#endif
#define CLK_SP_PLL1_LOCK BIT(0)
#define CLK_SP_PLL2_LOCK BIT(2)
@@ -109,7 +119,7 @@ typedef struct
* @struct SYSBUS_SVC_PLD
* @brief Payload struct that holds the service payload
*/
typedef struct
typedef struct __attribute__((packed))
{
uint32_t dataId; ///< data identifier
uint8_t nodeId; ///< destination ID for tx, source ID for rx
@@ -313,7 +323,7 @@ void SysMonitor_UpdateSysinfo(const SYSINFO *info);
void SysMonitor_GetSysinfo(SYSINFO *info);
int32_t SysMonitor_UpdateSendPayload(SYSBUS_SVC_PLD *payload);
void SysMonitor_GetSendPayload(SYSBUS_SVC_PLD **payload);
void SysMonitor_GetSendPayload(SYSBUS_SVC_PLD **payload, uint8_t dstId);
int32_t SysMonitor_GenRecvRsp(SYSBUS_SVC_PLD *payload);
void SysMonitor_UpdateLinklayerLog(const LINKLOG *log);