/**********************************************************************
* © 2012 Microchip Technology Inc.
*
* SOFTWARE LICENSE AGREEMENT:
* Microchip Technology Incorporated ("Microchip") retains all ownership and 
* intellectual property rights in the code accompanying this message and in all 
* derivatives hereto.  You may use this code, and any derivatives created by 
* any person or entity by or on your behalf, exclusively with Microchip's
* proprietary products.  Your acceptance and/or use of this code constitutes 
* agreement to the terms and conditions of this notice.
*
* CODE ACCOMPANYING THIS MESSAGE IS SUPPLIED BY MICROCHIP "AS IS".  NO 
* WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED 
* TO, IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A 
* PARTICULAR PURPOSE APPLY TO THIS CODE, ITS INTERACTION WITH MICROCHIP'S 
* PRODUCTS, COMBINATION WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. 
*
* YOU ACKNOWLEDGE AND AGREE THAT, IN NO EVENT, SHALL MICROCHIP BE LIABLE, WHETHER 
* IN CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE OR BREACH OF STATUTORY DUTY), 
* STRICT LIABILITY, INDEMNITY, CONTRIBUTION, OR OTHERWISE, FOR ANY INDIRECT, SPECIAL, 
* PUNITIVE, EXEMPLARY, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, FOR COST OR EXPENSE OF 
* ANY KIND WHATSOEVER RELATED TO THE CODE, HOWSOEVER CAUSED, EVEN IF MICROCHIP HAS BEEN 
* ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.  TO THE FULLEST EXTENT 
* ALLOWABLE BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO 
* THIS CODE, SHALL NOT EXCEED THE PRICE YOU PAID DIRECTLY TO MICROCHIP SPECIFICALLY TO 
* HAVE THIS CODE DEVELOPED.
*
* You agree that you are solely responsible for testing the code and 
* determining its suitability.  Microchip has no obligation to modify, test, 
* certify, or support the code.
*
******************************************************************************/

/******************************************************************************/
/******************************************************************************/
/*                                                                            */
/*                    include files                                           */
/*                                                                            */
/******************************************************************************/
/******************************************************************************/

#include "general.h"
#include "periph.h"

void DDelay(void);
/******************************************************************************/
/* Configuration bits                                                         */
/******************************************************************************/
_FPOR(ALTI2C1_OFF & ALTI2C2_OFF);
_FWDT(PLLKEN_ON & FWDTEN_OFF);
_FOSCSEL(FNOSC_FRC & IESO_OFF & PWMLOCK_OFF);
_FGS(GWRP_OFF & GCP_OFF);

_FICD(ICS_PGD2 & JTAGEN_OFF);	// PGD3 for 28pin 	PGD2 for 44pin
_FOSC(FCKSM_CSECMD & POSCMD_XT);		//XT W/PLL
//_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_NONE); // FRC W/PLL

/********************Setting Configuration Bits End********************************/



/******************************************************************************/
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/******************************************************************************/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/******************************************************************************/
/* Function name: InitPeriph                                                  */
/* Function parameters: None                                                  */
/* Function return: None                                                      */
/* Description: Init the peripherals: PLL, ADC, PWM & GPIO                    */
/******************************************************************************/
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void InitPeriph(void)
{
  //The settings below set up the oscillator and PLL for x MIPS as
    //follows:
    //                  Fin  * M
    // Fosc       =     ---------
    //                   N2 * N1   
    //
    // Fin   	  = 7.37 MHz
    // Fosc       = x MHz
    // Fcy        = Fosc/2 = 

	/****************** Clock definitions *********************************/
 
/*
   // 70 MIPS (70.015 Mhz) (i.e (7.37 * (76/4))/2)

    PLLFBD =  74; 			    // M = 76    74
    CLKDIVbits.PLLPOST = 0; 	// N2 = (2 x (PLLPOST + 1)) = 2   0
    CLKDIVbits.PLLPRE = 0;		// N1 = (PLLPRE + 2) = 2        0
*/
    // 70 MIPS (70 Mhz) (i.e (8 * (70/4))/2)

	PLLFBD = 68; // dPLL derived in UserParms.h
	CLKDIVbits.PLLPOST = 0;		// N1=2
	CLKDIVbits.PLLPRE = 0;		// N2=2
    
// Initiate Clock Switch to Primary Oscillator with PLL (NOSC=0b011)

    __builtin_write_OSCCONH(0x03);
    __builtin_write_OSCCONL(0x01);
    while(OSCCONbits.COSC != 0x03);
    
    while(OSCCONbits.LOCK != 1);	

 /*   
    // Initiate Clock Switch to FRC with PLL (NOSC=0b001)

    __builtin_write_OSCCONH(0x01);
    __builtin_write_OSCCONL(0x01);


    while(OSCCONbits.COSC != 0b001);
    
    while(OSCCONbits.LOCK != 1);

 */

    // Turn saturation on to insure that overflows will be handled smoothly.
    CORCONbits.SATA  = 0;

	// ============= Port A ==============
	LATA  = 0;
	TRISA = 0x1F93;			// Reset value (all inputs)
    ANSELA = 0;
    ANSELAbits.ANSA1 = 1;	// RA1 (AN1) Opamp input C2IN1+ used for Ia
	ANSELAbits.ANSA0 = 1;	// RA0 (AN0) Opamp output OA2OUT used for Ia
	
	// ============= Port B ==============
    LATB  = 0x0000;
    TRISB = 0x03FF;			// RB10~15 outputs for PWM, rest are inputs
    ANSELB = 0;
    ANSELBbits.ANSB0 = 1;	// RB0 (AN2) Opamp input C2IN1- used for Ia
    ANSELBbits.ANSB1 = 1;	// RB1 (AN3) Opamp output OA1OUT used for Isum
    ANSELBbits.ANSB2 = 1;	// RB2 (AN4) Opamp input C1IN1+ used for Isum
    ANSELBbits.ANSB3 = 1;	// RB3 (AN5) Opamp input C1IN1- used for Isum
    
	// ============= Port C ==============
	LATC  = 0x0000;
	TRISC = 0xBFFF;			// Reset value (all inputs)
    ANSELC = 0;
    ANSELCbits.ANSC2 = 1;	// RC2 (AN8) Opamp input C3IN1+ used for Ib
    ANSELCbits.ANSC1 = 1;	// RC1 (AN7) Opamp input C3IN1- used for Ib
    ANSELCbits.ANSC0 = 1;	// RC0 (AN6) Opamp output C3OUT used for Ib
    
	// ============= Port D ==============
    LATD  = 0x0000;
    TRISD = 0x0160;			// Reset value (all inputs)
    TRISDbits.TRISD6 = 0;	// DBG_LED1 output
    TRISDbits.TRISD5 = 0;	// DBG_LED2 output
   
   	// ============= Port E ==============
    LATE  = 0x0000;
    TRISE = 0xF000;			// Reset value (all inputs)
    ANSELE = 0;
    ANSELEbits.ANSE13 = 1;	// Pot (AN13)
	
	// ============= Port F ==============
    LATF  = 0x0000;
    TRISF = 0x0173;			// Reset value (all inputs)
    TRISFbits.TRISF1 = 0;	// Output - UART TX

	// ============= Port G ==============
    LATG  = 0x0000;
    TRISG = 0x03C0;			// Reset value (all inputs)
		
	/************** Code section for the low pin count devices ******/
	/*Assigning the TX and RX pins to ports RP97 & RP53 to the dsPIC*/
	__builtin_write_OSCCONL(OSCCON & (~(1<<6))); // clear bit 6 

    RPINR19bits.U2RXR = 53;		// Make Pin RP53 U2RX
    RPOR7bits.RP97R = 3;	    // Make Pin RP97 U2TX
	
	__builtin_write_OSCCONL(OSCCON | (1<<6)); 	 // Set bit 6 	
	/****************************************************************/

  // Initialise OPAMP/Comparator 
   // OpAmp 1,2,3 for Signal Conditioning Currents & Comparator 4 for Fault Generation

                                // C1IN1+ :IBUS+ ; C1IN1- : IBUS- 
    CM1CON = 0x8C00;			// OpAmp1- OA1OUT is connected to pin,operates as an Op amp,Inverting I/P of Op amp is  C1IN1- pin
                                // C2IN1+ :IA+ ; C2IN1- : IBUS+ 
    CM2CON = 0x8C00;			// OpAmp2- OA2OUT is connected to pin,operates as an Op amp,Inverting I/P of Op amp is  C2IN1- pin
                                // C3IN1+ :IB+ ; C3IN1- : IBUS+ 
    CM3CON = 0x8C00;			// OpAmp3- OA3OUT is connected to pin,operates as an Op amp,Inverting I/P of Op amp is  C3IN1- pin
    
    CM4CON = 0x8011;            // cmp output non inverted
                                // VIN+ input connects to internal CVREFIN voltage
                                // VIN- input connects to CMP1 (source Ibus) 
 
    CVRCON = 0x008F;            // CVREF = (0.1031)*CVR + 0.825, CVR = 15
    CM4FLTR = 0x000F;           // max filtering

   // ============= Motor PWM ======================

    // Center aligned PWM.
    // Note: The PWM period is set to dLoopInTcy/2 but since it counts up and 
    // and then down => the interrupt flag is set to 1 at zero => actual 
    // interrupt period is dLoopInTcy

	PHASE1 = LOOPTIME_TCY;
	PHASE2 = LOOPTIME_TCY;
	PHASE3 = LOOPTIME_TCY;
	PTPER = 2*LOOPTIME_TCY+1;

	PWMCON1 = 0x0204;	        // Enable PWM output pins and configure them as 
	PWMCON2 = 0x0204;	        // complementary mode
	PWMCON3 = 0x0204;

	//I/O pins controlled by PWM
	IOCON1 = 0xC000;
	IOCON2 = 0xC000;
	IOCON3 = 0xC000;

	//set pin outputs
    
	DTR1 = 0x0000;
	DTR2 = 0x0000;
	DTR3 = 0x0000;

	ALTDTR1 = DDEADTIME;        // 700ns of dead time
	ALTDTR2 = DDEADTIME;	    // 700ns of dead time
	ALTDTR3 = DDEADTIME;	    // 700ns of dead time

	FCLCON1 = 0x03;             //Fault disabled
	FCLCON2 = 0x03;             //Fault disabled
	FCLCON3 = 0x03;             //Fault disabled

	PTCON2 = 0x0000;	        // Divide by 1 to generate PWM

    PDC1 = MIN_DUTY;            // Intialising the duty register 
    PDC2 = MIN_DUTY;            // Intialising the duty register
    PDC3 = MIN_DUTY;            // Intialising the duty register
    
	IPC23bits.PWM1IP = 4;	    // PWM Interrupt Priority 4
	IPC23bits.PWM2IP = 4;	    // PWM Interrupt Priority 4
	IPC24bits.PWM3IP = 4;	    // PWM Interrupt Priority 4

	IFS5bits.PWM1IF = 0;	    //clear PWM interrupt flag
	IEC5bits.PWM1IE = 0;	    //disable PWM interrupts

    PTCON = 0x8000;             // Enable PWM for center aligned operation	

    // SEVTCMP: Special Event Compare Count Register 
    // Phase of ADC capture set relative to PWM cycle: 0 offset and counting up
	SEVTCMP = 0;


	// ============= ADC - Measure Current & Pot ======================
    // ADC setup for simultanous sampling on 
    //      CH0=AN13, CH1=CMP1, CH2=CMP2, CH3=CMP3. 
    // Sampling triggered by Timer3 and stored in signed fractional form.
    // Signed fractional (DOUT = sddd dddd dd00 0000)
    AD1CON1bits.FORM = 3;    
	// Timer3 overflow ends sampling and starts conversion
	AD1CON1bits.SSRC = 3;
	AD1CON1bits.SSRCG = 0;
    // Simultaneous Sample Select bit (only applicable when CHPS = 01 or 1x)
    // Samples CH0, CH1, CH2, CH3 simultaneously (when CHPS = 1x)
    // Samples CH0 and CH1 simultaneously (when CHPS = 01)
    AD1CON1bits.SIMSAM = 1;  
    // Sampling begins immediately after last conversion completes. 
    // SAMP bit is auto set.
    AD1CON1bits.ASAM = 1;  


    AD1CON2 = 0;
    // Samples CH0, CH1, CH2, CH3 simultaneously (when CHPS = 1x)
    AD1CON2bits.CHPS = 2;  


    AD1CON3 = 0;
    // A/D Conversion Clock Select bits = 6 * Tcy
    AD1CON3bits.ADCS = 8;  


     /* ADCHS: ADC Input Channel Select Register */
    AD1CHS0 = 0;
    // CH0 is AN13 for POT
    AD1CHS0bits.CH0SA = 13;

   // CH1 positive input is CMP0, CH2 positive input is CMP1, CH3 positive input is CMP2
    AD1CHS123bits.CH123SA = 1;
  
 /* ADCSSL: ADC Input Scan Select Register */
    AD1CSSL = 0;

    // Turn on A/D module
    AD1CON1bits.ADON = 1;

	DDelay();
    //Fault enabled 
    FCLCON1 = 0x005C;           //Fault enabled Fault SRC - Comparator 4 O/P
	FCLCON2 = 0x005C;           //Fault enabled Fault SRC - Comparator 4 O/P
	FCLCON3 = 0x005C;           //Fault enabled Fault SRC - Comparator 4 O/P
	return;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/******************************************************************************/
/* Function name: DDelay                                                      */
/* Function parameters: None                                                  */
/* Function return: None                                                      */
/* Description: Delay Routine											      */
/******************************************************************************/
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void DDelay(void)
{
	long i;
	for (i = 0;i < 100000;i++);
	return;
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/******************************************************************************/
/* Function name: ResetPeriph                                                 */
/* Function parameters: None                                                  */
/* Function return: None                                                      */
/* Description: Reset the peripherals during runtime/reset configurations     */
/******************************************************************************/
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void ResetPeriph(void)
{

    // clear and Enable ADC interrupt 
    IFS0bits.AD1IF = 0; 
    IEC0bits.AD1IE = 1;

    /* Initialise duty regs */ 
    PDC1 = MIN_DUTY;
    PDC2 = MIN_DUTY;
    PDC3 = MIN_DUTY;
    return;

}
