Соберу здесь всю выжимку по данному девайсу.
Огромная благодарность Xrust за разработку контроллера.
Схема, герберы и прочая информация по универсальному контроллеру - здесь.
Купить платы или готовые устройства можно здесь.
По-умолчанию матрица для прошивки аутентичной клавиатуры (ЙЦУКЕН-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
[свернуть]
В прошивке выше переопределены пины для простого обжима шлейфа к разъему корвета:
Ниже исторический первый пост в теме.
Коллеги, привет!
Достался мне тут корпус в неплохом состоянии от Квант-8 и я собираюсь восстановить его начинку. Для этого почти все есть:
Плата от обычного корвета (только нужно либо перепаять выход FDD на стандартный ПКшный, либо сделать кабель)
Флопы
БП купил вот такой - есть опасения правда, что 60W не хватит, но если что, закажу большей мощности
Перегородки собираюсь сделать из метала как в родном, или на 3Д принтере - еще не решил...
Самый большой затык пока что в клавиатуре, коих насколько я понял в природе еще меньше, чем этих самых квантов. Поэтому хочу начать делать контроллер PS/2. Так как собственного мозга пока не хватает, обращаюсь к коллективному разуму))
Первичный сбор информации говорит о следующем:
1. Клавиатура у корвета - обычная матрица замыкателей 8 бит адресов, 16 бит данных (2х8, мультиплексоры читают по очереди, в зависимости от А8)
2. Хочется использовать тот разъем, что на плате корвета, и не тянуть дополнительно А8 или еще что-то. Максимум питание, но контроллер можно запитать и отдельно. В кванте на сколько я понял так и реализовано - клавиатура подключена к стандартному разъему на плате корвета, где просто дополнительно выведено питание.
3. Шина данных перед мультиплексором подтянута на +5В, ША инверсирована (т.е. считывание идет по бегающему 0)
Перелопатил все подобные наработки в этой области для других ретро-ПК, пришел к следующим выводам:
1. За основу лучше всего брать наработки CARO для ориона или ямахи (больше всего комментариев и логики в коде)
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?
В общем жду пожеланий, предложений, комментариев...