From e6453445380f436e580d1d132d8d2c32ef47efc2 Mon Sep 17 00:00:00 2001 From: Maxim Date: Thu, 12 Sep 2024 15:01:23 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Main.gd | 95 ++++++++++++++++++++++++---------------------------- constants.gd | 4 +-- yau07.gd | 68 ++++++++++++++++++++++++++++--------- 3 files changed, 98 insertions(+), 69 deletions(-) diff --git a/Main.gd b/Main.gd index 3a91268..18b7ef9 100644 --- a/Main.gd +++ b/Main.gd @@ -16,13 +16,14 @@ var unit = yau07.YaU07.new('ЯУ07') var state: int = 0 # Флаг для машины состояния var flag_online: bool = false # Флаг для подключения var flag_interval: bool = false # Флаг для включения непрерывной передачи с интервалом +var flag_wr_on_timer = true var ports_wr: Dictionary # Словарь с портами для записи var port_select: int = Constants.BASE_ADDR # Выбранный порд для чтения/записи var port: int var dt: float # Дельта var address: String var rx_data: PackedByteArray # Буфер принятый -var addr_receive: String # Адрес обращения к ПРД +var addr_receive: String # Адрес обращения к ПРД var port_receive: int # Порт обращения к ПРД var ROWS_REGS_DATA: Array = [ [TableNode, TableNode, TableNode, TableNode, TableNode], @@ -52,33 +53,33 @@ func _ready(): var edit_port = node_select.get_node2(4, 0) edit_port.editable = true edit_port.placeholder_text = 'Ввод значения' - + # Поле для ввода (запись в порт) var edit_node = node_select.get_node2(2, 1) edit_node.editable = true edit_node.placeholder_text = 'Ввод значения' edit_node.connect('text_submitted', Callable(self, '_on_written_text_submitted')) - + # Кнопка для включения $Turn_on.connect('toggled', Callable(self, '_on_button_pressed')) - + # Поле для ввода (базовый порт) var edit_addr = node_select.get_node2(0, 2) edit_addr.editable = true edit_addr.placeholder_text = ' 0x%x' % port_select edit_addr.connect('text_submitted', Callable(self, '_on_written_addres')) - + # Поле для ввода (интервал непрерывной записи) var edit_interval = node_select.get_node2(2, 2) edit_interval.editable = true edit_interval.placeholder_text = 'Ввод значения' edit_interval.connect('text_submitted', Callable(self, '_on_written_interval')) - + # Привязка для принятия широковещательного канала var rc = soc_brodcast.bind(Constants.BROADCAST_PORT, '*') if rc != OK: print('Ошибка: Неудачная привязка широковещательного адреса') - + ports_wr[port_select] = 0 unit.connect('line_changed', Callable(self, 'on_line_changed')) unit.connect('command_fail', Callable(self, 'on_command_fail')) @@ -101,65 +102,35 @@ func poll_receive(sock: Socket, _unit, addr: String, _port: int) -> bool: ## П return false -func _process(delta): +func _process(delta) -> void: if flag_online: if flag_interval == false: poll_receive(soc_brodcast, unit, address, port) - var fl_done = unit.cmd_state == unit.CmdState.DONE - if state == 1 and fl_done: ## Чтение из ИСА - unit.send_isa(unit.CmdCode.READ_ISA, [port_select]) - node_select.set_node_text(3, 1, ' ПРОЧИТАНО ИЗ %x' % port_select) - state = 2 - elif state == 2 and fl_done: ## Запись в ИСА - unit.send_isa(unit.CmdCode.WRITE_ISA, [port_select, ports_wr[port_select]]) - - if unit.isa_ports.has(port_select): - node_select.set_node_text(4, 1, ' %x' % unit.isa_ports[port_select]) - var isa: Array = [] - for i in unit.isa_ports: - isa.append('%x: %x' % [i, unit.isa_ports[i]]) - node_select.set_node_text(1, 1, ' ЗАПИСАТЬ В %x' % port_select) - $ISA.text = 'ISA: ' + str(isa) - state = 1 + state_machine() var rc = unit.process(delta) if rc == Error.OK: soc_unicast.send_to(address, port, unit.tx_data.slice(0, unit.tx_len)) - dt = delta + dt = delta -func on_timer(): +func on_timer() -> void: if flag_online: if flag_interval == true: poll_receive(soc_brodcast, unit, address, port) - var fl_done = unit.cmd_state == unit.CmdState.DONE - if state == 1 and fl_done: ## Чтение из ИСА - unit.send_isa(unit.CmdCode.READ_ISA, [port_select]) - node_select.set_node_text(3, 1, ' ПРОЧИТАНО ИЗ %x' % port_select) - state = 2 - elif state == 2 and fl_done: ## Запись в ИСА - unit.send_isa(unit.CmdCode.WRITE_ISA, [port_select, ports_wr[port_select]]) - - if unit.isa_ports.has(port_select): - node_select.set_node_text(4, 1, '%x' % unit.isa_ports[port_select]) - var isa: Array = [] - for i in unit.isa_ports: - isa.append('%x: %x' % [i, unit.isa_ports[i]]) - node_select.set_node_text(1, 1, ' ЗАПИСАТЬ В %x' % port_select) - $ISA.text = 'ISA: ' + str(isa) - state = 1 - + state_machine() + var rc = unit.process(dt) if rc == Error.OK: soc_unicast.send_to(address, port, unit.tx_data.slice(0, unit.tx_len)) -func on_line_changed(_unit): +func on_line_changed(_unit) -> void: print_debug() ## Ессли отсутствует подключение к ячейке ЯУ-07 -func on_command_fail(_unit): +func on_command_fail(_unit) -> void: var line_yau07_control = node_select.get_node2(0, 0) line_yau07_control.text = ' НЕТ СВЯЗИ С ЯУ-07' line_yau07_control.modulate = Color(1, 0, 0, 1) @@ -168,32 +139,52 @@ func on_command_fail(_unit): ## Индикация чтения портов -func on_command_done(_unit): +func on_command_done(_unit) -> void: if flag_online: var line_yau07_control = node_select.get_node2(0, 0) line_yau07_control.text = ' ЯУ-07 НА СВЯЗИ' line_yau07_control.modulate = Color(0, 1, 0, 1) +func state_machine() -> void: + var fl_done = unit.cmd_state == unit.CmdState.DONE + if state == 1 and fl_done: ## Чтение из ИСА + unit.send_isa(unit.CmdCode.READ_ISA, [port_select]) + node_select.set_node_text(3, 1, ' ПРОЧИТАНО ИЗ %x' % port_select) + state = 2 if flag_wr_on_timer else 1 + elif state == 2 and fl_done: ## Запись в ИСА + unit.send_isa(unit.CmdCode.WRITE_ISA, [port_select, ports_wr[port_select]]) + + if unit.isa_ports.has(port_select): + node_select.set_node_text(4, 1, '%x' % unit.isa_ports[port_select]) + var isa: Array = [] + for i in unit.isa_ports: + isa.append('%x: %x' % [i, unit.isa_ports[i]]) + node_select.set_node_text(1, 1, ' ЗАПИСАТЬ В %x' % port_select) + $ISA.text = 'ISA: ' + str(isa) + state = 1 + + ## Выставить адресс для записи -func _on_written_addres(write_addres): +func _on_written_addres(write_addres) -> void: port_select = write_addres.hex_to_int() - ports_wr[port_select] = 0 + if ports_wr.has(port_select) != true: + ports_wr[port_select] = 0 node_select.set_node_text(0, 2, '%x' % port_select) ## Запись числа порт -func _on_written_text_submitted(write_addres_data): +func _on_written_text_submitted(write_addres_data) -> void: var is_hex = true for chr in write_addres_data: if chr.to_upper() < '0' or chr.to_upper() > 'F': is_hex = false - break + break ports_wr[port_select] = write_addres_data.hex_to_int() if is_hex else 0xffff state = 2 # Запись -func _on_written_interval(write_interval): +func _on_written_interval(write_interval) -> void: timer.start(float(write_interval)) flag_interval = true var light_interval = node_select.get_node2(1, 2) @@ -201,7 +192,7 @@ func _on_written_interval(write_interval): ## Подключение -func _on_button_pressed(turn_on): +func _on_button_pressed(turn_on) -> void: if turn_on: address = node_select.get_node2(2,0).text port = int(node_select.get_node2(4,0).text) diff --git a/constants.gd b/constants.gd index e8295ff..d86a416 100644 --- a/constants.gd +++ b/constants.gd @@ -1,6 +1,6 @@ extends Node const UNICAST_PORT: int = 50080 -const UNICAST_ADDRESS: String = '10.1.1.14' +const UNICAST_ADDRESS: String = '10.1.1.3' const BROADCAST_PORT: int = 50000 -const BASE_ADDR = 0x100 +const BASE_ADDR: int = 0x100 diff --git a/yau07.gd b/yau07.gd index 4410d4b..0c3e4e6 100644 --- a/yau07.gd +++ b/yau07.gd @@ -13,10 +13,14 @@ class YaU07: ## Коды выполняемых команд enum CmdCode { - READ_ISA = 0, ## Код команды "читать порт ISA" ячейки ЯУ-07 - WRITE_ISA = 1, ## Код команды "записать порт ISA" ячейки ЯУ-07 + READ_ISA = 0, ## Код команды "читать порт ISA" ячейки ЯУ-07 + WRITE_ISA = 1, ## Код команды "записать порт ISA" ячейки ЯУ-07 + ERASE_FLASH = 49, ## Код команды "стереть данные из FLASH" ячейки ЯУ-07 + WRITE_FLASH = 50, ## Код команды "записать данные в FLASH" ячейки ЯУ-07 + READ_FLASH = 51, ## Код команды "прочитать данные из FLASH" ячейки ЯУ-07 + LOAD_FLASH = 52, ## Код команды "записать данные из FLASH в КЭМС" ячейки ЯУ-07 WRITE_BLOCK = 60, ## Код команды "записать блок данных ISA" внешней шины ячейки ЯУ-07 - READ_BLOCK = 61, ## Код команды "читать блок данных ISA" внешней шины ячейки ЯУ-07 + READ_BLOCK = 61, ## Код команды "читать блок данных ISA" внешней шины ячейки ЯУ-07 } ## Состояние автомата выполнения команды @@ -40,6 +44,7 @@ class YaU07: var cmd_result: = 1 ## Результат выполнения команды. Устанавливается в ЯУ-07 var cmd_data: = PackedByteArray() ## Данные команды. Устанавливается в ЯУ-07 var cmd_retry = 0 ## Счётчик оставшихся попыток выполнить команду + var cmd_code_rx = 0 ## Код последней выполненой команды var tick = 0.0 ## Текущее тик-время в мс var cmd_tick_tx = 0.0 ## Время последней отправки команды var cmd_tick_rx = 0.0 ## Время последнего приёма команды @@ -48,18 +53,18 @@ class YaU07: var tx_len = 0 ## Длина последнего отправленного пакета var isa_ports = {} ## Результат выполнения команды "читать порт" var isa_block = {} ## Результат выполнения команды "читать массив из порта" + var flash_data: = PackedByteArray() ## Данные прочитанные из Flash + var flash_len: = 0 ## Длинна данных прочитанных из Flash var online = false ## Состояние связи с ячейкой func _to_string() -> String: return String('яу07: %s %s' % [self.name, ['отключен', 'на связи'][int(online)]]) - func _init(nm): self.name = nm tx_data.resize(BUFFER_SIZE) tx_data.fill(0) tick = 0.0 - func process(delta: float): tick += delta if online and ((tick - cmd_tick_rx) > ONLINE_TIMEOUT): @@ -84,6 +89,33 @@ class YaU07: rc = Error.FAILED return rc + func send_flash(cmd_code: int, fl_data: Array, num_byte_rd: int) -> bool: + if (cmd_state == CmdState.WAIT) \ + or (cmd_state == CmdState.SEND) \ + or (cmd_state == CmdState.UNCK): + return false + if not ((cmd_code == CmdCode.ERASE_FLASH) or (cmd_code == CmdCode.WRITE_FLASH) \ + or (cmd_code == CmdCode.READ_FLASH) or (cmd_code == CmdCode.LOAD_FLASH)): + return false + cmd_num_tx = (cmd_num_rx + 1) % 0xffff + tx_data.encode_u16(0, cmd_retry) + tx_data.encode_u16(2, cmd_num_tx) + tx_data.encode_u8(6, cmd_code) + if cmd_code == CmdCode.ERASE_FLASH: + tx_len = 7 + elif cmd_code == CmdCode.WRITE_FLASH: + tx_data.encode_u8(7, 1) + tx_data.encode_u16(8, 0) + tx_data.encode_u16(10, len(fl_data)) + tx_len = 11 + len(fl_data) * 2 + for i in range(len(fl_data)): + tx_data.encode_u16(12 + i * 2, fl_data[i]) + elif cmd_code == CmdCode.READ_FLASH: + tx_len = 11 + tx_data.encode_u16(7, 0) + tx_data.encode_u16(9, num_byte_rd) + cmd_state = CmdState.SEND + return true func send_isa(cmd_code: int, ports_data: Array) -> bool: if (cmd_state == CmdState.WAIT) \ @@ -92,9 +124,7 @@ class YaU07: return false if not ((cmd_code == CmdCode.READ_ISA) or (cmd_code == CmdCode.WRITE_ISA)): return false - cmd_num_tx = (cmd_num_rx + 1) % 0xffff - var ports_count = ports_data.size() tx_len = ports_count * 2 + 8 tx_data.encode_u16(0, cmd_retry) @@ -111,7 +141,7 @@ class YaU07: i += 2 cmd_state = CmdState.SEND return true - + func send_block(cmd_code: int, block_len: int, port: Array) -> bool: if (cmd_state == CmdState.WAIT) \ or (cmd_state == CmdState.SEND) \ @@ -129,11 +159,12 @@ class YaU07: if cmd_code == CmdCode.WRITE_BLOCK: block_len /= 2 tx_data[6] = cmd_code - tx_data.encode_u16(7, block_len) + tx_data.encode_u16(7, block_len) tx_data.encode_u16(9, int(port[0])) cmd_state = CmdState.SEND return true + ## Возвращает код команды ЯУ-07 ## rx_data - Принятые данные ## Возвращает - Код команды не найден, 0...255 - код команды @@ -150,7 +181,6 @@ class YaU07: return null return rx_data[cmd_code_pos] # "код команды" - func parse_isa(rx_data: PackedByteArray, status_len) -> bool: var ports_count_pos = status_len + 10 # Положение в приёмном буфере количества портов if rx_data.size() < ports_count_pos: @@ -175,8 +205,6 @@ class YaU07: var ports_count_pos = status_len + 7 # Положение в приёмном буфере количества портов if rx_data.size() < ports_count_pos: return false - - var block_len = rx_data.decode_u16(ports_count_pos + 3) var block_adr = rx_data.decode_u16(ports_count_pos + 5) var block_data = [] @@ -185,7 +213,12 @@ class YaU07: block_data.append(rx_data.decode_u16(ports_count_pos + 7 + shift)) isa_block[block_adr] = block_data return true - + + func parse_flash(rx_data: PackedByteArray, status_len, cmd_code) -> bool: + if cmd_code == CmdCode.READ_FLASH: + flash_len = rx_data.decode_u16(status_len + 12) + flash_data = rx_data.slice(status_len + 14) + return true ## Заполняет состояние прибора данными прочитанными из портов ЯУ-07 ## для команд "читать порты" или "записать порты"[br] @@ -193,7 +226,7 @@ class YaU07: ## Возвращает [b]true[/b] - Данные обработаны успешно[br] ## Возвращает [b]false[/b] - Данные не обработаны из за ошибки[br] func parse(rx_data: PackedByteArray) -> bool: - + cmd_tick_rx = tick if not online: @@ -238,13 +271,18 @@ class YaU07: var rc = true if (cmd_code == CmdCode.READ_ISA) or (cmd_code == CmdCode.WRITE_ISA): rc = parse_isa(rx_data, status_len) - + elif (cmd_code == CmdCode.READ_BLOCK) or (cmd_code == CmdCode.WRITE_BLOCK): rc = parse_block(rx_data, status_len) + elif (cmd_code == CmdCode.ERASE_FLASH) or (cmd_code == CmdCode.WRITE_FLASH) \ + or (cmd_code == CmdCode.READ_FLASH) or (cmd_code == CmdCode.LOAD_FLASH): + rc = parse_flash(rx_data, status_len, cmd_code) + if rc: if (cmd_state == CmdState.WAIT) and (cmd_num_rx == cmd_num_tx): cmd_state = CmdState.DONE + cmd_code_rx = cmd_code emit_signal('command_done', self) else: emit_signal('parse_failed', self)