[c7cc629] | 1 | // ps/2 keyboard decoder on ATMega8, ATMega48
|
---|
| 2 | // Copyright 2010-2014, Adrien Destugues <pulkomandy@pulkomandy.tk>
|
---|
| 3 | // This file is distributed under the terms of the MIT Licence.
|
---|
[b82c7b3] | 4 |
|
---|
| 5 | // Parts borrowed from :
|
---|
| 6 | // keyboard.c
|
---|
| 7 | // for NerdKits with ATmega168
|
---|
| 8 | // hevans@nerdkits.com
|
---|
| 9 |
|
---|
| 10 | #include <avr/io.h>
|
---|
| 11 | #include <avr/interrupt.h>
|
---|
| 12 |
|
---|
| 13 |
|
---|
| 14 | //ps/2 Keyboard pin out
|
---|
| 15 | //pin 5 - clock
|
---|
| 16 | //pin 3 - GND
|
---|
| 17 | //pin 1 - data
|
---|
| 18 | //pin 4 - VCC
|
---|
| 19 |
|
---|
| 20 | //PIN configuration
|
---|
| 21 | #define PS2_PORT PIND
|
---|
[c7cc629] | 22 | #define PS2_CLK PD3 /* Also INT1 */
|
---|
[ea32107] | 23 |
|
---|
| 24 | #ifdef __AVR_ATtiny2313__
|
---|
| 25 | // K4KUSB modified board
|
---|
| 26 | #define PS2_DATA PD5
|
---|
| 27 | #else
|
---|
| 28 | // ENSSAT IR modified board
|
---|
[b82c7b3] | 29 | #define PS2_DATA PD4
|
---|
[ea32107] | 30 | #endif
|
---|
[b82c7b3] | 31 |
|
---|
[239ae4e] | 32 | static volatile uint8_t char_waiting;
|
---|
| 33 | static uint8_t started;
|
---|
| 34 | static uint8_t bit_count;
|
---|
| 35 | static uint8_t extended;
|
---|
[c7cc629] | 36 |
|
---|
[87ab18e] | 37 | volatile uint8_t kbd_data;
|
---|
[b82c7b3] | 38 | uint8_t release;
|
---|
| 39 |
|
---|
| 40 | // Interrupt vector - Triggered when there is activity on the clock line
|
---|
| 41 | ISR(INT1_vect)
|
---|
| 42 | {
|
---|
| 43 | //make sure clock line is low, if not ignore this transition
|
---|
| 44 | if(PS2_PORT & (1<<PS2_CLK)){
|
---|
| 45 | return;
|
---|
| 46 | }
|
---|
| 47 |
|
---|
| 48 | //if we have not started, check for start bit on DATA line
|
---|
| 49 | if(!started){
|
---|
| 50 | if ( (PS2_PORT & (1<<PS2_DATA)) == 0 ) {
|
---|
| 51 | started = 1;
|
---|
| 52 | bit_count = 0;
|
---|
| 53 | kbd_data = 0;
|
---|
| 54 | //printf_P(PSTR("%d"),started);
|
---|
| 55 | return;
|
---|
| 56 | }
|
---|
| 57 | } else if(bit_count < 8) { //we started, read in the new bit
|
---|
| 58 | //put a 1 in the right place of kdb_data if PC2 is high, leave
|
---|
| 59 | //a 0 otherwise
|
---|
| 60 | if(PS2_PORT & (1<<PS2_DATA)){
|
---|
| 61 | kbd_data |= (1<<bit_count);
|
---|
| 62 | }
|
---|
| 63 | bit_count++;
|
---|
| 64 | return;
|
---|
| 65 | } else if(bit_count == 8){ //pairty bit
|
---|
| 66 | //not implemented
|
---|
| 67 | bit_count++;
|
---|
| 68 | return;
|
---|
| 69 | } else { //stop bit
|
---|
| 70 | //should check to make sure DATA line is high, what to do if not?
|
---|
| 71 | started = 0;
|
---|
| 72 | bit_count = 0;
|
---|
| 73 | }
|
---|
| 74 |
|
---|
| 75 | if(kbd_data == 0xF0){ //release code
|
---|
| 76 | release = 1;
|
---|
| 77 | kbd_data = 0;
|
---|
| 78 | return;
|
---|
| 79 | } else { //not a special character
|
---|
[87ab18e] | 80 | #ifdef CALLBACK
|
---|
| 81 | CALLBACK
|
---|
| 82 | #endif
|
---|
[b82c7b3] | 83 | if(release){ //we were in release mode - exit release mode
|
---|
| 84 | release = 0;
|
---|
| 85 | } else {
|
---|
[87ab18e] | 86 | // Notify callback that there's a new char waiting
|
---|
[b82c7b3] | 87 | char_waiting = 1;
|
---|
| 88 | }
|
---|
| 89 | }
|
---|
| 90 | }
|
---|
| 91 |
|
---|
| 92 |
|
---|
| 93 | uint8_t read_char(){
|
---|
| 94 | while(!char_waiting);
|
---|
| 95 | char_waiting = 0;
|
---|
| 96 | return kbd_data;
|
---|
| 97 | }
|
---|
| 98 |
|
---|
| 99 |
|
---|
| 100 | void init_keyboard(){
|
---|
| 101 | started = 0;
|
---|
| 102 | kbd_data = 0;
|
---|
| 103 | bit_count = 0;
|
---|
| 104 |
|
---|
| 105 | //make PS2_CLK input pin
|
---|
[ea32107] | 106 | DDRD &= ~((1<<PS2_CLK) | (1<<PS2_DATA));
|
---|
[b82c7b3] | 107 | //turn on pullup resistor
|
---|
| 108 | PS2_PORT |= (1<<PS2_CLK);
|
---|
| 109 |
|
---|
[c7cc629] | 110 | // FIXME we can use the "pin change" interrupt rather than INT0/INT1 when not
|
---|
| 111 | // on the old clumsy ATMega8. This would allow for any pin to be used.
|
---|
| 112 | // PCMSK |= (1<<PIND3);
|
---|
[b82c7b3] | 113 | MCUCR |= (1<<ISC11); // Falling edge
|
---|
| 114 | MCUCR &= ~(1<<ISC10);
|
---|
[071dc14] | 115 | #ifdef __AVR_ATmega48P__
|
---|
| 116 | EIMSK |= (1<<INT1);
|
---|
[c7cc629] | 117 | #else // ATmega8
|
---|
[b82c7b3] | 118 | GIMSK |= (1<<INT1);
|
---|
[071dc14] | 119 | #endif
|
---|
[b82c7b3] | 120 |
|
---|
| 121 | sei();
|
---|
| 122 | }
|
---|
| 123 |
|
---|
| 124 |
|
---|