/*********************************************************************
 * FileName:        capture_rc.c
 * Dependencies:    See INCLUDES section below
 * Processor:       PIC18
 * Compiler:        C18 2.30.01+
 * Company:         sprut
 * Copyright:       2012 Joerg Bredendiek (sprut)
 *
 *
 ********************************************************************/


/** I N C L U D E S **********************************************************/
#include <p18cxxx.h>
#include "GenericTypeDefs.h"
#include "HardwareProfile.h"             // I/O pin mapping
#include "delays.h"
#include "capture_rc.h"
#include "led.h"
#include "axis.h"



/** V A R I A B L E S ********************************************************/
#pragma udata
WORD		pulse_array[maxpulse];
char		KZ_Array[3];
char		pulse_pointer;
char		got_frame;
char		DontTouch;
char		ZwoelfKanal;
char		KanalZahl;



/** D E C L A R A T I O N S **************************************************/
#pragma code

/*
CCP1 = RC2
CCP2 = RC1
beide Eingaenge capturen mit dem 16-bit-timer 1
Timer1:     																				1ms		1.5 ms	2ms		delta
Fosc / 4 / 8 = 48 MHZ / 32 = 1.5 MHz -> 0.666us		16-bit = 0.66us * 65536 = 43.69 ms		1500	2250	3000	1500	=  5DC		/5.859
1..2ms = 1ms = 256 -> resolution: 3.9 us
*/

void Init_Capture(void)
{
	pulse_pointer	= 0;
	got_frame 		= 0;
	DontTouch       = 0;
	KanalZahl		= 8;
	KZ_Array[0]		= KanalZahl;
	KZ_Array[1]		= KanalZahl;
	KZ_Array[2]		= KanalZahl;


	//Timer 1 initialisieren
	TMR1L = 0;
	TMR1H = 0;
	T1CONbits.RD16		= 1;	// 16 bit
	T1CONbits.T1CKPS1	= 1;	// PS 8:1
	T1CONbits.T1CKPS0	= 1;
	T1CONbits.T1OSCEN	= 0;	// Oszillator off
	T1CONbits.TMR1CS	= 0;	// Fosc/4
	T1CONbits.TMR1ON	= 1;	// Timer an
	//CCP1 initialisieren
	CCP1CON = 0b0100;			// Capture mode: every falling edge
	//CCP2 initialisieren
	CCP2CON = 0b0101;			// Capture mode: every rising edge

	// interrupts 
	PIR1 = 0;
	PIR2 = 0;
    PIR1bits.CCP1IF		= 0;	// clear CCP1 Interrupt Flag
    PIR1bits.TMR1IF		= 0;	// clear Timer1 Interrupt Flag
    PIR2bits.CCP2IF		= 0;    // clear CCP2 Interrupt Flag

    INTCONbits.PEIE 	= 1;    // enable Peripheral Interrupt Enable
	PIE1 = 0;
	PIE2 = 0;
    PIE1bits.CCP1IE 	= 1;    // enable CCP1 Interrupt
    PIE1bits.TMR1IE 	= 1;    // enable Timer1 Interrupt
    PIE2bits.CCP2IE 	= 1;    // enable CCP2 Interrupt

    INTCONbits.GIE		= 1;    // enable global interrupts
} // Init_Capture



void UP_Capture(void)
{

} // UP_Capture


// erkennt Störungen
// nurn die aktuelle Anzahl der Kanäle mit den Anzahlen der beiden letzuten Frames übereinstimmt
// dann wird true zurückgegeben
char KanalZahlOK(void)
{
	char OK = 0;
	KZ_Array[2] = KZ_Array[1];
	KZ_Array[1] = KZ_Array[0];
	KZ_Array[0] = KanalZahl;
	if 	(KZ_Array[2] == KZ_Array[1]) OK++;
	if 	(KZ_Array[1] == KZ_Array[0]) OK++;
	if 	(KZ_Array[2] == KZ_Array[0]) OK++;
	if (OK==3) {
		Led1_On();
		return 1;
	}
	Led1_Off();
	return 0;
}


#pragma code

/******************************************************************************
 * Function:        
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        
 *
 * Note:            Refer to PIC18F2455/2550/4455/4550 Errata concerning
 *                  high-priority interrupt problem.
 *   
 *****************************************************************************/

#pragma interruptlow InterruptHandler

void InterruptHandler (void)
{
	WORD_VAL	pulse;
	char k;

	// Timer 1 ueberlauf nach 43 ms ohne Pulse
	if (PIR1bits.TMR1IF)
	{
		got_frame       = 0;	
		pulse_pointer	= 0;
		Led1_Off();
		PIR1bits.TMR1IF = 0;
	}

	// Puls gefunden
    if (PIR1bits.CCP1IF || PIR2bits.CCP2IF)
	{
		TMR1L = 0;
		TMR1H = 0;
		if (PIR1bits.CCP1IF)
		{
	        PIR1bits.CCP1IF = 0;		// clear interrupt flag
			pulse.byte.HB = CCPR1H;
			pulse.byte.LB = CCPR1L;
		} else {
			PIR2bits.CCP2IF = 0;		// clear interrupt flag
			pulse.byte.HB = CCPR2H;
			pulse.byte.LB = CCPR2L;
		}
		if (pulse.Val > DreiMS)			// das war die Luecke
		{
			//ende des Frames
			// bei 12 Kanal : pulse_pointer == 25
			// bei  8 Kanal : pulse_pointer == 17
			if ( (pulse_pointer & 1) && (pulse_pointer >= 7)  && (pulse_pointer <= 25) )	//3..12 Kanäle
			{
				KanalZahl   = (pulse_pointer - 1) /2;
				if (KanalZahlOK() && (DontTouch==0) )
				{
					got_frame = pulse_pointer;	
					for (k=0; k<((pulse_pointer-1)/2); k++)
					{
						Kanal[k] = pulse_array[2*k +1] + pulse_array[2*k +2];
					}			
				}
			} else 
			{
				got_frame = 0;	
				Led1_Off();
			}
			pulse_pointer	= 0;
		} else {
			pulse_array[pulse_pointer++] = pulse.Val;
			if (pulse_pointer >= maxpulse)	// zu viele Pulse ohne Luecke
			{
				got_frame     = 0;	
				pulse_pointer = 0;
			}
		}
    } //  end if (PIR1bits.CCP1IF)

} // end void InterruptHandler(void)


/** EOF ************************************************************/