| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Device::Chip::PCA9685; |
|
2
|
|
|
|
|
|
|
|
|
3
|
4
|
|
|
4
|
|
77871
|
use strict; |
|
|
4
|
|
|
|
|
6
|
|
|
|
4
|
|
|
|
|
86
|
|
|
4
|
4
|
|
|
4
|
|
13
|
use warnings; |
|
|
4
|
|
|
|
|
4
|
|
|
|
4
|
|
|
|
|
130
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = 'v0.9'; |
|
7
|
|
|
|
|
|
|
|
|
8
|
4
|
|
|
4
|
|
20
|
use base qw/Device::Chip/; |
|
|
4
|
|
|
|
|
4
|
|
|
|
4
|
|
|
|
|
610
|
|
|
9
|
|
|
|
|
|
|
|
|
10
|
4
|
|
|
4
|
|
7817
|
use Future; |
|
|
4
|
|
|
|
|
4
|
|
|
|
4
|
|
|
|
|
66
|
|
|
11
|
4
|
|
|
4
|
|
13
|
use Time::HiRes q/usleep/; |
|
|
4
|
|
|
|
|
3
|
|
|
|
4
|
|
|
|
|
17
|
|
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=head1 NAME |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
C - A C implementation for the PCA9685 chip |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
This class implements a L interface for the PCA9685 chip, a 12-bit 16 channel PWM driver. |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
use Device::Chip::PCA9685; |
|
24
|
|
|
|
|
|
|
use Device::Chip::Adapter; |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
my $adapter = Device::Chip::Adapter->new_from_description("LinuxKernel"); |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
my $chip = Device::Chip::PCA9685->new(); |
|
29
|
|
|
|
|
|
|
# This is the i2c bus on an RPI 2 B+ |
|
30
|
|
|
|
|
|
|
$chip->mount($adapter, bus => '/dev/i2c-1')->get; |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
$chip->enable()->get; |
|
33
|
|
|
|
|
|
|
$chip->set_frequency(400)->get; # 400 Hz |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
$chip->set_channel_value(10, 1024)->get; # Set channel 10 to 25% (1024/4096) |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
$chip->set_channel_full_value(10, 1024, 3192)->get; # Set channel 10 to ON at COUNTER=1024, and OFF at COUNTER=3192 (50% duty cycle, with 25% phase difference) |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
=head1 METHODS |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
=cut |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
my %REGS = ( |
|
44
|
|
|
|
|
|
|
MODE1 => {addr => 0}, |
|
45
|
|
|
|
|
|
|
MODE2 => {addr => 1}, |
|
46
|
|
|
|
|
|
|
SUBADR1 => {addr => 2}, |
|
47
|
|
|
|
|
|
|
SUBADR2 => {addr => 3}, |
|
48
|
|
|
|
|
|
|
SUBADR3 => {addr => 4}, |
|
49
|
|
|
|
|
|
|
ALLCALLADR => {addr => 5}, |
|
50
|
|
|
|
|
|
|
ALL_CHAN_ON => {addr => 0xFA}, # 16bit |
|
51
|
|
|
|
|
|
|
ALL_CHAN_OFF => {addr => 0xFC}, # 16bit |
|
52
|
|
|
|
|
|
|
PRE_SCALE => {addr => 0xFE}, |
|
53
|
|
|
|
|
|
|
TEST_MODE => {addr => 0xFF}, |
|
54
|
|
|
|
|
|
|
); |
|
55
|
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
for my $n (0..15) { |
|
57
|
|
|
|
|
|
|
$REGS{"CHAN${n}_ON"} = {addr => 0x06 + $n * 4}; # 16bit |
|
58
|
|
|
|
|
|
|
$REGS{"CHAN${n}_OFF"} = {addr => 0x08 + $n * 4}; # 16bit |
|
59
|
|
|
|
|
|
|
} |
|
60
|
|
|
|
|
|
|
|
|
61
|
4
|
|
|
4
|
|
1209
|
use utf8; |
|
|
4
|
|
|
|
|
12
|
|
|
|
4
|
|
|
|
|
14
|
|
|
62
|
|
|
|
|
|
|
|
|
63
|
4
|
|
|
4
|
|
78
|
use constant PROTOCOL => "I2C"; |
|
|
4
|
|
|
|
|
3
|
|
|
|
4
|
|
|
|
|
1704
|
|
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
sub _read_u8 { |
|
66
|
1
|
|
|
1
|
|
1
|
my $self = shift; |
|
67
|
1
|
|
|
|
|
1
|
my ($register) = @_; |
|
68
|
|
|
|
|
|
|
|
|
69
|
1
|
|
|
|
|
3
|
my $regv = $REGS{$register}{addr}; |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
$self->protocol->write_then_read("\0", 1)->then( sub { |
|
72
|
1
|
|
|
1
|
|
94
|
my ($value) = @_; |
|
73
|
1
|
|
|
|
|
3
|
return Future->done(unpack("C", $value)); |
|
74
|
1
|
|
|
|
|
2
|
}); |
|
75
|
|
|
|
|
|
|
} |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub _write_u8 { |
|
78
|
5
|
|
|
5
|
|
46
|
my $self = shift; |
|
79
|
5
|
|
|
|
|
8
|
my ($register, $value) = @_; |
|
80
|
|
|
|
|
|
|
|
|
81
|
5
|
|
|
|
|
10
|
my $regv = $REGS{$register}{addr}; |
|
82
|
|
|
|
|
|
|
|
|
83
|
5
|
|
|
|
|
12
|
$self->protocol->write(pack("C C", $regv, $value)); |
|
84
|
|
|
|
|
|
|
} |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
sub _write_u16 { |
|
87
|
3
|
|
|
3
|
|
3
|
my $self = shift; |
|
88
|
3
|
|
|
|
|
5
|
my ($register, @values) = @_; |
|
89
|
|
|
|
|
|
|
|
|
90
|
3
|
|
|
|
|
5
|
my $regv = $REGS{$register}{addr}; |
|
91
|
|
|
|
|
|
|
|
|
92
|
3
|
|
|
|
|
7
|
$self->protocol->write(pack("C (S<)*", $regv, @values)); |
|
93
|
|
|
|
|
|
|
} |
|
94
|
|
|
|
|
|
|
|
|
95
|
3
|
|
|
3
|
0
|
496
|
sub I2C_options {my $self = shift; return (addr => 0x40, @_)}; # pass it through, but allow the address to change if passed in, should use a constructor instead |
|
|
3
|
|
|
|
|
11
|
|
|
96
|
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
=head2 set_channel_value |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
$chip->set_channel_value($channel, $time_on, $offset = 0)->get |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
Sets a channel PWM time based on a single value from 0-4095. Starts the channel to turn on at COUNTER = 0, and off at $time_on. |
|
102
|
|
|
|
|
|
|
C<$offset> lets you stagger the time that the channel comes on and off. This lets you vary the times that channels go on and off |
|
103
|
|
|
|
|
|
|
to reduce noise effects and power supply issues from large loads all coming on at once. |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
C<$on_time> := 0; C<$off_time> := $time_on; |
|
106
|
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
=cut |
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub set_channel_value { |
|
110
|
1
|
|
|
1
|
1
|
78
|
my $self = shift; |
|
111
|
1
|
|
|
|
|
1
|
my ($chan, $time_on, $offset) = @_; |
|
112
|
1
|
|
50
|
|
|
5
|
$offset //= 0; |
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
# set the high parts first, we shouldn't ever have backtracking then |
|
115
|
|
|
|
|
|
|
|
|
116
|
1
|
50
|
33
|
|
|
7
|
if ($time_on < 0 || $time_on >= 4096) { |
|
117
|
0
|
0
|
|
|
|
0
|
$time_on = $time_on >= 4096 ? 4095 : 0; |
|
118
|
0
|
|
|
|
|
0
|
warn "Channel outside allowed value, clamping: $chan, $time_on\n"; |
|
119
|
|
|
|
|
|
|
} |
|
120
|
|
|
|
|
|
|
|
|
121
|
1
|
|
|
|
|
2
|
$offset %= 4096; # wrap the offset around, that way you can increment it by any amount and have it work as expected |
|
122
|
1
|
|
|
|
|
1
|
$time_on = ($time_on + $offset) % 4096; # wrap it around based on the offset. |
|
123
|
|
|
|
|
|
|
|
|
124
|
1
|
|
|
|
|
3
|
$self->set_channel_full_value($chan, $offset, $time_on); |
|
125
|
|
|
|
|
|
|
} |
|
126
|
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=head2 set_channel_full_value |
|
128
|
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
$chip->set_channel_full_value($channel, $on_time, $off_time)->get |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
Set a channel value, on and off time. Lets you control the full on and off time based on the 12 bit counter on the device. |
|
132
|
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=cut |
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
sub set_channel_full_value { |
|
136
|
1
|
|
|
1
|
1
|
2
|
my ($self, $chan, $on_t, $off_t) = @_; |
|
137
|
|
|
|
|
|
|
|
|
138
|
1
|
|
|
|
|
5
|
$self->_write_u16("CHAN${chan}_ON" => ($on_t & 0x0FFF), ($off_t & 0x0FFF)); |
|
139
|
|
|
|
|
|
|
} |
|
140
|
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=head2 set_channel_on |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
$chip->set_channel_on($channel)->get |
|
144
|
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
Set a channel to full on. No off time at all. |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
=cut |
|
148
|
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
sub set_channel_on { |
|
150
|
1
|
|
|
1
|
1
|
1072
|
my ($self, $chan) = @_; |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
# Set bit 4 of ON high, this is the bit that sets the channel to full on |
|
153
|
1
|
|
|
|
|
4
|
$self->_write_u16("CHAN${chan}_ON" => 0x1000, 0x0000); |
|
154
|
|
|
|
|
|
|
} |
|
155
|
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
=head2 set_channel_off |
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
$chip->set_channel_off($channel)->get |
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
Set a channel to full off. No on time at all. |
|
161
|
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=cut |
|
163
|
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
sub set_channel_off { |
|
165
|
1
|
|
|
1
|
1
|
806
|
my ($self, $chan) = @_; |
|
166
|
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
# Set bit 4 of OFF high, this is the bit that sets the channel to full off |
|
168
|
1
|
|
|
|
|
4
|
$self->_write_u16("CHAN${chan}_ON" => 0x0000, 0x1000); |
|
169
|
|
|
|
|
|
|
} |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
=head2 set_default_mode |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
$chip->set_default_mode()->get |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
Reset the default mode back to the PCA9685. |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
=cut |
|
178
|
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
sub set_default_mode { |
|
180
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
181
|
|
|
|
|
|
|
# Sets all the mode registers to the chip defaults |
|
182
|
0
|
|
|
|
|
0
|
Future->needs_all( |
|
183
|
|
|
|
|
|
|
$self->_write_u8(MODE1 => 0b0000_0001), |
|
184
|
|
|
|
|
|
|
$self->_write_u8(MODE2 => 0b000_00100), |
|
185
|
|
|
|
|
|
|
); |
|
186
|
|
|
|
|
|
|
} |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
=head2 set_frequency |
|
189
|
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
$chip->set_frequency() |
|
191
|
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
Set the prescaler to the desired frequency for PWM. Returns the real frequency due to rounding. |
|
193
|
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=cut |
|
195
|
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
sub set_frequency { |
|
197
|
1
|
|
|
1
|
1
|
106
|
my $self = shift; |
|
198
|
1
|
|
|
|
|
1
|
my ($freq) = @_; |
|
199
|
4
|
|
|
4
|
|
4010
|
use Data::Dumper; |
|
|
4
|
|
|
|
|
17882
|
|
|
|
4
|
|
|
|
|
857
|
|
|
200
|
|
|
|
|
|
|
|
|
201
|
1
|
|
|
|
|
6
|
my $divisor = int( ( 25000000 / ( 4096 * $freq ) ) + 0.5 ) - 1; |
|
202
|
1
|
50
|
|
|
|
2
|
if ($divisor < 3) { die "PCA9685 forces the scaler to be at least >= 3 (1526 Hz)." }; |
|
|
0
|
|
|
|
|
0
|
|
|
203
|
1
|
50
|
|
|
|
3
|
if ($divisor > 255) { die "PCA9685 forces the scaler to be <= 255 (24Hz)." }; |
|
|
0
|
|
|
|
|
0
|
|
|
204
|
|
|
|
|
|
|
|
|
205
|
1
|
|
|
|
|
1
|
my $realfreq = 25000000 / (($divisor + 1)*(4096)); |
|
206
|
|
|
|
|
|
|
|
|
207
|
1
|
|
|
|
|
1
|
my $old_mode1; |
|
208
|
|
|
|
|
|
|
$self->_read_u8("MODE1")->then( sub { |
|
209
|
1
|
|
|
1
|
|
57
|
( $old_mode1 ) = @_; |
|
210
|
|
|
|
|
|
|
|
|
211
|
1
|
|
|
|
|
2
|
my $new_mode1 = ($old_mode1 & 0x7f) | 0x10; # Set the chip to sleep, make sure reset is disabled while we do this to avoid noise/phase differences |
|
212
|
|
|
|
|
|
|
|
|
213
|
1
|
|
|
|
|
4
|
$self->_write_u8(MODE1 => $new_mode1); |
|
214
|
|
|
|
|
|
|
})->then( sub { |
|
215
|
1
|
|
|
1
|
|
92
|
Future->needs_all( |
|
216
|
|
|
|
|
|
|
$self->_write_u8(PRE_SCALE => $divisor), |
|
217
|
|
|
|
|
|
|
$self->_write_u8(MODE1 => $old_mode1), |
|
218
|
|
|
|
|
|
|
); |
|
219
|
|
|
|
|
|
|
})->then( sub { |
|
220
|
1
|
|
|
1
|
|
5248
|
usleep(5000); |
|
221
|
1
|
|
|
|
|
7
|
$self->_write_u8(MODE1 => $old_mode1 | 0x80); # turn on the external clock, should this be optional? |
|
222
|
|
|
|
|
|
|
})->then( sub { |
|
223
|
1
|
|
|
1
|
|
109
|
return Future->done( $realfreq ); |
|
224
|
1
|
|
|
|
|
4
|
}); |
|
225
|
|
|
|
|
|
|
} |
|
226
|
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
=head2 enable |
|
228
|
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
$chip->enable()->get |
|
230
|
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
Enable the device. Must be the first thing done with the device. |
|
232
|
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
=cut |
|
234
|
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
sub enable { |
|
236
|
1
|
|
|
1
|
1
|
78
|
my $self = shift; |
|
237
|
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
# 0x20 == AI, auto-increment addresses during register transfer |
|
239
|
|
|
|
|
|
|
# Useful for 16bit read/write |
|
240
|
1
|
|
|
|
|
3
|
$self->_write_u8(MODE1 => 0x20); |
|
241
|
|
|
|
|
|
|
} |
|
242
|
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
=head1 AUTHOR |
|
244
|
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
Ryan Voots, |
|
246
|
|
|
|
|
|
|
Paul 'LeoNerd' Evans |
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
=cut |
|
249
|
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
1; |