a500kbd
diff 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 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/main.c Thu Oct 12 04:08:48 2017 +0300 1.3 @@ -0,0 +1,120 @@ 1.4 +#define F_CPU XTAL 1.5 +#include <stdio.h> 1.6 +#include <avr/io.h> 1.7 +#include <avr/interrupt.h> 1.8 +#include <util/delay.h> 1.9 +#include <util/parity.h> 1.10 +#include "serial.h" 1.11 + 1.12 +/* pin assignments: 1.13 + * B0 PS/2 data 1.14 + * B1 PS/2 clock 1.15 + * C0 KBD data 1.16 + * C1 KBD clock 1.17 + */ 1.18 + 1.19 +#define BIT_DATA 1 1.20 +#define BIT_CLK 2 1.21 + 1.22 +#define PS2LOW(bit) do { DDRB |= (bit); PORTB &= ~(bit); } while(0) 1.23 +#define PS2HIGH(bit) do { DDRB |= (bit); PORTB |= (bit); } while(0) 1.24 +#define PS2REL(bit) do { DDRB &= ~(bit); PORTB &= ~(bit); } while(0) 1.25 +#define PS2INTR_UNMASK do { PCICR |= (1 << PCIE0); } while(0) 1.26 +#define PS2INTR_MASK do { PCICR &= ~(1 << PCIE0); } while(0) 1.27 + 1.28 +void ps2write(unsigned char c); 1.29 +int ps2read(unsigned char *c); 1.30 + 1.31 + 1.32 +int main(void) 1.33 +{ 1.34 + int led = 1, dir = 1; 1.35 + 1.36 + DDRB = 0; 1.37 + DDRC = 0; 1.38 + PORTB = 0; 1.39 + PORTC = 0; 1.40 + 1.41 + /* initialize the UART and enable interrupts */ 1.42 + init_serial(9600); 1.43 + sei(); 1.44 + 1.45 + printf("PS/2 keyboard controller - John Tsiombikas <nuclear@member.fsf.org>\r\n"); 1.46 + fflush(stdout); 1.47 + 1.48 + for(;;) { 1.49 + printf("hello!\r\n"); 1.50 + fflush(stdout); 1.51 + unsigned char c; 1.52 + 1.53 + ps2write(0xed); 1.54 + ps2read(&c); 1.55 + if(c != 0xfa) { 1.56 + printf("expected ack, got: %xh\r\n", (unsigned int)c); 1.57 + } else { 1.58 + ps2write(led); 1.59 + if(led == 1) dir = 1; 1.60 + if(led == 7) dir = -1; 1.61 + 1.62 + if(dir > 0) { 1.63 + led <<= 1; 1.64 + } else { 1.65 + led >>= 1; 1.66 + } 1.67 + 1.68 + _delay_ms(1000); 1.69 + } 1.70 + } 1.71 + return 0; 1.72 +} 1.73 + 1.74 +void ps2write(unsigned char c) 1.75 +{ 1.76 + int i; 1.77 + unsigned short out = (unsigned short)c | ((unsigned short)(~parity_even_bit(c) & 1) << 8); 1.78 + 1.79 + /* pull clock low for >60us */ 1.80 + PS2LOW(BIT_CLK); 1.81 + _delay_us(60); 1.82 + 1.83 + /* then pull data low and release clock */ 1.84 + PS2LOW(BIT_DATA); 1.85 + PS2REL(BIT_CLK); 1.86 + 1.87 + for(i=0; i<9; i++) { 1.88 + printf("bit %d: wait for clk-low\r\n", i); 1.89 + while(PINB & BIT_CLK); /* wait for kbd to drive the clock low */ 1.90 + PORTB |= out & 1; 1.91 + out >>= 1; 1.92 + printf("bit %d: wait for clk-high\r\n", i); 1.93 + while(!(PINB & BIT_CLK)); /* wait for kbd to drive the clock high */ 1.94 + } 1.95 + 1.96 + PS2REL(BIT_DATA); 1.97 + /* wait for ack */ 1.98 + printf("wait for ack (low)\r\n"); 1.99 + while(PINB & BIT_DATA); 1.100 + printf("wait for ack (high)\r\n"); 1.101 + while(!(PINB & BIT_DATA)); 1.102 +} 1.103 + 1.104 +int ps2read(unsigned char *c) 1.105 +{ 1.106 + int i, p; 1.107 + unsigned short in = 0; 1.108 + 1.109 + /* wait for kbd to drive the clock low for the start bit (blocks here) */ 1.110 + while(PINB & BIT_CLK); 1.111 + while(!(PINB & BIT_CLK)); 1.112 + 1.113 + for(i=0; i<9; i++) { 1.114 + while(PINB & BIT_CLK); /* wait for clock to go low */ 1.115 + in |= (PINB & 1) << i; 1.116 + while(!(PINB & BIT_CLK)); 1.117 + } 1.118 + 1.119 + p = ~parity_even_bit((unsigned char)in); 1.120 + *c = in; 1.121 + 1.122 + return (p == ((in >> 8) & 1)) ? 0 : -1; 1.123 +}