Введение

Набирая текст на клавиатуре мы не задумываемся как она работает, пока не столкнемся с той или иной проблемой, для решения которой уже нужно понимание внутреннего устройства. Часто пользователи и геймеры сталкиваются с проблемами связанными с одновременным нажатием нескольких клавиш. В некоторых ситуациях это неприятно, а иногда даже критично. Давайте разбираться, что такое KRO, #KRO, 6KRO, NKRO и Ghosting.

Расшифруем эти аббревиатуры:

KRO (Key Rollover) Количество одновременных нажатий клавиш.

#KRO – символ # – это максимальное количество клавиш, которые можно нажать одновременно и не сомневаться, что сигнал будет правильно обработан и передан компьютеру. Большинство мембранных клавиатур выпускается в классах 2KRO или 3KRO. Среди механических встречаются и клавиатуры класса 20KRO.

6KRO – (6-Key Rollover) 6 одновременных нажатий клавиш.

NKRO – неограниченное количество одновременных нажатий клавиш.

Ghosting – «фантомное нажатие». Подача сигнала с клавиши, которой вы не касались.

Разберемся как фиксируются и передаются нажатия клавиш в различных клавиатурах и как это устроено.

Полноразмерная клавиатура содержит 104/105 клавиш. Для регистрации нажатия со стопроцентной точностью требуется провести от каждой кнопки до контроллера провод и один общий на все — землю. Примерно по такой схеме:

Логично, что данная реализация сложная и дорога в производстве, виной тому, в основном, физические ограничения микроконтроллеров, на базе которых строятся клавиатуры. Дело в том, что с увеличением количества выводов у микроконтроллеров и программируемых логических микросхем растёт и их размер, что, в свою очередь, влечёт за собой рост энергопотребления, возможностей, но главное — цены. В итоге, вы можете выбрать либо дешёвый чип с небольшой производительностью, но с малым количеством входов и выходов, либо более мощную микросхему, производительность которой, однако, сильно превышает ваши требования. Но только этот мощный чип будет обладать достаточным количеством выводов, чтобы подключить каждую кнопку клавиатуры.

Поэтому многие недорогие клавиатуры строятся по принципу матрицы. Это набор пересекающихся горизонтальных и вертикальный контактов. Контроллер сканирует столбцы, обнаруживая сигнал сканирует уже строки и таким образом вычисляет нажатие.

В случае, если вы нажимаете, S + H и захотите нажать третью клавишу в другом ряду, контроллер уже не может сказать, какая из линий была замкнута и в лучшем случае не обнаружит одно из трёх нажатий, а в худшем, из-за особенностей разводки, определит ещё какое нибудь лишнее, которое вы не совершали. 

Давайте посмотрим, что случится, если нажать несколько кнопок, находящихся одновременно в одной строке и в одном столбце.

Пример фантомного нажатия

На рисунке три кнопки нажаты одновременно. Две из них находятся в столбце «C2», и две — в строке «Rm». Это значит, что одна из нажатых кнопок делит строку с другой нажатой кнопкой, а столбец — с третьей нажатой кнопкой. Именно в такой ситуации и происходит фантомное нажатие. Представьте, что в данный момент мы опрашиваем столбец «C1» (то есть, он придавлен к земле — находится в состоянии «0»). Такой характерный аккорд нажатых кнопок приводит к следующему: даже несмотря на то, что левая верхняя кнопка не нажата, строка «R2» находится в состоянии «0», потому что она придавлена к земле столбцом «C1» (находящемся в «0») через три нажатые кнопки. В результате клавиатурный контроллер считывает левую верхнюю кнопку, как «нажатую», вне зависимости от того, нажата она на самом деле или нет. Описанная ситуация называется фантомным нажатием (ghosting), потому что некоторые комбинации одновременно нажатых кнопок вызывают фантомное срабатывание других кнопок (ghost keypresses), хотя физически эти другие кнопки и не нажаты.

Можно поймать момент возникновения фантомного нажатия и заблокировать его. Обычный человек не в состоянии одновременно нажать или отпустить две клавиши с идеальной точностью. Поэтому, сканируя матрицу достаточно быстро, мы можем предположить, что между двумя проходами по матрице изменить своё состояние может не больше одной кнопки. В таком случае, контроллер принимает одиночные нажатия и следит за возникновением ситуаций, когда между проходами матрицы оказываются нажатыми две кнопки или более. Учитывая, что сканирование матрицы происходит со скоростью, при которой штатное возникновение таких ситуаций крайне маловероятно, можно заключить, что одна из только что нажатых кнопок — призрак. Поэтому контроллер должен проигнорировать все эти нажатия. Кроме того, безопаснее сразу не сообщать компьютеру об изменениях статуса клавиатуры — сначала имеет смысл подождать, пока все эти срабатывания не пропадут.

Есть и другой подход. Можно выявить ситуацию, когда срабатывает «третья» кнопка, и заблокировать как это нажатие, так и все последующие. Блокировку не снимать до тех пор, пока фантомное срабатывание не пропадёт, и ситуация опять не станет нормальной. Для реализации этого подхода программа должна помнить, какие именно кнопки сейчас нажаты (а обычно она это помнит и так), чтобы отклонять последующие срабатывания кнопок, в строках и в столбцах которых уже зафиксированы одновременные нажатия. Если написать программу с умом, то блокироваться будут только проблемные срабатывания, а все последующие будут приниматься как обычно — кроме тех, что снова нарушат правила. Раз контроллер отвергает нажатие каждой кнопки, уже имеющей одновременные срабатывания в своей строке и столбце, то выходит, что в зависимости от статуса одних кнопок, другие могут не регистрироваться вообще. Эта ситуация широко известна как блокирование (jamming). То есть кнопки, которые препятствуют одновременным срабатываниям других кнопок, получается, «блокируют» часть клавиатуры.

С точки зрения пользователя, можно одновременно нажать все кнопки из одного столбца (не нажимая кнопок из другого), но одновременно нажать все кнопки из одной строки можно только в том случае, если в столбце у каждой из этих кнопок зафиксировано не более одного срабатывания. То же самое относится и к нажатию кнопок из одного столбца — дополнительные срабатывания фиксируются только в том случае, если кнопки находятся в строках, которые «не заняты».

Люди часто путают «фантомное срабатывание» и «блокирование срабатывания» («ghosting» и «jamming»)

В клавиатурах с использованием таких матриц, как мы только что рассмотрели, невозможно избежать ни фантомных срабатываний, ни блокирования. Поскольку фантомные срабатывания в повседневной работе недопустимы, то для борьбы с ними практически все производители резинокупольных клавиатур пускают в ход различные ухищрения, и в игру вступает блокирование. 

Решается подобное поведение различными хитростями в области разводки: наиболее популярные сочетания размещаются на разных линиях, функциональным клавишам, которые часто являются элементами хоткеев, назначаются отдельные линии. Разводка остается достаточно простой, но в недорогих клавиатурах редко встречается 5+KRO — обычно дело ограничивается 3-4 одновременно зажатыми клавишами. 

Сейчас эта дешёвая система почти полностью вытеснена более сложной, «открытой» матрицей, однако, экземпляры до сих пор встречаются.

В дорогих клавиатурах используются более сложные схемы, несколько контроллеров, индивидуальное подключение, многослойные печатные платы, одним словом различные подходы, которые уменьшают или полностью убирают Ghosting, но приводят к росту цены.

Так же стоит рассказать, что такое дребезг контактов в механических переключателях и про борьбу с ним. При работе с механическими кнопками возникает одна проблема — дребезг контактов. Суть его в том, что при замыкании контакт срабатывает не один раз, а в момент замыкания и размыкания происходит несколько срабатываний. Происходит это от того, что идеальный контакт возникает не сразу, а через какое то время, искрит и скрежещет, хоть это и не видно. Вот и получается, что вместо одного перепада получаем вначале серию всплесков и только потом возникает устойчивое состояние.

Но микроконтроллер работает с такой скоростью, что успевает посчитать эти всплески как устойчивые состояния. Решить эту проблему можно аппаратно, с помощью RS триггера, так и программно — внеся небольшую задержку перед следующим опросом кнопки. Задержка подбирается такой, чтобы дребезг успел прекратиться к ее окончанию.

Про PS/2 или что было до USB

Самым распространенным разъемом для подключения мыши и клавиатуры до USB был PS/2. Впервые он появился в 1987 году на компьютерах IBM PS/2. Скорость передачи данных — от 80 до 300 Кб/с и зависит от производительности подключенного устройства и программного драйвера.

Сиреневый — клавиатура, зелёный — мышь

Из шести контактов в разъёме используется четыре: тактовые импульсы, данные, питание, общий.

  • Pin 4 — Питание, +5 В. Используется для подачи питания на подключаемое устройство.
  • Pin 3 — Земля/Корпус. Общий вывод для питания.
  • Pin 5 — CLK — синхронизация (Clock). Включается при передаче данных мышью.
  • Pin 1 — Data, передаваемые данные.

В настоящее время подавляющее большинство изготавливаемых компьютерных мышей и клавиатур имеют разъем USB, современные материнские платы не имеют разъёма PS/2 или имеют только один разъём, хоть ещё и можно встретить материнские платы с этим разъемом, это скорее уже редкость. Современные ноутбуки и ультрабуки вовсе не имеют внешних разъемов PS/2. Также у PS/2 наблюдается ряд недостатков таких как проблемы с Plug’n’Play и неудобство самого разъема.

Сами устройства ввода генерировали прерывание и отправляли информацию о нажатых кнопках или перемещении курсора. И тут хоть стучи по клавиатуре палкой, если всё разведено грамотно, и rollover не упирается в аппаратные возможности клавиатуры — клавиатура отправит всё, что прочитает контроллер.

NKRO на USB

И так мы разобрались, что PS/2 разъем практически вышел из употребления, давайте посмотрим как обстоят дела с популярным USB.

Для работы клавиатур через USB до загрузки системы (BIOS / UEFI) используется стандартный HID-драйвер (human interface device), который был разработан для максимально широкой поддержки клавиатур и USB-хостов. Класс USB HID описывает устройства таким образом, чтобы стандартная реализация USB-хоста и USB-устройства могли взаимодействовать без установки специальных драйверов.

Обычная клавиатура (с поддержкой USB HID) использует выходной (исходящий от USB-хоста) поток данных (endpoint USB-стека) для получения информации о состоянии индикаторов (Num / Caps / Scroll Lock), и входной поток (исходящий от клавиатуры, «входящий» для USB-хоста) для отправки информации о нажатых клавишах.

Если следовать наиболее строгой спецификации USB HID v1.11, которая поддерживает режим USB Boot (и позволяет использовать USB-клавиатуру для входа в BIOS и работы в нём), то клавиатура будет отправлять прерывания на CPU каждый раз, как USB-хост будет опрашивать её, вне зависимости от того, изменилось её состояние или нет. Таким образом «эмулируется» работа PS/2 клавиатур минимальными издержками.

В данном случае клавиатура работает по стандарту USB 1.1 (иногда 2.0) Low-speed, а частота опроса порта составляет 100 Гц. В данном режиме максимальная длина пакета на USB равна 8 байтам, а отправляются они раз в 10 мс. Один из байтов зарезервирован, так что на работу клавиатуры остаётся 7 байт, т.е. количество достаточное, чтобы закодировать нажатие любой клавиши-модификатора и еще шести других.

Получится, кто клавиатура работает в режиме 6-KRO, и он является стандартным для большинства USB-клавиатур. Сделать меньше — можно, больше — только с нарушением спецификации USB HID. Уже после загрузки система может увеличить частоту опроса USB-порта, загрузить драйвер, который позволит работать с мультимедийными клавишами и макросам.

Обходы ограничений USB HID, собственно, встречаются двух видов. В первом случае клавиатура обнаруживается фирменным ПО, переводится в какой-нибудь специальный режим и отправляет данные с контроллера напрямую в драйвер, а тот уже общается с системой. Минус такого решения — увеличивается т.н. input lag: задержка ввода.

Второе решение подкупает своей простотой и бесхитростностью, но по сути является костылём:

Клавиатура просто представляется в системе несколькими HID-устройствами, каждое из которых имеет свои 6KRO. Таким методом пользуются популярные производители периферии такие как Logitech, A4tech, Cougar и SteelSeries.

Кардинальное решение матричных проблем

Если вы еще раз взглянете на картинку про фантомные нажатия, то сможете заметить, что во всём виновата правая нижняя кнопка.

А ведь эта кнопка — единственная, через которую ток в данной ситуации течёт «вверх». Так что, если мы не хотим, чтобы текущие «вверх» токи мешали нам нормально считывать матрицу, то давайте введем диоды, чтобы ток мог идти по столбцам строго сверху вниз, втекая в выходы микроконтроллера.

К сожалению, сэкономить тут не получится — придётся ставить по диоду на каждую кнопку. Если же говорить о полярности, то вы уже должны были разобраться, что в данном конкретном случае диоды должны пропускать ток «сверху вниз», то есть их катоды («кончики стрелок») должны смотреть на выходы микроконтроллера (столбцы), тогда как аноды должны быть обращены ко входам (строкам).

Итоговая матрица

Не имеет значения, с какой стороны кнопки располагать диод; главное — соблюсти верную полярность. Просто запомните, что в данном случае ток всегда будет течь от входов к выходам. К слову, если входы подтянуты к питанию, а выходы — в режиме ОС, то так происходить будет всегда.

При данном подходе получается, что ток всегда будет течь «вправо вниз», и это исключает появление замкнутых токовых контуров при одновременном нажатии нескольких кнопок. Кроме того, эта конструкция — единственная, которая может обеспечить клавиатуре полный NKRO. Вдобавок, нелишним будет упомянуть (хотя это и кажется очевидным), что проблема отсутствия у выходов микроконтроллера режима ОС решается теперь автоматически. Диоды, установленные последовательно с каждой кнопкой, избавляют выходы от замыкания.

Существуют моды проделанные энтузиастами по установке диодов в механические клавиатуры:

Итоги

Получается все производители выбрали использовать хитрость, что собственно не создает пользователю особых проблем и он получает вполне рабочий NKRO по USB. Но имейте в виду, что NKRO матрицы и NKRO клавиатуры — это две большие разницы.

Проблему матрицы полностью решают диоды включенные последовательно с каждой кнопкой. Тогда можно обеспечить сканирование любых комбинаций. Чтобы не иметь проблем с NKRO желательно быть обладателем качественной механической клавиатуры.

Литература:
http://blog.komar.be/how-to-make-a-keyboard-the-matrix/
https://deskthority.net/viewtopic.php?f=7&t=6050&start=
https://geekhack.org/index.php?topic=20898.0
https://habr.com/ru/company/ulmart/blog/384797/
https://fantech.com.ua/articles/noob-vs-pro-4-fantomnye-nazhatiya-nkro-i-anti-ghosting/
https://ru.computersm.com/simple-questions-what-is-nkro-technology#menu-1
https://geekboards.ru/page/termin
https://habr.com/ru/post/394585/
https://www.digitalcitizen.life/what-is-nkro-6kro-keyboards/
http://easyelectronics.ru/matrichnaya-klaviatura.html