]> www.fi.muni.cz Git - bike-lights.git/blobdiff - firmware/ambient.c
ambient.c: detect drop of ambient light
[bike-lights.git] / firmware / ambient.c
index 735f80e968a940c7a77dc210bb73d07c0ee16ace..b8397532026fed989d06ff6454974be46e043850 100644 (file)
@@ -1,9 +1,18 @@
 #include <avr/io.h>
+#include <avr/eeprom.h>
 
 #include "lights.h"
 
-static uint16_t ambient_val;
+#define AMBIENT_VAL_SHIFT 2
+static uint16_t ambient_val, ambient_val16;
 volatile unsigned char ambient_zone;
+static unsigned char ambient_min, ambient_max, ambient_16drop;
+
+/* logging */
+#define AMBIENT_LOG_SIZE 128
+static unsigned char ambient_log_offset_stored EEMEM;
+static unsigned char ambient_log_offset;
+static unsigned char ambient_log[AMBIENT_LOG_SIZE] EEMEM;
 
 /* My photodiode reads 0x00C5 .. 0x033B */
 typedef struct {
@@ -15,17 +24,52 @@ typedef struct {
  * and having small overlaps in order to provide a bit of hysteresis.
  */
 static ambient_zone_t ambient_zones[] = {
-       { 0x0000, 0x3400 }, // dark
-       { 0x3300, 0x5000 },
-       { 0x4c00, 0x8000 },
-       { 0x7800, 0xffff }
+       { 0x0000                   , 0x0280<<AMBIENT_VAL_SHIFT }, // dark
+       { 0x0270<<AMBIENT_VAL_SHIFT, 0x02f0<<AMBIENT_VAL_SHIFT }, // evening
+       { 0x02e8<<AMBIENT_VAL_SHIFT, 0x0306<<AMBIENT_VAL_SHIFT }, // dawn
+       { 0x0300<<AMBIENT_VAL_SHIFT, 0xffff                    }, // day
 };
 #define N_AMBIENT_ZONES (sizeof(ambient_zones)/sizeof(ambient_zones[0]))
 
 void init_ambient()
 {
        ambient_val = 0;
+       ambient_val16 = 0;
+       ambient_max = 0;
+       ambient_min = 0xFF;
        ambient_zone = 1;
+       ambient_16drop = 0;
+
+       ambient_log_offset = eeprom_read_byte(&ambient_log_offset_stored);
+
+       if (ambient_log_offset == AMBIENT_LOG_SIZE)
+               ambient_log_offset = 0; // start over
+}
+
+void susp_ambient()
+{
+       unsigned char stored_offset;
+
+       ambient_log_min_max();
+
+       stored_offset = eeprom_read_byte(&ambient_log_offset_stored);
+       if (stored_offset != ambient_log_offset)
+               eeprom_write_byte(&ambient_log_offset_stored,
+                       ambient_log_offset);
+}
+
+void ambient_log_min_max()
+{
+       if (ambient_log_offset >= AMBIENT_LOG_SIZE - 1)
+               return;
+
+       eeprom_write_byte(&ambient_log[ambient_log_offset++], ambient_min);
+       // eeprom_write_byte(&ambient_log[ambient_log_offset++], ambient_max);
+       eeprom_write_byte(&ambient_log[ambient_log_offset++], ambient_16drop);
+
+       ambient_min = 0xFF;
+       ambient_max = 0;
+       ambient_16drop = 0;
 }
 
 void ambient_zone_changed()
@@ -45,8 +89,10 @@ void ambient_zone_changed()
 void ambient_adc(uint16_t adcval)
 {
        unsigned char old_zone = ambient_zone;
+       unsigned char byte_val, byte_val16;
 
-       ambient_val += adcval - (ambient_val >> 3);
+       ambient_val += adcval - (ambient_val
+               >> (AMBIENT_VAL_SHIFT - AMBIENT_ADC_SHIFT));
 
        while (ambient_zones[ambient_zone].lo > ambient_val)
                ambient_zone--;
@@ -54,6 +100,22 @@ void ambient_adc(uint16_t adcval)
        while (ambient_zones[ambient_zone].hi < ambient_val)
                ambient_zone++;
 
+       byte_val = ambient_val >> (2 + AMBIENT_VAL_SHIFT - AMBIENT_ADC_SHIFT);
+
+       ambient_val16 += byte_val - (ambient_val16 >> 4);
+       byte_val16 = ambient_val16 >> 4;
+
+       if (byte_val16 > byte_val) {
+               byte_val16 -= byte_val;
+               if (byte_val16 > ambient_16drop)
+                       ambient_16drop = byte_val16;
+       }
+
+       if (ambient_min > byte_val)
+               ambient_min = byte_val;
+
+       if (ambient_max < byte_val)
+               ambient_max = byte_val;
 #if 0
        if (old_zone != ambient_zone) {
                log_byte(0xab);