#include "logging.h"
-static unsigned char pwm = 1;
+#define N_STEPS 5
+static unsigned char steps[] = { 60, 85, 121, 171, 242 };
+static unsigned char intensity = 0;
static void timer_init()
{
DDRB |= _BV(PB4);
- TCCR1 = _BV(CS10); // clk/1 = 1 MHz
- // TCCR1 = _BV(CS11) | _BV(CS13); // clk/512 = 2 kHz
+ // TCCR1 = _BV(CS10); // clk/1 = 1 MHz
+ TCCR1 = _BV(CS11) | _BV(CS13); // clk/512 = 2 kHz
GTCCR = _BV(COM1B1) | _BV(PWM1B);
OCR1C = 255;
+ OCR1B = steps[0];
+ TIMSK = _BV(OCIE1B) | _BV(TOIE1);
+}
+
+volatile unsigned char adc_type, adc_drop;
+
+ISR(TIM1_OVF_vect)
+{
+ adc_drop = 2;
+ adc_type = 1;
+ ADCSRA |= _BV(ADSC);
+}
+
+ISR(TIM1_COMPB_vect)
+{
+ adc_drop = 2;
+ adc_type = 0;
+ ADCSRA |= _BV(ADSC);
+}
+
+static void set_pwm(unsigned char pwm)
+{
OCR1B = pwm;
}
{
power_adc_enable();
- ADCSRA = _BV(ADEN) | _BV(ADPS1) | _BV(ADPS0); // clk/8 = 125 kHz
+ ADCSRA = _BV(ADEN) | _BV(ADPS1) | _BV(ADPS0) | _BV(ADIE); // clk/8 = 125 kHz
ADMUX = _BV(REFS1) | _BV(MUX1) | _BV(MUX0); // 1.1V ref., PB3 single-ended
DIDR0 = _BV(ADC3D);
}
+volatile uint16_t batt_on, batt_off;
+
+ISR(ADC_vect)
+{
+ uint16_t adcw = ADCW;
+
+ if (adc_drop) {
+ adc_drop--;
+ ADCSRA |= _BV(ADSC);
+ return;
+ }
+
+ if (adc_type == 0) {
+ if (batt_off) {
+ batt_off += adcw - (batt_off >> 5);
+ } else {
+ batt_off = adcw << 5;
+ }
+ } else {
+ if (batt_on) {
+ batt_on += adcw - (batt_on >> 5);
+ } else {
+ batt_on = adcw << 5;
+ }
+ }
+}
+
static void status_led_init()
{
DDRB |= _BV(PB2);
PORTB &= ~_BV(PB2);
}
+static unsigned char status_led_is_on()
+{
+ return PORTB & _BV(PB2) ? 1 : 0;
+}
+
static void buttons_init()
{
DDRB &= ~(_BV(PB0) | _BV(PB1)); // set as input
static void button_one_pressed()
{
- if (pwm > 1) {
- pwm >>= 1;
- OCR1B = pwm;
+ if (intensity > 0) {
+ set_pwm(steps[--intensity]);
} else {
power_down();
}
static void button_two_pressed()
{
- if (pwm < 0x80) {
- pwm <<= 1;
- OCR1B = pwm;
+ if (intensity < N_STEPS-1) {
+ set_pwm(steps[++intensity]);
}
}
button_state = newstate;
}
+static unsigned char blink_on_time, blink_off_time, n_blinks;
+static unsigned char blink_counter;
+
+static void timer_blink()
+{
+ if (blink_counter) {
+ blink_counter--;
+ } else if (status_led_is_on()) {
+ status_led_off();
+ blink_counter = blink_off_time;
+ } else if (n_blinks) {
+ --n_blinks;
+ status_led_on();
+ blink_counter = blink_on_time;
+ } else {
+ n_blinks = intensity + 1;
+ blink_on_time = 0;
+ blink_off_time = 2;
+ blink_counter = 10;
+#if 0
+ log_byte(0xbb);
+ log_byte(batt_on >> 7);
+ log_byte(batt_off >> 7);
+#endif
+ }
+}
+
int main()
{
log_init();
power_down();
-#if 0
- ADCSRA |= _BV(ADSC);
- while (!(ADCSRA & _BV(ADIF)))
- ;
- log_word(ADCW);
- ADCSRA |= _BV(ADSC);
- while (!(ADCSRA & _BV(ADIF)))
- ;
- log_word(ADCW);
- log_flush();
-#endif
sei();
// we try to be completely IRQ-driven, so just wait for IRQs here
if (wdt_timer_fired) {
wdt_timer_fired = 0;
timer_check_buttons();
+ timer_blink();
+ log_flush();
}
}
}