zondag 1 oktober 2023

PS/2 Keyboard Output (sending data to a keyboard)

As you have seen on this blog I have made multiple implementations that allow reading data from a PS/2 keyboard. However, in order to control the LED you have to also be able to write to the keyboard. This is far trickier than it seems, and the documentation on the Internet is limited. Basically the best document is only available using the wayback machine. There is also a working piece of code for the Arduino which isn't pretty and uses interrupts, which can be something people would shy away from (although I might try to implement a version with it).

The most important aspect is the timing schedule. There are many diagrams on the Internet, and most of them are wrong. This is the correct diagram, made by Craig Peacock and copied from the above linked website.


And here is a simplified C code implementation for PicMicro processors (suspendKeyboard() will take the clock line and move it to 0, resumeKeyboard() will release the clock line, keyboardClockHigh() waits for the clock line to go high, keyboardClockLow() waits for the clock line to go low, RB4 is considered to be the data line):

void sendKeyboard(unsigned char value, unsigned char parity) {
    suspendKeyboard();
    __delay_us(60);
    TRISBbits.TRISB4 = 0;
    PORTBbits.RB4 = 0;
    resumeKeyboard();
    keyboardClockHigh();
    for (int i = 0; i < 8; i++) {
        keyboardClockLow();
        if (value & 1) {
            PORTBbits.RB4 = 1;
        } else {
            PORTBbits.RB4 = 0;
        }
        value = value >> 1;
        keyboardClockHigh();
    }
    keyboardClockLow();
    if (parity) {
        PORTBbits.RB4 = 1;
    } else {
        PORTBbits.RB4 = 0;
    }
    keyboardClockHigh();
    keyboardClockLow();
    TRISBbits.TRISB4 = 1;
    while (PORTBbits.RB4) {};
    while (!PORTBbits.RB4) {};
    keyboardClockHigh();
    suspendKeyboard();
}

The full version of this code I will add later. Note that in order to actually change the LED on the keyboard, you need to send two bytes, as follows: first you need to send 0xED, then wait for the keyboard to respond with 0xFA, after which you send 0-7 based on which LED you wish to turn on. 

Geen opmerkingen: