diff --git a/drivers/analog/adc.c b/drivers/analog/adc.c index 1b16f9428f..db91a33251 100644 --- a/drivers/analog/adc.c +++ b/drivers/analog/adc.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include @@ -78,6 +79,8 @@ static int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, static void adc_notify(FAR struct adc_dev_s *dev); static int adc_poll(FAR struct file *filep, struct pollfd *fds, bool setup); +static int adc_reset_fifo(FAR struct adc_dev_s *dev); +static int adc_samples_on_read(FAR struct adc_dev_s *dev); /**************************************************************************** * Private Data @@ -431,7 +434,29 @@ static int adc_ioctl(FAR struct file *filep, int cmd, unsigned long arg) FAR struct adc_dev_s *dev = inode->i_private; int ret; - ret = dev->ad_ops->ao_ioctl(dev, cmd, arg); + switch (cmd) + { + case ANIOC_RESET_FIFO: + { + ret = adc_reset_fifo(dev); + } + break; + + case ANIOC_SAMPLES_ON_READ: + { + ret = adc_samples_on_read(dev); + } + break; + + default: + { + /* Those IOCTLs might be used in arch specific section */ + + ret = dev->ad_ops->ao_ioctl(dev, cmd, arg); + } + break; + } + return ret; } @@ -613,6 +638,54 @@ return_with_irqdisabled: return ret; } +/**************************************************************************** + * Name: adc_reset_fifo + ****************************************************************************/ + +static int adc_reset_fifo(FAR struct adc_dev_s *dev) +{ + irqstate_t flags; + FAR struct adc_fifo_s *fifo = &dev->ad_recv; + + /* Interrupts must be disabled while accessing the ad_recv FIFO */ + + flags = enter_critical_section(); + + fifo->af_head = fifo->af_tail; + + leave_critical_section(flags); + + return OK; +} + +/**************************************************************************** + * Name: adc_samples_on_read + ****************************************************************************/ + +static int adc_samples_on_read(FAR struct adc_dev_s *dev) +{ + irqstate_t flags; + FAR struct adc_fifo_s *fifo = &dev->ad_recv; + int16_t ret; + + /* Interrupts must be disabled while accessing the ad_recv FIFO */ + + flags = enter_critical_section(); + + ret = fifo->af_tail - fifo->af_head; + + leave_critical_section(flags); + + if (ret < 0) + { + /* Increment return value by the size of FIFO */ + + ret += CONFIG_ADC_FIFOSIZE; + } + + return ret; +} + /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/include/nuttx/analog/ioctl.h b/include/nuttx/analog/ioctl.h index 39860fbbc7..6859af9b1e 100644 --- a/include/nuttx/analog/ioctl.h +++ b/include/nuttx/analog/ioctl.h @@ -40,24 +40,32 @@ /* DAC/ADC */ -#define ANIOC_TRIGGER _ANIOC(0x0001) /* Trigger one conversion - * IN: None - * OUT: None */ -#define ANIOC_WDOG_UPPER _ANIOC(0x0002) /* Set upper threshold for - * watchdog - * IN: Threshold value - * OUT: None */ -#define ANIOC_WDOG_LOWER _ANIOC(0x0003) /* Set lower threshold for - * watchdog - * IN: Threshold value - * OUT: None */ -#define ANIOC_GET_NCHANNELS _ANIOC(0x0004) /* Get the number of - * configured channels - * IN: None - * OUT: Number of channels */ +#define ANIOC_TRIGGER _ANIOC(0x0001) /* Trigger one conversion + * IN: None + * OUT: None */ +#define ANIOC_WDOG_UPPER _ANIOC(0x0002) /* Set upper threshold for + * watchdog + * IN: Threshold value + * OUT: None */ +#define ANIOC_WDOG_LOWER _ANIOC(0x0003) /* Set lower threshold for + * watchdog + * IN: Threshold value + * OUT: None */ +#define ANIOC_GET_NCHANNELS _ANIOC(0x0004) /* Get the number of + * configured channels + * IN: None + * OUT: Number of channels */ +#define ANIOC_RESET_FIFO _ANIOC(0x0005) /* Clear data receive FIFO + * IN: None + * OUT: None */ +#define ANIOC_SAMPLES_ON_READ _ANIOC(0x0006) /* Get the number of + * samples to be read + * IN: None + * OUT: Number of samples + * waiting to be read */ #define AN_FIRST 0x0001 /* First common command */ -#define AN_NCMDS 4 /* Number of common commands */ +#define AN_NCMDS 6 /* Number of common commands */ /* User defined ioctl commands are also supported. These will be forwarded * by the upper-half driver to the lower-half driver via the ioctl()