File Coverage

blib/lib/PINE64/MCP3208.pm
Criterion Covered Total %
statement 9 59 15.2
branch 0 12 0.0
condition 0 9 0.0
subroutine 3 5 60.0
pod 2 2 100.0
total 14 87 16.0


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2 1     1   68302 use strict;
  1         3  
  1         35  
3 1     1   558 use Time::HiRes qw(usleep);
  1         1472  
  1         6  
4 1     1   699 use PINE64::GPIO;
  1         587  
  1         527  
5              
6             package PINE64::MCP3208;
7              
8             our $VERSION = '0.901';
9              
10             #SPI / bitbang varables
11             my ($clk, $din, $dout, $chpsel);
12              
13             #channels: first bit is set to single, not differential
14             #5 bits because the first is the start bit
15             my @ch0 = (1,1,0,0,0);
16             my @ch1 = (1,1,0,0,1);
17             my @ch2 = (1,1,0,1,0);
18             my @ch3 = (1,1,0,1,1);
19             my @ch4 = (1,1,1,0,0);
20             my @ch5 = (1,1,1,0,1);
21             my @ch6 = (1,1,1,1,0);
22             my @ch7 = (1,1,1,1,1);
23              
24             #instantiate PINE64 gpio device
25             my $p64 = PINE64::GPIO->new();
26              
27             sub new{
28 0     0 1   my $class = shift;
29 0           my $self = bless {}, $class;
30              
31             #
32 0           $clk = $_[0]; #clock
33 0           $din = $_[1]; #instructions to adc
34 0           $dout = $_[2]; #10-bit output from adc
35 0           $chpsel = $_[3]; #latch / load to init comm to adc
36              
37             #init gpio lines
38 0           $p64->gpio_enable($clk, 'out');
39 0           $p64->gpio_enable($din, 'out');
40 0           $p64->gpio_enable($dout, 'in');
41 0           $p64->gpio_enable($chpsel, 'out');
42            
43             #init chpsel high, comm begins when
44             #chipsel goes from high to low
45 0           $p64->gpio_write($chpsel, 1);
46              
47 0           return $self;
48              
49             }#end new
50              
51             sub read3208{
52             #init empty array that will
53             #contain 10-bit reading from ADC
54 0     0 1   my @reading = ();
55             #get reading from the MCP3004 ADC
56             #starts comm when cs goes from high to low
57            
58             #ADC channel number
59             #channel is an array reference
60 0           my $channel = $_[1];
61              
62             #delay between clock pulses
63             #needs to operate at 10KHz so
64             #sample is accurate, so min usleep(100)
65 0           my $delay = $_[2];
66              
67             #reference voltate, used only for calculations
68             #can be omitted
69 0           my $vref = $_[3];
70              
71             #main clock variable
72 0           my $i=0;
73            
74             #high flag for data gpio line
75 0           my $hf = 0;
76              
77             #number of clock pulses,
78 0           my $ncp = 38; #for 20 clock pulses
79              
80             #high or low state of clock pulse
81 0           my $state = 0;
82 0           my $seed = 3; #seed used to determine high or low, start 3 so first pulse is high
83            
84             #toggles CS line to init communication with the adc
85             #start low, go high, then low. comm begins when CS
86             #brought from high to low
87 0           $p64->gpio_write($chpsel, 0);
88 0           Time::HiRes::usleep($delay);
89            
90             #main loop
91 0           while($i<$ncp){
92 0           $state = $seed%2;#toggles between 1 and 0
93 0           $seed++;
94              
95             #clock pulse high
96 0 0         if(($i%2) eq 0){
97             #print "i: $i\tcp high\tstate: $state\n";
98              
99 0 0 0       if($channel->[$i/2] eq 1 && $i <=8){
100 0           $p64->gpio_write($din, 1);
101 0           $hf = 1;#set high flag
102             #print "ch[".($i/2)."]: ".$channel->[$i/2]."\n";
103             }#end if
104 0 0 0       if($channel->[$i/2] eq 0 && $i <=8){
105 0           $p64->gpio_write($din,0);
106             }#end if zero on data line
107             }#end if high
108              
109             #if($i>8){#data line
110             #everything after D0 bit is don't care,
111             #set to state
112             #gpio_write($din, $state);
113             #}#end else
114              
115             #clock pulse
116 0           $p64->gpio_write($clk, $state);
117              
118             #read data out
119             #data clocked out on falling
120             #edge of clk
121 0 0 0       if(($i%2) == 1 && $i >12){
122             #read state of gpio pin connected
123             #to data out of ADC
124 0           push @reading, $p64->gpio_read($dout);
125             #print "i[$i]: ".$reading[($i-14)/2]."\n"
126             }#end read data out
127              
128             #lower data if high flag set
129 0 0         if($hf eq 1){
130             #gpio_write($din,0);
131 0           $hf = 0;#reset high flag
132             }#end if
133            
134             #pause between clk pls
135 0           Time::HiRes::usleep($delay);
136              
137             #increment counter
138 0           $i++;
139             }#end while
140            
141             #make din low
142 0           $p64->gpio_write($din, 0);
143              
144             #make chip select high
145 0           $p64->gpio_write($chpsel, 1);
146              
147             #perform calcuations, return a voltage
148             #based of 12-bit reading, and vref val
149 0           my $bindig = 2048;
150 0           my $rdgval = 0;
151 0           my $voltage = 0;
152 0           for(my $x=0; $x<12;$x++){
153 0 0         if(@reading[$x] == 1){
154 0           $rdgval = $rdgval + $bindig;
155             }#end if
156 0           $bindig = $bindig / 2;
157             }#end for
158              
159             #voltage calculation
160 0           $voltage = ($rdgval*$vref)/4096;
161              
162 0           return (\@reading, $rdgval, $voltage);
163             }#end read3208
164              
165             1;
166             __END__