X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=tos%2Fplatforms%2Fmulle%2Fsoftwarei2c%2FSoftwareI2CPacketC.nc;fp=tos%2Fplatforms%2Fmulle%2Fsoftwarei2c%2FSoftwareI2CPacketC.nc;h=1a6904ad56305bef117394339a88827102ad2b34;hb=f1b1bacb52777dced4f53563b4a30fc31940ca7d;hp=bb2a9cd9d50376fdccf1cac8ca97be922c12aa9f;hpb=31ff2c2cf814676d013f819729ee17c1d26f2f29;p=tinyos-2.x.git diff --git a/tos/platforms/mulle/softwarei2c/SoftwareI2CPacketC.nc b/tos/platforms/mulle/softwarei2c/SoftwareI2CPacketC.nc index bb2a9cd9..1a6904ad 100644 --- a/tos/platforms/mulle/softwarei2c/SoftwareI2CPacketC.nc +++ b/tos/platforms/mulle/softwarei2c/SoftwareI2CPacketC.nc @@ -48,282 +48,283 @@ */ generic module SoftwareI2CPacketC(int speed) { - provides interface I2CPacket; - - uses interface GeneralIO as SDA; - uses interface GeneralIO as SCL; - uses interface BusyWait; + provides interface I2CPacket; + + uses interface GeneralIO as SDA; + uses interface GeneralIO as SCL; + uses interface BusyWait; } 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; + } +}