Page 1 of 1
AT keyboard - sometimes loosing track of 11 bits
Posted: 17 January 2009, 7:24 AM
by ndudman
Hi
Ive included a simple broken down part of my project which has an AT serial keyboard connected via INT0 and a data line... the key presses chars are Debug.printed out along with the current bitcounter 0-11...
The problem I have, if keys get pressed really quickly or perhaps uP doing something else... is that the get_kb_bitcount() starts to show that the c code in keyboard.c has lost count (miss-counted) the 1-11 interrupts per key press... once it has lots count then the char codes returned make no sense.
I have to admit and say I dont understand exactly how everything works as the code isnt all mine, although Ive spent a while going through, but I thought of adding some recovery code, perhaps some timer that if a key isnt pressed for a while that we just make sure that the bitcount is 0 and if not ensure its reset.
Im just not sure quite how to do that with the timer interrupts, or if this is the best way... Also wanted to share something in case its useful to others or they can improve and help
Thanks
Neil
ps Perhaps its overkill to have a whole AT PC keyboard connected, but old ones seemed cheap, used only two ports and more or less unlimited amount of keys... and except for the sometimes loosing track seems to work well.
Posted: 17 January 2009, 8:14 AM
by ndudman
Hi
Perhaps it was easier then I thought ?
I added
Code: Select all
dim gaurdCounterStack(1 to 60) as Byte
along with a new task in the Main()
Code: Select all
callTask gaurdCounter(), gaurdCounterStack
and the sub also
Code: Select all
'~ ------------------------------------------------------
'~ Anther task which checks if a non 0 value of the counter
'~ remains for a certain period... indicating that then
'~ keyboard is confused and counter should be reset to 0
'~ ------------------------------------------------------
Declare sub reset_kb_bitcount()
sub gaurdCounter() Attribute(used)
do
Dim bitCount as Byte
Dim bitnextCount as Byte
bitCount = get_kb_bitcount()
Call SetInterval(1.0)
call WaitForInterval(0)
bitnextCount = get_kb_bitcount()
if (bitCount = bitnextCount AND bitCount <> 0) then
call reset_kb_bitcount()
Debug.print "ERR"
else
Debug.print "OK"
end if
call delay(1.0)
loop
end sub
And also a little function to reset the counter in keyboard.c
Code: Select all
void reset_kb_bitcount(void) {
_kb_bitcount = 0;
}
Not sure if I have the timing right... but it seems to work. I really like this development enviroment
and am enjoying myself
Thanks
Neil
Re: AT keyboard - sometimes loosing track of 11 bits
Posted: 17 January 2009, 8:22 AM
by dkinzer
ndudman wrote:except for the sometimes loosing track seems to work well.
I believe that the problem is in
int0Task(). The issue is that the subroutine
callInt() really needs to run to completion every time it is called and, as written, it is not protected from a task switch or an interrupt. If either of these occurs,
callInt will probably miss bits.
The problem can be at least partially fixed by modifying
int0Task() as shown below.
Code: Select all
Sub int0Task()
Do
Call WaitForInterrupt(zxPinFallingEdge, WaitInt0)
Atomic
Call callInt()
End Atomic
Loop
End Sub
Of course, the best way to correct the problem is to have the code in
callInt() be run as an ISR. The original C code was intended to run that way.
Posted: 17 January 2009, 14:22 PM
by ndudman
Thanks Don
So i went back to the origional c code and changed it back to use ISR directly
and enabled the interrupts with the following, this time reading the Atmega datasheet made more sense then the other times.
Code: Select all
EICRA=(EICRA&0xFC)|(0x02<<ISC00); // Set falling edge
EIMSK=(EIMSK&0xBF)|(0x01<<INT0); // Enable interrupt
Ive gone about this the long way... reinventing the wheel... but have learnt much about how it works...thanks the help
Neil
Posted: 17 January 2009, 14:30 PM
by ndudman
So Ive much simplified the code... after Id compilated it... but one problem remains
At the keyboard.c _kb_buf_get(void)
I had to add a little delay here, didnt know how to do it except call a zbasic sub.
Code: Select all
while(_kb_buf_count()==0) {
//~ ~ zf_myprint3(_kb_buf_count());
zf_myDelay();
}
The origional line was
Code: Select all
while(_kb_buf_count()==0) ;
Which I didnt understand why it wouldnt work, my guess was that it need to yeild or something so that the value could actually change perhaps ? Only a crude guess.
Any pointers ?
Thanks
Neil
Posted: 17 January 2009, 15:04 PM
by dkinzer
ndudman wrote:I had to add a little delay here, didnt know how to do it except call a zbasic sub.
The WinAVR include files provide a way to invoke approximate millisecond and microsecond delays but are limited to compile-time constant delays. I see now that I should have included these files among the avr-gcc that are installed with ZBasic. You can add them to your installation by extracting the contents of the attached .zip file (preserving pathnames) to the WinAVR/avr/include subdirectory of the ZBasic installation directory. When you're done you should have a file
<ZBasic install directory>/WinAvr/avr/include/util/delay.h.
Once that file is present, you can use the delay functions in C code by adding the two lines below near the top of your .c file.
Code: Select all
#define F_CPU 14745600UL
#include <util/delay.h>
Then, wherever you need a fixed delay, you can realize it as shown below.
Code: Select all
while(_kb_buf_count()==0)
{
_delay_ms(10); // a 10 mS delay
}
This issue also revealed that the generated build commands should include the definition of F_CPU so that it doesn't have to be added manually as above.
Posted: 17 January 2009, 17:51 PM
by ndudman
Don
I applied the zip file and made the changes to my c file... however it dosnt work... only with the zf_myDelay(); can I press and see key presses... Im confused...
Neil
Posted: 17 January 2009, 18:03 PM
by ndudman
Don
Back to the origional problem I had of loosing track of the bit count(1-11 or so interrupts per keypress)... Im now using the following kind of definition within the keyboard.c file.
I understand that INT0 cant be interrupted by anything else ? so if its loosing track of the count, which it still is (much better though)... where could I have a look ?
Thanks
Neil
Posted: 17 January 2009, 19:00 PM
by dkinzer
ndudman wrote:I applied the zip file and made the changes to my c file... however it dosnt work...
Do you mean that it doesn't compile or that it doesn't receive characters properly? If the latter, I'm afraid that I can't be of much help because I don't know why a delay might be needed.
Posted: 17 January 2009, 19:21 PM
by dkinzer
ndudman wrote:so if its loosing track of the count, which it still is (much better though)... where could I have a look ?
How are you connecting the PS/2 keyboard signals to the ZX? The circuit diagram in the attached image shows how it should be done. The pullup resistors are essential but the value is not critical; anything in the 1K to 10K range should be fine. It is also essential that the ground of the PS/2 connector be connected to the same ground as the ZX.