/***************************************************************************//**
 *   @file   interrupts.c
 *   @brief  Gestion des interruptions du microcontroller
 *   @author Kévin (Kevin.marchand@intelligence-electronique.com)
********************************************************************************
 * Copyright 2014(c) PLCD, Inc.
 *
 * Fonctions déclenchées par les interruptions.
 *
 * Refer to the C30 (MPLAB C Compiler for PIC24F MCUs and dsPIC33F DSCs) User
 * Guide for an up to date list of the available interrupt options.
 *
 *  Noms des vecteurs d'interruption primaire disponible sur le dsPIC33E :
 * - _INT0Interrupt,   _IC4Interrupt,      _U4TXInterrupt,
 * _IC1Interrupt,      _IC5Interrupt,      _SPI3ErrInterrupt,
 * - _OC1Interrupt,      _IC6Interrupt,      _SPI3Interrupt,
 * _T1Interrupt,       _OC5Interrupt,      _OC9Interrupt,
 * - _DMA0Interrupt,     _OC6Interrupt,      _IC9Interrupt,
 * _IC2Interrupt,      _OC7Interrupt,      _PWM1Interrupt,
 * - _OC2Interrupt,      _OC8Interrupt,      _PWM2Interrupt,
 * _T2Interrupt,       _PMPInterrupt,      _PWM3Interrupt,
 * - _T3Interrupt,       _DMA4Interrupt,     _PWM4Interrupt,
 * _SPI1ErrInterrupt,  _T6Interrupt,       _PWM5Interrupt,
 * - _SPI1Interrupt,     _T7Interrupt,       _PWM6Interrupt,
 * _U1RXInterrupt,     _SI2C2Interrupt,    _PWM7Interrupt,
 * - _U1TXInterrupt,     _MI2C2Interrupt,    _DMA8Interrupt,
 * _AD1Interrupt,      _T8Interrupt,       _DMA9Interrupt,
 * - _DMA1Interrupt,     _T9Interrupt,       _DMA10Interrupt,
 * _NVMInterrupt,      _INT3Interrupt,     _DMA11Interrupt,
 * - _SI2C1Interrupt,    _INT4Interrupt,     _SPI4ErrInterrupt,
 * _MI2C1Interrupt,    _C2RxRdyInterrupt,  _SPI4Interrupt,
 * - _CM1Interrupt,      _C2Interrupt,       _OC10Interrupt,
 * _CNInterrupt,       _QEI1Interrupt,     _IC10Interrupt,
 * - _INT1Interrupt,     _DCIEInterrupt,     _OC11Interrupt,
 * _AD2Interrupt,      _DCIInterrupt,      _IC11Interrupt,
 * - _IC7Interrupt,      _DMA5Interrupt,     _OC12Interrupt,
 * _IC8Interrupt,      _RTCCInterrupt,     _IC12Interrupt,
 * - _DMA2Interrupt,     _U1ErrInterrupt,    _DMA12Interrupt,
 * _OC3Interrupt,      _U2ErrInterrupt,    _DMA13Interrupt,
 * - _OC4Interrupt,      _CRCInterrupt,      _DMA14Interrupt,
 * _T4Interrupt,       _DMA6Interrupt,     _OC13Interrupt,
 * - _T5Interrupt,       _DMA7Interrupt,     _IC13Interrupt,
 * _INT2Interrupt,     _C1TxReqInterrupt,  _OC14Interrupt,
 * - _U2RXInterrupt,     _C2TxReqInterrupt,  _IC14Interrupt,
 * _U2TXInterrupt,     _QEI2Interrupt,     _OC15Interrupt,
 * - _SPI2ErrInterrupt,  _U3ErrInterrupt,    _IC15Interrupt,
 * _SPI2Interrupt,     _U3RXInterrupt,     _OC16Interrupt,
 * - _C1RxRdyInterrupt,  _U3TXInterrupt,     _IC16Interrupt,
 * _C1Interrupt,       _USB1Interrupt,     _ICDInterrupt,
 * - _DMA3Interrupt,     _U4ErrInterrupt,    _PWMSpEventMatchInterrupt,
 * _IC3Interrupt,      _U4RXInterrupt,     _PWMSecSpEventMatchInterrupt
 *
 *
 * Example Syntax :
 * @code
 * void __attribute__((interrupt,auto_psv)) <Vector_Name>(void)
 * {
 *     <Clear_Interrupt_Flag>
 *      ...
 * }
 * @endcode
 * For more comprehensive interrupt examples refer to the C30 (MPLAB C
 * Compiler for PIC24 MCUs and dsPIC DSCs) User Guide in the
 * <C30_compiler_instal_directory>/doc directory for the latest compiler
 * release.
 * For XC16, refer to the MPLAB XC16 C Compiler User's Guide in the
 * <XC16_compiler_instal_directory>/doc folder.
********************************************************************************
 *   SVN Revision: 1
*******************************************************************************/

/******************************************************************************/
/***************************** Include Files **********************************/
/******************************************************************************/

/* Device header file */
#if defined(__XC16__)
    #include <xc.h>
#elif defined(__C30__)
    #if defined(__dsPIC33E__)
    	#include <p33Exxxx.h>
    #elif defined(__dsPIC33F__)
    	#include <p33Fxxxx.h>
    #endif
#endif

#include <stdint.h>        /* Includes uint16_t definition   */
#include <stdbool.h>       /* Includes true/false definition */
#include "user.h"
#include "GenericTypeDefs.h"
#include "UARTsComm.h"
#include "uart.h"
#include "ADC10bitsDrv.h"
#include "MODBUSTCPServer.h"
#include "AD7190.h"
#include "PPS.h"

#include "B40/abcc_sys_adapt.h"
#include "B40/abcc.h"
#include "B40/user_adi.h"
#include "B40/ad_obj.h"

#include "usb_config.h"
#include "ECAN/ECAN1Drv.h"
#include "Process.h"

extern WORD INPUT_REG[INPUT_REG_SIZE];
/******************************************************************************/
/************************** Interrupt Routines ********************************/
/******************************************************************************/

/***************************************************************************//**
 * @brief Interruption de réception RX de l'<b>UART1</b> (exécutée à la réception de données).
 * @details Cette fonction assure le contrôle de l'intégrité des octets reçus et les
 * ajoutes au buffer de réception. Puis appel la fonction ReceiveUART1()
 * pour le contrôle de la trame.
 * @see ReceiveUART1()
*******************************************************************************/
void __attribute__((__interrupt__, __shadow__,__auto_psv__)) _U1RXInterrupt(void)
{
    /* Lit le tampon de réception tant que un ou plusieurs caractère peut être lu*/
    while( DataRdyUART1())
    {
        if(U1STAbits.OERR == 1)                                                 // See if Receive buffer has overflowed
            U1STAbits.OERR = 0;                                                 // Reset flag
        if((U1STAbits.FERR == 1) || (U1STAbits.PERR == 1)){                     // Accept data only if there were no Framing or Parity Error(s)
            ReadUART1();
            TrameU1.buffIdx = 0;                                                // Init buffer si erreur
            continue;
        }
        if(TrameU1.buffIdx >= sizeof(TrameU1.Buff))
            TrameU1.buffIdx = 0;
        TrameU1.Buff[TrameU1.buffIdx++] = ReadUART1();
    } 
    ReceiveUART1();                                                             // Read data
    IFS0bits.U1RXIF = 0;
    TrameU1.Compteur = 5;
}
/***************************************************************************//**
 * @brief Interruption de réception RX de l'<b>UART2</b> (exécutée à la réception de données).
 * @details Cette fonction assure le contrôle de l'intégrité des octets reçus et les
 * ajoutes au buffer de réception. Puis appel la fonction ReceiveUART2()
 * pour le contrôle de la trame.
 * @see ReceiveUART2()
*******************************************************************************/
void __attribute__((__interrupt__, __shadow__,__auto_psv__)) _U2RXInterrupt(void)
{
    /* Lit le tampon de réception tant que un ou plusieurs caractères peut être lu */
    while( DataRdyUART2())
    {
        if(U2STAbits.OERR == 1)                                                 // See if Receive buffer has overflowed
            U2STAbits.OERR = 0;                                                 // Reset flag
    
        if((U2STAbits.FERR == 1) || (U2STAbits.PERR == 1)){                     // Accept data only if there were no Framing or Parity Error(s)
            ReadUART2();
            TrameU2.buffIdx = 0;                                                // Init buffer si erreur
            continue;
        }
        if(TrameU2.buffIdx >= sizeof(TrameU2.Buff))
            TrameU2.buffIdx = 0;
        TrameU2.Buff[TrameU2.buffIdx++] = ReadUART2();
    }
    ReceiveUART2();                                                             // Read data
    IFS1bits.U2RXIF = 0;
    TrameU2.Compteur = 5;
}

/***************************************************************************//**
 * @brief Interruption de réception RX de l'<b>UART3</b> (exécutée à la réception de données).
 * @details Cette fonction assure le contrôle de l'intégrité des octets reçus et les
 * ajoutes au buffer de réception. Puis appel la fonction ReceiveUART3()
 * pour le contrôle de la trame.
 * @see ReceiveUART3()
*******************************************************************************/
void __attribute__((__interrupt__, __shadow__,__auto_psv__)) _U3RXInterrupt(void)
{
    /* Lit le tampon de réception tant que un ou plusieurs caractères peut être lu */
    while( DataRdyUART3())
    {
        if(U3STAbits.OERR == 1)                                                 // See if Receive buffer has overflowed
            U3STAbits.OERR = 0;                                                 // Reset flag

        if((U3STAbits.FERR == 1) || (U3STAbits.PERR == 1)){                     // Accept data only if there were no Framing or Parity Error(s)
            ReadUART3();
            TrameU3.buffIdx = 0;                                                // Init buffer si erreur
            continue;
        }
        if(TrameU3.buffIdx >= sizeof(TrameU3.Buff))
            TrameU3.buffIdx = 0;
        TrameU3.Buff[TrameU3.buffIdx++] = ReadUART3();
    }
    ReceiveUART3();                                                             // Read data
    IFS5bits.U3RXIF = 0;
    TrameU3.Compteur = 5;
}

/***************************************************************************//**
 * @brief Interruption de réception RX de l'<b>UART4</b> (exécutée à la réception de données).
 * @details Cette fonction assure le contrôle de l'intégrité des octets reçus et les
 * ajoutes au buffer de réception. Puis appel la fonction ReceiveUART4()
 * pour le contrôle de la trame.
 * @see ReceiveUART4()
*******************************************************************************/
void __attribute__((__interrupt__, __shadow__,__auto_psv__)) _U4RXInterrupt(void)
{
    /* Lit le tampon de réception tant que un ou plusieurs caractères peut être lu */
    while( DataRdyUART4())
    {
        if(U4STAbits.OERR == 1)                                                 // See if Receive buffer has overflowed
            U4STAbits.OERR = 0;                                                 // Reset flag

        if((U4STAbits.FERR == 1) || (U4STAbits.PERR == 1)){                     // Accept data only if there were no Framing or Parity Error(s)
            ReadUART4();
            TrameU4.buffIdx = 0;                                                // Init buffer si erreur
            continue;
        }
        if(TrameU4.buffIdx >= sizeof(TrameU4.Buff))
            TrameU4.buffIdx = 0;
        TrameU4.Buff[TrameU4.buffIdx++] = ReadUART4();
    }
    ReceiveUART4();                                                             // Read data
    IFS5bits.U4RXIF = 0;
    TrameU4.Compteur = 5;
}

/***************************************************************************//**
 * @brief Interruption DMA0.
 * @details Cette fonction assure le buffering des échantillons de l'ADC.
 * @see ProcessADCSamples()
*******************************************************************************/
void __attribute__ ( (interrupt, auto_psv) ) _DMA0Interrupt( void )
{
    if(DmaBufferSwitch == 0)
    {
        ProcessADCSamples(NUM_AN1, &BufferA[NUM_AN1][0]);
        ProcessADCSamples(NUM_AN2, &BufferA[NUM_AN2][0]);
    }
    else
    {
//        ProcessADCSamples(NUM_AN1, &BufferB[NUM_AN1][0]);
//        ProcessADCSamples(NUM_AN2, &BufferB[NUM_AN2][0]);
    }

    DmaBufferSwitch ^= 1;
    IFS0bits.DMA0IF = 0;		// Clear the DMA0 Interrupt Flag
    
}

/***************************************************************************//**
 * @brief Interruption entrée INT1.
 * @details Cette fonction assure le comptage des impulsions sur l'entrée INT1.
 *
*******************************************************************************/
void __attribute__((__interrupt__, __shadow__,__auto_psv__)) _INT1Interrupt(void)
{
    LED1_IO ^= 1;

    if (EXP.CptInt1 == -1)
        ResetCounterMillis();

    if (PAR.EntreeTOR[9] == DI_VitesseMene)
    {
        entTOR[8] ^= 1;
        T100[timer_VitesseNulle] = 30;                                          // 3s
        EXP.PulseTotal++;
        EXP.TotPulseReglage++;
    }

    EXP.CptInt1++;
    EXP.TempsVitesse1 = GetCounterMillis();
    IFS1bits.INT1IF = 0;
}
/***************************************************************************//**
 * @brief Interruption entrée INT2.
 * @details Cette fonction assure le comptage des impulsions sur l'entrée INT2.
 *
*******************************************************************************/
void __attribute__((__interrupt__, __shadow__,__auto_psv__)) _INT2Interrupt(void)
{
    LED1_IO ^= 1;

    if (EXP.CptInt2 == -1)
        ResetCounterMillis();

    if (PAR.EntreeTOR[10] == DI_VitesseMene)
    {
        entTOR[9] ^= 1;
        T100[timer_VitesseNulle] = 30;                                          // 3s
        EXP.PulseTotal++;
        EXP.TotPulseReglage++;
    }

    EXP.CptInt2++;
    EXP.TempsVitesse2 = GetCounterMillis();
    IFS1bits.INT2IF = 0;
}

/***************************************************************************//**
 * @brief Interruption entrée INT3 RDY pin de l'AD7190.
 * @details Permet la lecture de l'échantillon dès que la converssion par
 *  l'AD7190 a été effectuée. Mode d'acquisition par interruption
 *  (voir AD7190_StartContinuousRead()).
 *
*******************************************************************************/
void __attribute__((__interrupt__, __shadow__,__auto_psv__)) _INT3Interrupt(void)
{
unsigned long sample = 0x0;

sample = AD7190_GetRegisterValue(AD7190_REG_DATA, 3, 0);
IFS3bits.INT3IF = 0;
    
EXP.TestCompteur1++;
EXP.PoidsPoints = sample;
EXP.NouveauPoids = 1;

// Calcul des totalisateurs pour Pese essieux
if (PAR.CategorieProgramme == TY_PeseEssieux)
{
    EXP.PEs_CumulPoidsEssieu = EXP.PEs_CumulPoidsEssieu + sample;
    EXP.PEs_NbMesurePoids++;
}
}


/***************************************************************************//**
 * @brief Interruption entrée INT4 IRQ B40 pin.
 * @details Cette fonction assure le fonctionnement sous interruption
 * avec le module B40.
 *
*******************************************************************************/
void __attribute__((__interrupt__, __shadow__,__auto_psv__)) _INT4Interrupt(void)
{
     ABCC_SYS_EnterCritical();
     ABCC_ISR();
     ABCC_SYS_ExitCritical();
     IFS3bits.INT4IF = 0;
}


#if defined(USB_INTERRUPT)
/***************************************************************************//**
 * @brief Interruption USB.
 * @details Cette fonction assure le fonctionnement de l'USB sous interruption
 *
*******************************************************************************/
void __attribute__((interrupt,auto_psv)) _USB1Interrupt()
{
    USBDeviceTasks();
}
#endif

/***************************************************************************//**
 * @brief Interruption ECAN1.
 * @details Only the Transmit Message, Receive Message Events and Error flags
 *          are processed. You can check for the other events as well.
 *
*******************************************************************************/
void __attribute__((__interrupt__,no_auto_psv)) _C1Interrupt(void)
{
    _C1IF = 0;

    if(C1INTFbits.TBIF == 1)
    {
        /* Transmit done. Set the flag so that
         * the main application loop knows that
         * the message was transmitted */

        C1INTFbits.TBIF = 0;
        //transmitNextECANmsg = 1;
    }
    if(C1INTFbits.RBIF == 1)
    {
        /* Received a packet. Check if the
         * rxBufferIndex is at the boundary
         * and reset to initial condition
         * if needed.

         * You can check the RXFUL flags
          if needed. */

        if(rxECANBufferIndex == (NUM_OF_RX_BUFFERS - 1))
            rxECANBufferIndex = -1;

        C1INTFbits.RBIF = 0;
        C1RXFUL1 = 0;
        receivedECANmsg = 1;
        rxECANBufferIndex ++;
    }
    if(C1INTFbits.ERRIF == 1)
    {
        C1INTFbits.ERRIF = 0;
    }
}