File Coverage

blib/lib/RPi/ADC/ADS.pm
Criterion Covered Total %
statement 98 137 71.5
branch 39 60 65.0
condition 3 15 20.0
subroutine 16 21 76.1
pod 10 10 100.0
total 166 243 68.3


line stmt bran cond sub pod time code
1             package RPi::ADC::ADS;
2              
3 19     19   239010 use strict;
  19         29  
  19         545  
4 19     19   136 use warnings;
  19         26  
  19         1900  
5              
6             our $VERSION = '1.03';
7              
8             require XSLoader;
9             XSLoader::load('RPi::ADC::ADS', $VERSION);
10              
11             use constant {
12              
13 19         5570 DEFAULT_QUEUE => 0x03, # bits 1-0 (0-3)
14             MAX_QUEUE => 0x03,
15              
16             DEFAULT_POLARITY => 0x00, # bit 3
17             MAX_POLARITY => 0x08,
18              
19             DEFAULT_RATE => 0x00, # bits 7-5
20             MAX_RATE => 0xE0,
21              
22             DEFAULT_MODE => 0x100, # bit 8
23             MAX_MODE => 0x100,
24              
25             DEFAULT_GAIN => 0x200, # bits 11-9
26             MAX_GAIN => 0xE00,
27              
28             DEFAULT_CHANNEL => 0x4000, # bits 14-12
29             MAX_CHANNEL => 0x7000,
30 19     19   97 };
  19         23  
31              
32             # channel multiplexer
33              
34             my %mux = (
35             # bit 14-12 (most significant bit shown)
36              
37             # single-ended
38             0 => 0x4000, # 01000000, 16384
39             1 => 0x5000, # 01010000, 20480
40             2 => 0x6000, # 01100000, 24576
41             3 => 0x7000, # 01110000, 28672
42              
43             # differential
44             4 => 0x0, # 00000000, 0
45             5 => 0x1000, # 00010000, 4096
46             6 => 0x2000, # 00100000, 8192
47             7 => 0x3000, # 00110000, 12288
48             );
49              
50             # comparitor queue
51              
52             my %queue = (
53             # bit 1-0 (least significant bit shown)
54              
55             0 => 0x00, # 00000000, 0
56             1 => 0x01, # 00000001, 1
57             2 => 0x02, # 00000010, 2
58             3 => 0x03, # 00000011, 3
59             );
60              
61             # comparator polarity
62              
63             my %polarity = (
64             # bit 3 (least significant bit shown)
65              
66             0 => 0x00, # 00000000, 0
67             1 => 0x08, # 00000001, 8
68             );
69              
70             # data rate
71              
72             my %rate = (
73             # bit 7-5 (least significant bit shown)
74              
75             0 => 0x00, # 00000000, 0
76             1 => 0x20, # 00100000, 32
77             2 => 0x40, # 01000000, 64
78             3 => 0x60, # 01100000, 96
79             4 => 0x80, # 10000000, 128
80             5 => 0xA0, # 10100000, 160
81             6 => 0xC0, # 00000001, 192
82             7 => 0xE0, # 00000001, 224
83             );
84              
85             # operating mode
86              
87             my %mode = (
88             # bit 8 (both bits shown)
89              
90             0 => 0x00, # 0|00000000, 0
91             1 => 0x100, # 1|00000000, 256
92             );
93              
94             # amplifier gain
95              
96             my %gain = (
97             # bit 11-9 (most significant bit shown)
98              
99             0 => 0x00, # 00000000, 0
100             1 => 0x200, # 00000010, 512
101             2 => 0x400, # 00000100, 1024
102             3 => 0x600, # 00000110, 1536
103             4 => 0x800, # 00001000, 2048
104             5 => 0xA00, # 00001010, 2560
105             6 => 0xC00, # 00001100, 3072
106             7 => 0xE00, # 00001110, 3584
107             );
108              
109             # map of all the above config register maps
110              
111             my $param_map;
112              
113             BEGIN {
114              
115 19     19   133 $param_map = {
116             channel => \%mux,
117             queue => \%queue,
118             polarity => \%polarity,
119             rate => \%rate,
120             mode => \%mode,
121             gain => \%gain,
122             };
123              
124 19     19   106 no strict 'refs';
  19         53  
  19         3857  
125              
126 19         71 for my $sub (keys %$param_map) {
127              
128             *$sub = sub {
129              
130 277     277   44875 my ($self, $opt) = @_;
131              
132 277 100       401 if (defined $opt) {
133 53 100       137 if (! exists $param_map->{$sub}{$opt}) {
134 5         36 die "$sub param requires an integer\n";
135             }
136 48         74 $self->{$sub} = $param_map->{$sub}{$opt};
137             }
138              
139 272         392 my $default = "DEFAULT_" . uc $sub;
140 272         330 my $max = "MAX_" . uc $sub;
141              
142 272 100       789 $self->{$sub} = __PACKAGE__->$default if ! defined $self->{$sub};
143 272         754 $self->_bit_set($self->{$sub}, __PACKAGE__->$max);
144 272         392 return $self->{$sub};
145             }
146 114         28634 }
147             }
148              
149             # object methods (public)
150              
151             sub new {
152 45     45 1 2877982 my ($class, %args) = @_;
153              
154 45         92 my $self = bless {}, $class;
155              
156             # set up the initial default config register
157              
158 45         140 $self->register(0x80, 0x00);
159              
160             # primary C args
161              
162 45         158 $self->model($args{model});
163 45         151 $self->addr($args{addr});
164 45         120 $self->device($args{device});
165              
166             # control register switches
167              
168 45         127 $self->channel($args{channel});
169 45         148 $self->queue($args{queue});
170 45         142 $self->polarity($args{polarity});
171 45         142 $self->mode($args{mode});
172 45         125 $self->gain($args{gain});
173              
174             # default number of conversions to average per read (1 = single read)
175              
176 45         152 $self->samples($args{samples});
177              
178 45         131 return $self;
179             }
180             sub addr {
181 57     57 1 2811 my ($self, $addr) = @_;
182              
183 57 100       98 if (defined $addr){
184 8 100       14 if (! grep {$addr eq $_} qw(72 73 74 75)){
  32         57  
185 3         15 die "invalid address. " .
186             "Use 0x48 (72), 0x49 (73), 0x4A (74) or 0x4B (75)\n";
187             }
188 5         9 $self->{addr} = $addr;
189             }
190              
191 54 100       147 $self->{addr} = 0x48 if ! defined $self->{addr};
192              
193 54         73 return $self->{addr};
194             }
195             sub device {
196 71     71 1 6323 my ($self, $dev) = @_;
197              
198 71 100       120 if (defined $dev){
199 16 100       52 if ($dev !~ m|/dev/i2c-\d|){
200 5         24 die "invalid device name: $dev. " .
201             "Must be /dev/i2c-N, where N is 0-9\n";
202             }
203 11         16 $self->{device} = $dev;
204             }
205              
206 66 100       141 $self->{device} = '/dev/i2c-1' if ! defined $self->{device};
207              
208 66         93 return $self->{device};
209             }
210             sub model {
211 69     69 1 12720 my ($self, $model) = @_;
212              
213 69 100       155 if (defined $model){
214 24 100       128 if ($model !~ /^ADS1[01]1[3458]/){
215 7         40 die "invalid model name: $model. " .
216             "Must be 'ADS1x1y' where x is 1 or 0, and y is 3, 4, 5 or 8\n";
217             }
218 17         28 $self->{model} = $model
219             }
220              
221 62 100       200 $self->{model} = 'ADS1015' if ! defined $self->{model};
222              
223 62         322 my ($model_num) = $self->{model} =~ /(\d+)/;
224              
225 62         158 $self->_resolution($model_num);
226              
227 62         154 return $self->{model};
228             }
229              
230             # operational methods (public)
231              
232             sub bits {
233 314     314 1 413 my $self = shift;
234              
235 314         419 my @bytes = $self->register;
236              
237 314         437 my $bits = ($bytes[0] << 8) | $bytes[1];
238              
239 314         542 return $bits;
240             }
241             sub register {
242 670     670 1 4612 my ($self, $msb, $lsb) = @_;
243              
244             # config register
245              
246 670 100       913 if (defined $msb){
247 317 50       428 if (! defined $lsb){
248 0         0 die "register() requires \$msb and \$lsb params\n";
249             }
250 317 50       695 if (! grep {$msb == $_} (0..255)){
  81152         82746  
251 0         0 die "msg param requires an int 0..255\n";
252             }
253 317 50       1688 if (! grep {$lsb == $_} (0..255)){
  81152         80330  
254 0         0 die "lsb param requires an int 0..255\n";
255             }
256              
257 317         1786 $self->{register_data} = [$msb, $lsb];
258             }
259              
260 670         616 return @{ $self->{register_data} };
  670         1360  
261             }
262              
263             # private methods
264              
265             sub _bit_set {
266             # unset and set config register bits
267              
268 272     272   326 my ($self, $value, $max) = @_;
269              
270 272         356 my $bits = $self->bits;
271              
272             # unset
273 272         321 $bits &= ~$max;
274              
275             # set
276 272         245 $bits |= $value;
277              
278 272         273 my $lsb = $bits & 0xFF;
279 272         293 my $msb = $bits >> 8;
280              
281 272         313 $self->register($msb, $lsb);
282             }
283             sub _register_data {
284              
285             # for testing/validation purposes
286              
287 6     6   27 my $tables = {
288             mux => \%mux,
289             queue => \%queue,
290             polarity => \%polarity,
291             rate => \%rate,
292             mode => \%mode,
293             gain => \%gain,
294             };
295              
296 6         13 return $tables;
297             }
298             sub _resolution {
299             # decides/sets resolution to 12 or 16 bits
300              
301 71     71   111 my ($self, $model) = @_;
302              
303 71 100       138 if (defined $model){
304 62 100       189 if ($model =~ /11\d{2}/){
305 9         15 $self->{resolution} = 16;
306             }
307             else {
308 53         107 $self->{resolution} = 12;
309             }
310             }
311 71         155 return $self->{resolution};
312             }
313              
314             # device methods
315              
316             sub samples {
317 55     55 1 10015 my ($self, $samples) = @_;
318              
319 55 100       149 if (defined $samples){
320 7 100 100     60 if ($samples !~ /^\d+$/ || $samples < 1){
321 5         34 die "samples() requires a positive integer\n";
322             }
323 2         4 $self->{samples} = $samples;
324             }
325              
326 50 100       150 $self->{samples} = 1 if ! defined $self->{samples};
327              
328 50         71 return $self->{samples};
329             }
330             sub volts {
331 0     0 1   my ($self, $channel, $samples) = @_;
332              
333 0 0         if (defined $channel){
334 0           $self->channel($channel);
335             }
336              
337 0           my $addr = $self->addr;
338 0           my $dev = $self->device;
339 0           my @write_buf = $self->register;
340              
341 0           my $v = voltage_c(
342             $addr, $dev, $write_buf[0], $write_buf[1], $self->_resolution,
343             $self->_samples($samples),
344             );
345              
346 0 0 0       if ($self->channel > 3 && $v < 0){
347 0           return 0;
348             }
349              
350 0           return $v;
351             }
352             sub raw {
353 0     0 1   my ($self, $channel, $samples) = @_;
354              
355 0 0         if (defined $channel){
356 0           $self->channel($channel);
357             }
358              
359 0           my $addr = $self->addr;
360 0           my $dev = $self->device;
361 0           my @write_buf = $self->register;
362              
363 0           my $r = raw_c(
364             $addr, $dev, $write_buf[0], $write_buf[1], $self->_resolution,
365             $self->_samples($samples),
366             );
367              
368 0 0 0       if ($self->channel > 3 && $r < 0){
369 0           return 0;
370             }
371              
372 0           return $r;
373              
374             }
375             sub percent {
376 0     0 1   my ($self, $channel, $samples) = @_;
377              
378 0 0         if (defined $channel){
379 0           $self->channel($channel);
380             }
381              
382 0           my $addr = $self->addr;
383 0           my $dev = $self->device;
384 0           my @write_buf = $self->register;
385              
386 0           my $percent = percent_c(
387             $addr, $dev, $write_buf[0], $write_buf[1], $self->_resolution,
388             $self->_samples($samples),
389             );
390              
391 0 0         $percent = 100 if $percent > 100;
392              
393 0 0 0       if ($self->channel > 3 && $percent < 0){
394 0           return 0;
395             }
396              
397 0           return sprintf("%.2f", $percent);
398             }
399              
400             sub _samples {
401 0     0     my ($self, $samples) = @_;
402              
403             # Per-call override if given, otherwise the object default; validate either.
404 0 0         $samples = $self->samples if ! defined $samples;
405              
406 0 0 0       if ($samples !~ /^\d+$/ || $samples < 1){
407 0           die "samples must be a positive integer\n";
408             }
409              
410 0           return $samples;
411             }
412              
413       0     sub _vim {}
414              
415             1;
416              
417             __END__