mirror of
https://github.com/taigrr/arduinolibs
synced 2025-01-18 04:33:12 -08:00
Bit-banged I2C implementation on any pin
This commit is contained in:
parent
9a1cd00521
commit
cbd5345b49
@ -610,7 +610,7 @@ WARN_LOGFILE =
|
|||||||
# directories like "/usr/src/myproject". Separate the files or directories
|
# directories like "/usr/src/myproject". Separate the files or directories
|
||||||
# with spaces.
|
# with spaces.
|
||||||
|
|
||||||
INPUT = ../libraries/FreetronicsLCD ../libraries/BlinkLED .
|
INPUT = ../libraries/FreetronicsLCD ../libraries/BlinkLED ../libraries/BitBangI2C .
|
||||||
|
|
||||||
# This tag can be used to specify the character encoding of the source files
|
# This tag can be used to specify the character encoding of the source files
|
||||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
|
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
|
||||||
|
216
libraries/BitBangI2C/BitBangI2C.cpp
Normal file
216
libraries/BitBangI2C/BitBangI2C.cpp
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
/*
|
||||||
|
* 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 "BitBangI2C.h"
|
||||||
|
#include <WProgram.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class BitBangI2C BitBangI2C.h <BitBangI2C.h>
|
||||||
|
* \brief Bit-banged implementation of an I2C master.
|
||||||
|
*
|
||||||
|
* This class implements the I2C master protocol on any arbitrary pair
|
||||||
|
* of data and clock pins. It is not restricted to pre-defined pins as
|
||||||
|
* is the case for the standard \c Wire library.
|
||||||
|
*
|
||||||
|
* This implementation only implements the master side of the protocol.
|
||||||
|
* It assumes that there is a single bus master, no arbitration, and
|
||||||
|
* no clock stretching.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define i2cDelay() delayMicroseconds(5)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Constructs a new bit-banged I2C master on \a dataPin and \a clockPin.
|
||||||
|
*/
|
||||||
|
BitBangI2C::BitBangI2C(uint8_t dataPin, uint8_t clockPin)
|
||||||
|
: _dataPin(dataPin)
|
||||||
|
, _clockPin(clockPin)
|
||||||
|
, started(false)
|
||||||
|
{
|
||||||
|
// Initially set the CLOCK and DATA lines to be outputs in the high state.
|
||||||
|
pinMode(_clockPin, OUTPUT);
|
||||||
|
pinMode(_dataPin, OUTPUT);
|
||||||
|
digitalWrite(_clockPin, HIGH);
|
||||||
|
digitalWrite(_dataPin, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \typedef BitBangI2C::ack_t
|
||||||
|
* \brief Type that represents an I2C ACK or NACK indication.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \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);
|
||||||
|
if (started) {
|
||||||
|
// Already started, so send a restart condition.
|
||||||
|
digitalWrite(_dataPin, HIGH);
|
||||||
|
digitalWrite(_clockPin, HIGH);
|
||||||
|
i2cDelay();
|
||||||
|
}
|
||||||
|
digitalWrite(_dataPin, LOW);
|
||||||
|
i2cDelay();
|
||||||
|
digitalWrite(_clockPin, LOW);
|
||||||
|
i2cDelay();
|
||||||
|
started = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Transmits an I2C stop condition on the bus.
|
||||||
|
*/
|
||||||
|
void BitBangI2C::stop()
|
||||||
|
{
|
||||||
|
pinMode(_dataPin, OUTPUT);
|
||||||
|
digitalWrite(_dataPin, LOW);
|
||||||
|
digitalWrite(_clockPin, HIGH);
|
||||||
|
i2cDelay();
|
||||||
|
digitalWrite(_dataPin, HIGH);
|
||||||
|
i2cDelay();
|
||||||
|
started = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define I2C_WRITE 0x00
|
||||||
|
#define I2C_WRITE10 0xF0
|
||||||
|
#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)
|
||||||
|
{
|
||||||
|
start();
|
||||||
|
if (address < 0x80) {
|
||||||
|
// 7-bit address.
|
||||||
|
return 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \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)
|
||||||
|
{
|
||||||
|
uint8_t mask = 0x80;
|
||||||
|
while (mask != 0) {
|
||||||
|
writeBit((value & mask) != 0);
|
||||||
|
mask >>= 1;
|
||||||
|
}
|
||||||
|
return readBit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \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)
|
||||||
|
{
|
||||||
|
uint8_t value = 0;
|
||||||
|
for (uint8_t bit = 0; bit < 8; ++bit)
|
||||||
|
value = (value << 1) | readBit();
|
||||||
|
writeBit(ack);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitBangI2C::writeBit(bool bit)
|
||||||
|
{
|
||||||
|
pinMode(_dataPin, OUTPUT);
|
||||||
|
if (bit)
|
||||||
|
digitalWrite(_dataPin, HIGH);
|
||||||
|
else
|
||||||
|
digitalWrite(_dataPin, LOW);
|
||||||
|
i2cDelay();
|
||||||
|
digitalWrite(_clockPin, HIGH);
|
||||||
|
i2cDelay();
|
||||||
|
digitalWrite(_clockPin, LOW);
|
||||||
|
i2cDelay();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BitBangI2C::readBit()
|
||||||
|
{
|
||||||
|
pinMode(_dataPin, INPUT);
|
||||||
|
digitalWrite(_dataPin, HIGH);
|
||||||
|
digitalWrite(_clockPin, HIGH);
|
||||||
|
bool bit = digitalRead(_dataPin);
|
||||||
|
i2cDelay();
|
||||||
|
digitalWrite(_clockPin, LOW);
|
||||||
|
i2cDelay();
|
||||||
|
return bit;
|
||||||
|
}
|
55
libraries/BitBangI2C/BitBangI2C.h
Normal file
55
libraries/BitBangI2C/BitBangI2C.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* 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 BitBangI2C_h
|
||||||
|
#define BitBangI2C_h
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
class BitBangI2C {
|
||||||
|
public:
|
||||||
|
BitBangI2C(uint8_t dataPin, uint8_t clockPin);
|
||||||
|
|
||||||
|
typedef bool ack_t;
|
||||||
|
|
||||||
|
static const ack_t ACK = false;
|
||||||
|
static const ack_t NACK = true;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t _dataPin;
|
||||||
|
uint8_t _clockPin;
|
||||||
|
bool started;
|
||||||
|
|
||||||
|
void writeBit(bool bit);
|
||||||
|
bool readBit();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user