Пример #1
0
S_API double s_rel_diff(double a, double b)
{
	double c = S_ABS(a);
	double d = S_ABS(b);


	d = S_MAX(c, d);

	return d == 0.0 ? 0.0 : (S_ABS(a - b) / d);
}
Пример #2
0
/**
 * @brief  Computes the values of the wakeup timer counter and prescaler from the user time expressed in millisecond.
 *         The prescaler and the counter values are computed maintaining the prescaler value as
 *         small as possible in order to obtain the best resolution, and in the meantime minimizing the error.
 * @param  fDesiredMsec desired wakeup timeout in millisecs.
 *         This parameter must be a float. Since the counter and prescaler are 8 bit registers the maximum
 *         reachable value is maxTime = fTclk x 256 x 256.
 * @param  pcCounter pointer to the variable in which the value for the wakeup timer counter has to be stored.
 *         This parameter must be a uint8_t*.
 * @param  pcPrescaler pointer to the variable in which the value for the wakeup timer prescaler has to be stored.
 *         This parameter must be an uint8_t*.
 * @retval None
 */
void SpiritTimerComputeWakeUpValues(float fDesiredMsec , uint8_t* pcCounter , uint8_t* pcPrescaler)
{
  uint8_t b0, a0;
  uint32_t n;
  int32_t err, err_min;

  /* Check the parameters */
  s_assert_param(IS_WKUP_TIMEOUT(fDesiredMsec));

  n = (uint32_t)((fDesiredMsec*1000)/WAKEUP_TCLK);
  err_min = n;
  /* These are the initial values for the prescaler and the counter, where the prescaler
     is settled to the minimum value and the counter accordingly. In order to avoid a zero
     division for the counter the prescaler is increased by one. Then because the wakeup timeout
     is calculated as: Twu=(PRESCALER +1)*(COUNTER+1)*Tck the counter and the prescaler are decreased by one.*/
  *pcPrescaler = a0 = (n/0xFF)+1;
  *pcCounter = b0 = (n / *pcPrescaler);
  (*pcPrescaler)--;

  /* If the desired value is over the maximum limit, the counter and the
  prescaler are settled to their maximum values, and doesn't execute the routine */
  if(fDesiredMsec>1888.0)
  {
    *pcCounter = 0xFF;
    *pcPrescaler = 0xFF;
    return;
  }

  /* Iterative cycle to minimize the error */
  for (; ; (*pcPrescaler)++)
  {
    *pcCounter = ((n/(*pcPrescaler+1))-1);
    err = (((int32_t)*pcPrescaler)+1) * (((int32_t)*pcCounter)+1) - (int32_t)n;
    if (S_ABS(err) > (*pcPrescaler / 2))
    {
      (*pcCounter)++;
      err = (((int32_t)*pcPrescaler)+1) * (((int32_t)*pcCounter)+1) - (int32_t)n;
    }
    if (S_ABS(err) < S_ABS(err_min))
    {
      err_min = err;
      a0 = *pcPrescaler;
      b0 = *pcCounter;
      if (err == 0) break;
    }
    if(*pcPrescaler == 0xFF) break;
  }
  *pcPrescaler = a0;
  *pcCounter = b0;

}
Пример #3
0
/**
 * @brief  Computes the values of the wakeup timer counter and prescaler from the user time expressed in millisecond.
 *         The prescaler and the counter values are computed maintaining the prescaler value as
 *         small as possible in order to obtain the best resolution, and in the meantime minimizing the error.
 * @param  fDesiredMsec desired wakeup timeout in millisecs.
 *         This parameter must be a float. Since the counter and prescaler are 8 bit registers the maximum
 *         reachable value is maxTime = fTclk x 256 x 256.
 * @param  pcCounter pointer to the variable in which the value for the wakeup timer counter has to be stored.
 *         This parameter must be a uint8_t*.
 * @param  pcPrescaler pointer to the variable in which the value for the wakeup timer prescaler has to be stored.
 *         This parameter must be an uint8_t*.
 * @retval None
 */
void SpiritTimerComputeWakeUpValues(float fDesiredMsec , uint8_t* pcCounter , uint8_t* pcPrescaler)
{
  float rco_freq,err;
  uint32_t n;
  
  rco_freq=((float)SpiritTimerGetRcoFrequency())/1000;
  
  /* N cycles in the time base of the timer: 
     - clock of the timer is RCO frequency
     - divide times 1000 more because we have an input in ms (variable rco_freq is already this frequency divided by 1000)
  */
  n=(uint32_t)(fDesiredMsec*rco_freq);
    
  /* check if it is possible to reach that target with prescaler and counter of spirit1 */
  if(n/0xFF>0xFD)
  {
    /* if not return the maximum possible value */
    (*pcCounter) = 0xFF;
    (*pcPrescaler) = 0xFF;
    return;
  }
  
  /* prescaler is really 2 as min value */
  (*pcPrescaler)=(n/0xFF)+2;
  (*pcCounter) = n / (*pcPrescaler);
  
  /* check if the error is minimum */
  err=S_ABS((float)(*pcCounter)*(*pcPrescaler)/rco_freq-fDesiredMsec);
  
  if((*pcCounter)<=254)
  {
    if(S_ABS((float)((*pcCounter)+1)*(*pcPrescaler)/rco_freq-fDesiredMsec)<err)
      (*pcCounter)=(*pcCounter)+1;
  }
    
  /* decrement prescaler and counter according to the logic of this timer in spirit1 */
  (*pcPrescaler)--;
  if((*pcCounter)>1)
    (*pcCounter)--;
  else
    (*pcCounter)=1;
}
Пример #4
0
/**
 * @brief  Computes the values of the rx_timeout timer counter and prescaler from the user time expressed in millisecond.
 *         The prescaler and the counter values are computed maintaining the prescaler value as
 *         small as possible in order to obtain the best resolution, and in the meantime minimizing the error.
 * @param  fDesiredMsec desired rx_timeout in millisecs.
 *         This parameter must be a float. Since the counter and prescaler are 8 bit registers the maximum
 *         reachable value is maxTime = fTclk x 255 x 255.
 * @param  pcCounter pointer to the variable in which the value for the rx_timeout counter has to be stored.
 *         This parameter must be a uint8_t*.
 * @param  pcPrescaler pointer to the variable in which the value for the rx_timeout prescaler has to be stored.
 *         This parameter must be an uint8_t*.
 * @retval None
 */
void SpiritTimerComputeRxTimeoutValues(float fDesiredMsec , uint8_t* pcCounter , uint8_t* pcPrescaler)
{
  uint8_t b0, a0, xtal;
  uint32_t n;
  int32_t err, err_min;

  /* Reads the Xtal configuration in the ANA_FUNC_CONF_0 register */
  g_xStatus = SpiritSpiReadRegisters(ANA_FUNC_CONF0_BASE, 1, &xtal);

  /* Check the parameters and set the number of clock cylces according to the xtal configuration */
  if((xtal & 0x40)== SELECT_24_26_MHZ_MASK)
  {
    /* Check the parameters */
    s_assert_param(IS_RX_TIMEOUT_26MHz(fDesiredMsec));
    /* If the desired value is over the maximum limit, the counter and the
    prescaler are settled to their maximum values, and doesn't execute the routine */
    if(fDesiredMsec>3026.0)
    {
      *pcCounter = 0xFF;
      *pcPrescaler = 0xFF;
      return;
    }
    n = (uint32_t)((fDesiredMsec*1000)/RX_TCLK_26MHz);
  }
  else
  {
    /* Check the parameters */
    s_assert_param(IS_RX_TIMEOUT_24MHz(fDesiredMsec));
    /* If the desired value is over the maximum limit the counter and the
    prescaler are settled to their maximum values, and doesn't execute the routine */
    if(fDesiredMsec>3278.0)
    {
      *pcCounter = 0xFF;
      *pcPrescaler = 0xFF;
      return;
    }
    n = (uint32_t)((fDesiredMsec*1000)/RX_TCLK_24MHz);
  }

  err_min = n;
  /* These are the initial values for the prescaler and the counter, where the prescaler
     is settled to the minimum value and the counter accordingly. In order to avoid a zero
     division for the counter the prescaler is increased by one.*/

  *pcPrescaler = a0 = ((n-1)/0xFF)+1;
  *pcCounter = b0 = (n / *pcPrescaler);

  /* Iterative cycle to minimize the error */
  for (; ; (*pcPrescaler)++)
  {
    *pcCounter = n / *pcPrescaler;
    err = 1+((int32_t)(*pcPrescaler)+1) * ((int32_t)*pcCounter) - (int32_t)n;
    if (S_ABS(err) > (*pcPrescaler / 2))
    {
      (*pcCounter)++;
      err = 1+((int32_t)(*pcPrescaler)+1) * ((int32_t)*pcCounter) - (int32_t)n;
    }
    if (S_ABS(err) < S_ABS(err_min))
    {
      err_min = err;
      a0 = *pcPrescaler;
      b0 = *pcCounter;
      if (err == 0) break;
    }
    if(*pcPrescaler == 0xFF) break;
  }
  *pcPrescaler = a0;
  *pcCounter = b0;

}