#include <avr/interrupt.h>
volatile uint16_t adcval;
-unsigned char pwmval = 0x10;
-volatile uint16_t adc_exp = 0x10;
unsigned char led_is_on = 0;
volatile unsigned char adccount = 0;
-volatile struct
-{
- uint8_t pwm_int: 1;
- uint8_t adc_int: 1;
- uint8_t tmr_int: 1;
-}
-intflags;
+typedef struct {
+ unsigned char pwmval, expected;
+} led_level_t;
+
+led_level_t led_modes[2] = {
+ { 0x50, 0x38 },
+ { 0x38, 0x04 },
+};
+
+unsigned char led_mode = 0;
+unsigned char led_mode_changed = 0;
static void inline led_on()
{
DDRB |= _BV( PB5 );
+ PORTA |= _BV( PA0 );
led_is_on = 1;
}
{
led_is_on = 0;
DDRB &= ~_BV( PB5 );
+ PORTA &=~ _BV( PA0 );
// ADCSRA &= ~(_BV(ADIE) | _BV(ADIF));
}
/* ------------ Timer ----------- */
-volatile uint16_t clock = 0;
+volatile uint16_t jiffies = 0;
static void inline init_tmr()
{
TIMSK |= _BV(OCIE0A);
DDRA |= _BV( PA0 );
- clock = 0;
+ jiffies = 0;
}
static void inline tmr_handler()
{
- unsigned char c = clock & 0x1F;
- unsigned char c1 = clock & 0xFF;
+ unsigned char c = jiffies & 0x0F;
+ unsigned char c1 = jiffies & 0x7F;
+
+ ++jiffies;
- ++clock;
#if 0
- if (c == 10 || c == 30)
+ if (c == 1)
led_on();
- if (c == 20 || c == 40)
+ if (c == 9)
led_off();
#endif
if (c == 0x02 || c == 0x08)
led_on();
+
if (c == 0x05 || c == 0x0b)
led_off();
- if ((clock & 0x7F) == 0x1F) {
- if (c1 < 0x80) {
- adc_exp = 0x80;
- } else {
- adc_exp = 0x20;
- }
+#if 1
+ if (c1 == 0x10) {
+ led_mode = 0;
+ led_mode_changed = 1;
+ OCR1D = led_modes[led_mode].pwmval;
+ } else if (c1 == 0x70) {
+ led_mode = 1;
+ led_mode_changed = 1;
+ OCR1D = led_modes[led_mode].pwmval;
}
+#endif
+
ADCSRA |= _BV(ADSC);
#if 0
if (led_is_on && adcval != 0xFFEE) {
| _BV(CS10) // no clock prescaling
;
OCR1C = 0xFF; // TOP value
- OCR1D = OCR1B = OCR1A = pwmval;
+ OCR1D = OCR1B = OCR1A = 0;
// OCR1D = 0;
- // DDRB |= _BV( PB5 );
+ DDRB |= _BV( PB5 );
PORTB &= ~(_BV( PB5 ) | _BV( PB1 ) | _BV( PB3 ));
// led_off();
static void inline adc_handler()
{
- uint16_t new_pwm = pwmval;
- uint16_t old_pwm = pwmval;
- uint16_t old_adc = adcval;
+ uint16_t new_pwm = led_modes[led_mode].pwmval;
+ uint16_t old_pwm = new_pwm;
+ uint16_t adc_exp = led_modes[led_mode].expected;
+
adcval = ADCW;
adccount++;
// log_word(((adcval & 0x3FC) << 6) | pwmval);
- log_word(((adcval & 0xFF) << 8) | pwmval);
if (!led_is_on)
return;
- // adcval = (adcval + 3*old_adc)/4;
// ADCSRA &= ~(_BV(ADIE) | _BV(ADIF));
- if (adcval < 1) {
- adcval = 1;
- } else if (adcval > adc_exp) {
- new_pwm = old_pwm*adc_exp/adcval;
- } else if (adcval < adc_exp && 2 * adcval > adc_exp) {
- new_pwm = old_pwm*adc_exp/adcval;
- } else if (adcval < adc_exp) {
- new_pwm = 2 * old_pwm;
+ if (led_mode_changed) {
+ led_mode_changed = 0;
+ goto set_pwm;
+ }
+
+ log_word(((adcval & 0xFF) << 8) | old_pwm);
+
+ 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;
}
- new_pwm = (3*old_pwm + new_pwm) / 4;
if (new_pwm > 0x60) { // odpojeno?
new_pwm = 0x60;
}
new_pwm = 2;
}
- // if (new_pwm < 15*old_pwm/16 || new_pwm > 17*old_pwm/16) {
- pwmval = new_pwm;
- OCR1D = pwmval;
- // }
+set_pwm:
+ if (new_pwm != old_pwm) {
+ led_modes[led_mode].pwmval = new_pwm;
+ OCR1D = new_pwm;
+ }
// ADCSRA |= _BV(ADSC);
}
int main(void)
{
+ _delay_ms(1500);
init_log();
init_pwm();
init_adc();
init_tmr();
- debug_setstate(2);
+ led_on();
+ debug_setstate(3);
sei();
while (1)
- ;// sleep_mode();
+ ; // sleep_mode();
#if 0
- DDRA |= _BV( PA0 );
- while( 1 ) {
- PORTA |= _BV( PA0 );
- _delay_ms(200);
- PORTA &=~ _BV( PA0 );
- }
+ while (1) {
+ PORTA |= _BV( PA0 );
+ _delay_ms(200);
+ PORTA &=~ _BV( PA0 );
+ _delay_ms(200);
+ }
#endif
}