Project

General

Profile

Revision 78

Added by Kevin Woo over 16 years ago

I2C is documented. This is a pre-merge commit.

View differences:

branches/i2c/code/projects/libdragonfly/purgatory/i2c.h
1
/**
2
 * @file i2c.h
3
 * @brief Definitions for i2c.
4
 * 
5
 * Definitions for i2c. KEVIN - what is i2c?
6
 *
7
 * @author CMU Robotics Club
8
 **/
9

  
10

  
11
#ifndef _I2C_H_
12
#define _I2C_H_
13

  
14
#include <stddef.h>
15

  
16
// for i2c_byte coming from charge board
17
//I2C Message Codes
18
#define I2C_MSG_ACKNOWLEDGE       'A'
19
#define I2C_MSG_BATTERY_CHARGING  'C'
20
#define I2C_MSG_DATA              'D'
21
#define I2C_MSG_CONTACT_ERROR     'E'
22
#define I2C_MSG_BATTERY_FULL      'F'
23
#define I2C_MSG_NO_CONTACT        'N'
24
#define I2C_MSG_REQUEST_DATA      'R'
25
#define I2C_MSG_GO_TO_SLEEP       'Y'
26
#define I2C_MSG_ENTERING_SLEEP    'Z'
27

  
28
char i2c_prev_byte; //store first byte of i2c packet (255 if null)
29

  
30
// for i2c_register (checked in charging FSM)
31
#define I2C_REG_DEFAULT			0
32
#define I2C_REG_CHARGING		1
33
#define I2C_REG_CONTACT_ERROR	2
34
#define I2C_REG_BATTERY_FULL	3
35
#define I2C_REG_NO_CONTACT		4
36
int i2c_register;
37

  
38
/** @brief KEVIN **/
39
typedef void (*fun_srecv_t)(char);
40

  
41
/** @brief KEVIN **/
42
typedef int (*fun_mrecv_t)(char);
43

  
44
/** @brief KEVIN **/
45
typedef char (*fun_send_t)(void);
46

  
47
/** @brief KEVIN **/
48
int i2c_init(char addr, fun_mrecv_t master_recv, fun_srecv_t slave_recv, fun_send_t slave_send);
49

  
50
/** @brief KEVIN **/
51
void i2c_clear(void);
52

  
53
/** @brief A function for the master to send data to a slave. **/
54
int i2c_send(char dest, char* data, size_t bytes);
55

  
56
/** @brief KEVIN **/
57
int i2c_request(char dest);
58

  
59
/** @brief KEVIN **/
60
void i2c_packet_rec (char i2c_byte);
61
/** @brief KEVIN **/
62
void i2c_packet_sniff(char data);
63

  
64

  
65

  
66
unsigned char i2c_homing_sensor_data;
67
unsigned char i2c_homing_sensor_data_dirty;
68
//data dirty-ness
69
//data is dirty if the user decides so (generally, after it is used and new data is required).
70
//the bit set to 1 will mark the data with the same name as dirty.
71
//each time a new sensor value is read, the dirty bit is set to fresh, indicating that new data was available.
72
#define I2C_DATA_FRESH 0		//fresh = not dirty
73
#define I2C_DATA_DIRTY 1		//dirty is true
74

  
75

  
76
#endif
branches/i2c/code/projects/libdragonfly/purgatory/i2c.c
1
/* @file i2c.c
2
 * @brief KEVIN
3
 * In the case where you have master sends and then a master request to the same
4
 * address, you will not give up control of the line because the send and
5
 * request addresses are seen as different addresses. Inbetween it will send a
6
 * restart but will not give up the line.
7
 *
8
 * @author CMU Robotics Club
9
 * @bug Not tested.
10
 */
11

  
12
#include <avr/interrupt.h>
13
#include <util/twi.h>
14

  
15
#include "i2c.h"
16
#include "ring_buffer.h"
17
#include "serial.h"
18

  
19
/* Set bit rate 12 = 100kbit/s (max speed setting is 10 for an
20
 * 8 MHz clock). It is a divider, so the lower the number the faster the speed.
21
 */
22
#define I2C_BIT_RATE_DIVIDER 0x0C
23

  
24
static int start_flag;
25

  
26
static fun_mrecv_t master_recv_function;
27
static fun_srecv_t slave_recv_function;
28
static fun_send_t slave_send_function;
29

  
30
RING_BUFFER_NEW(i2c_buffer, 64, char, i2c_write_buff, i2c_addr_buff);
31

  
32
/**
33
 * KEVIN - description
34
 * 
35
 * @param addr KEVIN
36
 * @param master_recv KEVIN
37
 * @param slave_recv KEVIN
38
 * @param slave_send KEVIN
39
 * 
40
 * @return KEVIN
41
 *
42
 **/
43
int i2c_init(char addr, fun_mrecv_t master_recv, fun_srecv_t slave_recv, fun_send_t slave_send) {
44
  master_recv_function = master_recv;
45
  slave_recv_function = slave_recv;
46
  slave_send_function = slave_send;
47

  
48
  RING_BUFFER_CLEAR(i2c_write_buff);
49
  RING_BUFFER_CLEAR(i2c_addr_buff);
50
  
51
  /* enables twi interrupt, automatic ack sending, and all twi hardware */
52
  TWCR =  (_BV(TWEA) | _BV(TWEN) | _BV(TWIE));
53

  
54
  /* sets the bit rate of data transmission */
55
  TWBR = I2C_BIT_RATE_DIVIDER;
56

  
57
  /* sets the address (it is stored in the 7 most significant bits) and allows
58
   * global messages to be accepted */
59
  TWAR = (addr << 1) | 1;
60
  
61
  
62
  i2c_homing_sensor_data_dirty = I2C_DATA_DIRTY;
63
  
64
  return 0;
65
}
66

  
67
/**
68
 * KEVIN - description
69
 **/
70
void i2c_clear(void)
71
{
72
  RING_BUFFER_CLEAR(i2c_write_buff);
73
  RING_BUFFER_CLEAR(i2c_addr_buff);
74
  i2c_register = I2C_REG_DEFAULT;
75
}
76

  
77
/**
78
 * KEVIN - description
79
 * 
80
 * @param dest KEVIN
81
 * @param data KEVIN
82
 * @param bytes KEVIN
83
 *
84
 * @return KEVIN
85
 **/
86
int i2c_send(char dest, char *data, size_t bytes) {
87
  int i;
88

  
89
  /* adding data to be sent to ring buffers is not atomic,
90
   * so disable interrupts */
91
  cli();
92
  for(i = 0; i < bytes; i++) {
93
    if(RING_BUFFER_FULL(i2c_write_buff)) {
94
      sei();
95
      return -1;
96
    }
97

  
98
    RING_BUFFER_ADD(i2c_write_buff, data[i]);
99
    RING_BUFFER_ADD(i2c_addr_buff, dest << 1);
100
  }
101
  sei();
102
    
103
	/* send the start bit, only if this device is not currently master */
104
  if(!start_flag) {
105
    start_flag = 1;
106
    TWCR |= _BV(TWSTA);
107
    TWCR |= _BV(TWINT);
108
  }
109
  
110
  return 0;
111
}
112

  
113
/**
114
 * KEVIN - description
115
 *
116
 * @param dest KEVIN
117
 *
118
 * @return KEVIN
119
 **/
120
int i2c_request(char dest) {
121
  if(RING_BUFFER_FULL(i2c_write_buff))
122
    return -1;
123
  
124
  RING_BUFFER_ADD(i2c_write_buff, 0);
125
  RING_BUFFER_ADD(i2c_addr_buff, (dest << 1) | 1);
126
  
127
  if(!start_flag) {
128
    start_flag = 1;
129
    TWCR |= _BV(TWSTA);
130
    TWCR |= _BV(TWINT);
131
  }
132
  
133
  return 0;
134
}
135
 
136
ISR(TWI_vect) {
137
  static char data_to_send;
138
  static char addr_to_send = -1;
139
  char addr, statusCode;
140
  
141
    //Get status code (only upper 5 bits)
142
    statusCode = (TWSR & 0xF8);
143
  
144
  switch (statusCode) {
145
    //Start sent successfully
146
    case TW_START:
147
    case TW_REP_START:
148
      /* Send address and write
149
       * ring_buffer will not be empty */
150
      RING_BUFFER_REMOVE(i2c_addr_buff, addr_to_send);
151
      RING_BUFFER_REMOVE(i2c_write_buff, data_to_send);
152
      
153
      /* first send the address */
154
      TWDR = addr_to_send; 
155
      
156
      //Turn off start bits
157
      TWCR &= ~_BV(TWSTA);
158
      break;
159

  
160
    //Master Transmit - Address sent succesfully
161
    case TW_MT_SLA_ACK:
162
      //Send byte
163
      TWDR = data_to_send;
164
      break;
165
    //Master Transmit - Data sent succesfully
166
    case TW_MT_DATA_ACK:
167
      //If there is still data to send
168
      if(!RING_BUFFER_EMPTY(i2c_write_buff)) {
169
        RING_BUFFER_PEEK(i2c_addr_buff, addr);
170
        
171
        //Still data for this address
172
        if(addr == addr_to_send) {
173
          RING_BUFFER_REMOVE(i2c_addr_buff, addr);
174
          RING_BUFFER_REMOVE(i2c_write_buff, TWDR);
175
          break;
176
        }
177
        //No more data for this address, data for another address -> resend start
178
        else {
179
          TWCR |= _BV(TWSTA);
180
          break;
181
        }
182
      }
183
      
184
      /* there are no bytes to send */
185
      TWCR |= _BV(TWSTO);
186
      start_flag = 0;
187
      break;
188
    
189
    //Master Receive - Address sent succesfully
190
    case TW_MR_SLA_ACK:
191
      break;
192
    //Master Receive - Data received succesfully
193
    case TW_MR_DATA_ACK:
194
      if(master_recv_function) {
195
        if(!master_recv_function(TWDR)) {
196
          TWCR &= ~_BV(TWEA);
197
        }
198
      }
199
      break;
200
    case TW_MR_DATA_NACK:
201
      TWCR |= _BV(TWEA);
202
      
203
      //If there is still data to send
204
      if(!RING_BUFFER_EMPTY(i2c_write_buff)) {
205
        TWCR |= _BV(TWSTA);
206
        break;
207
      }
208
      
209
      /* there are no bytes to send */
210
      TWCR |= _BV(TWSTO);
211
      start_flag = 0;
212
      break;
213
    
214
    //Slave Transmit - Address received
215
    case TW_ST_SLA_ACK:
216
      break;
217
    //Slave Transmit - Nack received, no data requsted
218
    case TW_ST_DATA_NACK:
219
      break;
220
    //Slave Transmit - Data requested, ack received
221
    case TW_ST_DATA_ACK:
222
      if (slave_send_function) {
223
        TWDR = slave_send_function();
224
      }
225
      break;
226
    
227
    //Slave Receive - Address received  
228
    case TW_SR_SLA_ACK:
229
      break;
230
    //Slave Receive - Data received, ack returned
231
    case TW_SR_DATA_ACK:
232
      if(slave_recv_function)
233
        slave_recv_function(TWDR);
234
      break;
235
      
236
    //Stop sent  
237
    case TW_SR_STOP:
238
      break;
239
  }
240
  
241
  /* Toggle TWINT so that it resets and executes the commands */
242
  TWCR |= _BV(TWINT);
243
}
244

  
245
/**
246
 * KEVIN - description
247
 * @param data KEVIN
248
 **/
249
void i2c_packet_sniff(char data) {
250
  usb_putc(data);
251
  usb_putc(' ');
252
}
253

  
254
/**
255
 * KEVIN - description
256
 *
257
 * @param i2c_byte KEVIN
258
 **/
259
void i2c_packet_rec (char i2c_byte)
260
{
261
  if(i2c_prev_byte == 'H') {
262
    usb_puti(i2c_byte);
263
	i2c_homing_sensor_data = i2c_byte;
264
	i2c_homing_sensor_data_dirty = I2C_DATA_FRESH;
265
  }
266
  else
267
  	usb_putc(i2c_byte);
268
  usb_putc(' ');
269
  i2c_prev_byte = i2c_byte;
270
  switch(i2c_byte)
271
	{
272
		case I2C_MSG_BATTERY_CHARGING:
273
			i2c_register = I2C_REG_CHARGING;
274
			break;
275
		case I2C_MSG_CONTACT_ERROR:
276
			i2c_register = I2C_REG_CONTACT_ERROR;
277
			break;
278
		case I2C_MSG_BATTERY_FULL:
279
			i2c_register = I2C_REG_BATTERY_FULL;
280
			break;
281
		case I2C_MSG_NO_CONTACT:
282
			i2c_register = I2C_REG_NO_CONTACT;
283
			break;
284
		default:
285
			i2c_register = I2C_REG_DEFAULT;
286
			break;
287
	}
288
}
289

  
branches/i2c/code/projects/libdragonfly/i2c.c
2 2
 * @brief
3 3
 * In the case where you have master sends and then a master request to the same
4 4
 * address, you will not give up control of the line because the send and
5
 * request addresses are seen as different addresses. Inbetween it will send a
5
 * request addresses are seen as different addresses. In between it will send a
6 6
 * restart but will not give up the line.
7 7
 *
8
 * @author CMU Robotics Club
8
 * @author CMU Robotics Club, Kevin Woo, Sursh Nidhiry
9 9
 * @bug Not tested.
10 10
 */
11 11

  
......
27 27
 * This code will operate in a multi-master enviornment and can be either a
28 28
 * slave or a master at any time (as long as they are not one or the other at
29 29
 * the moment. You can queue up multiple transmission modes in the buffer up to 
30
 * the buffer size. The buffer is a ring buffer.
30
 * the buffer size. The buffer is implemented as a ring buffer.
31 31
 *
32 32
 * It is implemented using callback functions. Whenever you want to send a packet
33 33
 * you can call the built in send function (as a master) and it will send an array
34
 * of bytes. Master recieve and slave send/receive are all handled by call back
34
 * of bytes. Master recieve and slave send/receive are all handled by the call back
35 35
 * functions. It is up to the end user to create functions that will handle the
36 36
 * receiving of packets. Their functions will be called with every byte recieved
37 37
 * so you must either buffer the inputs or handle each one separately.
......
75 75
 *								requests data from you.
76 76
 **/
77 77
int i2c_init(char addr, fun_mrecv_t master_recv, fun_srecv_t slave_recv, fun_send_t slave_send) {
78
  master_recv_function = master_recv;
79
  slave_recv_function = slave_recv;
80
  slave_send_function = slave_send;
78
    master_recv_function = master_recv;
79
    slave_recv_function = slave_recv;
80
    slave_send_function = slave_send;
81 81

  
82
  RING_BUFFER_CLEAR(i2c_write_buff);
83
  RING_BUFFER_CLEAR(i2c_addr_buff);
82
    RING_BUFFER_CLEAR(i2c_write_buff);
83
    RING_BUFFER_CLEAR(i2c_addr_buff);
84 84
  
85
  /* enables twi interrupt, automatic ack sending, and all twi hardware */
86
  TWCR =  (_BV(TWEA) | _BV(TWEN) | _BV(TWIE));
85
    /* enables twi interrupt, automatic ack sending, and all twi hardware */
86
    TWCR =  (_BV(TWEA) | _BV(TWEN) | _BV(TWIE));
87 87

  
88
  /* sets the bit rate of data transmission */
89
  TWBR = I2C_BIT_RATE_DIVIDER;
88
    /* sets the bit rate of data transmission */
89
    TWBR = I2C_BIT_RATE_DIVIDER;
90 90

  
91
  /* sets the address (it is stored in the 7 most significant bits) and allows
92
   * global messages to be accepted */
93
  TWAR = (addr << 1) | 1;
91
    /* sets the address (it is stored in the 7 most significant bits) and allows
92
     * global messages to be accepted */
93
    TWAR = (addr << 1) | 1;
94 94
  
95
  return 0;
95
    return 0;
96 96
}
97 97

  
98 98
/**
......
107 107
 *						many bytes from the array that the function will send.
108 108
 **/
109 109
int i2c_send(char dest, char *data, size_t bytes) {
110
  int i;
110
    int i;
111 111

  
112
  /* adding data to be sent to ring buffers is not atomic,
113
   * so disable interrupts */
114
  cli();
115
  for(i = 0; i < bytes; i++) {
116
    if(RING_BUFFER_FULL(i2c_write_buff)) {
117
      sei();
118
      return -1;
112
    /* adding data to be sent to ring buffers is not atomic,
113
     * so disable interrupts */
114
    cli();
115
    for(i = 0; i < bytes; i++) {
116
        if(RING_BUFFER_FULL(i2c_write_buff)) {
117
            sei();
118
            return -1;
119
        }
120

  
121
        RING_BUFFER_ADD(i2c_write_buff, data[i]);
122
        RING_BUFFER_ADD(i2c_addr_buff, dest << 1);
119 123
    }
120

  
121
    RING_BUFFER_ADD(i2c_write_buff, data[i]);
122
    RING_BUFFER_ADD(i2c_addr_buff, dest << 1);
123
  }
124
  /* re-enable the interrupts */
125
  sei();
126 124
    
127
	/* send the start bit, only if this device is not currently master */
128
  if(!start_flag) {
129
    start_flag = 1;
130
    TWCR |= _BV(TWSTA);
131
    TWCR |= _BV(TWINT);
132
  }
125
    /* re-enable the interrupts */
126
    sei();
127
    
128
    /* send the start bit, only if this device is not currently master */
129
    if(!start_flag) {
130
        start_flag = 1;
131
        TWCR |= _BV(TWSTA);
132
        TWCR |= _BV(TWINT);
133
    }
133 134
  
134
  return 0;
135
    return 0;
135 136
}
136 137
 
137 138
/**
......
145 146
 * @param dest		The destination that we want to receive information from.
146 147
 **/ 
147 148
int i2c_request(char dest) {
148
  if(RING_BUFFER_FULL(i2c_write_buff))
149
    return -1;
149
    if(RING_BUFFER_FULL(i2c_write_buff))
150
        return -1;
150 151
  
151
  RING_BUFFER_ADD(i2c_write_buff, 0);
152
  RING_BUFFER_ADD(i2c_addr_buff, (dest << 1) | 1);
152
    RING_BUFFER_ADD(i2c_write_buff, 0);
153
    RING_BUFFER_ADD(i2c_addr_buff, (dest << 1) | 1);
153 154
  
154
  if(!start_flag) {
155
    start_flag = 1;
156
    TWCR |= _BV(TWSTA);
157
    TWCR |= _BV(TWINT);
158
  }
155
    if(!start_flag) {
156
        start_flag = 1;
157
        TWCR |= _BV(TWSTA);
158
        TWCR |= _BV(TWINT);
159
    }
159 160
  
160
  return 0;
161
    return 0;
161 162
}
162 163
 
163 164
/**
......
166 167
 * Uses the status codes from the I2C register to handle the events
167 168
 * needed to advance in I2C stages. For instance, you will get a bit for
168 169
 * receiving a start ack, then a address ack, then a data ack, etc.
169
 * The events are handled in each switch case.
170
 * The events are handled in each switch case. The status codes are defined
171
 * by avr-gcc in /util/twi.h but are the same codes as the Atmel documentation.
172
 *
170 173
 * Bytes are sent by popping off the ring buffer. It also will keep track
171 174
 * of what modes the send is in.
175
 *
172 176
 * Errors are handled here as well.
173 177
 **/ 
178
 /* @} */
174 179
ISR(TWI_vect) {
175
  static char data_to_send;
176
  static char addr_to_send = -1;
177
  char addr, statusCode;
178
  //PORTG &= ~_BV(PG2);
180
	static char data_to_send;
181
	static char addr_to_send = -1;
182
	char addr, statusCode;
179 183
  
180
    //Get status code (only upper 5 bits)
181
    statusCode = (TWSR & 0xF8);
182
	//usb_putc(statusCode);
183
  switch (statusCode) {
184
    //Start sent successfully
185
    case TW_START:
186
    case TW_REP_START:
187
      /* Send address and write
188
       * ring_buffer will not be empty */
189
      RING_BUFFER_REMOVE(i2c_addr_buff, addr_to_send);
190
      RING_BUFFER_REMOVE(i2c_write_buff, data_to_send);
191
      
192
      /* first send the address */
193
      TWDR = addr_to_send; 
194
      
195
      //Turn off start bits
196
      TWCR &= ~_BV(TWSTA);
197
      break;
184
	//Get status code (only upper 5 bits)
185
	statusCode = (TWSR & 0xF8);
198 186

  
199
    //Master Transmit - Address sent succesfully
200
    case TW_MT_SLA_ACK:
201
      //Send byte
202
      TWDR = data_to_send;
203
		PORTG &= ~_BV(PG2);
204
      break;
205
	 //Master Transmit - Data sent succesfully
206
    case TW_MT_DATA_ACK:
207
      //If there is still data to send
208
      if(!RING_BUFFER_EMPTY(i2c_write_buff)) {
209
        RING_BUFFER_PEEK(i2c_addr_buff, addr);
187
    switch (statusCode) {
188
        //Start sent successfully
189
        case TW_START:
190
        case TW_REP_START:
191
            /* Send address and write
192
             * ring_buffer will not be empty */
193
            RING_BUFFER_REMOVE(i2c_addr_buff, addr_to_send);
194
            RING_BUFFER_REMOVE(i2c_write_buff, data_to_send);
195
            
196
            /* first send the address */
197
            TWDR = addr_to_send; 
198
            
199
            //Turn off start bits
200
            TWCR &= ~_BV(TWSTA);
201
            break;
202

  
203
        //Master Transmit - Address sent succesfully
204
        case TW_MT_SLA_ACK:
205
        //Send byte
206
            TWDR = data_to_send;
207
            PORTG &= ~_BV(PG2);
208
            break;
209
	 
210
        //Master Transmit - Data sent succesfully
211
        case TW_MT_DATA_ACK:    
212
            //If there is still data to send
213
            if(!RING_BUFFER_EMPTY(i2c_write_buff)) {
214
                RING_BUFFER_PEEK(i2c_addr_buff, addr);
210 215
        
211
        //Still data for this address
212
        if(addr == addr_to_send) {
213
          RING_BUFFER_REMOVE(i2c_addr_buff, addr);
214
          RING_BUFFER_REMOVE(i2c_write_buff, TWDR);
215
          break;
216
        }
217
        //No more data for this address, data for another address -> resend start
218
        else {
219
          TWCR |= _BV(TWSTA);
220
          break;
221
        }
222
      }
216
                //Still data for this address
217
                if (addr == addr_to_send) {
218
                    RING_BUFFER_REMOVE(i2c_addr_buff, addr);
219
                    RING_BUFFER_REMOVE(i2c_write_buff, TWDR);
220
                    break;
221
                //No more data for this address, data for another address -> resend start
222
                } else {
223
                    TWCR |= _BV(TWSTA);
224
                    break;
225
                }
226
            }
227
            /* there are no bytes to send */
228
            TWCR |= _BV(TWSTO);
229
            start_flag = 0;
230
            break; 
231
            
232
        //Master Transmit - Slave sends a nack, transmit is done
233
        case TW_MT_DATA_NACK:
234
            PORTG |= _BV(PG2);
235
            TWCR |= _BV(TWSTO);
236
            start_flag = 0;
237
            break;
238
    
239
        //Master Receive - Address sent succesfully
240
        case TW_MR_SLA_ACK:
241
            PORTG |= _BV(PG2);
242
            break;
243
            
244
        //Master Receive - Data received succesfully
245
        case TW_MR_DATA_ACK:
246
            if(master_recv_function) {
247
                if(!master_recv_function(TWDR)) {
248
                    TWCR &= ~_BV(TWEA);
249
                }
250
            }
251
            break;
252
            
253
        //Master Receive - Slave sends a nack, transmission is done    
254
        case TW_MR_DATA_NACK:
255
            TWCR |= _BV(TWEA);
223 256
      
224
      /* there are no bytes to send */
225
      TWCR |= _BV(TWSTO);
226
      start_flag = 0;
227
      break;
228
		
229
    case TW_MT_DATA_NACK:
230
		PORTG |= _BV(PG2);
231
		TWCR |= _BV(TWSTO);
232
      start_flag = 0;
233
		break;
234
    //Master Receive - Address sent succesfully
235
    case TW_MR_SLA_ACK:
236
	 PORTG |= _BV(PG2);
237
      break;
238
    //Master Receive - Data received succesfully
239
    case TW_MR_DATA_ACK:
240
      if(master_recv_function) {
241
        if(!master_recv_function(TWDR)) {
242
          TWCR &= ~_BV(TWEA);
243
        }
244
      }
245
      break;
246
    case TW_MR_DATA_NACK:
247
      TWCR |= _BV(TWEA);
257
            //If there is still data to send
258
            if(!RING_BUFFER_EMPTY(i2c_write_buff)) {
259
                TWCR |= _BV(TWSTA);
260
                break;
261
            }
248 262
      
249
      //If there is still data to send
250
      if(!RING_BUFFER_EMPTY(i2c_write_buff)) {
251
        TWCR |= _BV(TWSTA);
252
        break;
253
      }
254
      
255
      /* there are no bytes to send */
256
      TWCR |= _BV(TWSTO);
257
      start_flag = 0;
258
		  
259
      break;
263
            /* there are no bytes to send */
264
            TWCR |= _BV(TWSTO);
265
            start_flag = 0;  
266
            break;
260 267
    
261
    //Slave Transmit - Address received
262
    case TW_ST_SLA_ACK:
263
      break;
264
    //Slave Transmit - Nack received, no data requsted
265
    case TW_ST_DATA_NACK:
266
      break;
267
    //Slave Transmit - Data requested, ack received
268
    case TW_ST_DATA_ACK:
269
      if (slave_send_function) {
270
        TWDR = slave_send_function();
271
      }
272
      break;
268
        //Slave Transmit - Address received
269
        case TW_ST_SLA_ACK:
270
            break;
273 271
    
274
    //Slave Receive - Address received  
275
    case TW_SR_SLA_ACK:
276
      break;
277
    //Slave Receive - Data received, ack returned
278
    case TW_SR_DATA_ACK:
279
      if(slave_recv_function)
280
        slave_recv_function(TWDR);
281
      break;
272
        //Slave Transmit - Nack received, no data requsted
273
        case TW_ST_DATA_NACK:
274
            break;
275
        
276
        //Slave Transmit - Data requested, ack received
277
        case TW_ST_DATA_ACK:
278
            if (slave_send_function) {
279
                TWDR = slave_send_function();
280
            }
281
            break;
282
    
283
        //Slave Receive - Address received  
284
        case TW_SR_SLA_ACK:
285
            break;
286
    
287
        //Slave Receive - Data received, ack returned
288
        case TW_SR_DATA_ACK:
289
            if(slave_recv_function) {
290
                slave_recv_function(TWDR);
291
            }
292
            
293
            break;
282 294
      
283
    //Stop sent  
284
    case TW_SR_STOP:
285
      break;
286
	default:
287
		TWCR |= _BV(TWSTO);
288
      start_flag = 0;
289
		RING_BUFFER_CLEAR(i2c_write_buff);
290
		RING_BUFFER_CLEAR(i2c_addr_buff);
291
	//PORTG |= _BV(PG2);
292
  	
293
  }
295
        //Stop sent  
296
        case TW_SR_STOP:
297
            break;
298
	
299
        //Problem on the bus, reset everything
300
        default:
301
            TWCR |= _BV(TWSTO);
302
            start_flag = 0;
303
            RING_BUFFER_CLEAR(i2c_write_buff);
304
            RING_BUFFER_CLEAR(i2c_addr_buff);  	
305
    }
294 306
  
295

  
296
  
297 307
  /* Toggle TWINT so that it resets and executes the commands */
298 308
  TWCR |= _BV(TWINT);
299
  
300

  
301 309
}
branches/i2c/code/projects/libdragonfly/i2c.h
1 1
/** @file i2c.h
2
 *  @brief
2
 *  @brief Header file for I2C
3 3
 *
4
 *  @author CMU Robotics Club`
4
 *  @author CMU Robotics Club, Kevin Woo, Suresh Nidhiry
5 5
 */
6 6

  
7 7

  
......
10 10

  
11 11
#include <stddef.h>
12 12

  
13
/** @brief */
13
/** @brief Address of slave receive handler function */
14 14
typedef void (*fun_srecv_t)(char);
15 15

  
16
/** @brief */
16
/** @brief Address of master receive handler function*/
17 17
typedef int (*fun_mrecv_t)(char);
18 18

  
19
/** @brief */
19
/** @brief Address of slave send handler function*/
20 20
typedef char (*fun_send_t)(void);
21 21

  
22
/** @brief */
23 22
int i2c_init(char addr, fun_mrecv_t master_recv, fun_srecv_t slave_recv, fun_send_t slave_send);
24

  
25
/** @brief A function for the master to send data to a slave.
26
*/
27 23
int i2c_send(char dest, char* data, size_t bytes);
28

  
29
/** @brief */
30 24
int i2c_request(char dest);
31 25

  
32 26
void i2c_packet_rec (char i2c_byte);
branches/i2c/code/projects/libdragonfly/ring_buffer.h
1
/** @file Include macros to create a ring buffer. Originally written for 15-410.
2
 *  Modified for use in ATMega128 serial driver
3
 *
4
 *	@author Cornell Wright (cgwright)
5
 *	@author Jason P. Winters (jpwinter)
6
 *
7
 *	@bugs Could not create buffer of non byte-sized elements due to modding with sizeof(queue).  
8
 * 		  Fixed 3/2/07, Felix Duvallet and Brad Neuman
9
 */
10

  
11
#ifndef _RING_BUFFER_H
12
#define _RING_BUFFER_H
13

  
14
/** @brief Creates the struct for a new ring buffer. This just expands to a
15
 *	structure definition and thus should be invoked in the global context.
16
 *
17
 *	@param struct_name Name of the ring buffer struct.
18
 *
19
 *	@param size The size of the buffer to create.
20
 *
21
 *	@param type The type of object that the queue is to hold.
22
 *
23
 *	@param ... Name or names of the instance or instances of the ring buffer(s)
24
 *	to be created.
25
 */
26
#define RING_BUFFER_NEW(struct_name, size, type, ...)	\
27
	struct struct_name {	\
28
		type queue[size];	\
29
		uint8_t start;			\
30
		uint8_t end;			\
31
		uint8_t buffer_size;			\
32
	} __VA_ARGS__
33

  
34

  
35
/** @brief Initializes the ring buffer, setting its size to the correct value
36
 *
37
 *	@param buf The ring buffer to initialize.
38
 *
39
 *  @param size The size of the ring buffer (in array elements)
40
 */
41
#define RING_BUFFER_INIT(buf, size) 			\
42
	do {										\
43
		(buf).buffer_size = size;				\
44
	} while(0)
45

  
46

  
47
/** @brief Sets the specified ring buffer to be empty.
48
 *
49
 *	@param buf The ring buffer to make empty.
50
 */
51
#define RING_BUFFER_CLEAR(buf)	\
52
	do {						\
53
		(buf).start = 0;		\
54
		(buf).end = 0;			\
55
	} while (0)
56

  
57
/** @brief Returns true if the ring buffer specified is empty.
58
 *
59
 *	@param buf The buffer to check emptiness of.
60
 */
61
#define RING_BUFFER_EMPTY(buf) ((buf).start == (buf).end)
62

  
63

  
64
/** @brief Returns true if the ring buffer specified is full.
65
 *
66
 *	@param buf The buffer to check fullness of.
67
 */
68
#define RING_BUFFER_FULL(buf)	\
69
		(((buf).end + 1) % (buf).buffer_size == (buf).start)
70

  
71

  
72
/** @brief Adds val to ring buffer buf. Note that val must be of the type
73
 *	used in creating the ring buffer to prevent the compiler from spewing
74
 *	confusing errors. Also, this assumes that the ring buffer is not full.
75
 *
76
 *	@param buf The ring buffer to add to.
77
 *	@param val The value to add.
78
 */
79
#define RING_BUFFER_ADD(buf, val)		\
80
	do {								\
81
		(buf).queue[(buf).end] = val;	\
82
		(buf).end = ((buf).end + 1) % (buf).buffer_size;	\
83
	} while (0)
84

  
85

  
86
/** @brief Removes the value at the head of the ring buffer and puts it in
87
 *	val_ret. Note that val_ret must be the same type used in creating the ring
88
 *	buffer to prevent the compiler from spewing confusing errors. Also, this
89
 *	assumes that the ring buffer is not empty.
90
 *
91
 *	@param buf The ring buffer to remove from.
92
 *	@param val_ret Where to put the value removed from the head of the ring
93
 *	buffer.
94
 */
95
#define RING_BUFFER_REMOVE(buf, val_ret)	\
96
	do {	\
97
		(val_ret) = (buf).queue[(buf).start];	\
98
		(buf).start = ((buf).start + 1) % (buf).buffer_size;	\
99
	} while (0)
100

  
101
/** @brief Checks the value at the head of the ring buffer without removing it
102
 *  and puts it into val_ret. Note that val_ret must be the same type used in
103
 *  creating the ring buffer to prevent the compiler from spewing confusing
104
 *  errors. Also, this assumes that the ring buffer is not empty.
105
 *
106
 *  @param buf The ring buffer to check from
107
 *  @param val_ret where to put the value checked from the head of the ring
108
 */
109
 #define RING_BUFFER_PEEK(buf, val_ret)  \
110
  do { \
111
    (val_ret) = (buf).queue[(buf).start]; \
112
  } while(0)
113

  
114
#endif /* _RING_BUFFER_H */
115

  

Also available in: Unified diff