-
Notifications
You must be signed in to change notification settings - Fork 1
/
ads1115rpi.cpp
149 lines (125 loc) · 3.56 KB
/
ads1115rpi.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include "ads1115rpi.h"
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
void ADS1115rpi::start(ADS1115settings settings) {
ads1115settings = settings;
char gpioFilename[20];
snprintf(gpioFilename, 19, "/dev/i2c-%d", settings.i2c_bus);
fd_i2c = open(gpioFilename, O_RDWR);
if (fd_i2c < 0) {
char i2copen[] = "Could not open I2C.\n";
#ifdef DEBUG
fprintf(stderr,i2open);
#endif
throw i2copen;
}
if (ioctl(fd_i2c, I2C_SLAVE, settings.address) < 0) {
char i2cslave[] = "Could not access I2C adress.\n";
#ifdef DEBUG
fprintf(stderr,i2cslave);
#endif
throw i2cslave;
}
#ifdef DEBUG
fprintf(stderr,"Init.\n");
#endif
// Enable RDY
i2c_writeWord(reg_lo_thres, 0x0000);
i2c_writeWord(reg_hi_thres, 0x8000);
unsigned r = (0b10000000 << 8); // kick it all off
r = r | (1 << 2) | (1 << 3); // data ready active high & latching
r = r | (settings.samplingRate << 5);
r = r | (settings.pgaGain << 9);
r = r | (settings.channel << 12) | 1 << 14; // unipolar
i2c_writeWord(reg_config,r);
#ifdef DEBUG
fprintf(stderr,"Receiving data.\n");
#endif
chipDRDY = gpiod_chip_open_by_number(settings.drdy_chip);
pinDRDY = gpiod_chip_get_line(chipDRDY,settings.drdy_gpio);
int ret = gpiod_line_request_rising_edge_events(pinDRDY, "Consumer");
if (ret < 0) {
#ifdef DEBUG
fprintf(stderr,"Request event notification failed on pin %d and chip %d.\n",settings.drdy_chip,settings.drdy_gpio);
#endif
throw "Could not request event for IRQ.";
}
running = true;
thr = std::thread(&ADS1115rpi::worker,this);
}
void ADS1115rpi::setChannel(ADS1115settings::Input channel) {
unsigned r = i2c_readWord(reg_config);
r = r & (~(3 << 12));
r = r | (channel << 12);
i2c_writeWord(reg_config,r);
ads1115settings.channel = channel;
}
void ADS1115rpi::dataReady() {
float v = (float)i2c_readConversion() / (float)0x7fff * fullScaleVoltage() * 2;
for(auto &cb: adsCallbackInterfaces) {
cb->hasADS1115Sample(v);
}
}
void ADS1115rpi::worker() {
while (running) {
const struct timespec ts = { 1, 0 };
gpiod_line_event_wait(pinDRDY, &ts);
struct gpiod_line_event event;
gpiod_line_event_read(pinDRDY, &event);
dataReady();
}
}
void ADS1115rpi::stop() {
if (!running) return;
running = false;
thr.join();
gpiod_line_release(pinDRDY);
gpiod_chip_close(chipDRDY);
close(fd_i2c);
}
// i2c read and write protocols
void ADS1115rpi::i2c_writeWord(uint8_t reg, unsigned data)
{
uint8_t tmp[3];
tmp[0] = reg;
tmp[1] = (char)((data & 0xff00) >> 8);
tmp[2] = (char)(data & 0x00ff);
long int r = write(fd_i2c,&tmp,3);
if (r < 0) {
#ifdef DEBUG
fprintf(stderr,"Could not write word from %02x. ret=%d.\n",ads1115settings.address,r);
#endif
throw "Could not write to i2c.";
}
}
unsigned ADS1115rpi::i2c_readWord(uint8_t reg)
{
uint8_t tmp[2];
tmp[0] = reg;
write(fd_i2c,&tmp,1);
long int r = read(fd_i2c, tmp, 2);
if (r < 0) {
#ifdef DEBUG
fprintf(stderr,"Could not read word from %02x. ret=%d.\n",ads1115settings.address,r);
#endif
throw "Could not read from i2c.";
}
return (((unsigned)(tmp[0])) << 8) | ((unsigned)(tmp[1]));
}
int ADS1115rpi::i2c_readConversion()
{
const int reg = 0;
char tmp[3];
tmp[0] = reg;
write(fd_i2c,&tmp,1);
long int r = read(fd_i2c, tmp, 2);
if (r < 0) {
#ifdef DEBUG
fprintf(stderr,"Could not read ADC value. ret=%d.\n",r);
#endif
throw "Could not read from i2c.";
}
return ((int)(tmp[0]) << 8) | (int)(tmp[1]);
}