⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lh79524_adc_driver.c

📁 LH79524SoftwareLH79524 Software
💻 C
📖 第 1 页 / 共 4 页
字号:
      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_time_2_clock(adccfgptr, adc_ch_cfgptr->settle_time))
      | 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;
    }
  }
}

/*********************************************************************** 
* 
* Function: adc_setup_4wire_touchscreen
* 
* Purpose: 
*  Set up the sequencer for a 4-wire touch screen measurement.
* 
* Processing: 
*  Initialize the adc to its default state.
*  Map all touchscreen pins to ADC input
*  Set up the idle step to prevent false pen auto-triggering.
*  Flush the result FIFO.
*  Clear the pen and end of sequence interrupts.
*  Set up the sequence as follows:
*      0. Strong pullup on X+ pin, other pins float.
*         Measure on pin x+. This measurement will be discarded.
*         This step de-glitches any partial triggers.
*      1. Weak pullup on X+ pin, X- floats, Y- to Ground and neg
*         ref, Y+ floats (ratiometric).
*         Measure on X+ pin. This measurement is used to verify
*         the pen was down at the beginning of the coordinate
*         measurement.
*      2. X+ and X- float, Y- to Ground and neg
*         ref, Y+ to VDDA_ADC and positive reference (ratiometric).
*         Measure on pin x+. This is the X measurement.
*      3. Repeat the X measurement 3 more times (we will average
*         4 measurements to improve signal-to-noise.
*      4. Y+ and Y- float, X- to Ground and neg
*         ref, X+ to VDDA_ADC and positive reference (ratiometric).
*         Measure on pin Y+. This is the Y measurement.
*      5. Repeat the Y measurement 3 more times (we will average
*         4 measurements to improve signal-to-noise.
*      6. Strong pullup on X+ pin, other pins float.
*         Measure on pin x+. This measurement will be discarded.
*         This step de-glitches any partial triggers.
*      7. Weak pullup on X+ pin, X- floats, Y- to Ground and neg
*         ref, Y+ floats (ratiometric).
*         Measure on X+ pin. This measurement is used to verify
*         the pen was down at the end of the coordinate
*         measurement. 
* 
* Parameters: 
*  tsc_cfg:				Pointer to touch screen config structure
*  adccfgptr:     Pointer to ADC config structure
* 
* Outputs: None. 
* 
* Returns: Nothing
*
* Notes: 
*  This ADC configuration is intended to be used in conjunction
*  with an end of sequence interrupt handler that follows the following
*  algorithm
*      1. Read and discard the first measurement in the result FIFO
*      2. Read the 2nd result. If the measured voltage is below a
*         threashhold, then the pen is down, otherwise it is up. If
*         the pen is up, read and discard the remaining measurements;
*         then return from interrupt.
*      3. Pen is down. Read and average the next 4 results as the X
*         coordinate.
*      4. Read and average the next 4 results as the Y coordinate
*         measurement.
*      5  Read and discard the next result.
*      6. Read the last FIFO result. If the measured voltage is
*         below a threashhold, then the pen is still down, otherwise
*         it is up. If the pen is up, return from interrupt. If the
*         pen is still down, report the new X and Y measurements.
*
*  There are sevreal ways to trigger measurements. 
*  The recomended way that is more power efficient is to set up a a pen
*  interrupt handler that switches the ADC module for pen-triggered
*  to soft_triggered measurements. Initially, the ADC is set up
*  for pen-triggered measurements. On pen down, the pen interrupt
*  handler switches the ADC to software-triggered measurements.
*  The system polls the touch screen periodically 
*  until the end of sequence interrupt handler detects pen up. 
*  The handler then switches the ADC back to pen-triggered measurements.
* 
**********************************************************************/ 
static STATUS adc_setup_4wire_touchscreen(ADC_TSC_CONV_T* tsc_cfg, 
                                          ADC_CFG_T *adccfgptr)
{
  ADC_CH_CONV_T step; /* a step in the sequence*/
  ADC_REGS_T *adcregsptr = adccfgptr->regptr;
  UNS_32 tmp;
  ADC_VREFP_T pen_detect_p = ADC_REFP_VREF;
  ADC_VREFN_T pen_detect_n = ADC_REFN_VREF;
  
  while ((adcregsptr->adcfifosts & ADC_FIFO_EMPTY) == 0)
  {
    tmp = adcregsptr->adcresults;
  }
  
  adcregsptr->adcic = (ADC_EOS_CLR | ADC_PEN_CLR);
  /* Empty ring buffer and set conversion counter
  to 0 */
  adccfgptr->rx_head = adccfgptr->rx_tail = 0;
  adccfgptr->conv_count = 0;

  /* It is only necessary to turn on the reference buffer if the on-chip
  reference is used as the positive reference for a measurement. If
  an external reference is used (e.g. for ratiometric measurements),
  then the reference buffer can be off (saves power) */
  if(tsc_cfg->vrefp_x != ADC_REFP_VN8)
  {
    adcregsptr->adcpcr |= ADC_REF_ENABLE;
  }
  else
  {
    pen_detect_p = tsc_cfg->vrefp_x;
    pen_detect_n = tsc_cfg->vrefn_x;
  }
  
  /* Build and save the idle channel step */
  tmp = (ADC_SETTIME(adc_time_2_clock(adccfgptr, tsc_cfg->settle_time)) |
    ADC_INPSEL(ADC_ANALOG_1) |
    ADC_INNSEL(ADC_REFN_VREFN) |
    ADC_REFP_SEL(pen_detect_p));
  adcregsptr->adcidlehi = tmp;
  
  tmp = (ADC_REFN_SEL(pen_detect_n) |
    (ADC_FET_AN0_VDDA1K | ADC_FET_AN3_GND));
  adcregsptr->adcidlelo = tmp;
  
  /* for rest of the steps keep settling time same */
  step.settle_time = tsc_cfg->settle_time;
  
  /* Build step 0 - prior to 1st pen-down check*/
  step.inpc = ADC_ANALOG_0;
  step.innc = ADC_REFN_VREFN;
  step.vrefp = pen_detect_p; 
  step.vrefn = pen_detect_n; 
  step.bias = ADC_FET_AN0_VDDA;
  adc_add_sequence_entry(&step, adccfgptr);
  
  /* Build step 1 - check pen down state prior to coords*/
  step.inpc = ADC_ANALOG_0;
  step.innc = ADC_REFN_VREFN;
  step.vrefp = pen_detect_p; 
  step.vrefn = pen_detect_n; 
  step.bias = (ADC_FET_AN0_VDDA1K | ADC_FET_AN3_GND);
  adc_add_sequence_entry(&step, adccfgptr);
  
  /* Build step 2,3,4 & 5 - measure x coords*/
  for(tmp = 0; tmp < 4; tmp++)
  {
    step.inpc = ADC_ANALOG_2;
    step.innc = ADC_REFN_VREFN;
    step.vrefp = tsc_cfg->vrefp_x; 
    step.vrefn = tsc_cfg->vrefn_x; 
    step.bias = (ADC_FET_AN1_GND | ADC_FET_AN0_VDDA);
    adc_add_sequence_entry(&step, adccfgptr);
  }
  
  /* Build step 6,7,8 & 9 - measure y coords*/
  for(tmp = 0; tmp < 4; tmp++)
  {
    step.inpc = ADC_ANALOG_0;
    step.innc = ADC_REFN_VREFN;
    step.vrefp = tsc_cfg->vrefp_y; 
    step.vrefn = tsc_cfg->vrefn_y; 
    step.bias = (ADC_FET_AN3_GND | ADC_FET_AN2_VDDA);
    adc_add_sequence_entry(&step, adccfgptr);
  }
  
  /* Build step 10 - prior to last pen-down check*/
  step.inpc = ADC_ANALOG_0;
  step.innc = ADC_REFN_VREFN;
  step.vrefp = pen_detect_p; 
  step.vrefn = pen_detect_n; 
  step.bias = ADC_FET_AN0_VDDA;
  adc_add_sequence_entry(&step, adccfgptr);
  
  /* Build step 11 - prior to last pen-down check*/
  step.inpc = ADC_ANALOG_0;
  step.innc = ADC_REFN_VREFN;
  step.vrefp = pen_detect_p; 
  step.vrefn = pen_detect_n; 
  step.bias = (ADC_FET_AN0_VDDA1K | ADC_FET_AN3_GND);
  adc_add_sequence_entry(&step, adccfgptr);
  
  
  return _NO_ERROR;
}

/*********************************************************************** 
* 
* Function: adc_setup_5wire_touchscreen
* 
* Purpose: 
*  Set up the sequencer for a 5-wire touch screen measurement.
* 
* Processing: 
*  Initialize the adc to its default state.
*  Map all touchscreen pins to ADC input
*  Set up the idle step to prevent false pen auto-triggering.
*  Flush the result FIFO.
*  Clear the pen and end of sequence interrupts.
*  Set up the sequence as follows:
*      0. Strong pullup on UL pin, other pins float.
*         Measure on pin x+. This measurement will be discarded.
*         This step de-glitches any partial triggers.
*      1. Weak pullup on UL pin, wiper to VSSA_ADC, other pins float.
*         Measure on UL pin. This measurement is used to verify
*         the pen was down at the beginning of the coordinate
*         measurement.
*      2. UL and LL to VDDA_ADC. UR and LR to VSSA_ADC.
*         UL to positive reference and LR to negative reference
*         (ratiometric). Wiper floats.
*         Measure on pin Wiper. This is the X measurement.
*      3. Repeat the X measurement 3 more times (we will average
*         4 measurements to improve signal-to-noise.
*      4. UL and UR to VDDA_ADC. LL and LR to VSSA_ADC.
*         UL to positive reference and LR to negative reference
*         (ratiometric). Wiper floats.
*         Measure on pin Wiper. This is the Y measurement.
*      5. Repeat the Y measurement 3 more times (we will average
*         4 measurements to improve signal-to-noise.
*      6. Strong pullup on UL pin, other pins float.
*         Measure on pin UL. This measurement will be discarded.
*         This step de-glitches any partial triggers.
*      7. Weak pullup on UL pin, wiper to ground.
*         Measure on X+ pin. This measurement is used to verify
*         the pen was down at the end of the coordinate
*         measurement. 
* 
* Parameters: 
*  tsc_cfg:				Pointer to touch screen config structure
*  adccfgptr:     Pointer to ADC config structure
* 
* Outputs: None. 
* 
* Returns: Nothing
*
* Notes: 
*  This ADC configuration is intended to be used in conjunction
*  with an end of sequence interrupt handler that follows the following
*  algorithm
*      1. Read and discard the first measurement in the result FIFO
*      2. Read the 2nd result. If the measured voltage is below a
*         threashhold, then the pen is down, otherwise it is up. If
*         the pen is up, read and discard the remaining measurements;
*         then return from interrupt.
*      3. Pen is down. Read and average the next 4 results as the X
*         coordinate.
*      4. Read and average the next 4 results as the Y coordinate
*         measurement.
*      5  Read and discard the next result.
*      6. Read the last FIFO result. If the measured voltage is
*         below a threashhold, then the pen is still down, otherwise
*         it is up. If the pen is up, return from interrupt. If the
*         pen is still down, report the new X and Y measurements.
*
*  There are sevreal ways to trigger measurements. 
*  The recomended way that is more power efficient is to set up a a pen
*  interrupt handler that switches the ADC module for pen-triggered
*  to soft_triggered measurements. Initially, the ADC is set up
*  for pen-triggered measurements. On pen down, the pen interrupt
*  handler switches the ADC to software-triggered measurements.
*  The system polls the touch screen periodically 
*  until the end of sequence interrupt handler detects pen up. 
*  The handler then switches the ADC back to pen-triggered measurements.
*
**********************************************************************/ 
static STATUS adc_setup_5wire_touchscreen(ADC_TSC_CONV_T* tsc_cfg, 
                                          ADC_CFG_T *adccfgptr)
{
  ADC_CH_CONV_T step; /* a step in the sequence*/
  ADC_REGS_T *adcregsptr = adccfgptr->regptr;
  UNS_32 tmp;
  ADC_VREFP_T pen_detect_p = ADC_REFP_VREF;
  ADC_VREFN_T pen_detect_n = ADC_REFN_VREF;
  
  while ((adcregsptr->adcfifosts & ADC_FIFO_EMPTY) == 0)
  {
    tmp = adcregsptr->adcresults;
  }
  
  adcregsptr->adcic = (ADC_EOS_CLR | ADC_PEN_CLR);
  /* Empty ring buffer and set conversion counter
  to 0 */
  adccfgptr->rx_head = adccfgptr->rx_tail = 0;
  adccfgptr->conv_count = 0;
  
  /* It is only necessary to turn on the reference buffer if the on-chip
  reference is used as the positive reference for a measurement. If
  an external reference is used (e.g. for ratiometric measurements),
  then the reference buffer can be off (saves power) */
  if(tsc_cfg->vrefp_x != ADC_REFP_VN8)
  {
    adcregsptr->adcpcr |= ADC_REF_ENABLE;
  }
  else
  {
    pen_detect_p = tsc_cfg->vrefp_x;
    pen_detect_n = tsc_cfg->vrefn_x;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -