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 }