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
Diff: keyboard.cpp
- 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]); + } + } + } + } +} + +