Trackball based on the NXP LPC11U24 and the ADNS-9500

Dependencies:   ADNS9500 USBDevice mbed 25LCxxx_SPI

Files at this revision

API Documentation at this revision

Comitter:
xxann5
Date:
Thu Mar 14 13:48:14 2013 +0000
Parent:
7:d6ee49a89009
Child:
9:ee05aa95f5c9
Commit message:
* support for 4th and 5th buttons.; * support for horizontal scrolling.; * support for 16bit x and y coordinates.; * added dispatch table for buttons. They are now programmable.; * support for programming the eeprom

Changed in this revision

25LCxxx_SPI.lib Show annotated file Show diff for this revision Revisions of this file
ADNS9500.lib Show annotated file Show diff for this revision Revisions of this file
PinDetect.lib Show diff for this revision Revisions of this file
USBDevice.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
main.h Show annotated file Show diff for this revision Revisions of this file
--- a/25LCxxx_SPI.lib	Mon Jan 14 04:27:55 2013 +0000
+++ b/25LCxxx_SPI.lib	Thu Mar 14 13:48:14 2013 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/hlipka/code/25LCxxx_SPI/#d9429070ea6f
+http://mbed.org/users/xxann5/code/25LCxxx_SPI/#0c31e878a076
--- a/ADNS9500.lib	Mon Jan 14 04:27:55 2013 +0000
+++ b/ADNS9500.lib	Thu Mar 14 13:48:14 2013 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/xxann5/code/ADNS9500/#de76a70defb3
+http://mbed.org/users/xxann5/code/ADNS9500/#af2fb65ee807
--- a/PinDetect.lib	Mon Jan 14 04:27:55 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/users/AjK/code/PinDetect/#cb3afc45028b
--- a/USBDevice.lib	Mon Jan 14 04:27:55 2013 +0000
+++ b/USBDevice.lib	Thu Mar 14 13:48:14 2013 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/xxann5/code/USBDevice/#01e3466e25ff
+https://mbed.org/users/mbed_official/code/USBDevice/#4f27799a971d
--- a/main.cpp	Mon Jan 14 04:27:55 2013 +0000
+++ b/main.cpp	Thu Mar 14 13:48:14 2013 +0000
@@ -1,215 +1,463 @@
-/* Copyright (c) 2012-2013 Chris Majoros(chris@majoros.us), MIT License
-*
-* 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.
-*/
+/* 
+ *  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"
 
-DigitalOut myled(p15);
 
 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
 
-    printf( "Hi i just started running\n\r");
-    uint8_t o;
-    uint8_t i;
-    MOUSE_TYPE mtype;
-
-    if( btn_program ){
-        mtype = RAW;
-        o = 64;
-        i = 64;
+    //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{
-        mtype = REL_MOUSE;
-        o = 0;
-        i = 0;
+        printf("Programming mode\n\r");
+        program( eeprom );
     }
-
-    // TODO switch to P#_#
-    SPI eeprom_spi( p11, p12, p13); // mosi, miso, sclk 
-    eeprom_spi.format(8,3);
-    eeprom_spi.frequency(1000000);
-    Ser25LCxxx eeprom( &eeprom_spi, p14, 0x10000, 0x20 );
-    
-    //Retreave settings from the EEPROM and override the default values.
-    for( int i = 0; i < sizeof(s)/sizeof(uint16_t); i++ ){
-        s[i] = get_setting( &eeprom, i );
-        printf( "Setting %02d: %d\r\n", i, s[i]);
-    }
-
-
-    //if( mtype == RAW ){
-    //    program();
-    //}
-    //else{
-    //    track();
-    //}
 }
 
 void track( Ser25LCxxx *eeprom ){
+    activity = 0;
     /* 
     * mosi miso sclk ncs FREQ, motion
     */
-    sensor = new adns9500::ADNS9500(p5, p6, p7, p8, adns9500::MAX_SPI_FREQUENCY, p21);
-    
-    send_rep.length = 8;
+    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
     
-    btn_hr.mode(PullUp);
-    btn_hr.attach_asserted(&btn_hr_press);
-    btn_hr.attach_deasserted(&btn_hr_release);
-    btn_hr.setSampleFrequency();
+    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");
 
-    btn_z.mode(PullUp);
-    btn_z.attach_asserted(&btn_z_press);
-    btn_z.attach_deasserted(&btn_z_release);
-    btn_z.setSampleFrequency();
-/*
-    btn_l.mode(PullUp);
-    btn_l.attach_asserted(&btn_l_press);
-    btn_l.attach_deasserted(&btn_l_release);
-    btn_l.setSampleFrequency();
-*/
-    btn_m.mode(PullUp);
-    btn_m.attach_asserted(&btn_m_press);
-    btn_m.attach_deasserted(&btn_m_release);
-    btn_m.setSampleFrequency();
+// 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_r.mode(PullUp);
-    btn_r.attach_asserted(&btn_r_press);
-    btn_r.attach_deasserted(&btn_r_release);
-    btn_r.setSampleFrequency();
-    //btn_r.setAssertValue( 0 );
-    //btn_r.setSamplesTillAssert( 5 );
+    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]]);
     
-    int dx, dy;
+    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]]);
 
-    sensor->attach(&motionCallback);
+// Profile buttons
+    prfl_a.mode(PullUp);
+    prfl_a.fall(&prfl_a_set);
+    prfl_a.rise(&prfl_stub);
     
-    sensor->reset();
+    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);
     
-    //Retreave adns meta data from the EEPROM and override the default values.
-    for( int i = 0; i < sizeof(a)/sizeof(uint16_t); i++ ){
-        a[i] = get_adns_meta( eeprom, i );
-        printf( "ADNS Meta %02d: %d\r\n", i, s[i]);
-    }
+    prfl_d.mode(PullUp);
+    prfl_d.fall(&prfl_d_set);
+    prfl_d.rise(&prfl_stub);
     
-    uint8_t *adns_fw;
-    adns_fw = get_adns_firmware( eeprom, 0, ADNS_FW_LEN );
+    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);
     
-    // We are now does with the eeprom 
-    delete eeprom;
-    
-    uint16_t crc = sensor->sromDownload( adns_fw, a[ADNS_FW_LEN] );
-      
-    if( a[ADNS_CRC] != crc )
-    {
-        error( "CRC does not match: [%x] [%x], Exiting.\r\n", a[ADNS_CRC], crc );
+    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;
+    //delete adns_fw;
+
+    printf("Enableing lazer\n\r");
+    sensor.enableLaser();
+    sensor.setResolution( s[CPI_X], s[CPI_Y] );
 
-    sensor->enableLaser();
-    
-    sensor->setResolution( s[CPI_DEFAULT] );
-    int btn_l_avg = 0;
-    DigitalOut myled(P0_7);
+    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] );
+        }
         
-        btn_l_avg=(btn_l_avg * 9 + btn_l * 10)/10;
-        if (btn_l_avg > 5){
-            btn_l_press();
+        if( set_res_z ){
+            printf("Setting Z rez\n\r");
+            set_res_z = false;
+            sensor.setResolution( s[CPI_Z], s[CPI_H] );
         }
-        else{
-            btn_l_release();
+        
+        if( set_res_default ){
+            printf("Setting default rez\n\r");
+            set_res_default = false;
+            sensor.setResolution( s[CPI_X], s[CPI_Y] );
         }
-
-        
-        if( motion_triggered ){
+              
+        if( !motion_in){
 
             motion_triggered = false;
 
-            sensor->getMotionDelta(dx, dy);
-
+            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 does not know its upside down and backwords
-             * so we are helping it out with the y axis.
+             * The sensor is not aware of its orientation so we need to muck
+             * with the values a it.
              */
             if( z_axis_active ){
-                mouse->scroll( - dy );
+                printf("scroll,%X,%X,\n\r", -dx, dy);
+                mouse->scroll( dy, - dx );
             }
             else{
-                mouse->move( dx, - dy ); 
+                
+                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 program(){
-
-    // We are now does with the eeprom 
-    //delete eeprom;
-}
-
-void motionCallback(){
-    motion_triggered = true;
-}
-
-void btn_hr_press(){
-    high_rez_active = true;
-    sensor->setResolution( s[CPI_HR_DEFAULT] ); 
-}
-void btn_hr_release(){
-    high_rez_active = false;
-    sensor->setResolution( s[CPI_DEFAULT] );
-}
-
-void btn_z_press(){
-    z_axis_active = true;
-    sensor->setResolution( s[CPI_Z_DEFAULT] );
-}
-void btn_z_release(){
-    z_axis_active = false;
-    sensor->setResolution( s[CPI_DEFAULT] );
-}
-
 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);
+    //mouse->press(MOUSE_MIDDLE);
 }
 void btn_m_release(){
-    mouse->release(MOUSE_MIDDLE);
+    //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.
@@ -220,24 +468,29 @@
  */
 
 
-void set_setting( Ser25LCxxx *eeprom, uint16_t attrib, uint16_t val ){
+int set_setting( Ser25LCxxx *eeprom, uint16_t attrib, uint16_t val, uint16_t base_address ){
 
-    int hl[2];
+    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] );
 
-    eeprom->write( attrib * 2, 0x2, hl );
-
+    if ( eeprom->write( attrib * 2, 0x2, hl )){
+        return true;
+    }
+    return false;
 }
 
-uint16_t get_setting( Ser25LCxxx *eeprom, uint16_t attrib ){
+uint16_t get_setting( Ser25LCxxx *eeprom, uint16_t attrib, uint16_t base_address ){
     
     uint16_t val;
-    int *hl;
+    uint8_t *hl;
     
-    hl = eeprom->read( (attrib * 2), 0x2 );
+    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;
@@ -246,43 +499,20 @@
     return s[attrib];
 }
 
-void clear_setting( Ser25LCxxx *eeprom, uint16_t attrib ){
-    int val[2];
+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) , 0x2, val );
+    eeprom->write( (attrib * 2) + base_address , 0x2, val );
 }
 
+
 /*
  * Getting and setting the firmware is a bit easer as it is all 8bit.
  */
-void set_adns_firmware( Ser25LCxxx *eeprom, uint16_t offset, uint16_t len, uint8_t* val ){
-    eeprom->write( (ADNS_FW_OFFSET + offset) , len, (int*)val );
-}
-
-uint8_t* get_adns_firmware( Ser25LCxxx *eeprom, uint16_t offset, uint16_t len ){
-    return (uint8_t*)eeprom->read( (ADNS_FW_OFFSET + offset), len );
+void load_data( Ser25LCxxx *eeprom, uint16_t base, uint16_t len, const uint8_t* data ){
+    eeprom->write( base , len, data );
 }
 
-/*
- * Same deal as the trackball settings.
- */
- 
-void set_adns_meta( Ser25LCxxx *eeprom, uint16_t attrib, uint16_t val ){
-
-    int hl[2];
-    
-    // TODO: Its working but is it working the way i think its working
-    hl[0] = (int)val;
-    hl[1] = (int)(val >> 8);
-    
-    eeprom->write( (ADNS_META_OFFSET + (attrib * 2 )), 0x2, hl );
-}
-
-uint16_t get_adns_meta( Ser25LCxxx *eeprom, uint16_t attrib ){
-    uint16_t val;
-    int *hl;
-    
-    hl = eeprom->read( (ADNS_META_OFFSET + (attrib * 2 )), 0x2 );
-    val = UINT16( hl[1], hl[0] );
-    return val;
+uint8_t* get_data( Ser25LCxxx *eeprom, uint16_t base, uint16_t len ){
+    return (uint8_t*)eeprom->read( base, len );
 }
\ No newline at end of file
--- a/main.h	Mon Jan 14 04:27:55 2013 +0000
+++ b/main.h	Thu Mar 14 13:48:14 2013 +0000
@@ -1,111 +1,202 @@
-/* Copyright (c) 2012-2013 Chris Majoros(chris@majoros.us), MIT License
-*
-* 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.
-*/
+/* 
+ *  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 "mbed.h"
 #include "USBHID.h"
 #include "USBMouse.h"
-
-#include <math.h>
-#include <stdint.h>
-
-
-#define PINDETECT_PIN_ASSTERED  0    //setAssertValue
-#define PINDETECT_SAMPLE_PERIOD 100 //setSampleFrequency
-#define PINDETECT_ASSERT_COUNT  10    //setSamplesTillAssert
-#define PINDETECT_HOLD_COUNT    500
-
-#include "PinDetect.h"
-
-#define ADNS9500_SROM_91
-
-#define DEBUG
-
-#include "adns9500.hpp"
 #include "Ser25lcxxx.h"
 
-enum cli_actions {
-    SET   = 0x01,
-    GET   = 0x02,
-    CLEAR = 0x03,
-    INIT  = 0x04,
-};
+#include <stdint.h>
 
-enum settings {    
-    CPI_DEFAULT     = 0x00,
-    CPI_MAX         = 0x01,
-    CPI_MIN         = 0x02,
-    CPI_STEP        = 0x03,
-    CPI_Z_DEFAULT   = 0x04,
-    CPI_HR_DEFAULT  = 0x05,
-    
-    VID             = 0x06,
-    PID             = 0x07,
+#define ADNS9500_SROM_91
+#define ADNS9500_CRCHI (0xBE)
+#define ADNS9500_CRCLO (0xEF)
+#define ADNS9500_ID (0x56)
+#define ADNS6010_FIRMWARE_CRC (0xBEEF)
+#define ADNS9500_FIRMWARE_LEN 3070
 
-    LED_SHOW        = 0x08,
-    SETTINGS_OFFSET = 0x00
-};
+#include "adns9500.hpp"
 
-enum ands_meta {
-    ADNS_CRC         = 0x0,
-    ADNS_ID          = 0x1,
-    ADNS_FW_LEN      = 0x2,
-    ADNS_FW_OFFSET   = 0xF000,
-    ADNS_META_OFFSET = 0xEFF0
-};
 
 #define UINT16(ub, lb)             (uint16_t)(((ub & 0xff) << 8) | (lb & 0xff))
 #define INT16(ub, lb)              (int16_t)(((ub & 0xff) << 8) | (lb & 0xff))
-  
-//This report will contain data to be sent
-HID_REPORT send_rep;
-HID_REPORT recv_rep;
+
+#define SETTINGS_BASE 0x00
+#define PROFILE_BASE 0xff
+#define PROFILE_LEN 0x13
+
+#define MBED
+
+typedef void (*fn)(void);
+
+enum cli_actions {
+    SET       = 0x01,
+    GET       = 0x02,
+    LOAD_DATA = 0x03,
+    GET_DATA  = 0x04,
+    CLEAR     = 0x05,
+    INIT      = 0x06
+};
+
+enum cli_replies {
+    retval  = 0x01,
+    message = 0x02
+};
 
-PinDetect btn_l(P1_25);
-PinDetect btn_m(P1_19);
-PinDetect btn_r(P0_20);
-PinDetect btn_z(P0_2);
-PinDetect btn_hr(P1_26);
+enum buttons {
+    BUTTON_LEFT = 0x00, //explisitly showing we start at zero
+    BUTTON_MIDDLE,
+    BUTTON_RIGHT,
+    BUTTON_FORWORD,
+    BUTTON_BACK,
+    BUTTON_Z,
+    BUTTON_HIGH_RES,
+};
+enum settings {    
+    CPI_X = 0x00, //explisitly showing we start at zero
+    CPI_Y,
+    CPI_X_MULITIPLYER,
+    CPI_Y_MULITIPLYER,
+    CPI_MAX, // Not currently used.
+    CPI_MIN, // Not currently used.
+    CPI_STEP, // Not currently used.
+    CPI_Z,
+    CPI_H,
+    CPI_HR_X,
+    CPI_HR_Y,
+    
+    BTN_A,
+    BTN_B,
+    BTN_C,
+    BTN_D,
+    BTN_E,
+    BTN_F,
+    BTN_G,
+    
+    LED_ACTION, // Not currently used
+    
+    VID,
+    PID,
+    RELEASE,
+    
+    PROFILE_DEFAULT,
+    PROFILE_CURRENT,
+    
+
+
+    ADNS_CRC,
+    ADNS_ID,
+    ADNS_FW_LEN,
+    ADNS_FW_OFFSET,
+};
+
 
-DigitalIn btn_program(P0_4);
+
+
+#ifdef MBED
+DigitalIn run_mode(p36);
+
+DigitalIn motion_in(p14);
+
+DigitalOut activity(p35);
+
+InterruptIn debug(p29);
+    
+InterruptIn btn_a(p21);
+InterruptIn btn_b(p22);
+InterruptIn btn_c(p23);
+InterruptIn btn_d(p24);
+InterruptIn btn_e(p25);
+InterruptIn btn_f(p26);
+InterruptIn btn_g(p27);
 
-adns9500::ADNS9500 *sensor;
+InterruptIn prfl_a(p20);
+InterruptIn prfl_b(p19);
+InterruptIn prfl_c(p18);
+InterruptIn prfl_d(p17);
+InterruptIn prfl_e(p16);
+#elif
+DigitalIn run_mode(P1_29);
+
+DigitalIn motion_in(P0_22);
+
+DigitalOut activity(P1_28);
+
+InterruptIn btn_a(P0_18);
+InterruptIn btn_b(P0_16);
+InterruptIn btn_c(P0_17);
+InterruptIn btn_d(P0_23);
+InterruptIn btn_e(P1_15);
+InterruptIn btn_f(P1_??);
+InterruptIn btn_g(P1_??);
+
+InterruptIn prfl_a(P0_4);
+InterruptIn prfl_b(P0_5);
+InterruptIn prfl_c(P0_21);
+InterruptIn prfl_d(P1_23);
+InterruptIn prfl_e(P1_24);
+#endif
+
+// We are global for the callbacks
 USBMouse *mouse;
 
-bool motion_triggered = false;
-bool z_axis_active    = false;
-bool high_rez_active  = false;
+bool motion_triggered = true;
+bool z_axis_active = false;
+bool high_rez_active = false;
+bool profile_load = true; // Always inishally load the profile even if it might be the same.
+bool set_res_hr = false;
+bool set_res_z = false;
+bool set_res_default = false;
+//uint32_t rest_counter;
 
-uint16_t s[9] = {
-    1080,    // CPI_DEFAULT
+uint16_t s[28] = {
+    540,     // CPI_X
+    540,     // CPI_Y
+    40,      // CPI_X_MULITIPLYER
+    40,      // CPI_Y_MULITIPLYER
     5040,    // CPI_MAX
     0,       // CPI_MIN
     90,      // CPI_STEP
-    90,      // CPI_Z_DEFAULT
-    180,     // CPI_HR_DEFULT
-    0x192f,  // VID
-    0x0000,  // PID
-    0,       // LED_SHOW
+    0,       // CPI_Z
+    0,       // CPI_H
+    360,     // CPI_HR_X
+    360,     // CPI_HR_Y
+    BUTTON_LEFT,
+    BUTTON_MIDDLE,
+    BUTTON_RIGHT,
+    BUTTON_Z,
+    BUTTON_HIGH_RES,
+    BUTTON_FORWORD,
+    BUTTON_BACK,
+    0x00,    // LED_ACTION
+    0x192f,  // VID  (No default, must be set)
+    0x0000,  // PID  (No default, must be set)
+    0x00,    // PROFILE_DEFAULT
+    0x00,    // PROFILE_CURRENT
+    0x0000,  // RELEASE
+    0xffff,  // ADNS_CRC    (No default, must be set)
+    0xffff,  // ADNS_ID     (No default, must be set)
+    0xffff,  // ADNS_FW_LEN (No default, must be set)
+    0xea60   // ADNS_FW_OFFSET
 };
 
-uint16_t a[3];
+
 
-void track();
-void program();
+void track( Ser25LCxxx *eeprom );
+void program( Ser25LCxxx *eeprom );
 
 void motionCallback( void );
 
@@ -124,12 +215,25 @@
 void btn_r_press( void );
 void btn_r_release( void );
 
-void set_setting( Ser25LCxxx *eeprom, uint16_t attrib, uint16_t val );
-uint16_t get_setting( Ser25LCxxx *eeprom, uint16_t attrib);
-void clear_setting( Ser25LCxxx *eeprom, uint16_t attrib);
+void btn_f_press( void );
+void btn_f_release( void );
+
+void btn_b_press( void );
+void btn_b_release( void );
 
-void set_adns_firmware( Ser25LCxxx *eeprom, uint16_t offset, uint16_t len, uint8_t* val );
-uint8_t* get_adns_firmware( Ser25LCxxx *eeprom, uint16_t offset, uint16_t len );
+void prfl_a_set( void );
+void prfl_b_set( void );
+void prfl_c_set( void );
+void prfl_d_set( void );
+void prfl_e_set( void );
 
-void set_adns_meta( Ser25LCxxx *eeprom, uint16_t attrib, uint16_t val );
-uint16_t get_adns_meta( Ser25LCxxx *eeprom, uint16_t attrib );
\ No newline at end of file
+void prfl_stub( void );
+void debug_out(void);
+
+int set_setting( Ser25LCxxx *eeprom, uint16_t attrib, uint16_t val, uint16_t base_address );
+uint16_t get_setting( Ser25LCxxx *eeprom, uint16_t attrib, uint16_t base_address );
+void clear_setting( Ser25LCxxx *eeprom, uint16_t attrib, uint16_t base_address );
+
+void load_data( Ser25LCxxx *eeprom, uint16_t base, uint16_t len, const uint8_t* data );
+
+uint8_t* get_data( Ser25LCxxx *eeprom, uint16_t base, uint16_t len );
\ No newline at end of file