AT keyboard - sometimes loosing track of 11 bits

Discussion of issues related specifically to writing code for native mode devices. This includes ZBasic code as well as assembly language code and C code, both inline and standalone.
Post Reply
ndudman
Posts: 79
Joined: 25 December 2008, 14:00 PM

AT keyboard - sometimes loosing track of 11 bits

Post 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.
Attachments
keyboardtest.tar.gz
(19.43 KiB) Downloaded 3071 times
ndudman
Posts: 79
Joined: 25 December 2008, 14:00 PM

Post 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 &#40;bitCount = bitnextCount  AND bitCount <> 0&#41; then 
				call reset_kb_bitcount&#40;&#41;
				Debug.print "ERR"
			else 
				Debug.print "OK"
			end if	
		call delay&#40;1.0&#41;
	loop	
end sub
And also a little function to reset the counter in keyboard.c

Code: Select all

void reset_kb_bitcount&#40;void&#41; &#123;
	_kb_bitcount = 0;
&#125;
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
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Re: AT keyboard - sometimes loosing track of 11 bits

Post 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&#40;&#41;
  Do
    Call WaitForInterrupt&#40;zxPinFallingEdge, WaitInt0&#41;
    Atomic
      Call callInt&#40;&#41;
    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.
- Don Kinzer
ndudman
Posts: 79
Joined: 25 December 2008, 14:00 PM

Post 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=&#40;EICRA&0xFC&#41;|&#40;0x02<<ISC00&#41;;		// Set falling edge
EIMSK=&#40;EIMSK&0xBF&#41;|&#40;0x01<<INT0&#41;;		// Enable interrupt
Ive gone about this the long way... reinventing the wheel... but have learnt much about how it works...thanks the help

Neil
ndudman
Posts: 79
Joined: 25 December 2008, 14:00 PM

Post 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&#40;_kb_buf_count&#40;&#41;==0&#41; &#123;
		//~ ~ zf_myprint3&#40;_kb_buf_count&#40;&#41;&#41;;
		zf_myDelay&#40;&#41;;
	&#125;
The origional line was

Code: Select all

while&#40;_kb_buf_count&#40;&#41;==0&#41; ;
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
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post 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&#40;_kb_buf_count&#40;&#41;==0&#41;
&#123;
  _delay_ms&#40;10&#41;;  // a 10 mS delay
&#125;
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.
Attachments
AVR_util.zip
(16.64 KiB) Downloaded 3015 times
- Don Kinzer
ndudman
Posts: 79
Joined: 25 December 2008, 14:00 PM

Post 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
ndudman
Posts: 79
Joined: 25 December 2008, 14:00 PM

Post 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.

Code: Select all

ISR&#40;INT0_vect&#41; &#123;
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
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post 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.
- Don Kinzer
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post 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.
Attachments
PS2_Connection.jpg
PS2_Connection.jpg (34.33 KiB) Viewed 10498 times
- Don Kinzer
Post Reply