blob: edc1020f5cb902c22b26fd3a26e55b26609a8326 [file] [log] [blame]
/* --COPYRIGHT--,BSD
* Copyright (c) 2014, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --/COPYRIGHT--*/
//*****************************************************************************
//
// esi.h - Driver for the ESI Module.
//
//*****************************************************************************
//*****************************************************************************
//
//! \addtogroup esi_api
//! @{
//
//*****************************************************************************
#include "inc/hw_regaccess.h"
#include "inc/hw_memmap.h"
#ifdef __MSP430_HAS_ESI__
#include "esi.h"
#include <assert.h>
// Uncomment for finding lower peak of the lower half cycle.
// This required to set ESI comparator output as inverted
#define INVERTED
static uint16_t measureESIOSC(void);
static void FindDAC(uint8_t selected_channel,
uint8_t software_trigger);
const ESI_AFE1_InitParams ESI_AFE1_INITPARAMS_DEFAULT =
{ESI_EXCITATION_CIRCUIT_DISABLED,
ESI_SAMPLE_HOLD_DISABLED,
ESI_MID_VOLTAGE_GENERATOR_DISABLED,
ESI_SAMPLE_HOLD_VSS_TO_ESIVSS,
ESI_INVERTER_FOR_AFE1_DISABLE};
const ESI_AFE2_InitParams ESI_AFE2_INITPARAMS_DEFAULT = {
ESI_AFE2_INPUT_SELECT_CHx,
ESI_INVERTER_FOR_AFE2_DISABLE,
ESI_TSM_COMPARATOR_CONTROL_AFE2_DISABLE,
ESI_TSM_DAC_CONTROL_AFE2_DISABLE
};
const ESI_TSM_InitParams ESI_TSM_INITPARAMS_DEFAULT = { ESI_TSM_SMCLK_DIV_1,
ESI_TSM_ACLK_DIV_1,
ESI_TSM_START_TRIGGER_DIV_2,
ESI_TSM_REPEAT_NEW_TRIGGER,
ESI_TSM_STOP_SEQUENCE,
ESI_TSM_HIGH_FREQ_CLK_FUNCTION_ON};
const ESI_PSM_InitParams ESI_PSM_INITPARAMS_DEFAULT = { ESI_PSM_Q6_DISABLE,
ESI_PSM_Q7_TRIGGER_DISABLE,
ESI_PSM_CNT0_DISABLE,
ESI_PSM_CNT0_RESET,
ESI_PSM_CNT1_DISABLE,
ESI_PSM_CNT1_RESET,
ESI_PSM_CNT2_DISABLE,
ESI_PSM_CNT2_RESET,
ESI_PSM_S3_SELECT,
ESI_PSM_TEST4_IS_Q2,};
//*****************************************************************************
//
//! Get ESI PSM Counter 0 Value
//!
//! This function reads the ESI Counter 0 register
//!
//! \return Counter value
//
//*****************************************************************************
uint16_t ESI_getCounter0(void)
{
return (ESICNT0);
}
//*****************************************************************************
//
//! Get ESI PSM Counter 1 Value
//!
//! This function reads the ESI Counter1 register
//!
//! \return Counter value
//
//*****************************************************************************
uint16_t ESI_getCounter1(void)
{
return (ESICNT1);
}
//*****************************************************************************
//
//! Get ESI PSM Counter 2 Value
//!
//! This function reads the ESI Counter2 register
//!
//! \return Counter value
//
//*****************************************************************************
uint16_t ESI_getCounter2(void)
{
return (ESICNT2);
}
//*****************************************************************************
//
//! Get ESI PSM Oscillator Counter Value
//!
//! This function reads the ESI Oscillator Counter register
//!
//! \return Counter value
//
//*****************************************************************************
uint16_t ESI_getOscCounter(void)
{
return (ESICNT3);
}
//*****************************************************************************
//
//! Initializes the ESI analog front end AFE1
//!
//! \param params is ESI_AFE1_InitParams struct
//!
//! This functions initializes the ESI analog front end AFE1.
//!
//! \return None
//
//*****************************************************************************
void ESI_AFE1_init(ESI_AFE1_InitParams *params)
{
// Unset the AFE1 bits
ESIAFE &= ~(ESITEN + ESISH + ESIVCC2 + ESIVSS + ESICACI3 + ESICISEL +
ESICA1X + ESICA1INV);
ESIAFE |=
params->excitationCircuitSelect +
params->sampleAndHoldSelect +
params->midVoltageGeneratorSelect +
params->sampleAndHoldVSSConnect +
params->inverterSelectOutputAFE1
;
switch(params->inputSelectAFE1)
{
case ESI_AFE1_INPUT_SELECT_CHx:
break;
case ESI_AFE1_INPUT_SELECT_CIx:
ESIAFE |= ESICA1X;
break;
case ESI_AFE1_INPUT_SELECT_CI3:
ESIAFE |= ESICA1X;
ESIAFE &= ~ESICISEL;
ESIAFE |= ESICACI3;
break;
case ESI_AFE1_INPUT_SELECT_CI:
ESIAFE |= ESICA1X;
ESIAFE |= ESICISEL;
break;
default:
break;
}
}
//*****************************************************************************
//
//! Initializes the ESI analog front end - AFE2
//!
//! \param params is ESI_AFE2_InitParams struct
//!
//! This functions initializes the ESI analog front end AFE2
//!
//! \return None
//
//*****************************************************************************
void ESI_AFE2_init(ESI_AFE2_InitParams *params)
{
// Unset the AFE2 bits
ESIAFE &= ~(ESICA2X + ESICA2INV + ESICA2EN + ESIDAC2EN);
ESIAFE |=
params->inputSelectAFE2 +
params->inverterSelectOutputAFE2 +
params->tsmControlComparatorAFE2 +
params->tsmControlDacAFE2
;
}
//*****************************************************************************
//
//! Reads the latched comparator outputs form the AFEs
//!
//! \param channelSelect. Valid values are
//! ESI_AFE1_CHANNEL0_SELECT
//! ESI_AFE1_CHANNEL1_SELECT
//! ESI_AFE1_CHANNEL2_SELECT
//! ESI_AFE1_CHANNEL3_SELECT
//! ESI_AFE2_CHANNEL0_SELECT
//! ESI_AFE2_CHANNEL1_SELECT
//! ESI_AFE2_CHANNEL2_SELECT
//! ESI_AFE2_CHANNEL3_SELECT
//! ESI_AFE1_TEST_CHANNEL0_SELECT
//! ESI_AFE1_TEST_CHANNEL1_SELECT
//!
//! This function gets the ESIPPU register to get latched output values of the
//! comparator outputs for AFE1 and AFE2
//!
//! \return Valid values are
//! ESI_AFE_OUTPUT_LOW
//! ESI_AFE_OUTPUT_HIGH
//
//*****************************************************************************
uint16_t ESI_getLatchedComparatorOutput(uint16_t channelSelect)
{
uint16_t result;
result = ESIPPU;
return (result &= channelSelect);
}
//*****************************************************************************
//
//! Initializes the TSM
//!
//! \param params is ESI_TSM_InitParams struct
//!
//! This function initializes the TSM.
//!
//! \return None
//
//*****************************************************************************
void ESI_TSM_init(ESI_TSM_InitParams *params)
{
ESITSM =
params->smclkDivider +
params->aclkDivider +
params->startTriggerAclkDivider +
params->repeatMode +
params->startTriggerSelection +
params->tsmFunctionSelection
;
}
//*****************************************************************************
//
//! Clear TSM entries
//!
//! This function clears all TSM entries
//!
//! \return None
//
//*****************************************************************************
void ESI_TSM_clearTable(void)
{
uint16_t *pTsm, i;
// Clear TSM Table (for testing only. not neccessary in real application)
pTsm = (uint16_t *)&ESITSM0;
for(i = 0; i < 32; i++)
{
*pTsm++ = 0x0200;
}
}
//*****************************************************************************
//
//! Copy TSM entries
//!
//! This function copies all TSM entries
//!
//! \return None
//
//*****************************************************************************
void ESI_TSM_copyTable(uint16_t* tsmTable,
uint16_t size)
{
uint16_t *pt_tsmTable;
uint16_t i;
// Copy the TSM_Table into ESI TSM registers
// Destination pointer
pt_tsmTable = (uint16_t *)&ESITSM0;
// Divided by 2 because of unsigned integer (2bytes)
i = size / 2;
do
{
*pt_tsmTable++ = *tsmTable++;
}
while(--i);
}
//*****************************************************************************
//
//! TSM trigger using software
//!
//! This function starts a software initiated TSM sequence
//!
//! \return None
//
//*****************************************************************************
void ESI_TSM_softwareTrigger(void)
{
ESITSM |= ESISTART;
}
//*****************************************************************************
//
//! TSM trigger using software
//!
//! This function starts a software initiated TSM sequence
//!
//! \return ESIREATx bits from selected stateRegNum
//
//*****************************************************************************
uint8_t ESI_TSM_getTSMStateDuration(uint8_t stateRegNum)
{
volatile uint16_t* stateRegBase = (volatile uint16_t*)&ESITSM0;
return((*(stateRegBase + stateRegNum) & 0xf800) >> 11);
}
//*****************************************************************************
//
//! TSM trigger using software
//!
//! This function starts a software initiated TSM sequence
//!
//! \return ESIREATx bits from selected stateRegNum
//
//*****************************************************************************
void ESI_TSM_setTSMStateDuration(uint8_t stateRegNum,
uint8_t duration)
{
assert(stateRegNum <= ESI_TSM_STATE_REG_31);
assert(duration <= ESI_TSM_STATE_DURATION_MAX);
volatile uint16_t* stateRegBase = (volatile uint16_t*)&ESITSM0;
*(stateRegBase + stateRegNum) &= ~0xF800;
*(stateRegBase + stateRegNum) |= (duration << 11);
}
//*****************************************************************************
//
//! Initialize Processing State Machine
//
//! \param params is ESI_PSM_InitParams struct
//!
//! This function initializes the PSM registers.
//!
//! \return None
//
//*****************************************************************************
void ESI_PSM_init(ESI_PSM_InitParams *params)
{
ESIPSM =
params->Q6Select +
params->Q7TriggerSelect +
params->count0Select +
params->count0Reset +
params->count1Select +
params->count1Reset +
params->count2Select +
params->count2Reset +
params->V2Select +
params->TEST4Select
;
}
//*****************************************************************************
//
//! Clear PSM entries
//!
//! This function clears all PSM entries
//!
//! \return None
//
//*****************************************************************************
void ESI_PSM_clearTable(void)
{
uint8_t *pPsm, i;
// Clear TSM Table (for testing only. not neccessary in real application)
pPsm = (uint8_t *)&ESIRAM0;
for(i = 0; i < 128; i++)
{
*pPsm++ = 0x0;
}
}
//*****************************************************************************
//
//! Copy PSM entries
//!
//! This function copies all PSM entries
//!
//! \return None
//
//*****************************************************************************
void ESI_PSM_copyTable(uint8_t* psmTable,
uint8_t size)
{
uint8_t *pt_psmTable;
uint8_t i;
assert(size <= 128);
// Copy the TSM_Table into ESI TSM registers
pt_psmTable = (uint8_t *)&ESIRAM0; // Destination pointer
i = size;
do
{
*pt_psmTable++ = *psmTable++;
}
while(--i);
}
//*****************************************************************************
//
//! Reset PSM counters
//!
//! \param counterToReset is the counter that needs t be reset
//!
//! This function resets the PSM counters
//!
//! \return None
//
//*****************************************************************************
void ESI_PSM_resetCounter(uint16_t counterToReset)
{
ESIPSM |= counterToReset;
}
//*****************************************************************************
//
//! Enables the internal Oscillator
//!
//!
//! This function enables the high frequency internal oscillator
//!
//! \return None
//
//*****************************************************************************
void ESI_enableInternalOscillator(void)
{
ESIOSC |= ESIHFSEL;
}
//*****************************************************************************
//
//! Disables the internal Oscillator
//!
//!
//! This function disables the high frequency internal oscillator
//!
//! \return None
//
//*****************************************************************************
void ESI_disableInternalOscillator(void)
{
ESIOSC &= ~ESIHFSEL;
}
//*****************************************************************************
//
//! Connects comparator output to timerA input
//!
//! \param counterToReset ESI_TIMERA_INPUT_TSM_COMPOUT or
//! ESI_TIMERA_INPUT_TSM_PPUSRC
//!
//! This function connects the chosen comparator output to TimerA
//!
//! \return None
//
//*****************************************************************************
void ESI_timerAInputSelect(uint16_t select)
{
ESICTL |= select;
}
//*****************************************************************************
//
//! Connects psm source to comparator output
//!
//! \param sourceNum PSM_S1_SOURCE, PSM_S2_SOURCE or PSM_S3_SOURCE
//! \param sourceSelect can have the following values
//! ESI_PSM_SOURCE_IS_ESIOUT0
//! ESI_PSM_SOURCE_IS_ESIOUT1
//! ESI_PSM_SOURCE_IS_ESIOUT2
//! ESI_PSM_SOURCE_IS_ESIOUT3
//! ESI_PSM_SOURCE_IS_ESIOUT4
//! ESI_PSM_SOURCE_IS_ESIOUT5
//! ESI_PSM_SOURCE_IS_ESIOUT6
//! ESI_PSM_SOURCE_IS_ESIOUT7
//!
//! This function connects the chosen comparator output to TimerA
//!
//! \return None
//
//*****************************************************************************
void ESI_psmSourceSelect(uint16_t sourceNum,
uint16_t sourceSelect)
{
switch(sourceNum)
{
case PSM_S1_SOURCE:
ESICTL &= ~(ESIS1SEL0 | ESIS1SEL1 | ESIS1SEL2);
ESICTL |= (sourceSelect << 7);
break;
case PSM_S2_SOURCE:
ESICTL &= ~(ESIS2SEL0 | ESIS2SEL1 | ESIS2SEL2);
ESICTL |= (sourceSelect << 10);
break;
case PSM_S3_SOURCE:
ESICTL &= ~(ESIS3SEL0 | ESIS3SEL1 | ESIS3SEL2);
ESICTL |= (sourceSelect << 13);
break;
default:
break;
}
}
//*****************************************************************************
//
//! Connects testChannel0 to comparator input
//!
//! \param sourceSelect can have the following values
//! ESI_TEST_CHANNEL0_SOURCE_IS_CH0_CI0
//! ESI_TEST_CHANNEL0_SOURCE_IS_CH1_CI1
//! ESI_TEST_CHANNEL0_SOURCE_IS_CH2_CI2
//! ESI_TEST_CHANNEL0_SOURCE_IS_CH3_CI3
//!
//! This function connects the chosen comparator input to the test channel0
//!
//! \return None
//
//*****************************************************************************
void ESI_testChannel0SourceSelect(uint16_t sourceSelect)
{
ESICTL &= ~(ESI_TEST_CHANNEL0_SOURCE_IS_CH3_CI3);
ESICTL |= sourceSelect;
}
//*****************************************************************************
//
//! Connects testChannel1to comparator input
//!
//! \param sourceSelect can have the following values
//! ESI_TEST_CHANNEL1_SOURCE_IS_CH0_CI0
//! ESI_TEST_CHANNEL1_SOURCE_IS_CH1_CI1
//! ESI_TEST_CHANNEL1_SOURCE_IS_CH2_CI2
//! ESI_TEST_CHANNEL1_SOURCE_IS_CH3_CI3
//!
//! This function connects the chosen comparator input to the test channel1
//!
//! \return None
//
//*****************************************************************************
void ESI_testChannel1SourceSelect(uint16_t sourceSelect)
{
ESICTL &= ~(ESI_TEST_CHANNEL1_SOURCE_IS_CH3_CI3);
ESICTL |= sourceSelect;
}
//*****************************************************************************
//
//! Enable ESI peripheral
//!
//! \return None
//
//*****************************************************************************
void ESI_enable(void)
{
ESICTL |= ESIEN;
}
//*****************************************************************************
//
//! Disable ESI peripheral
//!
//! \return None
//
//*****************************************************************************
void ESI_disable(void)
{
ESICTL &= ~ESIEN;
}
//*****************************************************************************
//
//! Start calibration on ESI internal Oscillator
//!
//! This function starts calibration of internal osciallator. After calling this
//! function the user and use ESI_adjustInternalOscFreq() to adjust the freq. of
//! the oscillator.
//!
//! \return None
//
//*****************************************************************************
void ESI_startInternalOscCal(void)
{
assert(ESIOSC | ESIHFSEL);
ESIOSC |= ESICLKGON;
}
//*****************************************************************************
//
//! Adjusts frequency ESI internal Oscillator
//!
//! This function adjusts frequency ESI internal Oscillator. It increases or
//! decrease the freq by 3% based on incOrDec value.
//!
//! \return None
//
//*****************************************************************************
void ESI_adjustInternalOscFreq(uint16_t incOrDec)
{
uint16_t adjustValue;
assert(ESIOSC | ESIHFSEL);
adjustValue = ESIOSC >> 8;
if(incOrDec == ESI_INTERNAL_OSC_FREQ_INCREASE)
{
adjustValue = adjustValue + 1;
adjustValue = adjustValue << 8;
}
else
{
adjustValue = adjustValue - 1;
adjustValue = adjustValue << 8;
}
ESIOSC |= adjustValue;
}
//*****************************************************************************
//
//! Sets frequency of ESI internal Oscillator
//!
//!
//! \return None
//
//*****************************************************************************
void ESI_setNominalInternalOscFreq(void)
{
ESIOSC = ESICLKFQ5 + ESICLKGON + ESIHFSEL;
}
//*****************************************************************************
//
//! The following function return the number of ESIOSC cycle during an ACLK
//! cycle.
//!
//!
//! \return None
//
//*****************************************************************************
static uint16_t measureESIOSC(void){
// This and next instruction realizes a clear->set ESICLKGON bit.
ESIOSC &= ~(ESICLKGON);
// This starts measurement.
ESIOSC |= ESICLKGON + ESIHFSEL;
// Reading ESICNT3 while counting always result in reading a 0x01.
while(ESICNT3 == 1)
{
;
}
// Stop ESIOSC oscillator
ESIOSC &= ~(ESICLKGON);
return (ESICNT3);
}
//******************************************************************************
//! The following function returns the ESICLKFQx bits on ESIOSC register
//
//! \param none
//
//! \return ESICLKFQ bits only
//******************************************************************************
uint8_t ESI_getESICLKFQ(void){
uint16_t temp;
// Store ESIOSC content
temp = ESIOSC;
// Get ESICLKFQx bits
temp = (temp >> 8) & 0x3F;
return(temp);
}
//******************************************************************************
//! The following function sets ESICLKFQx bits on ESIOSC register
//
//! \param setting is to the loaded to ESIOSC. Valid parameters a value between
//! 0x00 and 0x3F. 0x00 corresponds to minimum frequency, 0x20
//! corresponds to nominal frequency and 0x3F corresponds to maximum
//! frequency.
//
//! \return none
//******************************************************************************
void ESI_setESICLKFQ(uint8_t setting)
{
uint16_t temp;
assert(setting < 0x40);
temp = ESIOSC; // get actual ESIOSC register content
temp &= ~(0x3F00);
temp = ((uint16_t) setting << 8) + temp; // and update ESICLKFQ bits
ESIOSC = temp;
}
//*****************************************************************************
//
//! Calibrate ESI internal Oscillator
//!
//!
//! \return None
//
//*****************************************************************************
void ESI_calibrateInternalOscFreq(uint16_t targetAclkCounts)
{
ESI_setNominalInternalOscFreq();
ESI_measureESIOSC(ESI_ESIOSC_OVERSAMPLE_4);
if(ESICNT3 > targetAclkCounts)
{
//freq is too high
do
{
ESI_adjustInternalOscFreq(ESI_INTERNAL_OSC_FREQ_DECREASE);
}
while(ESI_measureESIOSC(ESI_ESIOSC_OVERSAMPLE_4) > targetAclkCounts);
}
else
{
//freq is too low
do
{
ESI_adjustInternalOscFreq(ESI_INTERNAL_OSC_FREQ_INCREASE);
}
while(ESI_measureESIOSC(ESI_ESIOSC_OVERSAMPLE_4) > targetAclkCounts);
ESI_adjustInternalOscFreq(ESI_INTERNAL_OSC_FREQ_DECREASE);
}
}
//*****************************************************************************
//
//! The following function returns an average of ESIOSC measurement.
//!
//! \param
//!
//! \return averaged ESIOSC measurement.
//
//*****************************************************************************
uint16_t ESI_measureESIOSC(uint8_t oversample){
uint8_t i;
uint16_t temp = 0;
assert(oversample < 9);
for(i = oversample; i > 0; i--)
{
temp += measureESIOSC();
}
temp /= oversample;
return(temp);
}
//*****************************************************************************
//
//! Set upper threshold for PSM counter 1
//!
//! \param threshold is the upper threashold that causes ESIIFG3 to get set.
//!
//! This function sets the threshold value for PSM counter 1. ESIIFG3 gets set
//! when counter value and this threahold are equal.
//!
//! \return None
//
//*****************************************************************************
void ESI_setPSMCounter1UpperThreshold(uint16_t threshold)
{
ESITHR1 = threshold;
}
//*****************************************************************************
//
//! Set lower threshold for PSM counter 1
//!
//! \param threshold is the lower threashold that causes ESIIFG3 to get set.
//!
//! This function set the threshold value for PSM counter 1. ESIIFG3 gets set
//! when counter value and this threahold are equal.
//!
//! \return None
//
//*****************************************************************************
void ESI_setPSMCounter1LowerThreshold(uint16_t threshold)
{
ESITHR2 = threshold;
}
//*****************************************************************************
//
//! sets AFE1 DAC threshold Value
//!
//! \param dacValue is value to be written to DAC register.
//! \param dacRegNum is DAC register number
//!
//! Write DAC threshold value into selected DAC register
//!
//! \return None
//
//*****************************************************************************
void ESI_setAFE1DACValue(uint16_t dacValue,
uint8_t dacRegNum)
{
volatile uint16_t* dacRegBase = (volatile uint16_t*) &ESIDAC1R0;
*(dacRegBase + dacRegNum) = dacValue;
}
//*****************************************************************************
//
//! gets AFE1 DAC threshold Value
//!
//! \param dacValue is value to be written to DAC register.
//! \param dacRegNum is DAC register number
//!
//! Read DAC threshold value into selected DAC register
//!
//! \return DAC value from selected DAC register.
//
//*****************************************************************************
uint16_t ESI_getAFE1DACValue(uint8_t dacRegNum)
{
volatile uint16_t* dacRegBase = (volatile uint16_t*) &ESIDAC1R0;
return(*(dacRegBase + dacRegNum));
}
//*****************************************************************************
//
//! sets AFE2 DAC threshold Value
//!
//! \param dacValue is value to be written to DAC register.
//! \param dacRegNum is DAC register number
//!
//! Write DAC threshold value into selected DAC register
//!
//! \return None
//
//*****************************************************************************
void ESI_setAFE2DACValue(uint16_t dacValue,
uint8_t dacRegNum)
{
volatile uint16_t* dacRegBase = (volatile uint16_t*) &ESIDAC2R0;
*(dacRegBase + dacRegNum) = dacValue;
}
//*****************************************************************************
//
//! gets AFE2 DAC threshold Value
//!
//! \param dacValue is value to be written to DAC register.
//! \param dacRegNum is DAC register number
//!
//! Read DAC threshold value into selected DAC register
//!
//! \return DAC value from selected DAC register.
//
//*****************************************************************************
uint16_t ESI_getAFE2DACValue(uint8_t dacRegNum)
{
volatile uint16_t* dacRegBase = (volatile uint16_t*) &ESIDAC2R0;
return(*(dacRegBase + dacRegNum));
}
//*****************************************************************************
//
//! sets TSM state register
//!
//! \param params constructs the state value
//! \param stateRegNum is state register offset
//!
//! Sets selected TSM state register.
//!
//! \return None
//
//*****************************************************************************
void ESI_setTSMstateReg(ESI_TSM_StateParams *params,
uint8_t stateRegNum)
{
volatile uint16_t* stateRegBase = (volatile uint16_t*) &ESITSM0;
*(stateRegBase + stateRegNum) =
(params->inputChannelSelect +
params->LCDampingSelect +
params->excitationSelect +
params->comparatorSelect +
params->highFreqClkOn_or_compAutoZeroCycle +
params->outputLatchSelect +
params->testCycleSelect +
params->dacSelect +
params->tsmStop +
params->tsmClkSrc) |
(params->duration << 11);
}
//*****************************************************************************
//
//! Get ESI interrupt Vector Register
//!
//! \return None
//
//*****************************************************************************
uint16_t ESI_getInterruptVectorRegister(void)
{
return (ESIIV);
}
//*****************************************************************************
//
//! Enables ESI interrupts
//!
//! \param interruptMask is the bit mask of the interrupt sources to
//! be enabled. Mask value is the logical OR of any of the following:
//! \b ESI_INTERRUPT_AFE1_ESIOUTX
//! \b ESI_INTERRUPT_ESISTOP
//! \b ESI_INTERRUPT_ESISTART
//! \b ESI_INTERRUPT_ESICNT1
//! \b ESI_INTERRUPT_ESICNT2
//! \b ESI_INTERRUPT_Q6_BIT_SET
//! \b ESI_INTERRUPT_Q7_BIT_SET
//! \b ESI_INTERRUPT_ESICNT0_COUNT_INTERVAL
//! \b ESI_INTERRUPT_AFE2_ESIOUTX
//!
//! Modified bits of \b ESIINT1 register.
//!
//! \return None
//
//*****************************************************************************
void ESI_enableInterrupt(uint16_t interruptMask)
{
ESIINT1 |= (interruptMask);
}
//*****************************************************************************
//
//! Disables ESI interrupts
//!
//! \param interruptMask is the bit mask of the interrupt sources to
//! be disabled. Mask value is the logical OR of any of the following:
//! \b ESI_INTERRUPT_AFE1_ESIOUTX
//! \b ESI_INTERRUPT_ESISTOP
//! \b ESI_INTERRUPT_ESISTART
//! \b ESI_INTERRUPT_ESICNT1
//! \b ESI_INTERRUPT_ESICNT2
//! \b ESI_INTERRUPT_Q6_BIT_SET
//! \b ESI_INTERRUPT_Q7_BIT_SET
//! \b ESI_INTERRUPT_ESICNT0_COUNT_INTERVAL
//! \b ESI_INTERRUPT_AFE2_ESIOUTX
//!
//! Modified bits of \b ESIINT1 register.
//!
//! \return None
//
//*****************************************************************************
void ESI_disableInterrupt(uint16_t interruptMask)
{
ESIINT1 &= ~(interruptMask);
}
//*****************************************************************************
//
//! Get ESI interrupt status
//!
//! \param interruptMask is the masked interrupt flag status to be returned.
//! Mask value is the logical OR of any of the following:
//! - \b ESI_INTERRUPT_FLAG_AFE1_ESIOUTX
//! - \b ESI_INTERRUPT_FLAG_ESISTOP
//! - \b ESI_INTERRUPT_FLAG_ESISTART
//! - \b ESI_INTERRUPT_FLAG_ESICNT1
//! - \b ESI_INTERRUPT_FLAG_ESICNT2
//! - \b ESI_INTERRUPT_FLAG_Q6_BIT_SET
//! - \b ESI_INTERRUPT_FLAG_Q7_BIT_SET
//! - \b ESI_INTERRUPT_FLAG_ESICNT0_COUNT_INTERVAL
//! - \b ESI_INTERRUPT_FLAG_AFE2_ESIOUTX
//!
//! \return Logical OR of any of the following:
//! - \b ESI_INTERRUPT_FLAG_AFE1_ESIOUTX
//! - \b ESI_INTERRUPT_FLAG_ESISTOP
//! - \b ESI_INTERRUPT_FLAG_ESISTART
//! - \b ESI_INTERRUPT_FLAG_ESICNT1
//! - \b ESI_INTERRUPT_FLAG_ESICNT2
//! - \b ESI_INTERRUPT_FLAG_Q6_BIT_SET
//! - \b ESI_INTERRUPT_FLAG_Q7_BIT_SET
//! - \b ESI_INTERRUPT_FLAG_ESICNT0_COUNT_INTERVAL
//! - \b ESI_INTERRUPT_FLAG_AFE2_ESIOUTX
//! \n indicating the status of the masked flags
//
//*****************************************************************************
uint16_t ESI_getInterruptStatus(uint16_t interruptMask)
{
return (ESIINT2 & interruptMask);
}
//*****************************************************************************
//
//! Clear ESI interrupt flag
//!
//! \param interruptMask is the masked interrupt flag status to be returned.
//! Mask value is the logical OR of any of the following:
//! - \b ESI_INTERRUPT_FLAG_AFE1_ESIOUTX
//! - \b ESI_INTERRUPT_FLAG_ESISTOP
//! - \b ESI_INTERRUPT_FLAG_ESISTART
//! - \b ESI_INTERRUPT_FLAG_ESICNT1
//! - \b ESI_INTERRUPT_FLAG_ESICNT2
//! - \b ESI_INTERRUPT_FLAG_Q6_BIT_SET
//! - \b ESI_INTERRUPT_FLAG_Q7_BIT_SET
//! - \b ESI_INTERRUPT_FLAG_ESICNT0_COUNT_INTERVAL
//! - \b ESI_INTERRUPT_FLAG_AFE2_ESIOUTX
//!
//! \return None
//
//*****************************************************************************
void ESI_clearInterrupt(uint16_t interruptMask)
{
ESIINT2 &= ~(interruptMask);
}
//*****************************************************************************
//
//! Set source of IFG0 interrupt flag
//!
//! \param ifg0Src values are as follows
//! ESI_IFG0_SET_WHEN_ESIOUT0_SET
//! ESI_IFG0_SET_WHEN_ESIOUT0_RESET
//! ESI_IFG0_SET_WHEN_ESIOUT1_SET
//! ESI_IFG0_SET_WHEN_ESIOUT1_RESET
//! ESI_IFG0_SET_WHEN_ESIOUT2_SET
//! ESI_IFG0_SET_WHEN_ESIOUT2_RESET
//! ESI_IFG0_SET_WHEN_ESIOUT3_SET
//! ESI_IFG0_SET_WHEN_ESIOUT3_RESET
//!
//! \return None
//
//*****************************************************************************
void ESI_setIFG0Source(uint16_t ifg0Src)
{
ESIINT1 &= ~ESI_IFG0_SET_WHEN_ESIOUT3_RESET;
ESIINT1 |= ifg0Src;
}
//*****************************************************************************
//
//! Set source of IFG8 interrupt flag
//!
//! \param ifg8Src values are as follows
//! ESI_IFG8_SET_WHEN_ESIOUT4_SET
//! ESI_IFG8_SET_WHEN_ESIOUT4_RESET
//! ESI_IFG8_SET_WHEN_ESIOUT5_SET
//! ESI_IFG8_SET_WHEN_ESIOUT5_RESET
//! ESI_IFG8_SET_WHEN_ESIOUT6_SET
//! ESI_IFG8_SET_WHEN_ESIOUT6_RESET
//! ESI_IFG8_SET_WHEN_ESIOUT7_SET
//! ESI_IFG8_SET_WHEN_ESIOUT7_RESET
//!
//! \return None
//
//*****************************************************************************
void ESI_setIFG8Source(uint16_t ifg8Src)
{
ESIINT1 &= ~ESI_IFG8_SET_WHEN_ESIOUT7_RESET;
ESIINT1 |= ifg8Src;
}
//*****************************************************************************
//
//! Set source of IFG7 interrupt flag
//!
//! \param ifg7Src values are as follows
//! ESI_IFG7_SOURCE_EVERY_COUNT_OF_CNT0
//! ESI_IFG7_SOURCE_CNT0_MOD4
//! ESI_IFG7_SOURCE_CNT0_MOD256
//! ESI_IFG7_SOURCE_CNT0_ROLLOVER
//!
//! \return None
//
//*****************************************************************************
void ESI_setIFG7Source(uint16_t ifg7Src)
{
ESIINT2 &= ~ESI_IFG7_SOURCE_CNT0_ROLLOVER;
ESIINT2 |= ifg7Src;
}
//*****************************************************************************
//
//! Set source of IFG4 interrupt flag
//!
//! \param ifg4Src values are as follows
//! ESI_IFG4_SOURCE_EVERY_COUNT_OF_CNT2
//! ESI_IFG4_SOURCE_CNT2_MOD4
//! ESI_IFG4_SOURCE_CNT2_MOD256
//! ESI_IFG4_SOURCE_CNT2_ROLLOVER
//!
//! \return None
//
//*****************************************************************************
void ESI_setIFG4Source(uint16_t ifg4Src)
{
ESIINT2 &= ~ESI_IFG4_SOURCE_CNT2_ROLLOVER;
ESIINT2 |= ifg4Src;
}
//*****************************************************************************
//
//! Simple DAC calibration code using pre-defined TSM
//! Supports AFE1 only.
//! \param selected_channel acceptable values
//! ESI_AFE1_CHANNEL0_SELECT
//! ESI_AFE1_CHANNEL1_SELECT
//! ESI_AFE1_CHANNEL2_SELECT
//! ESI_AFE1_CHANNEL3_SELECT
//!
//!
//! \return None
//
//*****************************************************************************
void ESI_LC_DAC_calibration(uint8_t selected_channel)
{
#define NUM_SENSOR_CAL 4
#define MIN_HYSTERESIS 30
#define STEP_TO_FINISH 4
unsigned int i;
unsigned char test_bit, done;
unsigned int hysteresis[NUM_SENSOR_CAL],
hysteresis_hi[NUM_SENSOR_CAL],
hysteresis_lo[NUM_SENSOR_CAL],
current[NUM_SENSOR_CAL],
average[NUM_SENSOR_CAL],
max[NUM_SENSOR_CAL],
min[NUM_SENSOR_CAL];
// State: 0 = output low
// 1 = output high
// 2 = undetermined (between 2 hysteresis level)
unsigned char previous_state[NUM_SENSOR_CAL],
current_state[NUM_SENSOR_CAL],
step[NUM_SENSOR_CAL];
// Reset values
for(i = 0; i < NUM_SENSOR_CAL; i++)
{
max[i] = 0;
min[i] = 0xffff;
previous_state[i] = 2;
step[i] = 0;
}
do
{
// Find the current oscillating level, using software mode
FindDAC(selected_channel, 1);
test_bit = 1;
done = 1;
for(i = 0; i < NUM_SENSOR_CAL; i++)
{
// skip if the channel is not selected
if(test_bit & selected_channel)
{
current[i] = ESI_getAFE1DACValue(i * 2);
// Record max and min value
if(current[i] > max[i])
{
max[i] = current[i];
}
if(current[i] < min[i])
{
min[i] = current[i];
}
// Update average and hysteresis level
average[i] = (max[i] + min[i]) >> 1;
hysteresis[i] = (max[i] - min[i]) >> 3;
if(hysteresis[i] < MIN_HYSTERESIS)
{
hysteresis[i] = MIN_HYSTERESIS;
}
hysteresis[i] >>= 1;
hysteresis_hi[i] = average[i] + hysteresis[i];
hysteresis_lo[i] = average[i] - hysteresis[i];
// Determine output state based on hysteresis_hi and hysteresis_lo
if(current[i] < hysteresis_lo[i])
{
current_state[i] = 0;
}
else if(current[i] > hysteresis_hi[i])
{
current_state[i] = 1;
}
else
{
current_state[i] = 2;
}
// If there is state change, proceed to next step
switch(current_state[i])
{
case 0:
case 1:
if(previous_state[i] != current_state[i])
{
step[i]++;
previous_state[i] = current_state[i];
}
break;
default:
break;
}
// Any selected sensor which has not finished calibration will set done to zero
if(step[i] < STEP_TO_FINISH)
{
done = 0;
}
}
test_bit <<= 1;
}
}
while(!done);
// Record DAC Values
test_bit = 1;
done = ESI_DAC1_REG0; // Temp value for recording DAC
for(i = 0; i < NUM_SENSOR_CAL; i++)
{
if(test_bit & selected_channel)
{
ESI_setAFE1DACValue(hysteresis_hi[i], done++);
ESI_setAFE1DACValue(hysteresis_lo[i], done++);
}
test_bit <<= 1;
}
}
//*****************************************************************************
//
//! Find the current oscillating level, using software mode
//!
//!
//! \return None
//
//*****************************************************************************
static void FindDAC(unsigned char selected_channel,
unsigned char software_trigger)
{
// DAC Level tester, using successive approximation approach
unsigned int DAC_BIT = 0x0800, Prev_DAC_BIT = 0x0C00;
unsigned int i;
unsigned int test_bit, DAC_index;
// Set initial DAC value for each selected channel
// AFE 1
if(selected_channel & 0x0f)
{
test_bit = 0x01;
DAC_index = ESI_DAC1_REG0;
for(i = 0; i < 4; i++)
{
if(selected_channel & test_bit)
{
ESI_setAFE1DACValue(DAC_BIT, DAC_index++);
ESI_setAFE1DACValue(DAC_BIT, DAC_index++);
}
else
{
DAC_index += 2;
}
test_bit <<= 1;
}
}
// AFE 2
if(selected_channel & 0xf0)
{
test_bit = 0x10;
DAC_index = ESI_DAC2_REG0;
for(i = 0; i < 4; i++)
{
if(selected_channel & test_bit)
{
ESI_setAFE2DACValue(DAC_BIT, DAC_index++);
ESI_setAFE2DACValue(DAC_BIT, DAC_index++);
}
else
{
DAC_index += 2;
}
test_bit <<= 1;
}
}
ESI_enableInterrupt(ESI_INTERRUPT_ESISTOP); // enable ESISTOP INT
// Find the DAC value for each selected channel
do
{
ESI_clearInterrupt (ESI_INTERRUPT_FLAG_ESISTOP);
if(software_trigger)
{
ESI_TSM_softwareTrigger();
}
__bis_SR_register(LPM3_bits + GIE); // wait for the ESISTOP flag
DAC_BIT >>= 1; // right shift one bit
// AFE 1
if(selected_channel & 0x0f)
{
test_bit = 0x01;
DAC_index = ESI_DAC1_REG0;
for(i = 0; i < 4; i++)
{
if(selected_channel & test_bit)
{
#ifndef INVERTED
if(ESI_getLatchedComparatorOutput(test_bit) ==
ESI_AFE_OUTPUT_HIGH)
#else
if(ESI_getLatchedComparatorOutput(test_bit) ==
ESI_AFE_OUTPUT_LOW)
#endif
{
ESI_setAFE1DACValue(ESI_getAFE1DACValue(
DAC_index) | DAC_BIT,
DAC_index);
DAC_index++;
ESI_setAFE1DACValue(ESI_getAFE1DACValue(
DAC_index) | DAC_BIT,
DAC_index);
DAC_index++;
}
else
{
ESI_setAFE1DACValue(ESI_getAFE1DACValue(
DAC_index) ^ Prev_DAC_BIT,
DAC_index);
DAC_index++;
ESI_setAFE1DACValue(ESI_getAFE1DACValue(
DAC_index) ^ Prev_DAC_BIT,
DAC_index);
DAC_index++;
}
}
else
{
DAC_index += 2;
}
test_bit <<= 1;
}
}
// AFE 2
if(selected_channel & 0xf0)
{
test_bit = 0x10;
DAC_index = ESI_DAC2_REG0;
for(i = 0; i < 4; i++)
{
if(selected_channel & test_bit)
{
#ifndef INVERTED
if(ESI_getLatchedComparatorOutput(test_bit) ==
ESI_AFE_OUTPUT_HIGH)
#else
if(ESI_getLatchedComparatorOutput(test_bit) ==
ESI_AFE_OUTPUT_LOW)
#endif
{
ESI_setAFE1DACValue(ESI_getAFE2DACValue(
DAC_index) | DAC_BIT,
DAC_index);
DAC_index++;
ESI_setAFE1DACValue(ESI_getAFE2DACValue(
DAC_index) | DAC_BIT,
DAC_index);
DAC_index++;
}
else
{
ESI_setAFE1DACValue(ESI_getAFE2DACValue(
DAC_index) ^ Prev_DAC_BIT,
DAC_index);
DAC_index++;
ESI_setAFE1DACValue(ESI_getAFE2DACValue(
DAC_index) ^ Prev_DAC_BIT,
DAC_index);
DAC_index++;
}
}
else
{
DAC_index += 2;
}
test_bit <<= 1;
}
}
Prev_DAC_BIT >>= 1; // right shift one bit
}
while(DAC_BIT);
ESI_disableInterrupt(ESI_INTERRUPT_ESISTOP);
__no_operation();
}
//*****************************************************************************
//
//! Close the doxygen group for esi_api
//! @}
//
//*****************************************************************************
#endif