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=904f2161f5fba06f4b27f38cf23b6a9c2b90417d;hp=aca12577fd1f4876549232b817e48eda534360f4;hb=5a5088f09ea11dd3c36f3bb6833a0c5d85715641;hpb=245a5fcfa3da6628a5634a9899913c0be143ffa9 diff --git a/firmware/ambient.c b/firmware/ambient.c index aca1257..904f216 100644 --- a/firmware/ambient.c +++ b/firmware/ambient.c @@ -3,10 +3,12 @@ #include "lights.h" -#define AMBIENT_VAL_SHIFT 2 -static uint16_t ambient_val, ambient_val16; +#define AMBIENT_FAST_SHIFT 2 // running avg of ADC vals +#define AMBIENT_SLOW_SHIFT 6 // 1 << AMBIENT_SLOW_SHIFT times slower + +static uint16_t ambient_fast, ambient_slow; volatile unsigned char ambient_zone; -static unsigned char ambient_min, ambient_max, ambient_16drop; +static unsigned char ambient_min, ambient_max, ambient_drop; /* logging */ #define AMBIENT_LOG_SIZE 128 @@ -16,7 +18,7 @@ static unsigned char ambient_log[AMBIENT_LOG_SIZE] EEMEM; /* My photodiode reads 0x00C5 .. 0x033B */ typedef struct { - uint16_t lo, hi; + uint16_t lo, hi; // TODO: consider changing this to bytes } ambient_zone_t; /* @@ -24,20 +26,20 @@ typedef struct { * and having small overlaps in order to provide a bit of hysteresis. */ static ambient_zone_t ambient_zones[N_AMBIENT_ZONES] = { - { 0x0000 , 0x0250<= 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_max -= ambient_min; + ambient_max >>= 2; + if (ambient_max > 15) + ambient_max = 15; + + ambient_drop >>= 2; + if (ambient_drop > 15) + ambient_drop = 15; + + eeprom_write_byte(&ambient_log[ambient_log_offset++], ambient_min); + eeprom_write_byte(&ambient_log[ambient_log_offset++], + (ambient_max << 4) | ambient_drop); ambient_min = 0xFF; ambient_max = 0; - ambient_16drop = 0; + ambient_drop = 0; } static inline void ambient_zone_changed() @@ -77,42 +88,64 @@ static inline void ambient_zone_changed() pattern_reload(); } -void ambient_adc(uint16_t adcval) +static unsigned char val_to_zone(uint16_t ambient_val) { - unsigned char old_zone = ambient_zone; - unsigned char byte_val, byte_val16; + unsigned char new_zone = ambient_zone; - ambient_val += adcval - (ambient_val - >> (AMBIENT_VAL_SHIFT - AMBIENT_ADC_SHIFT)); + while (ambient_zones[new_zone].lo > ambient_val) + new_zone--; + + while (ambient_zones[new_zone].hi < ambient_val) + new_zone++; + + return new_zone; +} - while (ambient_zones[ambient_zone].lo > ambient_val) - ambient_zone--; +void ambient_adc(uint16_t adcval) +{ + unsigned char new_zone, user_zone; + unsigned char byte_fast, byte_slow, drop; + uint16_t a_10bit; - while (ambient_zones[ambient_zone].hi < ambient_val) - ambient_zone++; + // running avg - shorter timespan + ambient_fast += adcval - (ambient_fast >> AMBIENT_FAST_SHIFT); - byte_val = ambient_val >> (2 + AMBIENT_VAL_SHIFT - AMBIENT_ADC_SHIFT); + // running avg - longer timespan + a_10bit = ambient_fast >> (AMBIENT_FAST_SHIFT + AMBIENT_ADC_SHIFT); + ambient_slow += a_10bit - (ambient_slow >> AMBIENT_SLOW_SHIFT); - ambient_val16 += byte_val - (ambient_val16 >> 4); - byte_val16 = ambient_val16 >> 4; + // ambient zones are governed by shorter timespan by default + new_zone = val_to_zone(a_10bit); - if (byte_val16 > byte_val) { - byte_val16 -= byte_val; - if (byte_val16 > ambient_16drop) - ambient_16drop = byte_val16; + if (new_zone > 1 && ( + new_zone == ambient_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); } - if (ambient_min > byte_val) - ambient_min = byte_val; + // user_param ambient zone override + if ((user_zone = get_user_param(0)) > 0) + new_zone = user_zone - 1; - if (ambient_max < byte_val) - ambient_max = byte_val; + // TODO: maybe use these values instead of 10-bit? + byte_fast = a_10bit >> 2; + byte_slow = ambient_slow >> (AMBIENT_SLOW_SHIFT + 2); - // user_param ambient zone override - if ((byte_val = get_user_param(0)) > 0) - ambient_zone = byte_val - 1; + if (byte_slow > byte_fast) { + drop = byte_slow - byte_fast; + if (drop > ambient_drop) + ambient_drop = drop; + } + + if (ambient_min > byte_fast) + ambient_min = byte_fast; + + if (ambient_max < byte_fast) + ambient_max = byte_fast; - if (old_zone != ambient_zone) { + if (new_zone != ambient_zone) { + ambient_zone = new_zone; #if 0 log_byte(0xab); log_byte(ambient_zone);