1515 You should have received a copy of the GNU Lesser General Public
1616 License along with this library; if not, write to the Free Software
1717 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18+
19+ Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
1820*/
1921
2022#include <math.h>
3739#include "twi.h"
3840
3941static volatile uint8_t twi_state ;
40- static uint8_t twi_slarw ;
42+ static volatile uint8_t twi_slarw ;
43+ static volatile uint8_t twi_sendStop ; // should the transaction end with a stop
44+ static volatile uint8_t twi_inRepStart ; // in the middle of a repeated start
4145
4246static void (* twi_onSlaveTransmit )(void );
4347static void (* twi_onSlaveReceive )(uint8_t * , int );
4448
4549static uint8_t twi_masterBuffer [TWI_BUFFER_LENGTH ];
4650static volatile uint8_t twi_masterBufferIndex ;
47- static uint8_t twi_masterBufferLength ;
51+ static volatile uint8_t twi_masterBufferLength ;
4852
4953static uint8_t twi_txBuffer [TWI_BUFFER_LENGTH ];
5054static volatile uint8_t twi_txBufferIndex ;
@@ -65,6 +69,8 @@ void twi_init(void)
6569{
6670 // initialize state
6771 twi_state = TWI_READY ;
72+ twi_sendStop = true; // default value
73+ twi_inRepStart = false;
6874
6975 // activate internal pullups for twi.
7076 digitalWrite (SDA , 1 );
@@ -103,9 +109,10 @@ void twi_setAddress(uint8_t address)
103109 * Input address: 7bit i2c device address
104110 * data: pointer to byte array
105111 * length: number of bytes to read into array
112+ * sendStop: Boolean indicating whether to send a stop at the end
106113 * Output number of bytes read
107114 */
108- uint8_t twi_readFrom (uint8_t address , uint8_t * data , uint8_t length )
115+ uint8_t twi_readFrom (uint8_t address , uint8_t * data , uint8_t length , uint8_t sendStop )
109116{
110117 uint8_t i ;
111118
@@ -119,6 +126,7 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length)
119126 continue ;
120127 }
121128 twi_state = TWI_MRX ;
129+ twi_sendStop = sendStop ;
122130 // reset error state (0xFF.. no error occured)
123131 twi_error = 0xFF ;
124132
@@ -135,8 +143,20 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length)
135143 twi_slarw = TW_READ ;
136144 twi_slarw |= address << 1 ;
137145
138- // send start condition
139- TWCR = _BV (TWEN ) | _BV (TWIE ) | _BV (TWEA ) | _BV (TWINT ) | _BV (TWSTA );
146+ if (true == twi_inRepStart ) {
147+ // if we're in the repeated start state, then we've already sent the start,
148+ // (@@@ we hope), and the TWI statemachine is just waiting for the address byte.
149+ // We need to remove ourselves from the repeated start state before we enable interrupts,
150+ // since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning
151+ // up. Also, don't enable the START interrupt. There may be one pending from the
152+ // repeated start that we sent outselves, and that would really confuse things.
153+ twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR
154+ TWDR = twi_slarw ;
155+ TWCR = _BV (TWINT ) | _BV (TWEA ) | _BV (TWEN ) | _BV (TWIE ); // enable INTs, but not START
156+ }
157+ else
158+ // send start condition
159+ TWCR = _BV (TWEN ) | _BV (TWIE ) | _BV (TWEA ) | _BV (TWINT ) | _BV (TWSTA );
140160
141161 // wait for read operation to complete
142162 while (TWI_MRX == twi_state ){
@@ -162,13 +182,14 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length)
162182 * data: pointer to byte array
163183 * length: number of bytes in array
164184 * wait: boolean indicating to wait for write or not
185+ * sendStop: boolean indicating whether or not to send a stop at the end
165186 * Output 0 .. success
166187 * 1 .. length to long for buffer
167188 * 2 .. address send, NACK received
168189 * 3 .. data send, NACK received
169190 * 4 .. other twi error (lost bus arbitration, bus error, ..)
170191 */
171- uint8_t twi_writeTo (uint8_t address , uint8_t * data , uint8_t length , uint8_t wait )
192+ uint8_t twi_writeTo (uint8_t address , uint8_t * data , uint8_t length , uint8_t wait , uint8_t sendStop )
172193{
173194 uint8_t i ;
174195
@@ -182,6 +203,7 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait
182203 continue ;
183204 }
184205 twi_state = TWI_MTX ;
206+ twi_sendStop = sendStop ;
185207 // reset error state (0xFF.. no error occured)
186208 twi_error = 0xFF ;
187209
@@ -198,8 +220,23 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait
198220 twi_slarw = TW_WRITE ;
199221 twi_slarw |= address << 1 ;
200222
201- // send start condition
202- TWCR = _BV (TWEN ) | _BV (TWIE ) | _BV (TWEA ) | _BV (TWINT ) | _BV (TWSTA );
223+ // if we're in a repeated start, then we've already sent the START
224+ // in the ISR. Don't do it again.
225+ //
226+ if (true == twi_inRepStart ) {
227+ // if we're in the repeated start state, then we've already sent the start,
228+ // (@@@ we hope), and the TWI statemachine is just waiting for the address byte.
229+ // We need to remove ourselves from the repeated start state before we enable interrupts,
230+ // since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning
231+ // up. Also, don't enable the START interrupt. There may be one pending from the
232+ // repeated start that we sent outselves, and that would really confuse things.
233+ twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR
234+ TWDR = twi_slarw ;
235+ TWCR = _BV (TWINT ) | _BV (TWEA ) | _BV (TWEN ) | _BV (TWIE ); // enable INTs, but not START
236+ }
237+ else
238+ // send start condition
239+ TWCR = _BV (TWINT ) | _BV (TWEA ) | _BV (TWEN ) | _BV (TWIE ) | _BV (TWSTA ); // enable INTs
203240
204241 // wait for write operation to complete
205242 while (wait && (TWI_MTX == twi_state )){
@@ -343,7 +380,16 @@ SIGNAL(TWI_vect)
343380 TWDR = twi_masterBuffer [twi_masterBufferIndex ++ ];
344381 twi_reply (1 );
345382 }else {
346- twi_stop ();
383+ if (twi_sendStop )
384+ twi_stop ();
385+ else {
386+ twi_inRepStart = true; // we're gonna send the START
387+ // don't enable the interrupt. We'll generate the start, but we
388+ // avoid handling the interrupt until we're in the next transaction,
389+ // at the point where we would normally issue the start.
390+ TWCR = _BV (TWINT ) | _BV (TWSTA )| _BV (TWEN ) ;
391+ twi_state = TWI_READY ;
392+ }
347393 }
348394 break ;
349395 case TW_MT_SLA_NACK : // address sent, nack received
@@ -374,6 +420,17 @@ SIGNAL(TWI_vect)
374420 case TW_MR_DATA_NACK : // data received, nack sent
375421 // put final byte into buffer
376422 twi_masterBuffer [twi_masterBufferIndex ++ ] = TWDR ;
423+ if (twi_sendStop )
424+ twi_stop ();
425+ else {
426+ twi_inRepStart = true; // we're gonna send the START
427+ // don't enable the interrupt. We'll generate the start, but we
428+ // avoid handling the interrupt until we're in the next transaction,
429+ // at the point where we would normally issue the start.
430+ TWCR = _BV (TWINT ) | _BV (TWSTA )| _BV (TWEN ) ;
431+ twi_state = TWI_READY ;
432+ }
433+ break ;
377434 case TW_MR_SLA_NACK : // address sent, nack received
378435 twi_stop ();
379436 break ;
0 commit comments