Contiki 2.5
i2c-drv.c
Go to the documentation of this file.
1 /* Copyright (c) 2010, Stephan Rottmann
2  *
3  * Permission is hereby granted, free of charge, to any person
4  * obtaining a copy of this software and associated documentation
5  * files (the "Software"), to deal in the Software without
6  * restriction, including without limitation the rights to use,
7  * copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following
10  * conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 /**
26  * \addtogroup Drivers
27  * @{
28  *
29  * \addtogroup i2c_driver
30  * @{
31  */
32 
33 /**
34  * \file
35  * I2C driver implementation
36  * \author
37  * Stephan Rottman <rottmann@ibr.cs.tu-bs.de>
38  * modified by Ulf Kulau <kulau@ibr.cs.tu-bs.de>
39  */
40 
41 #include "i2c-drv.h"
42 
43 #ifndef PRR
44 #define PRR PRR0
45 #endif
46 
47 void i2c_init(void)
48 {
49  TWSR &= ~((1<<TWPS1) | (1<<TWPS0));
50 #if I2C_HIGH_SPEED
51  TWBR = 2; //400KHz
52 #else
53  TWBR = 32; //100KHz
54 #endif
55 
56 }
57 
58 
59 int8_t _i2c_start(uint8_t addr, uint8_t rep)
60 {
61  PRR &= ~(1<<PRTWI);
62  i2c_init();
63  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
64  while(!(TWCR & (1<<TWINT)));
65  if((TWSR&0xF8) != ((!rep)?I2C_START:I2C_REP_START))
66  return -1;
67 
68  TWDR = addr;
69  TWCR = (1<<TWINT) | (1<<TWEN);
70 
71  while(!(TWCR & (1<<TWINT)));
72  if(!(((TWSR&0xF8) == I2C_MT_SLA_ACK) || ((TWSR&0xF8) == I2C_MR_SLA_ACK)))
73  return -2;
74 
75  return 0;
76 }
77 
78 int8_t i2c_start(uint8_t addr)
79 {
80  return _i2c_start(addr, 0);
81 }
82 
83 int8_t i2c_rep_start(uint8_t addr)
84 {
85  return _i2c_start(addr, 1);
86 }
87 
88 int8_t i2c_write(uint8_t data)
89 {
90  TWDR = data;
91  TWCR = (1<<TWINT) | (1<<TWEN);
92 
93  while(!(TWCR & (1<<TWINT)));
94  if((TWSR&0xF8) != I2C_MT_DATA_ACK)
95  return -1;
96 
97  return 0;
98 }
99 
100 int8_t i2c_read(uint8_t *data, uint8_t ack)
101 {
102  uint16_t i = 0;
103  TWCR = (1<<TWINT)|(1<<TWEN)| (ack?(1<<TWEA):0);
104  while(!(TWCR & (1<<TWINT))){
105  if(i++ > 800){
106  return -1;
107  }
108  }
109  if((TWSR&0xF8) != (ack?I2C_MR_DATA_ACK:I2C_MR_DATA_NACK))
110  return -1;
111  *data = TWDR;
112  return 0;
113 }
114 
115 int8_t i2c_read_ack(uint8_t *data)
116 {
117  return i2c_read(data, 1);
118 }
119 
120 int8_t i2c_read_nack(uint8_t *data)
121 {
122  return i2c_read(data, 0);
123 }
124 
125 void i2c_stop(void)
126 {
127 
128  TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
129  while(TWCR & (1<<TWSTO));
130 
131  TWCR &= ~(TWEN);
132 
133  PRR |= (1<<PRTWI);
134  DDRC &= ~( (1<<PC0) | (1<<PC1) );
135  PORTC |= ((1<<PC0) | (1<<PC1));
136 
137 }