Merge branch 'mega' of https://github.com/letscontrolit/ESPEasy into feature/P118-select-cs-and-refactoring
@@ -53,6 +53,13 @@
|
||||
Set text position (move the cursor) and print the text. Combines the ``txp`` and ``txt`` commands in 1. Depending on the setting **Text Coordinates in col/row**, these coordinates are pixels (default) or column/rows.
|
||||
"
|
||||
"
|
||||
``<trigger>,txl,[<line>],<text>[,[<line>],<text>...]``
|
||||
","
|
||||
Print 1 or more texts on specified lines, starting at column 1. If a ``<line>`` is not specified (the comma must still be there!) the next display-line will be used, depending on current font-height, if the initial ``<line>`` is not specified, starts at line 1. ``<line>`` must be a positive integer value.
|
||||
|
||||
Always uses column/rows mode (and restores the currently active pixels or column/rows mode).
|
||||
"
|
||||
"
|
||||
``<trigger>,txc,<foreColor>[,<backgroundColor>]``
|
||||
","
|
||||
Set text color (background is transparent if not provided, or the same as the foreground color).
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
:widths: 20, 30
|
||||
|
||||
"
|
||||
Generic variables, available for all ``AdafruitGFX_Helper`` enabled plugins, currently: :ref:`P095_page`, :ref:`P096_page`, :ref:`P116_page` and :ref:`P131_page`.
|
||||
Generic variables, available for all ``AdafruitGFX_Helper`` enabled plugins, currently: :ref:`P095_page`, :ref:`P096_page`, :ref:`P116_page`, :ref:`P131_page` and :ref:`P141_page`.
|
||||
","
|
||||
Generic notes:
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ Select 9600 (Nextion's factory default baud rate is 9600).
|
||||
Command Statements (Optional)
|
||||
******************************
|
||||
|
||||
Up to ten different *Nextion Command Statements* can be created that automatically execute at each timer interval.
|
||||
Up to twenty different *Nextion Command Statements* can be created that automatically execute at each timer interval.
|
||||
This provides a convenient way to periodically populate your Nextion display with data from the ESPEasy system variables.
|
||||
System variables are discussed here: https://www.letscontrolit.com/wiki/index.php/ESPEasy_System_Variables
|
||||
|
||||
@@ -420,6 +420,10 @@ Change log
|
||||
.. versionchanged:: mega
|
||||
...
|
||||
|
||||
|improved|
|
||||
2022/09/27
|
||||
Changed number of available lines to 20.
|
||||
|
||||
|improved|
|
||||
2020/09/25
|
||||
Updated text with additional information.
|
||||
|
||||
@@ -30,6 +30,7 @@ Supported hardware
|
||||
|
||||
* :ref:`P092_ESR21_page` Simple Solar Control.
|
||||
* :ref:`P092_UVR31_page` single-circuit universal control system.
|
||||
* :ref:`P092_UVR42_page` single-circuit universal control system.
|
||||
* :ref:`P092_UVR61-3_page` three-circuit universal control system (up to v8.2).
|
||||
* :ref:`P092_UVR61-3v8_3_page` three-circuit universal control system (v8.3 or higher).
|
||||
* :ref:`P092_UVR1611_page` freely programmable universal control system.
|
||||
@@ -41,5 +42,8 @@ Change log
|
||||
.. versionadded:: 1.0
|
||||
...
|
||||
|
||||
|added|
|
||||
2022-03-26 Add support for UVR42.
|
||||
|
||||
|added|
|
||||
Initial release version.
|
||||
|
||||
@@ -75,4 +75,4 @@ Data acquisition
|
||||
* **Send to controller** 1..3: Check which controller (if any) you want to publish to. All or no controller can be used.
|
||||
* **Interval**: How often should the task publish its value (10..60 seconds is normal).
|
||||
|
||||
.. note:: Intervall not less than **10 seconds**! The reading of the DL bus happens twice per intervall.
|
||||
.. note:: Interval not less than **10 seconds**! The reading of the DL bus happens twice per interval.
|
||||
|
||||
@@ -79,4 +79,4 @@ Data acquisition
|
||||
* **Send to controller** 1..3: Check which controller (if any) you want to publish to. All or no controller can be used.
|
||||
* **Interval**: How often should the task publish its value (10..60 seconds is normal).
|
||||
|
||||
.. note:: Intervall not less than **10 seconds**! The reading of the DL bus happens twice per intervall.
|
||||
.. note:: Interval not less than **10 seconds**! The reading of the DL bus happens twice per interval.
|
||||
|
||||
@@ -69,4 +69,4 @@ Data acquisition
|
||||
* **Send to controller** 1..3: Check which controller (if any) you want to publish to. All or no controller can be used.
|
||||
* **Interval**: How often should the task publish its value (20..60 seconds is normal).
|
||||
|
||||
.. note:: Intervall not less than **20 seconds**! The reading of the DL bus happens twice per intervall.
|
||||
.. note:: Interval not less than **20 seconds**! The reading of the DL bus happens twice per interval.
|
||||
|
||||
|
After Width: | Height: | Size: 261 KiB |
@@ -0,0 +1,72 @@
|
||||
.. include:: ../Plugin/_plugin_substitutions_p09x.repl
|
||||
.. _P092_UVR42_page:
|
||||
|
||||
UVR42
|
||||
=====
|
||||
|
||||
|P092_typename|
|
||||
|P092_status|
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
The UVR42 unit is a single-circuit universal control system.
|
||||
The UVR42 unit is designed for simple solar installations and heating systems (storage charging, domestic hot water preparation)
|
||||
|
||||
* The DL bus runs at 24 volts.
|
||||
* The data frame consist of 10 bytes (excluding sync).
|
||||
* The data are transmitted @ 50Hz, therefore the transmission of one data set takes about 2.32 seconds.
|
||||
|
||||
.. image:: P092_UVR42.jpg
|
||||
|
||||
Wiring
|
||||
------
|
||||
|
||||
.. image:: P092_24V_Wiring.png
|
||||
|
||||
Protocol
|
||||
--------
|
||||
|
||||
.. image:: P092_UVR42_Protocol.png
|
||||
|
||||
Setup
|
||||
-----
|
||||
|
||||
.. note:: A new device task must be created for each value to be read from the DL bus!
|
||||
|
||||
.. image:: P092_Setup.png
|
||||
|
||||
Task settings
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
* **Device**: Heating - DL-Bus (Technische Alternative)
|
||||
* **Name**: Name of the task (example name **ValueN**, where N is a number).
|
||||
* **Enable**: Should the task be enabled or not
|
||||
|
||||
Sensor
|
||||
^^^^^^
|
||||
|
||||
* **1st GPIO**: DL bus input e.g. **GPIO 14 (D5)**
|
||||
* **DL-Bus Type**: **UVR42**
|
||||
|
||||
.. note:: The settings for **1st GPIO** and **DL-Bus Type** must be the same for all used DL bus tasks!
|
||||
|
||||
Inputs
|
||||
^^^^^^
|
||||
|
||||
.. note:: The description of the **Frame data** and the related **Frame bytes** can be found in the section **Protocol**!
|
||||
|
||||
.. csv-table::
|
||||
:header: "Frame data", "Frame bytes", "Value", "Index", "Decimals"
|
||||
:widths: 16, 8, 8, 5, 5
|
||||
|
||||
"Temp1 ... Temp4", "2 ... 9", "Sensor", "1 - 4", "1"
|
||||
"Output byte", "10", "Digital Output", "1 - 2", "0"
|
||||
|
||||
Data acquisition
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
* **Send to controller** 1..3: Check which controller (if any) you want to publish to. All or no controller can be used.
|
||||
* **Interval**: How often should the task publish its value (20..60 seconds is normal).
|
||||
|
||||
.. note:: Interval not less than **20 seconds**! The reading of the DL bus happens twice per interval.
|
||||
|
After Width: | Height: | Size: 30 KiB |
@@ -77,4 +77,4 @@ Data acquisition
|
||||
* **Send to controller** 1..3: Check which controller (if any) you want to publish to. All or no controller can be used.
|
||||
* **Interval**: How often should the task publish its value (10..60 seconds is normal).
|
||||
|
||||
.. note:: Interval not less than **10 seconds**! The reading of the DL bus happens twice per intervall.
|
||||
.. note:: Interval not less than **10 seconds**! The reading of the DL bus happens twice per interval.
|
||||
|
||||
@@ -82,4 +82,4 @@ Data acquisition
|
||||
* **Send to controller** 1..3: Check which controller (if any) you want to publish to. All or no controller can be used.
|
||||
* **Interval**: How often should the task publish its value (10..60 seconds is normal).
|
||||
|
||||
.. note:: Interval not less than **10 seconds**! The reading of the DL bus happens twice per intervall.
|
||||
.. note:: Interval not less than **10 seconds**! The reading of the DL bus happens twice per interval.
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
.. include:: ../Plugin/_plugin_substitutions_p14x.repl
|
||||
.. _P141_page:
|
||||
|
||||
|P141_typename|
|
||||
==================================================
|
||||
|
||||
|P141_shortinfo|
|
||||
|
||||
Plugin details
|
||||
--------------
|
||||
|
||||
Type: |P141_type|
|
||||
|
||||
Name: |P141_name|
|
||||
|
||||
Status: |P141_status|
|
||||
|
||||
GitHub: |P141_github|_
|
||||
|
||||
Maintainer: |P141_maintainer|
|
||||
|
||||
Used libraries: |P141_usedlibraries|
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
The Philips chip PCD8544 is used for driving a monochrome LCD display, often known as the Nokia 5110 LCD display, as the display was installed in that mobile phone.
|
||||
|
||||
The monochrome display has an 84 x 48 pixel resolution.
|
||||
|
||||
The plugin can be configured to show predefined text, a reservation for up to 9 lines is made, but only the lines that can fit on-screen will be shown, or via commands, sent via http or from rules, text or graphical elements like lines, rectangles, circles, pixels, etc., can be shown.
|
||||
|
||||
Hardware
|
||||
---------
|
||||
|
||||
An image, grabbed from a supplier, showing the display:
|
||||
|
||||
.. image:: P141_Nokia5110_display.png
|
||||
:alt: Nokia 5110 84 x 48 pixels
|
||||
|
||||
Nokia 5110 84 x 48 pixels
|
||||
|
||||
Connections
|
||||
^^^^^^^^^^^^
|
||||
|
||||
These displays are connected using the SPI interface, using at least 4 signal wires, implementing CS (SCE) to allow multiple SPI-connected devices.
|
||||
|
||||
The text on most displays is somewhat confusing, as not the usual SPI names are used:
|
||||
|
||||
.. image:: P141_DisplayConnections.png
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
- RST pin resets the display. It's an active low pin meaning; you can reset the display by pulling it low. You can also connect this pin to the Arduino reset so that it will reset the screen automatically.
|
||||
- CE(Chip Enable) pin is used to select one of many connected devices sharing same SPI bus. It's an active low pin as well.
|
||||
- D/C(Data/Command) pin tells the display whether the data it's receiving is a command or displayable data.
|
||||
- DIN is a serial data pin for SPI interface.
|
||||
- CLK is a serial clock pin for SPI interface.
|
||||
- VCC pin supplies power for the LCD which we connect to the 3.3V volts pin on the Arduino.
|
||||
- BL(Backlight) pin controls the backlight of the display. To control its brightness, you can add a potentiometer or connect this pin to any PWM-capable Arduino pin.
|
||||
- GND should be connected to the ground of Arduino
|
||||
|
||||
ESP LCD
|
||||
-------- ------
|
||||
(gpio) --> RST (optional)
|
||||
(gpio) --> SCE (=CS/CE)
|
||||
(gpio) --> D/C
|
||||
MOSI --> DIN(MOSI)
|
||||
CLK --> SCLK
|
||||
3V3 --- VCC (the displays only support 3.3V)
|
||||
(gpio) --> LED (optional)
|
||||
GND --- GND
|
||||
|
||||
(gpio) = configurable GPIO pin.
|
||||
|
||||
|
||||
Device
|
||||
------
|
||||
|
||||
.. image:: P141_DeviceConfiguration.png
|
||||
:alt: Device configuration
|
||||
|
||||
* **Name** A unique name should be entered here.
|
||||
|
||||
* **Enabled** The device can be disabled or enabled. When not enabled the device should not use any resources.
|
||||
|
||||
Actuator
|
||||
^^^^^^^^
|
||||
|
||||
* **GPIO -> SCE** Select the GPIO pin to use for the ``SCE``, a.k.a. ``CS``, connection.
|
||||
* **GPIO -> D/C** The GPIO pin to use for the ``D/C`` connection (Data/Command).
|
||||
* **GPIO -> RST (optional)** Select the GPIO pin to use for the ``RST`` (reset) connection. If the display doesn't have a ``RST`` connection, or no free pin is available, it can be set to *None*.
|
||||
* **GPIO -> Backlight (optional)** Select the GPIO pin to use for controlling the backlight. To save power, the backlight can be dimmed, or turned off if the display is turned off. If set to *None* and the ``LED`` input connected to ``VCC``, the max. brightness is used for the backlight.
|
||||
* **Backlight percentage** The backlight can be controlled via PWM modulation on the Backlight (LED) pin of the display. This is set as a percentage between 0 and 100%.
|
||||
* **Display Contrast**: The PCD8544 supports setting the contrast level, to get an optimally visible display content. This can be fine-tuned here. Range: 0..100%.
|
||||
* **Display button** A GPIO pin can be configured to wake the display on demand. This, combined with the **Display Timeout** setting, can preserve the lifetime of the display, and save some power.
|
||||
* **Inversed Logic** When checked, reverses the pin-state action of the **Display button** gpio. This allows an external circuit, f.e. an IR sensor, that may provide a *high* signal when activated, to wake the display.
|
||||
* **Display Timeout** Select the timeout in seconds to turn off the display after the last update or wake-up. Only used if the **Display button** is *also* configured.
|
||||
|
||||
Layout
|
||||
^^^^^^^^
|
||||
|
||||
* **Rotation** Depending on how the display is to be mounted/installed, it may be needed to rotate the content, or, as we have a non-square resolution, to use the display in *Portrait* layout instead of the default *Landscape*.
|
||||
|
||||
Available options:
|
||||
|
||||
.. image:: P141_RotationOptions.png
|
||||
:alt: Rotation
|
||||
|
||||
The available options rotate the display content in a counter clock-wise direction.
|
||||
|
||||
* **Text print Mode** Defines the handling of text when predefined text or text via the ``txt`` or ``txtfull`` subcommands (see below) is displayed.
|
||||
|
||||
Available options:
|
||||
|
||||
.. image:: P141_TextPrintModeOptions.png
|
||||
:alt: Text print mode
|
||||
|
||||
* *Continue to next line* Simply 'prints' all text to the display, with automatic overflow to the next line(s) if the text doesn't fit on the current line.
|
||||
* *Truncate exceeding message* Display the provided message, but any excess at the right border of the display is discarded.
|
||||
* *Clear then truncate exceeding message* Clear from the current cursor position to the end of the display, then display the provided message, but any excess at the right border of the display is discarded.
|
||||
* *Truncate, centered when MaxWidth set*: Like *Truncate exceeding message*, but can center the content when a max. width for the text is provided.
|
||||
|
||||
Default setting is *Clear then truncate exceeding message*.
|
||||
|
||||
* **Font scaling** The scaling factor for the currently active font. Select a factor between 1 and 10.
|
||||
|
||||
* **Invert display**: This monochrome display supports inverting the content. The default can be set here.
|
||||
|
||||
* **Clear display on exit** When checked, will clear the display when the task is disabled, either from settings or via the ``TaskDisable`` command. The screen will be cleared, turned off, and when a backlight pin is configured, also the backlight is turned off.
|
||||
|
||||
* **Write Command trigger** The command to handle any commands for this device can be selected here.
|
||||
|
||||
Available options:
|
||||
|
||||
.. image:: P141_WriteCommandTriggerOptions.png
|
||||
:alt: Write-command trigger
|
||||
|
||||
* *pcd8544*
|
||||
* *lcd*
|
||||
|
||||
The command is handled non-case sensitive. See below for available commands and subcommands.
|
||||
|
||||
* **Wake display on receiving text** When checked, the display will be enabled once any content is written to the screen, either triggered by the Interval, or from a command. Default checked.
|
||||
|
||||
* **Text Coordinates in col/row** When checked, the coordinates for the ``txp``, ``txz`` and ``txtfull`` subcommands will be handled in cursor columns & rows, instead of pixels. Column and row are calculated from the current font size and font scaling settings.
|
||||
|
||||
* **Background-fill for text** When checked, for any text-line sent to the screen, the entire background (including top and bottom lines) will have the provided background color, *unless* transparent is used (Background color == Foreground color). Default unchecked.
|
||||
|
||||
Content
|
||||
^^^^^^^^
|
||||
|
||||
* **Line 1..9** Predefined content can be specified. The number of lines used depends on the font used, the font scaling that is set and the rotation.
|
||||
|
||||
The usual variables, like ``[Taskname#Valuename]``, or ``%v1%``, system variables, formulas and functions can be used.
|
||||
|
||||
Input length is limited to 60 characters per line. If a longer calculated text is needed for a line, then it should be set from the rules or from an external source via http commands.
|
||||
|
||||
Next to Line 9, the remaining capacity in characters is displayed.
|
||||
|
||||
The total combination of lines * input length can not exceed 540 characters (sized dynamically). An error message will be shown after (trying to) save the settings, **any excess content will be discarded!**
|
||||
|
||||
* **Linespacing** When using a font scale > 1 the whitespace between the lines can be quite big. To be able to fine-tune that, this option is available, allowing 0 .. 14 pixels fixed linespacing, or use the default 'Auto' setting that calculates the linespacing based on font height and scale.
|
||||
|
||||
* **Interval** By default, Interval will be set to 0. If set to a non-zero value, the pre-configured content (if any) will be updated automatically using that interval (seconds). Depending on the **Text print Mode** setting, content that may have been draw from rules or external commands, may be erased.
|
||||
|
||||
Values
|
||||
^^^^^^
|
||||
|
||||
The current text-cursor position is available in 2 variables **CursorX** and **CursorY**, that will be updated on every change of text or received command. **No** events are generated, and these values will never be sent to controllers.
|
||||
|
||||
The values can be used in rules, if desired. They will follow the **Text Coordinates in col/row** setting.
|
||||
|
||||
Commands
|
||||
----------
|
||||
|
||||
.. include:: P141_commands.repl
|
||||
.. include:: AdaGFX_commands.repl
|
||||
|
||||
Values
|
||||
------
|
||||
|
||||
.. include:: AdaGFX_values.repl
|
||||
|
||||
.. Events
|
||||
.. ~~~~~~
|
||||
|
||||
.. .. include:: P141_events.repl
|
||||
|
||||
|
||||
|
||||
Change log
|
||||
----------
|
||||
|
||||
.. versionadded:: 2.0
|
||||
...
|
||||
|
||||
|added| 2022-08-25 Migrated (rewritten) from the ESPEasyPluginPlayground to ESPEasy using the ESPEasy AdafruitGFX Helper.
|
||||
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 173 KiB |
|
After Width: | Height: | Size: 101 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
@@ -0,0 +1,48 @@
|
||||
.. csv-table::
|
||||
:header: "Command Syntax", "Extra information"
|
||||
:widths: 20, 30
|
||||
|
||||
"
|
||||
This plugin allows dynamic configuration of the command-trigger. Available triggers are:
|
||||
|
||||
* ``pcd8544``
|
||||
* ``lcd``
|
||||
|
||||
The default trigger is ``pcd8544``
|
||||
","
|
||||
Some commands are postfixed with ``cmd``, indicating device specific commands. Not device-specific commands are genericly applicable to all *Adafruit Graphics* enabled devices, using the ESPEasy ``AdafruitGFX_helper`` module.
|
||||
|
||||
Commands can be sent from several sources, from the Tools page using the Submit button, from Rules, and via the webbrowser address bar or other applications that can open an url.
|
||||
|
||||
When using the Tools or Rules route, the commands shown here can be used as displayed, when using an url, a command should be prefixed with: ``http://<esp-ip-address>/control?cmd=``
|
||||
"
|
||||
"
|
||||
| ``pcd8544cmd,off``
|
||||
","
|
||||
| Switch the display off. As this hardware doesn't have the option to be turned off, the display will be cleared. If the Backlight is connected and configured, that will also be turned off.
|
||||
"
|
||||
"
|
||||
| ``pcd8544cmd,on``
|
||||
","
|
||||
| Switch the display on (after it was turned off). Also turns on the backlight if that is connected and configured. Any content that was displayed when the display was turned off is *not* restored.
|
||||
"
|
||||
"
|
||||
| ``pcd8544cmd,clear``
|
||||
","
|
||||
| Clear the display, using the default background color.
|
||||
"
|
||||
"
|
||||
| ``pcd8544cmd,backlight,<percentage>``
|
||||
","
|
||||
| Set the level of backlight brightness, from 0..100%. Only applicable if a backlight pin is configured.
|
||||
"
|
||||
"
|
||||
| ``pcd8544cmd,contrast,<percentage>``
|
||||
","
|
||||
| Set the level of display contrast, from 0..100%.
|
||||
"
|
||||
"
|
||||
| ``pcd8544cmd,inv[,<0|1>]``
|
||||
","
|
||||
| Set the state of Inverted display, 0 = normal, 1 = inverted. When no value is supplied, the state is inverted.
|
||||
"
|
||||
@@ -360,6 +360,7 @@ There are different released versions of ESP Easy:
|
||||
":ref:`P133_page`","|P133_status|","P133"
|
||||
":ref:`P134_page`","|P134_status|","P134"
|
||||
":ref:`P135_page`","|P135_status|","P135"
|
||||
":ref:`P141_page`","|P141_status|","P141"
|
||||
|
||||
|
||||
Internal GPIO handling
|
||||
|
||||
@@ -12,3 +12,4 @@
|
||||
.. include:: ../Plugin/_plugin_substitutions_p11x.repl
|
||||
.. include:: ../Plugin/_plugin_substitutions_p12x.repl
|
||||
.. include:: ../Plugin/_plugin_substitutions_p13x.repl
|
||||
.. include:: ../Plugin/_plugin_substitutions_p14x.repl
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
.. |P141_name| replace:: :cyan:`PCD8544 Nokia 5110 LCD`
|
||||
.. |P141_type| replace:: :cyan:`Display`
|
||||
.. |P141_typename| replace:: :cyan:`Display - PCD8544 Nokia 5110 LCD`
|
||||
.. |P141_porttype| replace:: `.`
|
||||
.. |P141_status| replace:: :yellow:`DISPLAY`
|
||||
.. |P141_github| replace:: P141_PCD8544_Nokia5110.ino
|
||||
.. _P141_github: https://github.com/letscontrolit/ESPEasy/blob/mega/src/_P141_PCD8544_Nokia5110.ino
|
||||
.. |P141_usedby| replace:: `.`
|
||||
.. |P141_shortinfo| replace:: `Nokia 5110 monochrome LCD`
|
||||
.. |P141_maintainer| replace:: `tonhuisman`
|
||||
.. |P141_compileinfo| replace:: `.`
|
||||
.. |P141_usedlibraries| replace:: `https://github.com/adafruit/Adafruit_NeoMatrix`
|
||||
@@ -726,6 +726,10 @@ P135 :ref:`P135_page`
|
||||
|
||||
.. include:: ../Plugin/P135_commands.repl
|
||||
|
||||
P141 :ref:`P141_page`
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. include:: ../Plugin/P141_commands.repl
|
||||
|
||||
.. .. *** Insert regular plugin commands above this remark! ***
|
||||
|
||||
|
||||
@@ -0,0 +1,432 @@
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@file Adafruit_PCD8544.cpp
|
||||
|
||||
@mainpage Adafruit PCD8544 Nokia 5110 LCD Library
|
||||
|
||||
@section intro Introduction
|
||||
|
||||
This is a library for our Monochrome Nokia 5110 LCD Displays
|
||||
|
||||
Pick one up today in the adafruit shop!
|
||||
------> http://www.adafruit.com/products/338
|
||||
|
||||
These displays use SPI to communicate, 4 or 5 pins are required to
|
||||
interface
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
@section author Author
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
|
||||
@section license License
|
||||
|
||||
BSD license, check license.txt for more information
|
||||
All text above, and the splash screen below must be included in any
|
||||
redistribution
|
||||
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
#include "Adafruit_PCD8544.h"
|
||||
#include "Arduino.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/** the memory buffer for the LCD */
|
||||
uint8_t pcd8544_buffer[LCDWIDTH * LCDHEIGHT / 8] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFF, 0xFC, 0xE0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
|
||||
0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x80, 0xC0,
|
||||
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC7, 0xC7, 0x87, 0x8F, 0x9F,
|
||||
0x9F, 0xFF, 0xFF, 0xFF, 0xC1, 0xC0, 0xE0, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFC, 0xFC, 0xFC, 0xFC, 0xFE, 0xFE, 0xFE, 0xFC, 0xFC, 0xF8, 0xF8,
|
||||
0xF0, 0xE0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0,
|
||||
0xF1, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0x0F, 0x0F, 0x87,
|
||||
0xE7, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0x3F, 0xF9, 0xF8, 0xF8, 0xF8, 0xF8,
|
||||
0xF8, 0xF8, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x7F, 0x3F, 0x0F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x7E, 0x3F, 0x3F, 0x0F,
|
||||
0x1F, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xE0, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFC, 0xF0, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||
0x03, 0x03, 0x03, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x03, 0x0F, 0x1F, 0x3F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x7F, 0x7F, 0x1F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
/*!
|
||||
@brief Update the bounding box for partial updates
|
||||
@param xmin left
|
||||
@param ymin bottom
|
||||
@param xmax right
|
||||
@param ymax top
|
||||
*/
|
||||
void Adafruit_PCD8544::updateBoundingBox(uint8_t xmin, uint8_t ymin,
|
||||
uint8_t xmax, uint8_t ymax) {
|
||||
xUpdateMin = min(xUpdateMin, xmin);
|
||||
xUpdateMax = max(xUpdateMax, xmax);
|
||||
yUpdateMin = min(yUpdateMin, ymin);
|
||||
yUpdateMax = max(yUpdateMax, ymax);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Constructor for software SPI with explicit CS pin
|
||||
@param sclk_pin SCLK pin
|
||||
@param din_pin DIN pin
|
||||
@param dc_pin DC pin
|
||||
@param cs_pin CS pin
|
||||
@param rst_pin RST pin
|
||||
*/
|
||||
Adafruit_PCD8544::Adafruit_PCD8544(int8_t sclk_pin, int8_t din_pin,
|
||||
int8_t dc_pin, int8_t cs_pin, int8_t rst_pin)
|
||||
: Adafruit_GFX(LCDWIDTH, LCDHEIGHT) {
|
||||
spi_dev = new Adafruit_SPIDevice(cs_pin, sclk_pin, -1, din_pin,
|
||||
4000000); // 4mhz max speed
|
||||
|
||||
_dcpin = dc_pin;
|
||||
_rstpin = rst_pin;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Constructor for hardware SPI based on hardware controlled SCK (SCLK)
|
||||
and MOSI (DIN) pins. CS is still controlled by any IO pin. NOTE: MISO and SS
|
||||
will be set as an input and output respectively, so be careful sharing those
|
||||
pins!
|
||||
@param dc_pin DC pin
|
||||
@param cs_pin CS pin
|
||||
@param rst_pin RST pin
|
||||
@param theSPI Pointer to SPIClass device for hardware SPI
|
||||
*/
|
||||
Adafruit_PCD8544::Adafruit_PCD8544(int8_t dc_pin, int8_t cs_pin, int8_t rst_pin,
|
||||
SPIClass *theSPI)
|
||||
: Adafruit_GFX(LCDWIDTH, LCDHEIGHT) {
|
||||
spi_dev = new Adafruit_SPIDevice(cs_pin, 4000000, SPI_BITORDER_MSBFIRST,
|
||||
SPI_MODE0, theSPI);
|
||||
|
||||
_dcpin = dc_pin;
|
||||
_rstpin = rst_pin;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief The most basic function, set a single pixel, in the main buffer
|
||||
@param x x coord
|
||||
@param y y coord
|
||||
@param color pixel color (BLACK or WHITE)
|
||||
*/
|
||||
void Adafruit_PCD8544::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
||||
setPixel(x, y, color, pcd8544_buffer);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief The most basic function, set a single pixel
|
||||
@param x x coord
|
||||
@param y y coord
|
||||
@param color pixel color (BLACK or WHITE)
|
||||
@param buffer The framebuffer to set the pixel in
|
||||
*/
|
||||
void Adafruit_PCD8544::setPixel(int16_t x, int16_t y, bool color,
|
||||
uint8_t *buffer) {
|
||||
if ((x < 0) || (x >= _width) || (y < 0) || (y >= _height))
|
||||
return;
|
||||
|
||||
int16_t t;
|
||||
switch (rotation) {
|
||||
case 1:
|
||||
t = x;
|
||||
x = y;
|
||||
y = LCDHEIGHT - 1 - t;
|
||||
break;
|
||||
case 2:
|
||||
x = LCDWIDTH - 1 - x;
|
||||
y = LCDHEIGHT - 1 - y;
|
||||
break;
|
||||
case 3:
|
||||
t = x;
|
||||
x = LCDWIDTH - 1 - y;
|
||||
y = t;
|
||||
break;
|
||||
}
|
||||
updateBoundingBox(x, y, x, y);
|
||||
|
||||
// x is which column
|
||||
if (color)
|
||||
buffer[x + (y / 8) * LCDWIDTH] |= 1 << (y % 8);
|
||||
else
|
||||
buffer[x + (y / 8) * LCDWIDTH] &= ~(1 << (y % 8));
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief The most basic function, get a single pixel
|
||||
@param x x coord
|
||||
@param y y coord
|
||||
@param buffer The framebuffer to get the pixel from
|
||||
@return color of the pixel at x,y
|
||||
*/
|
||||
bool Adafruit_PCD8544::getPixel(int16_t x, int16_t y, uint8_t *buffer) {
|
||||
if ((x < 0) || (x >= _width) || (y < 0) || (y >= _height))
|
||||
return false;
|
||||
|
||||
int16_t t;
|
||||
switch (rotation) {
|
||||
case 1:
|
||||
t = x;
|
||||
x = y;
|
||||
y = LCDHEIGHT - 1 - t;
|
||||
break;
|
||||
case 2:
|
||||
x = LCDWIDTH - 1 - x;
|
||||
y = LCDHEIGHT - 1 - y;
|
||||
break;
|
||||
case 3:
|
||||
t = x;
|
||||
x = LCDWIDTH - 1 - y;
|
||||
y = t;
|
||||
break;
|
||||
}
|
||||
|
||||
return (buffer[x + (y / 8) * LCDWIDTH] >> (y % 8)) & 0x1;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Initialize the display. Set bias and contrast, enter normal mode.
|
||||
*/
|
||||
void Adafruit_PCD8544::initDisplay() {
|
||||
|
||||
// toggle RST low to reset
|
||||
if (_rstpin >= 0) {
|
||||
pinMode(_rstpin, OUTPUT);
|
||||
digitalWrite(_rstpin, LOW);
|
||||
delay(1); // 1 ns minimum
|
||||
digitalWrite(_rstpin, HIGH);
|
||||
}
|
||||
|
||||
setBias(_bias);
|
||||
setContrast(_contrast);
|
||||
|
||||
// normal mode
|
||||
command(PCD8544_FUNCTIONSET);
|
||||
|
||||
// Set display to Normal
|
||||
command(PCD8544_DISPLAYCONTROL | PCD8544_DISPLAYNORMAL);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Set up SPI, initialize the display, set the bounding box
|
||||
@param contrast Initial contrast value
|
||||
@param bias Initial bias value
|
||||
@returns True on initialization success
|
||||
*/
|
||||
bool Adafruit_PCD8544::begin(uint8_t contrast, uint8_t bias) {
|
||||
|
||||
if (!spi_dev->begin()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set common pin outputs.
|
||||
pinMode(_dcpin, OUTPUT);
|
||||
if (_rstpin >= 0)
|
||||
pinMode(_rstpin, OUTPUT);
|
||||
|
||||
_bias = bias;
|
||||
_contrast = contrast;
|
||||
_reinit_interval = 0;
|
||||
_display_count = 0;
|
||||
initDisplay();
|
||||
|
||||
// initial display line
|
||||
// set page address
|
||||
// set column address
|
||||
// write display data
|
||||
|
||||
// set up a bounding box for screen updates
|
||||
|
||||
updateBoundingBox(0, 0, LCDWIDTH - 1, LCDHEIGHT - 1);
|
||||
// Push out pcd8544_buffer to the Display (will show the AFI logo)
|
||||
display();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Send a command to the LCD
|
||||
@param c Command byte
|
||||
*/
|
||||
void Adafruit_PCD8544::command(uint8_t c) {
|
||||
digitalWrite(_dcpin, LOW);
|
||||
spi_dev->write(&c, 1);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Send data to the LCD
|
||||
@param c Data byte
|
||||
*/
|
||||
void Adafruit_PCD8544::data(uint8_t c) {
|
||||
digitalWrite(_dcpin, HIGH);
|
||||
spi_dev->write(&c, 1);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Set the contrast level
|
||||
@param val Contrast value
|
||||
*/
|
||||
void Adafruit_PCD8544::setContrast(uint8_t val) {
|
||||
if (val > 0x7f) {
|
||||
val = 0x7f;
|
||||
}
|
||||
_contrast = val;
|
||||
command(PCD8544_FUNCTIONSET | PCD8544_EXTENDEDINSTRUCTION);
|
||||
command(PCD8544_SETVOP | val);
|
||||
command(PCD8544_FUNCTIONSET);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Set the bias level
|
||||
@param val Bias value
|
||||
*/
|
||||
void Adafruit_PCD8544::setBias(uint8_t val) {
|
||||
if (val > 0x07) {
|
||||
val = 0x07;
|
||||
}
|
||||
_bias = val;
|
||||
command(PCD8544_FUNCTIONSET | PCD8544_EXTENDEDINSTRUCTION);
|
||||
command(PCD8544_SETBIAS | val);
|
||||
command(PCD8544_FUNCTIONSET);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Get the bias level
|
||||
@return Bias value
|
||||
*/
|
||||
uint8_t Adafruit_PCD8544::getBias() { return _bias; }
|
||||
|
||||
/*!
|
||||
@brief Get the contrast level
|
||||
@return Contrast value
|
||||
*/
|
||||
uint8_t Adafruit_PCD8544::getContrast() { return _contrast; }
|
||||
|
||||
/*!
|
||||
@brief Set the interval for reinitializing the display
|
||||
@param val Reinit after this many calls to display()
|
||||
*/
|
||||
void Adafruit_PCD8544::setReinitInterval(uint8_t val) {
|
||||
_reinit_interval = val;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Get the reinit interval
|
||||
@return Reinit interval
|
||||
*/
|
||||
uint8_t Adafruit_PCD8544::getReinitInterval() { return _reinit_interval; }
|
||||
|
||||
/*!
|
||||
@brief Update the display
|
||||
*/
|
||||
void Adafruit_PCD8544::display(void) {
|
||||
if (_reinit_interval) {
|
||||
_display_count++;
|
||||
if (_display_count >= _reinit_interval) {
|
||||
_display_count = 0;
|
||||
initDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t page = (yUpdateMin / 8); page < (yUpdateMax / 8) + 1; page++) {
|
||||
command(PCD8544_SETYADDR | page);
|
||||
|
||||
uint8_t startcol = xUpdateMin;
|
||||
uint8_t endcol = xUpdateMax;
|
||||
|
||||
command(PCD8544_SETXADDR | startcol);
|
||||
|
||||
digitalWrite(_dcpin, HIGH);
|
||||
spi_dev->write(pcd8544_buffer + (LCDWIDTH * page) + startcol,
|
||||
endcol - startcol + 1);
|
||||
}
|
||||
|
||||
command(PCD8544_SETYADDR); // no idea why this is necessary but it is to
|
||||
// finish the last byte?
|
||||
|
||||
xUpdateMin = LCDWIDTH - 1;
|
||||
xUpdateMax = 0;
|
||||
yUpdateMin = LCDHEIGHT - 1;
|
||||
yUpdateMax = 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Clear the entire display
|
||||
*/
|
||||
void Adafruit_PCD8544::clearDisplay(void) {
|
||||
memset(pcd8544_buffer, 0, LCDWIDTH * LCDHEIGHT / 8);
|
||||
updateBoundingBox(0, 0, LCDWIDTH - 1, LCDHEIGHT - 1);
|
||||
cursor_y = cursor_x = 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Invert the entire display
|
||||
@param i True to invert the display, false to keep it uninverted
|
||||
*/
|
||||
void Adafruit_PCD8544::invertDisplay(bool i) {
|
||||
command(PCD8544_FUNCTIONSET);
|
||||
command(PCD8544_DISPLAYCONTROL |
|
||||
(i ? PCD8544_DISPLAYINVERTED : PCD8544_DISPLAYNORMAL));
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Scroll the display by creating a new buffer and moving each pixel
|
||||
@param xpixels The x offset, can be negative to scroll backwards
|
||||
@param ypixels The y offset, can be negative to scroll updwards
|
||||
*/
|
||||
void Adafruit_PCD8544::scroll(int8_t xpixels, int8_t ypixels) {
|
||||
uint8_t new_buffer[LCDWIDTH * LCDHEIGHT / 8];
|
||||
memset(new_buffer, 0, LCDWIDTH * LCDHEIGHT / 8);
|
||||
|
||||
// negative pixels wrap around
|
||||
while (ypixels < 0) {
|
||||
ypixels += height();
|
||||
}
|
||||
ypixels %= height();
|
||||
while (xpixels < 0) {
|
||||
xpixels += width();
|
||||
}
|
||||
xpixels %= width();
|
||||
|
||||
for (int x = 0; x < width(); x++) {
|
||||
for (int y = 0; y < height(); y++) {
|
||||
if (getPixel(x, y, pcd8544_buffer)) {
|
||||
int new_x = (x + xpixels) % _width;
|
||||
int new_y = (y + ypixels) % _height;
|
||||
setPixel(new_x, new_y, true, new_buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy(pcd8544_buffer, new_buffer, LCDWIDTH * LCDHEIGHT / 8);
|
||||
updateBoundingBox(0, 0, LCDWIDTH - 1, LCDHEIGHT - 1);
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@file Adafruit_PCD8544.h
|
||||
|
||||
This is a library for our Monochrome Nokia 5110 LCD Displays
|
||||
|
||||
Pick one up today in the adafruit shop!
|
||||
------> http://www.adafruit.com/products/338
|
||||
|
||||
These displays use SPI to communicate, 4 or 5 pins are required to
|
||||
interface
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, check license.txt for more information
|
||||
All text above, and the splash screen must be included in any redistribution
|
||||
*/
|
||||
/**************************************************************************/
|
||||
#ifndef _ADAFRUIT_PCD8544_H
|
||||
#define _ADAFRUIT_PCD8544_H
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <Adafruit_GFX.h>
|
||||
#include <Adafruit_SPIDevice.h>
|
||||
#include <SPI.h>
|
||||
|
||||
#define LCDWIDTH 84 ///< LCD is 84 pixels wide
|
||||
#define LCDHEIGHT 48 ///< 48 pixels high
|
||||
|
||||
#define PCD8544_POWERDOWN 0x04 ///< Function set, Power down mode
|
||||
#define PCD8544_ENTRYMODE 0x02 ///< Function set, Entry mode
|
||||
#define PCD8544_EXTENDEDINSTRUCTION \
|
||||
0x01 ///< Function set, Extended instruction set control
|
||||
|
||||
#define PCD8544_DISPLAYBLANK 0x0 ///< Display control, blank
|
||||
#define PCD8544_DISPLAYNORMAL 0x4 ///< Display control, normal mode
|
||||
#define PCD8544_DISPLAYALLON 0x1 ///< Display control, all segments on
|
||||
#define PCD8544_DISPLAYINVERTED 0x5 ///< Display control, inverse mode
|
||||
|
||||
#define PCD8544_FUNCTIONSET 0x20 ///< Basic instruction set
|
||||
#define PCD8544_DISPLAYCONTROL \
|
||||
0x08 ///< Basic instruction set - Set display configuration
|
||||
#define PCD8544_SETYADDR \
|
||||
0x40 ///< Basic instruction set - Set Y address of RAM, 0 <= Y <= 5
|
||||
#define PCD8544_SETXADDR \
|
||||
0x80 ///< Basic instruction set - Set X address of RAM, 0 <= X <= 83
|
||||
|
||||
#define PCD8544_SETTEMP \
|
||||
0x04 ///< Extended instruction set - Set temperature coefficient
|
||||
#define PCD8544_SETBIAS 0x10 ///< Extended instruction set - Set bias system
|
||||
#define PCD8544_SETVOP \
|
||||
0x80 ///< Extended instruction set - Write Vop to register
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief The PCD8544 LCD class
|
||||
*/
|
||||
class Adafruit_PCD8544 : public Adafruit_GFX {
|
||||
public:
|
||||
Adafruit_PCD8544(int8_t sclk_pin, int8_t din_pin, int8_t dc_pin,
|
||||
int8_t cs_pin, int8_t rst_pin);
|
||||
Adafruit_PCD8544(int8_t dc_pin, int8_t cs_pin, int8_t rst_pin,
|
||||
SPIClass *theSPI = &SPI);
|
||||
|
||||
virtual ~Adafruit_PCD8544() {}
|
||||
|
||||
bool begin(uint8_t contrast = 40, uint8_t bias = 0x04);
|
||||
|
||||
void command(uint8_t c);
|
||||
void data(uint8_t c);
|
||||
|
||||
void setContrast(uint8_t val);
|
||||
uint8_t getContrast(void);
|
||||
|
||||
uint8_t getBias(void);
|
||||
void setBias(uint8_t val);
|
||||
|
||||
void clearDisplay(void);
|
||||
void display();
|
||||
void updateBoundingBox(uint8_t xmin, uint8_t ymin, uint8_t xmax,
|
||||
uint8_t ymax);
|
||||
|
||||
void setReinitInterval(uint8_t val);
|
||||
uint8_t getReinitInterval(void);
|
||||
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||
void setPixel(int16_t x, int16_t y, bool color, uint8_t *buffer);
|
||||
bool getPixel(int16_t x, int16_t y, uint8_t *buffer);
|
||||
|
||||
void initDisplay();
|
||||
void invertDisplay(bool i);
|
||||
void scroll(int8_t vpixels, int8_t hpixels);
|
||||
|
||||
private:
|
||||
Adafruit_SPIDevice *spi_dev = NULL;
|
||||
int8_t _rstpin = -1, _dcpin = -1;
|
||||
|
||||
uint8_t _contrast; ///< Contrast level, Vop
|
||||
uint8_t _bias; ///< Bias value
|
||||
uint8_t _reinit_interval; ///< Reinitialize the display after this many calls
|
||||
///< to display()
|
||||
uint8_t _display_count; ///< Count for reinit interval
|
||||
|
||||
uint8_t xUpdateMin, xUpdateMax, yUpdateMin, yUpdateMax;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
# Adafruit PCD8544 Nokia 5110 LCD Library [](https://github.com/adafruit/Adafruit-PCD8544-Nokia-5110-LCD-library/actions)[](http://adafruit.github.io/Adafruit-PCD8544-Nokia-5110-LCD-library/html/index.html)
|
||||
|
||||
This is a library for our Monochrome Nokia 5110 LCD Displays
|
||||
|
||||
Pick one up today in the Adafruit shop!
|
||||
------> https://www.adafruit.com/product/338
|
||||
|
||||
These displays use SPI to communicate, 4 or 5 pins are required to
|
||||
interface.
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, check license.txt for more information.
|
||||
All text above must be included in any redistribution.
|
||||
|
||||
To install, use the Arduino Library Manager to search for 'Adafruit VCNL4010'
|
||||
and install the library.
|
||||
|
||||
You will also need the Adafruit GFX Graphics core which does all the circles, text, rectangles, etc.
|
||||
You can get it by searching for 'Adafruit GFX' in the Arduino Library Manager or check it out here:
|
||||
https://github.com/adafruit/Adafruit-GFX-Library
|
||||
@@ -0,0 +1,127 @@
|
||||
# Adafruit Community Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and leaders pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level or type of
|
||||
experience, education, socio-economic status, nationality, personal appearance,
|
||||
race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
We are committed to providing a friendly, safe and welcoming environment for
|
||||
all.
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Be kind and courteous to others
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Collaborating with other community members
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and sexual attention or advances
|
||||
* The use of inappropriate images, including in a community member's avatar
|
||||
* The use of inappropriate language, including in a community member's nickname
|
||||
* Any spamming, flaming, baiting or other attention-stealing behavior
|
||||
* Excessive or unwelcome helping; answering outside the scope of the question
|
||||
asked
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate
|
||||
|
||||
The goal of the standards and moderation guidelines outlined here is to build
|
||||
and maintain a respectful community. We ask that you don’t just aim to be
|
||||
"technically unimpeachable", but rather try to be your best self.
|
||||
|
||||
We value many things beyond technical expertise, including collaboration and
|
||||
supporting others within our community. Providing a positive experience for
|
||||
other community members can have a much more significant impact than simply
|
||||
providing the correct answer.
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project leaders are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project leaders have the right and responsibility to remove, edit, or
|
||||
reject messages, comments, commits, code, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any community member for other behaviors that they deem
|
||||
inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Moderation
|
||||
|
||||
Instances of behaviors that violate the Adafruit Community Code of Conduct
|
||||
may be reported by any member of the community. Community members are
|
||||
encouraged to report these situations, including situations they witness
|
||||
involving other community members.
|
||||
|
||||
You may report in the following ways:
|
||||
|
||||
In any situation, you may send an email to <support@adafruit.com>.
|
||||
|
||||
On the Adafruit Discord, you may send an open message from any channel
|
||||
to all Community Helpers by tagging @community helpers. You may also send an
|
||||
open message from any channel, or a direct message to @kattni#1507,
|
||||
@tannewt#4653, @Dan Halbert#1614, @cater#2442, @sommersoft#0222, or
|
||||
@Andon#8175.
|
||||
|
||||
Email and direct message reports will be kept confidential.
|
||||
|
||||
In situations on Discord where the issue is particularly egregious, possibly
|
||||
illegal, requires immediate action, or violates the Discord terms of service,
|
||||
you should also report the message directly to Discord.
|
||||
|
||||
These are the steps for upholding our community’s standards of conduct.
|
||||
|
||||
1. Any member of the community may report any situation that violates the
|
||||
Adafruit Community Code of Conduct. All reports will be reviewed and
|
||||
investigated.
|
||||
2. If the behavior is an egregious violation, the community member who
|
||||
committed the violation may be banned immediately, without warning.
|
||||
3. Otherwise, moderators will first respond to such behavior with a warning.
|
||||
4. Moderators follow a soft "three strikes" policy - the community member may
|
||||
be given another chance, if they are receptive to the warning and change their
|
||||
behavior.
|
||||
5. If the community member is unreceptive or unreasonable when warned by a
|
||||
moderator, or the warning goes unheeded, they may be banned for a first or
|
||||
second offense. Repeated offenses will result in the community member being
|
||||
banned.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct and the enforcement policies listed above apply to all
|
||||
Adafruit Community venues. This includes but is not limited to any community
|
||||
spaces (both public and private), the entire Adafruit Discord server, and
|
||||
Adafruit GitHub repositories. Examples of Adafruit Community spaces include
|
||||
but are not limited to meet-ups, audio chats on the Adafruit Discord, or
|
||||
interaction at a conference.
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. As a community
|
||||
member, you are representing our community, and are expected to behave
|
||||
accordingly.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 1.4, available at
|
||||
<https://www.contributor-covenant.org/version/1/4/code-of-conduct.html>,
|
||||
and the [Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html).
|
||||
|
||||
For other projects adopting the Adafruit Community Code of
|
||||
Conduct, please contact the maintainers of those projects for enforcement.
|
||||
If you wish to use this code of conduct for your own project, consider
|
||||
explicitly mentioning your moderation policy or making a copy with your
|
||||
own moderation policy so as to avoid confusion.
|
||||
@@ -0,0 +1,377 @@
|
||||
/*********************************************************************
|
||||
This is an example sketch for our Monochrome Nokia 5110 LCD Displays
|
||||
|
||||
Pick one up today in the adafruit shop!
|
||||
------> http://www.adafruit.com/products/338
|
||||
|
||||
These displays use SPI to communicate, 4 or 5 pins are required to
|
||||
interface
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, check license.txt for more information
|
||||
All text above, and the splash screen must be included in any redistribution
|
||||
*********************************************************************/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <Adafruit_GFX.h>
|
||||
#include <Adafruit_PCD8544.h>
|
||||
|
||||
// Software SPI (slower updates, more flexible pin options):
|
||||
// pin 7 - Serial clock out (SCLK)
|
||||
// pin 6 - Serial data out (DIN)
|
||||
// pin 5 - Data/Command select (D/C)
|
||||
// pin 4 - LCD chip select (CS)
|
||||
// pin 3 - LCD reset (RST)
|
||||
Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3);
|
||||
|
||||
// Hardware SPI (faster, but must use certain hardware pins):
|
||||
// SCK is LCD serial clock (SCLK) - this is pin 13 on Arduino Uno
|
||||
// MOSI is LCD DIN - this is pin 11 on an Arduino Uno
|
||||
// pin 5 - Data/Command select (D/C)
|
||||
// pin 4 - LCD chip select (CS)
|
||||
// pin 3 - LCD reset (RST)
|
||||
// Adafruit_PCD8544 display = Adafruit_PCD8544(5, 4, 3);
|
||||
// Note with hardware SPI MISO and SS pins aren't used but will still be read
|
||||
// and written to during SPI transfer. Be careful sharing these pins!
|
||||
|
||||
#define NUMFLAKES 10
|
||||
#define XPOS 0
|
||||
#define YPOS 1
|
||||
#define DELTAY 2
|
||||
|
||||
#define BLACK 1 ///< Black pixel
|
||||
#define WHITE 0 ///< White pixel
|
||||
|
||||
|
||||
#define LOGO16_GLCD_HEIGHT 16
|
||||
#define LOGO16_GLCD_WIDTH 16
|
||||
|
||||
static const unsigned char PROGMEM logo16_glcd_bmp[] =
|
||||
{ 0B00000000, 0B11000000,
|
||||
0B00000001, 0B11000000,
|
||||
0B00000001, 0B11000000,
|
||||
0B00000011, 0B11100000,
|
||||
0B11110011, 0B11100000,
|
||||
0B11111110, 0B11111000,
|
||||
0B01111110, 0B11111111,
|
||||
0B00110011, 0B10011111,
|
||||
0B00011111, 0B11111100,
|
||||
0B00001101, 0B01110000,
|
||||
0B00011011, 0B10100000,
|
||||
0B00111111, 0B11100000,
|
||||
0B00111111, 0B11110000,
|
||||
0B01111100, 0B11110000,
|
||||
0B01110000, 0B01110000,
|
||||
0B00000000, 0B00110000 };
|
||||
|
||||
void testdrawbitmap(const uint8_t *bitmap, uint8_t w, uint8_t h) {
|
||||
uint8_t icons[NUMFLAKES][3];
|
||||
randomSeed(666); // whatever seed
|
||||
|
||||
// initialize
|
||||
for (uint8_t f=0; f< NUMFLAKES; f++) {
|
||||
icons[f][XPOS] = random(display.width());
|
||||
icons[f][YPOS] = 0;
|
||||
icons[f][DELTAY] = random(5) + 1;
|
||||
|
||||
Serial.print("x: ");
|
||||
Serial.print(icons[f][XPOS], DEC);
|
||||
Serial.print(" y: ");
|
||||
Serial.print(icons[f][YPOS], DEC);
|
||||
Serial.print(" dy: ");
|
||||
Serial.println(icons[f][DELTAY], DEC);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
// draw each icon
|
||||
for (uint8_t f=0; f< NUMFLAKES; f++) {
|
||||
display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, BLACK);
|
||||
}
|
||||
display.display();
|
||||
delay(200);
|
||||
|
||||
while(Serial.available()) {
|
||||
switch (Serial.read()) {
|
||||
case 'w':display.setContrast(display.getContrast() + 1);
|
||||
break;
|
||||
case 's':if(display.getContrast()) display.setContrast(display.getContrast() - 1);
|
||||
break;
|
||||
case 'e':display.setBias(display.getBias() + 1);
|
||||
break;
|
||||
case 'd':if(display.getBias()) display.setBias(display.getBias() - 1);
|
||||
break;
|
||||
case 'R':display.setReinitInterval(10);
|
||||
break;
|
||||
case 'r':display.initDisplay();
|
||||
display.setReinitInterval(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Serial.print("contrast (w/s): 0x");
|
||||
Serial.print(display.getContrast(), HEX);
|
||||
Serial.print(" bias (e/d): 0x");
|
||||
Serial.print(display.getBias(), HEX);
|
||||
Serial.print(" reinitialize display (r/R): 0x");
|
||||
Serial.print(display.getReinitInterval(), HEX);
|
||||
Serial.print(" \r");
|
||||
|
||||
// then erase it + move it
|
||||
for (uint8_t f=0; f< NUMFLAKES; f++) {
|
||||
display.drawBitmap(icons[f][XPOS], icons[f][YPOS], logo16_glcd_bmp, w, h, WHITE);
|
||||
// move it
|
||||
icons[f][YPOS] += icons[f][DELTAY];
|
||||
// if its gone, reinit
|
||||
if (icons[f][YPOS] > display.height()) {
|
||||
icons[f][XPOS] = random(display.width());
|
||||
icons[f][YPOS] = 0;
|
||||
icons[f][DELTAY] = random(5) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void testdrawchar(void) {
|
||||
display.setTextSize(1);
|
||||
display.setTextColor(BLACK);
|
||||
display.setCursor(0,0);
|
||||
|
||||
for (uint8_t i=0; i < 168; i++) {
|
||||
if (i == '\n') continue;
|
||||
display.write(i);
|
||||
//if ((i > 0) && (i % 14 == 0))
|
||||
//display.println();
|
||||
}
|
||||
display.display();
|
||||
}
|
||||
|
||||
void testdrawcircle(void) {
|
||||
for (int16_t i=0; i<display.height(); i+=2) {
|
||||
display.drawCircle(display.width()/2, display.height()/2, i, BLACK);
|
||||
display.display();
|
||||
}
|
||||
}
|
||||
|
||||
void testfillrect(void) {
|
||||
uint8_t color = 1;
|
||||
for (int16_t i=0; i<display.height()/2; i+=3) {
|
||||
// alternate colors
|
||||
display.fillRect(i, i, display.width()-i*2, display.height()-i*2, color%2);
|
||||
display.display();
|
||||
color++;
|
||||
}
|
||||
}
|
||||
|
||||
void testdrawtriangle(void) {
|
||||
for (int16_t i=0; i<min(display.width(),display.height())/2; i+=5) {
|
||||
display.drawTriangle(display.width()/2, display.height()/2-i,
|
||||
display.width()/2-i, display.height()/2+i,
|
||||
display.width()/2+i, display.height()/2+i, BLACK);
|
||||
display.display();
|
||||
}
|
||||
}
|
||||
|
||||
void testfilltriangle(void) {
|
||||
uint8_t color = BLACK;
|
||||
for (int16_t i=min(display.width(),display.height())/2; i>0; i-=5) {
|
||||
display.fillTriangle(display.width()/2, display.height()/2-i,
|
||||
display.width()/2-i, display.height()/2+i,
|
||||
display.width()/2+i, display.height()/2+i, color);
|
||||
if (color == WHITE) color = BLACK;
|
||||
else color = WHITE;
|
||||
display.display();
|
||||
}
|
||||
}
|
||||
|
||||
void testdrawroundrect(void) {
|
||||
for (int16_t i=0; i<display.height()/2-2; i+=2) {
|
||||
display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, BLACK);
|
||||
display.display();
|
||||
}
|
||||
}
|
||||
|
||||
void testfillroundrect(void) {
|
||||
uint8_t color = BLACK;
|
||||
for (int16_t i=0; i<display.height()/2-2; i+=2) {
|
||||
display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, color);
|
||||
if (color == WHITE) color = BLACK;
|
||||
else color = WHITE;
|
||||
display.display();
|
||||
}
|
||||
}
|
||||
|
||||
void testdrawrect(void) {
|
||||
for (int16_t i=0; i<display.height()/2; i+=2) {
|
||||
display.drawRect(i, i, display.width()-2*i, display.height()-2*i, BLACK);
|
||||
display.display();
|
||||
}
|
||||
}
|
||||
|
||||
void testdrawline() {
|
||||
for (int16_t i=0; i<display.width(); i+=4) {
|
||||
display.drawLine(0, 0, i, display.height()-1, BLACK);
|
||||
display.display();
|
||||
}
|
||||
for (int16_t i=0; i<display.height(); i+=4) {
|
||||
display.drawLine(0, 0, display.width()-1, i, BLACK);
|
||||
display.display();
|
||||
}
|
||||
delay(250);
|
||||
|
||||
display.clearDisplay();
|
||||
for (int16_t i=0; i<display.width(); i+=4) {
|
||||
display.drawLine(0, display.height()-1, i, 0, BLACK);
|
||||
display.display();
|
||||
}
|
||||
for (int8_t i=display.height()-1; i>=0; i-=4) {
|
||||
display.drawLine(0, display.height()-1, display.width()-1, i, BLACK);
|
||||
display.display();
|
||||
}
|
||||
delay(250);
|
||||
|
||||
display.clearDisplay();
|
||||
for (int16_t i=display.width()-1; i>=0; i-=4) {
|
||||
display.drawLine(display.width()-1, display.height()-1, i, 0, BLACK);
|
||||
display.display();
|
||||
}
|
||||
for (int16_t i=display.height()-1; i>=0; i-=4) {
|
||||
display.drawLine(display.width()-1, display.height()-1, 0, i, BLACK);
|
||||
display.display();
|
||||
}
|
||||
delay(250);
|
||||
|
||||
display.clearDisplay();
|
||||
for (int16_t i=0; i<display.height(); i+=4) {
|
||||
display.drawLine(display.width()-1, 0, 0, i, BLACK);
|
||||
display.display();
|
||||
}
|
||||
for (int16_t i=0; i<display.width(); i+=4) {
|
||||
display.drawLine(display.width()-1, 0, i, display.height()-1, BLACK);
|
||||
display.display();
|
||||
}
|
||||
delay(250);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
Serial.println("PCD test");
|
||||
display.begin();
|
||||
// init done
|
||||
|
||||
// you can change the contrast around to adapt the display
|
||||
// for the best viewing!
|
||||
display.setContrast(75);
|
||||
|
||||
display.display(); // show splashscreen
|
||||
delay(2000);
|
||||
display.clearDisplay(); // clears the screen and buffer
|
||||
|
||||
// draw a single pixel
|
||||
display.drawPixel(10, 10, BLACK);
|
||||
display.display();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
// draw many lines
|
||||
testdrawline();
|
||||
display.display();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
// draw rectangles
|
||||
testdrawrect();
|
||||
display.display();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
// draw multiple rectangles
|
||||
testfillrect();
|
||||
display.display();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
// draw mulitple circles
|
||||
testdrawcircle();
|
||||
display.display();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
// draw a circle, 10 pixel radius
|
||||
display.fillCircle(display.width()/2, display.height()/2, 10, BLACK);
|
||||
display.display();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
testdrawroundrect();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
testfillroundrect();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
testdrawtriangle();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
testfilltriangle();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
// draw the first ~12 characters in the font
|
||||
testdrawchar();
|
||||
display.display();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
// text display tests
|
||||
display.setTextSize(1);
|
||||
display.setTextColor(BLACK);
|
||||
display.setCursor(0,0);
|
||||
display.println("Hello, world!");
|
||||
display.setTextColor(WHITE, BLACK); // 'inverted' text
|
||||
display.println(3.141592);
|
||||
display.setTextSize(2);
|
||||
display.setTextColor(BLACK);
|
||||
display.print("0x"); display.println(0xDEADBEEF, HEX);
|
||||
display.display();
|
||||
delay(2000);
|
||||
|
||||
// rotation example
|
||||
display.clearDisplay();
|
||||
display.setRotation(1); // rotate 90 degrees counter clockwise, can also use values of 2 and 3 to go further.
|
||||
display.setTextSize(1);
|
||||
display.setTextColor(BLACK);
|
||||
display.setCursor(0,0);
|
||||
display.println("Rotation");
|
||||
display.setTextSize(2);
|
||||
display.println("Example!");
|
||||
display.display();
|
||||
delay(2000);
|
||||
|
||||
// revert back to no rotation
|
||||
display.setRotation(0);
|
||||
|
||||
// miniature bitmap display
|
||||
display.clearDisplay();
|
||||
display.drawBitmap(30, 16, logo16_glcd_bmp, 16, 16, 1);
|
||||
display.display();
|
||||
|
||||
// invert the display
|
||||
display.invertDisplay(true);
|
||||
delay(1000);
|
||||
display.invertDisplay(false);
|
||||
delay(1000);
|
||||
|
||||
// draw a bitmap icon and 'animate' movement
|
||||
testdrawbitmap(logo16_glcd_bmp, LOGO16_GLCD_WIDTH, LOGO16_GLCD_HEIGHT);
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
name=Adafruit PCD8544 Nokia 5110 LCD library
|
||||
version=2.0.1
|
||||
author=Adafruit
|
||||
maintainer=Adafruit <info@adafruit.com>
|
||||
sentence=Arduino driver for PC8544, most commonly found in small Nokia 5110's
|
||||
paragraph=Arduino driver for PC8544, most commonly found in small Nokia 5110's
|
||||
category=Display
|
||||
url=https://github.com/adafruit/Adafruit-PCD8544-Nokia-5110-LCD-library
|
||||
architectures=*
|
||||
depends=Adafruit GFX Library, Adafruit BusIO
|
||||
@@ -0,0 +1,26 @@
|
||||
Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2012, Adafruit Industries
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -49,6 +49,7 @@ lib_deps =
|
||||
RAK12019_LTR390_UV_Light
|
||||
Adafruit NeoMatrix
|
||||
IthoCC1101
|
||||
Adafruit PCD8544 Nokia 5110 LCD library
|
||||
extra_scripts = post:tools/pio/post_esp32.py
|
||||
${extra_scripts_default.extra_scripts}
|
||||
build_unflags = -Wall
|
||||
|
||||
@@ -96,6 +96,7 @@ lib_deps =
|
||||
RAK12019_LTR390_UV_Light
|
||||
Adafruit NeoMatrix
|
||||
IthoCC1101
|
||||
Adafruit PCD8544 Nokia 5110 LCD library
|
||||
lib_ignore = ${esp82xx_defaults.lib_ignore}
|
||||
IRremoteESP8266
|
||||
HeatpumpIR
|
||||
|
||||
@@ -457,6 +457,7 @@ static const char DATA_ESPEASY_DEFAULT_MIN_CSS[] PROGMEM = {
|
||||
// #define USES_P134 // A02YYUW
|
||||
// #define USES_P135 // SCD4x
|
||||
// #define P135_FEATURE_RESET_COMMANDS 1 // Enable/Disable quite spacious (~950 bytes) 'selftest' and 'factoryreset' subcommands
|
||||
// #define USES_P141 // PCD8544 Nokia 5110 LCD
|
||||
|
||||
// #define USES_P128 // NeoPixelBusFX
|
||||
// #define P128_USES_GRB // Default
|
||||
|
||||
@@ -7,15 +7,19 @@
|
||||
// #######################################################################################################
|
||||
// ################################### Plugin 075: Nextion <info@sensorio.cz> ###########################
|
||||
// ################################### Created on the work of majklovec ###########################
|
||||
// ################################### Revisions by BertB and ThomasB ###########################
|
||||
// ################################### Last Revision: Oct-03-2018 (TB) ###########################
|
||||
// ################################### Revisions by BertB, ThomasB and others ###########################
|
||||
// ################################### Last Revision: 2022-09-27 ###########################
|
||||
// #######################################################################################################
|
||||
//
|
||||
// Updated: Oct-03-2018, ThomasB.
|
||||
// Added P075_DEBUG_LOG define to reduce info log messages and prevent serial log flooding.
|
||||
// Added SendStatus() to post log message on browser to acknowledge HTTP write.
|
||||
// Added reserve() to minimize string memory allocations.
|
||||
//
|
||||
|
||||
/** Changelog:
|
||||
* 2022-09-27 tonhuisman: Use Changelog formatted updates
|
||||
* Extend nr. of lines available for text/commands to 20, minor code improvements
|
||||
* Updated: Oct-03-2018, ThomasB.
|
||||
* Added P075_DEBUG_LOG define to reduce info log messages and prevent serial log flooding.
|
||||
* Added SendStatus() to post log message on browser to acknowledge HTTP write.
|
||||
* Added reserve() to minimize string memory allocations.
|
||||
*/
|
||||
|
||||
// *****************************************************************************************************
|
||||
// Defines start here
|
||||
@@ -26,11 +30,11 @@
|
||||
|
||||
// Plug-In defines
|
||||
# define PLUGIN_075
|
||||
# define PLUGIN_ID_075 75
|
||||
# define PLUGIN_NAME_075 "Display - Nextion"
|
||||
# define PLUGIN_DEFAULT_NAME "NEXTION"
|
||||
# define PLUGIN_VALUENAME1_075 "idx"
|
||||
# define PLUGIN_VALUENAME2_075 "value"
|
||||
# define PLUGIN_ID_075 75
|
||||
# define PLUGIN_NAME_075 "Display - Nextion"
|
||||
# define PLUGIN_DEFAULT_NAME "NEXTION"
|
||||
# define PLUGIN_VALUENAME1_075 "idx"
|
||||
# define PLUGIN_VALUENAME2_075 "value"
|
||||
|
||||
|
||||
// *****************************************************************************************************
|
||||
@@ -41,8 +45,6 @@ boolean Plugin_075(uint8_t function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
// static boolean AdvHwSerial = false; // Web GUI checkbox flag; false = softserial mode, true = hardware UART serial.
|
||||
|
||||
switch (function) {
|
||||
case PLUGIN_DEVICE_ADD: {
|
||||
Device[++deviceCount].Number = PLUGIN_ID_075;
|
||||
@@ -79,7 +81,6 @@ boolean Plugin_075(uint8_t function, struct EventStruct *event, String& string)
|
||||
|
||||
|
||||
case PLUGIN_GET_DEVICEGPIONAMES: {
|
||||
// AdvHwSerial = PCONFIG(0);
|
||||
serialHelper_getGpioNames(event);
|
||||
break;
|
||||
}
|
||||
@@ -112,7 +113,7 @@ boolean Plugin_075(uint8_t function, struct EventStruct *event, String& string)
|
||||
// Data += String(datax);
|
||||
// addFormNote(Data);
|
||||
|
||||
addFormSubHeader(""); // Blank line, vertical space.
|
||||
addFormSubHeader(F("")); // Blank line, vertical space.
|
||||
addFormHeader(F("Nextion Command Statements (Optional)"));
|
||||
P075_data_struct *P075_data = static_cast<P075_data_struct *>(getPluginTaskData(event->TaskIndex));
|
||||
|
||||
@@ -168,18 +169,20 @@ boolean Plugin_075(uint8_t function, struct EventStruct *event, String& string)
|
||||
// PCONFIG(0) = isFormItemChecked(F("AdvHwSerial"));
|
||||
P075_BaudRate = getFormItemInt(F("p075_baud"));
|
||||
P075_IncludeValues = isFormItemChecked(F("IncludeValues"));
|
||||
P075_data_struct *P075_data = static_cast<P075_data_struct *>(getPluginTaskData(event->TaskIndex));
|
||||
|
||||
if (nullptr != P075_data) {
|
||||
P075_data->loadDisplayLines(event->TaskIndex);
|
||||
}
|
||||
/* Task will be stopped and restarted, so no reason to reload the display here
|
||||
P075_data_struct *P075_data = static_cast<P075_data_struct *>(getPluginTaskData(event->TaskIndex));
|
||||
|
||||
if (nullptr != P075_data) {
|
||||
P075_data->loadDisplayLines(event->TaskIndex);
|
||||
}
|
||||
*/
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case PLUGIN_INIT: {
|
||||
// AdvHwSerial = PCONFIG(0);
|
||||
uint8_t BaudCode = P075_BaudRate;
|
||||
|
||||
if (BaudCode > P075_B115200) { BaudCode = P075_B9600; }
|
||||
@@ -264,10 +267,8 @@ boolean Plugin_075(uint8_t function, struct EventStruct *event, String& string)
|
||||
# ifdef P075_DEBUG_LOG
|
||||
String log;
|
||||
log.reserve(P75_Nchars + 50); // Prevent re-allocation
|
||||
log = F("NEXTION075 : Cmd Statement Line-");
|
||||
log += String(x + 1);
|
||||
log += F(" Sent: ");
|
||||
log += newString;
|
||||
log += concat(F("NEXTION075 : Cmd Statement Line-"), x + 1);
|
||||
log += concat(F(" Sent: "), newString);
|
||||
addLogMove(LOG_LEVEL_INFO, log);
|
||||
# endif // ifdef P075_DEBUG_LOG
|
||||
}
|
||||
@@ -275,22 +276,20 @@ boolean Plugin_075(uint8_t function, struct EventStruct *event, String& string)
|
||||
|
||||
// At Interval timer, send idx & value data only if user enabled "values" interval mode.
|
||||
if (P075_IncludeValues) {
|
||||
# ifdef P075_DEBUG_LOG
|
||||
# ifdef P075_DEBUG_LOG
|
||||
String log;
|
||||
log.reserve(120); // Prevent re-allocation
|
||||
log = F("NEXTION075: Interval values data enabled, resending idx=");
|
||||
log += formatUserVarNoCheck(event->TaskIndex, 0);
|
||||
log += F(", value=");
|
||||
log += formatUserVarNoCheck(event->TaskIndex, 1);
|
||||
log += concat(F("NEXTION075: Interval values data enabled, resending idx="), formatUserVarNoCheck(event->TaskIndex, 0));
|
||||
log += concat(F(", value="), formatUserVarNoCheck(event->TaskIndex, 1));
|
||||
addLogMove(LOG_LEVEL_INFO, log);
|
||||
# endif // ifdef P075_DEBUG_LOG
|
||||
# endif // ifdef P075_DEBUG_LOG
|
||||
|
||||
success = true;
|
||||
}
|
||||
else {
|
||||
# ifdef P075_DEBUG_LOG
|
||||
# ifdef P075_DEBUG_LOG
|
||||
addLog(LOG_LEVEL_INFO, F("NEXTION075: Interval values data disabled, idx & value not resent"));
|
||||
# endif // ifdef P075_DEBUG_LOG
|
||||
# endif // ifdef P075_DEBUG_LOG
|
||||
|
||||
success = false;
|
||||
}
|
||||
@@ -311,11 +310,10 @@ boolean Plugin_075(uint8_t function, struct EventStruct *event, String& string)
|
||||
{
|
||||
String log;
|
||||
log.reserve(24 + nextionArguments.length()); // Prevent re-allocation
|
||||
log = F("NEXTION075 : WRITE = ");
|
||||
log += nextionArguments;
|
||||
log += concat(F("NEXTION075 : WRITE = "), nextionArguments);
|
||||
# ifndef BUILD_NO_DEBUG
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
#endif
|
||||
# endif // ifndef BUILD_NO_DEBUG
|
||||
SendStatus(event, log); // Reply (echo) to sender. This will print message on browser.
|
||||
}
|
||||
|
||||
@@ -371,8 +369,7 @@ boolean Plugin_075(uint8_t function, struct EventStruct *event, String& string)
|
||||
if (charCount >= RXBUFFWARN) {
|
||||
String log;
|
||||
log.reserve(70); // Prevent re-allocation
|
||||
log += F("NEXTION075 : RxD P075_data->easySerial Buffer capacity warning, ");
|
||||
log += String(charCount);
|
||||
log += concat(F("NEXTION075 : RxD P075_data->easySerial Buffer capacity warning, "), charCount);
|
||||
log += F(" bytes");
|
||||
addLogMove(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
@@ -444,8 +441,7 @@ boolean Plugin_075(uint8_t function, struct EventStruct *event, String& string)
|
||||
# ifdef P075_DEBUG_LOG
|
||||
String log;
|
||||
log.reserve(50); // Prevent re-allocation
|
||||
log = F("NEXTION075 : Code = ");
|
||||
log += tmpString;
|
||||
log += concat(F("NEXTION075 : Code = "), tmpString);
|
||||
addLogMove(LOG_LEVEL_INFO, log);
|
||||
# endif // ifdef P075_DEBUG_LOG
|
||||
|
||||
@@ -488,19 +484,19 @@ boolean Plugin_075(uint8_t function, struct EventStruct *event, String& string)
|
||||
validFloatFromString(Svalue, UserVar[event->BaseVarIndex + 1]);
|
||||
sendData(event);
|
||||
|
||||
# ifdef P075_DEBUG_LOG
|
||||
# ifdef P075_DEBUG_LOG
|
||||
String log;
|
||||
log.reserve(80); // Prevent re-allocation
|
||||
log = F("NEXTION075 : Pipe Command Sent: ");
|
||||
log += F("NEXTION075 : Pipe Command Sent: ");
|
||||
log += __buffer;
|
||||
log += formatUserVarNoCheck(event->TaskIndex, 0);
|
||||
addLogMove(LOG_LEVEL_INFO, log);
|
||||
# endif // ifdef P075_DEBUG_LOG
|
||||
# endif // ifdef P075_DEBUG_LOG
|
||||
}
|
||||
else {
|
||||
# ifdef P075_DEBUG_LOG
|
||||
# ifdef P075_DEBUG_LOG
|
||||
addLog(LOG_LEVEL_INFO, F("NEXTION075 : Unknown Pipe Command, skipped"));
|
||||
# endif // ifdef P075_DEBUG_LOG
|
||||
# endif // ifdef P075_DEBUG_LOG
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
For following devices just a pull up resistor is needed if the device is used stand alone:
|
||||
UVR1611, UVR61-3 and ESR21
|
||||
|
||||
@tonhuisman 2022-09-24 Optimizations, suppress some logging for stressed builds
|
||||
@tonhuisman 2022-03-26 Add support for UVR42 (Very similar to an UVR31, has 1 extra sensor value and 1 extra digital value)
|
||||
|
||||
@uwekaditz 2020-12-028 documentation for UVR61-3 (v8.3 or higher)
|
||||
|
||||
@uwekaditz 2020-10-28 P092_data->init() is always done if P092_init == false, not depending on P092_data == nullptr
|
||||
@@ -71,7 +74,7 @@
|
||||
# define PLUGIN_VALUENAME1_092 "Value"
|
||||
|
||||
// global values needed for all tasks
|
||||
uint8_t P092_Last_DLB_Pin; // check if DL bus pin has been changed by one task -> change requires new init because of interrupt
|
||||
uint8_t P092_Last_DLB_Pin = 0xFF; // check if DL bus pin has been changed by one task -> change requires new init because of interrupt
|
||||
boolean P092_init = false; // P092_data_struct can be initialized only once, even if several tasks running
|
||||
P092_data_struct *P092_data = nullptr; // pointer to P092_data_struct, must be the same for all tasks
|
||||
|
||||
@@ -79,11 +82,6 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
|
||||
const String plugin_092_ValStr = F("p092_Value");
|
||||
const String plugin_092_IdxStr = F("p092_Idx");
|
||||
|
||||
|
||||
switch (function)
|
||||
{
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
@@ -132,27 +130,38 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string)
|
||||
choice = static_cast<uint8_t>(eP092pinmode::ePPM_InputPullUp);
|
||||
}
|
||||
}
|
||||
# ifdef INPUT_PULLDOWN
|
||||
int Opcount = 3;
|
||||
# else // ifdef INPUT_PULLDOWN
|
||||
int Opcount = 2;
|
||||
# endif // ifdef INPUT_PULLDOWN
|
||||
const __FlashStringHelper *options[3];
|
||||
options[0] = F("Input");
|
||||
options[1] = F("Input pullup");
|
||||
options[2] = F("Input pulldown");
|
||||
int optionValues[3] =
|
||||
{ static_cast<int>(eP092pinmode::ePPM_Input),
|
||||
# ifdef INPUT_PULLDOWN
|
||||
# define Opcount 3
|
||||
# else // ifdef INPUT_PULLDOWN
|
||||
# define Opcount 2
|
||||
# endif // ifdef INPUT_PULLDOWN
|
||||
const __FlashStringHelper *options[] = {
|
||||
F("Input"),
|
||||
F("Input pullup"),
|
||||
# ifdef INPUT_PULLDOWN
|
||||
F("Input pulldown"),
|
||||
# endif // ifdef INPUT_PULLDOWN
|
||||
};
|
||||
const int optionValues[] = {
|
||||
static_cast<int>(eP092pinmode::ePPM_Input),
|
||||
static_cast<int>(eP092pinmode::ePPM_InputPullUp),
|
||||
static_cast<int>(eP092pinmode::ePPM_InputPullDown) };
|
||||
addFormSelector(F("Pin mode"), F("p092_pinmode"), Opcount, options, optionValues, choice);
|
||||
# ifdef INPUT_PULLDOWN
|
||||
static_cast<int>(eP092pinmode::ePPM_InputPullDown),
|
||||
# endif // ifdef INPUT_PULLDOWN
|
||||
};
|
||||
addFormSelector(F("Pin mode"), F("ppinmode"), Opcount, options, optionValues, choice);
|
||||
}
|
||||
{
|
||||
const __FlashStringHelper *Devices[P092_DLbus_DeviceCount] = { F("ESR21"), F("UVR31"), F("UVR1611"), F("UVR 61-3 (up to v8.2)"), F(
|
||||
"UVR 61-3 (v8.3 or higher)") };
|
||||
const int DevTypes[P092_DLbus_DeviceCount] = { 21, 31, 1611, 6132, 6133 };
|
||||
const __FlashStringHelper *Devices[P092_DLbus_DeviceCount] = {
|
||||
F("ESR21"),
|
||||
F("UVR31"),
|
||||
F("UVR42"),
|
||||
F("UVR1611"),
|
||||
F("UVR 61-3 (up to v8.2)"),
|
||||
F("UVR 61-3 (v8.3 or higher)") };
|
||||
const int DevTypes[P092_DLbus_DeviceCount] = { 21, 31, 42, 1611, 6132, 6133 };
|
||||
|
||||
addFormSelector(F("DL-Bus Type"), F("p092_dlbtype"), P092_DLbus_DeviceCount, Devices, DevTypes, nullptr, PCONFIG(0), true);
|
||||
addFormSelector(F("DL-Bus Type"), F("pdlbtype"), P092_DLbus_DeviceCount, Devices, DevTypes, nullptr, PCONFIG(0), true);
|
||||
}
|
||||
{
|
||||
int P092_ValueType, P092_ValueIdx;
|
||||
@@ -201,6 +210,10 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string)
|
||||
P092_MaxIdx[6] = 1; // Heat power (kW)
|
||||
P092_MaxIdx[7] = 1; // Heat meter (MWh)
|
||||
break;
|
||||
case 42: // UVR42
|
||||
P092_MaxIdx[1] = 4; // Sensor
|
||||
P092_MaxIdx[3] = 2; // Digital output
|
||||
break;
|
||||
case 1611: // UVR1611
|
||||
P092_MaxIdx[1] = 16; // Sensor
|
||||
P092_MaxIdx[3] = 13; // Digital output
|
||||
@@ -233,7 +246,7 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string)
|
||||
P092_ValueIdx = PCONFIG(1) & 0x00FF;
|
||||
|
||||
addFormSelector(plugin_092_DefValueName,
|
||||
plugin_092_ValStr,
|
||||
F("pValue"),
|
||||
P092_DLbus_OptionCount,
|
||||
Options,
|
||||
P092_OptionTypes,
|
||||
@@ -252,7 +265,7 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string)
|
||||
CurIdx = P092_MaxIdx[P092_ValueType];
|
||||
}
|
||||
addHtml(F(" Index: "));
|
||||
addNumericBox(plugin_092_IdxStr, CurIdx, 1, P092_MaxIdx[P092_ValueType]);
|
||||
addNumericBox(F("pIdx"), CurIdx, 1, P092_MaxIdx[P092_ValueType]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,14 +289,14 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string)
|
||||
4 // [0,0001MWh] F("Heat meter (MWh)")
|
||||
};
|
||||
|
||||
PCONFIG(0) = getFormItemInt(F("p092_dlbtype"));
|
||||
PCONFIG(0) = getFormItemInt(F("pdlbtype"));
|
||||
|
||||
if (PCONFIG(0) == 1611) { // only UVR1611
|
||||
P092_OptionValueDecimals[6] = 2;
|
||||
}
|
||||
|
||||
int OptionIdx = getFormItemInt(plugin_092_ValStr);
|
||||
int CurIdx = getFormItemInt(plugin_092_IdxStr);
|
||||
int OptionIdx = getFormItemInt(F("pValue"));
|
||||
int CurIdx = getFormItemInt(F("pIdx"));
|
||||
|
||||
if (CurIdx < 1) {
|
||||
CurIdx = 1;
|
||||
@@ -291,7 +304,7 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string)
|
||||
PCONFIG(1) = (OptionIdx << 8) + CurIdx;
|
||||
ExtraTaskSettings.TaskDeviceValueDecimals[event->BaseVarIndex] = P092_OptionValueDecimals[OptionIdx];
|
||||
|
||||
PCONFIG(2) = getFormItemInt(F("p092_pinmode"));
|
||||
PCONFIG(2) = getFormItemInt(F("ppinmode"));
|
||||
|
||||
if (nullptr == P092_data) {
|
||||
addLog(LOG_LEVEL_ERROR, F("## P092_save: Error DL-Bus: Class not initialized!"));
|
||||
@@ -306,11 +319,13 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string)
|
||||
// interrupt was already attached to P092_DLB_Pin
|
||||
P092_data->DLbus_Data->IsISRset = false; // to ensure that a new interrupt is attached in P092_data->init()
|
||||
detachInterrupt(digitalPinToInterrupt(P092_data->DLbus_Data->ISR_DLB_Pin));
|
||||
# ifndef LIMIT_BUILD_SIZE
|
||||
addLog(LOG_LEVEL_INFO, F("P092_save: detachInterrupt"));
|
||||
# endif // ifndef LIMIT_BUILD_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef PLUGIN_092_DEBUG
|
||||
# ifdef PLUGIN_092_DEBUG
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
String log = F("PLUGIN_WEBFORM_SAVE :");
|
||||
@@ -381,7 +396,7 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string)
|
||||
log += P092_data->P092_DataSettings.IdxCRC;
|
||||
addLogMove(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
# endif // PLUGIN_092_DEBUG
|
||||
# endif // PLUGIN_092_DEBUG
|
||||
UserVar[event->BaseVarIndex] = NAN;
|
||||
success = true;
|
||||
break;
|
||||
@@ -390,9 +405,7 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string)
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
String log = F("PLUGIN_092_INIT Task:");
|
||||
log += event->TaskIndex;
|
||||
addLogMove(LOG_LEVEL_INFO, log);
|
||||
addLogMove(LOG_LEVEL_INFO, concat(F("PLUGIN_092_INIT Task:"), event->TaskIndex));
|
||||
}
|
||||
|
||||
if (P092_init) {
|
||||
@@ -400,7 +413,9 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string)
|
||||
}
|
||||
else {
|
||||
if (P092_data == nullptr) {
|
||||
# ifndef LIMIT_BUILD_SIZE
|
||||
addLog(LOG_LEVEL_INFO, F("Create P092_data_struct ..."));
|
||||
# endif // ifndef LIMIT_BUILD_SIZE
|
||||
|
||||
P092_data = new (std::nothrow) P092_data_struct();
|
||||
initPluginTaskData(event->TaskIndex, P092_data);
|
||||
@@ -409,16 +424,19 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string)
|
||||
addLog(LOG_LEVEL_ERROR, F("## P092_init: Create P092_data_struct failed!"));
|
||||
return false;
|
||||
}
|
||||
# ifndef LIMIT_BUILD_SIZE
|
||||
}
|
||||
else {
|
||||
addLog(LOG_LEVEL_INFO, F("P092_data_struct -> Already created"));
|
||||
# endif // ifndef LIMIT_BUILD_SIZE
|
||||
}
|
||||
P092_data_struct *P092_data =
|
||||
static_cast<P092_data_struct *>(getPluginTaskData(event->TaskIndex));
|
||||
P092_data_struct *P092_data = static_cast<P092_data_struct *>(getPluginTaskData(event->TaskIndex));
|
||||
|
||||
# ifndef LIMIT_BUILD_SIZE
|
||||
addLog(LOG_LEVEL_INFO, F("Init P092_data_struct ..."));
|
||||
# endif // ifndef LIMIT_BUILD_SIZE
|
||||
|
||||
if (!P092_data->init(CONFIG_PIN1, PCONFIG(0), eP092pinmode PCONFIG(2))) {
|
||||
if (!P092_data->init(CONFIG_PIN1, PCONFIG(0), static_cast<eP092pinmode>(PCONFIG(2)))) {
|
||||
addLog(LOG_LEVEL_ERROR, F("## P092_init: Error DL-Bus: Class not initialized!"));
|
||||
clearPluginTaskData(event->TaskIndex);
|
||||
return false;
|
||||
@@ -438,7 +456,7 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (P092_init == false) {
|
||||
if (!P092_init) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -449,7 +467,9 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string)
|
||||
if (!P092_data->DLbus_Data->IsISRset) {
|
||||
// on a CHANGE on the data pin P092_Pin_changed is called
|
||||
P092_data->DLbus_Data->attachDLBusInterrupt();
|
||||
# ifndef LIMIT_BUILD_SIZE
|
||||
addLog(LOG_LEVEL_INFO, F("P092 ISR set"));
|
||||
# endif // ifndef LIMIT_BUILD_SIZE
|
||||
}
|
||||
|
||||
if (P092_data->DLbus_Data->ISR_Receiving) {
|
||||
@@ -472,10 +492,9 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string)
|
||||
|
||||
if (success) {
|
||||
P092_data->P092_LastReceived = millis();
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
String log = F("Received data OK TI:");
|
||||
log += event->TaskIndex;
|
||||
addLogMove(LOG_LEVEL_INFO, log);
|
||||
addLogMove(LOG_LEVEL_INFO, concat(F("Received data OK TI:"), event->TaskIndex));
|
||||
}
|
||||
}
|
||||
P092_data->P092_ReceivedOK = success;
|
||||
@@ -484,8 +503,8 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string)
|
||||
success = P092_data->P092_ReceivedOK;
|
||||
}
|
||||
|
||||
if ((P092_data->DLbus_Data->IsNoData == false) &&
|
||||
((P092_data->P092_ReceivedOK == false) ||
|
||||
if ((!P092_data->DLbus_Data->IsNoData) &&
|
||||
((!P092_data->P092_ReceivedOK) ||
|
||||
(timePassedSince(P092_data->P092_LastReceived) > (static_cast<long>(Settings.TaskDeviceTimer[event->TaskIndex] * 1000 / 2))))) {
|
||||
P092_data->Plugin_092_StartReceiving(event->TaskIndex);
|
||||
success = true;
|
||||
@@ -495,11 +514,12 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_READ:
|
||||
{
|
||||
# ifndef LIMIT_BUILD_SIZE
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
String log = F("PLUGIN_092_READ Task:");
|
||||
log += event->TaskIndex;
|
||||
addLogMove(LOG_LEVEL_INFO, log);
|
||||
addLogMove(LOG_LEVEL_INFO, concat(F("PLUGIN_092_READ Task:"), event->TaskIndex));
|
||||
}
|
||||
# endif // ifndef LIMIT_BUILD_SIZE
|
||||
|
||||
if (!NetworkConnected()) {
|
||||
// too busy for DLbus while wifi connect is running
|
||||
@@ -507,7 +527,7 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (P092_init == false) {
|
||||
if (!P092_init) {
|
||||
addLog(LOG_LEVEL_ERROR, F("## P092_read: Error DL-Bus: Not initialized!"));
|
||||
return false;
|
||||
}
|
||||
@@ -519,8 +539,8 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string)
|
||||
|
||||
if (P092_data->DLbus_Data->ISR_DLB_Pin != CONFIG_PIN1) {
|
||||
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
|
||||
String log = F("## P092_read: Error DL-Bus: Device Pin setting not correct!");
|
||||
log += F(" DLB_Pin:");
|
||||
String log;
|
||||
log += F("## P092_read: Error DL-Bus: Device Pin setting not correct! DLB_Pin:");
|
||||
log += P092_data->DLbus_Data->ISR_DLB_Pin;
|
||||
log += F(" Setting:");
|
||||
log += CONFIG_PIN1;
|
||||
@@ -542,9 +562,9 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string)
|
||||
|
||||
success = P092_data->P092_ReceivedOK;
|
||||
|
||||
if (P092_data->P092_ReceivedOK == false) {
|
||||
if (!P092_data->P092_ReceivedOK) {
|
||||
addLog(LOG_LEVEL_INFO, F("P092_read: Still receiving DL-Bus bits!"));
|
||||
return true;
|
||||
success = true;
|
||||
}
|
||||
else {
|
||||
P092_data_struct::sP092_ReadData P092_ReadData;
|
||||
@@ -562,6 +582,7 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,356 @@
|
||||
#include "_Plugin_Helper.h"
|
||||
|
||||
#ifdef USES_P141
|
||||
|
||||
// #######################################################################################################
|
||||
// ########################### Plugin 141: PCD8544 Nokia 5110 LCD display ################################
|
||||
// #######################################################################################################
|
||||
|
||||
|
||||
/** Changelog:
|
||||
* 2022-10-08 tonhuisman: Enable PLUGIN_GET_CONFIG_VALUE event to get runtime info from plugin
|
||||
* 2022-09-24 tonhuisman: Store inverted setting when changed via inv subcommand (not saved)
|
||||
* 2022-09-23 tonhuisman: Allow backlight form 0% instead of from 1% to be able to completely turn it off
|
||||
* Allow contrast setting from 0..100%.
|
||||
* 2022-09-21 tonhuisman: Allow contrast setting from 1..100%, add contrast subcommand
|
||||
* 2022-09-19 tonhuisman: Skip empty Lines (don't clear display line) on TaskRun/PLUGIN_READ
|
||||
* 2022-09-12 tonhuisman: Remove unneeded color settings, as we have the Inverted display option
|
||||
* 2022-09-11 tonhuisman: Disable some less needed features to reduce .bin size, remove Cursor X/Y Values for challenged builds
|
||||
* remove unused Splash feature code (was already disabled)
|
||||
* 2022-09-10 tonhuisman: Add configurable line spacing for configured Lines (user request), clear screen when using the 'off' subcommand
|
||||
* 2022-08-25 tonhuisman: Remove strange option 'tft' for command trigger, as this has nothing to with a tft display
|
||||
* Clear screen with correct color on exit when inverted is active
|
||||
* 2022-08-23 tonhuisman: Add <trigger>cmd,inv[,0|1] subcommand for inverting the display, also an extra Config option
|
||||
* is added to set 'Invert display' as the default.
|
||||
* 2022-08-20 tonhuisman: Migrate/rewrite from ESPEasy PluginPlayground _P208_Nokia_LCD_5110.ino, now based
|
||||
* on Plugin 116 ST77xx
|
||||
*/
|
||||
|
||||
# define PLUGIN_141
|
||||
# define PLUGIN_ID_141 141
|
||||
# define PLUGIN_NAME_141 "Display - PCD8544 Nokia 5110 LCD"
|
||||
# define PLUGIN_VALUENAME1_141 "CursorX"
|
||||
# define PLUGIN_VALUENAME2_141 "CursorY"
|
||||
|
||||
# include "src/PluginStructs/P141_data_struct.h"
|
||||
|
||||
boolean Plugin_141(uint8_t function, struct EventStruct *event, String& string)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_141;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_SPI3;
|
||||
Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_NONE;
|
||||
Device[deviceCount].Ports = 0;
|
||||
Device[deviceCount].PullUpOption = false;
|
||||
Device[deviceCount].InverseLogicOption = false;
|
||||
Device[deviceCount].FormulaOption = false;
|
||||
# if P141_FEATURE_CURSOR_XY_VALUES
|
||||
Device[deviceCount].ValueCount = 2;
|
||||
# endif // if P141_FEATURE_CURSOR_XY_VALUES
|
||||
Device[deviceCount].SendDataOption = false;
|
||||
Device[deviceCount].TimerOption = true;
|
||||
Device[deviceCount].TimerOptional = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_141);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
# if P141_FEATURE_CURSOR_XY_VALUES
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_141));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_141));
|
||||
# endif // if P141_FEATURE_CURSOR_XY_VALUES
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEGPIONAMES:
|
||||
{
|
||||
event->String1 = formatGpioName_output(F("SCE"));
|
||||
event->String2 = formatGpioName_output(F("D/C"));
|
||||
event->String3 = formatGpioName_output_optional(F("RST "));
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_SET_DEFAULTS:
|
||||
{
|
||||
# ifdef ESP32
|
||||
|
||||
if (Settings.InitSPI == 2) { // When using ESP32 H(ardware-)SPI
|
||||
P141_CS_PIN = P141_LCD_CS_HSPI;
|
||||
} else
|
||||
# endif // ifdef ESP32
|
||||
{
|
||||
P141_CS_PIN = P141_LCD_CS;
|
||||
}
|
||||
P141_DC_PIN = P141_LCD_DC;
|
||||
P141_RST_PIN = P141_LCD_RST;
|
||||
P141_CONFIG_BUTTON_PIN = -1;
|
||||
P141_CONFIG_BACKLIGHT_PIN = -1;
|
||||
P141_CONFIG_BACKLIGHT_PERCENT = 50; // Percentage backlight
|
||||
P141_CONFIG_CONTRAST = 60; // 60% seems to be properly visible, but may depend on the actual display
|
||||
|
||||
uint32_t lSettings = 0;
|
||||
|
||||
// Clear then Truncate exceeding message
|
||||
set4BitToUL(lSettings, P141_CONFIG_FLAG_MODE, static_cast<int>(AdaGFXTextPrintMode::ClearThenTruncate));
|
||||
set4BitToUL(lSettings, P141_CONFIG_FLAG_FONTSCALE, 1);
|
||||
set4BitToUL(lSettings, P141_CONFIG_FLAG_LINESPACING, 15); // Auto
|
||||
set4BitToUL(lSettings, P141_CONFIG_FLAG_CMD_TRIGGER, static_cast<int>(P141_CommandTrigger::pcd8544));
|
||||
bitWrite(lSettings, P141_CONFIG_FLAG_BACK_FILL, 1); // No back-fill
|
||||
P141_CONFIG_FLAGS = lSettings;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
AdaGFXFormBacklight(F("pbacklight"), P141_CONFIG_BACKLIGHT_PIN,
|
||||
F("pbackpercent"), P141_CONFIG_BACKLIGHT_PERCENT);
|
||||
|
||||
addFormNumericBox(F("Display Contrast"), F("pcontrast"), P141_CONFIG_CONTRAST, 0, 100);
|
||||
addUnit(F("0-100%"));
|
||||
|
||||
AdaGFXFormDisplayButton(F("pbutton"), P141_CONFIG_BUTTON_PIN,
|
||||
F("pbtnInverse"), bitRead(P141_CONFIG_FLAGS, P141_CONFIG_FLAG_INVERT_BUTTON),
|
||||
F("ptimer"), P141_CONFIG_DISPLAY_TIMEOUT);
|
||||
|
||||
addFormSubHeader(F("Layout"));
|
||||
|
||||
AdaGFXFormRotation(F("protate"), P141_CONFIG_FLAG_GET_ROTATION);
|
||||
|
||||
AdaGFXFormTextPrintMode(F("pmode"), P141_CONFIG_FLAG_GET_MODE);
|
||||
|
||||
AdaGFXFormFontScaling(F("pfontscale"), P141_CONFIG_FLAG_GET_FONTSCALE);
|
||||
|
||||
addFormCheckBox(F("Invert display"), F("pinvert"), bitRead(P141_CONFIG_FLAGS, P141_CONFIG_FLAG_INVERTED));
|
||||
|
||||
addFormCheckBox(F("Clear display on exit"), F("pclearOnExit"), bitRead(P141_CONFIG_FLAGS, P141_CONFIG_FLAG_CLEAR_ON_EXIT));
|
||||
|
||||
{
|
||||
const __FlashStringHelper *commandTriggers[] = { // Be sure to use all options available in the enum
|
||||
toString(P141_CommandTrigger::pcd8544),
|
||||
toString(P141_CommandTrigger::lcd),
|
||||
};
|
||||
const int commandTriggerOptions[] = {
|
||||
static_cast<int>(P141_CommandTrigger::pcd8544),
|
||||
static_cast<int>(P141_CommandTrigger::lcd),
|
||||
};
|
||||
addFormSelector(F("Write Command trigger"),
|
||||
F("pcmdtrigger"),
|
||||
sizeof(commandTriggerOptions) / sizeof(int),
|
||||
commandTriggers,
|
||||
commandTriggerOptions,
|
||||
P141_CONFIG_FLAG_GET_CMD_TRIGGER);
|
||||
# ifndef LIMIT_BUILD_SIZE
|
||||
addFormNote(F("Select the command that is used to handle commands for this display."));
|
||||
# endif // ifndef LIMIT_BUILD_SIZE
|
||||
}
|
||||
|
||||
// Inverted state!
|
||||
addFormCheckBox(F("Wake display on receiving text"), F("pNoDisplay"), !bitRead(P141_CONFIG_FLAGS, P141_CONFIG_FLAG_NO_WAKE));
|
||||
# ifndef LIMIT_BUILD_SIZE
|
||||
addFormNote(F("When checked, the display wakes up at receiving remote updates."));
|
||||
# endif // ifndef LIMIT_BUILD_SIZE
|
||||
|
||||
AdaGFXFormTextColRowMode(F("pcolrow"), bitRead(P141_CONFIG_FLAGS, P141_CONFIG_FLAG_USE_COL_ROW) == 1);
|
||||
|
||||
AdaGFXFormTextBackgroundFill(F("pbackfill"), bitRead(P141_CONFIG_FLAGS, P141_CONFIG_FLAG_BACK_FILL) == 0); // Inverse
|
||||
|
||||
addFormSubHeader(F("Content"));
|
||||
|
||||
String strings[P141_Nlines];
|
||||
LoadCustomTaskSettings(event->TaskIndex, strings, P141_Nlines, 0);
|
||||
|
||||
# ifndef LIMIT_BUILD_SIZE
|
||||
uint16_t remain = P141_Nlines * (P141_Nchars + 1); // DAT_TASKS_CUSTOM_SIZE;
|
||||
# endif // ifndef LIMIT_BUILD_SIZE
|
||||
|
||||
for (uint8_t varNr = 0; varNr < P141_Nlines; varNr++) {
|
||||
addFormTextBox(concat(F("Line "), varNr + 1), getPluginCustomArgName(varNr), strings[varNr], P141_Nchars);
|
||||
# ifndef LIMIT_BUILD_SIZE
|
||||
remain -= (strings[varNr].length() + 1);
|
||||
# endif // ifndef LIMIT_BUILD_SIZE
|
||||
}
|
||||
# ifndef LIMIT_BUILD_SIZE
|
||||
addUnit(concat(F("Remaining: "), remain));
|
||||
# endif // ifndef LIMIT_BUILD_SIZE
|
||||
|
||||
AdaGFXFormLineSpacing(F("linespc"), P141_CONFIG_FLAG_GET_LINESPACING);
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
P141_CONFIG_BUTTON_PIN = getFormItemInt(F("pbutton"));
|
||||
P141_CONFIG_DISPLAY_TIMEOUT = getFormItemInt(F("ptimer"));
|
||||
P141_CONFIG_BACKLIGHT_PIN = getFormItemInt(F("pbacklight"));
|
||||
P141_CONFIG_BACKLIGHT_PERCENT = getFormItemInt(F("pbackpercent"));
|
||||
P141_CONFIG_CONTRAST = getFormItemInt(F("pcontrast"));
|
||||
|
||||
uint32_t lSettings = 0;
|
||||
bitWrite(lSettings, P141_CONFIG_FLAG_NO_WAKE, !isFormItemChecked(F("pNoDisplay"))); // Bit 0 NoDisplayOnReceivingText,
|
||||
// reverse logic, default=checked!
|
||||
bitWrite(lSettings, P141_CONFIG_FLAG_INVERT_BUTTON, isFormItemChecked(F("pbtnInverse"))); // Bit 1 buttonInverse
|
||||
bitWrite(lSettings, P141_CONFIG_FLAG_CLEAR_ON_EXIT, isFormItemChecked(F("pclearOnExit"))); // Bit 2 ClearOnExit
|
||||
bitWrite(lSettings, P141_CONFIG_FLAG_USE_COL_ROW, isFormItemChecked(F("pcolrow"))); // Bit 3 Col/Row addressing
|
||||
|
||||
set4BitToUL(lSettings, P141_CONFIG_FLAG_MODE, getFormItemInt(F("pmode"))); // Bit 4..7 Text print mode
|
||||
set4BitToUL(lSettings, P141_CONFIG_FLAG_ROTATION, getFormItemInt(F("protate"))); // Bit 8..11 Rotation
|
||||
set4BitToUL(lSettings, P141_CONFIG_FLAG_FONTSCALE, getFormItemInt(F("pfontscale"))); // Bit 12..15 Font scale
|
||||
set4BitToUL(lSettings, P141_CONFIG_FLAG_LINESPACING, getFormItemInt(F("linespc"))); // Bit 16..19 Line spacing
|
||||
set4BitToUL(lSettings, P141_CONFIG_FLAG_CMD_TRIGGER, getFormItemInt(F("pcmdtrigger"))); // Bit 20..23 Command trigger
|
||||
|
||||
bitWrite(lSettings, P141_CONFIG_FLAG_BACK_FILL, !isFormItemChecked(F("pbackfill"))); // Bit 28 Back fill text (inv)
|
||||
bitWrite(lSettings, P141_CONFIG_FLAG_INVERTED, isFormItemChecked(F("pinvert"))); // Bit 29 Invert display
|
||||
P141_CONFIG_FLAGS = lSettings;
|
||||
|
||||
String strings[P141_Nlines];
|
||||
String error;
|
||||
|
||||
for (uint8_t varNr = 0; varNr < P141_Nlines; varNr++) {
|
||||
strings[varNr] = web_server.arg(getPluginCustomArgName(varNr));
|
||||
}
|
||||
|
||||
error = SaveCustomTaskSettings(event->TaskIndex, strings, P141_Nlines, 0);
|
||||
|
||||
if (!error.isEmpty()) {
|
||||
addHtmlError(error);
|
||||
}
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DISPLAY_PARAMETERS:
|
||||
{
|
||||
event->Par1 = 84; // X-resolution in pixels
|
||||
event->Par2 = 48; // Y-resolution in pixels
|
||||
event->Par3 = P141_CONFIG_FLAG_GET_ROTATION; // Rotation (0..3: 0, 90, 180, 270 degrees)
|
||||
event->Par4 = static_cast<int>(AdaGFXColorDepth::Monochrome); // Color depth
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
if (Settings.InitSPI != 0) {
|
||||
initPluginTaskData(event->TaskIndex,
|
||||
new (std::nothrow) P141_data_struct(P141_CONFIG_FLAG_GET_ROTATION,
|
||||
P141_CONFIG_FLAG_GET_FONTSCALE,
|
||||
static_cast<AdaGFXTextPrintMode>(P141_CONFIG_FLAG_GET_MODE),
|
||||
P141_CONFIG_BACKLIGHT_PIN,
|
||||
P141_CONFIG_BACKLIGHT_PERCENT,
|
||||
P141_CONFIG_CONTRAST,
|
||||
P141_CONFIG_DISPLAY_TIMEOUT,
|
||||
toString(static_cast<P141_CommandTrigger>(
|
||||
P141_CONFIG_FLAG_GET_CMD_TRIGGER)),
|
||||
ADAGFX_WHITE,
|
||||
ADAGFX_BLACK,
|
||||
bitRead(P141_CONFIG_FLAGS, P141_CONFIG_FLAG_BACK_FILL) == 0,
|
||||
bitRead(P141_CONFIG_FLAGS, P141_CONFIG_FLAG_INVERTED) == 1));
|
||||
P141_data_struct *P141_data = static_cast<P141_data_struct *>(getPluginTaskData(event->TaskIndex));
|
||||
|
||||
if (nullptr != P141_data) {
|
||||
success = P141_data->plugin_init(event); // Start the display
|
||||
}
|
||||
# ifndef LIMIT_BUILD_SIZE
|
||||
} else {
|
||||
addLog(LOG_LEVEL_ERROR, F("PCD8544: SPI not enabled."));
|
||||
# endif // ifndef LIMIT_BUILD_SIZE
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_EXIT:
|
||||
{
|
||||
P141_data_struct *P141_data = static_cast<P141_data_struct *>(getPluginTaskData(event->TaskIndex));
|
||||
|
||||
if (nullptr != P141_data) {
|
||||
success = P141_data->plugin_exit(event); // Stop the display
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Check more often for debouncing the button, when enabled
|
||||
case PLUGIN_FIFTY_PER_SECOND:
|
||||
{
|
||||
if (P141_CONFIG_BUTTON_PIN != -1) {
|
||||
P141_data_struct *P141_data = static_cast<P141_data_struct *>(getPluginTaskData(event->TaskIndex));
|
||||
|
||||
if (nullptr != P141_data) {
|
||||
P141_data->registerButtonState(digitalRead(P141_CONFIG_BUTTON_PIN), bitRead(P141_CONFIG_FLAGS, P141_CONFIG_FLAG_INVERT_BUTTON));
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_TEN_PER_SECOND:
|
||||
{
|
||||
P141_data_struct *P141_data = static_cast<P141_data_struct *>(getPluginTaskData(event->TaskIndex));
|
||||
|
||||
if (nullptr != P141_data) {
|
||||
success = P141_data->plugin_ten_per_second(event); // 10 per second actions
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_ONCE_A_SECOND:
|
||||
{
|
||||
P141_data_struct *P141_data = static_cast<P141_data_struct *>(getPluginTaskData(event->TaskIndex));
|
||||
|
||||
if (nullptr != P141_data) {
|
||||
success = P141_data->plugin_once_a_second(event); // Once a second actions
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_READ:
|
||||
{
|
||||
P141_data_struct *P141_data = static_cast<P141_data_struct *>(getPluginTaskData(event->TaskIndex));
|
||||
|
||||
if (nullptr != P141_data) {
|
||||
success = P141_data->plugin_read(event); // Read operation, redisplay the configured content
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WRITE:
|
||||
{
|
||||
P141_data_struct *P141_data = static_cast<P141_data_struct *>(getPluginTaskData(event->TaskIndex));
|
||||
|
||||
if (nullptr != P141_data) {
|
||||
success = P141_data->plugin_write(event, string); // Write operation, handle commands, mostly delegated to AdafruitGFX_helper
|
||||
}
|
||||
break;
|
||||
}
|
||||
# if ADAGFX_ENABLE_GET_CONFIG_VALUE
|
||||
case PLUGIN_GET_CONFIG_VALUE:
|
||||
{
|
||||
P141_data_struct *P141_data = static_cast<P141_data_struct *>(getPluginTaskData(event->TaskIndex));
|
||||
|
||||
if (nullptr != P141_data) {
|
||||
success = P141_data->plugin_get_config_value(event, string); // GetConfig operation, handle variables, fully delegated to
|
||||
// AdafruitGFX_helper
|
||||
}
|
||||
break;
|
||||
}
|
||||
# endif // if ADAGFX_ENABLE_GET_CONFIG_VALUE
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
#endif // USES_P141
|
||||
@@ -51,7 +51,7 @@ bool validateAndParseTaskValueArguments(struct EventStruct * event, const char *
|
||||
String taskName;
|
||||
taskIndex_t tmpTaskIndex = taskIndex;
|
||||
if ((event->Par1 <= 0 || event->Par1 >= INVALID_TASK_INDEX) && GetArgv(Line, taskName, 2)) {
|
||||
tmpTaskIndex = findTaskIndexByName(taskName);
|
||||
tmpTaskIndex = findTaskIndexByName(taskName, true);
|
||||
if (tmpTaskIndex != INVALID_TASK_INDEX) {
|
||||
event->Par1 = tmpTaskIndex + 1;
|
||||
}
|
||||
|
||||
@@ -1442,7 +1442,7 @@ To create/register a plugin, you have to :
|
||||
#define LIMIT_BUILD_SIZE // Reduce buildsize (on ESP8266 / pre-IDF4.x) to fit in all Display plugins
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(FEATURE_SD)
|
||||
#if !defined(FEATURE_SD) && !defined(ESP8266)
|
||||
#define FEATURE_SD 1
|
||||
#endif
|
||||
#ifndef USES_P012
|
||||
@@ -1490,6 +1490,9 @@ To create/register a plugin, you have to :
|
||||
#ifndef USES_P116
|
||||
#define USES_P116 // ST77xx
|
||||
#endif
|
||||
#ifndef USES_P141
|
||||
#define USES_P141 // PCD8544 Nokia 5110
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Collection of all climate plugins.
|
||||
@@ -1895,6 +1898,24 @@ To create/register a plugin, you have to :
|
||||
#ifndef USES_P135
|
||||
// #define USES_P135 //
|
||||
#endif
|
||||
#ifndef USES_P136
|
||||
// #define USES_P136 //
|
||||
#endif
|
||||
#ifndef USES_P137
|
||||
// #define USES_P137 //
|
||||
#endif
|
||||
#ifndef USES_P138
|
||||
// #define USES_P138 //
|
||||
#endif
|
||||
#ifndef USES_P139
|
||||
// #define USES_P139 //
|
||||
#endif
|
||||
#ifndef USES_P140
|
||||
// #define USES_P140 //
|
||||
#endif
|
||||
#ifndef USES_P141
|
||||
#define USES_P141 // PCD8544 Nokia 5110
|
||||
#endif
|
||||
|
||||
// Controllers
|
||||
#ifndef USES_C015
|
||||
@@ -1953,7 +1974,7 @@ To create/register a plugin, you have to :
|
||||
#define DISABLE_SOFTWARE_SERIAL
|
||||
#endif
|
||||
|
||||
#if defined(USES_P095) || defined(USES_P096) || defined(USES_P116) || defined(USES_P131) // Add any plugin that uses AdafruitGFX_Helper
|
||||
#if defined(USES_P095) || defined(USES_P096) || defined(USES_P116) || defined(USES_P131) || defined(USES_P141) // Add any plugin that uses AdafruitGFX_Helper
|
||||
#ifndef PLUGIN_USES_ADAFRUITGFX
|
||||
#define PLUGIN_USES_ADAFRUITGFX // Ensure AdafruitGFX_helper is available for graphics displays (only)
|
||||
#endif
|
||||
|
||||
@@ -106,8 +106,9 @@ bool CPluginCall(CPlugin::Function Function, struct EventStruct *event, String&
|
||||
if ((Settings.Protocol[x] != 0) && Settings.ControllerEnabled[x]) {
|
||||
protocolIndex_t ProtocolIndex = getProtocolIndex_from_ControllerIndex(x);
|
||||
event->ControllerIndex = x;
|
||||
String dummy;
|
||||
const bool success = CPluginCall(ProtocolIndex, Function, event, dummy);
|
||||
String command;
|
||||
if (Function == CPlugin::Function::CPLUGIN_WRITE) command = str;
|
||||
const bool success = CPluginCall(ProtocolIndex, Function, event, command);
|
||||
if (success && Function == CPlugin::Function::CPLUGIN_WRITE) {
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -289,8 +289,8 @@ void AdaGFXFormBacklight(const __FlashStringHelper *backlightPinId,
|
||||
uint16_t backlightPercentage) {
|
||||
addFormPinSelect(PinSelectPurpose::Generic_output, formatGpioName_output_optional(F("Backlight ")), backlightPinId, backlightPin);
|
||||
|
||||
addFormNumericBox(F("Backlight percentage"), backlightPercentageId, backlightPercentage, 1, 100);
|
||||
addUnit(F("1-100%"));
|
||||
addFormNumericBox(F("Backlight percentage"), backlightPercentageId, backlightPercentage, 0, 100);
|
||||
addUnit(F("0-100%"));
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
@@ -324,6 +324,30 @@ void AdaGFXFormFontScaling(const __FlashStringHelper *fontScalingId,
|
||||
addUnit(unit);
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
* Show a selector for line-spacing setting, supported by Adafruit_GFX
|
||||
****************************************************************************************/
|
||||
void AdaGFXFormLineSpacing(const __FlashStringHelper *id,
|
||||
uint8_t selectedIndex) {
|
||||
String lineSpacings[16];
|
||||
int lineSpacingOptions[16];
|
||||
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
if (15 == i) {
|
||||
# ifndef LIMIT_BUILD_SIZE
|
||||
lineSpacings[i] = F("Auto, using font height * scaling");
|
||||
# else // ifndef LIMIT_BUILD_SIZE
|
||||
lineSpacings[i] = F("Auto");
|
||||
# endif // ifndef LIMIT_BUILD_SIZE
|
||||
} else {
|
||||
lineSpacings[i] = i;
|
||||
}
|
||||
lineSpacingOptions[i] = i;
|
||||
}
|
||||
addFormSelector(F("Linespacing"), id, 16, lineSpacings, lineSpacingOptions, selectedIndex);
|
||||
addUnit(F("px"));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* AdaGFXparseTemplate: Replace variables and adjust unicode special characters to Adafruit font
|
||||
***************************************************************************/
|
||||
@@ -675,6 +699,49 @@ void AdafruitGFX_helper::getCursorXY(int16_t& currentX,
|
||||
currentY = _lastY;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* setTxtfullCompensation: x and/or y values defined here are subtracted from x and y position
|
||||
* - set to 1 for x-1/y-1 pixel for P095 and P096
|
||||
* - set to 2 for y+1 pixel
|
||||
* - set to 3 for x+1 pixel
|
||||
***************************************************************************/
|
||||
void AdafruitGFX_helper::setTxtfullCompensation(uint8_t compensation) {
|
||||
switch (compensation) {
|
||||
case 1: // P095
|
||||
{
|
||||
_x_compensation = 1;
|
||||
_y_compensation = 1;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
_x_compensation = 0;
|
||||
_y_compensation = -1;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
_x_compensation = -1;
|
||||
_y_compensation = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
_x_compensation = 0;
|
||||
_y_compensation = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* invertDisplay(): Store display-inverted state and proxy to _display
|
||||
***************************************************************************/
|
||||
void AdafruitGFX_helper::invertDisplay(bool i) {
|
||||
_displayInverted = i;
|
||||
_display->invertDisplay(_displayInverted);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* processCommand: Parse string to <command>,<subcommand>[,<arguments>...] and execute that command
|
||||
***************************************************************************/
|
||||
@@ -702,14 +769,22 @@ bool AdafruitGFX_helper::processCommand(const String& string) {
|
||||
String log;
|
||||
std::vector<String> sParams;
|
||||
std::vector<int> nParams;
|
||||
int argCount = 0;
|
||||
bool loop = true;
|
||||
uint8_t emptyCount = 0;
|
||||
int argCount = 0;
|
||||
bool loop = true;
|
||||
|
||||
while (loop) { // Process all provided arguments
|
||||
sParams.push_back(parseStringKeepCase(string, argCount + 3)); // 0-offset + 1st and 2nd argument used by trigger/subcommand
|
||||
while (loop) { // Process all provided arguments
|
||||
// 0-offset + 1st and 2nd argument used by trigger/subcommand, don't trim off spaces
|
||||
sParams.push_back(parseStringKeepCase(string, argCount + 3, ',', false));
|
||||
nParams.push_back(0);
|
||||
validIntFromString(sParams[argCount], nParams[argCount]);
|
||||
loop = !sParams[argCount].isEmpty();
|
||||
|
||||
if (sParams[argCount].isEmpty()) {
|
||||
emptyCount++;
|
||||
} else {
|
||||
emptyCount = 0; // Reset empty counter
|
||||
}
|
||||
loop = emptyCount < 3 || argCount <= ADAGFX_PARSE_MAX_ARGS; // Keep picking up arguments until we have the last 3 empty
|
||||
|
||||
# ifndef BUILD_NO_DEBUG
|
||||
|
||||
@@ -722,18 +797,10 @@ bool AdafruitGFX_helper::processCommand(const String& string) {
|
||||
}
|
||||
# endif // ifndef BUILD_NO_DEBUG
|
||||
|
||||
if (loop) { argCount++; }
|
||||
argCount++;
|
||||
}
|
||||
{ // Guarantee minimal nParams/sParams size
|
||||
int args = argCount;
|
||||
|
||||
while (args <= ADAGFX_PARSE_MAX_ARGS) {
|
||||
sParams.push_back(EMPTY_STRING);
|
||||
nParams.push_back(0);
|
||||
args++;
|
||||
}
|
||||
}
|
||||
success = true; // If we get this far, we'll flip the flag if something wrong is found
|
||||
argCount -= emptyCount; // Not counting the empty arguments
|
||||
success = true; // If we get this far, we'll flip the flag if something wrong is found
|
||||
|
||||
# ifndef BUILD_NO_DEBUG
|
||||
|
||||
@@ -766,7 +833,7 @@ bool AdafruitGFX_helper::processCommand(const String& string) {
|
||||
if (_columnRowMode) {
|
||||
_display->setCursor(nParams[0] * _fontwidth + _xo, nParams[1] * _fontheight + _yo);
|
||||
} else {
|
||||
_display->setCursor(nParams[0] + _xo - _p095_compensation, nParams[1] + _yo - _p095_compensation);
|
||||
_display->setCursor(nParams[0] + _xo - _x_compensation, nParams[1] + _yo - _y_compensation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -784,9 +851,28 @@ bool AdafruitGFX_helper::processCommand(const String& string) {
|
||||
} else {
|
||||
_display->setCursor(nParams[0] + _xo, nParams[1] + _yo);
|
||||
}
|
||||
_display->println(parseStringToEndKeepCase(string, 5)); // Print entire rest of provided line
|
||||
_display->println(parseStringToEndKeepCase(string, 5)); // Print entire rest of provided line
|
||||
}
|
||||
}
|
||||
else if (subcommand.equals(F("txl")) && (argCount >= 2)) // txl: Text at line(s)
|
||||
{
|
||||
uint8_t _line = 0;
|
||||
uint8_t _column = 0;
|
||||
uint8_t idx = 0;
|
||||
bool currentColRowState = _columnRowMode;
|
||||
setColumnRowMode(true); // this command is by default set to Column/Row mode
|
||||
|
||||
while (idx < argCount && !sParams[idx + 1].isEmpty()) {
|
||||
if (nParams[idx] > 0) {
|
||||
_line = nParams[idx];
|
||||
} else {
|
||||
_line++;
|
||||
}
|
||||
printText(sParams[idx + 1].c_str(), _column, _line - 1, _fontscaling, _fgcolor, _bgcolor);
|
||||
idx += 2;
|
||||
}
|
||||
setColumnRowMode(currentColRowState);
|
||||
}
|
||||
else if (subcommand.equals(F("txc")) && ((argCount == 1) || (argCount == 2))) // txc: Textcolor, fg and opt. bg colors
|
||||
{
|
||||
_fgcolor = AdaGFXparseColor(sParams[0], _colorDepth);
|
||||
@@ -815,14 +901,14 @@ bool AdafruitGFX_helper::processCommand(const String& string) {
|
||||
|
||||
# if ADAGFX_ARGUMENT_VALIDATION
|
||||
|
||||
if (invalidCoordinates(nParams[0] - _p095_compensation, nParams[1] - _p095_compensation, _columnRowMode)) {
|
||||
if (invalidCoordinates(nParams[0] - _x_compensation, nParams[1] - _y_compensation, _columnRowMode)) {
|
||||
success = false;
|
||||
} else
|
||||
# endif // if ADAGFX_ARGUMENT_VALIDATION
|
||||
{
|
||||
printText(sParams[2].c_str(),
|
||||
nParams[0] - _p095_compensation,
|
||||
nParams[1] - _p095_compensation,
|
||||
nParams[0] - _x_compensation,
|
||||
nParams[1] - _y_compensation,
|
||||
_fontscaling,
|
||||
_fgcolor,
|
||||
_fgcolor); // transparent bg
|
||||
@@ -832,14 +918,14 @@ bool AdafruitGFX_helper::processCommand(const String& string) {
|
||||
|
||||
# if ADAGFX_ARGUMENT_VALIDATION
|
||||
|
||||
if (invalidCoordinates(nParams[0] - _p095_compensation, nParams[1] - _p095_compensation, _columnRowMode)) {
|
||||
if (invalidCoordinates(nParams[0] - _x_compensation, nParams[1] - _y_compensation, _columnRowMode)) {
|
||||
success = false;
|
||||
} else
|
||||
# endif // if ADAGFX_ARGUMENT_VALIDATION
|
||||
{
|
||||
printText(sParams[3].c_str(),
|
||||
nParams[0] - _p095_compensation,
|
||||
nParams[1] - _p095_compensation,
|
||||
nParams[0] - _x_compensation,
|
||||
nParams[1] - _y_compensation,
|
||||
nParams[2],
|
||||
_fgcolor,
|
||||
_fgcolor); // transparent bg
|
||||
@@ -849,15 +935,15 @@ bool AdafruitGFX_helper::processCommand(const String& string) {
|
||||
|
||||
# if ADAGFX_ARGUMENT_VALIDATION
|
||||
|
||||
if (invalidCoordinates(nParams[0] - _p095_compensation, nParams[1] - _p095_compensation, _columnRowMode)) {
|
||||
if (invalidCoordinates(nParams[0] - _x_compensation, nParams[1] - _y_compensation, _columnRowMode)) {
|
||||
success = false;
|
||||
} else
|
||||
# endif // if ADAGFX_ARGUMENT_VALIDATION
|
||||
{
|
||||
uint16_t color = AdaGFXparseColor(sParams[3], _colorDepth);
|
||||
printText(sParams[4].c_str(),
|
||||
nParams[0] - _p095_compensation,
|
||||
nParams[1] - _p095_compensation,
|
||||
nParams[0] - _x_compensation,
|
||||
nParams[1] - _y_compensation,
|
||||
nParams[2],
|
||||
color,
|
||||
color); // transparent bg
|
||||
@@ -867,14 +953,14 @@ bool AdafruitGFX_helper::processCommand(const String& string) {
|
||||
|
||||
# if ADAGFX_ARGUMENT_VALIDATION
|
||||
|
||||
if (invalidCoordinates(nParams[0] - _p095_compensation, nParams[1] - _p095_compensation, _columnRowMode)) {
|
||||
if (invalidCoordinates(nParams[0] - _x_compensation, nParams[1] - _y_compensation, _columnRowMode)) {
|
||||
success = false;
|
||||
} else
|
||||
# endif // if ADAGFX_ARGUMENT_VALIDATION
|
||||
{
|
||||
printText(sParams[5].c_str(),
|
||||
nParams[0] - _p095_compensation,
|
||||
nParams[1] - _p095_compensation,
|
||||
nParams[0] - _x_compensation,
|
||||
nParams[1] - _y_compensation,
|
||||
nParams[2],
|
||||
AdaGFXparseColor(sParams[3], _colorDepth),
|
||||
AdaGFXparseColor(sParams[4], _colorDepth));
|
||||
@@ -885,7 +971,7 @@ bool AdafruitGFX_helper::processCommand(const String& string) {
|
||||
|
||||
# if ADAGFX_ARGUMENT_VALIDATION
|
||||
|
||||
if (invalidCoordinates(nParams[0] - _p095_compensation, nParams[1] - _p095_compensation, _columnRowMode)) {
|
||||
if (invalidCoordinates(nParams[0] - _x_compensation, nParams[1] - _y_compensation, _columnRowMode)) {
|
||||
success = false;
|
||||
} else
|
||||
# endif // if ADAGFX_ARGUMENT_VALIDATION
|
||||
@@ -897,8 +983,8 @@ bool AdafruitGFX_helper::processCommand(const String& string) {
|
||||
_display->setTextWrap(_textPrintMode == AdaGFXTextPrintMode::ContinueToNextLine);
|
||||
}
|
||||
printText(sParams[argCount - 1].c_str(),
|
||||
nParams[0] - _p095_compensation,
|
||||
nParams[1] - _p095_compensation,
|
||||
nParams[0] - _x_compensation,
|
||||
nParams[1] - _y_compensation,
|
||||
nParams[2],
|
||||
AdaGFXparseColor(sParams[3], _colorDepth),
|
||||
AdaGFXparseColor(sParams[4], _colorDepth),
|
||||
@@ -1693,9 +1779,7 @@ bool AdafruitGFX_helper::processCommand(const String& string) {
|
||||
# ifndef BUILD_NO_DEBUG
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
String log = F("AdaGFX defined window id: ");
|
||||
log += win;
|
||||
addLogMove(LOG_LEVEL_INFO, log);
|
||||
addLogMove(LOG_LEVEL_INFO, concat(F("AdaGFX defined window id: "), static_cast<int>(win)));
|
||||
}
|
||||
# endif // ifndef BUILD_NO_DEBUG
|
||||
|
||||
@@ -1792,6 +1876,7 @@ bool AdafruitGFX_helper::pluginGetConfigValue(String& string) {
|
||||
/****************************************************************************
|
||||
* draw a button shape with provided color, can also clear a previously drawn button
|
||||
***************************************************************************/
|
||||
# if ADAGFX_ENABLE_BUTTON_DRAW
|
||||
void AdafruitGFX_helper::drawButtonShape(const Button_type_e& buttonType,
|
||||
const int & x,
|
||||
const int & y,
|
||||
@@ -1858,6 +1943,8 @@ void AdafruitGFX_helper::drawButtonShape(const Button_type_e& buttonType,
|
||||
}
|
||||
}
|
||||
|
||||
# endif // if ADAGFX_ENABLE_BUTTON_DRAW
|
||||
|
||||
/****************************************************************************
|
||||
* printText: Print text on display at a specific pixel or column/row location
|
||||
***************************************************************************/
|
||||
@@ -1874,6 +1961,7 @@ void AdafruitGFX_helper::printText(const char *string,
|
||||
int16_t xText = 0;
|
||||
int16_t yText = 0;
|
||||
uint16_t wText = 0;
|
||||
uint16_t wChar = 0;
|
||||
uint16_t hText = 0;
|
||||
int16_t oTop = 0;
|
||||
int16_t oBottom = 0;
|
||||
@@ -1882,6 +1970,8 @@ void AdafruitGFX_helper::printText(const char *string,
|
||||
uint16_t res_y = _res_y;
|
||||
uint16_t xOffset = 0;
|
||||
uint16_t yOffset = 0;
|
||||
uint16_t hChar1 = 0;
|
||||
uint16_t wChar1 = 0;
|
||||
String newString = string;
|
||||
|
||||
# if ADAGFX_ENABLE_FRAMED_WINDOW
|
||||
@@ -1891,25 +1981,39 @@ void AdafruitGFX_helper::printText(const char *string,
|
||||
_y += yOffset;
|
||||
# endif // if ADAGFX_ENABLE_FRAMED_WINDOW
|
||||
|
||||
_display->setTextSize(textSize);
|
||||
_display->getTextBounds(String('A'), 0, 0, &xText, &yText, &wChar1, &hChar1); // Calculate ~1 char height
|
||||
|
||||
if (_columnRowMode) {
|
||||
_x = X * (_fontwidth * textSize); // We need this multiple times
|
||||
_y = (Y * (_fontheight * textSize)) + (_heightOffset * textSize);
|
||||
_x = X * (_fontwidth * textSize); // We need this multiple times
|
||||
|
||||
if (15 == _lineSpacing) {
|
||||
_y = (Y * (_fontheight * textSize)) + (_heightOffset * textSize);
|
||||
} else {
|
||||
_y = (Y * (hChar1 + _lineSpacing)) + _heightOffset; // Apply explicit line spacing
|
||||
}
|
||||
}
|
||||
|
||||
_display->setCursor(_x, _y);
|
||||
_display->setTextColor(color, bkcolor);
|
||||
_display->setTextSize(textSize);
|
||||
|
||||
if (_textPrintMode != AdaGFXTextPrintMode::ContinueToNextLine) {
|
||||
_display->getTextBounds(newString, _x, _y, &xText, &yText, &wText, &hText); // Count length
|
||||
# if ADAGFX_ENABLE_FRAMED_WINDOW
|
||||
|
||||
while ((newString.length() > 0) && (((_x - xOffset) + wText) > res_x)) {
|
||||
if (0 == getWindow()) // Only on Window 0
|
||||
# endif // if ADAGFX_ENABLE_FRAMED_WINDOW
|
||||
{
|
||||
wChar = wChar1;
|
||||
}
|
||||
_display->getTextBounds(newString, _x, _y, &xText, &yText, &wText, &hText); // Calculate length
|
||||
|
||||
while ((newString.length() > 0) && (((_x - xOffset) + wText) > res_x + wChar)) {
|
||||
newString.remove(newString.length() - 1); // Cut last character off
|
||||
_display->getTextBounds(newString, _x, _y, &xText, &yText, &wText, &hText); // Re-count length
|
||||
_display->getTextBounds(newString, _x, _y, &xText, &yText, &wText, &hText); // Re-calculate length
|
||||
}
|
||||
}
|
||||
|
||||
_display->getTextBounds(newString, _x, _y, &xText, &yText, &wText, &hText); // Count length
|
||||
_display->getTextBounds(newString, _x, _y, &xText, &yText, &wText, &hText); // Calculate length
|
||||
|
||||
if ((maxWidth > 0) && ((_x - xOffset) + maxWidth <= res_x)) {
|
||||
res_x = (_x - xOffset) + maxWidth;
|
||||
@@ -2184,10 +2288,11 @@ void AdaGFXHtmlColorDepthDataList(const __FlashStringHelper *id,
|
||||
switch (colorDepth) {
|
||||
case AdaGFXColorDepth::BlackWhiteRed:
|
||||
case AdaGFXColorDepth::BlackWhite2Greyscales:
|
||||
AdaGFXaddHtmlDataListColorOptionValue(static_cast<uint16_t>(AdaGFXMonoRedGreyscaleColors::ADAGFXEPD_RED), colorDepth);
|
||||
AdaGFXaddHtmlDataListColorOptionValue(static_cast<uint16_t>(AdaGFXMonoRedGreyscaleColors::ADAGFXEPD_DARK), colorDepth);
|
||||
AdaGFXaddHtmlDataListColorOptionValue(static_cast<uint16_t>(AdaGFXMonoRedGreyscaleColors::ADAGFXEPD_LIGHT), colorDepth);
|
||||
// Fall through
|
||||
AdaGFXaddHtmlDataListColorOptionValue(static_cast<uint16_t>(AdaGFXMonoRedGreyscaleColors::ADAGFXEPD_RED), colorDepth);
|
||||
AdaGFXaddHtmlDataListColorOptionValue(static_cast<uint16_t>(AdaGFXMonoRedGreyscaleColors::ADAGFXEPD_DARK), colorDepth);
|
||||
AdaGFXaddHtmlDataListColorOptionValue(static_cast<uint16_t>(AdaGFXMonoRedGreyscaleColors::ADAGFXEPD_LIGHT), colorDepth);
|
||||
|
||||
// Fall through
|
||||
case AdaGFXColorDepth::Monochrome:
|
||||
AdaGFXaddHtmlDataListColorOptionValue(static_cast<uint16_t>(AdaGFXMonoRedGreyscaleColors::ADAGFXEPD_BLACK), colorDepth);
|
||||
AdaGFXaddHtmlDataListColorOptionValue(static_cast<uint16_t>(AdaGFXMonoRedGreyscaleColors::ADAGFXEPD_WHITE), colorDepth);
|
||||
|
||||
@@ -12,6 +12,16 @@
|
||||
***************************************************************************/
|
||||
/************
|
||||
* Changelog:
|
||||
* 2022-10-05 tonhuisman: No longer trim off spaces from arguments to commands
|
||||
* 2022-09-23 tonhuisman: Allow backlight percentage from 0% instead of from 1% to be able to completely turn it off
|
||||
* 2022-09-12 tonhuisman: Add line-spacing option for Column/Row mode, default set to auto, optional 0..14 pixels line-spacing
|
||||
* Add line spacing form selector function
|
||||
* 2022-09-10 tonhuisman: Enable printing partial characters falling off at the right edge of the screen, only when on Window 0
|
||||
* 2022-08-25 tonhuisman: Add invertDisplay() functionality, often used for monochrome displays
|
||||
* 2022-08-23 tonhuisman: Several small improvements, and a few bugfixes
|
||||
* 2022-08-20 tonhuisman: Add txl subcommand to display text on 1 or more lines, autoincrementing the line nr,
|
||||
* always in row/column mode.
|
||||
* Improved argument parsing to allow up to 2 empty arguments between filled arguments
|
||||
* 2022-06-07 tonhuisman: Code improvements in initialization, move offset calculation to printText() function
|
||||
* 2022-06-06 tonhuisman: Process any special characters for lenght and textheight values for correct sizing
|
||||
* 2022-06-05 tonhuisman: Add support for getting config values: win (current window id), iswin (exists?), width & height (current window),
|
||||
@@ -171,9 +181,9 @@
|
||||
# endif // ifndef ADAGFX_SUPPORT_8and16COLOR
|
||||
# endif // ifdef PLUGIN_SET_MAX
|
||||
|
||||
# define ADAGFX_PARSE_PREFIX F("~") // Subcommand-trigger prefix and postfix strings
|
||||
# define ADAGFX_PARSE_PREFIX F("~") // Subcommand-trigger prefix and postfix strings
|
||||
# define ADAGFX_PARSE_PREFIX_LEN 1
|
||||
# define ADAGFX_PARSE_POSTFIX F("~") // Will be removed before the normal template parsing is done
|
||||
# define ADAGFX_PARSE_POSTFIX F("~") // Will be removed before the normal template parsing is done
|
||||
# define ADAGFX_PARSE_POSTFIX_LEN 1
|
||||
|
||||
# define ADAGFX_UNIVERSAL_TRIGGER F("adagfx_trigger") // Universal command trigger
|
||||
@@ -232,16 +242,16 @@ enum class AdaGFXTextPrintMode : uint8_t {
|
||||
|
||||
# if ADAGFX_SUPPORT_7COLOR
|
||||
# if ADAGFX_SUPPORT_8and16COLOR
|
||||
# define ADAGFX_COLORDEPTH_COUNT 7
|
||||
# define ADAGFX_MONOCOLORS_COUNT 4
|
||||
# define ADAGFX_COLORDEPTH_COUNT 7
|
||||
# define ADAGFX_MONOCOLORS_COUNT 4
|
||||
# else // if ADAGFX_SUPPORT_8and16COLOR
|
||||
# define ADAGFX_COLORDEPTH_COUNT 5
|
||||
# define ADAGFX_MONOCOLORS_COUNT 4
|
||||
# endif // if ADAGFX_SUPPORT_8and16COLOR
|
||||
# else // if ADAGFX_SUPPORT_7COLOR
|
||||
# if ADAGFX_SUPPORT_8and16COLOR
|
||||
# define ADAGFX_COLORDEPTH_COUNT 6
|
||||
# define ADAGFX_MONOCOLORS_COUNT 3
|
||||
# define ADAGFX_COLORDEPTH_COUNT 6
|
||||
# define ADAGFX_MONOCOLORS_COUNT 3
|
||||
# else // if ADAGFX_SUPPORT_8and16COLOR
|
||||
# define ADAGFX_COLORDEPTH_COUNT 4
|
||||
# define ADAGFX_MONOCOLORS_COUNT 3
|
||||
@@ -258,7 +268,7 @@ enum class AdaGFXColorDepth : uint16_t {
|
||||
EightColor = 8u, // 8 regular colors
|
||||
SixteenColor = 16u, // 16 colors
|
||||
# endif // if ADAGFX_SUPPORT_8and16COLOR
|
||||
FullColor = 65535u // 65535 colors (max. supported by RGB565)
|
||||
FullColor = 65535u // 65535 colors (max. supported by RGB565)
|
||||
};
|
||||
|
||||
# if ADAGFX_ENABLE_BUTTON_DRAW
|
||||
@@ -367,6 +377,8 @@ String AdaGFXcolorToString(const uint16_t & color,
|
||||
# if ADAGFX_SUPPORT_7COLOR
|
||||
uint16_t AdaGFXrgb565ToColor7(const uint16_t& color); // Convert rgb565 color to 7-color
|
||||
# endif // if ADAGFX_SUPPORT_7COLOR
|
||||
void AdaGFXFormLineSpacing(const __FlashStringHelper *id,
|
||||
uint8_t selectedIndex);
|
||||
|
||||
class AdafruitGFX_helper {
|
||||
public:
|
||||
@@ -426,20 +438,24 @@ public:
|
||||
uint16_t& ypix);
|
||||
void getColors(uint16_t& fgcolor,
|
||||
uint16_t& bgcolor);
|
||||
void getCursorXY(int16_t& currentX, // Get last known (text)cursor position, recalculates to col/row if that
|
||||
int16_t& currentY); // setting is acive
|
||||
void getCursorXY(int16_t& currentX, // Get last known (text)cursor position, recalculates to col/row if that
|
||||
int16_t& currentY); // setting is acive
|
||||
|
||||
void setTxtfullCompensation(uint8_t compensation) { // Set to 1 for backward comp. with P095/P096 txtfull subcommands, uses offset -1
|
||||
_p095_compensation = compensation;
|
||||
void setTxtfullCompensation(uint8_t compensation); // Set to 1 for backward comp. with P095/P096 txtfull subcommands, uses offset -1
|
||||
// Set to 2 for extra offset of +1 on y axis
|
||||
// Set to 3 for extra offset of +1 on x axis
|
||||
|
||||
void setRotation(uint8_t m); // Set the helper-rotation the same as the display object rotation
|
||||
|
||||
void setColumnRowMode(bool state) { // When true, addressing for txp, txtfull commands is in columns/rows, default in
|
||||
_columnRowMode = state; // pixels NOT compatible with _x_compensation!
|
||||
}
|
||||
|
||||
void setRotation(uint8_t m); // Set the helper-rotation the same as the display object rotation
|
||||
|
||||
void setColumnRowMode(bool state) { // When true, addressing for txp, txtfull commands is in columns/rows, default in pixels
|
||||
_columnRowMode = state; // NOT compatible with _p095_compensation!
|
||||
void setLineSpacing(int8_t lineSpacing) { // Set inter-line spacing in Column/Row mode
|
||||
_lineSpacing = lineSpacing & 0xF; // Limited to 0..14 px, 15 = auto, based on fontheight * fontsize
|
||||
}
|
||||
|
||||
String getTrigger() { // Returns the current trigger
|
||||
String getTrigger() { // Returns the current trigger
|
||||
return _trigger;
|
||||
}
|
||||
|
||||
@@ -467,7 +483,7 @@ public:
|
||||
const int16_t& h,
|
||||
int16_t windowId = -1,
|
||||
const int8_t & rotation = -1);
|
||||
bool deleteWindow(const uint8_t& windowId);
|
||||
bool deleteWindow(const uint8_t& windowId);
|
||||
# endif // if ADAGFX_ENABLE_FRAMED_WINDOW
|
||||
|
||||
uint16_t getTextSize(const String& text,
|
||||
@@ -478,6 +494,8 @@ public:
|
||||
return _useValidation;
|
||||
}
|
||||
|
||||
void invertDisplay(bool i);
|
||||
|
||||
private:
|
||||
|
||||
void initialize();
|
||||
@@ -513,13 +531,16 @@ private:
|
||||
uint16_t _textrows;
|
||||
int16_t _lastX;
|
||||
int16_t _lastY;
|
||||
uint8_t _fontwidth = 6; // Default font characteristics
|
||||
uint8_t _fontheight = 10;
|
||||
int8_t _heightOffset = 0;
|
||||
bool _isProportional = false;
|
||||
uint8_t _p095_compensation = 0;
|
||||
bool _columnRowMode = false;
|
||||
int8_t _rotation = 0;
|
||||
uint8_t _fontwidth = 6; // Default font characteristics
|
||||
uint8_t _fontheight = 10;
|
||||
int8_t _heightOffset = 0;
|
||||
bool _isProportional = false;
|
||||
int8_t _x_compensation = 0;
|
||||
int8_t _y_compensation = 0;
|
||||
bool _columnRowMode = false;
|
||||
int8_t _rotation = 0;
|
||||
bool _displayInverted = false;
|
||||
int8_t _lineSpacing = 15; // Default fontheight * fontsize
|
||||
|
||||
uint16_t _display_x;
|
||||
uint16_t _display_y;
|
||||
|
||||
@@ -561,7 +561,7 @@ void transformValue(
|
||||
|
||||
// Find the first (enabled) task with given name
|
||||
// Return INVALID_TASK_INDEX when not found, else return taskIndex
|
||||
taskIndex_t findTaskIndexByName(const String& deviceName)
|
||||
taskIndex_t findTaskIndexByName(const String& deviceName, bool allowDisabled)
|
||||
{
|
||||
// cache this, since LoadTaskSettings does take some time.
|
||||
#ifdef USE_SECOND_HEAP
|
||||
@@ -578,7 +578,7 @@ taskIndex_t findTaskIndexByName(const String& deviceName)
|
||||
|
||||
for (taskIndex_t taskIndex = 0; taskIndex < TASKS_MAX; taskIndex++)
|
||||
{
|
||||
if (Settings.TaskDeviceEnabled[taskIndex]) {
|
||||
if (Settings.TaskDeviceEnabled[taskIndex] || allowDisabled) {
|
||||
String taskDeviceName = getTaskDeviceName(taskIndex);
|
||||
|
||||
if (!taskDeviceName.isEmpty())
|
||||
|
||||
@@ -40,7 +40,7 @@ void transformValue(
|
||||
|
||||
// Find the first (enabled) task with given name
|
||||
// Return INVALID_TASK_INDEX when not found, else return taskIndex
|
||||
taskIndex_t findTaskIndexByName(const String& deviceName);
|
||||
taskIndex_t findTaskIndexByName(const String& deviceName, bool allowDisabled = false);
|
||||
|
||||
// Find the first device value index of a taskIndex.
|
||||
// Return VARS_PER_TASK if none found.
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
// Configuration Settings. Custom Configuration Memory must be less than 1024 Bytes (per TD'er findings).
|
||||
// #define P75_Nlines 12 // Custom Config, Number of user entered Command Statment Lines. DO NOT USE!
|
||||
// #define P75_Nchars 64 // Custom Config, Length of user entered Command Statment Lines. DO NOT USE!
|
||||
# define P75_Nlines 10 // Custom Config, Number of user entered Command Statments.
|
||||
# define P75_Nlines 20 // Custom Config, Number of user entered Command Statments.
|
||||
# define P75_Nchars 51 // Custom Config, Length of user entered Command Statments.
|
||||
|
||||
// Nextion defines
|
||||
|
||||
@@ -10,14 +10,14 @@
|
||||
// #define DLbus_DEBUG
|
||||
|
||||
// Flags for pulse width (bit 0 is the content!)
|
||||
#define DLbus_FlagSingleWidth 0x02
|
||||
#define DLbus_FlagDoubleWidth 0x04
|
||||
#define DLbus_FlagShorterThanSingleWidth 0x10
|
||||
#define DLbus_FlagBetweenDoubleSingleWidth 0x20
|
||||
#define DLbus_FlagLongerThanDoubleWidth 0x40
|
||||
#define DLbus_FlagLongerThanTwiceDoubleWidth 0x80
|
||||
#define DLbus_FlagsWrongTiming (DLbus_FlagLongerThanTwiceDoubleWidth | DLbus_FlagLongerThanDoubleWidth | \
|
||||
DLbus_FlagBetweenDoubleSingleWidth | DLbus_FlagShorterThanSingleWidth)
|
||||
# define DLbus_FlagSingleWidth 0x02
|
||||
# define DLbus_FlagDoubleWidth 0x04
|
||||
# define DLbus_FlagShorterThanSingleWidth 0x10
|
||||
# define DLbus_FlagBetweenDoubleSingleWidth 0x20
|
||||
# define DLbus_FlagLongerThanDoubleWidth 0x40
|
||||
# define DLbus_FlagLongerThanTwiceDoubleWidth 0x80
|
||||
# define DLbus_FlagsWrongTiming (DLbus_FlagLongerThanTwiceDoubleWidth | DLbus_FlagLongerThanDoubleWidth | \
|
||||
DLbus_FlagBetweenDoubleSingleWidth | DLbus_FlagShorterThanSingleWidth)
|
||||
|
||||
// Helper for ISR call
|
||||
DLBus *DLBus::__instance = nullptr;
|
||||
@@ -60,8 +60,8 @@ void DLBus::AddToErrorLog(const String& string)
|
||||
void DLBus::attachDLBusInterrupt(void)
|
||||
{
|
||||
ISR_Receiving = false;
|
||||
IsISRset = true;
|
||||
IsNoData = false;
|
||||
IsISRset = true;
|
||||
IsNoData = false;
|
||||
attachInterrupt(digitalPinToInterrupt(ISR_DLB_Pin), ISR, CHANGE);
|
||||
}
|
||||
|
||||
@@ -84,15 +84,15 @@ void IRAM_ATTR DLBus::ISR(void)
|
||||
|
||||
void IRAM_ATTR DLBus::ISR_PinChanged(void)
|
||||
{
|
||||
// long TimeDiff = usecPassedSince(ISR_TimeLastBitChange); // time difference to previous pulse in µs
|
||||
uint32_t _now = micros();
|
||||
int32_t TimeDiff = (int32_t)(_now - ISR_TimeLastBitChange);
|
||||
// long TimeDiff = usecPassedSince(ISR_TimeLastBitChange); // time difference to previous pulse in µs
|
||||
uint32_t _now = micros();
|
||||
int32_t TimeDiff = (int32_t)(_now - ISR_TimeLastBitChange);
|
||||
|
||||
// ISR_TimeLastBitChange = micros(); // save last pin change time
|
||||
ISR_TimeLastBitChange = _now; // save last pin change time
|
||||
// ISR_TimeLastBitChange = micros(); // save last pin change time
|
||||
ISR_TimeLastBitChange = _now; // save last pin change time
|
||||
|
||||
if (ISR_Receiving) {
|
||||
uint8_t val = digitalRead(ISR_DLB_Pin); // read state
|
||||
uint8_t val = digitalRead(ISR_DLB_Pin); // read state
|
||||
|
||||
// check pulse width
|
||||
if (TimeDiff >= 2 * ISR_MinDoublePulseWidth) {
|
||||
@@ -140,9 +140,9 @@ boolean DLBus::CheckTimings(void) {
|
||||
uint8_t WrongTimeCnt = 0;
|
||||
int i;
|
||||
|
||||
#ifdef DLbus_DEBUG
|
||||
# ifdef DLbus_DEBUG
|
||||
uint16_t WrongTimingArray[5][6];
|
||||
#endif // DLbus_DEBUG
|
||||
# endif // DLbus_DEBUG
|
||||
|
||||
// AddToInfoLog(F("Receive stopped."));
|
||||
|
||||
@@ -155,28 +155,28 @@ boolean DLBus::CheckTimings(void) {
|
||||
if (rawval & DLbus_FlagsWrongTiming) {
|
||||
// wrong DLbus_time_diff
|
||||
if (ISR_PulseCount > 0) {
|
||||
#ifdef DLbus_DEBUG
|
||||
# ifdef DLbus_DEBUG
|
||||
WrongTimingArray[WrongTimeCnt][0] = i;
|
||||
WrongTimingArray[WrongTimeCnt][1] = ISR_PulseCount;
|
||||
WrongTimingArray[WrongTimeCnt][2] = BitNumber;
|
||||
WrongTimingArray[WrongTimeCnt][3] = rawval;
|
||||
#endif // DLbus_DEBUG
|
||||
# endif // DLbus_DEBUG
|
||||
|
||||
if ((rawval == DLbus_FlagLongerThanTwiceDoubleWidth) && (*(ISR_PtrChangeBitStream + i - 1) == (DLbus_FlagDoubleWidth | 0x01))) {
|
||||
// Add two additional short pulses (low and high), previous bit is High and contains DLbus_FlagDoubleWidth
|
||||
ProcessBit(0);
|
||||
ProcessBit(1);
|
||||
#ifdef DLbus_DEBUG
|
||||
# ifdef DLbus_DEBUG
|
||||
WrongTimingArray[WrongTimeCnt][4] = DLbus_FlagSingleWidth;
|
||||
WrongTimingArray[WrongTimeCnt][5] = DLbus_FlagSingleWidth + 1;
|
||||
#endif // DLbus_DEBUG
|
||||
# endif // DLbus_DEBUG
|
||||
}
|
||||
#ifdef DLbus_DEBUG
|
||||
# ifdef DLbus_DEBUG
|
||||
else {
|
||||
WrongTimingArray[WrongTimeCnt][4] = 0xff;
|
||||
WrongTimingArray[WrongTimeCnt][5] = 0xff;
|
||||
}
|
||||
#endif // DLbus_DEBUG
|
||||
# endif // DLbus_DEBUG
|
||||
WrongTimeCnt++;
|
||||
|
||||
if (WrongTimeCnt >= 5) {
|
||||
@@ -201,7 +201,7 @@ boolean DLBus::CheckTimings(void) {
|
||||
|
||||
// AddToInfoLog(F("DLbus_ChangeBitStream copied."));
|
||||
|
||||
#ifdef DLbus_DEBUG
|
||||
# ifdef DLbus_DEBUG
|
||||
|
||||
if (WrongTimeCnt > 0) {
|
||||
if (IsLogLevelInfo) {
|
||||
@@ -234,7 +234,7 @@ boolean DLBus::CheckTimings(void) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // DLbus_DEBUG
|
||||
# endif // DLbus_DEBUG
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -459,7 +459,6 @@ P092_data_struct::~P092_data_struct() {
|
||||
delete DLbus_Data;
|
||||
DLbus_Data = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool P092_data_struct::init(int8_t pin1, int P092DeviceIndex, eP092pinmode P092pinmode) {
|
||||
@@ -473,29 +472,29 @@ bool P092_data_struct::init(int8_t pin1, int P092DeviceIndex, eP092pinmode P092p
|
||||
DLbus_Data->IsLogLevelInfo = loglevelActiveFor(LOG_LEVEL_INFO);
|
||||
DLbus_Data->ISR_DLB_Pin = pin1;
|
||||
|
||||
//interrupt is detached in PLUGIN_WEBFORM_SAVE and attached in PLUGIN_ONCE_A_SECOND
|
||||
//to ensure that new interrupt is attached after new pin is configured, setting
|
||||
//IsISRset to false is done here.
|
||||
DLbus_Data->IsISRset = false;
|
||||
// interrupt is detached in PLUGIN_WEBFORM_SAVE and attached in PLUGIN_ONCE_A_SECOND
|
||||
// to ensure that new interrupt is attached after new pin is configured, setting
|
||||
// IsISRset to false is done here.
|
||||
DLbus_Data->IsISRset = false;
|
||||
|
||||
switch (P092pinmode) {
|
||||
case eP092pinmode::ePPM_InputPullUp:
|
||||
addLog(LOG_LEVEL_INFO, F("P092_init: Set input pin with pullup"));
|
||||
pinMode(pin1, INPUT_PULLUP);
|
||||
break;
|
||||
#ifdef INPUT_PULLDOWN
|
||||
break;
|
||||
# ifdef INPUT_PULLDOWN
|
||||
case eP092pinmode::ePPM_InputPullDown:
|
||||
addLog(LOG_LEVEL_INFO, F("P092_init: Set input pin with pulldown"));
|
||||
pinMode(pin1, INPUT_PULLDOWN);
|
||||
break;
|
||||
#endif
|
||||
break;
|
||||
# endif // ifdef INPUT_PULLDOWN
|
||||
default:
|
||||
addLog(LOG_LEVEL_INFO, F("P092_init: Set input pin"));
|
||||
pinMode(pin1, INPUT);
|
||||
}
|
||||
|
||||
// on a CHANGE on the data pin P092_Pin_changed is called
|
||||
//DLbus_Data->attachDLBusInterrupt();
|
||||
// on a CHANGE on the data pin P092_Pin_changed is called
|
||||
// DLbus_Data->attachDLBusInterrupt();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -528,14 +527,21 @@ void P092_data_struct::Plugin_092_SetIndices(int P092DeviceIndex) {
|
||||
P092_DataSettings.IdxCRC = 30;
|
||||
|
||||
switch (P092DeviceIndex) {
|
||||
case 31: // UVR31
|
||||
P092_DataSettings.DataBytes = 8;
|
||||
case 31: // UVR31
|
||||
case 42: // UVR42
|
||||
|
||||
if (P092DeviceIndex == 31) { // UVR31
|
||||
P092_DataSettings.DataBytes = 8;
|
||||
P092_DataSettings.DeviceByte0 = 0x30;
|
||||
} else { // UVR42
|
||||
P092_DataSettings.DataBytes = 10;
|
||||
P092_DataSettings.DeviceByte0 = 0x10;
|
||||
}
|
||||
P092_DataSettings.DLbus_MinPulseWidth = P092_min_width_50;
|
||||
P092_DataSettings.DLbus_MaxPulseWidth = P092_max_width_50;
|
||||
P092_DataSettings.DLbus_MinDoublePulseWidth = P092_double_min_width_50;
|
||||
P092_DataSettings.DLbus_MaxDoublePulseWidth = P092_double_max_width_50;
|
||||
|
||||
P092_DataSettings.DeviceByte0 = 0x30;
|
||||
P092_DataSettings.DeviceByte1 = 0;
|
||||
iDeviceBytes = 1;
|
||||
P092_DataSettings.MaxExtSensors = 0;
|
||||
@@ -644,7 +650,7 @@ void P092_data_struct::Plugin_092_StartReceiving(taskIndex_t taskindex) {
|
||||
if (DLbus_Data->ISR_PulseCount == 0) {
|
||||
// nothing received
|
||||
DLbus_Data->ISR_Receiving = false;
|
||||
DLbus_Data->IsNoData = true; // stop receiving until next PLUGIN_092_READ
|
||||
DLbus_Data->IsNoData = true; // stop receiving until next PLUGIN_092_READ
|
||||
addLog(LOG_LEVEL_ERROR, F("## StartReceiving: Error: Nothing received! No DL bus connected!"));
|
||||
}
|
||||
}
|
||||
@@ -964,4 +970,4 @@ boolean P092_data_struct::P092_fetch_heatmeter(int number, sP092_ReadData *ReadD
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // ifdef USES_P092
|
||||
#endif // ifdef USES_P092
|
||||
|
||||
@@ -115,7 +115,7 @@ private:
|
||||
# define P092_double_max_width_50 (P092_double_pulse_width_50 + (P092_pulse_width_50 * P092_percentage_variance / 100))
|
||||
|
||||
# define P092_DLbus_OptionCount 8
|
||||
# define P092_DLbus_DeviceCount 5
|
||||
# define P092_DLbus_DeviceCount 6
|
||||
|
||||
|
||||
struct P092_data_struct : public PluginTaskData_base {
|
||||
|
||||
@@ -0,0 +1,404 @@
|
||||
#include "../PluginStructs/P141_data_struct.h"
|
||||
|
||||
#ifdef USES_P141
|
||||
|
||||
# include "../Helpers/Hardware.h"
|
||||
|
||||
/****************************************************************************
|
||||
* toString: return the command string selected
|
||||
***************************************************************************/
|
||||
const __FlashStringHelper* toString(P141_CommandTrigger cmd) {
|
||||
switch (cmd) {
|
||||
case P141_CommandTrigger::lcd: return F("lcd");
|
||||
case P141_CommandTrigger::pcd8544: break;
|
||||
}
|
||||
return F("pcd8544"); // Default command trigger
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Constructor
|
||||
***************************************************************************/
|
||||
P141_data_struct::P141_data_struct(uint8_t rotation,
|
||||
uint8_t fontscaling,
|
||||
AdaGFXTextPrintMode textmode,
|
||||
int8_t backlightPin,
|
||||
uint8_t backlightPercentage,
|
||||
uint8_t contrast,
|
||||
uint32_t displayTimer,
|
||||
String commandTrigger,
|
||||
uint16_t fgcolor,
|
||||
uint16_t bgcolor,
|
||||
bool textBackFill,
|
||||
bool displayInverted)
|
||||
: _rotation(rotation), _fontscaling(fontscaling), _textmode(textmode), _backlightPin(backlightPin),
|
||||
_backlightPercentage(backlightPercentage), _contrast(contrast), _displayTimer(displayTimer),
|
||||
_displayTimeout(displayTimer), _commandTrigger(commandTrigger), _fgcolor(fgcolor), _bgcolor(bgcolor),
|
||||
_textBackFill(textBackFill), _displayInverted(displayInverted)
|
||||
{
|
||||
updateFontMetrics();
|
||||
_commandTrigger.toLowerCase();
|
||||
_commandTriggerCmd = concat(_commandTrigger, F("cmd"));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Destructor
|
||||
***************************************************************************/
|
||||
P141_data_struct::~P141_data_struct() {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* plugin_init: Initialize display
|
||||
***************************************************************************/
|
||||
bool P141_data_struct::plugin_init(struct EventStruct *event) {
|
||||
bool success = false;
|
||||
|
||||
ButtonState = false; // button not touched
|
||||
ButtonLastState = 0xFF; // Last state checked (debouncing in progress)
|
||||
DebounceCounter = 0; // debounce counter
|
||||
|
||||
if (nullptr == pcd8544) {
|
||||
addLog(LOG_LEVEL_INFO, F("PCD8544: Init start."));
|
||||
|
||||
pcd8544 = new (std::nothrow) Adafruit_PCD8544(P141_DC_PIN, P141_CS_PIN, P141_RST_PIN);
|
||||
# ifndef BUILD_NO_DEBUG
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
String log;
|
||||
log.reserve(90);
|
||||
log += F("PCD8544: Init done, address: 0x");
|
||||
log += String(reinterpret_cast<ulong>(pcd8544), HEX);
|
||||
log += ' ';
|
||||
|
||||
if (nullptr == pcd8544) {
|
||||
log += F("in");
|
||||
}
|
||||
log += F("valid, commands: ");
|
||||
log += _commandTrigger;
|
||||
log += F(", display: PCD8544");
|
||||
addLogMove(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
# endif // ifndef BUILD_NO_DEBUG
|
||||
} else {
|
||||
addLog(LOG_LEVEL_INFO, F("PCD8544: No init?"));
|
||||
}
|
||||
|
||||
if (nullptr != pcd8544) {
|
||||
pcd8544->begin(); // Start the display
|
||||
gfxHelper = new (std::nothrow) AdafruitGFX_helper(pcd8544,
|
||||
_commandTrigger,
|
||||
_xpix,
|
||||
_ypix,
|
||||
AdaGFXColorDepth::Monochrome,
|
||||
_textmode,
|
||||
_fontscaling,
|
||||
_fgcolor,
|
||||
_bgcolor,
|
||||
true,
|
||||
_textBackFill);
|
||||
|
||||
displayOnOff(true);
|
||||
|
||||
if (nullptr != gfxHelper) {
|
||||
pcd8544->setContrast(_contrast);
|
||||
gfxHelper->invertDisplay(_displayInverted);
|
||||
gfxHelper->setRotation(_rotation);
|
||||
pcd8544->fillScreen(_bgcolor); // fill screen with black color
|
||||
pcd8544->setTextColor(_fgcolor, _bgcolor); // set text color to white and black background
|
||||
|
||||
gfxHelper->setColumnRowMode(bitRead(P141_CONFIG_FLAGS, P141_CONFIG_FLAG_USE_COL_ROW));
|
||||
gfxHelper->setLineSpacing(P141_CONFIG_FLAG_GET_LINESPACING);
|
||||
pcd8544->setTextSize(_fontscaling); // Handles 0 properly, text size, default 1 = very small
|
||||
pcd8544->setCursor(0, 0); // move cursor to position (0, 0) pixel
|
||||
pcd8544->display();
|
||||
updateFontMetrics();
|
||||
|
||||
|
||||
if (P141_CONFIG_BUTTON_PIN != -1) {
|
||||
pinMode(P141_CONFIG_BUTTON_PIN, INPUT_PULLUP);
|
||||
}
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* updateFontMetrics: recalculate x and y columns, based on font size and font scale
|
||||
***************************************************************************/
|
||||
void P141_data_struct::updateFontMetrics() {
|
||||
if (nullptr != gfxHelper) {
|
||||
gfxHelper->getTextMetrics(_textcols, _textrows, _fontwidth, _fontheight, _fontscaling, _heightOffset, _xpix, _ypix);
|
||||
gfxHelper->getColors(_fgcolor, _bgcolor);
|
||||
} else {
|
||||
_textcols = _xpix / (_fontwidth * _fontscaling);
|
||||
_textrows = _ypix / (_fontheight * _fontscaling);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* plugin_exit: De-initialize before destruction
|
||||
***************************************************************************/
|
||||
bool P141_data_struct::plugin_exit(struct EventStruct *event) {
|
||||
# ifdef BUILD_NO_DEBUG
|
||||
addLog(LOG_LEVEL_INFO, F("PCD8544: Exit."));
|
||||
# endif // ifdef BUILD_NO_DEBUG
|
||||
|
||||
if ((nullptr != pcd8544) && bitRead(P141_CONFIG_FLAGS, P141_CONFIG_FLAG_CLEAR_ON_EXIT)) {
|
||||
pcd8544->fillScreen(_displayInverted
|
||||
? ADAGFX_WHITE
|
||||
: ADAGFX_BLACK); // fill screen with black or white color
|
||||
pcd8544->display();
|
||||
displayOnOff(false);
|
||||
}
|
||||
cleanup();
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* cleanup: De-initialize pointers
|
||||
***************************************************************************/
|
||||
void P141_data_struct::cleanup() {
|
||||
if (nullptr != gfxHelper) { delete gfxHelper; }
|
||||
gfxHelper = nullptr;
|
||||
|
||||
if (nullptr != pcd8544) { delete pcd8544; }
|
||||
pcd8544 = nullptr;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* plugin_read: Re-draw the default content
|
||||
***************************************************************************/
|
||||
bool P141_data_struct::plugin_read(struct EventStruct *event) {
|
||||
if (nullptr != pcd8544) {
|
||||
String strings[P141_Nlines];
|
||||
LoadCustomTaskSettings(event->TaskIndex, strings, P141_Nlines, 0);
|
||||
|
||||
bool hasContent = false;
|
||||
|
||||
for (uint8_t x = 0; x < P141_Nlines && !hasContent; x++) {
|
||||
hasContent = !strings[x].isEmpty();
|
||||
}
|
||||
|
||||
if (hasContent) {
|
||||
gfxHelper->setColumnRowMode(false); // Turn off column mode
|
||||
uint8_t yPos = 0; // Bound to the display
|
||||
int16_t dum = 0;
|
||||
uint16_t udum = 0;
|
||||
uint16_t hText = 0;
|
||||
|
||||
for (uint8_t x = 0; x < P141_Nlines; x++) {
|
||||
String newString = AdaGFXparseTemplate(strings[x], _textcols, gfxHelper);
|
||||
|
||||
# if ADAGFX_PARSE_SUBCOMMAND
|
||||
updateFontMetrics();
|
||||
# endif // if ADAGFX_PARSE_SUBCOMMAND
|
||||
|
||||
if ((yPos < _ypix) && !newString.isEmpty()) {
|
||||
gfxHelper->printText(newString.c_str(), 0, yPos, _fontscaling, _fgcolor, _bgcolor);
|
||||
}
|
||||
delay(0);
|
||||
|
||||
if (15 == P141_CONFIG_FLAG_GET_LINESPACING) {
|
||||
yPos += (_fontheight * _fontscaling); // Auto, using font-height and scaling
|
||||
} else {
|
||||
pcd8544->getTextBounds(F("Ay"), 0, 0, &dum, &dum, &udum, &hText); // Measure current font-height
|
||||
yPos += hText + P141_CONFIG_FLAG_GET_LINESPACING; // Explicit distance
|
||||
}
|
||||
}
|
||||
pcd8544->display();
|
||||
gfxHelper->setColumnRowMode(bitRead(P141_CONFIG_FLAGS, P141_CONFIG_FLAG_USE_COL_ROW)); // Restore column mode
|
||||
# if P141_FEATURE_CURSOR_XY_VALUES
|
||||
updateValues(event);
|
||||
# endif // if P141_FEATURE_CURSOR_XY_VALUES
|
||||
}
|
||||
}
|
||||
return false; // Always return false, so no attempt to send to
|
||||
// Controllers or generate events is started
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* plugin_ten_per_second: check button, if any, that wakes up the display
|
||||
***************************************************************************/
|
||||
bool P141_data_struct::plugin_ten_per_second(struct EventStruct *event) {
|
||||
if ((P141_CONFIG_BUTTON_PIN != -1) && (getButtonState()) && (nullptr != pcd8544)) {
|
||||
displayOnOff(true);
|
||||
markButtonStateProcessed();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* plugin_once_a_second: Count down display timer, if any, and turn display off if countdown reached
|
||||
***************************************************************************/
|
||||
bool P141_data_struct::plugin_once_a_second(struct EventStruct *event) {
|
||||
if (_displayTimer > 0) {
|
||||
_displayTimer--;
|
||||
|
||||
if ((nullptr != pcd8544) && (_displayTimer == 0)) {
|
||||
displayOnOff(false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* plugin_write: Handle commands
|
||||
***************************************************************************/
|
||||
bool P141_data_struct::plugin_write(struct EventStruct *event,
|
||||
const String & string) {
|
||||
bool success = false;
|
||||
String cmd = parseString(string, 1);
|
||||
|
||||
if ((nullptr != pcd8544) && cmd.equals(_commandTriggerCmd)) {
|
||||
String arg1 = parseString(string, 2);
|
||||
success = true;
|
||||
|
||||
if (arg1.equals(F("off"))) { // Screen off
|
||||
displayOnOff(false);
|
||||
}
|
||||
else if (arg1.equals(F("on"))) { // Screen on
|
||||
displayOnOff(true);
|
||||
}
|
||||
else if (arg1.equals(F("clear"))) { // Empty screen
|
||||
pcd8544->fillScreen(_bgcolor);
|
||||
pcd8544->display(); // Put on display
|
||||
}
|
||||
else if (arg1.equals(F("inv")) && // Invert display
|
||||
(event->Par2 >= 0) && (event->Par2 <= 1)) {
|
||||
if (parseString(string, 3).isEmpty()) { // No argument: flip previous state
|
||||
_displayInverted = !_displayInverted;
|
||||
} else {
|
||||
_displayInverted = (event->Par2 == 1); // Set state
|
||||
}
|
||||
|
||||
// Store in settings, but do not save
|
||||
bitWrite(P141_CONFIG_FLAGS, P141_CONFIG_FLAG_INVERTED, _displayInverted);
|
||||
|
||||
if (nullptr != gfxHelper) {
|
||||
gfxHelper->invertDisplay(_displayInverted);
|
||||
} else {
|
||||
pcd8544->invertDisplay(_displayInverted);
|
||||
}
|
||||
pcd8544->display(); // Put on display
|
||||
}
|
||||
else if (arg1.equals(F("backlight"))) { // Backlight percentage
|
||||
if ((P141_CONFIG_BACKLIGHT_PIN != -1) && // All is valid?
|
||||
(event->Par2 >= 0) &&
|
||||
(event->Par2 <= 100)) {
|
||||
P141_CONFIG_BACKLIGHT_PERCENT = event->Par2; // Set but don't store
|
||||
_backlightPercentage = event->Par2; // Also set to current
|
||||
displayOnOff(true);
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
else if (arg1.equals(F("contrast")) && // Display contrast
|
||||
(event->Par2 >= 0) &&
|
||||
(event->Par2 <= 100)) {
|
||||
P141_CONFIG_CONTRAST = event->Par2; // Set but don't store
|
||||
_contrast = event->Par2; // Also set to current
|
||||
pcd8544->setContrast(_contrast);
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
else if (pcd8544 && (cmd.equals(_commandTrigger) ||
|
||||
(gfxHelper && gfxHelper->isAdaGFXTrigger(cmd)))) {
|
||||
if (!bitRead(P141_CONFIG_FLAGS, P141_CONFIG_FLAG_NO_WAKE)) { // Wake display?
|
||||
displayOnOff(true);
|
||||
}
|
||||
|
||||
if (nullptr != gfxHelper) {
|
||||
success = gfxHelper->processCommand(string);
|
||||
|
||||
updateFontMetrics(); // Font or color may have changed
|
||||
|
||||
if (success) {
|
||||
pcd8544->display(); // Put on display
|
||||
# if P141_FEATURE_CURSOR_XY_VALUES
|
||||
updateValues(event);
|
||||
# endif // if P141_FEATURE_CURSOR_XY_VALUES
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
# if P141_FEATURE_CURSOR_XY_VALUES
|
||||
|
||||
/****************************************************************************
|
||||
* updateValues: put x and y coordinates in Values 0 and 1
|
||||
***************************************************************************/
|
||||
void P141_data_struct::updateValues(struct EventStruct *event) {
|
||||
int16_t curX, curY;
|
||||
|
||||
gfxHelper->getCursorXY(curX, curY); // Get current X and Y coordinates, and put into Values
|
||||
UserVar[event->BaseVarIndex] = curX;
|
||||
UserVar[event->BaseVarIndex + 1] = curY;
|
||||
}
|
||||
|
||||
# endif // if P141_FEATURE_CURSOR_XY_VALUES
|
||||
|
||||
# if ADAGFX_ENABLE_GET_CONFIG_VALUE
|
||||
|
||||
/****************************************************************************
|
||||
* plugin_get_config_value: Retrieve values like [<taskname>#<valuename>]
|
||||
***************************************************************************/
|
||||
bool P141_data_struct::plugin_get_config_value(struct EventStruct *event,
|
||||
String & string) {
|
||||
bool success = false;
|
||||
|
||||
if (gfxHelper != nullptr) {
|
||||
success = gfxHelper->pluginGetConfigValue(string);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
# endif // if ADAGFX_ENABLE_GET_CONFIG_VALUE
|
||||
|
||||
/****************************************************************************
|
||||
* displayOnOff: Turn display on or off
|
||||
***************************************************************************/
|
||||
void P141_data_struct::displayOnOff(bool state) {
|
||||
if (_backlightPin != -1) {
|
||||
# if defined(ESP8266)
|
||||
analogWrite(_backlightPin, state ? ((1024 / 100) * _backlightPercentage) : 0);
|
||||
# endif // if defined(ESP8266)
|
||||
# if defined(ESP32)
|
||||
analogWriteESP32(_backlightPin, state ? ((1024 / 100) * _backlightPercentage) : 0, 0);
|
||||
# endif // if defined(ESP32)
|
||||
}
|
||||
|
||||
if (!state && pcd8544) { pcd8544->fillScreen(ADAGFX_BLACK); } // Can't turn off, clearing the display is the least bad alternative
|
||||
_displayTimer = (state ? _displayTimeout : 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* registerButtonState: the button has been pressed, apply some debouncing
|
||||
***************************************************************************/
|
||||
void P141_data_struct::registerButtonState(uint8_t newButtonState,
|
||||
bool bPin3Invers) {
|
||||
if ((ButtonLastState == 0xFF) || (bPin3Invers != (!!newButtonState))) {
|
||||
ButtonLastState = newButtonState;
|
||||
DebounceCounter++;
|
||||
} else {
|
||||
ButtonLastState = 0xFF; // Reset
|
||||
markButtonStateProcessed();
|
||||
}
|
||||
|
||||
if ((ButtonLastState == newButtonState) &&
|
||||
(DebounceCounter >= P141_DebounceTreshold)) {
|
||||
ButtonState = true;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* markButtonStateProcessed: reset the button state
|
||||
***************************************************************************/
|
||||
void P141_data_struct::markButtonStateProcessed() {
|
||||
ButtonState = false;
|
||||
DebounceCounter = 0;
|
||||
}
|
||||
|
||||
#endif // ifdef USES_P141
|
||||
@@ -0,0 +1,159 @@
|
||||
#ifndef PLUGINSTRUCTS_P141_DATA_STRUCT_H
|
||||
#define PLUGINSTRUCTS_P141_DATA_STRUCT_H
|
||||
|
||||
#include "../../_Plugin_Helper.h"
|
||||
#ifdef USES_P141
|
||||
|
||||
# include <Adafruit_GFX.h> // include Adafruit graphics library
|
||||
# include <Adafruit_PCD8544.h> // include Adafruit PCD8544 LCD library
|
||||
|
||||
# include "../Helpers/AdafruitGFX_helper.h" // Use Adafruit graphics helper object
|
||||
|
||||
# define P141_FEATURE_CURSOR_XY_VALUES 1 // Enable availability of CursorX and CursorY values
|
||||
|
||||
# ifdef LIMIT_BUILD_SIZE
|
||||
# if P141_FEATURE_CURSOR_XY_VALUES
|
||||
# undef P141_FEATURE_CURSOR_XY_VALUES
|
||||
# define P141_FEATURE_CURSOR_XY_VALUES 0
|
||||
# endif // if P141_FEATURE_CURSOR_XY_VALUES
|
||||
# endif // ifdef LIMIT_BUILD_SIZE
|
||||
|
||||
# define P141_Nlines 9 // The number of different lines which can be displayed
|
||||
# define P141_Nchars 60 // Allow space for variables and formatting
|
||||
# define P141_DebounceTreshold 5 // number of 20 msec (fifty per second) ticks before the button has settled
|
||||
|
||||
# define P141_CS_PIN PIN(0) // CS pin
|
||||
# define P141_DC_PIN PIN(1) // DC pin
|
||||
# define P141_RST_PIN PIN(2) // RST pin
|
||||
# define P141_CONFIG_BUTTON_PIN PIN(3) // Pin for display-button
|
||||
# define P141_CONFIG_DISPLAY_TIMEOUT PCONFIG(1) // Time-out when display-button is enabled
|
||||
# define P141_CONFIG_CONTRAST PCONFIG(2) // Contrast
|
||||
# define P141_CONFIG_BACKLIGHT_PIN PCONFIG(3) // Backlight pin
|
||||
# define P141_CONFIG_BACKLIGHT_PERCENT PCONFIG(4) // Backlight percentage
|
||||
|
||||
# define P141_CONFIG_FLAGS PCONFIG_ULONG(0) // All flags
|
||||
# define P141_CONFIG_FLAG_NO_WAKE 0 // Flag: Don't wake display
|
||||
# define P141_CONFIG_FLAG_INVERT_BUTTON 1 // Flag: Inverted button state
|
||||
# define P141_CONFIG_FLAG_CLEAR_ON_EXIT 2 // Flag: Clear display on exit
|
||||
# define P141_CONFIG_FLAG_USE_COL_ROW 3 // Flag: Use Col/Row text addressing in commands
|
||||
# define P141_CONFIG_FLAG_MODE 4 // Flag-offset to store 4 bits for Mode, uses bits 4, 5, 6 and 7
|
||||
# define P141_CONFIG_FLAG_ROTATION 8 // Flag-offset to store 4 bits for Rotation, uses bits 8, 9, 10 and 11
|
||||
# define P141_CONFIG_FLAG_FONTSCALE 12 // Flag-offset to store 4 bits for Font scaling, uses bits 12, 13, 14 and 15
|
||||
# define P141_CONFIG_FLAG_LINESPACING 16 // Flag-offset to store 4 bits for Linespacing, uses bits 16, 17, 18 and 19
|
||||
# define P141_CONFIG_FLAG_CMD_TRIGGER 20 // Flag-offset to store 4 bits for Command trigger, uses bits 20, 21, 22 and 23
|
||||
# define P141_CONFIG_FLAG_BACK_FILL 28 // Flag: Background fill when printing text
|
||||
# define P141_CONFIG_FLAG_INVERTED 29 // Flag: Invert display content
|
||||
|
||||
// Getters
|
||||
# define P141_CONFIG_FLAG_GET_MODE (get4BitFromUL(P141_CONFIG_FLAGS, P141_CONFIG_FLAG_MODE))
|
||||
# define P141_CONFIG_FLAG_GET_ROTATION (get4BitFromUL(P141_CONFIG_FLAGS, P141_CONFIG_FLAG_ROTATION))
|
||||
# define P141_CONFIG_FLAG_GET_FONTSCALE (get4BitFromUL(P141_CONFIG_FLAGS, P141_CONFIG_FLAG_FONTSCALE))
|
||||
|
||||
# define P141_CONFIG_FLAG_GET_LINESPACING (get4BitFromUL(P141_CONFIG_FLAGS, P141_CONFIG_FLAG_LINESPACING))
|
||||
# define P141_CONFIG_FLAG_GET_CMD_TRIGGER (get4BitFromUL(P141_CONFIG_FLAGS, P141_CONFIG_FLAG_CMD_TRIGGER))
|
||||
|
||||
// Define the default values for both ESP32/lolin32 and D1 Mini
|
||||
# ifdef ESP32
|
||||
# define P141_LCD_CS 14
|
||||
# define P141_LCD_CS_HSPI 26 // when connected to Hardware-SPI GPIO-14 is already used
|
||||
# define P141_LCD_DC 27
|
||||
# define P141_LCD_RST 33
|
||||
# else // ifdef ESP32
|
||||
|
||||
// for D1 Mini
|
||||
# define P141_LCD_CS 16 // D0
|
||||
# define P141_LCD_DC 15 // D8
|
||||
# define P141_LCD_RST -1
|
||||
# endif // ifdef ESP32
|
||||
|
||||
enum class P141_CommandTrigger : uint8_t {
|
||||
pcd8544 = 0u,
|
||||
lcd = 1u,
|
||||
};
|
||||
|
||||
const __FlashStringHelper* toString(P141_CommandTrigger cmd);
|
||||
|
||||
struct P141_data_struct : public PluginTaskData_base {
|
||||
public:
|
||||
|
||||
P141_data_struct(uint8_t rotation,
|
||||
uint8_t fontscaling,
|
||||
AdaGFXTextPrintMode textmode,
|
||||
int8_t backlightPin,
|
||||
uint8_t backlightPercentage,
|
||||
uint8_t contrast,
|
||||
uint32_t displayTimer,
|
||||
String commandTrigger,
|
||||
uint16_t fgcolor = ADAGFX_WHITE,
|
||||
uint16_t bgcolor = ADAGFX_BLACK,
|
||||
bool textBackFill = true,
|
||||
bool displayInverted = false);
|
||||
~P141_data_struct();
|
||||
|
||||
bool plugin_init(struct EventStruct *event);
|
||||
bool plugin_exit(struct EventStruct *event);
|
||||
bool plugin_read(struct EventStruct *event);
|
||||
bool plugin_write(struct EventStruct *event,
|
||||
const String & string);
|
||||
bool plugin_ten_per_second(struct EventStruct *event);
|
||||
bool plugin_once_a_second(struct EventStruct *event);
|
||||
# if ADAGFX_ENABLE_GET_CONFIG_VALUE
|
||||
bool plugin_get_config_value(struct EventStruct *event,
|
||||
String & string);
|
||||
# endif // if ADAGFX_ENABLE_GET_CONFIG_VALUE
|
||||
|
||||
void registerButtonState(uint8_t newButtonState,
|
||||
bool bPin3Invers);
|
||||
void markButtonStateProcessed();
|
||||
bool getButtonState() {
|
||||
return ButtonState;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void displayOnOff(bool state);
|
||||
void updateFontMetrics();
|
||||
void cleanup();
|
||||
# if P141_FEATURE_CURSOR_XY_VALUES
|
||||
void updateValues(struct EventStruct *event);
|
||||
# endif // if P141_FEATURE_CURSOR_XY_VALUES
|
||||
|
||||
Adafruit_PCD8544 *pcd8544 = nullptr;
|
||||
AdafruitGFX_helper *gfxHelper = nullptr;
|
||||
|
||||
uint16_t _xpix = 84; // Fixed size
|
||||
uint16_t _ypix = 48;
|
||||
uint16_t _textcols;
|
||||
uint16_t _textrows;
|
||||
uint8_t _fontwidth = 6; // Default font characteristics
|
||||
uint8_t _fontheight = 10;
|
||||
uint8_t _heightOffset = 0;
|
||||
|
||||
uint8_t _rotation;
|
||||
uint8_t _fontscaling;
|
||||
AdaGFXTextPrintMode _textmode;
|
||||
int8_t _backlightPin;
|
||||
uint8_t _backlightPercentage;
|
||||
uint8_t _contrast;
|
||||
uint32_t _displayTimer;
|
||||
uint32_t _displayTimeout;
|
||||
String _commandTrigger;
|
||||
uint16_t _fgcolor;
|
||||
uint16_t _bgcolor;
|
||||
bool _textBackFill;
|
||||
bool _displayInverted;
|
||||
|
||||
String _commandTriggerCmd;
|
||||
|
||||
// Display button
|
||||
bool ButtonState = false; // button not touched
|
||||
uint8_t ButtonLastState = 0; // Last state checked (debouncing in progress)
|
||||
uint8_t DebounceCounter = 0; // debounce counter
|
||||
|
||||
int8_t _leftMarginCompensation = 0; // Not settable yet
|
||||
int8_t _topMarginCompensation = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif // ifdef USES_P141
|
||||
#endif // ifndef PLUGINSTRUCTS_P141_DATA_STRUCT_H
|
||||