text: /********************************************************************
   Software License Agreement:
  
   The software supplied herewith by Microchip Technology Incorporated
   (the "Company") for its PIC(R) Microcontroller is intended and
   supplied to you, the Company's customer, for use solely and
   exclusively on Microchip PIC Microcontroller products. The
   software is owned by the Company and/or its supplier, and is
   protected under applicable copyright laws. All rights are reserved.
   Any use in violation of the foregoing restrictions may subject the
   user to criminal sanctions under applicable laws, as well as to
   civil liability for the breach of the terms and conditions of this
   license.
  
   THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,
   WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
   TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
   PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
   IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
   CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
   *******************************************************************/
  
  #include "system.h"
  #include "system_config.h"
  #include "usb.h"
  
  /** CONFIGURATION Bits **********************************************/
  #pragma config WDTEN = OFF          //WDT disabled (enabled by SWDTEN bit)
  #pragma config PLLDIV = 3           //Divide by 3 (12 MHz oscillator input)
  #pragma config STVREN = ON          //stack overflow/underflow reset enabled
  #pragma config XINST = OFF          //Extended instruction set disabled
  #pragma config CPUDIV = OSC1        //No CPU system clock divide
  #pragma config CP0 = OFF            //Program memory is not code-protected
  #pragma config OSC = HSPLL          //HS oscillator, PLL enabled, HSPLL used by USB
  #pragma config FCMEN = OFF          //Fail-Safe Clock Monitor disabled
  #pragma config IESO = OFF           //Two-Speed Start-up disabled
  #pragma config WDTPS = 32768        //1:32768
  #pragma config DSWDTOSC = INTOSCREF //DSWDT uses INTOSC/INTRC as clock
  #pragma config RTCOSC = T1OSCREF    //RTCC uses T1OSC/T1CKI as clock
  #pragma config DSBOREN = OFF        //Zero-Power BOR disabled in Deep Sleep
  #pragma config DSWDTEN = OFF        //Disabled
  #pragma config DSWDTPS = 8192       //1:8,192 (8.5 seconds)
  #pragma config IOL1WAY = OFF        //IOLOCK bit can be set and cleared
  #pragma config MSSP7B_EN = MSK7     //7 Bit address masking
  #pragma config WPFP = PAGE_1        //Write Protect Program Flash Page 0
  #pragma config WPEND = PAGE_0       //Start protection at page 0
  #pragma config WPCFG = OFF          //Write/Erase last page protect Disabled
  #pragma config WPDIS = OFF          //WPFP[5:0], WPEND, and WPCFG bits ignored
  #pragma config T1DIG = ON           //Sec Osc clock source may be selected
  #pragma config LPT1OSC = OFF        //high power Timer1 mode
   
  /*********************************************************************
  * Function: void SYSTEM_Initialize( SYSTEM_STATE state )
  *
  * Overview: Initializes the system.
  *
  * PreCondition: None
  *
  * Input:  SYSTEM_STATE - the state to initialize the system into
  *
  * Output: None
  *
  ********************************************************************/
  void SYSTEM_Initialize( SYSTEM_STATE state )
  {
      switch(state)
      {
          case SYSTEM_STATE_USB_START:
               //In this devices family of USB microcontrollers, the PLL will not power up and be enabled
               //by default, even if a PLL enabled oscillator configuration is selected (such as HS+PLL).
               //This allows the device to power up at a lower initial operating frequency, which can be
               //advantageous when powered from a source which is not gauranteed to be adequate for 48MHz
               //operation.  On these devices, user firmware needs to manually set the OSCTUNE<PLLEN> bit to
               //power up the PLL.
               {
                   unsigned int pll_startup_counter = 600;
                   OSCTUNEbits.PLLEN = 1;  //Enable the PLL and wait 2+ms until the PLL locks before enabling USB module
                   while(pll_startup_counter--);
               }
               //Device switches over automatically to PLL output after PLL is locked and ready.
  			 
              LED_Enable(LED_USB_DEVICE_STATE);
              BUTTON_Enable(BUTTON_DEVICE_CDC_BASIC_DEMO);
              break;
              
          case SYSTEM_STATE_USB_SUSPEND: 
              //Should also configure all other I/O pins for lowest power consumption.
              //Typically this is done by driving unused I/O pins as outputs and driving them high or low.
              //In this example, this is not done however, in case the user is expecting the I/O pins
              //to remain tri-state and has hooked something up to them.
              //Leaving the I/O pins floating will waste power and should not be done in a
              //real application.
  
              //Sleep on sleep, 125kHz selected as microcontroller clock source
              break;
              
          case SYSTEM_STATE_USB_RESUME:
              OSCCON = 0x70;		//Primary clock source selected.
              
              //Adding a software start up delay will ensure
              //that the primary oscillator and PLL are running before executing any other
              //code.  If the PLL isn't being used, (ex: primary osc = 48MHz externally applied EC)
              //then this code adds a small unnecessary delay, but it is harmless to execute anyway.
              {
                  unsigned int pll_startup_counter = 800;                      //Long delay at 31kHz, but ~0.8ms at 48MHz
                  while(pll_startup_counter--);			//Clock will switch over while executing this delay loop
              }
              break;
      }
  }
  
  			
  			
  #if defined(__XC8)
  void interrupt SYS_InterruptHigh(void)
  {
      #if defined(USB_INTERRUPT)
          USBDeviceTasks();
      #endif
  }
  #else
          void YourHighPriorityISRCode();
          void YourLowPriorityISRCode();
          
  	//On PIC18 devices, addresses 0x00, 0x08, and 0x18 are used for
  	//the reset, high priority interrupt, and low priority interrupt
  	//vectors.  However, the current Microchip USB bootloader
  	//examples are intended to occupy addresses 0x00-0x7FF or
  	//0x00-0xFFF depending on which bootloader is used.  Therefore,
  	//the bootloader code remaps these vectors to new locations
  	//as indicated below.  This remapping is only necessary if you
  	//wish to program the hex file generated from this project with
  	//the USB bootloader.  If no bootloader is used, edit the
  	//usb_config.h file and comment out the following defines:
  	//#define PROGRAMMABLE_WITH_USB_HID_BOOTLOADER
  	//#define PROGRAMMABLE_WITH_USB_LEGACY_CUSTOM_CLASS_BOOTLOADER
  
  	#if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)
  		#define REMAPPED_RESET_VECTOR_ADDRESS			0x1000
  		#define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS	0x1008
  		#define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS	0x1018
  	#elif defined(PROGRAMMABLE_WITH_USB_MCHPUSB_BOOTLOADER)
  		#define REMAPPED_RESET_VECTOR_ADDRESS			0x800
  		#define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS	0x808
  		#define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS	0x818
  	#else
  		#define REMAPPED_RESET_VECTOR_ADDRESS			0x00
  		#define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS	0x08
  		#define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS	0x18
  	#endif
  
  	#if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)||defined(PROGRAMMABLE_WITH_USB_MCHPUSB_BOOTLOADER)
  	extern void _startup (void);        // See c018i.c in your C18 compiler dir
  	#pragma code REMAPPED_RESET_VECTOR = REMAPPED_RESET_VECTOR_ADDRESS
  	void _reset (void)
  	{
  	    _asm goto _startup _endasm
  	}
  	#endif
  
          #pragma code REMAPPED_HIGH_INTERRUPT_VECTOR = REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS
  	void Remapped_High_ISR (void)
  	{
  	     _asm goto YourHighPriorityISRCode _endasm
  	}
  	#pragma code REMAPPED_LOW_INTERRUPT_VECTOR = REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS
  	void Remapped_Low_ISR (void)
  	{
  	     _asm goto YourLowPriorityISRCode _endasm
  	}
  
  	#if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)||defined(PROGRAMMABLE_WITH_USB_MCHPUSB_BOOTLOADER)
  	//Note: If this project is built while one of the bootloaders has
  	//been defined, but then the output hex file is not programmed with
  	//the bootloader, addresses 0x08 and 0x18 would end up programmed with 0xFFFF.
  	//As a result, if an actual interrupt was enabled and occured, the PC would jump
  	//to 0x08 (or 0x18) and would begin executing "0xFFFF" (unprogrammed space).  This
  	//executes as nop instructions, but the PC would eventually reach the REMAPPED_RESET_VECTOR_ADDRESS
  	//(0x1000 or 0x800, depending upon bootloader), and would execute the "goto _startup".  This
  	//would effective reset the application.
  
  	//To fix this situation, we should always deliberately place a
  	//"goto REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS" at address 0x08, and a
  	//"goto REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS" at address 0x18.  When the output
  	//hex file of this project is programmed with the bootloader, these sections do not
  	//get bootloaded (as they overlap the bootloader space).  If the output hex file is not
  	//programmed using the bootloader, then the below goto instructions do get programmed,
  	//and the hex file still works like normal.  The below section is only required to fix this
  	//scenario.
  	#pragma code HIGH_INTERRUPT_VECTOR = 0x08
  	void High_ISR (void)
  	{
  	     _asm goto REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS _endasm
  	}
  	#pragma code LOW_INTERRUPT_VECTOR = 0x18
  	void Low_ISR (void)
  	{
  	     _asm goto REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS _endasm
  	}
  	#endif	//end of "#if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)||defined(PROGRAMMABLE_WITH_USB_LEGACY_CUSTOM_CLASS_BOOTLOADER)"
  
  	#pragma code
  
  
  	//These are your actual interrupt handling routines.
  	#pragma interrupt YourHighPriorityISRCode
  	void YourHighPriorityISRCode()
  	{
  		//Check which interrupt flag caused the interrupt.
  		//Service the interrupt
  		//Clear the interrupt flag
  		//Etc.
          #if defined(USB_INTERRUPT)
  	        USBDeviceTasks();
          #endif
  
  	}	//This return will be a "retfie fast", since this is in a #pragma interrupt section
  	#pragma interruptlow YourLowPriorityISRCode
  	void YourLowPriorityISRCode()
  	{
  		//Check which interrupt flag caused the interrupt.
  		//Service the interrupt
  		//Clear the interrupt flag
  		//Etc.
  
  	}	//This return will be a "retfie", since this is in a #pragma interruptlow section
  #endif     
  