Да, я искал форумы Arduino.cc и здесь. Да, я нашел статьи, касающиеся библиотеки ps2dev. Да, я прочитал (хорошо, некоторые я просмотрел) статью об интерфейсе PS / 2 на этом сайте . Да, у меня это работает, вроде. Мне нужны идеи, чтобы сделать прыжок на полную мощность. :)
Нет, я не могу просто эмулировать USB HID Keyboard и оставить все как есть - это должна быть эмуляция PS / 2 Keyboard. Да, я посылаю правильные сигналы «сделай и сломай» - он даже обрабатывает очень сложные комбинации клавиш. На данный момент у меня есть код, написанный для моего Arduino, как указано ниже (технически это Freeduino 1.22), и я отправлял нажатия клавиш через терминал Serial Monitor или PuTTY, а также с помощью удобной оболочки / драйвера Python, которая отправляет фактические Информация о скан-коде PS / 2 - и вообще делает мою жизнь намного проще - также снимает часть нагрузки с Arduino.
Прямо сейчас у меня на Arduino работает эскиз, который имитирует клавиатуру PS / 2. Естественно, я должен загрузить свою «целевую» машину (машину, в которую входит PS / 2 Plug), и я вижу, что происходит «рукопожатие». Загрузитесь в WinDoze, откройте блокнот и нажмите на клавишу (успешно), используя мой «драйвер» Python. (Драйвер просто размещается на терминале Serial Monitor / PuTTY и читает / записывает в последовательный порт, используя модуль под названием PySerial.) Все это делается на материнской плате AMD in ASUS «target».
Теперь цель состоит в том, чтобы заставить его работать на моей «мишени» на материнской плате Intel, я подключаю его, загружаюсь и не играю в кости. Итак, я немного изменил эскиз, чтобы попытаться понять, что на самом деле происходит с моим маленьким другом Арди. Версия после модов отображается ниже. Насколько я понимаю (код был «заимствован» из другого поста на форуме Arduino.cc, здесь ) Он попытается установить соединение с «целью» через PS / 2 в первую очередь, мигая встроенным светодиодом в течение 0,5 секунды до тех пор, пока соединение установлено. Цель Intel не проходит через 5 секунд мигания, и последовательное соединение никогда не устанавливается с «хостом».
У меня такой вопрос: есть ли существенное различие в том, как клавиатуры ps / 2 устанавливают связь с целевым компьютером? Это действительно разница в дизайне, или я должен искать что-то более основное, что проблема здесь? Я слышал кое-что о необходимости подтягивающих резисторов на входах данных / тактовых импульсов, но это должно быть обработано в коде, особенно потому, что он РАБОТАЕТ на другой цели, но не на той, с которой мне нужно работать.
Есть идеи? Я бы хотел, чтобы это работало КАК МОЖНО СКОРЕЕ - я буду продолжать делать отладку, любые указания или предложения будут с благодарностью. Всем им будет уделено полное внимание, потому что мне нужно по-новому взглянуть на эту проблему. Возможно, нужна лучшая реализация в библиотеке ps2dev?
#include "ps2dev.h" // to emulate a PS/2 device
// Orange = 2
// Blue = 3
// Red = 5V (3 in)
// Black = GND (4 in)
// EXT Power, USB for COM only
PS2dev keyboard(3,2); // PS2dev object (2:data, 3:clock)
int enabled = 0; // pseudo variable for state of "keyboard"
boolean serialConnected = false;
int incomingByte = 0;
void ack() {
//acknowledge commands
while(keyboard.write(0xFA));
}
int kbdCmd(int command) {
unsigned char val;
switch (command) {
case 0xFF: //reset
ack();
//the while loop lets us wait for the host to be ready
while(keyboard.write(0xAA)!=0);
break;
case 0xFE: //resend
ack();
break;
case 0xF6: //set defaults
//enter stream mode
ack();
break;
case 0xF5: //disable data reporting
//FM
enabled = 0;
ack();
break;
case 0xF4: //enable data reporting
//FM
enabled = 1;
ack();
break;
case 0xF3: //set typematic rate
ack();
keyboard.read(&val); //do nothing with the rate
ack();
break;
case 0xF2: //get device id
ack();
keyboard.write(0xAB);
keyboard.write(0x83);
break;
case 0xF0: //set scan code set
ack();
keyboard.read(&val); //do nothing with the rate
ack();
break;
case 0xEE: //echo
//ack();
keyboard.write(0xEE);
break;
case 0xED: //set/reset LEDs
ack();
keyboard.read(&val); //do nothing with the rate
ack();
break;
}
}
void connectHost() {
while (Serial.available() <= 0) {
Serial.print('A'); // send a capital A
delay(300);
}
}
void setup() {
pinMode(13, OUTPUT);
//establish serial connection with host
Serial.begin(9600);
// establish ps/2 connection with target
while(keyboard.write(0xAA)!=0){
digitalWrite(13, HIGH);
delay(500);
digitalWrite(13, LOW);
delay(500);
}
delay(100);
connectHost();
Serial.println("\nSerial Host Connected");
Serial.flush();
}
void loop() {
unsigned char c;
if( (digitalRead(3)==LOW) || (digitalRead(2) == LOW)) {
if(digitalRead(3)==LOW){
Serial.println("pin 3 is LOW");
} else {
Serial.println("pin 2 is LOW");
}
while(keyboard.read(&c));
kbdCmd(c);
Serial.print("Target: 0x");
Serial.println(c, HEX);
}
else {//if host device wants to send a command:
//echo ASCII code from terminal and write to ps/2
if(Serial.available() > 0) {
incomingByte = Serial.read();
keyboard.write(incomingByte);
Serial.print("Host: 0x");
Serial.print(incomingByte, HEX);
Serial.print(" ");
Serial.print(incomingByte);
Serial.print(" ");
Serial.println(incomingByte, BIN);
}
}
}
Ответы:
Как я понимаю, вы подключаете свой Arduino к двум разным целевым машинам, и на одной он работает, а на другой - нет.
Таким образом, кажется, есть разница между требованиями инициализации двух машин. На этой странице в самом низу есть список возможных последовательностей инициализации. Начните со сравнения вашей инициализации с этой.
Это будет намного проще, если использовать логический анализатор. Я использую Intronix Logicport , но есть и более дешевые, и лучшие, хотя и не в одно и то же время.
Подключиться к шине с открытым коллектором немного громоздко, потому что вы не видите, какое устройство говорит. Тем не менее, если вы положили в резисторе в конце , где подтяжка не , вы можете сказать , по уровню напряжения , которое устройство держит вниз автобус. Каждая шина с открытым коллектором (например, PS / 2) нуждается в подтягивающих резисторах, обычно они встроены в ПК. Вы можете легко увидеть различные уровни напряжения на DSO. Только с LA вы должны записывать дважды с разными пороговыми напряжениями.
источник
Учитывая, что ваш проект работает с одной материнской платой, а не с другой, у вас, кажется, есть классический случай «частичного соответствия спецификациям» - в вашем проекте, и, возможно, даже на одной из материнских плат. Но большинство клавиатур будет работать с любой материнской платой, поэтому надежная реализация должна быть переносимой. Проблема в том, что вам придется выяснить, почему у вас нет.
Вы можете сделать это, просто взглянув на проблему и подумав, как она должна работать (возможно, после перерыва - или однажды ответ ударит вас в душе), но вы будете более эффективны, если сможете контролировать что здесь происходит. Для электрических проблем это означает область, для протоколов - логический анализатор. В этой области есть несколько дешевых опций, например, плата "bus пират", которая имеет некоторые специфические возможности для протокола клавиатуры или что-то на основе FPGA, которая может иметь более длинный буфер захвата (см. Sump.org).
Еще одна вещь, которую вы могли бы попробовать, это использовать другое устройство, либо микроконтроллер, либо FPGA, чтобы построить хост клавиатуры и использовать его для тестирования вашего проекта на предмет ограничений спецификации.
источник
Я не смотрел библиотеку ps2dev, чтобы понять, как именно она работает, но одна вещь действительно бросается в глаза.
На данный момент делается одна попытка подключиться к «хосту» компьютера. Когда это не удается, ожидается еще одна секунда (светодиод на 0,5 с, светодиод на 0,5 с), прежде чем будет предпринята другая попытка.
Если материнская плата Intel не ждет достаточно времени для обнаружения клавиатуры, возможно, она никогда не получит попытку подключения, пока не продолжит свою последовательность загрузки.
Если вы уменьшите время ожидания до 0,1 с (измените время задержки (500) на задержку (50)), вам может повезти.
Если нет, попробуйте еще быстрее. Черт, даже попробуй это без промедления и посмотри, как это пойдет.
источник