HiPi

 view release on metacpan or  search on metacpan

lib/HiPi/Interface/EPaper.pm  view on Meta::CPAN

#########################################################################################
# Package        HiPi::Interface::EPaper
# Description  : Control Monochrome OLEDs
# Copyright    : Copyright (c) 2018 Mark Dootson
# License      : This is free software; you can redistribute it and/or modify it under
#                the same terms as the Perl 5 programming language system itself.
#########################################################################################

package HiPi::Interface::EPaper;

#########################################################################################
use strict;
use warnings;
use parent qw( HiPi::Interface );
use HiPi qw( :rpi :spi :epaper );
use Carp;
use UNIVERSAL::require;
use HiPi::Graphics::DrawingContext;
use HiPi::Interface::EPaper::DisplayBuffer;

__PACKAGE__->create_ro_accessors( qw(
    device_width device_height offsetx type rotation
    frame_1_bpp frame_2_bpp
    frame_1_type frame_2_type
    dc_pin reset_pin busy_pin gpio
    lut_vcom0 lut_vcom1 lut_w lut_b lut_g1 lut_g2 lut_red0 lut_red1
    lut_full lut_partial
    can_partial  busy_state
    frame_1_invert frame_2_invert
    spi_chunksize
    _in_deep_sleep is_tri_colour
    border_control
) );

__PACKAGE__->create_accessors( qw( context lut_state ) );

our $VERSION ='0.81';

sub new {
    my ($class, %userparams) = @_;
    
    my %params = (
        devicename   => '/dev/spidev0.0',
        speed        => SPI_SPEED_MHZ_1,
        bitsperword  => 8,
        delay        => 0,
        device       => undef,
        reset_pin    => undef,
        dc_pin       => undef,
        busy_pin     => undef,
        type         => undef,
        gpio         => undef,
        device_width => undef,
        device_height => undef,
        rotation     => undef,
        can_partial  => 0,
        lut_state    => EPD_UPD_MODE_FIXED,
        invert_draw  => 0,
        busy_state   => RPI_LOW,
        offsetx      => 0,
        spi_chunksize => 4096,
        
    );
     
    # get user params
    foreach my $key( keys (%userparams) ) {
        $params{$key} = $userparams{$key};
    }
    
    my $epaperclass;
    
    croak q(No valid 'type' parameter given) unless $params{type};
    
    if( $params{type} == EPD_WS_1_54_152_X_152_C ) {
        $epaperclass = 'HiPi::Interface::EPaper::Waveshare::EPD152X152';
        
    } elsif( $params{type} == EPD_WS_1_54_200_X_200_B ) {
        $epaperclass = 'HiPi::Interface::EPaper::Waveshare::EPD200X200B';
        
    } elsif( $params{type} == EPD_WS_1_54_200_X_200_A) {
        $epaperclass = 'HiPi::Interface::EPaper::Waveshare::EPD200X200';
        
    } elsif( $params{type} == EPD_WS_2_13_250_X_122_A ) {
        $epaperclass = 'HiPi::Interface::EPaper::Waveshare::EPD250X122';
    
    } elsif( $params{type} == EPD_WS_2_13_212_X_104_B ) {
        $epaperclass = 'HiPi::Interface::EPaper::Waveshare::EPD212X104';
    
    } elsif( $params{type} == EPD_WS_2_90_296_X_128_A ) {
        $epaperclass = 'HiPi::Interface::EPaper::Waveshare::EPD296X128';
    
    } elsif( $params{type} == EPD_WS_2_90_296_X_128_B ) {
        $epaperclass = 'HiPi::Interface::EPaper::Waveshare::EPD296X128B';
        
    } elsif( $params{type} == EPD_PIMORONI_INKY_PHAT_V2 ) {
        $epaperclass = 'HiPi::Interface::EPaper::Pimoroni::EPDInkyPHAT_V2';
    } else {
        croak q(No valid 'type' parameter given);
    }
    
    $epaperclass->use or die $@;
    
    my $self = $epaperclass->_create( %params );
    
    $self->context(
        HiPi::Interface::EPaper::DisplayBuffer->new(
            device_width    => $self->device_width,
            device_height   => $self->device_height,
            rotation        => $self->rotation,
            frame_1_bpp     => $self->frame_1_bpp,
            frame_2_bpp     => $self->frame_2_bpp,
            frame_1_type    => $self->frame_1_type,
            frame_2_type    => $self->frame_2_type,
            frame_1_invert  => $self->frame_1_invert,
            frame_2_invert  => $self->frame_2_invert,
            offsetx         => $self->offsetx,
        )
    );
    
    unless( $params{'skip_reset'} ) {
        $self->display_reset;
        #if( $params{'draw_logo'} ) {
        #    $self->draw_logo;
        #    $self->display_update;
        #}
    }
    
    return $self;
}

sub _create {
    my( $class, %params ) = @_;
    
    unless(defined($params{device})) {
        require HiPi::Device::SPI;
        $params{device} = HiPi::Device::SPI->new(
            speed        => $params{speed},
            bitsperword  => $params{bitsperword},
            delay        => $params{delay},
            devicename   => $params{devicename},
        );
    }
    
    unless(defined($params{gpio})) {
        require HiPi::GPIO;
        $params{gpio} = HiPi::GPIO->new
    }
    
    my $self = $class->SUPER::new( %params );
    
    # init the GPIO settings;
    
    $self->gpio->set_pin_mode( $self->reset_pin, RPI_MODE_OUTPUT);
    $self->gpio->set_pin_mode( $self->dc_pin, RPI_MODE_OUTPUT);
    $self->gpio->set_pin_mode( $self->busy_pin, RPI_MODE_INPUT);
    
    return $self;
}

sub reset {
    my $self = shift;
    $self->gpio->set_pin_level( $self->reset_pin, RPI_LOW);
    $self->delay( 200 );
    $self->gpio->set_pin_level( $self->reset_pin, RPI_HIGH);
    $self->delay( 200 );
}

sub send_command {
    my( $self, $command, @data ) = @_;
    $self->gpio->set_pin_level( $self->dc_pin, RPI_LOW);
    $self->delayMicroseconds(10);
    $self->device->transfer( pack('C*', ( $command ) ) );
    if( @data ) {
        $self->send_data( @data );
    }
    return;
}

sub send_data {
    my($self, @data) = @_;
    $self->gpio->set_pin_level( $self->dc_pin, RPI_HIGH );
    $self->delayMicroseconds(10);
    $self->device->transfer( pack('C*', @data ) );
    return;
}

sub wait_for_idle {
    my $self = shift;
    while( $self->gpio->get_pin_level( $self->busy_pin ) == $self->busy_state ) {
        $self->delay(100);
    }
    return;
}

sub logical_width {
    my $self = shift;
    if( $self->rotation == EPD_ROTATION_90 || $self->rotation == EPD_ROTATION_270 ) {
        return $self->device_height;
    } else {
        return $self->device_width;
    }
}

sub logical_height {
    my $self = shift;
    if( $self->rotation == EPD_ROTATION_90 || $self->rotation == EPD_ROTATION_270 ) {
        return $self->device_width;
    } else {
        return $self->device_height;
    }
}

#----------------------------------------------------
# Common Type Methods
#----------------------------------------------------

sub display_reset {
    my $self = shift;
    carp 'display_reset not supported in this class';
}

sub display_update {
    my $self = shift;
    carp 'display_update not supported in this class';
}

#----------------------------------------------------
# Waveshare 2 & 3 col non partial methods
#----------------------------------------------------

sub set_lut_bw {
    my $self = shift;
    carp 'set_lut_bw not supported in this class';
}

sub set_lut_colour {
    my $self = shift;
    carp 'set_lut_colour not supported in this class';
}

#----------------------------------------------------
# Waveshare Partial Update Methods
#----------------------------------------------------

sub create_partial_context {
    my $self = shift;
    carp 'create_partial_context not supported in this class';
}



( run in 1.490 second using v1.01-cache-2.11-cpan-39bf76dae61 )