UAVX Multicopter Flight Controller.

Dependencies:   mbed

Committer:
gke
Date:
Fri Feb 25 01:35:24 2011 +0000
Revision:
1:1e3318a30ddd
Parent:
0:62a1c91a859a
Child:
2:90292f8bd179
This version has broken I2C - posted for debugging involvement of Simon et al.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
gke 0:62a1c91a859a 1 // ===============================================================================================
gke 0:62a1c91a859a 2 // = UAVXArm Quadrocopter Controller =
gke 0:62a1c91a859a 3 // = Copyright (c) 2008 by Prof. Greg Egan =
gke 0:62a1c91a859a 4 // = Original V3.15 Copyright (c) 2007 Ing. Wolfgang Mahringer =
gke 0:62a1c91a859a 5 // = http://code.google.com/p/uavp-mods/ http://uavp.ch =
gke 0:62a1c91a859a 6 // ===============================================================================================
gke 0:62a1c91a859a 7
gke 0:62a1c91a859a 8 // This is part of UAVXArm.
gke 0:62a1c91a859a 9
gke 0:62a1c91a859a 10 // UAVXArm is free software: you can redistribute it and/or modify it under the terms of the GNU
gke 0:62a1c91a859a 11 // General Public License as published by the Free Software Foundation, either version 3 of the
gke 0:62a1c91a859a 12 // License, or (at your option) any later version.
gke 0:62a1c91a859a 13
gke 0:62a1c91a859a 14 // UAVXArm is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without
gke 0:62a1c91a859a 15 // even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
gke 0:62a1c91a859a 16 // See the GNU General Public License for more details.
gke 0:62a1c91a859a 17
gke 0:62a1c91a859a 18 // You should have received a copy of the GNU General Public License along with this program.
gke 0:62a1c91a859a 19 // If not, see http://www.gnu.org/licenses/
gke 0:62a1c91a859a 20
gke 0:62a1c91a859a 21 #include "UAVXArm.h"
gke 0:62a1c91a859a 22
gke 1:1e3318a30ddd 23 boolean I2C0AddressResponds(uint8);
gke 1:1e3318a30ddd 24 #ifdef HAVE_I2C1
gke 1:1e3318a30ddd 25 boolean I2C1AddressResponds(uint8);
gke 1:1e3318a30ddd 26 #endif // HAVE_I2C1
gke 1:1e3318a30ddd 27 void TrackMinI2CRate(uint32);
gke 1:1e3318a30ddd 28 void ShowI2CDeviceName(uint8);
gke 1:1e3318a30ddd 29 uint8 ScanI2CBus(void);
gke 1:1e3318a30ddd 30 boolean ESCWaitClkHi(void);
gke 1:1e3318a30ddd 31 void ProgramSlaveAddress(uint8);
gke 1:1e3318a30ddd 32 void ConfigureESCs(void);
gke 1:1e3318a30ddd 33
gke 0:62a1c91a859a 34 uint32 MinI2CRate = I2C_MAX_RATE_HZ;
gke 0:62a1c91a859a 35
gke 1:1e3318a30ddd 36 //______________________________________________________________________________________________
gke 1:1e3318a30ddd 37
gke 1:1e3318a30ddd 38 // Software I2C
gke 1:1e3318a30ddd 39
gke 1:1e3318a30ddd 40 #ifdef SW_I2C
gke 1:1e3318a30ddd 41
gke 1:1e3318a30ddd 42 #define I2CDelay5uS wait_us(5)
gke 1:1e3318a30ddd 43 #define I2CDelay2uS // wait_us(2)
gke 1:1e3318a30ddd 44 #define HighLowDelay // wait_us(1)
gke 1:1e3318a30ddd 45 #define FloatDelay // ???
gke 1:1e3318a30ddd 46
gke 1:1e3318a30ddd 47 #define I2CSDALow {I2C0SDA.write(0);HighLowDelay;I2C0SDA.output();}
gke 1:1e3318a30ddd 48 #define I2CSDAFloat {I2C0SDA.input();}
gke 1:1e3318a30ddd 49 #define I2CSCLLow {I2C0SCL.write(0);HighLowDelay;I2C0SCL.output();}
gke 1:1e3318a30ddd 50 #define I2CSCLFloat {I2C0SCL.input();FloatDelay;}
gke 1:1e3318a30ddd 51
gke 1:1e3318a30ddd 52 void MyI2C::frequency(uint32 f) {
gke 1:1e3318a30ddd 53 // delay depending on rate
gke 1:1e3318a30ddd 54 } // frequency
gke 1:1e3318a30ddd 55
gke 1:1e3318a30ddd 56 boolean MyI2C::waitclock(void) {
gke 1:1e3318a30ddd 57 static uint32 s;
gke 1:1e3318a30ddd 58
gke 1:1e3318a30ddd 59 I2CSCLFloat; // set SCL to input, output a high
gke 1:1e3318a30ddd 60 s = 0;
gke 1:1e3318a30ddd 61 while ( !I2C0SCL.read() )
gke 1:1e3318a30ddd 62 if ( ++s > 60000 ) {
gke 1:1e3318a30ddd 63 Stats[I2CFailS]++;
gke 1:1e3318a30ddd 64 return (false);
gke 1:1e3318a30ddd 65 }
gke 1:1e3318a30ddd 66 return( true );
gke 1:1e3318a30ddd 67 } // waitclock
gke 1:1e3318a30ddd 68
gke 1:1e3318a30ddd 69 void MyI2C::start(void) {
gke 1:1e3318a30ddd 70 static boolean r;
gke 1:1e3318a30ddd 71
gke 1:1e3318a30ddd 72 I2CSDAFloat;
gke 1:1e3318a30ddd 73 r = waitclock();
gke 1:1e3318a30ddd 74 I2CSDALow;
gke 1:1e3318a30ddd 75 I2CDelay5uS;
gke 1:1e3318a30ddd 76 I2CSCLLow;
gke 1:1e3318a30ddd 77 } // start
gke 1:1e3318a30ddd 78
gke 1:1e3318a30ddd 79 void MyI2C::stop(void) {
gke 1:1e3318a30ddd 80 static boolean r;
gke 1:1e3318a30ddd 81
gke 1:1e3318a30ddd 82 I2CSDALow;
gke 1:1e3318a30ddd 83 r = waitclock();
gke 1:1e3318a30ddd 84 I2CSDAFloat;
gke 1:1e3318a30ddd 85 I2CDelay5uS;
gke 1:1e3318a30ddd 86 } // stop
gke 1:1e3318a30ddd 87
gke 1:1e3318a30ddd 88 uint8 MyI2C::blockread(uint8 a, char* S, uint8 l) {
gke 1:1e3318a30ddd 89 static uint8 b;
gke 1:1e3318a30ddd 90 static boolean err;
gke 1:1e3318a30ddd 91
gke 1:1e3318a30ddd 92 I2C0.start();
gke 1:1e3318a30ddd 93 err = I2C0.write(a|1) != I2C_ACK;
gke 1:1e3318a30ddd 94 for (b = 0; b < (l - 1); b++)
gke 1:1e3318a30ddd 95 S[b] = I2C0.read(I2C_ACK);
gke 1:1e3318a30ddd 96 S[l-1] = I2C0.read(I2C_NACK);
gke 1:1e3318a30ddd 97 I2C0.stop();
gke 1:1e3318a30ddd 98
gke 1:1e3318a30ddd 99 return( err );
gke 1:1e3318a30ddd 100 } // blockread
gke 1:1e3318a30ddd 101
gke 1:1e3318a30ddd 102 uint8 MyI2C::read(uint8 ack) {
gke 1:1e3318a30ddd 103 static uint8 s, d;
gke 1:1e3318a30ddd 104
gke 1:1e3318a30ddd 105 I2CSDAFloat;
gke 1:1e3318a30ddd 106 d = 0;
gke 1:1e3318a30ddd 107 s = 8;
gke 1:1e3318a30ddd 108 do {
gke 1:1e3318a30ddd 109 if ( waitclock() ) {
gke 1:1e3318a30ddd 110 d <<= 1;
gke 1:1e3318a30ddd 111 if ( I2C0SDA.read() ) d |= 1;
gke 1:1e3318a30ddd 112 I2CSCLLow;
gke 1:1e3318a30ddd 113 I2CDelay2uS;
gke 1:1e3318a30ddd 114 } else
gke 1:1e3318a30ddd 115 return( 0 );
gke 1:1e3318a30ddd 116 } while ( --s );
gke 1:1e3318a30ddd 117
gke 1:1e3318a30ddd 118 I2C0SDA.write(ack);
gke 1:1e3318a30ddd 119 HighLowDelay;
gke 1:1e3318a30ddd 120 I2C0SDA.output();
gke 1:1e3318a30ddd 121 HighLowDelay;
gke 1:1e3318a30ddd 122
gke 1:1e3318a30ddd 123 if ( waitclock() ) {
gke 1:1e3318a30ddd 124 I2CSCLLow;
gke 1:1e3318a30ddd 125 return( d );
gke 1:1e3318a30ddd 126 } else
gke 1:1e3318a30ddd 127 return( 0 );
gke 1:1e3318a30ddd 128 } // read
gke 1:1e3318a30ddd 129
gke 1:1e3318a30ddd 130 void MyI2C::blockwrite(uint8 a, const char* S, uint8 l) {
gke 1:1e3318a30ddd 131 static uint8 b;
gke 1:1e3318a30ddd 132 static boolean r;
gke 1:1e3318a30ddd 133
gke 1:1e3318a30ddd 134 I2C0.start();
gke 1:1e3318a30ddd 135 r = I2C0.write(a) == I2C_ACK; // use this?
gke 1:1e3318a30ddd 136 for ( b = 0; b < l; b++ )
gke 1:1e3318a30ddd 137 r |= I2C0.write(S[b]);
gke 1:1e3318a30ddd 138 I2C0.stop();
gke 1:1e3318a30ddd 139
gke 1:1e3318a30ddd 140 } // blockwrite
gke 1:1e3318a30ddd 141
gke 1:1e3318a30ddd 142 uint8 MyI2C::write(uint8 d) {
gke 1:1e3318a30ddd 143 static uint8 s, r;
gke 1:1e3318a30ddd 144
gke 1:1e3318a30ddd 145 for ( s = 0; s < 8; s++)
gke 1:1e3318a30ddd 146 {
gke 1:1e3318a30ddd 147 if ( d & 0x80 ) {
gke 1:1e3318a30ddd 148 I2CSDAFloat;
gke 1:1e3318a30ddd 149 } else {
gke 1:1e3318a30ddd 150 I2CSDALow;
gke 1:1e3318a30ddd 151 }
gke 1:1e3318a30ddd 152
gke 1:1e3318a30ddd 153 if ( waitclock() ) {
gke 1:1e3318a30ddd 154 I2CSCLLow;
gke 1:1e3318a30ddd 155 d <<= 1;
gke 1:1e3318a30ddd 156 } else
gke 1:1e3318a30ddd 157 return(I2C_NACK);
gke 1:1e3318a30ddd 158 }
gke 1:1e3318a30ddd 159
gke 1:1e3318a30ddd 160 I2CSDAFloat;
gke 1:1e3318a30ddd 161 if ( waitclock() ) {
gke 1:1e3318a30ddd 162 r = I2C0SDA.read();
gke 1:1e3318a30ddd 163 I2CSCLLow;
gke 1:1e3318a30ddd 164 return( r );
gke 1:1e3318a30ddd 165 } else
gke 1:1e3318a30ddd 166 return(I2C_NACK);
gke 1:1e3318a30ddd 167
gke 1:1e3318a30ddd 168 } // write
gke 1:1e3318a30ddd 169
gke 1:1e3318a30ddd 170 #endif // SW_I2C
gke 1:1e3318a30ddd 171
gke 1:1e3318a30ddd 172 //______________________________________________________________________________________________
gke 1:1e3318a30ddd 173
gke 0:62a1c91a859a 174 void TrackMinI2CRate(uint32 r) {
gke 1:1e3318a30ddd 175 if ( r < MinI2CRate )
gke 1:1e3318a30ddd 176 MinI2CRate = r;
gke 0:62a1c91a859a 177 } // TrackMinI2CRate
gke 0:62a1c91a859a 178
gke 1:1e3318a30ddd 179 void ShowI2CDeviceName(uint8 d) {
gke 0:62a1c91a859a 180 TxChar(' ');
gke 0:62a1c91a859a 181 switch ( d ) {
gke 1:1e3318a30ddd 182 case ADXL345_ID:
gke 1:1e3318a30ddd 183 TxString("ADXL345 Acc");
gke 1:1e3318a30ddd 184 break;
gke 1:1e3318a30ddd 185 case ITG3200_ID:
gke 1:1e3318a30ddd 186 TxString("ITG3200 Gyro");
gke 1:1e3318a30ddd 187 break;
gke 1:1e3318a30ddd 188 case HMC5843_ID:
gke 1:1e3318a30ddd 189 TxString("HMC5843 Magnetometer");
gke 1:1e3318a30ddd 190 break;
gke 1:1e3318a30ddd 191 case HMC6352_ID:
gke 1:1e3318a30ddd 192 TxString("HMC6352 Compass");
gke 1:1e3318a30ddd 193 break;
gke 1:1e3318a30ddd 194 case ADS7823_ID:
gke 1:1e3318a30ddd 195 TxString("ADS7823 ADC");
gke 1:1e3318a30ddd 196 break;
gke 1:1e3318a30ddd 197 case MCP4725_ID_0xCC:
gke 1:1e3318a30ddd 198 TxString("MCP4725 DAC");
gke 1:1e3318a30ddd 199 break;
gke 1:1e3318a30ddd 200 case MCP4725_ID_0xC8:
gke 1:1e3318a30ddd 201 TxString("MCP4725 DAC");
gke 1:1e3318a30ddd 202 break;
gke 1:1e3318a30ddd 203 case BOSCH_ID:
gke 1:1e3318a30ddd 204 TxString("Bosch Baro");
gke 1:1e3318a30ddd 205 break;
gke 1:1e3318a30ddd 206 case TMP100_ID:
gke 1:1e3318a30ddd 207 TxString("TMP100 Temp");
gke 1:1e3318a30ddd 208 break;
gke 1:1e3318a30ddd 209 case PCA9551_ID:
gke 1:1e3318a30ddd 210 TxString("PCA9551 LED");
gke 1:1e3318a30ddd 211 break;
gke 1:1e3318a30ddd 212 case LISL_ID:
gke 1:1e3318a30ddd 213 TxString("LIS3L Acc");
gke 1:1e3318a30ddd 214 break;
gke 1:1e3318a30ddd 215 default:
gke 1:1e3318a30ddd 216 break;
gke 0:62a1c91a859a 217 } // switch
gke 0:62a1c91a859a 218 TxChar(' ');
gke 0:62a1c91a859a 219
gke 0:62a1c91a859a 220 } // ShowI2CDeviceName
gke 0:62a1c91a859a 221
gke 1:1e3318a30ddd 222 boolean I2C0AddressResponds(uint8 s) {
gke 1:1e3318a30ddd 223 static boolean r;
gke 1:1e3318a30ddd 224 I2C0.start();
gke 1:1e3318a30ddd 225 r = I2C0.write(s) == I2C_ACK;
gke 1:1e3318a30ddd 226 I2C0.stop();
gke 1:1e3318a30ddd 227 return (r);
gke 1:1e3318a30ddd 228 } // I2C0AddressResponds
gke 1:1e3318a30ddd 229
gke 1:1e3318a30ddd 230 #ifdef HAVE_IC1
gke 1:1e3318a30ddd 231 boolean I2C1AddressResponds(uint8 s) {
gke 1:1e3318a30ddd 232 static boolean r;
gke 1:1e3318a30ddd 233 I2C1.start();
gke 1:1e3318a30ddd 234 r = I2C1.write(s) == I2C_ACK;
gke 1:1e3318a30ddd 235 I2C1.stop();
gke 1:1e3318a30ddd 236 return (r);
gke 1:1e3318a30ddd 237 } // I2C1AddressResponds
gke 1:1e3318a30ddd 238 #endif // HAVE_IC1
gke 1:1e3318a30ddd 239
gke 0:62a1c91a859a 240 uint8 ScanI2CBus(void) {
gke 0:62a1c91a859a 241 uint8 s;
gke 0:62a1c91a859a 242 uint8 d;
gke 0:62a1c91a859a 243
gke 0:62a1c91a859a 244 d = 0;
gke 0:62a1c91a859a 245 TxString("Buss 0\r\n");
gke 0:62a1c91a859a 246 for ( s = 0x10 ; s <= 0xf6 ; s += 2 ) {
gke 1:1e3318a30ddd 247 if ( I2C0AddressResponds(s) ) {
gke 1:1e3318a30ddd 248 d++;
gke 1:1e3318a30ddd 249 DebugPin = 1;
gke 1:1e3318a30ddd 250 TxString("\t0x");
gke 1:1e3318a30ddd 251 TxValH(s);
gke 1:1e3318a30ddd 252 ShowI2CDeviceName( s );
gke 1:1e3318a30ddd 253 TxNextLine();
gke 1:1e3318a30ddd 254 DebugPin = 0;
gke 1:1e3318a30ddd 255 }
gke 1:1e3318a30ddd 256 Delay1mS(2);
gke 1:1e3318a30ddd 257 }
gke 1:1e3318a30ddd 258
gke 1:1e3318a30ddd 259 #ifdef HAVE_I2C1
gke 1:1e3318a30ddd 260 TxString("Buss 1\r\n");
gke 1:1e3318a30ddd 261 for ( s = 0x10 ; s <= 0xf6 ; s += 2 ) {
gke 1:1e3318a30ddd 262 if ( I2C0AddressResponds(s) ) {
gke 0:62a1c91a859a 263 d++;
gke 0:62a1c91a859a 264 TxString("\t0x");
gke 0:62a1c91a859a 265 TxValH(s);
gke 0:62a1c91a859a 266 ShowI2CDeviceName( s );
gke 0:62a1c91a859a 267 TxNextLine();
gke 0:62a1c91a859a 268 }
gke 0:62a1c91a859a 269 Delay1mS(2);
gke 0:62a1c91a859a 270 }
gke 1:1e3318a30ddd 271 #endif // HAVE_I2C1
gke 0:62a1c91a859a 272
gke 0:62a1c91a859a 273 PCA9551Test();
gke 0:62a1c91a859a 274
gke 0:62a1c91a859a 275 return(d);
gke 0:62a1c91a859a 276 } // ScanI2CBus
gke 0:62a1c91a859a 277
gke 1:1e3318a30ddd 278 void ProgramSlaveAddress(uint8 a) {
gke 0:62a1c91a859a 279 static uint8 s;
gke 0:62a1c91a859a 280
gke 0:62a1c91a859a 281 for (s = 0x10 ; s < 0xf0 ; s += 2 ) {
gke 0:62a1c91a859a 282 I2CESC.start();
gke 0:62a1c91a859a 283 if ( I2CESC.read(s) == I2C_ACK )
gke 1:1e3318a30ddd 284 if ( s == a ) { // ESC is already programmed OK
gke 0:62a1c91a859a 285 I2CESC.stop();
gke 0:62a1c91a859a 286 TxString("\tESC at SLA 0x");
gke 1:1e3318a30ddd 287 TxValH(a);
gke 0:62a1c91a859a 288 TxString(" is already programmed OK\r\n");
gke 0:62a1c91a859a 289 return;
gke 0:62a1c91a859a 290 } else {
gke 0:62a1c91a859a 291 if ( I2CESC.read(0x87) == I2C_ACK ) // select register 0x07
gke 1:1e3318a30ddd 292 if ( I2CESC.write( a ) == I2C_ACK ) { // new slave address
gke 0:62a1c91a859a 293 I2CESC.stop();
gke 0:62a1c91a859a 294 TxString("\tESC at SLA 0x");
gke 0:62a1c91a859a 295 TxValH(s);
gke 0:62a1c91a859a 296 TxString(" reprogrammed to SLA 0x");
gke 1:1e3318a30ddd 297 TxValH(a);
gke 0:62a1c91a859a 298 TxNextLine();
gke 0:62a1c91a859a 299 return;
gke 0:62a1c91a859a 300 }
gke 0:62a1c91a859a 301 }
gke 0:62a1c91a859a 302 I2CESC.stop();
gke 0:62a1c91a859a 303 }
gke 0:62a1c91a859a 304 TxString("\tESC at SLA 0x");
gke 1:1e3318a30ddd 305 TxValH(a);
gke 0:62a1c91a859a 306 TxString(" no response - check cabling and pullup resistors!\r\n");
gke 0:62a1c91a859a 307 } // ProgramSlaveAddress
gke 0:62a1c91a859a 308
gke 0:62a1c91a859a 309 boolean CheckESCBus(void) {
gke 0:62a1c91a859a 310 return ( true );
gke 0:62a1c91a859a 311 } // CheckESCBus
gke 0:62a1c91a859a 312
gke 0:62a1c91a859a 313 void ConfigureESCs(void) {
gke 0:62a1c91a859a 314 int8 m;
gke 0:62a1c91a859a 315
gke 0:62a1c91a859a 316 if ( (int8)P[ESCType] == ESCYGEI2C ) {
gke 0:62a1c91a859a 317 TxString("\r\nProgram YGE ESCs\r\n");
gke 0:62a1c91a859a 318 for ( m = 0 ; m < NoOfI2CESCOutputs ; m++ ) {
gke 1:1e3318a30ddd 319 TxString("Connect ONLY M");
gke 1:1e3318a30ddd 320 TxChar('1' + m);
gke 0:62a1c91a859a 321 TxString(" ESC, then press any key \r\n");
gke 0:62a1c91a859a 322 while ( PollRxChar() != 'x' ); // UAVPSet uses 'x' for any key button
gke 0:62a1c91a859a 323 // TxString("\r\n");
gke 0:62a1c91a859a 324 ProgramSlaveAddress( 0x62 + ( m*2 ));
gke 0:62a1c91a859a 325 }
gke 0:62a1c91a859a 326 TxString("\r\nConnect ALL ESCs and power-cycle the Quadrocopter\r\n");
gke 0:62a1c91a859a 327 } else
gke 0:62a1c91a859a 328 TxString("\r\nYGEI2C not selected as ESC?\r\n");
gke 0:62a1c91a859a 329 } // ConfigureESCs
gke 0:62a1c91a859a 330
gke 0:62a1c91a859a 331
gke 0:62a1c91a859a 332