i have successfully(somewhat) interfaced ps2 keyboard with msp430.
everything goes perfect mostly before ~25 keystrokes.
but mostly after ~25 keystrokes , error in communication occurs(parity error).
all data after error-data is also having parity problem. (ie anything after error data is garbage.)
im using POT for converting 5V -> 3V , GND common, powering keyboard from external source(i have tried changing keyboard also).
i have a MSP430G2553IN20 launchpad board.
the data is printed on screen, that i can see.
// port2
#include <hardware/port2.h>
void port2_init()
{
KEYBOARD_PS2_PDIR &= ~(KEYBOARD_PS2_DATA | KEYBOARD_PS2_CLK);
KEYBOARD_PS2_PREN |= KEYBOARD_PS2_DATA | KEYBOARD_PS2_CLK;
KEYBOARD_PS2_POUT |= KEYBOARD_PS2_DATA | KEYBOARD_PS2_CLK;
KEYBOARD_PS2_PIES |= KEYBOARD_PS2_CLK;
KEYBOARD_PS2_PIE |= KEYBOARD_PS2_CLK;
KEYBOARD_PS2_PIFG &= ~KEYBOARD_PS2_CLK;
P1DIR |= BIT6;
P1OUT &= ~BIT6;
/* interrupt goes to pin2_interrupt() */
}
void port2_interrupt()
{
P1OUT ^= BIT6;
KEYBOARD_PS2_PIFG &= ~KEYBOARD_PS2_CLK;
keyboard_ps2.index++;
switch(keyboard_ps2.index)
{
case -1:
keyboard_ps2.data = 0;
keyboard_ps2.parity = 0;
/* start bit */
break;
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
/* data */
if(KEYBOARD_PS2_PIN & KEYBOARD_PS2_DATA)
{
keyboard_ps2.data |= (1 << keyboard_ps2.index);
keyboard_ps2.parity ^= 0x01;
}
break;
case 8:
if((!(KEYBOARD_PS2_PIN & KEYBOARD_PS2_DATA)) == (!keyboard_ps2.parity))
{
/* incorrect data */
P1DIR |= BIT6;
/* hang */
while(1)
{
P1OUT ^= BIT6;
__delay_cycles(600000);
}
}
/* TODO: check parity for data */
break;
case 9:
/* STOP bit */
keyboard_ps2_data_decode();
default:
keyboard_ps2.index = -2;
break;
}
}
//ps2.c
#include <keyboard/ps2.h>
struct __keyboard_ps2 keyboard_ps2 =
{
.index = -2,
};
void keyboard_ps2_data_decode()
{
switch(keyboard_ps2.data)
{
case 0xF0:
/* some key released */
keyboard_ps2.make = FALSE;
return;
case 0xE0:
/* behaviour modifier */
keyboard_ps2.modifier = TRUE;
return;
case 0x12: /* left SHIFT */
case 0x59: /* right SHIFT */
keyboard_ps2.latch_shift = keyboard_ps2.make;
break;
/* right CTRL : <modifier> 0x14 */
case 0x14: /* left CTRL */
keyboard_ps2.latch_ctrl = keyboard_ps2.make;
break;
/* right ALT : <modifier> 0x11 */
case 0x11: /* left ALT */
keyboard_ps2.latch_alt = keyboard_ps2.make;
break;
/* including modifier version */
case 0x1F: /* left GUI */
//keyboard_ps2.latch_gui = keyboard_ps2.make;
break;
/* caps */
case 0x58:
if(keyboard_ps2.make)
{
/* flip caps */
keyboard_ps2.latch_caps ^= 0x01;
}
break;
default:
if(keyboard_ps2.make)
{
keyboard_ps2_resolve_scancode();
}
break;
}
keyboard_ps2.make = TRUE;
keyboard_ps2.modifier = FALSE;
}
void keyboard_ps2_resolve_scancode()
{
register uint8_t ch = 0;
if(keyboard_ps2.modifier)
{
switch (keyboard_ps2.data)
{
case 0x4A:
ch = '/';
break;
case 0x5A:
ch = KEYBOARD_PS2_ENTER;
break;
case 0x69:
ch = KEYBOARD_PS2_END;
break;
case 0x6B:
ch = KEYBOARD_PS2_LEFTARROW;
break;
case 0x6C:
ch = KEYBOARD_PS2_HOME;
break;
case 0x70:
ch = KEYBOARD_PS2_INSERT;
break;
case 0x71:
ch = KEYBOARD_PS2_DELETE;
break;
case 0x72:
ch = KEYBOARD_PS2_DOWNARROW;
break;
case 0x74:
ch = KEYBOARD_PS2_RIGHTARROW;
break;
case 0x75:
ch = KEYBOARD_PS2_UPARROW;
break;
case 0x7A:
ch = KEYBOARD_PS2_PAGEDOWN;
break;
case 0x7D:
ch = KEYBOARD_PS2_PAGEUP;
break;
}
}
else if(keyboard_ps2.data < KEYBOARD_PS2_KEYMAP_SIZE)
{
ch = keyboard_ps2_scancode_en[keyboard_ps2.data][keyboard_ps2.latch_shift];
/* caps lock feature, turn character to opposite case */
if(keyboard_ps2.latch_caps)
{
if('a' <= ch && ch <= 'z' )
{
ch -= 'a' - 'A';
}
else if('A' <= ch && ch <= 'Z')
{
ch += 'a' - 'A';
}
}
}
if(ch)
{
//uart_send(ch);
cqueue_push(&uart_cqueue_rx, ch);
}
}
//ps2.h
#ifndef _KEYBOARD_PS2_H_
#define _KEYBOARD_PS2_H_
#include <common.h>
#include <uart.h>
#include <cqueue.h>
#define KEYBOARD_PS2_PDIR P2DIR
#define KEYBOARD_PS2_PIN P2IN
#define KEYBOARD_PS2_POUT P2OUT
#define KEYBOARD_PS2_PIFG P2IFG
#define KEYBOARD_PS2_PIES P2IES
#define KEYBOARD_PS2_PIE P2IE
#define KEYBOARD_PS2_PREN P2REN
#define KEYBOARD_PS2_DATA BIT3
#define KEYBOARD_PS2_CLK BIT4
/* port/derivative: http://www.pjrc.com/teensy/td_libs_PS2Keyboard.html */
/* scancodes */
#define KEYBOARD_PS2_TAB 9
#define KEYBOARD_PS2_ENTER 13
#define KEYBOARD_PS2_BACKSPACE 127
#define KEYBOARD_PS2_ESCAPE 27
#define KEYBOARD_PS2_INSERT 0
#define KEYBOARD_PS2_DELETE 127
#define KEYBOARD_PS2_HOME 0
#define KEYBOARD_PS2_END 0
#define KEYBOARD_PS2_PAGEUP 25
#define KEYBOARD_PS2_PAGEDOWN 26
#define KEYBOARD_PS2_UPARROW 11
#define KEYBOARD_PS2_LEFTARROW 8
#define KEYBOARD_PS2_DOWNARROW 10
#define KEYBOARD_PS2_RIGHTARROW 21
#define KEYBOARD_PS2_F1 0
#define KEYBOARD_PS2_F2 0
#define KEYBOARD_PS2_F3 0
#define KEYBOARD_PS2_F4 0
#define KEYBOARD_PS2_F5 0
#define KEYBOARD_PS2_F6 0
#define KEYBOARD_PS2_F7 0
#define KEYBOARD_PS2_F8 0
#define KEYBOARD_PS2_F9 0
#define KEYBOARD_PS2_F10 0
#define KEYBOARD_PS2_F11 0
#define KEYBOARD_PS2_F12 0
#define KEYBOARD_PS2_SCROLL 0
#define KEYBOARD_PS2_KEYMAP_SIZE 136
#define keyboard_ps2_scancode_char(ch1, ch2) {ch1, ch2}
struct __keyboard_ps2
{
uint8_t data;
int8_t index;
uint8_t parity:1;
uint8_t modifier:1;
uint8_t make:1;
uint8_t latch_shift:1;
uint8_t latch_ctrl:1;
uint8_t latch_alt:1;
uint8_t latch_num:1;
//uint8_t latch_gui:1;
uint8_t latch_caps:1;
};
extern struct __keyboard_ps2 keyboard_ps2;
extern const uint8_t keyboard_ps2_scancode_en[KEYBOARD_PS2_KEYMAP_SIZE][2];
void keyboard_ps2_init();
void keyboard_ps2_data_decode(void);
void keyboard_ps2_resolve_scancode(void);
#endif
//port2.h
#ifndef _KEYBOARD_PS2_H_
#define _KEYBOARD_PS2_H_
#include <common.h>
#include <uart.h>
#include <cqueue.h>
#define KEYBOARD_PS2_PDIR P2DIR
#define KEYBOARD_PS2_PIN P2IN
#define KEYBOARD_PS2_POUT P2OUT
#define KEYBOARD_PS2_PIFG P2IFG
#define KEYBOARD_PS2_PIES P2IES
#define KEYBOARD_PS2_PIE P2IE
#define KEYBOARD_PS2_PREN P2REN
#define KEYBOARD_PS2_DATA BIT3
#define KEYBOARD_PS2_CLK BIT4
/* port/derivative: http://www.pjrc.com/teensy/td_libs_PS2Keyboard.html */
/* scancodes */
#define KEYBOARD_PS2_TAB 9
#define KEYBOARD_PS2_ENTER 13
#define KEYBOARD_PS2_BACKSPACE 127
#define KEYBOARD_PS2_ESCAPE 27
#define KEYBOARD_PS2_INSERT 0
#define KEYBOARD_PS2_DELETE 127
#define KEYBOARD_PS2_HOME 0
#define KEYBOARD_PS2_END 0
#define KEYBOARD_PS2_PAGEUP 25
#define KEYBOARD_PS2_PAGEDOWN 26
#define KEYBOARD_PS2_UPARROW 11
#define KEYBOARD_PS2_LEFTARROW 8
#define KEYBOARD_PS2_DOWNARROW 10
#define KEYBOARD_PS2_RIGHTARROW 21
#define KEYBOARD_PS2_F1 0
#define KEYBOARD_PS2_F2 0
#define KEYBOARD_PS2_F3 0
#define KEYBOARD_PS2_F4 0
#define KEYBOARD_PS2_F5 0
#define KEYBOARD_PS2_F6 0
#define KEYBOARD_PS2_F7 0
#define KEYBOARD_PS2_F8 0
#define KEYBOARD_PS2_F9 0
#define KEYBOARD_PS2_F10 0
#define KEYBOARD_PS2_F11 0
#define KEYBOARD_PS2_F12 0
#define KEYBOARD_PS2_SCROLL 0
#define KEYBOARD_PS2_KEYMAP_SIZE 136
#define keyboard_ps2_scancode_char(ch1, ch2) {ch1, ch2}
struct __keyboard_ps2
{
uint8_t data;
int8_t index;
uint8_t parity:1;
uint8_t modifier:1;
uint8_t make:1;
uint8_t latch_shift:1;
uint8_t latch_ctrl:1;
uint8_t latch_alt:1;
uint8_t latch_num:1;
//uint8_t latch_gui:1;
uint8_t latch_caps:1;
};
extern struct __keyboard_ps2 keyboard_ps2;
extern const uint8_t keyboard_ps2_scancode_en[KEYBOARD_PS2_KEYMAP_SIZE][2];
void keyboard_ps2_init();
void keyboard_ps2_data_decode(void);
void keyboard_ps2_resolve_scancode(void);
#endif