Contiki-NG
Loading...
Searching...
No Matches
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/*---------------------------------------------------------------------------*/
70static void
71sstart(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/*---------------------------------------------------------------------------*/
88static void
89sreset(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 */
106static int
107swrite(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/*---------------------------------------------------------------------------*/
135static unsigned
136sread(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
167static unsigned char
168rev8bits(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 */
183static unsigned
184crc8_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 */
203void
204sht11_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 */
233void
234sht11_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 */
248static unsigned int
249scmd(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 */
297unsigned int
298sht11_temp(void)
299{
300 return scmd(MEASURE_TEMP);
301}
302/*---------------------------------------------------------------------------*/
303/*
304 * Call may take up to 210ms.
305 */
306unsigned int
307sht11_humidity(void)
308{
309 return scmd(MEASURE_HUMI);
310}
311/*---------------------------------------------------------------------------*/
312#if 1 /* But ok! */
313unsigned
314sht11_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
345int
346sht11_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
365int
366sht11_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