static unsigned char pwmled_mode_set[N_PWMLEDS];
static uint16_t pwm_probes[N_PWMLEDS];
+static int16_t differences[N_PWMLEDS];
static void start_probing(unsigned char n)
{
}
for (i = 0; i < N_PWMLEDS; i++) {
+ differences[i] = 0;
start_probing(i);
}
}
log_byte(n);
log_byte(mode);
#endif
-
- if (mode == 0) {
- pwm_off(n);
- pwmled_state[n] = ST_OFF;
- return;
- }
-
- if (mode <= N_PWMLED_MODES) {
+ if (mode > 0 && mode <= N_PWMLED_MODES) {
uint16_t pwmval;
mode--;
pwmval = pwm_vals[n*N_PWMLED_MODES+mode];
pwmled_state[n] = ST_ON;
pwmled_mode[n] = mode;
pwmled_mode_set[n] = 1;
+ differences[n] = 0;
+ } else {
+ pwm_off(n);
+ pwmled_state[n] = ST_OFF;
}
}
static void inline on_adc(unsigned char n, uint16_t adcval)
{
unsigned char mode = pwmled_mode[n];
- uint16_t adc_exp = adc_vals[n*N_PWMLED_MODES+mode];
- uint16_t *pwm_p = &pwm_vals[n*N_PWMLED_MODES+mode];
- uint16_t old_pwm = *pwm_p;
- uint16_t new_pwm = old_pwm;
+ uint16_t adc_exp = adc_vals[n*N_PWMLED_MODES+mode];
+ uint16_t *pwm_p = &pwm_vals[n*N_PWMLED_MODES+mode];
+ int16_t old_pwm = *pwm_p;
+ int16_t new_pwm = old_pwm;
#if 0
log_byte(0xF5);
log_word(adcval);
#endif
+
if (pwmled_mode_set[n]) { // ignore the first reading
pwmled_mode_set[n] = 0;
return;
}
- // FIXME: running average?
- if (2*adcval > 5*adc_exp) { // >2.5x expected, lower significantly
- new_pwm = 2*old_pwm/3;
- } else if (3*adcval > 4*adc_exp) { // >1.33x expected, lower a bit
- new_pwm = old_pwm - 1;
- } else if (4*adcval < 3*adc_exp) { // 0.75x expected, raise a bit
- new_pwm = old_pwm + 1;
- }
+ differences[n] += adcval;
+ differences[n] -= adc_exp;
- // FIXME: better disconnect detection
- if (new_pwm > pwm_max[n]) { // FIXME: disconnected?
+ if (differences[n] > 16)
+ new_pwm -= 2;
+ else if (differences[n] > 4)
+ new_pwm--;
+ else if (differences[n] < -16)
+ new_pwm += 2;
+ else if (differences[n] < -4)
+ new_pwm++;
+ // new_pwm -= differences[n] >> 3;
+
+ if (new_pwm == old_pwm)
+ return;
+
+ differences[n] = 0;
+
+ if (new_pwm > (int16_t)pwm_max[n]) {
+ // FIXME: disconnected?
new_pwm = pwm_max[n];
}
- if (new_pwm < 2) { // short-circuit?
- new_pwm = 2;
+
+ if (new_pwm < 1) {
+ // FIXME: short-circuit?
+ new_pwm = 1;
}
- if (new_pwm != old_pwm) {
- *pwm_p = new_pwm;
- pwm_set(n, new_pwm);
-#if 0
- log_byte(0xF9);
+ *pwm_p = new_pwm;
+ pwm_set(n, new_pwm);
+
+ if (jiffies > 500 && n == 1) {
+ log_byte(adcval & 0xFF);
log_byte(new_pwm);
-#endif
}
}
void pwmled_adc(unsigned char n, uint16_t adcval)
{
unsigned char i, probing;
+
switch (pwmled_state[n]) {
case ST_PROBING:
probing_adc(n, adcval);
-
#if 1
probing = 0;
for (i = 0; i < N_PWMLEDS; i++)