8a87f7fce266dfc00cc91395df29c91e727b420b
[fw/altos] / src / drivers / ao_ads1256.c
1 /*
2  * Copyright © 2019 Bdale Garbee <bdale@gag.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  */
14
15 #include <ao.h>
16 #include <ao_exti.h>
17 #include "ao_ads1256.h"
18
19 #define DEBUG_LOW       1
20 #define DEBUG_HIGH      2
21
22 #define DEBUG           0
23
24 #if DEBUG
25 #define PRINTD(l, ...) do { if (DEBUG & (l)) { printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } } while(0)
26 #else
27 #define PRINTD(l,...)
28 #endif
29
30 struct ao_ads1256_sample        ao_ads1256_current;
31 uint8_t         nextchan = 0;
32 uint8_t         ao_ads1256_drdy;
33
34 static void
35 ao_ads1256_start(void) {
36         ao_spi_get_bit(AO_ADS1256_SPI_CS_PORT,
37                        AO_ADS1256_SPI_CS_PIN,
38                        AO_ADS1256_SPI_BUS,
39                        AO_ADS1256_SPI_SPEED);
40 }
41
42 static void
43 ao_ads1256_stop(void) {
44         ao_spi_put_bit(AO_ADS1256_SPI_CS_PORT,
45                        AO_ADS1256_SPI_CS_PIN,
46                        AO_ADS1256_SPI_BUS);
47 }
48
49 /*
50 static uint8_t
51 ao_ads1256_reg_read(uint8_t addr)
52 {
53         uint8_t d[2];
54
55         d[0] = addr | AO_ADS1256_RREG;
56         d[1] = 0;                       
57         ao_ads1256_start();
58         ao_spi_send(d, 2, AO_ADS1256_SPI_BUS);
59         d[0] = 0;
60         ao_spi_recv(d, 1, AO_ADS1256_SPI_BUS);
61         ao_ads1256_stop();
62
63         PRINTD(DEBUG_LOW, "read %x = %x\n", addr, d[0]);
64
65         return d[0];
66 }
67 */
68 /*
69 static void
70 ao_ads1256_reg_write(uint8_t addr, uint8_t value)
71 {
72         uint8_t d[3];
73
74         PRINTD(DEBUG_LOW, "write %x %x\n", addr, value);
75         d[0] = addr | AO_ADS1256_WREG;
76         d[1] = 0;                       
77         d[2] = value;
78         ao_ads1256_start();
79         ao_spi_send(d, 3, AO_ADS1256_SPI_BUS);
80         ao_ads1256_stop();
81
82 }
83 */
84
85 static void 
86 ao_ads1256_isr(void)
87 {
88         ao_ads1256_drdy = 1;
89         ao_wakeup(&ao_ads1256_drdy);
90 }
91
92 static void
93 ao_ads1256_setup(void)
94 {
95         uint8_t d[20];
96
97         ao_delay(1);
98
99         /* set up interrupt on DRDY going low */
100
101         ao_exti_setup(AO_ADS1256_DRDY_PORT, AO_ADS1256_DRDY_PIN,
102                 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
103                 ao_ads1256_isr);
104
105         /* reset the chip */
106
107 //      d[0] = AO_ADS1256_RESET;
108 //      ao_ads1256_start();
109 //      ao_spi_send(d, 1, AO_ADS1256_SPI_BUS);
110 //      ao_ads1256_stop();
111
112         /* read status register */
113
114         d[0] = AO_ADS1256_STATUS | AO_ADS1256_RREG;
115         ao_ads1256_start();
116         ao_spi_send(d, 1, AO_ADS1256_SPI_BUS);
117         d[0] = 0;
118         ao_spi_send(d, 1, AO_ADS1256_SPI_BUS);
119         ao_spi_recv(d, 1, AO_ADS1256_SPI_BUS);
120         ao_ads1256_stop();
121
122         printf ("ADS1256 status 0x%x\n", d[0]);
123
124         /* write configuration registers, tell converter to start working */
125
126         d[0] = AO_ADS1256_STATUS | AO_ADS1256_WREG;
127         d[1] = 4;       /* write 5 registers starting with STATUS */
128         d[2] = 0x00;    /* msb first, auto-cal off, analog buffer disabled */
129         d[3] = 0x08;    /* mux AIN0 relative to AINCOM */
130         d[4] = 0x20;    /* clock out = fclkin, sensor detect off, pga gain 1 */
131         d[5] = 0xf0;    /* data rate 30,000 SPS */
132         d[6] = 0xf0;    /* all gpio pins are inputs */
133         d[7] = AO_ADS1256_SYNC;
134         d[8] = AO_ADS1256_WAKEUP;
135         ao_ads1256_start();
136         ao_spi_send(d, 9, AO_ADS1256_SPI_BUS);
137         ao_ads1256_stop();
138 }
139
140 static void
141 ao_ads1256(void)
142 {
143         uint8_t d[6], curchan;
144
145         ao_ads1256_setup();
146
147         ao_exti_enable(AO_ADS1256_DRDY_PORT, AO_ADS1256_DRDY_PIN);
148
149         for (;;) {
150                 ao_arch_block_interrupts();
151                 ao_ads1256_drdy = 0;
152                 while (ao_ads1256_drdy == 0)
153                         ao_sleep(&ao_ads1256_drdy);
154                 ao_arch_release_interrupts();
155
156                 curchan = nextchan;
157                 nextchan = (nextchan + 1) % AO_ADS1256_CHANNELS;
158
159                 d[0] = AO_ADS1256_MUX | AO_ADS1256_WREG;
160                 d[1] = 0;                       /* write one register */
161                 d[2] = nextchan << 4 | 0x08; ;  /* relative to AINCOM */
162                 d[3] = AO_ADS1256_SYNC;
163                 d[4] = AO_ADS1256_WAKEUP;
164                 d[5] = AO_ADS1256_RDATA;
165                 ao_ads1256_start();
166                 ao_spi_send(d, 6, AO_ADS1256_SPI_BUS);
167 //              ao_delay(1);
168                 ao_spi_recv(d, 3, AO_ADS1256_SPI_BUS);
169                 ao_ads1256_stop();
170
171                 ao_ads1256_current.ain[curchan] = 
172                         d[0] << 16 | d[1] << 8 | d[2];
173
174                 // FIXME
175                 //      If nextchan == 0, we have a complete set of inputs
176                 //      and we need to log them somewhere
177
178                 ao_ads1256_drdy = 0;
179         }
180 }
181
182 static struct ao_task ao_ads1256_task;
183
184 static void
185 ao_ads1256_dump(void)   
186 {
187         static int done;
188
189         if (!done) {
190                 done = 1;
191                 ao_add_task(&ao_ads1256_task, ao_ads1256, "ads1256");
192         }
193                 
194         printf ("ADS1256 value %d %d %d %d\n",
195                 ao_ads1256_current.ain[0],
196                 ao_ads1256_current.ain[1],
197                 ao_ads1256_current.ain[2],
198                 ao_ads1256_current.ain[3]);
199 }
200
201 const struct ao_cmds ao_ads1256_cmds[] = {
202         { ao_ads1256_dump,      "D\0Display ADS1256 data" },
203         { 0, NULL },
204 };
205
206 void
207 ao_ads1256_init(void)
208 {
209         ao_cmd_register(ao_ads1256_cmds);
210
211 //      ao_enable_output(AO_ADS1256_RESET_PORT, AO_ADS1256_RESET_PIN, 0);
212
213         ao_spi_init_cs(AO_ADS1256_SPI_CS_PORT, 
214                 (1 << AO_ADS1256_SPI_CS_PIN));
215
216 //      ao_add_task(&ao_ads1256_task, ao_ads1256, "ads1256");
217 }