#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
/* 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)
{
*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.
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);
}
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);
}
/* 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();
#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
*/
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);
/***************************************************************************** */