Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2194 - 1
/*****************************************************************************
2
*
3
* Atmel Corporation
4
*
5
* File              : TWI_Slave.c
6
* Compiler          : IAR EWAAVR 2.28a/3.10c
7
* Revision          : $Revision: 2475 $
8
* Date              : $Date: 2007-09-20 12:00:43 +0200 (to, 20 sep 2007) $
9
* Updated by        : $Author: mlarsson $
10
*
11
* Support mail      : avr@atmel.com
12
*
13
* Supported devices : All devices with a TWI module can be used.
14
*                     The example is written for the ATmega16
15
*
16
* AppNote           : AVR311 - TWI Slave Implementation
17
*
18
* Description       : This is sample driver to AVRs TWI module.
19
*                     It is interupt driveren. All functionality is controlled through
20
*                     passing information to and from functions. Se main.c for samples
21
*                     of how to use the driver.
22
*
23
****************************************************************************/
24
/*! \page MISRA
25
 *
26
 * General disabling of MISRA rules:
27
 * * (MISRA C rule 1) compiler is configured to allow extensions
28
 * * (MISRA C rule 111) bit fields shall only be defined to be of type unsigned int or signed int
29
 * * (MISRA C rule 37) bitwise operations shall not be performed on signed integer types
30
 * As it does not work well with 8bit architecture and/or IAR
31
 
32
 * Other disabled MISRA rules
33
 * * (MISRA C rule 109) use of union - overlapping storage shall not be used
34
 * * (MISRA C rule 61) every non-empty case clause in a switch statement shall be terminated with a break statement
35
*/
36
 
37
#if defined(__ICCAVR__)
38
#include "ioavr.h"              
39
#include "inavr.h"
40
#else
41
#include <avr/io.h>
42
#include <avr/interrupt.h>
43
#endif
44
#include "twi_slave.h"
45
 
46
// Emulate GCC ISR() statement in IAR
47
#if defined(__ICCAVR__)
48
#define PRAGMA(x) _Pragma( #x )
49
#define ISR(vec) PRAGMA( vector=vec ) __interrupt void handler_##vec(void)
50
#endif 
51
 
52
static unsigned char TWI_buf[TWI_BUFFER_SIZE];     // Transceiver buffer. Set the size in the header file
53
static unsigned char TWI_msgSize  = 0;             // Number of bytes to be transmitted.
54
static unsigned char TWI_state    = TWI_NO_STATE;  // State byte. Default set to TWI_NO_STATE.
55
 
56
// This is true when the TWI is in the middle of a transfer
57
// and set to false when all bytes have been transmitted/received
58
// Also used to determine how deep we can sleep.
59
static volatile unsigned char TWI_busy = 0;
60
 
61
union TWI_statusReg_t TWI_statusReg = {0};           // TWI_statusReg is defined in TWI_Slave.h
62
 
63
/****************************************************************************
64
Call this function to set up the TWI slave to its initial standby state.
65
Remember to enable interrupts from the main application after initializing the TWI.
66
Pass both the slave address and the requrements for triggering on a general call in the
67
same byte. Use e.g. this notation when calling this function:
68
TWI_Slave_Initialise( (TWI_slaveAddress<<TWI_ADR_BITS) | (TRUE<<TWI_GEN_BIT) );
69
The TWI module is configured to NACK on any requests. Use a TWI_Start_Transceiver function to
70
start the TWI.
71
****************************************************************************/
72
void twi_slave_init( unsigned char TWI_ownAddress )
73
{
74
  TWAR = TWI_ownAddress;                            // Set own TWI slave address. Accept TWI General Calls.
75
  TWCR = (1<<TWEN)|                                 // Enable TWI-interface and release TWI pins.
76
         (0<<TWIE)|(0<<TWINT)|                      // Disable TWI Interupt.
77
         (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Do not ACK on any requests, yet.
78
         (0<<TWWC);                                 //
79
  TWI_busy = 0;
80
}    
81
 
82
/****************************************************************************
83
Call this function to test if the TWI_ISR is busy transmitting.
84
****************************************************************************/
85
unsigned char twi_slave_busy( void )
86
{
87
  return TWI_busy;
88
}
89
 
90
/****************************************************************************
91
Call this function to fetch the state information of the previous operation. The function will hold execution (loop)
92
until the TWI_ISR has completed with the previous operation. If there was an error, then the function
93
will return the TWI State code.
94
****************************************************************************/
95
unsigned char twi_slave_get_status( void )
96
{
97
  while ( twi_slave_busy() ) {}             // Wait until TWI has completed the transmission.
98
  return ( TWI_state );                         // Return error state. 
99
}
100
 
101
/****************************************************************************
102
Call this function to send a prepared message, or start the Transceiver for reception. Include
103
a pointer to the data to be sent if a SLA+W is received. The data will be copied to the TWI buffer.
104
Also include how many bytes that should be sent. Note that unlike the similar Master function, the
105
Address byte is not included in the message buffers.
106
The function will hold execution (loop) until the TWI_ISR has completed with the previous operation,
107
then initialize the next operation and return.
108
****************************************************************************/
109
void twi_slave_start_with_data( unsigned char *msg, unsigned char msgSize )
110
{
111
  unsigned char temp;
112
 
113
  while ( twi_slave_busy() ) {}             // Wait until TWI is ready for next transmission.
114
 
115
  TWI_msgSize = msgSize;                        // Number of data to transmit.
116
  for ( temp = 0; temp < msgSize; temp++ )      // Copy data that may be transmitted if the TWI Master requests data.
117
  {
118
    TWI_buf[ temp ] = msg[ temp ];
119
  }
120
  TWI_statusReg.all = 0;      
121
  TWI_state         = TWI_NO_STATE ;
122
  TWCR = (1<<TWEN)|                             // TWI Interface enabled.
123
         (1<<TWIE)|(1<<TWINT)|                  // Enable TWI Interupt and clear the flag.
124
         (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|       // Prepare to ACK next time the Slave is addressed.
125
         (0<<TWWC);                             //
126
  TWI_busy = 1;
127
}
128
 
129
/****************************************************************************
130
Call this function to start the Transceiver without specifing new transmission data. Useful for restarting
131
a transmission, or just starting the transceiver for reception. The driver will reuse the data previously put
132
in the transceiver buffers. The function will hold execution (loop) until the TWI_ISR has completed with the
133
previous operation, then initialize the next operation and return.
134
****************************************************************************/
135
void twi_slave_start( void )
136
{
137
  while ( twi_slave_busy() ) {}             // Wait until TWI is ready for next transmission.
138
  TWI_statusReg.all = 0;      
139
  TWI_state         = TWI_NO_STATE ;
140
  TWCR = (1<<TWEN)|                             // TWI Interface enabled.
141
         (1<<TWIE)|(1<<TWINT)|                  // Enable TWI Interupt and clear the flag.
142
         (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|       // Prepare to ACK next time the Slave is addressed.
143
         (0<<TWWC);                             //
144
  TWI_busy = 0;
145
}
146
/****************************************************************************
147
Call this function to read out the received data from the TWI transceiver buffer. I.e. first call
148
TWI_Start_Transceiver to get the TWI Transceiver to fetch data. Then Run this function to collect the
149
data when they have arrived. Include a pointer to where to place the data and the number of bytes
150
to fetch in the function call. The function will hold execution (loop) until the TWI_ISR has completed
151
with the previous operation, before reading out the data and returning.
152
If there was an error in the previous transmission the function will return the TWI State code.
153
****************************************************************************/
154
unsigned char twi_slave_get_data( unsigned char *msg, unsigned char msgSize )
155
{
156
  unsigned char i;
157
 
158
  while ( twi_slave_busy() ) {}             // Wait until TWI is ready for next transmission.
159
 
160
  if( TWI_statusReg.lastTransOK )               // Last transmission completed successfully.              
161
  {                                            
162
    for ( i=0; i<msgSize; i++ )                 // Copy data from Transceiver buffer.
163
    {
164
      msg[ i ] = TWI_buf[ i ];
165
    }
166
    TWI_statusReg.RxDataInBuf = FALSE;          // Slave Receive data has been read from buffer.
167
  }
168
  return( TWI_statusReg.lastTransOK );                                  
169
}
170
 
171
 
172
// ********** Interrupt Handlers ********** //
173
/****************************************************************************
174
This function is the Interrupt Service Routine (ISR), and called when the TWI interrupt is triggered;
175
that is whenever a TWI event has occurred. This function should not be called directly from the main
176
application.
177
****************************************************************************/
178
ISR(TWI_vect)
179
{
180
  static unsigned char TWI_bufPtr;
181
 
182
  switch (TWSR)
183
  {
184
    case TWI_STX_ADR_ACK:            // Own SLA+R has been received; ACK has been returned
185
//    case TWI_STX_ADR_ACK_M_ARB_LOST: // Arbitration lost in SLA+R/W as Master; own SLA+R has been received; ACK has been returned
186
      TWI_bufPtr   = 0;                                 // Set buffer pointer to first data location
187
    case TWI_STX_DATA_ACK:           // Data byte in TWDR has been transmitted; ACK has been received
188
      TWDR = TWI_buf[TWI_bufPtr++];
189
      TWCR = (1<<TWEN)|                                 // TWI Interface enabled
190
             (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to send byte
191
             (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // 
192
             (0<<TWWC);                                 //
193
      TWI_busy = 1;
194
      break;
195
    case TWI_STX_DATA_NACK:          // Data byte in TWDR has been transmitted; NACK has been received. 
196
                                     // I.e. this could be the end of the transmission.
197
      if (TWI_bufPtr == TWI_msgSize) // Have we transceived all expected data?
198
      {
199
        TWI_statusReg.lastTransOK = TRUE;               // Set status bits to completed successfully. 
200
      }
201
      else                          // Master has sent a NACK before all data where sent.
202
      {
203
        TWI_state = TWSR;                               // Store TWI State as errormessage.      
204
      }        
205
 
206
      TWCR = (1<<TWEN)|                                 // Enable TWI-interface and release TWI pins
207
             (1<<TWIE)|(1<<TWINT)|                      // Keep interrupt enabled and clear the flag
208
             (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Answer on next address match
209
             (0<<TWWC);                                 //
210
 
211
      TWI_busy = 0;   // Transmit is finished, we are not busy anymore
212
      break;    
213
    case TWI_SRX_GEN_ACK:            // General call address has been received; ACK has been returned
214
//    case TWI_SRX_GEN_ACK_M_ARB_LOST: // Arbitration lost in SLA+R/W as Master; General call address has been received; ACK has been returned
215
      TWI_statusReg.genAddressCall = TRUE;
216
    case TWI_SRX_ADR_ACK:            // Own SLA+W has been received ACK has been returned
217
//    case TWI_SRX_ADR_ACK_M_ARB_LOST: // Arbitration lost in SLA+R/W as Master; own SLA+W has been received; ACK has been returned    
218
                                                        // Dont need to clear TWI_S_statusRegister.generalAddressCall due to that it is the default state.
219
      TWI_statusReg.RxDataInBuf = TRUE;      
220
      TWI_bufPtr   = 0;                                 // Set buffer pointer to first data location
221
 
222
                                                        // Reset the TWI Interupt to wait for a new event.
223
      TWCR = (1<<TWEN)|                                 // TWI Interface enabled
224
             (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to send byte
225
             (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Expect ACK on this transmission
226
             (0<<TWWC);  
227
      TWI_busy = 1;
228
 
229
      break;
230
    case TWI_SRX_ADR_DATA_ACK:       // Previously addressed with own SLA+W; data has been received; ACK has been returned
231
    case TWI_SRX_GEN_DATA_ACK:       // Previously addressed with general call; data has been received; ACK has been returned
232
      // TODO: What is this? Seems to be no bounds checking!
233
      TWI_buf[TWI_bufPtr++]     = TWDR;
234
      TWI_statusReg.lastTransOK = TRUE;                 // Set flag transmission successfull.       
235
                                                        // Reset the TWI Interupt to wait for a new event.
236
      TWCR = (1<<TWEN)|                                 // TWI Interface enabled
237
             (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to send byte
238
             (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Send ACK after next reception
239
             (0<<TWWC);                                 // 
240
      TWI_busy = 1;
241
      break;
242
    case TWI_SRX_STOP_RESTART:       // A STOP condition or repeated START condition has been received while still addressed as Slave    
243
                                                        // Enter not addressed mode and listen to address match
244
      TWCR = (1<<TWEN)|                                 // Enable TWI-interface and release TWI pins
245
             (1<<TWIE)|(1<<TWINT)|                      // Enable interrupt and clear the flag
246
             (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Wait for new address match
247
             (0<<TWWC);                                 //
248
 
249
      TWI_busy = 0;  // We are waiting for a new address match, so we are not busy
250
 
251
      break;          
252
    case TWI_SRX_ADR_DATA_NACK:      // Previously addressed with own SLA+W; data has been received; NOT ACK has been returned
253
    case TWI_SRX_GEN_DATA_NACK:      // Previously addressed with general call; data has been received; NOT ACK has been returned
254
    case TWI_STX_DATA_ACK_LAST_BYTE: // Last data byte in TWDR has been transmitted (TWEA = �0�); ACK has been received
255
//    case TWI_NO_STATE              // No relevant state information available; TWINT = �0�
256
    case TWI_BUS_ERROR:         // Bus error due to an illegal START or STOP condition
257
      TWI_state = TWSR;                 //Store TWI State as errormessage, operation also clears noErrors bit
258
      TWCR =   (1<<TWSTO)|(1<<TWINT);   //Recover from TWI_BUS_ERROR, this will release the SDA and SCL pins thus enabling other devices to use the bus
259
      break;
260
    default:    
261
      TWI_state = TWSR;                                 // Store TWI State as errormessage, operation also clears the Success bit.      
262
      TWCR = (1<<TWEN)|                                 // Enable TWI-interface and release TWI pins
263
             (1<<TWIE)|(1<<TWINT)|                      // Keep interrupt enabled and clear the flag
264
             (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Acknowledge on any new requests.
265
             (0<<TWWC);                                 //
266
 
267
      TWI_busy = 0; // Unknown status, so we wait for a new address match that might be something we can handle
268
  }
269
}
270
 
271
/*
272
void example(){
273
        unsigned char messageBuf[TWI_BUFFER_SIZE];
274
  unsigned char TWI_slaveAddress;
275
 
276
  // LED feedback port - connect port B to the STK500 LEDS
277
  DDRB  = 0xFF; // Set to ouput
278
  PORTB = 0x55; // Startup pattern
279
 
280
  // Own TWI slave address
281
  TWI_slaveAddress = 0x10;
282
 
283
  // Initialise TWI module for slave operation. Include address and/or enable General Call.
284
  TWI_Slave_Initialise( (unsigned char)((TWI_slaveAddress<<TWI_ADR_BITS) | (TRUE<<TWI_GEN_BIT) ));
285
 
286
  SEI();
287
 
288
  // Start the TWI transceiver to enable reseption of the first command from the TWI Master.
289
  TWI_Start_Transceiver();
290
 
291
  // This example is made to work together with the AVR315 TWI Master application note. In adition to connecting the TWI
292
  // pins, also connect PORTB to the LEDS. The code reads a message as a TWI slave and acts according to if it is a
293
  // general call, or an address call. If it is an address call, then the first byte is considered a command byte and
294
  // it then responds differently according to the commands.
295
 
296
  // This loop runs forever. If the TWI is busy the execution will just continue doing other operations.
297
  for(;;)
298
  {
299
    #ifdef POWER_MANAGEMENT_ENABLED
300
      // Sleep while waiting for TWI transceiver to complete or waiting for new commands.
301
      // If we have data in the buffer, we can't enter sleep because we have to take care
302
      // of it first.
303
      // If the transceiver is busy, we enter idle mode because it will wake up by all TWI
304
      // interrupts.
305
      // If the transceiver not is busy, we can enter power-down mode because next receive
306
      // should be a TWI address match and it wakes the device up from all sleep modes.
307
      if( ! TWI_statusReg.RxDataInBuf ) {
308
        if(TWI_Transceiver_Busy()) {
309
          MCUCR = (1<<SE)|(0<<SM2)|(0<<SM1)|(0<<SM0); // Enable sleep with idle mode
310
        } else {
311
          MCUCR = (1<<SE)|(0<<SM2)|(1<<SM1)|(0<<SM0); // Enable sleep with power-down mode
312
        }
313
        SLEEP();
314
      } else {
315
        NOP(); // There is data in the buffer, code below takes care of it.
316
      }
317
    #else // No power management
318
      // Here you can add your own code that should be run while waiting for the TWI to finish    
319
      NOP(); // Put own code here.
320
    #endif
321
 
322
 
323
    // Check if the TWI Transceiver has completed an operation.
324
    if ( ! TWI_Transceiver_Busy() )                              
325
    {
326
      // Check if the last operation was successful
327
      if ( TWI_statusReg.lastTransOK )
328
      {
329
        // Check if the last operation was a reception
330
        if ( TWI_statusReg.RxDataInBuf )
331
        {
332
          TWI_Get_Data_From_Transceiver(messageBuf, 2);        
333
          // Check if the last operation was a reception as General Call        
334
          if ( TWI_statusReg.genAddressCall )
335
          {
336
            // Put data received out to PORTB as an example.        
337
            PORTB = messageBuf[0];
338
          }              
339
          else // Ends up here if the last operation was a reception as Slave Address Match  
340
          {
341
            // Example of how to interpret a command and respond.
342
 
343
            // TWI_CMD_MASTER_WRITE stores the data to PORTB
344
            if (messageBuf[0] == TWI_CMD_MASTER_WRITE)
345
            {
346
              PORTB = messageBuf[1];                            
347
            }
348
            // TWI_CMD_MASTER_READ prepares the data from PINB in the transceiver buffer for the TWI master to fetch.
349
            if (messageBuf[0] == TWI_CMD_MASTER_READ)
350
            {
351
              messageBuf[0] = PINB;
352
              TWI_Start_Transceiver_With_Data( messageBuf, 1 );
353
            }
354
          }
355
        }                
356
        else // Ends up here if the last operation was a transmission  
357
        {
358
            NOP(); // Put own code here.
359
        }
360
        // Check if the TWI Transceiver has already been started.
361
        // If not then restart it to prepare it for new receptions.            
362
        if ( ! TWI_Transceiver_Busy() )
363
        {
364
          TWI_Start_Transceiver();
365
        }
366
      }
367
      else // Ends up here if the last operation completed unsuccessfully
368
      {
369
        TWI_Act_On_Failure_In_Last_Transmission( TWI_Get_State_Info() );
370
      }
371
    }
372
  }
373
}*/