1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <atomic.h> 18 #include <gpio.h> 19 #include <nanohubPacket.h> 20 #include <plat/exti.h> 21 #include <plat/gpio.h> 22 #include <platform.h> 23 #include <plat/syscfg.h> 24 #include <sensors.h> 25 #include <seos.h> 26 #include <slab.h> 27 #include <i2c.h> 28 #include <timer.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <variant/variant.h> 32 33 #define SI7034A10_APP_ID APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 22) 34 35 /* Sensor defs */ 36 #define SI7034_ID_SAMPLE 0xFF 37 #define SI7034_ID_PROD 0x22 38 39 #define SI7034_RESET_CMD 0xFE 40 #define SI7034_READID_0_CMD 0xFC 41 #define SI7034_READID_1_CMD 0xC9 42 #define SI7034_READDATA_0_CMD 0x7C 43 #define SI7034_READDATA_1_CMD 0xA2 44 45 #define SI7034_HUMIGRADES(humi_val) ((humi_val * 12500) >> 13) 46 #define SI7034_CENTIGRADES(temp_val) (((temp_val * 21875) >> 13) - 45000) 47 48 #define INFO_PRINT(fmt, ...) \ 49 do { \ 50 osLog(LOG_INFO, "%s " fmt, "[SI7034]", ##__VA_ARGS__); \ 51 } while (0); 52 53 #define DEBUG_PRINT(fmt, ...) \ 54 do { \ 55 if (SI7034_DBG_ENABLED) { \ 56 osLog(LOG_DEBUG, "%s " fmt, "[SI7034]", ##__VA_ARGS__); \ 57 } \ 58 } while (0); 59 60 #define ERROR_PRINT(fmt, ...) \ 61 do { \ 62 osLog(LOG_ERROR, "%s " fmt, "[SI7034]", ##__VA_ARGS__); \ 63 } while (0); 64 65 /* DO NOT MODIFY, just to avoid compiler error if not defined using FLAGS */ 66 #ifndef SI7034_DBG_ENABLED 67 #define SI7034_DBG_ENABLED 0 68 #endif /* SI7034_DBG_ENABLED */ 69 70 enum si7034SensorEvents 71 { 72 EVT_SENSOR_I2C = EVT_APP_START + 1, 73 EVT_SENSOR_HUMIDITY_TIMER, 74 EVT_SENSOR_TEMP_TIMER, 75 EVT_TEST, 76 }; 77 78 enum si7034SensorState { 79 SENSOR_BOOT, 80 SENSOR_VERIFY_ID, 81 SENSOR_READ_SAMPLES, 82 }; 83 84 #ifndef SI7034A10_I2C_BUS_ID 85 #error "SI7034A10_I2C_BUS_ID is not defined; please define in variant.h" 86 #endif 87 88 #ifndef SI7034A10_I2C_SPEED 89 #define SI7034A10_I2C_SPEED 400000 90 #endif 91 92 #ifndef SI7034A10_I2C_ADDR 93 #define SI7034A10_I2C_ADDR 0x70 94 #endif 95 96 enum si7034SensorIndex { 97 HUMIDITY = 0, 98 TEMP, 99 NUM_OF_SENSOR, 100 }; 101 102 struct si7034Sensor { 103 uint32_t handle; 104 }; 105 106 #define SI7034_MAX_PENDING_I2C_REQUESTS 4 107 #define SI7034_MAX_I2C_TRANSFER_SIZE 6 108 109 struct I2cTransfer 110 { 111 size_t tx; 112 size_t rx; 113 int err; 114 uint8_t txrxBuf[SI7034_MAX_I2C_TRANSFER_SIZE]; 115 uint8_t state; 116 bool inUse; 117 }; 118 119 /* Task structure */ 120 struct si7034Task { 121 uint32_t tid; 122 123 /* timer */ 124 uint32_t humiTimerHandle; 125 uint32_t tempTimerHandle; 126 127 /* sensor flags */ 128 bool humiOn; 129 bool humiReading; 130 bool tempOn; 131 bool tempReading; 132 133 struct I2cTransfer transfers[SI7034_MAX_PENDING_I2C_REQUESTS]; 134 135 /* sensors */ 136 struct si7034Sensor sensors[NUM_OF_SENSOR]; 137 }; 138 139 static struct si7034Task mTask; 140 141 // Allocate a buffer and mark it as in use with the given state, or return NULL 142 // if no buffers available. Must *not* be called from interrupt context. 143 static struct I2cTransfer *allocXfer(uint8_t state) 144 { 145 size_t i; 146 147 for (i = 0; i < ARRAY_SIZE(mTask.transfers); i++) { 148 if (!mTask.transfers[i].inUse) { 149 mTask.transfers[i].inUse = true; 150 mTask.transfers[i].state = state; 151 return &mTask.transfers[i]; 152 } 153 } 154 155 ERROR_PRINT("Ran out of i2c buffers!"); 156 return NULL; 157 } 158 159 static inline void releaseXfer(struct I2cTransfer *xfer) 160 { 161 xfer->inUse = false; 162 } 163 164 static void i2cCallback(void *cookie, size_t tx, size_t rx, int err) 165 { 166 struct I2cTransfer *xfer = cookie; 167 168 xfer->tx = tx; 169 xfer->rx = rx; 170 xfer->err = err; 171 172 osEnqueuePrivateEvt(EVT_SENSOR_I2C, cookie, NULL, mTask.tid); 173 if (err != 0) 174 ERROR_PRINT("i2c error (tx: %d, rx: %d, err: %d)\n", tx, rx, err); 175 } 176 177 static bool si7034_i2c_read(uint8_t addr0, uint8_t addr1, uint8_t state) 178 { 179 struct I2cTransfer *xfer = allocXfer(state); 180 int ret = -1; 181 182 if (xfer != NULL) { 183 xfer->txrxBuf[0] = addr0; 184 xfer->txrxBuf[1] = addr1; 185 ret = i2cMasterTxRx(SI7034A10_I2C_BUS_ID, SI7034A10_I2C_ADDR, 186 xfer->txrxBuf, 2, xfer->txrxBuf, 6, i2cCallback, xfer); 187 if (ret) { 188 releaseXfer(xfer); 189 return false; 190 } 191 } 192 193 return (ret == -1) ? false : true; 194 } 195 196 static bool si7034_i2c_write(uint8_t data, uint8_t state) 197 { 198 struct I2cTransfer *xfer = allocXfer(state); 199 int ret = -1; 200 201 if (xfer != NULL) { 202 xfer->txrxBuf[0] = data; 203 ret = i2cMasterTx(SI7034A10_I2C_BUS_ID, SI7034A10_I2C_ADDR, 204 xfer->txrxBuf, 1, i2cCallback, xfer); 205 if (ret) { 206 releaseXfer(xfer); 207 return false; 208 } 209 } 210 211 return (ret == -1) ? false : true; 212 } 213 214 /* Sensor Info */ 215 static void sensorHumiTimerCallback(uint32_t timerId, void *data) 216 { 217 osEnqueuePrivateEvt(EVT_SENSOR_HUMIDITY_TIMER, data, NULL, mTask.tid); 218 } 219 220 static void sensorTempTimerCallback(uint32_t timerId, void *data) 221 { 222 osEnqueuePrivateEvt(EVT_SENSOR_TEMP_TIMER, data, NULL, mTask.tid); 223 } 224 225 #define DEC_INFO(name, type, axis, inter, samples, rates) \ 226 .sensorName = name, \ 227 .sensorType = type, \ 228 .numAxis = axis, \ 229 .interrupt = inter, \ 230 .minSamples = samples, \ 231 .supportedRates = rates 232 233 static uint32_t si7034Rates[] = { 234 SENSOR_HZ(0.1), 235 SENSOR_HZ(1.0f), 236 SENSOR_HZ(5.0f), 237 SENSOR_HZ(10.0f), 238 SENSOR_HZ(25.0f), 239 0 240 }; 241 242 // should match "supported rates in length" and be the timer length for that rate in nanosecs 243 static const uint64_t si7034RatesRateVals[] = 244 { 245 10 * 1000000000ULL, 246 1 * 1000000000ULL, 247 1000000000ULL / 5, 248 1000000000ULL / 10, 249 1000000000ULL / 25, 250 }; 251 252 253 static const struct SensorInfo si7034SensorInfo[NUM_OF_SENSOR] = 254 { 255 { DEC_INFO("Humidity", SENS_TYPE_HUMIDITY, NUM_AXIS_EMBEDDED, NANOHUB_INT_NONWAKEUP, 256 300, si7034Rates) }, 257 { DEC_INFO("Temperature", SENS_TYPE_AMBIENT_TEMP, NUM_AXIS_EMBEDDED, NANOHUB_INT_NONWAKEUP, 258 20, si7034Rates) }, 259 }; 260 261 /* Sensor Operations */ 262 static bool humiPower(bool on, void *cookie) 263 { 264 DEBUG_PRINT("%s: %d\n", __func__, on); 265 266 if (mTask.humiTimerHandle) { 267 timTimerCancel(mTask.humiTimerHandle); 268 mTask.humiTimerHandle = 0; 269 mTask.humiReading = false; 270 } 271 mTask.humiOn = on; 272 return sensorSignalInternalEvt(mTask.sensors[HUMIDITY].handle, 273 SENSOR_INTERNAL_EVT_POWER_STATE_CHG, on, 0); 274 } 275 276 static bool humiFwUpload(void *cookie) 277 { 278 DEBUG_PRINT("%s\n", __func__); 279 280 return sensorSignalInternalEvt(mTask.sensors[HUMIDITY].handle, 281 SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0); 282 } 283 284 static bool humiSetRate(uint32_t rate, uint64_t latency, void *cookie) 285 { 286 DEBUG_PRINT("%s %ld (%lld)\n", __func__, rate, latency); 287 288 if (mTask.humiTimerHandle) 289 timTimerCancel(mTask.humiTimerHandle); 290 291 mTask.humiTimerHandle = timTimerSet(sensorTimerLookupCommon(si7034Rates, 292 si7034RatesRateVals, rate), 0, 50, sensorHumiTimerCallback, NULL, false); 293 294 return sensorSignalInternalEvt(mTask.sensors[HUMIDITY].handle, 295 SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency); 296 } 297 298 static bool humiFlush(void *cookie) 299 { 300 return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_HUMIDITY), SENSOR_DATA_EVENT_FLUSH, NULL); 301 } 302 303 static bool tempPower(bool on, void *cookie) 304 { 305 DEBUG_PRINT("%s: %d\n", __func__, on); 306 307 if (mTask.tempTimerHandle) { 308 timTimerCancel(mTask.tempTimerHandle); 309 mTask.tempTimerHandle = 0; 310 mTask.tempReading = false; 311 } 312 mTask.tempOn = on; 313 return sensorSignalInternalEvt(mTask.sensors[TEMP].handle, 314 SENSOR_INTERNAL_EVT_POWER_STATE_CHG, on, 0); 315 } 316 317 static bool tempFwUpload(void *cookie) 318 { 319 DEBUG_PRINT("%s\n", __func__); 320 321 return sensorSignalInternalEvt(mTask.sensors[TEMP].handle, 322 SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0); 323 } 324 325 static bool tempSetRate(uint32_t rate, uint64_t latency, void *cookie) 326 { 327 DEBUG_PRINT("%s %ld (%lld)\n", __func__, rate, latency); 328 329 if (mTask.tempTimerHandle) 330 timTimerCancel(mTask.tempTimerHandle); 331 332 mTask.tempTimerHandle = timTimerSet(sensorTimerLookupCommon(si7034Rates, 333 si7034RatesRateVals, rate), 0, 50, sensorTempTimerCallback, NULL, false); 334 335 return sensorSignalInternalEvt(mTask.sensors[TEMP].handle, 336 SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency); 337 } 338 339 static bool tempFlush(void *cookie) 340 { 341 return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_AMBIENT_TEMP), SENSOR_DATA_EVENT_FLUSH, NULL); 342 } 343 344 #define DEC_OPS(power, firmware, rate, flush, cal, cfg) \ 345 .sensorPower = power, \ 346 .sensorFirmwareUpload = firmware, \ 347 .sensorSetRate = rate, \ 348 .sensorFlush = flush, \ 349 .sensorCalibrate = cal, \ 350 .sensorCfgData = cfg 351 352 static const struct SensorOps si7034SensorOps[NUM_OF_SENSOR] = 353 { 354 { DEC_OPS(humiPower, humiFwUpload, humiSetRate, humiFlush, NULL, NULL) }, 355 { DEC_OPS(tempPower, tempFwUpload, tempSetRate, tempFlush, NULL, NULL) }, 356 }; 357 358 static void handleI2cEvent(const void *evtData) 359 { 360 struct I2cTransfer *xfer = (struct I2cTransfer *)evtData; 361 union EmbeddedDataPoint sample; 362 uint32_t value; 363 uint8_t i; 364 365 switch (xfer->state) { 366 case SENSOR_BOOT: 367 if (!si7034_i2c_read(SI7034_READID_0_CMD, SI7034_READID_1_CMD, SENSOR_VERIFY_ID)) { 368 DEBUG_PRINT("Not able to read ID\n"); 369 return; 370 } 371 break; 372 373 case SENSOR_VERIFY_ID: 374 /* Check the sensor ID */ 375 if (xfer->err != 0) 376 return; 377 INFO_PRINT("Device ID = (%02x)\n", xfer->txrxBuf[0]); 378 if ((xfer->txrxBuf[0] != SI7034_ID_SAMPLE) && 379 (xfer->txrxBuf[0] != SI7034_ID_PROD)) 380 break; 381 INFO_PRINT("detected\n"); 382 for (i = 0; i < NUM_OF_SENSOR; i++) 383 sensorRegisterInitComplete(mTask.sensors[i].handle); 384 385 /* TEST the environment in standalone mode */ 386 if (SI7034_DBG_ENABLED) { 387 mTask.humiOn = mTask.tempOn = true; 388 osEnqueuePrivateEvt(EVT_TEST, NULL, NULL, mTask.tid); 389 } 390 break; 391 392 case SENSOR_READ_SAMPLES: 393 if (mTask.humiOn && mTask.humiReading) { 394 value = ((uint32_t)(xfer->txrxBuf[3]) << 8) | xfer->txrxBuf[4]; 395 value = SI7034_HUMIGRADES(value); 396 value = (value > 100000) ? 100000 : value; 397 DEBUG_PRINT("Humidity = %u\n", (unsigned)value); 398 sample.fdata = (float)value / 1000.0f; 399 400 osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_HUMIDITY), sample.vptr, NULL); 401 } 402 403 if (mTask.tempOn && mTask.tempReading) { 404 value = ((uint32_t)(xfer->txrxBuf[0]) << 8) | xfer->txrxBuf[1]; 405 value = SI7034_CENTIGRADES(value); 406 DEBUG_PRINT("Temp = %u\n", (unsigned)value); 407 sample.fdata = (float)value / 1000.0f; 408 409 osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_AMBIENT_TEMP), sample.vptr, NULL); 410 } 411 412 mTask.humiReading = mTask.tempReading = false; 413 break; 414 415 default: 416 break; 417 } 418 419 releaseXfer(xfer); 420 } 421 422 static void handleEvent(uint32_t evtType, const void* evtData) 423 { 424 switch (evtType) { 425 case EVT_APP_START: 426 osEventUnsubscribe(mTask.tid, EVT_APP_START); 427 si7034_i2c_write(SI7034_RESET_CMD, SENSOR_BOOT); 428 break; 429 430 case EVT_SENSOR_I2C: 431 handleI2cEvent(evtData); 432 break; 433 434 case EVT_SENSOR_HUMIDITY_TIMER: 435 DEBUG_PRINT("EVT_SENSOR_HUMIDITY_TIMER\n"); 436 437 if (!mTask.humiOn) 438 break; 439 /* Start sampling for a value */ 440 if (!mTask.humiReading && !mTask.tempReading) 441 si7034_i2c_read(SI7034_READDATA_0_CMD, SI7034_READDATA_1_CMD, SENSOR_READ_SAMPLES); 442 mTask.humiReading = true; 443 break; 444 445 case EVT_SENSOR_TEMP_TIMER: 446 DEBUG_PRINT("EVT_SENSOR_TEMP_TIMER\n"); 447 448 if (!mTask.tempOn) 449 break; 450 /* Start sampling for a value */ 451 if (!mTask.humiReading && !mTask.tempReading) 452 si7034_i2c_read(SI7034_READDATA_0_CMD, SI7034_READDATA_1_CMD, SENSOR_READ_SAMPLES); 453 mTask.tempReading = true; 454 break; 455 456 case EVT_TEST: 457 DEBUG_PRINT("EVT_TEST\n"); 458 459 humiSetRate(SENSOR_HZ(1), 0, NULL); 460 tempSetRate(SENSOR_HZ(1), 0, NULL); 461 break; 462 463 default: 464 break; 465 } 466 } 467 468 static bool startTask(uint32_t task_id) 469 { 470 uint8_t i; 471 472 mTask.tid = task_id; 473 474 DEBUG_PRINT("task started\n"); 475 476 mTask.humiOn = mTask.humiReading = false; 477 mTask.tempOn = mTask.tempReading = false; 478 479 /* Init the communication part */ 480 i2cMasterRequest(SI7034A10_I2C_BUS_ID, SI7034A10_I2C_SPEED); 481 482 for (i = 0; i < NUM_OF_SENSOR; i++) { 483 mTask.sensors[i].handle = 484 sensorRegister(&si7034SensorInfo[i], &si7034SensorOps[i], NULL, false); 485 } 486 487 osEventSubscribe(mTask.tid, EVT_APP_START); 488 489 return true; 490 } 491 492 static void endTask(void) 493 { 494 uint8_t i; 495 496 DEBUG_PRINT("task ended\n"); 497 498 for (i = 0; i < NUM_OF_SENSOR; i++) { 499 sensorUnregister(mTask.sensors[i].handle); 500 } 501 } 502 503 INTERNAL_APP_INIT(SI7034A10_APP_ID, 0, startTask, endTask, handleEvent); 504