summaryrefslogtreecommitdiffstats
path: root/bsps/arm/beagle/include/bsp/qep.h
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/arm/beagle/include/bsp/qep.h')
-rw-r--r--bsps/arm/beagle/include/bsp/qep.h382
1 files changed, 382 insertions, 0 deletions
diff --git a/bsps/arm/beagle/include/bsp/qep.h b/bsps/arm/beagle/include/bsp/qep.h
new file mode 100644
index 0000000000..fc086e3c80
--- /dev/null
+++ b/bsps/arm/beagle/include/bsp/qep.h
@@ -0,0 +1,382 @@
+/**
+ * @file
+ *
+ * @ingroup arm_beagle
+ *
+ * @brief eQEP (enhanced Quadrature Encoder Pulse) support API.
+ */
+
+/**
+ * Copyright (c) 2020 James Fitzsimons <james.fitzsimons@gmail.com>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ *
+ * For details of the Enhanced Quadrature Encoder Pulse (eQEP) Module refer to
+ * page 2511 of the TI Technical Reference Manual
+ * (https://www.ti.com/lit/ug/spruh73q/spruh73q.pdf)
+ *
+ * This driver supports using the QEP modules in Quadrature-clock Mode.
+ * Direction-count Mode is not currently supported. Similarly the QEPI: Index
+ * or Zero Marker and QEPS: Strobe Input pins are not currently supported.
+ *
+ * The mode can be any one of:
+ * - Quadrature-count mode - For encoders that generate pulses 90 degrees
+ * out of phase for determining direction and speed.
+ * - Direction-count mode - for position encoders that provide direction and
+ * clock outputs, instead of quadrature outputs.
+ * - UP-count mode - The counter direction signal is hard-wired for up count
+ * and the position counter is used to measure the frequency of the QEPA
+ * input.
+ * - DOWN-count mode - The counter direction signal is hard-wired for a down
+ * count and the position counter is used to measure the frequency of the
+ * QEPA input.
+ *
+ * When the eQEP module is configured in quadrature mode, the module
+ * can either provide an absolute position, or a relative position. Absolute
+ * simply increments or decrements depending on the direction. Relative
+ * increments until the unit timer overflows at which point it latches the
+ * position value, resets the position count to zero and starts again.
+ */
+
+#ifndef LIBBSP_ARM_BEAGLE_QEP_H
+#define LIBBSP_ARM_BEAGLE_QEP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define AM335X_EQEP_REGS (0x00000180)
+#define AM335X_EQEP_0_REGS (AM335X_PWMSS0_MMAP_ADDR + AM335X_EQEP_REGS)
+#define AM335X_EQEP_1_REGS (AM335X_PWMSS1_MMAP_ADDR + AM335X_EQEP_REGS)
+#define AM335X_EQEP_2_REGS (AM335X_PWMSS2_MMAP_ADDR + AM335X_EQEP_REGS)
+
+/* eQEP registers of the PWMSS modules - see page 1672 of the TRM for details */
+#define AM335x_EQEP_QPOSCNT 0x0 /* eQEP Position Counter */
+#define AM335x_EQEP_QPOSINIT 0x4 /* eQEP Position Counter Initialization */
+#define AM335x_EQEP_QPOSMAX 0x8 /* eQEP Maximum Position Count */
+#define AM335x_EQEP_QPOSCMP 0xC /* eQEP Position-Compare */
+#define AM335x_EQEP_QPOSILAT 0x10 /* eQEP Index Position Latch */
+#define AM335x_EQEP_QPOSSLAT 0x14 /* eQEP Strobe Position Latch */
+#define AM335x_EQEP_QPOSLAT 0x18 /* eQEP Position Counter Latch */
+#define AM335x_EQEP_QUTMR 0x1C /* eQEP Unit Timer */
+#define AM335x_EQEP_QUPRD 0x20 /* eQEP Unit Period */
+#define AM335x_EQEP_QWDTMR 0x24 /* eQEP Watchdog Timer */
+#define AM335x_EQEP_QWDPRD 0x26 /* eQEP Watchdog Period */
+#define AM335x_EQEP_QDECCTL 0x28 /* eQEP Decoder Control */
+#define AM335x_EQEP_QEPCTL 0x2A /* eQEP Control */
+#define AM335x_EQEP_QCAPCTL 0x2C /* eQEP Capture Control */
+#define AM335x_EQEP_QPOSCTL 0x2E /* eQEP Position-Compare Control */
+#define AM335x_EQEP_QEINT 0x30 /* eQEP Interrupt Enable */
+#define AM335x_EQEP_QFLG 0x32 /* eQEP Interrupt Flag */
+#define AM335x_EQEP_QCLR 0x34 /* eQEP Interrupt Clear */
+#define AM335x_EQEP_QFRC 0x36 /* eQEP Interrupt Force */
+#define AM335x_EQEP_QEPSTS 0x38 /* eQEP Status */
+#define AM335x_EQEP_QCTMR 0x3A /* eQEP Capture Timer */
+#define AM335x_EQEP_QCPRD 0x3C /* eQEP Capture Period */
+#define AM335x_EQEP_QCTMRLAT 0x3E /* eQEP Capture Timer Latch */
+#define AM335x_EQEP_QCPRDLAT 0x40 /* eQEP Capture Period Latch */
+#define AM335x_EQEP_REVID 0x5C /* eQEP Revision ID */
+
+/* bitmasks for eQEP registers */
+#define AM335x_EQEP_QEPCTL_UTE (1 << 1)
+#define AM335x_EQEP_QEPCTL_QCLM (1 << 2)
+#define AM335x_EQEP_QEPCTL_PHEN (1 << 3)
+#define AM335x_EQEP_QEPCTL_IEL (1 << 4)
+#define AM335x_EQEP_QEPCTL_SWI (1 << 7)
+#define AM335x_EQEP_QEPCTL_PCRM (3 << 12)
+#define AM335x_EQEP_QDECCTL_QSRC (3 << 14)
+#define AM335x_EQEP_QDECCTL_XCR (1 << 11)
+#define AM335x_EQEP_QDECCTL_SWAP (1 << 10)
+#define AM335x_EQEP_QDECCTL_IGATE (1 << 9)
+#define AM335x_EQEP_QDECCTL_QAP (1 << 8)
+#define AM335x_EQEP_QDECCTL_QBP (1 << 7)
+#define AM335x_EQEP_QDECCTL_QIP (1 << 6)
+#define AM335x_EQEP_QDECCTL_QSP (1 << 5)
+#define AM335x_EQEP_CLK_EN (1 << 4)
+#define AM335x_EQEP_QEINT_UTO (1 << 11)
+#define AM335x_EQEP_QFLG_UTO (1 << 11)
+#define AM335x_EQEP_QFLG_MASK 0x0FFF
+
+/* The pin mux modes for the QEP input pins on the P8 and P9 headers */
+#define BBB_P8_11_MUX_QEP 4
+#define BBB_P8_12_MUX_QEP 4
+#define BBB_P8_15_MUX_QEP 4
+#define BBB_P8_16_MUX_QEP 4
+#define BBB_P8_31_MUX_QEP 2
+#define BBB_P8_32_MUX_QEP 2
+#define BBB_P8_33_MUX_QEP 2
+#define BBB_P8_35_MUX_QEP 2
+#define BBB_P8_39_MUX_QEP 3
+#define BBB_P8_40_MUX_QEP 3
+#define BBB_P8_41_MUX_QEP 3
+#define BBB_P8_42_MUX_QEP 3
+#define BBB_P9_25_MUX_QEP 1
+#define BBB_P9_27_MUX_QEP 1
+#define BBB_P9_41_MUX_QEP 1
+#define BBB_P9_42_MUX_QEP 1
+
+#define NANO_SEC_PER_SEC 1000000000
+/* This is the max clock rate for the EPWMSS module. See 15.1.2.2 of the TRM.
+ * If the CPU was using dynamic scaling this could potentially be wrong */
+#define SYSCLKOUT 100000000
+
+/**
+ * @brief The set of possible eQEP Position Counter Input Modes
+ *
+ * Enumerated type to define various modes for the eQEP module. The values
+ * correspond to the values for the QSRC bits of the QDECCTL register.
+ */
+typedef enum {
+ QUADRATURE_COUNT = 0,
+ DIRECTION_COUNT,
+ UP_COUNT,
+ DOWN_COUNT
+} BBB_QEP_COUNT_MODE;
+
+/**
+ * @brief The set of possible modes for Quadrature decode
+ *
+ */
+typedef enum {
+ ABSOLUTE = 0,
+ RELATIVE
+} BBB_QEP_QUADRATURE_MODE;
+
+/**
+ * @brief The set of possible eQEP input pins
+ *
+ */
+typedef enum {
+ BBB_P8_11_2B_IN,
+ BBB_P8_12_2A_IN,
+ BBB_P8_15_2_STROBE,
+ BBB_P8_16_2_IDX,
+ BBB_P8_31_1_IDX,
+ BBB_P8_32_1_STROBE,
+ BBB_P8_33_1B_IN,
+ BBB_P8_35_1A_IN,
+ BBB_P8_39_2_IDX,
+ BBB_P8_40_2_STROBE,
+ BBB_P8_41_2A_IN,
+ BBB_P8_42_2B_IN,
+ BBB_P9_25_0_STROBE,
+ BBB_P9_27_0B_IN,
+ BBB_P9_41_0_IDX,
+ BBB_P9_42_0A_IN
+} bbb_qep_pin;
+
+
+/**
+ * @brief This function definition is used to declare a callback function that
+ * will be called by the interrupt handler of the QEP driver. In order for the
+ * interrupt event to trigger the driver must be configured in RELATIVE mode
+ * (using the beagle_qep_get_quadrature_mode function), and the unit timer must
+ * have been configured (using the beagle_eqep_set_timer_period function).
+ *
+ * @param BBB_PWMSS This argument is provided to the user call back function so
+ * that the user can tell which QEP module raised the interrupt.
+ *
+ * @param position The value of the position counter that was latched when the
+ * unit timer raised this interrupt. This is the value that would be returned
+ * by calling "beagle_qep_get_position".
+ *
+ * @param user This a pointer to a user provided data structure. The user sets
+ * this pointer value when configuring the unit timer callback via the
+ * beagle_eqep_set_timer_period function and it is returned here as an argument.
+ * The driver does not touch this value.
+ */
+typedef void (*bbb_eqep_timer_callback)(
+ BBB_PWMSS,
+ uint32_t position,
+ void* user
+);
+
+
+/**
+ * @brief This structure represents an eQEP module instance. The members
+ * represent the configuration of a specific eQEP module. There are three
+ * eQEP modules in the AM335x, one associated with each PWMSS unit.
+ * @var bbb_eqep::pwmss_id The PWMSS unit this eQEP module belongs to.
+ * @var bbb_eqep::mmio_base The base address for this eQEP modules registers
+ * @var bbb_eqep::irq The IRQ vector for this eQEP module
+ * @var bbb_eqep::timer_callback An optional user provided callback function
+ * when the driver is configured in RELATIVE mode using the unit timer
+ * @var bbb_eqep::user An optional pointer to user provided data that will be
+ * handed to the callback function as an argument.
+ * @var bbb_eqep::count_mode The count mode for this eQEP module. Defaults to
+ * QUADRATURE.
+ * @var bbb_eqep::quadrature_mode The mode for QUADRATURE operation. Defaults
+ * to ABSOLUTE - will count up to overflow or until the user resets the
+ * position. Can be set to RELATIVE which will trigger a call back of the unit
+ * timer if configured.
+ * @var bbb_eqep::invert_qa 1 to invert the A channel input, 0 to leave as is.
+ * @var bbb_eqep::invert_qb 1 to invert the B channel input, 0 to leave as is.
+ * @var bbb_eqep::invert_qi 1 to invert the INDEX input, 0 to leave as is.
+ * @var bbb_eqep::invert_qs 1 to invert the STROBE input, 0 to leave as is.
+ * @var bbb_eqep::swap_inputs 1 to swap the A and B channel inputs, 0 to leave
+ * as is.
+ *
+ */
+typedef struct {
+ const BBB_PWMSS pwmss_id;
+ const uint32_t mmio_base;
+ const rtems_vector_number irq;
+ bbb_eqep_timer_callback timer_callback;
+ void* user;
+ BBB_QEP_COUNT_MODE count_mode;
+ BBB_QEP_QUADRATURE_MODE quadrature_mode;
+ uint32_t invert_qa;
+ uint32_t invert_qb;
+ uint32_t invert_qi;
+ uint32_t invert_qs;
+ uint32_t swap_inputs;
+} bbb_eqep;
+
+
+/**
+ * @brief Initialises the eQEP module of the specified PWMSS unit. This
+ * configures the clocks, sets up the interrupt handler and unit timer,
+ * The module is configured in Quadrature decode mode using
+ * absolute position by default.
+ *
+ * @param pwmss_id The PWMSS module to configure the eQEP for.
+ * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is
+ * supplied.
+ */
+rtems_status_code beagle_qep_init(BBB_PWMSS pwmss_id);
+
+/**
+ * @brief Enables the eQEP module of the specified PWMSS unit.
+ *
+ * @param pwmss_id The PWMSS module which will have the eQEP function enabled.
+ * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is
+ * supplied.
+ */
+rtems_status_code beagle_qep_enable(BBB_PWMSS pwmss_id);
+
+/**
+ * @brief Disables the eQEP module of the specified PWMSS unit.
+ *
+ * @param pwmss_id The PWMSS module which will have the eQEP function disabled.
+ * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is
+ * supplied.
+ */
+rtems_status_code beagle_qep_disable(BBB_PWMSS pwmss_id);
+
+/**
+ * @brief Configures a given pin for use with the eQEP function of the supplied
+ * PWMSS module.
+ *
+ * @param pin_no The P9 or P8 header pin to be configured for the eQEP function.
+ * @param pwmss_id The PWMSS module which will have the eQEP function enabled.
+ * @param pullup_enable If true then the internal pull up resistor on the
+ * specified pin will be enabled, if false the pull down will be enabled.
+ * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is
+ * supplied.
+ */
+rtems_status_code beagle_qep_pinmux_setup(
+ bbb_qep_pin pin_no,
+ BBB_PWMSS pwmss_id,
+ bool pullup_enable
+);
+
+/**
+ * @brief Returns the current position value of the eQEP function for the
+ * specified PWMSS module.
+ *
+ * @param pwmss_id Identifies which PWMSS module to return the eQEP position for
+ * @return int32_t The current position value.
+ */
+int32_t beagle_qep_get_position(BBB_PWMSS pwmss_id);
+
+/**
+ * @brief Sets the initial position value of the eQEP function for the
+ * specified PWMSS module.
+ *
+ * @param pwmss_id Identifies which PWMSS module to set the eQEP position for
+ * @param position The value to initialise the position register with.
+ * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is
+ * supplied.
+ */
+rtems_status_code beagle_qep_set_position(
+ BBB_PWMSS pwmss_id,
+ uint32_t position
+);
+
+/**
+ * @brief Sets the count mode for the eQEP module.
+ * @param pwmss_id Identifies which PWMSS module to set the eQEP count mode for.
+ * @param mode One of the above modes to configure the eQEP module for.
+ * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is
+ * supplied.
+ */
+rtems_status_code beagle_qep_set_count_mode(
+ BBB_PWMSS pwmss_id,
+ BBB_QEP_COUNT_MODE mode
+);
+
+/**
+ * @brief Gets the currently configured count mode for the eQEP module.
+ * @param pwmss_id Identifies which PWMSS module to set the eQEP count mode for.
+ * @return An enum value representing the current count mode.
+ */
+BBB_QEP_COUNT_MODE beagle_qep_get_count_mode(BBB_PWMSS pwmss_id);
+
+/**
+ * @brief Returns the currently configured quadrature mode - either absolute,
+ * or relative.
+ * @param pwmss_id Identifies which PWMSS module to get the eQEP quadrature
+ * mode for.
+ * @return BBB_QEP_QUADRATURE_MODE The currently configured quadrature mode.
+ */
+BBB_QEP_QUADRATURE_MODE beagle_qep_get_quadrature_mode(BBB_PWMSS pwmss_id);
+
+/**
+ * @brief Sets the quadrature mode to either absolute or relative.
+ * @param pwmss_id Identifies which PWMSS module to set the eQEP quadrature
+ * mode for.
+ * @param mode BBB_QEP_QUADRATURE_MODE Set the mode of the eQEP to either
+ * absolute or relative.
+ * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is
+ * supplied.
+ */
+rtems_status_code beagle_qep_set_quadrature_mode(
+ BBB_PWMSS pwmss_id,
+ BBB_QEP_QUADRATURE_MODE mode
+);
+
+/**
+ * @brief Returns the the currently configured unit timer period.
+ * @param pwmss_id Identifies which PWMSS module to get the eQEP timer value for
+ * @return uint32_t The current unit timer value in nanoseconds
+ */
+uint32_t beagle_eqep_get_timer_period(BBB_PWMSS pwmss_id);
+
+/**
+ * @brief Sets the unit timer period for the eQEP module.
+ * 0 = off, greater than zero sets the period.
+ * @param pwmss_id Identifies which PWMSS module to set the eQEP unit timer for.
+ * @param period The value in nanoseconds to set the unit timer period to.
+ * @param timer_callback This is the user provided callback function that will
+ * be called by the interrupt event handler on expiry of the unit timer. The
+ * user can provide NULL if they don't require a call back.
+ * @param user This is a pointer to a user provided data structure that will be
+ * handed back as an argument to the timer callback. The driver does not touch
+ * this value.
+ * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is
+ * supplied.
+ */
+rtems_status_code beagle_eqep_set_timer_period(
+ BBB_PWMSS pwmss_id,
+ uint64_t period,
+ bbb_eqep_timer_callback timer_callback,
+ void* user
+);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_ARM_BEAGLE_QEP_H */