/*
Ansteuerung eine 2-phasigen Lichterkette per Timer0 und Erzeugung von Stromimpulsen
zum Wachhalten einer Powerbank per WDT.

Um 2-phasige Blinkeffekte bei Lichterketten über zwei Adern zu erzeugen, sind die
angeschlossenen LEDs zur Hälfte invertiert an die Zuleitung angeschlossen. Je nach
Polung leuchtet die eine Phase oder die andere. Um Dauerlicht von beiden Phasen zu
erhalten, muß die Polung der Ausgänge permanent gewechselt werden. Dazu erzeugt Timer0
an den Ausgängen LED1_PIN und LED2_PIN ein gegenphasiges Signal mit rund 1,95 kHz.
Laut Datenblatt darf der Ausgangsstrom/Ausgang max. 40 mA betragen, was unter Umständen
einen strombegrenzen Widerstand in der Zuleitung erfordert.

Da viele Powerbanks bei nur 40 mA Laststrom nach einer Minute abgeschalten, wird zusätzlich
ein Ausgangsimpuls an den Ausgängen OUT1_PIN und OUT2_PIN erzeugt. Zusammen mit einem
Widerstand 47 Ohm wird alle 4 s einen Stromimpuls von 80 mA für 0,3 s erzeugt. Das reicht
aus, um viele Powerbanks wach zu halten und erzeugt nur eine zusätzliche Stromaufnahme
von rund 6 mA. Die Stromaufnahme inkl. LED-Kette bleibt unter 50 mA.

Bei Bedarf anpassen:
Das Programm erzeugt einen negativen Impuls, sodaß der 47 Ohm Widerstand an +5 V einerseits
und andererseits an die OUT_PINS angeschlossen wird.

Michael Nowak
www.mino-elektronik.de
2021-12-24
 */ 

#include <avr/io.h>
#include <avr/interrupt.h>

#define BIT(x)	(1<<x)

#define LED1_PIN  BIT(0)          // PB0 
#define LED2_PIN  BIT(2)          // PB2
#define OUT1_PIN  BIT(3)          // PB3 
#define OUT2_PIN  BIT(4)          // PB4

#define LED_PINS  (LED1_PIN | LED2_PIN)
#define OUT_PINS  (OUT1_PIN | OUT2_PIN)

#define WDT_PAUSE     (60*4)      // 4 Sekunden Pause bei 60 Hz WDT
#define WDT_IMPULS    (19)        // 0,3 s aktiv

uint16_t wdt_cnt;                 // Abwärtszähler für die WDT-Zeiten

ISR(WDT_vect) {                   // Aufruffrequenz 60 Hz
  if(!wdt_cnt--) {
// für +Impuls nachfolgende Zeitvorgaben vertauschen
    if(PORTB & OUT1_PIN)          // bei aktuellem +Pegel   
      wdt_cnt = WDT_IMPULS;       // Zeit für -Impuls vorgeben
    else
      wdt_cnt = WDT_PAUSE;        // ansonsten Pausenzeit einstellen
    PORTB ^= OUT_PINS;            // neuen Pegel einstellen
  }                  
}

ISR(TIMER0_OVF_vect)            
{
  PORTB ^= LED_PINS;;
}

int main(void)
{
  DDRB = LED_PINS | OUT_PINS;
  PORTB = LED1_PIN;               // gegenphasiges Signal für LEDs einstellen
  WDTCR = BIT(WDIE);              // schnellstes Watchdog-Intervall 16 ms   
  wdt_cnt = WDT_IMPULS;           // mit Ausgangsimpuls = aktiv beginnen
  PORTB |= OUT_PINS;              // und beide Ausgänge einschalten
  TCCR0B = BIT(CS00);             // T0 einschalten 1 MHz Takt
  TIMSK |= BIT(TOIE0);            // OVF freigeben
  sei();                          // ISR zulassen
  while (1) 
    {
    }
}