[Tinyos-2-commits] CVS: tinyos-2.x/tos/chips/atm128/i2c Atm128I2C.h, 1.1.2.3, 1.1.2.4 Atm128I2CMasterC.nc, 1.1.2.1, 1.1.2.2 Atm128I2CMasterP.nc, 1.1.2.1, 1.1.2.2 HplAtm128I2CBus.nc, 1.1.2.1, 1.1.2.2 HplAtm128I2CBusC.nc, 1.1.2.1, 1.1.2.2 HplAtm128I2CBusP.nc, 1.1.2.1, 1.1.2.2

Phil Levis scipio at users.sourceforge.net
Mon May 1 14:50:52 PDT 2006


Update of /cvsroot/tinyos/tinyos-2.x/tos/chips/atm128/i2c
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9424

Modified Files:
      Tag: tinyos-2_0_devel-BRANCH
	Atm128I2C.h Atm128I2CMasterC.nc Atm128I2CMasterP.nc 
	HplAtm128I2CBus.nc HplAtm128I2CBusC.nc HplAtm128I2CBusP.nc 
Log Message:
Rewrite of the I2C code. It's fully synchronous now. Future work includes
making it async in the same way as SPI.

The low-level I2C interface needs work; the way that the TWINT bit of
the TSCR works is problematic, in that you cannot write bits without
also twiddling TWINT.



Index: Atm128I2C.h
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/atm128/i2c/Attic/Atm128I2C.h,v
retrieving revision 1.1.2.3
retrieving revision 1.1.2.4
diff -C2 -d -r1.1.2.3 -r1.1.2.4
*** Atm128I2C.h	27 Jan 2006 23:13:22 -0000	1.1.2.3
--- Atm128I2C.h	1 May 2006 21:50:50 -0000	1.1.2.4
***************
*** 28,33 ****
  #define _H_Atm128I2C_h
  
! #define ATM128_I2C_SLA_W 0x00
! #define ATM128_I2C_SLA_R 0x01
  
  typedef uint8_t Atm128_TWBR_t;  //!< Two Wire Bit Rate Register
--- 28,33 ----
  #define _H_Atm128I2C_h
  
! #define ATM128_I2C_SLA_WRITE 0x00
! #define ATM128_I2C_SLA_READ 0x01
  
  typedef uint8_t Atm128_TWBR_t;  //!< Two Wire Bit Rate Register

Index: Atm128I2CMasterC.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/atm128/i2c/Attic/Atm128I2CMasterC.nc,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -C2 -d -r1.1.2.1 -r1.1.2.2
*** Atm128I2CMasterC.nc	27 Jan 2006 22:19:36 -0000	1.1.2.1
--- Atm128I2CMasterC.nc	1 May 2006 21:50:50 -0000	1.1.2.2
***************
*** 1,5 ****
  /// $Id$
  
! /**
   * Copyright (c) 2004-2005 Crossbow Technology, Inc.  All rights reserved.
   *
--- 1,5 ----
  /// $Id$
  
! /*
   * Copyright (c) 2004-2005 Crossbow Technology, Inc.  All rights reserved.
   *
***************
*** 23,36 ****
   */
  
! /// @author Martin Turon <mturon at xbow.com>
  
! generic configuration HalI2CMasterC (uint8_t device)
! {
!     provides interface HalI2CMaster as I2CDevice;
  }
  implementation {
!     components HplI2CBusC, new HalI2CMasterP(device);
! 
!     I2CDevice = HalI2CMasterP;
!     HalI2CMasterP.I2C -> HplI2CBusC;
  }
--- 23,43 ----
   */
  
! /**
!  * @author Martin Turon <mturon at xbow.com>
!  * @author Philip Levis
!  */
  
! configuration Atm128I2CMasterC {
!   provides interface AsyncStdControl;
!   provides interface I2CPacket;
  }
  implementation {
!   components HplAtm128I2CBusC, new Atm128I2CMasterP();
!   components NoLedsC, LedsC;
!   
!   AsyncStdControl = Atm128I2CMasterP;
!   I2CPacket = Atm128I2CMasterP;
!   Atm128I2CMasterP.I2C -> HplAtm128I2CBusC;
!   Atm128I2CMasterP.WriteLeds -> NoLedsC;
!   Atm128I2CMasterP.ReadLeds -> LedsC;
  }

Index: Atm128I2CMasterP.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/atm128/i2c/Attic/Atm128I2CMasterP.nc,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -C2 -d -r1.1.2.1 -r1.1.2.2
*** Atm128I2CMasterP.nc	27 Jan 2006 22:19:36 -0000	1.1.2.1
--- Atm128I2CMasterP.nc	1 May 2006 21:50:50 -0000	1.1.2.2
***************
*** 34,196 ****
   *
   * @author Martin Turon <mturon at xbow.com>
   *
!  * @version    2005/9/11    mturon     Initial version
   */
! generic module HalI2CMasterP (uint8_t device)
! {
!     provides {
! 	interface HalI2CMaster as I2CDevice;
!     }
!     uses {
! 	interface HplI2CBus as I2C;
!     }
  }
  implementation {
!     enum {
! 	I2C_READY,
! 	I2C_PING,
! 	I2C_READ,
! 	I2C_WRITE,
!     };
! 
!     uint8_t i2cMode;      //!< What type of transaction are we working on?
!     uint8_t i2cOffset;    //!< Offset address into device memmap to read/write
!      int8_t i2cLength;    //!< Length of data to read/write
! 
!     norace uint8_t *i2cData;     //!< Pointer to next data byte
! 
!     /**
!      * An efficient I2C engine for the ATmega128.  This task handles state 
!      * transitions triggered by the .symbolDone() interrupt of the hardware
!      * I2C subsystem.  The hardware stores actual subtransaction state in 
!      * the status register.  The type of user transaction (i2cMode) drives 
!      * this engine at a higher level.  
!      *
!      * @author   Martin Turon
!      *
!      * @version  2005/9/10    mturon      Initial version
!      */
!     void task i2cEngine() {
! 	uint8_t state = call I2C.status();
! 
! 	switch (i2cMode) {
! 	    case I2C_PING:
! 	    case I2C_READ:
! 		switch (state) {
! 		    case ATM128_I2C_START:
! 			call I2C.deviceRead(device);   // talk in read mode
! 			call I2C.send();
! 			break;
! 			
! 		    case ATM128_I2C_MR_SLA_ACK:
! 		    case ATM128_I2C_MR_DATA_ACK:
! 			if (i2cLength-- > 0) {
! 			    // if data left, read next byte
! 			    call I2C.send();
! 			} else {
! 			    // otherwise, complete with success
! 			    call I2C.end();
! 	    
! 			    if (i2cMode == I2C_PING) {	
! 				    signal I2CDevice.pingDone(SUCCESS);
! 			    } else {
! 				    
! 					signal I2CDevice.readDone();   
! 			    }
! 
! 			    i2cMode = I2C_READY;
! 			}
! 			break;
! 			
! 		    default:
! 			call I2C.end();
! 			i2cMode = I2C_READY;
! 			// signal error
! 		}
! 		break;
! 
! 	    case I2C_WRITE:
! 		switch (state) {
! 		    case ATM128_I2C_START:
! 			call I2C.deviceWrite(device);  // talk in write mode
! 			call I2C.send();
! 			break;
! 
! 		    case ATM128_I2C_MW_SLA_ACK:
! 		    case ATM128_I2C_MW_DATA_ACK:
! 			if (i2cLength-- > 0) {
! 			    // if data left, write next byte
! 			    call I2C.set(*i2cData);
! 			    call I2C.send();
! 			} else {
! 			    // otherwise, clean exit
! 			    call I2C.end();
! 			    i2cMode = I2C_READY;			    
! 			    signal I2CDevice.writeDone();
! 			}
! 			break;
  
! 		    default:
! 			call I2C.end();
! 			i2cMode = I2C_READY;
! 			// signal error
! 		}
! 		break;
! 	}
  
! 	if (i2cMode == I2C_READY) return;
  
! 	// start timeout timer
      }
  
!   /** Ping a I2C slave device to see if it exists. */
!   command error_t I2CDevice.ping() {
!       if (i2cMode != I2C_READY) 
! 	  return FAIL;
! 
!       i2cMode   = I2C_PING;
!       i2cData   = NULL;
!       i2cLength = 0;
!       call I2C.begin();
!       return SUCCESS;
    }
  
!   /** Write a byte sequence to an I2C slave device. */
!   command error_t I2CDevice.write(uint8_t *data, uint8_t length) {
!       if (i2cMode != I2C_READY) 
! 	  return FAIL;
  
!       i2cMode   = I2C_WRITE;
!       i2cData   = data;
!       i2cLength = length;
!       call I2C.begin();
!       return SUCCESS;
    }
  
!   /** Read a byte sequence from an I2C slave device. */
!   command error_t I2CDevice.read(uint8_t *data, uint8_t length) {
!       if (i2cMode != I2C_READY) 
! 	  return FAIL;
  
!       i2cMode   = I2C_READ;
!       i2cData   = data;
!       i2cLength = length;
!       call I2C.begin();
!       return SUCCESS;
    }
  
!   default event void I2CDevice.pingDone  (error_t result) {}
!   default event void I2CDevice.readDone  () {}
!   default event void I2CDevice.writeDone () {}
  
!   /** Intercept interrupt signal when pending symbol completes. */
!   async event void I2C.symbolSent() { 
!       if (call I2C.status() == ATM128_I2C_MW_DATA_ACK) {
! 	  // If reading, grab the next data byte.
! 	  if (i2cData != NULL) 
! 	      *i2cData++ = call I2C.get();
!       }
!       // Queue up handling for next symbol
!       post i2cEngine();
    }
  }
--- 34,280 ----
   *
   * @author Martin Turon <mturon at xbow.com>
+  * @author Philip Levis
   *
!  * @version $Id$
   */
! generic module Atm128I2CMasterP() {
!   provides interface AsyncStdControl;
!   provides interface I2CPacket;
!   
!   uses interface HplAtm128I2CBus as I2C;
!   uses interface Leds as ReadLeds;
!   uses interface Leds as WriteLeds;
  }
  implementation {
!   task void readDoneTask();
!   task void writeDoneTask();
  
!   enum {
!     I2C_OFF     = 0,
!     I2C_IDLE    = 1,
!     I2C_READING = 2,
!     I2C_WRITING = 3,
!     I2C_SPINOUT = 10000,
!   } atm128_i2c_state_t;
  
!   uint8_t state = I2C_OFF;
!   
!   uint8_t packetAddr;
!   uint8_t* packetPtr;
!   uint8_t packetLen;
  
!   async command error_t AsyncStdControl.start() {
!     atomic {
!       if (state == I2C_OFF) {
! 	call I2C.init(FALSE);
! 	call I2C.enable(TRUE);
! 	call I2C.enableAck(TRUE);
! 	state = I2C_IDLE;
! 	return SUCCESS;
!       }
!       else {
! 	return FAIL;
!       }
      }
+   }
  
!   async command error_t AsyncStdControl.stop() {
!     atomic {
!       if (state == I2C_IDLE) {
! 	call I2C.enable(FALSE);
! 	call I2C.enableInterrupt(FALSE);
! 	call I2C.clearInterruptPending();
! 	call I2C.off();
! 	state = I2C_OFF;
! 	return SUCCESS;
!       }
!       else {
! 	return FAIL;
!       }
!     }
    }
  
!   error_t i2c_abort() {
!     call I2C.enableInterrupt(FALSE);
!     call I2C.stop();
!     call I2C.clearInterruptPending();
!     return FAIL;
!   }
  
!   bool i2c_wait() {
!     uint16_t i;
!     for (i = 0; i < I2C_SPINOUT; i++) {
!       if (call I2C.isInterruptPending()) {
! 	return TRUE;
!       }
!     }
!     return FALSE;
!   }
!   
!   async command error_t I2CPacket.read(uint8_t addr, uint8_t* data, uint8_t len) {
!     uint8_t localLen;
!     bool waitSuccess;
!     atomic {
!       if (state == I2C_IDLE) {
! 	state = I2C_READING;
!       }
!       else if (state == I2C_OFF) {
! 	return EOFF;
!       }
!       else {
! 	return EBUSY;
!       }
!     }
!     /* This follows the procedure described on page 209 of the atmega128L
!      * data sheet. It is synchronous (does not handle interrupts).*/
!     atomic {
!       packetAddr = addr;
!       packetPtr = data;
!       packetLen = len;
!       localLen = len;
!     }
!     /* Clear interrupt pending, send the I2C start command and abort
!        if we're not in the start state.*/
!     call I2C.enableInterrupt(FALSE);
!     call I2C.start();
!     waitSuccess = i2c_wait();
!     if (!waitSuccess || call I2C.status() != ATM128_I2C_START) {
!       call ReadLeds.led1On();
!       return i2c_abort();
!     }
!     
!     /* Clear the start bit, write the address and abort if we're not in
!        the right state. */
!     call I2C.write(addr | ATM128_I2C_SLA_READ);
!     /* We don't need to clear the interrupt pending bit because
!        clearing the start bit will do so automatically (it reads TWINT
!        to be 1, then writes that back). */
!     call I2C.clearStart();
!     waitSuccess = i2c_wait();
!     if (!waitSuccess) {
!       call ReadLeds.led1On();
!       return i2c_abort();
!     }
!     else if (call I2C.status() != ATM128_I2C_MR_SLA_ACK) {
!       call ReadLeds.led2On();
!       return i2c_abort();
!     }
!     
!     /* Read in the data bytes. */
!     for (len = 0; len < localLen; len++) {
!       call I2C.clearInterruptPending();
!       data[len] = call I2C.read();
!       waitSuccess = i2c_wait();
!       if (!waitSuccess) {
! 	call ReadLeds.led2On();	
! 	return i2c_abort();
!       }
!       else if (call I2C.status() != ATM128_I2C_MR_DATA_ACK) {
! 	call ReadLeds.led2On();
! 	return i2c_abort();
!       }
!     }
!     /* Send a stop condition and clear TWINT to send it. */
!     call I2C.stop();
!     post readDoneTask();
!     return SUCCESS;
    }
  
!   async command error_t I2CPacket.write(uint8_t addr, uint8_t* data, uint8_t len) {
!     uint8_t localLen;
!     bool waitSuccess;
!     atomic {
!       if (state == I2C_IDLE) {
! 	state = I2C_READING;
!       }
!       else if (state == I2C_OFF) {
! 	return EOFF;
!       }
!       else {
! 	return EBUSY;
!       }
!     }
!     /* This follows the procedure described on page 209 of the atmega128L
!      * data sheet. It is synchronous (does not handle interrupts).*/
!     atomic {
!       packetAddr = addr;
!       packetPtr = data;
!       packetLen = len;
!       localLen = len;
!     }
!     /* Clear interrupt pending, send the I2C start command and abort
!        if we're not in the start state.*/
!     call I2C.enableInterrupt(FALSE);
!     call I2C.start();
!     waitSuccess = i2c_wait();
!     if (!waitSuccess || call I2C.status() != ATM128_I2C_START) {
!       call WriteLeds.led0On();
!       return i2c_abort();
!     }
!     
!     /* Clear the start bit, write the address and abort if we're not in
!        the right state. */
!     call I2C.write(addr | ATM128_I2C_SLA_WRITE);
!     /* We don't need to clear the interrupt pending bit because
!        clearing the start bit will do so automatically (it reads TWINT
!        to be 1, then writes that back). */
!     call I2C.clearStart();
!     waitSuccess = i2c_wait();
!     if (!waitSuccess || call I2C.status() != ATM128_I2C_MW_SLA_ACK) {
!       call WriteLeds.led1On();
!       return i2c_abort();
!     }
!     
!     /* Read in the data bytes. */
!     for (len = 0; len < localLen; len++) {
!       call I2C.write(data[len]);
!       call I2C.clearInterruptPending();
!       waitSuccess = i2c_wait();
!       if (!waitSuccess) {
! 	call WriteLeds.led1On();	
! 	return i2c_abort();
!       }
!       else if (call I2C.status() != ATM128_I2C_MW_DATA_ACK) {
! 	call WriteLeds.led2On();
! 	return i2c_abort();
!       }
!     }
  
!     /* Send a stop condition and clear TWINT to send it. */
!     call I2C.stop();
!     post writeDoneTask();
!     return SUCCESS;
    }
+   
+   task void readDoneTask() {
+     uint8_t addr;
+     uint8_t len;
+     uint8_t* ptr;
  
!     atomic {
!       addr = packetAddr;
!       len = packetLen;
!       ptr = packetPtr;
!       state = I2C_IDLE;
!     }
!     
!     signal I2CPacket.readDone(addr, ptr, len, SUCCESS);
!   }
!   
!   task void writeDoneTask() {
!     uint8_t addr;
!     uint8_t len;
!     uint8_t* ptr;
  
!     atomic {
!       addr = packetAddr;
!       len = packetLen;
!       ptr = packetPtr;
!       state = I2C_IDLE;
!     }
!     
!     signal I2CPacket.writeDone(addr, ptr, len, SUCCESS);
    }
+ 
+   async event void I2C.symbolSent() {}
  }

Index: HplAtm128I2CBus.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/atm128/i2c/Attic/HplAtm128I2CBus.nc,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -C2 -d -r1.1.2.1 -r1.1.2.2
*** HplAtm128I2CBus.nc	27 Jan 2006 22:19:36 -0000	1.1.2.1
--- HplAtm128I2CBus.nc	1 May 2006 21:50:50 -0000	1.1.2.2
***************
*** 34,76 ****
   *
   * @author Martin Turon <mturon at xbow.com>
   *
!  * @version    2005/9/11    mturon     Initial version
   */
! interface HplI2CBus {
! 
!     command void init();    //!< Initialize i2c clock speed
! 
!     // Transaction interface
!     command void begin();   //!< Start bus transaction (send start symbol)
!     command void end();     //!< End bus transaction
!     command void send();    //!< Send next byte of transaction
! 
!     // Data interface
!     command error_t ping (uint8_t dev);              //!< Ping device
!     command error_t write(uint8_t dev, uint8_t data);  //!< Write to device
!     command error_t read (uint8_t dev, uint8_t *data); //!< Read from device
! 
!     command error_t writeBuffer(uint8_t dev, uint8_t *data, int8_t len);
!     command error_t readBuffer (uint8_t dev, uint8_t *data, int8_t len);
! 
!     async command uint8_t get();               //!< Get data register
!     async command void    set(uint8_t data);   //!< Set data register
  
!     async command void deviceRead (uint8_t addr); //!< Set device to read
!     async command void deviceWrite(uint8_t addr); //!< Set device to write
  
!     async command Atm128I2CControl_t getControl();
!     async command Atm128I2CStatus_t  getStatus();
  
!     async command void setControl( Atm128I2CControl_t x );
!     async command void setStatus ( Atm128I2CStatus_t x );
!     
!     async command uint8_t status();
!     async command bool    isDone();
!     async command error_t waitDone();
  
! //    async command void enable(); 
! //    async command void disable();
  
-     async event void symbolSent();
  }
--- 34,73 ----
   *
   * @author Martin Turon <mturon at xbow.com>
+  * @author Philip Levis
   *
!  * @version  $Id$
   */
! interface HplAtm128I2CBus {
  
!   async command void init(bool hasExternalPulldown);
!   async command void off();
!   
!   async command uint8_t status();
!   
!   // Transaction interface
!   async command void start();   //!< Start bus transaction (send start symbol)
!   async command bool isStarting();
!   async command void clearStart();
!   
!   async command void stop();    //!< End bus transaction
!   async command bool isStopping();
  
!   // Data interface
!   async command void write(uint8_t data);
!   async command uint8_t read();
  
!   async command void enableAck(bool enable);
!   async command bool isAckEnabled();
!   async command void enableInterrupt(bool enable);
!   async command bool isInterruptEnabled();
!   async command bool isInterruptPending();
!   async command void clearInterruptPending();
!   
!   async event void symbolSent();
!   
!   async command void enable(bool enable);
!   async command bool isEnabled();
  
!   async command bool hasWriteCollided();
  
  }

Index: HplAtm128I2CBusC.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/atm128/i2c/Attic/HplAtm128I2CBusC.nc,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -C2 -d -r1.1.2.1 -r1.1.2.2
*** HplAtm128I2CBusC.nc	27 Jan 2006 22:19:36 -0000	1.1.2.1
--- HplAtm128I2CBusC.nc	1 May 2006 21:50:50 -0000	1.1.2.2
***************
*** 32,55 ****
   *
   * @author Martin Turon <mturon at xbow.com>
   *
!  * @version    2005/9/11    mturon     Initial version
   */
! configuration HplI2CBusC
! {
!     provides interface HplI2CBus as I2C;
  }
  implementation {
  
!     components LedsC
!     	, HplAtm128GeneralIOC
!     	, BusyWaitMicroC
!     	, HplI2CBusP
!     	;
    
!     I2C = HplI2CBusP.I2C;
!     
!     HplI2CBusP.Leds -> LedsC;
!     HplI2CBusP.uWait -> BusyWaitMicroC;
!     HplI2CBusP.I2CClk -> HplAtm128GeneralIOC.PortD0;
!     HplI2CBusP.I2CData -> HplAtm128GeneralIOC.PortD1;
  }
--- 32,49 ----
   *
   * @author Martin Turon <mturon at xbow.com>
+  * @author Philip Levis
   *
!  * @version    $Id$
   */
! 
! configuration HplAtm128I2CBusC {
!   provides interface HplAtm128I2CBus as I2C;
  }
  implementation {
  
!   components HplAtm128GeneralIOC as IO, HplAtm128I2CBusP as Bus;
    
!   I2C         = Bus.I2C;
!   Bus.I2CClk  -> IO.PortD0;
!   Bus.I2CData -> IO.PortD1;
  }

Index: HplAtm128I2CBusP.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/atm128/i2c/Attic/HplAtm128I2CBusP.nc,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -C2 -d -r1.1.2.1 -r1.1.2.2
*** HplAtm128I2CBusP.nc	27 Jan 2006 22:19:36 -0000	1.1.2.1
--- HplAtm128I2CBusP.nc	1 May 2006 21:50:50 -0000	1.1.2.2
***************
*** 37,269 ****
   *
   * @author Martin Turon <mturon at xbow.com>
   *
!  * @version    2005/9/11    mturon     Initial version
   */
! module HplI2CBusP
! {
!     provides interface HplI2CBus as I2C;
  
!     uses {
!         interface Leds;
! 	interface BusyWait<TMicro,uint16_t> as uWait;
! 	interface GeneralIO as I2CClk;
! 	interface GeneralIO as I2CData;
!     }
  }
  implementation {
  
!   command void I2C.init() {
!       // Set the internal pullup resisters
!       call I2CClk.makeOutput();
!       call I2CData.makeOutput();
        call I2CClk.set();
        call I2CData.set();
!       
!       TWSR = 0;                             // set prescaler == 0
!       TWBR = (F_CPU / 100000UL - 16) / 2;   // set I2C baud rate
!       // TWBR = 50;
    }
  
    /** Send START symbol and begin I2C bus transaction. */
!   command void I2C.begin() {
!       //TWCR = 1<<TWIE | 1<<TWEN | 1<<TWSTA | 1<<TWINT ;
!       Atm128I2CControl_t ctrl;
!       ctrl.bits = (Atm128I2CControl_s) { twen : 1, twint : 1, twsta : 1, twie : 1 };
!       call I2C.setControl(ctrl);      
    }
! 
!   /** Signal STOP and end I2C bus transaction. */
!   command void I2C.end() {
!       Atm128I2CControl_t ctrl;
!       ctrl.bits = (Atm128I2CControl_s) { twen : 1, twint : 1, twsto : 1, twie: 0 };
!       call I2C.setControl(ctrl);      
    }
! 
!   /** Send next byte of I2C bus transaction. */
!   command void I2C.send() {
!       Atm128I2CControl_t ctrl;
!       ctrl.bits = (Atm128I2CControl_s) { twen : 1, twint : 1, twie : 1 };
!       call I2C.setControl(ctrl);      
    }
! 
!   error_t i2c_quit() {
!       call I2C.end();
!       return FAIL;
    }
! 
!   /** Ping a I2C slave device to see if it exists. */
!   command error_t I2C.ping(uint8_t addr) {
! 
! //      call Leds.set(call I2C.isDone());
! 
! //      avr_i2c_enable();
! //      avr_i2c_start();
! //      avr_i2c_wait();
! 
!       call I2C.begin();
!       call I2C.waitDone();
! 
!       call Leds.set(call I2C.status()>>3 & 0x7); 
!       //(call I2C.getStatus()).bits.tws);
! 
!       // confirm start sent status
!       if (!(call I2C.status() == ATM128_I2C_START)) return i2c_quit();
! 
! 
!       call I2C.deviceRead(addr);
!       call I2C.send();
!       call I2C.waitDone();
!       // confirm slave ack status
!       if (!(call I2C.status() == ATM128_I2C_MR_SLA_ACK)) return i2c_quit();
!       
!       call I2C.end();
! 
!       return SUCCESS;
    }
! 
    /** Write a byte to an I2C slave device. */
!   command error_t I2C.write(uint8_t addr, uint8_t data) {
!       call I2C.begin();
!       call I2C.waitDone();
!       // confirm start sent status
!       if (!(call I2C.status() == ATM128_I2C_START)) return i2c_quit();
! 
!       call I2C.deviceWrite(addr);
!       call I2C.send();
!       call I2C.waitDone();
!       // confirm slave ack status
!       if (!(call I2C.status() == ATM128_I2C_MW_SLA_ACK)) return i2c_quit();
!       
!       call I2C.set(data);
!       call I2C.send();
!       call I2C.waitDone();
!       // confirm data ack status
!       if (!(call I2C.status() == ATM128_I2C_MW_DATA_ACK)) return i2c_quit();
! 
!       call I2C.end();
! 
!       return SUCCESS;
    }
  
!   /** Read a byte from an I2C slave device. */
!   command error_t I2C.read(uint8_t addr, uint8_t *data) {
!       call I2C.begin();
!       call I2C.waitDone();
!       // confirm start sent status
!       if (!(call I2C.status() == ATM128_I2C_START)) return i2c_quit();
! 
!       call I2C.deviceRead(addr);
!       call I2C.send();
!       call I2C.waitDone();
!       // confirm slave ack status
!       if (!(call I2C.status() == ATM128_I2C_MR_SLA_ACK)) return i2c_quit();
!       
!       call I2C.send();
!       call I2C.waitDone();
!       *data = call I2C.get();
!       // confirm data ack status
!       if (!(call I2C.status() == ATM128_I2C_MR_DATA_ACK)) return i2c_quit();
! 
!       call I2C.end();
! 
!       return SUCCESS;
    }
  
!   /** Write one data byte to a given offset on a I2C slave device. */
!   command error_t I2C.writeBuffer(uint8_t device, uint8_t *data, int8_t len) {
!       call I2C.begin();
!       call I2C.waitDone();
!       // confirm start sent status
!       if (!(call I2C.status() == ATM128_I2C_START)) return i2c_quit();
! 
!       call I2C.deviceWrite(device);
!       call I2C.send();
!       call I2C.waitDone();
!       // confirm slave ack status
!       if (!(call I2C.status() == ATM128_I2C_MW_SLA_ACK)) return i2c_quit();
!       
!       while (len-- > 0) {
! 	  call I2C.set(*data++);
! 	  call I2C.send();
! 	  call I2C.waitDone();
! 	  // confirm data ack status
! 	  if (!(call I2C.status() == ATM128_I2C_MW_DATA_ACK)) return i2c_quit();
!       }
! 
!       call I2C.end();
! 
!       return SUCCESS;
    }
! 
!   /** Read one data byte to a given offset on a I2C slave device. */
!   command error_t I2C.readBuffer(uint8_t device, uint8_t *data, int8_t len) {
!       call I2C.begin();
!       call I2C.waitDone();
!       // confirm start sent status
!       if (!(call I2C.status() == ATM128_I2C_START)) return i2c_quit();
! 
!       call I2C.deviceRead(device);
!       call I2C.send();
!       call I2C.waitDone();
!       // confirm slave ack status
!       if (!(call I2C.status() == ATM128_I2C_MR_SLA_ACK)) return i2c_quit();
!             
!       while (len-- > 0) {
! 	  call I2C.send();
! 	  call I2C.waitDone();
! 	  *data++ = call I2C.get();
! 	  // confirm data ack status
! 	  if (!(call I2C.status() == ATM128_I2C_MR_DATA_ACK)) return i2c_quit();
!       }
! 
!       call I2C.end();
! 
!       return SUCCESS;
    }
  
!   //=== Read the data registers. ========================================
!   async command uint8_t I2C.get()    { return TWDR; }
! 
!   //=== Write the data registers. =======================================
!   async command void I2C.set(uint8_t data)  { TWDR = data; }
! 
!   async command void I2C.deviceRead  (uint8_t addr)  { TWDR = addr | 0x01; }
!   async command void I2C.deviceWrite (uint8_t addr)  { TWDR = addr; }
! 
!   //=== Read the control registers. =====================================
!   async command Atm128I2CControl_t I2C.getControl() { 
!     return *(Atm128I2CControl_t*)&TWCR; 
    }
!   async command Atm128I2CStatus_t I2C.getStatus() { 
!     return *(Atm128I2CStatus_t*)&TWSR; 
    }
! 
!   //=== Write the control registers. ====================================
!   async command void I2C.setControl( Atm128I2CControl_t x ) {TWCR = x.flat;}
!   async command void I2C.setStatus ( Atm128I2CStatus_t x )  {TWSR = x.flat;}
! 
!   async command uint8_t I2C.status() { return TWSR & 0xF8; }
! 
!   //=== Utility routines ===============================================
! 
!   async command bool I2C.isDone() { 
!     return (call I2C.getControl()).bits.twint; 
    }
  
!   async command error_t I2C.waitDone() { 
!       int i = 0;
!       while (!call I2C.isDone()) {
! 	  call uWait.wait(100);
! 	  if (i++ > I2C_TIMEOUT) return FAIL; // timeout
!       }
!       return SUCCESS;
    }
  
! //  async command void I2C.enable()  { SET_BIT(TWCR,TWE);   }
! //  async command void I2C.disable() { CLR_BIT(TWCR,TWE);   }
  
    default async event void I2C.symbolSent() { }
    AVR_NONATOMIC_HANDLER(SIG_2WIRE_SERIAL) {
!       atomic signal I2C.symbolSent();
    }
  }
--- 37,166 ----
   *
   * @author Martin Turon <mturon at xbow.com>
+  * @author Philip Levis
   *
!  * @version $Id$
   */
! module HplAtm128I2CBusP {
!   provides interface HplAtm128I2CBus as I2C;
  
!   uses {
!     interface GeneralIO as I2CClk;
!     interface GeneralIO as I2CData;
!   }
  }
  implementation {
  
!   async command void I2C.init(bool hasExternalPulldown) {
!     // Set the internal pullup resisters
!     if (hasExternalPulldown) {
!       //call I2CClk.makeOutput();
!       //call I2CData.makeOutput();
        call I2CClk.set();
        call I2CData.set();
!     }
!     call I2CClk.makeInput();
!     call I2CData.makeInput();
!     TWSR = 0;                             // set prescaler == 0
!     TWBR = (F_CPU / 50000UL - 16) / 2;   // set I2C baud rate
!     //TWBR = 50;
!     TWAR = 0;
!     TWCR = 0;
    }
  
+   async command void I2C.off() {
+     call I2CClk.clr();
+     call I2CData.clr();
+   }
+   
+   async command uint8_t I2C.status() {
+     return TWSR & 0xf8;
+   }
+   
    /** Send START symbol and begin I2C bus transaction. */
!   async command void I2C.start() {
!     SET_BIT(TWCR, TWSTA);
    }
!   async command bool I2C.isStarting() {
!     return READ_BIT(TWCR, TWSTA);
    }
!   async command void I2C.clearStart() {
!     CLR_BIT(TWCR, TWSTA);
    }
!   
!   /** Signal STOP and end I2C bus transaction. */
!   async command void I2C.stop() {
!     uint8_t tmp = TWCR;
!     tmp |= (1 << TWSTO);
!     tmp &= ~(1 << TWEA);
!     TWCR = tmp;
!     //SET_BIT(TWCR, TWSTO);
    }
!   async command bool I2C.isStopping() {
!     return READ_BIT(TWCR, TWSTO);
    }
!   
    /** Write a byte to an I2C slave device. */
!   async command void I2C.write(uint8_t data) {
!     TWDR = data;
    }
  
!   async command uint8_t I2C.read() {
!     return TWDR;
    }
  
!   async command void I2C.enableAck(bool enable) {
!     if (enable) {
!       SET_BIT(TWCR, TWEA);
!     }
!     else {
!       CLR_BIT(TWCR, TWEA);
!     }
    }
!   
!   async command bool I2C.isAckEnabled() {
!     return READ_BIT(TWCR, TWEA);
!   }
!   
!   async command void I2C.enableInterrupt(bool enable) {
!     if (enable) {
!       SET_BIT(TWCR, TWIE);
!     }
!     else {
!       CLR_BIT(TWCR, TWIE);
!     }
    }
  
!   async command bool I2C.isInterruptEnabled() {
!     return READ_BIT(TWCR, TWIE);
    }
!   
!   async command bool I2C.isInterruptPending() {
!     return READ_BIT(TWCR, TWINT);
    }
!   
!   async command void I2C.clearInterruptPending() {
!     SET_BIT(TWCR, TWINT);
!   }
!   
!   async command void I2C.enable(bool enable) {
!     if (enable) {
!       SET_BIT(TWCR, TWEN);
!     }
!     else {
!       CLR_BIT(TWCR, TWEN);
!     }
    }
  
!   async command bool I2C.isEnabled() {
!     return READ_BIT(TWCR, TWEN);
    }
  
!   async command bool I2C.hasWriteCollided() {
!     return READ_BIT(TWCR, TWWC);
!   }
  
    default async event void I2C.symbolSent() { }
    AVR_NONATOMIC_HANDLER(SIG_2WIRE_SERIAL) {
!     signal I2C.symbolSent();
    }
  }



More information about the Tinyos-2-commits mailing list