/*******************************************
 *
 * Igor-Amperemeter
 *
 * (C) Fingers elektrische Welt 2010
 *
 *******************************************/
#include <p18cxxx.h>
#include <p18F452.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include "defines.h"

#pragma config OSC = HS

// >----- Mach mal Pause ---------<

#define	XTAL_FREQ	4MHZ		      // Jaja, ich WEISS dass das falsch ist *Grummel*
#define	MHZ	*1000

#define Lampe		PORTBbits.RB5				  // Lampenpin mit SolidState-Relais

#define	DelayUs(x)	{ unsigned int _dcnt; \
			  _dcnt = (x)/(12MHZ/(XTAL_FREQ))|1; \
			  while(--_dcnt != 0) \
				  continue; }

// >----- Mach mal Pause ---------<

// Diverses
char outpbuf [Buflen];                      // Ausgabepuffer;
volatile unsigned long Timerticks = 0;			// Systemticker alle 10ms

// Zeitmessung
volatile unsigned long SekundenTicker = 0;  // Systemticker jede Sekunde ++
volatile unsigned int MinutenTicker = 0;	// Jede Minute 1 rauf

char Lichtblitzer = FALSE;					// Hatter schon geblinkt ?

void main (void);
void InterruptHandlerHigh (void);

/**************************
 *
 * Systemticker erhöhen
 *
 **************************/
void Systemticker (void)
 {
  Timerticks++;

  //-------------------------
  // Sekundenweise ausführen
  //-------------------------
  if ((Timerticks % 100) == 0)
   {

    // Sekundenzähler
    SekundenTicker++;

   if (( SekundenTicker % 60) == 0) MinutenTicker++;

   } // Von if ((Timerticks % 100) == 0)

 }

/**************************
 *
 * Systemticker auslesen
 *
 **************************/
long Get_Ticker (void)
 {
  return (Timerticks);
 }

/*************************************
 *
 * Verzögern im Millisekundenbereich
 *
 *************************************/
void Delayms (int time)
 {
  unsigned long ticker;

  ticker = Get_Ticker ();

  while ( (ticker + (time / 10)) > Get_Ticker () )
   {
    ClrWdt();
   }
 }

//----------------------------------------------------------------------------
// High priority interrupt vector

#pragma code InterruptVectorHigh = 0x08
void
InterruptVectorHigh (void)
{
  _asm
    goto InterruptHandlerHigh //jump to interrupt routine
  _endasm
}


//----------------------------------------------------------------------------
// High priority interrupt routine

#pragma code
#pragma interrupt InterruptHandlerHigh

void
InterruptHandlerHigh ()
{
   //--------------------
   // Timer 1 Überlauf ?
   //--------------------
   if (PIR1bits.TMR1IF)
   	{

      Systemticker ();                                  // Systemticker erhöhen

      PIR1bits.TMR1IF=0;                                         // Clear Interrupt-Flag

      // Werte für 10 MHz
      TMR1L=0xCB;                                       // Timer 1 neu vorladen (0xF3CB = 10ms)
      TMR1H=0xF3;                                       // n = 2^16 - t [s] * 625000

   	} // From Timer 1 Überlauf

   return;									                            // Zurück zum Hauptprogramm

}

/***************************
 *
 * Wandlerwert reinlutschen
 *
 ***************************/
unsigned int ADCGetRaw (void)
 {
  //-----------------
  // Wo solls rein ?
  //-----------------
  ADCON0bits.CHS2 = 0;
  ADCON0bits.CHS1 = 0;
  ADCON0bits.CHS0 = 0;
  DelayUs (1000);  // Kondensator laden
  ADCON0bits.GO = 1;     // Los gehts
  while (ADCON0bits.GO);

  return (ADRES);
 }

/******************************
 *
 * Startklar machen den Eimer
 *
 ******************************/
void sysinit (void)
 {
  unsigned int Lichtwert = 0;

  TRISA = 0b00000001;           // AN0 = Lichtsensor
  TRISB = 0b00000010;           // RB0 = Relais; RB1 = Taster
  TRISC = 0b00000000;

  ClrWdt();

  //------------
  // Timer-Init
  //------------
  PIE1bits.TMR1IE=1;									                      // enable Interrupt of TMR1
  T1CON=49;									                      // Prescaler=1:8 + Timer on (49)
  INTCONbits.PEIE=1;          							                  // Peripherie Int=on
  INTCONbits.GIE=1;										                      // Define Interupts
  ClrWdt();

  //--------------------------
  // AD-Wandler-Einstellungen
  //--------------------------
  ADCON0bits.ADCS1 = 1;
  ADCON0bits.ADCS0 = 0;
  ADCON0bits.ADON = 1;             // Wandler ein
  ADCON1bits.ADFM = 1;             // Rechtsseitig

  ADCON1bits.PCFG3 = 0;            // Externe Referenz, alle Kanäle Analog
  ADCON1bits.PCFG2 = 0;
  ADCON1bits.PCFG1 = 0;
  ADCON1bits.PCFG0 = 0;

  //-------------------
  // PWM-Einstellungen
  //-------------------

  // Ausgang startklar machen
  TRISC &= ~0b00000000;

  // PWM Duty Cycle bit1 and bit0
  CCP1CONbits.DC1B1 = 0;
  CCP1CONbits.DC1B0 = 0;

  // PWM-Modus
  CCP1CONbits.CCP1M3 = 1;
  CCP1CONbits.CCP1M2 = 1;
  CCP1CONbits.CCP1M1 = 0;
  CCP1CONbits.CCP1M0 = 0;

  // Startwert für PWM setzen
  CCPR1L = 20;

  // Timer 2 klarmachen
  PR2 = 0xFF;
  // Postscaler 1:16
  T2CONbits.TOUTPS3 = 1;
  T2CONbits.TOUTPS2 = 1;
  T2CONbits.TOUTPS1 = 1;
  T2CONbits.TOUTPS0 = 1;
  // Prescaler 1:16
  T2CONbits.T2CKPS1 = 1;
  T2CONbits.T2CKPS0 = 1;
  // Und los
  T2CONbits.TMR2ON = 1;

  // Zufallsgenerator starten
  Lichtwert = ADCGetRaw ();
  srand (Lichtwert);

  Lampe = 1;
  Delayms (100);
  Lampe = 0;
  Delayms (100);
  Lampe = 1;
  Delayms (100);
  Lampe = 0;
  Delayms (100);
  Lampe = 1;
  Delayms (100);
  Lampe = 0;
  Delayms (100);


 }

/***************************************
 *
 * Hier geht das total los das Mopped !
 *
 ***************************************/
void main()
{
 unsigned int Zufallswert;
 unsigned int Zufallstrom;
 char Rauf;
 signed char Zuckwert;
 unsigned int Zeitschleife;

  sysinit ();

  // Mach das hier mal, bis du kotzen musst
  while (1)
   {
    ClrWdt();

    // Die nächsten Zufallswerte generieren
Zufallswert =  rand ();
Zufallswert /=  6550;
Zufallswert += 3;


  //  Zufallswert =  3 + (rand () / 6550); // Erzeugt bei RAND_MAX = 2^15 einen Wert zwischen 3 und 8 für die Zeitschleife
//    Zufallstrom = 30 + (rand () / 819);  // Erzeugt bei RAND_MAX = 2^15 einen Wert zwischen 30 und 70 für den Mittelwert der PWM

Zufallstrom = rand ();
Zufallstrom /= 160;
Zufallstrom += 30;


    // Die folgende Schleife läuft also 3-8 Sekunden
    Rauf = 1;
    Zuckwert = 0;
    Zeitschleife = SekundenTicker;
    while (SekundenTicker <= (Zeitschleife + Zufallswert))
     {
      // Zeitschleife = SekundenTicker;    // Zeit messen
      ClrWdt();
      CCPR1L = (char)(Zufallstrom + Zuckwert);       // PWM setzen

      // Jetzt einfach ein wenig mit dem Zeiger zucken

      // Kurze Pause, dann PWM-Wert ändern
      Delayms (200);
      if (Rauf) Zuckwert++; else Zuckwert--;
      if (Zuckwert == 20) Rauf = 0;
      if (Zuckwert == -20) Rauf = 1;

     } // Von while (Zeitschleife <= (Zeitschleife + Zufallswert))

    // Mit Lampe rumblinken
    if ((MinutenTicker % 5) == 0)
     {
       if (!Lichtblitzer)
 	    {
         Lichtblitzer = TRUE;
         Lampe = 1;
		     Delayms (100);
		     Lampe = 0;
	    }
	 } else Lichtblitzer = FALSE;





   } // Von While (1)

} // Thats all folks


