From: Bdale Garbee Date: Fri, 8 Mar 2019 05:03:53 +0000 (-0700) Subject: altos: first draft of driver for ADS1256 ADC from TI X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=125e99e41b0ae92e7b5d24e064df78fb6ee66696 altos: first draft of driver for ADS1256 ADC from TI --- diff --git a/src/drivers/ao_ads1256.c b/src/drivers/ao_ads1256.c new file mode 100644 index 00000000..8a87f7fc --- /dev/null +++ b/src/drivers/ao_ads1256.c @@ -0,0 +1,217 @@ +/* + * 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_ads1256.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_ads1256_sample ao_ads1256_current; +uint8_t nextchan = 0; +uint8_t ao_ads1256_drdy; + +static void +ao_ads1256_start(void) { + ao_spi_get_bit(AO_ADS1256_SPI_CS_PORT, + AO_ADS1256_SPI_CS_PIN, + AO_ADS1256_SPI_BUS, + AO_ADS1256_SPI_SPEED); +} + +static void +ao_ads1256_stop(void) { + ao_spi_put_bit(AO_ADS1256_SPI_CS_PORT, + AO_ADS1256_SPI_CS_PIN, + AO_ADS1256_SPI_BUS); +} + +/* +static uint8_t +ao_ads1256_reg_read(uint8_t addr) +{ + uint8_t d[2]; + + d[0] = addr | AO_ADS1256_RREG; + d[1] = 0; + ao_ads1256_start(); + ao_spi_send(d, 2, AO_ADS1256_SPI_BUS); + d[0] = 0; + ao_spi_recv(d, 1, AO_ADS1256_SPI_BUS); + ao_ads1256_stop(); + + PRINTD(DEBUG_LOW, "read %x = %x\n", addr, d[0]); + + return d[0]; +} +*/ +/* +static void +ao_ads1256_reg_write(uint8_t addr, uint8_t value) +{ + uint8_t d[3]; + + PRINTD(DEBUG_LOW, "write %x %x\n", addr, value); + d[0] = addr | AO_ADS1256_WREG; + d[1] = 0; + d[2] = value; + ao_ads1256_start(); + ao_spi_send(d, 3, AO_ADS1256_SPI_BUS); + ao_ads1256_stop(); + +} +*/ + +static void +ao_ads1256_isr(void) +{ + ao_ads1256_drdy = 1; + ao_wakeup(&ao_ads1256_drdy); +} + +static void +ao_ads1256_setup(void) +{ + uint8_t d[20]; + + ao_delay(1); + + /* set up interrupt on DRDY going low */ + + ao_exti_setup(AO_ADS1256_DRDY_PORT, AO_ADS1256_DRDY_PIN, + AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH, + ao_ads1256_isr); + + /* reset the chip */ + +// d[0] = AO_ADS1256_RESET; +// ao_ads1256_start(); +// ao_spi_send(d, 1, AO_ADS1256_SPI_BUS); +// ao_ads1256_stop(); + + /* read status register */ + + d[0] = AO_ADS1256_STATUS | AO_ADS1256_RREG; + ao_ads1256_start(); + ao_spi_send(d, 1, AO_ADS1256_SPI_BUS); + d[0] = 0; + ao_spi_send(d, 1, AO_ADS1256_SPI_BUS); + ao_spi_recv(d, 1, AO_ADS1256_SPI_BUS); + ao_ads1256_stop(); + + printf ("ADS1256 status 0x%x\n", d[0]); + + /* write configuration registers, tell converter to start working */ + + d[0] = AO_ADS1256_STATUS | AO_ADS1256_WREG; + d[1] = 4; /* write 5 registers starting with STATUS */ + d[2] = 0x00; /* msb first, auto-cal off, analog buffer disabled */ + d[3] = 0x08; /* mux AIN0 relative to AINCOM */ + d[4] = 0x20; /* clock out = fclkin, sensor detect off, pga gain 1 */ + d[5] = 0xf0; /* data rate 30,000 SPS */ + d[6] = 0xf0; /* all gpio pins are inputs */ + d[7] = AO_ADS1256_SYNC; + d[8] = AO_ADS1256_WAKEUP; + ao_ads1256_start(); + ao_spi_send(d, 9, AO_ADS1256_SPI_BUS); + ao_ads1256_stop(); +} + +static void +ao_ads1256(void) +{ + uint8_t d[6], curchan; + + ao_ads1256_setup(); + + ao_exti_enable(AO_ADS1256_DRDY_PORT, AO_ADS1256_DRDY_PIN); + + for (;;) { + ao_arch_block_interrupts(); + ao_ads1256_drdy = 0; + while (ao_ads1256_drdy == 0) + ao_sleep(&ao_ads1256_drdy); + ao_arch_release_interrupts(); + + curchan = nextchan; + nextchan = (nextchan + 1) % AO_ADS1256_CHANNELS; + + d[0] = AO_ADS1256_MUX | AO_ADS1256_WREG; + d[1] = 0; /* write one register */ + d[2] = nextchan << 4 | 0x08; ; /* relative to AINCOM */ + d[3] = AO_ADS1256_SYNC; + d[4] = AO_ADS1256_WAKEUP; + d[5] = AO_ADS1256_RDATA; + ao_ads1256_start(); + ao_spi_send(d, 6, AO_ADS1256_SPI_BUS); +// ao_delay(1); + ao_spi_recv(d, 3, AO_ADS1256_SPI_BUS); + ao_ads1256_stop(); + + ao_ads1256_current.ain[curchan] = + d[0] << 16 | d[1] << 8 | d[2]; + + // FIXME + // If nextchan == 0, we have a complete set of inputs + // and we need to log them somewhere + + ao_ads1256_drdy = 0; + } +} + +static struct ao_task ao_ads1256_task; + +static void +ao_ads1256_dump(void) +{ + static int done; + + if (!done) { + done = 1; + ao_add_task(&ao_ads1256_task, ao_ads1256, "ads1256"); + } + + printf ("ADS1256 value %d %d %d %d\n", + ao_ads1256_current.ain[0], + ao_ads1256_current.ain[1], + ao_ads1256_current.ain[2], + ao_ads1256_current.ain[3]); +} + +const struct ao_cmds ao_ads1256_cmds[] = { + { ao_ads1256_dump, "D\0Display ADS1256 data" }, + { 0, NULL }, +}; + +void +ao_ads1256_init(void) +{ + ao_cmd_register(ao_ads1256_cmds); + +// ao_enable_output(AO_ADS1256_RESET_PORT, AO_ADS1256_RESET_PIN, 0); + + ao_spi_init_cs(AO_ADS1256_SPI_CS_PORT, + (1 << AO_ADS1256_SPI_CS_PIN)); + +// ao_add_task(&ao_ads1256_task, ao_ads1256, "ads1256"); +} diff --git a/src/drivers/ao_ads1256.h b/src/drivers/ao_ads1256.h new file mode 100644 index 00000000..44139256 --- /dev/null +++ b/src/drivers/ao_ads1256.h @@ -0,0 +1,57 @@ +/* + * 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. + */ + +#ifndef _AO_ADS1256_H_ +#define _AO_ADS1256_H_ + +/* commands */ +#define AO_ADS1256_WAKEUP 0x00 +#define AO_ADS1256_RDATA 0x01 +#define AO_ADS1256_RDATAC 0x03 +#define AO_ADS1256_SDATAC 0x0f +#define AO_ADS1256_RREG 0x10 +#define AO_ADS1256_WREG 0x50 +#define AO_ADS1256_SELFCAL 0xf0 +#define AO_ADS1256_SELFOCAL 0xf1 +#define AO_ADS1256_SELFGCAL 0xf2 +#define AO_ADS1256_SYSOCAL 0xf3 +#define AO_ADS1256_SYSGCAL 0xf4 +#define AO_ADS1256_SYNC 0xfc +#define AO_ADS1256_STANDBY 0xfd +#define AO_ADS1256_RESET 0xfe +#define AO_ADS1256_WAKEUP2 0xff + +/* register map */ +#define AO_ADS1256_STATUS 0x00 +#define AO_ADS1256_MUX 0x01 +#define AO_ADS1256_ADCON 0x02 +#define AO_ADS1256_DRATE 0x03 +#define AO_ADS1256_IO 0x04 +#define AO_ADS1256_OFC0 0x05 +#define AO_ADS1256_OFC1 0x06 +#define AO_ADS1256_OFC2 0x07 +#define AO_ADS1256_FSC0 0x08 +#define AO_ADS1256_FSC1 0x09 +#define AO_ADS1256_FSC2 0x0a + +struct ao_ads1256_sample { + int32_t ain[AO_ADS1256_CHANNELS]; +}; + +extern struct ao_ads1256_sample ao_ads1256_current; + +void +ao_ads1256_init(void); + +#endif /* _AO_ADS1256_H_ */