Subversion Repositories HomeAutomation

Rev

Blame | Last modification | View Log | SVN | RSS feed

  1. /*****************************************************************************
  2. *
  3. * File              TWI_Master.c compiled with gcc
  4. * Date              Dec 2, 2008
  5. * Source            Modified from AVR315 - TWI Master Implementation
  6. * Supported devices : All devices with a TWI module can be used.
  7. *                     The example is written for the ATmega168. Requires 4MHz clock.
  8. *
  9. * Description       : This is a sample driver for the TWI hardware modules.
  10. *                     It is interrupt driven. All functionality is controlled through
  11. *                     passing information to and from functions.
  12. *Note: Error checking is implemented by setting lastTransOK to false in the TWI_statusReg.
  13. *   The transceiver state can be read by calling TWI_Get_State_Info to read the TWI_state
  14. *   to know in what state the failure occurred.
  15. * 12/19/08  Added Random (Memory) read function. Requires repeated Start without
  16. *               Stop read function. -jkl
  17. * 5/3/09    Revised to allow Random Read with more than one address byte. -jkl
  18. *
  19. ****************************************************************************/
  20.  
  21. #include <avr/interrupt.h>
  22. #include <avr/io.h>
  23. #include "TWI_Master.h"
  24.  
  25.  
  26. static unsigned char TWI_buf[ TWI_BUFFER_SIZE ];    // Transceiver buffer
  27. static unsigned char TWI_msgSize;                   // Number of bytes to be transmitted.
  28. static unsigned char SavedMsgSize;                   // For multiple memory reads.
  29. static unsigned char TWI_state = TWI_NO_STATE;      // State byte. Default set to TWI_NO_STATE.
  30.  
  31. void TWI_Start_Transceiver( void );
  32.  
  33. union TWI_statusReg TWI_statusReg = {0};            // TWI_statusReg is defined in TWI_Master.h
  34.  
  35. /****************************************************************************
  36. Call this function to set up the TWI master to its initial standby state.
  37. Remember to enable interrupts from the main application after initializing the TWI.
  38. Requires 4MHz clock rate.
  39. ****************************************************************************/
  40. void TWI_Master_Initialise(void)
  41. {
  42.   TWBR = TWI_TWBR;                                  // Set bit rate register (Baudrate). Defined in header file.
  43. // TWSR = TWI_TWPS;                                  // Not used. Driver presumes prescaler to be 00.
  44.   TWDR = 0xFF;                                      // Default content = SDA released.
  45.   TWCR = (1<<TWEN)|                                 // Enable TWI-interface and release TWI pins.
  46.          (0<<TWIE)|(0<<TWINT)|                      // Disable Interupt.
  47.          (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // No Signal requests.
  48.          (0<<TWWC);                                 //
  49. }    
  50.    
  51. /****************************************************************************
  52. Call this function to test if the TWI_ISR is busy transmitting.
  53. ****************************************************************************/
  54. unsigned char TWI_Transceiver_Busy( void )
  55. {
  56.   return ( TWCR & (1<<TWIE) );                  // IF TWI Interrupt is enabled then the Transceiver is busy
  57. }
  58.  
  59. /****************************************************************************
  60. Call this function to fetch the state information of the previous operation.
  61. The function will hold execution (loop) until the TWI_ISR has completed with
  62. the previous operation. If there was an error, then the function will return
  63. the TWI State code.
  64. ****************************************************************************/
  65. unsigned char TWI_Get_State_Info( void )
  66. {
  67.   while ( TWI_Transceiver_Busy() );             // Wait until TWI has completed the transmission.
  68.   return ( TWI_state );                         // Return error state.
  69. }
  70.  
  71. /****************************************************************************
  72. Call this function to perform a random read. That is, a starting memory address
  73. is written, a second START is sent after receiving ACK, the slave address is re-
  74. transmitted with the read bit set, and multiple bytes are read from memory. This
  75. function works by setting the TWI_statusReg.memRead bit and calling the
  76. TWI_Start_Read_Write function. The ISR handles the repeated start.
  77. -- 5/3/09 - added addrLen argument.
  78. ****************************************************************************/
  79. void TWI_Start_Random_Read( unsigned char *msg, unsigned char msgSize, unsigned char addrLen )
  80. {
  81.     msg[0] &= ~(TRUE<<TWI_READ_BIT);    // Be sure read/write bit is clear (write) regardless.
  82.     SavedMsgSize = msgSize;             // Save msgSize - it'll be restored in the ISR
  83.     TWI_statusReg.memRead = TRUE;       // Flag memory read
  84.     TWI_Start_Read_Write( msg, addrLen );       // Set size for initial call.
  85. }
  86. /****************************************************************************
  87. Call this function to send a prepared message. The first byte must contain the
  88. slave address and the read/write bit. Consecutive bytes contain the data to be
  89. sent, or empty locations for data to be read from the slave. Also include how
  90. many bytes should be sent/read including the address byte.The function
  91. will hold execution (loop) until the TWI_ISR has completed with the previous
  92. operation, then initialize the next operation and return.
  93. ****************************************************************************/
  94. void TWI_Start_Read_Write( unsigned char *msg, unsigned char msgSize )
  95. {
  96.   unsigned char temp;
  97.  
  98.   while ( TWI_Transceiver_Busy() );              // Wait until TWI is ready for next transmission.
  99.     TWI_msgSize = msgSize;                        // Number of data to transmit.                      
  100.   TWI_buf[0]  = msg[0];                          // Store slave address with R/W setting.
  101.   if (!( msg[0] & (TRUE<<TWI_READ_BIT) ))       // If it is a write operation, then also copy data.
  102.   {
  103.     for ( temp = 1; temp < msgSize; temp++ )
  104.       TWI_buf[ temp ] = msg[ temp ];
  105.   }
  106.   //TWI_statusReg.all = 0;
  107.   TWI_statusReg.lastTransOK = FALSE;            //  clear OK bit
  108.   TWI_state         = TWI_NO_STATE ;
  109.  
  110.   TWCR = (1<<TWEN)|                             // TWI Interface enabled.
  111.          (1<<TWIE)|(1<<TWINT)|                  // Enable TWI Interupt and clear the flag.
  112.          (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|       // Initiate a START condition.
  113.          (0<<TWWC);                            
  114. }
  115.  
  116. /****************************************************************************
  117. Call this function to resend the last message. The driver will reuse the data
  118. previously put in the transceiver buffers. The function will hold execution
  119. (loop) until the TWI_ISR has completed with the previous operation,
  120. then initialize the next operation and return.
  121. ****************************************************************************/
  122. void TWI_Start_Transceiver( void )
  123. {
  124.   while ( TWI_Transceiver_Busy() );             // Wait until TWI is ready for next transmission.
  125.     //TWI_statusReg.all = 0;
  126.   TWI_statusReg.lastTransOK = FALSE;            // can't clear all bits      
  127.   TWI_state         = TWI_NO_STATE ;
  128.   TWCR = (1<<TWEN)|                             // TWI Interface enabled.
  129.          (1<<TWIE)|(1<<TWINT)|                  // Enable TWI Interupt and clear the flag.
  130.          (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|       // Initiate a START condition.
  131.          (0<<TWWC);                             //
  132. }
  133.  
  134. /****************************************************************************
  135. Call this function to read out the requested data from the TWI transceiver buffer.
  136. I.e. first call TWI_Start_Transceiver to send a request for data to the slave.
  137. Then Run this function to collect the data when they have arrived. Include a
  138. pointer to where to place the data and the number of bytes requested (including
  139. the address field) in the function call. The function will hold execution (loop)
  140. until the TWI_ISR has completed with the previous operation, before reading out
  141. the data and returning. If there was an error in the previous transmission the
  142. function will return the TWI error code.
  143. ****************************************************************************/
  144. unsigned char TWI_Read_Data_From_Buffer( unsigned char *msg, unsigned char msgSize )
  145. {
  146.   unsigned char i;
  147.  
  148.   while ( TWI_Transceiver_Busy() );             // Wait until TWI is ready for next transmission.
  149.  
  150.   if( TWI_statusReg.lastTransOK )               // Last transmission competed successfully.              
  151.   {                                            
  152.     for ( i=0; i<msgSize; i++ )                 // Copy data from Transceiver buffer.
  153.     {
  154.       msg[ i ] = TWI_buf[ i ];
  155.     }
  156.     //return (TRUE);
  157.   }
  158.   return( TWI_statusReg.lastTransOK );         //!!!!!!!!!!!Fix This !!!!!!!!!!!!!!!!!!  
  159.   // return (FALSE);
  160. }
  161.  
  162. // ********** Interrupt Handlers ********** //
  163. /****************************************************************************
  164. This function is the Interrupt Service Routine (ISR), and called when the TWI
  165. interrupt is triggered; that is whenever a TWI event has occurred. This function
  166. should not be called directly from the main application.
  167. Notes: (12/2/08  -jkl)
  168. - Setup of Interrupt vector is changed to the gcc method.
  169. - The TWSR is masked in case a value is in the prescaler (TWI_TWPS).
  170. - TWSR is also masked before it is stored to TWI_state.
  171. Notes (12/19/08 -jkl)
  172. - Provides a dual start without stop read mode for Memory.
  173.     To use it, set the Dual Start Bit in the TWI_statusReg. More????
  174.     Need to set size to 2, then without sending a STOP:
  175. - set READ bit in Slave Address
  176. - set size to correct value
  177. - clear memRead bit in status reg
  178. - send a new START sequence - everything else should work ;)}
  179.  
  180. ****************************************************************************/
  181.  
  182. ISR(TWI_vect)
  183. {
  184.   static unsigned char TWI_bufPtr;
  185.  
  186.   switch (TWSR & 0xf8)          // Mask off prescaler bits
  187.   {
  188.     case TWI_START:             // START has been transmitted  
  189.     case TWI_REP_START:         // Repeated START has been transmitted
  190.       TWI_bufPtr = 0;                                     // Set buffer pointer to the TWI Address location
  191.     case TWI_MTX_ADR_ACK:       // SLA+W has been tramsmitted and ACK received
  192.     case TWI_MTX_DATA_ACK:      // Data byte has been tramsmitted and ACK received
  193.       if (TWI_bufPtr < TWI_msgSize)
  194.       {
  195.         TWDR = TWI_buf[TWI_bufPtr++];
  196.         TWCR = (1<<TWEN)|                                 // TWI Interface enabled
  197.                (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to send byte
  198.                (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           //
  199.                (0<<TWWC);                                 //  
  200.       }else                    // Send STOP after last byte
  201.       {
  202.         if (TWI_statusReg.memRead)                  // memory read with dual start
  203.         {
  204.             TWI_buf[0] |= (TRUE<<TWI_READ_BIT); // set READ bit in Slave Address
  205.             TWI_msgSize =   SavedMsgSize;           // set size to correct value
  206.             TWI_statusReg.all = 0;                  // clear memRead bit in status reg
  207.                     // send a new START sequence - everything else should work ;)}
  208.             TWI_state         = TWI_NO_STATE ;
  209.             TWCR = (1<<TWEN)|                             // TWI Interface enabled.
  210.                 (1<<TWIE)|(1<<TWINT)|                  // Enable TWI Interupt and clear the flag.
  211.                 (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|       // Initiate a START condition.
  212.                 (0<<TWWC);    
  213.         }
  214.         else
  215.         {
  216.             TWI_statusReg.lastTransOK = TRUE;                 // Set status bits to completed successfully.
  217.             TWCR = (1<<TWEN)|                                 // TWI Interface enabled
  218.                (0<<TWIE)|(1<<TWINT)|                      // Disable TWI Interrupt and clear the flag
  219.                (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|           // Initiate a STOP condition.
  220.                (0<<TWWC);                      
  221.         }
  222.       }
  223.       break;
  224.     case TWI_MRX_DATA_ACK:      // Data byte has been received and ACK tramsmitted
  225.       TWI_buf[TWI_bufPtr++] = TWDR;
  226.     case TWI_MRX_ADR_ACK:       // SLA+R has been tramsmitted and ACK received
  227.       if (TWI_bufPtr < (TWI_msgSize-1) )                  // Detect the last byte to NACK it.
  228.       {
  229.         TWCR = (1<<TWEN)|                                 // TWI Interface enabled
  230.                (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to read next byte
  231.                (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Send ACK after reception
  232.                (0<<TWWC);                                 //  
  233.       }else                    // Send NACK after next reception
  234.       {
  235.         TWCR = (1<<TWEN)|                                 // TWI Interface enabled
  236.                (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to read next byte
  237.                (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Send NACK after reception
  238.                (0<<TWWC);                                 //
  239.       }    
  240.       break;
  241.     case TWI_MRX_DATA_NACK:     // Data byte has been received and NACK tramsmitted
  242.       TWI_buf[TWI_bufPtr] = TWDR;
  243.       TWI_statusReg.lastTransOK = TRUE;                 // Set status bits to completed successfully.
  244.       TWCR = (1<<TWEN)|                                 // TWI Interface enabled
  245.              (0<<TWIE)|(1<<TWINT)|                      // Disable TWI Interrupt and clear the flag
  246.              (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|           // Initiate a STOP condition.
  247.              (0<<TWWC);                                 //
  248.       break;      
  249.     case TWI_ARB_LOST:          // Arbitration lost
  250.       TWCR = (1<<TWEN)|                                 // TWI Interface enabled
  251.              (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag
  252.              (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|           // Initiate a (RE)START condition.
  253.              (0<<TWWC);                                 //
  254.       break;
  255.     case TWI_MTX_ADR_NACK:      // SLA+W has been tramsmitted and NACK received
  256.     case TWI_MRX_ADR_NACK:      // SLA+R has been tramsmitted and NACK received    
  257.     case TWI_MTX_DATA_NACK:     // Data byte has been tramsmitted and NACK received
  258. //    case TWI_NO_STATE              // No relevant state information available; TWINT = �0�
  259.     case TWI_BUS_ERROR:         // Bus error due to an illegal START or STOP condition
  260.     default:    
  261.       TWI_state = TWSR & 0xf8;                          // Store TWSR and automatically sets clears noErrors bit.
  262.                                                         // Reset TWI Interface
  263.       TWCR = (1<<TWEN)|                                 // Enable TWI-interface and release TWI pins
  264.              (0<<TWIE)|(0<<TWINT)|                      // Disable Interupt
  265.              (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // No Signal requests
  266.              (0<<TWWC);                                 //
  267.   }
  268. }
  269.