aboutsummaryrefslogtreecommitdiffstats
path: root/os
diff options
context:
space:
mode:
authorStephane D'Alu <sdalu@sdalu.com>2016-07-07 20:41:09 +0200
committerStephane D'Alu <sdalu@sdalu.com>2016-07-07 20:41:09 +0200
commit9c88423d66e9b4eafecc658058f25f79e08ff120 (patch)
tree7a3bd206daee9784bf95c0f4c2cb077f8b195fff /os
parentaf18f7d43fe8f07016e985fed9e5dcd021da3303 (diff)
downloadChibiOS-Contrib-9c88423d66e9b4eafecc658058f25f79e08ff120.tar.gz
ChibiOS-Contrib-9c88423d66e9b4eafecc658058f25f79e08ff120.tar.bz2
ChibiOS-Contrib-9c88423d66e9b4eafecc658058f25f79e08ff120.zip
move functions to hal_qei.*, fixed comments
Diffstat (limited to 'os')
-rw-r--r--os/hal/include/hal_qei.h30
-rw-r--r--os/hal/ports/NRF51/NRF51822/hal_qei_lld.c154
-rw-r--r--os/hal/ports/NRF51/NRF51822/hal_qei_lld.h48
-rw-r--r--os/hal/src/hal_qei.c123
4 files changed, 201 insertions, 154 deletions
diff --git a/os/hal/include/hal_qei.h b/os/hal/include/hal_qei.h
index 92f03fc..1032c84 100644
--- a/os/hal/include/hal_qei.h
+++ b/os/hal/include/hal_qei.h
@@ -65,8 +65,36 @@ typedef struct QEIDriver QEIDriver;
*/
typedef void (*qeicallback_t)(QEIDriver *qeip);
+/**
+ * @brief Driver possible handling of counter overflow/underflow.
+ *
+ * @details When counter is going to overflow, the new value is
+ * computed according to this mode in such a way that
+ * the counter will either wrap around, stay unchange
+ * or reach min/max
+ *
+ * @note All driver implementation should support the
+ * QEI_OVERFLOW_WRAP mode.
+ *
+ * @note Mode QEI_OVERFLOW_DISCARD and QEI_OVERFLOW_MINMAX are included
+ * if QEI_USE_OVERFLOW_DISCARD and QEI_USE_OVERFLOW_MINMAX are
+ * set to TRUE in halconf_community.h and are not necessary supported
+ * by all drivers
+ */
+typedef enum {
+ QEI_OVERFLOW_WRAP = 0, /**< Counter value will wrap around. */
+#if QEI_USE_OVERFLOW_DISCARD == TRUE
+ QEI_OVERFLOW_DISCARD = 1, /**< Counter doesn't change. */
+#endif
+#if QEI_USE_OVERFLOW_MINMAX == TRUE
+ QEI_OVERFLOW_MINMAX = 2, /**< Counter will be updated upto min or max.*/
+#endif
+} qeioverflow_t;
+
+
#include "hal_qei_lld.h"
+
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
@@ -119,6 +147,8 @@ extern "C" {
qeicnt_t qeiGetCount(QEIDriver *qeip);
qeidelta_t qeiUpdate(QEIDriver *qeip);
qeidelta_t qeiUpdateI(QEIDriver *qeip);
+ bool qei_adjust_count(qeicnt_t *count, qeidelta_t *delta,
+ qeicnt_t min, qeicnt_t max, qeioverflow_t mode);
#ifdef __cplusplus
}
#endif
diff --git a/os/hal/ports/NRF51/NRF51822/hal_qei_lld.c b/os/hal/ports/NRF51/NRF51822/hal_qei_lld.c
index 069c362..fbaf3aa 100644
--- a/os/hal/ports/NRF51/NRF51822/hal_qei_lld.c
+++ b/os/hal/ports/NRF51/NRF51822/hal_qei_lld.c
@@ -16,7 +16,7 @@
/**
* @file NRF51/hal_qei_lld.c
- * @brief NRF51 QEI subsystem low level driver header.
+ * @brief NRF51 QEI subsystem low level driver.
*
* @addtogroup QEI
* @{
@@ -28,110 +28,6 @@
/*===========================================================================*/
-/* To be moved in hal_qei */
-/*===========================================================================*/
-
-static inline
-bool qei_adjust_count(qeicnt_t *count, qeidelta_t *delta,
- qeicnt_t min, qeicnt_t max, qeioverflow_t mode) {
- // See: https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow
-
- // 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 HAL_QEI_SUPPORT_OVERFLOW_DISCARD == TRUE
- case QEI_OVERFLOW_DISCARD:
- *delta = _delta;
- *count = _count;
- break;
-#endif
-#if HAL_QEI_SUPPORT_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 HAL_QEI_SUPPORT_OVERFLOW_DISCARD == TRUE
- case QEI_OVERFLOW_DISCARD:
- *delta = _delta;
- *count = _count;
- break;
-#endif
-#if HAL_QEI_SUPPORT_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 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 Set counter value
- *
- * @param[in] qeip pointer to the @p QEIDriver object
- * @param[in] value the 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();
-}
-
-
-/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
@@ -163,7 +59,7 @@ QEIDriver QEID1;
static void serve_interrupt(QEIDriver *qeip) {
NRF_QDEC_Type *qdec = qeip->qdec;
-#if NRF51_QEI_USE_ACC_OVERFLOW_CB == TRUE
+#if NRF51_QEI_USE_ACC_OVERFLOWED_CB == TRUE
/* Accumulator overflowed
*/
if (qdec->EVENTS_ACCOF) {
@@ -180,15 +76,15 @@ static void serve_interrupt(QEIDriver *qeip) {
if (qdec->EVENTS_REPORTRDY) {
qdec->EVENTS_REPORTRDY = 0;
- // Read (and clear counters due to shortcut)
+ /* Read (and clear counters due to shortcut) */
int16_t acc = ( int16_t)qdec->ACCREAD;
uint16_t accdbl = (uint16_t)qdec->ACCDBLREAD;
- // Inverse direction if requested
+ /* Inverse direction if requested */
if (qeip->config->dirinv)
acc = -acc; // acc is [-1024..+1023], its okay on int16_t
- // Adjust counter
+ /* Adjust counter */
qei_lld_adjust_count(qeip, acc);
}
}
@@ -241,7 +137,7 @@ void qei_lld_start(QEIDriver *qeip) {
const QEIConfig *cfg = qeip->config;
if (qeip->state == QEI_STOP) {
- // Set Pins
+ /* Set Pins */
palSetLineMode(cfg->phase_a, PAL_MODE_INPUT);
palSetLineMode(cfg->phase_b, PAL_MODE_INPUT);
#if NRF51_QEI_USE_LED == TRUE
@@ -250,8 +146,8 @@ void qei_lld_start(QEIDriver *qeip) {
}
#endif
- // Set interrupt masks and enable interrupt
-#if NRF51_QEI_USE_ACC_OVERFLOW_CB == TRUE
+ /* Set interrupt masks and enable interrupt */
+#if NRF51_QEI_USE_ACC_OVERFLOWED_CB == TRUE
qdec->INTENSET = QDEC_INTENSET_REPORTRDY_Msk |
QDEC_INTENSET_ACCOF_Msk;
#else
@@ -263,11 +159,11 @@ void qei_lld_start(QEIDriver *qeip) {
}
#endif
- // Select pin for Phase A and Phase B
+ /* Select pin for Phase A and Phase B */
qdec->PSELA = PAL_PAD(cfg->phase_a);
qdec->PSELB = PAL_PAD(cfg->phase_b);
- // Select (optional) pin for LED, and configure it
+ /* Select (optional) pin for LED, and configure it */
#if NRF51_QEI_USE_LED == TRUE
qdec->PSELLED = PAL_PAD(cfg->led);
qdec->LEDPOL = ((cfg->led_polarity == QEI_LED_POLARITY_LOW)
@@ -279,22 +175,22 @@ void qei_lld_start(QEIDriver *qeip) {
qdec->PSELLED = (uint32_t)-1;
#endif
- // Set sampling resolution and debouncing
+ /* Set sampling resolution and debouncing */
qdec->SAMPLEPER = cfg->resolution;
qdec->DBFEN = (cfg->debouncing ? QDEC_DBFEN_DBFEN_Enabled
: QDEC_DBFEN_DBFEN_Disabled)
<< QDEC_DBFEN_DBFEN_Pos;
- // Define minimum sampling before reporting
- // and create shortcut to clear accumulation
+ /* Define minimum sampling before reporting
+ and create shortcut to clear accumulation */
qdec->REPORTPER = cfg->report;
qdec->SHORTS = QDEC_SHORTS_REPORTRDY_READCLRACC_Msk;
- // Enable peripheric
+ /* Enable peripheric */
qdec->ENABLE = 1;
}
- // Initially state is stopped, events cleared
+ /* Initially state is stopped, events cleared */
qdec->TASKS_STOP = 1;
qdec->EVENTS_SAMPLERDY = 0;
qdec->EVENTS_REPORTRDY = 0;
@@ -317,20 +213,20 @@ void qei_lld_stop(QEIDriver *qeip) {
qdec->TASKS_STOP = 1;
qdec->ENABLE = 0;
- // Unset interrupt masks and disable interrupt
+ /* Unset interrupt masks and disable interrupt */
#if NRF51_QEI_USE_QDEC0 == TRUE
if (&QEID1 == qeip) {
nvicDisableVector(QDEC_IRQn);
}
#endif
-#if NRF51_QEI_USE_ACC_OVERFLOW_CB == TRUE
+#if NRF51_QEI_USE_ACC_OVERFLOWED_CB == TRUE
qdec->INTENCLR = QDEC_INTENCLR_REPORTRDY_Msk |
QDEC_INTENCLR_ACCOF_Msk;
#else
qdec->INTENCLR = QDEC_INTENCLR_REPORTRDY_Msk;
#endif
- // Return pins to reset state
+ /* Return pins to reset state */
palSetLineMode(cfg->phase_a, PAL_MODE_RESET);
palSetLineMode(cfg->phase_b, PAL_MODE_RESET);
#if NRF51_QEI_USE_LED == TRUE
@@ -349,7 +245,7 @@ void qei_lld_stop(QEIDriver *qeip) {
* @notapi
*/
void qei_lld_enable(QEIDriver *qeip) {
-#if NRF51_QEI_USE_ACC_OVERFLOW_CB == TRUE
+#if NRF51_QEI_USE_ACC_OVERFLOWED_CB == TRUE
qeip->overflowed = 0;
#endif
@@ -380,7 +276,7 @@ void qei_lld_disable(QEIDriver *qeip) {
* @notapi
*/
qeidelta_t qei_lld_adjust_count(QEIDriver *qeip, qeidelta_t delta) {
- // Get boundaries
+ /* Get boundaries */
qeicnt_t min = QEI_COUNT_MIN;
qeicnt_t max = QEI_COUNT_MAX;
if (qeip->config->min != qeip->config->max) {
@@ -388,22 +284,22 @@ qeidelta_t qei_lld_adjust_count(QEIDriver *qeip, qeidelta_t delta) {
max = qeip->config->max;
}
- // Snapshot counter for later comparison
+ /* Snapshot counter for later comparison */
qeicnt_t count = qeip->count;
- // Adjust counter value
+ /* Adjust counter value */
bool overflowed = qei_adjust_count(&qeip->count, &delta,
min, max, qeip->config->overflow);
- // Notify for value change
+ /* Notify for value change */
if ((qeip->count != count) && qeip->config->notify_cb)
qeip->config->notify_cb(qeip);
- // Notify for overflow (passing the remaining delta)
+ /* Notify for overflow (passing the remaining delta) */
if (overflowed && qeip->config->overflow_cb)
qeip->config->overflow_cb(qeip, delta);
- // Remaining delta
+ /* Remaining delta */
return delta;
}
diff --git a/os/hal/ports/NRF51/NRF51822/hal_qei_lld.h b/os/hal/ports/NRF51/NRF51822/hal_qei_lld.h
index 4de946e..5037591 100644
--- a/os/hal/ports/NRF51/NRF51822/hal_qei_lld.h
+++ b/os/hal/ports/NRF51/NRF51822/hal_qei_lld.h
@@ -35,14 +35,26 @@
/* Driver constants. */
/*===========================================================================*/
+/**
+ * @brief For LED active on LOW
+ */
#define QEI_LED_POLARITY_LOW 0
+
+/**
+ * @brief For LED active on HIGH
+ */
#define QEI_LED_POLARITY_HIGH 1
+/**
+ * @brief Mininum usable value for defining counter underflow
+ */
#define QEI_COUNT_MIN (-2147483648)
-#define QEI_COUNT_MAX (2147483647)
-#define HAL_QEI_SUPPORT_OVERFLOW_MINMAX TRUE
-#define HAM_QEI_SUPPORT_OVERFLOW_DISCARD TRUE
+/**
+ * @brief Maximum usable value for defining counter overflow
+ */
+#define QEI_COUNT_MAX ( 2147483647)
+
/*===========================================================================*/
@@ -69,8 +81,8 @@
* is included.
* @note The default is @p FALSE.
*/
-#if !defined(NRF51_QEI_USE_ACC_OVERFLOW_CB) || defined(__DOXYGEN__)
-#define NRF51_QEI_USE_ACC_OVERFLOW_CB FALSE
+#if !defined(NRF51_QEI_USE_ACC_OVERFLOWED_CB) || defined(__DOXYGEN__)
+#define NRF51_QEI_USE_ACC_OVERFLOWED_CB FALSE
#endif
/**
@@ -143,21 +155,6 @@ typedef enum {
QEI_REPORT_280 = 0x07UL, /**< 280 samples per report. */
} qeireport_t;
-
-// XXX: to be moved in hal_qei
-/**
- * @brief Handling of counter overflow/underflow.
- */
-typedef enum {
- QEI_OVERFLOW_WRAP = 0, /**< Counter value will wrap around. */
-#if HAL_QEI_SUPPORT_OVERFLOW_DISCARD == TRUE
- QEI_OVERFLOW_DISCARD = 1, /**< Counter doesn't change. */
-#endif
-#if HAL_QEI_SUPPORT_OVERFLOW_MINMAX == TRUE
- QEI_OVERFLOW_MINMAX = 2, /**< Counter will be updated to min or max. */
-#endif
-} qeioverflow_t;
-
/**
* @brief QEI direction inversion.
*/
@@ -252,7 +249,8 @@ typedef struct {
/**
* @brief Period in µs the LED is switched on prior to sampling.
*
- * @details LED warming is between 0 and 511 (including boundaries)
+ * @details LED warming is expressed in micro-seconds and value
+ * is [0..511]
*
* @note 31µs is the recommanded default.
*
@@ -273,16 +271,16 @@ typedef struct {
*/
bool debouncing;
/**
- * @brief Number of sample per report
+ * @brief Number of samples per report
*
* @details Default to QEI_REPORT_10
*/
qeireport_t report;
-#if NRF51_QEI_USE_ACC_OVERFLOW_CB == TRUE
+#if NRF51_QEI_USE_ACC_OVERFLOWED_CB == TRUE
/**
* @brief Notify of internal accumulator overflowed
+ * (ie: MCU discarding samples)
*
- * @note MCU has discarded some of the samples.
* @note Called from ISR context.
*/
qeicallback_t overflowed_cb;
@@ -313,7 +311,7 @@ struct QEIDriver {
* @brief Counter
*/
qeicnt_t count;
-#if NRF51_QEI_USE_ACC_OVERFLOW_CB == TRUE
+#if NRF51_QEI_USE_ACC_OVERFLOWED_CB == TRUE
/**
* @brief Number of time the MCU discarded updates due to
* accumulator overflow
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