Prof Greg Egan / Mbed 2 deprecated UAVXArm-GKE

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers i2c.c Source File

i2c.c

00001 // ===============================================================================================
00002 // =                              UAVXArm Quadrocopter Controller                                =
00003 // =                           Copyright (c) 2008 by Prof. Greg Egan                             =
00004 // =                 Original V3.15 Copyright (c) 2007 Ing. Wolfgang Mahringer                   =
00005 // =                           http://code.google.com/p/uavp-mods/                               =
00006 // ===============================================================================================
00007 
00008 //    This is part of UAVXArm.
00009 
00010 //    UAVXArm is free software: you can redistribute it and/or modify it under the terms of the GNU
00011 //    General Public License as published by the Free Software Foundation, either version 3 of the
00012 //    License, or (at your option) any later version.
00013 
00014 //    UAVXArm is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without
00015 //    even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016 //    See the GNU General Public License for more details.
00017 
00018 //    You should have received a copy of the GNU General Public License along with this program.
00019 //    If not, see http://www.gnu.org/licenses/
00020 
00021 #include "UAVXArm.h"
00022 
00023 boolean I2C0AddressResponds(uint8);
00024 #ifdef HAVE_I2C1
00025 boolean I2C1AddressResponds(uint8);
00026 #endif // HAVE_I2C1
00027 void TrackMinI2CRate(uint32);
00028 void ShowI2CDeviceName(uint8);
00029 uint8 ScanI2CBus(void);
00030 boolean ESCWaitClkHi(void);
00031 void ProgramSlaveAddress(uint8);
00032 void ConfigureESCs(void);
00033 
00034 uint16 I2CError[256];
00035 uint8 I2CSpeed = 10; // 100KHz
00036 uint32 MinI2CRate = I2C_MAX_RATE_HZ;
00037 
00038 //______________________________________________________________________________________________
00039 
00040 // Software I2C
00041 
00042 #ifdef SW_I2C
00043 
00044 void SDelay(uint16 d) { // 1.25 + 0.0475 * n uS ~0.05uS per click
00045 
00046     volatile int16 v;
00047 
00048     for (v = 0; v < d ; v++ ) {};
00049 
00050 }  // SDelay
00051 
00052 /*
00053 #define SCLLowStartT SDelay(I2CSpeed)
00054 #define DataLowPadT SDelay(I2CSpeed)
00055 #define SCLLowPadT SDelay(I2CSpeed)
00056 #define SCLHighT SDelay(I2CSpeed)
00057 */
00058 
00059 #if ( I2C_MAX_RATE_HZ == 400000 )
00060 
00061 #define SCLLowStartT SDelay(10)
00062 #define DataLowPadT SDelay(16) // 10
00063 #define SCLLowPadT SDelay(6)
00064 #define SCLHighT SDelay(10)
00065 
00066 #else
00067 
00068 #define SCLLowStartT  SDelay(82)
00069 #define DataLowPadT SDelay(82)
00070 #define SCLLowPadT SDelay(82)
00071 #define SCLHighT SDelay(85)
00072 
00073 #endif //I2C400KHZ
00074 
00075 
00076 #define I2CSDALow {I2C0SDA.write(0);I2C0SDA.output();SCLLowPadT;}
00077 #define I2CSDAFloat {I2C0SDA.input();SCLLowPadT;}
00078 #define I2CSCLLow {I2C0SCL.write(0);I2C0SCL.output();}
00079 #define I2CSCLFloat {I2C0SCL.input();SCLHighT;}
00080 
00081 void MyI2C::frequency(uint32 f) {
00082 // delay depending on rate
00083 
00084     if ( f == 400000 )
00085         I2CSpeed = 10;
00086     else
00087         I2CSpeed = 80;
00088 } // frequency
00089 
00090 void MyI2C::start(void) {
00091 
00092     I2CSDAFloat;
00093     r = waitclock();
00094     I2CSDALow;
00095     SCLLowStartT;
00096     I2CSCLLow;
00097 } // start
00098 
00099 void MyI2C::stop(void) {
00100 
00101     I2CSDALow;
00102     r = waitclock();
00103     I2CSDAFloat;
00104     SCLLowStartT;
00105 
00106 } // stop
00107 
00108 boolean MyI2C::waitclock(void) {
00109     static uint32 s;
00110 
00111     I2CSCLFloat;        // set SCL to input, output a high
00112     s = 0;
00113     while ( I2C0SCL.read() == 0 )
00114         if ( ++s > 16000 ) { // ~1mS
00115             I2CError[0]++;
00116             // possible add SCL cycles here to attempt to force device reset
00117             Stats[I2CFailS]++;
00118             return (false);
00119         }
00120     return( true );
00121 } // waitclock
00122 
00123 uint8 MyI2C::read(uint8 ack) {
00124     static uint8 s, d;
00125 
00126     I2CSDAFloat;
00127     d = 0;
00128     s = 8;
00129     do {
00130         if ( waitclock() ) {
00131             d <<= 1;
00132             if ( I2C0SDA.read() ) {
00133                 d |= 1;
00134                 I2CSCLLow;
00135                 DataLowPadT;
00136             } else {
00137                 I2CSCLLow;
00138                 SDelay(10);//DataLowPadT;
00139             }
00140         } else
00141             return( 0 );
00142     } while ( --s );
00143 
00144     if ( ack == I2C_NACK )
00145         I2C0SDA.write(0xffff); // Port write with mask selecting SDA - messy
00146     else
00147         I2C0SDA.write(0);
00148     I2C0SDA.output();
00149 
00150     SCLLowPadT;
00151 
00152     if ( waitclock() ) {
00153         I2CSCLLow;
00154         return( d );
00155     } else
00156         return( 0 );
00157 
00158 } // read
00159 
00160 uint8 MyI2C::write(uint8 d) {
00161     static uint8 s, r;
00162 
00163     for ( s = 0; s < 8; s++) {
00164         if ( d & 0x80 ) {
00165             I2CSDAFloat;
00166         } else {
00167             I2CSDALow;
00168         }
00169 
00170         if ( waitclock() ) {
00171             I2CSCLLow;
00172             d <<= 1;
00173         } else
00174             return(I2C_NACK);
00175     }
00176 
00177     I2CSDAFloat;
00178     if ( waitclock() ) {
00179         if ( I2C0SDA.read() )
00180             r = I2C_NACK;
00181         else
00182             r = I2C_ACK;
00183         I2CSDALow;// kill runt pulses
00184         I2CSCLLow;
00185         return ( r );
00186     } else {
00187 //   I2CSCLLow;
00188         return(I2C_NACK);
00189     }
00190 
00191 } // write
00192 
00193 uint8 MyI2C::blockread(uint8 a, char* S, uint8 l) {
00194     static uint8 b;
00195     static boolean err;
00196 
00197     I2C0.start();
00198     err = I2C0.write(a|1) != I2C_ACK;
00199     for (b = 0; b < (l - 1); b++)
00200         S[b] = I2C0.read(I2C_ACK);
00201     S[l-1] = I2C0.read(I2C_NACK);
00202     I2C0.stop();
00203 
00204     return( err );
00205 } // blockread
00206 
00207 boolean MyI2C::blockwrite(uint8 a, const char* S, uint8 l) {
00208     static uint8 b;
00209 
00210     I2C0.start();
00211     if ( I2C0.write(a) != I2C_ACK ) goto BlockWriteError; // use this?
00212     for ( b = 0; b < l; b++ )
00213         if ( I2C0.write(S[b]) != I2C_ACK ) goto BlockWriteError;
00214     I2C0.stop();
00215 
00216     return(false);
00217 
00218 BlockWriteError:
00219     I2C0.stop();
00220 
00221     return(true);
00222 
00223 } // blockwrite
00224 
00225 #endif // SW_I2C
00226 
00227 //______________________________________________________________________________________________
00228 
00229 void TrackMinI2CRate(uint32 r) {
00230 
00231 // CURRENTLY USING DEFINE TO SPECIFY RATE - UAVXArm.h
00232     if ( r < MinI2CRate )
00233         MinI2CRate = r;
00234 } // TrackMinI2CRate
00235 
00236 void ShowI2CDeviceName(uint8 d) {
00237     TxChar(' ');
00238     switch ( d  ) {
00239         case ADXL345_ID:
00240             TxString("ADXL345 Acc");
00241             break;
00242         case ITG3200_ID:
00243             TxString("ITG3200 Gyro");
00244             break;
00245         case HMC5843_ID:
00246             TxString("HMC5843 Magnetometer");
00247             break;
00248         case HMC6352_ID:
00249             TxString("HMC6352 Compass");
00250             break;
00251         case ADS7823_ID:
00252             TxString("ADS7823 ADC");
00253             break;
00254         case MCP4725_ID_0xCC:
00255             TxString("MCP4725 DAC");
00256             break;
00257         case MCP4725_ID_0xC8:
00258             TxString("MCP4725 DAC");
00259             break;
00260         case BOSCH_ID:
00261             TxString("Bosch Baro");
00262             break;
00263         case TMP100_ID:
00264             TxString("TMP100 Temp");
00265             break;
00266         case PCA9551_ID:
00267             TxString("PCA9551 LED");
00268             break;
00269         case LISL_ID:
00270             TxString("LIS3L Acc");
00271             break;
00272         default:
00273             break;
00274     } // switch
00275     TxChar(' ');
00276 
00277 } // ShowI2CDeviceName
00278 
00279 boolean I2C0AddressResponds(uint8 s) {
00280     static boolean r;
00281     I2C0.start();
00282     r = I2C0.write(s) == I2C_ACK;
00283     I2C0.stop();
00284     return (r);
00285 } // I2C0AddressResponds
00286 
00287 #ifdef HAVE_IC1
00288 boolean I2C1AddressResponds(uint8 s) {
00289     static boolean r;
00290     I2C1.start();
00291     r = I2C1.write(s) == I2C_ACK;
00292     I2C1.stop();
00293     return (r);
00294 } // I2C1AddressResponds
00295 #endif // HAVE_IC1
00296 
00297 uint8 ScanI2CBus(void) {
00298     uint8 s;
00299     uint8 d;
00300 
00301     d = 0;
00302     TxString("Buss 0\r\n");
00303 
00304 #ifdef SW_I2C
00305     TxString("I2C Ver.:\tSoftware\r\n");
00306 #else
00307     TxString("I2C Ver.:\tHardware (CAUTION)\r\n");
00308 #endif // SW_I2C
00309 
00310 #if ( I2C_MAX_RATE_HZ == 400000 )
00311     TxString("Rate:\t400KHz\r\n");
00312 #else
00313     TxString("Rate:\t100KHz\r\n");
00314 #endif
00315     TxString("SCL Hangs:\t");
00316     TxVal32(I2CError[0], 0, 0);
00317     TxNextLine();
00318     for ( s = 0x10 ; s <= 0xf6 ; s += 2 ) {
00319         if (  I2C0AddressResponds(s) ) {
00320             d++;
00321             TxString("\t0x");
00322             TxValH(s);
00323             TxChar(HT);
00324             TxVal32(I2CError[s], 0, HT);
00325             ShowI2CDeviceName( s );
00326             TxNextLine();
00327         }
00328         Delay1mS(2);
00329     }
00330 
00331 #ifdef HAVE_I2C1
00332     TxString("Buss 1\r\n");
00333 
00334 #ifdef SW_I2C
00335     TxString("I2C Ver.:\tSoftware\r\n");
00336 #else
00337     TxString("I2C Ver.:\tHardware (CAUTION)\r\n");
00338 #endif // SW_I2C
00339 
00340 #if ( I2C_MAX_RATE_HZ == 400000 )
00341     TxString("Rate:\t400KHz\r\n");
00342 #else
00343     TxString("Rate:\t100KHz\r\n");
00344 #endif
00345     TxString("SCL Hangs:\t");
00346     TxNextLine();
00347     for ( s = 0x10 ; s <= 0xf6 ; s += 2 ) {
00348         if ( I2C0AddressResponds(s) ) {
00349             d++;
00350             TxString("\t0x");
00351             TxValH(s);
00352             TxChar(HT);
00353             TxVal32(I2CError[s], 0, HT);
00354             ShowI2CDeviceName( s );
00355             TxNextLine();
00356         }
00357         Delay1mS(2);
00358     }
00359 #endif // HAVE_I2C1
00360 
00361     PCA9551Test();
00362 
00363     return(d);
00364 } // ScanI2CBus
00365 
00366 void ProgramSlaveAddress(uint8 a) {
00367     static uint8 s;
00368 
00369     for (s = 0x10 ; s < 0xf0 ; s += 2 ) {
00370         I2CESC.start();
00371         if ( I2CESC.read(s) == I2C_ACK )
00372             if ( s == a ) {   // ESC is already programmed OK
00373                 I2CESC.stop();
00374                 TxString("\tESC at SLA 0x");
00375                 TxValH(a);
00376                 TxString(" is already programmed OK\r\n");
00377                 return;
00378             } else {
00379                 if ( I2CESC.read(0x87) == I2C_ACK ) // select register 0x07
00380                     if ( I2CESC.write( a ) == I2C_ACK ) { // new slave address
00381                         I2CESC.stop();
00382                         TxString("\tESC at SLA 0x");
00383                         TxValH(s);
00384                         TxString(" reprogrammed to SLA 0x");
00385                         TxValH(a);
00386                         TxNextLine();
00387                         return;
00388                     }
00389             }
00390         I2CESC.stop();
00391     }
00392     TxString("\tESC at SLA 0x");
00393     TxValH(a);
00394     TxString(" no response - check cabling and pullup resistors!\r\n");
00395 } // ProgramSlaveAddress
00396 
00397 boolean CheckESCBus(void) {
00398     return ( true );
00399 } // CheckESCBus
00400 
00401 void ConfigureESCs(void) {
00402     int8 m;
00403 
00404     if ( (int8)P[ESCType] == ESCYGEI2C ) {
00405         TxString("\r\nProgram YGE ESCs\r\n");
00406         for ( m = 0 ; m < NoOfI2CESCOutputs ; m++ ) {
00407             TxString("Connect ONLY M");
00408             TxChar('1' + m);
00409             TxString(" ESC, then press any key \r\n");
00410             while ( PollRxChar() != 'x' ); // UAVPSet uses 'x' for any key button
00411             //    TxString("\r\n");
00412             ProgramSlaveAddress( 0x62 + ( m*2 ));
00413         }
00414         TxString("\r\nConnect ALL ESCs and power-cycle the Quadrocopter\r\n");
00415     } else
00416         TxString("\r\nYGEI2C not selected as ESC?\r\n");
00417 } // ConfigureESCs
00418 
00419 void InitI2C(void) {
00420 
00421     uint8 i;
00422 
00423     for ( i = 0; i < 255; i++ )
00424         I2CError[i] = 0;
00425 
00426 } // InitI2C
00427 
00428 
00429