imxrt/encoder: add support for index position capture
This commit enhances imxrt encoder driver with index capture support. The index is captured when the index interrupt occurs and can be passed to application layer with QEIOC_GETINDEX ioctl call. Signed-off-by: Michal Lenc <michallenc@seznam.cz>
This commit is contained in:
parent
8e2b4576bf
commit
23b27419e2
@ -1025,6 +1025,10 @@ config ENC1_HNE
|
||||
|
||||
endif # ENC1_HIP
|
||||
|
||||
config ENC1_XIE
|
||||
bool "INDEX signal position capture"
|
||||
default n
|
||||
|
||||
config ENC1_XIP
|
||||
bool "INDEX signal initializes position counter"
|
||||
default n
|
||||
@ -1100,6 +1104,10 @@ config ENC2_HNE
|
||||
|
||||
endif # ENC2_HIP
|
||||
|
||||
config ENC2_XIE
|
||||
bool "INDEX signal position capture"
|
||||
default n
|
||||
|
||||
config ENC2_XIP
|
||||
bool "INDEX signal initializes position counter"
|
||||
default n
|
||||
@ -1177,6 +1185,10 @@ config ENC3_HNE
|
||||
|
||||
endif # ENC3_HIP
|
||||
|
||||
config ENC3_XIE
|
||||
bool "INDEX signal position capture"
|
||||
default n
|
||||
|
||||
config ENC3_XIP
|
||||
bool "INDEX signal initializes position counter"
|
||||
default n
|
||||
@ -1252,6 +1264,10 @@ config ENC4_HNE
|
||||
|
||||
endif # ENC4_HIP
|
||||
|
||||
config ENC4_XIE
|
||||
bool "INDEX signal position capture"
|
||||
default n
|
||||
|
||||
config ENC4_XIP
|
||||
bool "INDEX signal initializes position counter"
|
||||
default n
|
||||
|
@ -80,6 +80,10 @@
|
||||
# define CONFIG_ENC1_HNE 0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_ENC1_XIE
|
||||
# define CONFIG_ENC1_XIE 0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_ENC1_XIP
|
||||
# define CONFIG_ENC1_XIP 0
|
||||
#endif
|
||||
@ -121,6 +125,10 @@
|
||||
# define CONFIG_ENC2_HNE 0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_ENC2_XIE
|
||||
# define CONFIG_ENC2_XIE 0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_ENC2_XIP
|
||||
# define CONFIG_ENC2_XIP 0
|
||||
#endif
|
||||
@ -162,6 +170,10 @@
|
||||
# define CONFIG_ENC3_HNE 0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_ENC3_XIE
|
||||
# define CONFIG_ENC3_XIE 0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_ENC3_XIP
|
||||
# define CONFIG_ENC3_XIP 0
|
||||
#endif
|
||||
@ -203,6 +215,10 @@
|
||||
# define CONFIG_ENC4_HNE 0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_ENC4_XIE
|
||||
# define CONFIG_ENC4_XIE 0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_ENC4_XIP
|
||||
# define CONFIG_ENC4_XIP 0
|
||||
#endif
|
||||
@ -236,6 +252,7 @@
|
||||
#define XNE_SHIFT (3)
|
||||
#define REV_SHIFT (4)
|
||||
#define MOD_SHIFT (5)
|
||||
#define XIE_SHIFT (6)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
@ -246,6 +263,7 @@
|
||||
struct imxrt_qeconfig_s
|
||||
{
|
||||
uint32_t base; /* Register base address */
|
||||
uint32_t irq; /* Encoder interrupt */
|
||||
uint32_t init_val; /* Value to initialize position counters to */
|
||||
uint32_t modulus; /* Modulus to use when modulo counting is enabled */
|
||||
uint16_t in_filt_per; /* Period for input filter sampling in # of periph
|
||||
@ -258,13 +276,18 @@ struct imxrt_qeconfig_s
|
||||
* will reinitialize the position counter. Bits 4-0:
|
||||
* [MOD, REV, XNE, XIP, HNE, HIP]
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_DEBUG_SENSORS
|
||||
bool tst_dir_adv; /* Whether to generate down/up test signals */
|
||||
uint8_t tst_period; /* Period of PHASE pulses in # of periph clock cycles */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct imxrt_qedata_s
|
||||
{
|
||||
int32_t index_pos; /* Last position of index occurance */
|
||||
uint32_t index_cnt; /* Number of index occurance */
|
||||
};
|
||||
|
||||
/* ENC Device Private Data */
|
||||
|
||||
struct imxrt_enc_lowerhalf_s
|
||||
@ -277,10 +300,11 @@ struct imxrt_enc_lowerhalf_s
|
||||
|
||||
/* IMXRT driver-specific fields: */
|
||||
|
||||
const struct imxrt_qeconfig_s *config; /* static configuration */
|
||||
sem_t sem_excl; /* Mutual exclusion semaphore to
|
||||
* ensure atomic 32-bit reads.
|
||||
*/
|
||||
FAR const struct imxrt_qeconfig_s *config; /* static configuration */
|
||||
struct qe_index_s *data;
|
||||
sem_t sem_excl; /* Mutual exclusion semaphore to
|
||||
* ensure atomic 32-bit reads.
|
||||
*/
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@ -312,6 +336,8 @@ static void imxrt_enc_modulo_enable(struct imxrt_enc_lowerhalf_s *priv,
|
||||
uint32_t modulus);
|
||||
static void imxrt_enc_modulo_disable(struct imxrt_enc_lowerhalf_s *priv);
|
||||
|
||||
static int imxrt_enc_index(int irq, void *context, FAR void *arg);
|
||||
|
||||
#ifdef CONFIG_DEBUG_SENSORS
|
||||
static int imxrt_enc_test_gen(struct imxrt_enc_lowerhalf_s *priv,
|
||||
uint16_t value);
|
||||
@ -350,12 +376,14 @@ static const struct qe_ops_s g_qecallbacks =
|
||||
static const struct imxrt_qeconfig_s imxrt_enc1_config =
|
||||
{
|
||||
.base = IMXRT_ENC1_BASE,
|
||||
.irq = IMXRT_IRQ_ENC1,
|
||||
.init_val = CONFIG_ENC1_INITVAL,
|
||||
.modulus = CONFIG_ENC1_MODULUS,
|
||||
.in_filt_per = CONFIG_ENC1_FILTPER,
|
||||
.in_filt_cnt = CONFIG_ENC1_FILTCNT,
|
||||
.init_flags = CONFIG_ENC1_HIP << HIP_SHIFT |
|
||||
CONFIG_ENC1_HNE << HNE_SHIFT |
|
||||
CONFIG_ENC1_XIE << XIE_SHIFT |
|
||||
CONFIG_ENC1_XIP << XIP_SHIFT |
|
||||
CONFIG_ENC1_XNE << XNE_SHIFT |
|
||||
CONFIG_ENC1_DIR << REV_SHIFT |
|
||||
@ -367,10 +395,18 @@ static const struct imxrt_qeconfig_s imxrt_enc1_config =
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct qe_index_s imxrt_enc1_data =
|
||||
{
|
||||
.qenc_pos = 0,
|
||||
.indx_pos = 0,
|
||||
.indx_cnt = 0,
|
||||
};
|
||||
|
||||
static struct imxrt_enc_lowerhalf_s imxrt_enc1_priv =
|
||||
{
|
||||
.ops = &g_qecallbacks,
|
||||
.ops = &g_qecallbacks,
|
||||
.config = &imxrt_enc1_config,
|
||||
.data = &imxrt_enc1_data,
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -378,12 +414,14 @@ static struct imxrt_enc_lowerhalf_s imxrt_enc1_priv =
|
||||
static const struct imxrt_qeconfig_s imxrt_enc2_config =
|
||||
{
|
||||
.base = IMXRT_ENC2_BASE,
|
||||
.irq = IMXRT_IRQ_ENC2,
|
||||
.init_val = CONFIG_ENC2_INITVAL,
|
||||
.modulus = CONFIG_ENC2_MODULUS,
|
||||
.in_filt_per = CONFIG_ENC2_FILTPER,
|
||||
.in_filt_cnt = CONFIG_ENC2_FILTCNT,
|
||||
.init_flags = CONFIG_ENC2_HIP << HIP_SHIFT |
|
||||
CONFIG_ENC2_HNE << HNE_SHIFT |
|
||||
CONFIG_ENC2_XIE << XIE_SHIFT |
|
||||
CONFIG_ENC2_XIP << XIP_SHIFT |
|
||||
CONFIG_ENC2_XNE << XNE_SHIFT |
|
||||
CONFIG_ENC2_DIR << REV_SHIFT |
|
||||
@ -395,10 +433,18 @@ static const struct imxrt_qeconfig_s imxrt_enc2_config =
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct qe_index_s imxrt_enc2_data =
|
||||
{
|
||||
.qenc_pos = 0,
|
||||
.indx_pos = 0,
|
||||
.indx_cnt = 0,
|
||||
};
|
||||
|
||||
static struct imxrt_enc_lowerhalf_s imxrt_enc2_priv =
|
||||
{
|
||||
.ops = &g_qecallbacks,
|
||||
.config = &imxrt_enc2_config,
|
||||
.data = &imxrt_enc2_data,
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -406,12 +452,14 @@ static struct imxrt_enc_lowerhalf_s imxrt_enc2_priv =
|
||||
static const struct imxrt_qeconfig_s imxrt_enc3_config =
|
||||
{
|
||||
.base = IMXRT_ENC3_BASE,
|
||||
.irq = IMXRT_IRQ_ENC3,
|
||||
.init_val = CONFIG_ENC3_INITVAL,
|
||||
.modulus = CONFIG_ENC3_MODULUS,
|
||||
.in_filt_per = CONFIG_ENC3_FILTPER,
|
||||
.in_filt_cnt = CONFIG_ENC3_FILTCNT,
|
||||
.init_flags = CONFIG_ENC3_HIP << HIP_SHIFT |
|
||||
CONFIG_ENC3_HNE << HNE_SHIFT |
|
||||
CONFIG_ENC3_XIE << XIE_SHIFT |
|
||||
CONFIG_ENC3_XIP << XIP_SHIFT |
|
||||
CONFIG_ENC3_XNE << XNE_SHIFT |
|
||||
CONFIG_ENC3_DIR << REV_SHIFT |
|
||||
@ -423,10 +471,18 @@ static const struct imxrt_qeconfig_s imxrt_enc3_config =
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct qe_index_s imxrt_enc3_data =
|
||||
{
|
||||
.qenc_pos = 0,
|
||||
.indx_pos = 0,
|
||||
.indx_cnt = 0,
|
||||
};
|
||||
|
||||
static struct imxrt_enc_lowerhalf_s imxrt_enc3_priv =
|
||||
{
|
||||
.ops = &g_qecallbacks,
|
||||
.config = &imxrt_enc3_config,
|
||||
.data = &imxrt_enc3_data,
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -434,12 +490,14 @@ static struct imxrt_enc_lowerhalf_s imxrt_enc3_priv =
|
||||
static const struct imxrt_qeconfig_s imxrt_enc4_config =
|
||||
{
|
||||
.base = IMXRT_ENC4_BASE,
|
||||
.irq = IMXRT_IRQ_ENC4,
|
||||
.init_val = CONFIG_ENC4_INITVAL,
|
||||
.modulus = CONFIG_ENC4_MODULUS,
|
||||
.in_filt_per = CONFIG_ENC4_FILTPER,
|
||||
.in_filt_cnt = CONFIG_ENC4_FILTCNT,
|
||||
.init_flags = CONFIG_ENC4_HIP << HIP_SHIFT |
|
||||
CONFIG_ENC4_HNE << HNE_SHIFT |
|
||||
CONFIG_ENC4_XIE << XIE_SHIFT |
|
||||
CONFIG_ENC4_XIP << XIP_SHIFT |
|
||||
CONFIG_ENC4_XNE << XNE_SHIFT |
|
||||
CONFIG_ENC4_DIR << REV_SHIFT |
|
||||
@ -451,10 +509,18 @@ static const struct imxrt_qeconfig_s imxrt_enc4_config =
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct qe_index_s imxrt_enc4_data =
|
||||
{
|
||||
.qenc_pos = 0,
|
||||
.indx_pos = 0,
|
||||
.indx_cnt = 0,
|
||||
};
|
||||
|
||||
static struct imxrt_enc_lowerhalf_s imxrt_enc4_priv =
|
||||
{
|
||||
.ops = &g_qecallbacks,
|
||||
.config = &imxrt_enc4_config,
|
||||
.data = &imxrt_enc4_data,
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -640,6 +706,15 @@ static int imxrt_enc_reconfig(struct imxrt_enc_lowerhalf_s *priv,
|
||||
clear |= ENC_CTRL_HNE;
|
||||
}
|
||||
|
||||
if ((args >> XIE_SHIFT) & 1)
|
||||
{
|
||||
set |= ENC_CTRL_XIE;
|
||||
}
|
||||
else
|
||||
{
|
||||
clear |= ENC_CTRL_XIE;
|
||||
}
|
||||
|
||||
if ((args >> XIP_SHIFT) & 1)
|
||||
{
|
||||
set |= ENC_CTRL_XIP;
|
||||
@ -752,6 +827,41 @@ static void imxrt_enc_modulo_disable(struct imxrt_enc_lowerhalf_s *priv)
|
||||
imxrt_enc_modifyreg16(priv, IMXRT_ENC_CTRL2_OFFSET, ENC_CTRL2_MOD, 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imxrt_enc_index
|
||||
*
|
||||
* Description:
|
||||
* Get the index position and increments index count.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int imxrt_enc_index(int irq, void *context, FAR void *arg)
|
||||
{
|
||||
FAR struct imxrt_enc_lowerhalf_s *priv =
|
||||
(FAR struct imxrt_enc_lowerhalf_s *)arg;
|
||||
FAR const struct imxrt_qeconfig_s *config = priv->config;
|
||||
FAR struct qe_index_s *data = priv->data;
|
||||
uint16_t regval = getreg16(config->base + IMXRT_ENC_CTRL_OFFSET);
|
||||
|
||||
if ((regval & ENC_CTRL_XIRQ) != 0)
|
||||
{
|
||||
/* Clear the interrupt */
|
||||
|
||||
regval |= ENC_CTRL_XIRQ;
|
||||
putreg16(regval, config->base + IMXRT_ENC_CTRL_OFFSET);
|
||||
|
||||
/* Get index position */
|
||||
|
||||
imxrt_position(arg, &data->indx_pos);
|
||||
|
||||
/* Increment index count */
|
||||
|
||||
priv->data->indx_cnt += 1;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_SENSORS
|
||||
|
||||
/****************************************************************************
|
||||
@ -867,6 +977,18 @@ static int imxrt_setup(struct qe_lowerhalf_s *lower)
|
||||
imxrt_enc_putreg16(priv, IMXRT_ENC_TST_OFFSET, regval);
|
||||
#endif
|
||||
|
||||
if ((config->init_flags && XIE_SHIFT) == 1)
|
||||
{
|
||||
ret = irq_attach(config->irq, imxrt_enc_index, priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
snerr("ERROR: irq_attach failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
up_enable_irq(config->irq);
|
||||
}
|
||||
|
||||
/* Control and Control 2 register */
|
||||
|
||||
regval = ENC_CTRL_SWIP;
|
||||
@ -874,6 +996,7 @@ static int imxrt_setup(struct qe_lowerhalf_s *lower)
|
||||
regval |= ((config->init_flags >> HIP_SHIFT) & 1) ? ENC_CTRL_HIP : 0;
|
||||
regval |= ((config->init_flags >> HNE_SHIFT) & 1) ? ENC_CTRL_HNE : 0;
|
||||
regval |= ((config->init_flags >> XIP_SHIFT) & 1) ? ENC_CTRL_XIP : 0;
|
||||
regval |= ((config->init_flags >> XIE_SHIFT) & 1) ? ENC_CTRL_XIE : 0;
|
||||
regval |= ((config->init_flags >> XNE_SHIFT) & 1) ? ENC_CTRL_XNE : 0;
|
||||
imxrt_enc_putreg16(priv, IMXRT_ENC_CTRL_OFFSET, regval);
|
||||
|
||||
@ -913,6 +1036,15 @@ static int imxrt_shutdown(struct qe_lowerhalf_s *lower)
|
||||
imxrt_enc_putreg16(priv, IMXRT_ENC_TST_OFFSET, 0);
|
||||
#endif
|
||||
|
||||
/* Disable interrupts if used */
|
||||
|
||||
if ((priv->config->init_flags && XIE_SHIFT) == 1)
|
||||
{
|
||||
up_disable_irq(priv->config->irq);
|
||||
|
||||
irq_detach(priv->config->irq);
|
||||
}
|
||||
|
||||
imxrt_enc_putreg16(priv, IMXRT_ENC_FILT_OFFSET, 0);
|
||||
imxrt_enc_putreg16(priv, IMXRT_ENC_LINIT_OFFSET, 0);
|
||||
imxrt_enc_putreg16(priv, IMXRT_ENC_UINIT_OFFSET, 0);
|
||||
@ -1027,6 +1159,7 @@ static int imxrt_ioctl(struct qe_lowerhalf_s *lower, int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
struct imxrt_enc_lowerhalf_s *priv = (struct imxrt_enc_lowerhalf_s *)lower;
|
||||
FAR struct qe_index_s *data = priv->data;
|
||||
switch (cmd)
|
||||
{
|
||||
/* QEIOC_POSDIFF:
|
||||
@ -1055,6 +1188,10 @@ static int imxrt_ioctl(struct qe_lowerhalf_s *lower, int cmd,
|
||||
case QEIOC_RESETATMAX:
|
||||
imxrt_enc_modulo_disable(priv);
|
||||
break;
|
||||
case QEIOC_GETINDEX:
|
||||
imxrt_position(lower, &data->qenc_pos);
|
||||
*((struct qe_index_s *)arg) = *data;
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_DEBUG_SENSORS
|
||||
case QEIOC_TEST_GEN:
|
||||
|
Loading…
Reference in New Issue
Block a user