//******************************************************************************
//
//  UV-Belichtungstimer
//  Autor: Bernhard Hanf
//  Datum: 20.03.2005
//
//******************************************************************************
//  Speicherung der eingestellten Zeit im internen EEPROM
//  PortA[0:3] steuert den HEX->7Segment Decoder 4511 
//******************************************************************************

#include <16F84.h>                        // PIC16F84A verwendet
#use delay (clock=4000000)                // 4MHz Quarz
#fuses XT,NOWDT                           // XT Mode, kein Watchdog

#define  relais   PIN_B7                  // Relaisanschluss
#define  t_auf    PIN_B5                  // Taste auf
#define  t_ab     PIN_B4                  // Taste ab
#define  t_ss     PIN_B3                  // Taste Start/Stop
#define  seg1     PIN_B2                  // 1. Anzeige
#define  seg2     PIN_B1                  // 2. Anzeige
#define  seg3     PIN_B0                  // 3. Anzeige

int16  time;                              // Timerablaufzeit
int8 wert1, wert2, wert3;                 // Anzeigestellen 1 2 3
byte segzae = 1;                          // Segmentdurchlauf 1->3
byte zaesek = 200;                        // 200 * 5ms = 1Sek
byte relreg = 0;                          // Relaisstatusregister


#INT_TIMER0                               // naechste Fkt ist T0-Int
void TIMER0_isr()
{  set_timer0(99);                        // Timer Voreinstellung -> ergibt 5ms
   zaesek--;                              // Durchlaufzaehler --

   wert1 = time / 100;                    // 1. Anzeige
   wert2 = (time / 10) % 10;              // 2. Anzeige
   wert3 = time % 10;                     // 3. Anzeige

   if(segzae == 1)                        // jedes Segment fuer 5ms ansteuern
   {  segzae++;                           // Segmentzaehler erhöhen
      output_low(seg3);                   // letzte Anzeige abschalten
      output_high(seg1);                  // neue Anzeige einschalten
      output_a(relreg | wert1);           // Wert ausgeben, Relaisstellung drauf odern
   }
   else if(segzae == 2)
   {  segzae++;                           // Segmentzaehler erhöhen
      output_low(seg1);                   // letzte Anzeige abschalten
      output_high(seg2);                  // neue Anzeige einschalten
      output_a(relreg | wert2);           // Wert ausgeben, Relaisstellung drauf odern
   }
   else if(segzae == 3)
   {  segzae = 1;                         // Zaehler wieder auf 1 setzen
      output_low(seg2);                   // letzte Anzeige abschalten
      output_high(seg3);                  // neue Anzeige einschalten
      output_a(relreg | wert3);           // Wert ausgeben, Relaisstellung drauf odern
   }

   if((zaesek == 100) || (zaesek == 0))   // jede halbe Sek Tasten abfragen
   {  if(!input(t_auf))                   // wenn Taste auf gedrückt
      {  time++;                          // Time + 1
         if (time > 999)                  // maximal 999
            time = 999;
      }
      else if(!input(t_ab))               // wenn Taste ab gedrückt
      {  if(time == 0)                    // wenn nach Zeitablauf auf 0 steht
            time++;                       // weiteres Unterlaufen verhindern
         time--;                          // Time -1
         if (time < 1)
            time = 1;                     // minimal 1
      }
      else if(!input(t_ss))               // Start/Stop Taste
      {  if((relreg == 0) && (time > 0))  // wenn Relais aus und Zeit groesser 0
         {  output_high(relais);          // dann Relais an
            relreg = 16;                  // Relaisstatusreg setzen
            write_eeprom(11, wert1);      // Werte in EEPROM übernehmen
            write_eeprom(12, wert2);
            write_eeprom(13, wert3);
         }
         else
         {  output_low(relais);           // Relais aus
            relreg = 0;
         }
      }
    }

    if((zaesek == 0) && (relreg == 16))   // Jede volle Sek + wenn Relais an ist
    {  time--;                            // Zeit - 1
       if(time == 0)                      // wenn Zeit abgelaufen ist
       {  output_low(relais);             // Relais abschalten
          relreg  = 0;                    // Relaisreg rücksetzen
          wert1 = read_eeprom(11);        // Werte aus dem EEPROM holen
          wert2 = read_eeprom(12);
          wert3 = read_eeprom(13);
          time  = wert3;                  // den Zeitzaehler neu setzen
          time += wert2 * 10;
          time += wert1 * 100;
       }
       zaesek = 200;                      // Sekundenzaehler neu einstellen
    }
}

void main()
{  port_b_pullups(FALSE);
   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_32);

   wert1 = read_eeprom(11);               // Werte aus dem EEPROM holen
   wert2 = read_eeprom(12);
   wert3 = read_eeprom(13);

   time  = wert3;                         // dem Zeitzaehler zuordnen
   time += wert2 * 10;
   time += wert1 * 100;

   enable_interrupts(INT_RTCC);
   enable_interrupts(global);

   while(1);                              // Dauerschleife
}

