arduino / arduino/ArduinoCore-avr
TWI: actual consummed bytes in slave mode
- Dominant language
- C
- Stars
- 1.5k
- Forks
- 1.1k
- PR merge metrics
- No merged PRs in 30d
Description
Lots of I²C protocols require the slave to increment a counter when the master reads data. The amount of read bytes is unknown before actual access most of the time. Thus we need a tool to get this value back to the user application.
The information is already available inside twi.c utility. The chosen implementation below adds a new callback which is called from ISR when master stops to read [or has read all available bytes] with the amount of consumed bytes as parameter.
Here a patch to do this, based on Arduino Wire library from Debian package (arduino-core 1.0.5+dfsg2-2). We tried to keep the same coding-style as the rest of code.
```
From b543c1b336397e93ee6fc2742edaf651a27e269e Mon Sep 17 00:00:00 2001
From: JackDesBwa
Date: Sun, 28 Jun 2015 09:58:49 +0200
Subject: [PATCH] add onRequestComplete in Wire library
This event is available to know how many bytes were actually consumed after a
transmit in slave mode. Lots of i2c protocols require a counter to be
automatically incremented inside the slave based of actual consumed bytes by
the master. This callback allows to implement such a mechanism.
---
libraries/Wire/Wire.cpp | 19 +++++++++++++++++++
libraries/Wire/Wire.h | 3 +++
libraries/Wire/keywords.txt | 1 +
libraries/Wire/utility/twi.c | 14 ++++++++++++++
libraries/Wire/utility/twi.h | 1 +
5 files changed, 38 insertions(+)
diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp
index 4e7a17c..c7da65a 100644
--- a/libraries/Wire/Wire.cpp
+++ b/libraries/Wire/Wire.cpp
@@ -40,6 +40,7 @@ uint8_t TwoWire::txBufferIndex = 0;
uint8_t TwoWire::txBufferLength = 0;
uint8_t TwoWire::transmitting = 0;
+void (*TwoWire::user_onRequestComplete)(int);
void (*TwoWire::user_onRequest)(void);
void (*TwoWire::user_onReceive)(int);
@@ -65,6 +66,7 @@ void TwoWire::begin(void)
void TwoWire::begin(uint8_t address)
{
twi_setAddress(address);
+ twi_attachSlaveTxDoneEvent(onRequestCompleteService);
twi_attachSlaveTxEvent(onRequestService);
twi_attachSlaveRxEvent(onReceiveService);
begin();
@@ -280,6 +282,17 @@ void TwoWire::onRequestService(void)
user_onRequest();
}
+// behind the scenes function that is called when data request is completed
+void TwoWire::onRequestCompleteService(int numBytes)
+{
+ // don't bother if user hasn't registered a callback
+ if(!user_onRequestComplete){
+ return;
+ }
+ // alert user program
+ user_onRequestComplete(numBytes);
+}
+
// sets function called on slave write
void TwoWire::onReceive( void (*function)(int) )
{
@@ -292,6 +305,12 @@ void TwoWire::onRequest( void (*function)(void) )
user_onRequest = function;
}
+// sets function called on slave read end
+void TwoWire::onRequestComplete( void (*function)(int) )
+{
+ user_onRequestComplete = function;
+}
+
// Preinstantiate Objects //////////////////////////////////////////////////////
TwoWire Wire = TwoWire();
diff --git a/libraries/Wire/Wire.h b/libraries/Wire/Wire.h
index a93d0f5..50d0fab 100644
--- a/libraries/Wire/Wire.h
+++ b/libraries/Wire/Wire.h
@@ -40,8 +40,10 @@ class TwoWire : public Stream
static uint8_t txBufferLength;
static uint8_t transmitting;
+ static void (*user_onRequestComplete)(int);
static void (*user_onRequest)(void);
static void (*user_onReceive)(int);
+ static void onRequestCompleteService(int);
static void onRequestService(void);
static void onReceiveService(uint8_t*, int);
public:
@@ -64,6 +66,7 @@ class TwoWire : public Stream
virtual int peek(void);
virtual void flush(void);
void onReceive( void (*)(int) );
+ void onRequestComplete( void (*)(int) );
void onRequest( void (*)(void) );
inline size_t write(unsigned long n) { return write((uint8_t)n); }
diff --git a/libraries/Wire/keywords.txt b/libraries/Wire/keywords.txt
index 12f129b..d3c0524 100644
--- a/libraries/Wire/keywords.txt
+++ b/libraries/Wire/keywords.txt
@@ -18,6 +18,7 @@ send KEYWORD2
receive KEYWORD2
onReceive KEYWORD2
onRequest KEYWORD2
+onRequestComplete KEYWORD2
#######################################
# Instances (KEYWORD2)
diff --git a/libraries/Wire/utility/twi.c b/libraries/Wire/utility/twi.c
index 201d7d1..5ba934c 100644
--- a/libraries/Wire/utility/twi.c
+++ b/libraries/Wire/utility/twi.c
@@ -45,6 +45,7 @@ static volatile uint8_t twi_inRepStart; // in the middle of a repeated start
static void (*twi_onSlaveTransmit)(void);
static void (*twi_onSlaveReceive)(uint8_t*, int);
+static void (*twi_onSlaveTransmitionEnded)(int);
static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH];
static volatile uint8_t twi_masterBufferIndex;
@@ -309,6 +310,17 @@ void twi_attachSlaveTxEvent( void (*function)(void) )
}
/*
+ * Function twi_attachSlaveTxDoneEvent
+ * Desc sets function called after a slave write operation
+ * Input function: callback function to use
+ * Output none
+ */
+void twi_attachSlaveTxDoneEvent( void (*function)(int) )
+{
+ twi_onSlaveTransmitionEnded = function;
+}
+
+/*
* Function twi_reply
* Desc sends byte or readys receive line
* Input ack: byte indicating to ack or to nack
@@ -509,6 +521,8 @@ ISR(TWI_vect)
break;
case TW_ST_DATA_NACK: // received nack, we are done
case TW_ST_LAST_DATA: // received ack, but we are done already!
+ // inform user of the actual consummed bytes
+ twi_onSlaveTransmitionEnded(twi_txBufferIndex-1);
// ack future responses
twi_reply(1);
// leave slave receiver state
diff --git a/libraries/Wire/utility/twi.h b/libraries/Wire/utility/twi.h
index 6526593..ae61ba3 100644
--- a/libraries/Wire/utility/twi.h
+++ b/libraries/Wire/utility/twi.h
@@ -45,6 +45,7 @@
uint8_t twi_transmit(const uint8_t*, uint8_t);
void twi_attachSlaveRxEvent( void (*)(uint8_t*, int) );
void twi_attachSlaveTxEvent( void (*)(void) );
+ void twi_attachSlaveTxDoneEvent( void (*)(int) );
void twi_reply(uint8_t);
void twi_stop(void);
void twi_releaseBus(void);
--
1.9.1
```
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.