]> www.fi.muni.cz Git - tinyboard.git/blobdiff - projects/step-up-1/main.c
Experimental step-up driver for chain of 5630 LEDs.
[tinyboard.git] / projects / step-up-1 / main.c
diff --git a/projects/step-up-1/main.c b/projects/step-up-1/main.c
new file mode 100644 (file)
index 0000000..6d38f06
--- /dev/null
@@ -0,0 +1,236 @@
+#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
+}