Add partial support for event driven conversions Only two events supported yet. Suppo...
authorNathael Pajani <nathael.pajani@ed3l.fr>
Fri, 26 Sep 2014 10:09:51 +0000 (12:09 +0200)
committerNathael Pajani <nathael.pajani@ed3l.fr>
Tue, 8 Nov 2022 16:03:04 +0000 (17:03 +0100)
drivers/adc.c
include/core/lpc_regs_12xx.h
include/drivers/adc.h

index 669960f..8d4dfc9 100644 (file)
@@ -29,6 +29,7 @@
 #include "core/lpc_core_cm0.h"
 #include "core/system.h"
 #include "core/pio.h"
+#include "drivers/adc.h"
 
 /* Should be as near to 9MHz as possible */
 #define adc_clk_Val  9000000
@@ -47,34 +48,13 @@ void ADC_Handler(void)
        /* FIXME : Add an handler callback. */
 }
 
-/* Start a conversion on the given channel (0 to 7) */
-void adc_start_convertion_once(unsigned int channel, int use_int)
-{
-       struct lpc_adc* adc = LPC_ADC;
-
-       if (channel > 7)
-               return;
-
-       /* Set conversion channel bit */
-       adc->ctrl = ((adc->ctrl & ~LPC_ADC_CHANNEL_MASK) | LPC_ADC_CHANNEL(channel));
-       if (use_int) {
-               /* Set interrupt Bit */
-               adc->int_en = LPC_ADC_CHANNEL(channel);
-       } else {
-               adc->int_en = 0;
-       }
-       /* Clear burst conversion if running ? */
-       adc->ctrl &= ~LPC_ADC_BURST;
-       /* Start conversion */
-       adc->ctrl = ((adc->ctrl & ~LPC_ADC_START_CONV_MASK) | LPC_ADC_START_CONV_NOW);
-}
-
-
 /* Read the conversion from the given channel (0 to 7) 
  * This function reads the conversion value directly in the data register and
  * always returns a value.
- * Return 1 if the value is a new one, else return 0.
+ * Return 0 if the value is a new one and no overrun occured.
  * Return -1 if channel does not exist
+ * Retuen 1 if the value is an old one
+ * Return 2 if an overrun occured
  */
 int adc_get_value(uint16_t * val, int channel)
 {
@@ -89,11 +69,43 @@ int adc_get_value(uint16_t * val, int channel)
        *val = ((save_reg >> LPC_ADC_RESULT_SHIFT) & LPC_ADC_RESULT_MASK);
        /* Has this conversion value been already read ? */
        if (! (save_reg & LPC_ADC_CONV_DONE)) {
-               return 0;
+               return 1;
+       }
+       if (save_reg & LPC_ADC_OVERRUN) {
+               return 2;
        }
-       return 1;
+       return 0;
 }
 
+/* Start a conversion on the given channel (0 to 7) */
+void adc_start_convertion_once(unsigned int channel, int use_int)
+{
+       struct lpc_adc* adc = LPC_ADC;
+       uint32_t reg_val = 0;
+
+       if (channel > 7)
+               return;
+
+       /* Get a clean control register */
+       reg_val = adc->ctrl & ~(LPC_ADC_CHANNEL_MASK | LPC_ADC_START_CONV_MASK | LPC_ADC_BURST);
+
+       /* Set conversion channel bit */
+       reg_val |= LPC_ADC_CHANNEL(channel);
+
+       /*  Use of interrupts for the specified channel ? */
+       if (use_int) {
+               /* Set interrupt Bit */
+               adc->int_en = LPC_ADC_CHANNEL(channel);
+       } else {
+               adc->int_en = 0;
+       }
+
+       /* Start conversion */
+       reg_val |= LPC_ADC_START_CONV_NOW;
+       adc->ctrl = (reg_val & LPC_ADC_CTRL_MASK);
+}
+
+
 /* Start burst conversions.
  * channels is a bit mask of requested channels.
  * Use LPC_ADC_CHANNEL(x) (x = 0 .. 7) for channels selection.
@@ -103,20 +115,58 @@ void adc_start_burst_conversion(uint8_t channels)
        struct lpc_adc* adc = LPC_ADC;
        uint32_t reg_val = 0;
 
+       /* Get a clean control register */
+       reg_val = adc->ctrl & ~(LPC_ADC_CHANNEL_MASK | LPC_ADC_START_CONV_MASK | LPC_ADC_BURST);
+
        /* Set conversion channel bits and burst mode */
-       reg_val = ((adc->ctrl & ~LPC_ADC_CHANNEL_MASK) | channels);
+       reg_val |= channels;
        reg_val |= LPC_ADC_BURST;
+
+       /*  Use of interrupts for the specified channels ? */
+       /* FIXME : Need to choose between one single global interrupt or specific interrupts .... */
+       /* FIXME : Actually none. */
+       adc->int_en = 0;
+
+       /* Start conversion */
        adc->ctrl = (reg_val & LPC_ADC_CTRL_MASK);
 }
 
 
-/* Unsupported Yet */
 /* This should be used to configure conversion start on falling or rising edges of
  * some signals, or on timer for burst conversions.
  */
-void adc_prepare_conversion_on_event(void)
+void adc_prepare_conversion_on_event(uint8_t channels, uint8_t event, int use_int)
 {
-       /* Unsupported Yet */
+       struct lpc_adc* adc = LPC_ADC;
+       uint32_t reg_val = 0;
+
+       /* Get a clean control register */
+       reg_val = adc->ctrl & ~(LPC_ADC_CHANNEL_MASK | LPC_ADC_START_CONV_MASK | LPC_ADC_BURST);
+       /* Set conversion channel bits and burst mode */
+       reg_val |= channels;
+       /* Set conversion condition bits */
+       switch (event) {
+               case ADC_CONV_ON_CT32B0_MAT0_RISING :
+                       reg_val |= LPC_ADC_START_CONV_EVENT(LPC_ADC_START_CONV_EDGE_CT32B0_MAT0);
+                       reg_val |= LPC_ADC_START_EDGE_RISING;
+                       break;
+               case ADC_CONV_ON_CT16B0_MAT0_RISING :
+                       reg_val |= LPC_ADC_START_CONV_EVENT(LPC_ADC_START_CONV_EDGE_CT16B0_MAT0);
+                       reg_val |= LPC_ADC_START_EDGE_RISING;
+                       break;
+               default:
+                       break;
+       }
+
+       /*  Use of interrupts for the specified channel ? */
+       if (use_int) {
+               /* FIXME : Need to choose between one single global interrupt or specific interrupts .... */
+       } else {
+               adc->int_en = 0;
+       }
+
+       /* Enable conversion on selected event */
+       adc->ctrl = (reg_val & LPC_ADC_CTRL_MASK);
 }
 
 
@@ -142,9 +192,9 @@ void adc_clk_update(void)
        uint32_t main_clock = get_main_clock();
        uint32_t clkdiv = 0;
 
-       /* Configure ADC */
-       clkdiv = (main_clock/adc_clk_Val);
-       adc->ctrl |= ((clkdiv & 0x0F) << 8);
+       /* Configure ADC clock to get the 9MHz sample clock */
+       clkdiv = (main_clock / adc_clk_Val);
+       adc->ctrl |= ((clkdiv & 0xFF) << 8);
 }
 
 
@@ -164,6 +214,9 @@ void adc_on(void)
        /* Prevent unconfigured conversion start */
        adc->ctrl &= ~LPC_ADC_START_CONV_MASK;
 
+       /* Remove the default global interrupt enabled setting */
+       adc->int_en = 0;
+
        /* Configure ADC pins */
        set_adc_pins();
 
index dce2aaf..d4cdff2 100644 (file)
@@ -747,6 +747,17 @@ struct lpc_adc
 #define LPC_ADC_BURST     (0x01 << 16)
 
 #define LPC_ADC_START_CONV_NOW  (0x01 << 24)
+enum lpc_adc_start_conv_events {
+       LPC_ADC_START_CONV_EDGE_CT16B0_CAP0 = 2,
+       LPC_ADC_START_CONV_EDGE_CT32B0_CAP0,
+       LPC_ADC_START_CONV_EDGE_CT32B0_MAT0,
+       LPC_ADC_START_CONV_EDGE_CT32B0_MAT1,
+       LPC_ADC_START_CONV_EDGE_CT16B0_MAT0,
+       LPC_ADC_START_CONV_EDGE_CT16B0_MAT1,
+};
+#define LPC_ADC_START_CONV_EVENT(x) (((x) & 0x7) << 24)
+#define LPC_ADC_START_EDGE_FALLING  (0x1 << 27)
+#define LPC_ADC_START_EDGE_RISING   (0x0 << 27)
 #define LPC_ADC_START_CONV_MASK (0x07 << 24)
 
 /* ADC Data register bits */
index aef8e9f..49999d7 100644 (file)
 #define DRIVERS_ADC_H
 
 
+#include <stdint.h>
+
 /***************************************************************************** */
 /*                Analog to Digital Converter (ADC)                            */
 /***************************************************************************** */
 
-#include <stdint.h>
+enum adc_events {
+       /* CT32B0 */
+       ADC_CONV_ON_CT32B0_CAP0_RISING,
+       ADC_CONV_ON_CT32B0_CAP0_FALLING,
+       ADC_CONV_ON_CT32B0_MAT0_RISING,
+       ADC_CONV_ON_CT32B0_MAT0_FALLING,
+       ADC_CONV_ON_CT32B0_MAT1_RISING,
+       ADC_CONV_ON_CT32B0_MAT1_FALLING,
+       /* CT16B0 */
+       ADC_CONV_ON_CT16B0_CAP0_RISING,
+       ADC_CONV_ON_CT16B0_CAP0_FALLING,
+       ADC_CONV_ON_CT16B0_MAT0_RISING,
+       ADC_CONV_ON_CT16B0_MAT0_FALLING,
+       ADC_CONV_ON_CT16B0_MAT1_RISING,
+       ADC_CONV_ON_CT16B0_MAT1_FALLING,
+};
 
-/* Start a conversion on the given channel (0 to 7) */
-void adc_start_convertion_once(unsigned int channel, int use_int);
 
 /* Read the conversion from the given channel (0 to 7)
  * This function reads the conversion value directly in the data register and
@@ -39,17 +54,19 @@ void adc_start_convertion_once(unsigned int channel, int use_int);
  */
 int adc_get_value(uint16_t * val, int channel);
 
+/* Start a conversion on the given channel (0 to 7) */
+void adc_start_convertion_once(unsigned int channel, int use_int);
+
 /* Start burst conversions.
  * channels is a bit mask of requested channels.
  * Use LPC_ADC_CHANNEL(x) (x = 0 .. 7) for channels selection.
  */
 void adc_start_burst_conversion(uint8_t channels);
 
-/* Unsupported Yet */
 /* This should be used to configure conversion start on falling or rising edges of
  * some signals, or on timer for burst conversions.
  */
-void adc_prepare_conversion_on_event(void);
+void adc_prepare_conversion_on_event(uint8_t channels, uint8_t event, int use_int);
 
 
 /***************************************************************************** */