diff --git a/platform/sky/dev/sht11.c b/platform/sky/dev/sht11.c new file mode 100644 index 000000000..eb4481588 --- /dev/null +++ b/platform/sky/dev/sht11.c @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2007, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)$Id: sht11.c,v 1.1 2007/04/04 12:48:50 bg- Exp $ + */ + +/* + * Device driver for the Sensirion SHT1x/SHT7x family of humidity and + * temperature sensors. + */ + +#include + +#include + +#include + +/* + * SHT11_SDA P1.5 + * SHT11_SCL P1.6 + * SHT11_PWR P1.7 + */ + +#define SDA 5 +#define SCL 6 +#define PWR 7 + +/* Confusingly similar to I2C but not quite :-( */ +#define I2C_PxDIR P1DIR +#define I2C_PxIN P1IN +#define I2C_PxOUT P1OUT +#define I2C_PxSEL P1SEL + +#define SDA_0() (I2C_PxDIR |= BV(SDA)) /* SDA Output=0 */ +#define SDA_1() (I2C_PxDIR &= ~BV(SDA)) /* SDA Input */ +#define SDA_IS_1 (I2C_PxIN & BV(SDA)) + +#define SCL_0() (I2C_PxOUT &= ~BV(SCL)) /* SCL Output=0 */ +#define SCL_1() (I2C_PxOUT |= BV(SCL)) /* SCL Output=1 */ + + /* adr command r/w */ +#define STATUS_REG_W 0x06 /* 000 0011 0 */ +#define STATUS_REG_R 0x07 /* 000 0011 1 */ +#define MEASURE_TEMP 0x03 /* 000 0001 1 */ +#define MEASURE_HUMI 0x05 /* 000 0010 1 */ +#define RESET 0x1e /* 000 1111 0 */ + +/* This can probably be reduced to 250ns according to data sheet. */ +#define delay_400ns() _NOP() + +static void +sstart(void) +{ + SDA_1(); SCL_0(); + delay_400ns(); + SCL_1(); + delay_400ns(); + SDA_0(); + delay_400ns(); + SCL_0(); + delay_400ns(); + SCL_1(); + delay_400ns(); + SDA_1(); + delay_400ns(); + SCL_0(); +} + +static void +sreset(void) +{ + int i; + SDA_1(); SCL_0(); + for (i = 0; i < 9 ; i++) { + SCL_1(); + delay_400ns(); + SCL_0(); + } + sstart(); /* Start transmission, why??? */ +} + +/* + * Return true if we received an ACK. + */ +static int +swrite(unsigned _c) +{ + unsigned char c = _c; + int i; + int ret; + + for (i = 0; i < 8; i++, c <<= 1) { + if (c & 0x80) + SDA_1(); + else + SDA_0(); + SCL_1(); + delay_400ns(); + SCL_0(); + } + + SDA_1(); + SCL_1(); + delay_400ns(); + ret = !SDA_IS_1; + + SCL_0(); + + return ret; +} + +static unsigned +sread(int send_ack) +{ + int i; + unsigned char c = 0x00; + + SDA_1(); + for (i = 0; i < 8; i++) { + c <<= 1; + SCL_1(); + delay_400ns(); + if (SDA_IS_1) + c |= 0x1; + SCL_0(); + } + + if (send_ack) + SDA_0(); + SCL_1(); + delay_400ns(); + SCL_0(); + + SDA_1(); /* Release SDA */ + + return c; +} + +#define CRC_CHECK +#ifdef CRC_CHECK +static unsigned char +rev8bits(unsigned char v) +{ + unsigned char r = v; + int s = 7; + + for (v >>= 1; v; v >>= 1) { + r <<= 1; + r |= v & 1; + s--; + } + r <<= s; /* Shift when v's highest bits are zero */ + return r; +} + +/* BEWARE: Bit reversed CRC8 using polynomial ^8 + ^5 + ^4 + 1 */ +static unsigned +crc8_add(unsigned acc, unsigned byte) +{ + int i; + acc ^= byte; + for (i = 0; i < 8; i++) + if (acc & 0x80) + acc = (acc << 1) ^ 0x31; + else + acc <<= 1; + + return acc & 0xff; +} +#endif /* CRC_CHECK */ + +void +sht11_init(void) +{ + /* + * SCL Output={0,1} + * SDA 0: Output=0 + * 1: Input and pull-up (Output=0) + */ + P1OUT |= BV(PWR); + P1OUT &= ~(BV(SDA) | BV(SCL)); + P1DIR |= BV(PWR) | BV(SCL); +} + +/* + * Only commands MEASURE_HUMI or MEASURE_TEMP! + */ +static unsigned +scmd(unsigned cmd) +{ + unsigned long n; + + if (cmd != MEASURE_HUMI && cmd != MEASURE_TEMP) + return -1; + + sstart(); /* Start transmission */ + if (!swrite(cmd)) + goto fail; + + for (n = 0; n < 250000; n++) + if (!SDA_IS_1) { + unsigned t0, t1, rcrc; + t0 = sread(1); + t1 = sread(1); + rcrc = sread(0); +#ifdef CRC_CHECK + { + unsigned crc; + crc = crc8_add(0x0, cmd); + crc = crc8_add(crc, t0); + crc = crc8_add(crc, t1); + if (crc != rev8bits(rcrc)) + goto fail; + } +#endif + return (t0 << 8) | t1; + } + + fail: + sreset(); + return -1; +} + +unsigned +sht11_temp(void) +{ + return scmd(MEASURE_TEMP); +} + +unsigned +sht11_humidity(void) +{ + return scmd(MEASURE_HUMI); +} + +#if 0 /* But ok! */ +unsigned +sget_sreg(void) +{ + unsigned sreg, rcrc; + + sstart(); /* Start transmission */ + if (!swrite(STATUS_REG_R)) + goto fail; + + sreg = sread(1); + rcrc = sread(0); + +#ifdef CRC_CHECK + { + unsigned crc; + crc = crc8_add(0x0, STATUS_REG_R); + crc = crc8_add(crc, sreg); + if (crc != rev8bits(rcrc)) + goto fail; + } +#endif + + return sreg; + + fail: + sreset(); + return -1; +} +#endif + +#if 0 +unsigned +sset_sreg(unsigned sreg) +{ + sstart(); /* Start transmission */ + if (!swrite(STATUS_REG_W)) + goto fail; + if (!swrite(sreg)) + goto fail; + + return 0; + + fail: + sreset(); + return -1; +} +#endif + +#if 0 +int +sht11_reset(void) +{ + sstart(); /* Start transmission */ + if (!swrite(RESET)) + goto fail; + + return 0; + + fail: + sreset(); + return -1; +} +#endif diff --git a/platform/sky/dev/sht11.h b/platform/sky/dev/sht11.h new file mode 100644 index 000000000..5d0dec87e --- /dev/null +++ b/platform/sky/dev/sht11.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2007, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)$Id: sht11.h,v 1.1 2007/04/04 12:48:50 bg- Exp $ + */ + +#ifndef SHT11_H +#define SHT11_H + +void sht11_init(void); + +unsigned sht11_temp(void); +unsigned sht11_humidity(void); + +#endif /* SHT11_H */