Contiki 2.6

sht11.c

00001 /*
00002  * Copyright (c) 2007, Swedish Institute of Computer Science
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the Institute nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  *
00029  * @(#)$Id: sht11.c,v 1.3 2008/11/10 21:10:36 adamdunkels Exp $
00030  */
00031 
00032 /*
00033  * Device driver for the Sensirion SHT1x/SHT7x family of humidity and
00034  * temperature sensors.
00035  */
00036 
00037 #include "contiki.h"
00038 #include <stdio.h>
00039 #include <dev/sht11.h>
00040 #include "sht11-arch.h"
00041 
00042 #define DEBUG 0
00043 
00044 #if DEBUG
00045 #include <stdio.h>
00046 #define PRINTF(...) printf(__VA_ARGS__)
00047 #else
00048 #define PRINTF(...)
00049 #endif
00050 
00051 #ifndef SDA_0
00052 #define SDA_0()   (SHT11_PxDIR |=  BV(SHT11_ARCH_SDA))  /* SDA Output=0 */
00053 #define SDA_1()   (SHT11_PxDIR &= ~BV(SHT11_ARCH_SDA))  /* SDA Input */
00054 #define SDA_IS_1  (SHT11_PxIN & BV(SHT11_ARCH_SDA))
00055 
00056 #define SCL_0()   (SHT11_PxOUT &= ~BV(SHT11_ARCH_SCL))  /* SCL Output=0 */
00057 #define SCL_1()   (SHT11_PxOUT |=  BV(SHT11_ARCH_SCL))  /* SCL Output=1 */
00058 #endif
00059                                 /* adr   command  r/w */
00060 #define  STATUS_REG_W   0x06    /* 000    0011    0 */
00061 #define  STATUS_REG_R   0x07    /* 000    0011    1 */
00062 #define  MEASURE_TEMP   0x03    /* 000    0001    1 */
00063 #define  MEASURE_HUMI   0x05    /* 000    0010    1 */
00064 #define  RESET          0x1e    /* 000    1111    0 */
00065 
00066 /* This can probably be reduced to 250ns according to data sheet. */
00067 #ifndef delay_400ns
00068 #define delay_400ns() _NOP()
00069 #endif
00070 /*---------------------------------------------------------------------------*/
00071 static void
00072 sstart(void)
00073 {
00074   SDA_1(); SCL_0();
00075   delay_400ns();
00076   SCL_1();
00077   delay_400ns();
00078   SDA_0();
00079   delay_400ns();
00080   SCL_0();
00081   delay_400ns();
00082   SCL_1();
00083   delay_400ns();
00084   SDA_1();
00085   delay_400ns();
00086   SCL_0();
00087 }
00088 /*---------------------------------------------------------------------------*/
00089 static void
00090 sreset(void)
00091 {
00092   int i;
00093   SDA_1();
00094   SCL_0();
00095   for(i = 0; i < 9 ; i++) {
00096     SCL_1();
00097     delay_400ns();
00098     SCL_0();
00099     delay_400ns();
00100   }
00101   sstart();                     /* Start transmission, why??? */
00102 }
00103 /*---------------------------------------------------------------------------*/
00104 /*
00105  * Return true if we received an ACK.
00106  */
00107 static int
00108 swrite(unsigned _c)
00109 {
00110   unsigned char c = _c;
00111   int i;
00112   int ret;
00113 
00114   for(i = 0; i < 8; i++, c <<= 1) {
00115     if(c & 0x80) {
00116       SDA_1();
00117     } else {
00118       SDA_0();
00119     }
00120     SCL_1();
00121     delay_400ns();
00122     SCL_0();
00123     delay_400ns();
00124   }
00125 
00126   SDA_1();
00127   SCL_1();
00128   delay_400ns();
00129   ret = !SDA_IS_1;
00130 
00131   SCL_0();
00132 
00133   return ret;
00134 }
00135 /*---------------------------------------------------------------------------*/
00136 static unsigned
00137 sread(int send_ack)
00138 {
00139   int i;
00140   unsigned char c = 0x00;
00141 
00142   SDA_1();
00143   for(i = 0; i < 8; i++) {
00144     c <<= 1;
00145     SCL_1();
00146     delay_400ns();
00147     if(SDA_IS_1) {
00148       c |= 0x1;
00149     }
00150     SCL_0();
00151     delay_400ns();
00152   }
00153 
00154   if(send_ack) {
00155     SDA_0();
00156   }
00157   SCL_1();
00158   delay_400ns();
00159   SCL_0();
00160 
00161   SDA_1();                      /* Release SDA */
00162 
00163   return c;
00164 }
00165 /*---------------------------------------------------------------------------*/
00166 #define CRC_CHECK
00167 #ifdef CRC_CHECK
00168 static unsigned char
00169 rev8bits(unsigned char v)
00170 {
00171   unsigned char r = v;
00172   int s = 7;
00173 
00174   for (v >>= 1; v; v >>= 1) {
00175     r <<= 1;
00176     r |= v & 1;
00177     s--;
00178   }
00179   r <<= s;                  /* Shift when v's highest bits are zero */
00180   return r;
00181 }
00182 /*---------------------------------------------------------------------------*/
00183 /* BEWARE: Bit reversed CRC8 using polynomial ^8 + ^5 + ^4 + 1 */
00184 static unsigned
00185 crc8_add(unsigned acc, unsigned byte)
00186 {
00187   int i;
00188   acc ^= byte;
00189   for(i = 0; i < 8; i++) {
00190     if(acc & 0x80) {
00191       acc = (acc << 1) ^ 0x31;
00192     } else {
00193       acc <<= 1;
00194     }
00195   }
00196   return acc & 0xff;
00197 }
00198 #endif /* CRC_CHECK */
00199 /*---------------------------------------------------------------------------*/
00200 /*
00201  * Power up the device. The device can be used after an additional
00202  * 11ms waiting time.
00203  */
00204 void
00205 sht11_init(void)
00206 {
00207   /*
00208    * SCL Output={0,1}
00209    * SDA 0: Output=0
00210    *     1: Input and pull-up (Output=0)
00211    */
00212 #ifdef SHT11_INIT
00213   SHT11_INIT();
00214 #else
00215   SHT11_PxOUT |= BV(SHT11_ARCH_PWR);
00216   SHT11_PxOUT &= ~(BV(SHT11_ARCH_SDA) | BV(SHT11_ARCH_SCL));
00217   SHT11_PxDIR |= BV(SHT11_ARCH_PWR) | BV(SHT11_ARCH_SCL);
00218 #endif
00219 }
00220 /*---------------------------------------------------------------------------*/
00221 /*
00222  * Power of device.
00223  */
00224 void
00225 sht11_off(void)
00226 {
00227 #ifdef SHT11_OFF
00228   SHT11_OFF();
00229 #else
00230   SHT11_PxOUT &= ~BV(SHT11_ARCH_PWR);
00231   SHT11_PxOUT &= ~(BV(SHT11_ARCH_SDA) | BV(SHT11_ARCH_SCL));
00232   SHT11_PxDIR |= BV(SHT11_ARCH_PWR) | BV(SHT11_ARCH_SCL);
00233 #endif
00234 }
00235 /*---------------------------------------------------------------------------*/
00236 /*
00237  * Only commands MEASURE_HUMI or MEASURE_TEMP!
00238  */
00239 static unsigned int
00240 scmd(unsigned cmd)
00241 {
00242   unsigned long n;
00243 
00244   if(cmd != MEASURE_HUMI && cmd != MEASURE_TEMP) {
00245     PRINTF("Illegal command: %d\n", cmd);
00246     return -1;
00247   }
00248 
00249   sstart();                     /* Start transmission */
00250   if(!swrite(cmd)) {
00251     PRINTF("SHT11: scmd - swrite failed\n");
00252     goto fail;
00253   }
00254 
00255   for(n = 0; n < 250000; n++) {
00256     if(!SDA_IS_1) {
00257       unsigned t0, t1, rcrc;
00258       t0 = sread(1);
00259       t1 = sread(1);
00260       rcrc = sread(0);
00261       PRINTF("SHT11: scmd - read %d, %d\n", t0, t1);
00262 #ifdef CRC_CHECK
00263       {
00264         unsigned crc;
00265         crc = crc8_add(0x0, cmd);
00266         crc = crc8_add(crc, t0);
00267         crc = crc8_add(crc, t1);
00268         if(crc != rev8bits(rcrc)) {
00269           PRINTF("SHT11: scmd - crc check failed %d vs %d\n",
00270                  crc, rev8bits(rcrc));
00271           goto fail;
00272         }
00273       }
00274 #endif
00275       return (t0 << 8) | t1;
00276     }
00277   }
00278 
00279  fail:
00280   sreset();
00281   return -1;
00282 }
00283 /*---------------------------------------------------------------------------*/
00284 /*
00285  * Call may take up to 210ms.
00286  */
00287 unsigned int
00288 sht11_temp(void)
00289 {
00290   return scmd(MEASURE_TEMP);
00291 }
00292 /*---------------------------------------------------------------------------*/
00293 /*
00294  * Call may take up to 210ms.
00295  */
00296 unsigned int
00297 sht11_humidity(void)
00298 {
00299   return scmd(MEASURE_HUMI);
00300 }
00301 /*---------------------------------------------------------------------------*/
00302 #if 1 /* But ok! */
00303 unsigned
00304 sht11_sreg(void)
00305 {
00306   unsigned sreg, rcrc;
00307 
00308   sstart();                     /* Start transmission */
00309   if(!swrite(STATUS_REG_R)) {
00310     goto fail;
00311   }
00312 
00313   sreg = sread(1);
00314   rcrc = sread(0);
00315 
00316 #ifdef CRC_CHECK
00317   {
00318     unsigned crc;
00319     crc = crc8_add(0x0, STATUS_REG_R);
00320     crc = crc8_add(crc, sreg);
00321     if (crc != rev8bits(rcrc))
00322       goto fail;
00323   }
00324 #endif
00325 
00326   return sreg;
00327 
00328  fail:
00329   sreset();
00330   return -1;
00331 }
00332 #endif
00333 /*---------------------------------------------------------------------------*/
00334 #if 0
00335 int
00336 sht11_set_sreg(unsigned sreg)
00337 {
00338   sstart();                     /* Start transmission */
00339   if(!swrite(STATUS_REG_W)) {
00340     goto fail;
00341   }
00342   if(!swrite(sreg)) {
00343     goto fail;
00344   }
00345 
00346   return 0;
00347 
00348  fail:
00349   sreset();
00350   return -1;
00351 }
00352 #endif
00353 /*---------------------------------------------------------------------------*/
00354 #if 0
00355 int
00356 sht11_reset(void)
00357 {
00358   sstart();                     /* Start transmission */
00359   if(!swrite(RESET)) {
00360     goto fail;
00361   }
00362 
00363   return 0;
00364 
00365  fail:
00366   sreset();
00367   return -1;
00368 }
00369 #endif
00370 /*---------------------------------------------------------------------------*/