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=aeaa62ac8e5436bf13b3fa4c315078c87e1fd0e0;hb=5a5088f09ea11dd3c36f3bb6833a0c5d85715641;hpb=b2e743a2225d5014c7e614ebc9feb7eb51bc4ef6 diff --git a/firmware/ambient.c b/firmware/ambient.c index aeaa62a..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,29 +18,28 @@ 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; /* * Note: these have to be sorted, starting with 0, ending with 0xFFFF * and having small overlaps in order to provide a bit of hysteresis. */ -static ambient_zone_t ambient_zones[] = { - { 0x0000 , 0x0270<= AMBIENT_LOG_SIZE - 1) return; + 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); - eeprom_write_byte(&ambient_log[ambient_log_offset++], ambient_16drop); + 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; } -void ambient_zone_changed() +static inline void ambient_zone_changed() { -#if 1 - log_byte(0xab); - log_byte(ambient_zone); - log_word(ambient_val); - log_flush(); -#endif + pwmled_select_brightness(); + pattern_reload(); +} + +static unsigned char val_to_zone(uint16_t ambient_val) +{ + unsigned char new_zone = ambient_zone; - // led_set_pattern(N_PWMLEDS, status_led_pattern_select()); - // led_set_pattern(N_PWMLEDS+1, illumination_led_pattern_select()); - // pattern_reload(); + while (ambient_zones[new_zone].lo > ambient_val) + new_zone--; + + while (ambient_zones[new_zone].hi < ambient_val) + new_zone++; + + return new_zone; } void ambient_adc(uint16_t adcval) { - unsigned char old_zone = ambient_zone; - unsigned char byte_val, byte_val16; + unsigned char new_zone, user_zone; + unsigned char byte_fast, byte_slow, drop; + uint16_t a_10bit; - ambient_val += adcval - (ambient_val - >> (AMBIENT_VAL_SHIFT - AMBIENT_ADC_SHIFT)); + // running avg - shorter timespan + ambient_fast += adcval - (ambient_fast >> AMBIENT_FAST_SHIFT); - while (ambient_zones[ambient_zone].lo > ambient_val) - ambient_zone--; + // running avg - longer timespan + a_10bit = ambient_fast >> (AMBIENT_FAST_SHIFT + AMBIENT_ADC_SHIFT); + ambient_slow += a_10bit - (ambient_slow >> AMBIENT_SLOW_SHIFT); - while (ambient_zones[ambient_zone].hi < ambient_val) - ambient_zone++; + // ambient zones are governed by shorter timespan by default + new_zone = val_to_zone(a_10bit); + + 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); + } - byte_val = ambient_val >> (2 + AMBIENT_VAL_SHIFT - AMBIENT_ADC_SHIFT); + // user_param ambient zone override + if ((user_zone = get_user_param(0)) > 0) + new_zone = user_zone - 1; - ambient_val16 += byte_val - (ambient_val16 >> 4); - byte_val16 = ambient_val16 >> 4; + // TODO: maybe use these values instead of 10-bit? + byte_fast = a_10bit >> 2; + byte_slow = ambient_slow >> (AMBIENT_SLOW_SHIFT + 2); - if (byte_val16 > byte_val) { - byte_val16 -= byte_val; - if (byte_val16 > ambient_16drop) - ambient_16drop = byte_val16; + if (byte_slow > byte_fast) { + drop = byte_slow - byte_fast; + if (drop > ambient_drop) + ambient_drop = drop; } - if (ambient_min > byte_val) - ambient_min = byte_val; + if (ambient_min > byte_fast) + ambient_min = byte_fast; - if (ambient_max < byte_val) - ambient_max = byte_val; + if (ambient_max < byte_fast) + ambient_max = byte_fast; + + if (new_zone != ambient_zone) { + ambient_zone = new_zone; #if 0 - if (old_zone != ambient_zone) { log_byte(0xab); log_byte(ambient_zone); log_word(adcval); log_flush(); - } - // ambient_zone_changed(); #endif + ambient_zone_changed(); + } }