#define __ONLY_INIT_SP

#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */
#include "Bootloader_Drv.h" 
#include "Bootloader_Config.h"
#include "Bootloader_hid.h"
#include "Bootloader_tasks.h"


const byte NVOPT_INIT  @0x0000FFBF = 0x00;    // vector redirect, flash unsecure
const byte NVPROT_INIT @0x0000FFBD = 0xF6;    // 0xFC00-0xFFFF are protected 

const byte BackDoorKey[] @0xFFB0 = {0x40,0x60,0x7f,0xA5,0x55,0x44,0x38,0x99};

extern void _Startup(void);
extern interrupt void I2C_ISR(void);


unsigned char Flash_Program(unsigned int dst_addr, unsigned int data_addr, unsigned char length);
unsigned char Flash_Verify(unsigned int dst_addr, unsigned int data_addr, unsigned char length); 
unsigned char Flash_Erase(unsigned int addr);
void FLASHPGM_Copy(void)  ;


/*Local function definition*/ 
void Init_Sys(void);
extern void USB_Bootloader(void);


 
#define BOOTLOADER_START_ADDR 0xF800
 
void main(void) 
{

	PTGPE = 0x01;		                //Pull-up enable
  asm lda $FF;
  asm Wait_Pullup:
  asm dbnza Wait_Pullup;

  if(PTGD_PTGD0){
		asm lda	BOOTLOADER_START_ADDR-2;
		asm cbeqa	#$FF,USB_ICP; //usb ICP if new reset vector blank
		asm lda		(BOOTLOADER_START_ADDR-1);
		asm psha;
		asm lda		(BOOTLOADER_START_ADDR-2);
		asm psha;
    asm	rts;						//jmp to application program
  }
     
  else{
    asm USB_ICP:
    SOPT1 = 0x20;                   // disable COP only if bootloader mod is requested
  }
 
 
  DisableInterrupts;
  Init_Sys();                         /*initial the system*/
  FLASHPGM_Copy();
  FCDIV=0x4E;               // PRDIV8=1; DIV[5:0]=14, flash clock should be 150-200kHz
                            // bus clock=24M, flash clock=fbus/8/(DIV[5:0]+1) 
  
  Initialize_USBModule();  
   for(;;) 
   {
    Check_USBBus_Status();             /* use polling method*/
    USB_Bootloader();
   } 
}

 

/*****************************************************************************
 * Init_Sys: Initialize the system
 * Input: 	 None
 * Output:   None
 *
 ****************************************************************************/
void Init_Sys(void)
{
/*****************************************************************************
 * Function     MCU_Init
 * Overview:    Initialization of the MCU.
 *              It will configure the JM60 to disable STOP and COP Modules.
 *              It also set the MCG configuration and bus clock frequency.
 *
 * Input  : None
 *
 * Return : None
 ****************************************************************************/
  //Mcu_Init()

	//SOPT1 = 0xF3; 			  /*Enable the COP,  and enable the MCU stop mode*/
			                  /*  
                         *  0b00000010
                         *    ||||||||__ bit0:   
                         *    |||||||___ bit1: 
                         *    ||||||____ bit2: 
                         *    |||||_____ bit3: 
                         *    ||||______ bit4: 
                         *    |||_______ bit5: STOP Mode enable
                         *    ||________ bit6: COP configuration
                         *    |_________ bit7: COP configuration
                         */
	SOPT2 = 	0x00;
			                  /*  
                         *  0b00000010
                         *    ||||||||__ bit0:   ACIC  		ACMP output connect to TPM channel 0
                         *    |||||||___ bit1:   SPI2FE		SPI2 input filter enable
                         *    ||||||____ bit2:   SPI1FE		SPI1 input filter enable
                         *    |||||_____ bit3:   
                         *    ||||______ bit4: 
                         *    |||_______ bit5:   COPW COP Window
                         *    ||________ bit6:   COPCLKS	COP wactchdog clock select
                         *    |_________ bit7:   COPCLKS	COP wactchdog clock select
                         */
	SPMSC1 = 0x40;
			                  /*  
                         *  0b01000010
                         *    ||||||||__ bit0:   BGBE  		Bandgap Buffer enable
                         *    |||||||___ bit1:   0			
                         *    ||||||____ bit2:   LVDE		Low_Voltage detect enable
                         *    |||||_____ bit3:   LVDSE		Low_Voltage Detect in stop mode
                         *    ||||______ bit4:   LVDRE		Low_Voltage Detect Reset Enable
                         *    |||_______ bit5:   LVWIE		Low_Voltage Warning interrupt Enable
                         *    ||________ bit6:   LVWACK	Low-Voltage Warning Acknowledge
                         *    |_________ bit7:   LVWF		Low_Voltage Warning Flag
                         */
  SPMSC2 = 0x00;
		                  	/*  
                         *  0b01000010
                         *    ||||||||__ bit0:   PPDC  		Partlal Power Down Control
                         *    |||||||___ bit1:   0			
                         *    ||||||____ bit2:   PPDACK	Partlal Power Down Acknowledge
                         *    |||||_____ bit3:   PPDF		partlal Power Down Flag
                         *    ||||______ bit4:   LVWV		Low-Voltage Warning Voltage Select
                         *    |||_______ bit5:   LVDV		Low_Voltage Detect Voltage select
                         *    ||________ bit6:   0
                         *    |_________ bit7:   0
                         */
  

  // MCG_Init_12MHzXtal()

	// the MCG is default set to FEI mode, it should be change to FBE mode
	MCGC2 = 0x36;
			/*  
                         *  0b01110100
                         *    ||||||||__ bit0:   EREFSTEN	Exernal reference stop enable
                         *    |||||||___ bit1:   ERCLKEN	External reference enable
                         *    ||||||____ bit2:   EREFS		External reference select
                         *    |||||_____ bit3:   LP			Low power select
                         *    ||||______ bit4:   HGO		High gain oscillator select
                         *    |||_______ bit5:   Range		Frequency range select
                         *    ||________ bit6:   BDIV		Bus frequency divider	
                         *    |_________ bit7:   BDIV	
                         */
                         
	while(!(MCGSC & 0x02));		//wait for the OSC stable
			/*  
                         *  0b00000010
                         *    ||||||||__ bit0:   FTRIM		MCG fine trim
                         *    |||||||___ bit1:   OSCINIT	OSC initialization
                         *    ||||||____ bit2:   CLKST		Clock Mode status
                         *    |||||_____ bit3:   CLKST
                         *    ||||______ bit4:   IREFST		Internal reference status
                         *    |||_______ bit5:   PLLST		PLL select status
                         *    ||________ bit6:   LOCK		Lock Status
                         *    |_________ bit7:   LOLS		Loss of lock status
                         */
                         
	MCGC1 = 0x9B;
	MCGC1 = 0x98;

			/*  
                         *  0b10110000
                         *    ||||||||__ bit0:   IREFSTEN	Internal reference stop enable
                         *    |||||||___ bit1:   IRCLKEN	Internal reference clock enable		
                         *    ||||||____ bit2:   IREFS		Internal reference select
                         *    |||||_____ bit3:   RDIV		Reference divider
                         *    ||||______ bit4:   RDIV
                         *    |||_______ bit5:   RDIv
                         *    ||________ bit6:   CLKS		Clock source select
                         *    |_________ bit7:   CLKS
                         */
	
	while((MCGSC & 0x1C ) != 0x08);		// check the external reference clock is selected or not
	
	// Switch to PBE mode from FBE
	MCGC3 = 0x48;
			/*  
                         *  0b01000110
                         *    ||||||||__ bit0:   VDIV		VCO divider
                         *    |||||||___ bit1:   VDIV
                         *    ||||||____ bit2:   VDIV
                         *    |||||_____ bit3:   VDIV
                         *    ||||______ bit4:   0
                         *    |||_______ bit5:   CME		Clock Monitor Enable
                         *    ||________ bit6:   PLLS 		PLL select
                         *    |_________ bit7:   LOLIE		Loss of lock interrupt enable
                         */
	while ((MCGSC & 0x48) != 0x48);		//wait for the PLL is locked & 

	//Switch to PEE mode from PBE mode
	MCGC1 &= 0x3F;
	while((MCGSC & 0x6C) != 0x6C);
}

/*
void (* volatile const _UserEntry[])()@0xFBBC={
  0x9DCC,             // asm NOP(9D), asm JMP(CC)
  _Startup
};
*/



  
// redirect vector 0xFFC0-0xFFFD to 0xFBC0-0xFBFD


void _Entry(void) {

  SOPT1 = 0x20;                   // disable COP
//  asm JMP _Startup;
  INIT_SP_FROM_STARTUP_DESC();
 // Init();
  asm JMP main;  
};











