From 7157b88f4a683aa069d877b217f96c1063df01aa Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 26 Nov 2021 11:27:27 +0700 Subject: [PATCH] add Wire::end() --- libraries/Wire/Wire.cpp | 9 +++- libraries/Wire/Wire.h | 4 ++ libraries/Wire/utility/twi.c | 89 +++++++++++++++++++++++++----------- libraries/Wire/utility/twi.h | 2 + 4 files changed, 75 insertions(+), 29 deletions(-) diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index b500241..4bb1bc9 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -77,9 +77,14 @@ void TwoWire::begin(int address) begin((uint8_t)address); } -void TwoWire::setClock(uint32_t frequency) +void TwoWire::end(void) { - TWBR = ((F_CPU / frequency) - 16) / 2; + twi_disable(); +} + +void TwoWire::setClock(uint32_t clock) +{ + twi_setFrequency(clock); } uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) diff --git a/libraries/Wire/Wire.h b/libraries/Wire/Wire.h index 71cd2b8..f5a9805 100644 --- a/libraries/Wire/Wire.h +++ b/libraries/Wire/Wire.h @@ -33,6 +33,9 @@ #define BUFFER_LENGTH 32 +// WIRE_HAS_END means Wire has end() +#define WIRE_HAS_END 1 + class TwoWire : public Stream { private: @@ -55,6 +58,7 @@ class TwoWire : public Stream void begin(); void begin(uint8_t); void begin(int); + void end(); void setClock(uint32_t); void beginTransmission(uint8_t); void beginTransmission(int); diff --git a/libraries/Wire/utility/twi.c b/libraries/Wire/utility/twi.c index 6e64c01..c4a0db0 100644 --- a/libraries/Wire/utility/twi.c +++ b/libraries/Wire/utility/twi.c @@ -92,6 +92,22 @@ void twi_init(void) TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); } +/* + * Function twi_disable + * Desc disables twi pins + * Input none + * Output none + */ +void twi_disable(void) +{ + // disable twi module, acks, and twi interrupt + TWCR &= ~(_BV(TWEN) | _BV(TWIE) | _BV(TWEA)); + + // deactivate internal pullups for twi. + digitalWrite(SDA, 0); + digitalWrite(SCL, 0); +} + /* * Function twi_slaveInit * Desc sets slave address and enables interrupt @@ -104,6 +120,22 @@ void twi_setAddress(uint8_t address) TWAR = address << 1; } +/* + * Function twi_setClock + * Desc sets twi bit rate + * Input Clock Frequency + * Output none + */ +void twi_setFrequency(uint32_t frequency) +{ + TWBR = ((F_CPU / frequency) - 16) / 2; + + /* twi bit rate formula from atmega128 manual pg 204 + SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR)) + note: TWBR should be 10 or higher for master mode + It is 72 for a 16mhz Wiring board with 100kHz TWI */ +} + /* * Function twi_readFrom * Desc attempts to become twi bus master and read a @@ -155,24 +187,25 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sen twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR TWDR = twi_slarw; TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START - } - else + } else { // send start condition TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); + } // wait for read operation to complete while(TWI_MRX == twi_state){ continue; } - if (twi_masterBufferIndex < length) + if (twi_masterBufferIndex < length) { length = twi_masterBufferIndex; + } // copy twi buffer to data for(i = 0; i < length; ++i){ data[i] = twi_masterBuffer[i]; } - + return length; } @@ -235,10 +268,10 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR TWDR = twi_slarw; TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START - } - else + } else { // send start condition TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA); // enable INTs + } // wait for write operation to complete while(wait && (TWI_MTX == twi_state)){ @@ -322,7 +355,7 @@ void twi_reply(uint8_t ack) if(ack){ TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); }else{ - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT); + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT); } } @@ -382,16 +415,16 @@ ISR(TWI_vect) TWDR = twi_masterBuffer[twi_masterBufferIndex++]; twi_reply(1); }else{ - if (twi_sendStop) + if (twi_sendStop){ twi_stop(); - else { - twi_inRepStart = true; // we're gonna send the START - // don't enable the interrupt. We'll generate the start, but we - // avoid handling the interrupt until we're in the next transaction, - // at the point where we would normally issue the start. - TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ; - twi_state = TWI_READY; - } + } else { + twi_inRepStart = true; // we're gonna send the START + // don't enable the interrupt. We'll generate the start, but we + // avoid handling the interrupt until we're in the next transaction, + // at the point where we would normally issue the start. + TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ; + twi_state = TWI_READY; + } } break; case TW_MT_SLA_NACK: // address sent, nack received @@ -411,6 +444,7 @@ ISR(TWI_vect) case TW_MR_DATA_ACK: // data received, ack sent // put byte into buffer twi_masterBuffer[twi_masterBufferIndex++] = TWDR; + __attribute__ ((fallthrough)); case TW_MR_SLA_ACK: // address sent, ack received // ack if more bytes are expected, otherwise nack if(twi_masterBufferIndex < twi_masterBufferLength){ @@ -422,17 +456,17 @@ ISR(TWI_vect) case TW_MR_DATA_NACK: // data received, nack sent // put final byte into buffer twi_masterBuffer[twi_masterBufferIndex++] = TWDR; - if (twi_sendStop) - twi_stop(); - else { - twi_inRepStart = true; // we're gonna send the START - // don't enable the interrupt. We'll generate the start, but we - // avoid handling the interrupt until we're in the next transaction, - // at the point where we would normally issue the start. - TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ; - twi_state = TWI_READY; - } - break; + if (twi_sendStop){ + twi_stop(); + } else { + twi_inRepStart = true; // we're gonna send the START + // don't enable the interrupt. We'll generate the start, but we + // avoid handling the interrupt until we're in the next transaction, + // at the point where we would normally issue the start. + TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ; + twi_state = TWI_READY; + } + break; case TW_MR_SLA_NACK: // address sent, nack received twi_stop(); break; @@ -498,6 +532,7 @@ ISR(TWI_vect) twi_txBufferLength = 1; twi_txBuffer[0] = 0x00; } + __attribute__ ((fallthrough)); // transmit first byte from buffer, fall case TW_ST_DATA_ACK: // byte sent, ack returned // copy data to output register diff --git a/libraries/Wire/utility/twi.h b/libraries/Wire/utility/twi.h index 6526593..d27325e 100644 --- a/libraries/Wire/utility/twi.h +++ b/libraries/Wire/utility/twi.h @@ -39,7 +39,9 @@ #define TWI_STX 4 void twi_init(void); + void twi_disable(void); void twi_setAddress(uint8_t); + void twi_setFrequency(uint32_t); uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t, uint8_t); uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t); uint8_t twi_transmit(const uint8_t*, uint8_t);