Zo,

Ik dacht dat het wel leuk zou zijn om een keer een toetsenbord aan een schakeling te kunnen hangen, dus ben ik maar eens begonnen aan een eenvoudig stukje code om de data verzonden door een PS/2 keyboard uit te lezen.

De vrij simpele code ziet er als volgt uit:


#define	F_CPU	16000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>

#include "lcd.h"



volatile int8_t		bit_n = 0;
volatile uint8_t	buffer = 0;
volatile uint8_t	received_char = 0;


ISR(INT0_vect)
{
	if(bit_n > 0 && bit_n < 10)	// Ignore start, parity & stop bit
	{
		if(!bit_is_clear(PIND, PD5))
			buffer |= (1 << bit_n - 1);
		received_char = 0;
	} else if(bit_n == 11)
	{
		
		received_char = buffer;
		buffer = 0;
		bit_n = 0;
	}
	
	bit_n++;
	
	MCUCR |= _BV(ISC01);		// Trigger INT0 on falling edge
}


int main()
{
	char	str[10];
	
	cli();
	
	MCUCR |= _BV(ISC01);		// Trigger INT0 on falling edge
	GIMSK |= _BV(INT0);		// Enable INT0 interrupt
	
	sei();
	
	PORTD |= _BV(PD2) | _BV(PD5);		// Enable pullups
	
	lcd_init(LCD_DISP_ON);
	lcd_puts_P("Victory");
	
	while(1)
	{
		if(received_char)
		{
			itoa(received_char, str, 16);
			
			lcd_clrscr();
			lcd_puts(str);
			
			received_char = 0;
		}
	}
	
	return 0;
}

M'n clok input is dus PD2 en m'n data PD5. Op een neergaande flank van de clock ga ik kijken naar de data ingang en als deze 1 is schrijf ik de juiste waarde weg in buffer. Als alle 11 bits zijn gelezen, sluis ik buffer door naar received_char zodat de mainloop er iets mee kan doen en wordt het hele gebeuren gereset.

Enkele essentiele dingen als een keyboard buffer en scancode decoding ontbreken natuurlijk nog maar wat dit dus zou moeten doen is simpelweg de laatst ontvangen scancode op het LCD weergeven in hex.

Nu werkt dit eigenlijk maar half: als ik op een toets druk, verschijnt eerst de code die van de vorige toets ontvangen had moeten worden op het display, en pas als de typematic repeat in werking treedt de juiste code. Bijvoorbeeld: ik druk op de spatiebalk, de scancode op het LCD is netjes 29. Laat ik de spatiebalk los, dan verstuurt het keyboard de sequentie F0,29 als break code. Op het display verschijnt dan slechts de F0 en pas als ik een andere toets indruk komt er eerst nog de 29 en pas als de typematic repeat gaat werken de juiste scancode.

Ik heb al een uur ofzo naar de code zitten kijken maar volgens mij zou het - in al zijn eenvoud - toch echt moeten werken. Wat zie ik over het hoofd?

Alvast bedankt ;)

Komt omdat je maar 1 buffer hebt.
Probeer eens met 1 buffer en 2x received_char. De binnenkomende data stop je altijd in de tweede received_char, zodra je een breakcode binnen ziet komen stop je die in de eerste received_char. Beide schrijf je dan naar je LCD.

Hm, het werkt nog niet echt. Ik heb er maar meteen een echte FIFO-buffer aan toegevoegd, elke keer dat er 1 byte is ontvangen wordt die in de buffer geplaatst en in de mainloop wordt deze buffer gelezen en worden de gelezen scancodes uit de buffer verwijderd.

Helaas nog steeds hetzelfde probleem... het restant van de breakcode wordt pas weergegeven zodra ik op een andere toets druk.

Aan het toetsenbord kan het niet liggen want met een andere code die ik ergens heb gevonden werkt het wel. ;) Alleen is dat een gedrocht dat constant blockt als er niks wordt ontvangen en dat moeten we niet hebben.

---EDIT---

Joepie, het werkt. :P Turns out dat ik buf_n moest initialiseren op 1 ipv. 0 omdat ik altijd buf_n++ doe in de ISR. Daardoor moest ik ook nog buffer |= (1 << bit_n - 1); veranderen in buffer |= (1 << bit_n - 2);, maar nu doet alles het dus.

Nu nog scancode decoding maken, als er interesse is wil ik de uiteindelijke code nog wel een keer posten.

[Bericht gewijzigd door kipmans op (24%)]

Op 30 december 2008 22:00:05 schreef kipmans:

Nu nog scancode decoding maken, als er interesse is wil ik de uiteindelijke code nog wel een keer posten.

Ik ben al wat langer op zoek naar een code om het toetsenbord uit te lezen, ik zou het erg op prijs stellen dat ik die code mag gebruiken.

Ik heb gisteren en vandaag aan een scancoding decoding gewerkt, en dit is het resultaat:

ps2kbd.c ps2kbd.h ps2kbd_test.c

Een aantal dingen ontbreken nog (zie de header file), maar in z'n huidige vorm kun je er prima tekst mee op een LCD'tje tikken. In gecompileerde toestand is de code (met de huidige, incomplete, lookup tables) iets meer dan 1 kB. Ik heb nog niet echt gekeken of daar nog wat significants van af te schaven is.

Ik denk dat ik de meeste ontbrekende dingen behalve PRINT SCRN/SYSRQ en PAUSE/BREAK te zijner tijd nog wel ga implementeren.