UAVX Multicopter Flight Controller.

Dependencies:   mbed

Revision:
2:90292f8bd179
Parent:
1:1e3318a30ddd
--- a/i2c.c	Fri Feb 25 01:35:24 2011 +0000
+++ b/i2c.c	Tue Apr 26 12:12:29 2011 +0000
@@ -2,7 +2,7 @@
 // =                              UAVXArm Quadrocopter Controller                                =
 // =                           Copyright (c) 2008 by Prof. Greg Egan                             =
 // =                 Original V3.15 Copyright (c) 2007 Ing. Wolfgang Mahringer                   =
-// =                     http://code.google.com/p/uavp-mods/ http://uavp.ch                      =
+// =                           http://code.google.com/p/uavp-mods/                               =
 // ===============================================================================================
 
 //    This is part of UAVXArm.
@@ -31,6 +31,8 @@
 void ProgramSlaveAddress(uint8);
 void ConfigureESCs(void);
 
+uint16 I2CError[256];
+uint8 I2CSpeed = 10; // 100KHz
 uint32 MinI2CRate = I2C_MAX_RATE_HZ;
 
 //______________________________________________________________________________________________
@@ -39,51 +41,154 @@
 
 #ifdef SW_I2C
 
-#define I2CDelay5uS wait_us(5)
-#define I2CDelay2uS // wait_us(2)
-#define HighLowDelay // wait_us(1)
-#define FloatDelay // ???
+void SDelay(uint16 d) { // 1.25 + 0.0475 * n uS ~0.05uS per click
+
+    volatile int16 v;
+
+    for (v = 0; v < d ; v++ ) {};
+
+}  // SDelay
+
+/*
+#define SCLLowStartT SDelay(I2CSpeed)
+#define DataLowPadT SDelay(I2CSpeed)
+#define SCLLowPadT SDelay(I2CSpeed)
+#define SCLHighT SDelay(I2CSpeed)
+*/
+
+#if ( I2C_MAX_RATE_HZ == 400000 )
 
-#define I2CSDALow {I2C0SDA.write(0);HighLowDelay;I2C0SDA.output();}
-#define I2CSDAFloat {I2C0SDA.input();}
-#define I2CSCLLow {I2C0SCL.write(0);HighLowDelay;I2C0SCL.output();}
-#define I2CSCLFloat {I2C0SCL.input();FloatDelay;}
+#define SCLLowStartT SDelay(10)
+#define DataLowPadT SDelay(16) // 10
+#define SCLLowPadT SDelay(6)
+#define SCLHighT SDelay(10)
+
+#else
+
+#define SCLLowStartT  SDelay(82)
+#define DataLowPadT SDelay(82)
+#define SCLLowPadT SDelay(82)
+#define SCLHighT SDelay(85)
+
+#endif //I2C400KHZ
+
+
+#define I2CSDALow {I2C0SDA.write(0);I2C0SDA.output();SCLLowPadT;}
+#define I2CSDAFloat {I2C0SDA.input();SCLLowPadT;}
+#define I2CSCLLow {I2C0SCL.write(0);I2C0SCL.output();}
+#define I2CSCLFloat {I2C0SCL.input();SCLHighT;}
 
 void MyI2C::frequency(uint32 f) {
 // delay depending on rate
+
+    if ( f == 400000 )
+        I2CSpeed = 10;
+    else
+        I2CSpeed = 80;
 } // frequency
 
+void MyI2C::start(void) {
+
+    I2CSDAFloat;
+    r = waitclock();
+    I2CSDALow;
+    SCLLowStartT;
+    I2CSCLLow;
+} // start
+
+void MyI2C::stop(void) {
+
+    I2CSDALow;
+    r = waitclock();
+    I2CSDAFloat;
+    SCLLowStartT;
+
+} // stop
+
 boolean MyI2C::waitclock(void) {
     static uint32 s;
 
     I2CSCLFloat;        // set SCL to input, output a high
     s = 0;
-    while ( !I2C0SCL.read() )
-        if ( ++s > 60000 ) {
+    while ( I2C0SCL.read() == 0 )
+        if ( ++s > 16000 ) { // ~1mS
+            I2CError[0]++;
+            // possible add SCL cycles here to attempt to force device reset
             Stats[I2CFailS]++;
             return (false);
         }
     return( true );
 } // waitclock
 
-void MyI2C::start(void) {
-    static boolean r;
+uint8 MyI2C::read(uint8 ack) {
+    static uint8 s, d;
 
     I2CSDAFloat;
-    r = waitclock();
-    I2CSDALow;
-    I2CDelay5uS;
-    I2CSCLLow;
-} // start
+    d = 0;
+    s = 8;
+    do {
+        if ( waitclock() ) {
+            d <<= 1;
+            if ( I2C0SDA.read() ) {
+                d |= 1;
+                I2CSCLLow;
+                DataLowPadT;
+            } else {
+                I2CSCLLow;
+                SDelay(10);//DataLowPadT;
+            }
+        } else
+            return( 0 );
+    } while ( --s );
+
+    if ( ack == I2C_NACK )
+        I2C0SDA.write(0xffff); // Port write with mask selecting SDA - messy
+    else
+        I2C0SDA.write(0);
+    I2C0SDA.output();
+
+    SCLLowPadT;
+
+    if ( waitclock() ) {
+        I2CSCLLow;
+        return( d );
+    } else
+        return( 0 );
+
+} // read
 
-void MyI2C::stop(void) {
-    static boolean r;
+uint8 MyI2C::write(uint8 d) {
+    static uint8 s, r;
+
+    for ( s = 0; s < 8; s++) {
+        if ( d & 0x80 ) {
+            I2CSDAFloat;
+        } else {
+            I2CSDALow;
+        }
 
-    I2CSDALow;
-    r = waitclock();
+        if ( waitclock() ) {
+            I2CSCLLow;
+            d <<= 1;
+        } else
+            return(I2C_NACK);
+    }
+
     I2CSDAFloat;
-    I2CDelay5uS;
-} // stop
+    if ( waitclock() ) {
+        if ( I2C0SDA.read() )
+            r = I2C_NACK;
+        else
+            r = I2C_ACK;
+        I2CSDALow;// kill runt pulses
+        I2CSCLLow;
+        return ( r );
+    } else {
+//   I2CSCLLow;
+        return(I2C_NACK);
+    }
+
+} // write
 
 uint8 MyI2C::blockread(uint8 a, char* S, uint8 l) {
     static uint8 b;
@@ -99,79 +204,31 @@
     return( err );
 } // blockread
 
-uint8 MyI2C::read(uint8 ack) {
-    static uint8 s, d;
-
-    I2CSDAFloat;
-    d = 0;
-    s = 8;
-    do {
-        if ( waitclock() ) {
-            d <<= 1;
-            if ( I2C0SDA.read() ) d |= 1;
-            I2CSCLLow;
-            I2CDelay2uS;
-        } else
-            return( 0 );
-    } while ( --s );
-
-    I2C0SDA.write(ack);
-    HighLowDelay;
-    I2C0SDA.output();
-    HighLowDelay;
-
-    if ( waitclock() ) {
-        I2CSCLLow;
-        return( d );
-    } else
-        return( 0 );
-} // read
-
-void MyI2C::blockwrite(uint8 a, const char* S, uint8 l) {
+boolean MyI2C::blockwrite(uint8 a, const char* S, uint8 l) {
     static uint8 b;
-    static boolean r;
 
     I2C0.start();
-    r = I2C0.write(a) == I2C_ACK;  // use this?
+    if ( I2C0.write(a) != I2C_ACK ) goto BlockWriteError; // use this?
     for ( b = 0; b < l; b++ )
-        r |= I2C0.write(S[b]);
+        if ( I2C0.write(S[b]) != I2C_ACK ) goto BlockWriteError;
     I2C0.stop();
 
+    return(false);
+
+BlockWriteError:
+    I2C0.stop();
+
+    return(true);
+
 } // blockwrite
 
-uint8 MyI2C::write(uint8 d) {
-    static uint8 s, r;
-
-    for ( s = 0; s < 8; s++)
-    {
-        if ( d & 0x80 ) {
-            I2CSDAFloat;
-        } else {
-            I2CSDALow;
-        }
-
-        if ( waitclock() ) {
-            I2CSCLLow;
-            d <<= 1;
-        } else
-            return(I2C_NACK);
-    }
-
-    I2CSDAFloat;
-    if ( waitclock() ) {
-        r = I2C0SDA.read();
-        I2CSCLLow;
-        return( r );
-    } else
-        return(I2C_NACK);
-
-} // write
-
 #endif // SW_I2C
 
 //______________________________________________________________________________________________
 
 void TrackMinI2CRate(uint32 r) {
+
+// CURRENTLY USING DEFINE TO SPECIFY RATE - UAVXArm.h
     if ( r < MinI2CRate )
         MinI2CRate = r;
 } // TrackMinI2CRate
@@ -243,26 +300,57 @@
 
     d = 0;
     TxString("Buss 0\r\n");
+
+#ifdef SW_I2C
+    TxString("I2C Ver.:\tSoftware\r\n");
+#else
+    TxString("I2C Ver.:\tHardware (CAUTION)\r\n");
+#endif // SW_I2C
+
+#if ( I2C_MAX_RATE_HZ == 400000 )
+    TxString("Rate:\t400KHz\r\n");
+#else
+    TxString("Rate:\t100KHz\r\n");
+#endif
+    TxString("SCL Hangs:\t");
+    TxVal32(I2CError[0], 0, 0);
+    TxNextLine();
     for ( s = 0x10 ; s <= 0xf6 ; s += 2 ) {
         if (  I2C0AddressResponds(s) ) {
             d++;
-            DebugPin = 1;
             TxString("\t0x");
             TxValH(s);
+            TxChar(HT);
+            TxVal32(I2CError[s], 0, HT);
             ShowI2CDeviceName( s );
             TxNextLine();
-            DebugPin = 0;
         }
         Delay1mS(2);
     }
 
 #ifdef HAVE_I2C1
     TxString("Buss 1\r\n");
+
+#ifdef SW_I2C
+    TxString("I2C Ver.:\tSoftware\r\n");
+#else
+    TxString("I2C Ver.:\tHardware (CAUTION)\r\n");
+#endif // SW_I2C
+
+#if ( I2C_MAX_RATE_HZ == 400000 )
+    TxString("Rate:\t400KHz\r\n");
+#else
+    TxString("Rate:\t100KHz\r\n");
+#endif
+    TxString("SCL Hangs:\t");
+    TxNextLine();
     for ( s = 0x10 ; s <= 0xf6 ; s += 2 ) {
-        if (  I2C0AddressResponds(s) ) {
+        if ( I2C0AddressResponds(s) ) {
             d++;
             TxString("\t0x");
             TxValH(s);
+            TxChar(HT);
+            TxVal32(I2CError[s], 0, HT);
             ShowI2CDeviceName( s );
             TxNextLine();
         }
@@ -328,5 +416,14 @@
         TxString("\r\nYGEI2C not selected as ESC?\r\n");
 } // ConfigureESCs
 
+void InitI2C(void) {
+
+    uint8 i;
+
+    for ( i = 0; i < 255; i++ )
+        I2CError[i] = 0;
+
+} // InitI2C
 
 
+