X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?p=bike-lights.git;a=blobdiff_plain;f=firmware%2Fambient.c;h=3ae15d3c0e97080e1ac56957f06b67a883275305;hp=7a5b8e2c3c621f43a3c6aad52a6d5087ab304c1a;hb=dc4a8b74e6bd5ecfd139fabbb1f5bd8dad3b624e;hpb=24169faebe2fc7da98023c44a81db9f1894531db diff --git a/firmware/ambient.c b/firmware/ambient.c index 7a5b8e2..3ae15d3 100644 --- a/firmware/ambient.c +++ b/firmware/ambient.c @@ -7,11 +7,11 @@ #define AMBIENT_SLOW_SHIFT 6 // 1 << AMBIENT_SLOW_SHIFT times slower static uint16_t ambient_fast, ambient_slow; -volatile unsigned char ambient_zone; +volatile unsigned char ambient_zone, ambient_shadow; static unsigned char ambient_min, ambient_max, ambient_drop; /* logging */ -#define AMBIENT_LOG_SIZE 128 +#define AMBIENT_LOG_SIZE 256 static unsigned char ambient_log_offset_stored EEMEM; static unsigned char ambient_log_offset; static unsigned char ambient_log[AMBIENT_LOG_SIZE] EEMEM; @@ -26,12 +26,21 @@ typedef struct { * and having small overlaps in order to provide a bit of hysteresis. */ static ambient_zone_t ambient_zones[N_AMBIENT_ZONES] = { +#ifdef PAVLINA + { 0x0000, 0x02d0 }, // dark + { 0x02b0, 0x0318 }, // evening + { 0x0308, 0x032c }, // dawn + { 0x0324, 0xffff }, // day +#else { 0x0000, 0x0250 }, // dark - { 0x0240, 0x02e0 }, // evening - { 0x02c0, 0x0300 }, // dawn - { 0x02f8, 0xffff }, // day + { 0x0230, 0x02e8 }, // evening + { 0x02d0, 0x0302 }, // dawn + { 0x02fc, 0xffff }, // day +#endif }; +#define SHADOW_DROP_LIMIT 0x20 // in ADC units (0..0x3ff) + void init_ambient() { ambient_slow = 0; @@ -40,6 +49,7 @@ void init_ambient() ambient_min = 0xFF; ambient_zone = 1; ambient_drop = 0; + ambient_shadow = 0; ambient_log_offset = eeprom_read_byte(&ambient_log_offset_stored); @@ -62,7 +72,7 @@ void susp_ambient() void ambient_log_min_max() { if (ambient_log_offset >= AMBIENT_LOG_SIZE - 1) - return; + ambient_log_offset = 0; // start over ambient_max -= ambient_min; // ambient_max >>= 2; @@ -92,6 +102,9 @@ static unsigned char val_to_zone(uint16_t ambient_val) { unsigned char new_zone = ambient_zone; + if (new_zone >= N_AMBIENT_ZONES) + new_zone = N_AMBIENT_ZONES-1; + while (ambient_zones[new_zone].lo > ambient_val) new_zone--; @@ -103,34 +116,62 @@ static unsigned char val_to_zone(uint16_t ambient_val) void ambient_adc(uint16_t adcval) { - unsigned char new_zone, user_zone; + unsigned char new_zone, user_zone, new_shadow = 0; unsigned char byte_fast, byte_slow, drop; - uint16_t a_10bit; + uint16_t fast_10bit, slow_10bit; // running avg - shorter timespan ambient_fast += adcval - (ambient_fast >> AMBIENT_FAST_SHIFT); // running avg - longer timespan - a_10bit = ambient_fast >> (AMBIENT_FAST_SHIFT + AMBIENT_ADC_SHIFT); - ambient_slow += a_10bit - (ambient_slow >> AMBIENT_SLOW_SHIFT); + fast_10bit = ambient_fast >> (AMBIENT_FAST_SHIFT + AMBIENT_ADC_SHIFT); + ambient_slow += fast_10bit - (ambient_slow >> AMBIENT_SLOW_SHIFT); // ambient zones are governed by shorter timespan by default - new_zone = val_to_zone(a_10bit); + new_zone = val_to_zone(fast_10bit); + + slow_10bit = ambient_slow >> AMBIENT_SLOW_SHIFT; - if (new_zone > 1 && ( - new_zone == ambient_zone-1 || new_zone == ambient_zone+1)) { + if ((new_zone > ambient_zone) + || (new_zone > 1 && new_zone == ambient_zone - 1)) { // but change to the neighbouring zone is governed by _slow, // except to the darkest zone, where we want fast reaction. - new_zone = val_to_zone(ambient_slow >> AMBIENT_SLOW_SHIFT); + new_zone = val_to_zone(slow_10bit); } // user_param ambient zone override if ((user_zone = get_user_param(0)) > 0) new_zone = user_zone - 1; +#if 0 // ignore shadow-entering code altogether for now + // are we entering the shadow? + if (!user_zone && new_zone < ambient_zone + && ambient_zone >= 2 && slow_10bit > fast_10bit + && slow_10bit - fast_10bit >= SHADOW_DROP_LIMIT) { + // we are entering the shadow + new_shadow = 0x30; + } + + if (ambient_shadow) { + if (new_shadow) { + new_zone = ambient_zone; // don't change while entering shadow + ambient_shadow = new_shadow; // update the timeout + } else { + ambient_shadow--; + if (!ambient_shadow) { // leaving the shadow + ambient_zone_changed(); + } + } + } else if (new_shadow) { + ambient_shadow = new_shadow; // set up the timeout + new_zone = ambient_zone; // don't change while entering shadow + ambient_zone_changed(); // notify others the first time + } +#endif + // TODO: maybe use these values instead of 10-bit? - byte_fast = a_10bit >> 2; - byte_slow = ambient_slow >> (AMBIENT_SLOW_SHIFT + 2); + byte_fast = fast_10bit >> 2; + byte_slow = slow_10bit >> 2; if (byte_slow > byte_fast) { drop = byte_slow - byte_fast;