ADNS2051 Optical Sensor library
ADNS2051.cpp
- Committer:
- clemente
- Date:
- 2012-05-23
- Revision:
- 0:462017ee2a5b
File content as of revision 0:462017ee2a5b:
/* mbed ADNS2051 Optical Sensor library. Copyright (c) 2011 NXP 3787 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "mbed.h" #include "ADNS2051.h" #define SCLK_HIGH _sclk=1; #define SCLK_LOW _sclk=0; // #define SOUT_HIGH _sout=1; #define SOUT_LOW _sout=0; // #define CLKSPEED_100KHZ 10 #define CLKSPEED_200KHZ 5 #define CLKSPEED_500KHZ 2 #define CLKSPEED_1MHZ 1 #define CLKSPEED CLKSPEED_1MHZ // unsigned char pixmap[256]; ADNS2051::ADNS2051( PinName sout, PinName sclk) : _sout( sout), _sclk( sclk) { _sout.output(); } /* Init the ADNS 2051 connection. @return 0 = OK 1 = BAD connection */ unsigned char ADNS2051::init( void) { // sync the communication line to the ADNS chip sync(); // check the connection return ( chkconn()); // for now I use the ADNS's default values. } /* * Sync the communication to the ADNS. * Start a sequence, and then wait the watchdog timer expire. * After this sequence the sout and sclk are HIGH and ready to star a correct * write to or read from the ADNS chip. */ void ADNS2051::sync( void) { // let the data pin as output! _sout.output(); // SOUT_HIGH; SCLK_HIGH; wait_us(100); SCLK_LOW; wait_us(100); SCLK_HIGH; wait_us(100); /* the program wait until the ADNS's serial watchdog timer expire */ wait_ms( 1200); // Serial Port Transaction Timer [Tsptt] value: 1s (DS pag:10) } /* Verify the ADNS 2051 connection. return: 0 = OK 1 = BAD connection */ unsigned char ADNS2051::chkconn( void) { if ( read( PRODUCTID_REG) == PRODUCTID_VAL) return 0; else return 1; } /* */ unsigned char ADNS2051::get_productID( void) { return read( PRODUCTID_REG); } /* */ unsigned char ADNS2051::get_revisionID( void) { return read( REVISIONID_REG); } /** Change the default frame rate (1500 f/s) to 2300 f/s */ void ADNS2051::setframerate( void) { // write to the lower reg first. // the values are 2's compl hex for 2300 f/s (DS pag:38) write( FRMPRDLW_REG, 0x6E); write( FRMPRDUP_REG, 0xE1); } /** Return the SQUAL value. * * SQUAL is a measure of the number of features visible by the sensor in the * current frame. The maximum value is 255. Since small changes in the current frame * can result in changes in SQUAL, variations in SQUAL when looking at a surface are * expected. SQUAL is nearly equal to zero, if there is no surface below the sensor. */ unsigned char ADNS2051::surfacequality( void) { return read( SQUAL_REG); } /** Return the Average pixel value * * Average Pixel value in current frame. Minimum value = 0, * maximum = 63. The average pixel value can be adjusted every frame. */ unsigned char ADNS2051::averagepixel( void) { return read( AVRPXL_REG); } /** Return the Maximum Pixel value * * Maximum Pixel value in current frame. Minimum value = 0, * maximum value = 63. The maximum pixel value can be adjusted every frame. */ unsigned char ADNS2051::maxpixelval( void) { return read( MAXPXL_REG); } /** * read the motion register and update the deltaX and deltaY variable with the register value * * @return : * value 0 => no motion, no led fault, no overflow * bit 0 == 1 => motion * bit 1 == 1 => led fault * bit 3 == 1 => overflow */ unsigned char ADNS2051::readmotion( void) { unsigned char status; unsigned char res=0; // no motion, no LED fault... // Avago RECOMMENDS that registers 0x02, 0x03 and 0x04 be read sequentially status = read( MOTION_REG); deltaX = read( DELTAX_REG); deltaY = read( DELTAY_REG); // if ( status & (1<<OVERFY_BIT) || status & (1<<OVERFX_BIT) ) { res|=4; } // if ( status & (1<<RESOLUTION_BIT) ) currentresolution=800; else currentresolution=400; // if ( status & (1<<MOTION_BIT) ) res|=1; if ( status & (1<<LEDFAULT_BIT) ) res|=2; return( res); } /* Start the dump of the pixel map. Store the value to the array pixmap */ void ADNS2051::pixeldump( unsigned char *buffer) { unsigned char res; unsigned char i; // set no sleep and start pixdump write( CONFIGBIT_REG, 0x00 | (1<<SLEEP_BIT) | (1<<PIXDUMP_BIT)); i=0; while( 1) { // read the pix address... res=read( DTOUTUP_REG); // read the pix value res=read( DTOUTLW_REG); // if the MSB is set: no valid data... if ( res & (1<<PIXDATAVALID_BIT)) continue; // store the pix value buffer[i++]=res; // check if the pixel counter overflow... if ( i==0) break; } // reset PixDump bit. write( CONFIGBIT_REG, 0x00); } /* * Read a register from the ADNS2051 sensor. * Before to return wait 120us as required and set the IO pin as output. */ unsigned char ADNS2051::read(unsigned char address) { unsigned char value; int bit_pos; SCLK_HIGH; // Set the clock high. address &= 0x7F; // A '0' as its MSB to indicate data direction as "READ". /* Send the Address to the ADNS2051 */ for( bit_pos=7; bit_pos >=0; bit_pos--){ SCLK_LOW; // Set the clock LOW // SDIO is changed on falling edges of SCLK if(address & (1<<bit_pos)){ SOUT_HIGH; } else{ SOUT_LOW; } // wait_us( CLKSPEED); SCLK_HIGH; wait_us( CLKSPEED); } /* SCLK will need to be delayed after the last address data bit to ensure that the ADNS-2051 has at least 100 µs to prepare the requested data (DS pag.19) */ wait_us(120); // Change the sout to input... _sout.input(); _sout.mode( PullUp); /* Read the data byte from the ADNS2051 */ value=0; for( bit_pos=7; bit_pos >= 0; bit_pos--){ SCLK_LOW; wait_us( CLKSPEED); SCLK_HIGH; // data is ready on rising edge of clock signal. wait_us( CLKSPEED); /* read the input pin */ if ( _sout) value |= (1<<bit_pos); } // _sout.output(); // Timing between read and either write or subsequent read commands must be >120us wait_us( 120); return value; } void ADNS2051::write(unsigned char address, unsigned char value) { int bit_pos; SCLK_HIGH; // Set the clock high. address |= 0x80; // A '1' as its MSB to indicate data direction as "WRITE". /* Send the Address to the ADNS2051 */ for( bit_pos=7; bit_pos >=0; bit_pos--){ SCLK_LOW; // Set the clock LOW // SDIO is changed on falling edges of SCLK if(address & (1<<bit_pos)){ SOUT_HIGH; } else{ SOUT_LOW; } // wait_us( CLKSPEED); SCLK_HIGH; wait_us( CLKSPEED); } /* Send the value to the ADNS2051 */ for( bit_pos=7; bit_pos >=0; bit_pos--){ SCLK_LOW; // Set the clock LOW // SDIO is changed on falling edges of SCLK if(value & (1<<bit_pos)){ SOUT_HIGH; } else{ SOUT_LOW; } // wait_us( CLKSPEED); SCLK_HIGH; wait_us( CLKSPEED); } // Timing between read and either write or subsequent read commands must be >120us wait_us( 120); }