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 */
i2cCallback(void * cookie,size_t tx,size_t rx,int err)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 
sensorLP3943TimerCallback(uint32_t timerId,void * data)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.
allocXfer(uint8_t state)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.
releaseXfer(struct I2cTransfer * xfer)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().
writeRegister(uint8_t reg,uint8_t value,uint8_t state)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 */
sensorLP3943Power(bool on,void * cookie)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 
sensorLP3943FwUpload(void * cookie)200 static bool sensorLP3943FwUpload(void *cookie)
201 {
202     return sensorSignalInternalEvt(mTask.sHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
203 }
204 
sensorLP3943SetRate(uint32_t rate,uint64_t latency,void * cookie)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 
sensorCfgDataLedsLP3943(void * cfg,void * cookie)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 
sensorLedsOnOff(bool flag)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 
handleI2cEvent(struct I2cTransfer * xfer)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 
handleEvent(uint32_t evtType,const void * evtData)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 
startTask(uint32_t taskId)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 
endTask(void)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