aboutsummaryrefslogtreecommitdiff
path: root/digital-driver/firmware/TinyWireS/usiTwiSlave.c
diff options
context:
space:
mode:
Diffstat (limited to 'digital-driver/firmware/TinyWireS/usiTwiSlave.c')
-rw-r--r--digital-driver/firmware/TinyWireS/usiTwiSlave.c748
1 files changed, 0 insertions, 748 deletions
diff --git a/digital-driver/firmware/TinyWireS/usiTwiSlave.c b/digital-driver/firmware/TinyWireS/usiTwiSlave.c
deleted file mode 100644
index a263184..0000000
--- a/digital-driver/firmware/TinyWireS/usiTwiSlave.c
+++ /dev/null
@@ -1,748 +0,0 @@
-/********************************************************************************
-
-USI TWI Slave driver.
-
-Created by Donald R. Blake. donblake at worldnet.att.net
-Adapted by Jochen Toppe, jochen.toppe at jtoee.com
-
----------------------------------------------------------------------------------
-
-Created from Atmel source files for Application Note AVR312: Using the USI Module
-as an I2C slave.
-
-This program is free software; you can redistribute it and/or modify it under the
-terms of the GNU General Public License as published by the Free Software
-Foundation; either version 2 of the License, or (at your option) any later
-version.
-
-This program 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 General Public License for more details.
-
----------------------------------------------------------------------------------
-
-Change Activity:
-
- Date Description
- ------ -------------
- 16 Mar 2007 Created.
- 27 Mar 2007 Added support for ATtiny261, 461 and 861.
- 26 Apr 2007 Fixed ACK of slave address on a read.
- 04 Jul 2007 Fixed USISIF in ATtiny45 def
- 12 Dev 2009 Added callback functions for data requests
- 06 Feb 2016 Minor change to allow mutli-byte requestFrom() from master.
- 10 Feb 2016 Simplied RX/TX buffer code and allowed use of full buffer.
- 13 Feb 2016 Made USI_RECEIVE_CALLBACK() callback fully interrupt-driven
- 12 Dec 2016 Added support for ATtiny167
- 23 Dec 2017 Fixed repeated restart (which broke when making receive callback
- interrupt-driven)
-
-********************************************************************************/
-
-
-/********************************************************************************
- includes
-********************************************************************************/
-
-#include <avr/io.h>
-#include <avr/interrupt.h>
-
-#include "usiTwiSlave.h"
-//#include "../common/util.h"
-
-
-/********************************************************************************
- device dependent defines
-********************************************************************************/
-
-#if defined( __AVR_ATtiny167__ )
-# define DDR_USI DDRB
-# define PORT_USI PORTB
-# define PIN_USI PINB
-# define PORT_USI_SDA PB0
-# define PORT_USI_SCL PB2
-# define PIN_USI_SDA PINB0
-# define PIN_USI_SCL PINB2
-# define USI_START_COND_INT USISIF
-# define USI_START_VECTOR USI_START_vect
-# define USI_OVERFLOW_VECTOR USI_OVERFLOW_vect
-#endif
-
-#if defined( __AVR_ATtiny2313__ )
-# define DDR_USI DDRB
-# define PORT_USI PORTB
-# define PIN_USI PINB
-# define PORT_USI_SDA PB5
-# define PORT_USI_SCL PB7
-# define PIN_USI_SDA PINB5
-# define PIN_USI_SCL PINB7
-# define USI_START_COND_INT USISIF
-# define USI_START_VECTOR USI_START_vect
-# define USI_OVERFLOW_VECTOR USI_OVERFLOW_vect
-#endif
-
-#if defined(__AVR_ATtiny84__) | \
- defined(__AVR_ATtiny44__)
-# define DDR_USI DDRA
-# define PORT_USI PORTA
-# define PIN_USI PINA
-# define PORT_USI_SDA PORTA6
-# define PORT_USI_SCL PORTA4
-# define PIN_USI_SDA PINA6
-# define PIN_USI_SCL PINA4
-# define USI_START_COND_INT USISIF
-# define USI_START_VECTOR USI_START_vect
-# define USI_OVERFLOW_VECTOR USI_OVF_vect
-#endif
-
-#if defined( __AVR_ATtiny25__ ) | \
- defined( __AVR_ATtiny45__ ) | \
- defined( __AVR_ATtiny85__ )
-# define DDR_USI DDRB
-# define PORT_USI PORTB
-# define PIN_USI PINB
-# define PORT_USI_SDA PB0
-# define PORT_USI_SCL PB2
-# define PIN_USI_SDA PINB0
-# define PIN_USI_SCL PINB2
-# define USI_START_COND_INT USISIF
-# define USI_START_VECTOR USI_START_vect
-# define USI_OVERFLOW_VECTOR USI_OVF_vect
-#endif
-
-#if defined( __AVR_ATtiny26__ )
-# define DDR_USI DDRB
-# define PORT_USI PORTB
-# define PIN_USI PINB
-# define PORT_USI_SDA PB0
-# define PORT_USI_SCL PB2
-# define PIN_USI_SDA PINB0
-# define PIN_USI_SCL PINB2
-# define USI_START_COND_INT USISIF
-# define USI_START_VECTOR USI_STRT_vect
-# define USI_OVERFLOW_VECTOR USI_OVF_vect
-#endif
-
-#if defined( __AVR_ATtiny261__ ) | \
- defined( __AVR_ATtiny461__ ) | \
- defined( __AVR_ATtiny861__ )
-# define DDR_USI DDRB
-# define PORT_USI PORTB
-# define PIN_USI PINB
-# define PORT_USI_SDA PB0
-# define PORT_USI_SCL PB2
-# define PIN_USI_SDA PINB0
-# define PIN_USI_SCL PINB2
-# define USI_START_COND_INT USISIF
-# define USI_START_VECTOR USI_START_vect
-# define USI_OVERFLOW_VECTOR USI_OVF_vect
-#endif
-
-#if defined( __AVR_ATmega165__ ) | \
- defined( __AVR_ATmega325__ ) | \
- defined( __AVR_ATmega3250__ ) | \
- defined( __AVR_ATmega645__ ) | \
- defined( __AVR_ATmega6450__ ) | \
- defined( __AVR_ATmega329__ ) | \
- defined( __AVR_ATmega3290__ )
-# define DDR_USI DDRE
-# define PORT_USI PORTE
-# define PIN_USI PINE
-# define PORT_USI_SDA PE5
-# define PORT_USI_SCL PE4
-# define PIN_USI_SDA PINE5
-# define PIN_USI_SCL PINE4
-# define USI_START_COND_INT USISIF
-# define USI_START_VECTOR USI_START_vect
-# define USI_OVERFLOW_VECTOR USI_OVERFLOW_vect
-#endif
-
-#if defined( __AVR_ATmega169__ )
-# define DDR_USI DDRE
-# define PORT_USI PORTE
-# define PIN_USI PINE
-# define PORT_USI_SDA PE5
-# define PORT_USI_SCL PE4
-# define PIN_USI_SDA PINE5
-# define PIN_USI_SCL PINE4
-# define USI_START_COND_INT USISIF
-# define USI_START_VECTOR USI_START_vect
-# define USI_OVERFLOW_VECTOR USI_OVERFLOW_vect
-#endif
-
-// These macros make the stop condition detection code more readable.
-#define USI_PINS_SCL_SDA ( ( 1 << PIN_USI_SDA ) | ( 1 << PIN_USI_SCL ) )
-#define USI_PINS_SDA ( 1 << PIN_USI_SDA )
-#define USI_PINS_SCL ( 1 << PIN_USI_SCL )
-
-/********************************************************************************
-
- functions implemented as macros
-
-********************************************************************************/
-
-#define SET_USI_TO_SEND_ACK( ) \
-{ \
- /* prepare ACK, ack is a zero */ \
- USIDR = 0; \
- /* set SDA as output */ \
- DDR_USI |= ( 1 << PORT_USI_SDA ); \
- /* clear all interrupt flags, except Start Cond */ \
- USISR = \
- ( 0 << USI_START_COND_INT ) | \
- ( 1 << USIOIF ) | ( 1 << USIPF ) | \
- ( 1 << USIDC )| \
- /* set USI counter to shift 1 bit */ \
- ( 0x0E << USICNT0 ); \
-}
-
-#define SET_USI_TO_READ_ACK( ) \
-{ \
- /* set SDA as input */ \
- DDR_USI &= ~( 1 << PORT_USI_SDA ); \
- /* prepare ACK */ \
- USIDR = 0; \
- /* clear all interrupt flags, except Start Cond */ \
- USISR = \
- ( 0 << USI_START_COND_INT ) | \
- ( 1 << USIOIF ) | \
- ( 1 << USIPF ) | \
- ( 1 << USIDC ) | \
- /* set USI counter to shift 1 bit */ \
- ( 0x0E << USICNT0 ); \
-}
-
-#define SET_USI_TO_TWI_START_CONDITION_MODE( ) \
-{ \
- USICR = \
- /* enable Start Condition Interrupt, disable Overflow Interrupt */ \
- ( 1 << USISIE ) | ( 0 << USIOIE ) | \
- /* set USI in Two-wire mode, no USI Counter overflow hold */ \
- ( 1 << USIWM1 ) | ( 0 << USIWM0 ) | \
- /* Shift Register Clock Source = External, positive edge */ \
- /* 4-Bit Counter Source = external, both edges */ \
- ( 1 << USICS1 ) | ( 0 << USICS0 ) | ( 0 << USICLK ) | \
- /* no toggle clock-port pin */ \
- ( 0 << USITC ); \
- USISR = \
- /* clear all interrupt flags, except Start Cond */ \
- ( 0 << USI_START_COND_INT ) | ( 1 << USIOIF ) | ( 1 << USIPF ) | \
- ( 1 << USIDC ) | ( 0x0 << USICNT0 ); \
-}
-
-#define SET_USI_TO_SEND_DATA( ) \
-{ \
- /* set SDA as output */ \
- DDR_USI |= ( 1 << PORT_USI_SDA ); \
- /* clear all interrupt flags, except Start Cond */ \
- USISR = \
- ( 0 << USI_START_COND_INT ) | ( 1 << USIOIF ) | ( 1 << USIPF ) | \
- ( 1 << USIDC) | \
- /* set USI to shift out 8 bits */ \
- ( 0x0 << USICNT0 ); \
-}
-
-#define SET_USI_TO_READ_DATA( ) \
-{ \
- /* set SDA as input */ \
- DDR_USI &= ~( 1 << PORT_USI_SDA ); \
- /* clear all interrupt flags, except Start Cond */ \
- USISR = \
- ( 0 << USI_START_COND_INT ) | ( 1 << USIOIF ) | \
- ( 1 << USIPF ) | ( 1 << USIDC ) | \
- /* set USI to shift out 8 bits */ \
- ( 0x0 << USICNT0 ); \
-}
-
-#define USI_RECEIVE_CALLBACK() \
-{ \
- if (usi_onReceiverPtr) \
- { \
- if (usiTwiAmountDataInReceiveBuffer()) \
- { \
- usi_onReceiverPtr(usiTwiAmountDataInReceiveBuffer()); \
- } \
- } \
-}
-
-#define USI_REQUEST_CALLBACK() \
-{ \
- if(usi_onRequestPtr) usi_onRequestPtr(); \
-}
-
-/********************************************************************************
-
- typedef's
-
-********************************************************************************/
-
-typedef enum
-{
- USI_SLAVE_CHECK_ADDRESS = 0x00,
- USI_SLAVE_SEND_DATA = 0x01,
- USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA = 0x02,
- USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA = 0x03,
- USI_SLAVE_REQUEST_DATA = 0x04,
- USI_SLAVE_GET_DATA_AND_SEND_ACK = 0x05
-} overflowState_t;
-
-
-
-/********************************************************************************
-
- local variables
-
-********************************************************************************/
-
-static uint8_t slaveAddress;
-static uint8_t sleep_enable_bit;
-static uint8_t in_transaction;
-static volatile overflowState_t overflowState;
-
-
-static uint8_t rxBuf[ TWI_RX_BUFFER_SIZE ];
-static volatile uint8_t rxHead;
-static volatile uint8_t rxTail;
-static volatile uint8_t rxCount;
-
-static uint8_t txBuf[ TWI_TX_BUFFER_SIZE ];
-static volatile uint8_t txHead;
-static volatile uint8_t txTail;
-static volatile uint8_t txCount;
-
-
-
-/********************************************************************************
-
- local functions
-
-********************************************************************************/
-
-// flushes the TWI buffers
-
-static void flushTwiBuffers( void )
-{
- rxTail = 0;
- rxHead = 0;
- rxCount = 0;
- txTail = 0;
- txHead = 0;
- txCount = 0;
-} // end flushTwiBuffers
-
-
-
-/********************************************************************************
-
- public functions
-
-********************************************************************************/
-
-// initialise USI for TWI slave mode
-
-void usiTwiSlaveInit( uint8_t ownAddress )
-{
- // initialize the TX and RX buffers to empty
- flushTwiBuffers( );
-
- slaveAddress = ownAddress;
-
- // In Two Wire mode (USIWM1, USIWM0 = 1X), the slave USI will pull SCL
- // low when a start condition is detected or a counter overflow (only
- // for USIWM1, USIWM0 = 11). This inserts a wait state. SCL is released
- // by the ISRs (USI_START_vect and USI_OVERFLOW_vect).
-
- // Set SCL and SDA as output
- DDR_USI |= ( 1 << PORT_USI_SCL ) | ( 1 << PORT_USI_SDA );
-
- // set SCL high
- PORT_USI |= ( 1 << PORT_USI_SCL );
-
- // set SDA high
- PORT_USI |= ( 1 << PORT_USI_SDA );
-
- // Set SDA as input
- DDR_USI &= ~( 1 << PORT_USI_SDA );
-
- USICR =
- // enable Start Condition Interrupt
- ( 1 << USISIE ) |
- // disable Overflow Interrupt
- ( 0 << USIOIE ) |
- // set USI in Two-wire mode, no USI Counter overflow hold
- ( 1 << USIWM1 ) | ( 0 << USIWM0 ) |
- // Shift Register Clock Source = external, positive edge
- // 4-Bit Counter Source = external, both edges
- ( 1 << USICS1 ) | ( 0 << USICS0 ) | ( 0 << USICLK ) |
- // no toggle clock-port pin
- ( 0 << USITC );
-
- // clear all interrupt flags and reset overflow counter
-
- USISR = ( 1 << USI_START_COND_INT ) | ( 1 << USIOIF ) | ( 1 << USIPF ) | ( 1 << USIDC );
-
- // The 'in_transaction' variable remembers if the usiTwiSlave driver is in the middle of
- // an i2c transaction. Initialize it to zero
- in_transaction = 0;
-
-} // end usiTwiSlaveInit
-
-
-bool usiTwiDataInTransmitBuffer(void)
-{
-
- // return 0 (false) if the receive buffer is empty
- return txCount;
-
-} // end usiTwiDataInTransmitBuffer
-
-
-// put data in the transmission buffer, wait if buffer is full
-
-void usiTwiTransmitByte( uint8_t data )
-{
-
- // wait for free space in buffer
- while ( txCount == TWI_TX_BUFFER_SIZE) ;
-
- // store data in buffer
- txBuf[ txHead ] = data;
- txHead = ( txHead + 1 ) & TWI_TX_BUFFER_MASK;
- txCount++;
-
-} // end usiTwiTransmitByte
-
-
-// return a byte from the receive buffer, wait if buffer is empty
-
-uint8_t usiTwiReceiveByte( void )
-{
- uint8_t rtn_byte;
-
- // wait for Rx data
- while ( !rxCount );
-
- rtn_byte = rxBuf [ rxTail ];
- // calculate buffer index
- rxTail = ( rxTail + 1 ) & TWI_RX_BUFFER_MASK;
- rxCount--;
-
- // return data from the buffer.
- return rtn_byte;
-
-} // end usiTwiReceiveByte
-
-
-uint8_t usiTwiAmountDataInReceiveBuffer(void)
-{
- return rxCount;
-}
-
-
-/********************************************************************************
-
- USI Start Condition ISR
-
-********************************************************************************/
-
-ISR( USI_START_VECTOR )
-{
- uint8_t usi_pins;
- // http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__avr__interrupts.html
-
- // Notes about ISR. The compiler in the Arduino IDE handles some of the
- // basic ISR plumbing (unless the "ISR_NAKED" attribute is applied).
- // * The AVR processor resets the SREG.I bit when jumping into an ISR
- // * The compiler automatically adds code to save SREG
- // * < user's ISR code goes here >
- // * The compiler automatically adds code to restore SREG
- // * The compiler automatically uses the RETI instruction to return from the ISR.
- // The RETI instruction enables interrupts after the return from ISR.
- // The compiler behavior can be altered with attributes into the ISR declaration;
- // however, the description above is the default.
-
- // cli() call is not necessary. Processor disables interrupts when
- // jumping to an ISR
-
- // no need to save the SREG. The compiler does this automatically when using the
- // ISR construct without modifying attributes.
-
- if ( !in_transaction )
- {
- // remeber the sleep enable bit when entering the ISR
- sleep_enable_bit = MCUCR & ( 1 << SE );
-
- // clear the sleep enable bit to prevent the CPU from entering sleep mode while executing this ISR.
- MCUCR &= ~( 1 << SE );
- }
-
- // set default starting conditions for new TWI package
- overflowState = USI_SLAVE_CHECK_ADDRESS;
-
- // set SDA as input
- DDR_USI &= ~( 1 << PORT_USI_SDA );
-
- // the start condition is that the master pulls SDA low.
-
- // wait for SCL to go low to ensure the Start Condition has completed (the
- // start detector will hold SCL low ) - if a Stop Condition arises then leave
- // the interrupt to prevent waiting forever - don't use USISR to test for Stop
- // Condition as in Application Note AVR312 because the Stop Condition Flag is
- // going to be set from the last TWI sequence
-
- // while SCL is high and SDA is low
- while ( ( usi_pins = PIN_USI & USI_PINS_SCL_SDA ) == USI_PINS_SCL );
-
- // if SDA line was low at SCL edge, then start condition occurred
- if ( !( usi_pins & USI_PINS_SDA ) )
- {
- // a Stop Condition did not occur
-
- // Execute callback if this is a repeated start
- if (in_transaction)
- {
- USI_RECEIVE_CALLBACK();
- }
-
- USICR =
- // keep Start Condition Interrupt enabled to detect RESTART
- ( 1 << USISIE ) |
- // enable Overflow Interrupt
- ( 1 << USIOIE ) |
- // set USI in Two-wire mode, hold SCL low on USI Counter overflow
- ( 1 << USIWM1 ) | ( 1 << USIWM0 ) |
- // Shift Register Clock Source = External, positive edge
- // 4-Bit Counter Source = external, both edges
- ( 1 << USICS1 ) | ( 0 << USICS0 ) | ( 0 << USICLK ) |
- // no toggle clock-port pin
- ( 0 << USITC );
-
- //remember that the USI is in a valid i2c transaction
- in_transaction = 1;
-
- }
- else
- {
- // a Stop Condition did occur
-
- USICR =
- // enable Start Condition Interrupt
- ( 1 << USISIE ) |
- // disable Overflow Interrupt
- ( 0 << USIOIE ) |
- // set USI in Two-wire mode, no USI Counter overflow hold
- ( 1 << USIWM1 ) | ( 0 << USIWM0 ) |
- // Shift Register Clock Source = external, positive edge
- // 4-Bit Counter Source = external, both edges
- ( 1 << USICS1 ) | ( 0 << USICS0 ) | ( 0 << USICLK ) |
- // no toggle clock-port pin
- ( 0 << USITC );
-
- //no longer in valid i2c transaction
- in_transaction = 0;
- // restore the sleep enable bit
- MCUCR |= sleep_enable_bit;
-
- } // end if
-
- USISR =
- // clear interrupt flags - resetting the Start Condition Flag will
- // release SCL
- ( 1 << USI_START_COND_INT ) | ( 1 << USIOIF ) |
- ( 1 << USIPF ) |( 1 << USIDC ) |
- // set USI to sample 8 bits (count 16 external SCL pin toggles)
- ( 0x0 << USICNT0);
-
- // no need to restore the SREG. The compiler does this automatically when using the
- // ISR construct without modifying attributes.
-
- // The compiler automatically uses an RETI instruction to return when using the
- // ISR construct without modifying attributes.
-
-} // end ISR( USI_START_VECTOR )
-
-
-
-/********************************************************************************
-
- USI Overflow ISR
-
-Handles all the communication.
-
-Only disabled when waiting for a new Start Condition.
-
-********************************************************************************/
-
-ISR( USI_OVERFLOW_VECTOR )
-{
- uint8_t finished;
- uint8_t usi_pins;
-
- // http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__avr__interrupts.html
-
- // Notes about ISR. The compiler in the Arduino IDE handles some of the
- // basic ISR plumbing.
- // * The AVR processor resets the SREG.I bit when jumping into an ISR
- // * The compiler automatically adds code to save the SREG
- // * < user's ISR code goes here >
- // * The compiler automatically adds code to restore the SREG
- // * The compiler automatically uses the RETI instruction to return from the ISR.
- // The RETI insturction enables interrupts after the return from ISR.
- // The compiler behavior can be altered with attributes into the ISR declaration;
- // however, the description above is the default.
-
- // cli() call is not necessary. Processor disables interrupts when
- // jumping to an ISR
-
- // no need to save the SREG. The compiler does this automatically when using the
- // ISR construct without modifying attributes.
-
- // The ISR is only ever entered because the ISR(USI_START_VECTOR) interrupt
- // routine ran first. That routine saved the sleep mode and disabled sleep.
-
- // Most of the time this routine exits, it has setup the USI to shift in/out bits
- // and is expected to re-entered because of the USI overflow interrupt. Track whether or
- // not the transaction is completely finished.
- finished = 0;
-
-
- switch ( overflowState )
- {
-
- // Address mode: check address and send ACK (and next USI_SLAVE_SEND_DATA) if OK,
- // else reset USI
- case USI_SLAVE_CHECK_ADDRESS:
- if ( ( USIDR == 0 ) || ( ( USIDR >> 1 ) == slaveAddress) )
- {
- if ( USIDR & 0x01 )
- {
- overflowState = USI_SLAVE_SEND_DATA;
- }
- else
- {
- overflowState = USI_SLAVE_REQUEST_DATA;
- } // end if
-
- // ack the start frame
- // sets up the USI to pull SDA low and clock one bit (two edges)
- SET_USI_TO_SEND_ACK( );
- }
- else
- {
- SET_USI_TO_TWI_START_CONDITION_MODE( );
- finished = 1;
- }
- break;
-
- // master-read / slave-send: check reply and goto USI_SLAVE_SEND_DATA if OK,
- // else reset USI
- case USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA:
- // Execute request callback for each byte requested, as this is the intended
- // behavior of this library
- USI_REQUEST_CALLBACK();
- if ( USIDR )
- {
- // if NACK, the master does not want more data
- SET_USI_TO_TWI_START_CONDITION_MODE( );
- finished = 1;
- break;
- }
- // from here we just drop straight into USI_SLAVE_SEND_DATA if the
- // master sent an ACK
-
- // copy data from buffer to USIDR and set USI to shift byte
- // next USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA
- case USI_SLAVE_SEND_DATA:
- // Get data from Buffer
- if ( txCount )
- {
- USIDR = txBuf[ txTail ];
- txTail = ( txTail + 1 ) & TWI_TX_BUFFER_MASK;
- txCount--;
-
- overflowState = USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA;
- SET_USI_TO_SEND_DATA( );
- }
- else
- {
- // the buffer is empty
- SET_USI_TO_READ_ACK( ); // This might be neccessary sometimes see http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=805227#805227
- SET_USI_TO_TWI_START_CONDITION_MODE( );
- } // end if
- break;
-
- // set USI to sample reply from master
- // next USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA
- case USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA:
- overflowState = USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA;
- SET_USI_TO_READ_ACK( );
- break;
-
- // master-send / slave-receive: set USI to sample data from master, next
- // USI_SLAVE_GET_DATA_AND_SEND_ACK
- case USI_SLAVE_REQUEST_DATA:
- overflowState = USI_SLAVE_GET_DATA_AND_SEND_ACK;
- SET_USI_TO_READ_DATA( );
-
- // with the SET_USI_TO_READ_DATA() macro call above, the USI has
- // been setup to catch the next byte if the master sends one.
- // while that's going on, look for a stop condition here which
- // is when the SDA line goes high after the SCL line;
-
- // wait until SCL goes high
- while ( ! ( ( usi_pins = PIN_USI & USI_PINS_SCL_SDA ) & USI_PINS_SCL ) );
-
- // if SDA line was high at SCL edge, then not a stop condition
- if ( usi_pins & USI_PINS_SDA )
- break;
-
- // wait until SCL goes low or SDA goes high
- while ( ( usi_pins = PIN_USI & USI_PINS_SCL_SDA ) == USI_PINS_SCL );
-
- // if both SCL and SDA are high, then stop condition occurred
- if ( usi_pins == USI_PINS_SCL_SDA )
- {
- USI_RECEIVE_CALLBACK();
- SET_USI_TO_TWI_START_CONDITION_MODE( );
- finished = 1;
- }
-
- break;
-
- // copy data from USIDR and send ACK
- // next USI_SLAVE_REQUEST_DATA
- case USI_SLAVE_GET_DATA_AND_SEND_ACK:
- // put data into buffer
- // check buffer size
- if ( rxCount < TWI_RX_BUFFER_SIZE )
- {
- rxBuf[ rxHead ] = USIDR;
- rxHead = ( rxHead + 1 ) & TWI_RX_BUFFER_MASK;
- rxCount++;
- } else {
- // overrun
- // drop data
- }
- // next USI_SLAVE_REQUEST_DATA
- overflowState = USI_SLAVE_REQUEST_DATA;
- SET_USI_TO_SEND_ACK( );
- break;
-
- } // end switch
-
- if (finished)
- {
- //no longer in valid i2c transaction
- in_transaction = 0;
- // restore the sleep enable bit
- // note that this allows sleep -- it does not cause sleep
- MCUCR |= sleep_enable_bit;
- }
-
- // no need to restore the SREG. The compiler does this automatically when using the
- // ISR construct without modifying attributes.
-
- // The compiler automatically uses an RETI instruction to return when using the
- // ISR construct without modifying attributes.
-
-} // end ISR( USI_OVERFLOW_VECTOR )