/*******************************************************************************
*                                                                              *
* Copyright 2012 Rheinmetall Canada Inc.                                  	   *
*                                                                              *
* No part of this document may be reproduced, stored in                        *
* a retrieval system, or transmitted, in any form or by any means,             *
* electronic, mechanical, photocopying, recording, or otherwise,               *
* without the prior written permission of Rheinmetall Canada Inc.              *
*                                                                              *
*******************************************************************************/
/*
	Description:
	This is a template file for standard C header file.

*/

/* ************************************************************************** */
/* Revision:
### 20120521 JFM
	Original version.

### YYYYMMDD Initial, Bug Identification
	Change description.
 */

/* ************************************************************************** */
/* Includes */
#include "define.h"
#include "ADC.h"
#include "HallAcquisition.h"
#include "digitalio.h"
#include "PAStatus.h"

/* Globals */
unsigned int guiADCMode;
unsigned short egADCMotPhaseA;
unsigned short egADCMotPhaseB;
unsigned short egADCMotPhaseC;

/* Implementation */


//----------------------------------------------------------------------------
void InitADC(void)
{
	//At boot, init ADC in normal mode...
	guiADCMode = ADC_NORMAL_MODE;
	
	//configure input pins as analog inputs.
	TRISBbits.TRISB3 = 1;
	AD1PCFGbits.PCFG3 = 0;
	TRISBbits.TRISB4 = 1;
	AD1PCFGbits.PCFG4 = 0;
	TRISBbits.TRISB5 = 1;
	AD1PCFGbits.PCFG5 = 0;
	TRISBbits.TRISB8 = 1;
	AD1PCFGbits.PCFG8 = 0;
	TRISBbits.TRISB9 = 1;
	AD1PCFGbits.PCFG9 = 0;
	TRISBbits.TRISB11 = 1;
	AD1PCFGbits.PCFG11 = 0;
	TRISBbits.TRISB12 = 1;
	AD1PCFGbits.PCFG12 = 0;
	TRISBbits.TRISB13 = 1;
	AD1PCFGbits.PCFG13 = 0;
	
	AD1CON1 = 0;
	AD1CON2 = 0;
	AD1CON3 = 0;
	
	//configure output format (unsigned int 16 bits)
	AD1CON1bits.FORM = 0b000;
	//configure clock source and prescaling
	AD1CON3bits.ADRC = 0;	//Use Peripheral clock
	AD1CON3bits.ADCS = 4;	//Acording to datasheet TAD must be min 83.33ns --> minimal prescaler applied to TPBclk = 8 --> Conversion time ~= 100ns
	//AD1CON3bits.SAMC = 1;	//Used in automatic sampling mode (scan mode).  Shall be augmented if results are not accurate.  See datasheet.
	AD1CON3bits.SAMC = 30;	//Used in automatic sampling mode (scan mode).  Shall be augmented if results are not accurate.  See datasheet.
	
}
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
int ADCEnterHallACQMode(void)
{
	//configure ADC module
	AD1CON1bits.ON = 0;	//stop ADC to reconfigure.
	IEC1bits.AD1IE = 0;	//disable ADC interrupt for now
		
	AD1CHS = 0;		//Reset channel source since input source is controlled by hardware in scan mode.
	AD1CON2 = 0;
	AD1CSSL = 0;
	
	AD1CON1bits.SSRC = 0b111;	//manual conversion start.  Clearing SAMP starts conversion.  See AD1CON3bits.SAMC for sampling time.
//	AD1CON1bits.SSRC = 0b000;	//manual conversion start.  Clearing SAMP starts conversion.  See AD1CON3bits.SAMC for sampling time.
	AD1CON1bits.CLRASAM = 1;	
	AD1CON1bits.ASAM = 1;	
	
	//configure scan mode
	AD1CON2bits.CSCNA = 1;	//enable scan mode
	AD1CON2bits.SMPI = 2;	//Generate interrupt after the 3rd conversion.
	
	AD1CSSLbits.CSSL11= 1;	//select Phase A input in scan sequence
	AD1CSSLbits.CSSL12= 1;	//select Phase B input in scan sequence
	AD1CSSLbits.CSSL13= 1;	//select Phase C input in scan sequence
	AD1CON1bits.SAMP = 1 ;
	
	
	IPC6bits.AD1IP = 5;
	IPC6bits.AD1IS = 3;
	IFS1bits.AD1IF = 0;
	IEC1bits.AD1IE = 1;	//enable ADC interrupt
	
	AD1CON1bits.ON = 1;	//enable ADC.
		
	guiADCMode = ADC_HALL_ACQ_MODE;
	
	
	return 1;
}	
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
int ADCEnterTracesMode(void)
{
	//trick to reuse code but force the good mode :)
	ADCEnterHallACQMode();
	guiADCMode = ADC_TRACE_MODE;
	return 1;
}	
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
int ADCEnterCBITMode(void)
{
	//configure ADC module
	AD1CON1bits.ON = 0;	//stop ADC to reconfigure.
	IEC1bits.AD1IE = 0;	//disable ADC interrupt for now
		
	AD1CHS = 0;		//Reset channel source since input source is controlled by hardware in scan mode.
	AD1CON2 = 0;
	AD1CSSL = 0;
	
	AD1CON1bits.SSRC = 0b111;	//manual conversion start.  Clearing SAMP starts conversion.  See AD1CON3bits.SAMC for sampling time.
//	AD1CON1bits.SSRC = 0b000;	//manual conversion start.  Clearing SAMP starts conversion.  See AD1CON3bits.SAMC for sampling time.
	AD1CON1bits.CLRASAM = 1;	
	AD1CON1bits.ASAM = 1;	
	
	//configure scan mode
	AD1CON2bits.CSCNA = 1;	//enable scan mode
	AD1CON2bits.SMPI = 4;	//Generate interrupt after the 5th conversion.
	
	AD1CSSLbits.CSSL3= 1;	//select Vref input in scan sequence
	AD1CSSLbits.CSSL4= 1;	//select 5V input in scan sequence
	AD1CSSLbits.CSSL5= 1;	//select 3.3V input in scan sequence
	AD1CSSLbits.CSSL8= 1;	//select Motor Thermistor input in scan sequence
	AD1CSSLbits.CSSL9= 1;	//select Drive Thermistor input in scan sequence
	AD1CON1bits.SAMP = 1;
	
	
	IPC6bits.AD1IP = 5;
	IPC6bits.AD1IS = 3;
	IFS1bits.AD1IF = 0;
	IEC1bits.AD1IE = 1;	//enable ADC interrupt
	
	AD1CON1bits.ON = 1;	//enable ADC.
		
	guiADCMode = ADC_CBIT_MODE;
	
	
	return 1;
}
//----------------------------------------------------------------------------


//----------------------------------------------------------------------------
// Starts acquistion and conversion of the 3 phases.  The 3 inputs are scanned
// automatically by hardware and an interrupt is triggered when finished.
//
int ADCStartHallACQConversion(void)
{
	AD1CON1bits.ASAM = 1;
	AD1CON1bits.SAMP = 1;	//start sampling and start conversion.  Interrupt will be generated when data is ready
	return 1;
}
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
int ADCStartTracesConversion(void)
{
	AD1CON1bits.ASAM = 1;
	AD1CON1bits.SAMP = 1;	//start sampling and start conversion.  Interrupt will be generated when data is ready
	return 1;
}	
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
int ADCStartCBITConversion(void)
{
	if(guiADCMode == ADC_CBIT_MODE)
	{
		AD1CON1bits.ASAM = 1;
		AD1CON1bits.SAMP = 1;	//start sampling and start conversion.  Interrupt will be generated when data is ready
		return 1;
	}
	return 0;
}	
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
int ADCStopConversion(void)
{
	return 1;
}	
//----------------------------------------------------------------------------

int ADCGetMode(void)
{
	return guiADCMode;
}	



//----------------------------------------------------------------------------
void __ISR(_ADC_VECTOR, ipl5) ADCInterrupt(void)
{
	switch(guiADCMode)
	{
		case ADC_NORMAL_MODE:
		{
			break;
		}
		case ADC_CBIT_MODE:
		{
			estPAStatus.gusVoltageVref = ADC1BUF0;
			estPAStatus.gusVoltage5V = ADC1BUF1;
			estPAStatus.gusVoltage33V = ADC1BUF2;
			estPAStatus.gusVoltageThermMot = ADC1BUF3;
			estPAStatus.gusVoltageThermDrv = ADC1BUF4;
			
			estPAStatus.IsDataReady = 1;
			break;
		}	
		case ADC_TRACE_MODE:
		{
			egADCMotPhaseA = ADC1BUF0;
			egADCMotPhaseB = ADC1BUF1;
			egADCMotPhaseC = ADC1BUF2;	
			break;
		}
		case ADC_HALL_ACQ_MODE:
		{
			//Update data structure.
			if(gpstHallAcqDataPtr != 0 && gpstHallAcqDataPtr <= gpstHallAcqDataPtrEND)
			{
				gpstHallAcqDataPtr->MotPhaseA = ADC1BUF0;
				gpstHallAcqDataPtr->MotPhaseB = ADC1BUF1;
				gpstHallAcqDataPtr->MotPhaseC = ADC1BUF2;
				gpstHallAcqDataPtr->AnalogDataUpToDate = 1;
			}	
			break;
		}	
	}
	IFS1bits.AD1IF = 0;	
}	
//----------------------------------------------------------------------------

//EOF

