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



 
//const unsigned char boot@0x040A = 0x0000; //For MCF51 ONLY: bypass checksum /bootloader
// #define storedTRIM *((char*)0x03FF )  

 /* uncommented following three lines of code for S08MM128 device */
const unsigned char boot@0xFFBA = 0x00; //bypass checksum 
#define storedFTRIM *((char*)0xFFAE )
#define storedTRIM *((char*)0xFFAF )



#define DCO_MUL_512   0
#define DCO_MUL_1024   1
#define DCO_MUL_1536   2 

#define DCO_MUL_608    0x10
#define DCO_MUL_1216   0x11
#define DCO_MUL_1824   0x12

#define  MCGC2_BDIV_1 0 
#define MCGC2_BDIV_2 1
#define MCGC2_BDIV_4 2 
#define MCGC2_BDIV_8 3 

word ADC_result[8];  //16-bit
byte tempitem[8] ; //used to inspect all 8 ADC channel COCOn flags 
word ADC_result[8];  //16-bit
byte ADC_Flag = 0x00;
byte ADC_COCO_FLAGS = 0 ;
byte index = 0 ;
              
// Declare all functions 
void Bus20MHZ_FEI (void){
// fINT trimed to   39062.5  Hz 
MCGC2 = 0x00;
MCGTRM = storedTRIM ;
MCGC4 =  DCO_MUL_1024 ; 
MCGC2_BDIV = MCGC2_BDIV_1;
MCGC4_DRST_DRS =1; 
while (MCGSC_CLKST != MCGC1_CLKS ){}
}


void SetBus24MHz_FEI(void)
{
   MCGTRM = storedTRIM ; // fINT trimed to   31250  Hz 
   MCGC1 =0x04; //reset default; FEI mode
   MCGC2 = 0x00; //BDIV = 1. After reset typical BUS = fMCGOUT/4 = 16 MHz/4  = 4MHz
   MCGC3 = 0x01; //reset default value
   MCGC4 = 0x02; // Set FLL  = 1536 x 31.25Khz internal  = 48MHz
   while(MCGSC_CLKST !=  MCGC1_CLKS ) {} // wait till FEI is enaged
   while(! MCGSC_LOCK ){} //Ensure FLL is locked before proceed to next program
} //end of SetBus24MHz_FEI

void SetBus4MHz_FEI(void)
{
   MCGTRM = storedTRIM ; // fINT trimed to   31250  Hz 
   MCGC1 =0x04; //reset default; FEI mode
   MCGC2 = 0x40; //BDIV = 1. After reset typical BUS = fMCGOUT/4 = 16 MHz/4  = 4MHz
   MCGC3 = 0x01; //reset default value
   MCGC4 = 0x00; // Set FLL  = 512 x 31.25Khz internal  = 16MHz , bus = (16/2) /2 = 4MHz
   while(MCGSC_CLKST !=  MCGC1_CLKS ) {} // wait till FEI is enaged
   while(! MCGSC_LOCK ){} //Ensure FLL is locked before proceed to next program
} //end of SetBus4MHz_FEI 
   
void Vref_Enable(void)  {
VREFSC = 0x82;  //Tight Regulation 
}

void ADC_Cal(void)
{

  volatile unsigned short cal_var =0;

  ADCSC2_ADTRG = 0;           /* Enable Software Conversion Trigger for Calibration Process */
  ADCSC3_CAL = 1 ; 
  while (ADCSC1A_COCOA == 0)
  	{
  	/* Wait for conversion to complete */
  	}	

  if (ADCSC3_CALF == 1)     /* Check for Calibration fail error */
    {
      while(1){} // Trap in loop forever if calibration fail
    }

  /* Calculate plus-side calibration as per 21.4.7 */
  cal_var = 0x00;

  cal_var = (ADCCLP0); 
  cal_var += (ADCCLP1);
  cal_var += (ADCCLP2);
  cal_var += (ADCCLP3);
  cal_var += (ADCCLP4);
  cal_var += (ADCCLPS);

  cal_var =  cal_var/2;
  
  cal_var |= 0x8000; // Set MSB

  ADCPG = cal_var;

  /* Calculate minus-side calibration as per 21.4.7 */
  cal_var = 0x00;

  cal_var = (ADCCLM0); 
  cal_var += (ADCCLM1);
  cal_var += (ADCCLM2);
  cal_var += (ADCCLM3);
  cal_var += (ADCCLM4);
  cal_var += (ADCCLMS);

  cal_var = cal_var/2;

  cal_var |= 0x8000; // Set MSB

  ADCMG = cal_var;

  /* Clear CAL bit */
  ADCSC3_CAL = 0;


}  
void Adc_Enable(void) {
ADCCFG1 = 0x1F;          // High speed, /1 long sample, 16 bit, async clock
//ADCCFG1 = 0x1C;     // High speed, /1 long sample, 16 bit, bus clock
ADCSC3 = 0x87;           // Calibration, one conversion. with HW averging , 32 samples
}
 

// Declare Frequency measurment related functions

// External frequency measurment method (Fbus on pin 63  PTD4 100LQFP) 
void TPM1C2_PWM(word MOD) {                //ffff9804  =0x01
    // output at pin 63 (PTD4 / TPM1CH2) on 100 LQFP 
    // output at pin 52/PTD4 on 80 LQFP 
    TPM1MODH = (byte) (MOD>>8);   // set period 
    TPM1MODL = (byte) MOD-1;
    TPM1C2SC = 0x24;   // set channel 2 for PWM
    TPM1C2VH = (byte) (MOD>>9);   // set duty cycle to 50%
    TPM1C2VL = (byte) (MOD>>1);
    TPM1SC = 0x08;   // select bus clock and start timer
 }//end of TPM1C2_PWM 

// Internal frequency measurment method ( in debug)
void TPM_counter (void) {
 //MCGT = 0x10;
 MCGC4 = 0x02;
 MCGC1 = 0x06;
 MCGC2 = 0xC0;
 //SIMCSS = 0x20;
 SIMCO  = 0x03;
/*  int i     ; 
 for(i=0;i<16000000 ; i++) {
      asm (Nop); 
      }        */
 TPM1SC = 0x08; 
 TPM1CNTH = 0x00; // read H
 TPM1CNTL = 0x00; // read L 
 
 //TPM1SC = 0x08;
 
}
 


void sysInit(void)
{
      
      Vref_Enable();
      Adc_Enable ();   
      

}
void Assign_ADC_CHN_Interrupt (byte adc_chan, byte ISR_enable) {

if (ISR_enable){
  ADCSC1A = (adc_chan | ADCSC1A_AIENA_MASK);		// enable interrupt
  ADCSC1B = (adc_chan | ADCSC1B_AIENB_MASK);		// enable interrupt
  ADCSC1C = (adc_chan | ADCSC1C_AIENC_MASK);		// enable interrupt
  ADCSC1D = (adc_chan | ADCSC1D_AIEND_MASK);		// enable interrupt
  ADCSC1E = (adc_chan | ADCSC1E_AIENE_MASK);		// enable interrupt
  ADCSC1F=  (adc_chan | ADCSC1F_AIENF_MASK);		// enable interrupt
  ADCSC1G = (adc_chan | ADCSC1G_AIENG_MASK);		// enable interrupt
  ADCSC1H = (adc_chan | ADCSC1H_AIENH_MASK);		// enable interrupt
} else{
  
  // No interrupt, with polling the COCO flag
  ADCSC1A_ADCHA = adc_chan ;		
  ADCSC1B_ADCHB = adc_chan ;		
  ADCSC1C_ADCHC = adc_chan ;		
  ADCSC1D_ADCHD = adc_chan ;	
  ADCSC1E_ADCHE = adc_chan ;	
  ADCSC1F_ADCHF = adc_chan ;	
  ADCSC1G_ADCHG = adc_chan ;	
  ADCSC1H_ADCHH = adc_chan ;	
}
  
 ADCCFG2_ADACKEN = 1 ;  // Enabled as

} /*end of Assign_ADC_CHN_Interrupt*/

void ADC_ALL_CHNn_Conversions(byte chn)
{
	// Test flow:
	// 	1. Clear previous flags assign All 8 ADC HW Channles to same input adc input source
	//  2. Start conversion on desired channel.
	//  3. Await completion (flag polling).
	//  4. Read back 16-bit conversion value and pass to calling routine.
	
  //Step 1 
  //Assign_ADC_CHN_Interrupt (chn, 0) ;// Assign all 8 HW adc channels to same 
                                     // Pin NO ADC interrupts for all ADC conv. completion 
                                     // and clear flag by writting to all ADCSC1n
  Assign_ADC_CHN_Interrupt (chn, 1) ;
  ADCSC2_ADTRG = 1 ; // Hardhare trigger enabled. ADC conversion starts by either Back-back PDB or Channeln Delay PDB triggers
  PDBC2_SWTRIG = 1;	 // Start PDB by software trigger
  PTED_PTED3 = 1 ;
 // PDB_Channels_Delay_recording();//only use for Flag polling: ADC channels interrupts are disabled, comment this out if testing for B-B interrupt
  
}

 void PDB_Back_TO_Back_SWTrig_Test(void)
 {
      int i = 0 ;
      PTED_PTED3 = 0 ; 
      PTEDD_PTEDD3 = 1 ; 
    	// *** Setup PDB
	  PDBMOD = 0xffff;
      PDBIDLY = 65535 ; // Effective after writting PDBSC_DACTOE = 1, delay depends on bus speed.
      PDBSC_LDOK = 1   ;// Load value of PDBDLYn from buffers to registers
      PDBC1_TRIGSEL=7  ;// Software triggered 
      PDBSC_TOS =2 ; // needed for either Back to Back or Channel delay
      PDBSC_PDBIE = 0 ; // PDB interrupt disable
      PDBC2 = 0xFE ;    // Back to back triggers ADC conversion. SW trigger not yet started
      PDBCHEN = 0xFF;   // Eneable output to related ADC n channels
      PDBC1_CONT =1  ;  // 0= SingleShot Mode (good for polling) . 1 continuous mode (good for interrupt driven)
      PDBSC_PDBEN =1 ;  // Enable PDB module
      PDBC1_PRESCALER = 0; 
      PDBC1_MULT = 0 ;  

      ADCSC1A = (26 | ADCSC1A_AIENA_MASK);		// enable interrupt
      ADCSC1B = (26 | ADCSC1B_AIENB_MASK);		// enable interrupt
      ADCSC1C = (26 | ADCSC1C_AIENC_MASK);		// enable interrupt
      ADCSC1D = (26 | ADCSC1D_AIEND_MASK);		// enable interrupt
      ADCSC1E = (26 | ADCSC1E_AIENE_MASK);		// enable interrupt
      ADCSC1F=  (26 | ADCSC1F_AIENF_MASK);		// enable interrupt
      ADCSC1G = (26 | ADCSC1G_AIENG_MASK);		// enable interrupt
      ADCSC1H = (26 | ADCSC1H_AIENH_MASK);		// enable interrupt
      
      ADCSC2_ADTRG = 1 ; // Hardhare trigger enabled. ADC conversion starts by either Back-back PDB or Channeln Delay PDB triggers
      PDBC2_SWTRIG = 1;	 // Start PDB by software trigger
      PTED_PTED3 = 1 ;
    
      // PTE3 outputs alternating +/- pulses like this:  -_-_-_-_-- for about 10.2us per low/high with Bus@24MHz, 
      // the each +/- pulse represent conv. time(10.2us) for each ADCn output channel. 
} //end of PDB_Back_TO_Back_Test





void main(void) {
 
  /* include your code here */
  sysInit();
  SetBus24MHz_FEI(); 
  MCGTRM = storedTRIM ; // fINT trimed to   31250  Hz 

  EnableInterrupts; /* enable interrupts */

  PDB_Back_TO_Back_SWTrig_Test();
    
      
      while(1){
 
   
      }
      
        
      
      
 
  //for(;;) {
    //__RESET_WATCHDOG(); /* feeds the dog */
  //} /* loop forever */
  /* please make sure that you never leave main */
}

__interrupt VectorNumber_Vadc  void adc_ISR (void)
{
  
 (void)ADCRA; // read ADC result and clear the corresponding ADC channel flag
 (void)ADCRB; // read ADC result and clear the corresponding ADC channel flag
 (void)ADCRC;
 (void)ADCRD;
 (void)ADCRE;
 (void)ADCRF;
 (void)ADCRG;
 (void)ADCRH ;
  
 return;
}  // end of adc_ISR
