File Coverage

blib/lib/HiPi/Interface/MonoOLED.pm
Criterion Covered Total %
statement 30 245 12.2
branch 0 76 0.0
condition 0 57 0.0
subroutine 10 48 20.8
pod 0 31 0.0
total 40 457 8.7


line stmt bran cond sub pod time code
1             #########################################################################################
2             # Package HiPi::Interface::MonoOLED
3             # Description : Control Monochrome OLEDs
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::MonoOLED;
10              
11             #########################################################################################
12 1     1   1761 use utf8;
  1         15  
  1         6  
13 1     1   34 use strict;
  1         3  
  1         20  
14 1     1   5 use warnings;
  1         2  
  1         28  
15 1     1   5 use parent qw( HiPi::Interface );
  1         1  
  1         5  
16 1     1   66 use HiPi qw( :i2c :rpi :spi :oled );
  1         2  
  1         389  
17 1     1   7 use Carp;
  1         9  
  1         70  
18 1     1   7 use HiPi::Graphics::BitmapFont;
  1         1  
  1         48  
19 1     1   6 use HiPi::Graphics::DrawingContext;
  1         3  
  1         34  
20 1     1   482 use HiPi::Interface::MonoOLED::DisplayBuffer;
  1         2  
  1         148  
21              
22             __PACKAGE__->create_ro_accessors( qw(
23             backend spidriver rows cols col_offset
24             reset_pin dc_pin external_power flipped type controller
25             chunk_data buffer_rows
26             ) );
27              
28             __PACKAGE__->create_accessors( qw( context gpio ) );
29              
30             our $VERSION ='0.81';
31              
32             use constant {
33 1         3681 CONTROL_CONTINUE => 0x80,
34             CONTROL_COMMAND => 0x00,
35             CONTROL_DATA => 0x40,
36            
37             TYPE_CONTROL_SSD1306 => 0x01,
38             TYPE_CONTROL_SH1106 => 0x02,
39             TYPE_COLUMNS_128 => 0x04,
40             TYPE_ROWS_64 => 0x08,
41             TYPE_ROWS_32 => 0x10,
42             TYPE_BUS_I2C => 0x20,
43             TYPE_BUS_SPI => 0x40,
44             TYPE_COLUMNS_256 => 0x80,
45             TYPE_CONTROL_SSD1322 => 0x100,
46            
47             OLED_SETCONTRAST => 0x81,
48             OLED_DISPLAYALLON_RESUME => 0xA4,
49             OLED_DISPLAYALLON => 0xA5,
50             OLED_NORMALDISPLAY => 0xA6,
51             OLED_INVERTDISPLAY => 0xA7,
52             OLED_DISPLAYOFF => 0xAE,
53             OLED_DISPLAYON => 0xAF,
54              
55             OLED_SETDISPLAYOFFSET => 0xD3,
56             OLED_SETCOMPINS => 0xDA,
57              
58             OLED_SETVCOMDETECT => 0xDB,
59              
60             OLED_SETDISPLAYCLOCKDIV => 0xD5,
61             OLED_SETPRECHARGE => 0xD9,
62              
63             OLED_SETMULTIPLEX => 0xA8,
64              
65             OLED_SETSTARTLINE => 0x40,
66              
67             SSD1306_MEMORYMODE => 0x20,
68             SSD1306_COLUMNADDR => 0x21,
69            
70             SH1106_SETLOWCOLUMN => 0x00,
71             SH1106_SETHIGHCOLUMN => 0x10,
72            
73             SSD1306_PAGEADDR => 0x22,
74             SH1106_PAGEADDR => 0xB0,
75              
76             OLED_COMSCANINC => 0xC0,
77             OLED_COMSCANDEC => 0xC8,
78              
79             OLED_SEGREMAP => 0xA0,
80              
81             OLED_CHARGEPUMP => 0x8D,
82              
83             OLED_EXTERNALVCC => 0x1,
84             OLED_SWITCHCAPVCC => 0x2,
85            
86             SSD1306_ACTIVATE_SCROLL => 0x2F,
87             SSD1306_DEACTIVATE_SCROLL => 0x2E,
88             SSD1306_SET_VERTICAL_SCROLL_AREA => 0xA3,
89             SSD1306_RIGHT_HORIZONTAL_SCROLL => 0x26,
90             SSD1306_LEFT_HORIZONTAL_SCROLL => 0x27,
91             SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL => 0x29,
92             SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL => 0x2A,
93              
94             SSD1306_MEMORY_MODE_HORIZ => 0x00,
95             SSD1306_MEMORY_MODE_VERT => 0x01,
96             SSD1306_MEMORY_MODE_PAGE => 0x02,
97 1     1   7 };
  1         2  
98              
99              
100             sub new {
101 0     0 0   my ($class, %userparams) = @_;
102            
103 0           my %params = $class->_init_params( %userparams );
104            
105 0           my $self = $class->SUPER::new(%params);
106            
107 0           $self->context(
108             HiPi::Interface::MonoOLED::DisplayBuffer->new(
109             rows => $self->buffer_rows,
110             cols => $self->cols,
111             )
112             );
113            
114 0 0 0       $self->_set_gpio if(defined($self->dc_pin) || defined($self->reset_pin) );
115            
116 0 0         if(defined($self->dc_pin)) {
117 0 0         if( $self->gpio->get_pin_mode( $self->dc_pin ) != RPI_MODE_OUTPUT ) {
118 0           $self->gpio->set_pin_mode( $self->dc_pin, RPI_MODE_OUTPUT );
119             }
120 0           $self->gpio->set_pin_level( $self->dc_pin, RPI_LOW );
121             }
122            
123 0 0         if(defined($self->reset_pin)) {
124 0 0         if( $self->gpio->get_pin_mode( $self->reset_pin ) != RPI_MODE_OUTPUT ) {
125 0           $self->gpio->set_pin_mode( $self->reset_pin, RPI_MODE_OUTPUT );
126             }
127             }
128              
129 0 0         unless( $params{'skip_reset'} ) {
130 0           $self->display_reset;
131 0 0         unless( $params{'skip_logo'} ) {
132 0           $self->draw_logo;
133 0           $self->display_update;
134             }
135             }
136            
137 0           return $self;
138             }
139              
140             sub _init_params {
141 0     0     my( $class, %inparams ) = @_;
142 0           my $pi = HiPi::RaspberryPi->new();
143            
144 0 0         my %i2cparams = (
145             devicename => ( $pi->board_type == RPI_BOARD_TYPE_1 ) ? '/dev/i2c-0' : '/dev/i2c-1',
146             address => 0x3C,
147             device => undef,
148             reset_pin => undef,
149             chunk_data => 1,
150             );
151            
152 0           my %spiparams = (
153             devicename => '/dev/spidev0.0',
154             speed => SPI_SPEED_MHZ_1,
155             bitsperword => 8,
156             delay => 0,
157             device => undef,
158             reset_pin => undef,
159             dc_pin => undef,
160             );
161            
162 0   0       $inparams{type} //= SSD1306_128_X_64_I2C;
163 0           my $controltype = $inparams{type};
164            
165             # defaults
166 0           my %params = (
167             device => undef,
168             backend => 'i2c',
169             cols => 128,
170             rows => 64,
171             buffer_rows => 64,
172             col_offset => 0,
173             type => SSD1306_128_X_64_I2C,
174             controller => TYPE_CONTROL_SSD1306,
175             );
176            
177 0 0         $params{backend} = ( $controltype & TYPE_BUS_SPI ) ? 'spi' : 'i2c';
178             # $params{cols} = only support 128 type currently
179            
180 0 0         if( $controltype & TYPE_CONTROL_SH1106 ) {
181 0           $params{col_offset} = 2;
182 0           $params{controller} = TYPE_CONTROL_SH1106;
183             }
184            
185 0 0         $params{buffer_rows} = $params{rows} = ( $controltype & TYPE_ROWS_32 ) ? 32 : 64;
186            
187             # get user params
188 0           foreach my $key( keys (%inparams) ) {
189 0           $params{$key} = $inparams{$key};
190             }
191            
192             # fix any daft row figures
193 0 0         if( $params{rows} !~ /^32|64$/ ) {
194 0           $params{rows} = 64;
195             }
196 0 0         if( $params{buffer_rows} !~ /^32|64$/ ) {
197 0           $params{buffer_rows} = $params{rows};
198             }
199             # get backend params
200 0 0         if( $params{backend} eq 'spi' ) {
201 0           foreach my $key( keys %spiparams ) {
202 0   0       $params{$key} //= $spiparams{$key};
203             }
204             } else {
205 0           foreach my $key( keys %i2cparams ) {
206 0   0       $params{$key} //= $i2cparams{$key};
207             # set chunk_data for smbus / bcm2835
208 0 0         if($params{backend} eq 'i2c') {
209 0   0       $params{chunk_data} //= 0;
210             } else {
211 0   0       $params{chunk_data} //= 1;
212             }
213             }
214             }
215            
216 0 0         unless( defined($params{device}) ) {
217 0 0         if ( $params{backend} eq 'bcm2835' ) {
    0          
218 0           require HiPi::BCM2835::I2C;
219             $params{device} = HiPi::BCM2835::I2C->new(
220             address => $params{address},
221 0 0         peripheral => ( $params{devicename} eq '/dev/i2c-0' ) ? HiPi::BCM2835::I2C::BB_I2C_PERI_0() : HiPi::BCM2835::I2C::BB_I2C_PERI_1(),
222             );
223             } elsif( $params{backend} eq 'spi' ) {
224 0           require HiPi::Device::SPI;
225             $params{device} = HiPi::Device::SPI->new(
226             speed => $params{speed},
227             bitsperword => $params{bitsperword},
228             delay => $params{delay},
229             devicename => $params{devicename},
230 0           );
231             } else {
232 0           require HiPi::Device::I2C;
233             $params{device} = HiPi::Device::I2C->new(
234             devicename => $params{devicename},
235             address => $params{address},
236             busmode => $params{backend},
237 0           );
238             }
239             }
240            
241 0 0         $params{spidriver} = $params{device}->isa('HiPi::Device::SPI') ? 1 : 0;
242            
243 0           return %params;
244             }
245              
246             sub display_reset {
247 0     0 0   my $self = shift;
248            
249 0 0         if(defined($self->reset_pin)) {
250 0           $self->gpio->set_pin_level($self->reset_pin, RPI_LOW );
251 0           $self->delayMicroseconds(1000);
252 0           $self->gpio->set_pin_level($self->reset_pin, RPI_HIGH );
253 0           $self->delayMicroseconds(1000);
254             }
255            
256 0           $self->send_command(OLED_DISPLAYOFF);
257 0           $self->send_command(OLED_SETDISPLAYCLOCKDIV, 0x80);
258 0           $self->send_command(OLED_SETMULTIPLEX, $self->rows -1);
259 0           $self->send_command(OLED_SETDISPLAYOFFSET, 0x00);
260 0           $self->send_command(OLED_SETSTARTLINE | 0x0);
261 0 0         if ( $self->external_power ) {
262 0           $self->send_command(OLED_CHARGEPUMP, 0x10);
263             } else {
264 0           $self->send_command(OLED_CHARGEPUMP, 0x14);
265             }
266            
267 0 0         if( $self->controller == TYPE_CONTROL_SSD1306 ) {
268 0           $self->send_command( SSD1306_MEMORYMODE, SSD1306_MEMORY_MODE_HORIZ );
269             }
270            
271 0           $self->display_flip($self->flipped);
272            
273 0 0         if( $self->rows == 64 ) {
274 0           $self->send_command(OLED_SETCOMPINS, 0x12);
275             } else {
276 0           $self->send_command(OLED_SETCOMPINS, 0x02);
277             }
278            
279 0           $self->send_command(OLED_SETCONTRAST, 0x7f);
280            
281 0 0         if ( $self->external_power ) {
282 0           $self->send_command(OLED_SETPRECHARGE, 0x22);
283             } else {
284 0           $self->send_command(OLED_SETPRECHARGE, 0xF1);
285             }
286            
287 0           $self->send_command(OLED_SETVCOMDETECT, 0x40);
288 0           $self->send_command(OLED_DISPLAYALLON_RESUME);
289 0           $self->send_command(OLED_NORMALDISPLAY);
290 0 0         if( $self->controller == TYPE_CONTROL_SSD1306 ) {
291 0           $self->send_command(SSD1306_DEACTIVATE_SCROLL);
292             }
293 0           $self->clear_buffer;
294 0           $self->display_update;
295 0           $self->send_command(OLED_DISPLAYON);
296            
297 0           return;
298             }
299              
300             sub _set_gpio {
301 0     0     my $self = shift;
302 0 0 0       unless( defined( $self->gpio ) && $self->gpio->isa('HiPi::GPIO') ) {
303 0           require HiPi::GPIO;
304 0           $self->gpio( HiPi::GPIO->new );
305             }
306             }
307              
308             sub send_command {
309 0     0 0   my($self, @bytes) = @_;
310 0 0         if( $self->spidriver ) {
311 0           $self->_spi_send_command( @bytes );
312             } else {
313 0           $self->_i2c_send_command( @bytes );
314             }
315             }
316              
317             sub send_data {
318 0     0 0   my($self, @bytes) = @_;
319 0 0         if( $self->spidriver ) {
320 0           $self->_spi_send_data( @bytes );
321             } else {
322 0           $self->_i2c_send_data( @bytes );
323             }
324             }
325              
326             sub _spi_send_command {
327 0     0     my($self, @commands) = @_;
328 0           $self->gpio->set_pin_level( $self->dc_pin, RPI_LOW );
329 0           $self->delayMicroseconds(10);
330 0           $self->device->transfer( pack('C*', @commands ) );
331 0           return;
332             }
333              
334             sub _spi_send_data {
335 0     0     my($self, @data) = @_;
336 0           $self->gpio->set_pin_level( $self->dc_pin, RPI_HIGH );
337 0           $self->delayMicroseconds(10);
338 0           $self->device->transfer( pack('C*', @data ) );
339 0           return;
340             }
341              
342             sub _i2c_send_command {
343 0     0     my($self, @bytes) = @_;
344 0           my $bytecount = scalar @bytes;
345 0 0         return unless $bytecount;
346            
347 0           for ( my $i = 0; $i < $bytecount; $i ++ ) {
348 0           $self->device->bus_write( CONTROL_COMMAND, $bytes[$i] );
349             }
350             }
351              
352             sub _i2c_send_data {
353 0     0     my($self, @bytes) = @_;
354            
355             # set chunk size based on backend
356 0 0         my $chunksize = ( $self->chunk_data ) ? 16 : 0;
357              
358 0 0         if( $chunksize ) {
359            
360 0           my $numbytes = scalar @bytes;
361 0           my $chunks = int( $numbytes / $chunksize );
362 0           my $leftover = ( $numbytes % $chunksize );
363            
364 0           for (my $chunk = 0; $chunk < $chunks; $chunk ++ ) {
365 0           my $start = $chunk * $chunksize;
366 0           my $end = $start + $chunksize - 1;
367 0           $self->device->bus_write( CONTROL_DATA, @bytes[$start..$end] );
368             }
369            
370 0 0         if($leftover){
371 0           my $start = $chunks * $chunksize;
372 0           my $end = $start + $leftover - 1;
373 0           $self->device->bus_write( CONTROL_DATA, @bytes[$start..$end] );
374             }
375             } else {
376             # send it all at once
377 0           $self->device->bus_write( CONTROL_DATA, @bytes );
378             }
379            
380 0           return;
381             }
382              
383             sub clear_buffer {
384 0     0 0   my $self = shift;
385 0           $self->context->clear_buffer(0);
386             }
387              
388             sub fill_buffer {
389 0     0 0   my $self = shift;
390 0           $self->context->clear_buffer(0xFF);
391             }
392              
393             sub invert_display {
394 0     0 0   my $self = shift;
395 0           $self->send_command(OLED_INVERTDISPLAY);
396             }
397              
398             sub normal_display {
399 0     0 0   my $self = shift;
400 0           $self->send_command(OLED_NORMALDISPLAY);
401             }
402              
403             sub display_off {
404 0     0 0   my $self = shift;
405 0           $self->send_command(OLED_DISPLAYOFF);
406             }
407              
408             sub display_on {
409 0     0 0   my $self = shift;
410 0           $self->send_command(OLED_DISPLAYON);
411             }
412              
413             sub set_contrast {
414 0     0 0   my ($self, $contrast) = @_;
415 0           $self->send_command(OLED_SETCONTRAST, $contrast & 0xFF );
416             }
417              
418             sub set_start_line {
419 0     0 0   my($self, $line) = @_;
420 0 0 0       if( $line >= 0 && $line < $self->buffer_rows ) {
421 0           $self->send_command(OLED_SETSTARTLINE | $line);
422             }
423 0           return;
424             }
425              
426             sub create_context {
427 0     0 0   return HiPi::Graphics::DrawingContext->new;
428             }
429              
430             sub display_update {
431 0     0 0   my( $self ) = @_;
432 0           $self->block_update(0,0, $self->cols -1, $self->buffer_rows - 1);
433 0           return;
434             }
435              
436             sub block_update {
437 0     0 0   my ( $self, $x1, $y1, $x2, $y2 ) = @_;
438 0 0 0       if(
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
439             $x1 < 0 || $x1 >= $self->cols
440             || $x2 < 0 || $x2 >= $self->cols
441             || $y1 < 0 || $y1 >= $self->buffer_rows
442             || $y2 < 0 || $y2 >= $self->buffer_rows
443             || $y1 > $y2 || $x1 > $x2) {
444            
445 0           carp qq(block update parameters outside display bounds : $x1, $y1, $x2, $y2);
446 0           return;
447             }
448            
449 0           my $page_start = $y1 >> 3;
450 0           my $page_end = $y2 >> 3;
451 0           my $pagebytes = $self->cols;
452 0           my $colstart = $self->col_offset + $x1;
453 0           my $colend = $self->col_offset + $x2;
454 0           for (my $page = $page_start; $page <= $page_end; $page ++) {
455 0           $self->_set_ready_for_update( $page, $page, $colstart, $colend);
456 0           my $start = ($page * $pagebytes) + $x1;
457 0           my $end = $start + ( $x2 - $x1 );
458 0           $self->send_data( @{ $self->context->buffer }[$start..$end] );
  0            
459 0 0 0       if( $self->buffer_rows == 32 && $self->rows == 32 ) {
460             # repeat whole buffer
461 0           $self->_set_ready_for_update( $page + 4, $page + 4, $colstart, $colend);
462 0           $self->send_data( @{ $self->context->buffer }[$start..$end] );
  0            
463             }
464             }
465 0           return;
466             }
467              
468             sub _set_ready_for_update {
469 0     0     my($self, $page_start, $page_end, $col_start, $col_end ) = @_;
470 0 0         if( $self->controller == TYPE_CONTROL_SH1106 ) {
471 0           my $col_low = $col_start & 0x0F;
472 0           my $col_high = ($col_start >> 4) & 0x1F;
473 0           $self->send_command(SH1106_SETLOWCOLUMN | $col_low );
474 0           $self->send_command(SH1106_SETHIGHCOLUMN | $col_high );
475 0           $self->send_command(SH1106_PAGEADDR | $page_start );
476             } else {
477 0           $self->send_command(SSD1306_COLUMNADDR, $col_start, $col_end );
478 0           $self->send_command(SSD1306_PAGEADDR, $page_start, $page_end);
479             }
480 0           return;
481             }
482              
483             sub display_flip {
484 0     0 0   my($self, $flipped) = @_;
485 0   0       $flipped ||= 0;
486 0 0         if ( $flipped ) {
487 0           $self->send_command(OLED_SEGREMAP | 0x00);
488 0           $self->send_command(OLED_COMSCANINC);
489            
490             } else {
491 0           $self->send_command(OLED_SEGREMAP | 0x01);
492 0           $self->send_command(OLED_COMSCANDEC);
493             }
494 0           return;
495             }
496              
497             sub draw_logo {
498 0     0 0   my ($self, $x, $y) = @_;
499 0   0       $x ||= 0;
500 0   0       $y ||= 0;
501 0           my $raspberry = $self->get_logo;
502 0           $self->draw_rectangle( $x, $y, $x+127, $y+31);
503 0           $self->draw_text( $x+14, $y+4, 'Raspberry Pi', 'Sans12');
504 0           $self->draw_text( $x+37, $y+17, 'HiPi Perl','Sans12');
505 0           my $text = 'HiPi ' . $HiPi::VERSION;
506 0           $self->draw_text(22,40, $text, 'Sans20');
507 0           $self->draw_bit_array( $x+96, $y+4, $raspberry, 0 );
508             }
509              
510             sub get_logo {
511 0     0 0   my $raspberry = [
512             [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
513             [ 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0 ],
514             [ 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0 ],
515             [ 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0 ],
516             [ 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 ],
517            
518             [ 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0 ],
519             [ 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0 ],
520             [ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 ],
521             [ 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0 ],
522             [ 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0 ],
523            
524             [ 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0 ],
525             [ 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0 ],
526             [ 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0 ],
527             [ 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0 ],
528             [ 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0 ],
529            
530             [ 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0 ],
531             [ 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0 ],
532             [ 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0 ],
533             [ 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0 ],
534             [ 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0 ],
535            
536             [ 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 ],
537             [ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 ],
538             [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
539             ];
540            
541 0           return $raspberry;
542             }
543              
544             #---------------------------------------------------
545             # Context Interface
546             #---------------------------------------------------
547              
548 0     0 0   sub invert_pen { shift->context->invert_pen( @_ ); }
549              
550 0     0 0   sub draw_context { shift->context->draw_context( @_ ); }
551              
552 0     0 0   sub draw_pixel { shift->context->draw_pixel( @_ ); }
553              
554 0     0 0   sub draw_text { shift->context->draw_text( @_ ); }
555              
556 0     0 0   sub get_text_extents { shift->context->get_text_extents( @_ ); }
557              
558 0     0 0   sub draw_circle { shift->context->draw_circle( @_ ); }
559              
560 0     0 0   sub draw_ellipse { shift->context->draw_ellipse( @_ ); }
561              
562 0     0 0   sub draw_arc { shift->context->draw_arc( @_ ); }
563              
564 0     0 0   sub draw_rectangle { shift->context->draw_rectangle( @_ ); }
565              
566 0     0 0   sub draw_rounded_rectangle { shift->context->draw_rounded_rectangle( @_ ); }
567              
568 0     0 0   sub draw_line { shift->context->draw_line( @_ ); }
569              
570 0     0 0   sub draw_polygon { shift->context->draw_polygon( @_ ); }
571              
572 0     0 0   sub draw_bit_array { shift->context->draw_bit_array( @_ ); }
573              
574             #---------------------------------------------------
575             # Command Aliases
576             #---------------------------------------------------
577              
578             *HiPi::Interface::MonoOLED::update_display = \&display_update;
579              
580             1;
581              
582             __END__