a500kbd
annotate src/main.c @ 0:8e8e17a0f88e
initial commit: serial comms up, kbd doesn't respond
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 12 Oct 2017 04:08:48 +0300 |
parents | |
children | 3228a731d4db |
rev | line source |
---|---|
nuclear@0 | 1 #define F_CPU XTAL |
nuclear@0 | 2 #include <stdio.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 <util/parity.h> |
nuclear@0 | 7 #include "serial.h" |
nuclear@0 | 8 |
nuclear@0 | 9 /* pin assignments: |
nuclear@0 | 10 * B0 PS/2 data |
nuclear@0 | 11 * B1 PS/2 clock |
nuclear@0 | 12 * C0 KBD data |
nuclear@0 | 13 * C1 KBD clock |
nuclear@0 | 14 */ |
nuclear@0 | 15 |
nuclear@0 | 16 #define BIT_DATA 1 |
nuclear@0 | 17 #define BIT_CLK 2 |
nuclear@0 | 18 |
nuclear@0 | 19 #define PS2LOW(bit) do { DDRB |= (bit); PORTB &= ~(bit); } while(0) |
nuclear@0 | 20 #define PS2HIGH(bit) do { DDRB |= (bit); PORTB |= (bit); } while(0) |
nuclear@0 | 21 #define PS2REL(bit) do { DDRB &= ~(bit); PORTB &= ~(bit); } while(0) |
nuclear@0 | 22 #define PS2INTR_UNMASK do { PCICR |= (1 << PCIE0); } while(0) |
nuclear@0 | 23 #define PS2INTR_MASK do { PCICR &= ~(1 << PCIE0); } while(0) |
nuclear@0 | 24 |
nuclear@0 | 25 void ps2write(unsigned char c); |
nuclear@0 | 26 int ps2read(unsigned char *c); |
nuclear@0 | 27 |
nuclear@0 | 28 |
nuclear@0 | 29 int main(void) |
nuclear@0 | 30 { |
nuclear@0 | 31 int led = 1, dir = 1; |
nuclear@0 | 32 |
nuclear@0 | 33 DDRB = 0; |
nuclear@0 | 34 DDRC = 0; |
nuclear@0 | 35 PORTB = 0; |
nuclear@0 | 36 PORTC = 0; |
nuclear@0 | 37 |
nuclear@0 | 38 /* initialize the UART and enable interrupts */ |
nuclear@0 | 39 init_serial(9600); |
nuclear@0 | 40 sei(); |
nuclear@0 | 41 |
nuclear@0 | 42 printf("PS/2 keyboard controller - John Tsiombikas <nuclear@member.fsf.org>\r\n"); |
nuclear@0 | 43 fflush(stdout); |
nuclear@0 | 44 |
nuclear@0 | 45 for(;;) { |
nuclear@0 | 46 printf("hello!\r\n"); |
nuclear@0 | 47 fflush(stdout); |
nuclear@0 | 48 unsigned char c; |
nuclear@0 | 49 |
nuclear@0 | 50 ps2write(0xed); |
nuclear@0 | 51 ps2read(&c); |
nuclear@0 | 52 if(c != 0xfa) { |
nuclear@0 | 53 printf("expected ack, got: %xh\r\n", (unsigned int)c); |
nuclear@0 | 54 } else { |
nuclear@0 | 55 ps2write(led); |
nuclear@0 | 56 if(led == 1) dir = 1; |
nuclear@0 | 57 if(led == 7) dir = -1; |
nuclear@0 | 58 |
nuclear@0 | 59 if(dir > 0) { |
nuclear@0 | 60 led <<= 1; |
nuclear@0 | 61 } else { |
nuclear@0 | 62 led >>= 1; |
nuclear@0 | 63 } |
nuclear@0 | 64 |
nuclear@0 | 65 _delay_ms(1000); |
nuclear@0 | 66 } |
nuclear@0 | 67 } |
nuclear@0 | 68 return 0; |
nuclear@0 | 69 } |
nuclear@0 | 70 |
nuclear@0 | 71 void ps2write(unsigned char c) |
nuclear@0 | 72 { |
nuclear@0 | 73 int i; |
nuclear@0 | 74 unsigned short out = (unsigned short)c | ((unsigned short)(~parity_even_bit(c) & 1) << 8); |
nuclear@0 | 75 |
nuclear@0 | 76 /* pull clock low for >60us */ |
nuclear@0 | 77 PS2LOW(BIT_CLK); |
nuclear@0 | 78 _delay_us(60); |
nuclear@0 | 79 |
nuclear@0 | 80 /* then pull data low and release clock */ |
nuclear@0 | 81 PS2LOW(BIT_DATA); |
nuclear@0 | 82 PS2REL(BIT_CLK); |
nuclear@0 | 83 |
nuclear@0 | 84 for(i=0; i<9; i++) { |
nuclear@0 | 85 printf("bit %d: wait for clk-low\r\n", i); |
nuclear@0 | 86 while(PINB & BIT_CLK); /* wait for kbd to drive the clock low */ |
nuclear@0 | 87 PORTB |= out & 1; |
nuclear@0 | 88 out >>= 1; |
nuclear@0 | 89 printf("bit %d: wait for clk-high\r\n", i); |
nuclear@0 | 90 while(!(PINB & BIT_CLK)); /* wait for kbd to drive the clock high */ |
nuclear@0 | 91 } |
nuclear@0 | 92 |
nuclear@0 | 93 PS2REL(BIT_DATA); |
nuclear@0 | 94 /* wait for ack */ |
nuclear@0 | 95 printf("wait for ack (low)\r\n"); |
nuclear@0 | 96 while(PINB & BIT_DATA); |
nuclear@0 | 97 printf("wait for ack (high)\r\n"); |
nuclear@0 | 98 while(!(PINB & BIT_DATA)); |
nuclear@0 | 99 } |
nuclear@0 | 100 |
nuclear@0 | 101 int ps2read(unsigned char *c) |
nuclear@0 | 102 { |
nuclear@0 | 103 int i, p; |
nuclear@0 | 104 unsigned short in = 0; |
nuclear@0 | 105 |
nuclear@0 | 106 /* wait for kbd to drive the clock low for the start bit (blocks here) */ |
nuclear@0 | 107 while(PINB & BIT_CLK); |
nuclear@0 | 108 while(!(PINB & BIT_CLK)); |
nuclear@0 | 109 |
nuclear@0 | 110 for(i=0; i<9; i++) { |
nuclear@0 | 111 while(PINB & BIT_CLK); /* wait for clock to go low */ |
nuclear@0 | 112 in |= (PINB & 1) << i; |
nuclear@0 | 113 while(!(PINB & BIT_CLK)); |
nuclear@0 | 114 } |
nuclear@0 | 115 |
nuclear@0 | 116 p = ~parity_even_bit((unsigned char)in); |
nuclear@0 | 117 *c = in; |
nuclear@0 | 118 |
nuclear@0 | 119 return (p == ((in >> 8) & 1)) ? 0 : -1; |
nuclear@0 | 120 } |