Contiki 2.5
sht11.c
1 /*
2  * Copyright (c) 2007, 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  * @(#)$Id: sht11.c,v 1.3 2008/11/10 21:10:36 adamdunkels Exp $
30  */
31 
32 /*
33  * Device driver for the Sensirion SHT1x/SHT7x family of humidity and
34  * temperature sensors.
35  */
36 
37 #include "contiki.h"
38 #include <stdio.h>
39 #include <dev/sht11.h>
40 #include "sht11-arch.h"
41 
42 #define DEBUG 0
43 
44 #if DEBUG
45 #include <stdio.h>
46 #define PRINTF(...) printf(__VA_ARGS__)
47 #else
48 #define PRINTF(...)
49 #endif
50 
51 #ifndef SDA_0
52 #define SDA_0() (SHT11_PxDIR |= BV(SHT11_ARCH_SDA)) /* SDA Output=0 */
53 #define SDA_1() (SHT11_PxDIR &= ~BV(SHT11_ARCH_SDA)) /* SDA Input */
54 #define SDA_IS_1 (SHT11_PxIN & BV(SHT11_ARCH_SDA))
55 
56 #define SCL_0() (SHT11_PxOUT &= ~BV(SHT11_ARCH_SCL)) /* SCL Output=0 */
57 #define SCL_1() (SHT11_PxOUT |= BV(SHT11_ARCH_SCL)) /* SCL Output=1 */
58 #endif
59  /* adr command r/w */
60 #define STATUS_REG_W 0x06 /* 000 0011 0 */
61 #define STATUS_REG_R 0x07 /* 000 0011 1 */
62 #define MEASURE_TEMP 0x03 /* 000 0001 1 */
63 #define MEASURE_HUMI 0x05 /* 000 0010 1 */
64 #define RESET 0x1e /* 000 1111 0 */
65 
66 /* This can probably be reduced to 250ns according to data sheet. */
67 #ifndef delay_400ns
68 #define delay_400ns() _NOP()
69 #endif
70 /*---------------------------------------------------------------------------*/
71 static void
72 sstart(void)
73 {
74  SDA_1(); SCL_0();
75  delay_400ns();
76  SCL_1();
77  delay_400ns();
78  SDA_0();
79  delay_400ns();
80  SCL_0();
81  delay_400ns();
82  SCL_1();
83  delay_400ns();
84  SDA_1();
85  delay_400ns();
86  SCL_0();
87 }
88 /*---------------------------------------------------------------------------*/
89 static void
90 sreset(void)
91 {
92  int i;
93  SDA_1();
94  SCL_0();
95  for(i = 0; i < 9 ; i++) {
96  SCL_1();
97  delay_400ns();
98  SCL_0();
99  delay_400ns();
100  }
101  sstart(); /* Start transmission, why??? */
102 }
103 /*---------------------------------------------------------------------------*/
104 /*
105  * Return true if we received an ACK.
106  */
107 static int
108 swrite(unsigned _c)
109 {
110  unsigned char c = _c;
111  int i;
112  int ret;
113 
114  for(i = 0; i < 8; i++, c <<= 1) {
115  if(c & 0x80) {
116  SDA_1();
117  } else {
118  SDA_0();
119  }
120  SCL_1();
121  delay_400ns();
122  SCL_0();
123  delay_400ns();
124  }
125 
126  SDA_1();
127  SCL_1();
128  delay_400ns();
129  ret = !SDA_IS_1;
130 
131  SCL_0();
132 
133  return ret;
134 }
135 /*---------------------------------------------------------------------------*/
136 static unsigned
137 sread(int send_ack)
138 {
139  int i;
140  unsigned char c = 0x00;
141 
142  SDA_1();
143  for(i = 0; i < 8; i++) {
144  c <<= 1;
145  SCL_1();
146  delay_400ns();
147  if(SDA_IS_1) {
148  c |= 0x1;
149  }
150  SCL_0();
151  delay_400ns();
152  }
153 
154  if(send_ack) {
155  SDA_0();
156  }
157  SCL_1();
158  delay_400ns();
159  SCL_0();
160 
161  SDA_1(); /* Release SDA */
162 
163  return c;
164 }
165 /*---------------------------------------------------------------------------*/
166 #define CRC_CHECK
167 #ifdef CRC_CHECK
168 static unsigned char
169 rev8bits(unsigned char v)
170 {
171  unsigned char r = v;
172  int s = 7;
173 
174  for (v >>= 1; v; v >>= 1) {
175  r <<= 1;
176  r |= v & 1;
177  s--;
178  }
179  r <<= s; /* Shift when v's highest bits are zero */
180  return r;
181 }
182 /*---------------------------------------------------------------------------*/
183 /* BEWARE: Bit reversed CRC8 using polynomial ^8 + ^5 + ^4 + 1 */
184 static unsigned
185 crc8_add(unsigned acc, unsigned byte)
186 {
187  int i;
188  acc ^= byte;
189  for(i = 0; i < 8; i++) {
190  if(acc & 0x80) {
191  acc = (acc << 1) ^ 0x31;
192  } else {
193  acc <<= 1;
194  }
195  }
196  return acc & 0xff;
197 }
198 #endif /* CRC_CHECK */
199 /*---------------------------------------------------------------------------*/
200 /*
201  * Power up the device. The device can be used after an additional
202  * 11ms waiting time.
203  */
204 void
205 sht11_init(void)
206 {
207  /*
208  * SCL Output={0,1}
209  * SDA 0: Output=0
210  * 1: Input and pull-up (Output=0)
211  */
212 #ifdef SHT11_INIT
213  SHT11_INIT();
214 #else
215  SHT11_PxOUT |= BV(SHT11_ARCH_PWR);
216  SHT11_PxOUT &= ~(BV(SHT11_ARCH_SDA) | BV(SHT11_ARCH_SCL));
217  SHT11_PxDIR |= BV(SHT11_ARCH_PWR) | BV(SHT11_ARCH_SCL);
218 #endif
219 }
220 /*---------------------------------------------------------------------------*/
221 /*
222  * Power of device.
223  */
224 void
225 sht11_off(void)
226 {
227 #ifdef SHT11_OFF
228  SHT11_OFF();
229 #else
230  SHT11_PxOUT &= ~BV(SHT11_ARCH_PWR);
231  SHT11_PxOUT &= ~(BV(SHT11_ARCH_SDA) | BV(SHT11_ARCH_SCL));
232  SHT11_PxDIR |= BV(SHT11_ARCH_PWR) | BV(SHT11_ARCH_SCL);
233 #endif
234 }
235 /*---------------------------------------------------------------------------*/
236 /*
237  * Only commands MEASURE_HUMI or MEASURE_TEMP!
238  */
239 static unsigned int
240 scmd(unsigned cmd)
241 {
242  unsigned long n;
243 
244  if(cmd != MEASURE_HUMI && cmd != MEASURE_TEMP) {
245  PRINTF("Illegal command: %d\n", cmd);
246  return -1;
247  }
248 
249  sstart(); /* Start transmission */
250  if(!swrite(cmd)) {
251  PRINTF("SHT11: scmd - swrite failed\n");
252  goto fail;
253  }
254 
255  for(n = 0; n < 250000; n++) {
256  if(!SDA_IS_1) {
257  unsigned t0, t1, rcrc;
258  t0 = sread(1);
259  t1 = sread(1);
260  rcrc = sread(0);
261  PRINTF("SHT11: scmd - read %d, %d\n", t0, t1);
262 #ifdef CRC_CHECK
263  {
264  unsigned crc;
265  crc = crc8_add(0x0, cmd);
266  crc = crc8_add(crc, t0);
267  crc = crc8_add(crc, t1);
268  if(crc != rev8bits(rcrc)) {
269  PRINTF("SHT11: scmd - crc check failed %d vs %d\n",
270  crc, rev8bits(rcrc));
271  goto fail;
272  }
273  }
274 #endif
275  return (t0 << 8) | t1;
276  }
277  }
278 
279  fail:
280  sreset();
281  return -1;
282 }
283 /*---------------------------------------------------------------------------*/
284 /*
285  * Call may take up to 210ms.
286  */
287 unsigned int
288 sht11_temp(void)
289 {
290  return scmd(MEASURE_TEMP);
291 }
292 /*---------------------------------------------------------------------------*/
293 /*
294  * Call may take up to 210ms.
295  */
296 unsigned int
297 sht11_humidity(void)
298 {
299  return scmd(MEASURE_HUMI);
300 }
301 /*---------------------------------------------------------------------------*/
302 #if 1 /* But ok! */
303 unsigned
304 sht11_sreg(void)
305 {
306  unsigned sreg, rcrc;
307 
308  sstart(); /* Start transmission */
309  if(!swrite(STATUS_REG_R)) {
310  goto fail;
311  }
312 
313  sreg = sread(1);
314  rcrc = sread(0);
315 
316 #ifdef CRC_CHECK
317  {
318  unsigned crc;
319  crc = crc8_add(0x0, STATUS_REG_R);
320  crc = crc8_add(crc, sreg);
321  if (crc != rev8bits(rcrc))
322  goto fail;
323  }
324 #endif
325 
326  return sreg;
327 
328  fail:
329  sreset();
330  return -1;
331 }
332 #endif
333 /*---------------------------------------------------------------------------*/
334 #if 0
335 int
336 sht11_set_sreg(unsigned sreg)
337 {
338  sstart(); /* Start transmission */
339  if(!swrite(STATUS_REG_W)) {
340  goto fail;
341  }
342  if(!swrite(sreg)) {
343  goto fail;
344  }
345 
346  return 0;
347 
348  fail:
349  sreset();
350  return -1;
351 }
352 #endif
353 /*---------------------------------------------------------------------------*/
354 #if 0
355 int
356 sht11_reset(void)
357 {
358  sstart(); /* Start transmission */
359  if(!swrite(RESET)) {
360  goto fail;
361  }
362 
363  return 0;
364 
365  fail:
366  sreset();
367  return -1;
368 }
369 #endif
370 /*---------------------------------------------------------------------------*/