[Перевод] Экран для старой кассы стоил около $300, и я вывел картинку на VGA через Raspberry Pi Pico


Смотрели когда-нибудь на старое устройство и думали, можно ли заставить его дисплей работать с современным железом? С этого проект и начался.
У меня есть старый кассовый аппарат Samsung SPS-1000 с монохромным STN-дисплеем. Дисплейный модуль у него сломан. Я поискал такой же на eBay, и стоил он около 300 долларов. Сдаваться я не стал и решил разобраться, как касса управляет дисплеем и можно ли перехватить исходные сигналы и превратить их в обычный VGA.
В итоге я снял данные прямо с интерфейса дисплея Samsung SPS-1000 микроконтроллером STM32F407, потом RP2040, и восстановил картинку на VGA-мониторе в реальном времени. Сама касса при этом работает как обычно: микроконтроллер только слушает сигналы и собирает изображение независимо от неё.
Способ не привязан к SPS-1000. Его можно попробовать на многих старых монохромных STN-дисплеях и других экранах с параллельными данными и сигналами синхронизации.
Идея простая: старый контроллер дисплея не заменяем, а разбираемся в его сигналах, снимаем данные и строим новый интерфейс вывода.
Что понадобится
Raspberry Pi Pico (RP2040).
Отладочная плата STM32F407 Discovery.
Преобразователь уровней: 20-выводная микросхема в DIP-корпусе (например, 74LVC245 или 74HCT245), чтобы безопасно опустить логику с 5 В до 3,3 В.
Понижающий DC-DC-преобразователь: из 5 В от жгута кассы он делает стабильные 3,3 В для Pico.
Разъём VGA DB15, гнездо (на переходной плате или для монтажа на панель).
Резисторы 270 Ом для цветовых линий VGA и перемычка или резистор 0 Ом (необязательно, чтобы отключать питание при отладке).
Макетная плата, паяльник, монтажный провод и штыревые разъёмы.
Прим. пер.: 74HCT245 для такого понижения не подходит. Он питается от 4,5–5,5 В, и его выходы дают уровень около напряжения питания, то есть те же 5 В. Для перевода 5 В в 3,3 В нужен вариант вроде 74LVC245 с питанием 3,3 В.
Как устроен исходный дисплей
В Samsung SPS-1000 стоит монохромный STN-дисплей. Управляет им контроллер SED1351FOA, он и формирует все сигналы для ЖК-панели.

Изучив плату дисплея и её разъёмы, я определил такие сигналы:
U0, U1, U2, U3 — четырёхбитная шина пиксельных данных;
XSCL — тактовый сигнал данных;
LP — строчная синхронизация, защёлкивание строки;
YD — кадровая синхронизация.
Разрешение экрана — 320 × 240 пикселей.
Главным открытием стало то, что контроллер и так выдаёт цифровые данные о пикселях. Подключаться к самому стеклу ЖК-панели не нужно: сигналы можно снять раньше, чем они дойдут до драйверов дисплея. Задача сразу стала намного проще.
Как работает перехват
Микроконтроллер подключается к существующему интерфейсу дисплея и непрерывно считывает четырёхбитную шину. Контроллером Samsung он не управляет: его дело только наблюдать за сигналами.
Цепочка выглядит так:
Контроллер дисплея Samsung выдаёт четырёхбитные данные.
XSCL задаёт моменты считывания.
LP отмечает начало новой строки.
YD отмечает начало нового кадра.
Микроконтроллер складывает данные в ОЗУ.
Программа превращает снятое изображение в кадровый буфер для VGA.
VGA-движок формирует синхронизацию и видеосигнал для обычного монитора.
Важнее всего здесь понять, как шина данных, тактовый сигнал и синхронизация связаны по времени. Когда это ясно, тот же приём можно перенести на другие дисплеи.
Тайминги дисплея
Это, пожалуй, самая важная часть проекта. Прежде чем писать код захвата, я изучил тайминги исходного интерфейса ЖК-дисплея.
Экран имеет 320 пикселей по горизонтали и 240 по вертикали, а шина данных шириной 4 бита. За один такт по ней приходит четырёхбитная выборка, то есть четыре монохромных пикселя. Значит, на активную часть строки уходит 320 / 4 = 80 тактов.
Вот что я намерил:
Параметр | Значение |
|---|---|
Активных пикселей в строке | 320 |
Ширина шины данных | 4 бита |
Активных тактов в строке | 80 |
Всего тактов в строке | 218 |
Всего строк в кадре | 242 |
Лишние такты и строки приходятся на неактивные участки развёртки. Эти замеры показывают, где в общем потоке сигнала лежит само изображение.

Прим. пер.: в заметках к проекту автор приводит и абсолютные значения. XSCL идёт с частотой 8,013 МГц, то есть период около 124,8 нс. Частота строк 36,70 кГц, длительность строки примерно 27,25 мкс. Частота кадров 151,65 Гц. Цифры сходятся: 218 тактов по 124,8 нс дают те же 27,2 мкс. На осциллограмме напряжение сигналов доходит до 5,4–5,6 В, поэтому преобразователь уровней здесь не формальность. Из-за такта 125 нс автор считает опрос GPIO и обычные прерывания слишком медленными для захвата.
Совет всем, кто возится со старыми ЖК-дисплеями: не выводите тайминги из заявленного разрешения. Измеряйте сигналы и определяйте активную область сами. У разных контроллеров бывают разные интервалы гашения, полярность тактов, поведение синхронизации и форматы данных.
Восстановление изображения
Снятые данные ещё не являются кадровым буфером для VGA. Каждая четырёхбитная выборка несёт четыре монохромных пикселя, и программа должна разложить её на отдельные точки.
Для ускорения я использовал таблицу поиска:
Читаем одну четырёхбитную выборку.
Используем её значение как индекс в таблице.
Получаем четыре бита в виде выходных пикселей.
Повторяем для всего изображения.
Так не нужно вычислять что-либо отдельно для каждого пикселя.
Исходное разрешение — 320 × 240, а на VGA я вывожу 640 × 480. Каждый исходный пиксель становится блоком 2 × 2, и монохромная картинка занимает весь экран.

Вывод на VGA
Монохромный VGA-сигнал я написал с нуля. Готовую графическую библиотеку брать не стал: хотелось понять, как VGA работает на уровне железа, поэтому видеотайминги и монохромный вывод реализовал сам.
Реализации получилось две, для STM32F407 Discovery и для Raspberry Pi Pico (RP2040). Обе формируют однобитный монохромный VGA-сигнал.
Однобитный здесь значит, что на пиксель приходится один бит кадрового буфера: 0 — чёрный, 1 — белый. Для монохромного STN-дисплея этого достаточно. Трёх цветовых каналов хранить не нужно, и буфер для 640 × 480 занимает всего 640 × 480 / 8 = 38 400 байт, то есть 37,5 КиБ.
Аналоговая часть — простая резистивная схема. Видеовыход микроконтроллера подключается через резистор 220 Ом к одному из входов RGB разъёма VGA:
на зелёный вход — получится зелёный монохром;
на красный — красный;
на синий — синий;
смешав каналы, можно получить другой цвет.
Прим. пер.: в списке деталей автор указывает резисторы 270 Ом, а в описании схемы 220 Ом.
Строчную и кадровую синхронизацию VGA микроконтроллер формирует отдельно.
Генератор должен выдерживать точные тайминги. Для стандартного режима 640 × 480 примерно при 60 Гц традиционные параметры такие:
пиксельная частота — около 25,175 МГц;
строчная частота — около 31,469 кГц;
кадровая частота — около 59,94 Гц.
Видеодвижок должен согласовывать пиксельные данные со строчной и кадровой синхронизацией, и здесь становятся важны аппаратные таймеры, DMA, GPIO и аккуратное управление временем.
Генератор VGA я реализовал независимо на обоих микроконтроллерах. Это оказалось отличной школой, потому что периферия у STM32F407 и RP2040 устроена по-разному, а цель одна: стабильный монохромный VGA с картинкой, восстановленной из сигналов дисплея Samsung SPS-1000. Заодно проект стал пригоднее для других экспериментов со встраиваемыми дисплеями.
Следующий шаг: Raspberry Pi Pico (RP2040)

Когда перехват заработал на STM32F407, я захотел повторить его на микроконтроллере поменьше и подешевле и выбрал Raspberry Pi Pico на RP2040.
Идея осталась той же:
снимать четырёхбитную шину данных ЖК-дисплея;
следить за тактовым сигналом XSCL;
ловить строчную синхронизацию LP;
ловить кадровую синхронизацию YD;
восстанавливать исходное монохромное изображение 320 × 240.
Сам подход к реверсу менять не пришлось. Я просто адаптировал захват под архитектуру RP2040.
Реализация на Pico заработала на удивление хорошо. В моих опытах RP2040 давал даже более устойчивое снятое изображение, чем STM32F407. Особенно меня впечатлило, как он справляется с параллельным захватом данных. Выходит, чтобы восстановить старый интерфейс ЖК-дисплея, большая и дорогая отладочная плата не обязательна.
Прим. пер.: по README репозитория захват на Pico идёт через PIO. Конечный автомат синхронизируется с XSCL и считывает шину, DMA перекладывает выборки из приёмного FIFO в кольцевой буфер, а прерывания по LP и YD отслеживают строки и кадры. Вся PIO-программа из репозитория умещается в четыре инструкции:
.program stn_sniff
; Waits for XSCL clock edge, reads 4 data pins, and pushes to RX FIFO via DMA
.wrap_target
wait 0 pin 0 ; Wait for XSCL falling edge (adjust to 1 for rising)
in pins, 4 ; Read 4 parallel data bits into input shift register
push noblock ; Push sample immediately to FIFO (consumed by DMA)
wait 1 pin 0 ; Wait for XSCL return edge to prevent re-triggering on same pulse
.wrap
Теперь у проекта две реализации одной идеи:
Параметр | STM32F407 Discovery | Raspberry Pi Pico |
|---|---|---|
Процессор | ARM Cortex-M4 | Двухъядерный Cortex-M0+ |
Архитектура | STM32 | RP2040 |
Захват данных | GPIO и DMA | PIO и DMA (по README репозитория) |
Интерфейс ЖК-дисплея | 4-битный параллельный | 4-битный параллельный |
Синхронизация | XSCL, LP, YD | XSCL, LP, YD |
Результат | Успешное восстановление на VGA | В моих опытах захват ещё устойчивее |
Отсюда важный вывод для всех, кто возьмётся за похожий проект: приём важнее конкретного микроконтроллера. Если вы понимаете сигналы дисплея, тайминги, формат данных и требования к памяти, реализацию можно перенести на другую платформу.
Для этого проекта с Samsung SPS-1000 я теперь предпочитаю Raspberry Pi Pico.

Результат
После опытов с GPIO, прерываниями, DMA и синхронизацией проект наконец заработал: STM32F407 снимал данные с дисплея Samsung SPS-1000 и восстанавливал изображение на VGA-мониторе.
Я также сбросил Samsung SPS-1000 к заводским настройкам и убедился, что касса продолжает нормально работать. На мониторе был виден живой интерфейс системы, и он менялся при переходах по меню.
Вывод
Проект начался со старой кассы и сломанного дисплея. Вместо того чтобы выбросить железо, я изучил сигналы и их тайминги, снял цифровые данные и собрал полностью новый интерфейс вывода на VGA.
Ценнее даже работающего VGA-экрана для Samsung SPS-1000 сам приём, который можно повторить. Если старый контроллер ЖК-дисплея всё ещё выдаёт цифровые данные о пикселях, их, возможно, получится снять и показать на современном железе.
Иногда для того, чтобы вернуть старую электронику к жизни, не нужно менять всё. Достаточно послушать её сигналы.
Больше всего мне понравилось увидеть, как интерфейс старого монохромного STN-дисплея работает на современном VGA-мониторе без каких-либо изменений в исходном контроллере дисплея. Проект показал, что стекло ЖК-панели не единственный способ добраться до выводимой информации.
Удачных экспериментов!
Файлы проекта
Исходный код и подробности реализации:
Документация:
Важное предупреждение. Проект предназначен для экспериментов с электроникой и реверс-инжиниринга. Прежде чем подключать устройство захвата к работающему прибору, всегда проверяйте уровни напряжения, назначение выводов и электрическую совместимость. Не считайте, что другой STN-дисплей имеет ту же распиновку или те же тайминги, что Samsung SPS-1000.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.