cores: Added mega1280
[simavr] / examples / board_i2ctest / avr_twi_master.c
1 /*****************************************************************************\r
2 *\r
3 * Atmel Corporation\r
4 *\r
5 * File              : TWI_Master.c\r
6 * Compiler          : IAR EWAAVR 2.28a/3.10c\r
7 * Revision          : $Revision: 1.13 $\r
8 * Date              : $Date: 24. mai 2004 11:31:20 $\r
9 * Updated by        : $Author: ltwa $\r
10 *\r
11 * Support mail      : avr@atmel.com\r
12 *\r
13 * Supported devices : All devices with a TWI module can be used.\r
14 *                     The example is written for the ATmega16\r
15 *\r
16 * AppNote           : AVR315 - TWI Master Implementation\r
17 *\r
18 * Description       : This is a sample driver for the TWI hardware modules.\r
19 *                     It is interrupt driveren. All functionality is controlled through \r
20 *                     passing information to and from functions. Se main.c for samples\r
21 *                     of how to use the driver.\r
22 *\r
23 *\r
24 ****************************************************************************/\r
25 \r
26 #include <avr/io.h>\r
27 #include <avr/interrupt.h>\r
28 #include "avr_twi_master.h"\r
29 \r
30 //static unsigned char TWI_buf[ TWI_BUFFER_SIZE ];    // Transceiver buffer\r
31 static unsigned char *TWI_buf;\r
32 static unsigned char TWI_msgSize;                   // Number of bytes to be transmitted.\r
33 static unsigned char TWI_sendStop;\r
34 static unsigned char TWI_state = TWI_NO_STATE;      // State byte. Default set to TWI_NO_STATE.\r
35 \r
36 union TWI_statusReg TWI_statusReg = {0};            // TWI_statusReg is defined in TWI_Master.h\r
37 \r
38 /****************************************************************************\r
39 Call this function to set up the TWI master to its initial standby state.\r
40 Remember to enable interrupts from the main application after initializing the TWI.\r
41 ****************************************************************************/\r
42 void TWI_Master_Initialise(void)\r
43 {\r
44   TWBR = TWI_TWBR;                                  // Set bit rate register (Baudrate). Defined in header file.\r
45 // TWSR = TWI_TWPS;                                  // Not used. Driver presumes prescaler to be 00.\r
46   TWDR = 0xFF;                                      // Default content = SDA released.\r
47   TWCR = (1<<TWEN)|                                 // Enable TWI-interface and release TWI pins.\r
48          (0<<TWIE)|(0<<TWINT)|                      // Disable Interupt.\r
49          (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // No Signal requests.\r
50          (0<<TWWC);                                 //\r
51 }    \r
52     \r
53 /****************************************************************************\r
54 Call this function to test if the TWI_ISR is busy transmitting.\r
55 ****************************************************************************/\r
56 unsigned char TWI_Transceiver_Busy( void )\r
57 {\r
58   return ( TWCR & (1<<TWIE) );                  // IF TWI Interrupt is enabled then the Transceiver is busy\r
59 }\r
60 \r
61 /****************************************************************************\r
62 Call this function to fetch the state information of the previous operation. The function will hold execution (loop)\r
63 until the TWI_ISR has completed with the previous operation. If there was an error, then the function \r
64 will return the TWI State code. \r
65 ****************************************************************************/\r
66 unsigned char TWI_Get_State_Info( void )\r
67 {\r
68   while ( TWI_Transceiver_Busy() );             // Wait until TWI has completed the transmission.\r
69   return ( TWI_state );                         // Return error state.\r
70 }\r
71 \r
72 /****************************************************************************\r
73 Call this function to send a prepared message. The first byte must contain the slave address and the\r
74 read/write bit. Consecutive bytes contain the data to be sent, or empty locations for data to be read\r
75 from the slave. Also include how many bytes that should be sent/read including the address byte.\r
76 The function will hold execution (loop) until the TWI_ISR has completed with the previous operation,\r
77 then initialize the next operation and return.\r
78 ****************************************************************************/\r
79 void TWI_Start_Transceiver_With_Data(\r
80                 unsigned char *msg, unsigned char msgSize, unsigned char sendStop )\r
81 {\r
82 //  unsigned char temp;\r
83 \r
84   while ( TWI_Transceiver_Busy() );             // Wait until TWI is ready for next transmission.\r
85 \r
86   TWI_msgSize = msgSize;                        // Number of data to transmit.\r
87   TWI_sendStop = sendStop;\r
88   TWI_buf = msg; // store our current message\r
89   TWI_statusReg.all = 0;      \r
90   TWI_state         = TWI_NO_STATE ;\r
91   TWCR = (1<<TWEN)|                             // TWI Interface enabled.\r
92          (1<<TWIE)|(1<<TWINT)|                  // Enable TWI Interupt and clear the flag.\r
93          (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|       // Initiate a START condition.\r
94          (0<<TWWC);                             //\r
95 }\r
96 \r
97 /****************************************************************************\r
98 Call this function to resend the last message. The driver will reuse the data previously put in the transceiver buffers.\r
99 The function will hold execution (loop) until the TWI_ISR has completed with the previous operation,\r
100 then initialize the next operation and return.\r
101 ****************************************************************************/\r
102 void TWI_Start_Transceiver( void )\r
103 {\r
104   while ( TWI_Transceiver_Busy() );             // Wait until TWI is ready for next transmission.\r
105   TWI_statusReg.all = 0;      \r
106   TWI_state         = TWI_NO_STATE ;\r
107   TWCR = (1<<TWEN)|                             // TWI Interface enabled.\r
108          (1<<TWIE)|(1<<TWINT)|                  // Enable TWI Interupt and clear the flag.\r
109          (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|       // Initiate a START condition.\r
110          (0<<TWWC);                             //\r
111 }\r
112 \r
113 /****************************************************************************\r
114 Call this function to read out the requested data from the TWI transceiver buffer. I.e. first call\r
115 TWI_Start_Transceiver to send a request for data to the slave. Then Run this function to collect the\r
116 data when they have arrived. Include a pointer to where to place the data and the number of bytes\r
117 requested (including the address field) in the function call. The function will hold execution (loop)\r
118 until the TWI_ISR has completed with the previous operation, before reading out the data and returning.\r
119 If there was an error in the previous transmission the function will return the TWI error code.\r
120 ****************************************************************************/\r
121 unsigned char TWI_Get_Data_From_Transceiver( unsigned char *msg, unsigned char msgSize )\r
122 {\r
123   unsigned char i;\r
124 \r
125   while ( TWI_Transceiver_Busy() );             // Wait until TWI is ready for next transmission.\r
126 \r
127   if( TWI_statusReg.lastTransOK )               // Last transmission competed successfully.              \r
128   {                                             \r
129     for ( i=0; i<msgSize; i++ )                 // Copy data from Transceiver buffer.\r
130     {\r
131       msg[ i ] = TWI_buf[ i ];\r
132     }\r
133   }\r
134   return( TWI_statusReg.lastTransOK );                                   \r
135 }\r
136 \r
137 // ********** Interrupt Handlers ********** //\r
138 /****************************************************************************\r
139 This function is the Interrupt Service Routine (ISR), and called when the TWI interrupt is triggered;\r
140 that is whenever a TWI event has occurred. This function should not be called directly from the main\r
141 application.\r
142 ****************************************************************************/\r
143 ISR( TWI_vect )\r
144 {\r
145   static unsigned char TWI_bufPtr;\r
146   \r
147   switch (TWSR)\r
148   {\r
149     case TWI_START:             // START has been transmitted  \r
150     case TWI_REP_START:         // Repeated START has been transmitted\r
151       TWI_bufPtr = 0;                                     // Set buffer pointer to the TWI Address location\r
152     case TWI_MTX_ADR_ACK:       // SLA+W has been tramsmitted and ACK received\r
153     case TWI_MTX_DATA_ACK:      // Data byte has been tramsmitted and ACK received\r
154       if (TWI_bufPtr < TWI_msgSize)\r
155       {\r
156         TWDR = TWI_buf[TWI_bufPtr++];\r
157         TWCR = (1<<TWEN)|                                 // TWI Interface enabled\r
158                (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to send byte\r
159                (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           //\r
160                (0<<TWWC);                                 //  \r
161       }else                    // Send STOP after last byte\r
162       {\r
163         TWI_statusReg.lastTransOK = TRUE;                 // Set status bits to completed successfully.\r
164         if (TWI_sendStop)\r
165                 TWCR = (1<<TWEN)|                                 // TWI Interface enabled\r
166                (0<<TWIE)|(1<<TWINT)|                      // Disable TWI Interrupt and clear the flag\r
167                (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|           // Initiate a STOP condition\r
168                (0<<TWWC);                                 //\r
169         else\r
170                 TWCR = (1<<TWEN)|                                 // TWI Interface enabled\r
171                (0<<TWIE)|(1<<TWINT)|                      // Disable TWI Interrupt and clear the flag\r
172                (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // DO NOT Initiate a STOP condition\r
173                (0<<TWWC);                                 //\r
174       }\r
175       break;\r
176     case TWI_MRX_DATA_ACK:      // Data byte has been received and ACK tramsmitted\r
177       TWI_buf[TWI_bufPtr++] = TWDR;\r
178     case TWI_MRX_ADR_ACK:       // SLA+R has been tramsmitted and ACK received\r
179       if (TWI_bufPtr < (TWI_msgSize-1) )                  // Detect the last byte to NACK it.\r
180       {\r
181         TWCR = (1<<TWEN)|                                 // TWI Interface enabled\r
182                (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to read next byte\r
183                (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Send ACK after reception\r
184                (0<<TWWC);                                 //  \r
185       }else                    // Send NACK after next reception\r
186       {\r
187         TWCR = (1<<TWEN)|                                 // TWI Interface enabled\r
188                (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to read next byte\r
189                (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Send NACK after reception\r
190                (0<<TWWC);                                 // \r
191       }    \r
192       break; \r
193     case TWI_MRX_DATA_NACK:     // Data byte has been received and NACK tramsmitted\r
194       TWI_buf[TWI_bufPtr] = TWDR;\r
195       TWI_statusReg.lastTransOK = TRUE;                 // Set status bits to completed successfully. \r
196       TWCR = (1<<TWEN)|                                 // TWI Interface enabled\r
197              (0<<TWIE)|(1<<TWINT)|                      // Disable TWI Interrupt and clear the flag\r
198              (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|           // Initiate a STOP condition.\r
199              (0<<TWWC);                                 //\r
200       break;      \r
201     case TWI_ARB_LOST:          // Arbitration lost\r
202       TWCR = (1<<TWEN)|                                 // TWI Interface enabled\r
203              (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag\r
204              (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|           // Initiate a (RE)START condition.\r
205              (0<<TWWC);                                 //\r
206       break;\r
207     case TWI_MTX_ADR_NACK:      // SLA+W has been tramsmitted and NACK received\r
208     case TWI_MRX_ADR_NACK:      // SLA+R has been tramsmitted and NACK received    \r
209     case TWI_MTX_DATA_NACK:     // Data byte has been tramsmitted and NACK received\r
210 //    case TWI_NO_STATE              // No relevant state information available; TWINT = �0�\r
211     case TWI_BUS_ERROR:         // Bus error due to an illegal START or STOP condition\r
212     default:     \r
213       TWI_state = TWSR;                                 // Store TWSR and automatically sets clears noErrors bit.\r
214                                                         // Reset TWI Interface\r
215       TWCR = (1<<TWEN)|                                 // Enable TWI-interface and release TWI pins\r
216              (0<<TWIE)|(0<<TWINT)|                      // Disable Interupt\r
217              (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // No Signal requests\r
218              (0<<TWWC);                                 //\r
219   }\r
220 }\r