Files
MySensors/drivers/BCM/Wire.cpp
T
Olivier 8bb3cfb2e1 MySensors 2.1.1 release (#752)
* Bump version to 2.2.0-beta (#713)

* OTA: Add incoming FW block check (#718)

* Linux: Add support for SPIDEV (#734)

RPi and Linux refactor.

Add GPIO Sysfs for GPIO operations.

Update configure script.

Fix some cppcheck warnings.

Add serial emulation that prints to stdout.

Fix some file headers.

* Fix getControllerConfig() (#737)

* Rename MyHwATmega328 to MyHwAVR (#738)

* AVR: Restrict fast pin function use (#739)

* Fix signing presentation bug (#740)

* Consolidate open PRs for bugfix release (#741)

* Revert "Bump version to 2.2.0-beta" (#744)

* Merge Master into Dev (#745)

* Fix spi flash error when compiling in Arduino IDE 1.6.6

* Bump minor version

* Fixed "invalid suffix on literal" warning

* Fix addressing bug in _doSign bitfield

* Make sure nodes not supporting signing informs GW

A node that does not support signing, still needs to inform the
gateway about this to make sure the gateway carries a valid signing
requirement table when a node Id that was requiering signing stops
doing this.
This fixes #286.

* Prevent SecureActuator from accepting ACKs as commands

As ACKs are not currently signed, allowing ACKs as commands
is a considerable security hole for this sketch. This is now resolved.

* Backport of bugfix (#259) in repeaters when forwarding signed messages

* Bumped version to 1.5.2

* Corrected doSign variable name (was _doSign)

* Bumped version to 1.5.3

* Add NULL termination to payloads

Messages addressed to "this" node, will have a null char
appended to the payload after message verification is
done, because some "getters" assume the message being a
string.

* MySensors 2.1.1 release
2017-01-18 21:57:07 +01:00

214 lines
4.8 KiB
C++

/*
TwoWire.h - TWI/I2C library for Arduino & Wiring
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
Modified December 2014 by Ivan Grokhotkov (ivan@esp8266.com) - esp8266 support
Modified April 2015 by Hrsto Gochkov (ficeto@ficeto.com) - alternative esp8266 support
Modified October 2016 by Marcelo Aquino <marceloaqno@gmail.org> for Raspberry Pi
*/
#include "Wire.h"
#include <stdlib.h>
#include <pthread.h>
#include "bcm2835.h"
#include "log.h"
static pthread_mutex_t i2cMutex = PTHREAD_MUTEX_INITIALIZER;
uint8_t TwoWire::rxBuffer[BUFFER_LENGTH];
uint8_t TwoWire::rxBufferIndex = 0;
uint8_t TwoWire::rxBufferLength = 0;
uint8_t TwoWire::txAddress = 0;
uint8_t TwoWire::txBuffer[BUFFER_LENGTH];
uint8_t TwoWire::txBufferIndex = 0;
uint8_t TwoWire::txBufferLength = 0;
uint8_t TwoWire::transmitting = 0;
void TwoWire::begin()
{
if (!bcm2835_i2c_begin()) {
logError("You need root privilege to use I2C.\n");
exit(1);
}
}
void TwoWire::begin(uint8_t address)
{
begin();
bcm2835_i2c_setSlaveAddress(address);
}
void TwoWire::begin(int address)
{
begin(static_cast<uint8_t>(address));
}
void TwoWire::end()
{
bcm2835_i2c_end();
}
void TwoWire::setClock(uint32_t clock)
{
bcm2835_i2c_set_baudrate(clock);
}
void TwoWire::beginTransmission(uint8_t address)
{
pthread_mutex_lock(&i2cMutex);
// indicate that we are transmitting
transmitting = 1;
// set address of targeted slave
txAddress = address;
// reset tx buffer iterator vars
txBufferIndex = 0;
txBufferLength = 0;
}
void TwoWire::beginTransmission(int address)
{
beginTransmission(static_cast<uint8_t>(address));
}
uint8_t TwoWire::endTransmission(void)
{
// transmit buffer
bcm2835_i2c_setSlaveAddress(txAddress);
uint8_t ret = bcm2835_i2c_write(reinterpret_cast<const char *>(txBuffer), txBufferLength);
// reset tx buffer iterator vars
txBufferIndex = 0;
txBufferLength = 0;
// indicate that we are done transmitting
transmitting = 0;
pthread_mutex_unlock(&i2cMutex);
if (ret == BCM2835_I2C_REASON_OK) {
return 0; // success
} else if (ret == BCM2835_I2C_REASON_ERROR_NACK) {
return 3; // error: data send, nack received
}
return 4; // other error
}
size_t TwoWire::requestFrom(uint8_t address, size_t quantity)
{
// clamp to buffer length
if (quantity > BUFFER_LENGTH) {
quantity = BUFFER_LENGTH;
}
rxBufferIndex = 0;
rxBufferLength = 0;
bcm2835_i2c_setSlaveAddress(address);
uint8_t ret = bcm2835_i2c_read(reinterpret_cast<char *>(rxBuffer), quantity);
if (ret == BCM2835_I2C_REASON_OK) {
rxBufferLength = quantity;
}
return rxBufferLength;
}
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity)
{
return requestFrom(address, static_cast<size_t>(quantity));
}
uint8_t TwoWire::requestFrom(int address, int quantity)
{
return requestFrom(static_cast<uint8_t>(address), static_cast<size_t>(quantity));
}
size_t TwoWire::write(uint8_t data)
{
if (transmitting) {
// in master transmitter mode
// don't bother if buffer is full
if (txBufferLength >= BUFFER_LENGTH) {
setWriteError();
return 0;
}
// put byte in tx buffer
txBuffer[txBufferIndex] = data;
++txBufferIndex;
// update amount in buffer
txBufferLength = txBufferIndex;
return 1;
} else {
return write(&data, 1);
}
}
size_t TwoWire::write(const uint8_t *data, size_t quantity)
{
if (transmitting) {
// in master transmitter mode
for (size_t i = 0; i < quantity; ++i) {
write(data[i]);
}
} else {
uint8_t rc = bcm2835_i2c_write(reinterpret_cast<const char *>(data), quantity);
if (rc != BCM2835_I2C_REASON_OK) {
return 0;
}
}
return quantity;
}
int TwoWire::available()
{
return rxBufferLength - rxBufferIndex;
}
int TwoWire::read()
{
int value = -1;
if (rxBufferIndex < rxBufferLength) {
value = rxBuffer[rxBufferIndex];
++rxBufferIndex;
}
return value;
}
int TwoWire::peek()
{
if (rxBufferIndex < rxBufferLength) {
return rxBuffer[rxBufferIndex];
}
return -1;
}
void TwoWire::flush()
{
rxBufferIndex = 0;
rxBufferLength = 0;
txBufferIndex = 0;
txBufferLength = 0;
}
TwoWire Wire = TwoWire();