Я — инженер техподдержки, наши клиенты знают меня как 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-геймпад» :)

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

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


  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. 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

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