altos: Create ao_data_fill shared function
[fw/altos] / src / lpc / ao_adc_lpc.c
index 9ecc7c1..6324155 100644 (file)
@@ -3,7 +3,8 @@
  *
  * 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)
@@ -161,19 +126,18 @@ 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
@@ -181,13 +145,13 @@ ao_adc_dump(void) __reentrant
 #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 },
 };
@@ -198,35 +162,41 @@ ao_adc_init(void)
        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;