A project to implement a console using the Mbed using VGA for video output and a PS/2 keyboard for the input. The eventual goal is to also include tools for managing SD cards, and a semi-self-hosting programming environment.

Dependencies:   PS2_MbedConsole fastlib SDFileSystem vga640x480g_mbedconsole lightvm mbed

MbedConsole is a cool little project to have a self-contained computer all on an Mbed. So far it has VGA and PS/2 support and can stand alone without a computer powering it. Next planned features are SD card support and a lightweight programmable VM complete with a file editor and self-hosted assembler.

You can view additional details about it at http://earlz.net/tags/mbedconsole

Revision:
10:bda85442b674
Child:
11:fede136943a9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/keyboard.cpp	Wed Sep 26 05:22:44 2012 +0000
@@ -0,0 +1,311 @@
+#include "mbedconsole.h"
+/**This is basically a straight rip off of my x86 OS project AlloyOS. I just ported the keyboard driver from it cause it always treated me well**/
+
+
+#define KEYBOARD_DATAPIN p11
+#define KEYBOARD_CLOCKPIN p12
+
+//how many keys the buffer can hold
+#define KBD_BUFFER_SIZE 128 
+
+//key defines
+#define LSHIFT_KEY 42
+#define RSHIFT_KEY 54
+#define CTRL_KEY 29
+#define ALT_KEY 56
+#define CAPS_KEY 58
+#define NUM_KEY 69
+#define SCROLL_KEY 70
+#define F_BASE_KEY 59  //59 is F1, 60 is F2, and so on until F10
+#define HOME_KEY 71
+#define UP_KEY 72
+#define PAGE_UP_KEY 73
+#define LEFT_KEY 75
+#define RIGHT_KEY 77
+#define END_KEY 79
+#define DOWN_KEY 80
+#define PAGE_DOWN_KEY 81
+#define INSERT_KEY 82
+#define DEL_KEY 83
+#define F11_KEY 87
+#define F12_KEY 89
+
+#define SCROLL_LED 1
+#define NUM_LED 2
+#define CAPS_LED 4
+
+
+const char kbdus[128] =
+{
+	0,  27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */
+ '9', '0', '-', '=', '\b', /* Backspace */
+ '\t',   /* Tab */
+ 'q', 'w', 'e', 'r', /* 19 */
+ 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter key */
+ 0,   /* 29   - Control */
+ 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 39 */
+ '\'', '`',   0,  /* Left shift */
+ '\\', 'z', 'x', 'c', 'v', 'b', 'n',   /* 49 */
+ 'm', ',', '.', '/',   0,    /* Right shift */
+ '*',
+ 0, /* Alt */
+ ' ', /* Space bar */
+ 0, /* Caps lock */
+ 0, /* 59 - F1 key ... > */
+ 0,   0,   0,   0,   0,   0,   0,   0,
+ 0, /* < ... F10 */
+ 0, /* 69 - Num lock*/
+ 0, /* Scroll Lock */
+ 0, /* Home key */
+ 0, /* Up Arrow */
+ 0, /* Page Up */
+ '-',
+ 0, /* Left Arrow */
+ 0,
+ 0, /* Right Arrow */
+ '+',
+ 0, /* 79 - End key*/
+ 0, /* Down Arrow */
+ 0, /* Page Down */
+ 0, /* Insert Key */
+ 0, /* Delete Key */
+ 0,   0,   0,
+ 0, /* F11 Key */
+ 0, /* F12 Key */
+ 0, /* All other keys are undefined */
+};
+
+const char kbdus_caps[128] =
+{
+	0,  27, '!', '@', '#', '$', '%', '^', '&', '*', /* 9 */
+ '(', ')', '_', '+', '\b', /* Backspace */
+ '\t',   /* Tab */
+ 'Q', 'W', 'E', 'R', /* 19 */
+ 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', /* Enter key */
+ 0,   /* 29   - Control */
+ 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* 39 */
+ '"', '~',   0,  /* Left shift */
+ '|', 'Z', 'X', 'C', 'V', 'B', 'N',   /* 49 */
+ 'M', '<', '>', '?',   0,    /* Right shift */
+ '*',
+ 0, /* Alt */
+ ' ', /* Space bar */
+ 0, /* Caps lock */
+ 0, /* 59 - F1 key ... > */
+ 0,   0,   0,   0,   0,   0,   0,   0,
+ 0, /* < ... F10 */
+ 0, /* 69 - Num lock*/
+ 0, /* Scroll Lock */
+ 0, /* Home key */
+ 0, /* Up Arrow */
+ 0, /* Page Up */
+ '-',
+ 0, /* Left Arrow */
+ 0,
+ 0, /* Right Arrow */
+ '+',
+ 0, /* 79 - End key*/
+ 0, /* Down Arrow */
+ 0, /* Page Down */
+ 0, /* Insert Key */
+ 0, /* Delete Key */
+ 0,   0,   0,
+ 0, /* F11 Key */
+ 0, /* F12 Key */
+ 0, /* All other keys are undefined */
+};
+
+
+typedef struct {
+	unsigned char caps;
+	unsigned char shift;
+	unsigned char scroll;
+	unsigned char num;
+	unsigned char ctrl;
+	unsigned char alt;
+}
+shift_locks; /*for simplicity and speed*/
+
+extern volatile shift_locks kbd_shifts;
+
+
+typedef struct {
+	uint16_t scancode;
+	uint8_t asci;
+}kbd_key;
+
+
+PS2KB_INIT *ps2_kb_init;
+PS2KB *ps2_kb;
+
+volatile kbd_key *keys;
+volatile uint8_t current_key=0;
+volatile uint8_t key_got=0;
+volatile char pending_key=0;
+volatile uint8_t led_status=0;
+
+void keyboard_callback(PS2KB kb, uint8_t val);
+
+void keyboard_init()
+{
+    keys=(kbd_key*)malloc(256*sizeof(kbd_key));
+	kbd_shifts.shift=0;
+	kbd_shifts.caps=0;
+	kbd_shifts.num=0;
+	kbd_shifts.scroll=0;
+	kbd_shifts.ctrl=0;
+	kbd_shifts.alt=0;
+    ps2_kb_init=new PS2KB_INIT(KEYBOARD_CLOCKPIN, KEYBOARD_DATAPIN);
+    ps2_kb=new PS2KB(KEYBOARD_CLOCKPIN, KEYBOARD_DATAPIN, (KeyboardCallback) &keyboard_callback);
+}
+
+
+
+volatile shift_locks kbd_shifts;
+
+
+
+/**The way the keyboard driver works is this:
+the buffer is 256 elements big. key_got and current_key are both
+bytes. Rather than setting current_key to 0, the entire buffer is constantly
+in use. when a key is pushed, current key is incremented. when a key is got(with safety checks)
+key_got is incremented. Also, when it reaches the end of the buffer, it simply wraps around
+to the beginning due to byte overflow. The worst that can happen is if 256 bytes get
+built up, in which case everything will be screwed up.. I should eventually controlt he capture
+of these keys to where not all of them are stored, and they are only stored when needed**/
+
+int kbd_PutBuffer(uint16_t scan,uint8_t asci){
+	keys[current_key].scancode=scan;
+	keys[current_key].asci=asci;
+	current_key++;
+	pending_key++;;
+	return 0;
+}
+
+kbd_key kbd_PopBuffer(){
+	kbd_key k;
+	while(pending_key==0){
+		//hlt();
+	//fill in busy code here	
+	}
+	
+	k.scancode=keys[key_got].scancode;
+	k.asci=keys[key_got].asci;
+	pending_key--;
+	key_got++;
+	return k;
+}
+
+uint8_t kbd_GetKey(){ //this will just return the asci code
+	kbd_key k;
+	k.asci=0;
+	while(k.asci==0){
+		k=kbd_PopBuffer();
+	}
+	return k.asci;
+}
+
+
+void kbd_update_leds(uint8_t status){
+	uint8_t tmp;
+	//TODO
+	/*while((inportb(0x64)&2)!=0){}
+	outportb(0x60,0xED);
+	
+	while((inportb(0x64)&2)!=0){}
+	outportb(0x60,status);
+	*/
+}
+
+
+ 
+int kbd_DoShifts(uint8_t scan){
+	switch(scan){
+		case RSHIFT_KEY:
+			kbd_shifts.shift++;
+			break;
+		case LSHIFT_KEY:
+			kbd_shifts.shift++;
+			break;
+		case CTRL_KEY:
+			kbd_shifts.ctrl++;
+			break;
+		case ALT_KEY:
+			kbd_shifts.alt++;
+			break;
+		case CAPS_KEY:
+			led_status^=CAPS_LED;
+			kbd_update_leds(led_status);
+			kbd_shifts.caps^=1;
+			break;
+		case NUM_KEY:
+			led_status^=NUM_LED;
+			kbd_update_leds(led_status);
+			kbd_shifts.num^=1;
+			break;
+		case SCROLL_KEY:
+			led_status^=SCROLL_LED;
+			kbd_update_leds(led_status);
+			kbd_shifts.scroll^=1;
+			break;
+		default:
+			return 0;
+			break;
+	}
+	return 1;
+}
+
+int kbd_DoUnshifts(uint8_t scan){
+	switch(scan){
+		case RSHIFT_KEY:
+			kbd_shifts.shift--;
+			break;
+		case LSHIFT_KEY:
+			kbd_shifts.shift--;
+			break;
+		case CTRL_KEY:
+			kbd_shifts.ctrl--;
+			break;
+		case ALT_KEY:
+			kbd_shifts.alt--;
+			break;
+		case CAPS_KEY:
+			//kbd_shifts.caps=0;
+			break;
+		case NUM_KEY:
+			//kbd_shifts.num=0;
+			break;
+		case SCROLL_KEY:
+			//kbd_shifts.scroll=0;
+			break;
+		default:
+			return 0;
+			break;
+	}
+	return 1;
+}
+volatile bool expecting_break=false;
+void keyboard_callback(PS2KB kb, uint8_t val) //this is called from interrupt! Must be fast
+{
+    	//stopints();
+    if(expecting_break){
+        val^=0x80;
+        kbd_DoUnshifts(val);
+        expecting_break=false;
+    }else{
+    	if(val>=0x80){ 	
+    		expecting_break=true;
+    	}else{
+    		if(kbd_DoShifts(val)==0){ //if not a shift-type key
+    			
+    			if ((kbd_shifts.caps^kbd_shifts.shift)==1) {
+    				kbd_PutBuffer(val,kbdus_caps[val]);
+    			}else{
+    				kbd_PutBuffer(val,kbdus[val]);
+    			}
+    		}
+    	}
+	}
+}
+
+