/******************************************************************************* * * * 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