Prvni ulozeni z chegewara githubu
This commit is contained in:
30
libraries/Wire/examples/WireMaster/WireMaster.ino
Normal file
30
libraries/Wire/examples/WireMaster/WireMaster.ino
Normal file
@ -0,0 +1,30 @@
|
||||
#include "Wire.h"
|
||||
|
||||
#define I2C_DEV_ADDR 0x55
|
||||
|
||||
uint32_t i = 0;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.setDebugOutput(true);
|
||||
Wire.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
delay(5000);
|
||||
|
||||
//Write message to the slave
|
||||
Wire.beginTransmission(I2C_DEV_ADDR);
|
||||
Wire.printf("Hello World! %u", i++);
|
||||
uint8_t error = Wire.endTransmission(true);
|
||||
Serial.printf("endTransmission: %u\n", error);
|
||||
|
||||
//Read 16 bytes from the slave
|
||||
uint8_t bytesReceived = Wire.requestFrom(I2C_DEV_ADDR, 16);
|
||||
Serial.printf("requestFrom: %u\n", bytesReceived);
|
||||
if((bool)bytesReceived){ //If received more than zero bytes
|
||||
uint8_t temp[bytesReceived];
|
||||
Wire.readBytes(temp, bytesReceived);
|
||||
log_print_buf(temp, bytesReceived);
|
||||
}
|
||||
}
|
28
libraries/Wire/examples/WireScan/WireScan.ino
Normal file
28
libraries/Wire/examples/WireScan/WireScan.ino
Normal file
@ -0,0 +1,28 @@
|
||||
#include "Wire.h"
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Wire.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
byte error, address;
|
||||
int nDevices = 0;
|
||||
|
||||
delay(5000);
|
||||
|
||||
Serial.println("Scanning for I2C devices ...");
|
||||
for(address = 0x01; address < 0x7f; address++){
|
||||
Wire.beginTransmission(address);
|
||||
error = Wire.endTransmission();
|
||||
if (error == 0){
|
||||
Serial.printf("I2C device found at address 0x%02X\n", address);
|
||||
nDevices++;
|
||||
} else if(error != 2){
|
||||
Serial.printf("Error %d at address 0x%02X\n", error, address);
|
||||
}
|
||||
}
|
||||
if (nDevices == 0){
|
||||
Serial.println("No I2C devices found");
|
||||
}
|
||||
}
|
37
libraries/Wire/examples/WireSlave/WireSlave.ino
Normal file
37
libraries/Wire/examples/WireSlave/WireSlave.ino
Normal file
@ -0,0 +1,37 @@
|
||||
#include "Wire.h"
|
||||
|
||||
#define I2C_DEV_ADDR 0x55
|
||||
|
||||
uint32_t i = 0;
|
||||
|
||||
void onRequest(){
|
||||
Wire.print(i++);
|
||||
Wire.print(" Packets.");
|
||||
Serial.println("onRequest");
|
||||
}
|
||||
|
||||
void onReceive(int len){
|
||||
Serial.printf("onReceive[%d]: ", len);
|
||||
while(Wire.available()){
|
||||
Serial.write(Wire.read());
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.setDebugOutput(true);
|
||||
Wire.onReceive(onReceive);
|
||||
Wire.onRequest(onRequest);
|
||||
Wire.begin((uint8_t)I2C_DEV_ADDR);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
char message[64];
|
||||
snprintf(message, 64, "%u Packets.", i++);
|
||||
Wire.slaveWrite((uint8_t *)message, strlen(message));
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
}
|
35
libraries/Wire/keywords.txt
Normal file
35
libraries/Wire/keywords.txt
Normal file
@ -0,0 +1,35 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For Wire
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
begin KEYWORD2
|
||||
end KEYWORD2
|
||||
setClock KEYWORD2
|
||||
getClock KEYWORD2
|
||||
setTimeOut KEYWORD2
|
||||
getTimeOut KEYWORD2
|
||||
beginTransmission KEYWORD2
|
||||
endTransmission KEYWORD2
|
||||
requestFrom KEYWORD2
|
||||
onReceive KEYWORD2
|
||||
onRequest KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Instances (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
Wire KEYWORD2
|
||||
TwoWire KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
9
libraries/Wire/library.properties
Normal file
9
libraries/Wire/library.properties
Normal file
@ -0,0 +1,9 @@
|
||||
name=Wire
|
||||
version=2.0.0
|
||||
author=Hristo Gochkov
|
||||
maintainer=Hristo Gochkov <hristo@espressif.com>
|
||||
sentence=Allows the communication between devices or sensors connected via Two Wire Interface Bus. For esp8266 boards.
|
||||
paragraph=
|
||||
category=Signal Input/Output
|
||||
url=http://arduino.cc/en/Reference/Wire
|
||||
architectures=esp32
|
698
libraries/Wire/src/Wire.cpp
Normal file
698
libraries/Wire/src/Wire.cpp
Normal file
@ -0,0 +1,698 @@
|
||||
/*
|
||||
TwoWire.cpp - 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 Nov 2017 by Chuck Todd (ctodd@cableone.net) - ESP32 ISR Support
|
||||
Modified Nov 2021 by Hristo Gochkov <Me-No-Dev> to support ESP-IDF API
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
}
|
||||
|
||||
#include "esp32-hal-i2c.h"
|
||||
#include "esp32-hal-i2c-slave.h"
|
||||
#include "Wire.h"
|
||||
#include "Arduino.h"
|
||||
|
||||
TwoWire::TwoWire(uint8_t bus_num)
|
||||
:num(bus_num & 1)
|
||||
,sda(-1)
|
||||
,scl(-1)
|
||||
,bufferSize(I2C_BUFFER_LENGTH) // default Wire Buffer Size
|
||||
,rxBuffer(NULL)
|
||||
,rxIndex(0)
|
||||
,rxLength(0)
|
||||
,txBuffer(NULL)
|
||||
,txLength(0)
|
||||
,txAddress(0)
|
||||
,_timeOutMillis(50)
|
||||
,nonStop(false)
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
,nonStopTask(NULL)
|
||||
,lock(NULL)
|
||||
#endif
|
||||
,is_slave(false)
|
||||
,user_onRequest(NULL)
|
||||
,user_onReceive(NULL)
|
||||
{}
|
||||
|
||||
TwoWire::~TwoWire()
|
||||
{
|
||||
end();
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if(lock != NULL){
|
||||
vSemaphoreDelete(lock);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool TwoWire::initPins(int sdaPin, int sclPin)
|
||||
{
|
||||
if(sdaPin < 0) { // default param passed
|
||||
if(num == 0) {
|
||||
if(sda==-1) {
|
||||
sdaPin = SDA; //use Default Pin
|
||||
} else {
|
||||
sdaPin = sda; // reuse prior pin
|
||||
}
|
||||
} else {
|
||||
if(sda==-1) {
|
||||
#ifdef WIRE1_PIN_DEFINED
|
||||
sdaPin = SDA1;
|
||||
#else
|
||||
log_e("no Default SDA Pin for Second Peripheral");
|
||||
return false; //no Default pin for Second Peripheral
|
||||
#endif
|
||||
} else {
|
||||
sdaPin = sda; // reuse prior pin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(sclPin < 0) { // default param passed
|
||||
if(num == 0) {
|
||||
if(scl == -1) {
|
||||
sclPin = SCL; // use Default pin
|
||||
} else {
|
||||
sclPin = scl; // reuse prior pin
|
||||
}
|
||||
} else {
|
||||
if(scl == -1) {
|
||||
#ifdef WIRE1_PIN_DEFINED
|
||||
sclPin = SCL1;
|
||||
#else
|
||||
log_e("no Default SCL Pin for Second Peripheral");
|
||||
return false; //no Default pin for Second Peripheral
|
||||
#endif
|
||||
} else {
|
||||
sclPin = scl; // reuse prior pin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sda = sdaPin;
|
||||
scl = sclPin;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwoWire::setPins(int sdaPin, int sclPin)
|
||||
{
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if(lock == NULL){
|
||||
lock = xSemaphoreCreateMutex();
|
||||
if(lock == NULL){
|
||||
log_e("xSemaphoreCreateMutex failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//acquire lock
|
||||
if(xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
|
||||
log_e("could not acquire lock");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if(!i2cIsInit(num)){
|
||||
initPins(sdaPin, sclPin);
|
||||
} else {
|
||||
log_e("bus already initialized. change pins only when not.");
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(lock);
|
||||
#endif
|
||||
return !i2cIsInit(num);
|
||||
}
|
||||
|
||||
bool TwoWire::allocateWireBuffer(void)
|
||||
{
|
||||
// or both buffer can be allocated or none will be
|
||||
if (rxBuffer == NULL) {
|
||||
rxBuffer = (uint8_t *)malloc(bufferSize);
|
||||
if (rxBuffer == NULL) {
|
||||
log_e("Can't allocate memory for I2C_%d rxBuffer", num);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (txBuffer == NULL) {
|
||||
txBuffer = (uint8_t *)malloc(bufferSize);
|
||||
if (txBuffer == NULL) {
|
||||
log_e("Can't allocate memory for I2C_%d txBuffer", num);
|
||||
freeWireBuffer(); // free rxBuffer for safety!
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// in case both were allocated before, they must have the same size. All good.
|
||||
return true;
|
||||
}
|
||||
|
||||
void TwoWire::freeWireBuffer(void)
|
||||
{
|
||||
if (rxBuffer != NULL) {
|
||||
free(rxBuffer);
|
||||
rxBuffer = NULL;
|
||||
}
|
||||
if (txBuffer != NULL) {
|
||||
free(txBuffer);
|
||||
txBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
size_t TwoWire::setBufferSize(size_t bSize)
|
||||
{
|
||||
// Maximum size .... HEAP limited ;-)
|
||||
if (bSize < 32) { // 32 bytes is the I2C FIFO Len for ESP32/S2/S3/C3
|
||||
log_e("Minimum Wire Buffer size is 32 bytes");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if(lock == NULL){
|
||||
lock = xSemaphoreCreateMutex();
|
||||
if(lock == NULL){
|
||||
log_e("xSemaphoreCreateMutex failed");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
//acquire lock
|
||||
if(xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
|
||||
log_e("could not acquire lock");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
// allocateWireBuffer allocates memory for both pointers or just free them
|
||||
if (rxBuffer != NULL || txBuffer != NULL) {
|
||||
// if begin() has been already executed, memory size changes... data may be lost. We don't care! :^)
|
||||
if (bSize != bufferSize) {
|
||||
// we want a new buffer size ... just reset buffer pointers and allocate new ones
|
||||
freeWireBuffer();
|
||||
bufferSize = bSize;
|
||||
if (!allocateWireBuffer()) {
|
||||
// failed! Error message already issued
|
||||
bSize = 0; // returns error
|
||||
log_e("Buffer allocation failed");
|
||||
}
|
||||
} // else nothing changes, all set!
|
||||
} else {
|
||||
// no memory allocated yet, just change the size value - allocation in begin()
|
||||
bufferSize = bSize;
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(lock);
|
||||
|
||||
#endif
|
||||
return bSize;
|
||||
}
|
||||
|
||||
// Slave Begin
|
||||
bool TwoWire::begin(uint8_t addr, int sdaPin, int sclPin, uint32_t frequency)
|
||||
{
|
||||
bool started = false;
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if(lock == NULL){
|
||||
lock = xSemaphoreCreateMutex();
|
||||
if(lock == NULL){
|
||||
log_e("xSemaphoreCreateMutex failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//acquire lock
|
||||
if(xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
|
||||
log_e("could not acquire lock");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if(is_slave){
|
||||
log_w("Bus already started in Slave Mode.");
|
||||
started = true;
|
||||
goto end;
|
||||
}
|
||||
if(i2cIsInit(num)){
|
||||
log_e("Bus already started in Master Mode.");
|
||||
goto end;
|
||||
}
|
||||
if (!allocateWireBuffer()) {
|
||||
// failed! Error Message already issued
|
||||
goto end;
|
||||
}
|
||||
if(!initPins(sdaPin, sclPin)){
|
||||
goto end;
|
||||
}
|
||||
i2cSlaveAttachCallbacks(num, onRequestService, onReceiveService, this);
|
||||
if(i2cSlaveInit(num, sda, scl, addr, frequency, bufferSize, bufferSize) != ESP_OK){
|
||||
log_e("Slave Init ERROR");
|
||||
goto end;
|
||||
}
|
||||
is_slave = true;
|
||||
started = true;
|
||||
end:
|
||||
if (!started) freeWireBuffer();
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(lock);
|
||||
#endif
|
||||
return started;
|
||||
}
|
||||
|
||||
// Master Begin
|
||||
bool TwoWire::begin(int sdaPin, int sclPin, uint32_t frequency)
|
||||
{
|
||||
bool started = false;
|
||||
esp_err_t err = ESP_OK;
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if(lock == NULL){
|
||||
lock = xSemaphoreCreateMutex();
|
||||
if(lock == NULL){
|
||||
log_e("xSemaphoreCreateMutex failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//acquire lock
|
||||
if(xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
|
||||
log_e("could not acquire lock");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if(is_slave){
|
||||
log_e("Bus already started in Slave Mode.");
|
||||
goto end;
|
||||
}
|
||||
if(i2cIsInit(num)){
|
||||
log_w("Bus already started in Master Mode.");
|
||||
started = true;
|
||||
goto end;
|
||||
}
|
||||
if (!allocateWireBuffer()) {
|
||||
// failed! Error Message already issued
|
||||
goto end;
|
||||
}
|
||||
if(!initPins(sdaPin, sclPin)){
|
||||
goto end;
|
||||
}
|
||||
err = i2cInit(num, sda, scl, frequency);
|
||||
started = (err == ESP_OK);
|
||||
|
||||
end:
|
||||
if (!started) freeWireBuffer();
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(lock);
|
||||
#endif
|
||||
return started;
|
||||
|
||||
}
|
||||
|
||||
bool TwoWire::end()
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if(lock != NULL){
|
||||
//acquire lock
|
||||
if(xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
|
||||
log_e("could not acquire lock");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if(is_slave){
|
||||
err = i2cSlaveDeinit(num);
|
||||
if(err == ESP_OK){
|
||||
is_slave = false;
|
||||
}
|
||||
} else if(i2cIsInit(num)){
|
||||
err = i2cDeinit(num);
|
||||
}
|
||||
freeWireBuffer();
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(lock);
|
||||
}
|
||||
#endif
|
||||
return (err == ESP_OK);
|
||||
}
|
||||
|
||||
uint32_t TwoWire::getClock()
|
||||
{
|
||||
uint32_t frequency = 0;
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//acquire lock
|
||||
if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
|
||||
log_e("could not acquire lock");
|
||||
} else {
|
||||
#endif
|
||||
if(is_slave){
|
||||
log_e("Bus is in Slave Mode");
|
||||
} else {
|
||||
i2cGetClock(num, &frequency);
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(lock);
|
||||
}
|
||||
#endif
|
||||
return frequency;
|
||||
}
|
||||
|
||||
bool TwoWire::setClock(uint32_t frequency)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//acquire lock
|
||||
if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
|
||||
log_e("could not acquire lock");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if(is_slave){
|
||||
log_e("Bus is in Slave Mode");
|
||||
err = ESP_FAIL;
|
||||
} else {
|
||||
err = i2cSetClock(num, frequency);
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(lock);
|
||||
#endif
|
||||
return (err == ESP_OK);
|
||||
}
|
||||
|
||||
void TwoWire::setTimeOut(uint16_t timeOutMillis)
|
||||
{
|
||||
_timeOutMillis = timeOutMillis;
|
||||
}
|
||||
|
||||
uint16_t TwoWire::getTimeOut()
|
||||
{
|
||||
return _timeOutMillis;
|
||||
}
|
||||
|
||||
void TwoWire::beginTransmission(uint16_t address)
|
||||
{
|
||||
if(is_slave){
|
||||
log_e("Bus is in Slave Mode");
|
||||
return;
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if(nonStop && nonStopTask == xTaskGetCurrentTaskHandle()){
|
||||
log_e("Unfinished Repeated Start transaction! Expected requestFrom, not beginTransmission! Clearing...");
|
||||
//release lock
|
||||
xSemaphoreGive(lock);
|
||||
}
|
||||
//acquire lock
|
||||
if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
|
||||
log_e("could not acquire lock");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
nonStop = false;
|
||||
txAddress = address;
|
||||
txLength = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
https://www.arduino.cc/reference/en/language/functions/communication/wire/endtransmission/
|
||||
endTransmission() returns:
|
||||
0: success.
|
||||
1: data too long to fit in transmit buffer.
|
||||
2: received NACK on transmit of address.
|
||||
3: received NACK on transmit of data.
|
||||
4: other error.
|
||||
5: timeout
|
||||
*/
|
||||
uint8_t TwoWire::endTransmission(bool sendStop)
|
||||
{
|
||||
if(is_slave){
|
||||
log_e("Bus is in Slave Mode");
|
||||
return 4;
|
||||
}
|
||||
if (txBuffer == NULL){
|
||||
log_e("NULL TX buffer pointer");
|
||||
return 4;
|
||||
}
|
||||
esp_err_t err = ESP_OK;
|
||||
if(sendStop){
|
||||
err = i2cWrite(num, txAddress, txBuffer, txLength, _timeOutMillis);
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(lock);
|
||||
#endif
|
||||
} else {
|
||||
//mark as non-stop
|
||||
nonStop = true;
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
nonStopTask = xTaskGetCurrentTaskHandle();
|
||||
#endif
|
||||
}
|
||||
switch(err){
|
||||
case ESP_OK: return 0;
|
||||
case ESP_FAIL: return 2;
|
||||
case ESP_ERR_TIMEOUT: return 5;
|
||||
default: break;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
size_t TwoWire::requestFrom(uint16_t address, size_t size, bool sendStop)
|
||||
{
|
||||
if(is_slave){
|
||||
log_e("Bus is in Slave Mode");
|
||||
return 0;
|
||||
}
|
||||
if (rxBuffer == NULL || txBuffer == NULL){
|
||||
log_e("NULL buffer pointer");
|
||||
return 0;
|
||||
}
|
||||
esp_err_t err = ESP_OK;
|
||||
if(nonStop
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
&& nonStopTask == xTaskGetCurrentTaskHandle()
|
||||
#endif
|
||||
){
|
||||
if(address != txAddress){
|
||||
log_e("Unfinished Repeated Start transaction! Expected address do not match! %u != %u", address, txAddress);
|
||||
return 0;
|
||||
}
|
||||
nonStop = false;
|
||||
rxIndex = 0;
|
||||
rxLength = 0;
|
||||
err = i2cWriteReadNonStop(num, address, txBuffer, txLength, rxBuffer, size, _timeOutMillis, &rxLength);
|
||||
if(err){
|
||||
log_e("i2cWriteReadNonStop returned Error %d", err);
|
||||
}
|
||||
} else {
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//acquire lock
|
||||
if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
|
||||
log_e("could not acquire lock");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
rxIndex = 0;
|
||||
rxLength = 0;
|
||||
err = i2cRead(num, address, rxBuffer, size, _timeOutMillis, &rxLength);
|
||||
if(err){
|
||||
log_e("i2cRead returned Error %d", err);
|
||||
}
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(lock);
|
||||
#endif
|
||||
return rxLength;
|
||||
}
|
||||
|
||||
size_t TwoWire::write(uint8_t data)
|
||||
{
|
||||
if (txBuffer == NULL){
|
||||
log_e("NULL TX buffer pointer");
|
||||
return 0;
|
||||
}
|
||||
if(txLength >= bufferSize) {
|
||||
return 0;
|
||||
}
|
||||
txBuffer[txLength++] = data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t TwoWire::write(const uint8_t *data, size_t quantity)
|
||||
{
|
||||
for(size_t i = 0; i < quantity; ++i) {
|
||||
if(!write(data[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return quantity;
|
||||
|
||||
}
|
||||
|
||||
int TwoWire::available(void)
|
||||
{
|
||||
int result = rxLength - rxIndex;
|
||||
return result;
|
||||
}
|
||||
|
||||
int TwoWire::read(void)
|
||||
{
|
||||
int value = -1;
|
||||
if (rxBuffer == NULL){
|
||||
log_e("NULL RX buffer pointer");
|
||||
return value;
|
||||
}
|
||||
if(rxIndex < rxLength) {
|
||||
value = rxBuffer[rxIndex++];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int TwoWire::peek(void)
|
||||
{
|
||||
int value = -1;
|
||||
if (rxBuffer == NULL){
|
||||
log_e("NULL RX buffer pointer");
|
||||
return value;
|
||||
}
|
||||
if(rxIndex < rxLength) {
|
||||
value = rxBuffer[rxIndex];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void TwoWire::flush(void)
|
||||
{
|
||||
rxIndex = 0;
|
||||
rxLength = 0;
|
||||
txLength = 0;
|
||||
//i2cFlush(num); // cleanup
|
||||
}
|
||||
|
||||
size_t TwoWire::requestFrom(uint8_t address, size_t len, bool sendStop)
|
||||
{
|
||||
return requestFrom(static_cast<uint16_t>(address), static_cast<size_t>(len), static_cast<bool>(sendStop));
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t len, uint8_t sendStop)
|
||||
{
|
||||
return requestFrom(static_cast<uint16_t>(address), static_cast<size_t>(len), static_cast<bool>(sendStop));
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(uint16_t address, uint8_t len, uint8_t sendStop)
|
||||
{
|
||||
return requestFrom(address, static_cast<size_t>(len), static_cast<bool>(sendStop));
|
||||
}
|
||||
|
||||
/* Added to match the Arduino function definition: https://github.com/arduino/ArduinoCore-API/blob/173e8eadced2ad32eeb93bcbd5c49f8d6a055ea6/api/HardwareI2C.h#L39
|
||||
* See: https://github.com/arduino-libraries/ArduinoECCX08/issues/25
|
||||
*/
|
||||
uint8_t TwoWire::requestFrom(uint16_t address, uint8_t len, bool stopBit)
|
||||
{
|
||||
return requestFrom((uint16_t)address, (size_t)len, stopBit);
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t len)
|
||||
{
|
||||
return requestFrom(static_cast<uint16_t>(address), static_cast<size_t>(len), true);
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(uint16_t address, uint8_t len)
|
||||
{
|
||||
return requestFrom(address, static_cast<size_t>(len), true);
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(int address, int len)
|
||||
{
|
||||
return requestFrom(static_cast<uint16_t>(address), static_cast<size_t>(len), true);
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(int address, int len, int sendStop)
|
||||
{
|
||||
return static_cast<uint8_t>(requestFrom(static_cast<uint16_t>(address), static_cast<size_t>(len), static_cast<bool>(sendStop)));
|
||||
}
|
||||
|
||||
void TwoWire::beginTransmission(int address)
|
||||
{
|
||||
beginTransmission(static_cast<uint16_t>(address));
|
||||
}
|
||||
|
||||
void TwoWire::beginTransmission(uint8_t address)
|
||||
{
|
||||
beginTransmission(static_cast<uint16_t>(address));
|
||||
}
|
||||
|
||||
uint8_t TwoWire::endTransmission(void)
|
||||
{
|
||||
return endTransmission(true);
|
||||
}
|
||||
|
||||
size_t TwoWire::slaveWrite(const uint8_t * buffer, size_t len)
|
||||
{
|
||||
return i2cSlaveWrite(num, buffer, len, _timeOutMillis);
|
||||
}
|
||||
|
||||
void TwoWire::onReceiveService(uint8_t num, uint8_t* inBytes, size_t numBytes, bool stop, void * arg)
|
||||
{
|
||||
TwoWire * wire = (TwoWire*)arg;
|
||||
if(!wire->user_onReceive){
|
||||
return;
|
||||
}
|
||||
if (wire->rxBuffer == NULL){
|
||||
log_e("NULL RX buffer pointer");
|
||||
return;
|
||||
}
|
||||
for(uint8_t i = 0; i < numBytes; ++i){
|
||||
wire->rxBuffer[i] = inBytes[i];
|
||||
}
|
||||
wire->rxIndex = 0;
|
||||
wire->rxLength = numBytes;
|
||||
wire->user_onReceive(numBytes);
|
||||
}
|
||||
|
||||
void TwoWire::onRequestService(uint8_t num, void * arg)
|
||||
{
|
||||
TwoWire * wire = (TwoWire*)arg;
|
||||
if(!wire->user_onRequest){
|
||||
return;
|
||||
}
|
||||
if (wire->txBuffer == NULL){
|
||||
log_e("NULL TX buffer pointer");
|
||||
return;
|
||||
}
|
||||
wire->txLength = 0;
|
||||
wire->user_onRequest();
|
||||
if(wire->txLength){
|
||||
wire->slaveWrite((uint8_t*)wire->txBuffer, wire->txLength);
|
||||
}
|
||||
}
|
||||
|
||||
void TwoWire::onReceive( void (*function)(int) )
|
||||
{
|
||||
user_onReceive = function;
|
||||
}
|
||||
|
||||
// sets function called on slave read
|
||||
void TwoWire::onRequest( void (*function)(void) )
|
||||
{
|
||||
user_onRequest = function;
|
||||
}
|
||||
|
||||
|
||||
TwoWire Wire = TwoWire(0);
|
||||
TwoWire Wire1 = TwoWire(1);
|
165
libraries/Wire/src/Wire.h
Normal file
165
libraries/Wire/src/Wire.h
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
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 November 2017 by Chuck Todd <stickbreaker on GitHub> to use ISR and increase stability.
|
||||
Modified Nov 2021 by Hristo Gochkov <Me-No-Dev> to support ESP-IDF API
|
||||
*/
|
||||
|
||||
#ifndef TwoWire_h
|
||||
#define TwoWire_h
|
||||
|
||||
#include <esp32-hal.h>
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#endif
|
||||
#include "Stream.h"
|
||||
|
||||
// WIRE_HAS_BUFFER_SIZE means Wire has setBufferSize()
|
||||
#define WIRE_HAS_BUFFER_SIZE 1
|
||||
// WIRE_HAS_END means Wire has end()
|
||||
#define WIRE_HAS_END 1
|
||||
|
||||
#ifndef I2C_BUFFER_LENGTH
|
||||
#define I2C_BUFFER_LENGTH 128 // Default size, if none is set using Wire::setBuffersize(size_t)
|
||||
#endif
|
||||
typedef void(*user_onRequest)(void);
|
||||
typedef void(*user_onReceive)(uint8_t*, int);
|
||||
|
||||
class TwoWire: public Stream
|
||||
{
|
||||
protected:
|
||||
uint8_t num;
|
||||
int8_t sda;
|
||||
int8_t scl;
|
||||
|
||||
size_t bufferSize;
|
||||
uint8_t *rxBuffer;
|
||||
size_t rxIndex;
|
||||
size_t rxLength;
|
||||
|
||||
uint8_t *txBuffer;
|
||||
size_t txLength;
|
||||
uint16_t txAddress;
|
||||
|
||||
uint32_t _timeOutMillis;
|
||||
bool nonStop;
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
TaskHandle_t nonStopTask;
|
||||
SemaphoreHandle_t lock;
|
||||
#endif
|
||||
private:
|
||||
bool is_slave;
|
||||
void (*user_onRequest)(void);
|
||||
void (*user_onReceive)(int);
|
||||
static void onRequestService(uint8_t, void *);
|
||||
static void onReceiveService(uint8_t, uint8_t*, size_t, bool, void *);
|
||||
bool initPins(int sdaPin, int sclPin);
|
||||
bool allocateWireBuffer(void);
|
||||
void freeWireBuffer(void);
|
||||
|
||||
public:
|
||||
TwoWire(uint8_t bus_num);
|
||||
~TwoWire();
|
||||
|
||||
//call setPins() first, so that begin() can be called without arguments from libraries
|
||||
bool setPins(int sda, int scl);
|
||||
|
||||
bool begin(int sda, int scl, uint32_t frequency=0); // returns true, if successful init of i2c bus
|
||||
bool begin(uint8_t slaveAddr, int sda, int scl, uint32_t frequency);
|
||||
// Explicit Overload for Arduino MainStream API compatibility
|
||||
inline bool begin()
|
||||
{
|
||||
return begin(-1, -1, static_cast<uint32_t>(0));
|
||||
}
|
||||
inline bool begin(uint8_t addr)
|
||||
{
|
||||
return begin(addr, -1, -1, 0);
|
||||
}
|
||||
inline bool begin(int addr)
|
||||
{
|
||||
return begin(static_cast<uint8_t>(addr), -1, -1, 0);
|
||||
}
|
||||
bool end();
|
||||
|
||||
size_t setBufferSize(size_t bSize);
|
||||
|
||||
void setTimeOut(uint16_t timeOutMillis); // default timeout of i2c transactions is 50ms
|
||||
uint16_t getTimeOut();
|
||||
|
||||
bool setClock(uint32_t);
|
||||
uint32_t getClock();
|
||||
|
||||
void beginTransmission(uint16_t address);
|
||||
void beginTransmission(uint8_t address);
|
||||
void beginTransmission(int address);
|
||||
|
||||
uint8_t endTransmission(bool sendStop);
|
||||
uint8_t endTransmission(void);
|
||||
|
||||
size_t requestFrom(uint16_t address, size_t size, bool sendStop);
|
||||
uint8_t requestFrom(uint16_t address, uint8_t size, bool sendStop);
|
||||
uint8_t requestFrom(uint16_t address, uint8_t size, uint8_t sendStop);
|
||||
size_t requestFrom(uint8_t address, size_t len, bool stopBit);
|
||||
uint8_t requestFrom(uint16_t address, uint8_t size);
|
||||
uint8_t requestFrom(uint8_t address, uint8_t size, uint8_t sendStop);
|
||||
uint8_t requestFrom(uint8_t address, uint8_t size);
|
||||
uint8_t requestFrom(int address, int size, int sendStop);
|
||||
uint8_t requestFrom(int address, int size);
|
||||
|
||||
size_t write(uint8_t);
|
||||
size_t write(const uint8_t *, size_t);
|
||||
int available(void);
|
||||
int read(void);
|
||||
int peek(void);
|
||||
void flush(void);
|
||||
|
||||
inline size_t write(const char * s)
|
||||
{
|
||||
return write((uint8_t*) s, strlen(s));
|
||||
}
|
||||
inline size_t write(unsigned long n)
|
||||
{
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
inline size_t write(long n)
|
||||
{
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
inline size_t write(unsigned int n)
|
||||
{
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
inline size_t write(int n)
|
||||
{
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
|
||||
void onReceive( void (*)(int) );
|
||||
void onRequest( void (*)(void) );
|
||||
size_t slaveWrite(const uint8_t *, size_t);
|
||||
};
|
||||
|
||||
extern TwoWire Wire;
|
||||
extern TwoWire Wire1;
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user