Blackberry's Pearl controlled with ARM7

I found really interesting a small protoboard created by Sparkfun that allows you to easily connect a Pearl (the one made famous by RIM / Blackberry devices) with a microcontroller. This time I choose the LPC2138 from NXP because I also have a complete 2D graphic engine for interfacing the LPC2138 with a Nokia 128×128 LCD with 16 bits per pixel. One issue with this device is that a small movement on the pearl is detected. And sometimes you want to move in a direction but this little ball moves in more than one direction at a time. So the big problem was designing a software able to detect the movements correctly, providing anti bouncing and a way to easily modify how many pulses of the pearl are detected as one movement.



void pearl_Task() {
    if ((!(PEARL_INPUT_PIN & (1 << PEARL_LEFT_PIN))) && (pearl_state_left == 0)) {
        pearl_dir_left_changes++;
        pearl_state_left = 1;
    }
    else if (((PEARL_INPUT_PIN & (1 << PEARL_LEFT_PIN)))
                  && (pearl_state_left == 1)) {
        pearl_dir_left_changes++;
        pearl_state_left = 0;
    }
    if ((!(PEARL_INPUT_PIN & (1 << PEARL_RIGHT_PIN))) && (pearl_state_right == 0)) {
        pearl_dir_right_changes++;
        pearl_state_right = 1;
    }
    else if (((PEARL_INPUT_PIN & (1 << PEARL_RIGHT_PIN)))
                  && (pearl_state_right == 1)) {
        pearl_dir_right_changes++;
        pearl_state_right = 0;
    }
    if ((!(PEARL_INPUT_PIN & (1 << PEARL_DOWN_PIN))) && (pearl_state_down == 0)) {
        pearl_dir_down_changes++;
        pearl_state_down = 1;
    }
    else if (((PEARL_INPUT_PIN & (1 << PEARL_DOWN_PIN)))
                  && (pearl_state_down == 1)) {
        pearl_dir_down_changes++;
        pearl_state_down = 0;
    }
    if ((!(PEARL_INPUT_PIN & (1 << PEARL_UP_PIN))) && (pearl_state_up == 0)) {
        pearl_dir_up_changes++;
        pearl_state_up = 1;
    }
    else if (((PEARL_INPUT_PIN & (1 << PEARL_UP_PIN)))
                  && (pearl_state_up == 1)) {
        pearl_dir_up_changes++;
        pearl_state_up = 0;
    }
}


This task can be perform in a main loop, or can be called by a timer when it overflows (as I do in my code). The following piece of code is an example of how to ask if a movement in a particular direction was performed.



unsigned char pearl_IsMovingLeft() {
	if (pearl_dir_left_changes >= PEARL_DIR_LEFT_LIMIT) {
		pearl_dir_left_changes = 0;
		return 1;
	}
	return 0;
}


Where if PEARL_DIR_LEFT_LIMIT is between 3 or 5 and you run the pearl task every 50mSec the movement is quite smooth.

Pearl (Blackberry’s Trackball) Driver [Header]

Pearl (Blackberry’s Trackball) Driver [Source]

Trackball schematic