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

Dependencies:   mbed

Committer:
aplatanado
Date:
Sat Apr 20 12:50:42 2013 +0000
Revision:
16:0f8e730f3272
Parent:
10:bbf9ff378632
apply some coding style rules to macros

Who changed what in which revision?

UserRevisionLine numberNew contents of line
aplatanado 0:782f2061a8f5 1 /*
aplatanado 1:fa3052be61b5 2 * adns9500.hpp - Interface to access to Avago ADNS-9500 laser mouse sensors
aplatanado 0:782f2061a8f5 3 *
aplatanado 0:782f2061a8f5 4 * Copyright 2012 Jesus Torres <jmtorres@ull.es>
aplatanado 0:782f2061a8f5 5 *
aplatanado 0:782f2061a8f5 6 * Licensed under the Apache License, Version 2.0 (the "License");
aplatanado 0:782f2061a8f5 7 * you may not use this file except in compliance with the License.
aplatanado 0:782f2061a8f5 8 * You may obtain a copy of the License at
aplatanado 0:782f2061a8f5 9 *
aplatanado 0:782f2061a8f5 10 * http://www.apache.org/licenses/LICENSE-2.0
aplatanado 0:782f2061a8f5 11 *
aplatanado 0:782f2061a8f5 12 * Unless required by applicable law or agreed to in writing, software
aplatanado 0:782f2061a8f5 13 * distributed under the License is distributed on an "AS IS" BASIS,
aplatanado 0:782f2061a8f5 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
aplatanado 0:782f2061a8f5 15 * See the License for the specific language governing permissions and
aplatanado 0:782f2061a8f5 16 * limitations under the License.
aplatanado 0:782f2061a8f5 17 */
aplatanado 0:782f2061a8f5 18
aplatanado 0:782f2061a8f5 19 #ifndef ADNS9500_HPP_
aplatanado 0:782f2061a8f5 20 #define ADNS9500_HPP_
aplatanado 0:782f2061a8f5 21
aplatanado 0:782f2061a8f5 22 #include <mbed.h>
aplatanado 0:782f2061a8f5 23 #include <stdint.h>
aplatanado 0:782f2061a8f5 24 #include <string>
aplatanado 0:782f2061a8f5 25
aplatanado 0:782f2061a8f5 26 #define ADNS9500_CONFIGURATION_II_RPT_MOD (1 << 2)
aplatanado 0:782f2061a8f5 27 #define ADNS9500_CONFIGURATION_IV_SROM_SIZE (1 << 1)
aplatanado 0:782f2061a8f5 28 #define ADNS9500_LASER_CTRL0_FORCE_DISABLED (1 << 0)
aplatanado 0:782f2061a8f5 29 #define ADNS9500_OBSERVATION_CHECK_BITS 0x3f
aplatanado 0:782f2061a8f5 30
aplatanado 16:0f8e730f3272 31 #define ADNS9500_HAS_MOTION_DETECTED(x) (bool)(x & 0x80)
aplatanado 16:0f8e730f3272 32 #define ADNS9500_HAS_LASER_FAULT(x) (bool)(x & 0x40)
aplatanado 16:0f8e730f3272 33 #define ADNS9500_IS_RUNNING_SROM_CODE(x) (bool)(x & 0x80)
aplatanado 16:0f8e730f3272 34 #define ADNS9500_HAS_FIRST_PIXEL(x) (bool)(x & 0x01)
aplatanado 16:0f8e730f3272 35 #define ADNS9500_PASS_OBSERVATION_TEST(x) (bool)(x & ADNS9500_OBSERVATION_CHECK_BITS)
aplatanado 7:1771f1c89df6 36 #define ADNS9500_UINT16(ub, lb) (uint16_t)(((ub & 0xff) << 8) | (lb & 0xff))
aplatanado 7:1771f1c89df6 37 #define ADNS9500_INT16(ub, lb) (int16_t)(((ub & 0xff) << 8) | (lb & 0xff))
aplatanado 0:782f2061a8f5 38
aplatanado 0:782f2061a8f5 39 namespace adns9500
aplatanado 0:782f2061a8f5 40 {
aplatanado 0:782f2061a8f5 41 // Maximum SPI clock frequency supported by the sensor
aplatanado 10:bbf9ff378632 42 const int MAX_SPI_FREQUENCY = 2000000;
aplatanado 0:782f2061a8f5 43
aplatanado 0:782f2061a8f5 44 // Internal oscillator norminal frequency
aplatanado 0:782f2061a8f5 45 const int INTERNAL_OSCILLATOR_FREQUENCY = 47000000;
aplatanado 0:782f2061a8f5 46
aplatanado 0:782f2061a8f5 47 // Number of pixels per frame
aplatanado 0:782f2061a8f5 48 const int NUMBER_OF_PIXELS_PER_FRAME = 900;
aplatanado 2:ee0c13ef1320 49
aplatanado 2:ee0c13ef1320 50 // Maximum surface quality
aplatanado 2:ee0c13ef1320 51 const int MAX_SURFACE_QUALITY = 676; // 169 * 4
aplatanado 0:782f2061a8f5 52
aplatanado 0:782f2061a8f5 53 //
aplatanado 0:782f2061a8f5 54 // Sensor registers
aplatanado 0:782f2061a8f5 55 //
aplatanado 0:782f2061a8f5 56
aplatanado 0:782f2061a8f5 57 enum Register
aplatanado 0:782f2061a8f5 58 {
aplatanado 0:782f2061a8f5 59 PRODUCT_ID = 0x00,
aplatanado 0:782f2061a8f5 60 REVISION_ID = 0x01,
aplatanado 0:782f2061a8f5 61 MOTION = 0x02,
aplatanado 0:782f2061a8f5 62 DELTA_X_L = 0x03,
aplatanado 0:782f2061a8f5 63 DELTA_X_H = 0x04,
aplatanado 0:782f2061a8f5 64 DELTA_Y_L = 0x05,
aplatanado 0:782f2061a8f5 65 DELTA_Y_H = 0x06,
aplatanado 0:782f2061a8f5 66 SQUAL = 0x07,
aplatanado 0:782f2061a8f5 67 PIXEL_SUM = 0x08,
aplatanado 0:782f2061a8f5 68 MAXIMUM_PIXEL = 0x09,
aplatanado 0:782f2061a8f5 69 MINIMUM_PIXEL = 0x0a,
aplatanado 0:782f2061a8f5 70 SHUTTER_LOWER = 0x0b,
aplatanado 0:782f2061a8f5 71 SHUTTER_UPPER = 0x0c,
aplatanado 0:782f2061a8f5 72 FRAME_PERIOD_LOWER = 0x0d,
aplatanado 0:782f2061a8f5 73 FRAME_PERIOD_UPPER = 0x0e,
aplatanado 0:782f2061a8f5 74 CONFIGURATION_I = 0x0f,
aplatanado 0:782f2061a8f5 75 CONFIGURATION_II = 0x10,
aplatanado 0:782f2061a8f5 76 FRAME_CAPTURE = 0x12,
aplatanado 0:782f2061a8f5 77 SROM_ENABLE = 0x13,
aplatanado 0:782f2061a8f5 78 LASER_CTRL0 = 0x20,
aplatanado 0:782f2061a8f5 79 DATA_OUT_LOWER = 0x25,
aplatanado 0:782f2061a8f5 80 DATA_OUT_UPPER = 0x26,
aplatanado 0:782f2061a8f5 81 SROM_ID = 0x2a,
aplatanado 0:782f2061a8f5 82 OBSERVATION = 0x24,
aplatanado 0:782f2061a8f5 83 CONFIGURATION_V = 0x2f,
aplatanado 0:782f2061a8f5 84 CONFIGURATION_IV = 0x39,
aplatanado 0:782f2061a8f5 85 POWER_UP_RESET = 0x3a,
aplatanado 0:782f2061a8f5 86 MOTION_BURST = 0x50,
aplatanado 0:782f2061a8f5 87 SROM_LOAD_BURST = 0x62,
aplatanado 3:898ed1944119 88 PIXEL_BURST = 0x64
aplatanado 0:782f2061a8f5 89 };
aplatanado 0:782f2061a8f5 90
aplatanado 0:782f2061a8f5 91 //
aplatanado 0:782f2061a8f5 92 // Supported resolutions
aplatanado 0:782f2061a8f5 93 //
aplatanado 0:782f2061a8f5 94
aplatanado 0:782f2061a8f5 95 enum Resolution
aplatanado 0:782f2061a8f5 96 {
aplatanado 0:782f2061a8f5 97 CPI_90 = 0x01,
aplatanado 0:782f2061a8f5 98 CPI_1630 = 0x12,
aplatanado 0:782f2061a8f5 99 CPI_3240 = 0x24,
aplatanado 0:782f2061a8f5 100 CPI_5040 = 0x38
aplatanado 0:782f2061a8f5 101 };
aplatanado 0:782f2061a8f5 102
aplatanado 0:782f2061a8f5 103 //
aplatanado 0:782f2061a8f5 104 // Motion burst data
aplatanado 0:782f2061a8f5 105 //
aplatanado 0:782f2061a8f5 106
aplatanado 0:782f2061a8f5 107 struct MotionData
aplatanado 0:782f2061a8f5 108 {
aplatanado 2:ee0c13ef1320 109 MotionData()
aplatanado 2:ee0c13ef1320 110 : motion(0), observation(0), dx(0), dy(0), dxMM(0), dyMM(0),
aplatanado 2:ee0c13ef1320 111 surfaceQuality(0), averagePixel(0), maximumPixel(0),
aplatanado 2:ee0c13ef1320 112 minimumPixel(0), shutter(0), framePeriod(0)
aplatanado 2:ee0c13ef1320 113 {}
aplatanado 2:ee0c13ef1320 114
aplatanado 0:782f2061a8f5 115 int motion;
aplatanado 0:782f2061a8f5 116 int observation;
aplatanado 0:782f2061a8f5 117 int dx;
aplatanado 0:782f2061a8f5 118 int dy;
aplatanado 2:ee0c13ef1320 119 float dxMM;
aplatanado 2:ee0c13ef1320 120 float dyMM;
aplatanado 2:ee0c13ef1320 121 int surfaceQuality;
aplatanado 2:ee0c13ef1320 122 float averagePixel;
aplatanado 0:782f2061a8f5 123 int maximumPixel;
aplatanado 0:782f2061a8f5 124 int minimumPixel;
aplatanado 0:782f2061a8f5 125 int shutter;
aplatanado 0:782f2061a8f5 126 int framePeriod;
aplatanado 0:782f2061a8f5 127 };
aplatanado 0:782f2061a8f5 128
aplatanado 0:782f2061a8f5 129 //
aplatanado 0:782f2061a8f5 130 // Interface to access to ADNS-9500 mouse sensor
aplatanado 0:782f2061a8f5 131 //
aplatanado 0:782f2061a8f5 132
aplatanado 0:782f2061a8f5 133 class ADNS9500
aplatanado 0:782f2061a8f5 134 {
aplatanado 0:782f2061a8f5 135 public:
aplatanado 0:782f2061a8f5 136
aplatanado 0:782f2061a8f5 137 //
aplatanado 0:782f2061a8f5 138 // Create the sensor interface
aplatanado 0:782f2061a8f5 139 //
aplatanado 0:782f2061a8f5 140 // @param mosi MOSI pin for the SPI interface
aplatanado 0:782f2061a8f5 141 // @param miso MISO pin for the SPI interface
aplatanado 0:782f2061a8f5 142 // @param sclk SCLK pin for the SPI interface
aplatanado 0:782f2061a8f5 143 // @param spi_frequency SPI clock frequency in Hz up to MAX_SPI_PORT_FREQUENCY
aplatanado 0:782f2061a8f5 144 // @param ncs A digital active-low output pin for sensor chip select
aplatanado 0:782f2061a8f5 145 // @param motion A digital active-low input pin activated by the sensor when motion
aplatanado 0:782f2061a8f5 146 // is detected
aplatanado 0:782f2061a8f5 147 //
aplatanado 0:782f2061a8f5 148 ADNS9500(PinName mosi, PinName miso, PinName sclk, PinName ncs,
aplatanado 0:782f2061a8f5 149 int spi_frequency = MAX_SPI_FREQUENCY, PinName motion = NC);
aplatanado 0:782f2061a8f5 150
aplatanado 0:782f2061a8f5 151 //
aplatanado 0:782f2061a8f5 152 // Destroy de sensor interface
aplatanado 0:782f2061a8f5 153 //
aplatanado 0:782f2061a8f5 154 ~ADNS9500();
aplatanado 0:782f2061a8f5 155
aplatanado 0:782f2061a8f5 156 //
aplatanado 0:782f2061a8f5 157 // Power up/reset the sensor
aplatanado 0:782f2061a8f5 158 // Terminate with error if the connection can not be established
aplatanado 0:782f2061a8f5 159 //
aplatanado 0:782f2061a8f5 160 // @param firmware If the firmware has to be downloaded, C-string containing the name
aplatanado 0:782f2061a8f5 161 // of the file where it is stored, or NULL in other case
aplatanado 0:782f2061a8f5 162 //
aplatanado 0:782f2061a8f5 163 void reset(const char* firmware = NULL);
aplatanado 0:782f2061a8f5 164
aplatanado 0:782f2061a8f5 165 //
aplatanado 0:782f2061a8f5 166 // Shutdown the sensor
aplatanado 0:782f2061a8f5 167 //
aplatanado 0:782f2061a8f5 168 void shutdown();
aplatanado 0:782f2061a8f5 169
aplatanado 0:782f2061a8f5 170 //
aplatanado 0:782f2061a8f5 171 // Read the value of a sensor register
aplatanado 0:782f2061a8f5 172 //
aplatanado 0:782f2061a8f5 173 // @param lregister The register which to read its value
aplatanado 0:782f2061a8f5 174 // @return The value of the register
aplatanado 0:782f2061a8f5 175 //
aplatanado 0:782f2061a8f5 176 int read(Register lregister);
aplatanado 0:782f2061a8f5 177
aplatanado 0:782f2061a8f5 178 //
aplatanado 0:782f2061a8f5 179 // Read the values of sensor registers
aplatanado 0:782f2061a8f5 180 //
aplatanado 0:782f2061a8f5 181 // @param uregister The register which to read the upper byte
aplatanado 0:782f2061a8f5 182 // @param lregister The register which to read the lower byte
aplatanado 0:782f2061a8f5 183 // @return The values of registers as a 16-bit integer, putting the value
aplatanado 0:782f2061a8f5 184 // of uregister in the upper byte and the value of lregister in the
aplatanado 0:782f2061a8f5 185 // lower byte
aplatanado 0:782f2061a8f5 186 //
aplatanado 0:782f2061a8f5 187 int read(Register uregister, Register lregister);
aplatanado 0:782f2061a8f5 188
aplatanado 0:782f2061a8f5 189 //
aplatanado 0:782f2061a8f5 190 // Get information about sensor status
aplatanado 0:782f2061a8f5 191 //
aplatanado 0:782f2061a8f5 192 // @return The value of MOTION register. It tells if motion or laser fault
aplatanado 0:782f2061a8f5 193 // conditions have ocurred, laser power setting status and operating
aplatanado 0:782f2061a8f5 194 // mode in current frame
aplatanado 0:782f2061a8f5 195 //
aplatanado 0:782f2061a8f5 196 int status()
aplatanado 0:782f2061a8f5 197 { return read(MOTION); }
aplatanado 0:782f2061a8f5 198
aplatanado 0:782f2061a8f5 199 //
aplatanado 0:782f2061a8f5 200 // Download the firmware to the sensor SROM
aplatanado 0:782f2061a8f5 201 //
aplatanado 0:782f2061a8f5 202 // @param filename The name of the file which contains the sensor firmware
aplatanado 0:782f2061a8f5 203 // @return The SROM CRC value
aplatanado 0:782f2061a8f5 204 //
aplatanado 0:782f2061a8f5 205 int sromDownload(const char* filename);
aplatanado 0:782f2061a8f5 206
aplatanado 0:782f2061a8f5 207 //
aplatanado 0:782f2061a8f5 208 // Enable the laser
aplatanado 0:782f2061a8f5 209 //
aplatanado 0:782f2061a8f5 210 // @param enable True if laser must be enabled, or false if laser must be disabled
aplatanado 0:782f2061a8f5 211 //
aplatanado 0:782f2061a8f5 212 void enableLaser(bool enable=true);
aplatanado 0:782f2061a8f5 213
aplatanado 0:782f2061a8f5 214 //
aplatanado 0:782f2061a8f5 215 // Get motion deltas from sensor
aplatanado 0:782f2061a8f5 216 //
aplatanado 0:782f2061a8f5 217 // @param dx The component X of displacement
aplatanado 0:782f2061a8f5 218 // @param dy The component Y of displacement
aplatanado 0:782f2061a8f5 219 // @return True if motion was occurred since the last time the function was called,
aplatanado 0:782f2061a8f5 220 // or false in other case
aplatanado 0:782f2061a8f5 221 //
aplatanado 0:782f2061a8f5 222 bool getMotionDelta(int& dx, int& dy);
aplatanado 0:782f2061a8f5 223
aplatanado 0:782f2061a8f5 224 //
aplatanado 0:782f2061a8f5 225 // Get motion deltas in mm. from sensor
aplatanado 0:782f2061a8f5 226 //
aplatanado 0:782f2061a8f5 227 // @param dx The component X of displacement in mm.
aplatanado 0:782f2061a8f5 228 // @param dy The component Y of displacement in mm.
aplatanado 0:782f2061a8f5 229 // @return True if motion was occurred since the last time the function was called,
aplatanado 0:782f2061a8f5 230 // or false in other case
aplatanado 0:782f2061a8f5 231 //
aplatanado 0:782f2061a8f5 232 bool getMotionDeltaMM(float& dx, float& dy);
aplatanado 0:782f2061a8f5 233
aplatanado 0:782f2061a8f5 234 //
aplatanado 0:782f2061a8f5 235 // Get all information about motion
aplatanado 0:782f2061a8f5 236 //
aplatanado 0:782f2061a8f5 237 // @param data The struct where sensor data will be stored
aplatanado 0:782f2061a8f5 238 // @return True if motion was occurred since the last time the function was called,
aplatanado 0:782f2061a8f5 239 // or false in other case
aplatanado 0:782f2061a8f5 240 //
aplatanado 0:782f2061a8f5 241 bool getMotionData(MotionData& data);
aplatanado 0:782f2061a8f5 242
aplatanado 0:782f2061a8f5 243 //
aplatanado 0:782f2061a8f5 244 // Set the resolution on XY axes together
aplatanado 0:782f2061a8f5 245 //
aplatanado 0:782f2061a8f5 246 // @param xy_resolution The resolution for X-axis and Y-axis
aplatanado 0:782f2061a8f5 247 //
aplatanado 0:782f2061a8f5 248 void setResolution(Resolution xy_resolution);
aplatanado 0:782f2061a8f5 249
aplatanado 0:782f2061a8f5 250 //
aplatanado 0:782f2061a8f5 251 // Set the resolutions on X-axis and Y-axis
aplatanado 0:782f2061a8f5 252 //
aplatanado 0:782f2061a8f5 253 // @param x_resolution The resolution for X-axis
aplatanado 0:782f2061a8f5 254 // @param y_resolution The resolution for Y-axis
aplatanado 0:782f2061a8f5 255 //
aplatanado 0:782f2061a8f5 256 void setResolution(Resolution x_resolution, Resolution y_resolution);
aplatanado 0:782f2061a8f5 257
aplatanado 0:782f2061a8f5 258 //
aplatanado 0:782f2061a8f5 259 // Get a full array of pixel values from a single frame.
aplatanado 0:782f2061a8f5 260 // This disables navigation and overwrites any donwloaded firmware,
aplatanado 0:782f2061a8f5 261 // so call to reset() is needed to restore them
aplatanado 0:782f2061a8f5 262 //
aplatanado 3:898ed1944119 263 // @param pixels A pointer to the array where pixel values will be stored
aplatanado 0:782f2061a8f5 264 //
aplatanado 3:898ed1944119 265 void captureFrame(uint8_t* pixels);
aplatanado 0:782f2061a8f5 266
aplatanado 0:782f2061a8f5 267 //
aplatanado 0:782f2061a8f5 268 // Member function invoked when motion has ocurred and if a motion pin
aplatanado 0:782f2061a8f5 269 // was specified when the object constructor was called.
aplatanado 0:782f2061a8f5 270 // By default it invokes the function specified by a previous call to attach()
aplatanado 0:782f2061a8f5 271 //
aplatanado 0:782f2061a8f5 272 virtual void motionTrigger()
aplatanado 0:782f2061a8f5 273 { motionTrigger_.call(); }
aplatanado 0:782f2061a8f5 274
aplatanado 0:782f2061a8f5 275 //
aplatanado 0:782f2061a8f5 276 // Attach a function to call when a falling edge occurs on motion pin
aplatanado 0:782f2061a8f5 277 //
aplatanado 0:782f2061a8f5 278 // @param function A pointer to a function or 0 to set the attached function as none
aplatanado 0:782f2061a8f5 279 //
aplatanado 0:782f2061a8f5 280 void attach(void (*function)(void))
aplatanado 0:782f2061a8f5 281 { motionTrigger_.attach(function); }
aplatanado 0:782f2061a8f5 282
aplatanado 0:782f2061a8f5 283 //
aplatanado 0:782f2061a8f5 284 // Attach a member function to call when a falling edge occurs on motion pin
aplatanado 0:782f2061a8f5 285 //
aplatanado 0:782f2061a8f5 286 // @param object A reference to the object to call the member function on
aplatanado 0:782f2061a8f5 287 // @param function A pointer to the member function to be called
aplatanado 0:782f2061a8f5 288 //
aplatanado 0:782f2061a8f5 289 template<typename T>
aplatanado 0:782f2061a8f5 290 void attach(T& object, void (T::*member)(void))
aplatanado 0:782f2061a8f5 291 { motionTrigger_.attach(object, member); }
aplatanado 0:782f2061a8f5 292
aplatanado 0:782f2061a8f5 293 private:
aplatanado 0:782f2061a8f5 294 SPI spi_;
aplatanado 0:782f2061a8f5 295 InterruptIn motion_;
aplatanado 0:782f2061a8f5 296 DigitalOut ncs_;
aplatanado 2:ee0c13ef1320 297
aplatanado 0:782f2061a8f5 298 bool enabled_;
aplatanado 0:782f2061a8f5 299 int xCpi_, yCpi_;
aplatanado 0:782f2061a8f5 300
aplatanado 0:782f2061a8f5 301 FunctionPointer motionTrigger_;
aplatanado 2:ee0c13ef1320 302
aplatanado 2:ee0c13ef1320 303 //
aplatanado 2:ee0c13ef1320 304 // Write a byte to the specified register
aplatanado 2:ee0c13ef1320 305 //
aplatanado 2:ee0c13ef1320 306 // @param address The register address
aplatanado 2:ee0c13ef1320 307 // @param value The value to be written to the register
aplatanado 2:ee0c13ef1320 308 //
aplatanado 2:ee0c13ef1320 309 void spiSend(Register address, int value);
aplatanado 2:ee0c13ef1320 310
aplatanado 2:ee0c13ef1320 311 //
aplatanado 2:ee0c13ef1320 312 // Read a byte from the specified register
aplatanado 2:ee0c13ef1320 313 //
aplatanado 2:ee0c13ef1320 314 // @param address The register address
aplatanado 2:ee0c13ef1320 315 // @return The value of the register
aplatanado 2:ee0c13ef1320 316 //
aplatanado 2:ee0c13ef1320 317 int spiReceive(Register address);
aplatanado 0:782f2061a8f5 318 };
aplatanado 0:782f2061a8f5 319 }
aplatanado 0:782f2061a8f5 320
aplatanado 0:782f2061a8f5 321 #endif /* ADNS9500_HPP_ */