break;
case 3: // ambient light: 1.1V, ADC5 (PA6), single-ended
ADMUX = _BV(REFS1) | _BV(MUX2) | _BV(MUX0);
- sum_shift = 0; // 1 measurement
+ sum_shift = 3; // 3 measurements
break;
case 4: // batt voltage: 1.1V, ADC6 (PA7), single-ended
ADMUX = _BV(REFS1) | _BV(MUX2) | _BV(MUX1);
static uint16_t ambient_val;
volatile unsigned char ambient_zone;
-static unsigned char ambient_zone_set;
-static uint16_t ambient_zones[] = {
- 0x0c00, 0x0d00, 0x1000, 0x1800, 0x2800, 0x2f80, 0xffff
+/* My photodiode reads 0x00C5 .. 0x033B */
+typedef struct {
+ uint16_t lo, hi;
+} 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, 0x3400 }, // dark
+ { 0x3300, 0x5000 },
+ { 0x4c00, 0x8000 },
+ { 0x7800, 0xffff }
};
#define N_AMBIENT_ZONES (sizeof(ambient_zones)/sizeof(ambient_zones[0]))
void init_ambient()
{
ambient_val = 0;
- ambient_zone = 0;
- ambient_zone_set = 0;
+ ambient_zone = 1;
}
void ambient_zone_changed()
{
+#if 1
log_byte(0xab);
log_byte(ambient_zone);
log_word(ambient_val);
log_flush();
+#endif
- pattern_reload();
+ // led_set_pattern(N_PWMLEDS, status_led_pattern_select());
+ // led_set_pattern(N_PWMLEDS+1, illumination_led_pattern_select());
+ // pattern_reload();
}
void ambient_adc(uint16_t adcval)
{
- unsigned char newzone;
-
- if (!ambient_zone_set)
- ambient_val = adcval << 4;
- else // running sum
- ambient_val += adcval - (ambient_val >> 4);
-
- newzone = 0;
- while (newzone < N_AMBIENT_ZONES-1
- && ambient_zones[newzone] < ambient_val)
- newzone++;
-
- // TODO: implement hysteresis?
- if (!ambient_zone_set || newzone != ambient_zone) {
- ambient_zone = newzone;
- ambient_zone_set = 1;
- // ambient_zone_changed();
+ unsigned char old_zone = ambient_zone;
+
+ ambient_val += adcval - (ambient_val >> 3);
+
+ while (ambient_zones[ambient_zone].lo > ambient_val)
+ ambient_zone--;
+
+ while (ambient_zones[ambient_zone].hi < ambient_val)
+ ambient_zone++;
+
+#if 0
+ if (old_zone != ambient_zone) {
+ log_byte(0xab);
+ log_byte(ambient_zone);
+ log_word(adcval);
+ log_flush();
}
+ // ambient_zone_changed();
+#endif
}
} else if (!cur && !prev) { // --- is still pressed ---
uint16_t duration = jiffies - button_start[button];
- if (duration > 80) {
+ if (duration > 160) {
set_status_led(button, on1_pattern);
// acknowledge long press
}
} else if (cur && !prev) { // --- just released ---
uint16_t duration = jiffies - button_start[button];
- if (duration > 6 && duration < 30) {
+ if (duration > 6 && duration < 60) {
short_press(button);
- } else if (duration > 80) {
+ } else if (duration > 160) {
set_status_led(button, NULL);
long_press(button);
}
};
pattern_t on1_pattern [] = {
- { 1, PATTERN_FOREVER }
+ { 1, 0x10 },
+ PATTERN_END
};
static pattern_t on2_pattern [] = {
- { 2, PATTERN_FOREVER }
+ { 2, 0x10 },
+ PATTERN_END
};
static pattern_t on3_pattern [] = {
- { 3, PATTERN_FOREVER }
+ { 3, 0x10 },
+ PATTERN_END
};
static pattern_t normal2_pattern[] = {
{
// TODO: battery critical
-#ifndef TESTING_FW
- return normal3_pattern;
-#endif
-
if (towbar_mode)
return NULL;
switch (ambient_zone) {
- case 0: return dim_mode ? NULL : on1_pattern;
- case 1: return dim_mode ? NULL : slow2_pattern;
- case 2: return dim_mode ? slow3_pattern : slow2_pattern;
+ case 0: return dim_mode ? NULL : on3_pattern;
+ case 1: return dim_mode ? NULL : normal3_pattern;
+ case 2: return dim_mode ? slow3_pattern : normal3_pattern;
case 3:
default: return dim_mode ? slow3_pattern : normal4_pattern;
}
// TODO: battery critical
#ifndef TESTING_FW
- return off_pattern;
+ return NULL;
#endif
+
if (towbar_mode) {
switch (ambient_zone) {
case 0:
? number_pattern(2, 1)
: number_pattern(3, 1);
case 2: return dim_mode
- ? number_pattern(3, 0)
- : number_pattern(4, 0);
+ ? number_pattern(1, 0)
+ : number_pattern(2, 0);
case 3:
default: return dim_mode
- ? number_pattern(5, 0)
- : number_pattern(6, 0);
+ ? number_pattern(3, 0)
+ : number_pattern(4, 0);
}
}
PATTERN_END
};
+pattern_t off_pattern[] = {
+ { 0, 0x1E },
+ PATTERN_END
+};
+
static void led_set_mode(unsigned char n, unsigned char mode)
{
if (n < N_PWMLEDS) {
void led_set_pattern(unsigned char n, pattern_t *pattern)
{
- led_patterns[n] = pattern;
+ if (!pattern)
+ pattern = off_pattern;
- if (!pattern) {
- led_set_mode(n, 0);
- return;
- }
+ led_patterns[n] = pattern;
led_counters[n] = pattern->duration;
led_set_mode(n, pattern->mode);
typedef struct {
uint16_t target, pwm;
int16_t err_sum;
- unsigned char mode, state, probe_steady;
+ unsigned char mode, state;
+ union {
+ unsigned char probe_steady, mode_changed;
+ };
uint16_t mode_pwm[N_PWMLED_MODES];
int16_t err_sums[N_PWMLED_MODES];
} pwmled_t;
led->state = ST_ON;
led->pwm = led->mode_pwm[mode - 1];
led->err_sum = led->err_sums[mode - 1];
+ led->mode_changed = 1;
pwm_set(n, led->pwm);
} else {
led->state = ST_OFF;
if (!ST_IS_ON(led->state))
return;
+ if (led->state == ST_ON && led->mode_changed) {
+ led->mode_changed--;
+ return;
+ }
// FIXME: test for maximum adcval value (adc_max[n])
old_pwm = led->pwm;
sum -= led->pwm << shift;
led->err_sum = sum;
- if (led->pwm >= PWM_MAX) {
+ if (led->pwm >= PWM_MAX
+ || (n == 1 && led->pwm > PWM_MAX/4 && adcval < 0x08)) {
pwmled_err(n);
return;
}