File Coverage

blib/lib/Device/BusPirate/Chip/MAX7219.pm
Criterion Covered Total %
statement 21 63 33.3
branch 0 18 0.0
condition 0 12 0.0
subroutine 7 19 36.8
pod 9 9 100.0
total 37 121 30.5


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2014 -- leonerd@leonerd.org.uk
5              
6             package Device::BusPirate::Chip::MAX7219;
7              
8 1     1   825 use strict;
  1         3  
  1         56  
9 1     1   8 use warnings;
  1         2  
  1         50  
10 1     1   19 use base qw( Device::BusPirate::Chip );
  1         1  
  1         749  
11              
12             our $VERSION = '0.01';
13              
14 1     1   695 use Carp;
  1         2  
  1         102  
15              
16 1     1   8 use constant CHIP => "MAX7219";
  1         1  
  1         90  
17 1     1   6 use constant MODE => "SPI";
  1         2  
  1         128  
18              
19             =head1 NAME
20              
21             C - use a F chip with C
22              
23             =head1 SYNOPSIS
24              
25             use Device::BusPirate;
26              
27             my $pirate = Device::BusPirate->new;
28             my $max = $pirate->mount_chip( "MAX7219" )->get;
29              
30             $max->mode->configure( open_drain => 0 )->get;
31             $max->power(1)->get;
32              
33             $max->intensity( 2 )->get;
34             $max->limit( 8 )->get;
35              
36             $max->displaytest( 1 )->get;
37             $max->shutdown( 0 )->get;
38              
39             sleep 3;
40              
41             $max->displaytest( 0 )->get;
42              
43             =head1 DESCRIPTION
44              
45             This L subclass provides specific communication to a
46             F F chip attached to the F via SPI. As
47             the F chip operates virtually identically, this chip will work too.
48              
49             The reader is presumed to be familiar with the general operation of this chip;
50             the documentation here will not attempt to explain or define chip-specific
51             concepts or features, only the use of this module to access them.
52              
53             =cut
54              
55             sub new
56             {
57 0     0 1   my $class = shift;
58 0           my $self = $class->SUPER::new( @_ );
59              
60 0           $self->{decode} = 0;
61              
62 0           return $self;
63             }
64              
65             use constant {
66 1         918 REG_NONE => 0x00,
67             REG_DIGIT => 0x01, # .. to 8
68             REG_DECODE => 0x09,
69             REG_INTENSITY => 0x0A,
70             REG_LIMIT => 0x0B,
71             REG_SHUTDOWN => 0x0C,
72             REG_DTEST => 0x0F,
73 1     1   6 };
  1         1  
74              
75             sub _writereg
76             {
77 0     0     my $self = shift;
78 0           my ( $reg, $value ) = @_;
79              
80 0           $self->mode->writeread_cs( chr( $reg ) . chr( $value ) );
81             }
82              
83             =head1 METHODS
84              
85             =cut
86              
87             =head2 $max->write_bcd( $digit, $val )->get
88              
89             Writes the value at the given digit, setting it to BCD mode if not already so.
90             C<$val> should be a single digit number or string, or one of the special
91             recognised characters in BCD mode of C<->, C, C, C, C

or space.

92             The value may optionally be followed by a decimal point C<.>, which will be
93             set on the display.
94              
95             Switches the digit into BCD mode if not already so.
96              
97             =cut
98              
99             sub write_bcd
100             {
101 0     0 1   my $self = shift;
102 0           my ( $digit, $val ) = @_;
103              
104 0 0 0       $digit >= 0 and $digit <= 7 or
105             croak "Digit must be 0 to 7";
106              
107 0           my $dp = ( $val =~ s/\.$// );
108 0 0         length $val == 1 or
109             croak "BCD value must be 1 character";
110 0 0         ( $val = index "0123456789-EHLP ", $val ) > -1 or
111             croak "Digit value '$val' is not allowed in BCD mode";
112              
113 0           my $decodemask = 1 << $digit;
114              
115             ( ( $self->{decode} & $decodemask ) ?
116             Future->done :
117             $self->set_decode( $self->{decode} | $decodemask )
118             )->then( sub {
119 0 0   0     $self->_writereg( REG_DIGIT+$digit, $val + ( $dp ? 0x80 : 0 ) );
120 0 0         });
121             }
122              
123             =head2 $max->write_raw( $digit, $bits )->get
124              
125             Writes the value at the given digit, setting the raw column lines to the 8-bit
126             value given.
127              
128             Switches the digit into undecoded raw mode if not already so.
129              
130             =cut
131              
132             sub write_raw
133             {
134 0     0 1   my $self = shift;
135 0           my ( $digit, $bits ) = @_;
136              
137 0 0 0       $digit >= 0 and $digit <= 7 or
138             croak "Digit must be 0 to 7";
139              
140 0           my $decodemask = 1 << $digit;
141              
142             ( ( $self->{decode} & $decodemask ) ?
143             $self->set_decode( $self->{decode} & ~$decodemask ) :
144             Future->done
145             )->then( sub {
146 0     0     $self->_writereg( REG_DIGIT+$digit, $bits );
147 0 0         });
148             }
149              
150             =head2 $max->write_hex( $digit, $val )->get
151              
152             Similar to C, but uses a segment decoder written in code rather
153             than on the chip itself, to turn values into sets of segments to display. This
154             makes it capable of displaying the letters C to C, in addition to
155             numbers, C<-> and space.
156              
157             =cut
158              
159             my %hex2bits;
160              
161             sub write_hex
162             {
163 0     0 1   my $self = shift;
164 0           my ( $digit, $val ) = @_;
165 0           my $dp = ( $val =~ s/\.$// );
166 0   0       my $bits = $hex2bits{$val} // croak "Unrecognised hex value $val";
167 0 0         $self->write_raw( $digit, $bits + ( $dp ? 0x80 : 0 ) );
168             }
169              
170             =head2 $max->set_decode( $bits )->get
171              
172             Directly sets the decode mode of all the digits at once. This is more
173             efficient for initialising digits into BCD or raw mode, than individual calls
174             to C or C for each digit individually.
175              
176             =cut
177              
178             sub set_decode
179             {
180 0     0 1   my $self = shift;
181 0           my ( $bits ) = @_;
182 0           $self->_writereg( REG_DECODE, $self->{decode} = $bits );
183             }
184              
185             =head2 $max->intensity( $value )->get
186              
187             Sets the intensity register. C<$value> must be between 0 and 15, with higher
188             values giving a more intense output.
189              
190             =cut
191              
192             sub intensity
193             {
194 0     0 1   my $self = shift;
195 0           $self->_writereg( REG_INTENSITY, @_ );
196             }
197              
198             =head2 $max->limit( $columns )->get
199              
200             Sets the scan limit register. C<$value> must be between 1 and 8, to set
201             between 1 and 8 digits. This should only be used to adjust for the number of
202             LED digits or columns units physically attached to the chip; not for normal
203             display blanking, as it affects the overall intensity.
204              
205             I that this is not directly the value written to the C register.
206              
207             =cut
208              
209             sub limit
210             {
211 0     0 1   my $self = shift;
212 0           my ( $columns ) = @_;
213 0 0 0       $columns >= 1 and $columns <= 8 or
214             croak "->limit columns must be between 1 and 8";
215              
216 0           $self->_writereg( REG_LIMIT, $columns - 1 );
217             }
218              
219             =head2 $max->shutdown( $off )->get
220              
221             Sets the shutdown register, entirely blanking the display and turning off all
222             output if set to a true value, or restoring the display to its previous
223             content if set false.
224              
225             I that this is not directly the value written to the C
226             register.
227              
228             =cut
229              
230             sub shutdown
231             {
232 0     0 1   my $self = shift;
233 0           my ( $off ) = @_;
234 0           $self->_writereg( REG_SHUTDOWN, !$off );
235             }
236              
237             =head2 $max->displaytest( $on )->get
238              
239             Sets the display test register, overriding the output control and turning on
240             every LED if set to a true value, or restoring normal operation if set to
241             false.
242              
243             =cut
244              
245             sub displaytest
246             {
247 0     0 1   my $self = shift;
248 0           my ( $on ) = @_;
249 0           $self->_writereg( REG_DTEST, $on );
250             }
251              
252             =head1 AUTHOR
253              
254             Paul Evans
255              
256             =cut
257              
258             while( ) {
259             my ( $hex, $segments ) = split m/=/;
260             my $bits = 0;
261             substr( $segments, $_, 1 ) eq "." and $bits += 1 << $_ for 0 .. 6;
262             $hex2bits{$hex} = $bits;
263             }
264              
265             0x55AA;
266              
267             __DATA__