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

pwmled.c: only one pwmled

parent 8ebf32f3
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -202,7 +202,7 @@ ISR(ADC_vect) { // IRQ handler
	switch (current_adc) {
	switch (current_adc) {
	case 0:
	case 0:
		// pwmled_adc(current_adc, adc_sum);
		// pwmled_adc(current_adc, adc_sum);
		pwmled_adc(1, adc_sum);
		pwmled_adc(adc_sum);
		break;
		break;
	}
	}


+2 −2
Original line number Original line Diff line number Diff line
@@ -44,8 +44,8 @@ void susp_tmr();


/* pwmled.c */
/* pwmled.c */
void init_pwmled();
void init_pwmled();
void pwmled_adc(unsigned char n, uint16_t adcval);
void pwmled_adc(uint16_t adcval);
void pwmled_set_mode(unsigned char n, unsigned char mode);
void pwmled_set_mode(unsigned char mode);


/* gpio.c */
/* gpio.c */
void init_gpio();
void init_gpio();
+46 −146
Original line number Original line Diff line number Diff line
@@ -2,18 +2,11 @@


#include "lights.h"
#include "lights.h"


typedef struct {
static uint16_t target;
	uint16_t target, pwm;
static uint16_t pwm_val;
	int16_t err_sum;
static int16_t err_sum;
	unsigned char mode, state;
static unsigned char state;
	union {
unsigned char mode_changed;
		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];


#define SENSE_MOHM	3000	/* 1 Ohm */
#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
 * ADC module returns sum of 1 << PWMLED_ADC_SHIFT measurements
 * Voltage in uV measured is current in mA * sense resistance in mOhm
 * 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) \
	((uint32_t)(ma) \
	* (SENSE_MOHM) \
	* (SENSE_MOHM) \
	* (1 << (PWMLED_ADC_SHIFT)) \
	* (1 << (PWMLED_ADC_SHIFT)) \
	* 1024 \
	* 1024 \
	/ (1100000/(gain))))
	/ 1100000))


static uint16_t adc_max[N_PWMLEDS] = {
static uint16_t adc_max = MA_TO_ADC(30);
	MA_GAIN_TO_ADC(  30,  1),
	MA_GAIN_TO_ADC(  30,  1),
};


static uint16_t adc_vals[N_PWMLEDS*N_PWMLED_MODES] = {
static uint16_t targets[N_PWMLED_MODES] = {
	/* pwmled0 */
	MA_TO_ADC( 2),
	MA_GAIN_TO_ADC(   2,  1),
	MA_TO_ADC( 8),
	MA_GAIN_TO_ADC(   5,  1),
	MA_TO_ADC(14),
	MA_GAIN_TO_ADC(  10,  1),
	MA_TO_ADC(20),
	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),
};
};


#define ST_DISABLED 0
#define ST_DISABLED 0
@@ -56,159 +40,75 @@ static uint16_t adc_vals[N_PWMLEDS*N_PWMLED_MODES] = {


void init_pwmled()
void init_pwmled()
{
{
	unsigned char i, j;
	pwm_val = 0;

	err_sum = 0;
	for (i = 0; i < N_PWMLEDS; i++) {
	target = targets[0];
		pwmled_t *led = pwmleds + i;
	state = ST_OFF;
		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;
}
}


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(state))

	if (!ST_CAN_SET_MODE(led->state))
		return;
		return;


	if (led->mode) { // save the previous state
	if (mode) {
		led->mode_pwm[led->mode - 1] = led->pwm;
		target = targets[mode - 1];
		led->err_sums[led->mode - 1] = led->err_sum;
		state = ST_ON;
	}
		mode_changed = 1;

		pwm_set(pwm_val);
	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 {
	} else {
		led->state = ST_OFF;
		state = ST_OFF;
		pwm_off();
		pwm_off();
	}
	}
}
}


#define PWMLED_PROBE_STEADY_COUNT 10
static inline void pwmled_err()

static inline unsigned char pwmled_probed_ok(unsigned char n, uint16_t old_pwm)
{
{
	pwmled_t *led = pwmleds + n;
	state = ST_DISABLED;

	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;
	} else {
		unsigned char i;

		led->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)
{
	pwmleds[n].state = ST_DISABLED;
	pwm_off();
	pwm_off();


	log_byte(0xF1);
	log_byte(0xF1);
	log_byte(n);
	// log_word(jiffies);
	log_flush();
	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;
	int32_t sum;
	unsigned char shift;
	unsigned char shift;


	if (!ST_IS_ON(led->state))
	if (!ST_IS_ON(state))
		return;
		return;


	if (led->state == ST_ON && led->mode_changed) {
	// skip the first reading after mode change
		led->mode_changed--;
	if (state == ST_ON && mode_changed) {
		mode_changed--;
		return;
		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)
	sum = ((int32_t)pwm_val << shift)
		+ led->err_sum + led->target - adcval;
		+ err_sum + target - adcval;


	if (sum < 0)
	if (sum < 0)
		sum = 0;
		sum = 0;


	led->pwm = sum >> shift;
	pwm_val = sum >> shift;
	sum -= led->pwm << shift;
	sum -= pwm_val << shift;
	led->err_sum = sum;
	err_sum = sum;


	if (led->pwm >= PWM_MAX
	if (pwm_val >= PWM_MAX
		|| (led->pwm > (2*PWM_MAX/3) && adcval < 0x08)) {
		|| (pwm_val > (2*PWM_MAX/3) && adcval < 0x08)) {
		pwmled_err(n);
		pwmled_err();
		return;
		return;
	}
	}


	if (led->state == ST_PROBING)
	pwm_set(pwm_val);
		if (pwmled_probed_ok(n, old_pwm))
			return;

	if (led->pwm == old_pwm)
		return;

	pwm_set(led->pwm);
}
}