Компьютерная компания Стива Джобса NeXT выпустила клавиатуру в 1988 году. Не имея опыта работы с электроникой, я попытался заставить её работать через USB. Чтобы сделать это, мне пришлось копнуть намного глубже, чем я думал, — на 100 лет назад, и изучить стандарты радиовещания 1920-х годов. Я получил массу новой информации, и мне было очень весело.
Недавно я наткнулся на клавиатуру и мышь NeXT в отличном состоянии. Это красивое устройство, и клавиши действительно приятны на ощупь, но клавиатура намного старше появления технологии USB, поэтому не сразу было понятно, как я могу подключить её к современному компьютеру. Там был странный 5-контактный круглый разъем, который, как мне удалось узнать, является разъёмом «DIN» типа «non-ADB».
На коннекторе даже есть рельефный логотип NeXT — выглядит прикольно:
Он соответствует знаменитому и красивому логотипу NeXT в верхней части клавиатуры:
К счастью, другие люди уже поработали над тем, чтобы старые клавиатуры NeXT работали и через USB. Существует довольно подробное руководство по adafruit. Я никогда по-настоящему не занимался программной работой на этом уровне, так как провел свою карьеру программиста, работая над крупными сервисами и распределёнными системами. Но это показалось мне интересным проектом, так что я купил плату Arduino Micro и 5-контактный разъем DIN от Digikey.
Я установил нужные программы и... ничего не работало как надо! Клавиши иногда работали, а иногда нет. Клавиша «A» работала отлично, но если бы я нажал «X» или «C», то перестал бы получать какие-либо сигналы, пока не отключу её и не включу снова. Что-то было не так.
Моей первой мыслью было, что я где-то что-то неправильно подключил. Но после тройной проверки я начал подозревать, что дело в программном обеспечении. После некоторых усилий я понял, как распечатать выходные данные на моем хост-компьютере через USB 1. Я ещё немного повозился, а затем обнаружил, что моя клавиатура, похоже, посылает разные сигналы «idle». Я получал 0x200C00, а не 0x200600. И все клавиши-модификаторы, казалось, отклонялись на один бит от ожидаемых значений в примере кода.
Я начал менять некоторые коды клавиш, чтобы они соответствовали нужным параметрам, думая, что некоторые значения могут отличаться для разных моделей клавиатуры. Но потом заметил, что клавиши нестабильно дают одинаковые коды! Ошибка крылась где-то глубже. Я начал интересоваться этой диаграммой в оригинальном руководстве Adafruit.
Я нашёл статью от человека по имени Дрейк, который отметил, что временной интервал может достигать 54 микросекунд. А затем я обнаружил, что прошивка клавиатуры TMK с открытым исходным кодом имеет реализацию для клавиатур Next, отличных от ADB, с интригующим комментарием:
/* The keyboard sends signal with 50us pulse width on OUT line
* while it seems to miss the 50us pulse on In line.
* next_kbd_set_leds() often fails to sync LED status with 50us
* but it works well with 51us(+1us) on TMK converter(ATMega32u2) at least.
* TODO: test on Teensy and Pro Micro configuration
*/
Очевидно, я был не единственным, кто с подозрением отнёсся к заявлению о 50 микросекундах.
Даже при разных значениях времени в этом протоколе всё ещё были странные вещи. Я имею в виду, зачем инженерам NeXT отправлять 22-битные сообщения? И почему они иногда были 23 битами? Это странное решение. Я предположил, что, возможно, они отправляли два 10-битных сообщения (состоящих из 1 начального бита, 8 бит данных и 1 стоп-бита), с небольшим промежутком между ними произвольной, но обычно небольшой длины). Это имело бы гораздо больше смысла: в нём использовались бы типичные 8-битные пакеты данных, а фрагмент переменного размера в середине позволил бы получателю настроить триггер для повторной синхронизации падающего края при чтении второго байта.
Но всё же, почему 51 микросекунда? Это казалось странной шириной импульса. Я просмотрел таблицу в Википедии общих тактовых частот, используемых в электронике, но не нашёл ничего, что выглядело бы слишком близко к 20 кГц — до тех пор, пока однажды, при настройке монитора для получения отладочных данных из моего Arduino, я не заметил опцию 19200 бод. Эврика! 19200 бод означает отправку битов со скоростью 19,2 кГц - другими словами, с шириной импульса 52,08 микросекунды! Могут ли non-ADB клавиатуры NeXT использовать сигнал 19200 бод?
Я размышлял и ещё над одним вариантом. Всё же передо мной была клавиатура 33-летней давности. Возможно, электронные компоненты в ней просто износились, со временем переходя на работу с чуть меньшей скоростью. Возможно, изначально они были рассчитаны на 20 кГц, и, возможно, диаграммы когда-то были правильными, но время "съело" их. Я нашёл подсказку в этом направлении в сообщении на форуме 2003 года, где кто-то упомянул, что старые клавиатуры Next, похоже, испортились. Может быть, они испортились из-за того, что часы медленно сбивались, делая клавиатуру всё более безумной.
Может такое быть?
Анализ сигналов с помощью Arduino
Эти вопросы не давали мне покоя, поэтому я начал пытаться добавить инструменты в код Arduino, чтобы видеть, когда начинались и заканчивались биты. Это оказалось бесполезным. В то время я не понимал, что библиотеки Arduino являются относительно высокоуровневыми, и поэтому такие функции, как digitalWrite и digitalRead, могут компилироваться в десятки инструкций, включая разыменование указателей, и могут занимать много тактов.
Микроконтроллер ATMega32u4 Arduino Micro имеет тактовую частоту 16 МГц, поэтому каждый тактовый цикл занимает 62,5 наносекунды. Не так уж много тактовых циклов требуется для того, чтобы вызов функции Arduino занял несколько микросекунд, а это значит, что мой наивный, читаемый код не очень хорошо измерял поведение этого сигнала, так как я подозревал, что разница между 50 и 51 или 54 микросекунды были проблематичными. Я продолжал получать данные, которые не имели никакого смысла, и которые на самом деле больше касались моей неспособности эффективно сэмплировать сигнал.
Я купил осциллограф
В итоге я решил, что пришло время обзавестись осциллографом и логическим анализатором. Именно тогда я понял, что каким-то образом стал одержим идеей выяснить частоту этой непонятной клавиатуры с проприетарным мёртвым протоколом. Я буквально лежал ночью без сна, просто задаваясь вопросом: о чем думали дизайнеры?
Когда осциллограф пришёл, я посмотрел краткое обучающее видео на YouTube, подключил его с небольшим советом от друзей и быстро изолировал сигнал — и вот оно, 52 микросекунды!
Это был чудесный момент. Наконец-то я смог увидеть мерцающий на экране сигнал. Но я обнаружил, что осциллограф сложен в использовании при попытке получить точное измерение ширины импульса. Я не сомневаюсь, что любой, у кого больше опыта, чем у меня, мог бы добиться большего успеха ... но мне нужно было попробовать другое устройство.
Логические анализаторы
Логические анализаторы удивительны:
Это устройство берёт образцы напряжения на выводе со скоростью 100 МГц, измеряя значение каждого провода каждые 10 наносекунд. Этот инструмент достаточно хорош, чтобы получить чёткое представление о том, что происходило:
Выяснилось несколько моментов:
Сигнал выглядит так, как будто это действительно два 9-битных сообщения, разделённых границей шириной 1 импульс.
Импульсы имели чрезвычайно стабильную ширину 52,74 +/- 0,02 микросекунды. Если электроника и старела, то, по крайней мере, она старела очень и очень последовательно.
Когда я сказал своему Arduino спать 51 микросекунду, он обычно спал 56,2 или 61,3 микросекунды. Это вызвало множество проблем.
Вот ещё одно изображение, показывающее эти тайминги — обратите внимание на цифры справа, которые измеряют промежутки между зелёными линиями:
Моей первой реакцией на это было «вау, этот дешёвый логический анализатор творит чудеса». Однако моей второй реакцией было ещё большее замешательство. 52,74 микросекунды соответствует... 18,960 кГц? Что это, черт возьми, такое?
Теперь у меня были инструменты для написания лучшего программного обеспечения для USB-конвертера. Я знал ширину импульса и мог последовательно получать точно правильные битовые шаблоны для любого нажатия клавиши или комбинации.
Но… Я не мог оставить без внимания вопрос о частоте. Почему 18 960 Герц для сигнала? Я решил, что пришло время взломать клавиатуру и посмотреть на компоненты.
Внутри зверя
Я открутил винты на задней панели клавиатуры. Сначала я был в замешательстве, пока не понял, что два винта хитро спрятаны под толстыми резиновыми ножками клавиатуры.
Затем я внимательно рассмотрел печатную плату. Первое, что я заметил, была массивная интегральная схема вверху с логотипом Motorola на ней. Я попытался погуглить, но почти ничего не смог найти.
Я перевернул печатную плату... и заметил, что на ней есть какие-то пометки. Они выглядели как этикетки, указывающие на использование деталей с другой стороны. Один выглядел особенно любопытно: Ceralock. Я посмотрел название, и “Ceralock”, похоже, является производителем генераторов и резонаторов - низкоуровневых компонентов, которые можно использовать для настройки частоты электронных сигналов. Может быть, именно в этом и кроется секрет!
И действительно, прямо напротив маркировки Ceralock была эта маленькая оранжевая башня:
Это CSB455E. Частота резонатора составляет 455 кГц. Итак, здесь что-то работает с частотой 455 кГц. Может быть, это биты с клавиатуры? Я немного поиграл с числами... и нашёл:
455 кГц / 24 = 18 958 Герц.
У меня буквально отвисла челюсть. Это примерно то, что я наблюдал с помощью логического анализатора. Это было невероятно приятно! Я наконец-то нашел ответ на старую загадку!
Клавиатуры NEXT без ADB имеют ширину импульса 52,74 микросекунды, поскольку они отправляют данные каждые 24 такта тактовой частоты 455 кГц.
455?
Оставался один вопрос: почему 455 кГц? Это странное число для компьютера: не простая степень 2, что затрудняет математику при масштабировании частоты.
Я спросил кое-кого из старых мудрых электронщиков, с которыми я работаю, и быстро получил ответ: в электронике вы постоянно видите тактовые частоты 455 кГц, особенно в старых устройствах, потому что они чрезвычайно часто используются в радиоприемниках AM.
За эти годы были изготовлены миллиарды этих маленьких компонентов с частотой 455 кГц для радиопромышленности, что делает их невероятно дешевыми. Они производят частоту, достаточно близкую к 19 200 бодам. Так что инженеры NeXT, вероятно, использовали один из них, потому что это был простой дешёвый компонент, который мог выполнить эту работу.
Хорошо, но почему они используются в радиоприемниках AM? Что ж, оказывается, это извечный вопрос, и он уходит корнями в далёкое прошлое. Я не совсем понимаю все детали, но AM-радио требуют небольшого тактового компонента, и желательно, чтобы этот компонент не находился слишком близко к любым активно используемым частотам вещания.
В Северной и Южной Америке AM-радио может транслироваться только на специально отведённых частотах, кратных 10 кГц: 440 кГц, 450 кГц, 460 кГц и так далее. Но в остальном мире AM-радио транслируется на частотах, кратных 9 кГц: 441 кГц, 450 кГц, 459 кГц, 468 кГц и так далее.
455 кГц — хороший компромисс между этими 2расстояниями между каналами». AM-радиоприемник с этим внутренним компонентом на частоте 455 кГц будет хорошо работать на любом рынке!
Эпилог
Я получил огромное удовольствие, изучая все эти вещи. Я даже не упомянул о своих приключениях, изучающих программирование AVR: как только я хорошо понял сигнал, я понял, что хотел бы, чтобы прерывания по таймеру управляли моей логикой, и обнаружил, что вспомогательные библиотеки Arduino более обременительны, чем полезны — и поэтому я выплыл в мутные воды программирования по данным.
Мой код доступен здесь, но предупреждаю, что я не делал никаких попыток переносимости и не могу ручаться за код. Я сделал это, чтобы чему-то научиться. Но мне, конечно, было очень весело, и я вернусь, чтобы узнать больше о мире электроники.
Что ещё интересного есть в блоге Cloud4Y
→ История Game Genie — чит-устройства, которое всколыхнуло мир
→ Как я случайно заблокировал 10 000 телефонов в Южной Америке
→ WD-40: средство, которое может почти всё
→ Как ИИ учится рисовать аниме
Подписывайтесь на наш Telegram-канал, чтобы не пропустить очередную статью. Пишем не чаще двух раз в неделю и только по делу.