// *****************************************************************************************
// * Programm: LLICHT.C                                                                    *
// *****************************************************************************************
// * Funktion: Lauflicht mit fünf verschiedenen Programmen und umschaltbarer Laufrichtung. *
// *****************************************************************************************
// * Autor:    Pramberger Peter                                                            *
// *****************************************************************************************

// """""- Projekt-Includes """""-
#include <LLICHT.H>;


// """"" Globale Variablen """""-
bool TMR_Overflow = 0;           // Überlauf des Timers aufgetreten
bool INT_ExtInt2 = 0;            // Externer Interrupt 2 aufgetreten
bool INT_ExtInt3 = 0;            // Externer Interrupt 3 aufgetreten
ubyte idata Zaehler = 0;         // Zählvariable zur Tastenentprellung


// """""" Unterprogramme """"""

void INT_Init (void)             // Initialisiert das Interrupt-System

   EXICON = 0x0050;              // """- Ext. Interrupt 2 Trigger """"
   DP2   &= 0xF3FF;              // Steigende Flanke an Pin P2.10
                                 // """- Ext. Interrupt 3 Trigger """"
                                 // Steigende Flanke an Pin P2.11
   CC10IC = 0x0048;              // """"- Externer Interrupt 2 """""
                                 // Interrupt-Prioritätslevel (ILVL) = 2
                                 // Interrupt-Gruppenlevel (GLVL) = 0
   CC11IC = 0x0044;              // """"- Externer Interrupt 3 """""
                                 // Interrupt-Prioritätslevel (ILVL) = 1
                                 // Interrupt-Gruppenlevel (GLVL) = 0
}

void IO_Init (void)              // Initialisiert Port 3

{
   P3   = 0x0000;                // """"- Port 3 Datenregister """""
                                 // Alternative Funktion von P3.2 deaktiviert
                                 // Status von P3.2 ist Low-Level
                                 // Alternative Funktion von P3.3 deaktiviert
                                 // Status von P3.3 ist Low-Level
                                 // Alternative Funktion von P3.4 deaktiviert
                                 // Status von P3.4 ist Low-Level
                                 // Alternative Funktion von P3.5 deaktiviert
                                 // Status von P3.5 ist Low-Level
                                 // Alternative Funktion von P3.6 deaktiviert
                                 // Status von P3.6 ist Low-Level
   ODP3 = 0x0000;                // """ Port 3 Open-Drain-Register """-
                                 // Pin P3.2 auf Push/Pull-Modus setzen
                                 // Pin P3.3 auf Push/Pull-Modus setzen
                                 // Pin P3.4 auf Push/Pull-Modus setzen
                                 // Pin P3.5 auf Push/Pull-Modus setzen
                                 // Pin P3.6 auf Push/Pull-Modus setzen
   DP3  = 0x007C;                // """- Port 3 Richtungsregister """"
                                 // Pin P3.2 als Ausgang konfigurieren
                                 // Pin P3.3 als Ausgang konfigurieren
                                 // Pin P3.4 als Ausgang konfigurieren
                                 // Pin P3.5 als Ausgang konfigurieren
                                 // Pin P3.6 als Ausgang konfigurieren
}

void TMR_Init (void)             // Initialisiert Timer 3

{
   T3CON = 0x0003;               // """- Timer 3 Control Register """"
                                 // Timer arbeitet im Timer-Modus
                                 // Prescaler-Faktor ist 64
                                 // Zählrichtung: aufwärts
                                 // Ext. Zählrichtungsumschaltung deaktiviert
   T3 = 0x3FFF;                  // Timer Register laden
   T3IC = 0x004C;                // """ Timer 3 Interrupt Register """-
                                 // Interrupt aktivieren
                                 // Interrupt-Prioritätslevel (ILVL) = 3
                                 // Interrupt-Gruppenlevel (GLVL) = 0
   T3R = 1;                      // Timer aktivieren
}

void Project_Init (void)

{
   IO_Init();                    // Initialisiert Port 3
   TMR_Init();                   // Initialisiert Timer 3
   INT_Init();                   // Initialisiert das Interrupt-System


   INT_EnableInterrupt (TIMER3_INT);     // Aktiviert Timer 3 Interrupt
   INT_EnableInterrupt (EXTERNAL_INT2);  // Aktiviert den ext. Interrupt 2
   INT_EnableInterrupt (EXTERNAL_INT3);  // Aktiviert den ext. Interrupt 3
   
   IEN = 1;                      // Setzt das Global-Enable-Bit
}


// """ Interrupt-Service-Routinen """

void INT_IsrExt2 (void) interrupt CC10INT  // ISR für externen Interrupt 2

{    INT_ExtInt2 = 1;              // Wenn externer Interrupt - Flag setzen
}

void INT_IsrExt3 (void) interrupt CC11INT  // ISR für externen Interrupt 3

{
   INT_ExtInt3 = 1;              // Wenn externer Interrupt - Flag setzen
}

void GT1_IsrTmr3 (void) interrupt T3INT    // ISR für Timer 3

{
   TMR_Overflow = 1;             // Wenn Timer überläuft - Flag setzen
   GT1_LoadTmr (TIMER_3, 0x3FFF);  // Timerregister nachladen
}


// —————— Hauptprogramm ——————-

void main (void)

{
   bool LED_Direction = 0;       // Umschaltung der Laufrichtung
   uword idata Temp = 0;         // Temporäre Variable
   ubyte idata Program = 0;      // Auswahl des Lauflicht-Programms


   Project_Init();               // Initialisieren der Hardware
   IO_WritePort (P3, 0x0F0F);    // Port 3 voreinstellen
   Temp = 0x0F0F;                // Variable voreinstellen
   LED_Direction = 1;            // Laufrichtung voreinstellen
  
   for (;;)                      // Endlos-Schleife
   {
      if (INT_ExtInt2 == 1)      // Wenn externer Interrupt 2 aufgetreten
      {
         INT_ExtInt2 = 0;
         if (Program 4)        // Wenn Program kleiner vier ist -
         {
            Program ++;          // Variable erhöhen.
         }
         else                    // Wenn Program gleich vier ist -
         {
            Program = 0;         // Variable auf Null setzen.
         }
         switch (Program)        // Je nach Wert von Program verzweigen
         {
            case 0: IO_WritePort (P3, 0x0F0F);  // Programm 1
                    Temp = 0x0F0F;
                    break;
            case 1: IO_WritePort (P3, 0x1111);  // Programm 2
                    Temp = 0x1111;
                    break;
            case 2: IO_WritePort (P3, 0x3333);  // Programm 3
                    Temp = 0x3333;
                    break;
            case 3: IO_WritePort (P3, 0x5555);  // Programm 4
                    Temp = 0x5555;
                    break;
            case 4: IO_WritePort (P3, 0x7777);  // Programm 5
                    Temp = 0x7777;
                    break;
         }
      }
      if (INT_ExtInt3 == 1)      // Wenn externer Interrupt 2 aufgetreten
      {
         INT_ExtInt3 = 0;
         LED_Direction = LED_Direction ^ 1;  // Laufrichtung umschalten
      }
      if (TMR_Overflow == 1)     // Wenn Timer-Interrupt aufgetreten
      {
         TMR_Overflow = 0;
         Zaehler ++;             // Zähler zur Tastenentprellung erhöhen
         if (LED_Direction == 0) // Wenn Variable gleich Null ist
         {
            Temp = _iror_ (Temp, 1);  // Variableninhalt nach rechts rotieren
            IO_WritePort (P3, Temp);  // Variable auf Port 3 schreiben
         }
         else                    // Wenn Variable gleich Eins ist
         {
            Temp = _irol_ (Temp, 1);  // Variableninhalt nach links rotieren
            IO_WritePort (P3, Temp);  // Variable auf Port 3 schreiben
         }
      }
      if (Zaehler == 6)          // Wenn Variable gleich sechs ist -
      {  Zaehler = 0;       
         INT_EnableInterrupt (EXTERNAL_INT2);  // Reaktiviert den ext. Int. 2
         INT_EnableInterrupt (EXTERNAL_INT3);  // Reaktiviert den ext. Int. 3
      }
      if (Zaehler 2)           // Wenn Variable kleiner zwei ist -
      {  INT_DisableInterrupt (EXTERNAL_INT2);   // Deaktiviert ext. Int. 2
         INT_DisableInterrupt (EXTERNAL_INT3);   // Deaktiviert ext. Int. 3
      }
   }
}