X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=pwmled.c;h=b4545e7391b205e477d8d882012a566df7823ba4;hb=1d7ad9daee131c758cdf95b5608f602254f10427;hp=ac0e4445cd803eb1f8b9fc0416ae87915e693b66;hpb=2f02dcff5103d6466523678a8fafb385530406d2;p=bike-lights.git diff --git a/pwmled.c b/pwmled.c index ac0e444..b4545e7 100644 --- a/pwmled.c +++ b/pwmled.c @@ -12,6 +12,7 @@ static unsigned char adc_vals[N_PWMLEDS*N_PWMLED_MODES] = { 0x04, 0x14, 0x24, 0x38, }; +// TODO: maybe convert this to bitmask to simplify pwmled_needs_adc() ? static unsigned char pwmled_state[N_PWMLEDS]; #define ST_DISABLED 0 #define ST_PROBING 1 @@ -19,6 +20,7 @@ static unsigned char pwmled_state[N_PWMLEDS]; #define ST_ON 3 static unsigned char pwmled_mode[N_PWMLEDS]; +static unsigned char pwmled_mode_set[N_PWMLEDS]; static unsigned char pwm_probes[N_PWMLEDS]; @@ -34,15 +36,18 @@ void pwmled_init() { unsigned char i; - for (i = 0; i < N_PWMLEDS*N_PWMLED_MODES; i++) + for (i = 0; i < N_PWMLEDS*N_PWMLED_MODES; i++) { pwm_vals[i] = 0; + pwmled_mode[i] = 0; + pwmled_mode_set[i] = 0; + } for (i = 0; i < N_PWMLEDS; i++) { start_probing(i); } } -unsigned char pwmled_is_on(unsigned char n) +unsigned char pwmled_needs_adc(unsigned char n) { unsigned char st = pwmled_state[n]; if (st == ST_PROBING || st == ST_ON) @@ -51,6 +56,43 @@ unsigned char pwmled_is_on(unsigned char n) return 0; } +unsigned char pwmled_enabled(unsigned char n) +{ + unsigned char st = pwmled_state[n]; + if (st == ST_OFF || st == ST_ON) + return 1; + else + return 0; +} + +void pwmled_set_mode(unsigned char n, unsigned char mode) +{ + if (!pwmled_enabled(n)) + return; + + log_byte(0xF8); + log_byte(n); + log_byte(mode); + + if (mode == 0) { + pwm_off(n); + pwmled_state[n] = ST_OFF; + return; + } + + if (mode <= N_PWMLED_MODES) { + unsigned char pwmval; + mode--; + pwmval = pwm_vals[n*N_PWMLED_MODES+mode]; + pwm_set(n, pwmval); + pwm_on(n); + log_byte(pwmval); + pwmled_state[n] = ST_ON; + pwmled_mode[n] = mode; + pwmled_mode_set[n] = 1; + } +} + static void inline probing_adc(unsigned char n, uint16_t adcval) { unsigned char need_bigger = 0, i; @@ -64,15 +106,16 @@ static void inline probing_adc(unsigned char n, uint16_t adcval) log_word(adcval); #endif -#if 0 - if (pwm == 0 && adcval > 0) { // non-zero voltage with zero PWM? + if (adcval > 0x100 // Too high + || (pwm == 0 && adcval > 0) // non-zero voltage with zero PWM + ) { + pwm_off(n); pwmled_state[n] = ST_DISABLED; - log_byte(n); log_byte(0xF0); + log_byte(n); log_word(adcval); return; } -#endif for (i = 0; i < N_PWMLED_MODES; i++, pwm_p++, adc_p++) { uint16_t adc = *adc_p; @@ -119,13 +162,24 @@ static void inline probing_adc(unsigned char n, uint16_t adcval) // Feedback loop static void inline on_adc(unsigned char n, uint16_t adcval) { -#if 0 - uint16_t new_pwm = led_modes[led_mode].pwmval; - uint16_t old_pwm = new_pwm; - uint16_t adc_exp = led_modes[led_mode].expected; + unsigned char mode = pwmled_mode[n]; + uint16_t adc_exp = adc_vals[n*N_PWMLED_MODES+mode]; + unsigned char *pwm_p = &pwm_vals[n*N_PWMLED_MODES+mode]; + uint16_t old_pwm = *pwm_p; + uint16_t new_pwm = old_pwm; + +#if 1 + log_byte(0xF5); + log_byte(n); + log_word(adcval); +#endif - log_word(((adcval & 0xFF) << 8) | old_pwm); + 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 @@ -134,20 +188,20 @@ static void inline on_adc(unsigned char n, uint16_t adcval) new_pwm = old_pwm + 1; } - if (new_pwm > 0x60) { // odpojeno? + // FIXME: better disconnect detection + if (new_pwm > 0x60) { // disconnected? new_pwm = 0x60; } - if (new_pwm < 2) { // zkrat? + if (new_pwm < 2) { // short-circuit? new_pwm = 2; } -set_pwm: if (new_pwm != old_pwm) { - led_modes[led_mode].pwmval = new_pwm; - OCR1D = new_pwm; + *pwm_p = new_pwm; + pwm_set(n, new_pwm); + log_byte(0xF9); + log_byte(new_pwm); } - // ADCSRA |= _BV(ADSC); -#endif } void pwmled_adc(unsigned char n, uint16_t adcval) @@ -157,6 +211,7 @@ void pwmled_adc(unsigned char n, uint16_t adcval) case ST_PROBING: probing_adc(n, adcval); +#if 1 probing = 0; for (i = 0; i < N_PWMLEDS; i++) if (pwmled_state[i] == ST_PROBING) @@ -169,12 +224,14 @@ void pwmled_adc(unsigned char n, uint16_t adcval) for (i = 0; i < N_PWMLEDS*N_PWMLED_MODES; i++) log_byte(pwm_vals[i]); log_flush(); + log_set_state(4); } +#endif return; case ST_ON: on_adc(n, adcval); return; - // WTF am I doing in this function then? + // WTF am I doing in this function then? Maybe recently switched off? } }