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 +}