Contiki-Inga 3.x
i2c.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, TU Braunschweig.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 /**
31  * \file
32  * I2C driver implementation
33  * \author
34  * Stephan Rottman <rottmann@ibr.cs.tu-bs.de>
35  * modified by Ulf Kulau <kulau@ibr.cs.tu-bs.de>
36  */
37 
38 /**
39  * \addtogroup inga_bus_driver
40  * @{
41  */
42 
43 /**
44  * \addtogroup i2c_driver
45  * @{
46  */
47 
48 #include "i2c.h"
49 
50 #ifndef PRR
51 #define PRR PRR0
52 #endif
53 void
54 i2c_init(void) {
55  TWSR &= ~((1 << TWPS1) | (1 << TWPS0));
56 #if I2C_HIGH_SPEED
57  TWBR = 2; //400KHz
58 #else
59  TWBR = 32; //100KHz
60 #endif
61 
62 }
63 /*----------------------------------------------------------------------------*/
64 int8_t
65 _i2c_start(uint8_t addr, uint8_t rep) {
66  uint16_t i = 0;
67 
68  PRR &= ~(1 << PRTWI);
69  TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
70  while (!(TWCR & (1 << TWINT))) {
71  if( i++ > 800 ) {
72  return -3;
73  }
74  }
75 
76  if ((TWSR & 0xF8) != ((!rep) ? I2C_START : I2C_REP_START))
77  return -1;
78 
79  TWDR = addr;
80  TWCR = (1 << TWINT) | (1 << TWEN);
81  i = 0;
82 
83  while (!(TWCR & (1 << TWINT))) {
84  if( i++ > 800 ) {
85  return -4;
86  }
87  }
88  if (!(((TWSR & 0xF8) == I2C_MT_SLA_ACK) || ((TWSR & 0xF8) == I2C_MR_SLA_ACK)))
89  return -2;
90 
91  return 0;
92 }
93 /*----------------------------------------------------------------------------*/
94 int8_t
95 i2c_start(uint8_t addr) {
96  return _i2c_start(addr, 0);
97 }
98 /*----------------------------------------------------------------------------*/
99 int8_t
100 i2c_rep_start(uint8_t addr) {
101  return _i2c_start(addr, 1);
102 }
103 /*----------------------------------------------------------------------------*/
104 int8_t
105 i2c_write(uint8_t data) {
106  uint16_t i = 0;
107 
108  TWDR = data;
109  TWCR = (1 << TWINT) | (1 << TWEN);
110 
111  while (!(TWCR & (1 << TWINT))) {
112  if( i++ > 800 ) {
113  return -2;
114  }
115  }
116 
117  if ((TWSR & 0xF8) != I2C_MT_DATA_ACK)
118  return -1;
119 
120  return 0;
121 }
122 /*----------------------------------------------------------------------------*/
123 int8_t
124 i2c_read(uint8_t *data, uint8_t ack) {
125  uint16_t i = 0;
126  TWCR = (1 << TWINT) | (1 << TWEN) | (ack ? (1 << TWEA) : 0);
127  while (!(TWCR & (1 << TWINT))) {
128  if (i++ > 800) {
129  return -1;
130  }
131  }
132  if ((TWSR & 0xF8) != (ack ? I2C_MR_DATA_ACK : I2C_MR_DATA_NACK))
133  return -1;
134  *data = TWDR;
135  return 0;
136 }
137 /*----------------------------------------------------------------------------*/
138 int8_t
139 i2c_read_ack(uint8_t *data) {
140  return i2c_read(data, 1);
141 }
142 /*----------------------------------------------------------------------------*/
143 int8_t
144 i2c_read_nack(uint8_t *data) {
145  return i2c_read(data, 0);
146 }
147 /*----------------------------------------------------------------------------*/
148 void
149 i2c_stop(void) {
150  uint16_t i = 0;
151 
152  TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
153  while (TWCR & (1 << TWSTO)) {
154  if (i++ > 800) {
155  return;
156  }
157  }
158 
159  TWCR &= ~(1 << TWEN);
160 
161  PRR |= (1 << PRTWI);
162  DDRC &= ~((1 << PC0) | (1 << PC1));
163  PORTC |= ((1 << PC0) | (1 << PC1));
164 
165 }