File Coverage

blib/lib/HiPi/Interface/EPaper/DisplayBuffer.pm
Criterion Covered Total %
statement 21 120 17.5
branch 0 58 0.0
condition 0 49 0.0
subroutine 7 17 41.1
pod 0 9 0.0
total 28 253 11.0


line stmt bran cond sub pod time code
1             #########################################################################################
2             # Package HiPi::Interface::EPaper
3             # Description : Control Monochrome EPaper displays
4             # Copyright : Copyright (c) 2018 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::EPaper::DisplayBuffer;
10              
11             #########################################################################################
12              
13 1     1   9 use strict;
  1         3  
  1         35  
14 1     1   8 use warnings;
  1         2  
  1         32  
15 1     1   5 use parent qw( HiPi::Graphics::DrawingContext );
  1         2  
  1         5  
16 1     1   108 use Carp;
  1         9  
  1         71  
17 1     1   8 use HiPi qw( :epaper );
  1         2  
  1         194  
18 1     1   7 use Try::Tiny;
  1         2  
  1         1236  
19              
20             __PACKAGE__->create_ro_accessors( qw(
21             device_height device_width buffers buffer_bytes
22             frame_1_bpp frame_2_bpp
23             frame_1_type frame_2_type
24             frame_invert
25             invert_draw offsetx
26             colour_frame black_frame
27             ) );
28              
29             __PACKAGE__->create_accessors( qw( pen rotation ) );
30              
31             our $VERSION ='0.81';
32              
33             sub new {
34 0     0 0   my( $class, %params) = @_;
35 0   0       $params{pen} //= EPD_BLACK_PEN;
36 0   0       $params{rotation} //= EPD_BLACK_PEN;
37 0           $params{frame_invert} = [ $params{frame_1_invert}, $params{frame_2_invert} ];
38 0           my $bytecount = $params{device_height} * ( $params{device_width} + $params{offsetx} );
39 0           $bytecount >>= 3;
40            
41            
42 0           $params{buffers} = [ [], [] ];
43            
44 0 0         if( $params{frame_1_type} != EPD_FRAME_TYPE_UNUSED ) {
45 0 0         my $mask = ( $params{frame_1_invert} ) ? 0 : 0xFF;
46 0           my @data = ( $mask ) x $bytecount;
47 0           $params{buffers}->[0] = \@data;
48             }
49            
50 0 0         if( $params{frame_2_type} != EPD_FRAME_TYPE_UNUSED ) {
51 0 0         my $mask = ( $params{frame_2_invert} ) ? 0 : 0xFF;
52 0           my @data = ( $mask ) x $bytecount;
53 0           $params{buffers}->[1] = \@data;
54             }
55            
56 0           $params{buffer_bytes} = $bytecount;
57            
58             # colour frame & black frame
59 0           $params{black_frame} = 0;
60 0           $params{colour_frame} = 0;
61            
62 0 0         if( $params{frame_1_type} == EPD_FRAME_TYPE_COLOUR ) {
    0          
63 0           $params{colour_frame} = 1;
64             } elsif($params{frame_2_type} == EPD_FRAME_TYPE_COLOUR ) {
65 0           $params{colour_frame} = 2;
66             }
67            
68 0 0         if( $params{frame_1_type} == EPD_FRAME_TYPE_BLACK ) {
    0          
69 0           $params{black_frame} = 1;
70             } elsif($params{frame_2_type} == EPD_FRAME_TYPE_BLACK ) {
71 0           $params{black_frame} = 2;
72             }
73            
74 0   0       $params{colour_frame} ||= $params{black_frame};
75            
76 0           my $self = $class->SUPER::new( %params );
77 0           return $self;
78             }
79              
80             sub clear_buffer {
81 0     0 0   my ($self, $frame) = @_;
82            
83 0 0         if( $frame ) {
84 0 0         my $mask = ( $self->frame_invert->[$frame] ) ? 0 : 0xFF;
85 0           for (my $i = 0; $i < @{ $self->buffers->[$frame] }; $i ++) {
  0            
86 0           $self->buffers->[$frame]->[$i] = $mask;
87             }
88             } else {
89 0           for my $frameno ( (0, 1) ) {
90 0           my $buffer = $self->buffers->[$frameno];
91 0 0         my $mask = ( $self->frame_invert->[$frameno] ) ? 0 : 0xFF;
92 0           for (my $i = 0; $i < @$buffer; $i ++) {
93 0           $buffer->[$i] = $mask;
94             }
95             }
96             }
97 0           return;
98             }
99              
100             sub draw_pixel {
101 0     0 0   my($self, $x, $y ) = @_;
102            
103 0           my $frametype = 0;
104 0 0         if( $self->pen == EPD_COLOUR_PEN ) {
105 0           $frametype = $self->colour_frame;
106             } else {
107 0           $frametype = $self->black_frame;
108             }
109 0 0         return unless $frametype;
110            
111 0           my $frame = $frametype - 1;
112            
113 0           my $inverted = $self->frame_invert->[$frame];
114            
115 0           my $maxX = $self->device_width + $self->offsetx;
116 0           my $adjH = $self->device_height -1;
117 0           my $adjW = $self->device_width -1;
118            
119             # rotate and check for bounds
120 0 0         if ($self->rotation == EPD_ROTATION_0 ) {
    0          
    0          
    0          
121 0 0 0       if($x < 0 || $x >= $self->device_width || $y < 0 || $y >= $self->device_height) {
      0        
      0        
122 0           return;
123             }
124             } elsif ($self->rotation == EPD_ROTATION_90) {
125 0 0 0       if($x < 0 || $x >= $self->device_height || $y < 0 || $y >= $self->device_width) {
      0        
      0        
126 0           return;
127             }
128 0           my $swap = $x;
129 0           $x = $adjW - $y;
130 0           $y = $swap;
131             } elsif ($self->rotation == EPD_ROTATION_180) {
132 0 0 0       if($x < 0 || $x >= $self->device_width || $y < 0 || $y >= $self->device_height) {
      0        
      0        
133 0           return;
134             }
135 0           $x = $adjW - $x;
136 0           $y = $adjH - $y;
137             } elsif ($self->rotation == EPD_ROTATION_270) {
138 0 0 0       if($x < 0 || $x >= $self->device_height || $y < 0 || $y >= $self->device_width) {
      0        
      0        
139 0           return;
140             }
141 0           my $swap = $x;
142 0           $x = $y;
143 0           $y = $adjH - $swap;
144             }
145            
146 0           my $index = ($x + $y * $maxX) >> 3;
147 0           my $shiftbits = $x % 8;
148 0           my $buffer = $self->buffers->[$frame];
149            
150 0 0         my $on = ( $self->pen ) ? 1 : 0;
151            
152 0 0         if($self->pen_inverted) {
153 0 0         $on = ( $on ) ? 0 : 1;
154             }
155            
156 0 0         if( $inverted ) {
157 0 0         if ($on) {
158 0           $buffer->[$index] |= 0x80 >> $shiftbits;
159             } else {
160 0           $buffer->[$index] &= ~(0x80 >> $shiftbits);
161             }
162             } else {
163 0 0         if ($on) {
164 0           $buffer->[$index] &= ~(0x80 >> $shiftbits);
165             } else {
166 0           $buffer->[$index] |= 0x80 >> $shiftbits;
167             }
168             }
169            
170 0           return;
171             }
172              
173             sub set_pen {
174 0     0 0   my($self, $newpen) = @_;
175 0           my $oldpen = $self->pen;
176 0           $self->pen( $newpen );
177 0           return $oldpen;
178             }
179              
180             sub logical_width {
181 0     0 0   my $self = shift;
182 0 0 0       if( $self->rotation == EPD_ROTATION_90 || $self->rotation == EPD_ROTATION_270 ) {
183 0           return $self->device_height;
184             } else {
185 0           return $self->device_width;
186             }
187             }
188              
189             sub logical_height {
190 0     0 0   my $self = shift;
191 0 0 0       if( $self->rotation == EPD_ROTATION_90 || $self->rotation == EPD_ROTATION_270 ) {
192 0           return $self->device_width;
193             } else {
194 0           return $self->device_height;
195             }
196             }
197              
198             # noops for buffer contexts
199              
200 0     0 0   sub rotate { carp q(you cannot call 'rotate' on a display context); }
201              
202 0     0 0   sub rotated_text { carp q(you cannot call 'rotate_text' on a display context); }
203              
204 0     0 0   sub clear_context { carp q(you cannot call 'clear_context' on a display context); }
205              
206              
207             #########################################################################################
208              
209             package HiPi::Interface::EPaper::PartialContext;
210              
211             #########################################################################################
212              
213 1     1   16 use base qw( HiPi::Interface::EPaper::DisplayBuffer );
  1         2  
  1         276  
214              
215             sub new {
216 0     0     my($class, %params) = @_;
217 0           my $self = $class->SUPER::new( %params );
218 0           return $self;
219             }
220              
221             1;
222              
223             __END__