Use a Sparkfun Blackberry Trackball Breakout Board as a mouse.

Dependencies:   mbed BBTrackball

acceleration.cpp

Committer:
AdamGreen
Date:
2011-12-11
Revision:
0:26bb60735515

File content as of revision 0:26bb60735515:

/* 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;
}