VirtualUsbKeyboard Arrow Keys for Atari Emulator (Stella)

I'm using the VirtualUsbKeyboard example code and I have only made a slight modification to the code. My goal is to use the Arrow Keys and the space bar to map in an old Atari joystick with a Atari emulator on a PC.

So far so good. The sketch works. The PC recognizes the HID keyboard. I wired in the joystick. Everything seems to be working.

Here is the problem:

When I bring up a game like Adventure when I move in a direction the motion is not smooth. I get a burst of movement then it stops, then bursts and stops.

If I use the regular arrow keys the motion is nice and smooth.

My thoughts are that I was clobbering the buffer with too many keystrokes but I've even tried only sending out a key

UsbKeyboard.sendKeyStroke();

once every 30ms. The behavior seems to be the same.

I'm at my limit of understanding USB HID behavior so I was hoping a great mind out there can help....

Other background: I'm using the ATmega168PV-10PU with ADAboot and a 12MHz Crystal on a protoboard.

Here is the code:

/**
* VirtualUsbKeyboard MODIFIED
*
* Enumerates itself as a HID (Human Interface Device) to a host
* computer using a USB shield. The Arduino then appears to the host to
* be a USB keyboard and keypress events can be sent on demand.
*
* This example watches the state of 6 push buttons and when a button
* is pressed it sends a matching keypress event to the host.
*
* Copyright 2009 Jonathan Oxer <jon@oxer.com.au>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. http://www.gnu.org/licenses/
*
* www.practicalarduino.com/projects/easy/virtual-usb-keyboard
*/

// Requires the use of the "UsbKeyboard" library available from
// http://code.rancidbacon.com/ProjectLogArduinoUSB
#include "UsbKeyboard.h"

// Define the inputs to use for buttons
#define BUTTON_FIRE 6
#define BUTTON_UP 7
#define BUTTON_DOWN 8
#define BUTTON_LEFT 9
#define BUTTON_RIGHT 10

int i = 0;

/**
* Configure button inputs and set up the USB connection to the host
*/
void setup()
{
 
  // Set the button pins to inputs
  pinMode (BUTTON_FIRE, INPUT);
  pinMode (BUTTON_UP, INPUT);
  pinMode (BUTTON_DOWN, INPUT);
  pinMode (BUTTON_LEFT, INPUT);
  pinMode (BUTTON_RIGHT, INPUT);
 
  // Enable the CPU's internal 20k pull-up resistors on the button
  // inputs so they default to a "high" state
  digitalWrite (BUTTON_FIRE, HIGH);
  digitalWrite (BUTTON_UP, HIGH);
  digitalWrite (BUTTON_DOWN, HIGH);
  digitalWrite (BUTTON_LEFT, HIGH);
  digitalWrite (BUTTON_RIGHT, HIGH);
 
  // Disable timer0 since it can mess with the USB timing. Note that
  // this means some functions such as delay() will no longer work.
  TIMSK0&=!(1<<TOIE0);

  // Clear interrupts while performing time-critical operations
  cli();

  // Force re-enumeration so the host will detect us
  usbDeviceDisconnect();
  delayMs(250);
  usbDeviceConnect();

  // Set interrupts again
  sei();
}


/**
* Main program loop. Scan for keypresses and send a matching keypress
* event to the host
* FIXME: currently repeats as fast as it can. Add transition detection
*/
void loop()
{

  UsbKeyboard.update();

  if (digitalRead(BUTTON_FIRE) == LOW) {
    UsbKeyboard.sendKeyStroke(KEY_SPACE);
   }

  if (digitalRead(BUTTON_UP) == LOW) {
    UsbKeyboard.sendKeyStroke(0x52);
  }

  if (digitalRead(BUTTON_DOWN) == LOW) {
    UsbKeyboard.sendKeyStroke(0x51);
  }

  if (digitalRead(BUTTON_LEFT) == LOW) {
    UsbKeyboard.sendKeyStroke(0x50);
   }

  if (digitalRead(BUTTON_RIGHT) == LOW) {
    UsbKeyboard.sendKeyStroke(0x4F);
   }

}


/**
* Define our own delay function so that we don't have to rely on
* operation of timer0, the interrupt used by the internal delay()
*/
void delayMs(unsigned int ms)
{
  for (int i = 0; i < ms; i++) {
    delayMicroseconds(1000);
  }
}