/****************************************************************************/
/* Copyright 2015 MBARI                                                     */
/****************************************************************************/
/* Summary  : PIC Utility, Device Configuration, and Peripheral Module Disable*/
/* Filename : picConfig.c                                                   */
/* Author   : Robert Herlien (rah)                                          */
/* Project  : OASIS Mooring Replacement (OASIS5)                            */
/* Revision: 1.0                                                            */
/* Created  : 07/16/2015                                                    */
/*                                                                          */
/* MBARI provides this documentation and code "as is", with no warranty,    */
/* express or implied, of its quality or consistency. It is provided without*/
/* support and without obligation on the part of the Monterey Bay Aquarium  */
/* Research Institute to assist in its use, correction, modification, or    */
/* enhancement. This information should not be published or distributed to  */
/* third parties without specific written permission from MBARI.            */
/*                                                                          */
/****************************************************************************/
/* Modification History:                                                    */
/* 16jul2015 rah - created                                                  */
/****************************************************************************/

#include <xc.h>
#include <picConfig.h>

#include <FreeRTOS.h>
#include <FreeRTOSConfig.h>
#include <task.h>


/****************************************************************************/
/*      PIC32 Device Configuration Bits                                     */
/****************************************************************************/

/*** DEVCFG0 ***/
#pragma config DEBUG =      OFF
#pragma config JTAGEN =     OFF
#pragma config ICESEL =     ICS_PGx1
#pragma config PWP =        OFF
#pragma config BWP =        OFF
#pragma config CP =         OFF

/*** DEVCFG1 ***/
#pragma config FNOSC =      PRI
#pragma config FSOSCEN =    OFF
#pragma config IESO =       OFF
#pragma config POSCMOD =    HS
#pragma config OSCIOFNC =   OFF
#pragma config FPBDIV =     DIV_2
#pragma config FCKSM =      CSDCMD
#pragma config WDTPS =      PS1048576		// Value for production
//#pragma config WDTPS =      PS65536		// Value for testing
#pragma config FWDTEN =     OFF
#pragma config WINDIS =     OFF
#pragma config FWDTWINSZ =  WINSZ_25

/*** DEVCFG2 ***/
#pragma config FPLLIDIV =   DIV_6
#pragma config FPLLMUL =    MUL_24
#pragma config FPLLODIV =   DIV_256
#pragma config UPLLIDIV =   DIV_6
#pragma config UPLLEN =     OFF

/*** DEVCFG3 ***/
#pragma config USERID =     0xffff
#pragma config FSRSSEL =    PRIORITY_7
#pragma config PMDL1WAY =   OFF
#pragma config IOL1WAY =    OFF
#pragma config FUSBIDIO =   OFF
#pragma config FVBUSONIO =  OFF


/* Following two functions copied from PIC32 PLib		*/

/*********************************************************************
 * Function:        INTDisableInterrupts()
 * PreCondition:    None
 * Input:           None
 * Output:          None
 * Side Effects:    Interrupts are disabled
 * Overview:        Interrupts are disabled by clearing the IE bit
 *                  in the status register
 ********************************************************************/
unsigned int __attribute__((nomips16)) INTDisableInterrupts(void)
{
    unsigned int status = 0;

    asm volatile("di    %0" : "=r"(status));

    return status;
}

/*********************************************************************
 * Function:        INTEnableInterrupts()
 * PreCondition:    None
 * Input:           None
 * Output:          None
 * Side Effects:    Interrupts are enabled
 * Overview:        Interrupts are enabled by setting the IE bit
 *                  in the status register
 ********************************************************************/
unsigned int __attribute__((nomips16))  INTEnableInterrupts(void)
{
    unsigned int status = 0;

    asm volatile("ei    %0" : "=r"(status));

    return status;
}


/************************************************************************/
/* Function    : picResetType											*/
/* Purpose     : Return and reset RCON									*/
/* Inputs      : None                                                   */
/* Outputs     : Value of RCON											*/
/************************************************************************/
unsigned int picResetType(void)
{
	unsigned int rcon = RCON & 0xffff;
	RCON = 0;
	return(rcon);
}


/************************************************************************/
/* Function    : picUnlock												*/
/* Purpose     : Unlock OSCCON											*/
/* Inputs      : None                                                   */
/* Outputs     : None                                                   */
/************************************************************************/
void picUnlock(void)
{
	int	ieSave = INTDisableInterrupts();

    SYSKEY = 0x0;
    SYSKEY = 0xAA996655;
    SYSKEY = 0x556699AA;

	if (ieSave)
		INTEnableInterrupts();
}


/************************************************************************/
/* Function    : picSoftReset											*/
/* Purpose     : Assert Software Reset									*/
/* Inputs      : None                                                   */
/* Outputs     : None                                                   */
/************************************************************************/
void picSoftReset(void)
{
#ifdef __DEBUG
	__builtin_software_breakpoint();
#else
	volatile int *p = &RSWRST;

	IEC0 = 0;							/* Turn off all interrupt sources*/
	IEC1 = 0;
	IEC2 = 0;

	picUnlock();						/* Unlock reset register		*/
	RSWRSTSET = _RSWRST_SWRST_MASK;		/* Enable reset					*/
	*p;									/* This read actually performs reset*/

	while(1)							/* Wait while CPU resets		*/
		;
#endif
}


/************************************************************************/
/* Function    : picPeriphInit()                                        */
/* Purpose     : Disable Unused Peripherals                             */
/* Inputs      : None                                                   */
/* Outputs     : None                                                   */
/************************************************************************/
void picPeriphInit(void)
{
    /********************** Disable Unused Peripherals **********************/
    PMD1CLR = _PMD1_AD1MD_MASK;     /* A/D module on                        */
    PMD1SET = _PMD1_CTMUMD_MASK;    /* Charge Time Measurement Unit off     */
    PMD1SET = _PMD1_CVRMD_MASK;     /* Comparator Voltage Reference off     */
    PMD2SET = _PMD2_CMP1MD_MASK;    /* Comparators off                      */
    PMD2SET = _PMD2_CMP2MD_MASK;
    PMD3SET = _PMD3_IC1MD_MASK;     /* Input Captures off                   */
    PMD3SET = _PMD3_IC2MD_MASK;
    PMD3SET = _PMD3_IC3MD_MASK;
    PMD3SET = _PMD3_IC4MD_MASK;
    PMD3SET = _PMD3_IC5MD_MASK;
    PMD3SET = _PMD3_OC1MD_MASK;     /* Output Compares off                  */
    PMD3SET = _PMD3_OC2MD_MASK;
    PMD3SET = _PMD3_OC3MD_MASK;
    PMD3SET = _PMD3_OC4MD_MASK;
    PMD3SET = _PMD3_OC5MD_MASK;
    PMD4CLR = _PMD4_T1MD_MASK;      /* Timer 1-3 on                         */
    PMD4CLR = _PMD4_T2MD_MASK;
    PMD4CLR = _PMD4_T3MD_MASK;
    PMD4SET = _PMD4_T4MD_MASK;      /* Timers 4-5 off                       */
    PMD4SET = _PMD4_T5MD_MASK;
    PMD5CLR = _PMD5_U1MD_MASK;      /* UARTS on                             */
    PMD5CLR = _PMD5_U2MD_MASK;
    PMD5CLR = _PMD5_U3MD_MASK;
    PMD5CLR = _PMD5_U4MD_MASK;
    PMD5CLR = _PMD5_U5MD_MASK;
    PMD5CLR = _PMD5_SPI1MD_MASK;    /* SPI1 on                              */
    PMD5CLR = _PMD5_SPI2MD_MASK;    /* SPI2 on                              */
    PMD5CLR = _PMD5_I2C1MD_MASK;    /* I2C bus 1 on                         */
    PMD5SET = _PMD5_I2C2MD_MASK;    /* I2C bus 2 off                        */
    PMD5SET = _PMD5_USBMD_MASK;     /* USB off                              */
    PMD6SET = _PMD6_RTCCMD_MASK;    /* RTC off                              */
    PMD6SET = _PMD6_REFOMD_MASK;    /* Reference clock output off           */
    PMD6SET = _PMD6_PMPMD_MASK;     /* Parallel Master Port off             */

}


/************************************************************************/
/* FreeRTOS Hook Functions that should not be needed because they're	*/
/* not enabled in FreeRTOSConfig.h.  Included here just in case somebody*/
/* mistakenly enables the functions										*/
/************************************************************************/
void vApplicationIdleHook(void)
{
}

void vApplicationTickHook(void)
{
}


/************************************************************************/
/* FreeRTOS Support Functions required iff configSUPPORT_STATIC_ALLOCATION*/
/* is set to 1 in FreeRTOSConfig.h.  They are called once from			*/
/* vTaskStartScheduler().												*/
/************************************************************************/

#if( configSUPPORT_STATIC_ALLOCATION == 1 )
/* Added 14jun2016, rah, to support FreeRTOS v9.0.0	*/

#define IDLE_STACK_SIZE	configMINIMAL_STACK_SIZE

StaticTask_t	idleTCB, timerTCB;
StackType_t		idleStack[IDLE_STACK_SIZE];
StackType_t		timerStack[configTIMER_TASK_STACK_DEPTH];

/*-----------------------------------------------------------*/

void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
								   StackType_t **ppxIdleTaskStackBuffer,
								   uint32_t *pulIdleTaskStackSize)
{
	*ppxIdleTaskTCBBuffer = &idleTCB;
	*ppxIdleTaskStackBuffer = idleStack;
	*pulIdleTaskStackSize = IDLE_STACK_SIZE;
}

/*-----------------------------------------------------------*/

void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
									StackType_t **ppxTimerTaskStackBuffer,
									uint32_t *pulTimerTaskStackSize)
{
	*ppxTimerTaskTCBBuffer = &timerTCB;
	*ppxTimerTaskStackBuffer = timerStack;
	*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}

#endif

