Просмотр полной версии : Контроллер для подключения PS/2 клавиатуры
Соберу здесь всю выжимку по данному девайсу.
Огромная благодарность Xrust (https://zx-pk.ru/members/8490-xrust.html) за разработку контроллера.
Схема, герберы и прочая информация по универсальному контроллеру - здесь. (https://zx-pk.ru/threads/33211-universalnyj-kontroller-ps-2-klaviatury-dlya-kompyuterov-s-matrichnymi-klaviaturami.html)
Купить платы или готовые устройства можно здесь. (https://zx-pk.com/forum/viewtopic.php?f=7&t=18766)
По-умолчанию матрица для прошивки аутентичной клавиатуры (ЙЦУКЕН-JCUKEN), но можно переключать по F12 на QWERTY, также учитывается, чтобы можно было относительно несложно обжать шлейф:
127,127,127,39, 43, 47, 45, 127,127,127,
127,127,41, 50,88,127,127,28,30,127,
20,74, 124, 127,127,127,44, 12, 98, 104,
122, 18,127,40, 2, 32, 36, 118, 120, 127,
127,48,68, 108, 100, 72, 116, 127,127,38,
76, 42, 46, 66, 114, 127,127,127,14, 64,
96, 112, 94, 127,127,106,70, 8, 4, 126,
92, 127,127,86, 80 ,102, 34,10, 84,127,
127,127,6,127,78, 90, 127,127,127,16,
62, 0, 127,82,127,127,127,127,127,127,
127,127,52,127,127,109, 127,103, 97, 127,
127,127,111, 70, 107, 101, 99, 79, 24,127,
58,127,105, 127, 127,77, 127,127
Вся прошивка, с включенным кодом перезагрузки контроллера по кнопке ScrollLock:
#include <PS2KeyRaw.h>
#define AX0 4
#define AX1 5
#define AX2 6
#define AX3 7
#define AY0 8
#define AY1 9
#define AY2 10
#define RSTMT 14
#define CSMT 15
#define DATMT 16
#define STBMT 17
#define DATAPIN 2
#define IRQPIN 3
volatile boolean d = HIGH;
uint8_t table[128] = {
127,127,127,39, 43, 47, 45, 127,127,127,
127,127,41, 50,88,127,127,28,30,127,
20,74, 124, 127,127,127,44, 12, 98, 104,
122, 18,127,40, 2, 32, 36, 118, 120, 127,
127,48,68, 108, 100, 72, 116, 127,127,38,
76, 42, 46, 66, 114, 127,127,127,14, 64,
96, 112, 94, 127,127,106,70, 8, 4, 126,
92, 127,127,86, 80 ,102, 34,10, 84,127,
127,127,6,127,78, 90, 127,127,127,16,
62, 0, 127,82,127,127,127,127,127,127,
127,127,52,127,127,109, 127,103, 97, 127,
127,127,111, 70, 107, 101, 99, 79, 24,127,
58,127,105, 127, 127,77, 127,127};
uint8_t t_qwerty[128] = {
127,127,127,39, 43, 47, 45, 127,127,127,
127,127,41, 50,88,127,127,28,30,127,
20,44, 124, 127,127,127,10, 40, 108, 32,
122, 18,127,104, 14, 102, 100, 118, 120, 127,
127,48,34, 98, 38, 42, 116, 127,127,66,
106, 78, 96, 12, 114, 127,127,127,68, 74,
36, 112, 94, 127,127,106,72, 76, 64, 126,
92, 127,127,86, 80 ,70, 34,46, 84,127,
127,127,6,127,78, 90, 127,127,127,16,
62, 0, 127,82,127,127,127,127,127,127,
127,127,52,127,127,109, 127,103, 97, 127,
127,127,111, 70, 107, 101, 99, 79, 24,127,
58,127,105, 127, 127,77, 127,127};
volatile boolean qwerty = false;
volatile boolean sw = true;
PS2KeyRaw keyboard;
void setup() {
//Инициализация портов
pinMode(19, OUTPUT);
pinMode(AX0, OUTPUT); //AX0
pinMode(AX1, OUTPUT); //AX1
pinMode(AX2, OUTPUT); //AX2
pinMode(AX3, OUTPUT); //AX3
pinMode(AY0, OUTPUT); //AY0
pinMode(AY1, OUTPUT); //AY1
pinMode(AY2, OUTPUT); //AY2
pinMode(RSTMT, OUTPUT); //RES
pinMode(CSMT, OUTPUT); //CS
pinMode(DATMT, OUTPUT); //DAT
pinMode(STBMT, OUTPUT); //STB
//Инициализация клавиатуры
keyboard.begin( DATAPIN, IRQPIN );
//Инициализация MT8816
SetAddr(0);
digitalWrite(RSTMT, LOW);
digitalWrite(CSMT, LOW);
digitalWrite(DATMT, LOW);
digitalWrite(STBMT, LOW); //инициализация
digitalWrite(CSMT, HIGH); //выбор чипа
digitalWrite(RSTMT, HIGH);
digitalWrite(RSTMT, LOW); //сброс
digitalWrite(CSMT, LOW);
}
void SetAddr(uint8_t addr) {
digitalWrite(AX0,bitRead(addr,0));
digitalWrite(AX1,bitRead(addr,1));
digitalWrite(AX2,bitRead(addr,2));
digitalWrite(AX3,bitRead(addr,3));
digitalWrite(AY0,bitRead(addr,4));
digitalWrite(AY1,bitRead(addr,5));
digitalWrite(AY2,bitRead(addr,6));
}
void SetKey(boolean data){
digitalWrite(CSMT, HIGH); //выбор чипа
digitalWrite(STBMT, HIGH); //строб on
digitalWrite(DATMT, data); //данные
digitalWrite(STBMT, LOW); //строб off
digitalWrite(CSMT, LOW);
}
void loop()
{
if( keyboard.available() ){
int c = keyboard.read(); //чтение кода
switch (c) {
case 0x7E: //если считался код 0x7E
digitalWrite(CSMT, HIGH); //выбор чипа
digitalWrite(RSTMT, HIGH);
digitalWrite(RSTMT, LOW); //сброс
digitalWrite(CSMT, LOW);
break;
case 0x07: //если считался F12
if (sw) {
qwerty = !qwerty; //меняем раскладку
sw = !sw; //ждем нажатия другой клавиши
}
break;
case 0xE0: //если считался префикс 0xE0
break;
case 0xF0: //если считался префикс 0xF0 (отпускание клавиши)
d = LOW;
break;
default:
if (qwerty) SetAddr(t_qwerty[c]);
else SetAddr(table[c]);
SetKey(d);
d = HIGH;
sw = true;
}
}
}
F12 - переключение раскладок JCUKEN-QWERTY
ScrollLock - перезагрузка контроллера (мой вариант при первом включении бывает что "залипает")
F11 - Стоп
WIN - Фикс
Alt - Алф
Не влезли клавиши - Ю, Сел.
Затруднился куда засунуть - ИЗ, ВЗ, СТРН.
Прошивка QWERTY хуже проработана - дублируются кнопки V H B
Для тех, кто собирается дорабатывать, сопоставление пинов разъему корвета:
1KD0 - X14
2KD0 - X15
1KD1 - X12
2KD1 - X13
1KD2 - X10
2KD2 - X11
1KD3 - X8
2KD3 - X9
1KD4 - X6
2KD4 - X7
1KD5 - X4
2KD5 - X5
1KD6 - X2
2KD6 - X3
1KD7 - X0
2KD7 - X1
KA0 - Y6
KA4 - Y7
KA1 - Y4
KA5 - Y5
KA2 - Y2
KA6 - Y3
KA3 - Y0
KA7 - Y1
В прошивке выше переопределены пины для простого обжима шлейфа к разъему корвета:
https://pic.maxiol.com/thumbs2/1624614748.1845264823.img2256j.jpg (https://pic.maxiol.com/?v=1624614748.1845264823.img2256j.jpg&dp=2)
Ниже исторический первый пост в теме.
Коллеги, привет!
Достался мне тут корпус в неплохом состоянии от Квант-8 и я собираюсь восстановить его начинку. Для этого почти все есть:
Плата от обычного корвета (только нужно либо перепаять выход FDD на стандартный ПКшный, либо сделать кабель)
Флопы
БП купил вот такой (https://ru.aliexpress.com/item/high-quality-Triple-Output-Switching-power-supply-60W-5V-12V-12V-5A-2-5A-0-5A/1711530628.html?spm=a2g0s.9042311.0.0.b6c033edy2zc 9M) - есть опасения правда, что 60W не хватит, но если что, закажу большей мощности
Перегородки собираюсь сделать из метала как в родном, или на 3Д принтере - еще не решил...
Самый большой затык пока что в клавиатуре, коих насколько я понял в природе еще меньше, чем этих самых квантов. Поэтому хочу начать делать контроллер PS/2. Так как собственного мозга пока не хватает, обращаюсь к коллективному разуму))
Первичный сбор информации говорит о следующем:
1. Клавиатура у корвета - обычная матрица замыкателей 8 бит адресов, 16 бит данных (2х8, мультиплексоры читают по очереди, в зависимости от А8)
2. Хочется использовать тот разъем, что на плате корвета, и не тянуть дополнительно А8 или еще что-то. Максимум питание, но контроллер можно запитать и отдельно. В кванте на сколько я понял так и реализовано - клавиатура подключена к стандартному разъему на плате корвета, где просто дополнительно выведено питание.
3. Шина данных перед мультиплексором подтянута на +5В, ША инверсирована (т.е. считывание идет по бегающему 0)
Перелопатил все подобные наработки в этой области для других ретро-ПК, пришел к следующим выводам:
1. За основу лучше всего брать наработки CARO для ориона или ямахи (http://caro.su/msx/kbd4msx/y_yis503.htm) (больше всего комментариев и логики в коде)
2. В качестве контроллера собираюсь использовать ATmega644 в DIP40 - и портов хватает (три полноценных порта - как раз 24 контакта для матрицы 8х16) и реализованы прерывания по изменению уровня на любом бите порта
Пока что не укладывается в голове:
1. Как лучше поступить: вставить в схему контроллера инверторы? или не утяжелять схему и писать прошивку с учетом инверсии? читал где-то на форумах, что есть риск положить +5 на землю программно...
2. Не нашел (или плохо искал) ничего подобного в других ПК - обычно ША больше 8 бит, а ШД - не более 8. Таким образом непонятно, как выстроить код, типа:
D0 EQU 000H
D1 EQU 001H
D2 EQU 002H
D3 EQU 003H
D4 EQU 004H
D5 EQU 005H
D6 EQU 006H
D7 EQU 007H <-- вот здесь математика оборвалась, младший байт закончился (((( а у нас еще 8 бит ШД есть...
;
A0 EQU 000H
A1 EQU 008H
A2 EQU 010H
A3 EQU 018H
A4 EQU 020H
A5 EQU 028H
A6 EQU 030H
A7 EQU 038H
;
Ctrl EQU 080H ; Ctrl Bit7=1
Shift EQU 040H ; Shift Bit6=1
AltTb EQU 0C0H ;
;
Kl_SL EQU A0+D0 ; Home
Kl_CTP EQU A0+D1 ; Insert
Kl_AP2 EQU A0+D2 ; ESCAPE
Kl_F1 EQU A0+D3
Kl_F2 EQU A0+D4 и т.д.
3. Видимо необходимо переписывать прошивку, чтобы в ответ на скан-код выдавался 16-битный ответ? и программно уже разбивать старший и младший байты по двум портам?
4. Правильно ли я понимаю, что таблица сопоставлений Скан-коды - ответы в ШД по прерываниям необходимо хранить в памяти AVR?
В общем жду пожеланий, предложений, комментариев...
А зачем столько ног? Бегло читал описание на Корвет (может не так читал и не то понял) выставляется 1 на ША клавиатуры и смотрятся 1 на ШД 8*2. Если подключать ps/2 клавиатуру то можно же просто использовать два порта ( не, можно и с одним извратится) считывать скан код сравнивать по таблице и давать 1 на нужную ногу. Не?
Serebriakov
21.06.2018, 00:36
Помнится FORTH32 уже делал подобный переходник на Atmega32-16 (http://zx-pk.ru/threads/23651/p=717098&viewfull=1#post717098), но ее скорости не хватало для нормальной обработки.
У Кванта клавиатура отличается от клавиатуры Корвета. Но если от Кванта берется только корпус, а плата родная Корветовская, то все ок.
Ну у кванта 4*8 матрица. Там проще, наверное :-)
Serebriakov
22.06.2018, 10:31
Написал FORTH32 на почту, вот ответ:
О, как давно это было-то...
Да, делал я подобный переходник. Но он был неполноценный. Дело во том, что скорости атмеги не хватало на то, чтобы проанализировать выставленную на сканирующий порт комбинацию, выбрать из памяти результат и выставить его в выходной порт. Пришлось подтормаживать процессор каждый раз, когда он обращается к порту клавиатуры, где-то на пару тактов. Тогда все работало, но возникали периодические странные глюки, даже не помню уже какие, но помню, что они меня малость достали.
С точки зрения конструкции все это означает, что переходник подключается не только к порту клавиатуры, но и к системному порту на материнской плате, причем сигнал RDY надо разорвать (удалить стоящую на этом порту перемычку). Это тоже совсем неэстетично. Ущербный получился переходник, хотя, как я понял, в соседних темах делали клаву для ZX без всяких извращений с подтормаживанием процессора. Как это делали я особо не разбирался, а потом в силу жизненных обстоятельств на год забросил корвет и все связанные с ним разработки. Теперь вот все собираюсь к этому вернуться, доделать наконец тот же extrom-адаптер, но без ESL, в одно рыло, заниматься этим как-то уже не так интересно.
Вообщем, исходник прошивки переходника я могу поискать в архиве, если интересно. И схему могу нарисовать.Но на нынешнем этапе появились недорогие ARM-контроллеры, те же stm32 например, их быстродействие в несколько раз выше атмеги, и они полностью 32-битные. По идее, такого контроллера должно за глаза хватить для обработки запросов к порту клавиатуры в реальном времени, без всяких тактов ожидания. Но лучше все же сделать разработку переходника на какой-нибдуь FPGA. Я вот подумываю об Altera Cyclone IV, их на алиэкспрессе как грязи и стоят не сильно дороже той же атмеги. Уж этого должно за глаза хватить - это же будет не программная, а аппаратная обработка, на основе встроенной в чип двухпортовой памяти.
Написал FORTH32 на почту, вот ответ:
По этому поводу - даже на СТМ32 полностью безвейтовый контроллер не сделать, уже проверено.
Если МК будет в бесконечном цикле ТОЛЬКО ждать опроса на шине, то самое оптимальное время реакции - около 400нс на частоте 168МГц. Это получено в результате тестов в реальном железе с реальным кодом (получение входной матрицы, формирование выходной матрицы). А нам же надо ещё и саму клавиатуру опрашивать ещё...
PS: У себя я уже 100% буду делать адаптер с FPGA - это самый оптимальный вариант. А FORTH32 по поводу FPGA можете написать, что не надо смотреть на циклоны - в данных случаях нужен чип, поддерживающий 5-и вольтовые сигналы. А это только MAX3000 и MAX7000. Первый можно настроить как OpenDrain с подтяжкой к +5, а вторые изначально 5-и вольтовые есть.
Если МК будет в бесконечном цикле ТОЛЬКО ждать опроса на шине, то самое оптимальное время реакции - около 400нс на частоте 168МГц.
А тут прерывания не получится использовать, чтобы не ждать в бесконечном цикле?
А тут прерывания не получится использовать, чтобы не ждать в бесконечном цикле?
Нет.
Замерял - получилось 375нс до начала обработчика прерывания. То есть получаем около 500нс с обработкой (или чуть больше, особо не проверял). Проверено на обработчике, который работает по битовой маске (при сканировании "бегающий ноль") - он занял около 250нс.
- - - Добавлено - - -
Так что если до 700нс оптимально - тогда да, можно и на СТМ32. И то, только на старших моделях, где тактовая выше 150МГц - приведённые тайминги проверялись на STM32F407VGT с частотой 168МГц.
Насколько я помню, MAX3000 - это максимум 256 макроячеек в самой старшей модели, а встроенного блока статической памяти вообще нет. Боюсь что не влезет - тут надо матрицу 8*16 в памяти держать, то есть 128 бит.
Я лично собрался делаль на циклоне 4. Проблема 5V в принципе обходится. Выходы адреса, идущие на клавиатуру - это ЛН2 с открытым коллектором, их можно подключать напрямую, включив в чипе внутреннюю подтяжку. Входы данных подтянуты к 5V внешним набором резисторов, который можно просто убрать с платы. Ну и, для гарантии, поключить к каждому выходу 3.3v стабилитрон на землю. Хотя это и не обязательно.
Зато в самом убогом циклоне4 (EP4CE6) имеется 6000 макроячеек и 128кбит статической памяти. Хвтати за глаза на все, в том числе и таблицу перекодировки клавиш. Преимуцество такого решения - подключаться надо только к порту клавиатуры. В системную шину, в том числе и CSKB, лезть не надо.
А так я несколько лет назад и правда сделал переходник на PS/2, если кому интересно, могу исходник выложить сюда. Но он требует подключения в разрыв сигнала RDY и тормозит процессор на каждом опросе клавиатуры.
Насколько я помню, MAX3000 - это максимум 256 макроячеек в самой старшей модели, а встроенного блока статической памяти вообще нет. Боюсь что не влезет - тут надо матрицу 8*16 в памяти держать, то есть 128 бит.
Я лично собрался делаль на циклоне 4. Проблема 5V в принципе обходится. Выходы адреса, идущие на клавиатуру - это ЛН2 с открытым коллектором, их можно подключать напрямую, включив в чипе внутреннюю подтяжку. Входы данных подтянуты к 5V внешним набором резисторов, который можно просто убрать с платы. Ну и, для гарантии, поключить к каждому выходу 3.3v стабилитрон на землю. Хотя это и не обязательно.
Зато в самом убогом циклоне4 (EP4CE6) имеется 6000 макроячеек и 128кбит статической памяти. Хвтати за глаза на все, в том числе и таблицу перекодировки клавиш. Преимуцество такого решения - подключаться надо только к порту клавиатуры. В системную шину, в том числе и CSKB, лезть не надо.
А так я несколько лет назад и правда сделал переходник на PS/2, если кому интересно, могу исходник выложить сюда. Но он требует подключения в разрыв сигнала RDY и тормозит процессор на каждом опросе клавиатуры.
На всю матрицу хватит "за глаза". У меня в 128 ячеек уместилась матрица, и ещё пара портов. Плюс это всё общается с СТМкой :)
Матрица у нас в виде 16 байт, то есть получаем 144 ячейки на хранение состояния. Это если реализовывать "в лоб".
- - - Добавлено - - -
По поводу циклона - тут будут траблы с питанием (там всё достаточно сложно может быть в некоторых случаях), да ещё и с онфигПЗУ надо быть в курсе многих дел :)
Плюс это всё общается с СТМкой
Так ты хочешь делать комбинированную схему, stm32+max3000, то есть использовать CPLD просто в качестве эмулятора двухпортовой памяти? Ну тогда конечно...
Но так неинтересно. Я хочу в FPGA запихать все - и матрицу, и PS/2 контроллер, и таблицу перекодировки кнопок. А на это 256 ячеек явно маловато.
На алиэкспрессе продаются недорогие готовые платки с EP4CE6, на которых уже есть и клок, и питание разведено, и конфиг-ром имеется. По сути, к ней ничего и не надо больше. Я вот на такой и буду делать.
andreil, а какое должно быть время отклика? Я давным-давно делал на дубовом LPC1769 (120 MHz) эмулятор картриджа для Вектрекса (проц 6809 на 1.5 МГц). Там конечно все тормозное, но более-менее одного порядка величины. Вот мой код рабства шины:
https://github.com/svofski/cartuchnik/blob/master/firmware/src/vectrex.S
К сожалению я ничего не замерял, оно просто работало, я даже в ОЗУ его не засовывал. Так что не могу привести никаких цифр. Но вдруг хоть чем-то пригодится. Все-таки питать стм32 сильно проще, чем Циклон. Еще и загрузчик.
Так ты хочешь делать комбинированную схему, stm32+max3000, то есть использовать CPLD просто в качестве эмулятора двухпортовой памяти? Ну тогда конечно...
Но так неинтересно. Я хочу в FPGA запихать все - и матрицу, и PS/2 контроллер, и таблицу перекодировки кнопок. А на это 256 ячеек явно маловато.
На алиэкспрессе продаются недорогие готовые платки с EP4CE6, на которых уже есть и клок, и питание разведено, и конфиг-ром имеется. По сути, к ней ничего и не надо больше. Я вот на такой и буду делать.
Ну, почти. Кроме буфера для клавиатуры CPLD в моей железке выполняет ещё преобразования векторов прерывания и полный арбитраж шины для прерываний, обрабатываемых мультикартой.
- - - Добавлено - - -
andreil, а какое должно быть время отклика? Я давным-давно делал на дубовом LPC1769 (120 MHz) эмулятор картриджа для Вектрекса (проц 6809 на 1.5 МГц). Там конечно все тормозное, но более-менее одного порядка величины. Вот мой код рабства шины:
https://github.com/svofski/cartuchnik/blob/master/firmware/src/vectrex.S
К сожалению я ничего не замерял, оно просто работало, я даже в ОЗУ его не засовывал. Так что не могу привести никаких цифр. Но вдруг хоть чем-то пригодится. Все-таки питать стм32 сильно проще, чем Циклон. Еще и загрузчик.
По времени отклика не скажу, но для ВМ80 обращение к портам занимает 3 цикла (если без ожидания).
По таймингам для 6809 вижу, что это занимает 695-330нс ("Usable Access Tirne"). Если это оно, тогда без CPLD никак...
А по поводу картриджа - там же не за 1 цикл было дело, как понимаю. А если растянуто на пару-тройку циклов (запись частей адреса и только потом чтение), то вполне можно успеть заранее подготовить данные.
То есть - если чтение клавиатуры выполняется одной командой (как в ZX'е), тогда только CPLD (в случае без введения ожиданий и прочего).
Вот я освежаю память. После E в течение 100нс захватывается адрес. После этого 440нс то самое Usable access time, после которого данные на шине должны быть валидными. Сколько-то они там держатся, пока не уйдет E, после чего шина данных обратно тристейтится. Я не знаю, что значит "растянуто на пару-тройку циклов", это и есть весь цикл. Вот эти временные диаграммы (http://www.commodore.ca/manuals/funet/cbm/documents/chipdata/6809/6809-03.gif) от процессора они как есть, в Вектрексе никаких премудростей нет, он прямо вот так кишками наружу всей шиной торчит. И это работает на Cortex-M3 120MHz из флеша. Это другой производитель, другой флеш контроллер, все вообще другое, но все же это сопоставимые устройства. stm32f4xx точно его за пояс заткнет.
У 8080 адрес устройства выставлен к negedge фазы 2 t1, а данные должны стабилизироваться на конец ф1 t3? Если так, то имеется больше одного такта (>400нс) на то, чтобы выставить данные. Тесно, но все укладывается вроде, особенно на 168 МГц.
Не пытаюсь никого переубедить, мил Циклон так и ладно. Просто заметил расхождение со своими ожиданиями и опытом.
У Кванта клавиатура отличается от клавиатуры Корвета.
Там такой же замыкатель, только больше кнопок. Плата кванта ничем не отличается от корвета, ПЗУ в них только другим прошиты, в т.ч. наверняка БИОС учитывает расширение клавиатуры.
Но он требует подключения в разрыв сигнала RDY и тормозит процессор на каждом опросе клавиатуры
Хотелось бы конечно сделать контроллер без вмешательства в схему платы, и без торможения проца. В т.ч. и без убирания инверсии ШД (выпаивания резисторов)
Очень рад, что тема наконец ожила))
- - - Добавлено - - -
forth32, можете опубликовать схему и прошивку?
По просьбам трудящихся выкладываю исходник и схему своего варианта PS2-контроллера. Вариант, конечно, не самый оптимальный, поскольку с этим контроллером наблюдались глюки. Во-первых, он изредка намертво подвешивает корвет, и вывести его из этого состояния можно только сигналом RESET или программным сбросом контроллера (я вывел его на кнопку Print Screen). Во-вторых, контроллер категорически откразывается работать с некоторыми биосами микродоса, при том что со всеми биосами CP/M он работает отлично. В чем причина, я в свое время так и не разобрался. Теперь же я решил сделать этот контроллер на FPGA вместо МК, поэтому возвращаться к отладке данной разработки не вижу смысла.
SaintTurnip
28.06.2018, 16:53
А концептуально так нельзя?
- к порту корвета подключен SRAM, в котором хранится состояние матрицы
- контроллер пишет в SRAM, когда позволяет CSKB
А концептуально так нельзя?
- к порту корвета подключен SRAM, в котором хранится состояние матрицы
- контроллер пишет в SRAM, когда позволяет CSKB
А чем это принципиально отличается от варианта с FPGA? Мало того, что схема получается сложнее - микроконтроллер, SRAM, адресный мультиплексор, еще кое-какая мелкая логика, вместо одного корпуса FPGA и восьминогого конфигрома. Но еще и сигнал CSKB от корвета приходит асинхронно по отношению к контроллеру, и что делать, если сигнал CSKB вдруг пришел, а контроллер как раз занят записью байта в SRAM?
В FPGA можно организовать полноценную двухпортовую SRAM, при этом операции выборки байта корветом и записи байта контроллером происходят абсолютно независимо друг от друга. Для того их и придумали, эти самые FPGA, чтобы не городить огород из логической рассыпухи. Лично я считаю, что это - наиболее оптимальный способ сделать полноценный адаптер PS/2.
Вот восстановлю свой корвет и займусь...
SaintTurnip
29.06.2018, 10:05
Даже не пытался критиковать FPGA.
- - - Добавлено - - -
CSKB может отрубать МК от SRAM - чего мультиплексору тухнуть.
(здесь был непродуманный псевдокод)
В SRAM в любом случае писать не все 256 адресов клавиатуры, а diff к последнему записанному состоянию.
Ну один, ну может два байта. Чего там успевать-то.
Плюсы МК - можно USB клаву подцепить, и все равно будет довольно дешево (ну, без учета сложности PCB)
- - - Добавлено - - -
forth32, есть корвет 8010 скучающий. Ты же из Питера?
CSKB может отрубать МК от SRAM - чего мультиплексору тухнуть.
Дело в том, что адрес КА0-КА7 поступает из корвета ВСЕГДА, а не по спаду CSKB. Этот сигнал неотключаемый, это просто инверсия младших адресных линий процессора. Таким образом, на время взаимодействия МК с контроллером нужно отключить эти сигналы от адресного входа SRAM и вместо них подключить порт контроллера, а по окончании записи данных вернуть все обратно. Отсюда и мультиплексор.
В SRAM в любом случае писать не все 256 адресов клавиатуры, а diff к последнему записанному состоянию.
Ну один, ну может два байта. Чего там успевать-то.
Боюсь, что ты тут тоже не прав. Попробую пояснить свою мысль.
Клавиатура - это, по сути, битовая матрица 8*16, то есть всего 128 бит. При этом, в случае нажатия нескольких кнопок на одной адресной горизонтали, например ctrl+shift - оба на КА7, выходной ноль появляется одновременно на нескольких выходах данных, в данном случае на 1KD5 и 1KD7 (разумеется, в момент сканирования линии КА7).
А вот SRAM - это совсем другое дело. Это, конечно, тоже матрица битовых ячеек памяти, но вот между горизонталями матрицы и адресными входами стоит дешифратор. Таким образом, 8 адресным входам соответствует 256 горизонталей матрицы. В этой ситуации при нажатии кнопки, например, CTRL, придется понять бит D5 во всех ячейках SRAM, у которых адрес A7=0 (сканирование клавиатуры идет нулями). А при отпускании кнопки - все эти биты опустить обратно. А это - 128 операций записи. Кроме того, всякие комбинации типа ctrl+shift юзер нажимает и отпускает обычно практически одновременно, поэтому получаем еще 128 операций. Итого 256. Согласись, что это уже весьма прилично по времени получается. За это время драйвер клавиатуры корвета полезет опрашивать клавиатуру, а SRAM занята текущей операцией записи слова из контроллера. Ведь, как я и говорил ранее, корвет и контроллер работают совершенно асинхронно. И что в этой ситуации делать? Прерывать запись нельзя, раз она уже начата, а драйвер клавиатуры ждать не будет. Он просто прочитает то, что сейчас выставлено на шине данных SRAM, а там выставлен текущий записываемый байт. Результат непредсказуем.
Конечно, на первый взгляд можно было бы прописывать не все 128 слов с А7=0, а только одно слово, с адресом 01111111. Поскольку драйвер клавиатуры, по идее, должен опрашивать адресные линии по одной. На практике оказалось, что есть программы, которые проверяют факт наличия нажатой кнопки, выставив адрес 00000000. То есть за одну операцию ввода можно узнать, нажата ли хотя бы одна кнопка на всей клавиатуре. Так, например, сделано в биосах некоторых версий микродоса. Не удивлюсь, если найдутся программы, особенно игрушки, опрашивающие клавиатуру произвольными сочетаниями адресных линий. Поэтому, я считаю, что матрицу клавиатуры надо реализовать полноценно. Но даже если этого не делать, то асинхронность опероса клавиатуры и записи данных обязательно рано или поздно приведут к конфликту.
Плюсы МК - можно USB клаву подцепить, и все равно будет довольно дешево (ну, без учета сложности PCB)
usb-клаву можно и к fpga зацепить - этих usb ip-core уже довольно много существует. А насчет цены - ну, наверное, подешевле будет. Правда, 16-битную SRAM в не-BGA корпусе еще найти надо, и она тоже денег будет стоить. Хотя, наверное, и подешевле FPGA. Но экономия будет рублей 500 максимум.
forth32, есть корвет 8010 скучающий. Ты же из Питера?
Да, я из питера. Если есть лишний корвет - пошли в личку договариваться, мне полноценный корвет не помешал бы.
SaintTurnip
30.06.2018, 18:00
На практике оказалось, что есть программы, которые проверяют факт наличия нажатой кнопки, выставив адрес 00000000. То есть за одну операцию ввода можно узнать, нажата ли хотя бы одна кнопка на всей клавиатуре
Спасибо за объяснение. Способ опроса всей клавиатуры и правда удобный.
Его можно поддержать, записывая в нужный адрес OR от состояния всех рядов. Комбинаций адресов не так много.
А как тебе такой вариант?
Выбросить:
* CSKB
* SRAM
* мультиплексор
Добавить:
* восемь декодеров i2c по 16 бит с защелками, типа PCF8575
* восемь буферов по 16 бит для адресного селектора
* шестнадцать OR на 8 входов
Корвет даже не отличит от настоящей клавиатуры. И в атмеге свободные пины останутся.
А что плата большая, так ведь и Корвет не маленький! :)
- - - Добавлено - - -
FPGA на системном разъеме может не только клавиатуру изображать.
Плисину пожирнее + SD + ОЗУ:
- Extender
- Виртуальный дисковод для 8010
- Расширение памяти до четырех страниц
- Мышь
- Джойстики
- Локалка
Только подумать как грамотно затенить реальные устройства. Может выпаять вообще.
Добавить:
* восемь декодеров i2c по 16 бит с защелками, типа PCF8575
* восемь буферов по 16 бит для адресного селектора
* шестнадцать OR на 8 входов
Корвет даже не отличит от настоящей клавиатуры. И в атмеге свободные пины останутся.
Ну вот нечто подобное я и предполагал сделать. Только мне лень разводить и травить плату, идти в магазин за микросхемами, паять всю эту пачку... Проще описать всю эту схему на верилоге и получить тот же самый результат. Ну нечто вроде такого:
module kb(
input [7:0]adr,
input reset,
input ps2data,
input ps2clock,
output [15:0]outdata
);
reg[15:0] data0;
reg[15:0] data1;
reg[15:0] data2;
reg[15:0] data3;
reg[15:0] data4;
reg[15:0] data5;
reg[15:0] data6;
reg[15:0] data7;
assign outdata=
(data0 & ~{2{adr}}) |
(data1 & ~{2{adr}}) |
(data2 & ~{2{adr}}) |
(data3 & ~{2{adr}}) |
(data4 & ~{2{adr}}) |
(data5 & ~{2{adr}}) |
(data6 & ~{2{adr}}) |
(data7 & ~{2{adr}});
Как и в твоем случае, строб по CSKB здесь не нужен, поскольку логика полностью асинхронная. К этому еще нужно добавить схему сброса регистров в 0 по ресету, ну и логику опероса клавиатуры. Ее можно или описать на том же верилоге, или, что лучше, синтезировать какое-нибудь процессорное ядро, например NIOS2 или хотя бы тот же AVR, и сделать программную обработку.
FPGA на системном разъеме может не только клавиатуру изображать.
Ну, я-то собираюсь его к разъему клавиатуры цеплять. Системный разъем - это отдельный разговор.
- Extender
- Виртуальный дисковод для 8010
- Расширение памяти до четырех страниц
- Мышь
- Джойстики
- Локалка
Я думаю, это уже слишком. Тогда уж можно просто весь корвет запихать в FPGA и вообще отказаться от этой громоздкой платы. Тут, кстати, кто-то уже пытался это сделать, но так и не допилил вроде бы до рабочего состояния.
Из вышеперечисленного я реализовывал только виртуальный дисковод, подключаемый к боковому разъему (проект EXTROM, где-то в этом разделе есть). Но там обошлись без FPGA, все сделано на любимой в народе атмеге.
SaintTurnip
01.07.2018, 11:51
Я думаю, это уже слишком
Учитывая, что локомотив тут ты, что сделаешь, тому и рады :)
Тогда уж можно просто весь корвет запихать в FPGA и вообще отказаться от этой громоздкой платы. Тут, кстати, кто-то уже пытался это сделать, но так и не допилил вроде бы до рабочего состояния.
Форумчанин ILoveSpeccy (http://zx-pk.ru/members/2665-ilovespeccy.html) довел до состояния беты и забросил. Жаль только исходники не опубликовал.
- - - Добавлено - - -
Ну, я-то собираюсь его к разъему клавиатуры цеплять. Системный разъем - это отдельный разговор.
С ним какие-то сложности? Это на него выведены все ноги процессора?
Собрал прототип "безвейтового" контроллера PS/2 клавиатуры для Корвета.
https://youtu.be/Qk7wn_3nMKQ
Идеей данной железки любезно поделился со мной andykarpov, за что ему огромное спасибо.
Вопрос в том, нужна ли кому-то данная железка? Стоит ли заказать для нее производство печаток?
И если ответы на эти вопросы будут положительными, то как народ видит раскладки клавиатуры?
ILoveSpeccy
09.08.2019, 21:00
Форумчанин ILoveSpeccy (http://zx-pk.ru/members/2665-ilovespeccy.html) довел до состояния беты и забросил. Жаль только исходники не опубликовал.
Исходники всегда лежали тут, не жалко.
https://github.com/ILoveSpeccy/Aeon-Lite/tree/master/cores/korvet
Буду только рад если кто до ума доведёт.
70184
Вот схема и скетч для безвейтового контроллера клавиатуры. "Красивую" раскладку с полным соответствием русских букв и символов пока не делал, т.к. еще слишком мало вообще работал с Корветом и не решил, как удобнее.
Скетч прост, как мычание. Массив задает соответствие между нажатой клавишей и замкнутыми контактами на матрице. Можно легко допилить переключение раскладок и добавить сколько угодно подобных массивов. Так же этот адаптер можно приспособить к практически любой матричной клавиатуре, не обязательно именно к Корвету. Вместо Атмеги 8 можно использовать, например, плату ардуино нано и т.п. Можно и без кварца обойтись, только сконфигурировать работу Атмеги от встроенного генератора. Выводы контроллера, предназначенные для SPI, UART и кварца не задействованы в скетче специально для универсальности.
70183
Вот еще даташит (https://www.futurlec.com/Datasheet/Zarlink/MT8816AE.pdf) на MT8816. Только имейте в виду, что нумерация выводов по крайней мере для DIP корпуса там дана ошибочная. В моей схеме - правильная.
Вот еще даташит (https://www.futurlec.com/Datasheet/Zarlink/MT8816AE.pdf) на MT8816. Только имейте в виду, что нумерация выводов по крайней мере для DIP корпуса там дана ошибочная. В моей схеме - правильная.А где там ошибка? Ткни носом.
Можно использовать также микросхему CD22M3494
https://www.renesas.com/ja-jp/www/doc/datasheet/cd22m3494.pdf
OrionExt
02.10.2019, 20:55
MT8816? есть вопросы?
caro, там Х выходы некоторые перепутаны. Сейчас найду картинку, сфоткаю и скину.
OrionExt
02.10.2019, 21:03
.
caro,
pin8 x6=x8
pin9 x7=x9
pin10 x8=x10
pin11 x9=x11
pin12 x10=x12
pin13 x11=x13
pin27 x12=x6
pin26 x13=x7
Массив задает соответствие между нажатой клавишей и замкнутыми контактами на матрице.
собрал контроллер, хочу улучшить раскладку, можешь поделиться принципами формирования массива? Не очень хочется в реверсинженеринг глубоко заныривать))))
Выглядит примерно вот так:
https://pic.maxiol.com/thumbs2/1624370262.1845264823.img2241.jpg (https://pic.maxiol.com/?v=1624370262.1845264823.img2241.jpg&dp=2)
Ну и конечно пины переопределить бы в прошивке, чтобы такую лапшу на шлейфе не разводить....
surinm, ответ здесь (https://zx-pk.ru/threads/33211-universalnyj-kontroller-ps-2-klaviatury-dlya-kompyuterov-s-matrichnymi-klaviaturami.html?p=1121285&viewfull=1#post1121285).
Обновил первый пост, добавил туда прошивку и все ссылки, необходимые для заказа или изготовления контроллера.
surinm, а переключение qwerty/йцукен уже реализовали?
surinm, а переключение qwerty/йцукен уже реализовали?
Это ж надо еще одну матрицу сформировать и например по NumLock переключать... сделаю попозже.... В моей прошивке задействован alf и Фикс, так что все работает на корвете штатно))) можно и на русском и на английском чепятать))
Это ж надо еще одну матрицу сформировать и например по NumLock переключать
Все верно, к меня пока руки не дошли.
Что-то в этом роде, сделал по F12, но почему-то переключается через раз. Если нажимать клавиши вместе с F12, то точно будет в другой раскладке... где-то я туплю...
#include <PS2KeyRaw.h>
#define AX0 4
#define AX1 5
#define AX2 6
#define AX3 7
#define AY0 8
#define AY1 9
#define AY2 10
#define RSTMT 14
#define CSMT 15
#define DATMT 16
#define STBMT 17
#define DATAPIN 2
#define IRQPIN 3
volatile boolean d = HIGH;
uint8_t table[128] = {127,127,127,39, 43, 47, 45, 127,127,127,
127,127,41, 50,88,127,127,28,30,127,
20,74, 124, 127,127,127,44, 12, 98, 104,
122, 18,127,40, 2, 32, 36, 118, 120, 127,
127,48,68, 108, 100, 72, 116, 127,127,38,
76, 42, 46, 66, 114, 127,127,127,14, 64,
96, 112, 94, 127,127,106,70, 8, 4, 126,
92, 127,127,86, 80 ,102, 34,10, 84,127,
127,127,6,127,78, 90, 127,127,127,16,
62, 0, 127,82,127,127,127,127,127,127,
127,127,52,127,127,109, 127,103, 97, 127,
127,127,111, 70, 107, 101, 99, 79, 24,127,
58,127,105, 127, 127,77, 127,127};
uint8_t t_qwerty[128] = {
127,127,127,44, 42, 40, 41, 127,127,127,
127,127,43, 102,54,127,127,127,112,127,
117,33, 65, 127,127,127,50, 35, 1, 39,
66, 127,127,3, 48, 4, 5, 68, 67, 127,
127,103,38, 6, 36, 34, 69, 127,127,22,
2, 16, 7, 49, 70, 127,127,127,21, 18,
37, 71, 80, 127,127,84,19, 17, 23, 64,
81, 127,127,86, 87 ,20, 83,32, 55,127,
127,127,82,127,51, 127, 127,127,127,119,
96, 53, 127,52,127,127,127,127,127,127,
127,127,101,127,127,9, 127,12, 15, 127,
127,127,8, 22, 10, 13, 14, 24, 115,127,
127,127,11, 85,127,25, 127,127};
boolean qwerty = false;
PS2KeyRaw keyboard;
void setup() {
//Инициализация портов
pinMode(19, OUTPUT);
pinMode(AX0, OUTPUT); //AX0
pinMode(AX1, OUTPUT); //AX1
pinMode(AX2, OUTPUT); //AX2
pinMode(AX3, OUTPUT); //AX3
pinMode(AY0, OUTPUT); //AY0
pinMode(AY1, OUTPUT); //AY1
pinMode(AY2, OUTPUT); //AY2
pinMode(RSTMT, OUTPUT); //RES
pinMode(CSMT, OUTPUT); //CS
pinMode(DATMT, OUTPUT); //DAT
pinMode(STBMT, OUTPUT); //STB
//Инициализация клавиатуры
keyboard.begin( DATAPIN, IRQPIN );
//Инициализация MT8816
SetAddr(0);
digitalWrite(RSTMT, LOW);
digitalWrite(CSMT, LOW);
digitalWrite(DATMT, LOW);
digitalWrite(STBMT, LOW); //инициализация
digitalWrite(CSMT, HIGH); //выбор чипа
digitalWrite(RSTMT, HIGH);
digitalWrite(RSTMT, LOW); //сброс
digitalWrite(CSMT, LOW);
}
void SetAddr(uint8_t addr) {
digitalWrite(AX0,bitRead(addr,0));
digitalWrite(AX1,bitRead(addr,1));
digitalWrite(AX2,bitRead(addr,2));
digitalWrite(AX3,bitRead(addr,3));
digitalWrite(AY0,bitRead(addr,4));
digitalWrite(AY1,bitRead(addr,5));
digitalWrite(AY2,bitRead(addr,6));
}
void SetKey(boolean data){
digitalWrite(CSMT, HIGH); //выбор чипа
digitalWrite(STBMT, HIGH); //строб on
digitalWrite(DATMT, data); //данные
digitalWrite(STBMT, LOW); //строб off
digitalWrite(CSMT, LOW);
}
void loop()
{
if( keyboard.available() ){
int c = keyboard.read(); //чтение кода
switch (c) {
case 0x7E: //если считался код 0x7E
digitalWrite(CSMT, HIGH); //выбор чипа
digitalWrite(RSTMT, HIGH);
digitalWrite(RSTMT, LOW); //сброс
digitalWrite(CSMT, LOW);
break;
case 0x07:
qwerty = !qwerty;
case 0xE0: //если считался префикс 0xE0
break;
case 0xF0: //если считался префикс 0xF0 (отпускание клавиши)
d = LOW;
break;
default:
if (qwerty) SetAddr(t_qwerty[c]);
else SetAddr(table[c]);
SetKey(d);
d = HIGH;
}
}
}
surinm, попробуйте сделать qwerty volatile.
surinm, попробуйте сделать qwerty volatile.
добавил, но думаю это не из-за этой директивы. Думаю, что это было из-за множественных нажатий в мозгу контроллера. Добавил переменную, которая переключает только один раз, дальше ждет нажатия другой клавиши, после этого заработало как надо. Финальную прошивку с переключением раскладок выложил в первом посте, также расширил комментарии к прошивке.
- - - Добавлено - - -
caro, там Х выходы некоторые перепутаны. Сейчас найду картинку, сфоткаю и скину.
Там в даташите дальше в таблице установки состояний тоже косячек, выводы тоже перепутаны.
https://pic.maxiol.com/thumbs2/1624774004.1845264823.20210627090423.png (https://pic.maxiol.com/?v=1624774004.1845264823.20210627090423.png&dp=2)
surinm, для отладки удобно использовать последовательный порт. Но тогда желательно кварц запаять.
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot