Interface to access to Avago ADNS-9500 laser mouse sensors.

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
aplatanado
Date:
Fri Feb 10 21:35:22 2012 +0000
Child:
1:fa3052be61b5
Commit message:
First library version. Not tested.

Changed in this revision

ADNS9500.cpp Show annotated file Show diff for this revision Revisions of this file
ADNS9500.hpp Show annotated file Show diff for this revision Revisions of this file
mbed.lib Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ADNS9500.cpp	Fri Feb 10 21:35:22 2012 +0000
@@ -0,0 +1,485 @@
+/*
+ * ADNS9500.hpp - Interface to access to Avago ADNS-9500 laser mouse sensors
+ *
+ *   Copyright 2012 Jesus Torres <jmtorres@ull.es>
+ *
+ * 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.
+ */
+
+#include <fstream>
+#include <math.h>
+#include <mbed.h>
+#include <string>
+
+#include <ADNS9500.hpp>
+
+#define WAIT_TSRAD()        wait_us(100)
+#define WAIT_TSRWR()        wait_us(20)
+#define WAIT_TBEXIT()       wait_us(1)      // 500ns
+#define WAIT_TNCSSCLK()     wait_us(1)      // 120ns
+#define WAIT_TSCLKNCS()     wait_us(20)
+#define WAIT_TLOAD()        wait_us(15)
+
+#define DEFAULT_MAX_FPS             1958
+#define DEFAULT_MAX_FRAME_PERIOD    ceil(1.0e6 / DEFAULT_MAX_FPS)   // in us
+#define DEFAULT_X_CPI               1620
+#define DEFAULT_Y_CPI               1620
+#define CPI_CHANGE_UNIT             90
+
+#define SET_BIT(word, mask)         (word | mask)
+#define CLEAR_BIT(word, mask)       (word & (~mask))
+
+namespace adns9500 {
+
+    ADNS9500::ADNS9500(PinName mosi, PinName miso, PinName sclk, PinName ncs,
+        int spi_frequency, PinName motion)
+        : spi_(mosi, miso, sclk),
+          motion_(motion),
+          ncs_(ncs),
+          enabled_(false),
+          dx_(0), dy_(0),
+          xCpi_(DEFAULT_X_CPI), yCpi_(DEFAULT_Y_CPI)
+    {
+        motion_.fall(this, &ADNS9500::motionTrigger);
+    }
+
+    ADNS9500::~ADNS9500()
+    {
+        shutdown();
+    }
+
+    void ADNS9500::reset(const char* firmware)
+    {
+        // SPI port reset
+        ncs_.write(1);
+        WAIT_TNCSSCLK();
+        ncs_.write(0);
+        WAIT_TNCSSCLK();
+        
+        // send 0x3a to POWER_UP_RESET and wait for at least 50ms
+        spi_.write(POWER_UP_RESET);
+        WAIT_TSRAD();
+        spi_.write(0x5a);
+        wait_ms(50);
+        
+        // clear observation register. Only required to deassert shutdown mode.
+        spi_.write(OBSERVATION);
+        WAIT_TSRAD();
+        spi_.write(0x00);
+        wait_us(DEFAULT_MAX_FRAME_PERIOD);
+        
+        // check observation register bits [5:0]
+        spi_.write(OBSERVATION);
+        WAIT_TSRAD();
+        int observation = spi_.write(0x00);
+        WAIT_TSRAD();
+
+        if (! ADNS9500_IF_OBSERVATION_TEST(observation))
+            error("ADNS9500::reset : observation register test failed: 0x%x\n", observation);
+
+        // read motion data
+        spi_.write(MOTION);
+        WAIT_TSRAD();
+        spi_.write(DELTA_X_L);
+        WAIT_TSRAD();
+        spi_.write(DELTA_X_H);
+        WAIT_TSRAD();
+        spi_.write(DELTA_Y_L);
+        WAIT_TSRAD();
+        spi_.write(DELTA_Y_H);
+        WAIT_TSRAD();
+        
+        // read product and revision id to test the connection        
+        spi_.write(PRODUCT_ID);
+        WAIT_TSRAD();
+        int product_id = spi_.write(REVISION_ID);
+        WAIT_TSRAD();
+        int revision_id = spi_.write(0x00);
+        WAIT_TSCLKNCS();
+
+        ncs_.write(1);
+
+        if (product_id != 0x33) {
+            error("ADNS9500::reset : bad product ID: 0x%x\n", product_id);
+        }
+
+        if (revision_id != 0x03) {
+            error("ADNS9500::reset : bad revision ID: 0x%x\n", revision_id);
+        }
+
+        enabled_ = true;
+
+        if (firmware) {
+            sromDownload(firmware);
+            enableLaser();
+        }
+    }
+
+    void ADNS9500::shutdown()
+    {
+        if (! enabled_)
+            error("ADNS9500::shutdown : the sensor is not enabled\n");
+        
+        ncs_.write(0);
+        WAIT_TNCSSCLK();
+        
+        // send 0x3a to POWER_UP_RESET
+        spi_.write(POWER_UP_RESET);
+        WAIT_TSRAD();
+        spi_.write(0x5a);
+        WAIT_TSCLKNCS();
+        
+        ncs_.write(1);
+        
+        enabled_ = false;
+    }
+
+    int ADNS9500::read(Register lregister)
+    {
+        if (! enabled_)
+            error("ADNS9500::read : the sensor is not enabled\n");
+    
+        ncs_.write(0);
+        WAIT_TNCSSCLK();
+        
+        // send the command to read the register
+        spi_.write(lregister);
+        WAIT_TSRAD();
+        int value = spi_.write(0x00);
+        WAIT_TSCLKNCS();
+        
+        ncs_.write(1);
+        return value;
+    }
+
+    int ADNS9500::read(Register uregister, Register lregister)
+    {
+        if (! enabled_)
+            error("ADNS9500::read : the sensor is not enabled\n");
+
+        ncs_.write(0);
+        WAIT_TNCSSCLK();
+
+        // send the command to read the registers
+        spi_.write(lregister);
+        WAIT_TSRAD();
+        int lvalue = spi_.write(uregister);
+        WAIT_TSRAD();
+        int uvalue = spi_.write(0x00);
+        WAIT_TSCLKNCS();
+
+        ncs_.write(1);
+
+        return ADNS9500_UINT16(uvalue, lvalue);
+    }
+    
+    int ADNS9500::sromDownload(const char* filename)
+    {
+        if (! enabled_)
+            error("ADNS9500::sromDownload : the sensor is not enabled\n");
+    
+        ncs_.write(0);
+        WAIT_TNCSSCLK();
+
+        // SROM download
+        spi_.write(CONFIGURATION_IV);
+        WAIT_TSRAD();
+        spi_.write(ADNS9500_CONFIGURATION_IV_SROM_SIZE);
+        WAIT_TSRAD();
+        spi_.write(SROM_ENABLE);
+        WAIT_TSRAD();
+        spi_.write(0x1d);
+        wait_us(DEFAULT_MAX_FRAME_PERIOD);
+        spi_.write(SROM_ENABLE);
+        WAIT_TSRAD();
+        spi_.write(0x18);
+        WAIT_TSRAD();
+        spi_.write(SROM_LOAD_BURST);
+        
+        // TODO: Comprobar que pasa si el archivo no existe
+        ifstream ifs(filename, ifstream::in);
+        while(ifs.good()) {
+            WAIT_TLOAD();
+            spi_.write(ifs.get());
+        }
+        WAIT_TSCLKNCS();
+        ncs_.write(1);
+        WAIT_TBEXIT();
+
+        if (! ifs.eof())
+            error("ADNS9500::sromDownload : error reading from file: %s\n", filename);
+
+        // test if SROM was downloaded successfully
+        wait_us(160);
+        ncs_.write(0);
+        WAIT_TNCSSCLK();
+        spi_.write(SROM_ID);
+        WAIT_TSRAD();
+        int srom_id = spi_.write(0x00);
+        WAIT_TSCLKNCS();
+        ncs_.write(1);
+        
+        if (! srom_id)
+            error("ADNS9500::sromDownload : the firmware was not successful downloaded\n");
+
+        // test laser fault condition
+        ncs_.write(0);
+        WAIT_TNCSSCLK();
+        spi_.write(MOTION);
+        WAIT_TSRAD();
+        int motion = spi_.write(0x00);
+        WAIT_TSCLKNCS();
+        ncs_.write(1);
+        
+        if (ADNS9500_IF_LASER_FAULT(motion))
+            error("ADNS9500::sromDownload : laser fault condition detected\n");
+        
+        // return the SROM CRC value
+        ncs_.write(0);
+        WAIT_TNCSSCLK();
+        
+        spi_.write(SROM_ENABLE);
+        WAIT_TSRAD();
+        spi_.write(0x15);
+        wait_us(10);
+        spi_.write(DATA_OUT_LOWER);
+        WAIT_TSRAD();
+        int lcrc = spi_.write(DATA_OUT_UPPER);
+        WAIT_TSRAD();
+        int ucrc = spi_.write(0x00);
+        
+        WAIT_TSCLKNCS();
+        ncs_.write(1);
+        
+        return ADNS9500_UINT16(ucrc, lcrc);
+    }
+
+    void ADNS9500::enableLaser(bool enable)
+    {
+        if (! enabled_)
+            error("ADNS9500::enableLaser : the sensor is not enabled\n");
+    
+        ncs_.write(0);
+        WAIT_TNCSSCLK();
+
+        spi_.write(LASER_CTRL0);
+        WAIT_TSRAD();
+        if (enable) {
+            int laser_ctrl0 = CLEAR_BIT(0x00, ADNS9500_LASER_CTRL0_FORCE_DISABLED);
+            spi_.write(laser_ctrl0);
+        }
+        else {
+            int laser_ctrl0 = SET_BIT(0x00, ADNS9500_LASER_CTRL0_FORCE_DISABLED);
+            spi_.write(laser_ctrl0);
+        }        
+
+        WAIT_TSCLKNCS();
+        ncs_.write(1);
+    }
+
+    bool ADNS9500::getMotionDelta(int& dx, int& dy)
+    {
+        if (! enabled_)
+            error("ADNS9500::getMotionDelta : the sensor is not enabled\n");
+
+        ncs_.write(0);
+        WAIT_TNCSSCLK();
+    
+        spi_.write(MOTION);
+        WAIT_TSRAD();
+        int motion = spi_.write(DELTA_X_L);
+        WAIT_TSRAD();
+        
+        if (ADNS9500_IF_MOTION(motion)) {
+            int tmp = spi_.write(DELTA_X_L);
+            WAIT_TSRAD();
+            dx = ADNS9500_UINT16(spi_.write(DELTA_X_H), tmp);
+            WAIT_TSRAD();
+            tmp = spi_.write(DELTA_Y_L);
+            WAIT_TSRAD();
+            dy = ADNS9500_UINT16(spi_.write(DELTA_Y_H), tmp);
+            
+            dx_ = dx;
+            dy_ = dy;
+        }
+        else {
+            spi_.write(0x00);
+
+            dx = dx_;
+            dy = dy_;
+        }
+        
+        WAIT_TSCLKNCS();
+        ncs_.write(1);
+
+        return ADNS9500_IF_MOTION(motion);
+    }
+    
+    bool ADNS9500::getMotionDeltaMM(float& dx, float& dy)
+    {
+        int rawDx, rawDy;
+
+        bool motion = getMotionDelta(rawDx, rawDy);
+        dx = (float)rawDx / xCpi_ * 25.4;
+        dy = (float)rawDy / yCpi_ * 25.4;
+
+        return motion;
+    }
+
+    bool ADNS9500::getMotionData(MotionData& data)
+    {
+        if (! enabled_)
+            error("ADNS9500::getMotionData : the sensor is not enabled\n");
+    
+        ncs_.write(0);
+        WAIT_TNCSSCLK();
+        
+        // activate motion burst mode
+        spi_.write(MOTION_BURST);
+        WAIT_TSRAD();
+        spi_.write(0x50);
+        
+        // if in run mode, wait for 1 frame
+        wait_us(DEFAULT_MAX_FRAME_PERIOD);
+        
+        // read motion burst data
+        data.motion = spi_.write(0x00);
+        data.observation = spi_.write(0x00);
+        
+        int ldx = spi_.write(0x00);
+        data.dx = ADNS9500_UINT16(spi_.write(0x00), ldx);
+        
+        int ldy = spi_.write(0x00);
+        data.dy = ADNS9500_UINT16(spi_.write(0x00), ldy);
+        
+        data.squal = spi_.write(0x00);
+        data.pixelSum = spi_.write(0x00);
+        data.maximumPixel = spi_.write(0x00);
+        data.minimumPixel = spi_.write(0x00);
+        
+        int ushutter = spi_.write(0x00);
+        data.shutter = ADNS9500_UINT16(ushutter, spi_.write(0x00));
+        
+        int uframe_period = spi_.write(0x00);
+        data.framePeriod = ADNS9500_UINT16(uframe_period, spi_.write(0x00));
+
+        WAIT_TSCLKNCS();
+        ncs_.write(1);
+        WAIT_TBEXIT();
+        
+        return ADNS9500_IF_MOTION(data.motion);
+    }
+    
+    void ADNS9500::setResolution(Resolution xy_resolution)
+    {
+        if (! enabled_)
+            error("ADNS9500::setResolution : the sensor is not enabled\n");
+        
+        ncs_.write(0);
+        WAIT_TNCSSCLK();
+        
+        // enable XY axes CPI in sync mode
+        spi_.write(CONFIGURATION_II);
+        WAIT_TSRAD();
+        int rpt_mod = spi_.write(0x00);
+        WAIT_TSRAD();
+        spi_.write(CLEAR_BIT(rpt_mod, ADNS9500_CONFIGURATION_II_RPT_MOD));
+        WAIT_TSRAD();
+
+        // set resolution for X-axis and Y-axis
+        spi_.write(CONFIGURATION_I);
+        WAIT_TSRAD();
+        spi_.write(xy_resolution);
+
+        WAIT_TSCLKNCS();
+        ncs_.write(1);
+        
+        xCpi_ = xy_resolution * CPI_CHANGE_UNIT;
+        yCpi_ = xy_resolution * CPI_CHANGE_UNIT;
+    }
+    
+    void ADNS9500::setResolution(Resolution x_resolution, Resolution y_resolution)
+    {
+        if (! enabled_)
+            error("ADNS9500::setResolution : the sensor is not enabled\n");
+            
+        ncs_.write(0);
+        WAIT_TNCSSCLK();
+
+        // disable XY axes CPI in sync mode
+        spi_.write(CONFIGURATION_II);
+        WAIT_TSRAD();
+        int rpt_mod = spi_.write(0x00);
+        WAIT_TSRAD();
+        spi_.write(SET_BIT(rpt_mod, ADNS9500_CONFIGURATION_II_RPT_MOD));
+        WAIT_TSRAD();
+        
+        // set resolution for X-axis
+        spi_.write(CONFIGURATION_I);
+        WAIT_TSRAD();
+        spi_.write(x_resolution);
+        WAIT_TSRAD();
+                
+        // set resolution for Y-axis
+        spi_.write(CONFIGURATION_V);
+        WAIT_TSRAD();
+        spi_.write(y_resolution);
+
+        WAIT_TSCLKNCS();
+        ncs_.write(1);
+
+        xCpi_ = x_resolution * CPI_CHANGE_UNIT;
+        yCpi_ = y_resolution * CPI_CHANGE_UNIT;
+    }
+    
+    void ADNS9500::captureFrame(uint8_t pixels[NUMBER_OF_PIXELS_PER_FRAME])
+    {
+        if (! enabled_)
+            error("ADNS9500::captureFrame : the sensor is not enabled\n");
+            
+        ncs_.write(0);
+        WAIT_TNCSSCLK();
+        
+        spi_.write(FRAME_CAPTURE);
+        WAIT_TSRAD();
+        spi_.write(0x93);
+        WAIT_TSRAD();
+        spi_.write(FRAME_CAPTURE);
+        WAIT_TSRAD();
+        spi_.write(0xc5);
+        wait_us(DEFAULT_MAX_FRAME_PERIOD);
+        wait_us(DEFAULT_MAX_FRAME_PERIOD);
+        
+        // check for first pixel reading motion bit
+        spi_.write(MOTION);
+        while(true) {
+            WAIT_TSRAD();
+            int motion = spi_.write(MOTION);
+            if (ADNS9500_IF_MOTION(motion))
+                break;
+        }
+        
+        // read pixel values
+        spi_.write(PIXEL_BURST);
+        WAIT_TSRAD();
+        for (uint8_t* p = pixels; p != pixels + sizeof(pixels); ++p) {
+            WAIT_TLOAD();
+            *p = spi_.write(PIXEL_BURST);
+        }
+
+        // burst exit        
+        WAIT_TSCLKNCS();
+        ncs_.write(1);
+        WAIT_TBEXIT();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ADNS9500.hpp	Fri Feb 10 21:35:22 2012 +0000
@@ -0,0 +1,293 @@
+/*
+ * ADNS9500.hpp - Interface to access to Avago ADNS-9500 laser mouse sensors
+ *
+ *   Copyright 2012 Jesus Torres <jmtorres@ull.es>
+ *
+ * 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.
+ */
+ 
+#ifndef ADNS9500_HPP_
+#define ADNS9500_HPP_
+
+#include <mbed.h>
+#include <stdint.h>
+#include <string>
+
+#define ADNS9500_CONFIGURATION_II_RPT_MOD   (1 << 2)
+#define ADNS9500_CONFIGURATION_IV_SROM_SIZE (1 << 1)
+#define ADNS9500_LASER_CTRL0_FORCE_DISABLED (1 << 0)
+#define ADNS9500_OBSERVATION_CHECK_BITS     0x3f
+
+#define ADNS9500_IF_MOTION(x)               (bool)(x & 0x80)
+#define ADNS9500_IF_LASER_FAULT(x)          (bool)(x & 0x40)
+#define ADNS9500_IF_RUNNING_SROM_CODE(x)    (bool)(x & 0x80)
+#define ADNS9500_IF_OBSERVATION_TEST(x)     (bool)(x & ADNS9500_OBSERVATION_CHECK_BITS)
+#define ADNS9500_UINT16(ub, lb)             ((uint16_t)ub << 8 | (uint16_t)lb)
+
+namespace adns9500
+{
+    // Maximum SPI clock frequency supported by the sensor
+    const int MAX_SPI_FREQUENCY = 2000000;
+    
+    // Internal oscillator norminal frequency
+    const int INTERNAL_OSCILLATOR_FREQUENCY = 47000000;
+    
+    // Number of pixels per frame
+    const int NUMBER_OF_PIXELS_PER_FRAME = 900;
+
+    //
+    // Sensor registers
+    //
+    
+    enum Register
+    {
+        PRODUCT_ID         = 0x00,
+        REVISION_ID        = 0x01,
+        MOTION             = 0x02,
+        DELTA_X_L          = 0x03,
+        DELTA_X_H          = 0x04,
+        DELTA_Y_L          = 0x05,
+        DELTA_Y_H          = 0x06,
+        SQUAL              = 0x07,
+        PIXEL_SUM          = 0x08,
+        MAXIMUM_PIXEL      = 0x09,
+        MINIMUM_PIXEL      = 0x0a,
+        SHUTTER_LOWER      = 0x0b,
+        SHUTTER_UPPER      = 0x0c,
+        FRAME_PERIOD_LOWER = 0x0d,
+        FRAME_PERIOD_UPPER = 0x0e,
+        CONFIGURATION_I    = 0x0f,
+        CONFIGURATION_II   = 0x10,
+        FRAME_CAPTURE      = 0x12,
+        SROM_ENABLE        = 0x13,
+        LASER_CTRL0        = 0x20,
+        DATA_OUT_LOWER     = 0x25,
+        DATA_OUT_UPPER     = 0x26,
+        SROM_ID            = 0x2a,
+        OBSERVATION        = 0x24,
+        CONFIGURATION_V    = 0x2f,
+        CONFIGURATION_IV   = 0x39,
+        POWER_UP_RESET     = 0x3a,
+        MOTION_BURST       = 0x50,
+        SROM_LOAD_BURST    = 0x62,
+        PIXEL_BURST        = 0x62
+    };
+
+    //
+    // Supported resolutions
+    //
+
+    enum Resolution
+    {
+        CPI_90   = 0x01,
+        CPI_1630 = 0x12,
+        CPI_3240 = 0x24,
+        CPI_5040 = 0x38
+    };
+    
+    //
+    // Motion burst data
+    //
+    
+    struct MotionData
+    {
+        int motion;
+        int observation;
+        int dx;
+        int dy;
+        int squal;
+        int pixelSum;
+        int maximumPixel;
+        int minimumPixel;
+        int shutter;
+        int framePeriod;
+    };
+
+    //
+    // Interface to access to ADNS-9500 mouse sensor
+    //
+
+    class ADNS9500
+    {
+        public:
+        
+            //
+            // Create the sensor interface
+            //
+            // @param mosi MOSI pin for the SPI interface
+            // @param miso MISO pin for the SPI interface
+            // @param sclk SCLK pin for the SPI interface
+            // @param spi_frequency SPI clock frequency in Hz up to MAX_SPI_PORT_FREQUENCY
+            // @param ncs A digital active-low output pin for sensor chip select
+            // @param motion A digital active-low input pin activated by the sensor when motion
+            //               is detected
+            //
+            ADNS9500(PinName mosi, PinName miso, PinName sclk, PinName ncs,
+                int spi_frequency = MAX_SPI_FREQUENCY, PinName motion = NC);
+
+            //
+            // Destroy de sensor interface
+            //
+            ~ADNS9500();
+
+            //
+            // Power up/reset the sensor
+            // Terminate with error if the connection can not be established
+            //
+            // @param firmware If the firmware has to be downloaded, C-string containing the name
+            //                 of the file where it is stored, or NULL in other case
+            //
+            void reset(const char* firmware = NULL);
+
+            //
+            // Shutdown the sensor
+            //
+            void shutdown();
+
+            //
+            // Read the value of a sensor register
+            //
+            // @param lregister The register which to read its value
+            // @return The value of the register
+            //
+            int read(Register lregister);
+            
+            //
+            // Read the values of sensor registers
+            //
+            // @param uregister The register which to read the upper byte
+            // @param lregister The register which to read the lower byte
+            // @return The values of registers as a 16-bit integer, putting the value
+            //         of uregister in the upper byte and the value of lregister in the
+            //         lower byte
+            //
+            int read(Register uregister, Register lregister);
+
+            //
+            // Get information about sensor status
+            //
+            // @return The value of MOTION register. It tells if motion or laser fault
+            //         conditions have ocurred, laser power setting status and operating
+            //         mode in current frame
+            //
+            int status()
+                { return read(MOTION); }
+           
+            //
+            // Download the firmware to the sensor SROM
+            //
+            // @param filename The name of the file which contains the sensor firmware
+            // @return The SROM CRC value
+            //
+            int sromDownload(const char* filename);
+
+            //
+            // Enable the laser
+            //
+            // @param enable True if laser must be enabled, or false if laser must be disabled
+            //
+            void enableLaser(bool enable=true);
+
+            //
+            // Get motion deltas from sensor
+            //
+            // @param dx The component X of displacement
+            // @param dy The component Y of displacement
+            // @return True if motion was occurred since the last time the function was called,
+            //         or false in other case
+            //
+            bool getMotionDelta(int& dx, int& dy);
+
+            //
+            // Get motion deltas in mm. from sensor
+            //
+            // @param dx The component X of displacement in mm.
+            // @param dy The component Y of displacement in mm.
+            // @return True if motion was occurred since the last time the function was called,
+            //         or false in other case
+            //
+            bool getMotionDeltaMM(float& dx, float& dy);
+            
+            //
+            // Get all information about motion
+            //
+            // @param data The struct where sensor data will be stored
+            // @return True if motion was occurred since the last time the function was called,
+            //         or false in other case
+            //
+            bool getMotionData(MotionData& data);
+
+            //
+            // Set the resolution on XY axes together
+            //
+            // @param xy_resolution The resolution for X-axis and Y-axis
+            //
+            void setResolution(Resolution xy_resolution);
+
+            //
+            // Set the resolutions on X-axis and Y-axis
+            //
+            // @param x_resolution The resolution for X-axis
+            // @param y_resolution The resolution for Y-axis
+            //
+            void setResolution(Resolution x_resolution, Resolution y_resolution);
+
+            //
+            // Get a full array of pixel values from a single frame.
+            // This disables navigation and overwrites any donwloaded firmware,
+            // so call to reset() is needed to restore them
+            //
+            // @param pixels The array where pixel values will be stored
+            //
+            void captureFrame(uint8_t pixels[NUMBER_OF_PIXELS_PER_FRAME]);
+
+            //
+            // Member function invoked when motion has ocurred and if a motion pin
+            // was specified when the object constructor was called.
+            // By default it invokes the function specified by a previous call to attach()
+            //
+            virtual void motionTrigger()
+                { motionTrigger_.call(); }
+
+            //
+            // Attach a function to call when a falling edge occurs on motion pin
+            //
+            // @param function A pointer to a function or 0 to set the attached function as none
+            //
+            void attach(void (*function)(void))
+                { motionTrigger_.attach(function); }
+
+            //
+            // Attach a member function to call when a falling edge occurs on motion pin
+            //
+            // @param object A reference to the object to call the member function on
+            // @param function A pointer to the member function to be called
+            //
+            template<typename T>
+            void attach(T& object, void (T::*member)(void))
+                { motionTrigger_.attach(object, member); }
+
+        private:
+            SPI spi_;
+            InterruptIn motion_;
+            DigitalOut ncs_;
+            
+            bool enabled_;            
+            int dx_, dy_;
+            int xCpi_, yCpi_;
+            
+            FunctionPointer motionTrigger_;
+    };
+}
+
+#endif /* ADNS9500_HPP_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.lib	Fri Feb 10 21:35:22 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/projects/libraries/svn/mbed/trunk@35
\ No newline at end of file