/*
 * File:   16F1829IRTest1.c
 * Author: JaysWoodshop
 * PIC 16F1829
 * Created on Jan. 23, 2016
 * 
 * 
*****************************************************************************/
/* Files to Include                                                           */
/******************************************************************************/
#include  <xc.h>

#define _XTAL_FREQ 4000000  //4MHz

// CONFIG1
#pragma config FOSC = INTOSC    // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = OFF       // Internal/External Switchover (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)
// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = OFF      // PLL Enable (4x PLL disabled)
#pragma config STVREN = OFF     // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)

//===============================
//Various defines
#define IRR1 PORTAbits.RA4      // IR Receiver Output pin 3
#define IRR2 PORTAbits.RA5      // IR Receiver Output pin 2
//#define RELAY LATAbits.LATA4     // Relay transistor pin 3
#define IRT1 LATCbits.LATC6      // IR LED Transmit pin 8
#define GLT LATCbits.LATC7      // test LED pin 9
//===============================
//Global variables
unsigned char IRR1Count;
unsigned char IRR2Count;
//unsigned char DelayCount;
unsigned char Previous_IR1_State;  // detect changes in IR beam state
unsigned char Previous_IR2_State;  // detect changes in IR beam state
//===============================

//Initialization 
void init(void)
{
    OSCCON = 0b01101000;        // 4MHz HF(1)page 53
    //TIMER0 - Set to count 1 seconds 
    //rollover .524 sec. @ 500kHz = 2 count, .066 sec. @ 4MHz = 15 count
    INTCON = 0b00000000;        // Interrupts disabled
    OPTION_REG = 0b00000111;    //WP disabled, timer0 from instruction clock, prescaler 256

    //initial state of all output pins is low
    LATA = 0b00000000;
    LATB = 0b00000000;
    LATC = 0b00000000;
    
    //enable all digital input buffers
    ANSELA = 0b00000000;
    ANSELB = 0b00000000;
    ANSELC = 0b00000000;
    
    //weak pull ups (all off 
    WPUA = 0;   
    WPUB = 0;   
    WPUC = 0;   
    
    //input thresholds
    INLVLA = 0b00111111;        //all inputs use CMOS levels
    INLVLB = 0b11110000;        //all inputs use CMOS levels
    INLVLC = 0b11111111;        //all inputs use CMOS levels
    
    //set pin in/out directions. All out except where we need an input
    TRISA = 0b00110000;         //RA4 are input
    TRISB = 0b00000000;         //all outputs
    TRISC = 0b00000000;         //all outputs
    
    /* Configure CCP4 in PWM mode to output ~38kHz @ RC6: See '1829 Data Sheet Section 24.3.2 */
    TRISCbits.TRISC6 = 1;   /* Disable the CCP4 pin output driver. */
    T2CONbits.TMR2ON = 0b0;   /* Disable Timer2 */
    T2CONbits.T2CKPS = 0b00;   /* ::= Timer2 pre scaler is 1 */
    PR2bits.PR2 = 0x19;   /* ~26 uSec @ 4 MHz Fosc */
    CCPR4Lbits.CCPR4L = 0x0c;   /* MSb's of the PWM duty cycle. */
    CCP4CONbits.DC4B = 0b00;   /* LSb's of the PWM duty cycle. */
    CCP4CONbits.CCP4M = 0b1100;   /* ::= CCP PWM Mode */
    CCPTMRSbits.C4TSEL = 0b00;   /* ::= CCP4 is based on Timer2 in PWM Mode */
    T2CONbits.TMR2ON = 0b1;   /* ::= Timer2 is on */
    TRISCbits.TRISC6 = 0;   /* Enable the CCP4 pin output driver. */

}    
//===============================
//Start train
void open_door(void)
{
    GLT = 1;        // Test LED 
}    
//===============================
void close_door(void)
{
    GLT = 0;        // Test LED 
}
//===============================
//Main loop    
// Initial conditions - No train (IR beam signal is 1 / door closed)
void main(void)
{
    init();
    IRR1Count = 0;
    IRR2Count = 0;
    close_door();
    Previous_IR1_State = 0;
    Previous_IR2_State = 0;
    
    while(1)
    {          // ____Process IR beam state____
        if(!IRR1)        // If break beam use !IRR1 not
            // If IRR1 is seeing IR = 0 if blocked = 1
        {      // IR beam state is 0
            if(Previous_IR1_State == 1)
            {
            // IR state changed 1 --> 0 (previous to current) --> end of car
                Previous_IR1_State = 0;
                // Current state becomes new previous state for the next loop
                // (re)init End Of Train detection delay
                //DelayCount = EOT_COUNT;
            }
        }
        else
        {
                // IR beam state is 1
            if(Previous_IR1_State == 0)
            {
                // IR beam state changed from 0 to 1 (previous to current) --> beginning of car
                Previous_IR1_State = 1;
                // Current state becomes new previous state for the next loop
                IRR1Count++;                
            }
        }
        if(!IRR2)        // If break beam use !IRR1 not
            // If IRR1 is seeing IR = 0 if blocked = 1
        {      // IR beam state is 0
            if(Previous_IR2_State == 1)
            {
            // IR state changed 1 --> 0 (previous to current) --> end of car
                Previous_IR2_State = 0;
                // Current state becomes new previous state for the next loop
                // (re)init End Of Train detection delay
                //DelayCount = EOT_COUNT;
            }
        }
        else
        {
                // IR beam state is 1
            if(Previous_IR2_State == 0)
            {
                // IR beam state changed from 0 to 1 (previous to current) --> beginning of car
                Previous_IR2_State = 1;
                // Current state becomes new previous state for the next loop
                IRR2Count++;                
            }
        }
        
                // ____Gate state control____
        // Gate closed while IRR1 != IRR2
        if (IRR1Count != IRR2Count)
        {
            open_door(); // Open and keep open while train is passing
        }
        else
        {
            close_door(); // Close and keep closed while no train
            IRR1Count = 0;
            IRR2Count = 0;
        }
    } // while(true)
}   // End of main

