Extract reusable device protocols, ports and logic analyzers from SETGUI
This commit is contained in:
57
python/set_devices/ump_logger_demo.py
Normal file
57
python/set_devices/ump_logger_demo.py
Normal file
@@ -0,0 +1,57 @@
|
||||
"""Синтетические записи УМП для проверки графиков без подключения платы."""
|
||||
import math
|
||||
|
||||
from set_devices import ump_logger as codec
|
||||
|
||||
|
||||
def sample(time_ms, period_ms=20):
|
||||
"""Повторяемый цикл: пуск, разгон 6–16 мА, отключение и спад тока."""
|
||||
phase = time_ms % 6000
|
||||
started = 1000 <= phase < 5000
|
||||
reset = 5000 <= phase < 5300
|
||||
# Как в прошивке: фронт команды включает выход на 1000 мс.
|
||||
start_out = 1000 <= phase < 2000
|
||||
stop_out = 5000 <= phase < 6000
|
||||
ramp = max(0, min(2500, phase - 1000))
|
||||
if started:
|
||||
current = 6 + 10 * ramp / 2500 + 0.2 * math.sin(phase / 90)
|
||||
elif phase >= 5000:
|
||||
current = 4 + 12 * max(0, 1 - (phase - 5000) / 300)
|
||||
else:
|
||||
current = 4
|
||||
|
||||
words = [0] * codec.WORDS
|
||||
words[0], words[1] = time_ms & 65535, (time_ms >> 16) & 65535
|
||||
words[2] = 1 | (0x100 if 5000 <= phase < 5000 + period_ms else 0)
|
||||
words[3] = (int(started) << 7) | (int(reset) << 6)
|
||||
words[4] = int(1200 <= phase < 5100) | (int(started) << 1) | (int(reset) << 2)
|
||||
words[5] = int(start_out) | (int(stop_out) << 1) | (int(started) << 2)
|
||||
words[6] = (2000 - phase) if start_out else ((6000 - phase) if stop_out else 0)
|
||||
words[7] = max(0, 250 - phase)
|
||||
words[8] = round(500 + (current - 4) * 3000 / 16)
|
||||
words[9] = round(current * 10)
|
||||
for channel in range(4):
|
||||
measured = round(120 * math.sin(phase / (180 + channel * 70) + channel))
|
||||
words[10 + channel] = measured & 65535
|
||||
words[14 + channel] = (1 << channel) if 5100 <= phase < 5400 else 0
|
||||
words[36 + channel] = 2048 + measured * 4
|
||||
words[18:24] = [0xE07F, words[3], 6, 16, (time_ms // 100) & 65535, 0]
|
||||
words[24:31] = [6, 16, 500, 3500, 2000, 500, 3500]
|
||||
words[31:36] = [ramp if started else 0, 2500, 60, 160, round(ramp * 1000 / 2500)]
|
||||
return codec.sample(words)
|
||||
|
||||
|
||||
def capture(period_ms):
|
||||
"""Пример архива: до 399 точек предыстории, отключение и 1 с после него."""
|
||||
before = list(range(5000, -1, -period_ms))[1:400][::-1]
|
||||
after = list(range(5000 + period_ms, 6000, period_ms)) + [6000]
|
||||
available = codec.CAPACITY - len(before) - 1
|
||||
truncated = len(after) > available
|
||||
if truncated:
|
||||
after = after[:available - 1] + after[-1:]
|
||||
records = [sample(t, period_ms) for t in before + [5000] + after]
|
||||
# Последний снимок относится к концу постинтервала, а не новому циклу.
|
||||
records[-1]['event'] = 5 | (0x200 if truncated else 0)
|
||||
records[-1]['post_truncated'] = int(truncated)
|
||||
records[-1]['off_trigger'] = 0
|
||||
return records
|
||||
Reference in New Issue
Block a user