From 9c88423d66e9b4eafecc658058f25f79e08ff120 Mon Sep 17 00:00:00 2001 From: Stephane D'Alu Date: Thu, 7 Jul 2016 20:41:09 +0200 Subject: move functions to hal_qei.*, fixed comments --- os/hal/src/hal_qei.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) (limited to 'os/hal/src') 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 @@ -46,6 +46,91 @@ /* Driver exported functions. */ /*===========================================================================*/ +/** + * @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 @@ -167,6 +252,44 @@ qeicnt_t qeiGetCount(QEIDriver *qeip) { return cnt; } +/** + * @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. * -- cgit v1.2.3