pi-lcd-0.1.1.0: Control an Adafruit character LCD and keypad kit on a Raspberry Pi

Copyright© Patrick Pelletier 2017
LicenseBSD3
Maintainercode@funwithsoftware.org
PortabilityLinux
Safe HaskellNone
LanguageHaskell2010

System.Hardware.PiLcd

Contents

Description

This module contains everything you need to use an Adafruit character LCD and keypad kit from Haskell. The kit has a 16x2 character LCD, an RGB backlight which can produce 8 possible colors, and five buttons: Up, Down, Left, Right, and Select.

Since the physical LCD+Keypad Kit is a global resource, only one PiLcd should exist at a time. (Except in the very exceptional case where you have more than one LCD+Keypad Kit connected to your Raspberry Pi, at different addresses on the I²C bus.) If you create more than one PiLcd at once when you only have one physical LCD+Keypad Kit, things will get very confused. Also, PiLcd is not threadsafe, so if you want to use the PiLcd from more than one thread, you will need to handle locking yourself.

However, PiLcd is safe in the presence of async exceptions. (In other words, updateDisplay and other operations will either atomically occur or not occur; they will not be interrupted in the middle and leave the hardware in an inconsistent state.)

Synopsis

Creating a PiLcd

openPiLcd :: LcdAddress -> LcdOptions -> IO PiLcd Source #

Opens the LCD+keypad kit, at the specified address, with the specified options.

closePiLcd :: PiLcd -> IO () Source #

Closes the PiLcd, leaving the display contents and backlight setting untouched.

turnOffAndClosePiLcd :: PiLcd -> IO () Source #

Like closePiLcd, but clears the display, turns off the display, and turns off the backlight before closing the PiLcd.

data PiLcd Source #

An opaque type representing an LCD and keypad kit.

data LcdAddress Source #

Specifies how to connect to the LCD+Keypad Kit. laBus should be 1 for revision 2 Raspberry Pis and later. For revision 1 Pis (those with 256 MB of RAM), the bus should be 0. If you need a way to automatically detect this, consider using the piBoardRev function in the wiringPi package. On the other hand, there is not much reason to ever change laAddr from the default 0x20. (The only reason would be if you changed the address of your LCD+Keypad Kit by messing with the address bit solder pads on the back. And probably the only reason you'd want to do that is to connect more than one LCD+Keypad Kit. That should work, in theory, but hasn't been tested.)

Constructors

LcdAddress 

Fields

  • laBus :: Int

    The I2C bus to communicate on

  • laAddr :: Int

    The address on that bus to find the LCD+keypad kit

defaultLcdAddress :: LcdAddress Source #

Default values for LcdAddress. Defaults to bus 1 and address 0x20.

data LcdOptions Source #

Specifies the characteristics of the LCD.

Constructors

LcdOptions 

Fields

data RomCode Source #

The HD44780U LCD controller comes in two different variants with different character ROMs. (See Table 4 on pages 17-18 of the HD44780U datasheet.) Unfortunately, as best as I can interpret this exchange with Adafruit customer support, Adafruit ships a mixture of A00 ROMs and A02 ROMs, depending on what's available at the moment. ("We take what's available or we don't sell LCDs.") This is a bit annoying, since there doesn't seem to be any way to query the HD44780U to find out which ROM it has. So, the user has to test their LCD and then specify which ROM they have.

Constructors

RomA00 
RomA02 

defaultLcdOptions :: LcdOptions Source #

Defaults to 2 lines, 16 columns, ROM code A00, and no additional custom characters.

Backlight color

The kit lacks PWM, so each of the red, green, and blue LEDs can be either on or off, yielding 8 possible colors.

data Color Source #

Colors for the LED backlight. If you have a single-color backlight, just use Off and White to turn it off and on.

Constructors

Off 
Red 
Green 
Blue 
Cyan 
Magenta 
Yellow 
White 

setBacklightColor :: PiLcd -> Color -> IO () Source #

Set the LED backlight to one of the eight possible Color values. If you have a single-color backlight, just use Off and White to turn it off and on.

Buttons

data ButtonDirection Source #

Indicates whether a button was pressed or released.

Constructors

Press 
Release 

Instances

Bounded ButtonDirection Source # 
Enum ButtonDirection Source # 
Eq ButtonDirection Source # 
Ord ButtonDirection Source # 
Read ButtonDirection Source # 
Show ButtonDirection Source # 

getButtonEvent :: PiLcd -> IO (Maybe ButtonEvent) Source #

If a button has been pressed or released since the last call to getButtonEvent, returns information on that press or release as a ButtonEvent.

getButtons :: PiLcd -> IO Word8 Source #

Returns all of the buttons which are currently depressed, as a bitwise "or" of buttonSelect, buttonRight, buttonDown, buttonUp, and buttonLeft.

Button bitmask values

Display

Displays Unicode text on the LCD. Only updates the parts of the LCD which have changed. Automatically manages custom characters, using the 5x8 fixed font for characters which are not built-in to the the LCD controller's ROM. Only eight distinct non-built-in characters can be on the display at any one time.

Only supports characters which are made up of a single code point. (In other words, combining marks are not supported.) If your input contains decomposed characters, consider using the unicode-transforms package to convert to Normalization Form C.

updateDisplay :: PiLcd -> [Text] -> IO () Source #

Update the display to contain the specified lines of text. This is done intelligently; i. e. only the characters which have changed are rewritten. The lines are truncated or padded with spaces to make them the width of the display. Similarly, the list of lines is truncated or padded with blank lines to make it the height of the display.

charFromAsciiArt :: [String] -> [Word8] Source #

Converts a glyph from ASCII art to binary representation. Expects a list of eight lines, where each line contains five characters. A dot is considered "off" if the character is a space, or "on" if it is any other character. Returns the glyph in the format expected for custom characters: eight bytes where each byte contains data in the least significant five bits.

nativeChar :: Word8 -> Char Source #

If for some reason you want to specify a character in the native 8-bit encoding of the LCD, instead of in Unicode, just call nativeChar on the 8-bit character value. This maps it to a region of the Private Use Area which is treated specially.

User Interface

Displays a simple user interface. The first line of the display is used as a "list box", where the user can scroll through a list of items one at a time using the up and down buttons. The second line of the display is used for virtual "buttons", such as "OK" and "Cancel". The user uses the left and right buttons to select a virtual "button". When the user presses the Select button, the interaction is considered done, and the calling program is given the list item and button selection that the user made.

If there is only one item in the list, the up and down buttons won't do anything, and the "↕" indicator will not be displayed. So, if you want to display a static line of text and some buttons, just create a single-element list containing the line of text.

data UiData Source #

The data to be displayed in the user interface.

Constructors

UiData 

Fields

  • udList :: ![Text]

    items to be displayed one-at-a-time on the first line

  • udButtons :: ![Text]

    buttons to be displayed on the second line

data UiState Source #

The current state of the user interaction.

Constructors

UiState 

Fields

defaultUiState :: UiState Source #

Defaults to displaying the first list item (index 0) and highlighting the first button (index 0).

runUi Source #

Arguments

:: PiLcd 
-> UiData

Data to display in the UI

-> UiState

Current state of the interaction

-> IO (UiState, Bool)

New UI state, and a flag indicating whether the interaction is done (i. e. user has pressed and released the "Select" button)

Updates the display based on the given UI state, and updates the UI state based on a button press or release which may have occurred since the last call.

runUiUntilDone Source #

Arguments

:: PiLcd 
-> UiData

Data to display in the UI

-> UiState

Initial state (i. e. which list item and button start out highlighted)

-> IO UiState

Final state (selections user made)

Calls runUi repeatedly, with a short delay in between, feeding back the state, until the interaction is "done". (i. e. user has pressed and released the "Select" button) The final state is returned, which indicates the selection the user has made.

Exception handling

These are specialized forms of bracket, where an uncaught exception causes the backlight to turn red and the exception to be displayed on the LCD. Then the exception is rethrown. This is useful for headless setups, where the LCD is the primary means of user interface.

withPiLcd Source #

Arguments

:: LcdAddress 
-> LcdOptions 
-> (PiLcd -> IO a)

Body computation

-> IO a

Result returned by body

Opens a PiLcd with the given LcdAddress and LcdOptions, passes the PiLcd to the body computation, and then closes the PiLcd, regardless of whether the body exited normally or exceptionally. If an exception occurred, the exception is shown on the LCD.

withPiLcdThenTurnOff Source #

Arguments

:: LcdAddress 
-> LcdOptions 
-> (PiLcd -> IO a)

Body computation

-> IO a

Result returned by body

Like withPiLcd, but in the non-exceptional case, the display is cleared and the backlight is turned off.