📄 lh7a404_adc_driver.c
字号:
/***********************************************************************
* $Workfile: lh7a404_adc_driver.c $
* $Revision: 1.0 $
* $Author: WellsK $
* $Date: Oct 15 2003 17:24:44 $
*
* Project: LH7A404 ADC driver
*
* Description:
* This file contains driver support for the ADC module on the
* LH7A404
*
* Notes:
* The number of different configurations supported by the ADC
* is beyond the scope of this driver. This driver provides the
* following basic functions:
* Sequenced analog to digital conversions (polled, interrupt)
* Touchscreen conversions (polled, interrupt)
* Pendown state detect to touchscreen conversions (interrupt)
* Brownout interrupt handling (interrupt only)
* ADC status polling and general configuration
*
* Revision History:
* $Log: //smaicnt2/pvcs/VM/sharpmcu/archives/sharpmcu/software/csps/lh7a404/source/lh7a404_adc_driver.c-arc $
*
* Rev 1.0 Oct 15 2003 17:24:44 WellsK
* Initial revision.
*
*
***********************************************************************
* SHARP MICROELECTRONICS OF THE AMERICAS MAKES NO REPRESENTATION
* OR WARRANTIES WITH RESPECT TO THE PERFORMANCE OF THIS SOFTWARE,
* AND SPECIFICALLY DISCLAIMS ANY RESPONSIBILITY FOR ANY DAMAGES,
* SPECIAL OR CONSEQUENTIAL, CONNECTED WITH THE USE OF THIS SOFTWARE.
*
* SHARP MICROELECTRONICS OF THE AMERICAS PROVIDES THIS SOFTWARE SOLELY
* FOR THE PURPOSE OF SOFTWARE DEVELOPMENT INCORPORATING THE USE OF A
* SHARP MICROCONTROLLER OR SYSTEM-ON-CHIP PRODUCT. USE OF THIS SOURCE
* FILE IMPLIES ACCEPTANCE OF THESE CONDITIONS.
*
* COPYRIGHT (C) 2001 SHARP MICROELECTRONICS OF THE AMERICAS, INC.
* CAMAS, WA
**********************************************************************/
#include "lh7a404_adc_driver.h"
#include "lh7a404_csc_driver.h"
/***********************************************************************
* ADC driver private data and types
**********************************************************************/
/* Size of the ADC receive ring buffer */
#define ADC_RING_BUFSIZE 64
/* Function prototype used for polled and interrupt driven reads */
typedef INT_32 (*ADC_RFUNC_T) (void *, void *, INT_32);
/* ADC device configuration structure type */
typedef struct
{
BOOL_32 init; /* Device initialized flag */
ADC_REGS_T *regptr; /* Pointer to ADC registers */
UNS_16 rx[ADC_RING_BUFSIZE]; /* ADC data ring buffer */
INT_32 rx_head; /* ADC ring buffer head index */
INT_32 rx_tail; /* ADC ring buffer tail index */
UNS_16 conv_count; /* Number of conversions to perform */
PFV bro_cbfunc; /* Brown interrupt callback function */
PFV pd_cbfunc; /* Pendown interrupt completion callback
function */
PFV eos_cbfunc; /* End of sequence interrupt callback
function */
} ADC_CFG_T;
/* ADC device configuration structure */
STATIC ADC_CFG_T adccfg;
/***********************************************************************
* ADC driver public functions
**********************************************************************/
/***********************************************************************
*
* Function: adc_default
*
* Purpose: Places the ADC interface and controller in a default state
*
* Processing:
* Disable ADC interrupts, set ADC power control to off (idle) with
* maximum clock divider and 1 conversion, set general configuration
* to continuous conversion mode. Set up each MUX input to maximum
* clock with default references. Set up idle high and low control
* words. Clear the ADC FIFO and clear any latched interrupts.
*
* Parameters:
* adcregs: Pointer to an ADC register set
*
* Outputs: None
*
* Returns: Nothing
*
* Notes: None
*
**********************************************************************/
STATIC void adc_default(ADC_REGS_T *adcregs)
{
INT_32 idx;
/* Setup default state of ADC as idle, with all channels set up
in a safe configuration, and all interrupts masked */
/* Mask all interrupts */
adcregs->adcie = 0;
/* Setup mode as disabled, 1 conversion in a sequence, and
maximum ADC clock divider */
adcregs->adcpcr = (ADC_NOC_SET(1) | ADC_PWM_ALL_OFF |
ADC_CLKSEL_DIV128);
/* Set conversion mode to continuous with a single FIFO entry
watermark level */
adcregs->adcgencfg = (ADC_SSM_SSB | ADC_WM_SET(1));
/* Set up each control bank register to use a linear analog
input mapped array with maximum settling time */
for (idx = 0; idx <= 15; idx++)
{
/* High control word */
adcregs->adchicl[idx] = (ADC_SETTIME(0X1FF) |
ADC_INPSEL(idx) | ADC_INM_GND | ADC_REF_VREFP);
/* Low control word */
adcregs->adclocl[idx] = ADC_REF_VREFN;
}
/* Setup idle mode high and low words using analog input 0
as the default idle input */
adcregs->adcidlehi = (ADC_SETTIME(0X1FF) | ADC_INP_AN0 |
ADC_INM_GND | ADC_REF_VREFP);
adcregs->adcidlelo = ADC_REF_VREFP;
/* Make sure the FIFO is clear */
while ((adcregs->adcfifosts & ADC_FIFO_EMPTY) == 0)
{
idx = (INT_32) adcregs->adcresults;
}
/* Clear pending ADC interrupts */
adcregs->adcic = (ADC_EOS_CLR | ADC_PEN_CLR | ADC_BROWNOUT_CLR);
}
/***********************************************************************
*
* Function: adc_add_sequence_entry
*
* Purpose: Adds a new sample entry to the sequence list
*
* Processing:
* If the number of existing conversion sequence entries is greater
* than 16, then return _ERROR to the caller. Otherwise, generate
* the high and low sequence control words and place them into the
* the sequence register array indexed by conv_count. Set status to
* conv_count and increment conv_count by one. Return conv_count to
* the caller.
*
* Parameters:
* adc_ch_cfgptr: Pointer to a channel configuration structure
* adccfgptr: Pointer to ADC config structure
*
* Outputs: None
*
* Returns: A key to the new sequence entry (0 to 15)
*
* Notes: None
*
**********************************************************************/
STATIC STATUS adc_add_sequence_entry(ADC_CH_CONV_T *adc_ch_cfgptr,
ADC_CFG_T *adccfgptr)
{
UNS_32 tmphi, tmplo;
STATUS status = _ERROR;
/* Limit conversion count to 16 conversions */
if (adccfgptr->conv_count < 16)
{
/* Build the high and low control words based on the passed
channel configuration values */
tmphi = (ADC_SETTIME(adc_ch_cfgptr->settle_clks) |
ADC_INPSEL(adc_ch_cfgptr->inpc) |
ADC_INNSEL(adc_ch_cfgptr->innc) |
ADC_REFP_SEL(adc_ch_cfgptr->vrefp));
/* Build and save the control bank low word register */
tmplo = (ADC_REFN_SEL(adc_ch_cfgptr->vrefn) |adc_ch_cfgptr->bias);
/* Write registers */
adccfgptr->regptr->adchicl[adccfgptr->conv_count] = tmphi;
adccfgptr->regptr->adclocl[adccfgptr->conv_count] = tmplo;
/* Update the number of conversions in the sequence */
tmphi = adccfgptr->regptr->adcpcr & ~ADC_NOC_MASK;
adccfgptr->regptr->adcpcr = (tmphi | adccfgptr->conv_count);
/* Save key return value */
status = (STATUS) adccfgptr->conv_count;
/* Increment conversion count value */
adccfgptr->conv_count++;
}
return status;
}
/***********************************************************************
*
* Function: adc_chg_sequence_entry
*
* Purpose: Change an existing sequence entry
*
* Processing:
* If the sequence key (in the ADC_CH_CONV_T structure) is not
* within the limits of the converion list, return _ERROR to the
* caller. Otherwise, generate the new high and low configuration
* words for the channel indicated by the sequence key and update
* the registers in the ADC for that channel. Return _NO_ERROR to
* the caller.
*
* Parameters:
* adc_ch_cfgptr: Pointer to a channel configuration structure
* adccfgptr: Pointer to ADC config structure
*
* Outputs: None
*
* Returns: _ERROR is the sequence key is invalid, otherwise _NO_ERROR.
*
* Notes: None
*
**********************************************************************/
STATIC STATUS adc_chg_sequence_entry(ADC_CH_CONV_T *adc_ch_cfgptr,
ADC_CFG_T *adccfgptr)
{
UNS_32 tmphi, tmplo;
STATUS status = _ERROR;
/* Make sure the passed sequence entry is valid */
if (adc_ch_cfgptr->chkey <= adccfgptr->conv_count)
{
/* Key is valid */
/* Build the high and low control words based on the passed
channel configuration values */
tmphi = (ADC_SETTIME(adc_ch_cfgptr->settle_clks) |
ADC_INPSEL(adc_ch_cfgptr->inpc) |
ADC_INNSEL(adc_ch_cfgptr->innc) |
ADC_REFP_SEL(adc_ch_cfgptr->vrefp));
/* Build and save the control bank low word register */
tmplo = (ADC_REFN_SEL(adc_ch_cfgptr->vrefn) |
adc_ch_cfgptr->bias);
/* Write registers */
adccfgptr->regptr->adchicl[adc_ch_cfgptr->chkey] = tmphi;
adccfgptr->regptr->adclocl[adc_ch_cfgptr->chkey] = tmplo;
status = _NO_ERROR;
}
return status;
}
/***********************************************************************
*
* Function: adc_ring_fill
*
* Purpose: Move data from the ADC FIFO to the driver ring buffer
*
* Processing:
* While the ADC FIFO is not empty, copy an entry from the ADC
* FIFO into the ADC driver ring buffer. Increment the ring buffer
* head pointer. If it exceeds the ring buffer size, reset the
* head pointer to 0.
*
* Parameters:
* adccfgptr: Pointer to ADC config structure
*
* Outputs: None
*
* Returns: Nothing
*
* Notes: None
*
**********************************************************************/
STATIC void adc_ring_fill(ADC_CFG_T *adccfgptr)
{
ADC_REGS_T *adcregsptr = (ADC_REGS_T *) adccfgptr->regptr;
/* Continue stuffing the receive ring FIFO until the receive
FIFO is empty */
while ((adcregsptr->adcfifosts & ADC_FIFO_EMPTY) == 0)
{
adccfgptr->rx[adccfgptr->rx_head] =
(UNS_16) adcregsptr->adcresults;
/* Increment receive ring buffer head pointer */
adccfgptr->rx_head++;
if (adccfgptr->rx_head >= ADC_RING_BUFSIZE)
{
adccfgptr->rx_head = 0;
}
}
}
/***********************************************************************
* ADC driver public functions
**********************************************************************/
/***********************************************************************
*
* Function: adc_open
*
* Purpose: Open the ADC
*
* Processing:
* If init is not FALSE, return 0x00000000 to the caller. Otherwise,
* set init to TRUE, save the ADC peripheral register set address,
* and initialize the ADC interface and controller to a default
* state by calling adc_default(), and return a pointer to the ADC
* config structure to the caller.
*
* Parameters:
* ipbase: ADC descriptor device address
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -