Prof Greg Egan
/
UAVXArm-GKE
UAVX Multicopter Flight Controller.
i2c.c@2:90292f8bd179, 2011-04-26 (annotated)
- Committer:
- gke
- Date:
- Tue Apr 26 12:12:29 2011 +0000
- Revision:
- 2:90292f8bd179
- Parent:
- 1:1e3318a30ddd
Not flightworthy. Posted for others to make use of the I2C SW code.
Who changed what in which revision?
User | Revision | Line number | New 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 | 2:90292f8bd179 | 5 | // = http://code.google.com/p/uavp-mods/ = |
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 | 2:90292f8bd179 | 34 | uint16 I2CError[256]; |
gke | 2:90292f8bd179 | 35 | uint8 I2CSpeed = 10; // 100KHz |
gke | 0:62a1c91a859a | 36 | uint32 MinI2CRate = I2C_MAX_RATE_HZ; |
gke | 0:62a1c91a859a | 37 | |
gke | 1:1e3318a30ddd | 38 | //______________________________________________________________________________________________ |
gke | 1:1e3318a30ddd | 39 | |
gke | 1:1e3318a30ddd | 40 | // Software I2C |
gke | 1:1e3318a30ddd | 41 | |
gke | 1:1e3318a30ddd | 42 | #ifdef SW_I2C |
gke | 1:1e3318a30ddd | 43 | |
gke | 2:90292f8bd179 | 44 | void SDelay(uint16 d) { // 1.25 + 0.0475 * n uS ~0.05uS per click |
gke | 2:90292f8bd179 | 45 | |
gke | 2:90292f8bd179 | 46 | volatile int16 v; |
gke | 2:90292f8bd179 | 47 | |
gke | 2:90292f8bd179 | 48 | for (v = 0; v < d ; v++ ) {}; |
gke | 2:90292f8bd179 | 49 | |
gke | 2:90292f8bd179 | 50 | } // SDelay |
gke | 2:90292f8bd179 | 51 | |
gke | 2:90292f8bd179 | 52 | /* |
gke | 2:90292f8bd179 | 53 | #define SCLLowStartT SDelay(I2CSpeed) |
gke | 2:90292f8bd179 | 54 | #define DataLowPadT SDelay(I2CSpeed) |
gke | 2:90292f8bd179 | 55 | #define SCLLowPadT SDelay(I2CSpeed) |
gke | 2:90292f8bd179 | 56 | #define SCLHighT SDelay(I2CSpeed) |
gke | 2:90292f8bd179 | 57 | */ |
gke | 2:90292f8bd179 | 58 | |
gke | 2:90292f8bd179 | 59 | #if ( I2C_MAX_RATE_HZ == 400000 ) |
gke | 1:1e3318a30ddd | 60 | |
gke | 2:90292f8bd179 | 61 | #define SCLLowStartT SDelay(10) |
gke | 2:90292f8bd179 | 62 | #define DataLowPadT SDelay(16) // 10 |
gke | 2:90292f8bd179 | 63 | #define SCLLowPadT SDelay(6) |
gke | 2:90292f8bd179 | 64 | #define SCLHighT SDelay(10) |
gke | 2:90292f8bd179 | 65 | |
gke | 2:90292f8bd179 | 66 | #else |
gke | 2:90292f8bd179 | 67 | |
gke | 2:90292f8bd179 | 68 | #define SCLLowStartT SDelay(82) |
gke | 2:90292f8bd179 | 69 | #define DataLowPadT SDelay(82) |
gke | 2:90292f8bd179 | 70 | #define SCLLowPadT SDelay(82) |
gke | 2:90292f8bd179 | 71 | #define SCLHighT SDelay(85) |
gke | 2:90292f8bd179 | 72 | |
gke | 2:90292f8bd179 | 73 | #endif //I2C400KHZ |
gke | 2:90292f8bd179 | 74 | |
gke | 2:90292f8bd179 | 75 | |
gke | 2:90292f8bd179 | 76 | #define I2CSDALow {I2C0SDA.write(0);I2C0SDA.output();SCLLowPadT;} |
gke | 2:90292f8bd179 | 77 | #define I2CSDAFloat {I2C0SDA.input();SCLLowPadT;} |
gke | 2:90292f8bd179 | 78 | #define I2CSCLLow {I2C0SCL.write(0);I2C0SCL.output();} |
gke | 2:90292f8bd179 | 79 | #define I2CSCLFloat {I2C0SCL.input();SCLHighT;} |
gke | 1:1e3318a30ddd | 80 | |
gke | 1:1e3318a30ddd | 81 | void MyI2C::frequency(uint32 f) { |
gke | 1:1e3318a30ddd | 82 | // delay depending on rate |
gke | 2:90292f8bd179 | 83 | |
gke | 2:90292f8bd179 | 84 | if ( f == 400000 ) |
gke | 2:90292f8bd179 | 85 | I2CSpeed = 10; |
gke | 2:90292f8bd179 | 86 | else |
gke | 2:90292f8bd179 | 87 | I2CSpeed = 80; |
gke | 1:1e3318a30ddd | 88 | } // frequency |
gke | 1:1e3318a30ddd | 89 | |
gke | 2:90292f8bd179 | 90 | void MyI2C::start(void) { |
gke | 2:90292f8bd179 | 91 | |
gke | 2:90292f8bd179 | 92 | I2CSDAFloat; |
gke | 2:90292f8bd179 | 93 | r = waitclock(); |
gke | 2:90292f8bd179 | 94 | I2CSDALow; |
gke | 2:90292f8bd179 | 95 | SCLLowStartT; |
gke | 2:90292f8bd179 | 96 | I2CSCLLow; |
gke | 2:90292f8bd179 | 97 | } // start |
gke | 2:90292f8bd179 | 98 | |
gke | 2:90292f8bd179 | 99 | void MyI2C::stop(void) { |
gke | 2:90292f8bd179 | 100 | |
gke | 2:90292f8bd179 | 101 | I2CSDALow; |
gke | 2:90292f8bd179 | 102 | r = waitclock(); |
gke | 2:90292f8bd179 | 103 | I2CSDAFloat; |
gke | 2:90292f8bd179 | 104 | SCLLowStartT; |
gke | 2:90292f8bd179 | 105 | |
gke | 2:90292f8bd179 | 106 | } // stop |
gke | 2:90292f8bd179 | 107 | |
gke | 1:1e3318a30ddd | 108 | boolean MyI2C::waitclock(void) { |
gke | 1:1e3318a30ddd | 109 | static uint32 s; |
gke | 1:1e3318a30ddd | 110 | |
gke | 1:1e3318a30ddd | 111 | I2CSCLFloat; // set SCL to input, output a high |
gke | 1:1e3318a30ddd | 112 | s = 0; |
gke | 2:90292f8bd179 | 113 | while ( I2C0SCL.read() == 0 ) |
gke | 2:90292f8bd179 | 114 | if ( ++s > 16000 ) { // ~1mS |
gke | 2:90292f8bd179 | 115 | I2CError[0]++; |
gke | 2:90292f8bd179 | 116 | // possible add SCL cycles here to attempt to force device reset |
gke | 1:1e3318a30ddd | 117 | Stats[I2CFailS]++; |
gke | 1:1e3318a30ddd | 118 | return (false); |
gke | 1:1e3318a30ddd | 119 | } |
gke | 1:1e3318a30ddd | 120 | return( true ); |
gke | 1:1e3318a30ddd | 121 | } // waitclock |
gke | 1:1e3318a30ddd | 122 | |
gke | 2:90292f8bd179 | 123 | uint8 MyI2C::read(uint8 ack) { |
gke | 2:90292f8bd179 | 124 | static uint8 s, d; |
gke | 1:1e3318a30ddd | 125 | |
gke | 1:1e3318a30ddd | 126 | I2CSDAFloat; |
gke | 2:90292f8bd179 | 127 | d = 0; |
gke | 2:90292f8bd179 | 128 | s = 8; |
gke | 2:90292f8bd179 | 129 | do { |
gke | 2:90292f8bd179 | 130 | if ( waitclock() ) { |
gke | 2:90292f8bd179 | 131 | d <<= 1; |
gke | 2:90292f8bd179 | 132 | if ( I2C0SDA.read() ) { |
gke | 2:90292f8bd179 | 133 | d |= 1; |
gke | 2:90292f8bd179 | 134 | I2CSCLLow; |
gke | 2:90292f8bd179 | 135 | DataLowPadT; |
gke | 2:90292f8bd179 | 136 | } else { |
gke | 2:90292f8bd179 | 137 | I2CSCLLow; |
gke | 2:90292f8bd179 | 138 | SDelay(10);//DataLowPadT; |
gke | 2:90292f8bd179 | 139 | } |
gke | 2:90292f8bd179 | 140 | } else |
gke | 2:90292f8bd179 | 141 | return( 0 ); |
gke | 2:90292f8bd179 | 142 | } while ( --s ); |
gke | 2:90292f8bd179 | 143 | |
gke | 2:90292f8bd179 | 144 | if ( ack == I2C_NACK ) |
gke | 2:90292f8bd179 | 145 | I2C0SDA.write(0xffff); // Port write with mask selecting SDA - messy |
gke | 2:90292f8bd179 | 146 | else |
gke | 2:90292f8bd179 | 147 | I2C0SDA.write(0); |
gke | 2:90292f8bd179 | 148 | I2C0SDA.output(); |
gke | 2:90292f8bd179 | 149 | |
gke | 2:90292f8bd179 | 150 | SCLLowPadT; |
gke | 2:90292f8bd179 | 151 | |
gke | 2:90292f8bd179 | 152 | if ( waitclock() ) { |
gke | 2:90292f8bd179 | 153 | I2CSCLLow; |
gke | 2:90292f8bd179 | 154 | return( d ); |
gke | 2:90292f8bd179 | 155 | } else |
gke | 2:90292f8bd179 | 156 | return( 0 ); |
gke | 2:90292f8bd179 | 157 | |
gke | 2:90292f8bd179 | 158 | } // read |
gke | 1:1e3318a30ddd | 159 | |
gke | 2:90292f8bd179 | 160 | uint8 MyI2C::write(uint8 d) { |
gke | 2:90292f8bd179 | 161 | static uint8 s, r; |
gke | 2:90292f8bd179 | 162 | |
gke | 2:90292f8bd179 | 163 | for ( s = 0; s < 8; s++) { |
gke | 2:90292f8bd179 | 164 | if ( d & 0x80 ) { |
gke | 2:90292f8bd179 | 165 | I2CSDAFloat; |
gke | 2:90292f8bd179 | 166 | } else { |
gke | 2:90292f8bd179 | 167 | I2CSDALow; |
gke | 2:90292f8bd179 | 168 | } |
gke | 1:1e3318a30ddd | 169 | |
gke | 2:90292f8bd179 | 170 | if ( waitclock() ) { |
gke | 2:90292f8bd179 | 171 | I2CSCLLow; |
gke | 2:90292f8bd179 | 172 | d <<= 1; |
gke | 2:90292f8bd179 | 173 | } else |
gke | 2:90292f8bd179 | 174 | return(I2C_NACK); |
gke | 2:90292f8bd179 | 175 | } |
gke | 2:90292f8bd179 | 176 | |
gke | 1:1e3318a30ddd | 177 | I2CSDAFloat; |
gke | 2:90292f8bd179 | 178 | if ( waitclock() ) { |
gke | 2:90292f8bd179 | 179 | if ( I2C0SDA.read() ) |
gke | 2:90292f8bd179 | 180 | r = I2C_NACK; |
gke | 2:90292f8bd179 | 181 | else |
gke | 2:90292f8bd179 | 182 | r = I2C_ACK; |
gke | 2:90292f8bd179 | 183 | I2CSDALow;// kill runt pulses |
gke | 2:90292f8bd179 | 184 | I2CSCLLow; |
gke | 2:90292f8bd179 | 185 | return ( r ); |
gke | 2:90292f8bd179 | 186 | } else { |
gke | 2:90292f8bd179 | 187 | // I2CSCLLow; |
gke | 2:90292f8bd179 | 188 | return(I2C_NACK); |
gke | 2:90292f8bd179 | 189 | } |
gke | 2:90292f8bd179 | 190 | |
gke | 2:90292f8bd179 | 191 | } // write |
gke | 1:1e3318a30ddd | 192 | |
gke | 1:1e3318a30ddd | 193 | uint8 MyI2C::blockread(uint8 a, char* S, uint8 l) { |
gke | 1:1e3318a30ddd | 194 | static uint8 b; |
gke | 1:1e3318a30ddd | 195 | static boolean err; |
gke | 1:1e3318a30ddd | 196 | |
gke | 1:1e3318a30ddd | 197 | I2C0.start(); |
gke | 1:1e3318a30ddd | 198 | err = I2C0.write(a|1) != I2C_ACK; |
gke | 1:1e3318a30ddd | 199 | for (b = 0; b < (l - 1); b++) |
gke | 1:1e3318a30ddd | 200 | S[b] = I2C0.read(I2C_ACK); |
gke | 1:1e3318a30ddd | 201 | S[l-1] = I2C0.read(I2C_NACK); |
gke | 1:1e3318a30ddd | 202 | I2C0.stop(); |
gke | 1:1e3318a30ddd | 203 | |
gke | 1:1e3318a30ddd | 204 | return( err ); |
gke | 1:1e3318a30ddd | 205 | } // blockread |
gke | 1:1e3318a30ddd | 206 | |
gke | 2:90292f8bd179 | 207 | boolean MyI2C::blockwrite(uint8 a, const char* S, uint8 l) { |
gke | 1:1e3318a30ddd | 208 | static uint8 b; |
gke | 1:1e3318a30ddd | 209 | |
gke | 1:1e3318a30ddd | 210 | I2C0.start(); |
gke | 2:90292f8bd179 | 211 | if ( I2C0.write(a) != I2C_ACK ) goto BlockWriteError; // use this? |
gke | 1:1e3318a30ddd | 212 | for ( b = 0; b < l; b++ ) |
gke | 2:90292f8bd179 | 213 | if ( I2C0.write(S[b]) != I2C_ACK ) goto BlockWriteError; |
gke | 1:1e3318a30ddd | 214 | I2C0.stop(); |
gke | 1:1e3318a30ddd | 215 | |
gke | 2:90292f8bd179 | 216 | return(false); |
gke | 2:90292f8bd179 | 217 | |
gke | 2:90292f8bd179 | 218 | BlockWriteError: |
gke | 2:90292f8bd179 | 219 | I2C0.stop(); |
gke | 2:90292f8bd179 | 220 | |
gke | 2:90292f8bd179 | 221 | return(true); |
gke | 2:90292f8bd179 | 222 | |
gke | 1:1e3318a30ddd | 223 | } // blockwrite |
gke | 1:1e3318a30ddd | 224 | |
gke | 1:1e3318a30ddd | 225 | #endif // SW_I2C |
gke | 1:1e3318a30ddd | 226 | |
gke | 1:1e3318a30ddd | 227 | //______________________________________________________________________________________________ |
gke | 1:1e3318a30ddd | 228 | |
gke | 0:62a1c91a859a | 229 | void TrackMinI2CRate(uint32 r) { |
gke | 2:90292f8bd179 | 230 | |
gke | 2:90292f8bd179 | 231 | // CURRENTLY USING DEFINE TO SPECIFY RATE - UAVXArm.h |
gke | 1:1e3318a30ddd | 232 | if ( r < MinI2CRate ) |
gke | 1:1e3318a30ddd | 233 | MinI2CRate = r; |
gke | 0:62a1c91a859a | 234 | } // TrackMinI2CRate |
gke | 0:62a1c91a859a | 235 | |
gke | 1:1e3318a30ddd | 236 | void ShowI2CDeviceName(uint8 d) { |
gke | 0:62a1c91a859a | 237 | TxChar(' '); |
gke | 0:62a1c91a859a | 238 | switch ( d ) { |
gke | 1:1e3318a30ddd | 239 | case ADXL345_ID: |
gke | 1:1e3318a30ddd | 240 | TxString("ADXL345 Acc"); |
gke | 1:1e3318a30ddd | 241 | break; |
gke | 1:1e3318a30ddd | 242 | case ITG3200_ID: |
gke | 1:1e3318a30ddd | 243 | TxString("ITG3200 Gyro"); |
gke | 1:1e3318a30ddd | 244 | break; |
gke | 1:1e3318a30ddd | 245 | case HMC5843_ID: |
gke | 1:1e3318a30ddd | 246 | TxString("HMC5843 Magnetometer"); |
gke | 1:1e3318a30ddd | 247 | break; |
gke | 1:1e3318a30ddd | 248 | case HMC6352_ID: |
gke | 1:1e3318a30ddd | 249 | TxString("HMC6352 Compass"); |
gke | 1:1e3318a30ddd | 250 | break; |
gke | 1:1e3318a30ddd | 251 | case ADS7823_ID: |
gke | 1:1e3318a30ddd | 252 | TxString("ADS7823 ADC"); |
gke | 1:1e3318a30ddd | 253 | break; |
gke | 1:1e3318a30ddd | 254 | case MCP4725_ID_0xCC: |
gke | 1:1e3318a30ddd | 255 | TxString("MCP4725 DAC"); |
gke | 1:1e3318a30ddd | 256 | break; |
gke | 1:1e3318a30ddd | 257 | case MCP4725_ID_0xC8: |
gke | 1:1e3318a30ddd | 258 | TxString("MCP4725 DAC"); |
gke | 1:1e3318a30ddd | 259 | break; |
gke | 1:1e3318a30ddd | 260 | case BOSCH_ID: |
gke | 1:1e3318a30ddd | 261 | TxString("Bosch Baro"); |
gke | 1:1e3318a30ddd | 262 | break; |
gke | 1:1e3318a30ddd | 263 | case TMP100_ID: |
gke | 1:1e3318a30ddd | 264 | TxString("TMP100 Temp"); |
gke | 1:1e3318a30ddd | 265 | break; |
gke | 1:1e3318a30ddd | 266 | case PCA9551_ID: |
gke | 1:1e3318a30ddd | 267 | TxString("PCA9551 LED"); |
gke | 1:1e3318a30ddd | 268 | break; |
gke | 1:1e3318a30ddd | 269 | case LISL_ID: |
gke | 1:1e3318a30ddd | 270 | TxString("LIS3L Acc"); |
gke | 1:1e3318a30ddd | 271 | break; |
gke | 1:1e3318a30ddd | 272 | default: |
gke | 1:1e3318a30ddd | 273 | break; |
gke | 0:62a1c91a859a | 274 | } // switch |
gke | 0:62a1c91a859a | 275 | TxChar(' '); |
gke | 0:62a1c91a859a | 276 | |
gke | 0:62a1c91a859a | 277 | } // ShowI2CDeviceName |
gke | 0:62a1c91a859a | 278 | |
gke | 1:1e3318a30ddd | 279 | boolean I2C0AddressResponds(uint8 s) { |
gke | 1:1e3318a30ddd | 280 | static boolean r; |
gke | 1:1e3318a30ddd | 281 | I2C0.start(); |
gke | 1:1e3318a30ddd | 282 | r = I2C0.write(s) == I2C_ACK; |
gke | 1:1e3318a30ddd | 283 | I2C0.stop(); |
gke | 1:1e3318a30ddd | 284 | return (r); |
gke | 1:1e3318a30ddd | 285 | } // I2C0AddressResponds |
gke | 1:1e3318a30ddd | 286 | |
gke | 1:1e3318a30ddd | 287 | #ifdef HAVE_IC1 |
gke | 1:1e3318a30ddd | 288 | boolean I2C1AddressResponds(uint8 s) { |
gke | 1:1e3318a30ddd | 289 | static boolean r; |
gke | 1:1e3318a30ddd | 290 | I2C1.start(); |
gke | 1:1e3318a30ddd | 291 | r = I2C1.write(s) == I2C_ACK; |
gke | 1:1e3318a30ddd | 292 | I2C1.stop(); |
gke | 1:1e3318a30ddd | 293 | return (r); |
gke | 1:1e3318a30ddd | 294 | } // I2C1AddressResponds |
gke | 1:1e3318a30ddd | 295 | #endif // HAVE_IC1 |
gke | 1:1e3318a30ddd | 296 | |
gke | 0:62a1c91a859a | 297 | uint8 ScanI2CBus(void) { |
gke | 0:62a1c91a859a | 298 | uint8 s; |
gke | 0:62a1c91a859a | 299 | uint8 d; |
gke | 0:62a1c91a859a | 300 | |
gke | 0:62a1c91a859a | 301 | d = 0; |
gke | 0:62a1c91a859a | 302 | TxString("Buss 0\r\n"); |
gke | 2:90292f8bd179 | 303 | |
gke | 2:90292f8bd179 | 304 | #ifdef SW_I2C |
gke | 2:90292f8bd179 | 305 | TxString("I2C Ver.:\tSoftware\r\n"); |
gke | 2:90292f8bd179 | 306 | #else |
gke | 2:90292f8bd179 | 307 | TxString("I2C Ver.:\tHardware (CAUTION)\r\n"); |
gke | 2:90292f8bd179 | 308 | #endif // SW_I2C |
gke | 2:90292f8bd179 | 309 | |
gke | 2:90292f8bd179 | 310 | #if ( I2C_MAX_RATE_HZ == 400000 ) |
gke | 2:90292f8bd179 | 311 | TxString("Rate:\t400KHz\r\n"); |
gke | 2:90292f8bd179 | 312 | #else |
gke | 2:90292f8bd179 | 313 | TxString("Rate:\t100KHz\r\n"); |
gke | 2:90292f8bd179 | 314 | #endif |
gke | 2:90292f8bd179 | 315 | TxString("SCL Hangs:\t"); |
gke | 2:90292f8bd179 | 316 | TxVal32(I2CError[0], 0, 0); |
gke | 2:90292f8bd179 | 317 | TxNextLine(); |
gke | 0:62a1c91a859a | 318 | for ( s = 0x10 ; s <= 0xf6 ; s += 2 ) { |
gke | 1:1e3318a30ddd | 319 | if ( I2C0AddressResponds(s) ) { |
gke | 1:1e3318a30ddd | 320 | d++; |
gke | 1:1e3318a30ddd | 321 | TxString("\t0x"); |
gke | 1:1e3318a30ddd | 322 | TxValH(s); |
gke | 2:90292f8bd179 | 323 | TxChar(HT); |
gke | 2:90292f8bd179 | 324 | TxVal32(I2CError[s], 0, HT); |
gke | 1:1e3318a30ddd | 325 | ShowI2CDeviceName( s ); |
gke | 1:1e3318a30ddd | 326 | TxNextLine(); |
gke | 1:1e3318a30ddd | 327 | } |
gke | 1:1e3318a30ddd | 328 | Delay1mS(2); |
gke | 1:1e3318a30ddd | 329 | } |
gke | 1:1e3318a30ddd | 330 | |
gke | 1:1e3318a30ddd | 331 | #ifdef HAVE_I2C1 |
gke | 1:1e3318a30ddd | 332 | TxString("Buss 1\r\n"); |
gke | 2:90292f8bd179 | 333 | |
gke | 2:90292f8bd179 | 334 | #ifdef SW_I2C |
gke | 2:90292f8bd179 | 335 | TxString("I2C Ver.:\tSoftware\r\n"); |
gke | 2:90292f8bd179 | 336 | #else |
gke | 2:90292f8bd179 | 337 | TxString("I2C Ver.:\tHardware (CAUTION)\r\n"); |
gke | 2:90292f8bd179 | 338 | #endif // SW_I2C |
gke | 2:90292f8bd179 | 339 | |
gke | 2:90292f8bd179 | 340 | #if ( I2C_MAX_RATE_HZ == 400000 ) |
gke | 2:90292f8bd179 | 341 | TxString("Rate:\t400KHz\r\n"); |
gke | 2:90292f8bd179 | 342 | #else |
gke | 2:90292f8bd179 | 343 | TxString("Rate:\t100KHz\r\n"); |
gke | 2:90292f8bd179 | 344 | #endif |
gke | 2:90292f8bd179 | 345 | TxString("SCL Hangs:\t"); |
gke | 2:90292f8bd179 | 346 | TxNextLine(); |
gke | 1:1e3318a30ddd | 347 | for ( s = 0x10 ; s <= 0xf6 ; s += 2 ) { |
gke | 2:90292f8bd179 | 348 | if ( I2C0AddressResponds(s) ) { |
gke | 0:62a1c91a859a | 349 | d++; |
gke | 0:62a1c91a859a | 350 | TxString("\t0x"); |
gke | 0:62a1c91a859a | 351 | TxValH(s); |
gke | 2:90292f8bd179 | 352 | TxChar(HT); |
gke | 2:90292f8bd179 | 353 | TxVal32(I2CError[s], 0, HT); |
gke | 0:62a1c91a859a | 354 | ShowI2CDeviceName( s ); |
gke | 0:62a1c91a859a | 355 | TxNextLine(); |
gke | 0:62a1c91a859a | 356 | } |
gke | 0:62a1c91a859a | 357 | Delay1mS(2); |
gke | 0:62a1c91a859a | 358 | } |
gke | 1:1e3318a30ddd | 359 | #endif // HAVE_I2C1 |
gke | 0:62a1c91a859a | 360 | |
gke | 0:62a1c91a859a | 361 | PCA9551Test(); |
gke | 0:62a1c91a859a | 362 | |
gke | 0:62a1c91a859a | 363 | return(d); |
gke | 0:62a1c91a859a | 364 | } // ScanI2CBus |
gke | 0:62a1c91a859a | 365 | |
gke | 1:1e3318a30ddd | 366 | void ProgramSlaveAddress(uint8 a) { |
gke | 0:62a1c91a859a | 367 | static uint8 s; |
gke | 0:62a1c91a859a | 368 | |
gke | 0:62a1c91a859a | 369 | for (s = 0x10 ; s < 0xf0 ; s += 2 ) { |
gke | 0:62a1c91a859a | 370 | I2CESC.start(); |
gke | 0:62a1c91a859a | 371 | if ( I2CESC.read(s) == I2C_ACK ) |
gke | 1:1e3318a30ddd | 372 | if ( s == a ) { // ESC is already programmed OK |
gke | 0:62a1c91a859a | 373 | I2CESC.stop(); |
gke | 0:62a1c91a859a | 374 | TxString("\tESC at SLA 0x"); |
gke | 1:1e3318a30ddd | 375 | TxValH(a); |
gke | 0:62a1c91a859a | 376 | TxString(" is already programmed OK\r\n"); |
gke | 0:62a1c91a859a | 377 | return; |
gke | 0:62a1c91a859a | 378 | } else { |
gke | 0:62a1c91a859a | 379 | if ( I2CESC.read(0x87) == I2C_ACK ) // select register 0x07 |
gke | 1:1e3318a30ddd | 380 | if ( I2CESC.write( a ) == I2C_ACK ) { // new slave address |
gke | 0:62a1c91a859a | 381 | I2CESC.stop(); |
gke | 0:62a1c91a859a | 382 | TxString("\tESC at SLA 0x"); |
gke | 0:62a1c91a859a | 383 | TxValH(s); |
gke | 0:62a1c91a859a | 384 | TxString(" reprogrammed to SLA 0x"); |
gke | 1:1e3318a30ddd | 385 | TxValH(a); |
gke | 0:62a1c91a859a | 386 | TxNextLine(); |
gke | 0:62a1c91a859a | 387 | return; |
gke | 0:62a1c91a859a | 388 | } |
gke | 0:62a1c91a859a | 389 | } |
gke | 0:62a1c91a859a | 390 | I2CESC.stop(); |
gke | 0:62a1c91a859a | 391 | } |
gke | 0:62a1c91a859a | 392 | TxString("\tESC at SLA 0x"); |
gke | 1:1e3318a30ddd | 393 | TxValH(a); |
gke | 0:62a1c91a859a | 394 | TxString(" no response - check cabling and pullup resistors!\r\n"); |
gke | 0:62a1c91a859a | 395 | } // ProgramSlaveAddress |
gke | 0:62a1c91a859a | 396 | |
gke | 0:62a1c91a859a | 397 | boolean CheckESCBus(void) { |
gke | 0:62a1c91a859a | 398 | return ( true ); |
gke | 0:62a1c91a859a | 399 | } // CheckESCBus |
gke | 0:62a1c91a859a | 400 | |
gke | 0:62a1c91a859a | 401 | void ConfigureESCs(void) { |
gke | 0:62a1c91a859a | 402 | int8 m; |
gke | 0:62a1c91a859a | 403 | |
gke | 0:62a1c91a859a | 404 | if ( (int8)P[ESCType] == ESCYGEI2C ) { |
gke | 0:62a1c91a859a | 405 | TxString("\r\nProgram YGE ESCs\r\n"); |
gke | 0:62a1c91a859a | 406 | for ( m = 0 ; m < NoOfI2CESCOutputs ; m++ ) { |
gke | 1:1e3318a30ddd | 407 | TxString("Connect ONLY M"); |
gke | 1:1e3318a30ddd | 408 | TxChar('1' + m); |
gke | 0:62a1c91a859a | 409 | TxString(" ESC, then press any key \r\n"); |
gke | 0:62a1c91a859a | 410 | while ( PollRxChar() != 'x' ); // UAVPSet uses 'x' for any key button |
gke | 0:62a1c91a859a | 411 | // TxString("\r\n"); |
gke | 0:62a1c91a859a | 412 | ProgramSlaveAddress( 0x62 + ( m*2 )); |
gke | 0:62a1c91a859a | 413 | } |
gke | 0:62a1c91a859a | 414 | TxString("\r\nConnect ALL ESCs and power-cycle the Quadrocopter\r\n"); |
gke | 0:62a1c91a859a | 415 | } else |
gke | 0:62a1c91a859a | 416 | TxString("\r\nYGEI2C not selected as ESC?\r\n"); |
gke | 0:62a1c91a859a | 417 | } // ConfigureESCs |
gke | 0:62a1c91a859a | 418 | |
gke | 2:90292f8bd179 | 419 | void InitI2C(void) { |
gke | 2:90292f8bd179 | 420 | |
gke | 2:90292f8bd179 | 421 | uint8 i; |
gke | 2:90292f8bd179 | 422 | |
gke | 2:90292f8bd179 | 423 | for ( i = 0; i < 255; i++ ) |
gke | 2:90292f8bd179 | 424 | I2CError[i] = 0; |
gke | 2:90292f8bd179 | 425 | |
gke | 2:90292f8bd179 | 426 | } // InitI2C |
gke | 0:62a1c91a859a | 427 | |
gke | 0:62a1c91a859a | 428 | |
gke | 2:90292f8bd179 | 429 |