]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
Fixed a bug in the Software I2C. The first time a start condition was sent the clock...
authorr-studio <r-studio>
Thu, 22 Apr 2010 13:12:00 +0000 (13:12 +0000)
committerr-studio <r-studio>
Thu, 22 Apr 2010 13:12:00 +0000 (13:12 +0000)
Also added a low-power pin configuration.

tos/platforms/mulle/chips/ds2782/DS2782InternalC.nc
tos/platforms/mulle/chips/ds2782/DS2782InternalP.nc
tos/platforms/mulle/hardware.h
tos/platforms/mulle/pin_configuration.h [new file with mode: 0644]
tos/platforms/mulle/softwarei2c/SoftwareI2CPacketC.nc

index 0041b06f33038eaf52c9e9ab771e4b2736cf0a91..6c3063c0846d4f56e9cd908de64555b160934a9d 100644 (file)
@@ -57,7 +57,6 @@ implementation
   HplDS2782 = Logic;
   StdControl = Logic;
 
-  DS2782InternalP.SDA -> IOs.PortP70;
-  DS2782InternalP.SCL -> IOs.PortP71;
+  DS2782InternalP.Pullup -> IOs.PortP75;
   DS2782InternalP.ResourceDefaultOwner -> I2C;
 }
index 5d2b7cbc7c1f21ccb59042473525d0abfb98ee1e..6db69919ce51a4cd6f9eaf69c7a16264587965b7 100644 (file)
 module DS2782InternalP
 {
   uses interface ResourceDefaultOwner;
-  uses interface GeneralIO as SDA;
-  uses interface GeneralIO as SCL;
+  uses interface GeneralIO as Pullup;
 }
 implementation
 {
   async event void ResourceDefaultOwner.granted()
   {
-    call SDA.clr();
-    call SDA.makeOutput();
-    call SCL.clr();
-    call SCL.makeOutput();
+    call Pullup.clr();
   }
 
   async event void ResourceDefaultOwner.requested()
   {
+    call Pullup.set(); 
     call ResourceDefaultOwner.release();
   }
 
   async event void ResourceDefaultOwner.immediateRequested()
   {
+    call Pullup.set();
     call ResourceDefaultOwner.release();
   }
 }
index e2c63166aa6bd8cdc8dc08f877521a63b8afc68a..5da8a5868e6a3584e6c02ab10d2a43d76172fedc 100755 (executable)
 You should not remove this fix unless you are totaly sure of what you are doing!
 #endif
 
+#ifdef ENABLE_STOP_MODE
+#include "pin_configuration.h"
+#endif
+
 #include "m16c62phardware.h" // Header file for the MCU
 
 #endif  // __HARDWARE_H__
diff --git a/tos/platforms/mulle/pin_configuration.h b/tos/platforms/mulle/pin_configuration.h
new file mode 100644 (file)
index 0000000..8bae1b6
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2009 Communication Group and Eislab at
+ * Lulea University of Technology
+ *
+ * Contact: Laurynas Riliskis, LTU
+ * Mail: laurynas.riliskis@ltu.se
+ * All rights reserved.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the
+ *   distribution.
+ * - Neither the name of Communication Group at Lulea University of Technology
+ *   nor the names of its contributors may be used to endorse or promote
+ *    products derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL STANFORD
+ * UNIVERSITY OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Inactive pin states on Mulle.
+ *
+ * @author Henrik Makitaavola <henrik.makitaavola@gmail.com>
+ */
+
+#ifndef __PIN_CONFIGURATION_H__
+#define __PIN_CONFIGURATION_H__
+
+//P00/D0/AN10
+//P01/D1/AN11
+//P02/D2/AN12
+//P03/D3/AN13
+//P04/D4/AN14
+//P05/D5/AN15
+//P06/D6/AN16
+//P07/D7/AN17 - Radio.SLP_TR
+#define PORT_P0_INACTIVE_STATE M16C_PORT_INACTIVE_STATE(M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW)
+
+//P10/D8       RADIO.MISO (INPUT)
+//P11/D9       RADIO.MOSI
+//P12/D10      Accel.SLEEP_MODE
+//P13/D11
+//P14/D12
+//P15/D13/INT3
+//P16/D14/INT4
+//P17/D15/INT5
+#define PORT_P1_INACTIVE_STATE M16C_PORT_INACTIVE_STATE(M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW)
+
+#define PORT_P2_INACTIVE_STATE M16C_PORT_INACTIVE_STATE(M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW)
+
+//P30       Accel.GS1
+//P31       Accel.GS2  
+//P32/A10      Flash.EN
+//P33/A11      Radio.SCLK
+//P34/A12      Ext. LED
+//P35/A13      Radio.SEL (HIGH)
+//P36/A14      Red LED
+//P37/A14      Green LED                                                   
+#define PORT_P3_INACTIVE_STATE M16C_PORT_INACTIVE_STATE(M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_HIGH,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW)
+     
+//P40/A16      Flash.SO
+//P41/A17      Flash.SI
+//P42/A18      Flash.SCK
+//P43/A19      Radio.RST (HIGH)
+//P44/CS0      Flash.WP
+//P45/CS1      Flash.CS
+//P46/CS2      Flash.RESET
+//P47/CS3      RTC.CLKOE
+#define PORT_P4_INACTIVE_STATE M16C_PORT_INACTIVE_STATE(M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW)
+
+#define PORT_P5_INACTIVE_STATE M16C_PORT_INACTIVE_STATE(M16C_PIN_INACTIVE_INPUT,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_INPUT,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW)
+
+
+//P62/RXD0     UART0.TXD
+//P63/TXD0     UART0.RXD
+//P66/RXD1     UART1.TXD
+//P67/TXD1     UART1.RXD
+#define PORT_P6_INACTIVE_STATE M16C_PORT_INACTIVE_STATE(M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW)
+
+//P70/TXD2/SDA2        UART2.TXD
+//P71/RDX2/SCK2        UART2.TXD
+//P72/TA1OUT
+//P74/TA2OUT
+//P75  Vcc for I2C (must be pulled high before the I2C bus can be used)
+//P76  Accel VCC
+//P77  Radio VCC (HIGH)
+#define PORT_P7_INACTIVE_STATE M16C_PORT_INACTIVE_STATE(M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW)
+
+
+//P80/TA4OUT   H1.47 ; IC1.P97/ADTRG
+//P81/TA4IN
+//P82/INT0     RTC.CLKOUT
+//P83/INT1     RADIO.IRQ (INPUT)
+//P84/INT2     RTC.INT
+//P85/NMI      pulled high through resistor
+//P87/XCIN     RTC.CLKOUT
+#define PORT_P8_INACTIVE_STATE M16C_PORT_INACTIVE_STATE(M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_INPUT,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_INPUT,\
+                                                        M16C_PIN_INACTIVE_INPUT,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_INPUT)
+
+//P90/TB0IN    RTC.CLKOUT
+//P91
+//P92/TB2IN    RTC.CLKOUT
+//P93/DA0/TB3IN
+//P94/DA1/TB4IN
+//P95/ANEX0
+//P96/ANEX1
+//P97/ADTRG
+#define PORT_P9_INACTIVE_STATE M16C_PORT_INACTIVE_STATE(M16C_PIN_INACTIVE_INPUT,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_INPUT,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                        M16C_PIN_INACTIVE_INPUT)
+
+//P100/AN00
+//P101/AN01
+//P102/AN02
+//P103/AN03 - Accel.Z
+//P104/AN04 - Accel.Y
+//P105/AN05 - Accel.X
+//P106/AN06
+//P107/AN07
+#define PORT_P_10_INACTIVE_STATE M16C_PORT_INACTIVE_STATE(M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                          M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                          M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                          M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                          M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                          M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                          M16C_PIN_INACTIVE_OUTPUT_LOW,\
+                                                          M16C_PIN_INACTIVE_OUTPUT_LOW)
+
+
+
+
+
+
+#endif //__PIN_CONFIGURATION_H__
index bb2a9cd9d50376fdccf1cac8ca97be922c12aa9f..1a6904ad56305bef117394339a88827102ad2b34 100644 (file)
  */
 generic module SoftwareI2CPacketC(int speed)
 {
-       provides interface I2CPacket<TI2CBasicAddr>;
-       
-       uses interface GeneralIO as SDA;
-       uses interface GeneralIO as SCL;
-       uses interface BusyWait<TMicro, uint16_t>;
+  provides interface I2CPacket<TI2CBasicAddr>;
+
+  uses interface GeneralIO as SDA;
+  uses interface GeneralIO as SCL;
+  uses interface BusyWait<TMicro, uint16_t>;
 }
 implementation
 {
-       enum
+  enum
+  {
+    S_IDLE,
+    S_BUSY,      
+  };
+
+  uint8_t m_state = S_IDLE;
+  uint16_t m_addr;
+  uint8_t m_length;
+  uint8_t* m_data;
+  error_t m_error;
+  bool m_read;
+
+  uint8_t READSDA()
+  {
+    call SDA.makeInput();
+    return call SDA.get();
+  }
+
+  uint8_t READSCL()
+  {
+    call SCL.makeInput();
+    return call SCL.get();
+  }
+
+  void CLRSCL()
+  {
+    call SCL.clr();
+    call SCL.makeOutput();
+  }
+
+  void CLRSDA()
+  {
+    call SDA.clr();
+    call SDA.makeOutput();
+  }
+
+  void i2cDelay(uint16_t u) {
+    call BusyWait.wait(u);
+  }
+
+  uint8_t i2cReadBit(void)
+  {
+    uint8_t bit;
+
+    /* lets the slave drive data */
+    READSDA();
+    i2cDelay(speed/2);
+    /* Clock stretching */
+    while (READSCL() == 0);
+    /* SCL is high, now data is valid */
+    bit = READSDA();
+    i2cDelay(speed/2);
+    CLRSCL();
+    return bit;
+  }
+
+  error_t i2cWriteBit(bool bit)
+  {
+    if (bit) 
+      READSDA();
+    else 
+      CLRSDA();
+    i2cDelay(speed/2);
+    /* Clock stretching */
+    while (READSCL() == 0);
+    /* SCL is high, now data is valid */
+    /* check that nobody is driving SDA */
+    if (bit && READSDA() == 0)
+      return FAIL;
+    i2cDelay(speed/2);
+    CLRSCL();
+    return SUCCESS;
+  }
+
+  error_t i2cStartCond(void)
+  {
+    READSCL();
+    if (READSDA() == 0)
+      return FAIL;
+    /* SCL is high, set SDA from 1 to 0 */
+    CLRSDA();
+    i2cDelay(speed/2);
+    CLRSCL();
+    return SUCCESS;
+  }
+
+  error_t i2cStopCond(void)
+  {
+    /* set SDA to 0 */
+    CLRSDA();
+    i2cDelay(speed/2);
+    /* Clock stretching */
+    while (READSCL() == 0);
+    /* SCL is high, set SDA from 0 to 1 */
+    if (READSDA() == 0)
+      return FAIL;
+    i2cDelay(speed/2);
+    return SUCCESS;
+  }
+
+  error_t i2cTx(uint8_t byte)
+  {
+    uint8_t bit;
+    uint8_t ack;
+    error_t error = SUCCESS;
+
+    for (bit = 0; bit < 8; bit++) {
+      error = ecombine(error, i2cWriteBit(byte & 0x80));
+      byte <<= 1;
+    }
+
+    // The ack bit is 0 for success
+    if (!i2cReadBit())
+    {
+      return ecombine(error, SUCCESS);
+    }
+    else 
+    {
+      return FAIL;
+    }
+  }
+
+  uint8_t i2cRx (bool nack)
+  {
+    uint8_t byte = 0;
+    uint8_t bit;
+
+    for (bit = 0; bit < 8; bit++) {
+      byte <<= 1;
+      byte |= i2cReadBit();
+    }
+    i2cWriteBit(nack);
+    return byte;
+  }
+
+  task void signalTask()
+  {
+    uint16_t addr;
+    uint8_t length;
+    uint8_t* data;
+    error_t error;
+    bool read;
+    atomic
+    {
+      addr = m_addr;
+      length = m_length;
+      data = m_data;
+      error = m_error;
+      m_state = S_IDLE;
+      read = m_read;
+    }
+    if (read)
+    {
+      signal I2CPacket.readDone(error, addr, length,  data);
+    }
+    else
+    {
+      signal I2CPacket.writeDone(error, addr, length,  data);
+    }
+  }
+
+  async command error_t I2CPacket.read(i2c_flags_t flags, uint16_t addr, uint8_t length, uint8_t* data)
+  {
+    uint8_t i;
+    error_t error = SUCCESS;
+
+    // Both I2C_STOP and I2C_ACK_END flags are not allowed at the same time.
+    if ((flags & I2C_STOP) && (flags & I2C_ACK_END))
+    {
+      return EINVAL;
+    }
+
+    atomic
     {
-        S_IDLE,
-        S_BUSY,      
-    };
-
-    uint8_t m_state = S_IDLE;
-    uint16_t m_addr;
-    uint8_t m_length;
-    uint8_t* m_data;
-    error_t m_error;
-    bool m_read;
-    
-       uint8_t READSDA()
-       {
-               call SDA.makeInput();
-               return call SDA.get();
-       }
-
-       uint8_t READSCL()
-       {
-               call SCL.makeInput();
-               return call SCL.get();
-       }
-
-       void CLRSCL()
-       {
-               call SCL.clr();
-               call SCL.makeOutput();  
-       }
-       
-       void CLRSDA()
-       {
-               call SDA.clr();
-               call SDA.makeOutput();          
-       }
-
-       void i2cDelay(uint16_t u) {
-               call BusyWait.wait(u);
-       }
-       
-       uint8_t i2cReadBit(void)
-       {
-               uint8_t bit;
-               /* lets the slave drive data */
-               READSDA();
-               i2cDelay(speed/2);
-               /* Clock stretching */
-               while (READSCL() == 0);
-               /* SCL is high, now data is valid */
-               bit = READSDA();
-               i2cDelay(speed/2);
-               CLRSCL();
-               return bit;
-       }
-       error_t i2cWriteBit(bool bit)
-       {
-               if (bit) 
-                       READSDA();
-               else 
-                       CLRSDA();
-               i2cDelay(speed/2);
-               /* Clock stretching */
-               while (READSCL() == 0);
-               /* SCL is high, now data is valid */
-               /* check that nobody is driving SDA */
-               if (bit && READSDA() == 0)
-                       return FAIL;
-               i2cDelay(speed/2);
-               CLRSCL();
-               return SUCCESS;
-       }
-       error_t i2cStartCond(void)
-       {
-               if (READSDA() == 0)
-                       return FAIL;
-               /* SCL is high, set SDA from 1 to 0 */
-               CLRSDA();
-               i2cDelay(speed/2);
-               CLRSCL();
-               return SUCCESS;
-       }
-       error_t i2cStopCond(void)
-       {
-               /* set SDA to 0 */
-               CLRSDA();
-               i2cDelay(speed/2);
-               /* Clock stretching */
-               while (READSCL() == 0);
-               /* SCL is high, set SDA from 0 to 1 */
-               if (READSDA() == 0)
-                       return FAIL;
-               i2cDelay(speed/2);
-               return SUCCESS;
-       }
-       error_t i2cTx(uint8_t byte)
-       {
-               uint8_t bit;
-               uint8_t ack;
-               error_t error = SUCCESS;
-               
-               for (bit = 0; bit < 8; bit++) {
-                       error = ecombine(error, i2cWriteBit(byte & 0x80));
-                       byte <<= 1;
-               }
-               
-               // The ack bit is 0 for success
-               if (!i2cReadBit())
-               {
-                       return ecombine(error, SUCCESS);
-               }
-               else 
-               {
-                       return FAIL;
-               }
-       }
-       uint8_t i2cRx (bool nack)
-       {
-               uint8_t byte = 0;
-               uint8_t bit;
-        
-               for (bit = 0; bit < 8; bit++) {
-                    byte <<= 1;                
-                    byte |= i2cReadBit();              
-               }
-               i2cWriteBit(nack);
-               return byte;            
-       }
-    task void signalTask()
+      if (m_state == S_IDLE)
+      {
+        m_state = S_BUSY;
+      }
+      else
+      {
+        return EBUSY;
+      }
+    }
+    atomic
     {
-       uint16_t addr;
-           uint8_t length;
-           uint8_t* data;
-           error_t error;
-           bool read;
-        atomic
+      if (flags & I2C_START)
+      {
+        error = ecombine(error, i2cStartCond());
+        error = ecombine(error, i2cTx(addr+1)); 
+      }
+
+      // Only read data from the device if length is >0.
+      // TODO(henrik): Should a data length of 0 be a invalid input?
+      if (length > 0)
+      {
+        // Read the data from the device.
+        for (i = 0; i < length-1; ++i)
         {
-            addr = m_addr;
-            length = m_length;
-            data = m_data;
-            error = m_error;
-            m_state = S_IDLE;
-            read = m_read;
+          data[i] = i2cRx(false);
         }
-        if (read)
+        if (flags & I2C_ACK_END)
         {
-               signal I2CPacket.readDone(error, addr, length,  data);
+          data[length-1] = i2cRx(false);
         }
         else
         {
-               signal I2CPacket.writeDone(error, addr, length,  data);
+          data[length-1] = i2cRx(true);
         }
+      }
+      if (flags & I2C_STOP)
+      {
+        error = ecombine(error, i2cStopCond());
+      }
+
+      m_error = error;
+      m_addr = addr;
+      m_length = length;
+      m_data = data;
+      m_read = true;
     }
-       async command error_t I2CPacket.read(i2c_flags_t flags, uint16_t addr, uint8_t length, uint8_t* data)
-       {
-               uint8_t i;
-               error_t error = SUCCESS;
-               
-               // Both I2C_STOP and I2C_ACK_END flags are not allowed at the same time.
-               if ((flags & I2C_STOP) && (flags & I2C_ACK_END))
-        {
-               return EINVAL;
-        }
-        
-        atomic
-        {
-            if (m_state == S_IDLE)
-            {
-                m_state = S_BUSY;
-            }
-            else
-            {
-                               return EBUSY;
-            }
-        }
-        atomic
-        {
-            if (flags & I2C_START)
-            {
-                error = ecombine(error, i2cStartCond());
-                error = ecombine(error, i2cTx(addr+1)); 
-            }
-            
-            // Only read data from the device if length is >0.
-            // TODO(henrik): Should a data length of 0 be a invalid input?
-            if (length > 0)
-            {
-                   // Read the data from the device.
-                   for (i = 0; i < length-1; ++i)
-                   {
-                       data[i] = i2cRx(false);
-                   }
-                   if (flags & I2C_ACK_END)
-                   {
-                       data[length-1] = i2cRx(false);
-                   }
-                   else
-                   {
-                       data[length-1] = i2cRx(true);
-                   }
-               }
-            if (flags & I2C_STOP)
-            {
-                error = ecombine(error, i2cStopCond());
-            }
-
-            m_error = error;
-            m_addr = addr;
-            m_length = length;
-            m_data = data;
-            m_read = true;
-        }
-        post signalTask();
+    post signalTask();
 
-        return SUCCESS;
-       }
+    return SUCCESS;
+  }
 
-       async command error_t I2CPacket.write(i2c_flags_t flags, uint16_t addr, uint8_t length, uint8_t* data)
-       {
-               uint8_t i;
-        error_t error = SUCCESS;
-        
-        atomic
-        {
-            if (m_state == S_IDLE)
-            {
-                m_state = S_BUSY;
-            }
-            else
-            {
-                               return EBUSY;
-            }
-        }
-        atomic
-        {
-            if (flags & I2C_START)
-            {
-                error = ecombine(error, i2cStartCond());
-            }
-            
-            i2cTx(addr); 
-
-            // Send the data to the device.
-            for (i = 0; i < length; ++i)
-            {
-                error = ecombine(error, i2cTx(data[i]));
-            }
-
-            if (flags & I2C_STOP)
-            {
-                error = ecombine(error, i2cStopCond());
-            }
-
-            m_error = error;
-            m_addr = addr;
-            m_length = length;
-            m_data = data;
-            m_read = false;
-        }
-        post signalTask();
-        return SUCCESS;
-       }
-}
\ No newline at end of file
+  async command error_t I2CPacket.write(i2c_flags_t flags, uint16_t addr, uint8_t length, uint8_t* data)
+  {
+    uint8_t i;
+    error_t error = SUCCESS;
+
+    atomic
+    {
+      if (m_state == S_IDLE)
+      {
+        m_state = S_BUSY;
+      }
+      else
+      {
+        return EBUSY;
+      }
+    }
+    atomic
+    {
+      if (flags & I2C_START)
+      {
+        error = ecombine(error, i2cStartCond());
+      }
+
+      i2cTx(addr); 
+
+      // Send the data to the device.
+      for (i = 0; i < length; ++i)
+      {
+        error = ecombine(error, i2cTx(data[i]));
+      }
+
+      if (flags & I2C_STOP)
+      {
+        error = ecombine(error, i2cStopCond());
+      }
+
+      m_error = error;
+      m_addr = addr;
+      m_length = length;
+      m_data = data;
+      m_read = false;
+    }
+    post signalTask();
+    return SUCCESS;
+  }
+}