Interface library for the Sensirion SHT7x series humidity and temperature sensors.

This was developed and tested on the LPC1768 board.

Currently, it doesn't work for LPC11U24. I'm investigating why.

Committer:
JacobBramley
Date:
Sun Aug 11 18:11:05 2013 +0000
Revision:
0:f1a93e55feb5
First Mbed release of the Sensirion SHT7x interface library.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
JacobBramley 0:f1a93e55feb5 1 // Copyright (c) 2013 Jacob Bramley
JacobBramley 0:f1a93e55feb5 2 //
JacobBramley 0:f1a93e55feb5 3 // Permission is hereby granted, free of charge, to any person obtaining a copy
JacobBramley 0:f1a93e55feb5 4 // of this software and associated documentation files (the "Software"), to deal
JacobBramley 0:f1a93e55feb5 5 // in the Software without restriction, including without limitation the rights
JacobBramley 0:f1a93e55feb5 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
JacobBramley 0:f1a93e55feb5 7 // copies of the Software, and to permit persons to whom the Software is
JacobBramley 0:f1a93e55feb5 8 // furnished to do so, subject to the following conditions:
JacobBramley 0:f1a93e55feb5 9 //
JacobBramley 0:f1a93e55feb5 10 // The above copyright notice and this permission notice shall be included in
JacobBramley 0:f1a93e55feb5 11 // all copies or substantial portions of the Software.
JacobBramley 0:f1a93e55feb5 12 //
JacobBramley 0:f1a93e55feb5 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
JacobBramley 0:f1a93e55feb5 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
JacobBramley 0:f1a93e55feb5 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
JacobBramley 0:f1a93e55feb5 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
JacobBramley 0:f1a93e55feb5 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
JacobBramley 0:f1a93e55feb5 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
JacobBramley 0:f1a93e55feb5 19 // SOFTWARE.
JacobBramley 0:f1a93e55feb5 20
JacobBramley 0:f1a93e55feb5 21 #define __STC_LIMIT_MACROS
JacobBramley 0:f1a93e55feb5 22 #include <stdint.h>
JacobBramley 0:f1a93e55feb5 23 #include <stddef.h>
JacobBramley 0:f1a93e55feb5 24 #include <new>
JacobBramley 0:f1a93e55feb5 25 #include <math.h>
JacobBramley 0:f1a93e55feb5 26 #include <limits>
JacobBramley 0:f1a93e55feb5 27 #include "mbed.h"
JacobBramley 0:f1a93e55feb5 28 #include "sht7x.h"
JacobBramley 0:f1a93e55feb5 29
JacobBramley 0:f1a93e55feb5 30 // For some reason, Mbed's stdint.h doesn't define INT64_MIN.
JacobBramley 0:f1a93e55feb5 31 #ifndef INT64_MIN
JacobBramley 0:f1a93e55feb5 32 #define INT64_MIN (-0x8000000000000000)
JacobBramley 0:f1a93e55feb5 33 #endif
JacobBramley 0:f1a93e55feb5 34
JacobBramley 0:f1a93e55feb5 35 #ifdef TARGET_LPC11U24
JacobBramley 0:f1a93e55feb5 36 #define SLEEP() sleep()
JacobBramley 0:f1a93e55feb5 37 #else
JacobBramley 0:f1a93e55feb5 38 #define SLEEP() /* Busy-wait */
JacobBramley 0:f1a93e55feb5 39 #endif
JacobBramley 0:f1a93e55feb5 40
JacobBramley 0:f1a93e55feb5 41 namespace sht7x {
JacobBramley 0:f1a93e55feb5 42
JacobBramley 0:f1a93e55feb5 43 // ==== Public interface. ====
JacobBramley 0:f1a93e55feb5 44
JacobBramley 0:f1a93e55feb5 45 SHT7x::SHT7x(PinName sck, PinName sda)
JacobBramley 0:f1a93e55feb5 46 : sck_(DigitalOut(sck)), sda_(DigitalInOut(sda)) {
JacobBramley 0:f1a93e55feb5 47 sck_state_ = PIN_INVALID;
JacobBramley 0:f1a93e55feb5 48 sda_state_ = PIN_INVALID;
JacobBramley 0:f1a93e55feb5 49 state_ = STATE_UNKNOWN;
JacobBramley 0:f1a93e55feb5 50
JacobBramley 0:f1a93e55feb5 51 // The default sensor configuration, according to the datasheet.
JacobBramley 0:f1a93e55feb5 52 status_.precision = PRECISION_HIGH;
JacobBramley 0:f1a93e55feb5 53 status_.otp = OTP_ON;
JacobBramley 0:f1a93e55feb5 54 status_.heater = HEATER_OFF;
JacobBramley 0:f1a93e55feb5 55 status_.battery = BATTERY_GT_2_47;
JacobBramley 0:f1a93e55feb5 56
JacobBramley 0:f1a93e55feb5 57 // Configure the pins, but do nothing else at this point.
JacobBramley 0:f1a93e55feb5 58 sda_.mode(OpenDrain);
JacobBramley 0:f1a93e55feb5 59 sda_.output();
JacobBramley 0:f1a93e55feb5 60 this->set_sda(PIN_FREE);
JacobBramley 0:f1a93e55feb5 61 this->set_sck(PIN_0);
JacobBramley 0:f1a93e55feb5 62 }
JacobBramley 0:f1a93e55feb5 63
JacobBramley 0:f1a93e55feb5 64
JacobBramley 0:f1a93e55feb5 65 bool SHT7x::reset() {
JacobBramley 0:f1a93e55feb5 66 if (!check_state(STATE_UNKNOWN, STATE_SLEEP, STATE_COMMS_ERROR)) {
JacobBramley 0:f1a93e55feb5 67 return false;
JacobBramley 0:f1a93e55feb5 68 }
JacobBramley 0:f1a93e55feb5 69 state_ = STATE_RESETTING;
JacobBramley 0:f1a93e55feb5 70
JacobBramley 0:f1a93e55feb5 71 // If we're trying to reset the sensor, it's likely that the communications
JacobBramley 0:f1a93e55feb5 72 // channel has got into a weird state. We need it up and running in order to
JacobBramley 0:f1a93e55feb5 73 // send the reset command.
JacobBramley 0:f1a93e55feb5 74 reset_comms();
JacobBramley 0:f1a93e55feb5 75
JacobBramley 0:f1a93e55feb5 76 command(CMD_RESET);
JacobBramley 0:f1a93e55feb5 77 state_ = STATE_UNKNOWN;
JacobBramley 0:f1a93e55feb5 78
JacobBramley 0:f1a93e55feb5 79 status_.precision = PRECISION_HIGH;
JacobBramley 0:f1a93e55feb5 80 status_.otp = OTP_ON;
JacobBramley 0:f1a93e55feb5 81 status_.heater = HEATER_OFF;
JacobBramley 0:f1a93e55feb5 82 status_.battery = BATTERY_GT_2_47;
JacobBramley 0:f1a93e55feb5 83
JacobBramley 0:f1a93e55feb5 84 return true;
JacobBramley 0:f1a93e55feb5 85 }
JacobBramley 0:f1a93e55feb5 86
JacobBramley 0:f1a93e55feb5 87
JacobBramley 0:f1a93e55feb5 88 bool SHT7x::initialize() {
JacobBramley 0:f1a93e55feb5 89 if (!check_state(STATE_UNKNOWN)) {
JacobBramley 0:f1a93e55feb5 90 return false;
JacobBramley 0:f1a93e55feb5 91 }
JacobBramley 0:f1a93e55feb5 92 state_ = STATE_INITIALIZING;
JacobBramley 0:f1a93e55feb5 93
JacobBramley 0:f1a93e55feb5 94 // Wait for the sensor to turn on.
JacobBramley 0:f1a93e55feb5 95 // There is no external notification that the sensor is ready, so a timer
JacobBramley 0:f1a93e55feb5 96 // is the only option here.
JacobBramley 0:f1a93e55feb5 97 wait_us(time_reset());
JacobBramley 0:f1a93e55feb5 98
JacobBramley 0:f1a93e55feb5 99 state_ = STATE_SLEEP;
JacobBramley 0:f1a93e55feb5 100
JacobBramley 0:f1a93e55feb5 101 // Make sure that the cached status byte is up to date.
JacobBramley 0:f1a93e55feb5 102 return status();
JacobBramley 0:f1a93e55feb5 103 }
JacobBramley 0:f1a93e55feb5 104
JacobBramley 0:f1a93e55feb5 105
JacobBramley 0:f1a93e55feb5 106 bool SHT7x::configure(Precision precision, OTP otp, Heater heater) {
JacobBramley 0:f1a93e55feb5 107 if (!check_state(STATE_SLEEP)) {
JacobBramley 0:f1a93e55feb5 108 return false;
JacobBramley 0:f1a93e55feb5 109 }
JacobBramley 0:f1a93e55feb5 110 state_ = STATE_SETTING_CONFIGURATION;
JacobBramley 0:f1a93e55feb5 111
JacobBramley 0:f1a93e55feb5 112 // Overlay the new status on the existing one.
JacobBramley 0:f1a93e55feb5 113 if (precision != PRECISION_KEEP) { status_.precision = precision; }
JacobBramley 0:f1a93e55feb5 114 if (otp != OTP_KEEP) { status_.otp = otp; }
JacobBramley 0:f1a93e55feb5 115 if (heater != HEATER_KEEP) { status_.heater = heater; }
JacobBramley 0:f1a93e55feb5 116
JacobBramley 0:f1a93e55feb5 117 // Write the status byte.
JacobBramley 0:f1a93e55feb5 118 command(CMD_WRITE_STATUS);
JacobBramley 0:f1a93e55feb5 119 put_byte(encode_status_byte());
JacobBramley 0:f1a93e55feb5 120 get_ack();
JacobBramley 0:f1a93e55feb5 121
JacobBramley 0:f1a93e55feb5 122 // TODO: It's not obvious how to get a CRC byte from this command. Is it
JacobBramley 0:f1a93e55feb5 123 // necessary to read the status back again?
JacobBramley 0:f1a93e55feb5 124
JacobBramley 0:f1a93e55feb5 125 state_ = STATE_SLEEP;
JacobBramley 0:f1a93e55feb5 126 return true;
JacobBramley 0:f1a93e55feb5 127 }
JacobBramley 0:f1a93e55feb5 128
JacobBramley 0:f1a93e55feb5 129
JacobBramley 0:f1a93e55feb5 130 bool SHT7x::status() {
JacobBramley 0:f1a93e55feb5 131 if (!check_state(STATE_SLEEP)) {
JacobBramley 0:f1a93e55feb5 132 return false;
JacobBramley 0:f1a93e55feb5 133 }
JacobBramley 0:f1a93e55feb5 134
JacobBramley 0:f1a93e55feb5 135 // Read the status register to populate the cached values.
JacobBramley 0:f1a93e55feb5 136 command(CMD_READ_STATUS);
JacobBramley 0:f1a93e55feb5 137 uint32_t raw = get_byte();
JacobBramley 0:f1a93e55feb5 138 put_ack(0);
JacobBramley 0:f1a93e55feb5 139 uint32_t crc = get_byte();
JacobBramley 0:f1a93e55feb5 140 put_ack(1);
JacobBramley 0:f1a93e55feb5 141
JacobBramley 0:f1a93e55feb5 142 // We must decode the status byte before checking the CRC because the status
JacobBramley 0:f1a93e55feb5 143 // register is used to initialize the CRC check.
JacobBramley 0:f1a93e55feb5 144 decode_status_byte(raw);
JacobBramley 0:f1a93e55feb5 145
JacobBramley 0:f1a93e55feb5 146 if (check_crc(CMD_READ_STATUS, raw, crc)) {
JacobBramley 0:f1a93e55feb5 147 state_ = STATE_SLEEP;
JacobBramley 0:f1a93e55feb5 148 } else {
JacobBramley 0:f1a93e55feb5 149 state_ = STATE_COMMS_ERROR;
JacobBramley 0:f1a93e55feb5 150 }
JacobBramley 0:f1a93e55feb5 151
JacobBramley 0:f1a93e55feb5 152 return true;
JacobBramley 0:f1a93e55feb5 153 }
JacobBramley 0:f1a93e55feb5 154
JacobBramley 0:f1a93e55feb5 155
JacobBramley 0:f1a93e55feb5 156 bool SHT7x::status(Status * & status) {
JacobBramley 0:f1a93e55feb5 157 if (this->status()) {
JacobBramley 0:f1a93e55feb5 158 status = &status_;
JacobBramley 0:f1a93e55feb5 159 return true;
JacobBramley 0:f1a93e55feb5 160 }
JacobBramley 0:f1a93e55feb5 161 return false;
JacobBramley 0:f1a93e55feb5 162 }
JacobBramley 0:f1a93e55feb5 163
JacobBramley 0:f1a93e55feb5 164
JacobBramley 0:f1a93e55feb5 165 bool SHT7x::measure(Temp & temp, uint32_t mvdd) {
JacobBramley 0:f1a93e55feb5 166 if (!check_state(STATE_SLEEP)) {
JacobBramley 0:f1a93e55feb5 167 return false;
JacobBramley 0:f1a93e55feb5 168 }
JacobBramley 0:f1a93e55feb5 169 state_ = STATE_MEASURING_TEMPERATURE;
JacobBramley 0:f1a93e55feb5 170
JacobBramley 0:f1a93e55feb5 171 // TODO: Wait for sda low, rather than a timer.
JacobBramley 0:f1a93e55feb5 172 command(CMD_READ_TEMP);
JacobBramley 0:f1a93e55feb5 173 wait_us(time_reading_temperature());
JacobBramley 0:f1a93e55feb5 174
JacobBramley 0:f1a93e55feb5 175 uint32_t raw = get_byte() << 8;
JacobBramley 0:f1a93e55feb5 176 put_ack(0);
JacobBramley 0:f1a93e55feb5 177 raw |= get_byte() << 0;
JacobBramley 0:f1a93e55feb5 178 put_ack(0);
JacobBramley 0:f1a93e55feb5 179 uint32_t crc = get_byte();
JacobBramley 0:f1a93e55feb5 180 put_ack(1);
JacobBramley 0:f1a93e55feb5 181
JacobBramley 0:f1a93e55feb5 182 if (check_crc(CMD_READ_TEMP, raw, crc)) {
JacobBramley 0:f1a93e55feb5 183 new (&temp) Temp(bits_required_temperature(), raw, mvdd);
JacobBramley 0:f1a93e55feb5 184 state_ = STATE_SLEEP;
JacobBramley 0:f1a93e55feb5 185
JacobBramley 0:f1a93e55feb5 186 // Make sure that the cached status byte is up to date.
JacobBramley 0:f1a93e55feb5 187 // In particular, the Vdd voltage detection is updated after a measurement.
JacobBramley 0:f1a93e55feb5 188 return status();
JacobBramley 0:f1a93e55feb5 189 }
JacobBramley 0:f1a93e55feb5 190
JacobBramley 0:f1a93e55feb5 191 new (&temp) Temp();
JacobBramley 0:f1a93e55feb5 192 state_ = STATE_COMMS_ERROR;
JacobBramley 0:f1a93e55feb5 193 return false;
JacobBramley 0:f1a93e55feb5 194 }
JacobBramley 0:f1a93e55feb5 195
JacobBramley 0:f1a93e55feb5 196
JacobBramley 0:f1a93e55feb5 197 bool SHT7x::measure(Hum & hum, Temp const * temp) {
JacobBramley 0:f1a93e55feb5 198 if (!check_state(STATE_SLEEP)) {
JacobBramley 0:f1a93e55feb5 199 return false;
JacobBramley 0:f1a93e55feb5 200 }
JacobBramley 0:f1a93e55feb5 201 state_ = STATE_MEASURING_HUMIDITY;
JacobBramley 0:f1a93e55feb5 202
JacobBramley 0:f1a93e55feb5 203 // TODO: Wait for sda low, rather than a timer.
JacobBramley 0:f1a93e55feb5 204 command(CMD_READ_HUM);
JacobBramley 0:f1a93e55feb5 205 wait_us(time_reading_humidity());
JacobBramley 0:f1a93e55feb5 206
JacobBramley 0:f1a93e55feb5 207 // Two bytes are sent even for 8-bit humidity readings.
JacobBramley 0:f1a93e55feb5 208 uint32_t raw = get_byte() << 8;
JacobBramley 0:f1a93e55feb5 209 put_ack(0);
JacobBramley 0:f1a93e55feb5 210 raw |= get_byte() << 0;
JacobBramley 0:f1a93e55feb5 211 put_ack(0);
JacobBramley 0:f1a93e55feb5 212 uint32_t crc = get_byte();
JacobBramley 0:f1a93e55feb5 213 put_ack(1);
JacobBramley 0:f1a93e55feb5 214
JacobBramley 0:f1a93e55feb5 215 if (check_crc(CMD_READ_HUM, raw, crc)) {
JacobBramley 0:f1a93e55feb5 216 new (&hum) Hum(bits_required_humidity(), raw, temp);
JacobBramley 0:f1a93e55feb5 217 state_ = STATE_SLEEP;
JacobBramley 0:f1a93e55feb5 218
JacobBramley 0:f1a93e55feb5 219 // Make sure that the cached status byte is up to date.
JacobBramley 0:f1a93e55feb5 220 // In particular, the Vdd voltage detection is updated after a measurement.
JacobBramley 0:f1a93e55feb5 221 return status();
JacobBramley 0:f1a93e55feb5 222 }
JacobBramley 0:f1a93e55feb5 223
JacobBramley 0:f1a93e55feb5 224 new (&hum) Hum();
JacobBramley 0:f1a93e55feb5 225 state_ = STATE_COMMS_ERROR;
JacobBramley 0:f1a93e55feb5 226 return false;
JacobBramley 0:f1a93e55feb5 227 }
JacobBramley 0:f1a93e55feb5 228
JacobBramley 0:f1a93e55feb5 229
JacobBramley 0:f1a93e55feb5 230 // ==== Internal methods. ====
JacobBramley 0:f1a93e55feb5 231
JacobBramley 0:f1a93e55feb5 232 // Construct a status register value, suitable for writing with
JacobBramley 0:f1a93e55feb5 233 // CMD_WRITE_STATUS, from cached values.
JacobBramley 0:f1a93e55feb5 234 uint32_t SHT7x::encode_status_byte() const {
JacobBramley 0:f1a93e55feb5 235 uint8_t value = 0;
JacobBramley 0:f1a93e55feb5 236 value |= (status_.precision == PRECISION_LOW ) ? (0x01) : (0x00);
JacobBramley 0:f1a93e55feb5 237 value |= (status_.otp == OTP_OFF ) ? (0x02) : (0x00);
JacobBramley 0:f1a93e55feb5 238 value |= (status_.heater == HEATER_ON ) ? (0x04) : (0x00);
JacobBramley 0:f1a93e55feb5 239 value |= (status_.battery == BATTERY_LT_2_47) ? (0x40) : (0x00);
JacobBramley 0:f1a93e55feb5 240 return value;
JacobBramley 0:f1a93e55feb5 241 }
JacobBramley 0:f1a93e55feb5 242
JacobBramley 0:f1a93e55feb5 243
JacobBramley 0:f1a93e55feb5 244 // Update the cached status values with a status register value obtained from
JacobBramley 0:f1a93e55feb5 245 // the sensor using CMD_READ_STATUS.
JacobBramley 0:f1a93e55feb5 246 void SHT7x::decode_status_byte(uint32_t value) {
JacobBramley 0:f1a93e55feb5 247 status_.precision = (value & 0x01) ? PRECISION_LOW : PRECISION_HIGH;
JacobBramley 0:f1a93e55feb5 248 status_.otp = (value & 0x02) ? OTP_OFF : OTP_ON;
JacobBramley 0:f1a93e55feb5 249 status_.heater = (value & 0x04) ? HEATER_ON : HEATER_OFF;
JacobBramley 0:f1a93e55feb5 250 status_.battery = (value & 0x40) ? BATTERY_LT_2_47 : BATTERY_GT_2_47;
JacobBramley 0:f1a93e55feb5 251 }
JacobBramley 0:f1a93e55feb5 252
JacobBramley 0:f1a93e55feb5 253
JacobBramley 0:f1a93e55feb5 254 inline uint32_t SHT7x::bits_required_temperature() const {
JacobBramley 0:f1a93e55feb5 255 switch (status_.precision) {
JacobBramley 0:f1a93e55feb5 256 default:
JacobBramley 0:f1a93e55feb5 257 case PRECISION_HIGH: return 14;
JacobBramley 0:f1a93e55feb5 258 case PRECISION_LOW: return 12;
JacobBramley 0:f1a93e55feb5 259 }
JacobBramley 0:f1a93e55feb5 260 }
JacobBramley 0:f1a93e55feb5 261
JacobBramley 0:f1a93e55feb5 262
JacobBramley 0:f1a93e55feb5 263 inline uint32_t SHT7x::bits_required_humidity() const {
JacobBramley 0:f1a93e55feb5 264 switch (status_.precision) {
JacobBramley 0:f1a93e55feb5 265 default:
JacobBramley 0:f1a93e55feb5 266 case PRECISION_HIGH: return 12;
JacobBramley 0:f1a93e55feb5 267 case PRECISION_LOW: return 8;
JacobBramley 0:f1a93e55feb5 268 }
JacobBramley 0:f1a93e55feb5 269 }
JacobBramley 0:f1a93e55feb5 270
JacobBramley 0:f1a93e55feb5 271
JacobBramley 0:f1a93e55feb5 272 inline uint32_t SHT7x::time_atom() const {
JacobBramley 0:f1a93e55feb5 273 return 1;
JacobBramley 0:f1a93e55feb5 274 }
JacobBramley 0:f1a93e55feb5 275
JacobBramley 0:f1a93e55feb5 276
JacobBramley 0:f1a93e55feb5 277 inline uint32_t SHT7x::time_reset() const {
JacobBramley 0:f1a93e55feb5 278 return 11000;
JacobBramley 0:f1a93e55feb5 279 }
JacobBramley 0:f1a93e55feb5 280
JacobBramley 0:f1a93e55feb5 281
JacobBramley 0:f1a93e55feb5 282 inline uint32_t SHT7x::time_reading_temperature() const {
JacobBramley 0:f1a93e55feb5 283 switch (status_.precision) {
JacobBramley 0:f1a93e55feb5 284 default:
JacobBramley 0:f1a93e55feb5 285 case PRECISION_HIGH: return 320000; // 320ms, 14 bits
JacobBramley 0:f1a93e55feb5 286 case PRECISION_LOW: return 80000; // 80ms, 12 bits
JacobBramley 0:f1a93e55feb5 287 }
JacobBramley 0:f1a93e55feb5 288 }
JacobBramley 0:f1a93e55feb5 289
JacobBramley 0:f1a93e55feb5 290
JacobBramley 0:f1a93e55feb5 291 inline uint32_t SHT7x::time_reading_humidity() const {
JacobBramley 0:f1a93e55feb5 292 switch (status_.precision) {
JacobBramley 0:f1a93e55feb5 293 default:
JacobBramley 0:f1a93e55feb5 294 case PRECISION_HIGH: return 80000; // 80ms, 12 bits
JacobBramley 0:f1a93e55feb5 295 case PRECISION_LOW: return 20000; // 20ms, 8 bits
JacobBramley 0:f1a93e55feb5 296 }
JacobBramley 0:f1a93e55feb5 297 }
JacobBramley 0:f1a93e55feb5 298
JacobBramley 0:f1a93e55feb5 299
JacobBramley 0:f1a93e55feb5 300 void SHT7x::start() {
JacobBramley 0:f1a93e55feb5 301 uint32_t const t = time_atom();
JacobBramley 0:f1a93e55feb5 302
JacobBramley 0:f1a93e55feb5 303 set_sda(PIN_1); wait_us(t);
JacobBramley 0:f1a93e55feb5 304 set_sck(PIN_1); wait_us(t);
JacobBramley 0:f1a93e55feb5 305 set_sda(PIN_0); wait_us(t);
JacobBramley 0:f1a93e55feb5 306 set_sck(PIN_0); wait_us(t);
JacobBramley 0:f1a93e55feb5 307 wait_us(t);
JacobBramley 0:f1a93e55feb5 308 set_sck(PIN_1); wait_us(t);
JacobBramley 0:f1a93e55feb5 309 set_sda(PIN_1); wait_us(t);
JacobBramley 0:f1a93e55feb5 310 set_sck(PIN_0); wait_us(t);
JacobBramley 0:f1a93e55feb5 311 }
JacobBramley 0:f1a93e55feb5 312
JacobBramley 0:f1a93e55feb5 313
JacobBramley 0:f1a93e55feb5 314 void SHT7x::put_bit(int b) {
JacobBramley 0:f1a93e55feb5 315 uint32_t const t = time_atom();
JacobBramley 0:f1a93e55feb5 316
JacobBramley 0:f1a93e55feb5 317 set_sda(b); wait_us(t);
JacobBramley 0:f1a93e55feb5 318 set_sck(PIN_1); wait_us(t);
JacobBramley 0:f1a93e55feb5 319 wait_us(t);
JacobBramley 0:f1a93e55feb5 320 set_sck(PIN_0); wait_us(t);
JacobBramley 0:f1a93e55feb5 321 }
JacobBramley 0:f1a93e55feb5 322
JacobBramley 0:f1a93e55feb5 323
JacobBramley 0:f1a93e55feb5 324 int SHT7x::get_bit() {
JacobBramley 0:f1a93e55feb5 325 uint32_t const t = time_atom();
JacobBramley 0:f1a93e55feb5 326
JacobBramley 0:f1a93e55feb5 327 set_sda(PIN_FREE); wait_us(t);
JacobBramley 0:f1a93e55feb5 328 set_sck(PIN_1); wait_us(t);
JacobBramley 0:f1a93e55feb5 329 int b = sda_; wait_us(t);
JacobBramley 0:f1a93e55feb5 330 set_sck(PIN_0); wait_us(t);
JacobBramley 0:f1a93e55feb5 331
JacobBramley 0:f1a93e55feb5 332 return b;
JacobBramley 0:f1a93e55feb5 333 }
JacobBramley 0:f1a93e55feb5 334
JacobBramley 0:f1a93e55feb5 335
JacobBramley 0:f1a93e55feb5 336 // The protocol uses three different ACKs: One input ACK and two output ACKs. A
JacobBramley 0:f1a93e55feb5 337 // high output ACK usually ends a transmission. A low output ACK usually
JacobBramley 0:f1a93e55feb5 338 // acknowledges a byte as part of a transmission. Refer to the SHT7x datasheet
JacobBramley 0:f1a93e55feb5 339 // for details.
JacobBramley 0:f1a93e55feb5 340 void SHT7x::put_ack(int b) {
JacobBramley 0:f1a93e55feb5 341 uint32_t const t = time_atom();
JacobBramley 0:f1a93e55feb5 342
JacobBramley 0:f1a93e55feb5 343 set_sda(b); wait_us(t);
JacobBramley 0:f1a93e55feb5 344 set_sck(PIN_1); wait_us(t);
JacobBramley 0:f1a93e55feb5 345 wait_us(t);
JacobBramley 0:f1a93e55feb5 346 set_sck(PIN_0); wait_us(t);
JacobBramley 0:f1a93e55feb5 347 set_sda(PIN_FREE); wait_us(t);
JacobBramley 0:f1a93e55feb5 348 }
JacobBramley 0:f1a93e55feb5 349
JacobBramley 0:f1a93e55feb5 350
JacobBramley 0:f1a93e55feb5 351 void SHT7x::get_ack() {
JacobBramley 0:f1a93e55feb5 352 uint32_t const t = time_atom();
JacobBramley 0:f1a93e55feb5 353
JacobBramley 0:f1a93e55feb5 354 set_sda(PIN_FREE); wait_us(t);
JacobBramley 0:f1a93e55feb5 355 set_sck(PIN_1); wait_us(t);
JacobBramley 0:f1a93e55feb5 356 wait_us(t);
JacobBramley 0:f1a93e55feb5 357 set_sck(PIN_0); wait_us(t);
JacobBramley 0:f1a93e55feb5 358 }
JacobBramley 0:f1a93e55feb5 359
JacobBramley 0:f1a93e55feb5 360
JacobBramley 0:f1a93e55feb5 361 void SHT7x::put_byte(uint32_t byte) {
JacobBramley 0:f1a93e55feb5 362 // TODO: Unroll this.
JacobBramley 0:f1a93e55feb5 363 for (uint32_t i = 0; i < 8; i++) {
JacobBramley 0:f1a93e55feb5 364 put_bit((byte >> (7-i)) & 1);
JacobBramley 0:f1a93e55feb5 365 }
JacobBramley 0:f1a93e55feb5 366 }
JacobBramley 0:f1a93e55feb5 367
JacobBramley 0:f1a93e55feb5 368
JacobBramley 0:f1a93e55feb5 369 uint32_t SHT7x::get_byte() {
JacobBramley 0:f1a93e55feb5 370 uint32_t byte = 0;
JacobBramley 0:f1a93e55feb5 371 // TODO: Unroll this.
JacobBramley 0:f1a93e55feb5 372 for (uint32_t i = 0; i < 8; i++) {
JacobBramley 0:f1a93e55feb5 373 byte = (byte << 1) | get_bit();
JacobBramley 0:f1a93e55feb5 374 }
JacobBramley 0:f1a93e55feb5 375 return byte;
JacobBramley 0:f1a93e55feb5 376 }
JacobBramley 0:f1a93e55feb5 377
JacobBramley 0:f1a93e55feb5 378
JacobBramley 0:f1a93e55feb5 379 inline int SHT7x::get_sda() {
JacobBramley 0:f1a93e55feb5 380 return sda_.read();
JacobBramley 0:f1a93e55feb5 381 }
JacobBramley 0:f1a93e55feb5 382
JacobBramley 0:f1a93e55feb5 383
JacobBramley 0:f1a93e55feb5 384 inline void SHT7x::set_sda(int pin) {
JacobBramley 0:f1a93e55feb5 385 set_sda((pin) ? (PIN_1) : (PIN_0));
JacobBramley 0:f1a93e55feb5 386 }
JacobBramley 0:f1a93e55feb5 387
JacobBramley 0:f1a93e55feb5 388
JacobBramley 0:f1a93e55feb5 389 inline void SHT7x::set_sda(pin_State pin) {
JacobBramley 0:f1a93e55feb5 390 if (sda_state_ != pin) {
JacobBramley 0:f1a93e55feb5 391 sda_ = (pin == PIN_0) ? (0) : (1);
JacobBramley 0:f1a93e55feb5 392 sda_state_ = pin;
JacobBramley 0:f1a93e55feb5 393 }
JacobBramley 0:f1a93e55feb5 394 }
JacobBramley 0:f1a93e55feb5 395
JacobBramley 0:f1a93e55feb5 396
JacobBramley 0:f1a93e55feb5 397 inline void SHT7x::set_sck(int pin) {
JacobBramley 0:f1a93e55feb5 398 set_sck((pin) ? (PIN_1) : (PIN_0));
JacobBramley 0:f1a93e55feb5 399 }
JacobBramley 0:f1a93e55feb5 400
JacobBramley 0:f1a93e55feb5 401
JacobBramley 0:f1a93e55feb5 402 inline void SHT7x::set_sck(pin_State pin) {
JacobBramley 0:f1a93e55feb5 403 if (sck_state_ != pin) {
JacobBramley 0:f1a93e55feb5 404 sck_ = (pin == PIN_0) ? (0) : (1);
JacobBramley 0:f1a93e55feb5 405 sck_state_ = pin;
JacobBramley 0:f1a93e55feb5 406 }
JacobBramley 0:f1a93e55feb5 407 }
JacobBramley 0:f1a93e55feb5 408
JacobBramley 0:f1a93e55feb5 409
JacobBramley 0:f1a93e55feb5 410 void SHT7x::reset_comms() {
JacobBramley 0:f1a93e55feb5 411 for (uint32_t i = 0; i < 9; i++) {
JacobBramley 0:f1a93e55feb5 412 put_bit(1);
JacobBramley 0:f1a93e55feb5 413 }
JacobBramley 0:f1a93e55feb5 414 }
JacobBramley 0:f1a93e55feb5 415
JacobBramley 0:f1a93e55feb5 416
JacobBramley 0:f1a93e55feb5 417 void SHT7x::command(Command command) {
JacobBramley 0:f1a93e55feb5 418 start();
JacobBramley 0:f1a93e55feb5 419 put_byte(static_cast<uint32_t>(command));
JacobBramley 0:f1a93e55feb5 420 get_ack();
JacobBramley 0:f1a93e55feb5 421 }
JacobBramley 0:f1a93e55feb5 422
JacobBramley 0:f1a93e55feb5 423
JacobBramley 0:f1a93e55feb5 424 bool SHT7x::check_state(State s0) {
JacobBramley 0:f1a93e55feb5 425 State state = state_;
JacobBramley 0:f1a93e55feb5 426 return state == s0;
JacobBramley 0:f1a93e55feb5 427 }
JacobBramley 0:f1a93e55feb5 428
JacobBramley 0:f1a93e55feb5 429
JacobBramley 0:f1a93e55feb5 430 bool SHT7x::check_state(State s0, State s1) {
JacobBramley 0:f1a93e55feb5 431 State state = state_;
JacobBramley 0:f1a93e55feb5 432 return (state == s0) || (state == s1);
JacobBramley 0:f1a93e55feb5 433 }
JacobBramley 0:f1a93e55feb5 434
JacobBramley 0:f1a93e55feb5 435
JacobBramley 0:f1a93e55feb5 436 bool SHT7x::check_state(State s0, State s1, State s2) {
JacobBramley 0:f1a93e55feb5 437 State state = state_;
JacobBramley 0:f1a93e55feb5 438 return (state == s0) || (state == s1) || (state == s2);
JacobBramley 0:f1a93e55feb5 439 }
JacobBramley 0:f1a93e55feb5 440
JacobBramley 0:f1a93e55feb5 441
JacobBramley 0:f1a93e55feb5 442 int SHT7x::payload_size(Command command) {
JacobBramley 0:f1a93e55feb5 443 switch (command) {
JacobBramley 0:f1a93e55feb5 444 case CMD_READ_TEMP:
JacobBramley 0:f1a93e55feb5 445 case CMD_READ_HUM: return 2;
JacobBramley 0:f1a93e55feb5 446 case CMD_READ_STATUS:
JacobBramley 0:f1a93e55feb5 447 case CMD_WRITE_STATUS: return 1;
JacobBramley 0:f1a93e55feb5 448 case CMD_RESET:
JacobBramley 0:f1a93e55feb5 449 default: return 0;
JacobBramley 0:f1a93e55feb5 450 }
JacobBramley 0:f1a93e55feb5 451 }
JacobBramley 0:f1a93e55feb5 452
JacobBramley 0:f1a93e55feb5 453
JacobBramley 0:f1a93e55feb5 454 bool SHT7x::check_crc(Command command, uint32_t data, uint32_t crc_in) {
JacobBramley 0:f1a93e55feb5 455 int const data_bits = payload_size(command) * 8;
JacobBramley 0:f1a93e55feb5 456 int const bits = data_bits + 8;
JacobBramley 0:f1a93e55feb5 457
JacobBramley 0:f1a93e55feb5 458 data |= command << data_bits;
JacobBramley 0:f1a93e55feb5 459
JacobBramley 0:f1a93e55feb5 460 // The Sensirion application note describes an algorithm which reverses the
JacobBramley 0:f1a93e55feb5 461 // bits in the status byte to form the initial CRC, performs the CRC
JacobBramley 0:f1a93e55feb5 462 // calculation, then reverses the bits again at the end. This CRC
JacobBramley 0:f1a93e55feb5 463 // implementation operates in reverse, so there is no need to reverse the CRC.
JacobBramley 0:f1a93e55feb5 464
JacobBramley 0:f1a93e55feb5 465 // TODO: Optimize this further, if possible.
JacobBramley 0:f1a93e55feb5 466
JacobBramley 0:f1a93e55feb5 467 // The CRC is initialized with the status byte.
JacobBramley 0:f1a93e55feb5 468 uint32_t crc = encode_status_byte();
JacobBramley 0:f1a93e55feb5 469 for (int bit = bits - 1; bit >= 0; bit--) {
JacobBramley 0:f1a93e55feb5 470 // Eor bit 0 of the CRC with the top bit of the data to determine the value
JacobBramley 0:f1a93e55feb5 471 // to feed back into the CRC.
JacobBramley 0:f1a93e55feb5 472 uint32_t result = ((data >> bit) ^ crc) & 1;
JacobBramley 0:f1a93e55feb5 473 // Bit 0 contains that value that must be fed back into the CRC at bit
JacobBramley 0:f1a93e55feb5 474 // positions 7, 3 and 2, so use it to construct a bit mask. These bits
JacobBramley 0:f1a93e55feb5 475 // correspond to positions 0, 4 and 5 in the reversed-CRC implementation.
JacobBramley 0:f1a93e55feb5 476 uint32_t invert = (result << 7) | (result << 3) | (result << 2);
JacobBramley 0:f1a93e55feb5 477 crc = (crc >> 1) ^ invert;
JacobBramley 0:f1a93e55feb5 478 }
JacobBramley 0:f1a93e55feb5 479
JacobBramley 0:f1a93e55feb5 480 return crc == crc_in;
JacobBramley 0:f1a93e55feb5 481 }
JacobBramley 0:f1a93e55feb5 482
JacobBramley 0:f1a93e55feb5 483
JacobBramley 0:f1a93e55feb5 484 // ==== Readings. ====
JacobBramley 0:f1a93e55feb5 485
JacobBramley 0:f1a93e55feb5 486 // Shift 'v' right by 'shift' and perform signed rounding.
JacobBramley 0:f1a93e55feb5 487 static inline int64_t shift_round(int64_t v, uint32_t shift) {
JacobBramley 0:f1a93e55feb5 488 uint64_t u = static_cast<uint64_t>(v);
JacobBramley 0:f1a93e55feb5 489
JacobBramley 0:f1a93e55feb5 490 if (shift == 0) {
JacobBramley 0:f1a93e55feb5 491 return v;
JacobBramley 0:f1a93e55feb5 492 }
JacobBramley 0:f1a93e55feb5 493
JacobBramley 0:f1a93e55feb5 494 // Rounding (with ties away from zero).
JacobBramley 0:f1a93e55feb5 495 // Positive:
JacobBramley 0:f1a93e55feb5 496 // i += bit(shift-1)
JacobBramley 0:f1a93e55feb5 497 // Negative:
JacobBramley 0:f1a93e55feb5 498 // i += bit(shift-1) - 1
JacobBramley 0:f1a93e55feb5 499 // We can simply take the value of bit 31 and subtract the value of the
JacobBramley 0:f1a93e55feb5 500 // sign bit, then add the result to the truncated reading.
JacobBramley 0:f1a93e55feb5 501 // Note that this relies on C99-style division, where negative values are
JacobBramley 0:f1a93e55feb5 502 // truncated towards 0.
JacobBramley 0:f1a93e55feb5 503 int64_t i = (v / (1LL << shift));
JacobBramley 0:f1a93e55feb5 504 int64_t s = (u >> 63) & 1;
JacobBramley 0:f1a93e55feb5 505 int64_t h = (u >> (shift - 1)) & 1;
JacobBramley 0:f1a93e55feb5 506
JacobBramley 0:f1a93e55feb5 507 return i + h - s;
JacobBramley 0:f1a93e55feb5 508 }
JacobBramley 0:f1a93e55feb5 509
JacobBramley 0:f1a93e55feb5 510
JacobBramley 0:f1a93e55feb5 511 // ---- Temperature ----
JacobBramley 0:f1a93e55feb5 512
JacobBramley 0:f1a93e55feb5 513 // -- Floating point. --
JacobBramley 0:f1a93e55feb5 514
JacobBramley 0:f1a93e55feb5 515 float Temp::get_d1_f() const {
JacobBramley 0:f1a93e55feb5 516 // The following data-points are provided in the datasheet:
JacobBramley 0:f1a93e55feb5 517 // Vdd d1
JacobBramley 0:f1a93e55feb5 518 // 5 -40.1
JacobBramley 0:f1a93e55feb5 519 // 4 -39.8
JacobBramley 0:f1a93e55feb5 520 // 3.5 -39.7
JacobBramley 0:f1a93e55feb5 521 // 3 -39.6
JacobBramley 0:f1a93e55feb5 522 // 2.5 -39.4
JacobBramley 0:f1a93e55feb5 523 // The relationship between Vdd and d1 is not linear. However, the
JacobBramley 0:f1a93e55feb5 524 // deviation from a linear relationship is probably a result of aliasing
JacobBramley 0:f1a93e55feb5 525 // rather than anything else. The following relationship provides a linear
JacobBramley 0:f1a93e55feb5 526 // response that looks like a reasonable best-fit for the specified points:
JacobBramley 0:f1a93e55feb5 527 // Vdd d1
JacobBramley 0:f1a93e55feb5 528 // 5 -40.1
JacobBramley 0:f1a93e55feb5 529 // 2.5 -39.43
JacobBramley 0:f1a93e55feb5 530 //
JacobBramley 0:f1a93e55feb5 531 // d1 = -0.268 * Vdd - 38.76
JacobBramley 0:f1a93e55feb5 532 return -0.000268 * mvdd - 38.76;
JacobBramley 0:f1a93e55feb5 533 }
JacobBramley 0:f1a93e55feb5 534
JacobBramley 0:f1a93e55feb5 535
JacobBramley 0:f1a93e55feb5 536 float Temp::get_f() const {
JacobBramley 0:f1a93e55feb5 537 float d1 = get_d1_f();
JacobBramley 0:f1a93e55feb5 538 float d2;
JacobBramley 0:f1a93e55feb5 539 switch (get_bits()) {
JacobBramley 0:f1a93e55feb5 540 case 12: d2 = 0.04f; break;
JacobBramley 0:f1a93e55feb5 541 case 14: d2 = 0.01f; break;
JacobBramley 0:f1a93e55feb5 542 default: return std::numeric_limits<float>::quiet_NaN();
JacobBramley 0:f1a93e55feb5 543 }
JacobBramley 0:f1a93e55feb5 544 return d1 + d2 * get_raw();
JacobBramley 0:f1a93e55feb5 545 }
JacobBramley 0:f1a93e55feb5 546
JacobBramley 0:f1a93e55feb5 547
JacobBramley 0:f1a93e55feb5 548 // -- Fixed point. --
JacobBramley 0:f1a93e55feb5 549
JacobBramley 0:f1a93e55feb5 550 int64_t Temp::get_d1_q32() const {
JacobBramley 0:f1a93e55feb5 551 // See notes in get_d1_f() for justification of this formula.
JacobBramley 0:f1a93e55feb5 552 // d1 = -0.268 * Vdd - 38.76
JacobBramley 0:f1a93e55feb5 553 return -0x0011904bLL * mvdd - 0x26c28f5c28LL;
JacobBramley 0:f1a93e55feb5 554 }
JacobBramley 0:f1a93e55feb5 555
JacobBramley 0:f1a93e55feb5 556
JacobBramley 0:f1a93e55feb5 557 int64_t Temp::get_q32() const {
JacobBramley 0:f1a93e55feb5 558 int64_t d1 = get_d1_q32();
JacobBramley 0:f1a93e55feb5 559 int64_t d2;
JacobBramley 0:f1a93e55feb5 560 switch (get_bits()) {
JacobBramley 0:f1a93e55feb5 561 case 12: d2 = 0xa3d70a3LL; break; // 0.04, q32
JacobBramley 0:f1a93e55feb5 562 case 14: d2 = 0x28f5c28LL; break; // 0.01, q32
JacobBramley 0:f1a93e55feb5 563 default: return 0;
JacobBramley 0:f1a93e55feb5 564 }
JacobBramley 0:f1a93e55feb5 565 return d1 + d2 * get_raw();
JacobBramley 0:f1a93e55feb5 566 }
JacobBramley 0:f1a93e55feb5 567
JacobBramley 0:f1a93e55feb5 568
JacobBramley 0:f1a93e55feb5 569 int32_t Temp::get_fixed(int fbits) const {
JacobBramley 0:f1a93e55feb5 570 return shift_round(get_q32(), 32-fbits);
JacobBramley 0:f1a93e55feb5 571 }
JacobBramley 0:f1a93e55feb5 572
JacobBramley 0:f1a93e55feb5 573
JacobBramley 0:f1a93e55feb5 574 // ---- Humidity ----
JacobBramley 0:f1a93e55feb5 575
JacobBramley 0:f1a93e55feb5 576 // -- Floating point. --
JacobBramley 0:f1a93e55feb5 577
JacobBramley 0:f1a93e55feb5 578 float Hum::get_f() const {
JacobBramley 0:f1a93e55feb5 579 float c1 = -2.0468f;
JacobBramley 0:f1a93e55feb5 580 float c2;
JacobBramley 0:f1a93e55feb5 581 float c3;
JacobBramley 0:f1a93e55feb5 582 float t1 = 0.01f;
JacobBramley 0:f1a93e55feb5 583 float t2;
JacobBramley 0:f1a93e55feb5 584 float r;
JacobBramley 0:f1a93e55feb5 585 float raw = static_cast<float>(get_raw());
JacobBramley 0:f1a93e55feb5 586 switch (get_bits()) {
JacobBramley 0:f1a93e55feb5 587 case 8:
JacobBramley 0:f1a93e55feb5 588 c2 = 0.5872f;
JacobBramley 0:f1a93e55feb5 589 c3 = -4.0845E-4f;
JacobBramley 0:f1a93e55feb5 590 t2 = 0.00128f;
JacobBramley 0:f1a93e55feb5 591 break;
JacobBramley 0:f1a93e55feb5 592 case 12:
JacobBramley 0:f1a93e55feb5 593 c2 = 0.0367f;
JacobBramley 0:f1a93e55feb5 594 c3 = -1.5955E-6f;
JacobBramley 0:f1a93e55feb5 595 t2 = 0.00008f;
JacobBramley 0:f1a93e55feb5 596 break;
JacobBramley 0:f1a93e55feb5 597 default:
JacobBramley 0:f1a93e55feb5 598 return std::numeric_limits<float>::quiet_NaN();
JacobBramley 0:f1a93e55feb5 599 }
JacobBramley 0:f1a93e55feb5 600 r = c1 + (c2 * raw) + (c3 * (raw * raw));
JacobBramley 0:f1a93e55feb5 601 if (temp) {
JacobBramley 0:f1a93e55feb5 602 r += (temp->get_f() - 25.0f)*(t1+t2*raw);
JacobBramley 0:f1a93e55feb5 603 }
JacobBramley 0:f1a93e55feb5 604 // Clamp as specified in the datasheet.
JacobBramley 0:f1a93e55feb5 605 if (r < 0.0f) {
JacobBramley 0:f1a93e55feb5 606 return 0.0f;
JacobBramley 0:f1a93e55feb5 607 }
JacobBramley 0:f1a93e55feb5 608 if (r > 99.0f) {
JacobBramley 0:f1a93e55feb5 609 return 100.0f;
JacobBramley 0:f1a93e55feb5 610 }
JacobBramley 0:f1a93e55feb5 611 return r;
JacobBramley 0:f1a93e55feb5 612 }
JacobBramley 0:f1a93e55feb5 613
JacobBramley 0:f1a93e55feb5 614
JacobBramley 0:f1a93e55feb5 615 // -- Fixed point. --
JacobBramley 0:f1a93e55feb5 616
JacobBramley 0:f1a93e55feb5 617 int64_t Hum::get_q32() const {
JacobBramley 0:f1a93e55feb5 618 int64_t c1 = -0x20bfb15b5LL; // -2.0468
JacobBramley 0:f1a93e55feb5 619 int64_t c2;
JacobBramley 0:f1a93e55feb5 620 int64_t c3;
JacobBramley 0:f1a93e55feb5 621 int64_t t1 = 0x28f6LL; // 0.01, q20
JacobBramley 0:f1a93e55feb5 622 int64_t t2;
JacobBramley 0:f1a93e55feb5 623 int64_t r;
JacobBramley 0:f1a93e55feb5 624 int64_t raw = static_cast<int64_t>(get_raw());
JacobBramley 0:f1a93e55feb5 625 switch (get_bits()) {
JacobBramley 0:f1a93e55feb5 626 case 8:
JacobBramley 0:f1a93e55feb5 627 c2 = 0x9652bd3cLL; // 0.5872f;
JacobBramley 0:f1a93e55feb5 628 c3 = -0x1ac4a7LL; // -4.0845E-4f;
JacobBramley 0:f1a93e55feb5 629 t2 = 0x53eLL; // 0.00128f, q20;
JacobBramley 0:f1a93e55feb5 630 break;
JacobBramley 0:f1a93e55feb5 631 case 12:
JacobBramley 0:f1a93e55feb5 632 c2 = 0x9652bd3LL; // 0.0367f;
JacobBramley 0:f1a93e55feb5 633 c3 = -0x1ac4LL; // -1.5955E-6f;
JacobBramley 0:f1a93e55feb5 634 t2 = 0x54LL; // 0.00008f, q20;
JacobBramley 0:f1a93e55feb5 635 break;
JacobBramley 0:f1a93e55feb5 636 default:
JacobBramley 0:f1a93e55feb5 637 return INT64_MIN;
JacobBramley 0:f1a93e55feb5 638 }
JacobBramley 0:f1a93e55feb5 639 // The 'c' coefficients are all in q32 format. The raw value is in q0
JacobBramley 0:f1a93e55feb5 640 // (integer) format, so r will be in q32 format after this operation.
JacobBramley 0:f1a93e55feb5 641 r = c1 + (c2 * raw) + (c3 * (raw * raw));
JacobBramley 0:f1a93e55feb5 642 if (temp) {
JacobBramley 0:f1a93e55feb5 643 int64_t co = t1 + (t2 * raw); // q20
JacobBramley 0:f1a93e55feb5 644 int64_t t = temp->get_q32() - (25LL << 32);
JacobBramley 0:f1a93e55feb5 645 r += shift_round(co * t, 20);
JacobBramley 0:f1a93e55feb5 646 }
JacobBramley 0:f1a93e55feb5 647 // Clamp as specified in the datasheet.
JacobBramley 0:f1a93e55feb5 648 if (r < 0LL) {
JacobBramley 0:f1a93e55feb5 649 return 0LL;
JacobBramley 0:f1a93e55feb5 650 }
JacobBramley 0:f1a93e55feb5 651 if (r > (99LL<<32)) {
JacobBramley 0:f1a93e55feb5 652 return 100LL<<32;
JacobBramley 0:f1a93e55feb5 653 }
JacobBramley 0:f1a93e55feb5 654 return r;
JacobBramley 0:f1a93e55feb5 655 }
JacobBramley 0:f1a93e55feb5 656
JacobBramley 0:f1a93e55feb5 657
JacobBramley 0:f1a93e55feb5 658 int32_t Hum::get_fixed(int fbits) const {
JacobBramley 0:f1a93e55feb5 659 return shift_round(get_q32(), 32-fbits);
JacobBramley 0:f1a93e55feb5 660 }
JacobBramley 0:f1a93e55feb5 661
JacobBramley 0:f1a93e55feb5 662
JacobBramley 0:f1a93e55feb5 663 } // namespace sht7x