Consul 254 похож на принтер, но это не принтер. Ещё у него есть клавиатура, но при этом печатающая часть никак не связана со вводом, поэтому так просто получить что-то на бумаге не выйдет. Эту проблему мы и будем сегодня решать с помощью Ардуино и цветных проводочков. Конечно всё уже украдено до нас, и такую вещь уже описывали в журнале Моделист-Конструктор в 1989 году. Правда при этом использовался компьютер "Специалист", а не Ардуино.
![](https://habrastorage.org/getpro/habr/upload_files/499/ba3/72e/499ba372e14333e69799cee0a64cea2b.jpg)
Как устроена печать в Консуле
Печатающая часть машины управляется с помощью матрицы реле 8x8. Правда не все комбинации используются, так что выходит поменьше, чем 64 видов сигналов. Есть те, которые меняют состояние (нижний или верхний регистр), есть управляющие работой каретки (новая строка, пробел), а есть те, что печатают символы.
![Выглядит страшно, но разобраться вполне реально. Выглядит страшно, но разобраться вполне реально.](https://habrastorage.org/getpro/habr/upload_files/724/2bf/0f2/7242bf0f2c488a0af9789e57eddab03c.png)
Чтобы не вбивать все эти коды почти 64 команд, я вбил дампы для "Специалиста" из журнала (звучит очень логично, да), дизассемблировал драйвер и разобрал содержимое ПЗУ, управляющее матрицей реле. Оказалось, что там почему-то отличается раскладка русских символов. Может быть, было несколько вариантов таких машин? Или я что-то сделал не так.
![Таблица перекодировки символов со "Специалиста". Первая цифра в коде - столбец матрицы, вторая - строка. Например, пробел (0x20) кодируется как 02 или столбец I, строка C. Таблица перекодировки символов со "Специалиста". Первая цифра в коде - столбец матрицы, вторая - строка. Например, пробел (0x20) кодируется как 02 или столбец I, строка C.](https://habrastorage.org/getpro/habr/upload_files/c70/3a1/406/c703a14064699284d4761aa4726d7286.png)
Но, по крайней мере, некоторые символы совпадали, и я понял, что именно мне делать. Чтобы управлять матрицей, надо было чем-то подавать 12 Вольт на реле Консула. Напряжение я взял от компьютерного блока питания, а для его коммутации пришлось купить две платы, на каждой из которых есть восемь пятивольтовых реле. Такие модули легко подключить к ардуино, но выходов Uno уже не хватало, поэтому я взял Arduino Mega. Получилась примерно такая схема:
![Модули с реле показаны условно, потому что в библиотеке KiCAD готовых модулей не было. Как и платы Arduino, так что тут нарисован непосредственно микроконтроллер. Модули с реле показаны условно, потому что в библиотеке KiCAD готовых модулей не было. Как и платы Arduino, так что тут нарисован непосредственно микроконтроллер.](https://habrastorage.org/getpro/habr/upload_files/a0f/86c/b46/a0f86cb46e89425bae3f6cd301b6bacb.png)
А вот так выглядит эта схема в мире вещей:
Строки матрицы реле подключены к контактам A-H разъёма I, а столбцы - к контактам I-P. Соответственно, нужная строка выбирается с помощью одного внешнего регистра микроконтроллера, а столбец - с помощью другого. Очень удобно программировать, главное не включить пару строк или столцов одновременно.
Теперь дело за малым - включать реле в нужном порядке, чтобы срабатывающие молоточки написали текст "HELLO, WORLD!" или что поинтереснее. На этом этапе возникли несколько неожиданных проблем.
Во-первых, реле надо не только включать, но и выключать. Если сделать это слишком быстро, молоточек не сработает. Если задержаться, он сработает дважды. Да ещё и разные молоточки двигаются с немного отличающейся скоростью, задержку подобрать не выходит. К счастью, в Консуле есть контакт, который замыкается, когда молоточек приближается к бумаге. Так что если размыкать реле при его появлении, всё работает нормально.
Однако, вопреки утверждению из документации, этот сигнал не используется для пробела. Наверное логично, ведь при этом ничего не печатается. Но тогда должен быть какой-то другой секретный контакт для индикации движения каретки. Я правда не стал его искать, а просто использую задержку при выводе пробела. Тут проблем как с буквами не возникает.
А третья проблема оказалась не программной. Я очень долго возился с механикой возврата каретки. То возврат не начинался вообще, то не хотел заканчиваться, когда тесьма, которая тянет каретку, не хотела отпускать её. С помощью какого-то необъяснимого шаманства и объяснимой очень аккуратной (чтобы все движущиеся части попали куда надо) установки каретки на машину, эти проблемы удалось победить.
Пробуем что-то напечатать
Естественное желание любого советского человека с АЦПУ - распечатать Мону Лизу, как в "Служебном романе".
![](https://habrastorage.org/getpro/habr/upload_files/abf/ae6/708/abfae670879140a3a6470fe07d96f9c9.jpg)
Правда ровно такую же картинку найти не удалось. Да и ширина каретки не позволяет заправить в неё бумагу 42 см. Ну и ладно, возьмём другую картинку из интернета, заменим символы, которых в машине нет (например, #), и будем печатать.
![](https://habrastorage.org/getpro/habr/upload_files/773/0e6/797/7730e6797f31ffe66310f1376da4a22d.png)
И внезапно проявился ещё один странный баг. Если печатать пробел или букву "Z", то иногда проскакивает "крестик", который расположен в том же столбце матрицы реле. Причём литерный рычаг с символами 7x начинает двигаться позднее, чем Z, так что обычно лишний символ не успевает напечататься. Я так и не понял, почему это происходит. Может кто предложит идею?
![Молоточек с цифой 7 срабатывает, если долго подавать сигнал "пробел" или просто печатать букву Z. Молоточек с цифой 7 срабатывает, если долго подавать сигнал "пробел" или просто печатать букву Z.](https://habrastorage.org/getpro/habr/upload_files/9e1/f7e/20b/9e1f7e20b59546ea86c40a0443e834fd.png)
В общем я просто заменил все буквы Z на рисунке на N и всё же вывел картинку. Вот так это работало:
Конечно очень весело хардкодить такие картинки, но надо же и попробовать управлять машиной через её собственную клавиатуру, не зря же она существует.
Ввод и вывод
Алгоритм работы пишущей машинки:
читаем сканкод с клавиатуры;
преобразовываем сканкод в char;
находим строку и столбец для реле, которое надо включить;
включаем реле и печатаем символ на бумаге;
выключаем реле.
Про первую часть я уже писал отдельную статью. Там было упоминание, что Консул ничего не делает при нажатии клавиш смены регистра, а лишь посылает их код. Это действительно так. Но всё-таки его состояние меняется, если при нажатии этих клавиш (или в случайный момент времени, чтобы оператору было веселее печатать), мы отправим соответствующий сигнал (верхний или нижний регистр) на матрицу реле. В этом случае регистровый механизм смещается, а его положение можно определить по замкнутой или разомкнутой цепи IV C-IV K. Этот сигнал входит в один из тех битов, которые уже читаются, как код символа клавиатуры. Получается, что запоминать состояние регистра в компьютере смысла нет, достаточно иметь таблицу перекодировки с учётом этого сигнала (которую я и так набрал раньше).
Отдельное веселье ждало меня с русскими символами. Их коды, очевидно, больше, чем число 127. Поэтому при использовании char (который в этом компиляторе оказался знаковым) в качестве индекса массива, получались неправильные смещения после преобразования в size_t (или там ssize_t? попробуй разбери эти компиляторы). В результате всё работало не так. Хорошо, что Консул не умеет показывать синий экран.
В общем, пишущая машинка получилась. Хотя пока задействованы не все функции - Консул поддерживает двухцветную печать, но такая лента ко мне ещё не приехала, поэтому попробовать не вышло. Так что вероятно будет ещё одна серия про что-нибудь интересное.