Skip to content

Instantly share code, notes, and snippets.

@tiagosr
Created December 10, 2014 03:56
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tiagosr/6dc470ffc164d240175e to your computer and use it in GitHub Desktop.
Save tiagosr/6dc470ffc164d240175e to your computer and use it in GitHub Desktop.
PS/2 keyboard reader and Gradiente Expert 1.1 MSX keyboard adapter
/*
* ABNT2 PS/2 keyboard to Gradiente Expert 1.1 keyboard mapper
* (c) 2014 Tiago Rezende
*/
static const uint8_t ps2data = 2;
static const uint8_t ps2clk = 3;
//#define K(x) (uint8_t)((x>=0x80)?(x+0x8):((x<=0x07)?(x+0x80):(x-0x10)))
#define K(x) x
const PROGMEM uint8_t keymap_ABNT2[] = {
K(0xb7),
K(0xb7), // F9
K(0xb7),
K(0x71), // F5
K(0x67), // F3
K(0x65), // F1
K(0x66), // F2
K(0xb7), // F12
K(0xb7),
K(0xb7), // F10
K(0xb7), // F8
K(0xb7), // F6
K(0x70), // F4
K(0x73), // TAB
K(0xb7), // `
K(0xb7),
K(0xb7),
K(0x64), // L ALT
K(0x60), // L SHIFT
K(0xb7),
K(0x61), // L CTRL
K(0x46), // Q
K(0x01), // 1
K(0xb7),
K(0xb7),
K(0xb7),
K(0x57), // Z
K(0x50), // S
K(0x26), // A
K(0x54), // W
K(0x02), // 2
K(0xb7), // L WIN
K(0xb7),
K(0x30), // C
K(0x55), // X
K(0x31), // D
K(0x32), // E
K(0x04), // 4
K(0x03), // 3
K(0xb7),
K(0xb7),
K(0x80), // SPACE
K(0x53), // V
K(0x33), // F
K(0x51), // T
K(0x47), // R
K(0x05), // 5
K(0xb7),
K(0xb7),
K(0x43), // N
K(0x27), // B
K(0x35), // H
K(0x34), // G
K(0x56), // Y
K(0x06), // 6
K(0xb7),
K(0xb7),
K(0xb7),
K(0x42), // M
K(0x37), // J
K(0x52), // U
K(0x07), // 7
K(0x10), // 8
K(0xb7),
K(0xb7),
K(0x22), // ,
K(0x40), // K
K(0x36), // I
K(0x44), // O
K(0x00), // 0
K(0x11), // 9
K(0xb7),
K(0xb7),
K(0x23), // .
K(0x24), // ;
K(0x41), // L
K(0x21), // Ç
K(0x45), // P
K(0x12), // -
K(0xb7),
K(0xb7),
K(0x25), // /
K(0x17), // ~
K(0xb7),
K(0x15), // ´
K(0x13), // =
K(0xb7),
K(0xb7),
K(0x63), // CAPS
K(0x60), // R SHIFT
K(0x77), // ENTER
K(0x16), // [
K(0xb7),
K(0x21), // ]
K(0xb7),
K(0xb7),
K(0xb7),
K(0x14), // \
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0x75), // BACKSPACE
K(0xb7),
K(0xb7),
K(0x01), // KEYPAD 1,
K(0xb7),
K(0x04), // KEYPAD 4,
K(0x07), // KEYPAD 7,
K(0x23), // KEYPAD .
K(0xb7),
K(0xb7),
K(0x00), // KEYPAD 0
K(0x22), // KEYPAD ,
K(0x02), // KEYPAD 2
K(0x05), // KEYPAD 5
K(0x06), // KEYPAD 6
K(0x10), // KEYPAD 8
K(0x72), // ESCAPE
K(0xb7), // NUMLOCK
K(0xb7), // F11
K(0x90), // KEYPAD +
K(0x03), // KEYPAD 3
K(0x91), // KEYPAD -
K(0x92), // KEYPAD *
K(0x11), // KEYPAD 9,
K(0xb7), // SCROLL LOCK
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7), // F7
};
const PROGMEM uint8_t keymap_ext_ABNT2[] = {
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7), // WWW SEARCH
K(0x62), // R ALT
K(0xb7), // PRINT SCREEN
K(0xb7),
K(0x42), // R CTRL
K(0xb7), // PREV TRACK
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0x62), // L WIN
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7), // MESSENGER
K(0xb7),
K(0xb7), // R WIN
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7), // CALC
K(0xb7),
K(0xb7),
K(0xb7),
K(0x80), // CONTEXT
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7), // PLAY/PAUSE
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7), // WWW HOME
K(0xb7), // STOP
K(0xb7), // LOG OFF
K(0xb7),
K(0xb7),
K(0xb7), // SLEEP
K(0xb7), // MY COMPUTER
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7), // EMAIL
K(0xb7),
K(0x94), // KEYPAD /
K(0xb7),
K(0xb7),
K(0xb7), // NEXT TRACK
K(0xb7),
K(0xb7),
K(0xb7), // MEDIA SELECT
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0x77), // KP EN
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7), // WAKE
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7), // END
K(0xb7),
K(0x84), // L ARROW
K(0x81), // HOME
K(0xb7),
K(0xb7),
K(0xb7),
K(0x82), // INSERT
K(0x83), // DELETE
K(0x86), // D ARROW
K(0xb7),
K(0x87), // R ARROW
K(0x85), // U ARROW
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0x76), // PAGE DOWN
K(0xb7),
K(0xb7),
K(0x74), // PAGE UP
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7),
K(0xb7), // F7
};
uint8_t msx_buffer[16];
#define CO_BEGIN static int _co_state = 0; switch(_co_state) { case 0:
#define CO_WAIT(x) case __LINE__: if((x)) { _co_state = __LINE__; return; };
#define CO_YIELD do {_co_state = __LINE__; return; } while(0); case __LINE__: ;
#define CO_END };
#define CO_WAIT_HIGH(x) CO_WAIT(digitalRead(x) == 0)
#define CO_WAIT_LOW(x) CO_WAIT(digitalRead(x) != 0)
static inline void ps2kbd_interrupt(void) {
static uint8_t bitcount = 0, incoming = 0;
static uint32_t prev_ms = 0;
static boolean release_key, use_extended;
uint32_t now_ms;
uint8_t n, val;
val = digitalRead(ps2data);
now_ms = millis();
if(now_ms - prev_ms > 250) {
bitcount = 0;
incoming = 0;
}
prev_ms = now_ms;
n = bitcount - 1;
if (n <= 7) {
incoming = (val?0x80:0)|(incoming >> 1);
}
bitcount ++;
if(bitcount == 11) {
if(incoming == 0xf0) {
release_key = true;
} else if(incoming == 0xe0) {
use_extended = true;
} else {
uint8_t msx_scancode = pgm_read_byte(use_extended?(keymap_ext_ABNT2+incoming):(keymap_ABNT2+incoming));
if(release_key) {
msx_buffer[msx_scancode>>4] |= (1 << (msx_scancode & 0xf));
} else {
msx_buffer[msx_scancode>>4] &= ~(1 << (msx_scancode & 0xf));
}
/*
Serial.println(incoming);
/*
for(int i = 0; i < 16; i++) {
Serial.print(msx_buffer[i]>>4,HEX);
Serial.print(msx_buffer[i]&0xf,HEX);
}
Serial.println();
//*/
use_extended = false;
release_key = false;
}
bitcount = 0;
incoming = 0;
}
}
void ps2kbd_poll() {
static uint8_t incoming, i, outgoing, parity;
CO_BEGIN;
/*
pinMode(ps2data, OUTPUT);
digitalWrite(ps2data, 0);
pinMode(ps2clk, INPUT_PULLUP);
CO_WAIT_LOW(ps2clk);
outgoing = 0xff;
parity = 0;
for(i = 0; i < 8; i++) {
parity += outgoing & 1;
digitalWrite(ps2data, outgoing & 1);
CO_WAIT_HIGH(ps2clk);
CO_WAIT_LOW(ps2clk);
outgoing >>= 1;
}
digitalWrite(ps2data, parity & 1);
CO_WAIT_HIGH(ps2clk);
CO_WAIT_LOW(ps2clk);
digitalWrite(ps2data, 1);
CO_WAIT_HIGH(ps2clk);
CO_WAIT_LOW(ps2clk);
delayMicroseconds(50);
//CO_WAIT_LOW(ps2clk);
pinMode(ps2data, INPUT_PULLUP);
*/
while(true) {
CO_WAIT_HIGH(ps2clk);
CO_WAIT_LOW(ps2clk);
ps2kbd_interrupt();
}
CO_END;
}
void setup() {
//Serial.begin(9600);
//while(!Serial) {;}
pinMode(ps2data, INPUT_PULLUP);
pinMode(ps2clk, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP);
pinMode(7, INPUT_PULLUP);
pinMode(A0, OUTPUT);
pinMode(A1, OUTPUT);
pinMode(A2, OUTPUT);
pinMode(A3, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
for(uint8_t i = 0; i < 16; i++) {
msx_buffer[i] = 255;
}
attachInterrupt(1, ps2kbd_interrupt, FALLING);
}
void loop() {
uint8_t last_keys_index = 20;
uint8_t current;
uint8_t keys = 0;
PORTC &= 0xf0;
PORTB &= 0xf0;
while(true) {
while(last_keys_index == (current = __builtin_avr_swap(PIND)&0xf)) {
sei();
delayMicroseconds(1);
cli();
}
keys = msx_buffer[current];
PORTC = keys;
PORTB = __builtin_avr_swap(keys);
last_keys_index = current;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment