File Coverage

blib/lib/HiPi/Interface/LCDBackpackPCF8574.pm
Criterion Covered Total %
statement 24 84 28.5
branch 0 14 0.0
condition n/a
subroutine 8 19 42.1
pod 0 7 0.0
total 32 124 25.8


line stmt bran cond sub pod time code
1             #########################################################################################
2             # Package HiPi::Interface::LCDBackpackPCF8574
3             # Description : PCF8574 Backpack LCD Controller
4             # Copyright : Copyright (c) 2017 Mark Dootson
5             # License : This is free software; you can redistribute it and/or modify it under
6             # the same terms as the Perl 5 programming language system itself.
7             #########################################################################################
8              
9             package HiPi::Interface::LCDBackpackPCF8574;
10              
11             #########################################################################################
12              
13 1     1   1065 use strict;
  1         2  
  1         31  
14 1     1   5 use warnings;
  1         3  
  1         27  
15 1     1   6 use parent qw( HiPi::Interface::Common::HD44780 );
  1         2  
  1         4  
16 1     1   56 use Carp;
  1         3  
  1         50  
17 1     1   19 use HiPi qw( :rpi :lcd :i2c );
  1         2  
  1         460  
18 1     1   9 use HiPi::RaspberryPi;
  1         4  
  1         15  
19 1     1   500 use HiPi::Interface::PCF8574;
  1         3  
  1         114  
20              
21             our $VERSION ='0.81';
22              
23             __PACKAGE__->create_accessors( qw( address devicename backend _backlight ) );
24              
25             use constant {
26 1         1138 LCD_CLEARDISPLAY => 0x01,
27             LCD_RETURNHOME => 0x02,
28             LCD_ENTRYMODESET => 0x04,
29             LCD_DISPLAYCONTROL => 0x08,
30             LCD_CURSORSHIFT => 0x10,
31             LCD_FUNCTIONSET => 0x20,
32             LCD_SETCGRAMADDR => 0x40,
33             LCD_SETDDRAMADDR => 0x80,
34              
35             ## for display entry mode
36             LCD_ENTRYRIGHT => 0x00,
37             LCD_ENTRYLEFT => 0x02,
38             LCD_ENTRYSHIFTINCREMENT => 0x01,
39             LCD_ENTRYSHIFTDECREMENT => 0x00,
40              
41             ## for display on/off control
42             LCD_DISPLAYON => 0x04,
43             LCD_DISPLAYOFF => 0x00,
44             LCD_CURSORON => 0x02,
45             LCD_CURSOROFF => 0x00,
46             LCD_BLINKON => 0x01,
47             LCD_BLINKOFF => 0x00,
48              
49             ## for display/cursor shift
50             LCD_DISPLAYMOVE => 0x08,
51             LCD_CURSORMOVE => 0x00,
52             LCD_MOVERIGHT => 0x04,
53             LCD_MOVELEFT => 0x00,
54              
55             ## for function set
56             LCD_8BITMODE => 0x10,
57             LCD_4BITMODE => 0x00,
58             LCD_2LINE => 0x08,
59             LCD_1LINE => 0x00,
60             LCD_5x10DOTS => 0x04,
61             LCD_5x8DOTS => 0x00,
62            
63             ##
64             SEND_MODE_CMD => 0,
65             SEND_MODE_DATA => 1,
66             SEND_ENABLE => 4,
67             SEND_DISABLE => 0,
68             SEND_BACKLIGHT => 8,
69 1     1   9 };
  1         2  
70              
71             sub new {
72 0     0 0   my( $class, %userparams) = @_;
73            
74 0           my $pi = HiPi::RaspberryPi->new();
75            
76 0 0         my %params = (
77             # LCD
78             width => undef,
79             lines => undef,
80             backlightcontrol => 1,
81             device => undef,
82             positionmap => undef,
83             serialbuffermode => 0,
84            
85             # i2c params
86             address => 0x3F,
87             devicename => ( $pi->board_type == RPI_BOARD_TYPE_1 ) ? '/dev/i2c-0' : '/dev/i2c-1',
88             backend => 'i2c',
89             );
90            
91             # get user params
92 0           foreach my $key( keys (%userparams) ) {
93 0           $params{$key} = $userparams{$key};
94             }
95            
96 0 0         unless( defined($params{device}) ) {
97             $params{device} = HiPi::Interface::PCF8574->new(
98             devicename => $params{devicename},
99             address => $params{address},
100             backend => $params{backend},
101 0           );
102             }
103            
104 0           my $self = $class->SUPER::new(%params);
105 0           return $self;
106             }
107              
108             sub send_text {
109 0     0 0   my($self, $text) = @_;
110 0           for my $p ( split(//, $text) ) {
111 0           $self->_send_data( ord($p) );
112             }
113             }
114              
115             sub send_command {
116 0     0 0   my($self, $command) = @_;
117 0           my $lsb = $command & 0x0F;
118 0           my $msb = ( $command >> 4 ) & 0x0F;
119 0           $self->_write_command_part($msb);
120 0           $self->_write_command_part($lsb);
121             }
122              
123             sub _send_data {
124 0     0     my($self, $data) = @_;
125 0           my $lsb = $data & 0x0F;
126 0           my $msb = ( $data >> 4 ) & 0x0F;
127 0           $self->_write_data_part($msb);
128 0           $self->_write_data_part($lsb);
129             }
130              
131             sub backlight {
132 0     0 0   my($self, $brightness) = @_;
133            
134 0 0         $brightness = 0 if $brightness < 0;
135 0 0         $brightness = 100 if $brightness > 100;
136            
137             # $brightness = 0 to 100
138             # we translate to 0 - 250
139            
140 0 0         return unless $self->backlightcontrol;
141            
142 0           my $bset = int( 2.5 * $brightness);
143 0           $self->_backlight( $bset );
144 0           $self->_write_to_bus(0x00, SEND_MODE_DATA, SEND_DISABLE );
145             }
146              
147             sub update_baudrate {
148 0     0 0   my $self = shift;
149             # not handled
150 0           return;
151             }
152              
153             sub update_geometry {
154 0     0 0   my $self = shift;
155             # not handled
156 0           return;
157             }
158              
159             sub _write_command_part {
160 0     0     my($self, $data) = @_;
161 0           $self->_write_to_bus( $data, SEND_MODE_CMD, SEND_ENABLE );
162 0           $self->delayMicroseconds(1);
163 0           $self->_write_to_bus( $data, SEND_MODE_CMD, SEND_DISABLE );
164 0           $self->delayMicroseconds(40);
165             }
166              
167             sub _write_data_part {
168 0     0     my($self, $data) = @_;
169 0           $self->_write_to_bus( $data, SEND_MODE_DATA, SEND_ENABLE );
170 0           $self->delayMicroseconds(1);
171 0           $self->_write_to_bus( $data, SEND_MODE_DATA, SEND_DISABLE );
172 0           $self->delayMicroseconds(40);
173             }
174              
175             sub _write_to_bus {
176 0     0     my($self, $data, $mode, $onoff) = @_;
177 0           my $byte = $data << 4;
178 0           $byte |= ( $mode & 1 );
179 0 0         $byte |= SEND_ENABLE if $onoff;
180 0 0         $byte |= SEND_BACKLIGHT if $self->_backlight;
181 0           $self->device->write_byte( $byte );
182             }
183              
184             sub init_display {
185 0     0 0   my $self = shift;
186            
187 0           $self->_write_to_bus(0, 0, 0);
188 0           $self->delay(50);
189            
190             # put the LCD into 4 bit mode according to the hitachi HD44780 datasheet figure 26, pg 47
191 0           $self->_write_command_part(0x03);
192 0           $self->delayMicroseconds(4500);
193 0           $self->_write_command_part(0x03);
194 0           $self->delayMicroseconds(4500);
195 0           $self->_write_command_part(0x03);
196 0           $self->delayMicroseconds(150);
197 0           $self->_write_command_part(0x02);
198            
199 0           $self->send_command( HD44780_CURSOR_OFF );
200             }
201              
202             1;
203              
204             __END__