HiPi
Perl Modules for Raspberry Pi
Version 0.92 - released 28 March 2024

HiPi::Interface::MicroDotPHAT

This module provides an interface to the Pimoroni Micro Dot pHAT.

The interface is a Perl port of the Pimoroni Python library which is published under this Original Code License.

It uses HiPi::Device::IS31FL3730 to access the I2C IS31FL3730 LED drivers.

The Micro Dot pHAT contains 6 LTP-305 LED matrices each having 5 x 7 pixels giving an effective total display area of 30 x 7 pixels. Each matrix can also display a decimal point in its lower left corner.

The library creates a virtual buffer of unlimited size onto which you can write text and icons for scrolling around the Micro Dot pHAT display.

Methods are included for rotating and scrolling, plus writing text either kerned to one pixel spacing, or spaced to place one character per matrix.

Examples

( Ported python examples )

Methods

Create a new instance of HiPi::Interface::MicroDotPHAT

use HiPi::Interface::MicroDotPHAT;
my $phat = HiPi::Interface::MicroDotPHAT->new();

Write a string to the buffer. Returns the length, in pixels, of the written string.

  • $text: The text string to write
  • $x : Position the text along x (default 0)
  • $y : Position the text along y (default 0)
  • $kerning : Whether to kern the characters closely together or display one per matrix (default 1 == True). Set $kerning = 1 if you intend to scroll the text horizontally. Set to 0 if you want 1 character perl matrix.

# Write a string to the buffer, aligning one character per display, This is
# ideal for displaying still messages up to 6 characters long::

my $len = $phat->write_string("Bilge!", 0, 0, 0 );

# Write a string to buffer, with the characters as close together as possible.
# This is ideal for writing text which you intend to scroll::

$len = $phat->write_string("Hello World!");

Write a single character to the buffer.

  • $char: The character to write
  • $x : Position the text along x (default 0)
  • $y : Position the text along y (default 0)
# write characters A, B and C to first, second and third matrices

$phat->write_char( 'A', 0, 0 );
$phat->write_char( 'B', 5, 0 );
$phat->write_char( 'C', 10, 0 ); 

Output the buffer to the display

A copy of the buffer will be scrolled and rotated according to settings before being drawn to the display.

$phat->show();

Clears the buffer of all settings and resets to its startup size ( 30 x 7 pixels)

$phat->clear();

Draw tiny numbers to the buffer. Useful for drawing things like IP addresses. Can sometimes fit up to 3 digits on a single matrix.

  • $matrix: Index from 0 to 5 of the matrix to target
  • $text: the number to display
# write 25 in  tiny numbers to the second matrix
$phat->draw_tiny( 1, '25');

Set the state of a single pixel in the buffer. If the pixel falls outside the current buffer size, the buffer will be grown automatically.

  • $x: The x position of the pixel to set
  • $y: The y position of the pixel to set
  • $state: 1 or 0, == on or off ( default 1 )
$phat->set_pixel(13,5,1);

Set a whole column of the buffer. Only useful when not scrolling vertically

  • $x: The x position of the column to set
  • $columnbyte: An 8-bit integer, the 7 least significant bits correspond to each row
# set bottom 4 pixels in column 3 (index 2) to on
$phat->set_col( 2, 0b00001111 );
            
# set all pixels in column 3 (index 2) to on
$phat->set_col( 2, 0b01111111 );

Set the state of a decimal point

  • $matrix: Index from 0 to 5 of the matrix to target
  • $state: 1 or 0, set decimal point on or off
$phat->set_decimal( 3, 1);

Fill the entire current buffer setting all pixels on or off. Note, that unlike the 'clear' method, setting all pixels to 0 using 'fill' preserves buffer size and all other settings.

  • $state: 1 or 0, set all pixels on or off
$phat->fill ( 1 );

Set the display brightness.

  • $value: brightness setting between 0.0 and 1.0
$phat->set_brightness( 0.75 )

Scroll the buffer. Will scroll by 1 pixel horizontal if no arguments are supplied.

  • $x: amount to scroll in x direction
  • $y: amount to scroll in y direction
# scroll 1 pixel in x direction ( the default )
$phat->scroll();

# scroll 1 pixel in y direction
$phat->scroll( 0, 1 );

# scroll 1 pixel in both directions
$phat->scroll( 1, 1 );

Scroll the buffer horizontally by $amount

  • $amount: amount to scroll in x direction ( default 1 )
# scroll 1 pixel in x direction
$phat->scroll_horizontal( 1 );

Scroll the buffer vertically by $amount

  • $amount: amount to scroll in y direction ( default 1 )
# scroll 1 pixel in y direction
$phat->scroll_vertical( 1 );

Scroll buffer to given x, y position

  • $x: x position to scroll to
  • $y: y position to scroll to
$phat->scroll_to( 15, 12);

Set whether the display should be cleared on exit. Set this to 0 if you want to display a fixed message after your script exits. By default, the pHAT will be cleared when your script exits.

$phat->set_clear_on_exit( 0 );

Set whether the display should be flipped left to right (mirrored) when drawn

$phat->set_mirror( 1 );

Set whether the display should be rotated 180 degrees when drawn

$phat->set_rotate180( 1 );

Returns the current width of the buffer.

my $w = $phat->width();

Returns the current height of the buffer.

my $h = $phat->height();

Examples

The examples below are also part of the source distribution.

They are Perl ports of the original Python library examples.

Advanced Scrolling Example

Advanced scrolling example which displays a message line-by-line and then skips back to the beginning

#!/usr/bin/perl
use strict;
use warnings;

use HiPi::Interface::MicroDotPHAT;

my $phat = HiPi::Interface::MicroDotPHAT->new();

print q(Advanced Scrolling
Advanced scrolling example which displays a message line-by-line
and then skips back to the beginning.
Press Ctrl+C to exit.
);

my $rewind = 1;
my $delay = 30;

my $line_height = $phat->height + 2;
my $offset_left = 0;

my @lines = ("Fifteen men on the dead man's chest",
         "Yo ho ho, and a bottle of rum!",
         "Drink and the devil had done for the rest",
         "Yo ho ho, and a bottle of rum!",
         "But one man of her crew alive,",
         "Yo ho ho, and a bottle of rum!",
         "What put to sea with seventy-five",
         "Yo ho ho, and a bottle of rum!");

my $numlines = scalar( @lines );

my @lengths = ( 0 ) x $numlines;


for (my $i = 0; $i < @lines; $i ++ ) {
    $lengths[$i] = $phat->write_string( $lines[$i], $offset_left, $line_height * $i );
    $offset_left += $lengths[$i];
}

my $current_line = 0;
$phat->show;

while (1) {
    my $starttime = time;
    my $pos_x = 0;
    my $pos_y = 0;
    for ( my $current_line = 0; $current_line < $numlines; $current_line ++) {
        $phat->sleep_milliseconds( $delay * 10 );
        for (my $y = 0; $y < $lengths[$current_line]; $y ++) { 
            $phat->scroll(1,0);
            $pos_x += 1;
            $phat->sleep_milliseconds( $delay );
            $phat->show();
        }
        if ( $current_line == $numlines - 1 && $rewind ) {
            for ( my $y = 0; $y < $pos_y; $y ++ ) {
                $phat->scroll(- int($pos_x/$pos_y), - 1);
                $phat->show();
                $phat->sleep_milliseconds( $delay );
            }
            $phat->scroll_to(0,0);
            $phat->show();
            $phat->sleep_milliseconds( $delay );
            my $endtime = time;
            $starttime = time;
        } else {
            for (my $i = 0; $i < $line_height; $i++) {
                $phat->scroll(0,1);
                $pos_y += 1;
                $phat->show();
                $phat->sleep_milliseconds( $delay );
            }
        }
    }
    
}

1;
return to example list

Clock

Displays the time in hours, minutes and seconds

#!/usr/bin/perl
use strict;
use warnings;

use HiPi::Interface::MicroDotPHAT;

my $phat = HiPi::Interface::MicroDotPHAT->new();

print q(Clock
Displays the time in hours, minutes and seconds
Press Ctrl+C to exit.
);

my $offsetx = 0;
my $offsety = 0;
my $kerning = 0;

while(1) {
    $phat->clear();
    my($sec,$min,$hour) = localtime(time);
    if($sec % 2 == 0){
        $phat->set_decimal(2,1);
        $phat->set_decimal(4,1);
    } else {
        $phat->set_decimal(2,0);
        $phat->set_decimal(4,0);
    }
    $phat->write_string( sprintf('%02d%02d%02d', $hour, $min, $sec ), $offsetx ,$offsety, $kerning );
    $phat->show;
    $phat->sleep_milliseconds( 50 );
}

1;
return to example list

Fading text

Uses the brightness control to fade between messages.

#!/usr/bin/perl
use strict;
use warnings;

use HiPi::Interface::MicroDotPHAT;
use Time::HiRes ();

my $phat = HiPi::Interface::MicroDotPHAT->new();

print q(Fading Text
Uses the brightness control to fade between messages.
Press Ctrl+C to exit
);

my $speed = 5;
my @strings = ("One", "Two", "Three", "Four");
my $string = 0;
my $shown = 1;
$phat->show();

# Start time. Phase offset
my $start = Time::HiRes::time();

my $offsetx = 0;
my $offsety = 0;
my $kerning = 0;

while(1) {
    my $b = (sin((Time::HiRes::time() - $start) * $speed) + 1) / 2;
    $phat->set_brightness($b);
    
    if($b < 0.002 && $shown ) {
        $phat->clear();
        $phat->write_string($strings[$string], $offsetx, $offsety, $kerning);

        $string += 1;
        $string %=  scalar @strings;

        $phat->show();
        $shown = 0;
    }

    # At maximum brightness, confirm the string has been shown
    if ( $b > 0.998 ) {
        $shown = 1;
    }
    # Sleep a bit to save resources, this wont affect the fading speed
    $phat->sleep_milliseconds( 10 );
}

1;
return to example list

Flash

Flashes all the elements.

#!/usr/bin/perl
use strict;
use warnings;

use HiPi::Interface::MicroDotPHAT;

my $phat = HiPi::Interface::MicroDotPHAT->new();

print q(Flash
Flashes all the elements.
Press Ctrl+C to exit.
);

my $speed = 5;
my @strings = ("One", "Two", "Three", "Four");
my $string = 0;
my $shown = 1;
$phat->show();

my $t = 500;

while(1) {
    $phat->clear();
    $phat->show();
    $phat->sleep_milliseconds( $t );
    for(my $x = 0; $x < $phat->width; $x ++) {
        for (my $y = 0; $y < $phat->height; $y ++) {
            $phat->set_pixel($x,$y,1);
        }
    }
    for (my $x = 0; $x < 6; $x++ ) {
        $phat->set_decimal($x,1);
    }
    $phat->show();
    $phat->sleep_milliseconds( $t );
}

1;
return to example list

Graph

Plots random numbers scross the screen in a bar graph.

#!/usr/bin/perl
use strict;
use warnings;

use HiPi::Interface::MicroDotPHAT;

my $phat = HiPi::Interface::MicroDotPHAT->new();

print q(Graph
Plots random numbers scross the screen in a bar graph.
Press Ctrl+C to exit.
);

my @graph = ();
my $filled = 1;

while(1) {
    $phat->clear();
    push @graph, int(rand(7));
    
    while( @graph > 45 ) {
        shift @graph;
    }
    
    for (my $x = 0; $x < @graph; $x ++ ) {
        if ($filled ) {
            # bar graph
            $phat->set_col($x + ($phat->width- scalar @graph ), (
                0,
                0b1000000,
                0b1100000,
                0b1110000,
                0b1111000,
                0b1111100,
                0b1111110,
                0b1111111)[$graph[$x]] );
        } else {
            # plot
            $phat->set_col($x, 1 << ( 7 -  $graph[$x] ));
        }
    }

    $phat->show();
    $phat->sleep_milliseconds( 50 );
}

1;
return to example list

Scrolling Text

Scrolls a message across the screen.

#!/usr/bin/perl
use strict;
use warnings;

use HiPi::Interface::MicroDotPHAT;

my $phat = HiPi::Interface::MicroDotPHAT->new();

print q(Scrolling Text
Scrolls a message across the screen.
Usage: scrolling_text.pl "your message"
Press Ctrl+C to exit.
);

my $text = $ARGV[0] || "Fifteen men on the dead man's chest       ";

$phat->write_string( $text );

$phat->show;

while (1) {
    $phat->scroll;
    $phat->show;
    $phat->sleep_milliseconds( 50 );
}


1;
return to example list

Scrolling Word

Scrolls a word across the screen, one character per matrix

#!/usr/bin/perl
use strict;
use warnings;

use HiPi::Interface::MicroDotPHAT;

my $phat = HiPi::Interface::MicroDotPHAT->new();

print q(Scrolling Text
Scrolls a single word char by char across the screen.
Usage: scrolling_word.pl "your message"
Press Ctrl+C to exit.
);

my $text = $ARGV[0] || 'Perl';

my $charwidth = 5;
my $kerning = 0;

$phat->write_string( $text, 0, 0, $kerning );
$phat->show;

$phat->sleep_milliseconds( 500 );

while (1) {
    $phat->scroll( $charwidth );
    $phat->show();
    $phat->sleep_milliseconds( 500 );
}

1;
return to example list

Sine Wave

Displays a sine wave across your pHAT.

#!/usr/bin/perl
use strict;
use warnings;

use Time::HiRes ();
use HiPi::Interface::MicroDotPHAT;

my $phat = HiPi::Interface::MicroDotPHAT->new();

print q(Sine Wave
Displays a sine wave across your pHAT.
Press Ctrl+C to exit.
);

my $x = 0;

while (1) {
    $phat->clear();
    my $t = Time::HiRes::time() * 10;
    for ( my $x = 0; $x < $phat->width; $x ++) {
        my $y = int((sin($t + ($x/2.5)) + 1) * 3.5);
        $phat->set_pixel($x, $y, 1);
    }
    $phat->show();
    $phat->sleep_milliseconds( 50 );
}


1;
return to example list

Thermal

Displays the temperature measured from thermal zone 0, using /sys/class/thermal/thermal_zone0/temp

#!/usr/bin/perl
use strict;
use warnings;

use HiPi::Interface::MicroDotPHAT;

my $phat = HiPi::Interface::MicroDotPHAT->new();

print q(Thermal
Displays the temperature measured from thermal zone 0 using
/sys/class/thermal/thermal_zone0/temp
Press Ctrl+C to exit.
);

my $delay = 1000;
my $kerning = 0;

while(1) {
    $phat->clear();
    my $path = '/sys/class/thermal/thermal_zone0/temp';
    my $temp_raw = qx(cat $path);
    chomp( $temp_raw );
    my $temp = $temp_raw / 1000.0;
    $phat->write_string( sprintf('%.2fc', $temp ), 0, 0, $kerning );
    $phat->show;
    $phat->sleep_milliseconds( $delay );
}

1;
return to example list

Tiny Font

Displays an IP address in a tiny, tiny number font!

#!/usr/bin/perl
use strict;
use warnings;

use HiPi::Interface::MicroDotPHAT;

my $phat = HiPi::Interface::MicroDotPHAT->new();

print q(Tiny Font
Displays an IP address in a tiny, tiny number font!
Press Ctrl+C to exit.
);

my $x = 0;

while (1) {
    $phat->clear();
    $phat->draw_tiny(0,"192");
    $phat->draw_tiny(1,"178");
    $phat->draw_tiny(2,"0");
    $phat->draw_tiny(3,"68");
    $phat->draw_tiny(4, $x);

    $x++;
    $x = 0 if $x > 199;
    $phat->show();
    $phat->sleep_milliseconds( 100 );
}


1;
return to example list

Vertical Text

Scrolls text messages vertically.

#!/usr/bin/perl
use strict;
use warnings;

use HiPi::Interface::MicroDotPHAT;

my $phat = HiPi::Interface::MicroDotPHAT->new();

print q(Vertical Text
Scrolls text messages vertically.
Press Ctrl+C to exit.
);

my @lines = qw( One Two Three Four Five );

my $line_height = 7;

for(my $i = 0; $i < @lines; $i ++ ) {
    $phat->write_string( $lines[$i], 0, $i * $line_height, 0);
}
   
$phat->show;

while (1) {
    $phat->sleep_milliseconds( 1000 );
    my $iter = 0;
    while( $iter < $line_height ) {
        $iter++;
        $phat->scroll_vertical();
        $phat->show();
        $phat->sleep_milliseconds( 50 );
    }
}


1;
return to example list


Original Python Code Library License

MIT License

Copyright (c) 2017 Pimoroni Ltd.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.    
return to top