qtmobility/plugins/sensors/n900/n900lightsensor.cpp
changeset 4 90517678cc4f
parent 1 2b40d63a9c3d
child 11 06b8e2af4411
--- a/qtmobility/plugins/sensors/n900/n900lightsensor.cpp	Fri Apr 16 15:51:22 2010 +0300
+++ b/qtmobility/plugins/sensors/n900/n900lightsensor.cpp	Mon May 03 13:18:40 2010 +0300
@@ -40,6 +40,7 @@
 ****************************************************************************/
 
 #include "n900lightsensor.h"
+#include <QFile>
 #include <QDebug>
 #include <time.h>
 
@@ -50,8 +51,65 @@
     : n900filebasedsensor(sensor)
 {
     setReading<QAmbientLightReading>(&m_reading);
+    // Sensor takes 12-400ms to complete one reading and is triggered by
+    // a read of the /sys file (no interrupt/timing loop/etc. is used).
+    // Since no continuous operation is possible, don't set a data rate.
+    addDataRate(2, 2); // Close enough to 2 Hz
+    sensor->setDataRate(2);
+    setDescription(QLatin1String("tsl2563"));
 }
 
+void n900lightsensor::start()
+{
+    if (!QFile::exists(QLatin1String(filename)))
+        goto error;
+
+    n900filebasedsensor::start();
+    return;
+
+error:
+    sensorStopped();
+}
+
+struct lux_limit {
+    int min;
+    int max;
+};
+
+// Defines the min and max lux values that a given level has.
+// These are used to add histeresis to the sensor.
+// If the previous level is below a level, the lux must be at or above the minimum.
+// If the previous level is above a level, the lux muyt be at or below the maximum.
+static lux_limit limits[] = {
+    { 0,    0    }, // Undefined (not used)
+    { 0,    5    }, // Dark
+    { 10,   50   }, // Twilight
+    { 100,  200  }, // Light
+    { 500,  2000 }, // Bright
+    { 5000, 0    }  // Sunny
+};
+
+#if 0
+// Used for debugging
+static QString light_level(int level)
+{
+    switch (level) {
+    case 1:
+        return QLatin1String("Dark");
+    case 2:
+        return QLatin1String("Twilight");
+    case 3:
+        return QLatin1String("Light");
+    case 4:
+        return QLatin1String("Bright");
+    case 5:
+        return QLatin1String("Sunny");
+    default:
+        return QLatin1String("Undefined");
+    }
+}
+#endif
+
 void n900lightsensor::poll()
 {
     FILE *fd = fopen(filename, "r");
@@ -61,21 +119,37 @@
     fclose(fd);
     if (rs != 1) return;
 
-    QAmbientLightReading::LightLevel lightLevel = QAmbientLightReading::Undefined;
-    if (lux < 10)
-        lightLevel = QAmbientLightReading::Dark;
-    else if (lux < 50)
-        lightLevel = QAmbientLightReading::Twilight;
-    else if (lux < 100)
-        lightLevel = QAmbientLightReading::Light;
-    else if (lux < 150)
-        lightLevel = QAmbientLightReading::Bright;
-    else
-        lightLevel = QAmbientLightReading::Sunny;
+    // It's unweildly dealing with these constants so make some
+    // local aliases that are shorter. This makes the code below
+    // much easier to read.
+    enum {
+        Undefined = QAmbientLightReading::Undefined,
+        Dark = QAmbientLightReading::Dark,
+        Twilight = QAmbientLightReading::Twilight,
+        Light = QAmbientLightReading::Light,
+        Bright = QAmbientLightReading::Bright,
+        Sunny = QAmbientLightReading::Sunny
+    };
 
-    m_reading.setTimestamp(clock());
-    m_reading.setLightLevel(lightLevel);
+    int lightLevel = m_reading.lightLevel();
+    // Check for change direction to allow for histeresis
+    if      (lightLevel < Sunny    && lux >= limits[Sunny   ].min) lightLevel = Sunny;
+    else if (lightLevel < Bright   && lux >= limits[Bright  ].min) lightLevel = Bright;
+    else if (lightLevel < Light    && lux >= limits[Light   ].min) lightLevel = Light;
+    else if (lightLevel < Twilight && lux >= limits[Twilight].min) lightLevel = Twilight;
+    else if (lightLevel < Dark     && lux >= limits[Dark    ].min) lightLevel = Dark;
+    else if (lightLevel > Dark     && lux <= limits[Dark    ].max) lightLevel = Dark;
+    else if (lightLevel > Twilight && lux <= limits[Twilight].max) lightLevel = Twilight;
+    else if (lightLevel > Light    && lux <= limits[Light   ].max) lightLevel = Light;
+    else if (lightLevel > Bright   && lux <= limits[Bright  ].max) lightLevel = Bright;
 
-    newReadingAvailable();
+    //qDebug() << "lightLevel" << light_level(lightLevel) << "lux" << lux;
+
+    if (static_cast<int>(m_reading.lightLevel()) != lightLevel) {
+        m_reading.setTimestamp(clock());
+        m_reading.setLightLevel(static_cast<QAmbientLightReading::LightLevel>(lightLevel));
+
+        newReadingAvailable();
+    }
 }