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