Trackball based on the NXP LPC11U24 and the ADNS-9500
Dependencies: ADNS9500 USBDevice mbed 25LCxxx_SPI
main.cpp
- Committer:
- xxann5
- Date:
- 2013-03-14
- Revision:
- 9:ee05aa95f5c9
- Parent:
- 8:5674f5ab61cd
File content as of revision 9:ee05aa95f5c9:
/* * loststone is free sofware: you can redistribute it and/or modify * it under the terms of the GNU General Public License 3 as published by * the Free Software Foundation. * * loststone is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with loststone. If not, see <http://www.gnu.org/licenses/gpl.txt>. * * Copyright (c) 2012-2013 Chris Majoros(chris@majoros.us), GNU3 */ #include "main.h" int main(void) { printf("And away we go.\n\r"); activity = 1; run_mode.mode(PullUp); Ser25LCxxx *eeprom; #ifdef MBED SPI eeprom_spi( p11, p12, p13); // mosi, miso, sclk #elif SPI eeprom_spi( P0_21, P0_22, P1_20); // mosi, miso, sclk #endif eeprom_spi.format(8,3); eeprom_spi.frequency(1000000); #ifdef MBED eeprom = new Ser25LCxxx( &eeprom_spi, p15, 0x10000, 0x20 ); #elif eeprom = new Ser25LCxxx( &eeprom_spi, P1_27, 0x10000, 0x20 ); #endif //retreave default and system settings from the EEPROM and override the default values. printf("Loading settings\n\r"); for( int i = 0; i < sizeof(s)/sizeof(uint16_t); i++ ){ printf("Setting %d: %X\r\n", i, s[i]); //set_setting( eeprom, i, s[i], SETTINGS_BASE ); //s[i] = get_setting( eeprom, i, SETTINGS_BASE ); printf("Setting %d: %X\r\n", i, s[i]); } //eeprom->write( s[ADNS_FW_OFFSET], ADNS9500_FIRMWARE_LEN, adns9500FWArray ); if( run_mode ){ printf("Tracking mode\n\r"); track( eeprom ); } else{ printf("Programming mode\n\r"); program( eeprom ); } } void track( Ser25LCxxx *eeprom ){ activity = 0; /* * mosi miso sclk ncs FREQ, motion */ mouse = new USBMouse( REL_MOUSE, s[VID], s[PID], s[RELEASE]) ; /* * mosi == p5 / P0_9 * miso == p6 / P0_8 * sclk == p7 / P0_10 * ncs == p8 / P1_16 * spi_frequency = MAX_SPI_FREQUENCY * motion == p14 / P0_22 */ printf("Creating sensor object\n\r"); #ifdef MBED adns9500::ADNS9500 sensor(p5, p6, p7, p8, adns9500::MAX_SPI_FREQUENCY); #elif adns9500::ADNS9500 sensor(P0_9, P0_8, P0_10, P1_16, adns9500::MAX_SPI_FREQUENCY); #endif static fn press_funcs[] = { btn_l_press, btn_m_press, btn_r_press, btn_f_press, btn_b_press, btn_z_press, btn_hr_press}; static fn release_funcs[] = { btn_l_release, btn_m_release, btn_r_release, btn_f_release, btn_b_release, btn_z_release, btn_hr_release}; printf("Inisializing buttons\n\r"); // Mouse buttons btn_a.mode(PullNone); btn_a.fall(press_funcs[s[BTN_A]]); btn_a.rise(release_funcs[s[BTN_A]]); btn_b.mode(PullNone); btn_b.fall(press_funcs[s[BTN_B]]); btn_b.rise(release_funcs[s[BTN_B]]); btn_c.mode(PullNone); btn_c.fall(press_funcs[s[BTN_C]]); btn_c.rise(release_funcs[s[BTN_C]]); btn_d.mode(PullNone); btn_d.fall(press_funcs[s[BTN_D]]); btn_d.rise(release_funcs[s[BTN_D]]); btn_e.mode(PullNone); btn_e.fall(press_funcs[s[BTN_E]]); btn_e.rise(release_funcs[s[BTN_E]]); btn_f.mode(PullNone); btn_f.fall(press_funcs[s[BTN_F]]); btn_f.rise(release_funcs[s[BTN_F]]); btn_g.mode(PullNone); btn_g.fall(press_funcs[s[BTN_G]]); btn_g.rise(release_funcs[s[BTN_G]]); // Profile buttons prfl_a.mode(PullUp); prfl_a.fall(&prfl_a_set); prfl_a.rise(&prfl_stub); prfl_b.mode(PullUp); prfl_b.fall(&prfl_b_set); prfl_b.rise(&prfl_stub); prfl_c.mode(PullUp); prfl_c.fall(&prfl_c_set); prfl_c.rise(&prfl_stub); prfl_d.mode(PullUp); prfl_d.fall(&prfl_d_set); prfl_d.rise(&prfl_stub); prfl_e.mode(PullUp); prfl_e.fall(&prfl_e_set); prfl_e.rise(&prfl_stub); debug.mode(PullUp); debug.fall(&debug_out); debug.rise(&debug_out); int16_t dx, dy; float mx, my; sensor.reset(); uint8_t *adns_fw; //eeprom->write(ADNS_FW_OFFSET, ADNS_FW_LEN, adns9500FWArray); //adns_fw = eeprom->read( ADNS_FW_OFFSET, ADNS_FW_LEN ); //eeprom->write( s[ADNS_FW_OFFSET], ADNS9500_FIRMWARE_LEN, adns9500FWArray ); activity = 1; printf("Loading sensor firmware\r\n"); uint16_t crc = sensor.sromDownload( adns9500FWArray, ADNS9500_FIRMWARE_LEN ); //FIXME if( ADNS6010_FIRMWARE_CRC != crc ){ //ADNS6010_FIRMWARE_CRC printf("Firmware CRC does not match [%X] [%X]\n\r", ADNS6010_FIRMWARE_CRC, crc); while (true){ activity = 0; wait(0.2); activity = 1; wait(0.2); } } else{ activity = 0; printf("Firmware CRC matches [%X] [%X]\n\r", ADNS6010_FIRMWARE_CRC, crc); } // The firmware was set correctly. Freeing the 3K! of ram. //delete adns_fw; printf("Enableing lazer\n\r"); sensor.enableLaser(); sensor.setResolution( s[CPI_X], s[CPI_Y] ); printf("Starting Loop\n\r"); activity = 1; //rest_counter = 0; while (true){ //rest_counter++; /* * Moved the setResolution calls out of the interupt callbacks as they * havequite a few waits in them. I am hopping this is the reasion why * the hr and z buttons on occation stick or don't work the first time * you press them. */ if( set_res_hr ){ printf("Setting High hez\n\r"); set_res_hr = false; sensor.setResolution( s[CPI_HR_X], s[CPI_HR_Y] ); } if( set_res_z ){ printf("Setting Z rez\n\r"); set_res_z = false; sensor.setResolution( s[CPI_Z], s[CPI_H] ); } if( set_res_default ){ printf("Setting default rez\n\r"); set_res_default = false; sensor.setResolution( s[CPI_X], s[CPI_Y] ); } if( !motion_in){ motion_triggered = false; sensor.getMotionDelta(dx, dy); if( dx == 0 and dy == 0 ){ // FIXME: why is the ADNS9500 dropping the motion pin and then // giving me no motion? Do I have somthing wired up wrong? continue; } /* * The sensor is not aware of its orientation so we need to muck * with the values a it. */ if( z_axis_active ){ printf("scroll,%X,%X,\n\r", -dx, dy); mouse->scroll( dy, - dx ); } else{ mx = (float(abs(dx))/float(s[CPI_X_MULITIPLYER]) + 1.0); my = (float(abs(dy))/float(s[CPI_Y_MULITIPLYER]) + 1.0); printf("motion,%X,%X %.4f,%.4f %X,%X\n\r", -dx, dy, mx, my, int(- (dx * mx)), int(dy * my) ); mouse->move( - (dx * mx), (dy * my) ); //printf("rest_coutner,%d\n\r", rest_counter); //rest_counter = 0; } } // Load the current profile. // This rights the first 10 16bit values of the s array from the selected profile. // // Base is calculated... // selected profile * profile length * 2 + profile base // // (3 * 7 * 2) + 64 (multiplying by two because they are 16bit values. // TODO: should i move this to a function? if( profile_load ){ // for( int i = 0; i < PROFILE_LEN; i++ ){ // //s[i] = get_setting( eeprom, i, (s[PROFILE_CURRENT] * PROFILE_LEN) + PROFILE_BASE ); // } // sensor.setResolution( s[CPI_X], s[CPI_Y] ); profile_load = false; } } } void program( Ser25LCxxx *eeprom ){ //USBHID *hid = new USBHID( 64, 64, 0x192f, 0x0, 0x0); USBHID *hid = new USBHID(); //This report will contain data to be sent HID_REPORT send_rep; HID_REPORT recv_rep; send_rep.length = 64; uint16_t base; uint16_t len; //Fill the report for (int i = 0; i < send_rep.length; i++) { send_rep.data[i] = rand() & 0xff; } //Send the report //hid->send(&send_rep); uint8_t *tmp; printf("Entering loop\n\r"); while (1) { if( hid->readNB(&recv_rep)) { printf("Receaved some data.\n\r"); switch ((recv_rep.data[0])){ case SET: //set_setting( eeprom, recv_rep.data[1], UINT16(recv_rep.data[2],recv_rep.data[3])); break; case GET: //tmp = get_setting( eeprom, recv_rep.data[1] ); //send_rep.data[0] = (int)tmp; //send_rep.data[1] = (int)(tmp >> 8); //hid->send(&send_rep); break; case CLEAR: //clear_setting( eeprom, recv_rep.data[1] ); break; case INIT: eeprom->clearMem(); break; case LOAD_DATA: printf("LOADING DATA\n\r"); base = UINT16( recv_rep.data[1], recv_rep.data[2] ); len = recv_rep.data[3]; printf("BASE: %X LEN: %X\n\r", base, len); load_data( eeprom, base, len, &recv_rep.data[4] ); wait(0.1); tmp = get_data( eeprom, base, len ); printf("BASE: %X LEN: %X\n\r", base, len); for( uint16_t i=0; i < (len); i++){ printf("%X\n\r", tmp[i]); send_rep.data[i] = tmp[i]; //FIXME } hid->send(&send_rep); delete( tmp); break; case GET_DATA: //base = UINT16( recv_rep.data[1], recv_rep.data[2] ); //len = UINT16( recv_rep.data[3], recv_rep.data[4] ); //tmp = get_data( Ser25LCxxx *eeprom, uint16_t base, uint16_t len ){ default: // FIXME: error handling. break; } } } } void btn_l_press(){ printf("button,left,press\n\r"); mouse->press(MOUSE_LEFT); } void btn_l_release(){ printf("button,left,release\n\r"); mouse->release(MOUSE_LEFT); } void btn_m_press(){ //mouse->press(MOUSE_MIDDLE); } void btn_m_release(){ //mouse->release(MOUSE_MIDDLE); } void btn_r_press(){ printf("button,right,press\n\r"); mouse->press(MOUSE_RIGHT); } void btn_r_release(){ printf("button,right,release\n\r"); mouse->release(MOUSE_RIGHT); } void btn_f_press(){ printf("button,forword,press\n\r"); mouse->press(MOUSE_FORWORD); } void btn_f_release(){ printf("button,forword,release\n\r"); mouse->release(MOUSE_FORWORD); } void btn_b_press(){ printf("button,back,press\n\r"); mouse->press(MOUSE_BACK); } void btn_b_release(){ printf("button,back,release\n\r"); mouse->release(MOUSE_BACK); } void btn_hr_press(){ printf("button,high_res,press\n\r"); set_res_hr = true; set_res_default = false; high_rez_active = true; } void btn_hr_release(){ printf("button,high_res,release\n\r"); set_res_hr = false; set_res_default = true; high_rez_active = false; } void btn_z_press(){ printf("button,z,press\n\r"); set_res_z = true; set_res_default = false; z_axis_active = true; } void btn_z_release(){ printf("button,z,release\n\r"); set_res_z = false; set_res_default = true; z_axis_active = false; } void prfl_a_set(){ s[PROFILE_CURRENT] = 0; profile_load = true; } void prfl_b_set(){ s[PROFILE_CURRENT] = 1; profile_load = true; } void prfl_c_set(){ s[PROFILE_CURRENT] = 2; profile_load = true; } void prfl_d_set(){ s[PROFILE_CURRENT] = 3; profile_load = true; } void prfl_e_set(){ s[PROFILE_CURRENT] = 4; profile_load = true; } void prfl_stub(){ } void debug_out(){ printf("motion_triggerd %d\n\r" , motion_triggered); printf("z_axis_active %d\n\r", z_axis_active); printf("high_rez_active %d\n\r", high_rez_active); printf("profile_load %d\n\r", profile_load); // Always inishally load the profile even if it might be the same. printf("set_res_hr %d\n\r", set_res_hr); printf("set_res_z %d\n\r" , set_res_z); printf("set_res_default %d\n\r", set_res_default); } /* * The settings are kept in the first 'N' addresses of the of the EEPROM. * They are 16bits long. The default settings are in a uint16_t array. So * to set/get a setting you use the array value and multiple it by two. * This way I can easily get all setting at the start of the program by * simply looping through the array. */ int set_setting( Ser25LCxxx *eeprom, uint16_t attrib, uint16_t val, uint16_t base_address ){ uint8_t hl[2]; // TODO: Its working but is it working the way i think its working hl[0] = (int)val; hl[1] = (int)(val >> 8); printf("Set Setting %d: L[%X] H[%X]\n\r", attrib, hl[0], hl[1] ); if ( eeprom->write( attrib * 2, 0x2, hl )){ return true; } return false; } uint16_t get_setting( Ser25LCxxx *eeprom, uint16_t attrib, uint16_t base_address ){ uint16_t val; uint8_t *hl; hl = eeprom->read( (attrib * 2) + base_address, 0x2 ); printf("Get Setting %d: L[%X] H[%X]\n\r", attrib, hl[0], hl[1] ); val = UINT16( hl[1], hl[0] ); if( val != 0xFFFF ){ return val; } return s[attrib]; } void clear_setting( Ser25LCxxx *eeprom, uint16_t attrib, uint16_t base_address ){ uint8_t val[2]; val[0] = val[1] = 0xFF; eeprom->write( (attrib * 2) + base_address , 0x2, val ); } /* * Getting and setting the firmware is a bit easer as it is all 8bit. */ void load_data( Ser25LCxxx *eeprom, uint16_t base, uint16_t len, const uint8_t* data ){ eeprom->write( base , len, data ); } uint8_t* get_data( Ser25LCxxx *eeprom, uint16_t base, uint16_t len ){ return (uint8_t*)eeprom->read( base, len ); }