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