*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
#define AO_ADC_7 0
#endif
-#if AO_ADC_7
-# define AO_ADC_LAST 7
-#else
-# if AO_ADC_6
-# define AO_ADC_LAST 6
-# else
-# if AO_ADC_5
-# define AO_ADC_LAST 5
-# else
-# if AO_ADC_4
-# define AO_ADC_LAST 4
-# else
-# if AO_ADC_3
-# define AO_ADC_LAST 3
-# else
-# if AO_ADC_2
-# define AO_ADC_LAST 2
-# else
-# if AO_ADC_1
-# define AO_ADC_LAST 1
-# else
-# if AO_ADC_0
-# define AO_ADC_LAST 0
-# endif
-# endif
-# endif
-# endif
-# endif
-# endif
-# endif
-#endif
-
-static uint8_t ao_adc_ready;
-
-void lpc_adc_isr(void)
-{
- uint32_t stat = lpc_adc.stat;
- uint16_t *out = (uint16_t *) &ao_data_ring[ao_data_head].adc;
- vuint32_t *in = &lpc_adc.dr[0];
+#define AO_ADC_NUM (AO_ADC_0 + AO_ADC_1 + AO_ADC_2 + AO_ADC_3 + \
+ AO_ADC_4 + AO_ADC_5 + AO_ADC_6 + AO_ADC_7)
- lpc_adc.cr = 0;
- lpc_adc.stat = 0;
+/* ADC clock is divided by this value + 1, which ensures that
+ * the ADC clock will be strictly less than 4.5MHz as required
+ */
+#define AO_ADC_CLKDIV (AO_LPC_SYSCLK / 450000)
- /* Store converted values in packet */
+static uint8_t ao_adc_ready;
+static uint8_t ao_adc_sequence;
+static const uint8_t ao_adc_mask_seq[AO_ADC_NUM] = {
#if AO_ADC_0
- *out++ = lpc_adc.dr[0] >> 1;
+ 1 << 0,
#endif
#if AO_ADC_1
- *out++ = lpc_adc.dr[1] >> 1;
+ 1 << 1,
#endif
#if AO_ADC_2
- *out++ = lpc_adc.dr[2] >> 1;
+ 1 << 2,
#endif
#if AO_ADC_3
- *out++ = lpc_adc.dr[3] >> 1;
+ 1 << 3,
#endif
#if AO_ADC_4
- *out++ = lpc_adc.dr[4] >> 1;
+ 1 << 4,
#endif
#if AO_ADC_5
- *out++ = lpc_adc.dr[5] >> 1;
+ 1 << 6,
#endif
#if AO_ADC_6
- *out++ = lpc_adc.dr[6] >> 1;
+ 1 << 6,
#endif
#if AO_ADC_7
- *out++ = lpc_adc.dr[7] >> 1;
+ 1 << 7,
#endif
+};
- AO_DATA_PRESENT(AO_DATA_ADC);
- if (ao_data_present == AO_DATA_ALL) {
-#if HAS_MS5607
- ao_data_ring[ao_data_head].ms5607_raw = ao_ms5607_current;
-#endif
-#if HAS_MMA655X
- ao_data_ring[ao_data_head].mma655x = ao_mma655x_current;
-#endif
-#if HAS_HMC5883
- ao_data_ring[ao_data_head].hmc5883 = ao_hmc5883_current;
-#endif
-#if HAS_MPU6000
- ao_data_ring[ao_data_head].mpu6000 = ao_mpu6000_current;
-#endif
- ao_data_ring[ao_data_head].tick = ao_tick_count;
- ao_data_head = ao_data_ring_next(ao_data_head);
- ao_wakeup((void *) &ao_data_head);
+#define sample(id) (*out++ = (uint16_t) lpc_adc.dr[id] >> 1)
+
+static inline void lpc_adc_start(void) {
+ lpc_adc.cr = ((ao_adc_mask_seq[ao_adc_sequence] << LPC_ADC_CR_SEL) |
+ (AO_ADC_CLKDIV << LPC_ADC_CR_CLKDIV) |
+ (0 << LPC_ADC_CR_BURST) |
+ (LPC_ADC_CR_CLKS_11 << LPC_ADC_CR_CLKS) |
+ (LPC_ADC_CR_START_NOW << LPC_ADC_CR_START));
+}
+
+void lpc_adc_isr(void)
+{
+ uint16_t *out;
+
+ /* Store converted value in packet */
+ out = (uint16_t *) &ao_data_ring[ao_data_head].adc;
+ out[ao_adc_sequence] = (uint16_t) lpc_adc.gdr >> 1;
+ if (++ao_adc_sequence < AO_ADC_NUM) {
+ lpc_adc_start();
+ return;
}
+
+ AO_DATA_PRESENT(AO_DATA_ADC);
+ ao_data_fill(ao_data_head);
ao_adc_ready = 1;
}
-#define AO_ADC_MASK ((AO_ADC_0 << 0) | \
- (AO_ADC_1 << 1) | \
- (AO_ADC_2 << 2) | \
- (AO_ADC_3 << 3) | \
- (AO_ADC_4 << 4) | \
- (AO_ADC_5 << 5) | \
- (AO_ADC_6 << 6) | \
- (AO_ADC_7 << 7))
-
-#define AO_ADC_CLKDIV (AO_LPC_CLKOUT / 4500000)
/*
- * Start the ADC sequence using the DMA engine
+ * Start the ADC sequence using burst mode
*/
void
ao_adc_poll(void)
if (!ao_adc_ready)
return;
ao_adc_ready = 0;
-
- lpc_adc.cr = ((AO_ADC_MASK << LPC_ADC_CR_SEL) |
- (AO_ADC_CLKDIV << LPC_ADC_CR_CLKDIV) |
- (1 << LPC_ADC_CR_BURST) |
- (LPC_ADC_CR_CLKS_11 << LPC_ADC_CR_CLKS));
+ ao_adc_sequence = 0;
+ lpc_adc_start();
}
static void
-ao_adc_dump(void) __reentrant
+ao_adc_dump(void)
{
struct ao_data packet;
+#ifndef AO_ADC_DUMP
int16_t *d;
uint8_t i;
+#endif
ao_data_get(&packet);
#ifdef AO_ADC_DUMP
#else
printf("tick: %5u", packet.tick);
d = (int16_t *) (&packet.adc);
- for (i = 0; i < AO_NUM_ADC; i++)
+ for (i = 0; i < AO_ADC_NUM; i++)
printf (" %2d: %5d", i, d[i]);
printf("\n");
#endif
}
-__code struct ao_cmds ao_adc_cmds[] = {
+const struct ao_cmds ao_adc_cmds[] = {
{ ao_adc_dump, "a\0Display current ADC values" },
{ 0, NULL },
};
lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_ADC);
lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_ADC_PD);
- /* Enable interrupt when last channel is complete */
- lpc_adc.inten = (1 << AO_ADC_LAST);
+ /* Enable interrupt when channel is complete */
+ lpc_adc.inten = (1 << LPC_ADC_INTEN_ADGINTEN);
lpc_nvic_set_enable(LPC_ISR_ADC_POS);
lpc_nvic_set_priority(LPC_ISR_ADC_POS, AO_LPC_NVIC_CLOCK_PRIORITY);
#if AO_ADC_0
- ao_enable_analog(0, 11);
+ ao_enable_analog(0, 11, 0);
#endif
#if AO_ADC_1
- ao_enable_analog(0, 12);
+ ao_enable_analog(0, 12, 1);
#endif
#if AO_ADC_2
- ao_enable_analog(0, 13);
+ ao_enable_analog(0, 13, 2);
#endif
#if AO_ADC_3
- ao_enable_analog(0, 14);
+ ao_enable_analog(0, 14, 3);
#endif
#if AO_ADC_4
- ao_enable_analog(0, 14);
+ ao_enable_analog(0, 15, 4);
#endif
#if AO_ADC_5
- ao_enable_analog(0, 14);
+ ao_enable_analog(0, 16, 5);
#endif
#if AO_ADC_6
- ao_enable_analog(0, 14);
+ ao_enable_analog(0, 22, 6);
#endif
#if AO_ADC_7
- ao_enable_analog(0, 14);
+ ao_enable_analog(0, 23, 7);
#endif
+
+ lpc_adc.cr = ((0 << LPC_ADC_CR_SEL) |
+ (AO_ADC_CLKDIV << LPC_ADC_CR_CLKDIV) |
+ (0 << LPC_ADC_CR_BURST) |
+ (LPC_ADC_CR_CLKS_11 << LPC_ADC_CR_CLKS));
+
ao_cmd_register(&ao_adc_cmds[0]);
ao_adc_ready = 1;