Я — инженер техподдержки, наши клиенты знают меня как Aleksandr_Khlebnikov. Одна из задач инженеров в нашей компании — тестировать новое оборудование.  Мы как раз выпустили модуль расширения, добавляющий контроллеру выход HDMI.

Смотреть на веб-интерфейс во время тестирования скучно, и в голову пришла мысль: а что если попробовать запустить на контроллере Doom?

Doom, известный нам с 1993 года, сейчас запускают буквально на всем, что хоть как-то умеет выполнять код. Калькуляторы, банкоматы, продвинутые тесты на беременность, беговые дорожки и даже кубики LEGO — культовый шутер давно стал символом инженерного троллинга и «челленджа на минималках».

Мне стало интересно проверить, получится ли заставить ПЛК не просто показать игру, а позволить в нее реально поиграть. В железо я верил, в свои умения — чуть меньше. Все-таки контроллер «заточен» под специфические задачи, а лишняя функциональность в ОС отключена. Но раз внутри работает полноценный Linux — почему бы не попробовать?

Итак, эта история о том, как я подключил к ПЛК HDMI-монитор, как запустил Doom и что из этого вышло. А еще о том, как я сделал геймпад с интерфейсом Modbus RTU.

Немного о железе

Для эксперимента использовался контроллер, который обычно выполняет совсем другие задачи: управляет не только умными домами, но и котельными, насосными, вентустановками, микроклиматом серверных, а где-то даже помогает добывать нефть. В общем, Doom ему по регламенту явно не положен.

В него я воткнул WBE2-HDMI, подключил монитор и беспроводную мини-клавиатуру с тачпадом.  

Характеристики получившейся системы (для тех, кому важны цифры):

  • CPU: ARM Cortex-A53, 4 ядра, 1.5 ГГц (Allwinner T507);

  • RAM: LPDDR4, 2 ГБ;

  • Хранилище: eMMC 16 ГБ;

  • ОС: Debian 11 (Bullseye).

На этой системе я запускал DOOM
На этой системе я запускал DOOM

Установка

Пошел стандартным путем: поднял графическую подсистему X11 и поверх нее поставил Chocolate Doom.

apt install wb-hdmi (если контроллер заказан сразу с HDMI, этот шаг пропустите)
apt install -y xserver-xorg xinit openbox \
               chocolate-doom freedoom unclutter

С «ванильным» doom-wad-shareware в Bullseye не сложилось — его просто нет в репозитории. Поэтому я сразу взял Freedoom — свободные ресурсы, полностью совместимые с движком.

Проверил, что все на месте:

ls /usr/share/games/doom/
# freedoom1.wad и freedoom2.wad должны лежать здесь

Для запуска через X11 сделал минимальный ~/.xinitrc:

openbox &
/usr/games/chocolate-doom -iwad /usr/share/games/doom/freedoom1.wad

И дальше — просто:

startx

Первый запуск занял около десяти минут, но появившийся на экране знакомый коридор подтвердил успех.

Проблемы

Конечно, все пошло не идеально. Doom на контроллере — это не «apt install && play».

1. Автозапуск Firefox
HDMI-модуль в контроллере стартует через systemd-сервис xinit.service. По умолчанию он тянет скрипт /etc/X11/xinit/xinitrc.wb, который всегда запускает Firefox в режиме киоска. Получалось так: я жду Doom, а на экран упорно лезет браузер. Пришлось покопаться в конфиге и отключить этот автозапуск.

2. Звука нет
У контроллера нет аудиовыхода. ALSA честно ругалась на «no sound device». Для эксперимента не критично — ностальгия работает и в тишине.

3. Консольный режим не взлетел
Хотелось обойтись без X11 и запустить Doom через framebuffer. Но программа упиралась и требовала X-сервер. В итоге я смирился и оставил X11.

Результат

После всех доработок Doom запустился на HDMI-мониторе. И главное — шел плавно, без лагов. Можно было бегать, стрелять и словить ту самую ностальгию.

По замерам в htop:

  • CPU: все четыре ядра были загружены на 70–90%;

  • RAM: Doom потреблял около 132 МБ памяти;

  • Система в целом: занято ~440 МБ из 1.9 ГБ доступной оперативки.

При этом сервисные процессы контроллера (wb-rules, wb-mqtt-db, wb-metrics и другие) продолжали работать параллельно. Их нагрузка оставалась минимальной (1–3%). То есть даже в «игровом» сценарии контроллер не терял своей основной функциональности.

FPS субъективно ощущался «как в детстве» — примерно 20–25 кадров.

Геймпад с Modbus RTU

Аппетит приходит во время игры. Мне стало интересно: а можно ли управлять Doom прямо через «железо» контроллера? Например, подключить кнопки к нашему модулю дискретных входов WB-MCM8 и использовать его как настоящий геймпад.

На контроллере работает расширение протокола Modbus — Быстрый Modbus, обеспечивающее время отклика около 60 мс. Этого вполне достаточно, чтобы реакция была не хуже, чем у обычной клавиатуры.

Механизм простой:

нажатие кнопки →  драйвер запрашивает события → модуль сообщает об изменении регистра → публикуется значение в MQTT → эмулируется нажатие клавиши виртуальной клавиатуры → Doom реагирует.

Чтобы это заработало, нужно научить контроллер генерировать нажатия виртуальных клавиш. Здесь в игру вступает драйвер uinput.

Подготовка: включаем поддержку uinput

Uinput — это интерфейс для создания виртуальных устройств ввода. По умолчанию в ядре WB8 (6.8.0-wb144) драйвер uinput отсутствует.  Значит, нужно пересобрать ядро.

Сборка выполняется не на самом контроллере, а на ПК с Ubuntu или Debian (!). Чтобы вам было легче, вот уже собранный пакет.

1. Устанавливаем инструменты:

sudo apt update
sudo apt install build-essential libncurses5-dev fakeroot lzop bc git bison flex libssl-dev rsync gcc-aarch64-linux-gnu

2. Клонируем исходники ядра контроллера:

git clone --depth=1 --branch dev/v6.8 https://github.com/wirenboard/linux ~/linux
cd linux
git submodule update --init --recursive

3. Запускаем конфигуратор:

make KBUILD_OUTPUT=.build-wb8 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig

4. Включаем опцию:

Device Drivers → Input device support → Miscellaneous devices → User level driver support → [M]

5. Сохраняем .config и собираем deb-пакеты:

KERNEL_FLAVOUR=wb8 ./scripts/package/wb/do_build_deb.sh

Важно: на вопрос «Use defconfig instead?» отвечаем N.

После сборки появятся пакеты:

linux-image-wb8_6.8.0-wb144_arm64.deb
linux-headers-wb8_6.8.0-wb144_arm64.deb

Установка ядра на контроллер

1. Переносим собранный пакет ядра на контроллер:

scp linux-image-wb8_6.8.0-wb144_arm64.deb root@<WB_IP>:/root/

2. Устанавливаем нужные пакеты и перезагружаем:

apt install python3-evdev python3-uinput -y
dpkg -i /root/linux-image-wb8_6.8.0-wb144_arm64.deb
reboot

3. Проверяем после перезагрузки:

uname -a
lsmod | grep uinput || modprobe uinput
ls -l /dev/uinput

Если все сделано правильно, в системе появится /dev/uinput.

Python-скрипт: MQTT → клавиатура

Теперь свяжем кнопки модуля WB-MCM8 с клавишами Doom с помощью Python-скрипта.

import paho.mqtt.client as mqtt
import uinput

# Маппинг входов WB-MCM8 -> клавиши Doom
TOPIC_KEY_MAP = {
    "/devices/wb-mcm8_32/controls/Input 1": uinput.KEY_UP,       # Стрелка вверх
    "/devices/wb-mcm8_32/controls/Input 2": uinput.KEY_DOWN,     # Стрелка вниз
    "/devices/wb-mcm8_32/controls/Input 3": uinput.KEY_LEFT,     # Стрелка влево
    "/devices/wb-mcm8_32/controls/Input 4": uinput.KEY_RIGHT,    # Стрелка вправо
    "/devices/wb-mcm8_32/controls/Input 5": uinput.KEY_ENTER,    # Enter
    "/devices/wb-mcm8_32/controls/Input 6": uinput.KEY_ESC,      # Esc
    "/devices/wb-mcm8_32/controls/Input 7": uinput.KEY_LEFTCTRL, # Ctrl (огонь)
    "/devices/wb-mcm8_32/controls/Input 8": uinput.KEY_SPACE,    # Space (дверь/прыжок)
}

device = uinput.Device(list(TOPIC_KEY_MAP.values()), name="Virtual Keyboard")

def on_connect(client, userdata, flags, rc):
    print("Connected to MQTT with result code " + str(rc))
    for topic in TOPIC_KEY_MAP.keys():
        client.subscribe(topic)

def on_message(client, userdata, msg):
    topic = msg.topic
    payload = msg.payload.decode().strip()
    if topic in TOPIC_KEY_MAP:
        key = TOPIC_KEY_MAP[topic]
        if payload == "1":   # нажата кнопка
            device.emit(key, 1)  # KEY_DOWN
        elif payload == "0": # отпущена кнопка
            device.emit(key, 0)  # KEY_UP
        device.syn()

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

client.connect("localhost", 1883, 60)
client.loop_forever()

Запускаем скрипт:

python3 mqtt_keyboard.py

Проверка работы uinput

Чтобы убедиться, что виртуальная клавиатура доступна:

apt install evtest -y
evtest

В списке устройств должно появиться что-то вроде Virtual Keyboard. При нажатии кнопок будут видны события EV_KEY.

Теперь кнопки, подключенные к WB-MCM8, Doom воспринимает их как настоящие клавиши.


Например:

  • Input 1 → стрелка вверх

  • Input 7 → Ctrl (стрельба)

  • Input 8 → Space (открыть дверь)

Итоги и выводы

Я сделал это!

Конечно, Doom на контроллере в щите в реальной жизни никому не нужен. Этот контроллер создан для серьезных задач — автоматизации (в том числе домашней), диспетчеризации, контроля и учета. Но эксперимент показал: внутри ПЛК скрывается полноценный Linux-компьютер, который способен на большее, чем кажется на первый взгляд.

А конкретнее:

  • контроллер спокойно тянет X11 и легкие GUI-приложения;

  • HDMI-модуль — это не только «киоск с Firefox», но и основа для собственных графических интерфейсов;

  • даже посредством Modbus RTU можно добиться отклика не хуже, чем у стандартной клавиатуры.

Чего я добился:

  • Doom стал реально играбельным даже без внешней клавиатуры;

  • я глубже понял внутренности ядра и драйверов linux;

  • и главное — теперь у меня есть собственный «modbus-геймпад» :)

Эксперимент оказался и фаном, и ностальгией, а заодно помог лучше разобраться в системе.

Комментарии (17)


  1. NotebookKiller
    08.10.2025 08:17

    Олдскулы сведены!


  1. legustarasov
    08.10.2025 08:17

    Устройство на минималках:

    CPU: ARM Cortex-A53, 4 ядра, 1.5 ГГц (Allwinner T507);

    RAM: LPDDR4, 2 ГБ;

    Это все же чуть мощнее, чем 486 процессор с 16МБ оперативной памяти, на котором я залипал в DOOM :)))


    1. NotebookKiller
      08.10.2025 08:17

      И совсем чуточку побольше, чем 386 с 4МБ оперативки минимальных требований. Правда, по энергопотреблению это похоже существенно меньше, чем трёшка-четвёрка


      1. garageman
        08.10.2025 08:17

        Угу, ватт ~5 вместе с модулем ввода.


      1. TimurZhoraev
        08.10.2025 08:17

        Насколько помню можно было запускать на 386м Windows 3.11, который умел уже делать помимо EMM файл подкачки, тем самым формируя виртуальную память больше чем физическую, поэтому свернув окно до 160x100 пикселей (была такая опция, не помню хоткей) можно было вполне запустить и на 2 МБ в DOS-сессии командной строки.


        1. axe_chita
          08.10.2025 08:17

          Скорее всего это бы не взлетело, ЕМНИП то расширитель DOSX из Windows 3.x не умел делать виртуальную память для DPMI. Да и оверхэд промежуточных слоёв превращал эту возможность в сугубо теоретическую.

          Другое дело было уболтать и заставить DOS4/GW врубить поддержку виртуальной памяти и файла подкачки. Такой вариант имел гораздо более высокие шансы на успех.

          DOS/4GW Configuration Guide

          2 VMM

          The Virtual Memory Manager (VMM) uses a swap file on disk to augment RAM. With VMM you can use more memory than your machine actually has. When RAM is not sufficient, part of your program is swapped out to the disk file until it is needed again. The combination of the swap file and available RAM is the virtual memory.

          Your program can use VMM if you set the DOS environment variable, DOS4GVM, as follows. To set the DOS4GVM environment variable, use the format shown below.

          set DOS4GVM= [option[#value]] [option[#value]]

          A "#" is used with options that take values since the DOS command shell will not accept "=".

          If you set DOS4GVM equal to 1, the default parameters are used for all options.

          Example:
          C>set DOS4GVM=1

          2.1 VMM Default Parameters

          VMM parameters control the options listed below.

          MINMEM The minimum amount of RAM managed by VMM. The default is
          512KB.

          MAXMEM The maximum amount of RAM managed by VMM. The default is 4MB.

          SWAPMIN The minimum or initial size of the swap file. If this option is not used, the size of the swap file is based on VIRTUALSIZE (see below).

          SWAPINC The size by which the swap file grows.

          SWAPNAME The swap file name. The default name is "DOS4GVM.SWP". By default the file is in the root directory of the current drive. Specify the complete path name if you want to keep the swap file somewhere else.

          DELETESWAP Whether the swap file is deleted when your program exits. By default the file is not deleted. Program startup is quicker if the file is not deleted.

          VIRTUALSIZE The size of the virtual memory space. The default is 16MB.

          VMM Default Parameters 9
          Chapter 2

          2.2 Changing the Defaults

          You can change the defaults in two ways.

          1. Specify different parameter values as arguments to the DOS4GVM environment variable, as shown in the example below.

          set DOS4GVM=deleteswap maxmem#8192

          1. Create a configuration file with the filetype extension ".VMC", and call that as an argument to the DOS4GVM environment variable, as shown below.

          set DOS4GVM=@NEW4G.VMC

          2.2.1 The .VMC File

          A ".VMC" file contains VMM parameters and settings as shown in the example below. Comments are permitted. Comments on lines by themselves are preceded by an exclamation point (!). Comments that follow option settings are preceded by white space. Do not insert blank lines: processing stops at the first blank line.

          !Sample .VMC file
          !This file shows the default parameter values.
          minmem = 512 At least 512K bytes of RAM is required.
          maxmem = 4096 Uses no more than 4MB of RAM
          virtualsize = 16384 Swap file plus allocated memory is 16MB
          !To delete the swap file automatically when the program exits, add
          !deleteswap
          !To store the swap file in a directory called SWAPFILE, add
          !swapname = c:\swapfile\dos4gvm.swp


          1. TimurZhoraev
            08.10.2025 08:17

            Именно так помню на 386 и запускалось с 2 МБ (может 4 было не уверен, давно это было где то в году в 97м). Под простой ДОС ничего не работало, под видной 3.11 (набирал win.com прямо из нортон коммандера, было время) этот самый DOS4GW (может как раз автоматом получал виртуальное окружение, точно помню что была эта надпись у doom2.exe) в ДОС-сессии уже запускался, ждал минуты 2 init doom refresh daemons с бегущими точечками. Конечно полное разрешение было 2 fps (320 на 200), а если съёжить экран то вполне можно было бродить. Иногда из файла подкачки грузилось 1-2 секунды но это было не так критично и не часто. Звук классический через биппер, когда кибердемон был в кадре системник звучал как бензопила.


            1. axe_chita
              08.10.2025 08:17

              В четырех мегабайтах DOOM под Win3.x поверю, в двух мегабайтах не верю. Даже если и запустится, то это будет по круче "Фауста" Гёте. В смысле только из любви к искусству.


    1. Moog_Prodigy
      08.10.2025 08:17

      Чуть мощнее? В 2004 году я на P3-700 играл в gta vc и почти не тормозило. На 256 мб озушки...


    1. axe_chita
      08.10.2025 08:17

      AMD Am386DX40/128cache/4mb ram/Realtek VGA RT3105 512kb isa/hdd ide 120mb маленько (в 5-7 раз) медленнее 486dx66/100 ;)


  1. taraant
    08.10.2025 08:17

    Не ожидал такой прыти от быстрого Модбаса!
    Всмастривался в видео (в левом-нижнем углу) и по ощущениям задержка точно меньше 100мс (может и еще меньше - уже не понимаю) - если честно, то я не вижу задержки между нажатиями на кнопки и реакцией на видео.

    Там точно "джойстик" подключен через модуль по модбасу или может напрямую в контроллер?!... :)


    1. dust70
      08.10.2025 08:17

      Точно по Modbus RTU, причем на 9600.


  1. JBFW
    08.10.2025 08:17

    если бы в hdmi-модль еще и поддержку звука воткнули...
    Хотя может аппаратно она там и есть, просто ядро не знает?


    1. MicroVolk Автор
      08.10.2025 08:17

      Чуть позже тоже будет!)


    1. wofs
      08.10.2025 08:17

      Сейчас звук можно вывести через USB-звуковую карточку, всё что надо в ядре есть.


      1. JBFW
        08.10.2025 08:17

        Иногда удобнее HDMI - стандартный ТВ будет и экраном и колонками.
        А так-то да


  1. NutsUnderline
    08.10.2025 08:17

    все равно читерство по сравнении с. ПЛК по сути одноплатник с открытой ОС да еще и hdmi приделали. многие ПЛК гораздо(-гораздно) слабже по начинке даже если там и крутиться минимальный линукс, а то и что то более простое и закрытое