File Coverage

blib/lib/Device/TM1638.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Device::TM1638;
2              
3 1     1   13078 use 5.006;
  1         3  
  1         31  
4 1     1   7 use strict;
  1         1  
  1         29  
5 1     1   3 use warnings;
  1         5  
  1         25  
6 1     1   174 use Device::BCM2835;
  0            
  0            
7             use List::Util "min";
8              
9              
10             =head1 NAME
11              
12             Device::TM1638 - The great new Device::TM1638!
13              
14             =head1 VERSION
15              
16             Version 0.01
17              
18             =cut
19              
20             our $VERSION = '0.01';
21              
22              
23             =head1 SYNOPSIS
24              
25             Quick summary of what the module does.
26              
27             Perhaps a little code snippet.
28              
29             use Device::TM1638;
30              
31             my $foo = Device::TM1638->new();
32             ...
33              
34             =head1 EXPORT
35              
36             A list of functions that can be exported. You can delete this section
37             if you don't export anything, such as for a purely object-oriented module.
38              
39             =head1 SUBROUTINES/METHODS
40              
41             =head2 function1
42              
43             =cut
44             my %FONT = (
45             '!' => 0b10000110,
46             '"' => 0b00100010,
47             '#' => 0b01111110,
48             '$' => 0b01101101,
49             '%' => 0b00000000,
50             '&' => 0b00000000,
51             '(' => 0b00110000,
52             ')' => 0b00000110,
53             '*' => 0b00000000,
54             '+' => 0b00000000,
55             '' => 0b00000100,
56             '-' => 0b01000000,
57             '.' => 0b10000000,
58             '/' => 0b01010010,
59             '0' => 0b00111111,
60             '1' => 0b00000110,
61             '2' => 0b01011011,
62             '3' => 0b01001111,
63             '4' => 0b01100110,
64             '5' => 0b01101101,
65             '6' => 0b01111101,
66             '7' => 0b00100111,
67             '8' => 0b01111111,
68             '9' => 0b01101111,
69             ':' => 0b00000000,
70             ';' => 0b00000000,
71             '<' => 0b00000000,
72             '=' => 0b01001000,
73             '>' => 0b00000000,
74             '?' => 0b01010011,
75             '@' => 0b01011111,
76             'A' => 0b01110111,
77             'B' => 0b01111111,
78             'C' => 0b00111001,
79             'D' => 0b00111111,
80             'E' => 0b01111001,
81             'F' => 0b01110001,
82             'G' => 0b00111101,
83             'H' => 0b01110110,
84             'I' => 0b00000110,
85             'J' => 0b00011111,
86             'K' => 0b01101001,
87             'L' => 0b00111000,
88             'M' => 0b00010101,
89             'N' => 0b00110111,
90             'O' => 0b00111111,
91             'P' => 0b01110011,
92             'Q' => 0b01100111,
93             'R' => 0b00110001,
94             'S' => 0b01101101,
95             'T' => 0b01111000,
96             'U' => 0b00111110,
97             'V' => 0b00101010,
98             'W' => 0b00011101,
99             'X' => 0b01110110,
100             'Y' => 0b01101110,
101             'Z' => 0b01011011,
102             '[' => 0b00111001,
103             ']' => 0b00001111,
104             '^' => 0b00000000,
105             '_' => 0b00001000,
106             '`' => 0b00100000,
107             'a' => 0b01011111,
108             'b' => 0b01111100,
109             'c' => 0b01011000,
110             'd' => 0b01011110,
111             'e' => 0b01111011,
112             'f' => 0b00110001,
113             'g' => 0b01101111,
114             'h' => 0b01110100,
115             'i' => 0b00000100,
116             'j' => 0b00001110,
117             'k' => 0b01110101,
118             'l' => 0b00110000,
119             'm' => 0b01010101,
120             'n' => 0b01010100,
121             'o' => 0b01011100,
122             'p' => 0b01110011,
123             'q' => 0b01100111,
124             'r' => 0b01010000,
125             's' => 0b01101101,
126             't' => 0b01111000,
127             'u' => 0b00011100,
128             'v' => 0b00101010,
129             'w' => 0b00011101,
130             'x' => 0b01110110,
131             'y' => 0b01101110,
132             'z' => 0b01000111,
133             '{' => 0b01000110,
134             '|' => 0b00000110,
135             '}' => 0b01110000,
136             '~' => 0b00000001
137             );
138              
139             sub new {
140             my ($class, $dio, $clk, $stb) = @_;
141             my $ret = Device::BCM2835::init() or die;
142             return bless { dio => $dio,
143             clk => $clk,
144             stb => $stb,
145             }, $class;
146             }
147              
148             sub _write {
149             my ($pin, $value) = @_;
150             Device::BCM2835::gpio_write($pin, $value);
151             }
152              
153             sub _read {
154             my ($pin) = @_;
155             return Device::BCM2835::gpio_lev($pin);
156             }
157              
158             sub _gpio_fsel {
159             my ($pin, $value) = @_;
160             Device::BCM2835::gpio_fsel($pin, $value);
161             }
162              
163             sub enable {
164             my ($self, $intensity) = @_;
165             $intensity ||= 7;
166             _gpio_fsel($self->{dio}, &Device::BCM2835::BCM2835_GPIO_FSEL_OUTP);
167             _gpio_fsel($self->{clk}, &Device::BCM2835::BCM2835_GPIO_FSEL_OUTP);
168             _gpio_fsel($self->{stb}, &Device::BCM2835::BCM2835_GPIO_FSEL_OUTP);
169              
170             $self->stb_high;
171             _write($self->{clk}, 1);
172              
173             $self->send_command(0x40);
174             $self->send_command(0x80 | 8 | min(7, $intensity));
175              
176             $self->stb_low;
177              
178             $self->send_byte(0xc0);
179              
180             foreach (1..16) {
181             $self->send_byte(0x00);
182             }
183              
184             $self->stb_high;
185              
186             };
187              
188             sub send_command {
189             my ($self, $cmd) = @_;
190             $self->stb_low;
191             $self->send_byte($cmd);
192             $self->stb_high;
193             }
194              
195             sub send_data {
196             my ($self, $addr, $data) = @_;
197             $self->send_command(0x44);
198             $self->stb_low;
199             $self->send_byte(0xC0 | $addr);
200             $self->send_byte($data);
201             $self->stb_high;
202             }
203              
204             sub send_byte {
205             my ($self, $data) = @_;
206             for (1..8) {
207             _write($self->{clk}, 0);
208             _write($self->{dio}, $data & 1);
209             $data >>= 1;
210             _write($self->{clk}, 1);
211             };
212             }
213              
214             sub set_led {
215             my ($self, $n, $color) = @_;
216             $self->send_data(($n << 1) + 1, $color);
217             }
218              
219             sub _send_char {
220             my ($self, $pos, $data, $dot) = @_;
221             $dot ||= 0;
222             $self->send_data($pos << 1, $data | ($dot ? 128 : 0));
223             }
224              
225             sub send_char {
226             my ($self, $pos, $char, $dot) = @_;
227             $self->_send_char($pos, $FONT{$char}, $dot);
228             }
229              
230             sub set_digit {
231             my ($self, $pos, $digit, $dot) = @_;
232             $dot ||= 0;
233             for my $i (0..6) {
234             $self->_send_char($i, $self->get_bit_mask($pos, $digit, $i), $dot);
235             }
236             }
237              
238             sub get_bit_mask {
239             my ($self, $pos, $digit, $bit) = @_;
240             return (($FONT{$digit} >> $bit) & 1) << $pos;
241             }
242              
243             sub set_text {
244             my ($self, $text) = @_;
245            
246             my $dots = 0b00000000;
247             my $pos = index($text,'.');
248             if ($pos != -1) {
249             $dots = $dots | (128 >> $pos+(8-length($text)));
250             $text =~ s/\.//g;
251             }
252              
253             $self->_send_char(7, $self->rotate_bits($dots));
254             $text = substr($text, 0,8);
255             $text = reverse($text);
256             $text .= " " x (8-length($text));
257              
258             for my $i (0..7) {
259             my $byte = 0b00000000;
260             for my $pos (0..7) {
261             my $c = substr($text, $pos, 1);
262             if ($c ne ' ') {
263             $byte = ($byte | $self->get_bit_mask($pos, $c, $i));
264             }
265             $self->_send_char($i, $self->rotate_bits($byte));
266             }
267             }
268             }
269              
270             sub receive {
271             my ($self) = @_;
272             my $temp = 0;
273             _gpio_fsel($self->{dio}, &Device::BCM2835::BCM2835_GPIO_FSEL_INPT);
274             Device::BCM2835::gpio_set_pud($self->{dio}, &Device::BCM2835::BCM2835_GPIO_PUD_UP);
275             for my $i (0..7) {
276             $temp >>= 1;
277             _write($self->{clk}, 0);
278             if ($self->_read($self->{clk})) {
279             $temp |= 0x80;
280             }
281             _write($self->{clk}, 1);
282             _gpio_fsel($self->{dio}, &Device::BCM2835::BCM2835_GPIO_FSEL_OUTP);
283             }
284             return $temp;
285             }
286              
287             sub get_buttons {
288             my ($self) = @_;
289             my $keys = 0;
290             _write($self->{stb}, 0);
291             $self->send_byte(0x42);
292             for my $i (0..3) {
293             $keys |= $self->receive() << $i;
294             }
295             _write($self->{stb}, 1);
296             return $keys;
297             }
298              
299             sub rotate_bits {
300             my ($self, $num) = @_;
301             for my $i (0..4) {
302             $num = $self->rotr($num, 8);
303             }
304             return $num;
305             }
306              
307             sub rotr {
308             my ($self, $num, $bits) = @_;
309             $num &= (2**$bits-1);
310             my $bit = $num & 1;
311             $num >>= 1;
312             if ($bit) {
313             $num |= (1 << ($bits-1));
314             }
315             return $num
316             }
317              
318             sub stb_low {
319             my($self) = @_;
320             _write($self->{stb}, 0);
321             }
322              
323             sub stb_high {
324             my($self) = @_;
325             _write($self->{stb}, 1);
326             }
327              
328             1;
329              
330             =head1 AUTHOR
331              
332             Adam Wien, C<< >>
333              
334             =head1 BUGS
335              
336             Please report any bugs or feature requests to C, or through
337             the web interface at L. I will be notified, and then you'll
338             automatically be notified of progress on your bug as I make changes.
339              
340              
341              
342              
343             =head1 SUPPORT
344              
345             You can find documentation for this module with the perldoc command.
346              
347             perldoc Device::TM1638
348              
349              
350             You can also look for information at:
351              
352             =over 4
353              
354             =item * RT: CPAN's request tracker (report bugs here)
355              
356             L
357              
358             =item * AnnoCPAN: Annotated CPAN documentation
359              
360             L
361              
362             =item * CPAN Ratings
363              
364             L
365              
366             =item * Search CPAN
367              
368             L
369              
370             =back
371              
372              
373             =head1 ACKNOWLEDGEMENTS
374              
375              
376             =head1 LICENSE AND COPYRIGHT
377              
378             Copyright 2015 Adam Wien.
379              
380             This program is free software; you can redistribute it and/or modify it
381             under the terms of the the Artistic License (2.0). You may obtain a
382             copy of the full license at:
383              
384             L
385              
386             Any use, modification, and distribution of the Standard or Modified
387             Versions is governed by this Artistic License. By using, modifying or
388             distributing the Package, you accept this license. Do not use, modify,
389             or distribute the Package, if you do not accept this license.
390              
391             If your Modified Version has been derived from a Modified Version made
392             by someone other than you, you are nevertheless required to ensure that
393             your Modified Version complies with the requirements of this license.
394              
395             This license does not grant you the right to use any trademark, service
396             mark, tradename, or logo of the Copyright Holder.
397              
398             This license includes the non-exclusive, worldwide, free-of-charge
399             patent license to make, have made, use, offer to sell, sell, import and
400             otherwise transfer the Package with respect to any patent claims
401             licensable by the Copyright Holder that are necessarily infringed by the
402             Package. If you institute patent litigation (including a cross-claim or
403             counterclaim) against any party alleging that the Package constitutes
404             direct or contributory patent infringement, then this Artistic License
405             to you shall terminate on the date that such litigation is filed.
406              
407             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
408             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
409             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
410             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
411             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
412             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
413             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
414             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
415              
416              
417             =cut
418              
419             1; # End of Device::TM1638