Use a Sparkfun Blackberry Trackball Breakout Board as a mouse.

Dependencies:   mbed BBTrackball

Revision:
0:26bb60735515
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/acceleration.cpp	Sun Dec 11 05:38:54 2011 +0000
@@ -0,0 +1,141 @@
+/* Copyright 2011 Adam Green (http://mbed.org/users/AdamGreen/)
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+/* Implementation of classes to apply acceleration to input from
+   Sparkfun's Blackberry Trackball Breakout board.
+*/
+#include <mbed.h>
+#include "acceleration.h"
+
+#define ARRAYSIZE(X) (sizeof(X)/sizeof(X[0]))
+
+
+template<size_t SampleCount,
+         int    DecelerateThreshold,
+         int    AccelerateThreshold,
+         int    MaxAcceleration>
+unsigned char CAcceleratedRoller<SampleCount,
+                                 DecelerateThreshold,
+                                 AccelerateThreshold,
+                                 MaxAcceleration>::ClampToUChar(short Value)
+{
+    if (Value < 0)
+    {
+        Value = 0;
+    }
+    else if (Value > 0xFF)
+    {
+        Value = 0xFF;
+    }
+    
+    return Value;
+}
+
+
+template<size_t SampleCount,
+         int    DecelerateThreshold,
+         int    AccelerateThreshold,
+         int    MaxAcceleration>
+void CAcceleratedRoller<SampleCount,
+                        DecelerateThreshold,
+                        AccelerateThreshold,
+                        MaxAcceleration>::AccumulateSample(short CurrVelocity)
+{
+    unsigned char ClampedVelocity = ClampToUChar(CurrVelocity);
+    
+    // Calculate a running sum over the last SampleCount velocity samples.
+    m_VelocitySum -= m_Samples[m_SampleIndex];
+    m_VelocitySum += ClampedVelocity;
+    m_Samples[m_SampleIndex] = ClampedVelocity;
+    
+    m_SampleIndex++;
+    if (m_SampleIndex >= SampleCount)
+    {
+        m_SampleIndex = 0;
+    }
+    
+    // As we see a sustained high velocity, increase acceleration and decrease
+    // as the user slows down the velocity.
+    if (m_VelocitySum > AccelerateThreshold && m_Acceleration < MaxAcceleration)
+    {
+        m_Acceleration++;
+    }
+    if (m_VelocitySum < DecelerateThreshold && m_Acceleration > 1)
+    {
+        m_Acceleration--;
+    }
+}
+
+
+
+void CAcceleratedTrackball::UpdateLEDColourBasedOnMotion(int VelocityX, 
+                                                         int VelocityY, 
+                                                         int ButtonPressed)
+{
+    static const CBBTrackball::SColour  RedColour =   {255,   0,   0, 0};
+    static const CBBTrackball::SColour  GreenColour = {  0, 255,   0, 0};
+    static const CBBTrackball::SColour  BlueColour =  {  0,   0, 255, 0};
+    
+    // If the trackball is being moved then make it green, otherwise leave it
+    // red.
+    if (VelocityX || VelocityY)
+    {
+        m_IterationsSinceLastMotion = 0;
+        SetColour(&GreenColour);
+    }
+    else
+    {
+        if (m_IterationsSinceLastMotion > 250)
+        {
+            SetColour(&RedColour);
+        }
+        else
+        {
+            m_IterationsSinceLastMotion++;
+        }
+    }
+    
+    // Switch the button to blue when the button is pressed.
+    if (ButtonPressed)
+    {
+        SetColour(&BlueColour);
+    }
+}                                                  
+
+
+void CAcceleratedTrackball::GetState(int& DeltaX, int& DeltaY, int& ButtonPressed)
+{
+    CBBTrackball::SState    TrackballState;
+    short                   VelocityX;
+    short                   VelocityY;                  
+    
+    CBBTrackball::GetState(&TrackballState);
+
+    m_UpAcceleration.AccumulateSample(TrackballState.Up);
+    m_DownAcceleration.AccumulateSample(TrackballState.Down);
+    m_LeftAcceleration.AccumulateSample(TrackballState.Left);
+    m_RightAcceleration.AccumulateSample(TrackballState.Right);
+            
+    // NOTE: The breakout board is rotated 90 degrees on my breadboard.
+    VelocityX = TrackballState.Up * m_UpAcceleration.Acceleration() - 
+                TrackballState.Down * m_DownAcceleration.Acceleration();
+    VelocityY = TrackballState.Right * m_RightAcceleration.Acceleration() - 
+                TrackballState.Left * m_LeftAcceleration.Acceleration();
+
+    UpdateLEDColourBasedOnMotion(VelocityX, VelocityY, TrackballState.ButtonPressed);
+    
+    DeltaX = VelocityX;
+    DeltaY = VelocityY;
+    ButtonPressed = TrackballState.ButtonPressed;
+}