From: Bdale Garbee Date: Fri, 26 Apr 2019 00:42:14 +0000 (-0600) Subject: altos: first cut at ADS131A0X driver compiles now X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=7bb53af4acece794037e3a83133d8fa323e52082;p=fw%2Faltos altos: first cut at ADS131A0X driver compiles now --- diff --git a/src/drivers/ao_ads124s0x.c b/src/drivers/ao_ads124s0x.c index fa63ec06..145ba273 100644 --- a/src/drivers/ao_ads124s0x.c +++ b/src/drivers/ao_ads124s0x.c @@ -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 index 00000000..14c03014 --- /dev/null +++ b/src/drivers/ao_ads131a0x.c @@ -0,0 +1,275 @@ +/* + * Copyright © 2019 Bdale Garbee + * + * 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 +#include +#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"); +} diff --git a/src/drivers/ao_ads131a0x.h b/src/drivers/ao_ads131a0x.h index 7ceb9351..b2433c8d 100644 --- a/src/drivers/ao_ads131a0x.h +++ b/src/drivers/ao_ads131a0x.h @@ -15,47 +15,46 @@ #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]; diff --git a/src/kernel/ao.h b/src/kernel/ao.h index dddcd9cb..a02b74e4 100644 --- a/src/kernel/ao.h +++ b/src/kernel/ao.h @@ -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 diff --git a/src/kernel/ao_data.h b/src/kernel/ao_data.h index f52e17e2..7c5c20d0 100644 --- a/src/kernel/ao_data.h +++ b/src/kernel/ao_data.h @@ -76,6 +76,13 @@ #define AO_DATA_MAX6691 0 #endif +#if HAS_ADS131A0X +#include +#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) diff --git a/src/telestatic-v3.0/Makefile b/src/telestatic-v3.0/Makefile index 124b47fb..739ca030 100644 --- a/src/telestatic-v3.0/Makefile +++ b/src/telestatic-v3.0/Makefile @@ -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 = \ diff --git a/src/telestatic-v3.0/ao_pins.h b/src/telestatic-v3.0/ao_pins.h index aad17664..20aa9cec 100644 --- a/src/telestatic-v3.0/ao_pins.h +++ b/src/telestatic-v3.0/ao_pins.h @@ -108,7 +108,7 @@ * 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) @@ -121,6 +121,9 @@ #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 */ /*