1 /* 2 * Copyright (C) 2016 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 <stdlib.h> 18 #include <string.h> 19 20 #include <eventnums.h> 21 #include <heap.h> 22 #include <hostIntf.h> 23 #include <i2c.h> 24 #include <leds_gpio.h> 25 #include <nanohubPacket.h> 26 #include <sensors.h> 27 #include <seos.h> 28 #include <timer.h> 29 #include <util.h> 30 #include <variant/variant.h> 31 32 #define LP3943_LEDS_APP_ID APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 21) 33 #define LP3943_LEDS_APP_VERSION 1 34 35 #ifdef LP3943_I2C_BUS_ID 36 #define I2C_BUS_ID LP3943_I2C_BUS_ID 37 #else 38 #define I2C_BUS_ID 0 39 #endif 40 41 #ifdef LP3943_I2C_SPEED 42 #define I2C_SPEED LP3943_I2C_SPEED 43 #else 44 #define I2C_SPEED 400000 45 #endif 46 47 #ifdef LP3943_I2C_ADDR 48 #define I2C_ADDR LP3943_I2C_ADDR 49 #else 50 #define I2C_ADDR 0x60 51 #endif 52 53 #define LP3943_REG_PSC0 0x02 54 #define LP3943_REG_PWM0 0x03 55 #define LP3943_REG_PSC1 0x04 56 #define LP3943_REG_PWM1 0x05 57 #define LP3943_REG_LS0 0x06 58 #define LP3943_REG_LS1 0x07 59 #define LP3943_REG_LS2 0x08 60 #define LP3943_REG_LS3 0x09 61 62 #define LP3943_MAX_PENDING_I2C_REQUESTS 4 63 #define LP3943_MAX_I2C_TRANSFER_SIZE 2 64 #define LP3943_MAX_LED_NUM 16 65 #define LP3943_MAX_LED_SECTION 4 66 67 #ifndef LP3943_DBG_ENABLE 68 #define LP3943_DBG_ENABLE 0 69 #endif 70 #define LP3943_DBG_VALUE 0x55 71 72 enum LP3943SensorEvents 73 { 74 EVT_SENSOR_I2C = EVT_APP_START + 1, 75 EVT_SENSOR_LEDS_TIMER, 76 EVT_TEST, 77 }; 78 79 enum LP3943TaskState 80 { 81 STATE_RESET, 82 STATE_CLEAN_LS1, 83 STATE_CLEAN_LS2, 84 STATE_FINISH_INIT, 85 STATE_LED, 86 }; 87 88 struct I2cTransfer 89 { 90 size_t tx; 91 size_t rx; 92 int err; 93 uint8_t txrxBuf[LP3943_MAX_I2C_TRANSFER_SIZE]; 94 uint8_t state; 95 bool inUse; 96 }; 97 98 static struct LP3943Task 99 { 100 uint32_t id; 101 uint32_t sHandle; 102 uint32_t num; 103 bool ledsOn; 104 bool blink; 105 uint32_t ledsTimerHandle; 106 uint8_t led[LP3943_MAX_LED_SECTION]; 107 108 struct I2cTransfer transfers[LP3943_MAX_PENDING_I2C_REQUESTS]; 109 } mTask; 110 111 /* sensor callbacks from nanohub */ 112 static void i2cCallback(void *cookie, size_t tx, size_t rx, int err) 113 { 114 struct I2cTransfer *xfer = cookie; 115 116 xfer->tx = tx; 117 xfer->rx = rx; 118 xfer->err = err; 119 120 osEnqueuePrivateEvt(EVT_SENSOR_I2C, cookie, NULL, mTask.id); 121 if (err != 0) 122 osLog(LOG_INFO, "[LP3943] i2c error (tx: %d, rx: %d, err: %d)\n", tx, rx, err); 123 } 124 125 static void sensorLP3943TimerCallback(uint32_t timerId, void *data) 126 { 127 osEnqueuePrivateEvt(EVT_SENSOR_LEDS_TIMER, data, NULL, mTask.id); 128 } 129 130 static uint32_t ledsRates[] = { 131 SENSOR_HZ(0.1), 132 SENSOR_HZ(0.5), 133 SENSOR_HZ(1.0f), 134 SENSOR_HZ(2.0f), 135 0 136 }; 137 138 // should match "supported rates in length" 139 static const uint64_t ledsRatesRateVals[] = 140 { 141 10 * 1000000000ULL, 142 2 * 1000000000ULL, 143 1 * 1000000000ULL, 144 1000000000ULL / 2, 145 }; 146 147 // Allocate a buffer and mark it as in use with the given state, or return NULL 148 // if no buffers available. Must *not* be called from interrupt context. 149 static struct I2cTransfer *allocXfer(uint8_t state) 150 { 151 size_t i; 152 153 for (i = 0; i < ARRAY_SIZE(mTask.transfers); i++) { 154 if (!mTask.transfers[i].inUse) { 155 mTask.transfers[i].inUse = true; 156 mTask.transfers[i].state = state; 157 return &mTask.transfers[i]; 158 } 159 } 160 161 osLog(LOG_ERROR, "[LP3943]: Ran out of i2c buffers!"); 162 return NULL; 163 } 164 165 // Helper function to release I2cTranfer structure. 166 static inline void releaseXfer(struct I2cTransfer *xfer) 167 { 168 xfer->inUse = false; 169 } 170 171 // Helper function to write a one byte register. Returns true if we got a 172 // successful return value from i2cMasterTx(). 173 static bool writeRegister(uint8_t reg, uint8_t value, uint8_t state) 174 { 175 struct I2cTransfer *xfer = allocXfer(state); 176 int ret = -1; 177 178 if (xfer != NULL) { 179 xfer->txrxBuf[0] = reg; 180 xfer->txrxBuf[1] = value; 181 ret = i2cMasterTx(I2C_BUS_ID, I2C_ADDR, xfer->txrxBuf, 2, i2cCallback, xfer); 182 if (ret) 183 releaseXfer(xfer); 184 } 185 186 return (ret == 0); 187 } 188 189 /* Sensor Operations */ 190 static bool sensorLP3943Power(bool on, void *cookie) 191 { 192 if (mTask.ledsTimerHandle) { 193 timTimerCancel(mTask.ledsTimerHandle); 194 mTask.ledsTimerHandle = 0; 195 } 196 mTask.ledsOn = on; 197 return sensorSignalInternalEvt(mTask.sHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, on, 0); 198 } 199 200 static bool sensorLP3943FwUpload(void *cookie) 201 { 202 return sensorSignalInternalEvt(mTask.sHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0); 203 } 204 205 static bool sensorLP3943SetRate(uint32_t rate, uint64_t latency, void *cookie) 206 { 207 if (mTask.ledsTimerHandle) 208 timTimerCancel(mTask.ledsTimerHandle); 209 210 mTask.ledsTimerHandle = timTimerSet(sensorTimerLookupCommon(ledsRates, 211 ledsRatesRateVals, rate), 0, 50, sensorLP3943TimerCallback, NULL, false); 212 213 return sensorSignalInternalEvt(mTask.sHandle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency); 214 } 215 216 static bool sensorCfgDataLedsLP3943(void *cfg, void *cookie) 217 { 218 struct LedsCfg *lcfg = (struct LedsCfg *)cfg; 219 uint8_t laddr = LP3943_REG_LS0; 220 uint8_t lval; 221 uint8_t index; 222 uint8_t lnum; 223 224 if (lcfg->led_num >= mTask.num) { 225 osLog(LOG_INFO, "Wrong led number %"PRIu32"\n", lcfg->led_num); 226 return false; 227 } 228 index = lcfg->led_num >> 2; 229 lnum = (lcfg->led_num & 0x3) << 1; 230 lval = mTask.led[index]; 231 laddr += index; 232 if (lcfg->value) { 233 lval |= (1 << lnum); 234 } else { 235 lval &= ~(1 << lnum); 236 } 237 238 writeRegister(laddr, lval, STATE_LED); 239 mTask.led[index] = lval; 240 osLog(LOG_INFO, "Set led[%"PRIu32"]=%"PRIu32"\n", lcfg->led_num, lcfg->value); 241 return true; 242 } 243 244 static void sensorLedsOnOff(bool flag) 245 { 246 uint8_t laddr = LP3943_REG_LS0; 247 uint8_t lval; 248 uint8_t index; 249 250 for (index=0; index < LP3943_MAX_LED_SECTION; index++) { 251 lval = flag ? mTask.led[index] : 0; 252 writeRegister(laddr + index, lval, STATE_LED); 253 } 254 } 255 256 static const struct SensorInfo sensorInfoLedsLP3943 = { 257 .sensorName = "Leds-LP3943", 258 .sensorType = SENS_TYPE_LEDS_I2C, 259 .supportedRates = ledsRates, 260 }; 261 262 static const struct SensorOps sensorOpsLedsLP3943 = { 263 .sensorPower = sensorLP3943Power, 264 .sensorFirmwareUpload = sensorLP3943FwUpload, 265 .sensorSetRate = sensorLP3943SetRate, 266 .sensorCfgData = sensorCfgDataLedsLP3943, 267 }; 268 269 static void handleI2cEvent(struct I2cTransfer *xfer) 270 { 271 switch (xfer->state) { 272 case STATE_RESET: 273 writeRegister(LP3943_REG_LS1, 0, STATE_CLEAN_LS1); 274 break; 275 276 case STATE_CLEAN_LS1: 277 writeRegister(LP3943_REG_LS2, 0, STATE_FINISH_INIT); 278 break; 279 280 case STATE_CLEAN_LS2: 281 writeRegister(LP3943_REG_LS3, 0, STATE_FINISH_INIT); 282 break; 283 284 case STATE_FINISH_INIT: 285 if (xfer->err != 0) { 286 osLog(LOG_INFO, "[LP3943] not detected\n"); 287 } else { 288 osLog(LOG_INFO, "[LP3943] detected\n"); 289 sensorRegisterInitComplete(mTask.sHandle); 290 if (LP3943_DBG_ENABLE) { 291 mTask.ledsOn = true; 292 mTask.led[0] = LP3943_DBG_VALUE; 293 osEnqueuePrivateEvt(EVT_TEST, NULL, NULL, mTask.id); 294 } 295 } 296 break; 297 298 case STATE_LED: 299 break; 300 301 default: 302 break; 303 } 304 305 releaseXfer(xfer); 306 } 307 308 static void handleEvent(uint32_t evtType, const void* evtData) 309 { 310 switch (evtType) { 311 case EVT_APP_START: 312 osEventUnsubscribe(mTask.id, EVT_APP_START); 313 i2cMasterRequest(I2C_BUS_ID, I2C_SPEED); 314 315 /* Reset Leds */ 316 writeRegister(LP3943_REG_LS0, 0, STATE_RESET); 317 break; 318 319 case EVT_SENSOR_I2C: 320 handleI2cEvent((struct I2cTransfer *)evtData); 321 break; 322 323 case EVT_SENSOR_LEDS_TIMER: 324 if (!mTask.ledsOn) 325 break; 326 mTask.blink = !mTask.blink; 327 sensorLedsOnOff(mTask.blink); 328 break; 329 330 case EVT_TEST: 331 sensorLP3943SetRate(SENSOR_HZ(1), 0, NULL); 332 break; 333 334 default: 335 break; 336 } 337 } 338 339 static bool startTask(uint32_t taskId) 340 { 341 mTask.id = taskId; 342 mTask.num = LP3943_MAX_LED_NUM; 343 memset(mTask.led, 0x00, LP3943_MAX_LED_SECTION); 344 mTask.ledsOn = mTask.blink = false; 345 346 /* Register sensors */ 347 mTask.sHandle = sensorRegister(&sensorInfoLedsLP3943, &sensorOpsLedsLP3943, NULL, false); 348 349 osEventSubscribe(taskId, EVT_APP_START); 350 351 return true; 352 } 353 354 static void endTask(void) 355 { 356 sensorUnregister(mTask.sHandle); 357 } 358 359 INTERNAL_APP_INIT(LP3943_LEDS_APP_ID, LP3943_LEDS_APP_VERSION, startTask, endTask, handleEvent); 360