X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=pwmled.c;fp=pwmled.c;h=0000000000000000000000000000000000000000;hb=f956c1fa7f47b0e8b8afe323c2eff1b6c2607c2a;hp=2640dba05bfc05edcd0c1d0f5e02f5c907919922;hpb=f7cba12a75f10da7267c2e4d4488bb5ccddbb9d9;p=bike-lights.git diff --git a/pwmled.c b/pwmled.c deleted file mode 100644 index 2640dba..0000000 --- a/pwmled.c +++ /dev/null @@ -1,243 +0,0 @@ -#include - -#include "lights.h" - -static unsigned char pwm_vals[N_PWMLEDS*N_PWMLED_MODES]; -static unsigned char adc_vals[N_PWMLEDS*N_PWMLED_MODES] = { - /* pwmled0 */ - 0x04, 0x14, 0x24, 0x38, - /* pwmled1 */ - 0x04, 0x14, 0x24, 0x38, - /* pwmled2 */ - 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 -#define ST_OFF 2 -#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]; - -static void start_probing(unsigned char n) -{ - pwmled_state[n] = ST_PROBING; - pwm_set(n, 0); - pwm_on(n); - pwm_probes[n] = 0; -} - -void pwmled_init() -{ - unsigned char 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_needs_adc(unsigned char n) -{ - unsigned char st = pwmled_state[n]; - if (st == ST_PROBING || st == ST_ON) - return 1; - else - 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; - -#if 0 - log_byte(0xF8); - log_byte(n); - log_byte(mode); -#endif - - 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); -#if 0 - log_byte(pwmval); -#endif - 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; - unsigned char *pwm_p = &pwm_vals[n*N_PWMLED_MODES]; - unsigned char *adc_p = &adc_vals[n*N_PWMLED_MODES]; - unsigned char pwm = pwm_probes[n]; - -#if 0 - log_byte(0xF4); - log_byte(n); - log_word(adcval); -#endif - - 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(0xF0); - log_byte(n); - log_word(adcval); - return; - } - - for (i = 0; i < N_PWMLED_MODES; i++, pwm_p++, adc_p++) { - uint16_t adc = *adc_p; - if (adc >= adcval) { - *pwm_p = pwm; - need_bigger = 1; - } - } - -#if 0 - if ((n == 1 && pwm > 0x35) || adcval != 0) { - log_byte(n); - log_byte(0xF3); - log_byte(pwm); - log_word(adcval); - } -#endif - - if (!need_bigger) { // successfully probed - pwm_off(n); - // pwm_set(n, 0); - pwmled_state[n] = ST_OFF; - log_byte(0xF1); - log_byte(n); - - return; - } - - if (pwm >= 0x70) { // over the maximum! - pwm_off(n); - pwmled_state[n] = ST_DISABLED; - log_byte(0xF2); - log_byte(n); - // pwm_set(n, 0); - return; - } - - // try to increase - pwm++; - pwm_probes[n] = pwm; - pwm_set(n, pwm); -} - -// Feedback loop -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]; - unsigned char *pwm_p = &pwm_vals[n*N_PWMLED_MODES+mode]; - uint16_t old_pwm = *pwm_p; - uint16_t new_pwm = old_pwm; - -#if 0 - log_byte(0xF5); - log_byte(n); - 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; - } - - // FIXME: better disconnect detection - if (new_pwm > 0x60) { // disconnected? - new_pwm = 0x60; - } - if (new_pwm < 2) { // short-circuit? - new_pwm = 2; - } - - if (new_pwm != old_pwm) { - *pwm_p = new_pwm; - pwm_set(n, new_pwm); -#if 0 - log_byte(0xF9); - 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++) - if (pwmled_state[i] == ST_PROBING) - probing = 1; - - if (!probing) { - for (i = 0; i < N_PWMLEDS; i++) - log_byte(pwmled_state[i]); - - 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? Maybe recently switched off? - } -}