a500kbd

view src/amigakb.c @ 2:a4fd9c5a6655

first working version
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 17 Oct 2017 15:25:33 +0300
parents
children 31a1f0b53d98
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;
18 /* keycode bit transfer order: 6 5 4 3 2 1 0 7 (7 is pressed flag) */
19 keycode = (keycode << 1) | (~press & 1);
20 if(keycode == prev_keycode) return;
21 prev_keycode = keycode;
23 /* make sure we don't pulse the lines while grabbing control
24 * by first reinstating the pullups before changing direction
25 */
26 PORTD |= ACLK_BIT | ADATA_BIT;
27 DDRD |= ACLK_BIT | ADATA_BIT;
29 /* pulse the data line and wait for about 100us */
30 PORTD &= ~ADATA_BIT;
31 _delay_us(20);
32 PORTD |= ADATA_BIT;
33 _delay_us(100);
35 for(i=0; i<8; i++) {
36 /* data line is inverted */
37 if(keycode & 0x80) {
38 PORTD &= ~ADATA_BIT;
39 } else {
40 PORTD |= ADATA_BIT;
41 }
42 keycode <<= 1;
43 _delay_us(20);
44 /* pulse the clock */
45 cli();
46 PORTD &= ~ACLK_BIT;
47 EIFR |= (1 << INTF1);
48 sei();
49 _delay_us(20);
50 PORTD |= ACLK_BIT;
51 _delay_us(20);
52 }
54 /* similarly tristate first, then drop the pullups */
55 DDRD &= ~(ACLK_BIT | ADATA_BIT);
56 PORTD &= ~(ACLK_BIT | ADATA_BIT);
58 /* wait for ack */
59 reset_timer();
60 while(PIND & ADATA_BIT) {
61 if(get_msec() >= TIMEOUT_MSEC) {
62 resync();
63 break;
64 }
65 }
66 }
68 void amikb_reset(void)
69 {
70 cli();
71 PORTD &= ~ARST_BIT;
72 DDRD |= ARST_BIT;
73 _delay_ms(10);
74 PORTD |= ARST_BIT;
75 DDRD &= ~ARST_BIT;
76 sei();
77 }
79 static void resync(void)
80 {
81 PORTD |= ACLK_BIT | ADATA_BIT;
82 printf("lost sync\r\n");
84 for(;;) {
85 cli();
86 DDRD |= ACLK_BIT | ADATA_BIT;
88 PORTD &= ~ACLK_BIT;
89 EIFR |= (1 << INTF1); /* clear interrupt raised by the previous line */
90 sei();
91 _delay_us(20);
92 PORTD |= ACLK_BIT;
94 DDRD &= ~(ACLK_BIT | ADATA_BIT);
96 reset_timer();
97 while(get_msec() < TIMEOUT_MSEC) {
98 if(!(PIND & ADATA_BIT)) {
99 return;
100 }
101 }
102 }
103 }
105 static void handle_cmd(unsigned char cmd)
106 {
107 printf("amikbd got cmd: %x\r\n", (unsigned int)cmd);
108 }
110 ISR(INT1_vect)
111 {
112 static unsigned char value;
113 static int nbits;
115 value <<= 1;
116 if(PIND & ADATA_BIT) {
117 value |= 1;
118 }
119 if(++nbits >= 8) {
120 handle_cmd(value);
121 nbits = 0;
122 value = 0;
123 }
124 }