1
0
mirror of https://github.com/taigrr/arduinolibs synced 2025-01-18 04:33:12 -08:00

Refactor the I2C library API

This commit is contained in:
Rhys Weatherley
2012-05-18 09:37:42 +10:00
parent 5819690b42
commit 8a601d3a80
6 changed files with 277 additions and 157 deletions

View File

@@ -45,6 +45,9 @@ BitBangI2C::BitBangI2C(uint8_t dataPin, uint8_t clockPin)
: _dataPin(dataPin)
, _clockPin(clockPin)
, started(false)
, acked(true)
, inWrite(false)
, readCount(0)
{
// Initially set the CLOCK and DATA lines to be outputs in the high state.
pinMode(_clockPin, OUTPUT);
@@ -53,26 +56,11 @@ BitBangI2C::BitBangI2C(uint8_t dataPin, uint8_t clockPin)
digitalWrite(_dataPin, HIGH);
}
/**
* \typedef BitBangI2C::ack_t
* \brief Type that represents an I2C ACK or NACK indication.
*/
unsigned int BitBangI2C::maxTransferSize() const
{
return 0xFFFF;
}
/**
* \var BitBangI2C::ACK
* \brief Indicates that an I2C operation was acknowledged.
*/
/**
* \var BitBangI2C::NACK
* \brief Indicates that an I2C operation was not acknowledged.
*/
/**
* \brief Transmits an I2C start condition on the bus.
*
* \sa startRead(), startWrite()
*/
void BitBangI2C::start()
{
pinMode(_dataPin, OUTPUT);
@@ -87,11 +75,9 @@ void BitBangI2C::start()
digitalWrite(_clockPin, LOW);
i2cDelay();
started = true;
acked = true;
}
/**
* \brief Transmits an I2C stop condition on the bus.
*/
void BitBangI2C::stop()
{
pinMode(_dataPin, OUTPUT);
@@ -101,6 +87,7 @@ void BitBangI2C::stop()
digitalWrite(_dataPin, HIGH);
i2cDelay();
started = false;
inWrite = false;
}
#define I2C_WRITE 0x00
@@ -108,84 +95,77 @@ void BitBangI2C::stop()
#define I2C_READ 0x01
#define I2C_READ10 0xF1
/**
* \brief Starts a write operation by sending a start condition and the I2C control byte.
*
* The \a address must be the 7-bit or 10-bit address of the I2C slave
* on the bus.
*
* Returns BitBangI2C::ACK or BitBangI2C::NACK to indicate whether the
* read operation was acknowledged by the slave or not.
*
* \sa startWrite()
*/
BitBangI2C::ack_t BitBangI2C::startWrite(unsigned int address)
void BitBangI2C::startWrite(unsigned int address)
{
start();
inWrite = true;
if (address < 0x80) {
// 7-bit address.
return write((uint8_t)((address << 1) | I2C_WRITE));
write((uint8_t)((address << 1) | I2C_WRITE));
} else {
// 10-bit address.
if (write((uint8_t)(((address >> 7) & 0x06)) | I2C_WRITE10) == NACK)
return NACK;
return write((uint8_t)address);
write((uint8_t)(((address >> 7) & 0x06)) | I2C_WRITE10);
write((uint8_t)address);
}
}
/**
* \brief Starts a read operation by sending the start condition and the I2C control byte.
*
* The \a address must be the 7-bit or 10-bit address of the I2C slave
* on the bus.
*
* Returns BitBangI2C::ACK or BitBangI2C::NACK to indicate whether the
* read operation was acknowledged by the slave or not.
*
* \sa startWrite()
*/
BitBangI2C::ack_t BitBangI2C::startRead(unsigned int address)
{
start();
if (address < 0x80) {
// 7-bit address.
return write((uint8_t)((address << 1) | I2C_READ));
} else {
// 10-bit address.
if (write((uint8_t)(((address >> 7) & 0x06)) | I2C_READ10) == NACK)
return NACK;
return write((uint8_t)address);
}
}
/**
* \brief Writes a single byte \a value on the I2C bus.
*
* Returns BitBangI2C::ACK or BitBangI2C::NACK to indicate whether the
* slave acknowledged the byte or not.
*/
BitBangI2C::ack_t BitBangI2C::write(uint8_t value)
void BitBangI2C::write(uint8_t value)
{
uint8_t mask = 0x80;
while (mask != 0) {
writeBit((value & mask) != 0);
mask >>= 1;
}
return readBit();
if (readBit()) // 0: ACK, 1: NACK
acked = false;
}
/**
* \brief Reads a single byte from the I2C bus.
*
* If \a ack is BitBangI2C::ACK, then the byte is acknowledged. Otherwise
* the byte will not be acknowledged.
*/
uint8_t BitBangI2C::read(ack_t ack)
bool BitBangI2C::endWrite()
{
stop();
return acked;
}
bool BitBangI2C::startRead(unsigned int address, unsigned int count)
{
start();
inWrite = false;
if (address < 0x80) {
// 7-bit address.
write((uint8_t)((address << 1) | I2C_READ));
} else {
// 10-bit address.
write((uint8_t)(((address >> 7) & 0x06)) | I2C_READ10);
write((uint8_t)address);
}
if (!acked) {
readCount = 0;
return false;
}
readCount = count;
return true;
}
unsigned int BitBangI2C::available()
{
return readCount;
}
uint8_t BitBangI2C::read()
{
uint8_t value = 0;
for (uint8_t bit = 0; bit < 8; ++bit)
value = (value << 1) | readBit();
writeBit(ack);
if (readCount > 1) {
// More bytes left to read - send an ACK.
writeBit(false);
--readCount;
} else {
// Last byte - send the NACK and a stop condition.
writeBit(true);
stop();
readCount = 0;
}
return value;
}

View File

@@ -23,31 +23,32 @@
#ifndef BitBangI2C_h
#define BitBangI2C_h
#include <inttypes.h>
#include "I2CMaster.h"
class BitBangI2C {
class BitBangI2C : public I2CMaster {
public:
BitBangI2C(uint8_t dataPin, uint8_t clockPin);
typedef bool ack_t;
unsigned int maxTransferSize() const;
static const ack_t ACK = false;
static const ack_t NACK = true;
void startWrite(unsigned int address);
void write(uint8_t value);
bool endWrite();
void start();
void stop();
ack_t startWrite(unsigned int address);
ack_t startRead(unsigned int address);
ack_t write(uint8_t value);
uint8_t read(ack_t ack = ACK);
bool startRead(unsigned int address, unsigned int count);
unsigned int available();
uint8_t read();
private:
uint8_t _dataPin;
uint8_t _clockPin;
bool started;
bool acked;
bool inWrite;
unsigned int readCount;
void start();
void stop();
void writeBit(bool bit);
bool readBit();
};

View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) 2012 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "I2CMaster.h"
/**
* \class I2CMaster I2CMaster.h <I2CMaster.h>
* \brief Abstract base class for I2C master implementations.
*
* \sa I2CMaster
*/
/**
* \fn unsigned int I2CMaster::maxTransferSize() const
* \brief Returns the maximum number of bytes that can be read or written in a single request by this bus master.
*/
/**
* \fn void I2CMaster::startWrite(unsigned int address)
* \brief Starts a write operation by sending a start condition and the I2C control byte.
*
* The \a address must be the 7-bit or 10-bit address of the I2C slave
* on the bus.
*
* \sa write(), endWrite(), startRead()
*/
/**
* \fn void I2CMaster::write(uint8_t value)
* \brief Writes a single byte \a value on the I2C bus.
*
* \sa startWrite(), endWrite()
*/
/**
* \fn bool I2CMaster::endWrite()
* \brief Ends the current write operation.
*
* Returns true if the write operation was acknowledged; false otherwise.
*
* \sa startWrite(), write()
*/
/**
* \fn bool I2CMaster::startRead(unsigned int address, unsigned int count)
* \brief Starts a read operation for \a count bytes by sending the start condition and the I2C control byte.
*
* The \a address must be the 7-bit or 10-bit address of the I2C slave
* on the bus.
*
* Returns true if the read request was acknowledged by the I2C slave
* or false otherwise. If true, this function should be followed by
* \a count calls to read() to fetch the bytes.
*
* \sa available(), read(), startWrite()
*/
/**
* \fn unsigned int I2CMaster::available()
* \brief Returns the number of bytes that are still available for reading.
*
* \sa startRead(), read()
*/
/**
* \fn uint8_t I2CMaster::read()
* \brief Reads a single byte from the I2C bus.
*
* \sa startRead(), available()
*/

41
libraries/I2C/I2CMaster.h Normal file
View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2012 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef I2CMaster_h
#define I2CMaster_h
#include <inttypes.h>
class I2CMaster {
public:
virtual unsigned int maxTransferSize() const = 0;
virtual void startWrite(unsigned int address);
virtual void write(uint8_t value) = 0;
virtual bool endWrite() = 0;
virtual bool startRead(unsigned int address, unsigned int count) = 0;
virtual unsigned int available() = 0;
virtual uint8_t read() = 0;
};
#endif