+#include <avr/io.h>
+#include <util/delay.h>
+#include <avr/sleep.h>
+#include <avr/interrupt.h>
+#include <avr/power.h>
+#include <avr/wdt.h>
+
+#include "lights.h"
+
+#if 0
+static void hw_setup()
+{
+ power_all_disable();
+
+// init_battery();
+ init_pwm();
+// init_adc();
+// init_wdt();
+//
+// init_buttons();
+
+// init_pwmled();
+// init_pattern();
+// init_control();
+
+// set_sleep_mode(SLEEP_MODE_IDLE);
+}
+
+static void hw_suspend()
+{
+ susp_pwm();
+ susp_adc();
+ susp_wdt();
+
+ susp_buttons();
+
+ power_all_disable();
+}
+
+void power_down()
+{
+ hw_suspend();
+
+ do {
+ // G'night
+ set_sleep_mode(SLEEP_MODE_PWR_DOWN);
+ sleep_enable();
+ sleep_bod_disable();
+ sei();
+ sleep_cpu();
+
+ // G'morning
+ cli();
+ sleep_disable();
+
+ // allow wakeup by long button-press only
+ } while (!buttons_wait_for_release());
+
+ // ok, so I will wake up
+ hw_setup();
+}
+#endif
+
+
+uint16_t read_adc_sync()
+{
+ uint16_t rv;
+
+ ADCSRA |= _BV(ADSC); // start the conversion
+
+ // wait for the conversion to finish
+ while((ADCSRA & _BV(ADIF)) == 0)
+ ;
+
+ rv = ADCW;
+ ADCSRA |= _BV(ADIF); // clear the IRQ flag
+
+ return rv;
+}
+
+void init_adc()
+{
+ power_adc_enable();
+ ACSR |= _BV(ACD); // but disable the analog comparator
+
+ ADCSRA = _BV(ADEN) // enable
+ // | _BV(ADPS1) | _BV(ADPS0) // CLK/8 = 125 kHz
+ | _BV(ADPS2) // CLK/16 = 62.5 kHz
+ ;
+
+ // Disable digital input on all bits used by ADC
+ DIDR0 = _BV(ADC3D) | _BV(ADC2D);
+
+ ADMUX = _BV(REFS1) | _BV(MUX1) | _BV(MUX0);
+
+ /* Do first conversion and drop the result */
+ read_adc_sync();
+
+ // ADCSRA |= _BV(ADIE); // enable IRQ
+}
+
+int main(void)
+{
+ uint16_t a, p, c, target;
+ int32_t sum;
+ uint8_t micro;
+ init_log();
+
+ log_set_state(3);
+
+ init_pwm();
+ init_adc();
+ // init_pwmled();
+
+ pwm_set(1);
+ // setup_mux(0);
+ // pwmled_on_off(1);
+ // pwmled_set_target(1);
+
+ sum = 0;
+ c = 0;
+ micro = 0;
+ sei();
+
+ target = 0xf0;
+#if 0
+ while(1) {
+ unsigned char p;
+ for (p = 0xd4; p <= 0xd5; p+= 0x1) {
+ unsigned char i, j;
+ uint16_t sum;
+
+ pwm_set(p);
+
+ for (j = 0; j < 12; j++) {
+ sum = 0;
+ for (i = 0; i < 2; i++) {
+ sum += read_adc_sync();
+ }
+ log_byte(sum);
+ for (i = 0; i < 14; i++) {
+ sum += read_adc_sync();
+ }
+ }
+ log_flush();
+ }
+ }
+#endif
+ while (1) {
+ sum += target - read_adc_sync() - (sum >> 7);
+ micro++;
+ if (micro > 7)
+ micro = 0;
+
+ p = ((sum >> 4) + micro) >> 3;
+ if (p > 0xd8)
+ p = 0xd8;
+ pwm_set(p);
+ if (++c > 200) {
+ log_byte(p);
+ log_flush();
+ c = 0;
+ }
+ }
+
+ p = a = c = 0;
+ while (1) {
+ uint16_t i;
+ for (i = 0; i < 25; i++) {
+ uint16_t val;
+ val = read_adc_sync();
+ a += val - (a >> 5);
+ }
+
+ if (a < (42 << 5) && p < 250) {
+ p++;
+ } else if (p > 1 && a > (38 << 5)) {
+ p--;
+ }
+ pwm_set(p);
+ if (++c > 1000) {
+ log_byte(0xbb);
+ // log_word(read_adc_sync());
+ log_word(a);
+ log_word(p);
+ log_flush();
+ c = 0;
+ }
+ }
+
+ while(1) {
+ uint16_t i, t;
+ for (t = 0; t < 3; t++) {
+ pwmled_set_target(t);
+ for (i = 0; i < 1000; i++) {
+ need_pwmled_adc = 1;
+ while (need_pwmled_adc == 1)
+ ;
+ }
+ }
+ }
+
+#if 0
+ hw_setup();
+ power_down();
+
+#if 1
+ while (1) {
+ cli();
+ if (pwm_enabled) {
+ set_sleep_mode(SLEEP_MODE_IDLE);
+ } else if (adc_enabled) {
+ set_sleep_mode(SLEEP_MODE_ADC);
+ } else {
+ set_sleep_mode(SLEEP_MODE_PWR_DOWN);
+ }
+
+ sleep_enable();
+ // keep BOD active, no sleep_bod_disable();
+ sei();
+ sleep_cpu();
+ sleep_disable();
+ }
+#endif
+
+#if 0
+ DDRB |= _BV(PB2);
+ while (1) {
+ PORTB |= _BV( PB2 );
+ _delay_ms(200);
+ PORTB &=~ _BV( PB2 );
+ _delay_ms(200);
+ }
+#endif
+#endif
+}