a500kbd

view src/amigakb.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
line source
1 #include <stdio.h>
2 #include <avr/io.h>
3 #include <avr/interrupt.h>
4 #include <util/delay.h>
5 #include "amigakb.h"
6 #include "defs.h"
7 #include "timer.h"
9 #define TIMEOUT_MSEC 143
11 static void resync(void);
13 void amikb_sendkey(unsigned char keycode, int press)
14 {
15 int i;
16 static unsigned char prev_keycode = 0xff;
17 static unsigned char capslk;
19 if(keycode == 0x62) {
20 /* caps lock doesn't get a key release event when the key is released
21 * but rather when the caps lock is toggled off again
22 */
23 if(!press) return;
25 capslk = ~capslk;
26 press = capslk;
27 }
29 /* keycode bit transfer order: 6 5 4 3 2 1 0 7 (7 is pressed flag) */
30 keycode = (keycode << 1) | (~press & 1);
31 if(keycode == prev_keycode) return;
32 prev_keycode = keycode;
34 /* make sure we don't pulse the lines while grabbing control
35 * by first reinstating the pullups before changing direction
36 */
37 PORTD |= ACLK_BIT | ADATA_BIT;
38 DDRD |= ACLK_BIT | ADATA_BIT;
40 /* pulse the data line and wait for about 100us */
41 PORTD &= ~ADATA_BIT;
42 _delay_us(20);
43 PORTD |= ADATA_BIT;
44 _delay_us(100);
46 for(i=0; i<8; i++) {
47 /* data line is inverted */
48 if(keycode & 0x80) {
49 PORTD &= ~ADATA_BIT;
50 } else {
51 PORTD |= ADATA_BIT;
52 }
53 keycode <<= 1;
54 _delay_us(20);
55 /* pulse the clock */
56 cli();
57 PORTD &= ~ACLK_BIT;
58 EIFR |= (1 << INTF1);
59 sei();
60 _delay_us(20);
61 PORTD |= ACLK_BIT;
62 _delay_us(20);
63 }
65 /* similarly tristate first, then drop the pullups */
66 DDRD &= ~(ACLK_BIT | ADATA_BIT);
67 PORTD &= ~(ACLK_BIT | ADATA_BIT);
69 /* wait for ack */
70 reset_timer();
71 while(PIND & ADATA_BIT) {
72 if(get_msec() >= TIMEOUT_MSEC) {
73 resync();
74 break;
75 }
76 }
77 }
79 void amikb_reset(void)
80 {
81 cli();
82 PORTD &= ~ARST_BIT;
83 DDRD |= ARST_BIT;
84 _delay_ms(10);
85 PORTD |= ARST_BIT;
86 DDRD &= ~ARST_BIT;
87 sei();
88 }
90 static void resync(void)
91 {
92 PORTD |= ACLK_BIT | ADATA_BIT;
93 printf("lost sync\r\n");
95 for(;;) {
96 cli();
97 DDRD |= ACLK_BIT | ADATA_BIT;
99 PORTD &= ~ACLK_BIT;
100 EIFR |= (1 << INTF1); /* clear interrupt raised by the previous line */
101 sei();
102 _delay_us(20);
103 PORTD |= ACLK_BIT;
105 DDRD &= ~(ACLK_BIT | ADATA_BIT);
107 reset_timer();
108 while(get_msec() < TIMEOUT_MSEC) {
109 if(!(PIND & ADATA_BIT)) {
110 return;
111 }
112 }
113 }
114 }
116 static void handle_cmd(unsigned char cmd)
117 {
118 printf("amikbd got cmd: %x\r\n", (unsigned int)cmd);
119 }
121 ISR(INT1_vect)
122 {
123 static unsigned char value;
124 static int nbits;
126 value <<= 1;
127 if(PIND & ADATA_BIT) {
128 value |= 1;
129 }
130 if(++nbits >= 8) {
131 handle_cmd(value);
132 nbits = 0;
133 value = 0;
134 }
135 }