]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/platforms/mulle/softwarei2c/SoftwareI2CPacketC.nc
Fixed a bug in the Software I2C. The first time a start condition was sent the clock...
[tinyos-2.x.git] / tos / platforms / mulle / softwarei2c / SoftwareI2CPacketC.nc
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;
+  }
+}