Prof Greg Egan
/
UAVXArm-GKE
UAVX Multicopter Flight Controller.
Diff: i2c.c
- 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 +