HP5508A interferometer replacement hardware 2.0!

Paul Stoffgren released the Teensy 4.0, and it looks like a great match for a 2.0 version. Here links to the docs :

The Teensy uses a NXP iMXRT1062 chip at up to 600 Mhz clock rate and has a large range of integrated peripherals that are going to be useful.

I talked with Sam Goldwasser and he mentioned that it would be really nice to have the unit capable of receiving the Sin/Cos signal from Homodyne interferometers. These are described in great detail here:

http://www.repairfaq.org/sam/laserlia.htm#liaintqd

He explains how the quadrature signals get produced:

The signal in each channel is a sine wave oscillating as the distance changes. These two are related by a 90 degree shift, so that the signal can be represented as a sin/cos rotation of a unit vector. This is very similar to quadrature decoders as they are used in motion control to determine the position of a motor shaft. There is a nice explanation of these devices here: https://en.wikipedia.org/wiki/Rotary_encoder

But the gist of it is that these devices:

Produce a digital pulse train that looks like this:


Maybe with a code wheel or some other method.

These pulse trains are also in quadrature, and because they are incredibly popular there is ready made decoder hardware inside the NXP iMXRT1062. It has 4 hardware decoders ready to accept these digital signals. It is possible to use the analog signals in quadrature, if properly rectified like this:

This can be achieved by using a differential line receiver. In fact, the UA9638 we have been using previously will do this very well. Consider the following simple test setup:

The UA9638 is powered by 5V coming from the USB bus. The output is reduced from 5V to 3.3V using a simple resistor divider. An OLED on the IIC bus allows the displaying the encoder count.

I modified a test sketch for the encoders available here: https://github.com/mjs513/WIP/blob/master/ENC1_test_xbar1/ENC1_test_xbar1.ino

in order to display the counts on the OLED as well as write them to the serial console. The results are great:

The next step is to clean up the code and allow for simultaneous operation of all 4 decoder inputs. For now, here the code in the current messy state.


/* ---------------------------------------------------------------------------- -- ENC Peripheral Access Layer ---------------------------------------------------------------------------- */
/*! * @addtogroup ENC_Peripheral_Access_Layer ENC Peripheral Access Layer * @{ */
/** ENC - Register Layout Typedef */typedef struct { volatile uint16_t CTRL; /**< Control Register, offset: 0x0 */ volatile uint16_t FILT; /**< Input Filter Register, offset: 0x2 */ volatile uint16_t WTR; /**< Watchdog Timeout Register, offset: 0x4 */ volatile uint16_t POSD; /**< Position Difference Counter Register, offset: 0x6 */ volatile uint16_t POSDH; /**< Position Difference Hold Register, offset: 0x8 */ volatile uint16_t REV; /**< Revolution Counter Register, offset: 0xA */ volatile uint16_t REVH; /**< Revolution Hold Register, offset: 0xC */ volatile uint16_t UPOS; /**< Upper Position Counter Register, offset: 0xE */ volatile uint16_t LPOS; /**< Lower Position Counter Register, offset: 0x10 */ volatile uint16_t UPOSH; /**< Upper Position Hold Register, offset: 0x12 */ volatile uint16_t LPOSH; /**< Lower Position Hold Register, offset: 0x14 */ volatile uint16_t UINIT; /**< Upper Initialization Register, offset: 0x16 */ volatile uint16_t LINIT; /**< Lower Initialization Register, offset: 0x18 */ volatile uint16_t IMR; /**< Input Monitor Register, offset: 0x1A */ volatile uint16_t TST; /**< Test Register, offset: 0x1C */ volatile uint16_t CTRL2; /**< Control 2 Register, offset: 0x1E */ volatile uint16_t UMOD; /**< Upper Modulus Register, offset: 0x20 */ volatile uint16_t LMOD; /**< Lower Modulus Register, offset: 0x22 */ volatile uint16_t UCOMP; /**< Upper Position Compare Register, offset: 0x24 */ volatile uint16_t LCOMP; /**< Lower Position Compare Register, offset: 0x26 */} ENC_Type;
/* ---------------------------------------------------------------------------- -- ENC Register Masks ---------------------------------------------------------------------------- */
/*! * @addtogroup ENC_Register_Masks ENC Register Masks * @{ */
/*! @name CTRL - Control Register *//*! @{ */#define ENC_CTRL_CMPIE_MASK (0x1U)#define ENC_CTRL_CMPIE_SHIFT (0U)/*! CMPIE - Compare Interrupt Enable * 0b0..Compare interrupt is disabled * 0b1..Compare interrupt is enabled */#define ENC_CTRL_CMPIE(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL_CMPIE_SHIFT)) & ENC_CTRL_CMPIE_MASK)#define ENC_CTRL_CMPIRQ_MASK (0x2U)#define ENC_CTRL_CMPIRQ_SHIFT (1U)/*! CMPIRQ - Compare Interrupt Request * 0b0..No match has occurred * 0b1..COMP match has occurred */#define ENC_CTRL_CMPIRQ(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL_CMPIRQ_SHIFT)) & ENC_CTRL_CMPIRQ_MASK)#define ENC_CTRL_WDE_MASK (0x4U)#define ENC_CTRL_WDE_SHIFT (2U)/*! WDE - Watchdog Enable * 0b0..Watchdog timer is disabled * 0b1..Watchdog timer is enabled */#define ENC_CTRL_WDE(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL_WDE_SHIFT)) & ENC_CTRL_WDE_MASK)#define ENC_CTRL_DIE_MASK (0x8U)#define ENC_CTRL_DIE_SHIFT (3U)/*! DIE - Watchdog Timeout Interrupt Enable * 0b0..Watchdog timer interrupt is disabled * 0b1..Watchdog timer interrupt is enabled */#define ENC_CTRL_DIE(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL_DIE_SHIFT)) & ENC_CTRL_DIE_MASK)#define ENC_CTRL_DIRQ_MASK (0x10U)#define ENC_CTRL_DIRQ_SHIFT (4U)/*! DIRQ - Watchdog Timeout Interrupt Request * 0b0..No interrupt has occurred * 0b1..Watchdog timeout interrupt has occurred */#define ENC_CTRL_DIRQ(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL_DIRQ_SHIFT)) & ENC_CTRL_DIRQ_MASK)#define ENC_CTRL_XNE_MASK (0x20U)#define ENC_CTRL_XNE_SHIFT (5U)/*! XNE - Use Negative Edge of INDEX Pulse * 0b0..Use positive transition edge of INDEX pulse * 0b1..Use negative transition edge of INDEX pulse */#define ENC_CTRL_XNE(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL_XNE_SHIFT)) & ENC_CTRL_XNE_MASK)#define ENC_CTRL_XIP_MASK (0x40U)#define ENC_CTRL_XIP_SHIFT (6U)/*! XIP - INDEX Triggered Initialization of Position Counters UPOS and LPOS * 0b0..No action * 0b1..INDEX pulse initializes the position counter */#define ENC_CTRL_XIP(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL_XIP_SHIFT)) & ENC_CTRL_XIP_MASK)#define ENC_CTRL_XIE_MASK (0x80U)#define ENC_CTRL_XIE_SHIFT (7U)/*! XIE - INDEX Pulse Interrupt Enable * 0b0..INDEX pulse interrupt is disabled * 0b1..INDEX pulse interrupt is enabled */#define ENC_CTRL_XIE(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL_XIE_SHIFT)) & ENC_CTRL_XIE_MASK)#define ENC_CTRL_XIRQ_MASK (0x100U)#define ENC_CTRL_XIRQ_SHIFT (8U)/*! XIRQ - INDEX Pulse Interrupt Request * 0b0..No interrupt has occurred * 0b1..INDEX pulse interrupt has occurred */#define ENC_CTRL_XIRQ(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL_XIRQ_SHIFT)) & ENC_CTRL_XIRQ_MASK)#define ENC_CTRL_PH1_MASK (0x200U)#define ENC_CTRL_PH1_SHIFT (9U)/*! PH1 - Enable Signal Phase Count Mode * 0b0..Use standard quadrature decoder where PHASEA and PHASEB represent a two phase quadrature signal. * 0b1..Bypass the quadrature decoder. A positive transition of the PHASEA input generates a count signal. The PHASEB input and the REV bit control the counter direction. If CTRL[REV] = 0, PHASEB = 0, then count up If CTRL[REV] = 0, PHASEB = 1, then count down If CTRL[REV] = 1, PHASEB = 0, then count down If CTRL[REV] = 1, PHASEB = 1, then count up */#define ENC_CTRL_PH1(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL_PH1_SHIFT)) & ENC_CTRL_PH1_MASK)#define ENC_CTRL_REV_MASK (0x400U)#define ENC_CTRL_REV_SHIFT (10U)/*! REV - Enable Reverse Direction Counting * 0b0..Count normally * 0b1..Count in the reverse direction */#define ENC_CTRL_REV(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL_REV_SHIFT)) & ENC_CTRL_REV_MASK)#define ENC_CTRL_SWIP_MASK (0x800U)#define ENC_CTRL_SWIP_SHIFT (11U)/*! SWIP - Software Triggered Initialization of Position Counters UPOS and LPOS * 0b0..No action * 0b1..Initialize position counter */#define ENC_CTRL_SWIP(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL_SWIP_SHIFT)) & ENC_CTRL_SWIP_MASK)#define ENC_CTRL_HNE_MASK (0x1000U)#define ENC_CTRL_HNE_SHIFT (12U)/*! HNE - Use Negative Edge of HOME Input * 0b0..Use positive going edge-to-trigger initialization of position counters UPOS and LPOS * 0b1..Use negative going edge-to-trigger initialization of position counters UPOS and LPOS */#define ENC_CTRL_HNE(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL_HNE_SHIFT)) & ENC_CTRL_HNE_MASK)#define ENC_CTRL_HIP_MASK (0x2000U)#define ENC_CTRL_HIP_SHIFT (13U)/*! HIP - Enable HOME to Initialize Position Counters UPOS and LPOS * 0b0..No action * 0b1..HOME signal initializes the position counter */#define ENC_CTRL_HIP(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL_HIP_SHIFT)) & ENC_CTRL_HIP_MASK)#define ENC_CTRL_HIE_MASK (0x4000U)#define ENC_CTRL_HIE_SHIFT (14U)/*! HIE - HOME Interrupt Enable * 0b0..Disable HOME interrupts * 0b1..Enable HOME interrupts */#define ENC_CTRL_HIE(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL_HIE_SHIFT)) & ENC_CTRL_HIE_MASK)#define ENC_CTRL_HIRQ_MASK (0x8000U)#define ENC_CTRL_HIRQ_SHIFT (15U)/*! HIRQ - HOME Signal Transition Interrupt Request * 0b0..No interrupt * 0b1..HOME signal transition interrupt request */#define ENC_CTRL_HIRQ(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL_HIRQ_SHIFT)) & ENC_CTRL_HIRQ_MASK)/*! @} */
/*! @name FILT - Input Filter Register *//*! @{ */#define ENC_FILT_FILT_PER_MASK (0xFFU)#define ENC_FILT_FILT_PER_SHIFT (0U)#define ENC_FILT_FILT_PER(x) (((uint16_t)(((uint16_t)(x)) << ENC_FILT_FILT_PER_SHIFT)) & ENC_FILT_FILT_PER_MASK)#define ENC_FILT_FILT_CNT_MASK (0x700U)#define ENC_FILT_FILT_CNT_SHIFT (8U)#define ENC_FILT_FILT_CNT(x) (((uint16_t)(((uint16_t)(x)) << ENC_FILT_FILT_CNT_SHIFT)) & ENC_FILT_FILT_CNT_MASK)/*! @} */
/*! @name WTR - Watchdog Timeout Register *//*! @{ */#define ENC_WTR_WDOG_MASK (0xFFFFU)#define ENC_WTR_WDOG_SHIFT (0U)#define ENC_WTR_WDOG(x) (((uint16_t)(((uint16_t)(x)) << ENC_WTR_WDOG_SHIFT)) & ENC_WTR_WDOG_MASK)/*! @} */
/*! @name POSD - Position Difference Counter Register *//*! @{ */#define ENC_POSD_POSD_MASK (0xFFFFU)#define ENC_POSD_POSD_SHIFT (0U)#define ENC_POSD_POSD(x) (((uint16_t)(((uint16_t)(x)) << ENC_POSD_POSD_SHIFT)) & ENC_POSD_POSD_MASK)/*! @} */
/*! @name POSDH - Position Difference Hold Register *//*! @{ */#define ENC_POSDH_POSDH_MASK (0xFFFFU)#define ENC_POSDH_POSDH_SHIFT (0U)#define ENC_POSDH_POSDH(x) (((uint16_t)(((uint16_t)(x)) << ENC_POSDH_POSDH_SHIFT)) & ENC_POSDH_POSDH_MASK)/*! @} */
/*! @name REV - Revolution Counter Register *//*! @{ */#define ENC_REV_REV_MASK (0xFFFFU)#define ENC_REV_REV_SHIFT (0U)#define ENC_REV_REV(x) (((uint16_t)(((uint16_t)(x)) << ENC_REV_REV_SHIFT)) & ENC_REV_REV_MASK)/*! @} */
/*! @name REVH - Revolution Hold Register *//*! @{ */#define ENC_REVH_REVH_MASK (0xFFFFU)#define ENC_REVH_REVH_SHIFT (0U)#define ENC_REVH_REVH(x) (((uint16_t)(((uint16_t)(x)) << ENC_REVH_REVH_SHIFT)) & ENC_REVH_REVH_MASK)/*! @} */
/*! @name UPOS - Upper Position Counter Register *//*! @{ */#define ENC_UPOS_POS_MASK (0xFFFFU)#define ENC_UPOS_POS_SHIFT (0U)#define ENC_UPOS_POS(x) (((uint16_t)(((uint16_t)(x)) << ENC_UPOS_POS_SHIFT)) & ENC_UPOS_POS_MASK)/*! @} */
/*! @name LPOS - Lower Position Counter Register *//*! @{ */#define ENC_LPOS_POS_MASK (0xFFFFU)#define ENC_LPOS_POS_SHIFT (0U)#define ENC_LPOS_POS(x) (((uint16_t)(((uint16_t)(x)) << ENC_LPOS_POS_SHIFT)) & ENC_LPOS_POS_MASK)/*! @} */
/*! @name UPOSH - Upper Position Hold Register *//*! @{ */#define ENC_UPOSH_POSH_MASK (0xFFFFU)#define ENC_UPOSH_POSH_SHIFT (0U)#define ENC_UPOSH_POSH(x) (((uint16_t)(((uint16_t)(x)) << ENC_UPOSH_POSH_SHIFT)) & ENC_UPOSH_POSH_MASK)/*! @} */
/*! @name LPOSH - Lower Position Hold Register *//*! @{ */#define ENC_LPOSH_POSH_MASK (0xFFFFU)#define ENC_LPOSH_POSH_SHIFT (0U)#define ENC_LPOSH_POSH(x) (((uint16_t)(((uint16_t)(x)) << ENC_LPOSH_POSH_SHIFT)) & ENC_LPOSH_POSH_MASK)/*! @} */
/*! @name UINIT - Upper Initialization Register *//*! @{ */#define ENC_UINIT_INIT_MASK (0xFFFFU)#define ENC_UINIT_INIT_SHIFT (0U)#define ENC_UINIT_INIT(x) (((uint16_t)(((uint16_t)(x)) << ENC_UINIT_INIT_SHIFT)) & ENC_UINIT_INIT_MASK)/*! @} */
/*! @name LINIT - Lower Initialization Register *//*! @{ */#define ENC_LINIT_INIT_MASK (0xFFFFU)#define ENC_LINIT_INIT_SHIFT (0U)#define ENC_LINIT_INIT(x) (((uint16_t)(((uint16_t)(x)) << ENC_LINIT_INIT_SHIFT)) & ENC_LINIT_INIT_MASK)/*! @} */
/*! @name IMR - Input Monitor Register *//*! @{ */#define ENC_IMR_HOME_MASK (0x1U)#define ENC_IMR_HOME_SHIFT (0U)#define ENC_IMR_HOME(x) (((uint16_t)(((uint16_t)(x)) << ENC_IMR_HOME_SHIFT)) & ENC_IMR_HOME_MASK)#define ENC_IMR_INDEX_MASK (0x2U)#define ENC_IMR_INDEX_SHIFT (1U)#define ENC_IMR_INDEX(x) (((uint16_t)(((uint16_t)(x)) << ENC_IMR_INDEX_SHIFT)) & ENC_IMR_INDEX_MASK)#define ENC_IMR_PHB_MASK (0x4U)#define ENC_IMR_PHB_SHIFT (2U)#define ENC_IMR_PHB(x) (((uint16_t)(((uint16_t)(x)) << ENC_IMR_PHB_SHIFT)) & ENC_IMR_PHB_MASK)#define ENC_IMR_PHA_MASK (0x8U)#define ENC_IMR_PHA_SHIFT (3U)#define ENC_IMR_PHA(x) (((uint16_t)(((uint16_t)(x)) << ENC_IMR_PHA_SHIFT)) & ENC_IMR_PHA_MASK)#define ENC_IMR_FHOM_MASK (0x10U)#define ENC_IMR_FHOM_SHIFT (4U)#define ENC_IMR_FHOM(x) (((uint16_t)(((uint16_t)(x)) << ENC_IMR_FHOM_SHIFT)) & ENC_IMR_FHOM_MASK)#define ENC_IMR_FIND_MASK (0x20U)#define ENC_IMR_FIND_SHIFT (5U)#define ENC_IMR_FIND(x) (((uint16_t)(((uint16_t)(x)) << ENC_IMR_FIND_SHIFT)) & ENC_IMR_FIND_MASK)#define ENC_IMR_FPHB_MASK (0x40U)#define ENC_IMR_FPHB_SHIFT (6U)#define ENC_IMR_FPHB(x) (((uint16_t)(((uint16_t)(x)) << ENC_IMR_FPHB_SHIFT)) & ENC_IMR_FPHB_MASK)#define ENC_IMR_FPHA_MASK (0x80U)#define ENC_IMR_FPHA_SHIFT (7U)#define ENC_IMR_FPHA(x) (((uint16_t)(((uint16_t)(x)) << ENC_IMR_FPHA_SHIFT)) & ENC_IMR_FPHA_MASK)/*! @} */
/*! @name TST - Test Register *//*! @{ */#define ENC_TST_TEST_COUNT_MASK (0xFFU)#define ENC_TST_TEST_COUNT_SHIFT (0U)#define ENC_TST_TEST_COUNT(x) (((uint16_t)(((uint16_t)(x)) << ENC_TST_TEST_COUNT_SHIFT)) & ENC_TST_TEST_COUNT_MASK)#define ENC_TST_TEST_PERIOD_MASK (0x1F00U)#define ENC_TST_TEST_PERIOD_SHIFT (8U)#define ENC_TST_TEST_PERIOD(x) (((uint16_t)(((uint16_t)(x)) << ENC_TST_TEST_PERIOD_SHIFT)) & ENC_TST_TEST_PERIOD_MASK)#define ENC_TST_QDN_MASK (0x2000U)#define ENC_TST_QDN_SHIFT (13U)/*! QDN - Quadrature Decoder Negative Signal * 0b0..Leaves quadrature decoder signal in a positive direction * 0b1..Generates a negative quadrature decoder signal */#define ENC_TST_QDN(x) (((uint16_t)(((uint16_t)(x)) << ENC_TST_QDN_SHIFT)) & ENC_TST_QDN_MASK)#define ENC_TST_TCE_MASK (0x4000U)#define ENC_TST_TCE_SHIFT (14U)/*! TCE - Test Counter Enable * 0b0..Test count is not enabled * 0b1..Test count is enabled */#define ENC_TST_TCE(x) (((uint16_t)(((uint16_t)(x)) << ENC_TST_TCE_SHIFT)) & ENC_TST_TCE_MASK)#define ENC_TST_TEN_MASK (0x8000U)#define ENC_TST_TEN_SHIFT (15U)/*! TEN - Test Mode Enable * 0b0..Test module is not enabled * 0b1..Test module is enabled */#define ENC_TST_TEN(x) (((uint16_t)(((uint16_t)(x)) << ENC_TST_TEN_SHIFT)) & ENC_TST_TEN_MASK)/*! @} */
/*! @name CTRL2 - Control 2 Register *//*! @{ */#define ENC_CTRL2_UPDHLD_MASK (0x1U)#define ENC_CTRL2_UPDHLD_SHIFT (0U)/*! UPDHLD - Update Hold Registers * 0b0..Disable updates of hold registers on rising edge of TRIGGER * 0b1..Enable updates of hold registers on rising edge of TRIGGER */#define ENC_CTRL2_UPDHLD(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL2_UPDHLD_SHIFT)) & ENC_CTRL2_UPDHLD_MASK)#define ENC_CTRL2_UPDPOS_MASK (0x2U)#define ENC_CTRL2_UPDPOS_SHIFT (1U)/*! UPDPOS - Update Position Registers * 0b0..No action for POSD, REV, UPOS and LPOS on rising edge of TRIGGER * 0b1..Clear POSD, REV, UPOS and LPOS on rising edge of TRIGGER */#define ENC_CTRL2_UPDPOS(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL2_UPDPOS_SHIFT)) & ENC_CTRL2_UPDPOS_MASK)#define ENC_CTRL2_MOD_MASK (0x4U)#define ENC_CTRL2_MOD_SHIFT (2U)/*! MOD - Enable Modulo Counting * 0b0..Disable modulo counting * 0b1..Enable modulo counting */#define ENC_CTRL2_MOD(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL2_MOD_SHIFT)) & ENC_CTRL2_MOD_MASK)#define ENC_CTRL2_DIR_MASK (0x8U)#define ENC_CTRL2_DIR_SHIFT (3U)/*! DIR - Count Direction Flag * 0b0..Last count was in the down direction * 0b1..Last count was in the up direction */#define ENC_CTRL2_DIR(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL2_DIR_SHIFT)) & ENC_CTRL2_DIR_MASK)#define ENC_CTRL2_RUIE_MASK (0x10U)#define ENC_CTRL2_RUIE_SHIFT (4U)/*! RUIE - Roll-under Interrupt Enable * 0b0..Roll-under interrupt is disabled * 0b1..Roll-under interrupt is enabled */#define ENC_CTRL2_RUIE(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL2_RUIE_SHIFT)) & ENC_CTRL2_RUIE_MASK)#define ENC_CTRL2_RUIRQ_MASK (0x20U)#define ENC_CTRL2_RUIRQ_SHIFT (5U)/*! RUIRQ - Roll-under Interrupt Request * 0b0..No roll-under has occurred * 0b1..Roll-under has occurred */#define ENC_CTRL2_RUIRQ(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL2_RUIRQ_SHIFT)) & ENC_CTRL2_RUIRQ_MASK)#define ENC_CTRL2_ROIE_MASK (0x40U)#define ENC_CTRL2_ROIE_SHIFT (6U)/*! ROIE - Roll-over Interrupt Enable * 0b0..Roll-over interrupt is disabled * 0b1..Roll-over interrupt is enabled */#define ENC_CTRL2_ROIE(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL2_ROIE_SHIFT)) & ENC_CTRL2_ROIE_MASK)#define ENC_CTRL2_ROIRQ_MASK (0x80U)#define ENC_CTRL2_ROIRQ_SHIFT (7U)/*! ROIRQ - Roll-over Interrupt Request * 0b0..No roll-over has occurred * 0b1..Roll-over has occurred */#define ENC_CTRL2_ROIRQ(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL2_ROIRQ_SHIFT)) & ENC_CTRL2_ROIRQ_MASK)#define ENC_CTRL2_REVMOD_MASK (0x100U)#define ENC_CTRL2_REVMOD_SHIFT (8U)/*! REVMOD - Revolution Counter Modulus Enable * 0b0..Use INDEX pulse to increment/decrement revolution counter (REV). * 0b1..Use modulus counting roll-over/under to increment/decrement revolution counter (REV). */#define ENC_CTRL2_REVMOD(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL2_REVMOD_SHIFT)) & ENC_CTRL2_REVMOD_MASK)#define ENC_CTRL2_OUTCTL_MASK (0x200U)#define ENC_CTRL2_OUTCTL_SHIFT (9U)/*! OUTCTL - Output Control * 0b0..POSMATCH pulses when a match occurs between the position counters (POS) and the compare value (COMP). * 0b1..POSMATCH pulses when the UPOS, LPOS, REV, or POSD registers are read. */#define ENC_CTRL2_OUTCTL(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL2_OUTCTL_SHIFT)) & ENC_CTRL2_OUTCTL_MASK)#define ENC_CTRL2_SABIE_MASK (0x400U)#define ENC_CTRL2_SABIE_SHIFT (10U)/*! SABIE - Simultaneous PHASEA and PHASEB Change Interrupt Enable * 0b0..Simultaneous PHASEA and PHASEB change interrupt disabled. * 0b1..Simultaneous PHASEA and PHASEB change interrupt enabled. */#define ENC_CTRL2_SABIE(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL2_SABIE_SHIFT)) & ENC_CTRL2_SABIE_MASK)#define ENC_CTRL2_SABIRQ_MASK (0x800U)#define ENC_CTRL2_SABIRQ_SHIFT (11U)/*! SABIRQ - Simultaneous PHASEA and PHASEB Change Interrupt Request * 0b0..No simultaneous change of PHASEA and PHASEB has occurred. * 0b1..A simultaneous change of PHASEA and PHASEB has occurred. */#define ENC_CTRL2_SABIRQ(x) (((uint16_t)(((uint16_t)(x)) << ENC_CTRL2_SABIRQ_SHIFT)) & ENC_CTRL2_SABIRQ_MASK)/*! @} */
/*! @name UMOD - Upper Modulus Register *//*! @{ */#define ENC_UMOD_MOD_MASK (0xFFFFU)#define ENC_UMOD_MOD_SHIFT (0U)#define ENC_UMOD_MOD(x) (((uint16_t)(((uint16_t)(x)) << ENC_UMOD_MOD_SHIFT)) & ENC_UMOD_MOD_MASK)/*! @} */
/*! @name LMOD - Lower Modulus Register *//*! @{ */#define ENC_LMOD_MOD_MASK (0xFFFFU)#define ENC_LMOD_MOD_SHIFT (0U)#define ENC_LMOD_MOD(x) (((uint16_t)(((uint16_t)(x)) << ENC_LMOD_MOD_SHIFT)) & ENC_LMOD_MOD_MASK)/*! @} */
/*! @name UCOMP - Upper Position Compare Register *//*! @{ */#define ENC_UCOMP_COMP_MASK (0xFFFFU)#define ENC_UCOMP_COMP_SHIFT (0U)#define ENC_UCOMP_COMP(x) (((uint16_t)(((uint16_t)(x)) << ENC_UCOMP_COMP_SHIFT)) & ENC_UCOMP_COMP_MASK)/*! @} */
/*! @name LCOMP - Lower Position Compare Register *//*! @{ */#define ENC_LCOMP_COMP_MASK (0xFFFFU)#define ENC_LCOMP_COMP_SHIFT (0U)#define ENC_LCOMP_COMP(x) (((uint16_t)(((uint16_t)(x)) << ENC_LCOMP_COMP_SHIFT)) & ENC_LCOMP_COMP_MASK)/*! @} */

/*! * @} */ /* end of group ENC_Register_Masks */

/* ENC - Peripheral instance base addresses *//** Peripheral ENC1 base address */#define ENC1_BASE (0x403C8000u)/** Peripheral ENC1 base pointer */#define ENC1 ((ENC_Type *)ENC1_BASE)/** Peripheral ENC2 base address */#define ENC2_BASE (0x403CC000u)/** Peripheral ENC2 base pointer */#define ENC2 ((ENC_Type *)ENC2_BASE)/** Peripheral ENC3 base address */#define ENC3_BASE (0x403D0000u)/** Peripheral ENC3 base pointer */#define ENC3 ((ENC_Type *)ENC3_BASE)/** Peripheral ENC4 base address */#define ENC4_BASE (0x403D4000u)/** Peripheral ENC4 base pointer */#define ENC4 ((ENC_Type *)ENC4_BASE)/** Array initializer of ENC peripheral base addresses */#define ENC_BASE_ADDRS { 0u, ENC1_BASE, ENC2_BASE, ENC3_BASE, ENC4_BASE }/** Array initializer of ENC peripheral base pointers */#define ENC_BASE_PTRS { (ENC_Type *)0u, ENC1, ENC2, ENC3, ENC4 }/** Interrupt vectors for the ENC peripheral type */#define ENC_COMPARE_IRQS { NotAvail_IRQn, ENC1_IRQn, ENC2_IRQn, ENC3_IRQn, ENC4_IRQn }#define ENC_HOME_IRQS { NotAvail_IRQn, ENC1_IRQn, ENC2_IRQn, ENC3_IRQn, ENC4_IRQn }#define ENC_WDOG_IRQS { NotAvail_IRQn, ENC1_IRQn, ENC2_IRQn, ENC3_IRQn, ENC4_IRQn }#define ENC_INDEX_IRQS { NotAvail_IRQn, ENC1_IRQn, ENC2_IRQn, ENC3_IRQn, ENC4_IRQn }#define ENC_INPUT_SWITCH_IRQS { NotAvail_IRQn, ENC1_IRQn, ENC2_IRQn, ENC3_IRQn, ENC4_IRQn }
/*! * @} */ /* end of group ENC_Peripheral_Access_Layer */





/*! * @brief Interrupt enable/disable mask. */enum _enc_interrupt_enable{ kENC_HOMETransitionInterruptEnable = (1U << 0U), /*!< HOME interrupt enable. */ kENC_INDEXPulseInterruptEnable = (1U << 1U), /*!< INDEX pulse interrupt enable. */ kENC_WatchdogTimeoutInterruptEnable = (1U << 2U), /*!< Watchdog timeout interrupt enable. */ kENC_PositionCompareInerruptEnable = (1U << 3U), /*!< Position compare interrupt enable. */ kENC_SimultBothPhaseChangeInterruptEnable = (1U << 4U), /*!< Simultaneous PHASEA and PHASEB change interrupt enable. */ kENC_PositionRollOverInterruptEnable = (1U << 5U), /*!< Roll-over interrupt enable. */ kENC_PositionRollUnderInterruptEnable = (1U << 6U), /*!< Roll-under interrupt enable. */};
/*! * @brief Status flag mask. * * These flags indicate the counter's events. */enum _enc_status_flags{ kENC_HOMETransitionFlag = (1U << 0U), /*!< HOME signal transition interrupt request. */ kENC_INDEXPulseFlag = (1U << 1U), /*!< INDEX Pulse Interrupt Request. */ kENC_WatchdogTimeoutFlag = (1U << 2U), /*!< Watchdog timeout interrupt request. */ kENC_PositionCompareFlag = (1U << 3U), /*!< Position compare interrupt request. */ kENC_SimultBothPhaseChangeFlag = (1U << 4U), /*!< Simultaneous PHASEA and PHASEB change interrupt request. */ kENC_PositionRollOverFlag = (1U << 5U), /*!< Roll-over interrupt request. */ kENC_PositionRollUnderFlag = (1U << 6U), /*!< Roll-under interrupt request. */ kENC_LastCountDirectionFlag = (1U << 7U), /*!< Last count was in the up direction, or the down direction. */};
/*! * @brief Signal status flag mask. * * These flags indicate the counter's signal. */enum _enc_signal_status_flags{ kENC_RawHOMEStatusFlag = ENC_IMR_HOME_MASK, /*!< Raw HOME input. */ kENC_RawINDEXStatusFlag = ENC_IMR_INDEX_MASK, /*!< Raw INDEX input. */ kENC_RawPHBStatusFlag = ENC_IMR_PHB_MASK, /*!< Raw PHASEB input. */ kENC_RawPHAEXStatusFlag = ENC_IMR_PHA_MASK, /*!< Raw PHASEA input. */ kENC_FilteredHOMEStatusFlag = ENC_IMR_FHOM_MASK, /*!< The filtered version of HOME input. */ kENC_FilteredINDEXStatusFlag = ENC_IMR_FIND_MASK, /*!< The filtered version of INDEX input. */ kENC_FilteredPHBStatusFlag = ENC_IMR_FPHB_MASK, /*!< The filtered version of PHASEB input. */ kENC_FilteredPHAStatusFlag = ENC_IMR_FPHA_MASK, /*!< The filtered version of PHASEA input. */};
/*! * @brief Define HOME signal's trigger mode. * * The ENC would count the trigger from HOME signal line. */typedef enum _enc_home_trigger_mode{ kENC_HOMETriggerDisabled = 0U, /*!< HOME signal's trigger is disabled. */ kENC_HOMETriggerOnRisingEdge, /*!< Use positive going edge-to-trigger initialization of position counters. */ kENC_HOMETriggerOnFallingEdge, /*!< Use negative going edge-to-trigger initialization of position counters. */} enc_home_trigger_mode_t;
/*! * @brief Define INDEX signal's trigger mode. * * The ENC would count the trigger from INDEX signal line. */typedef enum _enc_index_trigger_mode{ kENC_INDEXTriggerDisabled = 0U, /*!< INDEX signal's trigger is disabled. */ kENC_INDEXTriggerOnRisingEdge, /*!< Use positive going edge-to-trigger initialization of position counters. */ kENC_INDEXTriggerOnFallingEdge, /*!< Use negative going edge-to-trigger initialization of position counters. */} enc_index_trigger_mode_t;
/*! * @brief Define type for decoder work mode. * * The normal work mode uses the standard quadrature decoder with PHASEA and PHASEB. When in signal phase count mode, * a positive transition of the PHASEA input generates a count signal while the PHASEB input and the reverse direction * control the counter direction. If the reverse direction is not enabled, PHASEB = 0 means counting up and PHASEB = 1 * means counting down. Otherwise, the direction is reversed. */typedef enum _enc_decoder_work_mode{ kENC_DecoderWorkAsNormalMode = 0U, /*!< Use standard quadrature decoder with PHASEA and PHASEB. */ kENC_DecoderWorkAsSignalPhaseCountMode, /*!< PHASEA input generates a count signal while PHASEB input control the direction. */} enc_decoder_work_mode_t;
/*! * @brief Define type for the condition of POSMATCH pulses. */typedef enum _enc_position_match_mode{ kENC_POSMATCHOnPositionCounterEqualToComapreValue = 0U, /*!< POSMATCH pulses when a match occurs between the position counters (POS) and the compare value (COMP). */ kENC_POSMATCHOnReadingAnyPositionCounter, /*!< POSMATCH pulses when any position counter register is read. */} enc_position_match_mode_t;
/*! * @brief Define type for determining how the revolution counter (REV) is incremented/decremented. */typedef enum _enc_revolution_count_condition{ kENC_RevolutionCountOnINDEXPulse = 0U, /*!< Use INDEX pulse to increment/decrement revolution counter. */ kENC_RevolutionCountOnRollOverModulus, /*!< Use modulus counting roll-over/under to increment/decrement revolution counter. */} enc_revolution_count_condition_t;
/*! * @brief Define type for direction of self test generated signal. */typedef enum _enc_self_test_direction{ kENC_SelfTestDirectionPositive = 0U, /*!< Self test generates the signal in positive direction. */ kENC_SelfTestDirectionNegative, /*!< Self test generates the signal in negative direction. */} enc_self_test_direction_t;
/*! * @brief Define user configuration structure for ENC module. */typedef struct _enc_config{ /* Basic counter. */ bool enableReverseDirection; /*!< Enable reverse direction counting. */ enc_decoder_work_mode_t decoderWorkMode; /*!< Enable signal phase count mode. */
/* Signal detection. */ enc_home_trigger_mode_t HOMETriggerMode; /*!< Enable HOME to initialize position counters. */ enc_index_trigger_mode_t INDEXTriggerMode; /*!< Enable INDEX to initialize position counters. */ bool enableTRIGGERClearPositionCounter; /*!< Clear POSD, REV, UPOS and LPOS on rising edge of TRIGGER, or not. */ bool enableTRIGGERClearHoldPositionCounter; /*!< Enable update of hold registers on rising edge of TRIGGER, or not. */
/* Watchdog. */ bool enableWatchdog; /*!< Enable the watchdog to detect if the target is moving or not. */ uint16_t watchdogTimeoutValue; /*!< Watchdog timeout count value. It stores the timeout count for the quadrature decoder module watchdog timer. This field is only available when "enableWatchdog" = true. The available value is a 16-bit unsigned number.*/
/* Filter for PHASEA, PHASEB, INDEX and HOME. */ uint16_t filterCount; /*!< Input Filter Sample Count. This value should be chosen to reduce the probability of noisy samples causing an incorrect transition to be recognized. The value represent the number of consecutive samples that must agree prior to the input filter accepting an input transition. A value of 0x0 represents 3 samples. A value of 0x7 represents 10 samples. The Available range is 0 - 7.*/ uint16_t filterSamplePeriod; /*!< Input Filter Sample Period. This value should be set such that the sampling period is larger than the period of the expected noise. This value represents the sampling period (in IPBus clock cycles) of the decoder input signals. The available range is 0 - 255. */
/* Position compare. */ enc_position_match_mode_t positionMatchMode; /*!< The condition of POSMATCH pulses. */ uint32_t positionCompareValue; /*!< Position compare value. The available value is a 32-bit number.*/
/* Modulus counting. */ enc_revolution_count_condition_t revolutionCountCondition; /*!< Revolution Counter Modulus Enable. */ bool enableModuloCountMode; /*!< Enable Modulo Counting. */ uint32_t positionModulusValue; /*!< Position modulus value. This value would be available only when "enableModuloCountMode" = true. The available value is a 32-bit number. */ uint32_t positionInitialValue; /*!< Position initial value. The available value is a 32-bit number. */} enc_config_t;
/*! * @brief Define configuration structure for self test module. * * The self test module provides a quadrature test signal to the inputs of the quadrature decoder module. * This is a factory test feature. It is also useful to customers' software development and testing. */typedef struct _enc_self_test_config{ enc_self_test_direction_t signalDirection; /*!< Direction of self test generated signal. */ uint16_t signalCount; /*!< Hold the number of quadrature advances to generate. The available range is 0 - 255.*/ uint16_t signalPeriod; /*!< Hold the period of quadrature phase in IPBus clock cycles. The available range is 0 - 31. */} enc_self_test_config_t;



#define ENC_CTRL_W1C_FLAGS (ENC_CTRL_HIRQ_MASK | ENC_CTRL_XIRQ_MASK | ENC_CTRL_DIRQ_MASK | ENC_CTRL_CMPIRQ_MASK)#define ENC_CTRL2_W1C_FLAGS (ENC_CTRL2_SABIRQ_MASK | ENC_CTRL2_ROIRQ_MASK | ENC_CTRL2_RUIRQ_MASK)
void ENC_GetDefaultConfig(enc_config_t *config){ /* Initializes the configure structure to zero. */ memset(config, 0, sizeof(*config));
config->enableReverseDirection = false; config->decoderWorkMode = kENC_DecoderWorkAsNormalMode; config->HOMETriggerMode = kENC_HOMETriggerDisabled; config->INDEXTriggerMode = kENC_INDEXTriggerDisabled; config->enableTRIGGERClearPositionCounter = false; config->enableTRIGGERClearHoldPositionCounter = false; config->enableWatchdog = false; config->watchdogTimeoutValue = 0U; config->filterCount = 0U; config->filterSamplePeriod = 0U; config->positionMatchMode = kENC_POSMATCHOnPositionCounterEqualToComapreValue; config->positionCompareValue = 0xFFFFFFFFU; config->revolutionCountCondition = kENC_RevolutionCountOnINDEXPulse; config->enableModuloCountMode = false; config->positionModulusValue = 0U; config->positionInitialValue = 0U;}

void ENC_DoSoftwareLoadInitialPositionValue(){ uint16_t tmp16 = ENC1_CTRL & (uint16_t)(~ENC_CTRL_W1C_FLAGS);
tmp16 |= ENC_CTRL_SWIP_MASK; /* Write 1 to trigger the command for loading initial position value. */ ENC1_CTRL = tmp16;}
void ENC_Init(const enc_config_t *config){ uint32_t tmp16;
CCM_CCGR4 |= CCM_CCGR4_ENC1(CCM_CCGR_ON);
/* ENC_CTRL. */ tmp16 = ENC1_CTRL & (uint16_t)(~(ENC_CTRL_W1C_FLAGS | ENC_CTRL_HIP_MASK | ENC_CTRL_HNE_MASK | ENC_CTRL_REV_MASK | ENC_CTRL_PH1_MASK | ENC_CTRL_XIP_MASK | ENC_CTRL_XNE_MASK | ENC_CTRL_WDE_MASK)); /* For HOME trigger. */ if (kENC_HOMETriggerDisabled != config->HOMETriggerMode) { tmp16 |= ENC_CTRL_HIP_MASK; if (kENC_HOMETriggerOnFallingEdge == config->HOMETriggerMode) { tmp16 |= ENC_CTRL_HNE_MASK; } } /* For encoder work mode. */ if (config->enableReverseDirection) { tmp16 |= ENC_CTRL_REV_MASK; } if (kENC_DecoderWorkAsSignalPhaseCountMode == config->decoderWorkMode) { tmp16 |= ENC_CTRL_PH1_MASK; } /* For INDEX trigger. */ if (kENC_INDEXTriggerDisabled != config->INDEXTriggerMode) { tmp16 |= ENC_CTRL_XIP_MASK; if (kENC_INDEXTriggerOnFallingEdge == config->INDEXTriggerMode) { tmp16 |= ENC_CTRL_XNE_MASK; } } /* Watchdog. */ if (config->enableWatchdog) { tmp16 |= ENC_CTRL_WDE_MASK; ENC1_WTR = config->watchdogTimeoutValue; /* WDOG can be only available when the feature is enabled. */ } ENC1_CTRL = tmp16;
/* ENC_FILT. */ ENC1_FILT = ENC_FILT_FILT_CNT(config->filterCount) | ENC_FILT_FILT_PER(config->filterSamplePeriod);
/* ENC_CTRL2. */ tmp16 = ENC1_CTRL2 & (uint16_t)(~(ENC_CTRL2_W1C_FLAGS | ENC_CTRL2_OUTCTL_MASK | ENC_CTRL2_REVMOD_MASK | ENC_CTRL2_MOD_MASK | ENC_CTRL2_UPDPOS_MASK | ENC_CTRL2_UPDHLD_MASK)); if (kENC_POSMATCHOnReadingAnyPositionCounter == config->positionMatchMode) { tmp16 |= ENC_CTRL2_OUTCTL_MASK; } if (kENC_RevolutionCountOnRollOverModulus == config->revolutionCountCondition) { tmp16 |= ENC_CTRL2_REVMOD_MASK; } if (config->enableModuloCountMode) { tmp16 |= ENC_CTRL2_MOD_MASK; /* Set modulus value. */ ENC1_UMOD = (uint16_t)(config->positionModulusValue >> 16U); /* Upper 16 bits. */ ENC1_LMOD = (uint16_t)(config->positionModulusValue); /* Lower 16 bits. */ } if (config->enableTRIGGERClearPositionCounter) { tmp16 |= ENC_CTRL2_UPDPOS_MASK; } if (config->enableTRIGGERClearHoldPositionCounter) { tmp16 |= ENC_CTRL2_UPDHLD_MASK; } ENC1_CTRL2 = tmp16;
/* ENC_UCOMP & ENC_LCOMP. */ ENC1_UCOMP = (uint16_t)(config->positionCompareValue >> 16U); /* Upper 16 bits. */ ENC1_LCOMP = (uint16_t)(config->positionCompareValue); /* Lower 16 bits. */
/* ENC_UINIT & ENC_LINIT. */ ENC1_UINIT = (uint16_t)(config->positionInitialValue >> 16U); /* Upper 16 bits. */ ENC1_LINIT = (uint16_t)(config->positionInitialValue); /* Lower 16 bits. */}
uint32_t ENC_GetPositionValue(){ uint32_t ret32;
ret32 = ENC1_UPOS; /* Get upper 16 bits and make a snapshot. */ ret32 <<= 16U; ret32 |= ENC1_LPOSH; /* Get lower 16 bits from hold register. */
return ret32;}
void ENC_SetInitialPositionValue(uint32_t value){ ENC1_UINIT = (uint16_t)(value >> 16U); /* Set upper 16 bits. */ ENC1_LINIT = (uint16_t)(value); /* Set lower 16 bits. */}
uint32_t ENC_GetHoldPositionValue(){ uint32_t ret32;
ret32 = ENC1_UPOSH; /* Get upper 16 bits and make a snapshot. */ ret32 <<= 16U; ret32 |= ENC1_LPOSH; /* Get lower 16 bits from hold register. */
return ret32;}
/*! * @brief Get the hold position counter's value. * * When any of the counter registers is read, the contents of each counter register is written to the corresponding hold * register. Taking a snapshot of the counters' values provides a consistent view of a system position and a velocity to * be attained. * * @param base ENC peripheral base address. * * @return Hold position counter's value. */uint32_t ENC_GetHoldPositionValue(ENC_Type *base);
/*! * @brief Get the position difference counter's value. * * @param base ENC peripheral base address. * * @return The position difference counter's value. */static inline uint16_t ENC_GetPositionDifferenceValue(){ return ENC1_POSD;}
/*! * @brief Get the hold position difference counter's value. * * When any of the counter registers is read, the contents of each counter register is written to the corresponding hold * register. Taking a snapshot of the counters' values provides a consistent view of a system position and a velocity to * be attained. * * @param base ENC peripheral base address. * * @return Hold position difference counter's value. */static inline uint16_t ENC_GetHoldPositionDifferenceValue(){ return ENC1_POSDH;}
/*! * @brief Get the position revolution counter's value. * * @param base ENC peripheral base address. * * @return The position revolution counter's value. */static inline uint16_t ENC_GetRevolutionValue(){ return ENC1_REV;}/*! * @brief Get the hold position revolution counter's value. * * When any of the counter registers is read, the contents of each counter register is written to the corresponding hold * register. Taking a snapshot of the counters' values provides a consistent view of a system position and a velocity to * be attained. * * @param base ENC peripheral base address. * * @return Hold position revolution counter's value. */static inline uint16_t ENC_GetHoldRevolutionValue(){ return ENC1_REVH;}






#include <U8x8lib.h>
#define PHASEA 1#define PHASEB 2#define PULLUPS 0 //set to 1 if pullups are needed
#define CORE_XIO_PIN0 IOMUXC_XBAR1_IN17_SELECT_INPUT#define CORE_XIO_PIN1 IOMUXC_XBAR1_IN16_SELECT_INPUT#define CORE_XIO_PIN2 IOMUXC_XBAR1_IN06_SELECT_INPUT#define CORE_XIO_PIN3 IOMUXC_XBAR1_IN07_SELECT_INPUT#define CORE_XIO_PIN4 IOMUXC_XBAR1_IN08_SELECT_INPUT#define CORE_XIO_PIN5 IOMUXC_XBAR1_IN09_SELECT_INPUT#define CORE_XIO_PIN6 IOMUXC_XBAR1_IN15_SELECT_INPUT#define CORE_XIO_PIN7 IOMUXC_XBAR1_IN14_SELECT_INPUT
struct xio_pin_input_config_table_struct { volatile uint32_t *reg;};
const struct xio_pin_input_config_table_struct xio_pin_to_info_PGM[] = { {&CORE_XIO_PIN0}, {&CORE_XIO_PIN1}, {&CORE_XIO_PIN2}, {&CORE_XIO_PIN3}, {&CORE_XIO_PIN4}, {&CORE_XIO_PIN5}, {&CORE_XIO_PIN6}, {&CORE_XIO_PIN7}};

enc_config_t mEncConfigStruct;uint32_t mCurPosValue;U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(/* reset=*/U8X8_PIN_NONE);char buffer[50];
void setup(){ while(!Serial && millis() < 4000); delay(2000); // initialize and clear display u8x8.begin(); u8x8.setPowerSave(0); u8x8.setFont(u8x8_font_chroma48medium8_r); u8x8.drawString(0, 0, "Started!");

CCM_CCGR2 |= CCM_CCGR2_XBAR1(CCM_CCGR_ON); //turn clock on for xbara1
enc_xbara_mapping(2, PHASEA, PULLUPS); enc_xbara_mapping(3, PHASEB, PULLUPS);
//========================================================================== /* XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputIomuxXbarIn21, kXBARA1_OutputEnc1PhaseAInput); * XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputIomuxXbarIn22, kXBARA1_OutputEnc1PhaseBInput); * XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputIomuxXbarIn23, kXBARA1_OutputEnc1Index); * These are the SDK settings * kXBARA1_OutputEnc1PhaseAInput = 66|0x100U, // XBARA1_OUT66 output assigned to ENC1_PHASE_A_INPUT * kXBARA1_OutputEnc1PhaseBInput = 67|0x100U, // XBARA1_OUT67 output assigned to ENC1_PHASE_B_INPUT * kXBARA1_OutputEnc1Index = 68|0x100U, // XBARA1_OUT68 output assigned to ENC1_INDEX * kXBARA1_OutputEnc1Home = 69|0x100U, // XBARA1_OUT69 output assigned to ENC1_HOME * kXBARA1_OutputEnc1Trigger = 70|0x100U, // XBARA1_OUT70 output assigned to ENC1_TRIGGER * * kXBARA1_InputIomuxXbarInout06 = 6|0x100U, // IOMUX_XBAR_INOUT06 output assigned to XBARA1_IN6 input. * kXBARA1_InputIomuxXbarInout07 = 7|0x100U, // IOMUX_XBAR_INOUT07 output assigned to XBARA1_IN7 input. * kXBARA1_InputIomuxXbarInout08 = 8|0x100U, // IOMUX_XBAR_INOUT08 output assigned to XBARA1_IN8 input. */
Serial.print("IOMUXC_GPR_GPR6: "); Serial.println(IOMUXC_GPR_GPR6, BIN);
delay(2000); //========================================================================
/* Initialize the ENC module. */ ENC_GetDefaultConfig(&mEncConfigStruct); ENC_Init(&mEncConfigStruct); ENC_DoSoftwareLoadInitialPositionValue(); /* Update the position counter with initial value. */}
uint32_t old_position = 0;
void loop(){ /* This read operation would capture all the position counter to responding hold registers. */ mCurPosValue = ENC_GetPositionValue();
if(mCurPosValue != old_position){ /* Read the position values. */ Serial.printf("Current position value: %ld\r\n", mCurPosValue); Serial.printf("Position differential value: %d\r\n", (int16_t)ENC_GetHoldPositionDifferenceValue()); Serial.printf("Position revolution value: %d\r\n", ENC_GetHoldRevolutionValue()); Serial.println(); u8x8.drawString(0, 0, " "); sprintf(buffer, "%i", mCurPosValue); u8x8.drawString(0, 0, buffer); }
old_position = mCurPosValue;}

void enc_xbara_mapping(uint8_t pin, uint8_t PHASE, uint8_t PUS){
const struct digital_pin_bitband_and_config_table_struct *p; const struct xio_pin_input_config_table_struct *x; uint32_t pinmode, mask; uint8_t xbara1_mux[] = {1, 0, 0, 0, 0, 0, 1, 1}; uint16_t xbara1_IO[] = {17, 16, 6, 7, 8, 9, 15, 14}; if (pin >= 8) return; //first 8 pins are xbara1 io pins p = digital_pin_to_info_PGM + pin; //mux is ctrl config for pin //pad is pad config //pinmode = *(p->reg + 1); //Pin ctrl configuration for encoder/xbara1 if(pin == 2 || pin == 3 || pin == 4 || pin == 5) { *(p->mux) = 0x03; } else { *(p->mux) = 0x01; } //Pad configuration for encoder/xbara1 if(PUS == 0){ *(p->pad) = 0x10B0; } else { *(p->pad) = 0x1f038; } x = xio_pin_to_info_PGM + pin; *(x->reg) = xbara1_mux[pin];
//XBARA1 Connection to encoder if(PHASE == 1) xbar_connect(xbara1_IO[pin], 66); if(PHASE == 2) xbar_connect(xbara1_IO[pin], 67);
}void xbar_connect(unsigned int input, unsigned int output){ if (input >= 88) return; if (output >= 132) return;#if 1 volatile uint16_t *xbar = &XBARA1_SEL0 + (output / 2); uint16_t val = *xbar; if (!(output & 1)) { val = (val & 0xFF00) | input; } else { val = (val & 0x00FF) | (input << 8); } *xbar = val;#else // does not work, seems 8 bit access is not allowed volatile uint8_t *xbar = (volatile uint8_t *)XBARA1_SEL0; xbar[output] = input;#endif}