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

Dependencies:   mbed

Committer:
aplatanado
Date:
Tue Jul 10 13:29:45 2012 +0000
Revision:
8:97e5df54b8bb
Parent:
3:898ed1944119
Child:
9:8b1e889e94fe
ensure ncs is high if observation test fails during reset

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 2:ee0c13ef1320 19 #include <cstdlib>
aplatanado 0:782f2061a8f5 20 #include <fstream>
aplatanado 0:782f2061a8f5 21 #include <math.h>
aplatanado 0:782f2061a8f5 22 #include <mbed.h>
aplatanado 0:782f2061a8f5 23 #include <string>
aplatanado 0:782f2061a8f5 24
aplatanado 1:fa3052be61b5 25 #include <adns9500.hpp>
aplatanado 0:782f2061a8f5 26
aplatanado 0:782f2061a8f5 27 #define WAIT_TSRAD() wait_us(100)
aplatanado 2:ee0c13ef1320 28 #define WAIT_TSRR() wait_us(20)
aplatanado 2:ee0c13ef1320 29 #define WAIT_TSRW() wait_us(20)
aplatanado 2:ee0c13ef1320 30 #define WAIT_TSWR() wait_us(120)
aplatanado 2:ee0c13ef1320 31 #define WAIT_TSWW() wait_us(120)
aplatanado 0:782f2061a8f5 32 #define WAIT_TBEXIT() wait_us(1) // 500ns
aplatanado 0:782f2061a8f5 33 #define WAIT_TNCSSCLK() wait_us(1) // 120ns
aplatanado 0:782f2061a8f5 34 #define WAIT_TSCLKNCS() wait_us(20)
aplatanado 0:782f2061a8f5 35 #define WAIT_TLOAD() wait_us(15)
aplatanado 0:782f2061a8f5 36
aplatanado 2:ee0c13ef1320 37 #define LONG_WAIT_MS(x) \
aplatanado 2:ee0c13ef1320 38 WAIT_TSCLKNCS(); ncs_.write(1); wait_ms(x); ncs_.write(0); WAIT_TNCSSCLK()
aplatanado 2:ee0c13ef1320 39 #define LONG_WAIT_US(x) \
aplatanado 2:ee0c13ef1320 40 WAIT_TSCLKNCS(); ncs_.write(1); wait_us(x); ncs_.write(0); WAIT_TNCSSCLK()
aplatanado 2:ee0c13ef1320 41
aplatanado 0:782f2061a8f5 42 #define DEFAULT_MAX_FPS 1958
aplatanado 2:ee0c13ef1320 43 #define DEFAULT_MAX_FRAME_PERIOD ((int)ceil(1e6 / DEFAULT_MAX_FPS)) // in us
aplatanado 0:782f2061a8f5 44 #define DEFAULT_X_CPI 1620
aplatanado 0:782f2061a8f5 45 #define DEFAULT_Y_CPI 1620
aplatanado 0:782f2061a8f5 46 #define CPI_CHANGE_UNIT 90
aplatanado 0:782f2061a8f5 47
aplatanado 2:ee0c13ef1320 48 #define SPI_BITS_PER_FRAME 8
aplatanado 2:ee0c13ef1320 49 #define SPI_MODE 3
aplatanado 2:ee0c13ef1320 50 #define SPI_WRITE_MODE 0x80
aplatanado 2:ee0c13ef1320 51
aplatanado 0:782f2061a8f5 52 #define SET_BIT(word, mask) (word | mask)
aplatanado 0:782f2061a8f5 53 #define CLEAR_BIT(word, mask) (word & (~mask))
aplatanado 0:782f2061a8f5 54
aplatanado 0:782f2061a8f5 55 namespace adns9500 {
aplatanado 0:782f2061a8f5 56
aplatanado 0:782f2061a8f5 57 ADNS9500::ADNS9500(PinName mosi, PinName miso, PinName sclk, PinName ncs,
aplatanado 0:782f2061a8f5 58 int spi_frequency, PinName motion)
aplatanado 0:782f2061a8f5 59 : spi_(mosi, miso, sclk),
aplatanado 0:782f2061a8f5 60 motion_(motion),
aplatanado 0:782f2061a8f5 61 ncs_(ncs),
aplatanado 0:782f2061a8f5 62 enabled_(false),
aplatanado 0:782f2061a8f5 63 xCpi_(DEFAULT_X_CPI), yCpi_(DEFAULT_Y_CPI)
aplatanado 0:782f2061a8f5 64 {
aplatanado 2:ee0c13ef1320 65 spi_.format(SPI_BITS_PER_FRAME, SPI_MODE);
aplatanado 2:ee0c13ef1320 66
aplatanado 2:ee0c13ef1320 67 motion_.mode(PullUp);
aplatanado 0:782f2061a8f5 68 motion_.fall(this, &ADNS9500::motionTrigger);
aplatanado 0:782f2061a8f5 69 }
aplatanado 0:782f2061a8f5 70
aplatanado 0:782f2061a8f5 71 ADNS9500::~ADNS9500()
aplatanado 0:782f2061a8f5 72 {
aplatanado 0:782f2061a8f5 73 shutdown();
aplatanado 0:782f2061a8f5 74 }
aplatanado 0:782f2061a8f5 75
aplatanado 0:782f2061a8f5 76 void ADNS9500::reset(const char* firmware)
aplatanado 0:782f2061a8f5 77 {
aplatanado 0:782f2061a8f5 78 // SPI port reset
aplatanado 0:782f2061a8f5 79 ncs_.write(1);
aplatanado 0:782f2061a8f5 80 WAIT_TNCSSCLK();
aplatanado 0:782f2061a8f5 81 ncs_.write(0);
aplatanado 0:782f2061a8f5 82 WAIT_TNCSSCLK();
aplatanado 0:782f2061a8f5 83
aplatanado 0:782f2061a8f5 84 // send 0x3a to POWER_UP_RESET and wait for at least 50ms
aplatanado 2:ee0c13ef1320 85 spiSend(POWER_UP_RESET, 0x5a);
aplatanado 2:ee0c13ef1320 86 LONG_WAIT_MS(50);
aplatanado 0:782f2061a8f5 87
aplatanado 0:782f2061a8f5 88 // clear observation register. Only required to deassert shutdown mode.
aplatanado 2:ee0c13ef1320 89 spiSend(OBSERVATION, 0x00);
aplatanado 2:ee0c13ef1320 90 LONG_WAIT_US(DEFAULT_MAX_FRAME_PERIOD);
aplatanado 8:97e5df54b8bb 91
aplatanado 8:97e5df54b8bb 92 WAIT_TSCLKNCS();
aplatanado 8:97e5df54b8bb 93 ncs_.write(1);
aplatanado 8:97e5df54b8bb 94
aplatanado 0:782f2061a8f5 95 // check observation register bits [5:0]
aplatanado 2:ee0c13ef1320 96 int observation = spiReceive(OBSERVATION);
aplatanado 0:782f2061a8f5 97 if (! ADNS9500_IF_OBSERVATION_TEST(observation))
aplatanado 0:782f2061a8f5 98 error("ADNS9500::reset : observation register test failed: 0x%x\n", observation);
aplatanado 0:782f2061a8f5 99
aplatanado 0:782f2061a8f5 100 // read motion data
aplatanado 8:97e5df54b8bb 101 ncs_.write(0);
aplatanado 8:97e5df54b8bb 102 WAIT_TNCSSCLK();
aplatanado 8:97e5df54b8bb 103
aplatanado 2:ee0c13ef1320 104 WAIT_TSRR();
aplatanado 2:ee0c13ef1320 105 spiReceive(MOTION);
aplatanado 2:ee0c13ef1320 106 WAIT_TSRR();
aplatanado 2:ee0c13ef1320 107 spiReceive(DELTA_X_L);
aplatanado 2:ee0c13ef1320 108 WAIT_TSRR();
aplatanado 2:ee0c13ef1320 109 spiReceive(DELTA_X_H);
aplatanado 2:ee0c13ef1320 110 WAIT_TSRR();
aplatanado 2:ee0c13ef1320 111 spiReceive(DELTA_Y_L);
aplatanado 2:ee0c13ef1320 112 WAIT_TSRR();
aplatanado 2:ee0c13ef1320 113 spiReceive(DELTA_Y_H);
aplatanado 0:782f2061a8f5 114
aplatanado 2:ee0c13ef1320 115 // read product and revision id to test the connection
aplatanado 2:ee0c13ef1320 116 WAIT_TSRR();
aplatanado 0:782f2061a8f5 117 spi_.write(PRODUCT_ID);
aplatanado 0:782f2061a8f5 118 WAIT_TSRAD();
aplatanado 2:ee0c13ef1320 119 int product_id = spi_.write(0x00);
aplatanado 2:ee0c13ef1320 120 WAIT_TSRR();
aplatanado 2:ee0c13ef1320 121 spi_.write(REVISION_ID);
aplatanado 0:782f2061a8f5 122 WAIT_TSRAD();
aplatanado 0:782f2061a8f5 123 int revision_id = spi_.write(0x00);
aplatanado 2:ee0c13ef1320 124
aplatanado 0:782f2061a8f5 125 WAIT_TSCLKNCS();
aplatanado 0:782f2061a8f5 126 ncs_.write(1);
aplatanado 0:782f2061a8f5 127
aplatanado 0:782f2061a8f5 128 if (product_id != 0x33) {
aplatanado 0:782f2061a8f5 129 error("ADNS9500::reset : bad product ID: 0x%x\n", product_id);
aplatanado 0:782f2061a8f5 130 }
aplatanado 0:782f2061a8f5 131
aplatanado 0:782f2061a8f5 132 if (revision_id != 0x03) {
aplatanado 0:782f2061a8f5 133 error("ADNS9500::reset : bad revision ID: 0x%x\n", revision_id);
aplatanado 0:782f2061a8f5 134 }
aplatanado 0:782f2061a8f5 135
aplatanado 0:782f2061a8f5 136 enabled_ = true;
aplatanado 0:782f2061a8f5 137
aplatanado 0:782f2061a8f5 138 if (firmware) {
aplatanado 0:782f2061a8f5 139 sromDownload(firmware);
aplatanado 0:782f2061a8f5 140 enableLaser();
aplatanado 0:782f2061a8f5 141 }
aplatanado 0:782f2061a8f5 142 }
aplatanado 0:782f2061a8f5 143
aplatanado 0:782f2061a8f5 144 void ADNS9500::shutdown()
aplatanado 0:782f2061a8f5 145 {
aplatanado 0:782f2061a8f5 146 if (! enabled_)
aplatanado 0:782f2061a8f5 147 error("ADNS9500::shutdown : the sensor is not enabled\n");
aplatanado 0:782f2061a8f5 148
aplatanado 0:782f2061a8f5 149 ncs_.write(0);
aplatanado 0:782f2061a8f5 150 WAIT_TNCSSCLK();
aplatanado 0:782f2061a8f5 151
aplatanado 0:782f2061a8f5 152 // send 0x3a to POWER_UP_RESET
aplatanado 2:ee0c13ef1320 153 spiSend(POWER_UP_RESET, 0x5a);
aplatanado 2:ee0c13ef1320 154
aplatanado 0:782f2061a8f5 155 WAIT_TSCLKNCS();
aplatanado 0:782f2061a8f5 156 ncs_.write(1);
aplatanado 0:782f2061a8f5 157
aplatanado 0:782f2061a8f5 158 enabled_ = false;
aplatanado 0:782f2061a8f5 159 }
aplatanado 0:782f2061a8f5 160
aplatanado 0:782f2061a8f5 161 int ADNS9500::read(Register lregister)
aplatanado 0:782f2061a8f5 162 {
aplatanado 0:782f2061a8f5 163 if (! enabled_)
aplatanado 0:782f2061a8f5 164 error("ADNS9500::read : the sensor is not enabled\n");
aplatanado 0:782f2061a8f5 165
aplatanado 0:782f2061a8f5 166 ncs_.write(0);
aplatanado 0:782f2061a8f5 167 WAIT_TNCSSCLK();
aplatanado 0:782f2061a8f5 168
aplatanado 0:782f2061a8f5 169 // send the command to read the register
aplatanado 2:ee0c13ef1320 170 int value = spiReceive(lregister);
aplatanado 2:ee0c13ef1320 171
aplatanado 0:782f2061a8f5 172 WAIT_TSCLKNCS();
aplatanado 0:782f2061a8f5 173 ncs_.write(1);
aplatanado 2:ee0c13ef1320 174
aplatanado 0:782f2061a8f5 175 return value;
aplatanado 0:782f2061a8f5 176 }
aplatanado 0:782f2061a8f5 177
aplatanado 0:782f2061a8f5 178 int ADNS9500::read(Register uregister, Register lregister)
aplatanado 0:782f2061a8f5 179 {
aplatanado 0:782f2061a8f5 180 if (! enabled_)
aplatanado 0:782f2061a8f5 181 error("ADNS9500::read : the sensor is not enabled\n");
aplatanado 0:782f2061a8f5 182
aplatanado 0:782f2061a8f5 183 ncs_.write(0);
aplatanado 0:782f2061a8f5 184 WAIT_TNCSSCLK();
aplatanado 0:782f2061a8f5 185
aplatanado 0:782f2061a8f5 186 // send the command to read the registers
aplatanado 2:ee0c13ef1320 187 int lvalue = spiReceive(lregister);
aplatanado 2:ee0c13ef1320 188 WAIT_TSRR();
aplatanado 2:ee0c13ef1320 189 int uvalue = spiReceive(uregister);
aplatanado 2:ee0c13ef1320 190
aplatanado 0:782f2061a8f5 191 WAIT_TSCLKNCS();
aplatanado 0:782f2061a8f5 192 ncs_.write(1);
aplatanado 0:782f2061a8f5 193
aplatanado 0:782f2061a8f5 194 return ADNS9500_UINT16(uvalue, lvalue);
aplatanado 0:782f2061a8f5 195 }
aplatanado 0:782f2061a8f5 196
aplatanado 0:782f2061a8f5 197 int ADNS9500::sromDownload(const char* filename)
aplatanado 0:782f2061a8f5 198 {
aplatanado 0:782f2061a8f5 199 if (! enabled_)
aplatanado 0:782f2061a8f5 200 error("ADNS9500::sromDownload : the sensor is not enabled\n");
aplatanado 0:782f2061a8f5 201
aplatanado 0:782f2061a8f5 202 ncs_.write(0);
aplatanado 0:782f2061a8f5 203 WAIT_TNCSSCLK();
aplatanado 0:782f2061a8f5 204
aplatanado 0:782f2061a8f5 205 // SROM download
aplatanado 2:ee0c13ef1320 206 spiSend(CONFIGURATION_IV, ADNS9500_CONFIGURATION_IV_SROM_SIZE);
aplatanado 2:ee0c13ef1320 207 WAIT_TSWW();
aplatanado 2:ee0c13ef1320 208 spiSend(SROM_ENABLE, 0x1d);
aplatanado 2:ee0c13ef1320 209 LONG_WAIT_US(DEFAULT_MAX_FRAME_PERIOD);
aplatanado 2:ee0c13ef1320 210
aplatanado 2:ee0c13ef1320 211 spiSend(SROM_ENABLE, 0x18);
aplatanado 2:ee0c13ef1320 212 WAIT_TSWW();
aplatanado 2:ee0c13ef1320 213 spi_.write(SET_BIT(SROM_LOAD_BURST, SPI_WRITE_MODE));
aplatanado 2:ee0c13ef1320 214
aplatanado 2:ee0c13ef1320 215 // we expect a line per byte in hex without 0x prefix
aplatanado 2:ee0c13ef1320 216 char buffer[4];
aplatanado 0:782f2061a8f5 217 ifstream ifs(filename, ifstream::in);
aplatanado 2:ee0c13ef1320 218 while(ifs.getline(buffer, sizeof(buffer)).good()) {
aplatanado 0:782f2061a8f5 219 WAIT_TLOAD();
aplatanado 2:ee0c13ef1320 220 int byte = strtol(buffer, NULL, 16);
aplatanado 2:ee0c13ef1320 221 spi_.write(byte);
aplatanado 0:782f2061a8f5 222 }
aplatanado 0:782f2061a8f5 223 WAIT_TSCLKNCS();
aplatanado 0:782f2061a8f5 224 ncs_.write(1);
aplatanado 0:782f2061a8f5 225 WAIT_TBEXIT();
aplatanado 0:782f2061a8f5 226
aplatanado 0:782f2061a8f5 227 if (! ifs.eof())
aplatanado 0:782f2061a8f5 228 error("ADNS9500::sromDownload : error reading from file: %s\n", filename);
aplatanado 0:782f2061a8f5 229
aplatanado 0:782f2061a8f5 230 // test if SROM was downloaded successfully
aplatanado 0:782f2061a8f5 231 wait_us(160);
aplatanado 0:782f2061a8f5 232 ncs_.write(0);
aplatanado 0:782f2061a8f5 233 WAIT_TNCSSCLK();
aplatanado 2:ee0c13ef1320 234
aplatanado 2:ee0c13ef1320 235 int srom_id = spiReceive(SROM_ID);
aplatanado 2:ee0c13ef1320 236
aplatanado 0:782f2061a8f5 237 WAIT_TSCLKNCS();
aplatanado 0:782f2061a8f5 238 ncs_.write(1);
aplatanado 0:782f2061a8f5 239
aplatanado 0:782f2061a8f5 240 if (! srom_id)
aplatanado 0:782f2061a8f5 241 error("ADNS9500::sromDownload : the firmware was not successful downloaded\n");
aplatanado 0:782f2061a8f5 242
aplatanado 0:782f2061a8f5 243 // test laser fault condition
aplatanado 0:782f2061a8f5 244 ncs_.write(0);
aplatanado 0:782f2061a8f5 245 WAIT_TNCSSCLK();
aplatanado 2:ee0c13ef1320 246
aplatanado 2:ee0c13ef1320 247 int motion = spiReceive(MOTION);
aplatanado 2:ee0c13ef1320 248
aplatanado 0:782f2061a8f5 249 WAIT_TSCLKNCS();
aplatanado 0:782f2061a8f5 250 ncs_.write(1);
aplatanado 0:782f2061a8f5 251
aplatanado 0:782f2061a8f5 252 if (ADNS9500_IF_LASER_FAULT(motion))
aplatanado 0:782f2061a8f5 253 error("ADNS9500::sromDownload : laser fault condition detected\n");
aplatanado 0:782f2061a8f5 254
aplatanado 0:782f2061a8f5 255 // return the SROM CRC value
aplatanado 0:782f2061a8f5 256 ncs_.write(0);
aplatanado 0:782f2061a8f5 257 WAIT_TNCSSCLK();
aplatanado 0:782f2061a8f5 258
aplatanado 2:ee0c13ef1320 259 spiSend(SROM_ENABLE, 0x15);
aplatanado 2:ee0c13ef1320 260 LONG_WAIT_MS(10);
aplatanado 2:ee0c13ef1320 261
aplatanado 2:ee0c13ef1320 262 int lcrc = spiReceive(DATA_OUT_LOWER);
aplatanado 2:ee0c13ef1320 263 WAIT_TSRR();
aplatanado 2:ee0c13ef1320 264 int ucrc = spiReceive(DATA_OUT_UPPER);
aplatanado 0:782f2061a8f5 265
aplatanado 0:782f2061a8f5 266 WAIT_TSCLKNCS();
aplatanado 0:782f2061a8f5 267 ncs_.write(1);
aplatanado 0:782f2061a8f5 268
aplatanado 0:782f2061a8f5 269 return ADNS9500_UINT16(ucrc, lcrc);
aplatanado 0:782f2061a8f5 270 }
aplatanado 0:782f2061a8f5 271
aplatanado 0:782f2061a8f5 272 void ADNS9500::enableLaser(bool enable)
aplatanado 0:782f2061a8f5 273 {
aplatanado 0:782f2061a8f5 274 if (! enabled_)
aplatanado 0:782f2061a8f5 275 error("ADNS9500::enableLaser : the sensor is not enabled\n");
aplatanado 2:ee0c13ef1320 276
aplatanado 0:782f2061a8f5 277 ncs_.write(0);
aplatanado 0:782f2061a8f5 278 WAIT_TNCSSCLK();
aplatanado 0:782f2061a8f5 279
aplatanado 0:782f2061a8f5 280 if (enable) {
aplatanado 0:782f2061a8f5 281 int laser_ctrl0 = CLEAR_BIT(0x00, ADNS9500_LASER_CTRL0_FORCE_DISABLED);
aplatanado 2:ee0c13ef1320 282 spiSend(LASER_CTRL0, laser_ctrl0);
aplatanado 0:782f2061a8f5 283 }
aplatanado 0:782f2061a8f5 284 else {
aplatanado 0:782f2061a8f5 285 int laser_ctrl0 = SET_BIT(0x00, ADNS9500_LASER_CTRL0_FORCE_DISABLED);
aplatanado 2:ee0c13ef1320 286 spiSend(LASER_CTRL0, laser_ctrl0);
aplatanado 0:782f2061a8f5 287 }
aplatanado 0:782f2061a8f5 288
aplatanado 0:782f2061a8f5 289 WAIT_TSCLKNCS();
aplatanado 0:782f2061a8f5 290 ncs_.write(1);
aplatanado 0:782f2061a8f5 291 }
aplatanado 0:782f2061a8f5 292
aplatanado 0:782f2061a8f5 293 bool ADNS9500::getMotionDelta(int& dx, int& dy)
aplatanado 0:782f2061a8f5 294 {
aplatanado 0:782f2061a8f5 295 if (! enabled_)
aplatanado 0:782f2061a8f5 296 error("ADNS9500::getMotionDelta : the sensor is not enabled\n");
aplatanado 0:782f2061a8f5 297
aplatanado 0:782f2061a8f5 298 ncs_.write(0);
aplatanado 0:782f2061a8f5 299 WAIT_TNCSSCLK();
aplatanado 2:ee0c13ef1320 300
aplatanado 2:ee0c13ef1320 301 dx = 0;
aplatanado 2:ee0c13ef1320 302 dy = 0;
aplatanado 2:ee0c13ef1320 303
aplatanado 2:ee0c13ef1320 304 int motion = spiReceive(MOTION);
aplatanado 0:782f2061a8f5 305 if (ADNS9500_IF_MOTION(motion)) {
aplatanado 2:ee0c13ef1320 306 WAIT_TSRR();
aplatanado 2:ee0c13ef1320 307 int dxl = spiReceive(DELTA_X_L);
aplatanado 2:ee0c13ef1320 308 WAIT_TSRR();
aplatanado 2:ee0c13ef1320 309 dx += ADNS9500_INT16(spiReceive(DELTA_X_H), dxl);
aplatanado 0:782f2061a8f5 310
aplatanado 2:ee0c13ef1320 311 WAIT_TSRR();
aplatanado 2:ee0c13ef1320 312 int dyl = spiReceive(DELTA_Y_L);
aplatanado 2:ee0c13ef1320 313 WAIT_TSRR();
aplatanado 2:ee0c13ef1320 314 dy += ADNS9500_INT16(spiReceive(DELTA_Y_H), dyl);
aplatanado 0:782f2061a8f5 315 }
aplatanado 0:782f2061a8f5 316
aplatanado 0:782f2061a8f5 317 WAIT_TSCLKNCS();
aplatanado 0:782f2061a8f5 318 ncs_.write(1);
aplatanado 2:ee0c13ef1320 319
aplatanado 0:782f2061a8f5 320 return ADNS9500_IF_MOTION(motion);
aplatanado 0:782f2061a8f5 321 }
aplatanado 0:782f2061a8f5 322
aplatanado 0:782f2061a8f5 323 bool ADNS9500::getMotionDeltaMM(float& dx, float& dy)
aplatanado 0:782f2061a8f5 324 {
aplatanado 0:782f2061a8f5 325 int rawDx, rawDy;
aplatanado 0:782f2061a8f5 326
aplatanado 0:782f2061a8f5 327 bool motion = getMotionDelta(rawDx, rawDy);
aplatanado 0:782f2061a8f5 328 dx = (float)rawDx / xCpi_ * 25.4;
aplatanado 0:782f2061a8f5 329 dy = (float)rawDy / yCpi_ * 25.4;
aplatanado 0:782f2061a8f5 330
aplatanado 0:782f2061a8f5 331 return motion;
aplatanado 0:782f2061a8f5 332 }
aplatanado 0:782f2061a8f5 333
aplatanado 0:782f2061a8f5 334 bool ADNS9500::getMotionData(MotionData& data)
aplatanado 0:782f2061a8f5 335 {
aplatanado 0:782f2061a8f5 336 if (! enabled_)
aplatanado 0:782f2061a8f5 337 error("ADNS9500::getMotionData : the sensor is not enabled\n");
aplatanado 0:782f2061a8f5 338
aplatanado 0:782f2061a8f5 339 ncs_.write(0);
aplatanado 0:782f2061a8f5 340 WAIT_TNCSSCLK();
aplatanado 0:782f2061a8f5 341
aplatanado 0:782f2061a8f5 342 // activate motion burst mode
aplatanado 0:782f2061a8f5 343 spi_.write(0x50);
aplatanado 2:ee0c13ef1320 344 WAIT_TSRAD(); // see the chronogram
aplatanado 0:782f2061a8f5 345
aplatanado 0:782f2061a8f5 346 // read motion burst data
aplatanado 0:782f2061a8f5 347 data.motion = spi_.write(0x00);
aplatanado 0:782f2061a8f5 348 data.observation = spi_.write(0x00);
aplatanado 0:782f2061a8f5 349
aplatanado 0:782f2061a8f5 350 int ldx = spi_.write(0x00);
aplatanado 2:ee0c13ef1320 351 data.dx = ADNS9500_INT16(spi_.write(0x00), ldx);
aplatanado 0:782f2061a8f5 352
aplatanado 0:782f2061a8f5 353 int ldy = spi_.write(0x00);
aplatanado 2:ee0c13ef1320 354 data.dy = ADNS9500_INT16(spi_.write(0x00), ldy);
aplatanado 0:782f2061a8f5 355
aplatanado 2:ee0c13ef1320 356 data.surfaceQuality = spi_.write(0x00) * 4;
aplatanado 2:ee0c13ef1320 357 data.averagePixel = spi_.write(0x00) / 1.76;
aplatanado 0:782f2061a8f5 358 data.maximumPixel = spi_.write(0x00);
aplatanado 0:782f2061a8f5 359 data.minimumPixel = spi_.write(0x00);
aplatanado 0:782f2061a8f5 360
aplatanado 0:782f2061a8f5 361 int ushutter = spi_.write(0x00);
aplatanado 0:782f2061a8f5 362 data.shutter = ADNS9500_UINT16(ushutter, spi_.write(0x00));
aplatanado 0:782f2061a8f5 363
aplatanado 0:782f2061a8f5 364 int uframe_period = spi_.write(0x00);
aplatanado 0:782f2061a8f5 365 data.framePeriod = ADNS9500_UINT16(uframe_period, spi_.write(0x00));
aplatanado 0:782f2061a8f5 366
aplatanado 0:782f2061a8f5 367 WAIT_TSCLKNCS();
aplatanado 0:782f2061a8f5 368 ncs_.write(1);
aplatanado 0:782f2061a8f5 369 WAIT_TBEXIT();
aplatanado 2:ee0c13ef1320 370
aplatanado 2:ee0c13ef1320 371 data.dxMM = (float)data.dx / xCpi_ * 25.4;
aplatanado 2:ee0c13ef1320 372 data.dyMM = (float)data.dy / yCpi_ * 25.4;
aplatanado 2:ee0c13ef1320 373
aplatanado 2:ee0c13ef1320 374 // write a value to Motion register to clear motion bit
aplatanado 2:ee0c13ef1320 375 ncs_.write(0);
aplatanado 2:ee0c13ef1320 376 WAIT_TNCSSCLK();
aplatanado 0:782f2061a8f5 377
aplatanado 2:ee0c13ef1320 378 spiSend(MOTION, 0x00);
aplatanado 2:ee0c13ef1320 379
aplatanado 2:ee0c13ef1320 380 WAIT_TSCLKNCS();
aplatanado 2:ee0c13ef1320 381 ncs_.write(1);
aplatanado 2:ee0c13ef1320 382
aplatanado 0:782f2061a8f5 383 return ADNS9500_IF_MOTION(data.motion);
aplatanado 0:782f2061a8f5 384 }
aplatanado 0:782f2061a8f5 385
aplatanado 0:782f2061a8f5 386 void ADNS9500::setResolution(Resolution xy_resolution)
aplatanado 0:782f2061a8f5 387 {
aplatanado 0:782f2061a8f5 388 if (! enabled_)
aplatanado 0:782f2061a8f5 389 error("ADNS9500::setResolution : the sensor is not enabled\n");
aplatanado 0:782f2061a8f5 390
aplatanado 0:782f2061a8f5 391 ncs_.write(0);
aplatanado 0:782f2061a8f5 392 WAIT_TNCSSCLK();
aplatanado 0:782f2061a8f5 393
aplatanado 0:782f2061a8f5 394 // enable XY axes CPI in sync mode
aplatanado 2:ee0c13ef1320 395 int rpt_mod = spiReceive(CONFIGURATION_II);
aplatanado 2:ee0c13ef1320 396 rpt_mod = CLEAR_BIT(rpt_mod, ADNS9500_CONFIGURATION_II_RPT_MOD);
aplatanado 2:ee0c13ef1320 397 WAIT_TSRW();
aplatanado 2:ee0c13ef1320 398 spiSend(CONFIGURATION_II, rpt_mod);
aplatanado 0:782f2061a8f5 399
aplatanado 0:782f2061a8f5 400 // set resolution for X-axis and Y-axis
aplatanado 2:ee0c13ef1320 401 WAIT_TSWW();
aplatanado 2:ee0c13ef1320 402 spiSend(CONFIGURATION_I, xy_resolution);
aplatanado 0:782f2061a8f5 403
aplatanado 0:782f2061a8f5 404 WAIT_TSCLKNCS();
aplatanado 0:782f2061a8f5 405 ncs_.write(1);
aplatanado 0:782f2061a8f5 406
aplatanado 0:782f2061a8f5 407 xCpi_ = xy_resolution * CPI_CHANGE_UNIT;
aplatanado 0:782f2061a8f5 408 yCpi_ = xy_resolution * CPI_CHANGE_UNIT;
aplatanado 0:782f2061a8f5 409 }
aplatanado 0:782f2061a8f5 410
aplatanado 0:782f2061a8f5 411 void ADNS9500::setResolution(Resolution x_resolution, Resolution y_resolution)
aplatanado 0:782f2061a8f5 412 {
aplatanado 0:782f2061a8f5 413 if (! enabled_)
aplatanado 0:782f2061a8f5 414 error("ADNS9500::setResolution : the sensor is not enabled\n");
aplatanado 0:782f2061a8f5 415
aplatanado 0:782f2061a8f5 416 ncs_.write(0);
aplatanado 0:782f2061a8f5 417 WAIT_TNCSSCLK();
aplatanado 0:782f2061a8f5 418
aplatanado 0:782f2061a8f5 419 // disable XY axes CPI in sync mode
aplatanado 2:ee0c13ef1320 420 int rpt_mod = spiReceive(CONFIGURATION_II);
aplatanado 2:ee0c13ef1320 421 rpt_mod = SET_BIT(rpt_mod, ADNS9500_CONFIGURATION_II_RPT_MOD);
aplatanado 2:ee0c13ef1320 422 WAIT_TSRW();
aplatanado 2:ee0c13ef1320 423 spiSend(CONFIGURATION_II, rpt_mod);
aplatanado 0:782f2061a8f5 424
aplatanado 0:782f2061a8f5 425 // set resolution for X-axis
aplatanado 2:ee0c13ef1320 426 WAIT_TSWW();
aplatanado 2:ee0c13ef1320 427 spiSend(CONFIGURATION_I, x_resolution);
aplatanado 0:782f2061a8f5 428
aplatanado 0:782f2061a8f5 429 // set resolution for Y-axis
aplatanado 2:ee0c13ef1320 430 WAIT_TSWW();
aplatanado 2:ee0c13ef1320 431 spiSend(CONFIGURATION_V, y_resolution);
aplatanado 0:782f2061a8f5 432
aplatanado 0:782f2061a8f5 433 WAIT_TSCLKNCS();
aplatanado 0:782f2061a8f5 434 ncs_.write(1);
aplatanado 0:782f2061a8f5 435
aplatanado 0:782f2061a8f5 436 xCpi_ = x_resolution * CPI_CHANGE_UNIT;
aplatanado 0:782f2061a8f5 437 yCpi_ = y_resolution * CPI_CHANGE_UNIT;
aplatanado 0:782f2061a8f5 438 }
aplatanado 0:782f2061a8f5 439
aplatanado 3:898ed1944119 440 void ADNS9500::captureFrame(uint8_t* pixels)
aplatanado 0:782f2061a8f5 441 {
aplatanado 0:782f2061a8f5 442 if (! enabled_)
aplatanado 0:782f2061a8f5 443 error("ADNS9500::captureFrame : the sensor is not enabled\n");
aplatanado 0:782f2061a8f5 444
aplatanado 0:782f2061a8f5 445 ncs_.write(0);
aplatanado 0:782f2061a8f5 446 WAIT_TNCSSCLK();
aplatanado 0:782f2061a8f5 447
aplatanado 2:ee0c13ef1320 448 spiSend(FRAME_CAPTURE, 0x93);
aplatanado 2:ee0c13ef1320 449 WAIT_TSWW();
aplatanado 2:ee0c13ef1320 450 spiSend(FRAME_CAPTURE, 0xc5);
aplatanado 2:ee0c13ef1320 451 LONG_WAIT_US(2*DEFAULT_MAX_FRAME_PERIOD);
aplatanado 2:ee0c13ef1320 452
aplatanado 0:782f2061a8f5 453 // check for first pixel reading motion bit
aplatanado 3:898ed1944119 454 int motion = spiReceive(MOTION);
aplatanado 3:898ed1944119 455 WAIT_TSRR();
aplatanado 3:898ed1944119 456 while(! ADNS9500_IF_FRAME_FIRST_PIXEL(motion)) {
aplatanado 2:ee0c13ef1320 457 int motion = spiReceive(MOTION);
aplatanado 2:ee0c13ef1320 458 WAIT_TSRR();
aplatanado 0:782f2061a8f5 459 }
aplatanado 2:ee0c13ef1320 460
aplatanado 0:782f2061a8f5 461 // read pixel values
aplatanado 0:782f2061a8f5 462 spi_.write(PIXEL_BURST);
aplatanado 0:782f2061a8f5 463 WAIT_TSRAD();
aplatanado 3:898ed1944119 464 for (uint8_t* p = pixels; p != pixels + NUMBER_OF_PIXELS_PER_FRAME; ++p) {
aplatanado 3:898ed1944119 465 *p = spi_.write(0x00);
aplatanado 0:782f2061a8f5 466 WAIT_TLOAD();
aplatanado 0:782f2061a8f5 467 }
aplatanado 0:782f2061a8f5 468
aplatanado 3:898ed1944119 469 // burst exit
aplatanado 0:782f2061a8f5 470 ncs_.write(1);
aplatanado 0:782f2061a8f5 471 WAIT_TBEXIT();
aplatanado 0:782f2061a8f5 472 }
aplatanado 2:ee0c13ef1320 473
aplatanado 2:ee0c13ef1320 474 void ADNS9500::spiSend(Register address, int value)
aplatanado 2:ee0c13ef1320 475 {
aplatanado 2:ee0c13ef1320 476 spi_.write(SET_BIT(address, SPI_WRITE_MODE));
aplatanado 2:ee0c13ef1320 477 spi_.write(value);
aplatanado 2:ee0c13ef1320 478 }
aplatanado 2:ee0c13ef1320 479
aplatanado 2:ee0c13ef1320 480 int ADNS9500::spiReceive(Register address)
aplatanado 2:ee0c13ef1320 481 {
aplatanado 2:ee0c13ef1320 482 spi_.write(CLEAR_BIT(address, SPI_WRITE_MODE));
aplatanado 2:ee0c13ef1320 483 WAIT_TSRAD();
aplatanado 2:ee0c13ef1320 484 return spi_.write(0x00);
aplatanado 2:ee0c13ef1320 485 }
aplatanado 0:782f2061a8f5 486 }