/* 
 * File:   main.c
 * Author: paulo
 *
 * Created on 13 de Fevereiro de 2014, 23:37
 */

#include <xc.h>

#include <stdio.h>
#include <stdlib.h>

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
 
// CONFIG1
#pragma config FOSC = INTOSC    //  (INTOSC oscillator; I/O function on CLKIN pin)
#pragma config WDTE = 0        // Watchdog Timer Enable (WDT enabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = 0       // 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 BOREN = 0       // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = ON       // PLL Enable (4x PLL enabled)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LPBOREN = OFF    // Low Power Brown-out Reset enable bit (LPBOR is disabled)
#pragma config LVP = 0         // Low-Voltage Programming Enable (Low-voltage programming enabled)



int status = 0; // Global variable

// Functions declaration
int pushButtonEventHandler(void);
int blink(void);
int init_ctrl(void);

int delay(int a, int b) {
    int i = 0;
    int j = 0;
    
    while(i<a){
        while(j<b)
        {
            j++;
        }
        j=0;
        i++;
    }
    
   return 0;
}

int init_ctrl(void) {
    // Set RA0 as Output pin (IO Out - to Raspi) to Low
    LATAbits.LATA0 = 0;
}


// Interrupt handler function
void interrupt myIsr(void) {
    // only RA4 driven interrupts
    if(IOCAFbits.IOCAF3) {
        pushButtonEventHandler();
        init_ctrl();
        IOCAFbits.IOCAF3 = 0; // clear interrupt flag
    }
}


/*
 * 
 */
int main(void) {
    int i = 0;
    ANSELAbits.ANSA1 = 0;
    ANSELAbits.ANSA0 = 0;

    // Disable PWM is RA1, RA0, RA2
    PWM1CONbits.PWM1EN = 0;
    PWM2CONbits.PWM2EN = 0;
    PWM3CONbits.PWM3EN = 0;

 
    // Set RA4 as Output pin (LED)
    TRISAbits.TRISA4 = 0;
    // Set RA5 as Output pin (Power switch control)
    TRISAbits.TRISA5 = 0;
    // Set RA0 as Output pin (IO Out - to Raspi)
    TRISAbits.TRISA0 = 0;
    // Set it to Low
    LATAbits.LATA0 = 0;

    // Set RA1 as Input pin
    TRISAbits.TRISA1 = 1;       // GPIO from Raspi (IO In)
    // Set RA2 as Input pin
    TRISAbits.TRISA2 = 1;       // Overcurrent sense


//Power-on default to Vout=OFF
    // Put RA4 Low to turn LED OFF
    LATAbits.LATA4 = 0;
    // Put RA5 Low to turn OFF output power
    LATAbits.LATA5 = 0;

    //Poll until button is pressed
    while(PORTAbits.RA3==1){}
    
    // Put RA4 High to turn LED ON
    LATAbits.LATA4 = 1;
    // Put RA5 High to turn ON output power
    LATAbits.LATA5 = 1;



    // enable the interrupts
    INTCONbits.GIE = 1;
    // enable the interrupts on change
    INTCONbits.IOCIE = 1;
    // interupt on faling edge of RA3
    IOCANbits.IOCAN3 = 1;

    // wait for raspi boot
    while(i<255) {
        delay(6,255);
        blink();
        i++;
    }
    
    while(PORTAbits.RA1==0) {
         delay(5,255);
         blink();
    }
    // Put RA4 High to turn LED ON
    LATAbits.LATA4 = 1;
    
    // Main loop
    while(1) {}

    return (0);
}


int pushButtonEventHandler(void) {
    int timeout = 0;
    int pressed = 1;
    int counter = 0;
    int i = 0;


    if(PORTAbits.RA3==0) {
        // first check if raspi in ON
        if(PORTAbits.RA1==1) {
            // STEP 1
            // if ON send poweroff command
            LATAbits.LATA0 = 1;
            // STEP 2: Wait for 0 at YKRUD IN
            i = 0;
            while(i<25 && PORTAbits.RA1!=0){
                delay(5,255);
                blink();
                i++;
            }
            if(i>=25) {
                return 0;   // timeout
            }

            // STEP 3: set YKRUD_OUT at Low
            LATAbits.LATA0 = 0;

            // STEP 4: Wait for 1 at YKRUD IN
            i = 0;
            while(i<25 && PORTAbits.RA1!=1){
                delay(5,255);
                i++;
            }
            if(i>=25) {
                return 0;   // timout
            }

            // STEP 5: set YKRUD_OUT at High
            LATAbits.LATA0 = 1;

            // STEP 6: Wait for 0 at YKRUD IN
            i = 0;
            while(i<25 && PORTAbits.RA1!=0){
                delay(5,255);
                i++;
            }
            if(i>=25) {
                return 0;   // timeout
            }

            // STEP 7: Wait for shut down
            while(timeout == 0) {
                // Check if still pressed
                if(PORTAbits.RA3==0 && pressed==1) {
                    if(counter==19) {
                        // do hard power off
                        LATAbits.LATA5 = 0; //Power OFF
                        LATAbits.LATA4 = 0;     //LED OFF
                        delay(15,255);
                        return 0;
                    }
                    counter++;
                } else {
                    pressed = 0;
                    timeout = 1;
                }

                // blink led
                blink();
                delay(6,255);
            }

            //  Wait before switching power off
            i = 0;
            while(i<130){
                delay(7,255);
                blink();
                i++;
            }
            LATAbits.LATA4 = 0;     //LED OFF
            LATAbits.LATA5 = 0;     //Power OFF
            return 0;


        } else {
            // Fast blink
            i = 0;
          //  while(1){
            while(i<60 && PORTAbits.RA1!=0){
                delay(2,255);
                blink();
                i++;
            }

            // If Raspi is OFF we need to switch power OFF->ON to start boot process
            LATAbits.LATA5 = 0;     //Power OFF
            delay(7,255);
            LATAbits.LATA5 = 1;     //Power ON
            // wait for raspi boot
            while(i<255) {
                delay(6,255);
                blink();
                i++;
            }
            while(PORTAbits.RA1==0) {
                blink();
                delay(6,255);
            }
            LATAbits.LATA4 = 1;       //LED ON
        }

    }

    return 0;
}



int blink(void) {
    // toogle led and output power
    if(status==0) {
        LATAbits.LATA4 = 1;     //LED ON
        //  LATAbits.LATA5 = 1;     //Power ON
        status = 1;
    } else {
        LATAbits.LATA4 = 0;     //LED OFF
        //  LATAbits.LATA5 = 0;     //Power OFF
        status = 0;
    }
    return 0;
}

