a500kbd

annotate src/main.c @ 3:31a1f0b53d98

- scroll lock now acts as caps lock - the scroll-lock light indicates drive activity
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 18 Oct 2017 08:20:58 +0300
parents a4fd9c5a6655
children
rev   line source
nuclear@0 1 #include <stdio.h>
nuclear@1 2 #include <ctype.h>
nuclear@0 3 #include <avr/io.h>
nuclear@0 4 #include <avr/interrupt.h>
nuclear@0 5 #include <util/delay.h>
nuclear@0 6 #include "serial.h"
nuclear@1 7 #include "scantbl.h"
nuclear@2 8 #include "ps2kbd.h"
nuclear@2 9 #include "amigakb.h"
nuclear@2 10 #include "defs.h"
nuclear@2 11 #include "timer.h"
nuclear@1 12
nuclear@1 13 enum {
nuclear@1 14 KF_BRK = 1,
nuclear@1 15 KF_EXT = 2,
nuclear@1 16 KF_EXT1 = 4,
nuclear@2 17
nuclear@2 18 KF_CTRL = 16,
nuclear@2 19 KF_LAMIGA = 32,
nuclear@2 20 KF_RAMIGA = 64
nuclear@1 21 };
nuclear@2 22 #define KF_TRANSIENT 0x0f
nuclear@2 23 #define KF_STICKY 0xf0
nuclear@0 24
nuclear@3 25 static unsigned char led_state;
nuclear@3 26
nuclear@0 27 int main(void)
nuclear@0 28 {
nuclear@1 29 unsigned int keyflags = 0;
nuclear@3 30 unsigned char c, keycode, prev_drvled = 0;
nuclear@2 31 int press;
nuclear@0 32
nuclear@2 33 /* disable all pullups globally */
nuclear@2 34 MCUCR |= 1 << PUD;
nuclear@2 35
nuclear@1 36 DDRD = 0;
nuclear@1 37 PORTD = 0;
nuclear@1 38 EIMSK = 0; /* mask external interrupts */
nuclear@1 39 EICRA = (1 << ISC11) | (1 << ISC01); /* falling edge interrupts */
nuclear@0 40
nuclear@2 41 init_timer();
nuclear@2 42
nuclear@0 43 /* initialize the UART and enable interrupts */
nuclear@0 44 init_serial(9600);
nuclear@0 45 sei();
nuclear@0 46
nuclear@0 47 printf("PS/2 keyboard controller - John Tsiombikas <nuclear@member.fsf.org>\r\n");
nuclear@1 48
nuclear@2 49 EIMSK = (1 << INT0) | (1 << INT1); /* enable ps/2 clock interrupt */
nuclear@0 50
nuclear@3 51 ps2setled(0); /* start with all LEDs off */
nuclear@3 52
nuclear@0 53 for(;;) {
nuclear@3 54 while(!ps2pending()) {
nuclear@3 55 unsigned char drvled = PIND & ADRVLED_BIT;
nuclear@3 56 if(drvled != prev_drvled) {
nuclear@3 57 prev_drvled = drvled;
nuclear@3 58 if(drvled) {
nuclear@3 59 led_state |= PS2LED_SCRLK;
nuclear@3 60 } else {
nuclear@3 61 led_state &= ~PS2LED_SCRLK;
nuclear@3 62 }
nuclear@3 63 ps2setled(led_state);
nuclear@3 64 }
nuclear@3 65 }
nuclear@3 66
nuclear@3 67 c = ps2read();
nuclear@1 68 switch(c) {
nuclear@1 69 case 0xe0: /* extended */
nuclear@1 70 keyflags |= KF_EXT;
nuclear@1 71 break;
nuclear@0 72
nuclear@1 73 case 0xe1: /* extended */
nuclear@1 74 keyflags |= KF_EXT1;
nuclear@1 75 break;
nuclear@0 76
nuclear@1 77 case 0xf0: /* break code */
nuclear@1 78 keyflags |= KF_BRK;
nuclear@1 79 break;
nuclear@1 80
nuclear@1 81 default:
nuclear@2 82 press = !(keyflags & KF_BRK);
nuclear@2 83
nuclear@2 84 keycode = 0xff;
nuclear@1 85 if(keyflags & KF_EXT) {
nuclear@1 86 if(c < KEYMAP_EXT_SIZE) {
nuclear@1 87 keycode = keymap_ext[(int)c];
nuclear@1 88 }
nuclear@1 89 } else if(keyflags & KF_EXT1) {
nuclear@0 90 } else {
nuclear@1 91 if(c < KEYMAP_NORMAL_SIZE) {
nuclear@1 92 keycode = keymap_normal[(int)c];
nuclear@1 93 }
nuclear@0 94 }
nuclear@0 95
nuclear@2 96 switch(keycode) {
nuclear@2 97 case AMIKEY_CTRL:
nuclear@2 98 if(press)
nuclear@2 99 keyflags |= KF_CTRL;
nuclear@2 100 else
nuclear@2 101 keyflags &= ~KF_CTRL;
nuclear@2 102 break;
nuclear@2 103
nuclear@2 104 case AMIKEY_LAMI:
nuclear@2 105 if(press)
nuclear@2 106 keyflags |= KF_LAMIGA;
nuclear@2 107 else
nuclear@2 108 keyflags &= ~KF_LAMIGA;
nuclear@2 109 break;
nuclear@2 110
nuclear@2 111 case AMIKEY_RAMI:
nuclear@2 112 if(press)
nuclear@2 113 keyflags |= KF_RAMIGA;
nuclear@2 114 else
nuclear@2 115 keyflags &= ~KF_RAMIGA;
nuclear@2 116 break;
nuclear@2 117
nuclear@2 118 default:
nuclear@2 119 break;
nuclear@2 120 }
nuclear@2 121
nuclear@2 122 if((keyflags & (KF_CTRL | KF_RAMIGA | KF_LAMIGA)) == (KF_CTRL | KF_RAMIGA | KF_LAMIGA)) {
nuclear@2 123 printf("CTRL - AMIGA - AMIGA!\r\n");
nuclear@2 124 amikb_reset();
nuclear@2 125 }
nuclear@2 126
nuclear@2 127 if(keycode != 0xff) {
nuclear@3 128 int press = ~keyflags & KF_BRK;
nuclear@3 129 amikb_sendkey(keycode, press);
nuclear@3 130 if(keycode == 0x62 && press) {
nuclear@3 131 led_state ^= PS2LED_CAPSLK;
nuclear@3 132 ps2setled(led_state);
nuclear@3 133 }
nuclear@3 134 /*printf("scancode %x -> [%s] amiga key %xh\r\n", (unsigned int)c, press ? "press" : "release", keycode);*/
nuclear@1 135 } else {
nuclear@3 136 printf("PS/2 unknown command or keycode: %x\r\n", (unsigned int)c);
nuclear@1 137 }
nuclear@2 138 keyflags &= ~KF_TRANSIENT;
nuclear@0 139 }
nuclear@0 140 }
nuclear@0 141 return 0;
nuclear@0 142 }