Contiki 3.x
i2c.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010, Swedish Institute of Computer Science.
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 /**
32  * \file
33  * i2c core functions
34  * \author
35  * Robert Olsson <robert@radio-sensors.com>
36  */
37 
38 #include <avr/pgmspace.h>
39 #include <avr/pgmspace.h>
40 #include <avr/sleep.h>
41 #include <avr/wdt.h>
42 #include "dev/watchdog.h"
43 #include "contiki.h"
44 #include "i2c.h"
45 #include <compat/twi.h>
46 #include <stdio.h>
47 #include <string.h>
48 #include "dev/co2_sa_kxx-sensor.h"
49 
50 void
51 i2c_init(uint32_t speed)
52 {
53  /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
54 
55  TWSR = 0; /* no prescaler */
56  TWBR = ((F_CPU / speed) - 16) / 2; /* must be > 10 for stable operation */
57 }
58 uint8_t
59 i2c_start(uint8_t addr)
60 {
61  uint8_t twst;
62  uint32_t n;
63 
64  /* Send START condition */
65  TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
66 
67  /* Wait until transmission completed */
68  for(n = 0; n < 100000 && !(TWCR & (1 << TWINT)); n++) {
69  }
70  if(n >= 100000) {
71  return 1;
72  }
73 
74  /* check value of TWI Status Register. Mask prescaler bits. */
75  twst = TW_STATUS & 0xF8;
76  if((twst != TW_START) && (twst != TW_REP_START)) {
77  return 1;
78  }
79 
80  /* send device address */
81  TWDR = addr;
82  TWCR = (1 << TWINT) | (1 << TWEN);
83 
84  /* wail until transmission completed and ACK/NACK has been received */
85  for(n = 0; n < 100000 && !(TWCR & (1 << TWINT)); n++) {
86  }
87  if(n >= 100000) {
88  return 1;
89  }
90 
91  /* check value of TWI Status Register. Mask prescaler bits. */
92  twst = TW_STATUS & 0xF8;
93  if((twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK)) {
94  return 1;
95  }
96 
97  return 0;
98 }
99 void
100 i2c_start_wait(uint8_t addr)
101 {
102  uint8_t twst;
103  while ( 1 )
104  {
105  // send START condition
106  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
107  // wait until transmission completed
108  while(!(TWCR & (1<<TWINT)));
109  // check value of TWI Status Register. Mask prescaler bits.
110  twst = TW_STATUS & 0xF8;
111  if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
112  // send device address
113  TWDR = addr;
114  TWCR = (1<<TWINT) | (1<<TWEN);
115  // wail until transmission completed
116  while(!(TWCR & (1<<TWINT)));
117  // check value of TWI Status Register. Mask prescaler bits.
118  twst = TW_STATUS & 0xF8;
119  if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) )
120  {
121  /* device busy, send stop condition to terminate write operation */
122  TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
123  // wait until stop condition is executed and bus released
124  while(TWCR & (1<<TWSTO));
125  continue;
126  }
127  //if( twst != TW_MT_SLA_ACK) return 1;
128  break;
129  }
130 }
131 void
132 i2c_stop(void)
133 {
134  TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN);
135  /* wait until ready */
136  while(TWCR & (1<<TWSTO));
137 }
138 void
139 i2c_write(uint8_t u8data)
140 {
141  TWDR = u8data;
142  TWCR = (1 << TWINT) | (1 << TWEN);
143  while((TWCR & (1 << TWINT)) == 0) ;
144 }
145 uint8_t
146 i2c_readAck(void)
147 {
148  TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA);
149  while((TWCR & (1 << TWINT)) == 0) ;
150  return TWDR;
151 }
152 uint8_t
153 i2c_readNak(void)
154 {
155  TWCR = (1 << TWINT) | (1 << TWEN);
156  while((TWCR & (1 << TWINT)) == 0) ;
157  return TWDR;
158 }
159 static void
160 print_delim(int p, char *s, const char *d)
161 {
162  if(p) {
163  printf("%s", d);
164  }
165  printf("%s", s);
166 }
167 void
168 i2c_write_mem(uint8_t addr, uint8_t reg, uint8_t value)
169 {
170  i2c_start(addr | I2C_WRITE);
171  i2c_write(reg);
172  i2c_write(value);
173  i2c_stop();
174 }
175 void
176 i2c_read_mem(uint8_t addr, uint8_t reg, uint8_t buf[], uint8_t bytes)
177 {
178  uint8_t i = 0;
179  i2c_start(addr | I2C_WRITE);
180  i2c_write(reg);
181  i2c_start(addr | I2C_READ);
182  for(i = 0; i < bytes; i++) {
183  if(i == bytes - 1) {
184  buf[i] = i2c_readNak();
185  } else {
186  buf[i] = i2c_readAck();
187  }
188  }
189  i2c_stop();
190 }
191 void
192 i2c_at24mac_read(char *buf, uint8_t eui64)
193 {
194  if(eui64) {
195  i2c_read_mem(I2C_AT24MAC_ADDR, 0x98, (uint8_t *)buf, 8);
196  }
197  /* 128bit unique serial number */
198  else {
199  i2c_read_mem(I2C_AT24MAC_ADDR, 0x80, (uint8_t *)buf, 16);
200  }
201 }
202 
203 uint16_t
204 i2c_probe(void)
205 {
206  int p = 0;
207  const char *del = ",";
208  uint16_t probed = 0;
210  if(!i2c_start(I2C_AT24MAC_ADDR)) {
211  i2c_stop();
212  probed |= I2C_AT24MAC;
213  print_delim(p++, "AT24MAC", del);
214  }
216  if(!i2c_start(I2C_SHT2X_ADDR)) {
217  i2c_stop();
218  probed |= I2C_SHT2X;
219  print_delim(p++, "SHT2X", del);
220  }
222  if(!i2c_start(I2C_CO2SA_ADDR)) {
223  i2c_stop();
224  probed |= I2C_CO2SA;
225  print_delim(p++, "CO2SA", del);
226  }
227  return probed;
228 }
void i2c_start(void)
Generate I2C START condition.
Definition: i2c.c:85
static uip_ds6_addr_t * addr
Pointer to a router list entry.
Definition: uip-nd6.c:124
void i2c_stop(void)
Generate I2C STOP condition.
Definition: i2c.c:95
void i2c_init(uint8_t port_sda, uint8_t pin_sda, uint8_t port_scl, uint8_t pin_scl, uint32_t bus_speed)
Initialize the I2C peripheral and pins.
Definition: i2c.c:49
void watchdog_periodic(void)
Writes the WDT clear sequence.
Definition: watchdog.c:64
void i2c_write(uint8_t data)
Send a byte to I2C bus.
Definition: i2c.c:106