#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 */
{ 0x02f8, 0xffff }, // day
};
+#define SHADOW_DROP_LIMIT 0x20 // in ADC units (0..0x3ff)
+
void init_ambient()
{
ambient_slow = 0;
ambient_min = 0xFF;
ambient_zone = 1;
ambient_drop = 0;
+ ambient_shadow = 0;
ambient_log_offset = eeprom_read_byte(&ambient_log_offset_stored);
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)) {
// 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;
+ // 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
+ }
+
// 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;