diff --git a/scenes/pribor-uyep/sch3-view.gd b/scenes/pribor-uyep/sch3-view.gd index b5bad1f1..91e6a4b5 100644 --- a/scenes/pribor-uyep/sch3-view.gd +++ b/scenes/pribor-uyep/sch3-view.gd @@ -6,44 +6,137 @@ extends "res://scenes/контроль/элемент-я.gd" ## информационного взаимодействия изделия 5П-28 ## с аппаратурой УА-РЭП на кораблях проекта 23900 +@export var base_input_address: = 0 ## Базовый адрес регистров входов +@export var base_holding_address: = 0 ## Базовый адрес регистров хранения +@export var regs_input_count: = 5 ## Количество регистров входов +@export var regs_holding_count: = 4 ## Количество регистров хранения +@export var modbus_address: = 3 ## Адрес устройства на шине Modbus + +var regs_input: = {} ## Регистры входные +var regs_holding: = {} ## Регистры хранения +var write_stack: = [] ## Стек команд для записи +var holding_stack: = [] ## Стек команд для чтения регистров хранения +var input_stack: = [] ## Стек команд для чтения регистров входов +var read_step: = 0 +var switches_sync: = false + + +class StackItem: + var addr: = 0 + var data = null + func _init(a: int, d): addr = a; data = d + func _to_string() -> String: return '%s: %s' % [addr, data] + + func on_data_received(_data: PackedByteArray): pass -func _enter_tree() -> void: +func _on_timeout(unit_sch3) -> void: + if write_stack.size(): + var ad = write_stack.pop_front() + if not unit_sch3.write(ad.addr, ad.data): + write_stack.push_back(ad) + if (read_step == 0) and (input_stack.size() == 0): + var ad = StackItem.new(base_input_address, regs_input_count) + input_stack.push_back(ad) + elif read_step == 1 and (holding_stack.size() == 0): + var ad = StackItem.new(base_holding_address, regs_holding_count) + holding_stack.push_back(ad) + if input_stack.size(): + var ad = input_stack.pop_front() + if not unit_sch3.read_input(ad.addr, ad.data): + input_stack.push_back(ad) + if holding_stack.size(): + var ad = holding_stack.pop_front() + if not unit_sch3.read_holding(ad.addr, ad.data): + holding_stack.push_back(ad) + read_step += 1 + read_step %= 2 + + +func on_toggled_switch(val: bool, unit_sch3: sch_3.Sch3, meta: Array): + var on_addr = meta[0] + var on_bit = meta[1] + var off_addr = meta[2] + var off_bit = meta[3] + if regs_holding.has(on_addr) and regs_holding.has(off_addr): + regs_holding[on_addr] = tools.set_bit(regs_holding[on_addr], on_bit, val) + regs_holding[off_addr] = tools.set_bit(regs_holding[off_addr], off_bit, not val) + var regs_data: = [] + var keys = regs_holding.keys() + keys.sort() + for addr in keys: + regs_data.append(regs_holding[addr]) + write_stack.push_back(StackItem.new(keys[0], regs_data)) + + +func _ready() -> void: if Engine.is_editor_hint(): return var unit_key = settings.get_unit_key(unit_name) - var unit = network.units[unit_key] - unit.connect('resp_input', on_resp_input) - - -func _exit_tree() -> void: - if Engine.is_editor_hint(): return - var unit_key = settings.get_unit_key(unit_name) - var unit = network.units[unit_key] - unit.disconnect('resp_input', on_resp_input) - - -func on_line_changed(_unit): - var items = get_tree().get_nodes_in_group('bits_items_good') + var unit_sch3 = network.units[unit_key] + unit_sch3.mb_addr = modbus_address + var items = get_tree().get_nodes_in_group('bits_items_switch') for item in items: - item.texture = textures[STATE_VAL.ERROR] + var meta = item.get_meta('bits') + item.connect('toggled', on_toggled_switch.bind(unit_sch3, meta)) + item.disabled = true + unit_sch3.connect('resp_input', on_resp_input) + unit_sch3.connect('resp_holding', on_resp_holding) + var timer = Timer.new() + timer.connect('timeout', _on_timeout.bind(unit_sch3)) + add_child(timer) + timer.start(1.0) -func on_resp_input(addr: int, data: PackedByteArray): - if (addr != 0) or (data.size() < 4): +func on_line_changed(unit_sch3): + for item in get_tree().get_nodes_in_group('bits_items_good'): + item.texture = textures[STATE_VAL.NONE] + if not unit_sch3.online: + for item in get_tree().get_nodes_in_group('bits_items_switch'): + item.disabled = true + regs_holding.clear() + regs_input.clear() + write_stack.clear() + input_stack.clear() + holding_stack.clear() + switches_sync = false + + +func on_resp_holding(base_addr: int, data: Array): + if (base_addr != base_holding_address) or (data.size() < regs_holding_count): + return + for i in data.size(): + regs_holding[base_addr + i] = data[i] + if not switches_sync: + for item in get_tree().get_nodes_in_group('bits_items_switch'): + var bits = item.get_meta('bits') + var byte: int = bits[0] + var bit: int = bits[1] + item.button_pressed = regs_holding[byte] & (1 << bit) > 0 + item.disabled = false + switches_sync = true + $margin/vbox/grid1/lbl_freq.text = '<нет данных>' + + +func on_resp_input(base_addr: int, data: Array): + if (base_addr != base_input_address) or (data.size() < regs_input_count): return # "Для контроля состояния управляющего элемента подачи электроэнергии на приборы ..." # "Для контроля подачи электроэнергии на приборы ..." # Таблицы 3.13 и 3.14. Ecли значения соответствующих битов в этих # регистрах равны, то "исправно". var items = get_tree().get_nodes_in_group('bits_items_good') + for i in data.size(): + regs_input[base_addr + i] = data[i] + # Таблица 3.15, Регистр PowerState + $margin/vbox/grid1/lbl_freq.text = '%d' % (regs_input[4] & 0x1ff) var cnt_good: int = 0 for item in items: var bits: Array = item.get_meta('bits') - var byte0: int = bits[0] - var bit0: int = bits[1] - var byte1: int = bits[2] - var bit1: int = bits[3] + var byte0: int = bits[0] # Индекс байта в данных "состояния управляющего элемента" + var bit0: int = bits[1] # Индекс бита в данных "состояния управляющего элемента" + var byte1: int = bits[2] # Индекс байта в данных "подачи электроэнергии на приборы" + var bit1: int = bits[3] # Индекс бита в данных "подачи электроэнергии на приборы" var v = STATE_VAL.GOOD \ if (data[byte0] & (1 << bit0)) \ == (data[byte1] & (1 << bit1)) \ diff --git a/scripts/sch3.gd b/scripts/sch3.gd index 25fc4629..a4535fcd 100644 --- a/scripts/sch3.gd +++ b/scripts/sch3.gd @@ -28,14 +28,14 @@ class Sch3 extends unit.Unit: online = false emit_signal('line_changed', self) if cmd_state == CmdState.WAIT: - cmd_state = CmdState.FAIL - emit_signal('command_fail', self) + if (tick - tx_tick) > ONLINE_TIMEOUT: + cmd_state = CmdState.FAIL + emit_signal('command_fail', self) var rc = Error.ERR_BUSY - if (tick - tx_tick) > REQUEST_PERIOD: - if read_input(0, 4): - tx_tick = tick - cmd_state = CmdState.WAIT - rc = Error.OK + if cmd_state == CmdState.SEND: + tx_tick = tick + cmd_state = CmdState.WAIT + rc = Error.OK return rc