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

Fork of ADNS9500 by Chris Majoros

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers adns9500.cpp Source File

adns9500.cpp

00001 /*
00002  * adns9500.hpp - Interface to access to Avago ADNS-9500 laser mouse sensors
00003  *
00004  *   Copyright 2012 Jesus Torres <jmtorres@ull.es>
00005  *
00006  * Licensed under the Apache License, Version 2.0 (the "License");
00007  * you may not use this file except in compliance with the License.
00008  * You may obtain a copy of the License at
00009  *
00010  *     http://www.apache.org/licenses/LICENSE-2.0
00011  *
00012  * Unless required by applicable law or agreed to in writing, software
00013  * distributed under the License is distributed on an "AS IS" BASIS,
00014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  * See the License for the specific language governing permissions and
00016  * limitations under the License.
00017  */
00018 
00019 #include <cstdio>
00020 #include <cstdlib>
00021 #include <mbed.h>
00022 #include <string>
00023 
00024 #include <adns9500.hpp>
00025 
00026 #define WAIT_TSRAD()        wait_us(100)
00027 #define WAIT_TSRR()         wait_us(20)
00028 #define WAIT_TSRW()         wait_us(20)
00029 #define WAIT_TSWR()         wait_us(120)
00030 #define WAIT_TSWW()         wait_us(120)
00031 #define WAIT_TBEXIT()       wait_us(1)      // 500ns
00032 #define WAIT_TNCSSCLK()     wait_us(1)      // 120ns
00033 #define WAIT_TSCLKNCS()     wait_us(20)
00034 #define WAIT_TLOAD()        wait_us(15)
00035 
00036 #define LONG_WAIT_MS(x)     \
00037     WAIT_TSCLKNCS(); ncs_.write(1); wait_ms(x); ncs_.write(0); WAIT_TNCSSCLK()
00038 #define LONG_WAIT_US(x)     \
00039     WAIT_TSCLKNCS(); ncs_.write(1); wait_us(x); ncs_.write(0); WAIT_TNCSSCLK()
00040 
00041 #define DEFAULT_MAX_FPS             1958
00042 #define DEFAULT_MAX_FRAME_PERIOD    (1000000 / DEFAULT_MAX_FPS + 1) // in us
00043 #define DEFAULT_X_CPI               1620
00044 #define DEFAULT_Y_CPI               1620
00045 #define CPI_CHANGE_UNIT             90
00046 
00047 #define SPI_BITS_PER_FRAME          8
00048 #define SPI_MODE                    3
00049 #define SPI_WRITE_MODE              0x80
00050 
00051 #define SET_BIT(word, mask)         (word | mask)
00052 #define CLEAR_BIT(word, mask)       (word & (~mask))
00053 
00054 namespace adns9500 {
00055 
00056     ADNS9500::ADNS9500(PinName mosi, PinName miso, PinName sclk, PinName ncs,
00057         int spi_frequency, PinName motion)
00058         : spi_(mosi, miso, sclk),
00059           motion_(motion),
00060           ncs_(ncs),
00061           enabled_(false),
00062           xCpi_(DEFAULT_X_CPI), yCpi_(DEFAULT_Y_CPI)
00063     {
00064         spi_.format(SPI_BITS_PER_FRAME, SPI_MODE);
00065         spi_.frequency(spi_frequency);
00066 
00067         motion_.mode(PullUp);
00068         motion_.fall(this, &ADNS9500::motionTrigger);
00069     }
00070 
00071     ADNS9500::~ADNS9500()
00072     {
00073         shutdown();
00074     }
00075 
00076     void ADNS9500::reset(const uint8_t* fw, uint16_t fw_len)
00077     {
00078         // SPI port reset
00079         ncs_.write(1);
00080         WAIT_TNCSSCLK();
00081         ncs_.write(0);
00082         WAIT_TNCSSCLK();
00083         
00084         // send 0x5a to POWER_UP_RESET and wait for at least 50ms
00085         spiSend(POWER_UP_RESET, 0x5a);
00086         LONG_WAIT_MS(50);
00087         
00088         // clear observation register. Only required to deassert shutdown mode.
00089         spiSend(OBSERVATION, 0x00);
00090         LONG_WAIT_US(DEFAULT_MAX_FRAME_PERIOD);
00091 
00092         // check observation register bits [5:0]
00093         int observation = spiReceive(OBSERVATION);
00094         if (! ADNS9500_IF_OBSERVATION_TEST(observation)) {
00095             WAIT_TSCLKNCS();
00096             ncs_.write(1);
00097 
00098             error("ADNS9500::reset : observation register test failed: 0x%x\n", observation);
00099         }
00100 
00101         // read motion data
00102         WAIT_TSRR();
00103         spiReceive(MOTION);
00104         WAIT_TSRR();
00105         spiReceive(DELTA_X_L);
00106         WAIT_TSRR();
00107         spiReceive(DELTA_X_H);
00108         WAIT_TSRR();
00109         spiReceive(DELTA_Y_L);
00110         WAIT_TSRR();
00111         spiReceive(DELTA_Y_H);
00112         
00113         // read product and revision id to test the connection
00114         WAIT_TSRR();
00115         int product_id = spiReceive(PRODUCT_ID);
00116         WAIT_TSRR();
00117         int revision_id = spiReceive(REVISION_ID);
00118 
00119         WAIT_TSCLKNCS();
00120         ncs_.write(1);
00121 
00122         if (product_id != 0x33) {
00123             error("ADNS9500::reset : bad product ID: 0x%x\n", product_id);
00124         }
00125 
00126         if (revision_id != 0x03) {
00127             error("ADNS9500::reset : bad revision ID: 0x%x\n", revision_id);
00128         }
00129 
00130         enabled_ = true;
00131 
00132         if (fw) {
00133             sromDownload(fw, fw_len);
00134             enableLaser();
00135         }
00136     }
00137 
00138     void ADNS9500::shutdown()
00139     {
00140         if (! enabled_)
00141             error("ADNS9500::shutdown : the sensor is not enabled\n");
00142         
00143         ncs_.write(0);
00144         WAIT_TNCSSCLK();
00145         
00146         // send 0x5a to POWER_UP_RESET
00147         spiSend(POWER_UP_RESET, 0x5a);
00148         
00149         WAIT_TSCLKNCS();
00150         ncs_.write(1);
00151         
00152         enabled_ = false;
00153     }
00154 
00155     int ADNS9500::read(Register lregister)
00156     {
00157         if (! enabled_)
00158             error("ADNS9500::read : the sensor is not enabled\n");
00159     
00160         ncs_.write(0);
00161         WAIT_TNCSSCLK();
00162         
00163         // send the command to read the register
00164         int value = spiReceive(lregister);
00165         
00166         WAIT_TSCLKNCS();
00167         ncs_.write(1);
00168 
00169         return value;
00170     }
00171 
00172     int ADNS9500::read(Register uregister, Register lregister)
00173     {
00174         if (! enabled_)
00175             error("ADNS9500::read : the sensor is not enabled\n");
00176 
00177         ncs_.write(0);
00178         WAIT_TNCSSCLK();
00179 
00180         // send the command to read the registers
00181         int lvalue = spiReceive(lregister);
00182         WAIT_TSRR();
00183         int uvalue = spiReceive(uregister);
00184 
00185         WAIT_TSCLKNCS();
00186         ncs_.write(1);
00187 
00188         return ADNS9500_UINT16(uvalue, lvalue);
00189     }
00190     
00191     int ADNS9500::sromDownload(const uint8_t* fw, uint16_t fw_len)
00192     {
00193         if (! enabled_)
00194             error("ADNS9500::sromDownload : the sensor is not enabled\n");
00195     
00196         ncs_.write(0);
00197         WAIT_TNCSSCLK();
00198 
00199         // SROM download
00200         spiSend(CONFIGURATION_IV, ADNS9500_CONFIGURATION_IV_SROM_SIZE);
00201         WAIT_TSWW();
00202         spiSend(SROM_ENABLE, 0x1d);
00203         LONG_WAIT_US(DEFAULT_MAX_FRAME_PERIOD);
00204 
00205         spiSend(SROM_ENABLE, 0x18);
00206         WAIT_TSWW();
00207         spi_.write(SET_BIT(SROM_LOAD_BURST, SPI_WRITE_MODE));
00208        
00209         for( uint16_t i = 0; i < fw_len; i++){
00210             WAIT_TLOAD();
00211             spi_.write(fw[i]);
00212         }
00213         WAIT_TSCLKNCS();
00214         ncs_.write(1);
00215         WAIT_TBEXIT();
00216 
00217         // test if SROM was downloaded successfully
00218         wait_us(160);
00219         ncs_.write(0);
00220         WAIT_TNCSSCLK();
00221         
00222         int srom_id = spiReceive(SROM_ID);
00223         
00224         printf("SROM ID: %x %i\r\n", srom_id, srom_id );
00225         WAIT_TSCLKNCS();
00226         ncs_.write(1);
00227         
00228         if (! srom_id)
00229             error("ADNS9500::sromDownload : the firmware was not successful downloaded\n");
00230 
00231         // test laser fault condition
00232         ncs_.write(0);
00233         WAIT_TNCSSCLK();
00234         
00235         int motion = spiReceive(MOTION);
00236         
00237         WAIT_TSCLKNCS();
00238         ncs_.write(1);
00239         
00240         if (ADNS9500_IF_LASER_FAULT(motion))
00241             error("ADNS9500::sromDownload : laser fault condition detected\n");
00242         
00243         // return the SROM CRC value
00244         ncs_.write(0);
00245         WAIT_TNCSSCLK();
00246         
00247         spiSend(SROM_ENABLE, 0x15);
00248         LONG_WAIT_MS(10);
00249         
00250         int lcrc = spiReceive(DATA_OUT_LOWER);
00251         WAIT_TSRR();
00252         int ucrc = spiReceive(DATA_OUT_UPPER);
00253         
00254         WAIT_TSCLKNCS();
00255         ncs_.write(1);
00256         return ADNS9500_UINT16(ucrc, lcrc);
00257     }
00258 
00259     void ADNS9500::enableLaser(bool enable)
00260     {
00261         if (! enabled_ ){
00262             error("ADNS9500::enableLaser : the sensor is not enabled\n");
00263         }
00264         
00265         ncs_.write(0);
00266         WAIT_TNCSSCLK();
00267 
00268         int laser_ctrl0 = spiReceive(LASER_CTRL0);
00269         
00270         ncs_.write(0);
00271         WAIT_TNCSSCLK();
00272   
00273         if (enable) {
00274             int laser_ctrl0 = CLEAR_BIT(0x00, ADNS9500_LASER_CTRL0_FORCE_DISABLED);
00275             spiSend(LASER_CTRL0, laser_ctrl0);
00276         }
00277         else {
00278             int laser_ctrl0 = SET_BIT(0x01, ADNS9500_LASER_CTRL0_FORCE_DISABLED);
00279             spiSend(LASER_CTRL0, laser_ctrl0);
00280         }        
00281 
00282         WAIT_TSCLKNCS();
00283         ncs_.write(1);
00284     }
00285     
00286     bool ADNS9500::getMotionDelta(int16_t& dx, int16_t& dy)
00287     {
00288         if (! enabled_)
00289             error("ADNS9500::getMotionDelta : the sensor is not enabled\n");
00290 
00291         ncs_.write(0);
00292         WAIT_TNCSSCLK();
00293 
00294         dx = 0;
00295         dy = 0;
00296 
00297         int motion = spiReceive(MOTION);
00298         
00299         if (ADNS9500_IF_MOTION(motion)) {
00300             WAIT_TSRR();
00301             int dxl = spiReceive(DELTA_X_L);
00302             WAIT_TSRR();
00303             dx = ADNS9500_INT16(spiReceive(DELTA_X_H), dxl);
00304             
00305             WAIT_TSRR();
00306             int dyl = spiReceive(DELTA_Y_L);
00307             WAIT_TSRR();
00308             dy = ADNS9500_INT16(spiReceive(DELTA_Y_H), dyl);
00309         }
00310         WAIT_TSCLKNCS();
00311         ncs_.write(1);
00312         
00313         return ADNS9500_IF_MOTION(motion);
00314     }
00315     
00316     bool ADNS9500::getMotionDeltaMM(float& dx, float& dy)
00317     {
00318         int16_t rawDx, rawDy;
00319         bool motion = getMotionDelta(rawDx, rawDy);
00320         dx = (float)rawDx / xCpi_ * 25.4;
00321         dy = (float)rawDy / yCpi_ * 25.4;
00322 
00323         return motion;
00324     }
00325 
00326     bool ADNS9500::getMotionData(MotionData& data)
00327     {
00328         if (! enabled_)
00329             error("ADNS9500::getMotionData : the sensor is not enabled\n");
00330     
00331         ncs_.write(0);
00332         WAIT_TNCSSCLK();
00333         
00334         // activate motion burst mode
00335         spi_.write(0x50);
00336         WAIT_TSRAD();   // see the chronogram
00337         
00338         // read motion burst data
00339         data.motion = spi_.write(0x00);
00340         data.observation = spi_.write(0x00);
00341         
00342         int ldx = spi_.write(0x00);
00343         data.dx = ADNS9500_INT16(spi_.write(0x00), ldx);
00344         
00345         int ldy = spi_.write(0x00);
00346         data.dy = ADNS9500_INT16(spi_.write(0x00), ldy);
00347         
00348         data.surfaceQuality = spi_.write(0x00) * 4;
00349         data.averagePixel = spi_.write(0x00) / 1.76;
00350         data.maximumPixel = spi_.write(0x00);
00351         data.minimumPixel = spi_.write(0x00);
00352         
00353         int ushutter = spi_.write(0x00);
00354         data.shutter = ADNS9500_UINT16(ushutter, spi_.write(0x00));
00355         
00356         int uframe_period = spi_.write(0x00);
00357         data.framePeriod = ADNS9500_UINT16(uframe_period, spi_.write(0x00));
00358 
00359         WAIT_TSCLKNCS();
00360         ncs_.write(1);
00361         WAIT_TBEXIT();
00362 
00363         data.dxMM = (float)data.dx / xCpi_ * 25.4;
00364         data.dyMM = (float)data.dy / yCpi_ * 25.4;
00365 
00366         // write a value to Motion register to clear motion bit
00367         ncs_.write(0);
00368         WAIT_TNCSSCLK();
00369         
00370         spiSend(MOTION, 0x00);
00371 
00372         WAIT_TSCLKNCS();
00373         ncs_.write(1);
00374 
00375         return ADNS9500_IF_MOTION(data.motion);
00376     }
00377     
00378     void ADNS9500::setResolution( uint16_t cpi_xy )
00379     {
00380         
00381         if (! enabled_)
00382             error("ADNS9500::setResolution : the sensor is not enabled\n");
00383 
00384         int res_xy = cpi_to_res(cpi_xy);
00385         
00386         ncs_.write(0);
00387         WAIT_TNCSSCLK();
00388         
00389         // enable XY axes CPI in sync mode
00390         int rpt_mod = spiReceive(CONFIGURATION_II);
00391         rpt_mod = CLEAR_BIT(rpt_mod, ADNS9500_CONFIGURATION_II_RPT_MOD);
00392         WAIT_TSRW();
00393         spiSend(CONFIGURATION_II, rpt_mod);
00394 
00395         // set resolution for X-axis and Y-axis
00396         WAIT_TSWW();
00397         spiSend(CONFIGURATION_I, res_xy);
00398 
00399         WAIT_TSCLKNCS();
00400         ncs_.write(1);
00401         
00402         xCpi_ = res_xy * CPI_CHANGE_UNIT;
00403         yCpi_ = res_xy * CPI_CHANGE_UNIT;
00404     }
00405     
00406     void ADNS9500::setResolution(uint16_t cpi_x, uint16_t cpi_y)
00407     {
00408         if (! enabled_)
00409             error("ADNS9500::setResolution : the sensor is not enabled\n");
00410         
00411         int res_x = cpi_to_res(cpi_x);
00412         int res_y = cpi_to_res(cpi_y);
00413            
00414         ncs_.write(0);
00415         WAIT_TNCSSCLK();
00416 
00417         // disable XY axes CPI in sync mode
00418         int rpt_mod = spiReceive(CONFIGURATION_II);
00419         rpt_mod = SET_BIT(rpt_mod, ADNS9500_CONFIGURATION_II_RPT_MOD);
00420         WAIT_TSRW();
00421         spiSend(CONFIGURATION_II, rpt_mod);
00422         
00423         // set resolution for X-axis
00424         WAIT_TSWW();
00425         spiSend(CONFIGURATION_I, res_x);
00426                 
00427         // set resolution for Y-axis
00428         WAIT_TSWW();
00429         spiSend(CONFIGURATION_V, res_y);
00430 
00431         WAIT_TSCLKNCS();
00432         ncs_.write(1);
00433 
00434         xCpi_ = res_x * CPI_CHANGE_UNIT;
00435         yCpi_ = res_y * CPI_CHANGE_UNIT;
00436     }
00437     
00438     void ADNS9500::captureFrame(uint8_t* pixels)
00439     {
00440         if (! enabled_)
00441             error("ADNS9500::captureFrame : the sensor is not enabled\n");
00442             
00443         ncs_.write(0);
00444         WAIT_TNCSSCLK();
00445         
00446         spiSend(FRAME_CAPTURE, 0x93);
00447         WAIT_TSWW();
00448         spiSend(FRAME_CAPTURE, 0xc5);
00449         LONG_WAIT_US(2*DEFAULT_MAX_FRAME_PERIOD);
00450 
00451         // check for first pixel reading motion bit
00452         int motion = spiReceive(MOTION);
00453         WAIT_TSRR();
00454         while(! ADNS9500_IF_FRAME_FIRST_PIXEL(motion)) {
00455             int motion = spiReceive(MOTION);
00456             WAIT_TSRR();
00457         }
00458 
00459         // read pixel values
00460         spi_.write(PIXEL_BURST);
00461         WAIT_TSRAD();
00462         for (uint8_t* p = pixels; p != pixels + NUMBER_OF_PIXELS_PER_FRAME; ++p) {
00463             *p = spi_.write(0x00);
00464             WAIT_TLOAD();
00465         }
00466 
00467         // burst exit
00468         ncs_.write(1);
00469         WAIT_TBEXIT();
00470     }
00471     
00472     void ADNS9500::spiSend(Register address, int value)
00473     {
00474         spi_.write(SET_BIT(address, SPI_WRITE_MODE));
00475         spi_.write(value);
00476     }
00477 
00478     int ADNS9500::spiReceive(Register address)
00479     {
00480         spi_.write(CLEAR_BIT(address, SPI_WRITE_MODE));
00481         WAIT_TSRAD();
00482         return spi_.write(0x00);
00483     }
00484 }