Trackball based on the NXP LPC11U24 and the ADNS-9500

Dependencies:   ADNS9500 USBDevice mbed 25LCxxx_SPI

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* 
00002  *  loststone is free sofware: you can redistribute it and/or modify
00003  *  it under the terms of the GNU General Public License 3 as published by
00004  *  the Free Software Foundation.
00005  *
00006  *  loststone is distributed in the hope that it will be useful,
00007  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00008  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00009  *  GNU General Public License for more details.
00010  * 
00011  *  You should have received a copy of the GNU General Public License
00012  *  along with loststone. If not, see <http://www.gnu.org/licenses/gpl.txt>.
00013  *
00014  *  Copyright (c) 2012-2013 Chris Majoros(chris@majoros.us), GNU3
00015  */
00016 
00017 #include "main.h"
00018 
00019 
00020 int main(void)
00021 {
00022     
00023     printf("And away we go.\n\r");
00024     activity = 1;
00025     run_mode.mode(PullUp);
00026     Ser25LCxxx *eeprom;
00027     
00028     #ifdef MBED
00029     SPI eeprom_spi( p11, p12, p13); // mosi, miso, sclk 
00030     #elif
00031     SPI eeprom_spi( P0_21, P0_22, P1_20); // mosi, miso, sclk 
00032     #endif
00033     
00034     eeprom_spi.format(8,3);
00035     eeprom_spi.frequency(1000000);
00036     
00037     #ifdef MBED
00038     eeprom = new Ser25LCxxx( &eeprom_spi, p15, 0x10000, 0x20 ); 
00039     #elif
00040     eeprom = new Ser25LCxxx( &eeprom_spi, P1_27, 0x10000, 0x20 ); 
00041     #endif
00042 
00043     //retreave default and system settings from the EEPROM and override the default values.
00044     printf("Loading settings\n\r");
00045     for( int i = 0; i < sizeof(s)/sizeof(uint16_t); i++ ){
00046         printf("Setting %d: %X\r\n", i, s[i]);
00047         //set_setting( eeprom, i, s[i], SETTINGS_BASE ); 
00048         //s[i] = get_setting( eeprom, i, SETTINGS_BASE );
00049         printf("Setting %d: %X\r\n", i, s[i]);
00050     }
00051     
00052     //eeprom->write( s[ADNS_FW_OFFSET], ADNS9500_FIRMWARE_LEN, adns9500FWArray );
00053     
00054     if( run_mode ){
00055         printf("Tracking mode\n\r");
00056         track( eeprom );
00057     }
00058     else{
00059         printf("Programming mode\n\r");
00060         program( eeprom );
00061     }
00062 }
00063 
00064 void track( Ser25LCxxx *eeprom ){
00065     activity = 0;
00066     /* 
00067     * mosi miso sclk ncs FREQ, motion
00068     */
00069     mouse = new USBMouse( REL_MOUSE, s[VID], s[PID], s[RELEASE]) ;
00070 
00071     /* 
00072      * mosi == p5 / P0_9
00073      * miso == p6 / P0_8
00074      * sclk == p7 / P0_10
00075      * ncs  == p8 / P1_16
00076      * spi_frequency = MAX_SPI_FREQUENCY
00077      * motion == p14 / P0_22
00078      */
00079 
00080     printf("Creating sensor object\n\r");
00081     #ifdef MBED
00082     adns9500::ADNS9500 sensor(p5, p6, p7, p8, adns9500::MAX_SPI_FREQUENCY);
00083     #elif
00084     adns9500::ADNS9500 sensor(P0_9, P0_8, P0_10, P1_16, adns9500::MAX_SPI_FREQUENCY); 
00085     #endif
00086     
00087     static fn press_funcs[] = {
00088         btn_l_press,
00089         btn_m_press,
00090         btn_r_press,
00091         btn_f_press,
00092         btn_b_press,
00093         btn_z_press,
00094         btn_hr_press};
00095         
00096     static fn release_funcs[] = {
00097         btn_l_release,
00098         btn_m_release,
00099         btn_r_release,
00100         btn_f_release,
00101         btn_b_release,
00102         btn_z_release,
00103         btn_hr_release};
00104         
00105     printf("Inisializing buttons\n\r");
00106 
00107 // Mouse buttons 
00108     btn_a.mode(PullNone);
00109     btn_a.fall(press_funcs[s[BTN_A]]);
00110     btn_a.rise(release_funcs[s[BTN_A]]);
00111     
00112     btn_b.mode(PullNone);
00113     btn_b.fall(press_funcs[s[BTN_B]]);
00114     btn_b.rise(release_funcs[s[BTN_B]]);
00115 
00116     btn_c.mode(PullNone);
00117     btn_c.fall(press_funcs[s[BTN_C]]);
00118     btn_c.rise(release_funcs[s[BTN_C]]);
00119     
00120     btn_d.mode(PullNone);
00121     btn_d.fall(press_funcs[s[BTN_D]]);
00122     btn_d.rise(release_funcs[s[BTN_D]]);
00123     
00124     btn_e.mode(PullNone);
00125     btn_e.fall(press_funcs[s[BTN_E]]);
00126     btn_e.rise(release_funcs[s[BTN_E]]);
00127     
00128     btn_f.mode(PullNone);
00129     btn_f.fall(press_funcs[s[BTN_F]]);
00130     btn_f.rise(release_funcs[s[BTN_F]]);
00131 
00132     btn_g.mode(PullNone);
00133     btn_g.fall(press_funcs[s[BTN_G]]);
00134     btn_g.rise(release_funcs[s[BTN_G]]);
00135 
00136 // Profile buttons
00137     prfl_a.mode(PullUp);
00138     prfl_a.fall(&prfl_a_set);
00139     prfl_a.rise(&prfl_stub);
00140     
00141     prfl_b.mode(PullUp);
00142     prfl_b.fall(&prfl_b_set);
00143     prfl_b.rise(&prfl_stub);
00144     
00145     prfl_c.mode(PullUp);
00146     prfl_c.fall(&prfl_c_set);
00147     prfl_c.rise(&prfl_stub);
00148     
00149     prfl_d.mode(PullUp);
00150     prfl_d.fall(&prfl_d_set);
00151     prfl_d.rise(&prfl_stub);
00152     
00153     prfl_e.mode(PullUp);
00154     prfl_e.fall(&prfl_e_set);
00155     prfl_e.rise(&prfl_stub);
00156     
00157     debug.mode(PullUp);
00158     debug.fall(&debug_out);
00159     debug.rise(&debug_out);
00160     
00161     int16_t dx, dy;
00162     float mx, my;
00163 
00164     sensor.reset();
00165 
00166     uint8_t *adns_fw;
00167 
00168     //eeprom->write(ADNS_FW_OFFSET, ADNS_FW_LEN, adns9500FWArray);
00169     //adns_fw = eeprom->read( ADNS_FW_OFFSET, ADNS_FW_LEN );
00170 //eeprom->write( s[ADNS_FW_OFFSET], ADNS9500_FIRMWARE_LEN, adns9500FWArray );
00171 
00172     activity = 1;
00173     printf("Loading sensor firmware\r\n");
00174     uint16_t crc = sensor.sromDownload( adns9500FWArray, ADNS9500_FIRMWARE_LEN ); //FIXME
00175 
00176     if( ADNS6010_FIRMWARE_CRC != crc ){ //ADNS6010_FIRMWARE_CRC
00177         printf("Firmware CRC does not match [%X] [%X]\n\r",
00178                ADNS6010_FIRMWARE_CRC,
00179                crc);             
00180         while (true){
00181             activity = 0;
00182             wait(0.2);
00183             activity = 1;
00184             wait(0.2);
00185         }
00186     }
00187     else{
00188         activity = 0;
00189         printf("Firmware CRC matches [%X] [%X]\n\r",
00190            ADNS6010_FIRMWARE_CRC,
00191            crc);
00192     }
00193 
00194     // The firmware was set correctly. Freeing the 3K! of ram.
00195     //delete adns_fw;
00196 
00197     printf("Enableing lazer\n\r");
00198     sensor.enableLaser();
00199     sensor.setResolution( s[CPI_X], s[CPI_Y] );
00200 
00201     printf("Starting Loop\n\r");
00202     activity = 1;
00203     //rest_counter = 0;
00204     while (true){
00205         //rest_counter++;
00206         /*
00207          * Moved the setResolution calls out of the interupt callbacks as they
00208          * havequite a few waits in them. I am hopping this is the reasion why
00209          * the hr and z buttons on occation stick or don't work the first time
00210          * you press them.
00211          */
00212         if( set_res_hr ){
00213             printf("Setting High hez\n\r");
00214             set_res_hr = false;
00215             sensor.setResolution( s[CPI_HR_X], s[CPI_HR_Y] );
00216         }
00217         
00218         if( set_res_z ){
00219             printf("Setting Z rez\n\r");
00220             set_res_z = false;
00221             sensor.setResolution( s[CPI_Z], s[CPI_H] );
00222         }
00223         
00224         if( set_res_default ){
00225             printf("Setting default rez\n\r");
00226             set_res_default = false;
00227             sensor.setResolution( s[CPI_X], s[CPI_Y] );
00228         }
00229               
00230         if( !motion_in){
00231 
00232             motion_triggered = false;
00233 
00234             sensor.getMotionDelta(dx, dy);
00235             if( dx == 0 and dy == 0 ){
00236                 // FIXME: why is the ADNS9500 dropping the motion pin and then
00237                 // giving me no motion? Do I have somthing wired up wrong?
00238                 continue;
00239             }
00240             /*
00241              * The sensor is not aware of its orientation so we need to muck
00242              * with the values a it.
00243              */
00244             if( z_axis_active ){
00245                 printf("scroll,%X,%X,\n\r", -dx, dy);
00246                 mouse->scroll( dy, - dx );
00247             }
00248             else{
00249                 
00250                 mx = (float(abs(dx))/float(s[CPI_X_MULITIPLYER]) + 1.0);
00251                 my = (float(abs(dy))/float(s[CPI_Y_MULITIPLYER]) + 1.0);
00252                 
00253                 printf("motion,%X,%X %.4f,%.4f %X,%X\n\r", -dx, dy, mx, my, int(- (dx * mx)), int(dy * my) );
00254 
00255                 mouse->move( - (dx * mx), (dy * my) ); 
00256                 //printf("rest_coutner,%d\n\r", rest_counter);
00257                 //rest_counter = 0;
00258             }
00259         }
00260         
00261 
00262         // Load the current profile.
00263         // This rights the first 10 16bit values of the s array from the selected profile.
00264         //
00265         // Base is calculated...
00266         //     selected profile * profile length * 2 + profile base
00267         //
00268         //     (3 * 7 * 2) + 64  (multiplying by two because they are 16bit values.
00269         // TODO: should i move this to a function?
00270         if( profile_load ){
00271         //    for( int i = 0; i < PROFILE_LEN; i++ ){
00272         //        //s[i] = get_setting( eeprom, i, (s[PROFILE_CURRENT] * PROFILE_LEN) + PROFILE_BASE );
00273         //    }
00274         //    sensor.setResolution( s[CPI_X], s[CPI_Y] );
00275             profile_load = false;
00276         }
00277     }
00278 }
00279 
00280 void program( Ser25LCxxx *eeprom ){
00281 
00282     
00283     //USBHID *hid = new USBHID( 64, 64, 0x192f, 0x0, 0x0);
00284     USBHID *hid = new USBHID();
00285     //This report will contain data to be sent
00286     HID_REPORT send_rep;
00287     HID_REPORT recv_rep;
00288     
00289     send_rep.length = 64;
00290     uint16_t base;
00291     uint16_t len;
00292     //Fill the report
00293     for (int i = 0; i < send_rep.length; i++) {
00294         send_rep.data[i] = rand() & 0xff;
00295     }
00296             
00297     //Send the report
00298     //hid->send(&send_rep);
00299 
00300     uint8_t *tmp;
00301 
00302     printf("Entering loop\n\r");
00303     while (1) {
00304         if( hid->readNB(&recv_rep)) {
00305             printf("Receaved some data.\n\r");
00306             switch ((recv_rep.data[0])){
00307                 case SET:
00308                     //set_setting( eeprom, recv_rep.data[1], UINT16(recv_rep.data[2],recv_rep.data[3]));
00309                     break;
00310                 case GET:
00311                     //tmp = get_setting( eeprom, recv_rep.data[1] );
00312                         
00313                     //send_rep.data[0] = (int)tmp;
00314                     //send_rep.data[1] = (int)(tmp >> 8);
00315                         
00316                     //hid->send(&send_rep);
00317                     
00318                     break;
00319                 case CLEAR:
00320                     //clear_setting( eeprom, recv_rep.data[1] );
00321                     break;
00322                 case INIT:
00323                     eeprom->clearMem();
00324                     break;
00325                 case LOAD_DATA:
00326                     printf("LOADING DATA\n\r");
00327                     base = UINT16( recv_rep.data[1], recv_rep.data[2] );
00328                     len  = recv_rep.data[3];
00329                     printf("BASE: %X LEN: %X\n\r", base, len);
00330                     load_data( eeprom, base, len, &recv_rep.data[4] );
00331                     wait(0.1);
00332                     tmp = get_data( eeprom, base, len );
00333                     printf("BASE: %X LEN: %X\n\r", base, len);
00334                     for( uint16_t i=0; i < (len); i++){
00335                         printf("%X\n\r", tmp[i]);
00336                         send_rep.data[i] = tmp[i]; //FIXME
00337                     }
00338                     hid->send(&send_rep);
00339                     delete( tmp);
00340                     break;
00341                 case GET_DATA:
00342                     //base = UINT16( recv_rep.data[1], recv_rep.data[2] );
00343                     //len  = UINT16( recv_rep.data[3], recv_rep.data[4] );
00344                     //tmp = get_data( Ser25LCxxx *eeprom, uint16_t base, uint16_t len ){
00345                 default:
00346                     // FIXME: error handling.
00347                     break;
00348             }
00349         }
00350     }
00351 }
00352 
00353 void btn_l_press(){
00354     printf("button,left,press\n\r");
00355     mouse->press(MOUSE_LEFT);
00356 }
00357 void btn_l_release(){
00358     printf("button,left,release\n\r");
00359     mouse->release(MOUSE_LEFT);
00360 }
00361 
00362 void btn_m_press(){
00363     //mouse->press(MOUSE_MIDDLE);
00364 }
00365 void btn_m_release(){
00366     //mouse->release(MOUSE_MIDDLE);
00367 }
00368 
00369 void btn_r_press(){
00370     printf("button,right,press\n\r");
00371     mouse->press(MOUSE_RIGHT);
00372 }
00373 
00374 void btn_r_release(){
00375     printf("button,right,release\n\r");
00376     mouse->release(MOUSE_RIGHT);
00377 }
00378 
00379 void btn_f_press(){
00380     printf("button,forword,press\n\r");
00381     mouse->press(MOUSE_FORWORD);
00382 }
00383 void btn_f_release(){
00384     printf("button,forword,release\n\r");
00385     mouse->release(MOUSE_FORWORD);
00386 }
00387 
00388 void btn_b_press(){
00389     printf("button,back,press\n\r");
00390     mouse->press(MOUSE_BACK);
00391 }
00392 
00393 void btn_b_release(){
00394     printf("button,back,release\n\r");
00395     mouse->release(MOUSE_BACK);
00396 }
00397 
00398 void btn_hr_press(){
00399     printf("button,high_res,press\n\r");
00400     set_res_hr = true;
00401     set_res_default = false;
00402     high_rez_active = true;
00403 }
00404 void btn_hr_release(){
00405     printf("button,high_res,release\n\r");
00406     set_res_hr = false;
00407     set_res_default = true;
00408     high_rez_active = false;
00409 }
00410 
00411 void btn_z_press(){
00412     printf("button,z,press\n\r");
00413     set_res_z = true;
00414     set_res_default = false;
00415     z_axis_active = true;
00416 }
00417 void btn_z_release(){
00418     printf("button,z,release\n\r");
00419     set_res_z = false;
00420     set_res_default = true;
00421     z_axis_active = false;
00422 }
00423 
00424 void prfl_a_set(){
00425     s[PROFILE_CURRENT] = 0;
00426     profile_load = true;
00427 }
00428 
00429 void prfl_b_set(){
00430     s[PROFILE_CURRENT] = 1;
00431     profile_load = true;
00432 }
00433 
00434 void prfl_c_set(){
00435     s[PROFILE_CURRENT] = 2;
00436     profile_load = true;
00437 }
00438 
00439 void prfl_d_set(){
00440     s[PROFILE_CURRENT] = 3;
00441     profile_load = true;
00442 }
00443 
00444 void prfl_e_set(){
00445     s[PROFILE_CURRENT] = 4;
00446     profile_load = true;
00447 }
00448 
00449 void prfl_stub(){
00450 }
00451 
00452 void debug_out(){
00453 printf("motion_triggerd %d\n\r" , motion_triggered);
00454 printf("z_axis_active %d\n\r", z_axis_active);
00455 printf("high_rez_active %d\n\r", high_rez_active);
00456 printf("profile_load %d\n\r", profile_load); // Always inishally load the profile even if it might be the same.
00457 printf("set_res_hr %d\n\r", set_res_hr);
00458 printf("set_res_z %d\n\r" , set_res_z);
00459 printf("set_res_default %d\n\r", set_res_default);
00460 }
00461 
00462 /*
00463  * The settings are kept in the first 'N' addresses of the of the EEPROM.
00464  * They are 16bits long. The default settings are in a uint16_t array. So
00465  * to set/get a setting you use the array value and multiple it by two.
00466  * This way I can easily get all setting at the start of the program by
00467  * simply looping through the array.
00468  */
00469 
00470 
00471 int set_setting( Ser25LCxxx *eeprom, uint16_t attrib, uint16_t val, uint16_t base_address ){
00472 
00473     uint8_t hl[2];
00474     
00475     // TODO: Its working but is it working the way i think its working
00476     hl[0] = (int)val;
00477     hl[1] = (int)(val >> 8);
00478     
00479     printf("Set Setting %d: L[%X] H[%X]\n\r", attrib, hl[0], hl[1] );
00480 
00481     if ( eeprom->write( attrib * 2, 0x2, hl )){
00482         return true;
00483     }
00484     return false;
00485 }
00486 
00487 uint16_t get_setting( Ser25LCxxx *eeprom, uint16_t attrib, uint16_t base_address ){
00488     
00489     uint16_t val;
00490     uint8_t *hl;
00491     
00492     hl = eeprom->read( (attrib * 2) + base_address, 0x2 );
00493     printf("Get Setting %d: L[%X] H[%X]\n\r", attrib, hl[0], hl[1] );
00494     val = UINT16( hl[1], hl[0] );
00495     if( val != 0xFFFF ){
00496         return val;
00497     }
00498 
00499     return s[attrib];
00500 }
00501 
00502 void clear_setting( Ser25LCxxx *eeprom, uint16_t attrib, uint16_t base_address ){
00503     uint8_t val[2];
00504     val[0] = val[1] = 0xFF;
00505     eeprom->write( (attrib * 2) + base_address , 0x2, val );
00506 }
00507 
00508 
00509 /*
00510  * Getting and setting the firmware is a bit easer as it is all 8bit.
00511  */
00512 void load_data( Ser25LCxxx *eeprom, uint16_t base, uint16_t len, const uint8_t* data ){
00513     eeprom->write( base , len, data );
00514 }
00515 
00516 uint8_t* get_data( Ser25LCxxx *eeprom, uint16_t base, uint16_t len ){
00517     return (uint8_t*)eeprom->read( base, len );
00518 }