a500kbd

annotate src/main.c @ 1:3228a731d4db

translate scancodes
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 14 Oct 2017 07:23:47 +0300
parents 8e8e17a0f88e
children a4fd9c5a6655
rev   line source
nuclear@0 1 #define F_CPU XTAL
nuclear@0 2 #include <stdio.h>
nuclear@1 3 #include <ctype.h>
nuclear@0 4 #include <avr/io.h>
nuclear@0 5 #include <avr/interrupt.h>
nuclear@0 6 #include <util/delay.h>
nuclear@0 7 #include <util/parity.h>
nuclear@0 8 #include "serial.h"
nuclear@1 9 #include "scantbl.h"
nuclear@0 10
nuclear@0 11 /* pin assignments:
nuclear@0 12 * B0 PS/2 data
nuclear@1 13 * D2 PS/2 clock (INT0)
nuclear@1 14 * B1 KBD data
nuclear@1 15 * D3 KBD clock (INT1)
nuclear@0 16 */
nuclear@0 17
nuclear@0 18 #define BIT_DATA 1
nuclear@0 19 #define BIT_CLK 2
nuclear@0 20
nuclear@0 21 #define PS2LOW(bit) do { DDRB |= (bit); PORTB &= ~(bit); } while(0)
nuclear@0 22 #define PS2HIGH(bit) do { DDRB |= (bit); PORTB |= (bit); } while(0)
nuclear@0 23 #define PS2REL(bit) do { DDRB &= ~(bit); PORTB &= ~(bit); } while(0)
nuclear@0 24
nuclear@0 25 void ps2write(unsigned char c);
nuclear@1 26 unsigned char ps2read(void);
nuclear@1 27 int ps2pending(void);
nuclear@0 28
nuclear@1 29 #define BUF_SZ 16
nuclear@1 30 #define BUF_IDX_MASK (BUF_SZ - 1)
nuclear@1 31 #define NEXT_IDX(x) (((x) + 1) & BUF_IDX_MASK)
nuclear@1 32 static volatile unsigned char keybuf[BUF_SZ];
nuclear@1 33 static volatile unsigned char key_rd, key_wr;
nuclear@1 34
nuclear@1 35 static volatile int sending;
nuclear@1 36
nuclear@1 37 enum {
nuclear@1 38 KF_BRK = 1,
nuclear@1 39 KF_EXT = 2,
nuclear@1 40 KF_EXT1 = 4,
nuclear@1 41 };
nuclear@0 42
nuclear@0 43 int main(void)
nuclear@0 44 {
nuclear@1 45 unsigned int keyflags = 0;
nuclear@1 46 int keycode;
nuclear@0 47
nuclear@0 48 DDRB = 0;
nuclear@1 49 DDRD = 0;
nuclear@0 50 PORTB = 0;
nuclear@1 51 PORTD = 0;
nuclear@1 52 EIMSK = 0; /* mask external interrupts */
nuclear@1 53 EICRA = (1 << ISC11) | (1 << ISC01); /* falling edge interrupts */
nuclear@0 54
nuclear@0 55 /* initialize the UART and enable interrupts */
nuclear@0 56 init_serial(9600);
nuclear@0 57 sei();
nuclear@0 58
nuclear@0 59 printf("PS/2 keyboard controller - John Tsiombikas <nuclear@member.fsf.org>\r\n");
nuclear@1 60
nuclear@1 61 EIMSK = (1 << INT0); /* enable ps/2 clock interrupt */
nuclear@0 62
nuclear@0 63 for(;;) {
nuclear@1 64 unsigned char c = ps2read();
nuclear@1 65 switch(c) {
nuclear@1 66 case 0xe0: /* extended */
nuclear@1 67 keyflags |= KF_EXT;
nuclear@1 68 break;
nuclear@0 69
nuclear@1 70 case 0xe1: /* extended */
nuclear@1 71 keyflags |= KF_EXT1;
nuclear@1 72 break;
nuclear@0 73
nuclear@1 74 case 0xf0: /* break code */
nuclear@1 75 keyflags |= KF_BRK;
nuclear@1 76 break;
nuclear@1 77
nuclear@1 78 default:
nuclear@1 79 keycode = 0;
nuclear@1 80 if(keyflags & KF_EXT) {
nuclear@1 81 printf("ext ");
nuclear@1 82 if(c < KEYMAP_EXT_SIZE) {
nuclear@1 83 keycode = keymap_ext[(int)c];
nuclear@1 84 }
nuclear@1 85 } else if(keyflags & KF_EXT1) {
nuclear@1 86 printf("ext1 ");
nuclear@0 87 } else {
nuclear@1 88 if(c < KEYMAP_NORMAL_SIZE) {
nuclear@1 89 keycode = keymap_normal[(int)c];
nuclear@1 90 }
nuclear@0 91 }
nuclear@0 92
nuclear@1 93 if(keycode >= 256) {
nuclear@1 94 /*printf("%s: %s (scancode: %x)\r\n", keyflags & KF_BRK ? "release" : "press", skeystr[keycode - 256], (unsigned int)c);*/
nuclear@1 95 printf("%s: key %xh (scancode: %x)\r\n", keyflags & KF_BRK ? "release" : "press", keycode, (unsigned int)c);
nuclear@1 96 } else if(isprint(keycode)) {
nuclear@1 97 printf("%s: %c (scancode: %x)\r\n", keyflags & KF_BRK ? "release" : "press", (char)keycode, (unsigned int)c);
nuclear@1 98 } else if(keycode > 0) {
nuclear@1 99 printf("%s: key %xh (scancode: %x)\r\n", keyflags & KF_BRK ? "release" : "press", keycode, (unsigned int)c);
nuclear@1 100 } else {
nuclear@1 101 printf("%s: %x\r\n", keyflags & KF_BRK ? "release" : "press", (unsigned int)c);
nuclear@1 102 }
nuclear@1 103 keyflags = 0;
nuclear@0 104 }
nuclear@0 105 }
nuclear@0 106 return 0;
nuclear@0 107 }
nuclear@0 108
nuclear@0 109 void ps2write(unsigned char c)
nuclear@0 110 {
nuclear@0 111 int i;
nuclear@1 112 unsigned short out = (unsigned short)c | ((unsigned short)(parity_even_bit(c) & 1) << 8);
nuclear@0 113
nuclear@0 114 /* pull clock low for >60us */
nuclear@0 115 PS2LOW(BIT_CLK);
nuclear@0 116 _delay_us(60);
nuclear@0 117
nuclear@0 118 /* then pull data low and release clock */
nuclear@0 119 PS2LOW(BIT_DATA);
nuclear@0 120 PS2REL(BIT_CLK);
nuclear@0 121
nuclear@0 122 for(i=0; i<9; i++) {
nuclear@0 123 while(PINB & BIT_CLK); /* wait for kbd to drive the clock low */
nuclear@0 124 PORTB |= out & 1;
nuclear@0 125 out >>= 1;
nuclear@0 126 while(!(PINB & BIT_CLK)); /* wait for kbd to drive the clock high */
nuclear@0 127 }
nuclear@0 128
nuclear@0 129 PS2REL(BIT_DATA);
nuclear@0 130 /* wait for ack */
nuclear@0 131 while(PINB & BIT_DATA);
nuclear@0 132 while(!(PINB & BIT_DATA));
nuclear@0 133 }
nuclear@0 134
nuclear@1 135 unsigned char ps2read(void)
nuclear@0 136 {
nuclear@1 137 unsigned char key;
nuclear@0 138
nuclear@1 139 while(key_rd == key_wr) {
nuclear@0 140 }
nuclear@0 141
nuclear@1 142 cli();
nuclear@1 143 key = keybuf[key_rd];
nuclear@1 144 key_rd = NEXT_IDX(key_rd);
nuclear@1 145 sei();
nuclear@0 146
nuclear@1 147 return key;
nuclear@0 148 }
nuclear@1 149
nuclear@1 150 int ps2pending(void)
nuclear@1 151 {
nuclear@1 152 return key_rd != key_wr;
nuclear@1 153 }
nuclear@1 154
nuclear@1 155 ISR(INT0_vect)
nuclear@1 156 {
nuclear@1 157 static unsigned char value, valp, parity;
nuclear@1 158 static int nbits;
nuclear@1 159
nuclear@1 160 if(sending) {
nuclear@1 161 } else {
nuclear@1 162 if(nbits > 0 && nbits < 9) {
nuclear@1 163 value >>= 1;
nuclear@1 164 if(PINB & 1) {
nuclear@1 165 value |= 0x80;
nuclear@1 166 parity ^= 1;
nuclear@1 167 }
nuclear@1 168 }/* else if(nbits == 9) {
nuclear@1 169 valp = PINB & 1;
nuclear@1 170 }*/
nuclear@1 171 if(++nbits >= 11) {
nuclear@1 172 nbits = 0;
nuclear@1 173
nuclear@1 174 /* check parity */
nuclear@1 175 /*if((parity & 1) == (valp & 1)) {}*/
nuclear@1 176 keybuf[key_wr] = (unsigned char)value;
nuclear@1 177 key_wr = NEXT_IDX(key_wr);
nuclear@1 178
nuclear@1 179 value = 0;
nuclear@1 180 parity = 0;
nuclear@1 181 }
nuclear@1 182 }
nuclear@1 183 }