altos: first cut at ADS131A0X driver compiles now
authorBdale Garbee <bdale@gag.com>
Fri, 26 Apr 2019 00:42:14 +0000 (18:42 -0600)
committerBdale Garbee <bdale@gag.com>
Fri, 26 Apr 2019 00:42:14 +0000 (18:42 -0600)
src/drivers/ao_ads124s0x.c
src/drivers/ao_ads131a0x.c [new file with mode: 0644]
src/drivers/ao_ads131a0x.h
src/kernel/ao.h
src/kernel/ao_data.h
src/telestatic-v3.0/Makefile
src/telestatic-v3.0/ao_pins.h

index fa63ec062e252ef2b67e43d08c03f2d8c133087d..145ba273fd37f67a32baeb2fd73b75584e1cd079 100644 (file)
@@ -100,7 +100,7 @@ ao_ads124s0x_setup(void)
 
        uint8_t devid = ao_ads124s0x_reg_read(AO_ADS124S0X_ID);
        if ((devid & 7) != AO_ADS124S0X_ID_ADS124S06)
-               ao_panic(AO_PANIC_SELF_TEST_ADS124S0X);
+               ao_panic(AO_PANIC_SELF_TEST_ADS);
 
        ao_exti_setup(AO_ADS124S0X_DRDY_PORT, AO_ADS124S0X_DRDY_PIN,
                AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
diff --git a/src/drivers/ao_ads131a0x.c b/src/drivers/ao_ads131a0x.c
new file mode 100644 (file)
index 0000000..14c0301
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Copyright © 2019 Bdale Garbee <bdale@gag.com>
+ *
+ * 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, 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
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <ao.h>
+#include <ao_exti.h>
+#include "ao_ads131a0x.h"
+
+#define DEBUG_LOW      1
+#define DEBUG_HIGH     2
+
+#define DEBUG          0
+
+#if DEBUG
+#define PRINTD(l, ...) do { if (DEBUG & (l)) { printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } } while(0)
+#else
+#define PRINTD(l,...)
+#endif
+
+struct ao_ads131a0x_sample     ao_ads131a0x_current;
+uint8_t                nextchan = 0;
+uint8_t                ao_ads131a0x_drdy;
+
+static void
+ao_ads131a0x_start(void) {
+       ao_spi_get_bit(AO_ADS131A0X_SPI_CS_PORT,
+                      AO_ADS131A0X_SPI_CS_PIN,
+                      AO_ADS131A0X_SPI_BUS,
+                      AO_ADS131A0X_SPI_SPEED);
+}
+
+static void
+ao_ads131a0x_stop(void) {
+       ao_spi_put_bit(AO_ADS131A0X_SPI_CS_PORT,
+                      AO_ADS131A0X_SPI_CS_PIN,
+                      AO_ADS131A0X_SPI_BUS);
+}
+
+static uint8_t
+ao_ads131a0x_reg_read(uint8_t addr)
+{
+       uint8_t d[15];
+
+       d[0] = addr | (AO_ADS131A0X_RREG >> 8);
+       d[1] = 0;                       
+       d[2] = 0;                       
+       d[3] = 0;                       
+       d[4] = 0;                       
+       d[5] = 0;                       
+       d[6] = 0;                       
+       d[7] = 0;                       
+       d[8] = 0;                       
+       d[9] = 0;                       
+       d[10] = 0;                      
+       d[11] = 0;                      
+       d[12] = 0;                      
+       d[13] = 0;                      
+       d[14] = 0;                      
+       ao_ads131a0x_start();
+       ao_spi_send(d, 15, AO_ADS131A0X_SPI_BUS);
+       ao_ads131a0x_stop();
+
+       /* data isn't actually returned until the next frame */
+       d[0] = AO_ADS131A0X_NULL >> 8;
+       d[1] = AO_ADS131A0X_NULL & 0xff;
+       ao_ads131a0x_start();
+       ao_spi_duplex(d, d, 15, AO_ADS131A0X_SPI_BUS);
+       ao_ads131a0x_stop();
+
+       /* first byte is register number, second byte is the data */
+       PRINTD(DEBUG_LOW, "read %x = %x\n", addr, d[1]);
+
+       return d[1];
+}
+
+/*
+static void
+ao_ads131a0x_reg_write(uint8_t addr, uint8_t value)
+{
+       uint8_t d[15];
+
+       PRINTD(DEBUG_LOW, "write %x %x\n", addr, value);
+       d[0] = addr | (AO_ADS131A0X_WREG >> 8);
+       d[1] = value;
+       d[2] = 0;                       
+       d[3] = 0;                       
+       d[4] = 0;                       
+       d[5] = 0;                       
+       d[6] = 0;                       
+       d[7] = 0;                       
+       d[8] = 0;                       
+       d[9] = 0;                       
+       d[10] = 0;                      
+       d[11] = 0;                      
+       d[12] = 0;                      
+       d[13] = 0;                      
+       d[14] = 0;                      
+       ao_ads131a0x_start();
+       ao_spi_send(d, 15, AO_ADS131A0X_SPI_BUS);
+       ao_ads131a0x_stop();
+}
+*/
+
+static void 
+ao_ads131a0x_isr(void)
+{
+       ao_ads131a0x_drdy = 1;
+       ao_wakeup(&ao_ads131a0x_drdy);
+}
+
+static void
+ao_ads131a0x_setup(void)
+{
+       uint8_t d[20];
+
+       ao_delay(1);
+
+       ao_gpio_set(AO_ADS131A0X_RESET_PORT, AO_ADS131A0X_RESET_PIN, 1);
+
+       ao_delay(1);
+
+       /* send unlock command?  why, if we've not locked it? */
+
+       uint8_t devid = ao_ads131a0x_reg_read(AO_ADS131A0X_ID_MSB);
+       if (devid != AO_ADS131A0X_ID_ADS131A04)
+               ao_panic(AO_PANIC_SELF_TEST_ADS);
+
+       ao_exti_setup(AO_ADS131A0X_DRDY_PORT, AO_ADS131A0X_DRDY_PIN,
+               AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
+               ao_ads131a0x_isr);
+
+       /* register writes use top 16 bits of each 24-bit word */
+
+       d[0] = AO_ADS131A0X_A_SYS_CFG | (AO_ADS131A0X_WREGS >> 8);
+       d[1] = 8;       /* write (n-1) registers starting with A_SYS_CFG */
+       d[2] = 0;
+
+       d[3] = 0x78;    /* A_SYS_CFG - charge pump off, high res, 4.0V ref,
+                          internal ref on, 5/95% fault thresholds */
+       d[4] = 0x00;    /* D_SYS_CFG - watchdog off, crc on device words, 
+                          shortest done and hi-z delays, non-fixed size, 
+                          crc disabled */
+       d[5] = 0;
+
+       d[6] = 0x02;    /* CLK1 - crystal osc on, ICLK = CLKIN / 2 */
+       d[7] = 0x20;    /* CLK2 - MOD = ICLK / 2, DATA = MOD / 4096 */
+       d[8] = 0;
+
+       d[9] = 0x0f;    /* ADC_ENA - all channels powered up */
+       d[10] = 0;      /* reserved */
+       d[11] = 0;
+
+       d[12] = 0x00;   /* ADC1 - gain = 1 */
+       d[13] = 0x00;   /* ADC2 - gain = 1 */
+       d[14] = 0;
+
+       d[15] = 0x00;   /* ADC3 - gain = 1 */
+       d[16] = 0x00;   /* ADC4 - gain = 1 */
+       d[17] = 0;
+
+       ao_ads131a0x_start();
+       ao_spi_send(d, 18, AO_ADS131A0X_SPI_BUS);
+       ao_ads131a0x_stop();
+
+       /* start conversions */
+       
+       d[0] = AO_ADS131A0X_WAKEUP >> 8;
+       d[1] = AO_ADS131A0X_WAKEUP & 0xff;
+       d[2] = 0;
+       ao_ads131a0x_start();
+       ao_spi_send(d, 3, AO_ADS131A0X_SPI_BUS);
+       ao_ads131a0x_stop();
+
+       /* documented initialization sends the LOCK command here, but I can 
+          see no value in doing that! */
+}
+
+static void
+ao_ads131a0x(void)
+{
+       uint8_t d[15];
+
+       ao_ads131a0x_setup();
+
+       ao_exti_enable(AO_ADS131A0X_DRDY_PORT, AO_ADS131A0X_DRDY_PIN);
+
+       for (;;) {
+               ao_arch_block_interrupts();
+               ao_ads131a0x_drdy = 0;
+               while (ao_ads131a0x_drdy == 0)
+                       ao_sleep(&ao_ads131a0x_drdy);
+               ao_arch_release_interrupts();
+
+               d[0] = AO_ADS131A0X_NULL >> 8;
+               d[1] = AO_ADS131A0X_NULL & 0xff;
+               d[2] = 0;                       
+               d[3] = 0;                       
+               d[4] = 0;                       
+               d[5] = 0;                       
+               d[6] = 0;                       
+               d[7] = 0;                       
+               d[8] = 0;                       
+               d[9] = 0;                       
+               d[10] = 0;                      
+               d[11] = 0;                      
+               d[12] = 0;                      
+               d[13] = 0;                      
+               d[14] = 0;                      
+
+               ao_ads131a0x_start();
+               ao_spi_duplex(d, d, 15, AO_ADS131A0X_SPI_BUS);
+               ao_ads131a0x_stop();
+
+               ao_ads131a0x_current.ain[0] = 
+                       d[3] << 16 | d[4] << 8 | d[5];
+               ao_ads131a0x_current.ain[1] = 
+                       d[6] << 16 | d[7] << 8 | d[8];
+               ao_ads131a0x_current.ain[2] = 
+                       d[9] << 16 | d[10] << 8 | d[11];
+               ao_ads131a0x_current.ain[3] = 
+                       d[12] << 16 | d[13] << 8 | d[14];
+
+               // FIXME
+               //       we need to log this data somewhere
+
+               ao_ads131a0x_drdy = 0;
+       }
+}
+
+static struct ao_task ao_ads131a0x_task;
+
+static void
+ao_ads131a0x_dump(void)        
+{
+       static int done;
+
+       if (!done) {
+               done = 1;
+               ao_add_task(&ao_ads131a0x_task, ao_ads131a0x, "ads131a0x");
+       }
+               
+       printf ("ADS131A0X value %d %d %d %d\n",
+               ao_ads131a0x_current.ain[0],
+               ao_ads131a0x_current.ain[1],
+               ao_ads131a0x_current.ain[2],
+               ao_ads131a0x_current.ain[3]);
+}
+
+const struct ao_cmds ao_ads131a0x_cmds[] = {
+       { ao_ads131a0x_dump,    "I\0Display ADS131A0X data" },
+       { 0, NULL },
+};
+
+void
+ao_ads131a0x_init(void)
+{
+       ao_cmd_register(ao_ads131a0x_cmds);
+
+       ao_enable_output(AO_ADS131A0X_RESET_PORT, AO_ADS131A0X_RESET_PIN, 0);
+
+       ao_spi_init_cs(AO_ADS131A0X_SPI_CS_PORT, 
+               (1 << AO_ADS131A0X_SPI_CS_PIN));
+
+//     ao_add_task(&ao_ads131a0x_task, ao_ads131a0x, "ads131a0x");
+}
index 7ceb93517b8198e369848f9ce854f445727b45c8..b2433c8dc3ed448651d42ba2757dc2f422c06fe2 100644 (file)
 #ifndef _AO_ADS131A0X_H_
 #define _AO_ADS131A0X_H_
 
-/* control commands */
-#define AO_ADS131A0X_NOP               0x00
-#define AO_ADS131A0X_WAKEUP            0x02
-#define AO_ADS131A0X_POWERDOWN         0x04
-#define AO_ADS131A0X_RESET             0x06
-#define AO_ADS131A0X_START             0x08
-#define AO_ADS131A0X_STOP              0x0a
+/* system commands */
+#define AO_ADS131A0X_NULL              0x0000
+#define AO_ADS131A0X_RESET             0x0011
+#define AO_ADS131A0X_STANDBY           0x0022
+#define AO_ADS131A0X_WAKEUP            0x0033
+#define AO_ADS131A0X_LOCK              0x0555
+#define AO_ADS131A0X_UNLOCK            0x0655
 
-/* calibration commands */
-#define AO_ADS131A0X_SYOCAL            0x16
-#define AO_ADS131A0X_SYGCAL            0x17
-#define AO_ADS131A0X_SFOCAL            0x19
+/* register write and read commands */
+#define AO_ADS131A0X_RREG              0x2000
+#define AO_ADS131A0X_RREGS             0x2000
+#define AO_ADS131A0X_WREG              0x4000
+#define AO_ADS131A0X_WREGS             0x6000
 
-/* data read command */
-#define AO_ADS131A0X_RDATA             0x12
+/* configuration register map */
 
-/* register read and write commands */
-#define AO_ADS131A0X_RREG              0x20
-#define AO_ADS131A0X_WREG              0x40
+/* read-only ID registers */
+#define AO_ADS131A0X_ID_MSB            0x00
+#define AO_ADS131A0X_ID_ADS124A02               0x02
+#define AO_ADS131A0X_ID_ADS131A04               0x04
+#define AO_ADS131A0X_ID_LSB            0x01
 
-/* configuration register map */
-#define AO_ADS131A0X_ID                        0x00
-#define AO_ADS131A0X_ID_ADS131A08              0x00
-#define AO_ADS131A0X_ID_ADS131A06              0x01
-#define AO_ADS131A0X_STATUS            0x01
-#define AO_ADS131A0X_INPMUX            0x02
-#define AO_ADS131A0X_PGA               0x03
-#define AO_ADS131A0X_DATARATE          0x04
-#define AO_ADS131A0X_REF               0x05
-#define AO_ADS131A0X_IDACMAG           0x06
-#define AO_ADS131A0X_IDACMUX           0x07
-#define AO_ADS131A0X_VBIAS             0x08
-#define AO_ADS131A0X_SYS               0x09
-#define AO_ADS131A0X_OFCAL0            0x0a
-#define AO_ADS131A0X_OFCAL1            0x0b
-#define AO_ADS131A0X_OFCAL2            0x0c
-#define AO_ADS131A0X_FSCAL0            0x0d
-#define AO_ADS131A0X_FSCAL1            0x0e
-#define AO_ADS131A0X_FSCAL2            0x0f
-#define AO_ADS131A0X_GPIODAT           0x10
-#define AO_ADS131A0X_GPIOCON           0x11
+/* status registers */
+#define AO_ADS131A0X_STAT_1            0x02
+#define AO_ADS131A0X_STAT_P            0x03
+#define AO_ADS131A0X_STAT_N            0x04
+#define AO_ADS131A0X_STAT_S            0x05
+#define AO_ADS131A0X_ERROR_CNT         0x06
+#define AO_ADS131A0X_STAT_M2           0x07
+
+/* user configuration registers */
+#define AO_ADS131A0X_A_SYS_CFG         0x0b
+#define AO_ADS131A0X_D_SYS_CFG         0x0c
+#define AO_ADS131A0X_CLK1              0x0d
+#define AO_ADS131A0X_CLK2              0x0e
+#define AO_ADS131A0X_ADC_ENA           0x0f
+#define AO_ADS131A0X_ADC1              0x11
+#define AO_ADS131A0X_ADC2              0x12
+#define AO_ADS131A0X_ADC3              0x13
+#define AO_ADS131A0X_ADC4              0x14
 
 struct ao_ads131a0x_sample {
        int32_t ain[AO_ADS131A0X_CHANNELS];
index dddcd9cb5afd6d8a4079d96eacac2842933b466a..a02b74e4d7228bdcaaf2e403b05119de2f67f438 100644 (file)
@@ -76,7 +76,7 @@ typedef AO_PORT_TYPE ao_port_t;
 #define AO_PANIC_SELF_TEST_MPU6000     0x40 | 3        /* Self test failure */
 #define AO_PANIC_SELF_TEST_MPU9250     0x40 | 3        /* Self test failure */
 #define AO_PANIC_SELF_TEST_MS5607      0x40 | 4        /* Self test failure */
-#define AO_PANIC_SELF_TEST_ADS124S0X   0x40 | 5        /* Self test failure */
+#define AO_PANIC_SELF_TEST_ADS         0x40 | 5        /* Self test failure */
 
 /* Stop the operating system, beeping and blinking the reason */
 void
index f52e17e2df01675562baab8df4f0c64a1251f72d..7c5c20d016a6f0daa778957504bae550db95fc7d 100644 (file)
 #define AO_DATA_MAX6691 0
 #endif
 
+#if HAS_ADS131A0X
+#include <ao_ads131a0x.h>
+#define AO_DATA_ADS131A0X (1 << 4)
+#else
+#define AO_DATA_ADS131A0X 0
+#endif
+
 #ifdef AO_DATA_RING
 
 #define AO_DATA_ALL    (AO_DATA_ADC|AO_DATA_MS5607|AO_DATA_MPU6000|AO_DATA_HMC5883|AO_DATA_MMA655X|AO_DATA_MPU9250|AO_DATA_ADXL375)
index 124b47fb87dccab2416c84c9de132af88ed3ff36..739ca030e60379d63cf1be2d986752b32c6ba401 100644 (file)
@@ -55,6 +55,7 @@ ALTOS_SRC = \
        ao_radio_cmac_cmd.c \
        ao_log.c \
        ao_log_telestatic.c \
+       ao_ads131a0x.c \
        ao_max6691.c
 
 PRODUCT_SRC = \
index aad17664bde320fd49357177b06c7c0fe6ebeb8c..20aa9cec30666febeeb49732baeca8d0a2922002 100644 (file)
  * ADS131A0X analog to digital converter
  */
 
-#define HAS_ADS131A0X                  0
+#define HAS_ADS131A0X                  1
 #define AO_ADS131A0X_SPI_CS_PORT       (&stm_gpioa)
 #define AO_ADS131A0X_SPI_CS_PIN                4
 #define AO_ADS131A0X_SPI_CS_MASK       (1 << AO_ADS131A0X_SPI_CS_PIN)
 #define AO_ADS131A0X_DONE_PORT         (&stm_gpioc)
 #define AO_ADS131A0X_DONE_PIN          14
 
+#define AO_ADS131A0X_RESET_PORT         (&stm_gpiob)
+#define AO_ADS131A0X_RESET_PIN          4
+
 #define AO_ADS131A0X_CHANNELS          4       /* how many inputs in use */
 
 /*