firmware: leds-lp3943: Add power, firmwareUpload and setRate functions

Change-Id: I7e07eb41e0eb5a4bb9d837b01879808bea788bbd
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/firmware/os/drivers/leds/leds_lp3943.c b/firmware/os/drivers/leds/leds_lp3943.c
index 4a627d5..9bce104 100644
--- a/firmware/os/drivers/leds/leds_lp3943.c
+++ b/firmware/os/drivers/leds/leds_lp3943.c
@@ -25,14 +25,13 @@
 #include <nanohubPacket.h>
 #include <sensors.h>
 #include <seos.h>
+#include <timer.h>
 #include <util.h>
 #include <variant/variant.h>
 
 #define LP3943_LEDS_APP_ID              APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 21)
 #define LP3943_LEDS_APP_VERSION         1
 
-#define DBG_ENABLE                      0
-
 #ifdef LP3943_I2C_BUS_ID
 #define I2C_BUS_ID                      LP3943_I2C_BUS_ID
 #else
@@ -60,9 +59,16 @@
 #define LP3943_MAX_LED_NUM              16
 #define LP3943_MAX_LED_SECTION          4
 
+#ifndef LP3943_DBG_ENABLE
+#define LP3943_DBG_ENABLE               1
+#endif
+#define LP3943_DBG_VALUE                0x55
+
 enum LP3943SensorEvents
 {
     EVT_SENSOR_I2C = EVT_APP_START + 1,
+    EVT_SENSOR_LEDS_TIMER,
+    EVT_TEST,
 };
 
 enum LP3943TaskState
@@ -89,12 +95,49 @@
     uint32_t id;
     uint32_t sHandle;
     uint32_t num;
-    uint8_t led[LP3943_MAX_LED_SECTION];
+    bool     ledsOn;
+    bool     blink;
+    uint32_t ledsTimerHandle;
+    uint8_t  led[LP3943_MAX_LED_SECTION];
 
     struct I2cTransfer transfers[LP3943_MAX_PENDING_I2C_REQUESTS];
 } mTask;
 
-static void i2cCallback(void *cookie, size_t tx, size_t rx, int err);
+/* sensor callbacks from nanohub */
+static void i2cCallback(void *cookie, size_t tx, size_t rx, int err)
+{
+    struct I2cTransfer *xfer = cookie;
+
+    xfer->tx = tx;
+    xfer->rx = rx;
+    xfer->err = err;
+
+    osEnqueuePrivateEvt(EVT_SENSOR_I2C, cookie, NULL, mTask.id);
+    if (err != 0)
+        osLog(LOG_INFO, "[LP3943] i2c error (tx: %d, rx: %d, err: %d)\n", tx, rx, err);
+}
+
+static void sensorLP3943TimerCallback(uint32_t timerId, void *data)
+{
+    osEnqueuePrivateEvt(EVT_SENSOR_LEDS_TIMER, data, NULL, mTask.id);
+}
+
+static uint32_t ledsRates[] = {
+    SENSOR_HZ(0.1),
+    SENSOR_HZ(0.5),
+    SENSOR_HZ(1.0f),
+    SENSOR_HZ(2.0f),
+    0
+};
+
+// should match "supported rates in length"
+static const uint64_t ledsRatesRateVals[] =
+{
+    10 * 1000000000ULL,
+    2 * 1000000000ULL,
+    1 * 1000000000ULL,
+    1000000000ULL / 2,
+};
 
 // Allocate a buffer and mark it as in use with the given state, or return NULL
 // if no buffers available. Must *not* be called from interrupt context.
@@ -138,19 +181,31 @@
     return (ret == 0);
 }
 
-/* sensor callbacks from nanohub */
-
-static void i2cCallback(void *cookie, size_t tx, size_t rx, int err)
+/* Sensor Operations */
+static bool sensorLP3943Power(bool on, void *cookie)
 {
-    struct I2cTransfer *xfer = cookie;
+    if (mTask.ledsTimerHandle) {
+        timTimerCancel(mTask.ledsTimerHandle);
+        mTask.ledsTimerHandle = 0;
+    }
+    mTask.ledsOn = on;
+    return sensorSignalInternalEvt(mTask.sHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, on, 0);
+}
 
-    xfer->tx = tx;
-    xfer->rx = rx;
-    xfer->err = err;
+static bool sensorLP3943FwUpload(void *cookie)
+{
+    return sensorSignalInternalEvt(mTask.sHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
+}
 
-    osEnqueuePrivateEvt(EVT_SENSOR_I2C, cookie, NULL, mTask.id);
-    if (err != 0)
-        osLog(LOG_INFO, "[LP3943] i2c error (tx: %d, rx: %d, err: %d)\n", tx, rx, err);
+static bool sensorLP3943SetRate(uint32_t rate, uint64_t latency, void *cookie)
+{
+    if (mTask.ledsTimerHandle)
+        timTimerCancel(mTask.ledsTimerHandle);
+
+    mTask.ledsTimerHandle = timTimerSet(sensorTimerLookupCommon(ledsRates,
+                ledsRatesRateVals, rate), 0, 50, sensorLP3943TimerCallback, NULL, false);
+
+    return sensorSignalInternalEvt(mTask.sHandle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
 }
 
 static bool sensorCfgDataLedsLP3943(void *cfg, void *cookie)
@@ -181,12 +236,28 @@
     return true;
 }
 
+static void sensorLedsOnOff(bool flag)
+{
+    uint8_t laddr = LP3943_REG_LS0;
+    uint8_t lval;
+    uint8_t index;
+
+    for (index=0; index < LP3943_MAX_LED_SECTION; index++) {
+        lval = flag ? mTask.led[index] : 0;
+        writeRegister(laddr + index, lval, STATE_LED);
+    }
+}
+
 static const struct SensorInfo sensorInfoLedsLP3943 = {
     .sensorName = "Leds-LP3943",
     .sensorType = SENS_TYPE_LEDS,
+    .supportedRates = ledsRates,
 };
 
 static const struct SensorOps sensorOpsLedsLP3943 = {
+    .sensorPower   = sensorLP3943Power,
+    .sensorFirmwareUpload = sensorLP3943FwUpload,
+    .sensorSetRate  = sensorLP3943SetRate,
     .sensorCfgData = sensorCfgDataLedsLP3943,
 };
 
@@ -211,6 +282,11 @@
             } else {
                 osLog(LOG_INFO, "[LP3943] detected\n");
                 sensorRegisterInitComplete(mTask.sHandle);
+                if (LP3943_DBG_ENABLE) {
+                    mTask.ledsOn = true;
+                    mTask.led[0] = LP3943_DBG_VALUE;
+                    osEnqueuePrivateEvt(EVT_TEST, NULL, NULL, mTask.id);
+                }
             }
             break;
 
@@ -227,17 +303,31 @@
 static void handleEvent(uint32_t evtType, const void* evtData)
 {
     switch (evtType) {
-        case EVT_APP_START:
-            osEventUnsubscribe(mTask.id, EVT_APP_START);
-            i2cMasterRequest(I2C_BUS_ID, I2C_SPEED);
+    case EVT_APP_START:
+        osEventUnsubscribe(mTask.id, EVT_APP_START);
+        i2cMasterRequest(I2C_BUS_ID, I2C_SPEED);
 
-            /* Reset Leds */
-            writeRegister(LP3943_REG_LS0, 0, STATE_RESET);
-            break;
+        /* Reset Leds */
+        writeRegister(LP3943_REG_LS0, 0, STATE_RESET);
+        break;
 
-        case EVT_SENSOR_I2C:
-            handleI2cEvent((struct I2cTransfer *)evtData);
+    case EVT_SENSOR_I2C:
+        handleI2cEvent((struct I2cTransfer *)evtData);
+        break;
+
+    case EVT_SENSOR_LEDS_TIMER:
+        if (!mTask.ledsOn)
             break;
+        mTask.blink = !mTask.blink;
+        sensorLedsOnOff(mTask.blink);
+        break;
+
+    case EVT_TEST:
+        sensorLP3943SetRate(SENSOR_HZ(1), 0, NULL);
+        break;
+
+    default:
+        break;
     }
 }
 
@@ -246,6 +336,7 @@
     mTask.id = taskId;
     mTask.num = LP3943_MAX_LED_NUM;
     memset(mTask.led, 0x00, LP3943_MAX_LED_SECTION);
+    mTask.ledsOn = mTask.blink = false;
 
     /* Register sensors */
     mTask.sHandle = sensorRegister(&sensorInfoLedsLP3943, &sensorOpsLedsLP3943, NULL, false);