00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00079 #include <cfg/os.h>
00080 #include <cfg/twi.h>
00081 #include <cfg/arch/gpio.h>
00082
00083 #include <dev/twif.h>
00084
00085 #if defined(__arm__)
00086
00087 #include <arch/arm.h>
00088
00094 #if !defined(TWI_PIO_ID)
00095 #if defined(MCU_AT91SAM7X256)
00096 #define TWI_PIO_ID PIOA_ID
00097 #elif defined(MCU_AT91SAM9260)
00098 #define TWI_PIO_ID PIOB_ID
00099 #else
00100 #define TWI_PIO_ID PIO_ID
00101 #endif
00102 #endif
00103
00109 #ifndef TWI_SDA_BIT
00110 #if defined(MCU_AT91SAM9260)
00111 #define TWI_SDA_BIT 12
00112 #else
00113 #define TWI_SDA_BIT 10
00114 #endif
00115 #endif
00116
00120 #ifndef TWI_DELAY
00121 #if defined(MCU_AT91SAM9260)
00122 #define TWI_DELAY 16
00123 #else
00124 #define TWI_DELAY 8
00125 #endif
00126 #endif
00127
00133 #ifndef TWI_SCL_BIT
00134 #if defined(MCU_AT91SAM9260)
00135 #define TWI_SCL_BIT 13
00136 #else
00137 #define TWI_SCL_BIT 11
00138 #endif
00139 #endif
00140
00146 #if TWI_PIO_ID == PIOA_ID
00147
00148 #ifndef TWI_SDA_PE_REG
00149 #define TWI_SDA_PE_REG PIOA_PER
00150 #endif
00151 #ifndef TWI_SDA_OE_REG
00152 #define TWI_SDA_OE_REG PIOA_OER
00153 #endif
00154 #ifndef TWI_SDA_OD_REG
00155 #define TWI_SDA_OD_REG PIOA_ODR
00156 #endif
00157 #ifndef TWI_SDA_COD_REG
00158 #define TWI_SDA_COD_REG PIOA_CODR
00159 #endif
00160 #ifndef TWI_SDA_SOD_REG
00161 #define TWI_SDA_SOD_REG PIOA_SODR
00162 #endif
00163 #ifndef TWI_SDA_PDS_REG
00164 #define TWI_SDA_PDS_REG PIOA_PDSR
00165 #endif
00166
00167 #ifndef TWI_SCL_PE_REG
00168 #define TWI_SCL_PE_REG PIOA_PER
00169 #endif
00170 #ifndef TWI_SCL_OE_REG
00171 #define TWI_SCL_OE_REG PIOA_OER
00172 #endif
00173 #ifndef TWI_SCL_OD_REG
00174 #define TWI_SCL_OD_REG PIOA_ODR
00175 #endif
00176 #ifndef TWI_SCL_COD_REG
00177 #define TWI_SCL_COD_REG PIOA_CODR
00178 #endif
00179 #ifndef TWI_SCL_SOD_REG
00180 #define TWI_SCL_SOD_REG PIOA_SODR
00181 #endif
00182 #ifndef TWI_SCL_PDS_REG
00183 #define TWI_SCL_PDS_REG PIOA_PDSR
00184 #endif
00185
00186 #elif TWI_PIO_ID == PIOB_ID
00187
00188 #ifndef TWI_SDA_PE_REG
00189 #define TWI_SDA_PE_REG PIOB_PER
00190 #endif
00191 #ifndef TWI_SDA_OE_REG
00192 #define TWI_SDA_OE_REG PIOB_OER
00193 #endif
00194 #ifndef TWI_SDA_OD_REG
00195 #define TWI_SDA_OD_REG PIOB_ODR
00196 #endif
00197 #ifndef TWI_SDA_COD_REG
00198 #define TWI_SDA_COD_REG PIOB_CODR
00199 #endif
00200 #ifndef TWI_SDA_SOD_REG
00201 #define TWI_SDA_SOD_REG PIOB_SODR
00202 #endif
00203 #ifndef TWI_SDA_PDS_REG
00204 #define TWI_SDA_PDS_REG PIOB_PDSR
00205 #endif
00206
00207 #ifndef TWI_SCL_PE_REG
00208 #define TWI_SCL_PE_REG PIOB_PER
00209 #endif
00210 #ifndef TWI_SCL_OE_REG
00211 #define TWI_SCL_OE_REG PIOB_OER
00212 #endif
00213 #ifndef TWI_SCL_OD_REG
00214 #define TWI_SCL_OD_REG PIOB_ODR
00215 #endif
00216 #ifndef TWI_SCL_COD_REG
00217 #define TWI_SCL_COD_REG PIOB_CODR
00218 #endif
00219 #ifndef TWI_SCL_SOD_REG
00220 #define TWI_SCL_SOD_REG PIOB_SODR
00221 #endif
00222 #ifndef TWI_SCL_PDS_REG
00223 #define TWI_SCL_PDS_REG PIOB_PDSR
00224 #endif
00225
00226 #elif TWI_PIO_ID == PIOC_ID
00227
00228 #ifndef TWI_SDA_PE_REG
00229 #define TWI_SDA_PE_REG PIOC_PER
00230 #endif
00231 #ifndef TWI_SDA_OE_REG
00232 #define TWI_SDA_OE_REG PIOC_OER
00233 #endif
00234 #ifndef TWI_SDA_OD_REG
00235 #define TWI_SDA_OD_REG PIOC_ODR
00236 #endif
00237 #ifndef TWI_SDA_COD_REG
00238 #define TWI_SDA_COD_REG PIOC_CODR
00239 #endif
00240 #ifndef TWI_SDA_SOD_REG
00241 #define TWI_SDA_SOD_REG PIOC_SODR
00242 #endif
00243 #ifndef TWI_SDA_PDS_REG
00244 #define TWI_SDA_PDS_REG PIOC_PDSR
00245 #endif
00246
00247 #ifndef TWI_SCL_PE_REG
00248 #define TWI_SCL_PE_REG PIOC_PER
00249 #endif
00250 #ifndef TWI_SCL_OE_REG
00251 #define TWI_SCL_OE_REG PIOC_OER
00252 #endif
00253 #ifndef TWI_SCL_OD_REG
00254 #define TWI_SCL_OD_REG PIOC_ODR
00255 #endif
00256 #ifndef TWI_SCL_COD_REG
00257 #define TWI_SCL_COD_REG PIOC_CODR
00258 #endif
00259 #ifndef TWI_SCL_SOD_REG
00260 #define TWI_SCL_SOD_REG PIOC_SODR
00261 #endif
00262 #ifndef TWI_SCL_PDS_REG
00263 #define TWI_SCL_PDS_REG PIOC_PDSR
00264 #endif
00265
00266 #else
00267
00268 #ifndef TWI_SDA_PE_REG
00269 #define TWI_SDA_PE_REG PIO_PER
00270 #endif
00271 #ifndef TWI_SDA_OE_REG
00272 #define TWI_SDA_OE_REG PIO_OER
00273 #endif
00274 #ifndef TWI_SDA_OD_REG
00275 #define TWI_SDA_OD_REG PIO_ODR
00276 #endif
00277 #ifndef TWI_SDA_COD_REG
00278 #define TWI_SDA_COD_REG PIO_CODR
00279 #endif
00280 #ifndef TWI_SDA_SOD_REG
00281 #define TWI_SDA_SOD_REG PIO_SODR
00282 #endif
00283 #ifndef TWI_SDA_PDS_REG
00284 #define TWI_SDA_PDS_REG PIO_PDSR
00285 #endif
00286
00287 #ifndef TWI_SCL_PE_REG
00288 #define TWI_SCL_PE_REG PIO_PER
00289 #endif
00290 #ifndef TWI_SCL_OE_REG
00291 #define TWI_SCL_OE_REG PIO_OER
00292 #endif
00293 #ifndef TWI_SCL_OD_REG
00294 #define TWI_SCL_OD_REG PIO_ODR
00295 #endif
00296 #ifndef TWI_SCL_COD_REG
00297 #define TWI_SCL_COD_REG PIO_CODR
00298 #endif
00299 #ifndef TWI_SCL_SOD_REG
00300 #define TWI_SCL_SOD_REG PIO_SODR
00301 #endif
00302 #ifndef TWI_SCL_PDS_REG
00303 #define TWI_SCL_PDS_REG PIO_PDSR
00304 #endif
00305
00306 #endif
00307
00308 #define TWI_ENABLE() { \
00309 outr(TWI_SDA_COD_REG, _BV(TWI_SDA_BIT)); \
00310 outr(TWI_SCL_COD_REG, _BV(TWI_SCL_BIT)); \
00311 outr(TWI_SDA_PE_REG, _BV(TWI_SDA_BIT)); \
00312 outr(TWI_SCL_PE_REG, _BV(TWI_SCL_BIT)); \
00313 }
00314
00315 #define SDA_LOW() { \
00316 outr(TWI_SDA_COD_REG, _BV(TWI_SDA_BIT)); \
00317 outr(TWI_SDA_OE_REG, _BV(TWI_SDA_BIT)); \
00318 }
00319
00320 #define SDA_HIGH() { \
00321 outr(TWI_SDA_SOD_REG, _BV(TWI_SDA_BIT)); \
00322 outr(TWI_SDA_OD_REG, _BV(TWI_SDA_BIT)); \
00323 }
00324
00325 #define SDA_STAT() (inr(TWI_SDA_PDS_REG) & _BV(TWI_SDA_BIT))
00326
00327 #define SCL_LOW() { \
00328 outr(TWI_SCL_COD_REG, _BV(TWI_SCL_BIT)); \
00329 outr(TWI_SCL_OE_REG, _BV(TWI_SCL_BIT)); \
00330 }
00331
00332 #define SCL_HIGH() { \
00333 outr(TWI_SCL_SOD_REG, _BV(TWI_SCL_BIT)); \
00334 outr(TWI_SCL_OD_REG, _BV(TWI_SCL_BIT)); \
00335 }
00336
00337 #elif defined(__AVR__)
00338
00339
00340
00341
00342 #include <cfg/arch/avr.h>
00343
00344 #ifndef TWI_SDA_BIT
00345 #define TWI_SDA_BIT 0
00346 #endif
00347
00348 #if (TWI_SDA_AVRPORT == AVRPORTD)
00349 #define TWI_SDA_PORT PORTD
00350 #define TWI_SDA_PIN PIND
00351 #define TWI_SDA_DDR DDRD
00352 #elif (TWI_SDA_AVRPORT == AVRPORTE)
00353 #define TWI_SDA_PORT PORTE
00354 #define TWI_SDA_PIN PINE
00355 #define TWI_SDA_DDR DDRE
00356 #elif (TWI_SDA_AVRPORT == AVRPORTF)
00357 #define TWI_SDA_PORT PORTF
00358 #define TWI_SDA_PIN PINF
00359 #define TWI_SDA_DDR DDRF
00360 #else
00361 #define TWI_SDA_PORT PORTB
00362 #define TWI_SDA_PIN PINB
00363 #define TWI_SDA_DDR DDRB
00364 #endif
00365
00366 #ifndef TWI_SCL_BIT
00367 #define TWI_SCL_BIT 1
00368 #endif
00369
00370 #if (TWI_SCL_AVRPORT == AVRPORTD)
00371 #define TWI_SCL_PORT PORTD
00372 #define TWI_SCL_DDR DDRD
00373 #elif (TWI_SCL_AVRPORT == AVRPORTE)
00374 #define TWI_SCL_PORT PORTE
00375 #define TWI_SCL_DDR DDRE
00376 #elif (TWI_SCL_AVRPORT == AVRPORTF)
00377 #define TWI_SCL_PORT PORTF
00378 #define TWI_SCL_DDR DDRF
00379 #else
00380 #define TWI_SCL_PORT PORTB
00381 #define TWI_SCL_DDR DDRB
00382 #endif
00383
00384 #define TWI_ENABLE() { \
00385 cbi(TWI_SDA_PORT, TWI_SDA_BIT); \
00386 cbi(TWI_SCL_PORT, TWI_SCL_BIT); \
00387 }
00388
00389 #define SDA_LOW() sbi(TWI_SDA_DDR, TWI_SDA_BIT)
00390 #define SDA_HIGH() cbi(TWI_SDA_DDR, TWI_SDA_BIT)
00391 #define SDA_STAT() bit_is_set(TWI_SDA_PIN, TWI_SDA_BIT)
00392
00393 #define SCL_LOW() sbi(TWI_SCL_DDR, TWI_SCL_BIT)
00394 #define SCL_HIGH() cbi(TWI_SCL_DDR, TWI_SCL_BIT)
00395
00396 #ifndef TWI_DELAY
00397 #define TWI_DELAY 8
00398 #endif
00399
00400 #endif
00401
00402
00403 static u_char tw_mm_error;
00404 static int twibb_initialized;
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 static void TwDelay(int nops)
00415 {
00416 while (nops--) {
00417 _NOP();
00418 }
00419 }
00420
00421
00422
00423
00424
00425
00426
00427
00428 static void TwStart(void)
00429 {
00430 SDA_HIGH();
00431 TwDelay(TWI_DELAY);
00432 SCL_HIGH();
00433 TwDelay(TWI_DELAY);
00434 SDA_LOW();
00435 TwDelay(TWI_DELAY);
00436 SCL_LOW();
00437 TwDelay(TWI_DELAY);
00438 }
00439
00440
00441
00442
00443
00444
00445
00446
00447 static void TwStop(void)
00448 {
00449 SDA_LOW();
00450 TwDelay(TWI_DELAY);
00451 SCL_HIGH();
00452 TwDelay(2 * TWI_DELAY);
00453 SDA_HIGH();
00454 TwDelay(8 * TWI_DELAY);
00455 }
00456
00457
00458
00459
00460
00461
00462
00463 static int TwPut(u_char octet)
00464 {
00465 int i;
00466
00467 for (i = 0x80; i; i >>= 1) {
00468
00469 if (octet & i) {
00470 SDA_HIGH();
00471 } else {
00472 SDA_LOW();
00473 }
00474
00475 TwDelay(TWI_DELAY);
00476
00477 SCL_HIGH();
00478 TwDelay(2 * TWI_DELAY);
00479 SCL_LOW();
00480 TwDelay(TWI_DELAY);
00481 }
00482
00483
00484 SDA_HIGH();
00485
00486
00487 SCL_HIGH();
00488 TwDelay(2 * TWI_DELAY);
00489 if (SDA_STAT()) {
00490 i = -1;
00491 } else {
00492 i = 0;
00493 }
00494 SCL_LOW();
00495
00496 return i;
00497 }
00498
00499
00500
00501
00502
00503
00504
00505 static u_char TwGet(void)
00506 {
00507 u_char rc = 0;
00508 int i;
00509
00510
00511 SDA_HIGH();
00512 TwDelay(TWI_DELAY);
00513 for (i = 0x80; i; i >>= 1) {
00514 TwDelay(TWI_DELAY);
00515
00516 SCL_HIGH();
00517 TwDelay(2 * TWI_DELAY);
00518
00519 if (SDA_STAT()) {
00520 rc |= i;
00521 }
00522 SCL_LOW();
00523 }
00524 return rc;
00525 }
00526
00527
00528
00529
00530
00531
00532
00533 static void TwAck(void)
00534 {
00535 SDA_LOW();
00536 TwDelay(TWI_DELAY);
00537 SCL_HIGH();
00538 TwDelay(2 * TWI_DELAY);
00539 SCL_LOW();
00540 TwDelay(TWI_DELAY);
00541 SDA_HIGH();
00542 }
00543
00571 int TwMasterTransact(u_char sla, CONST void *txdata, u_short txlen, void *rxdata, u_short rxsiz, u_long tmo)
00572 {
00573 int rc = 0;
00574 u_char *cp;
00575
00576 if (!twibb_initialized) {
00577 TwInit(0);
00578 }
00579
00580 if (txlen) {
00581 TwStart();
00582
00583 if ((rc = TwPut(sla << 1)) == 0) {
00584 for (cp = (u_char *)txdata; txlen--; cp++) {
00585 if ((rc = TwPut(*cp)) != 0) {
00586 break;
00587 }
00588 }
00589 }
00590 }
00591 if (rc == 0 && rxsiz) {
00592 TwStart();
00593
00594 if ((rc = TwPut((sla << 1) | 1)) == 0) {
00595 for (cp = rxdata;; cp++) {
00596 *cp = TwGet();
00597 if (++rc >= rxsiz) {
00598 break;
00599 }
00600 TwAck();
00601 }
00602 }
00603 }
00604 TwStop();
00605
00606 if (rc == -1) {
00607 tw_mm_error = TWERR_SLA_NACK;
00608 }
00609 return rc;
00610 }
00611
00620 int TwMasterError(void)
00621 {
00622 int rc = (int) tw_mm_error;
00623 tw_mm_error = 0;
00624
00625 return rc;
00626 }
00627
00651 int TwSlaveListen(u_char * sla, void *rxdata, u_short rxsiz, u_long tmo)
00652 {
00653 return -1;
00654 }
00655
00674 int TwSlaveRespond(void *txdata, u_short txlen, u_long tmo)
00675 {
00676 return -1;
00677 }
00678
00690 int TwSlaveError(void)
00691 {
00692 return TWERR_BUS;
00693 }
00694
00707 int TwIOCtl(int req, void *conf)
00708 {
00709 return 0;
00710 }
00711
00727 int TwInit(u_char sla)
00728 {
00729 SDA_HIGH();
00730 SCL_HIGH();
00731 TWI_ENABLE();
00732 twibb_initialized = 1;
00733
00734 return 0;
00735 }