diff options
Diffstat (limited to 'os/hal/src')
| -rw-r--r-- | os/hal/src/hal_qei.c | 123 | 
1 files changed, 123 insertions, 0 deletions
| diff --git a/os/hal/src/hal_qei.c b/os/hal/src/hal_qei.c index a2b7303..abecdf8 100644 --- a/os/hal/src/hal_qei.c +++ b/os/hal/src/hal_qei.c @@ -47,6 +47,91 @@  /*===========================================================================*/
  /**
 + * @brief   Helper for correclty handling overflow/underflow
 + *
 + * @details Underflow/overflow will be handled according to mode:
 + *          QEI_OVERFLOW_WRAP:    counter value will wrap around.
 + *          QEI_OVERFLOW_DISCARD: counter will not change
 + *          QEI_OVERFLOW_MINMAX:  counter will be updated upto min or max.
 + *
 + * @note    This function is for use by low level driver.
 + *
 + * @param[in,out] count counter value
 + * @param[in,out] delta adjustment value
 + * @param[in]     min   minimum allowed value for counter
 + * @param[in]     max   maximum allowed value for counter
 + * @param[in]     mode  how to handle overflow
 + *
 + * @return        true if counter underflow/overflow occured or
 + *                was due to occur
 + *
 + */
 +bool qei_adjust_count(qeicnt_t *count, qeidelta_t *delta,
 +		      qeicnt_t min, qeicnt_t max, qeioverflow_t mode) {
 +  /* For information on signed integer overflow see:
 +   * https://www.securecoding.cert.org/confluence/x/RgE
 +   */
 +
 +  /* Get values */
 +  const qeicnt_t   _count = *count;
 +  const qeidelta_t _delta = *delta;
 +
 +  /* Overflow operation
 +   */
 +  if ((_delta > 0) && (_count > (max - _delta))) {
 +    switch(mode) {
 +    case QEI_OVERFLOW_WRAP:
 +      *delta = 0;
 +      *count = (min + (_count - (max - _delta))) - 1;
 +      break;
 +#if QEI_USE_OVERFLOW_DISCARD == TRUE
 +    case QEI_OVERFLOW_DISCARD:
 +      *delta = _delta;
 +      *count = _count;
 +      break;
 +#endif
 +#if QEI_USE_OVERFLOW_MINMAX == TRUE
 +    case QEI_OVERFLOW_MINMAX:
 +      *delta = _count - (max - _delta);
 +      *count = max;
 +      break;
 +#endif
 +    }
 +    return true;
 +    
 + /* Underflow operation
 +  */
 +  } else if ((_delta < 0) && (_count < (min - _delta))) {
 +    switch(mode) {
 +    case QEI_OVERFLOW_WRAP:
 +      *delta = 0;
 +      *count = (max + (_count - (min - _delta))) + 1;
 +    break;
 +#if QEI_USE_OVERFLOW_DISCARD == TRUE
 +    case QEI_OVERFLOW_DISCARD:
 +      *delta = _delta;
 +      *count = _count;
 +      break;
 +#endif
 +#if QEI_USE_OVERFLOW_MINMAX == TRUE
 +    case QEI_OVERFLOW_MINMAX:
 +      *delta = _count - (min - _delta);
 +      *count = min;
 +      break;
 +#endif
 +    }
 +    return true;
 +
 +  /* Normal operation
 +   */
 +  } else {
 +    *delta = 0;
 +    *count = _count + _delta;
 +    return false;
 +  }
 +}
 +
 +/**
   * @brief   QEI Driver initialization.
   * @note    This function is implicitly invoked by @p halInit(), there is
   *          no need to explicitly initialize the driver.
 @@ -168,6 +253,44 @@ qeicnt_t qeiGetCount(QEIDriver *qeip) {  }
  /**
 + * @brief   Set counter value.
 + *
 + * @param[in] qeip      pointer to the @p QEIDriver object.
 + * @param[in] value     the new counter value.
 + *
 + * @api
 + */
 +void qeiSetCount(QEIDriver *qeip, qeicnt_t value) {
 +  osalDbgCheck(qeip != NULL);
 +  osalDbgAssert((qeip->state == QEI_READY) || (qeip->state == QEI_ACTIVE),
 +		"invalid state");
 +
 +  osalSysLock();
 +  qei_lld_set_count(qeip, value);
 +  osalSysUnlock();
 +}
 +
 +/**
 + * @brief   Adjust the counter by delta.
 + *
 + * @param[in] qeip      pointer to the @p QEIDriver object.
 + * @param[in] delta     the adjustement value.
 + * @return              the remaining delta (can occur during overflow).
 + *
 + * @api
 + */
 +qeidelta_t qeiAdjust(QEIDriver *qeip, qeidelta_t delta) {
 +  osalDbgCheck(qeip != NULL);
 +  osalDbgAssert((qeip->state == QEI_ACTIVE), "invalid state");
 +
 +  osalSysLock();
 +  delta = qei_lld_adjust_count(qeip, delta);
 +  osalSysUnlock();
 +
 +  return delta;
 +}
 +
 +/**
   * @brief   Returns the counter delta from last reading.
   *
   * @param[in] qeip      pointer to the @p QEIDriver object
 | 
