File Coverage

blib/lib/Device/BusPirate/Chip/SSD1306.pm
Criterion Covered Total %
statement 12 37 32.4
branch 0 2 0.0
condition n/a
subroutine 4 22 18.1
pod 3 4 75.0
total 19 65 29.2


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, 2015 -- leonerd@leonerd.org.uk
5              
6             package Device::BusPirate::Chip::SSD1306;
7              
8 1     1   756 use strict;
  1         2  
  1         39  
9 1     1   4 use warnings;
  1         2  
  1         31  
10 1     1   12 use base qw( Device::BusPirate::Chip );
  1         1  
  1         462  
11              
12             our $VERSION = '0.01';
13              
14             =head1 NAME
15              
16             C - use a F OLED driver with C
17              
18             =head1 DESCRIPTION
19              
20             This abstract L subclass provides communication to an
21             F chip attached to the F. To actually use it, you should
22             use one of the subclasses for the various interface types.
23              
24             =over 4
25              
26             =item *
27              
28             L - I2C
29              
30             =item *
31              
32             L - 4-wire SPI
33              
34             =back
35              
36             The reader is presumed to be familiar with the general operation of this chip;
37             the documentation here will not attempt to explain or define chip-specific
38             concepts or features, only the use of this module to access them.
39              
40             =cut
41              
42             =head1 METHODS
43              
44             The following methods documented with a trailing call to C<< ->get >> return
45             L instances.
46              
47             =cut
48              
49             use constant {
50 1         602 CMD_SET_CONTRAST => 0x81, # , contrast
51             CMD_DISPLAY_LAMPTEST => 0xA4, # + all on
52             CMD_DISPLAY_INVERT => 0xA6, # + invert
53             CMD_DISPLAY_OFF => 0xAE, #
54             CMD_DISPLAY_ON => 0xAF, #
55              
56             CMD_SCROLL_RIGHT => 0x26, # , 0, start page, time, end page, 0, 0xff
57             CMD_SCROLL_LEFT => 0x27, # , 0, start page, time, end page, 0, 0xff
58             CMD_SCROLL_VERT_RIGHT => 0x29, # , 0, start page, time, end page, vertical
59             CMD_SCROLL_VERT_LEFT => 0x2A, # , 0, start page, time, end page, vertical
60             CMD_SCROLL_DEACTIVATE => 0x2E, #
61             CMD_SCROLL_ACTIVATE => 0x2F, #
62             CMD_SET_SCROLL_AREA => 0xA3, # , start row, scroll rows
63              
64             CMD_SET_LOW_COLUMN => 0x00, # + column
65             CMD_SET_HIGH_COLUMN => 0x10, # + column
66             CMD_SET_ADDR_MODE => 0x20, # , mode
67             MODE_HORIZONTAL => 0,
68             MODE_VERTICAL => 1,
69             MODE_PAGE => 2,
70             CMD_SET_COLUMN_ADDR => 0x21, # , start column, end column
71             CMD_SET_PAGE_ADDR => 0x22, # , start page, end page
72             CMD_SET_PAGE_START => 0xB0, # + page
73              
74             CMD_SET_DISPLAY_START => 0x40, # + line
75             CMD_SET_SEGMENT_REMAP => 0xA0, # + remap
76             CMD_SET_MUX_RATIO => 0xA8, # , mux
77             CMD_SET_COM_SCAN_DIR => 0xC0, # + direction(8)
78             CMD_SET_DISPLAY_OFFS => 0xD3, # , line offset
79             CMD_SET_COM_PINS => 0xDA, # , (config << 4) | 0x02
80              
81             CMD_SET_CLOCKDIV => 0xD5, # , (freq << 4) | (divratio)
82             CMD_SET_PRECHARGE => 0xD9, # , (ph1 << 4) | (ph2)
83             CMD_SET_VCOMH_LEVEL => 0xDB, # , (level << 4)
84             CMD_SET_CHARGEPUMP => 0x8D, # , 0x10 | (enable << 2)
85              
86             CMD_NOP => 0xE3,
87 1     1   353 };
  1         1  
88              
89             =head2 $ssd->init->get
90              
91             Initialise the display after reset to some sensible defaults.
92              
93             =cut
94              
95             # This initialisation sequence is inspired by the Adafruit driver
96             # https://github.com/adafruit/Adafruit_SSD1306
97              
98             sub init
99             {
100 0     0 0   my $self = shift;
101              
102             $self->display( 0 )
103 0     0     ->then( sub { $self->send_cmd( CMD_SET_CLOCKDIV, ( 8 << 4 ) | 0x80 ) })
104 0     0     ->then( sub { $self->send_cmd( CMD_SET_MUX_RATIO, 0x3F ) })
105 0     0     ->then( sub { $self->send_cmd( CMD_SET_DISPLAY_OFFS, 0 ) })
106 0     0     ->then( sub { $self->send_cmd( CMD_SET_DISPLAY_START | 0 ) })
107 0     0     ->then( sub { $self->send_cmd( CMD_SET_CHARGEPUMP, 0x14 ) })
108 0     0     ->then( sub { $self->send_cmd( CMD_SET_ADDR_MODE, MODE_HORIZONTAL ) })
109 0     0     ->then( sub { $self->send_cmd( CMD_SET_SEGMENT_REMAP | 1 ) })
110 0     0     ->then( sub { $self->send_cmd( CMD_SET_COM_SCAN_DIR | 0 ) })
111 0     0     ->then( sub { $self->send_cmd( CMD_SET_COM_PINS, 0 | 0x12 ) })
112 0     0     ->then( sub { $self->send_cmd( CMD_SET_CONTRAST, 0x9F ) })
113 0     0     ->then( sub { $self->send_cmd( CMD_SET_PRECHARGE, ( 0x0f << 4 ) | ( 1 ) ) })
114 0     0     ->then( sub { $self->send_cmd( CMD_SET_VCOMH_LEVEL, ( 4 << 4 ) ) });
  0            
115             }
116              
117             =head2 $ssd->display( $on )->get
118              
119             Turn on or off the display.
120              
121             =cut
122              
123             sub display
124             {
125 0     0 1   my $self = shift;
126 0           my ( $on ) = @_;
127 0 0         $self->send_cmd( $on ? CMD_DISPLAY_ON : CMD_DISPLAY_OFF );
128             }
129              
130             =head2 $ssd->display_lamptest( $enable )->get
131              
132             Turn on or off the all-pixels-lit lamptest mode.
133              
134             =cut
135              
136             sub display_lamptest
137             {
138 0     0 1   my $self = shift;
139 0           my ( $enable ) = @_;
140              
141 0           $self->send_cmd( CMD_DISPLAY_LAMPTEST + !!$enable );
142             }
143              
144             =head2 $ssd->send_display( $pixels )->get
145              
146             Sends an entire screen-worth of pixel data. The C<$pixels> should be in a
147             packed binary string 128 * 8 bytes long.
148              
149             =cut
150              
151             sub send_display
152             {
153 0     0 1   my $self = shift;
154 0           my ( $pixels ) = @_;
155              
156             $self->send_cmd( CMD_SET_COLUMN_ADDR, 0, 127 )
157 0     0     ->then( sub { $self->send_cmd( CMD_SET_PAGE_ADDR, 0, 7 ) })
158 0     0     ->then( sub { $self->send_data( $pixels ) })
159 0           }
160              
161             =head1 TODO
162              
163             =over 4
164              
165             =item *
166              
167             More interfaces - I2C and 3-wire SPI
168              
169             =item *
170              
171             Maintain a framebuffer. Add some drawing commands like pixels and lines.
172              
173             =back
174              
175             =cut
176              
177             =head1 AUTHOR
178              
179             Paul Evans
180              
181             =cut
182              
183             0x55AA;