Commit e207868d authored by Jan Kasprzak's avatar Jan Kasprzak
Browse files

pwmled.c: only one pwmled

parent 8ebf32f3
......@@ -202,7 +202,7 @@ ISR(ADC_vect) { // IRQ handler
switch (current_adc) {
case 0:
// pwmled_adc(current_adc, adc_sum);
pwmled_adc(1, adc_sum);
pwmled_adc(adc_sum);
break;
}
......
......@@ -44,8 +44,8 @@ void susp_tmr();
/* pwmled.c */
void init_pwmled();
void pwmled_adc(unsigned char n, uint16_t adcval);
void pwmled_set_mode(unsigned char n, unsigned char mode);
void pwmled_adc(uint16_t adcval);
void pwmled_set_mode(unsigned char mode);
/* gpio.c */
void init_gpio();
......
......@@ -2,18 +2,11 @@
#include "lights.h"
typedef struct {
uint16_t target, pwm;
int16_t err_sum;
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;
pwmled_t pwmleds[N_PWMLEDS];
static uint16_t target;
static uint16_t pwm_val;
static int16_t err_sum;
static unsigned char state;
unsigned char mode_changed;
#define SENSE_MOHM 3000 /* 1 Ohm */
/*
......@@ -21,29 +14,20 @@ pwmled_t pwmleds[N_PWMLEDS];
* ADC module returns sum of 1 << PWMLED_ADC_SHIFT measurements
* Voltage in uV measured is current in mA * sense resistance in mOhm
*/
#define MA_GAIN_TO_ADC(ma, gain) ((uint16_t) \
#define MA_TO_ADC(ma) ((uint16_t) \
((uint32_t)(ma) \
* (SENSE_MOHM) \
* (1 << (PWMLED_ADC_SHIFT)) \
* 1024 \
/ (1100000/(gain))))
/ 1100000))
static uint16_t adc_max[N_PWMLEDS] = {
MA_GAIN_TO_ADC( 30, 1),
MA_GAIN_TO_ADC( 30, 1),
};
static uint16_t adc_max = MA_TO_ADC(30);
static uint16_t adc_vals[N_PWMLEDS*N_PWMLED_MODES] = {
/* pwmled0 */
MA_GAIN_TO_ADC( 2, 1),
MA_GAIN_TO_ADC( 5, 1),
MA_GAIN_TO_ADC( 10, 1),
MA_GAIN_TO_ADC( 20, 1),
/* pwmled1 */
MA_GAIN_TO_ADC( 2, 1),
MA_GAIN_TO_ADC( 8, 1),
MA_GAIN_TO_ADC( 14, 1),
MA_GAIN_TO_ADC( 20, 1),
static uint16_t targets[N_PWMLED_MODES] = {
MA_TO_ADC( 2),
MA_TO_ADC( 8),
MA_TO_ADC(14),
MA_TO_ADC(20),
};
#define ST_DISABLED 0
......@@ -56,159 +40,75 @@ static uint16_t adc_vals[N_PWMLEDS*N_PWMLED_MODES] = {
void init_pwmled()
{
unsigned char i, j;
for (i = 0; i < N_PWMLEDS; i++) {
pwmled_t *led = pwmleds + i;
led->err_sum = 0;
led->target = adc_vals[i*N_PWMLED_MODES];
led->pwm = 0;
led->mode = 1;
led->state = ST_PROBING;
led->probe_steady = 0;
for (j = 0; j < N_PWMLED_MODES; j++) {
led->mode_pwm[j] = 0;
led->err_sums[j] = 0;
}
}
pwmleds[0].state = ST_DISABLED;
pwm_val = 0;
err_sum = 0;
target = targets[0];
state = ST_OFF;
}
void pwmled_set_mode(unsigned char n, unsigned char mode)
void pwmled_set_mode(unsigned char mode)
{
pwmled_t *led = pwmleds + n;
if (!ST_CAN_SET_MODE(led->state))
if (!ST_CAN_SET_MODE(state))
return;
if (led->mode) { // save the previous state
led->mode_pwm[led->mode - 1] = led->pwm;
led->err_sums[led->mode - 1] = led->err_sum;
}
led->mode = mode;
if (mode > 0 && mode <= N_PWMLED_MODES) {
led->target = adc_vals[n*N_PWMLED_MODES + mode - 1];
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(led->pwm);
} else {
led->state = ST_OFF;
pwm_off();
}
}
#define PWMLED_PROBE_STEADY_COUNT 10
static inline unsigned char pwmled_probed_ok(unsigned char n, uint16_t old_pwm)
{
pwmled_t *led = pwmleds + n;
if (led->pwm == old_pwm) {
if (led->probe_steady < PWMLED_PROBE_STEADY_COUNT)
led->probe_steady++;
} else {
led->probe_steady = 0;
}
if (led->probe_steady < PWMLED_PROBE_STEADY_COUNT
&& old_pwm <= led->pwm)
return 0;
// probed OK
led->mode_pwm[led->mode - 1] = led->pwm;
led->err_sums[led->mode - 1] = 0;
// next mode to probe?
if (led->mode < N_PWMLED_MODES) {
led->probe_steady = 0;
led->err_sum = 0;
led->mode++;
led->target = adc_vals[n*N_PWMLED_MODES+led->mode-1];
return 0;
if (mode) {
target = targets[mode - 1];
state = ST_ON;
mode_changed = 1;
pwm_set(pwm_val);
} else {
unsigned char i;
led->state = ST_OFF;
state = ST_OFF;
pwm_off();
log_byte(0xF0);
log_byte(n);
// log_word(jiffies);
for (i = 0; i < N_PWMLED_MODES; i++)
log_word(led->mode_pwm[i]);
log_flush();
// pattern_reload();
// pwmled_set_mode(n, 2);
return 1;
}
}
static inline void pwmled_err(unsigned char n)
static inline void pwmled_err()
{
pwmleds[n].state = ST_DISABLED;
state = ST_DISABLED;
pwm_off();
log_byte(0xF1);
log_byte(n);
// log_word(jiffies);
log_flush();
}
void pwmled_adc(unsigned char n, uint16_t adcval)
void pwmled_adc(uint16_t adcval)
{
pwmled_t *led = pwmleds + n;
uint16_t old_pwm;
int32_t sum;
unsigned char shift;
if (!ST_IS_ON(led->state))
if (!ST_IS_ON(state))
return;
if (led->state == ST_ON && led->mode_changed) {
led->mode_changed--;
// skip the first reading after mode change
if (state == ST_ON && mode_changed) {
mode_changed--;
return;
}
// FIXME: test for maximum adcval value (adc_max[n])
old_pwm = led->pwm;
if (adcval > adc_max) {
pwmled_err();
return;
}
shift = led->state == ST_PROBING ? 3 : 8;
shift = 5;
sum = ((int32_t)led->pwm << shift)
+ led->err_sum + led->target - adcval;
sum = ((int32_t)pwm_val << shift)
+ err_sum + target - adcval;
if (sum < 0)
sum = 0;
led->pwm = sum >> shift;
sum -= led->pwm << shift;
led->err_sum = sum;
pwm_val = sum >> shift;
sum -= pwm_val << shift;
err_sum = sum;
if (led->pwm >= PWM_MAX
|| (led->pwm > (2*PWM_MAX/3) && adcval < 0x08)) {
pwmled_err(n);
if (pwm_val >= PWM_MAX
|| (pwm_val > (2*PWM_MAX/3) && adcval < 0x08)) {
pwmled_err();
return;
}
if (led->state == ST_PROBING)
if (pwmled_probed_ok(n, old_pwm))
return;
if (led->pwm == old_pwm)
return;
pwm_set(led->pwm);
pwm_set(pwm_val);
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment