Extend I/O Expander interrupt controls; Add test of level sensitve interrupt to Simulated I/O expander
This commit is contained in:
parent
189d2cf475
commit
3d5df2e5af
@ -59,6 +59,11 @@
|
||||
|
||||
#define SIM_POLLDELAY (CONFIG_SIM_INT_POLLDELAY / USEC_PER_TICK)
|
||||
|
||||
#define SIM_INT_ENABLED(d,p) \
|
||||
(((d)->intenab & ((ioe_pinset_t)1 << (p))) != 0)
|
||||
#define SIM_INT_DISABLED(d,p) \
|
||||
(((d)->intenab & ((ioe_pinset_t)1 << (p))) == 0)
|
||||
|
||||
#define SIM_LEVEL_SENSITIVE(d,p) \
|
||||
(((d)->trigger & ((ioe_pinset_t)1 << (p))) == 0)
|
||||
#define SIM_LEVEL_HIGH(d,p) \
|
||||
@ -99,6 +104,7 @@ struct sim_dev_s
|
||||
ioe_pinset_t invert; /* Pin value inversion */
|
||||
ioe_pinset_t outval; /* Value of output pins */
|
||||
ioe_pinset_t inval; /* Simulated input register */
|
||||
ioe_pinset_t intenab; /* Interrupt enable */
|
||||
ioe_pinset_t last; /* Last pin inputs (for detection of changes) */
|
||||
ioe_pinset_t trigger; /* Bit encoded: 0=level 1=edge */
|
||||
ioe_pinset_t level[2]; /* Bit encoded: 01=high/rising, 10 low/falling, 11 both */
|
||||
@ -281,35 +287,44 @@ static int sim_option(FAR struct ioexpander_dev_s *dev, uint8_t pin,
|
||||
switch ((uintptr_t)value)
|
||||
{
|
||||
case IOEXPANDER_VAL_HIGH: /* Interrupt on high level */
|
||||
priv->intenab |= bit;
|
||||
priv->trigger &= ~bit;
|
||||
priv->level[0] |= bit;
|
||||
priv->level[1] &= ~bit;
|
||||
break;
|
||||
|
||||
case IOEXPANDER_VAL_LOW: /* Interrupt on low level */
|
||||
priv->intenab |= bit;
|
||||
priv->trigger &= ~bit;
|
||||
priv->level[0] &= ~bit;
|
||||
priv->level[1] |= bit;
|
||||
break;
|
||||
|
||||
case IOEXPANDER_VAL_RISING: /* Interrupt on rising edge */
|
||||
priv->intenab |= bit;
|
||||
priv->trigger |= bit;
|
||||
priv->level[0] |= bit;
|
||||
priv->level[1] &= ~bit;
|
||||
break;
|
||||
|
||||
case IOEXPANDER_VAL_FALLING: /* Interrupt on falling edge */
|
||||
priv->intenab |= bit;
|
||||
priv->trigger |= bit;
|
||||
priv->level[0] &= ~bit;
|
||||
priv->level[1] |= bit;
|
||||
break;
|
||||
|
||||
case IOEXPANDER_VAL_BOTH: /* Interrupt on both edges */
|
||||
priv->intenab |= bit;
|
||||
priv->trigger |= bit;
|
||||
priv->level[0] |= bit;
|
||||
priv->level[1] |= bit;
|
||||
break;
|
||||
|
||||
case IOEXPANDER_VAL_DISABLE:
|
||||
priv->trigger &= ~bit;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
@ -655,20 +670,26 @@ static ioe_pinset_t sim_int_update(FAR struct sim_dev_s *priv)
|
||||
|
||||
for (pin = 0; pin < CONFIG_IOEXPANDER_NPINS; pin++)
|
||||
{
|
||||
if (SIM_EDGE_SENSITIVE(priv, pin))
|
||||
/* Get the value of the pin (accounting for inversion) */
|
||||
|
||||
pinval = ((input & 1) != 0);
|
||||
if ((priv->invert & (1 << pin)) != 0)
|
||||
{
|
||||
pinval = !pinval;
|
||||
}
|
||||
|
||||
if (SIM_INT_DISABLED(priv, pin))
|
||||
{
|
||||
/* Interrupts disabled on this pin. Do nothing.. just skip to the
|
||||
* next pin.
|
||||
*/
|
||||
}
|
||||
else if (SIM_EDGE_SENSITIVE(priv, pin))
|
||||
{
|
||||
/* Edge triggered. Was there a change in the level? */
|
||||
|
||||
if ((diff & 1) != 0)
|
||||
{
|
||||
/* Get the value of the pin (accounting for inversion) */
|
||||
|
||||
pinval = ((input & 1) != 0);
|
||||
if ((priv->invert & (1 << pin)) != 0)
|
||||
{
|
||||
pinval = !pinval;
|
||||
}
|
||||
|
||||
/* Set interrupt as a function of edge type */
|
||||
|
||||
if ((!pinval && SIM_EDGE_FALLING(priv, pin)) ||
|
||||
|
@ -73,17 +73,44 @@ int sim_gpio_initialize(void)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Register three pin drivers */
|
||||
/* Register four pin drivers */
|
||||
|
||||
/* Pin 0: an non-inverted, input pin */
|
||||
|
||||
(void)IOEXP_SETDIRECTION(ioe, 0, IOEXPANDER_DIRECTION_IN);
|
||||
(void)IOEXP_SETOPTION(ioe, 0, IOEXPANDER_OPTION_INVERT,
|
||||
(FAR void *)IOEXPANDER_VAL_NORMAL);
|
||||
(void)IOEXP_SETOPTION(ioe, 0, IOEXPANDER_OPTION_INTCFG,
|
||||
(FAR void *)IOEXPANDER_VAL_DISABLE);
|
||||
(void)gpio_lower_half(ioe, 0, GPIO_INPUT_PIN, 0);
|
||||
|
||||
/* Pin 1: an non-inverted, output pin */
|
||||
|
||||
(void)IOEXP_SETDIRECTION(ioe, 1, IOEXPANDER_DIRECTION_OUT);
|
||||
(void)IOEXP_SETOPTION(ioe, 1, IOEXPANDER_OPTION_INVERT,
|
||||
(FAR void *)IOEXPANDER_VAL_NORMAL);
|
||||
(void)IOEXP_SETOPTION(ioe, 2, IOEXPANDER_OPTION_INTCFG,
|
||||
(FAR void *)IOEXPANDER_VAL_DISABLE);
|
||||
(void)gpio_lower_half(ioe, 1, GPIO_OUTPUT_PIN, 1);
|
||||
|
||||
/* Pin 2: an non-inverted, edge interrupting pin */
|
||||
|
||||
(void)IOEXP_SETDIRECTION(ioe, 2, IOEXPANDER_DIRECTION_IN);
|
||||
(void)IOEXP_SETOPTION(ioe, 2, IOEXPANDER_OPTION_INVERT,
|
||||
(FAR void *)IOEXPANDER_VAL_NORMAL);
|
||||
(void)IOEXP_SETOPTION(ioe, 2, IOEXPANDER_OPTION_INTCFG,
|
||||
(FAR void *)IOEXPANDER_VAL_BOTH);
|
||||
(void)gpio_lower_half(ioe, 2, GPIO_INTERRUPT_PIN, 2);
|
||||
|
||||
/* Pin 3: a non-inverted, level interrupting pin */
|
||||
|
||||
(void)IOEXP_SETDIRECTION(ioe, 3, IOEXPANDER_DIRECTION_IN);
|
||||
(void)IOEXP_SETOPTION(ioe, 3, IOEXPANDER_OPTION_INVERT,
|
||||
(FAR void *)IOEXPANDER_VAL_NORMAL);
|
||||
(void)IOEXP_SETOPTION(ioe, 3, IOEXPANDER_OPTION_INTCFG,
|
||||
(FAR void *)IOEXPANDER_VAL_HIGH);
|
||||
(void)gpio_lower_half(ioe, 3, GPIO_INTERRUPT_PIN, 3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_EXAMPLES_GPIO && CONFIG_GPIO_LOWER_HALF */
|
||||
|
@ -366,6 +366,9 @@ static int pcf8574_option(FAR struct ioexpander_dev_s *dev, uint8_t pin,
|
||||
priv->level[1] |= bit;
|
||||
break;
|
||||
|
||||
case IOEXPANDER_VAL_DISABLE:
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
@ -612,6 +612,9 @@ static int tca64_option(FAR struct ioexpander_dev_s *dev, uint8_t pin,
|
||||
priv->level[1] |= bit;
|
||||
break;
|
||||
|
||||
case IOEXPANDER_VAL_DISABLE:
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
@ -61,25 +61,27 @@
|
||||
|
||||
/* Pin definitions **********************************************************/
|
||||
|
||||
#define IOEXPANDER_DIRECTION_IN 0
|
||||
#define IOEXPANDER_DIRECTION_OUT 1
|
||||
#define IOEXPANDER_DIRECTION_IN 0
|
||||
#define IOEXPANDER_DIRECTION_OUT 1
|
||||
|
||||
#define IOEXPANDER_PINMASK (((ioe_pinset_t)1 << CONFIG_IOEXPANDER_NPINS) - 1)
|
||||
#define PINSET_ALL (~((ioe_pinset_t)0))
|
||||
#define IOEXPANDER_PINMASK (((ioe_pinset_t)1 << CONFIG_IOEXPANDER_NPINS) - 1)
|
||||
#define PINSET_ALL (~((ioe_pinset_t)0))
|
||||
|
||||
/* Pin options */
|
||||
|
||||
#define IOEXPANDER_OPTION_INVERT 1 /* Set the "active" level for a pin */
|
||||
# define IOEXPANDER_VAL_NORMAL 0 /* Normal, no inversion */
|
||||
# define IOEXPANDER_VAL_INVERT 1 /* Inverted */
|
||||
#define IOEXPANDER_OPTION_INVERT 1 /* Set the "active" level for a pin */
|
||||
# define IOEXPANDER_VAL_NORMAL 0 /* Normal, no inversion */
|
||||
# define IOEXPANDER_VAL_INVERT 1 /* Inverted */
|
||||
|
||||
#define IOEXPANDER_OPTION_INTCFG 2 /* Configure interrupt for a pin */
|
||||
# define IOEXPANDER_VAL_LEVEL 1 /* xx1 Interrupt on level (vs. edge) */
|
||||
# define IOEXPANDER_VAL_HIGH 1 /* 001 Interrupt on high level */
|
||||
# define IOEXPANDER_VAL_LOW 3 /* 011 Interrupt on low level */
|
||||
# define IOEXPANDER_VAL_RISING 2 /* 010 Interrupt on rising edge */
|
||||
# define IOEXPANDER_VAL_FALLING 4 /* 100 Interrupt on falling edge */
|
||||
# define IOEXPANDER_VAL_BOTH 6 /* 110 Interrupt on both edges */
|
||||
#define IOEXPANDER_OPTION_INTCFG 2 /* Configure interrupt for a pin */
|
||||
# define IOEXPANDER_VAL_DISABLE 0 /* 0000 Disable pin interrupts */
|
||||
# define IOEXPANDER_VAL_LEVEL 1 /* xx01 Interrupt on level (vs. edge) */
|
||||
# define IOEXPANDER_VAL_HIGH 5 /* 0101 Interrupt on high level */
|
||||
# define IOEXPANDER_VAL_LOW 9 /* 1001 Interrupt on low level */
|
||||
# define IOEXPANDER_VAL_EDGE 2 /* xx10 Interrupt on edge (vs. level) */
|
||||
# define IOEXPANDER_VAL_RISING 6 /* 0110 Interrupt on rising edge */
|
||||
# define IOEXPANDER_VAL_FALLING 10 /* 1010 Interrupt on falling edge */
|
||||
# define IOEXPANDER_VAL_BOTH 14 /* 1110 Interrupt on both edges */
|
||||
|
||||
/* Access macros ************************************************************/
|
||||
|
||||
@ -319,20 +321,23 @@ struct ioexpander_ops_s
|
||||
CODE int (*ioe_direction)(FAR struct ioexpander_dev_s *dev, uint8_t pin,
|
||||
int direction);
|
||||
CODE int (*ioe_option)(FAR struct ioexpander_dev_s *dev, uint8_t pin,
|
||||
int opt, void *val);
|
||||
int opt, FAR void *val);
|
||||
CODE int (*ioe_writepin)(FAR struct ioexpander_dev_s *dev, uint8_t pin,
|
||||
bool value);
|
||||
CODE int (*ioe_readpin)(FAR struct ioexpander_dev_s *dev, uint8_t pin,
|
||||
bool *value);
|
||||
FAR bool *value);
|
||||
CODE int (*ioe_readbuf)(FAR struct ioexpander_dev_s *dev, uint8_t pin,
|
||||
bool *value);
|
||||
FAR bool *value);
|
||||
#ifdef CONFIG_IOEXPANDER_MULTIPIN
|
||||
CODE int (*ioe_multiwritepin)(FAR struct ioexpander_dev_s *dev,
|
||||
uint8_t *pins, bool *values, int count);
|
||||
FAR uint8_t *pins, FAR bool *values,
|
||||
int count);
|
||||
CODE int (*ioe_multireadpin)(FAR struct ioexpander_dev_s *dev,
|
||||
uint8_t *pins, bool *values, int count);
|
||||
FAR uint8_t *pins, FAR bool *values,
|
||||
int count);
|
||||
CODE int (*ioe_multireadbuf)(FAR struct ioexpander_dev_s *dev,
|
||||
uint8_t *pins, bool *values, int count);
|
||||
FAR uint8_t *pins, FAR bool *values,
|
||||
int count);
|
||||
#endif
|
||||
#ifdef CONFIG_IOEXPANDER_INT_ENABLE
|
||||
CODE FAR void *(*ioe_attach)(FAR struct ioexpander_dev_s *dev,
|
||||
|
Loading…
Reference in New Issue
Block a user