addd ssd1306 lib
14
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/.editorconfig
Normal file
@@ -0,0 +1,14 @@
|
||||
# This file is for unifying the coding style for different editors and IDEs
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
max_line_length = 120
|
||||
curly_bracket_next_line = false
|
||||
17
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/.github/stale.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 180
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 14
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
2
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.vscode
|
||||
.pio
|
||||
29
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/.travis.yml
Normal file
@@ -0,0 +1,29 @@
|
||||
# documentation at https://docs.platformio.org/en/latest/integration/ci/travis.html
|
||||
|
||||
language: python
|
||||
python:
|
||||
- "3.7"
|
||||
|
||||
# Cache PlatformIO packages using Travis CI container-based infrastructure
|
||||
sudo: false
|
||||
cache:
|
||||
directories:
|
||||
- "~/.platformio"
|
||||
- $HOME/.cache/pip
|
||||
|
||||
env:
|
||||
- PLATFORMIO_CI_SRC=examples/SSD1306UiDemo
|
||||
- PLATFORMIO_CI_SRC=examples/SSD1306SimpleDemo
|
||||
- PLATFORMIO_CI_SRC=examples/SSD1306DrawingDemo
|
||||
- PLATFORMIO_CI_SRC=examples/SSD1306OTADemo
|
||||
- PLATFORMIO_CI_SRC=examples/SSD1306ClockDemo
|
||||
- PLATFORMIO_CI_SRC=examples/SSD1306TwoScreenDemo
|
||||
|
||||
|
||||
install:
|
||||
- pip install -U platformio
|
||||
- pio update
|
||||
- platformio lib -g install "paulstoffregen/Time@^1.6"
|
||||
|
||||
script:
|
||||
- platformio ci --lib="." --board=nodemcuv2
|
||||
@@ -0,0 +1,4 @@
|
||||
set(COMPONENT_ADD_INCLUDEDIRS src)
|
||||
set(COMPONENT_PRIV_REQUIRES arduino-esp32)
|
||||
set(COMPONENT_SRCDIRS src)
|
||||
register_component()
|
||||
70
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/CONTRIBUTING.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Contributing to ThingPulse OLED SSD1306
|
||||
|
||||
:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:
|
||||
|
||||
The following is a set of guidelines for contributing to the ThingPulse OLED SSD1306 library on GitHub. These are just guidelines, not rules, use your best judgment and feel free to propose changes to this document in a pull request.
|
||||
|
||||
It is appreciated if you raise an issue _before_ you start changing the code, discussing the proposed change; emphasizing that you are proposing to develop the patch yourself, and outlining the strategy for implementation. This type of discussion is what we should be doing on the issues list and it is better to do this before or in parallel to developing the patch rather than having "you should have done it this way" type of feedback on the PR itself.
|
||||
|
||||
### Table Of Contents
|
||||
* [General remarks](#general-remarks)
|
||||
* [Writing Documentation](#writing-documentation)
|
||||
* [Working with Git and GitHub](#working-with-git-and-github)
|
||||
* [General flow](#general-flow)
|
||||
* [Keeping your fork in sync](#keeping-your-fork-in-sync)
|
||||
* [Commit messages](#commit-messages)
|
||||
|
||||
## General remarks
|
||||
We are a friendly and welcoming community and look forward to your contributions. Once your contribution is integrated into this repository we feel responsible for it. Therefore, be prepared for constructive feedback. Before we merge anything we need to ensure that it fits in and is consistent with the rest of code.
|
||||
If you made something really cool but won't spend the time to integrate it into this upstream project please still share it in your fork on GitHub. If you mention it in an issue we'll take a look at it anyway.
|
||||
|
||||
## Writing Documentation
|
||||
ThingPulse maintains documentation for its products at [https://github.com/thingpulse/docs/](https://github.com/thingpulse/docs/). If you contribute features for this project that require altering the respective product guide then we ask you to prepare a pull request with the necessary documentation changes as well.
|
||||
|
||||
## Working with Git and GitHub
|
||||
|
||||
Avoid intermediate merge commits. [Rebase](https://www.atlassian.com/git/tutorials/merging-vs-rebasing) your feature branch onto `master` to pull updates and verify your local changes against them before placing the pull request.
|
||||
|
||||
### General flow
|
||||
1. [Fork](https://help.github.com/articles/fork-a-repo) this repository on GitHub.
|
||||
1. [Create a branch](https://help.github.com/articles/creating-and-deleting-branches-within-your-repository/#creating-a-branch) in your fork on GitHub **based on the `master` branch**.
|
||||
1. Clone the fork on your machine with `git clone https://github.com/<your-account>/<esp8266-oled-ssd1306>.git`
|
||||
1. `cd <weather-station-fork>` then run `git remote add upstream https://github.com/ThingPulse/esp8266-oled-ssd1306`
|
||||
1. `git checkout <branch-name>`
|
||||
1. Make changes to the code base and commit them using e.g. `git commit -a -m 'Look ma, I did it'`
|
||||
1. When you're done bring your fork up-to-date with the upstream repo ([see below](#keeping-your-fork-in-sync)). Then rebase your branch on `master` running `git rebase master`.
|
||||
1. `git push`
|
||||
1. [Create a pull request](https://help.github.com/articles/creating-a-pull-request/) (PR) on GitHub.
|
||||
|
||||
This is just one way of doing things. If you're proficient in Git matters you're free to choose your own. If you want to read more then the [GitHub chapter in the Git book](http://git-scm.com/book/en/v2/GitHub-Contributing-to-a-Project#The-GitHub-Flow) is a way to start. [GitHub's own documentation](https://help.github.com/categories/collaborating/) contains a wealth of information as well.
|
||||
|
||||
### Keeping your fork in sync
|
||||
You need to sync your fork with the upstream repository from time to time, latest before you rebase (see flow above).
|
||||
|
||||
1. `git fetch upstream`
|
||||
1. `git checkout master`
|
||||
1. `git merge upstream/master`
|
||||
|
||||
### Commit messages
|
||||
|
||||
From: [http://git-scm.com/book/ch5-2.html](http://git-scm.com/book/ch5-2.html)
|
||||
<pre>
|
||||
Short (50 chars or less) summary of changes
|
||||
|
||||
More detailed explanatory text, if necessary. Wrap it to about 72
|
||||
characters or so. In some contexts, the first line is treated as the
|
||||
subject of an email and the rest of the text as the body. The blank
|
||||
line separating the summary from the body is critical (unless you omit
|
||||
the body entirely); tools like rebase can get confused if you run the
|
||||
two together.
|
||||
|
||||
Further paragraphs come after blank lines.
|
||||
|
||||
- Bullet points are okay, too
|
||||
- Typically a hyphen or asterisk is used for the bullet, preceded by a
|
||||
single space, with blank lines in between, but conventions vary here
|
||||
</pre>
|
||||
|
||||
Don't forget to [reference affected issues](https://help.github.com/articles/closing-issues-via-commit-messages/) in the commit message to have them closed automatically on GitHub.
|
||||
|
||||
[Amend](https://help.github.com/articles/changing-a-commit-message/) your commit messages if necessary to make sure what the world sees on GitHub is as expressive and meaningful as possible.
|
||||
429
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/README.md
Normal file
@@ -0,0 +1,429 @@
|
||||
[](https://travis-ci.org/ThingPulse/esp8266-oled-ssd1306)
|
||||
|
||||
# ThingPulse OLED SSD1306 (ESP8266/ESP32/Mbed-OS)
|
||||
|
||||
> We just released version 4.0.0. Please have a look at our [upgrade guide](UPGRADE-4.0.md)
|
||||
|
||||
This is a driver for SSD1306 128x64, 128x32, 64x48 and 64x32 OLED displays running on the Arduino/ESP8266 & ESP32 and mbed-os platforms.
|
||||
Can be used with either the I2C or SPI version of the display.
|
||||
|
||||
You can either download this library as a zip file and unpack it to your Arduino/libraries folder or find it in the Arduino library manager under "ESP8266 and ESP32 Oled Driver for SSD1306 display". For mbed-os a copy of the files are available as an mbed-os library.
|
||||
|
||||
It is also available as a platformio library. Just execute the following command:
|
||||
```
|
||||
platformio lib install 562
|
||||
```
|
||||
|
||||
## Service level promise
|
||||
|
||||
<table><tr><td><img src="https://thingpulse.com/assets/ThingPulse-open-source-prime.png" width="150">
|
||||
</td><td>This is a ThingPulse <em>prime</em> project. See our <a href="https://thingpulse.com/about/open-source-commitment/">open-source commitment declaration</a> for what this means.</td></tr></table>
|
||||
|
||||
## Credits
|
||||
|
||||
This library has initially been written by Daniel Eichhorn ([@squix78](https://github.com/squix78)). Many thanks go to Fabrice Weinberg ([@FWeinb](https://github.com/FWeinb)) for optimizing and refactoring many aspects of the library. Also many thanks to the many committers who helped to add new features and who fixed many bugs. Mbed-OS support and other improvements were contributed by Helmut Tschemernjak ([@helmut64](https://github.com/helmut64)).
|
||||
|
||||
The init sequence for the SSD1306 was inspired by Adafruit's library for the same display.
|
||||
|
||||
## mbed-os
|
||||
This library has been adopted to support the ARM mbed-os environment. A copy of this library is available in mbed-os under the name OLED_SSD1306 by Helmut Tschemernjak. An alternate installation option is to copy the following files into your mbed-os project: OLEDDisplay.cpp OLEDDisplay.h OLEDDisplayFonts.h OLEDDisplayUi.cpp OLEDDisplayUi.h SSD1306I2C.h
|
||||
|
||||
## Usage
|
||||
|
||||
Check out the examples folder for a few comprehensive demonstrations how to use the library. Also check out the [ESP8266 Weather Station](https://github.com/ThingPulse/esp8266-weather-station) library which uses the OLED library to display beautiful weather information.
|
||||
|
||||
## Upgrade
|
||||
|
||||
The API changed a lot with the 3.0 release. If you were using this library with older versions please have a look at the [Upgrade Guide](UPGRADE-3.0.md).
|
||||
|
||||
Going from 3.x version to 4.0 a lot of internals changed and compatibility for more displays was added. Please read the [Upgrade Guide](UPGRADE-4.0.md).
|
||||
|
||||
## Features
|
||||
|
||||
* Draw pixels at given coordinates
|
||||
* Draw lines from given coordinates to given coordinates
|
||||
* Draw or fill a rectangle with given dimensions
|
||||
* Draw Text at given coordinates:
|
||||
* Define Alignment: Left, Right and Center
|
||||
* Set the Fontface you want to use (see section Fonts below)
|
||||
* Limit the width of the text by an amount of pixels. Before this widths will be reached, the renderer will wrap the text to a new line if possible
|
||||
* Display content in automatically side scrolling carousel
|
||||
* Define transition cycles
|
||||
* Define how long one frame will be displayed
|
||||
* Draw the different frames in callback methods
|
||||
* One indicator per frame will be automatically displayed. The active frame will be displayed from inactive once
|
||||
|
||||
## Fonts
|
||||
|
||||
Fonts are defined in a proprietary but open format. You can create new font files by choosing from a given list
|
||||
of open sourced Fonts from this web app: http://oleddisplay.squix.ch
|
||||
Choose the font family, style and size, check the preview image and if you like what you see click the "Create" button. This will create the font array in a text area form where you can copy and paste it into a new or existing header file.
|
||||
|
||||
|
||||

|
||||
|
||||
## Hardware Abstraction
|
||||
|
||||
The library supports different protocols to access the OLED display. Currently there is support for I2C using the built in Wire.h library, I2C by using the much faster [BRZO I2C library](https://github.com/pasko-zh/brzo_i2c) written in assembler and it also supports displays which come with the SPI interface.
|
||||
|
||||
### I2C with Wire.h
|
||||
|
||||
```C++
|
||||
#include <Wire.h>
|
||||
#include "SSD1306Wire.h"
|
||||
|
||||
// for 128x64 displays:
|
||||
SSD1306Wire display(0x3c, SDA, SCL); // ADDRESS, SDA, SCL
|
||||
// for 128x32 displays:
|
||||
// SSD1306Wire display(0x3c, SDA, SCL, GEOMETRY_128_32); // ADDRESS, SDA, SCL, GEOMETRY_128_32 (or 128_64)
|
||||
// for using 2nd Hardware I2C (if available)
|
||||
// SSD1306Wire(0x3c, SDA, SCL, GEOMETRY_128_64, I2C_TWO); //default value is I2C_ONE if not mentioned
|
||||
// By default SD1306Wire set I2C frequency to 700000, you can use set either another frequency or skip setting the frequency by providing -1 value
|
||||
// SSD1306Wire(0x3c, SDA, SCL, GEOMETRY_128_64, I2C_ONE, 400000); //set I2C frequency to 400kHz
|
||||
// SSD1306Wire(0x3c, SDA, SCL, GEOMETRY_128_64, I2C_ONE, -1); //skip setting the I2C bus frequency
|
||||
```
|
||||
|
||||
for a SH1106:
|
||||
```C++
|
||||
#include <Wire.h>
|
||||
#include "SH1106Wire.h"
|
||||
|
||||
SH1106Wire display(0x3c, SDA, SCL); // ADDRESS, SDA, SCL
|
||||
// By default SH1106Wire set I2C frequency to 700000, you can use set either another frequency or skip setting the frequency by providing -1 value
|
||||
// SH1106Wire(0x3c, SDA, SCL, GEOMETRY_128_64, I2C_ONE, 400000); //set I2C frequency to 400kHz
|
||||
// SH1106Wire(0x3c, SDA, SCL, GEOMETRY_128_64, I2C_ONE, -1); //skip setting the I2C bus frequency
|
||||
```
|
||||
|
||||
### I2C with brzo_i2c
|
||||
|
||||
```C++
|
||||
#include <brzo_i2c.h>
|
||||
#include "SSD1306Brzo.h"
|
||||
|
||||
SSD1306Brzo display(0x3c, SDA, SCL); // ADDRESS, SDA, SCL
|
||||
```
|
||||
or for the SH1106:
|
||||
```C++
|
||||
#include <brzo_i2c.h>
|
||||
#include "SH1106Brzo.h"
|
||||
|
||||
SH1106Brzo display(0x3c, SDA, SCL); // ADDRESS, SDA, SCL
|
||||
```
|
||||
|
||||
### SPI
|
||||
|
||||
```C++
|
||||
#include <SPI.h>
|
||||
#include "SSD1306Spi.h"
|
||||
|
||||
SSD1306Spi display(D0, D2, D8); // RES, DC, CS
|
||||
```
|
||||
or for the SH1106:
|
||||
```C++
|
||||
#include <SPI.h>
|
||||
#include "SH1106Spi.h"
|
||||
|
||||
SH1106Spi display(D0, D2); // RES, DC
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Display Control
|
||||
|
||||
```C++
|
||||
// Initialize the display
|
||||
void init();
|
||||
|
||||
// Free the memory used by the display
|
||||
void end();
|
||||
|
||||
// Cycle through the initialization
|
||||
void resetDisplay(void);
|
||||
|
||||
// Connect again to the display through I2C
|
||||
void reconnect(void);
|
||||
|
||||
// Turn the display on
|
||||
void displayOn(void);
|
||||
|
||||
// Turn the display offs
|
||||
void displayOff(void);
|
||||
|
||||
// Clear the local pixel buffer
|
||||
void clear(void);
|
||||
|
||||
// Write the buffer to the display memory
|
||||
void display(void);
|
||||
|
||||
// Inverted display mode
|
||||
void invertDisplay(void);
|
||||
|
||||
// Normal display mode
|
||||
void normalDisplay(void);
|
||||
|
||||
// Set display contrast
|
||||
// really low brightness & contrast: contrast = 10, precharge = 5, comdetect = 0
|
||||
// normal brightness & contrast: contrast = 100
|
||||
void setContrast(uint8_t contrast, uint8_t precharge = 241, uint8_t comdetect = 64);
|
||||
|
||||
// Convenience method to access
|
||||
void setBrightness(uint8_t);
|
||||
|
||||
// Turn the display upside down
|
||||
void flipScreenVertically();
|
||||
|
||||
// Draw the screen mirrored
|
||||
void mirrorScreen();
|
||||
```
|
||||
|
||||
## Pixel drawing
|
||||
|
||||
```C++
|
||||
|
||||
/* Drawing functions */
|
||||
// Sets the color of all pixel operations
|
||||
// color : BLACK, WHITE, INVERSE
|
||||
void setColor(OLEDDISPLAY_COLOR color);
|
||||
|
||||
// Draw a pixel at given position
|
||||
void setPixel(int16_t x, int16_t y);
|
||||
|
||||
// Draw a line from position 0 to position 1
|
||||
void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1);
|
||||
|
||||
// Draw the border of a rectangle at the given location
|
||||
void drawRect(int16_t x, int16_t y, int16_t width, int16_t height);
|
||||
|
||||
// Fill the rectangle
|
||||
void fillRect(int16_t x, int16_t y, int16_t width, int16_t height);
|
||||
|
||||
// Draw the border of a circle
|
||||
void drawCircle(int16_t x, int16_t y, int16_t radius);
|
||||
|
||||
// Fill circle
|
||||
void fillCircle(int16_t x, int16_t y, int16_t radius);
|
||||
|
||||
// Draw a line horizontally
|
||||
void drawHorizontalLine(int16_t x, int16_t y, int16_t length);
|
||||
|
||||
// Draw a lin vertically
|
||||
void drawVerticalLine(int16_t x, int16_t y, int16_t length);
|
||||
|
||||
// Draws a rounded progress bar with the outer dimensions given by width and height. Progress is
|
||||
// a unsigned byte value between 0 and 100
|
||||
void drawProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t progress);
|
||||
|
||||
// Draw a bitmap in the internal image format
|
||||
void drawFastImage(int16_t x, int16_t y, int16_t width, int16_t height, const uint8_t *image);
|
||||
|
||||
// Draw a XBM
|
||||
void drawXbm(int16_t x, int16_t y, int16_t width, int16_t height, const char* xbm);
|
||||
```
|
||||
|
||||
## Text operations
|
||||
|
||||
``` C++
|
||||
void drawString(int16_t x, int16_t y, String text);
|
||||
|
||||
// Draws a String with a maximum width at the given location.
|
||||
// If the given String is wider than the specified width
|
||||
// The text will be wrapped to the next line at a space or dash
|
||||
void drawStringMaxWidth(int16_t x, int16_t y, int16_t maxLineWidth, String text);
|
||||
|
||||
// Returns the width of the const char* with the current
|
||||
// font settings
|
||||
uint16_t getStringWidth(const char* text, uint16_t length);
|
||||
|
||||
// Convencience method for the const char version
|
||||
uint16_t getStringWidth(String text);
|
||||
|
||||
// Specifies relative to which anchor point
|
||||
// the text is rendered. Available constants:
|
||||
// TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER_BOTH
|
||||
void setTextAlignment(OLEDDISPLAY_TEXT_ALIGNMENT textAlignment);
|
||||
|
||||
// Sets the current font. Available default fonts
|
||||
// ArialMT_Plain_10, ArialMT_Plain_16, ArialMT_Plain_24
|
||||
// Or create one with the font tool at http://oleddisplay.squix.ch
|
||||
void setFont(const uint8_t* fontData);
|
||||
```
|
||||
|
||||
## Ui Library (OLEDDisplayUi)
|
||||
|
||||
The Ui Library is used to provide a basic set of Ui elements called, `Frames` and `Overlays`. A `Frame` is used to provide
|
||||
information the default behaviour is to display a `Frame` for a defined time and than move to the next. The library also provides an `Indicator` that will be updated accordingly. An `Overlay` on the other hand is a pieces of information (e.g. a clock) that is displayed always at the same position.
|
||||
|
||||
|
||||
```C++
|
||||
/**
|
||||
* Initialise the display
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* Configure the internal used target FPS
|
||||
*/
|
||||
void setTargetFPS(uint8_t fps);
|
||||
|
||||
/**
|
||||
* Enable automatic transition to next frame after the some time can be configured with
|
||||
* `setTimePerFrame` and `setTimePerTransition`.
|
||||
*/
|
||||
void enableAutoTransition();
|
||||
|
||||
/**
|
||||
* Disable automatic transition to next frame.
|
||||
*/
|
||||
void disableAutoTransition();
|
||||
|
||||
/**
|
||||
* Set the direction if the automatic transitioning
|
||||
*/
|
||||
void setAutoTransitionForwards();
|
||||
void setAutoTransitionBackwards();
|
||||
|
||||
/**
|
||||
* Set the approx. time a frame is displayed
|
||||
*/
|
||||
void setTimePerFrame(uint16_t time);
|
||||
|
||||
/**
|
||||
* Set the approx. time a transition will take
|
||||
*/
|
||||
void setTimePerTransition(uint16_t time);
|
||||
|
||||
/**
|
||||
* Draw the indicator.
|
||||
* This is the default state for all frames if
|
||||
* the indicator was hidden on the previous frame
|
||||
* it will be slided in.
|
||||
*/
|
||||
void enableIndicator();
|
||||
|
||||
/**
|
||||
* Don't draw the indicator.
|
||||
* This will slide out the indicator
|
||||
* when transitioning to the next frame.
|
||||
*/
|
||||
void disableIndicator();
|
||||
|
||||
/**
|
||||
* Enable drawing of all indicators.
|
||||
*/
|
||||
void enableAllIndicators();
|
||||
|
||||
/**
|
||||
* Disable drawing of all indicators.
|
||||
*/
|
||||
void disableAllIndicators();
|
||||
|
||||
/**
|
||||
* Set the position of the indicator bar.
|
||||
*/
|
||||
void setIndicatorPosition(IndicatorPosition pos);
|
||||
|
||||
/**
|
||||
* Set the direction of the indicator bar. Defining the order of frames ASCENDING / DESCENDING
|
||||
*/
|
||||
void setIndicatorDirection(IndicatorDirection dir);
|
||||
|
||||
/**
|
||||
* Set the symbol to indicate an active frame in the indicator bar.
|
||||
*/
|
||||
void setActiveSymbol(const char* symbol);
|
||||
|
||||
/**
|
||||
* Set the symbol to indicate an inactive frame in the indicator bar.
|
||||
*/
|
||||
void setInactiveSymbol(const char* symbol);
|
||||
|
||||
/**
|
||||
* Configure what animation is used to transition from one frame to another
|
||||
*/
|
||||
void setFrameAnimation(AnimationDirection dir);
|
||||
|
||||
/**
|
||||
* Add frame drawing functions
|
||||
*/
|
||||
void setFrames(FrameCallback* frameFunctions, uint8_t frameCount);
|
||||
|
||||
/**
|
||||
* Add overlays drawing functions that are draw independent of the Frames
|
||||
*/
|
||||
void setOverlays(OverlayCallback* overlayFunctions, uint8_t overlayCount);
|
||||
|
||||
/**
|
||||
* Set the function that will draw each step
|
||||
* in the loading animation
|
||||
*/
|
||||
void setLoadingDrawFunction(LoadingDrawFunction loadingDrawFunction);
|
||||
|
||||
/**
|
||||
* Run the loading process
|
||||
*/
|
||||
void runLoadingProcess(LoadingStage* stages, uint8_t stagesCount);
|
||||
|
||||
// Manuell Controll
|
||||
void nextFrame();
|
||||
void previousFrame();
|
||||
|
||||
/**
|
||||
* Switch without transition to frame `frame`.
|
||||
*/
|
||||
void switchToFrame(uint8_t frame);
|
||||
|
||||
/**
|
||||
* Transition to frame `frame`, when the `frame` number is bigger than the current
|
||||
* frame the forward animation will be used, otherwise the backwards animation is used.
|
||||
*/
|
||||
void transitionToFrame(uint8_t frame);
|
||||
|
||||
// State Info
|
||||
OLEDDisplayUiState* getUiState();
|
||||
|
||||
// This needs to be called in the main loop
|
||||
// the returned value is the remaining time (in ms)
|
||||
// you have to draw after drawing to keep the frame budget.
|
||||
int8_t update();
|
||||
```
|
||||
|
||||
## Example: SSD1306Demo
|
||||
|
||||
### Frame 1
|
||||

|
||||
|
||||
This frame shows three things:
|
||||
* How to draw an xbm image
|
||||
* How to draw a static text which is not moved by the frame transition
|
||||
* The active/inactive frame indicators
|
||||
|
||||
### Frame 2
|
||||

|
||||
|
||||
Currently there are one fontface with three sizes included in the library: Arial 10, 16 and 24. Once the converter is published you will be able to convert any ttf font into the used format.
|
||||
|
||||
### Frame 3
|
||||
|
||||

|
||||
|
||||
This frame demonstrates the text alignment. The coordinates in the frame show relative to which position the texts have been rendered.
|
||||
|
||||
### Frame 4
|
||||
|
||||

|
||||
|
||||
This shows how to use define a maximum width after which the driver automatically wraps a word to the next line. This comes in very handy if you have longer texts to display.
|
||||
|
||||
### SPI version
|
||||
|
||||

|
||||
|
||||
This shows the code working on the SPI version of the display. See demo code for ESP8266 pins used.
|
||||
|
||||
## Selection of projects using this library
|
||||
|
||||
* [QRCode ESP8266](https://github.com/anunpanya/ESP8266_QRcode) (by @anunpanya)
|
||||
* [Scan I2C](https://github.com/hallard/Scan-I2C-WiFi) (by @hallard)
|
||||
* [ThingPulse Weather Station](https://github.com/ThingPulse/esp8266-weather-station)
|
||||
* [Meshtastic](https://www.meshtastic.org/) - an open source GPS communicator mesh radio
|
||||
* Yours?
|
||||
@@ -0,0 +1,20 @@
|
||||
# GEOMETRY_64_48
|
||||
|
||||
The 64x48 geometry setting are working with the `Wire.h` and `brzo_i2c` libraries.
|
||||
|
||||
I've tested it successfully with a WEMOS D1 mini Lite and a WEMOS OLED shield
|
||||
|
||||
Initialization code:
|
||||
|
||||
- Wire
|
||||
```
|
||||
#include <Wire.h>
|
||||
#include <SSD1306Wire.h>
|
||||
SSD1306Wire display(0x3c, D2, D1, GEOMETRY_64_48 ); // WEMOS OLED shield
|
||||
```
|
||||
|
||||
- BRZO i2c
|
||||
```
|
||||
#include <SSD1306Brzo.h>
|
||||
SSD1306Brzo display(0x3c, D2, D1, GEOMETRY_64_48 ); // WEMOS OLED Shield
|
||||
```
|
||||
125
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/UPGRADE-3.0.md
Normal file
@@ -0,0 +1,125 @@
|
||||
# Upgrade from 2.0 to 3.0
|
||||
|
||||
While developing version 3.0 we made some breaking changes to the public
|
||||
API of this library. This document will help you update your code to work with
|
||||
version 3.0
|
||||
|
||||
## Font Definitions
|
||||
|
||||
To get better performance and a smaller font definition format, we change the memory
|
||||
layout of the font definition format. If you are using custom fonts not included in
|
||||
this library we updated the font generator [here](http://oleddisplay.squix.ch/#/home).
|
||||
Please update your fonts to be working with 3.0 by selecting the respective version in the dropdown.
|
||||
|
||||
|
||||
## Architectural Changes
|
||||
|
||||
To become a more versatile library for the SSD1306 chipset we abstracted the
|
||||
hardware connection into subclasses of the base display class now called `OLEDDisplay`.
|
||||
This library is currently shipping with three implementations:
|
||||
|
||||
* `SSD1306Wire` implementing the I2C protocol using the Wire Library.
|
||||
* `SSD1306Brzo` implementing the I2C protocol using the faster [`brzo_i2c`](https://github.com/pasko-zh/brzo_i2c) library.
|
||||
* `SSD1306Spi` implementing the SPI protocol.
|
||||
|
||||
To keep backwards compatiblity with the old API `SSD1306` is an alias of `SSD1306Wire`.
|
||||
If you are not using the UI components you don't have to change anything to keep your code working.
|
||||
|
||||
## Name Changes
|
||||
|
||||
[Naming things is hard](http://martinfowler.com/bliki/TwoHardThings.html), to better reflect our intention with this library
|
||||
we changed the name of the base class to `OLEDDisplay` and the UI library accordingly to `OLEDDisplayUi`.
|
||||
As a consequence the type definitions of all frame and overlay related functions changed.
|
||||
This means that you have to update all your frame drawing callbacks from:
|
||||
|
||||
```c
|
||||
bool frame1(SSD1306 *display, SSD1306UiState* state, int x, int y);
|
||||
```
|
||||
|
||||
too
|
||||
|
||||
```c
|
||||
void frame1(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
|
||||
```
|
||||
|
||||
And your overlay drawing functions from:
|
||||
|
||||
```c
|
||||
bool overlay1(SSD1306 *display, SSD1306UiState* state);
|
||||
```
|
||||
|
||||
too
|
||||
|
||||
```c
|
||||
void overlay1(OLEDDisplay *display, OLEDDisplayUiState* state);
|
||||
```
|
||||
|
||||
## New Features
|
||||
|
||||
### Loading Animation
|
||||
|
||||
While using this library ourself we noticed a pattern emerging. We want to drawing
|
||||
a loading progress while connecting to WiFi and updating weather data etc.
|
||||
|
||||
The simplest thing was to add the function `drawProgressBar(x, y, width, height, progress)`
|
||||
,where `progress` is between `0` and `100`, right to the `OLEDDisplay` class.
|
||||
|
||||
But we didn't stop there. We added a new feature to the `OLEDDisplayUi` called `LoadingStages`.
|
||||
You can define your loading process like this:
|
||||
|
||||
```c++
|
||||
LoadingStage loadingStages[] = {
|
||||
{
|
||||
.process = "Connect to WiFi",
|
||||
.callback = []() {
|
||||
// Connect to WiFi
|
||||
}
|
||||
},
|
||||
{
|
||||
.process = "Get time from NTP",
|
||||
.callback = []() {
|
||||
// Get current time via NTP
|
||||
}
|
||||
}
|
||||
// more steps
|
||||
};
|
||||
|
||||
int LOADING_STAGES_COUNT = sizeof(loadingStages) / sizeof(LoadingStage);
|
||||
```
|
||||
|
||||
After defining your array of `LoadingStages` you can then run the loading process by using
|
||||
`ui.runLoadingProcess(loadingStages, LOADING_STAGES_COUNT)`. This will give you a
|
||||
nice little loading animation you can see in the beginning of [this](https://vimeo.com/168362918)
|
||||
video.
|
||||
|
||||
To further customize this you are free to define your own `LoadingDrawFunction` like this:
|
||||
|
||||
```c
|
||||
void myLoadingDraw(OLEDDisplay *display, LoadingStage* stage, uint8_t progress) {
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(ArialMT_Plain_10);
|
||||
// stage->process contains the text of the current progress e.q. "Connect to WiFi"
|
||||
display->drawString(64, 18, stage->process);
|
||||
// you could just print the current process without the progress bar
|
||||
display->drawString(64, 28, progress);
|
||||
}
|
||||
```
|
||||
|
||||
After defining a function like that, you can pass it to the Ui library by use
|
||||
`ui.setLoadingDrawFunction(myLoadingDraw)`.
|
||||
|
||||
|
||||
### Text Logging
|
||||
|
||||
It is always useful to display some text on the display without worrying to much
|
||||
where it goes and managing it. In 3.0 we made the `OLEDDisplay` class implement
|
||||
[`Print`](https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/Print.h)
|
||||
so you can use it like you would use `Serial`. We calls this feature `LogBuffer`
|
||||
and the only thing you have to do is to define how many lines you want to display
|
||||
and how many characters there are on average on each. This is done by calling
|
||||
`setLogBuffer(lines, chars);`. If there is not enough memory the function will
|
||||
return false.
|
||||
|
||||
After that you can draw the `LogBuffer` anywhere you want by calling `drawLogBuffer(x, y)`.
|
||||
(Note: You have to call `display()` to update the screen)
|
||||
We made a [video](https://www.youtube.com/watch?v=8Fiss77A3TE) showing this feature in action.
|
||||
27
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/UPGRADE-4.0.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Upgrade from 3.x to 4.0
|
||||
|
||||
There are changes that breaks compatibility with older versions.
|
||||
|
||||
1. You'll have to change data type for all your binary resources such as images and fonts from
|
||||
|
||||
```c
|
||||
const char MySymbol[] PROGMEM = {
|
||||
```
|
||||
|
||||
to
|
||||
|
||||
```c
|
||||
const uint8_t MySymbol[] PROGMEM = {
|
||||
```
|
||||
|
||||
1. Arguments of `setContrast` from `char` to `uint8_t`
|
||||
|
||||
```c++
|
||||
void OLEDDisplay::setContrast(char contrast, char precharge, char comdetect);
|
||||
```
|
||||
|
||||
to
|
||||
|
||||
```c++
|
||||
void OLEDDisplay::setContrast(uint8_t contrast, uint8_t precharge, uint8_t comdetect);
|
||||
```
|
||||
@@ -0,0 +1,3 @@
|
||||
COMPONENT_ADD_INCLUDEDIRS := src
|
||||
COMPONENT_SRCDIRS := src
|
||||
CXXFLAGS += -Wno-ignored-qualifiers
|
||||
@@ -0,0 +1,214 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* ThingPulse invests considerable time and money to develop these open source libraries.
|
||||
* Please support us by buying our products (and not the clones) from
|
||||
* https://thingpulse.com
|
||||
*
|
||||
*/
|
||||
|
||||
#include <TimeLib.h>
|
||||
|
||||
// Include the correct display library
|
||||
// For a connection via I2C using Wire include
|
||||
#include <Wire.h> // Only needed for Arduino 1.6.5 and earlier
|
||||
#include "SSD1306Wire.h" // legacy include: `#include "SSD1306.h"`
|
||||
// or #include "SH1106Wire.h", legacy include: `#include "SH1106.h"`
|
||||
// For a connection via I2C using brzo_i2c (must be installed) include
|
||||
// #include <brzo_i2c.h> // Only needed for Arduino 1.6.5 and earlier
|
||||
// #include "SSD1306Brzo.h"
|
||||
// #include "SH1106Brzo.h"
|
||||
// For a connection via SPI include
|
||||
// #include <SPI.h> // Only needed for Arduino 1.6.5 and earlier
|
||||
// #include "SSD1306Spi.h"
|
||||
// #include "SH1106SPi.h"
|
||||
|
||||
// Include the UI lib
|
||||
#include "OLEDDisplayUi.h"
|
||||
|
||||
// Include custom images
|
||||
#include "images.h"
|
||||
|
||||
// Use the corresponding display class:
|
||||
|
||||
// Initialize the OLED display using SPI
|
||||
// D5 -> CLK
|
||||
// D7 -> MOSI (DOUT)
|
||||
// D0 -> RES
|
||||
// D2 -> DC
|
||||
// D8 -> CS
|
||||
// SSD1306Spi display(D0, D2, D8);
|
||||
// or
|
||||
// SH1106Spi display(D0, D2);
|
||||
|
||||
// Initialize the OLED display using brzo_i2c
|
||||
// D3 -> SDA
|
||||
// D5 -> SCL
|
||||
// SSD1306Brzo display(0x3c, D3, D5);
|
||||
// or
|
||||
// SH1106Brzo display(0x3c, D3, D5);
|
||||
|
||||
// Initialize the OLED display using Wire library
|
||||
SSD1306Wire display(0x3c, D3, D5);
|
||||
// SH1106 display(0x3c, D3, D5);
|
||||
|
||||
OLEDDisplayUi ui ( &display );
|
||||
|
||||
int screenW = 128;
|
||||
int screenH = 64;
|
||||
int clockCenterX = screenW/2;
|
||||
int clockCenterY = ((screenH-16)/2)+16; // top yellow part is 16 px height
|
||||
int clockRadius = 23;
|
||||
|
||||
// utility function for digital clock display: prints leading 0
|
||||
String twoDigits(int digits){
|
||||
if(digits < 10) {
|
||||
String i = '0'+String(digits);
|
||||
return i;
|
||||
}
|
||||
else {
|
||||
return String(digits);
|
||||
}
|
||||
}
|
||||
|
||||
void clockOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) {
|
||||
|
||||
}
|
||||
|
||||
void analogClockFrame(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
|
||||
// ui.disableIndicator();
|
||||
|
||||
// Draw the clock face
|
||||
// display->drawCircle(clockCenterX + x, clockCenterY + y, clockRadius);
|
||||
display->drawCircle(clockCenterX + x, clockCenterY + y, 2);
|
||||
//
|
||||
//hour ticks
|
||||
for( int z=0; z < 360;z= z + 30 ){
|
||||
//Begin at 0° and stop at 360°
|
||||
float angle = z ;
|
||||
angle = ( angle / 57.29577951 ) ; //Convert degrees to radians
|
||||
int x2 = ( clockCenterX + ( sin(angle) * clockRadius ) );
|
||||
int y2 = ( clockCenterY - ( cos(angle) * clockRadius ) );
|
||||
int x3 = ( clockCenterX + ( sin(angle) * ( clockRadius - ( clockRadius / 8 ) ) ) );
|
||||
int y3 = ( clockCenterY - ( cos(angle) * ( clockRadius - ( clockRadius / 8 ) ) ) );
|
||||
display->drawLine( x2 + x , y2 + y , x3 + x , y3 + y);
|
||||
}
|
||||
|
||||
// display second hand
|
||||
float angle = second() * 6 ;
|
||||
angle = ( angle / 57.29577951 ) ; //Convert degrees to radians
|
||||
int x3 = ( clockCenterX + ( sin(angle) * ( clockRadius - ( clockRadius / 5 ) ) ) );
|
||||
int y3 = ( clockCenterY - ( cos(angle) * ( clockRadius - ( clockRadius / 5 ) ) ) );
|
||||
display->drawLine( clockCenterX + x , clockCenterY + y , x3 + x , y3 + y);
|
||||
//
|
||||
// display minute hand
|
||||
angle = minute() * 6 ;
|
||||
angle = ( angle / 57.29577951 ) ; //Convert degrees to radians
|
||||
x3 = ( clockCenterX + ( sin(angle) * ( clockRadius - ( clockRadius / 4 ) ) ) );
|
||||
y3 = ( clockCenterY - ( cos(angle) * ( clockRadius - ( clockRadius / 4 ) ) ) );
|
||||
display->drawLine( clockCenterX + x , clockCenterY + y , x3 + x , y3 + y);
|
||||
//
|
||||
// display hour hand
|
||||
angle = hour() * 30 + int( ( minute() / 12 ) * 6 ) ;
|
||||
angle = ( angle / 57.29577951 ) ; //Convert degrees to radians
|
||||
x3 = ( clockCenterX + ( sin(angle) * ( clockRadius - ( clockRadius / 2 ) ) ) );
|
||||
y3 = ( clockCenterY - ( cos(angle) * ( clockRadius - ( clockRadius / 2 ) ) ) );
|
||||
display->drawLine( clockCenterX + x , clockCenterY + y , x3 + x , y3 + y);
|
||||
}
|
||||
|
||||
void digitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
|
||||
String timenow = String(hour())+":"+twoDigits(minute())+":"+twoDigits(second());
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(ArialMT_Plain_24);
|
||||
display->drawString(clockCenterX + x , clockCenterY + y, timenow );
|
||||
}
|
||||
|
||||
// This array keeps function pointers to all frames
|
||||
// frames are the single views that slide in
|
||||
FrameCallback frames[] = { analogClockFrame, digitalClockFrame };
|
||||
|
||||
// how many frames are there?
|
||||
int frameCount = 2;
|
||||
|
||||
// Overlays are statically drawn on top of a frame eg. a clock
|
||||
OverlayCallback overlays[] = { clockOverlay };
|
||||
int overlaysCount = 1;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
Serial.println();
|
||||
|
||||
// The ESP is capable of rendering 60fps in 80Mhz mode
|
||||
// but that won't give you much time for anything else
|
||||
// run it in 160Mhz mode or just set it to 30 fps
|
||||
ui.setTargetFPS(60);
|
||||
|
||||
// Customize the active and inactive symbol
|
||||
ui.setActiveSymbol(activeSymbol);
|
||||
ui.setInactiveSymbol(inactiveSymbol);
|
||||
|
||||
// You can change this to
|
||||
// TOP, LEFT, BOTTOM, RIGHT
|
||||
ui.setIndicatorPosition(TOP);
|
||||
|
||||
// Defines where the first frame is located in the bar.
|
||||
ui.setIndicatorDirection(LEFT_RIGHT);
|
||||
|
||||
// You can change the transition that is used
|
||||
// SLIDE_LEFT, SLIDE_RIGHT, SLIDE_UP, SLIDE_DOWN
|
||||
ui.setFrameAnimation(SLIDE_LEFT);
|
||||
|
||||
// Add frames
|
||||
ui.setFrames(frames, frameCount);
|
||||
|
||||
// Add overlays
|
||||
ui.setOverlays(overlays, overlaysCount);
|
||||
|
||||
// Initialising the UI will init the display too.
|
||||
ui.init();
|
||||
|
||||
display.flipScreenVertically();
|
||||
|
||||
unsigned long secsSinceStart = millis();
|
||||
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
|
||||
const unsigned long seventyYears = 2208988800UL;
|
||||
// subtract seventy years:
|
||||
unsigned long epoch = secsSinceStart - seventyYears * SECS_PER_HOUR;
|
||||
setTime(epoch);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
int remainingTimeBudget = ui.update();
|
||||
|
||||
if (remainingTimeBudget > 0) {
|
||||
// You can do some work here
|
||||
// Don't do stuff if you are below your
|
||||
// time budget.
|
||||
delay(remainingTimeBudget);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
const unsigned char activeSymbol[] PROGMEM = {
|
||||
B00000000,
|
||||
B00000000,
|
||||
B00011000,
|
||||
B00100100,
|
||||
B01000010,
|
||||
B01000010,
|
||||
B00100100,
|
||||
B00011000
|
||||
};
|
||||
|
||||
const unsigned char inactiveSymbol[] PROGMEM = {
|
||||
B00000000,
|
||||
B00000000,
|
||||
B00000000,
|
||||
B00000000,
|
||||
B00011000,
|
||||
B00011000,
|
||||
B00000000,
|
||||
B00000000
|
||||
};
|
||||
@@ -0,0 +1,233 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
|
||||
* Copyright (c) 2018 by Fabrice Weinberg
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* ThingPulse invests considerable time and money to develop these open source libraries.
|
||||
* Please support us by buying our products (and not the clones) from
|
||||
* https://thingpulse.com
|
||||
*
|
||||
*/
|
||||
|
||||
// Include the correct display library
|
||||
// For a connection via I2C using Wire include
|
||||
#include <Wire.h> // Only needed for Arduino 1.6.5 and earlier
|
||||
#include "SSD1306Wire.h" // legacy include: `#include "SSD1306.h"`
|
||||
// or #include "SH1106Wire.h", legacy include: `#include "SH1106.h"`
|
||||
// For a connection via I2C using brzo_i2c (must be installed) include
|
||||
// #include <brzo_i2c.h> // Only needed for Arduino 1.6.5 and earlier
|
||||
// #include "SSD1306Brzo.h"
|
||||
// #include "SH1106Brzo.h"
|
||||
// For a connection via SPI include
|
||||
// #include <SPI.h> // Only needed for Arduino 1.6.5 and earlier
|
||||
// #include "SSD1306Spi.h"
|
||||
// #include "SH1106SPi.h"
|
||||
|
||||
// Use the corresponding display class:
|
||||
|
||||
// Initialize the OLED display using SPI
|
||||
// D5 -> CLK
|
||||
// D7 -> MOSI (DOUT)
|
||||
// D0 -> RES
|
||||
// D2 -> DC
|
||||
// D8 -> CS
|
||||
// SSD1306Spi display(D0, D2, D8);
|
||||
// or
|
||||
// SH1106Spi display(D0, D2);
|
||||
|
||||
// Initialize the OLED display using brzo_i2c
|
||||
// D3 -> SDA
|
||||
// D5 -> SCL
|
||||
// SSD1306Brzo display(0x3c, D3, D5);
|
||||
// or
|
||||
// SH1106Brzo display(0x3c, D3, D5);
|
||||
|
||||
// Initialize the OLED display using Wire library
|
||||
SSD1306Wire display(0x3c, D3, D5);
|
||||
// SH1106 display(0x3c, D3, D5);
|
||||
|
||||
// Adapted from Adafruit_SSD1306
|
||||
void drawLines() {
|
||||
for (int16_t i=0; i<display.getWidth(); i+=4) {
|
||||
display.drawLine(0, 0, i, display.getHeight()-1);
|
||||
display.display();
|
||||
delay(10);
|
||||
}
|
||||
for (int16_t i=0; i<display.getHeight(); i+=4) {
|
||||
display.drawLine(0, 0, display.getWidth()-1, i);
|
||||
display.display();
|
||||
delay(10);
|
||||
}
|
||||
delay(250);
|
||||
|
||||
display.clear();
|
||||
for (int16_t i=0; i<display.getWidth(); i+=4) {
|
||||
display.drawLine(0, display.getHeight()-1, i, 0);
|
||||
display.display();
|
||||
delay(10);
|
||||
}
|
||||
for (int16_t i=display.getHeight()-1; i>=0; i-=4) {
|
||||
display.drawLine(0, display.getHeight()-1, display.getWidth()-1, i);
|
||||
display.display();
|
||||
delay(10);
|
||||
}
|
||||
delay(250);
|
||||
|
||||
display.clear();
|
||||
for (int16_t i=display.getWidth()-1; i>=0; i-=4) {
|
||||
display.drawLine(display.getWidth()-1, display.getHeight()-1, i, 0);
|
||||
display.display();
|
||||
delay(10);
|
||||
}
|
||||
for (int16_t i=display.getHeight()-1; i>=0; i-=4) {
|
||||
display.drawLine(display.getWidth()-1, display.getHeight()-1, 0, i);
|
||||
display.display();
|
||||
delay(10);
|
||||
}
|
||||
delay(250);
|
||||
display.clear();
|
||||
for (int16_t i=0; i<display.getHeight(); i+=4) {
|
||||
display.drawLine(display.getWidth()-1, 0, 0, i);
|
||||
display.display();
|
||||
delay(10);
|
||||
}
|
||||
for (int16_t i=0; i<display.getWidth(); i+=4) {
|
||||
display.drawLine(display.getWidth()-1, 0, i, display.getHeight()-1);
|
||||
display.display();
|
||||
delay(10);
|
||||
}
|
||||
delay(250);
|
||||
}
|
||||
|
||||
// Adapted from Adafruit_SSD1306
|
||||
void drawRect(void) {
|
||||
for (int16_t i=0; i<display.getHeight()/2; i+=2) {
|
||||
display.drawRect(i, i, display.getWidth()-2*i, display.getHeight()-2*i);
|
||||
display.display();
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
// Adapted from Adafruit_SSD1306
|
||||
void fillRect(void) {
|
||||
uint8_t color = 1;
|
||||
for (int16_t i=0; i<display.getHeight()/2; i+=3) {
|
||||
display.setColor((color % 2 == 0) ? BLACK : WHITE); // alternate colors
|
||||
display.fillRect(i, i, display.getWidth() - i*2, display.getHeight() - i*2);
|
||||
display.display();
|
||||
delay(10);
|
||||
color++;
|
||||
}
|
||||
// Reset back to WHITE
|
||||
display.setColor(WHITE);
|
||||
}
|
||||
|
||||
// Adapted from Adafruit_SSD1306
|
||||
void drawCircle(void) {
|
||||
for (int16_t i=0; i<display.getHeight(); i+=2) {
|
||||
display.drawCircle(display.getWidth()/2, display.getHeight()/2, i);
|
||||
display.display();
|
||||
delay(10);
|
||||
}
|
||||
delay(1000);
|
||||
display.clear();
|
||||
|
||||
// This will draw the part of the circel in quadrant 1
|
||||
// Quadrants are numberd like this:
|
||||
// 0010 | 0001
|
||||
// ------|-----
|
||||
// 0100 | 1000
|
||||
//
|
||||
display.drawCircleQuads(display.getWidth()/2, display.getHeight()/2, display.getHeight()/4, 0b00000001);
|
||||
display.display();
|
||||
delay(200);
|
||||
display.drawCircleQuads(display.getWidth()/2, display.getHeight()/2, display.getHeight()/4, 0b00000011);
|
||||
display.display();
|
||||
delay(200);
|
||||
display.drawCircleQuads(display.getWidth()/2, display.getHeight()/2, display.getHeight()/4, 0b00000111);
|
||||
display.display();
|
||||
delay(200);
|
||||
display.drawCircleQuads(display.getWidth()/2, display.getHeight()/2, display.getHeight()/4, 0b00001111);
|
||||
display.display();
|
||||
}
|
||||
|
||||
void printBuffer(void) {
|
||||
// Initialize the log buffer
|
||||
// allocate memory to store 8 lines of text and 30 chars per line.
|
||||
display.setLogBuffer(5, 30);
|
||||
|
||||
// Some test data
|
||||
const char* test[] = {
|
||||
"Hello",
|
||||
"World" ,
|
||||
"----",
|
||||
"Show off",
|
||||
"how",
|
||||
"the log buffer",
|
||||
"is",
|
||||
"working.",
|
||||
"Even",
|
||||
"scrolling is",
|
||||
"working"
|
||||
};
|
||||
|
||||
for (uint8_t i = 0; i < 11; i++) {
|
||||
display.clear();
|
||||
// Print to the screen
|
||||
display.println(test[i]);
|
||||
// Draw it to the internal screen buffer
|
||||
display.drawLogBuffer(0, 0);
|
||||
// Display it on the screen
|
||||
display.display();
|
||||
delay(500);
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
display.init();
|
||||
|
||||
// display.flipScreenVertically();
|
||||
|
||||
display.setContrast(255);
|
||||
|
||||
drawLines();
|
||||
delay(1000);
|
||||
display.clear();
|
||||
|
||||
drawRect();
|
||||
delay(1000);
|
||||
display.clear();
|
||||
|
||||
fillRect();
|
||||
delay(1000);
|
||||
display.clear();
|
||||
|
||||
drawCircle();
|
||||
delay(1000);
|
||||
display.clear();
|
||||
|
||||
printBuffer();
|
||||
delay(1000);
|
||||
display.clear();
|
||||
}
|
||||
|
||||
void loop() { }
|
||||
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
|
||||
* Copyright (c) 2018 by Fabrice Weinberg
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* ThingPulse invests considerable time and money to develop these open source libraries.
|
||||
* Please support us by buying our products (and not the clones) from
|
||||
* https://thingpulse.com
|
||||
*
|
||||
*/
|
||||
|
||||
// WiFi includes
|
||||
#include <ESP8266WiFi.h>
|
||||
|
||||
// OTA Includes
|
||||
#include <ESP8266mDNS.h>
|
||||
#include <ArduinoOTA.h>
|
||||
|
||||
const char *ssid = "[Your SSID]";
|
||||
const char *password = "[Your Password]";
|
||||
|
||||
|
||||
// Include the correct display library
|
||||
// For a connection via I2C using Wire include
|
||||
#include <Wire.h> // Only needed for Arduino 1.6.5 and earlier
|
||||
#include "SSD1306Wire.h" // legacy include: `#include "SSD1306.h"`
|
||||
// or #include "SH1106Wire.h", legacy include: `#include "SH1106.h"`
|
||||
// For a connection via I2C using brzo_i2c (must be installed) include
|
||||
// #include <brzo_i2c.h> // Only needed for Arduino 1.6.5 and earlier
|
||||
// #include "SSD1306Brzo.h"
|
||||
// #include "SH1106Brzo.h"
|
||||
// For a connection via SPI include
|
||||
// #include <SPI.h> // Only needed for Arduino 1.6.5 and earlier
|
||||
// #include "SSD1306Spi.h"
|
||||
// #include "SH1106SPi.h"
|
||||
|
||||
// Use the corresponding display class:
|
||||
|
||||
// Initialize the OLED display using SPI
|
||||
// D5 -> CLK
|
||||
// D7 -> MOSI (DOUT)
|
||||
// D0 -> RES
|
||||
// D2 -> DC
|
||||
// D8 -> CS
|
||||
// SSD1306Spi display(D0, D2, D8);
|
||||
// or
|
||||
// SH1106Spi display(D0, D2);
|
||||
|
||||
// Initialize the OLED display using brzo_i2c
|
||||
// D3 -> SDA
|
||||
// D5 -> SCL
|
||||
// SSD1306Brzo display(0x3c, D3, D5);
|
||||
// or
|
||||
// SH1106Brzo display(0x3c, D3, D5);
|
||||
|
||||
// Initialize the OLED display using Wire library
|
||||
SSD1306Wire display(0x3c, D3, D5);
|
||||
// SH1106 display(0x3c, D3, D5);
|
||||
|
||||
|
||||
void setup() {
|
||||
WiFi.begin ( ssid, password );
|
||||
|
||||
// Wait for connection
|
||||
while ( WiFi.status() != WL_CONNECTED ) {
|
||||
delay ( 10 );
|
||||
}
|
||||
|
||||
display.init();
|
||||
display.flipScreenVertically();
|
||||
display.setContrast(255);
|
||||
|
||||
ArduinoOTA.begin();
|
||||
ArduinoOTA.onStart([]() {
|
||||
display.clear();
|
||||
display.setFont(ArialMT_Plain_10);
|
||||
display.setTextAlignment(TEXT_ALIGN_CENTER_BOTH);
|
||||
display.drawString(display.getWidth()/2, display.getHeight()/2 - 10, "OTA Update");
|
||||
display.display();
|
||||
});
|
||||
|
||||
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
|
||||
display.drawProgressBar(4, 32, 120, 8, progress / (total / 100) );
|
||||
display.display();
|
||||
});
|
||||
|
||||
ArduinoOTA.onEnd([]() {
|
||||
display.clear();
|
||||
display.setFont(ArialMT_Plain_10);
|
||||
display.setTextAlignment(TEXT_ALIGN_CENTER_BOTH);
|
||||
display.drawString(display.getWidth()/2, display.getHeight()/2, "Restart");
|
||||
display.display();
|
||||
});
|
||||
|
||||
// Align text vertical/horizontal center
|
||||
display.setTextAlignment(TEXT_ALIGN_CENTER_BOTH);
|
||||
display.setFont(ArialMT_Plain_10);
|
||||
display.drawString(display.getWidth()/2, display.getHeight()/2, "Ready for OTA:\n" + WiFi.localIP().toString());
|
||||
display.display();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
ArduinoOTA.handle();
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
|
||||
* Copyright (c) 2018 by Fabrice Weinberg
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* ThingPulse invests considerable time and money to develop these open source libraries.
|
||||
* Please support us by buying our products (and not the clones) from
|
||||
* https://thingpulse.com
|
||||
*
|
||||
*/
|
||||
|
||||
// Include the correct display library
|
||||
|
||||
// For a connection via I2C using the Arduino Wire include:
|
||||
#include <Wire.h> // Only needed for Arduino 1.6.5 and earlier
|
||||
#include "SSD1306Wire.h" // legacy: #include "SSD1306.h"
|
||||
// OR #include "SH1106Wire.h" // legacy: #include "SH1106.h"
|
||||
|
||||
// For a connection via I2C using brzo_i2c (must be installed) include:
|
||||
// #include <brzo_i2c.h> // Only needed for Arduino 1.6.5 and earlier
|
||||
// #include "SSD1306Brzo.h"
|
||||
// OR #include "SH1106Brzo.h"
|
||||
|
||||
// For a connection via SPI include:
|
||||
// #include <SPI.h> // Only needed for Arduino 1.6.5 and earlier
|
||||
// #include "SSD1306Spi.h"
|
||||
// OR #include "SH1106SPi.h"
|
||||
|
||||
|
||||
// Optionally include custom images
|
||||
#include "images.h"
|
||||
|
||||
|
||||
// Initialize the OLED display using Arduino Wire:
|
||||
SSD1306Wire display(0x3c, SDA, SCL); // ADDRESS, SDA, SCL - SDA and SCL usually populate automatically based on your board's pins_arduino.h
|
||||
// SSD1306Wire display(0x3c, D3, D5); // ADDRESS, SDA, SCL - If not, they can be specified manually.
|
||||
// SSD1306Wire display(0x3c, SDA, SCL, GEOMETRY_128_32); // ADDRESS, SDA, SCL, OLEDDISPLAY_GEOMETRY - Extra param required for 128x32 displays.
|
||||
// SH1106 display(0x3c, SDA, SCL); // ADDRESS, SDA, SCL
|
||||
|
||||
// Initialize the OLED display using brzo_i2c:
|
||||
// SSD1306Brzo display(0x3c, D3, D5); // ADDRESS, SDA, SCL
|
||||
// or
|
||||
// SH1106Brzo display(0x3c, D3, D5); // ADDRESS, SDA, SCL
|
||||
|
||||
// Initialize the OLED display using SPI:
|
||||
// D5 -> CLK
|
||||
// D7 -> MOSI (DOUT)
|
||||
// D0 -> RES
|
||||
// D2 -> DC
|
||||
// D8 -> CS
|
||||
// SSD1306Spi display(D0, D2, D8); // RES, DC, CS
|
||||
// or
|
||||
// SH1106Spi display(D0, D2); // RES, DC
|
||||
|
||||
|
||||
#define DEMO_DURATION 3000
|
||||
typedef void (*Demo)(void);
|
||||
|
||||
int demoMode = 0;
|
||||
int counter = 1;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
|
||||
// Initialising the UI will init the display too.
|
||||
display.init();
|
||||
|
||||
display.flipScreenVertically();
|
||||
display.setFont(ArialMT_Plain_10);
|
||||
|
||||
}
|
||||
|
||||
void drawFontFaceDemo() {
|
||||
// Font Demo1
|
||||
// create more fonts at http://oleddisplay.squix.ch/
|
||||
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display.setFont(ArialMT_Plain_10);
|
||||
display.drawString(0, 0, "Hello world");
|
||||
display.setFont(ArialMT_Plain_16);
|
||||
display.drawString(0, 10, "Hello world");
|
||||
display.setFont(ArialMT_Plain_24);
|
||||
display.drawString(0, 26, "Hello world");
|
||||
}
|
||||
|
||||
void drawTextFlowDemo() {
|
||||
display.setFont(ArialMT_Plain_10);
|
||||
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display.drawStringMaxWidth(0, 0, 128,
|
||||
"Lorem ipsum\n dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore." );
|
||||
}
|
||||
|
||||
void drawTextAlignmentDemo() {
|
||||
// Text alignment demo
|
||||
display.setFont(ArialMT_Plain_10);
|
||||
|
||||
// The coordinates define the left starting point of the text
|
||||
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display.drawString(0, 10, "Left aligned (0,10)");
|
||||
|
||||
// The coordinates define the center of the text
|
||||
display.setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display.drawString(64, 22, "Center aligned (64,22)");
|
||||
|
||||
// The coordinates define the right end of the text
|
||||
display.setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||
display.drawString(128, 33, "Right aligned (128,33)");
|
||||
}
|
||||
|
||||
void drawRectDemo() {
|
||||
// Draw a pixel at given position
|
||||
for (int i = 0; i < 10; i++) {
|
||||
display.setPixel(i, i);
|
||||
display.setPixel(10 - i, i);
|
||||
}
|
||||
display.drawRect(12, 12, 20, 20);
|
||||
|
||||
// Fill the rectangle
|
||||
display.fillRect(14, 14, 17, 17);
|
||||
|
||||
// Draw a line horizontally
|
||||
display.drawHorizontalLine(0, 40, 20);
|
||||
|
||||
// Draw a line horizontally
|
||||
display.drawVerticalLine(40, 0, 20);
|
||||
}
|
||||
|
||||
void drawCircleDemo() {
|
||||
for (int i=1; i < 8; i++) {
|
||||
display.setColor(WHITE);
|
||||
display.drawCircle(32, 32, i*3);
|
||||
if (i % 2 == 0) {
|
||||
display.setColor(BLACK);
|
||||
}
|
||||
display.fillCircle(96, 32, 32 - i* 3);
|
||||
}
|
||||
}
|
||||
|
||||
void drawProgressBarDemo() {
|
||||
int progress = (counter / 5) % 100;
|
||||
// draw the progress bar
|
||||
display.drawProgressBar(0, 32, 120, 10, progress);
|
||||
|
||||
// draw the percentage as String
|
||||
display.setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display.drawString(64, 15, String(progress) + "%");
|
||||
}
|
||||
|
||||
void drawImageDemo() {
|
||||
// see http://blog.squix.org/2015/05/esp8266-nodemcu-how-to-create-xbm.html
|
||||
// on how to create xbm files
|
||||
display.drawXbm(34, 14, WiFi_Logo_width, WiFi_Logo_height, WiFi_Logo_bits);
|
||||
}
|
||||
|
||||
Demo demos[] = {drawFontFaceDemo, drawTextFlowDemo, drawTextAlignmentDemo, drawRectDemo, drawCircleDemo, drawProgressBarDemo, drawImageDemo};
|
||||
int demoLength = (sizeof(demos) / sizeof(Demo));
|
||||
long timeSinceLastModeSwitch = 0;
|
||||
|
||||
void loop() {
|
||||
// clear the display
|
||||
display.clear();
|
||||
// draw the current demo method
|
||||
demos[demoMode]();
|
||||
|
||||
display.setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||
display.drawString(10, 128, String(millis()));
|
||||
// write the buffer to the display
|
||||
display.display();
|
||||
|
||||
if (millis() - timeSinceLastModeSwitch > DEMO_DURATION) {
|
||||
demoMode = (demoMode + 1) % demoLength;
|
||||
timeSinceLastModeSwitch = millis();
|
||||
}
|
||||
counter++;
|
||||
delay(10);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#define WiFi_Logo_width 60
|
||||
#define WiFi_Logo_height 36
|
||||
const uint8_t WiFi_Logo_bits[] PROGMEM = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF,
|
||||
0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
|
||||
0xFF, 0x03, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
|
||||
0x00, 0xFF, 0xFF, 0xFF, 0x07, 0xC0, 0x83, 0x01, 0x80, 0xFF, 0xFF, 0xFF,
|
||||
0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0C, 0x00,
|
||||
0xC0, 0xFF, 0xFF, 0x7C, 0x00, 0x60, 0x0C, 0x00, 0xC0, 0x31, 0x46, 0x7C,
|
||||
0xFC, 0x77, 0x08, 0x00, 0xE0, 0x23, 0xC6, 0x3C, 0xFC, 0x67, 0x18, 0x00,
|
||||
0xE0, 0x23, 0xE4, 0x3F, 0x1C, 0x00, 0x18, 0x00, 0xE0, 0x23, 0x60, 0x3C,
|
||||
0x1C, 0x70, 0x18, 0x00, 0xE0, 0x03, 0x60, 0x3C, 0x1C, 0x70, 0x18, 0x00,
|
||||
0xE0, 0x07, 0x60, 0x3C, 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C,
|
||||
0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00,
|
||||
0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x8F, 0x71, 0x3C,
|
||||
0x1C, 0x70, 0x18, 0x00, 0xC0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x08, 0x00,
|
||||
0xC0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x0C, 0x00, 0x80, 0xFF, 0xFF, 0x1F,
|
||||
0x00, 0x00, 0x06, 0x00, 0x80, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x07, 0x00,
|
||||
0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xF8, 0xFF, 0xFF,
|
||||
0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF,
|
||||
0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* ThingPulse invests considerable time and money to develop these open source libraries.
|
||||
* Please support us by buying our products (and not the clones) from
|
||||
* https://thingpulse.com
|
||||
*
|
||||
*/
|
||||
|
||||
// Include the correct display library
|
||||
// For a connection via I2C using Wire include
|
||||
#include <Wire.h> // Only needed for Arduino 1.6.5 and earlier
|
||||
#include "SSD1306Wire.h" // legacy include: `#include "SSD1306.h"`
|
||||
#include "images.h"
|
||||
|
||||
// Initialize the OLED display using Wire library
|
||||
SSD1306Wire display(0x3c, D3, D5);
|
||||
SSD1306Wire display2(0x3c, D1, D2);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
|
||||
// Initialising the UI will init the display too.
|
||||
display.init();
|
||||
display2.init();
|
||||
|
||||
// This will make sure that multiple instances of a display driver
|
||||
// running on different ports will work together transparently
|
||||
display.setI2cAutoInit(true);
|
||||
display2.setI2cAutoInit(true);
|
||||
|
||||
display.flipScreenVertically();
|
||||
display.setFont(ArialMT_Plain_10);
|
||||
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
|
||||
display2.flipScreenVertically();
|
||||
display2.setFont(ArialMT_Plain_10);
|
||||
display2.setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
display.clear();
|
||||
display.drawString(0, 0, "Hello world: " + String(millis()));
|
||||
display.display();
|
||||
|
||||
display2.clear();
|
||||
display2.drawString(0, 0, "Hello world: " + String(millis()));
|
||||
display2.display();
|
||||
|
||||
delay(10);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#define WiFi_Logo_width 60
|
||||
#define WiFi_Logo_height 36
|
||||
const uint8_t WiFi_Logo_bits[] PROGMEM = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF,
|
||||
0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
|
||||
0xFF, 0x03, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
|
||||
0x00, 0xFF, 0xFF, 0xFF, 0x07, 0xC0, 0x83, 0x01, 0x80, 0xFF, 0xFF, 0xFF,
|
||||
0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0C, 0x00,
|
||||
0xC0, 0xFF, 0xFF, 0x7C, 0x00, 0x60, 0x0C, 0x00, 0xC0, 0x31, 0x46, 0x7C,
|
||||
0xFC, 0x77, 0x08, 0x00, 0xE0, 0x23, 0xC6, 0x3C, 0xFC, 0x67, 0x18, 0x00,
|
||||
0xE0, 0x23, 0xE4, 0x3F, 0x1C, 0x00, 0x18, 0x00, 0xE0, 0x23, 0x60, 0x3C,
|
||||
0x1C, 0x70, 0x18, 0x00, 0xE0, 0x03, 0x60, 0x3C, 0x1C, 0x70, 0x18, 0x00,
|
||||
0xE0, 0x07, 0x60, 0x3C, 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C,
|
||||
0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00,
|
||||
0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x8F, 0x71, 0x3C,
|
||||
0x1C, 0x70, 0x18, 0x00, 0xC0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x08, 0x00,
|
||||
0xC0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x0C, 0x00, 0x80, 0xFF, 0xFF, 0x1F,
|
||||
0x00, 0x00, 0x06, 0x00, 0x80, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x07, 0x00,
|
||||
0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xF8, 0xFF, 0xFF,
|
||||
0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF,
|
||||
0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
@@ -0,0 +1,194 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
|
||||
* Copyright (c) 2018 by Fabrice Weinberg
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* ThingPulse invests considerable time and money to develop these open source libraries.
|
||||
* Please support us by buying our products (and not the clones) from
|
||||
* https://thingpulse.com
|
||||
*
|
||||
*/
|
||||
|
||||
// Include the correct display library
|
||||
// For a connection via I2C using Wire include
|
||||
#include <Wire.h> // Only needed for Arduino 1.6.5 and earlier
|
||||
#include "SSD1306Wire.h" // legacy include: `#include "SSD1306.h"`
|
||||
// or #include "SH1106Wire.h", legacy include: `#include "SH1106.h"`
|
||||
// For a connection via I2C using brzo_i2c (must be installed) include
|
||||
// #include <brzo_i2c.h> // Only needed for Arduino 1.6.5 and earlier
|
||||
// #include "SSD1306Brzo.h"
|
||||
// #include "SH1106Brzo.h"
|
||||
// For a connection via SPI include
|
||||
// #include <SPI.h> // Only needed for Arduino 1.6.5 and earlier
|
||||
// #include "SSD1306Spi.h"
|
||||
// #include "SH1106SPi.h"
|
||||
|
||||
// Include the UI lib
|
||||
#include "OLEDDisplayUi.h"
|
||||
|
||||
// Include custom images
|
||||
|
||||
#include "images.h"
|
||||
|
||||
// Use the corresponding display class:
|
||||
|
||||
// Initialize the OLED display using SPI
|
||||
// D5 -> CLK
|
||||
// D7 -> MOSI (DOUT)
|
||||
// D0 -> RES
|
||||
// D2 -> DC
|
||||
// D8 -> CS
|
||||
// SSD1306Spi display(D0, D2, D8);
|
||||
// or
|
||||
// SH1106Spi display(D0, D2);
|
||||
|
||||
// Initialize the OLED display using brzo_i2c
|
||||
// D3 -> SDA
|
||||
// D5 -> SCL
|
||||
// SSD1306Brzo display(0x3c, D3, D5);
|
||||
// or
|
||||
// SH1106Brzo display(0x3c, D3, D5);
|
||||
|
||||
// Initialize the OLED display using Wire library
|
||||
SSD1306Wire display(0x3c, D3, D5);
|
||||
// SH1106Wire display(0x3c, D3, D5);
|
||||
|
||||
OLEDDisplayUi ui ( &display );
|
||||
|
||||
void msOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) {
|
||||
display->setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||
display->setFont(ArialMT_Plain_10);
|
||||
display->drawString(128, 0, String(millis()));
|
||||
}
|
||||
|
||||
void drawFrame1(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
|
||||
// draw an xbm image.
|
||||
// Please note that everything that should be transitioned
|
||||
// needs to be drawn relative to x and y
|
||||
|
||||
display->drawXbm(x + 34, y + 14, WiFi_Logo_width, WiFi_Logo_height, WiFi_Logo_bits);
|
||||
}
|
||||
|
||||
void drawFrame2(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
|
||||
// Demonstrates the 3 included default sizes. The fonts come from SSD1306Fonts.h file
|
||||
// Besides the default fonts there will be a program to convert TrueType fonts into this format
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(ArialMT_Plain_10);
|
||||
display->drawString(0 + x, 10 + y, "Arial 10");
|
||||
|
||||
display->setFont(ArialMT_Plain_16);
|
||||
display->drawString(0 + x, 20 + y, "Arial 16");
|
||||
|
||||
display->setFont(ArialMT_Plain_24);
|
||||
display->drawString(0 + x, 34 + y, "Arial 24");
|
||||
}
|
||||
|
||||
void drawFrame3(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
|
||||
// Text alignment demo
|
||||
display->setFont(ArialMT_Plain_10);
|
||||
|
||||
// The coordinates define the left starting point of the text
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->drawString(0 + x, 11 + y, "Left aligned (0,10)");
|
||||
|
||||
// The coordinates define the center of the text
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->drawString(64 + x, 22 + y, "Center aligned (64,22)");
|
||||
|
||||
// The coordinates define the right end of the text
|
||||
display->setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||
display->drawString(128 + x, 33 + y, "Right aligned (128,33)");
|
||||
}
|
||||
|
||||
void drawFrame4(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
|
||||
// Demo for drawStringMaxWidth:
|
||||
// with the third parameter you can define the width after which words will be wrapped.
|
||||
// Currently only spaces and "-" are allowed for wrapping
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(ArialMT_Plain_10);
|
||||
display->drawStringMaxWidth(0 + x, 10 + y, 128, "Lorem ipsum\n dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore.");
|
||||
}
|
||||
|
||||
void drawFrame5(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
|
||||
|
||||
}
|
||||
|
||||
// This array keeps function pointers to all frames
|
||||
// frames are the single views that slide in
|
||||
FrameCallback frames[] = { drawFrame1, drawFrame2, drawFrame3, drawFrame4, drawFrame5 };
|
||||
|
||||
// how many frames are there?
|
||||
int frameCount = 5;
|
||||
|
||||
// Overlays are statically drawn on top of a frame eg. a clock
|
||||
OverlayCallback overlays[] = { msOverlay };
|
||||
int overlaysCount = 1;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
// The ESP is capable of rendering 60fps in 80Mhz mode
|
||||
// but that won't give you much time for anything else
|
||||
// run it in 160Mhz mode or just set it to 30 fps
|
||||
ui.setTargetFPS(60);
|
||||
|
||||
// Customize the active and inactive symbol
|
||||
ui.setActiveSymbol(activeSymbol);
|
||||
ui.setInactiveSymbol(inactiveSymbol);
|
||||
|
||||
// You can change this to
|
||||
// TOP, LEFT, BOTTOM, RIGHT
|
||||
ui.setIndicatorPosition(BOTTOM);
|
||||
|
||||
// Defines where the first frame is located in the bar.
|
||||
ui.setIndicatorDirection(LEFT_RIGHT);
|
||||
|
||||
// You can change the transition that is used
|
||||
// SLIDE_LEFT, SLIDE_RIGHT, SLIDE_UP, SLIDE_DOWN
|
||||
ui.setFrameAnimation(SLIDE_LEFT);
|
||||
|
||||
// Add frames
|
||||
ui.setFrames(frames, frameCount);
|
||||
|
||||
// Add overlays
|
||||
ui.setOverlays(overlays, overlaysCount);
|
||||
|
||||
// Initialising the UI will init the display too.
|
||||
ui.init();
|
||||
|
||||
display.flipScreenVertically();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
int remainingTimeBudget = ui.update();
|
||||
|
||||
if (remainingTimeBudget > 0) {
|
||||
// You can do some work here
|
||||
// Don't do stuff if you are below your
|
||||
// time budget.
|
||||
delay(remainingTimeBudget);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#define WiFi_Logo_width 60
|
||||
#define WiFi_Logo_height 36
|
||||
const uint8_t WiFi_Logo_bits[] PROGMEM = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF,
|
||||
0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
|
||||
0xFF, 0x03, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
|
||||
0x00, 0xFF, 0xFF, 0xFF, 0x07, 0xC0, 0x83, 0x01, 0x80, 0xFF, 0xFF, 0xFF,
|
||||
0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0C, 0x00,
|
||||
0xC0, 0xFF, 0xFF, 0x7C, 0x00, 0x60, 0x0C, 0x00, 0xC0, 0x31, 0x46, 0x7C,
|
||||
0xFC, 0x77, 0x08, 0x00, 0xE0, 0x23, 0xC6, 0x3C, 0xFC, 0x67, 0x18, 0x00,
|
||||
0xE0, 0x23, 0xE4, 0x3F, 0x1C, 0x00, 0x18, 0x00, 0xE0, 0x23, 0x60, 0x3C,
|
||||
0x1C, 0x70, 0x18, 0x00, 0xE0, 0x03, 0x60, 0x3C, 0x1C, 0x70, 0x18, 0x00,
|
||||
0xE0, 0x07, 0x60, 0x3C, 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C,
|
||||
0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00,
|
||||
0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x8F, 0x71, 0x3C,
|
||||
0x1C, 0x70, 0x18, 0x00, 0xC0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x08, 0x00,
|
||||
0xC0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x0C, 0x00, 0x80, 0xFF, 0xFF, 0x1F,
|
||||
0x00, 0x00, 0x06, 0x00, 0x80, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x07, 0x00,
|
||||
0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xF8, 0xFF, 0xFF,
|
||||
0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF,
|
||||
0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const uint8_t activeSymbol[] PROGMEM = {
|
||||
B00000000,
|
||||
B00000000,
|
||||
B00011000,
|
||||
B00100100,
|
||||
B01000010,
|
||||
B01000010,
|
||||
B00100100,
|
||||
B00011000
|
||||
};
|
||||
|
||||
const uint8_t inactiveSymbol[] PROGMEM = {
|
||||
B00000000,
|
||||
B00000000,
|
||||
B00000000,
|
||||
B00000000,
|
||||
B00011000,
|
||||
B00011000,
|
||||
B00000000,
|
||||
B00000000
|
||||
};
|
||||
100
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/keywords.txt
Normal file
@@ -0,0 +1,100 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map List
|
||||
#######################################
|
||||
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
INVERSE LITERAL1
|
||||
|
||||
TEXT_ALIGN_LEFT LITERAL1
|
||||
TEXT_ALIGN_RIGHT LITERAL1
|
||||
TEXT_ALIGN_CENTER LITERAL1
|
||||
TEXT_ALIGN_CENTER_BOTH LITERAL1
|
||||
|
||||
GEOMETRY_128_64 LITERAL1
|
||||
GEOMETRY_128_32 LITERAL1
|
||||
GEOMETRY_RAWMODE LITERAL1
|
||||
|
||||
ArialMT_Plain_10 LITERAL1
|
||||
ArialMT_Plain_16 LITERAL1
|
||||
ArialMT_Plain_24 LITERAL1
|
||||
|
||||
SLIDE_UP LITERAL1
|
||||
SLIDE_DOWN LITERAL1
|
||||
SLIDE_LEFT LITERAL1
|
||||
SLIDE_RIGHT LITERAL1
|
||||
|
||||
TOP LITERAL1
|
||||
RIGHT LITERAL1
|
||||
BOTTOM LITERAL1
|
||||
LEFT LITERAL1
|
||||
|
||||
LEFT_RIGHT LITERAL1
|
||||
RIGHT_LEFT LITERAL1
|
||||
|
||||
IN_TRANSITION LITERAL1
|
||||
FIXED LITERAL1
|
||||
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
OLEDDisplay KEYWORD1
|
||||
OLEDDisplayUi KEYWORD1
|
||||
|
||||
SH1106Wire KEYWORD1
|
||||
SH1106Brzo KEYWORD1
|
||||
SH1106Spi KEYWORD1
|
||||
|
||||
SSD1306Wire KEYWORD1
|
||||
SSD1306Brzo KEYWORD1
|
||||
SSD1306I2C KEYWORD1
|
||||
SSD1306Spi KEYWORD1
|
||||
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
allocateBuffer KEYWORD2
|
||||
init KEYWORD2
|
||||
resetDisplay KEYWORD2
|
||||
setColor KEYWORD2
|
||||
getColor KEYWORD2
|
||||
setPixel KEYWORD2
|
||||
setPixelColor KEYWORD2
|
||||
clearPixel KEYWORD2
|
||||
drawLine KEYWORD2
|
||||
drawRect KEYWORD2
|
||||
fillRect KEYWORD2
|
||||
drawCircle KEYWORD2
|
||||
drawCircleQuads KEYWORD2
|
||||
fillCircle KEYWORD2
|
||||
fillRing KEYWORD2
|
||||
drawHorizontalLine KEYWORD2
|
||||
drawVerticalLine KEYWORD2
|
||||
drawProgressBar KEYWORD2
|
||||
drawFastImage KEYWORD2
|
||||
drawXbm KEYWORD2
|
||||
drawIco16x16 KEYWORD2
|
||||
drawString KEYWORD2
|
||||
drawStringMaxWidth KEYWORD2
|
||||
getStringWidth KEYWORD2
|
||||
setTextAlignment KEYWORD2
|
||||
setFont KEYWORD2
|
||||
setFontTableLookupFunction KEYWORD2
|
||||
displayOn KEYWORD2
|
||||
displayOff KEYWORD2
|
||||
invertDisplay KEYWORD2
|
||||
normalDisplay KEYWORD2
|
||||
setContrast KEYWORD2
|
||||
setBrightness KEYWORD2
|
||||
resetOrientation KEYWORD2
|
||||
flipScreenVertically KEYWORD2
|
||||
mirrorScreen KEYWORD2
|
||||
display KEYWORD2
|
||||
setLogBuffer KEYWORD2
|
||||
drawLogBuffer KEYWORD2
|
||||
getWidth KEYWORD2
|
||||
getHeight KEYWORD2
|
||||
29
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/library.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "ESP8266 and ESP32 OLED driver for SSD1306 displays",
|
||||
"version": "4.2.0",
|
||||
"keywords": "ssd1306, oled, display, i2c",
|
||||
"description": "I2C display driver for SSD1306 OLED displays connected to ESP8266, ESP32, Mbed-OS",
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/ThingPulse/esp8266-oled-ssd1306"
|
||||
},
|
||||
"authors":
|
||||
[
|
||||
{
|
||||
"name": "Daniel Eichhorn, ThingPulse",
|
||||
"email": "squix78@gmail.com",
|
||||
"url": "https://thingpulse.com"
|
||||
},
|
||||
{
|
||||
"name": "Fabrice Weinberg",
|
||||
"email": "fabrice@weinberg.me"
|
||||
}
|
||||
],
|
||||
"frameworks": "arduino",
|
||||
"platforms": [
|
||||
"espressif8266",
|
||||
"espressif32",
|
||||
"nordicnrf52"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
name=ESP8266 and ESP32 OLED driver for SSD1306 displays
|
||||
version=4.2.0
|
||||
author=ThingPulse, Fabrice Weinberg
|
||||
maintainer=ThingPulse <info@thingpulse.com>
|
||||
sentence=I2C display driver for SSD1306 OLED displays connected to ESP8266, ESP32, Mbed-OS
|
||||
paragraph=The following geometries are currently supported: 128x64, 128x32, 64x48. The init sequence was inspired by Adafruit's library for the same display.
|
||||
category=Display
|
||||
url=https://github.com/ThingPulse/esp8266-oled-ssd1306
|
||||
architectures=esp8266,esp32
|
||||
24
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/license
Normal file
@@ -0,0 +1,24 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 by Daniel Eichhorn
|
||||
Copyright (c) 2016 by Fabrice Weinberg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
See more at http://blog.squix.ch
|
||||
19
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/platformio.ini
Normal file
@@ -0,0 +1,19 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; http://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:d1_mini]
|
||||
platform = espressif8266
|
||||
board = d1_mini
|
||||
framework = arduino
|
||||
upload_speed = 921600
|
||||
board_build.f_cpu = 160000000L
|
||||
upload_port = /dev/cu.SLAB_USBtoUART
|
||||
monitor_port = /dev/cu.SLAB_USBtoUART
|
||||
lib_deps =
|
||||
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 26 KiB |
@@ -0,0 +1,664 @@
|
||||
<!--The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 by Xavier Grosjean
|
||||
|
||||
Based on work
|
||||
Copyright (c) 2016 by Daniel Eichhorn
|
||||
Copyright (c) 2016 by Fabrice Weinberg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
-->
|
||||
<!--
|
||||
Standalone page to draw icons in matrix and generates the map definition with the format required by
|
||||
library for OLED SD1306 screen: https://github.com/squix78/esp8266-oled-ssd1306
|
||||
100% quick and dirty vanilla ECS6, no framework or library was injured for this project.
|
||||
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<style>
|
||||
#form, #chars table {
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
margin-top: 5px;
|
||||
}
|
||||
#chars table, tr, td, th {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
#chars td, th {
|
||||
border: 1px solid #CCC;
|
||||
width: 12px;
|
||||
height: 15px;
|
||||
}
|
||||
#chars th[action] {
|
||||
cursor:pointer;
|
||||
}
|
||||
#chars th[action="up"], #chars th[action="down"], #chars th[action="left"], #chars th[action="right"] {
|
||||
font-size: 10px;
|
||||
}
|
||||
#chars td.on {
|
||||
background-color: #00F;
|
||||
}
|
||||
|
||||
#addChar, #generate {
|
||||
display: none;
|
||||
}
|
||||
body.started #addChar, body.started #generate {
|
||||
display: inline;
|
||||
}
|
||||
body.started #create {
|
||||
display: none;
|
||||
}
|
||||
#page {
|
||||
position:relative;
|
||||
}
|
||||
#page>div {
|
||||
position: relative;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#output {
|
||||
margin-left: 20px;
|
||||
margin-top: 12px;
|
||||
font-size:12px;
|
||||
user-select: all;
|
||||
-moz-user-select: all;
|
||||
max-width:60%;
|
||||
}
|
||||
|
||||
#header {
|
||||
margin-top: 10px;
|
||||
}
|
||||
#inputText {
|
||||
width: 100%;
|
||||
height:120px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="form">
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td>Font array name:</td><td><input placeholder="Font array name" type="text" id="name" value="My_Font"/></td>
|
||||
<td width="75%" rowspan="5">
|
||||
<textarea id="inputText" placeholder="Or paste a char array font definition here">
|
||||
const uint8_t My_Font[] PROGMEM = {
|
||||
0x0A, // Width: 10
|
||||
0x0D, // Height: 13
|
||||
0x01, // First char: 1
|
||||
0x02, // Number of chars: 2
|
||||
// Jump Table:
|
||||
0x00, 0x00, 0x13, 0x0A, // 1
|
||||
0x00, 0x13, 0x14, 0x0A, // 2
|
||||
// Font Data:
|
||||
0xF0, 0x03, 0x10, 0x02, 0xF0, 0x03, 0x10, 0x02, 0xF0, 0x03, 0x10, 0x02, 0xF0, 0x03, 0x10, 0x02, 0xF0, 0x03, 0xC0, // 1
|
||||
0x00, 0x0C, 0x80, 0x0B, 0x70, 0x08, 0x0C, 0x08, 0xF3, 0x0A, 0xF3, 0x0A, 0x0C, 0x08, 0x70, 0x08, 0x80, 0x0B, 0x00, 0x0C, // 2
|
||||
};
|
||||
</textarea></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>First char code:</td><td><input placeholder="First char code" type="number" id="code" value="1" min="1"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Width:</td><td><input placeholder="Font width" type="number" id="width" value="10"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Height:</td><td><input placeholder="Font height" type="number" id="height" value="13" max="64"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3"> </td> <!--slightly improves layout-->
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<button id="create">Create</button>
|
||||
<button id="shiftUp">Shift all up</button>
|
||||
<button id="generate">Generate</button>
|
||||
<button id="savetoFile">Save To File</button>
|
||||
</td>
|
||||
<td><input type="file" id="fileinput" /> <button id="parse">Parse</button></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br/>
|
||||
</div>
|
||||
<div id="page">
|
||||
<div id="charxContainer" ondragstart="return false;">
|
||||
<div id="chars"></div><br/>
|
||||
<button id="addChar">Add a character</button>
|
||||
</div>
|
||||
<div id="output">
|
||||
<div class="output" id="header"> </div>
|
||||
<div class="output" id="jump"> </div>
|
||||
<div class="output" id="data"> </div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
(function() {
|
||||
let font;
|
||||
|
||||
class Font {
|
||||
constructor() {
|
||||
this.height = parseInt(document.getElementById('height').value);
|
||||
this.width = parseInt(document.getElementById('width').value);
|
||||
this.currentCharCode = parseInt(document.getElementById('code').value);
|
||||
this.fontContainer = document.getElementById('chars');
|
||||
this.bytesForHeight = (1 + ((this.height - 1) >> 3)); // number of bytes needed for this font height
|
||||
document.body.className = "started";
|
||||
document.getElementById('height').disabled = true;
|
||||
document.getElementById('width').disabled = true;
|
||||
}
|
||||
|
||||
// Should we have a Char and a Pixel class ? not sure it's worth it.
|
||||
// Let's use the DOM to store everything for now
|
||||
|
||||
static updateCaption(element, code) {
|
||||
element.textContent = `Char #${code}`;
|
||||
}
|
||||
|
||||
// Add a pixel matrix to draw a new character
|
||||
// jumpaData not used for now: some day, use the last byte for optimisation
|
||||
addChar(jumpData, charData) {
|
||||
let charContainer = this.fontContainer.appendChild(document.createElement("table"));
|
||||
charContainer.setAttribute("code", this.currentCharCode);
|
||||
let caption = charContainer.appendChild(document.createElement("caption"));
|
||||
Font.updateCaption(caption, this.currentCharCode);
|
||||
let header = charContainer.appendChild(document.createElement("tr"));
|
||||
header.innerHTML = '<th title="Delete this char" action="delete">✗</th>'
|
||||
+ '<th title="Add a char above" action="add">+</th>'
|
||||
+ '<th title="Shift pixels to the left" action="left">←</th>'
|
||||
+ '<th title="Shift pixels down" action="down">↓</th>'
|
||||
+ '<th title="Shift pixels up" action="up">↑</th>'
|
||||
+ '<th title="Shift pixels to the right" action="right">→</th>'
|
||||
+ '<th title="Copy from another character" action="copy">©</th>'
|
||||
+ '<th title="Reset all pixels" action="clean">∅</th>';
|
||||
// If data is provided, decode it to pixel initialization friendly structure
|
||||
let pixelInit = [];
|
||||
if (charData && charData.length) {
|
||||
// charData byte count needs to be a multiple of bytesForHeight. End bytes with value 0 may have been trimmed
|
||||
let missingBytes = charData.length % this.bytesForHeight;
|
||||
for(let b = 0; b < missingBytes ; b++) {
|
||||
charData.push(0);
|
||||
}
|
||||
while(charData.length) {
|
||||
let row = charData.splice(0, this.bytesForHeight).reverse();
|
||||
let pixelRow = [];
|
||||
for (let b = 0; b < row.length; b++) {
|
||||
let mask = 0x80;
|
||||
let byte = row[b];
|
||||
for (let bit = 0; bit < 8; bit++) {
|
||||
if (byte & mask) {
|
||||
pixelRow.push(1);
|
||||
} else {
|
||||
pixelRow.push(0);
|
||||
}
|
||||
mask = mask >> 1;
|
||||
}
|
||||
}
|
||||
pixelRow.splice(0, pixelRow.length - this.height);
|
||||
//Font.output('data', pixelRow);
|
||||
pixelInit.push(pixelRow.reverse());
|
||||
}
|
||||
}
|
||||
|
||||
for(let r = 0; r < this.height; r++) {
|
||||
let rowContainer = charContainer.appendChild(document.createElement("tr"));
|
||||
for(let c = 0; c < this.width; c++) {
|
||||
let pixContainer = rowContainer.appendChild(document.createElement("td"));
|
||||
pixContainer.setAttribute('action', 'toggle');
|
||||
// If there is some init data, set the pixel accordingly
|
||||
if (pixelInit.length && pixelInit[c]) {
|
||||
if (pixelInit[c][r]) {
|
||||
pixContainer.className = 'on';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.currentCharCode++;
|
||||
return charContainer;
|
||||
}
|
||||
|
||||
static togglePixel(pixel) {
|
||||
pixel.className = pixel.className === 'on' ? '': 'on';
|
||||
}
|
||||
|
||||
// Return anInt as hex string
|
||||
static toHexString(aByte) {
|
||||
let zero = aByte < 16?'0':'';
|
||||
return `0x${zero}${aByte.toString(16).toUpperCase()}`
|
||||
}
|
||||
|
||||
// Return least significant byte as hex string
|
||||
static getLsB(anInt) {
|
||||
return Font.toHexString(anInt & 0xFF);
|
||||
}
|
||||
// Return most significant byte as hex string
|
||||
static getMsB(anInt) {
|
||||
return Font.toHexString(anInt>>>8);
|
||||
}
|
||||
|
||||
static output(targetId, msg) {
|
||||
let output = document.getElementById(targetId);
|
||||
let line = output.appendChild(document.createElement('div'));
|
||||
line.textContent = msg;
|
||||
}
|
||||
static emptyChars() {
|
||||
document.getElementById('chars').textContent = '';
|
||||
}
|
||||
static emptyOutput() {
|
||||
document.getElementById('header').textContent = '';
|
||||
document.getElementById('jump').textContent = '';
|
||||
document.getElementById('data').textContent = '';
|
||||
}
|
||||
|
||||
saveFile() {
|
||||
let filename = document.getElementById('name').value.replace(/[^a-zA-Z0-9_$]/g, '_') + ".h";
|
||||
let data = document.getElementById("output").innerText;
|
||||
if(data.length < 10) return;
|
||||
let blobObject = new Blob([data], {type:'text/plain'});
|
||||
|
||||
if(window.navigator.msSaveBlob) {
|
||||
window.navigator.msSaveBlob(blobObject, filename);
|
||||
} else {
|
||||
let a = document.createElement("a");
|
||||
a.setAttribute("href", URL.createObjectURL(blobObject));
|
||||
a.setAttribute("download", filename);
|
||||
if (document.createEvent) {
|
||||
let event = document.createEvent('MouseEvents');
|
||||
event.initEvent('click', true, true);
|
||||
a.dispatchEvent(event);
|
||||
} else {
|
||||
a.click();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read from the <td> css class the pixels that need to be on
|
||||
// generates the jump table and font data
|
||||
generate() {
|
||||
// this.width -= 3; // hack to narrow an existing font
|
||||
Font.emptyOutput();
|
||||
let chars = this.fontContainer.getElementsByTagName('table');
|
||||
let firstCharCode = parseInt(document.getElementById('code').value);
|
||||
let name = document.getElementById('name').value.replace(/[^a-zA-Z0-9_$]/g, '_');
|
||||
|
||||
let bits2add = this.bytesForHeight*8 - this.height; // number of missing bits to fill leftmost byte
|
||||
let charCount = chars.length;
|
||||
let charAddr = 0;
|
||||
// Comments are used when parsing back a generated font
|
||||
Font.output('jump', ' // Jump Table:');
|
||||
Font.output('data', ' // Font Data:');
|
||||
// Browse each character
|
||||
for(let ch = 0; ch < charCount; ch++) {
|
||||
// Fix renumbering in case first char code was modified
|
||||
Font.updateCaption(chars[ch].getElementsByTagName('caption')[0], ch + firstCharCode);
|
||||
let charBytes = [];
|
||||
let charCode = ch + firstCharCode;
|
||||
let rows = chars[ch].getElementsByTagName('tr');
|
||||
let charNotZero = false;
|
||||
// Browse each column
|
||||
for(let col = 0; col < this.width ; col++) {
|
||||
let bits = ""; // using string because js uses 32b ints when performing bit operations
|
||||
// Browse each row starting from the bottom one, going up, and accumulate pixels in
|
||||
// a string: this rotates the glyph
|
||||
// Beware, row 0 is table headers.
|
||||
for(let r = rows.length-1; r >=1 ; r--) {
|
||||
let pixelState = rows[r].children[col].className;
|
||||
bits += (pixelState === 'on' ? '1': '0');
|
||||
}
|
||||
// Need to complete missing bits to have a sizeof byte multiple number of bits
|
||||
for(let b = 0; b < bits2add; b++) {
|
||||
bits = '0' + bits;
|
||||
}
|
||||
// Font.output('data', ` // ${bits}`); // Debugging help: rotated bitmap
|
||||
|
||||
// read bytes from the end
|
||||
for(let b = bits.length - 1; b >= 7; b -= 8) {
|
||||
//Font.output('data', ` // ${bits.substr(b-7, 8)}`); // Debugging help: rotated bitmap
|
||||
let byte = parseInt(bits.substr(b-7, 8), 2);
|
||||
if (byte !== 0) {
|
||||
charNotZero = true;
|
||||
}
|
||||
charBytes.push(Font.toHexString(byte));
|
||||
}
|
||||
}
|
||||
// Compute the used width of the character:
|
||||
// rightmost column with pixels plus one
|
||||
// one column is spread over several bytes...
|
||||
let charWidth = 0;
|
||||
for(let i=charBytes.length - 1; i >= 0; i-=this.bytesForHeight) {
|
||||
let sum = 0;
|
||||
for(let j=0; j < this.bytesForHeight; j++) {
|
||||
sum += parseInt(charBytes[i - j], 16);
|
||||
}
|
||||
if(sum !== 0) {
|
||||
charWidth = (i + 1)/this.bytesForHeight + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Memory optim: Remove bytes with value 0 at the end of the array.
|
||||
while(parseInt(charBytes[charBytes.length-1], 16) === 0 && charBytes.length > 1) {
|
||||
charBytes.pop();
|
||||
}
|
||||
if (charNotZero) {
|
||||
Font.output('data', ` ${charBytes.join(', ')}, // ${charCode}`);
|
||||
Font.output('jump', ` ${Font.getMsB(charAddr)}, ${Font.getLsB(charAddr)}, ${Font.toHexString(charBytes.length)}, ${Font.toHexString(charWidth)}, // ${charCode} `);
|
||||
charAddr += charBytes.length;
|
||||
} else {
|
||||
Font.output('jump', ` 0xFF, 0xFF, 0x00, ${Font.toHexString(this.width)}, // ${charCode} `);
|
||||
}
|
||||
}
|
||||
Font.output('data', '};');
|
||||
|
||||
Font.output('header', "// Font generated or edited with the glyphEditor");
|
||||
Font.output('header', `const uint8_t ${name}[] PROGMEM = {`);
|
||||
// Comments are used when parsing back a generated font
|
||||
Font.output('header', ` ${Font.toHexString(this.width)}, // Width: ${this.width}`);
|
||||
Font.output('header', ` ${Font.toHexString(this.height)}, // Height: ${this.height}`);
|
||||
Font.output('header', ` ${Font.toHexString(firstCharCode)}, // First char: ${firstCharCode}`);
|
||||
Font.output('header', ` ${Font.toHexString(charCount)}, // Number of chars: ${charCount}`);
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('fileinput').addEventListener('change', function(e) {
|
||||
let f = e.target.files[0];
|
||||
if (f) {
|
||||
let r = new FileReader();
|
||||
r.onload = function(e) {
|
||||
let contents = e.target.result;
|
||||
alert( "Got the file.\n"
|
||||
+"name: " + f.name + "\n"
|
||||
+"type: " + f.type + "\n"
|
||||
+"size: " + f.size + " bytes\n"
|
||||
+"starts with: " + contents.substr(0, contents.indexOf("\n"))
|
||||
);
|
||||
document.getElementById("inputText").value = contents;
|
||||
};
|
||||
r.readAsText(f);
|
||||
} else {
|
||||
alert("Failed to load file");
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('savetoFile').addEventListener('click', function() {
|
||||
font.saveFile();
|
||||
});
|
||||
|
||||
document.getElementById('shiftUp').addEventListener('click', function() {
|
||||
var chars = document.getElementById("chars");
|
||||
var tables = chars.getElementsByTagName("table");
|
||||
for(var i=0; i< tables.length; i++) {
|
||||
shiftUp(tables[i]);
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('generate').addEventListener('click', function() {
|
||||
font.generate();
|
||||
});
|
||||
document.getElementById('addChar').addEventListener('click', function() {
|
||||
font.addChar();
|
||||
});
|
||||
document.getElementById('inputText').addEventListener('click', function(e) {
|
||||
let target = e.target;
|
||||
target.select();
|
||||
});
|
||||
document.getElementById('chars').addEventListener('mousedown', function(e) {
|
||||
if (e.button !== 0) return;
|
||||
let target = e.target;
|
||||
let action = target.getAttribute('action') || '';
|
||||
if (action === '') return;
|
||||
let result, code, nextContainer, previousContainer, pixels ;
|
||||
let currentContainer = target.parentNode.parentNode;
|
||||
switch(action) {
|
||||
case 'add':
|
||||
code = currentContainer.getAttribute('code');
|
||||
nextContainer = font.addChar();
|
||||
currentContainer.parentNode.insertBefore(nextContainer, currentContainer);
|
||||
do {
|
||||
nextContainer.setAttribute('code', code);
|
||||
Font.updateCaption(nextContainer.getElementsByTagName('caption')[0], code);
|
||||
code ++;
|
||||
} while (nextContainer = nextContainer.nextSibling);
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
result = confirm("Delete this character ?");
|
||||
if (!result) return;
|
||||
code = currentContainer.getAttribute('code');
|
||||
nextContainer = currentContainer;
|
||||
while (nextContainer = nextContainer.nextSibling) {
|
||||
nextContainer.setAttribute('code', code);
|
||||
Font.updateCaption(nextContainer.getElementsByTagName('caption')[0], code);
|
||||
code ++;
|
||||
}
|
||||
currentContainer.parentNode.removeChild(currentContainer);
|
||||
break;
|
||||
|
||||
// Shift pixels to the left
|
||||
case 'left':
|
||||
pixels = currentContainer.getElementsByTagName('td');
|
||||
for(p = 0; p < pixels.length; p++) {
|
||||
if((p + 1) % font.width) {
|
||||
pixels[p].className = pixels[p + 1].className;
|
||||
} else {
|
||||
pixels[p].className = '';
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Shift pixels to the right
|
||||
case 'right':
|
||||
pixels = currentContainer.getElementsByTagName('td');
|
||||
for(p = pixels.length-1; p >=0 ; p--) {
|
||||
if(p % font.width) {
|
||||
pixels[p].className = pixels[p - 1].className;
|
||||
} else {
|
||||
pixels[p].className = '';
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Shift pixels down
|
||||
case 'down':
|
||||
pixels = currentContainer.getElementsByTagName('td');
|
||||
for(p = pixels.length-1; p >=0 ; p--) {
|
||||
if(p >= font.width) {
|
||||
pixels[p].className = pixels[p - font.width].className;
|
||||
} else {
|
||||
pixels[p].className = '';
|
||||
}
|
||||
} break;
|
||||
|
||||
// Shift pixels up
|
||||
case 'up':
|
||||
shiftUp(currentContainer);
|
||||
break;
|
||||
|
||||
case 'toggle':
|
||||
Font.togglePixel(target);
|
||||
break;
|
||||
|
||||
case 'clean':
|
||||
result = confirm("Delete the pixels ?");
|
||||
if (!result) return;
|
||||
pixels = currentContainer.getElementsByTagName('td');
|
||||
for (let p = 0; p < pixels.length; p++) {
|
||||
pixels[p].className = '';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'copy':
|
||||
let charNumber = parseInt(prompt("Source char #: "));
|
||||
let chars = font.fontContainer.getElementsByTagName('table');
|
||||
let tableOffset = charNumber - parseInt(document.getElementById('code').value);
|
||||
let srcPixels = chars[tableOffset].getElementsByTagName('td');
|
||||
let targetPixels = currentContainer.getElementsByTagName('td');
|
||||
for(let i=0; i < srcPixels.length; i++) {
|
||||
// First tds are in the th row, for editing actions. Skip them
|
||||
if (targetPixels[i].parentNode.localName === 'th') continue; // In case we give them css at some point...
|
||||
targetPixels[i].className = srcPixels[i].className;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// no.
|
||||
}
|
||||
|
||||
});
|
||||
function shiftUp(container) {
|
||||
var pixels = container.getElementsByTagName('td');
|
||||
for(p = 0; p < pixels.length; p++) {
|
||||
if(p < font.width*(font.height -1)) {
|
||||
pixels[p].className = pixels[p + font.width].className;
|
||||
} else {
|
||||
pixels[p].className = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('chars').addEventListener('mouseover', function(e) {
|
||||
let target = e.target;
|
||||
let action = target.getAttribute('action');
|
||||
if (action !== 'toggle' || e.buttons !== 1) return;
|
||||
Font.togglePixel(target);
|
||||
});
|
||||
document.getElementById('chars').addEventListener('dragstart', function() {
|
||||
return false;
|
||||
});
|
||||
|
||||
document.getElementById('create').addEventListener('click', function() {
|
||||
font = new Font();
|
||||
font.addChar();
|
||||
});
|
||||
|
||||
// parse a char array declaration for an existing font.
|
||||
// parsing heavily relies on comments.
|
||||
document.getElementById('parse').addEventListener('click', function() {
|
||||
if (document.getElementById('chars').childElementCount) {
|
||||
let result = confirm("Confirm you want to overwrite the existing grids ?");
|
||||
if (!result) return;
|
||||
}
|
||||
let lines = document.getElementById('inputText').value.split('\n');
|
||||
let name = '';
|
||||
let height = 0;
|
||||
let width = 0;
|
||||
let firstCharCode = 0;
|
||||
let jumpTable = [];
|
||||
let charData = [];
|
||||
let readingJumpTable = false;
|
||||
let readingData = false;
|
||||
|
||||
for(let l = 0 ; l < lines.length; l++) {
|
||||
// TODO ? keep C compilation directives to copy them (not lowercased :)) to newly generated char array
|
||||
let line = lines[l].trim();
|
||||
//alert(line);
|
||||
let fields;
|
||||
|
||||
// Declaration line: grab the name
|
||||
if (line.indexOf('PROGMEM') > 0) {
|
||||
fields = line.split(' ');
|
||||
name = fields[2].replace(/[\[\]]/g, '');
|
||||
continue;
|
||||
}
|
||||
line = line.toLowerCase();
|
||||
// Todo: could rely on line order...
|
||||
// width line: grab the width
|
||||
if (line.indexOf('width') > 0) {
|
||||
fields = line.split(',');
|
||||
width = fields[0];
|
||||
continue;
|
||||
}
|
||||
// height line: grab the height
|
||||
if (line.indexOf('height') > 0) {
|
||||
fields = line.split(',');
|
||||
height = fields[0];
|
||||
continue;
|
||||
}
|
||||
// first char code line: grab the first char code
|
||||
if (line.indexOf('first char') > 0) {
|
||||
fields = line.split(',');
|
||||
firstCharCode = fields[0];
|
||||
continue;
|
||||
}
|
||||
// End of array declaration
|
||||
// TODO warn if more lines: next fonts are ignored
|
||||
if (line.indexOf('};') === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (readingJumpTable || readingData) {
|
||||
if (line.indexOf('#') !== 0 && line.length !== 0 && line.indexOf('//') !== 0) {
|
||||
line = line.replace(/\/\/.*/, ''); // get rid of end of line comments
|
||||
fields = line.split(',');
|
||||
let newEntry = [];
|
||||
for(let f=0; f < fields.length; f++) {
|
||||
let value = parseInt(fields[f]);
|
||||
if (isNaN(value)) continue;
|
||||
if (readingData) {
|
||||
charData.push(value);
|
||||
}
|
||||
if (readingJumpTable) {
|
||||
newEntry.push(value);
|
||||
}
|
||||
}
|
||||
if (readingJumpTable) {
|
||||
jumpTable.push(newEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Begining of data
|
||||
if (line.indexOf('font data') > 0) {
|
||||
readingData = true;
|
||||
readingJumpTable = false;
|
||||
}
|
||||
// Begining of jump table
|
||||
if (line.indexOf('jump table') > 0) {
|
||||
readingJumpTable = true;
|
||||
}
|
||||
}
|
||||
if (!name || !height || !width || !firstCharCode) {
|
||||
alert("Does not look like a parsable font. Try again.");
|
||||
return;
|
||||
}
|
||||
|
||||
Font.emptyChars();
|
||||
Font.emptyOutput();
|
||||
document.getElementById('name').value = name;
|
||||
document.getElementById('height').value = parseInt(height);
|
||||
document.getElementById('width').value = parseInt(width);
|
||||
document.getElementById('code').value = parseInt(firstCharCode);
|
||||
font = new Font();
|
||||
for(let c = 0 ; c < jumpTable.length; c++) {
|
||||
let jumpEntry = jumpTable[c];
|
||||
let charEntry = [];
|
||||
// displayable character
|
||||
if (jumpEntry[0] !== 255 || jumpEntry[1] !== 255) {
|
||||
charEntry = charData.splice(0, jumpEntry[2]);
|
||||
}
|
||||
font.addChar(jumpEntry, charEntry);
|
||||
}
|
||||
document.body.className = "started";
|
||||
});
|
||||
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 41 KiB |
1045
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/src/OLEDDisplay.cpp
Normal file
384
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/src/OLEDDisplay.h
Normal file
@@ -0,0 +1,384 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
|
||||
* Copyright (c) 2018 by Fabrice Weinberg
|
||||
* Copyright (c) 2019 by Helmut Tschemernjak - www.radioshuttle.de
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* ThingPulse invests considerable time and money to develop these open source libraries.
|
||||
* Please support us by buying our products (and not the clones) from
|
||||
* https://thingpulse.com
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef OLEDDISPLAY_h
|
||||
#define OLEDDISPLAY_h
|
||||
|
||||
#ifdef ARDUINO
|
||||
#include <Arduino.h>
|
||||
#elif __MBED__
|
||||
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
|
||||
|
||||
#include <mbed.h>
|
||||
#define delay(x) wait_ms(x)
|
||||
#define yield() void()
|
||||
|
||||
/*
|
||||
* This is a little Arduino String emulation to keep the OLEDDisplay
|
||||
* library code in common between Arduino and mbed-os
|
||||
*/
|
||||
class String {
|
||||
public:
|
||||
String(const char *s) { _str = s; };
|
||||
int length() { return strlen(_str); };
|
||||
const char *c_str() { return _str; };
|
||||
void toCharArray(char *buf, unsigned int bufsize, unsigned int index = 0) const {
|
||||
memcpy(buf, _str + index, std::min(bufsize, strlen(_str)));
|
||||
};
|
||||
private:
|
||||
const char *_str;
|
||||
};
|
||||
|
||||
#else
|
||||
#error "Unkown operating system"
|
||||
#endif
|
||||
|
||||
#include "OLEDDisplayFonts.h"
|
||||
|
||||
//#define DEBUG_OLEDDISPLAY(...) Serial.printf( __VA_ARGS__ )
|
||||
//#define DEBUG_OLEDDISPLAY(...) dprintf("%s", __VA_ARGS__ )
|
||||
|
||||
#ifndef DEBUG_OLEDDISPLAY
|
||||
#define DEBUG_OLEDDISPLAY(...)
|
||||
#endif
|
||||
|
||||
// Use DOUBLE BUFFERING by default
|
||||
#ifndef OLEDDISPLAY_REDUCE_MEMORY
|
||||
#define OLEDDISPLAY_DOUBLE_BUFFER
|
||||
#endif
|
||||
|
||||
// Header Values
|
||||
#define JUMPTABLE_BYTES 4
|
||||
|
||||
#define JUMPTABLE_LSB 1
|
||||
#define JUMPTABLE_SIZE 2
|
||||
#define JUMPTABLE_WIDTH 3
|
||||
#define JUMPTABLE_START 4
|
||||
|
||||
#define WIDTH_POS 0
|
||||
#define HEIGHT_POS 1
|
||||
#define FIRST_CHAR_POS 2
|
||||
#define CHAR_NUM_POS 3
|
||||
|
||||
|
||||
// Display commands
|
||||
#define CHARGEPUMP 0x8D
|
||||
#define COLUMNADDR 0x21
|
||||
#define COMSCANDEC 0xC8
|
||||
#define COMSCANINC 0xC0
|
||||
#define DISPLAYALLON 0xA5
|
||||
#define DISPLAYALLON_RESUME 0xA4
|
||||
#define DISPLAYOFF 0xAE
|
||||
#define DISPLAYON 0xAF
|
||||
#define EXTERNALVCC 0x1
|
||||
#define INVERTDISPLAY 0xA7
|
||||
#define MEMORYMODE 0x20
|
||||
#define NORMALDISPLAY 0xA6
|
||||
#define PAGEADDR 0x22
|
||||
#define SEGREMAP 0xA0
|
||||
#define SETCOMPINS 0xDA
|
||||
#define SETCONTRAST 0x81
|
||||
#define SETDISPLAYCLOCKDIV 0xD5
|
||||
#define SETDISPLAYOFFSET 0xD3
|
||||
#define SETHIGHCOLUMN 0x10
|
||||
#define SETLOWCOLUMN 0x00
|
||||
#define SETMULTIPLEX 0xA8
|
||||
#define SETPRECHARGE 0xD9
|
||||
#define SETSEGMENTREMAP 0xA1
|
||||
#define SETSTARTLINE 0x40
|
||||
#define SETVCOMDETECT 0xDB
|
||||
#define SWITCHCAPVCC 0x2
|
||||
|
||||
#ifndef _swap_int16_t
|
||||
#define _swap_int16_t(a, b) { int16_t t = a; a = b; b = t; }
|
||||
#endif
|
||||
|
||||
enum OLEDDISPLAY_COLOR {
|
||||
BLACK = 0,
|
||||
WHITE = 1,
|
||||
INVERSE = 2
|
||||
};
|
||||
|
||||
enum OLEDDISPLAY_TEXT_ALIGNMENT {
|
||||
TEXT_ALIGN_LEFT = 0,
|
||||
TEXT_ALIGN_RIGHT = 1,
|
||||
TEXT_ALIGN_CENTER = 2,
|
||||
TEXT_ALIGN_CENTER_BOTH = 3
|
||||
};
|
||||
|
||||
|
||||
enum OLEDDISPLAY_GEOMETRY {
|
||||
GEOMETRY_128_64 = 0,
|
||||
GEOMETRY_128_32 = 1,
|
||||
GEOMETRY_64_48 = 2,
|
||||
GEOMETRY_64_32 = 3,
|
||||
GEOMETRY_RAWMODE = 4
|
||||
};
|
||||
|
||||
enum HW_I2C {
|
||||
I2C_ONE,
|
||||
I2C_TWO
|
||||
};
|
||||
|
||||
typedef char (*FontTableLookupFunction)(const uint8_t ch);
|
||||
char DefaultFontTableLookup(const uint8_t ch);
|
||||
|
||||
|
||||
#ifdef ARDUINO
|
||||
class OLEDDisplay : public Print {
|
||||
#elif __MBED__
|
||||
class OLEDDisplay : public Stream {
|
||||
#else
|
||||
#error "Unkown operating system"
|
||||
#endif
|
||||
|
||||
public:
|
||||
OLEDDisplay();
|
||||
virtual ~OLEDDisplay();
|
||||
|
||||
uint16_t width(void) const { return displayWidth; };
|
||||
uint16_t height(void) const { return displayHeight; };
|
||||
|
||||
// Use this to resume after a deep sleep without resetting the display (what init() would do).
|
||||
// Returns true if connection to the display was established and the buffer allocated, false otherwise.
|
||||
bool allocateBuffer();
|
||||
|
||||
// Allocates the buffer and initializes the driver & display. Resets the display!
|
||||
// Returns false if buffer allocation failed, true otherwise.
|
||||
bool init();
|
||||
|
||||
// Free the memory used by the display
|
||||
void end();
|
||||
|
||||
// Cycle through the initialization
|
||||
void resetDisplay(void);
|
||||
|
||||
/* Drawing functions */
|
||||
// Sets the color of all pixel operations
|
||||
void setColor(OLEDDISPLAY_COLOR color);
|
||||
|
||||
// Returns the current color.
|
||||
OLEDDISPLAY_COLOR getColor();
|
||||
|
||||
// Draw a pixel at given position
|
||||
void setPixel(int16_t x, int16_t y);
|
||||
|
||||
// Draw a pixel at given position and color
|
||||
void setPixelColor(int16_t x, int16_t y, OLEDDISPLAY_COLOR color);
|
||||
|
||||
// Clear a pixel at given position FIXME: INVERSE is untested with this function
|
||||
void clearPixel(int16_t x, int16_t y);
|
||||
|
||||
// Draw a line from position 0 to position 1
|
||||
void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1);
|
||||
|
||||
// Draw the border of a rectangle at the given location
|
||||
void drawRect(int16_t x, int16_t y, int16_t width, int16_t height);
|
||||
|
||||
// Fill the rectangle
|
||||
void fillRect(int16_t x, int16_t y, int16_t width, int16_t height);
|
||||
|
||||
// Draw the border of a circle
|
||||
void drawCircle(int16_t x, int16_t y, int16_t radius);
|
||||
|
||||
// Draw all Quadrants specified in the quads bit mask
|
||||
void drawCircleQuads(int16_t x0, int16_t y0, int16_t radius, uint8_t quads);
|
||||
|
||||
// Fill circle
|
||||
void fillCircle(int16_t x, int16_t y, int16_t radius);
|
||||
|
||||
// Draw a line horizontally
|
||||
void drawHorizontalLine(int16_t x, int16_t y, int16_t length);
|
||||
|
||||
// Draw a line vertically
|
||||
void drawVerticalLine(int16_t x, int16_t y, int16_t length);
|
||||
|
||||
// Draws a rounded progress bar with the outer dimensions given by width and height. Progress is
|
||||
// a unsigned byte value between 0 and 100
|
||||
void drawProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t progress);
|
||||
|
||||
// Draw a bitmap in the internal image format
|
||||
void drawFastImage(int16_t x, int16_t y, int16_t width, int16_t height, const uint8_t *image);
|
||||
|
||||
// Draw a XBM
|
||||
void drawXbm(int16_t x, int16_t y, int16_t width, int16_t height, const uint8_t *xbm);
|
||||
|
||||
// Draw icon 16x16 xbm format
|
||||
void drawIco16x16(int16_t x, int16_t y, const char *ico, bool inverse = false);
|
||||
|
||||
/* Text functions */
|
||||
|
||||
// Draws a string at the given location
|
||||
void drawString(int16_t x, int16_t y, String text);
|
||||
|
||||
// Draws a formatted string (like printf) at the given location
|
||||
void drawStringf(int16_t x, int16_t y, char* buffer, String format, ... );
|
||||
|
||||
// Draws a String with a maximum width at the given location.
|
||||
// If the given String is wider than the specified width
|
||||
// The text will be wrapped to the next line at a space or dash
|
||||
void drawStringMaxWidth(int16_t x, int16_t y, uint16_t maxLineWidth, String text);
|
||||
|
||||
// Returns the width of the const char* with the current
|
||||
// font settings
|
||||
uint16_t getStringWidth(const char* text, uint16_t length);
|
||||
|
||||
// Convencience method for the const char version
|
||||
uint16_t getStringWidth(String text);
|
||||
|
||||
// Specifies relative to which anchor point
|
||||
// the text is rendered. Available constants:
|
||||
// TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER_BOTH
|
||||
void setTextAlignment(OLEDDISPLAY_TEXT_ALIGNMENT textAlignment);
|
||||
|
||||
// Sets the current font. Available default fonts
|
||||
// ArialMT_Plain_10, ArialMT_Plain_16, ArialMT_Plain_24
|
||||
void setFont(const uint8_t *fontData);
|
||||
|
||||
// Set the function that will convert utf-8 to font table index
|
||||
void setFontTableLookupFunction(FontTableLookupFunction function);
|
||||
|
||||
/* Display functions */
|
||||
|
||||
// Turn the display on
|
||||
void displayOn(void);
|
||||
|
||||
// Turn the display offs
|
||||
void displayOff(void);
|
||||
|
||||
// Inverted display mode
|
||||
void invertDisplay(void);
|
||||
|
||||
// Normal display mode
|
||||
void normalDisplay(void);
|
||||
|
||||
// Set display contrast
|
||||
// really low brightness & contrast: contrast = 10, precharge = 5, comdetect = 0
|
||||
// normal brightness & contrast: contrast = 100
|
||||
void setContrast(uint8_t contrast, uint8_t precharge = 241, uint8_t comdetect = 64);
|
||||
|
||||
// Convenience method to access
|
||||
void setBrightness(uint8_t);
|
||||
|
||||
// Reset display rotation or mirroring
|
||||
void resetOrientation();
|
||||
|
||||
// Turn the display upside down
|
||||
void flipScreenVertically();
|
||||
|
||||
// Mirror the display (to be used in a mirror or as a projector)
|
||||
void mirrorScreen();
|
||||
|
||||
// Write the buffer to the display memory
|
||||
virtual void display(void) = 0;
|
||||
|
||||
// Clear the local pixel buffer
|
||||
void clear(void);
|
||||
|
||||
// Log buffer implementation
|
||||
|
||||
// This will define the lines and characters you can
|
||||
// print to the screen. When you exeed the buffer size (lines * chars)
|
||||
// the output may be truncated due to the size constraint.
|
||||
bool setLogBuffer(uint16_t lines, uint16_t chars);
|
||||
|
||||
// Draw the log buffer at position (x, y)
|
||||
void drawLogBuffer(uint16_t x, uint16_t y);
|
||||
|
||||
// Get screen geometry
|
||||
uint16_t getWidth(void);
|
||||
uint16_t getHeight(void);
|
||||
|
||||
// Implement needed function to be compatible with Print class
|
||||
size_t write(uint8_t c);
|
||||
size_t write(const char* s);
|
||||
|
||||
// Implement needed function to be compatible with Stream class
|
||||
#ifdef __MBED__
|
||||
int _putc(int c);
|
||||
int _getc() { return -1; };
|
||||
#endif
|
||||
|
||||
|
||||
uint8_t *buffer;
|
||||
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t *buffer_back;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
OLEDDISPLAY_GEOMETRY geometry;
|
||||
|
||||
uint16_t displayWidth;
|
||||
uint16_t displayHeight;
|
||||
uint16_t displayBufferSize;
|
||||
|
||||
// Set the correct height, width and buffer for the geometry
|
||||
void setGeometry(OLEDDISPLAY_GEOMETRY g, uint16_t width = 0, uint16_t height = 0);
|
||||
|
||||
OLEDDISPLAY_TEXT_ALIGNMENT textAlignment;
|
||||
OLEDDISPLAY_COLOR color;
|
||||
|
||||
const uint8_t *fontData;
|
||||
|
||||
// State values for logBuffer
|
||||
uint16_t logBufferSize;
|
||||
uint16_t logBufferFilled;
|
||||
uint16_t logBufferLine;
|
||||
uint16_t logBufferMaxLines;
|
||||
char *logBuffer;
|
||||
|
||||
|
||||
// the header size of the buffer used, e.g. for the SPI command header
|
||||
int BufferOffset;
|
||||
virtual int getBufferOffset(void) = 0;
|
||||
|
||||
// Send a command to the display (low level function)
|
||||
virtual void sendCommand(uint8_t com) {(void)com;};
|
||||
|
||||
// Connect to the display
|
||||
virtual bool connect() { return false; };
|
||||
|
||||
// Send all the init commands
|
||||
void sendInitCommands();
|
||||
|
||||
// converts utf8 characters to extended ascii
|
||||
char* utf8ascii(String s);
|
||||
|
||||
void inline drawInternal(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *data, uint16_t offset, uint16_t bytesInData) __attribute__((always_inline));
|
||||
|
||||
void drawStringInternal(int16_t xMove, int16_t yMove, char* text, uint16_t textLength, uint16_t textWidth);
|
||||
|
||||
FontTableLookupFunction fontTableLookupFunction;
|
||||
};
|
||||
|
||||
#endif
|
||||
1278
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/src/OLEDDisplayFonts.h
Normal file
@@ -0,0 +1,471 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
|
||||
* Copyright (c) 2018 by Fabrice Weinberg
|
||||
* Copyright (c) 2019 by Helmut Tschemernjak - www.radioshuttle.de
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* ThingPulse invests considerable time and money to develop these open source libraries.
|
||||
* Please support us by buying our products (and not the clones) from
|
||||
* https://thingpulse.com
|
||||
*
|
||||
*/
|
||||
|
||||
#include "OLEDDisplayUi.h"
|
||||
|
||||
void LoadingDrawDefault(OLEDDisplay *display, LoadingStage* stage, uint8_t progress) {
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(ArialMT_Plain_10);
|
||||
display->drawString(64, 18, stage->process);
|
||||
display->drawProgressBar(4, 32, 120, 8, progress);
|
||||
};
|
||||
|
||||
|
||||
OLEDDisplayUi::OLEDDisplayUi(OLEDDisplay *display) {
|
||||
this->display = display;
|
||||
|
||||
indicatorPosition = BOTTOM;
|
||||
indicatorDirection = LEFT_RIGHT;
|
||||
activeSymbol = ANIMATION_activeSymbol;
|
||||
inactiveSymbol = ANIMATION_inactiveSymbol;
|
||||
frameAnimationDirection = SLIDE_RIGHT;
|
||||
lastTransitionDirection = 1;
|
||||
frameCount = 0;
|
||||
nextFrameNumber = -1;
|
||||
overlayCount = 0;
|
||||
indicatorDrawState = 1;
|
||||
loadingDrawFunction = LoadingDrawDefault;
|
||||
updateInterval = 33;
|
||||
state.lastUpdate = 0;
|
||||
state.ticksSinceLastStateSwitch = 0;
|
||||
state.frameState = FIXED;
|
||||
state.currentFrame = 0;
|
||||
state.frameTransitionDirection = 1;
|
||||
state.isIndicatorDrawen = true;
|
||||
state.manuelControll = false;
|
||||
state.userData = NULL;
|
||||
shouldDrawIndicators = true;
|
||||
autoTransition = true;
|
||||
setTimePerFrame(5000);
|
||||
setTimePerTransition(500);
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::init() {
|
||||
this->display->init();
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::setTargetFPS(uint8_t fps){
|
||||
this->updateInterval = ((float) 1.0 / (float) fps) * 1000;
|
||||
|
||||
this->ticksPerFrame = timePerFrame / updateInterval;
|
||||
this->ticksPerTransition = timePerTransition / updateInterval;
|
||||
}
|
||||
|
||||
// -/------ Automatic controll ------\-
|
||||
|
||||
void OLEDDisplayUi::enableAutoTransition(){
|
||||
this->autoTransition = true;
|
||||
}
|
||||
void OLEDDisplayUi::disableAutoTransition(){
|
||||
this->autoTransition = false;
|
||||
}
|
||||
void OLEDDisplayUi::setAutoTransitionForwards(){
|
||||
this->state.frameTransitionDirection = 1;
|
||||
this->lastTransitionDirection = 1;
|
||||
}
|
||||
void OLEDDisplayUi::setAutoTransitionBackwards(){
|
||||
this->state.frameTransitionDirection = -1;
|
||||
this->lastTransitionDirection = -1;
|
||||
}
|
||||
void OLEDDisplayUi::setTimePerFrame(uint16_t time){
|
||||
this->timePerFrame = time;
|
||||
this->ticksPerFrame = timePerFrame / updateInterval;
|
||||
}
|
||||
void OLEDDisplayUi::setTimePerTransition(uint16_t time){
|
||||
this->timePerTransition = time;
|
||||
this->ticksPerTransition = timePerTransition / updateInterval;
|
||||
}
|
||||
|
||||
// -/------ Customize indicator position and style -------\-
|
||||
void OLEDDisplayUi::enableIndicator(){
|
||||
this->state.isIndicatorDrawen = true;
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::disableIndicator(){
|
||||
this->state.isIndicatorDrawen = false;
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::enableAllIndicators(){
|
||||
this->shouldDrawIndicators = true;
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::disableAllIndicators(){
|
||||
this->shouldDrawIndicators = false;
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::setIndicatorPosition(IndicatorPosition pos) {
|
||||
this->indicatorPosition = pos;
|
||||
}
|
||||
void OLEDDisplayUi::setIndicatorDirection(IndicatorDirection dir) {
|
||||
this->indicatorDirection = dir;
|
||||
}
|
||||
void OLEDDisplayUi::setActiveSymbol(const uint8_t* symbol) {
|
||||
this->activeSymbol = symbol;
|
||||
}
|
||||
void OLEDDisplayUi::setInactiveSymbol(const uint8_t* symbol) {
|
||||
this->inactiveSymbol = symbol;
|
||||
}
|
||||
|
||||
|
||||
// -/----- Frame settings -----\-
|
||||
void OLEDDisplayUi::setFrameAnimation(AnimationDirection dir) {
|
||||
this->frameAnimationDirection = dir;
|
||||
}
|
||||
void OLEDDisplayUi::setFrames(FrameCallback* frameFunctions, uint8_t frameCount) {
|
||||
this->frameFunctions = frameFunctions;
|
||||
this->frameCount = frameCount;
|
||||
this->resetState();
|
||||
}
|
||||
|
||||
// -/----- Overlays ------\-
|
||||
void OLEDDisplayUi::setOverlays(OverlayCallback* overlayFunctions, uint8_t overlayCount){
|
||||
this->overlayFunctions = overlayFunctions;
|
||||
this->overlayCount = overlayCount;
|
||||
}
|
||||
|
||||
// -/----- Loading Process -----\-
|
||||
|
||||
void OLEDDisplayUi::setLoadingDrawFunction(LoadingDrawFunction loadingDrawFunction) {
|
||||
this->loadingDrawFunction = loadingDrawFunction;
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::runLoadingProcess(LoadingStage* stages, uint8_t stagesCount) {
|
||||
uint8_t progress = 0;
|
||||
uint8_t increment = 100 / stagesCount;
|
||||
|
||||
for (uint8_t i = 0; i < stagesCount; i++) {
|
||||
display->clear();
|
||||
this->loadingDrawFunction(this->display, &stages[i], progress);
|
||||
display->display();
|
||||
|
||||
stages[i].callback();
|
||||
|
||||
progress += increment;
|
||||
yield();
|
||||
}
|
||||
|
||||
display->clear();
|
||||
this->loadingDrawFunction(this->display, &stages[stagesCount-1], progress);
|
||||
display->display();
|
||||
|
||||
delay(150);
|
||||
}
|
||||
|
||||
// -/----- Manuel control -----\-
|
||||
void OLEDDisplayUi::nextFrame() {
|
||||
if (this->state.frameState != IN_TRANSITION) {
|
||||
this->state.manuelControll = true;
|
||||
this->state.frameState = IN_TRANSITION;
|
||||
this->state.ticksSinceLastStateSwitch = 0;
|
||||
this->lastTransitionDirection = this->state.frameTransitionDirection;
|
||||
this->state.frameTransitionDirection = 1;
|
||||
}
|
||||
}
|
||||
void OLEDDisplayUi::previousFrame() {
|
||||
if (this->state.frameState != IN_TRANSITION) {
|
||||
this->state.manuelControll = true;
|
||||
this->state.frameState = IN_TRANSITION;
|
||||
this->state.ticksSinceLastStateSwitch = 0;
|
||||
this->lastTransitionDirection = this->state.frameTransitionDirection;
|
||||
this->state.frameTransitionDirection = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::switchToFrame(uint8_t frame) {
|
||||
if (frame >= this->frameCount) return;
|
||||
this->state.ticksSinceLastStateSwitch = 0;
|
||||
if (frame == this->state.currentFrame) return;
|
||||
this->state.frameState = FIXED;
|
||||
this->state.currentFrame = frame;
|
||||
this->state.isIndicatorDrawen = true;
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::transitionToFrame(uint8_t frame) {
|
||||
if (frame >= this->frameCount) return;
|
||||
this->state.ticksSinceLastStateSwitch = 0;
|
||||
if (frame == this->state.currentFrame) return;
|
||||
this->nextFrameNumber = frame;
|
||||
this->lastTransitionDirection = this->state.frameTransitionDirection;
|
||||
this->state.manuelControll = true;
|
||||
this->state.frameState = IN_TRANSITION;
|
||||
this->state.frameTransitionDirection = frame < this->state.currentFrame ? -1 : 1;
|
||||
}
|
||||
|
||||
|
||||
// -/----- State information -----\-
|
||||
OLEDDisplayUiState* OLEDDisplayUi::getUiState(){
|
||||
return &this->state;
|
||||
}
|
||||
|
||||
int16_t OLEDDisplayUi::update(){
|
||||
#ifdef ARDUINO
|
||||
unsigned long frameStart = millis();
|
||||
#elif __MBED__
|
||||
Timer t;
|
||||
t.start();
|
||||
unsigned long frameStart = t.read_ms();
|
||||
#else
|
||||
#error "Unkown operating system"
|
||||
#endif
|
||||
int32_t timeBudget = this->updateInterval - (frameStart - this->state.lastUpdate);
|
||||
if ( timeBudget <= 0) {
|
||||
// Implement frame skipping to ensure time budget is keept
|
||||
if (this->autoTransition && this->state.lastUpdate != 0) this->state.ticksSinceLastStateSwitch += ceil((double)-timeBudget / (double)this->updateInterval);
|
||||
|
||||
this->state.lastUpdate = frameStart;
|
||||
this->tick();
|
||||
}
|
||||
#ifdef ARDUINO
|
||||
return this->updateInterval - (millis() - frameStart);
|
||||
#elif __MBED__
|
||||
return this->updateInterval - (t.read_ms() - frameStart);
|
||||
#else
|
||||
#error "Unkown operating system"
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void OLEDDisplayUi::tick() {
|
||||
this->state.ticksSinceLastStateSwitch++;
|
||||
|
||||
switch (this->state.frameState) {
|
||||
case IN_TRANSITION:
|
||||
if (this->state.ticksSinceLastStateSwitch >= this->ticksPerTransition){
|
||||
this->state.frameState = FIXED;
|
||||
this->state.currentFrame = getNextFrameNumber();
|
||||
this->state.ticksSinceLastStateSwitch = 0;
|
||||
this->nextFrameNumber = -1;
|
||||
}
|
||||
break;
|
||||
case FIXED:
|
||||
// Revert manuelControll
|
||||
if (this->state.manuelControll) {
|
||||
this->state.frameTransitionDirection = this->lastTransitionDirection;
|
||||
this->state.manuelControll = false;
|
||||
}
|
||||
if (this->state.ticksSinceLastStateSwitch >= this->ticksPerFrame){
|
||||
if (this->autoTransition){
|
||||
this->state.frameState = IN_TRANSITION;
|
||||
}
|
||||
this->state.ticksSinceLastStateSwitch = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
this->display->clear();
|
||||
this->drawFrame();
|
||||
if (shouldDrawIndicators) {
|
||||
this->drawIndicator();
|
||||
}
|
||||
this->drawOverlays();
|
||||
this->display->display();
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::resetState() {
|
||||
this->state.lastUpdate = 0;
|
||||
this->state.ticksSinceLastStateSwitch = 0;
|
||||
this->state.frameState = FIXED;
|
||||
this->state.currentFrame = 0;
|
||||
this->state.isIndicatorDrawen = true;
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::drawFrame(){
|
||||
switch (this->state.frameState){
|
||||
case IN_TRANSITION: {
|
||||
float progress = 0.f;
|
||||
if (this->ticksPerTransition > 0u) {
|
||||
progress = (float) this->state.ticksSinceLastStateSwitch / (float) this->ticksPerTransition;
|
||||
}
|
||||
int16_t x = 0, y = 0, x1 = 0, y1 = 0;
|
||||
switch(this->frameAnimationDirection){
|
||||
case SLIDE_LEFT:
|
||||
x = -this->display->width() * progress;
|
||||
y = 0;
|
||||
x1 = x + this->display->width();
|
||||
y1 = 0;
|
||||
break;
|
||||
case SLIDE_RIGHT:
|
||||
x = this->display->width() * progress;
|
||||
y = 0;
|
||||
x1 = x - this->display->width();
|
||||
y1 = 0;
|
||||
break;
|
||||
case SLIDE_UP:
|
||||
x = 0;
|
||||
y = -this->display->height() * progress;
|
||||
x1 = 0;
|
||||
y1 = y + this->display->height();
|
||||
break;
|
||||
case SLIDE_DOWN:
|
||||
default:
|
||||
x = 0;
|
||||
y = this->display->height() * progress;
|
||||
x1 = 0;
|
||||
y1 = y - this->display->height();
|
||||
break;
|
||||
}
|
||||
|
||||
// Invert animation if direction is reversed.
|
||||
int8_t dir = this->state.frameTransitionDirection >= 0 ? 1 : -1;
|
||||
x *= dir; y *= dir; x1 *= dir; y1 *= dir;
|
||||
|
||||
bool drawenCurrentFrame;
|
||||
|
||||
|
||||
// Prope each frameFunction for the indicator Drawen state
|
||||
this->enableIndicator();
|
||||
(this->frameFunctions[this->state.currentFrame])(this->display, &this->state, x, y);
|
||||
drawenCurrentFrame = this->state.isIndicatorDrawen;
|
||||
|
||||
this->enableIndicator();
|
||||
(this->frameFunctions[this->getNextFrameNumber()])(this->display, &this->state, x1, y1);
|
||||
|
||||
// Build up the indicatorDrawState
|
||||
if (drawenCurrentFrame && !this->state.isIndicatorDrawen) {
|
||||
// Drawen now but not next
|
||||
this->indicatorDrawState = 2;
|
||||
} else if (!drawenCurrentFrame && this->state.isIndicatorDrawen) {
|
||||
// Not drawen now but next
|
||||
this->indicatorDrawState = 1;
|
||||
} else if (!drawenCurrentFrame && !this->state.isIndicatorDrawen) {
|
||||
// Not drawen in both frames
|
||||
this->indicatorDrawState = 3;
|
||||
}
|
||||
|
||||
// If the indicator isn't draw in the current frame
|
||||
// reflect it in state.isIndicatorDrawen
|
||||
if (!drawenCurrentFrame) this->state.isIndicatorDrawen = false;
|
||||
|
||||
break;
|
||||
}
|
||||
case FIXED:
|
||||
// Always assume that the indicator is drawn!
|
||||
// And set indicatorDrawState to "not known yet"
|
||||
this->indicatorDrawState = 0;
|
||||
this->enableIndicator();
|
||||
(this->frameFunctions[this->state.currentFrame])(this->display, &this->state, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::drawIndicator() {
|
||||
|
||||
// Only draw if the indicator is invisible
|
||||
// for both frames or
|
||||
// the indiactor is shown and we are IN_TRANSITION
|
||||
if (this->indicatorDrawState == 3 || (!this->state.isIndicatorDrawen && this->state.frameState != IN_TRANSITION)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t posOfHighlightFrame = 0;
|
||||
float indicatorFadeProgress = 0;
|
||||
|
||||
// if the indicator needs to be slided in we want to
|
||||
// highlight the next frame in the transition
|
||||
uint8_t frameToHighlight = this->indicatorDrawState == 1 ? this->getNextFrameNumber() : this->state.currentFrame;
|
||||
|
||||
// Calculate the frame that needs to be highlighted
|
||||
// based on the Direction the indiactor is drawn
|
||||
switch (this->indicatorDirection){
|
||||
case LEFT_RIGHT:
|
||||
posOfHighlightFrame = frameToHighlight;
|
||||
break;
|
||||
case RIGHT_LEFT:
|
||||
default:
|
||||
posOfHighlightFrame = this->frameCount - frameToHighlight;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (this->indicatorDrawState) {
|
||||
case 1: // Indicator was not drawn in this frame but will be in next
|
||||
// Slide IN
|
||||
indicatorFadeProgress = 1 - ((float) this->state.ticksSinceLastStateSwitch / (float) this->ticksPerTransition);
|
||||
break;
|
||||
case 2: // Indicator was drawn in this frame but not in next
|
||||
// Slide OUT
|
||||
indicatorFadeProgress = ((float) this->state.ticksSinceLastStateSwitch / (float) this->ticksPerTransition);
|
||||
break;
|
||||
}
|
||||
|
||||
//Space between indicators - reduce for small screen sizes
|
||||
uint16_t indicatorSpacing = 12;
|
||||
if (this->display->getHeight() < 64 && (this->indicatorPosition == RIGHT || this->indicatorPosition == LEFT)) {
|
||||
indicatorSpacing = 6;
|
||||
}
|
||||
|
||||
uint16_t frameStartPos = (indicatorSpacing * frameCount / 2);
|
||||
const uint8_t *image;
|
||||
|
||||
uint16_t x = 0,y = 0;
|
||||
|
||||
|
||||
for (uint8_t i = 0; i < this->frameCount; i++) {
|
||||
|
||||
switch (this->indicatorPosition){
|
||||
case TOP:
|
||||
y = 0 - (8 * indicatorFadeProgress);
|
||||
x = (this->display->width() / 2) - frameStartPos + 12 * i;
|
||||
break;
|
||||
case BOTTOM:
|
||||
y = (this->display->height() - 8) + (8 * indicatorFadeProgress);
|
||||
x = (this->display->width() / 2) - frameStartPos + 12 * i;
|
||||
break;
|
||||
case RIGHT:
|
||||
x = (this->display->width() - 8) + (8 * indicatorFadeProgress);
|
||||
y = (this->display->height() / 2) - frameStartPos + 2 + 12 * i;
|
||||
break;
|
||||
case LEFT:
|
||||
default:
|
||||
x = 0 - (8 * indicatorFadeProgress);
|
||||
y = (this->display->height() / 2) - frameStartPos + 2 + indicatorSpacing * i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (posOfHighlightFrame == i) {
|
||||
image = this->activeSymbol;
|
||||
} else {
|
||||
image = this->inactiveSymbol;
|
||||
}
|
||||
|
||||
this->display->drawFastImage(x, y, 8, 8, image);
|
||||
}
|
||||
}
|
||||
|
||||
void OLEDDisplayUi::drawOverlays() {
|
||||
for (uint8_t i=0;i<this->overlayCount;i++){
|
||||
(this->overlayFunctions[i])(this->display, &this->state);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t OLEDDisplayUi::getNextFrameNumber(){
|
||||
if (this->nextFrameNumber != -1) return this->nextFrameNumber;
|
||||
return (this->state.currentFrame + this->frameCount + this->state.frameTransitionDirection) % this->frameCount;
|
||||
}
|
||||
315
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/src/OLEDDisplayUi.h
Normal file
@@ -0,0 +1,315 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
|
||||
* Copyright (c) 2018 by Fabrice Weinberg
|
||||
* Copyright (c) 2019 by Helmut Tschemernjak - www.radioshuttle.de
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* ThingPulse invests considerable time and money to develop these open source libraries.
|
||||
* Please support us by buying our products (and not the clones) from
|
||||
* https://thingpulse.com
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef OLEDDISPLAYUI_h
|
||||
#define OLEDDISPLAYUI_h
|
||||
|
||||
#ifdef ARDUINO
|
||||
#include <Arduino.h>
|
||||
#elif __MBED__
|
||||
#include <mbed.h>
|
||||
#else
|
||||
#error "Unkown operating system"
|
||||
#endif
|
||||
|
||||
#include "OLEDDisplay.h"
|
||||
|
||||
//#define DEBUG_OLEDDISPLAYUI(...) Serial.printf( __VA_ARGS__ )
|
||||
|
||||
#ifndef DEBUG_OLEDDISPLAYUI
|
||||
#define DEBUG_OLEDDISPLAYUI(...)
|
||||
#endif
|
||||
|
||||
enum AnimationDirection {
|
||||
SLIDE_UP,
|
||||
SLIDE_DOWN,
|
||||
SLIDE_LEFT,
|
||||
SLIDE_RIGHT
|
||||
};
|
||||
|
||||
enum IndicatorPosition {
|
||||
TOP,
|
||||
RIGHT,
|
||||
BOTTOM,
|
||||
LEFT
|
||||
};
|
||||
|
||||
enum IndicatorDirection {
|
||||
LEFT_RIGHT,
|
||||
RIGHT_LEFT
|
||||
};
|
||||
|
||||
enum FrameState {
|
||||
IN_TRANSITION,
|
||||
FIXED
|
||||
};
|
||||
|
||||
|
||||
const uint8_t ANIMATION_activeSymbol[] PROGMEM = {
|
||||
0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00
|
||||
};
|
||||
|
||||
const uint8_t ANIMATION_inactiveSymbol[] PROGMEM = {
|
||||
0x00, 0x0, 0x0, 0x18, 0x18, 0x0, 0x0, 0x00
|
||||
};
|
||||
|
||||
|
||||
// Structure of the UiState
|
||||
struct OLEDDisplayUiState {
|
||||
uint64_t lastUpdate;
|
||||
uint16_t ticksSinceLastStateSwitch;
|
||||
|
||||
FrameState frameState;
|
||||
uint8_t currentFrame;
|
||||
|
||||
bool isIndicatorDrawen;
|
||||
|
||||
// Normal = 1, Inverse = -1;
|
||||
int8_t frameTransitionDirection;
|
||||
|
||||
bool manuelControll;
|
||||
|
||||
// Custom data that can be used by the user
|
||||
void* userData;
|
||||
};
|
||||
|
||||
struct LoadingStage {
|
||||
const char* process;
|
||||
void (*callback)();
|
||||
};
|
||||
|
||||
typedef void (*FrameCallback)(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
|
||||
typedef void (*OverlayCallback)(OLEDDisplay *display, OLEDDisplayUiState* state);
|
||||
typedef void (*LoadingDrawFunction)(OLEDDisplay *display, LoadingStage* stage, uint8_t progress);
|
||||
|
||||
class OLEDDisplayUi {
|
||||
private:
|
||||
OLEDDisplay *display;
|
||||
|
||||
// Symbols for the Indicator
|
||||
IndicatorPosition indicatorPosition;
|
||||
IndicatorDirection indicatorDirection;
|
||||
|
||||
const uint8_t* activeSymbol;
|
||||
const uint8_t* inactiveSymbol;
|
||||
|
||||
bool shouldDrawIndicators;
|
||||
|
||||
// Values for the Frames
|
||||
AnimationDirection frameAnimationDirection;
|
||||
|
||||
int8_t lastTransitionDirection;
|
||||
|
||||
uint16_t ticksPerFrame; // ~ 5000ms at 30 FPS
|
||||
uint16_t ticksPerTransition; // ~ 500ms at 30 FPS
|
||||
|
||||
bool autoTransition;
|
||||
|
||||
FrameCallback* frameFunctions;
|
||||
uint8_t frameCount;
|
||||
|
||||
// Internally used to transition to a specific frame
|
||||
int8_t nextFrameNumber;
|
||||
|
||||
// Values for Overlays
|
||||
OverlayCallback* overlayFunctions;
|
||||
uint8_t overlayCount;
|
||||
|
||||
// Will the Indicator be drawen
|
||||
// 3 Not drawn in both frames
|
||||
// 2 Drawn this frame but not next
|
||||
// 1 Not drown this frame but next
|
||||
// 0 Not known yet
|
||||
uint8_t indicatorDrawState;
|
||||
|
||||
// Loading screen
|
||||
LoadingDrawFunction loadingDrawFunction;
|
||||
|
||||
// UI State
|
||||
OLEDDisplayUiState state;
|
||||
|
||||
// Bookeeping for update
|
||||
uint16_t updateInterval = 33;
|
||||
|
||||
uint16_t timePerFrame;
|
||||
uint16_t timePerTransition;
|
||||
|
||||
uint8_t getNextFrameNumber();
|
||||
void drawIndicator();
|
||||
void drawFrame();
|
||||
void drawOverlays();
|
||||
void tick();
|
||||
void resetState();
|
||||
|
||||
public:
|
||||
|
||||
OLEDDisplayUi(OLEDDisplay *display);
|
||||
|
||||
/**
|
||||
* Initialise the display
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* Configure the internal used target FPS
|
||||
*/
|
||||
void setTargetFPS(uint8_t fps);
|
||||
|
||||
// Automatic Controll
|
||||
/**
|
||||
* Enable automatic transition to next frame after the some time can be configured with `setTimePerFrame` and `setTimePerTransition`.
|
||||
*/
|
||||
void enableAutoTransition();
|
||||
|
||||
/**
|
||||
* Disable automatic transition to next frame.
|
||||
*/
|
||||
void disableAutoTransition();
|
||||
|
||||
/**
|
||||
* Set the direction if the automatic transitioning
|
||||
*/
|
||||
void setAutoTransitionForwards();
|
||||
void setAutoTransitionBackwards();
|
||||
|
||||
/**
|
||||
* Set the approx. time a frame is displayed
|
||||
*/
|
||||
void setTimePerFrame(uint16_t time);
|
||||
|
||||
/**
|
||||
* Set the approx. time a transition will take
|
||||
*/
|
||||
void setTimePerTransition(uint16_t time);
|
||||
|
||||
// Customize indicator position and style
|
||||
|
||||
/**
|
||||
* Draw the indicator.
|
||||
* This is the defaut state for all frames if
|
||||
* the indicator was hidden on the previous frame
|
||||
* it will be slided in.
|
||||
*/
|
||||
void enableIndicator();
|
||||
|
||||
/**
|
||||
* Don't draw the indicator.
|
||||
* This will slide out the indicator
|
||||
* when transitioning to the next frame.
|
||||
*/
|
||||
void disableIndicator();
|
||||
|
||||
/**
|
||||
* Enable drawing of indicators
|
||||
*/
|
||||
void enableAllIndicators();
|
||||
|
||||
/**
|
||||
* Disable draw of indicators.
|
||||
*/
|
||||
void disableAllIndicators();
|
||||
|
||||
/**
|
||||
* Set the position of the indicator bar.
|
||||
*/
|
||||
void setIndicatorPosition(IndicatorPosition pos);
|
||||
|
||||
/**
|
||||
* Set the direction of the indicator bar. Defining the order of frames ASCENDING / DESCENDING
|
||||
*/
|
||||
void setIndicatorDirection(IndicatorDirection dir);
|
||||
|
||||
/**
|
||||
* Set the symbol to indicate an active frame in the indicator bar.
|
||||
*/
|
||||
void setActiveSymbol(const uint8_t* symbol);
|
||||
|
||||
/**
|
||||
* Set the symbol to indicate an inactive frame in the indicator bar.
|
||||
*/
|
||||
void setInactiveSymbol(const uint8_t* symbol);
|
||||
|
||||
|
||||
// Frame settings
|
||||
|
||||
/**
|
||||
* Configure what animation is used to transition from one frame to another
|
||||
*/
|
||||
void setFrameAnimation(AnimationDirection dir);
|
||||
|
||||
/**
|
||||
* Add frame drawing functions
|
||||
*/
|
||||
void setFrames(FrameCallback* frameFunctions, uint8_t frameCount);
|
||||
|
||||
// Overlay
|
||||
|
||||
/**
|
||||
* Add overlays drawing functions that are draw independent of the Frames
|
||||
*/
|
||||
void setOverlays(OverlayCallback* overlayFunctions, uint8_t overlayCount);
|
||||
|
||||
|
||||
// Loading animation
|
||||
/**
|
||||
* Set the function that will draw each step
|
||||
* in the loading animation
|
||||
*/
|
||||
void setLoadingDrawFunction(LoadingDrawFunction loadingFunction);
|
||||
|
||||
|
||||
/**
|
||||
* Run the loading process
|
||||
*/
|
||||
void runLoadingProcess(LoadingStage* stages, uint8_t stagesCount);
|
||||
|
||||
|
||||
// Manual Control
|
||||
void nextFrame();
|
||||
void previousFrame();
|
||||
|
||||
/**
|
||||
* Switch without transition to frame `frame`.
|
||||
*/
|
||||
void switchToFrame(uint8_t frame);
|
||||
|
||||
/**
|
||||
* Transition to frame `frame`, when the `frame` number is bigger than the current
|
||||
* frame the forward animation will be used, otherwise the backwards animation is used.
|
||||
*/
|
||||
void transitionToFrame(uint8_t frame);
|
||||
|
||||
// State Info
|
||||
OLEDDisplayUiState* getUiState();
|
||||
|
||||
int16_t update();
|
||||
};
|
||||
#endif
|
||||
39
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/src/SH1106.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
|
||||
* Copyright (c) 2018 by Fabrice Weinberg
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* ThingPulse invests considerable time and money to develop these open source libraries.
|
||||
* Please support us by buying our products (and not the clones) from
|
||||
* https://thingpulse.com
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SH1106_h
|
||||
#define SH1106_h
|
||||
#include "SH1106Wire.h"
|
||||
|
||||
// For make SH1106 an alias for SH1106Wire
|
||||
typedef SH1106Wire SH1106;
|
||||
|
||||
|
||||
#endif
|
||||
141
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/src/SH1106Brzo.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
|
||||
* Copyright (c) 2018 by Fabrice Weinberg
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* ThingPulse invests considerable time and money to develop these open source libraries.
|
||||
* Please support us by buying our products (and not the clones) from
|
||||
* https://thingpulse.com
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SH1106Brzo_h
|
||||
#define SH1106Brzo_h
|
||||
|
||||
#include "OLEDDisplay.h"
|
||||
#include <brzo_i2c.h>
|
||||
|
||||
#if F_CPU == 160000000L
|
||||
#define BRZO_I2C_SPEED 1000
|
||||
#else
|
||||
#define BRZO_I2C_SPEED 800
|
||||
#endif
|
||||
|
||||
class SH1106Brzo : public OLEDDisplay {
|
||||
private:
|
||||
uint8_t _address;
|
||||
uint8_t _sda;
|
||||
uint8_t _scl;
|
||||
|
||||
public:
|
||||
SH1106Brzo(uint8_t _address, uint8_t _sda, uint8_t _scl, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64) {
|
||||
setGeometry(g);
|
||||
|
||||
this->_address = _address;
|
||||
this->_sda = _sda;
|
||||
this->_scl = _scl;
|
||||
}
|
||||
|
||||
bool connect(){
|
||||
brzo_i2c_setup(_sda, _scl, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void display(void) {
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t minBoundY = UINT8_MAX;
|
||||
uint8_t maxBoundY = 0;
|
||||
|
||||
uint8_t minBoundX = UINT8_MAX;
|
||||
uint8_t maxBoundX = 0;
|
||||
uint8_t x, y;
|
||||
|
||||
// Calculate the Y bounding box of changes
|
||||
// and copy buffer[pos] to buffer_back[pos];
|
||||
for (y = 0; y < (displayHeight / 8); y++) {
|
||||
for (x = 0; x < displayWidth; x++) {
|
||||
uint16_t pos = x + y * displayWidth;
|
||||
if (buffer[pos] != buffer_back[pos]) {
|
||||
minBoundY = _min(minBoundY, y);
|
||||
maxBoundY = _max(maxBoundY, y);
|
||||
minBoundX = _min(minBoundX, x);
|
||||
maxBoundX = _max(maxBoundX, x);
|
||||
}
|
||||
buffer_back[pos] = buffer[pos];
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
// If the minBoundY wasn't updated
|
||||
// we can savely assume that buffer_back[pos] == buffer[pos]
|
||||
// holdes true for all values of pos
|
||||
if (minBoundY == UINT8_MAX) return;
|
||||
|
||||
byte k = 0;
|
||||
uint8_t sendBuffer[17];
|
||||
sendBuffer[0] = 0x40;
|
||||
|
||||
// Calculate the colum offset
|
||||
uint8_t minBoundXp2H = (minBoundX + 2) & 0x0F;
|
||||
uint8_t minBoundXp2L = 0x10 | ((minBoundX + 2) >> 4 );
|
||||
|
||||
brzo_i2c_start_transaction(this->_address, BRZO_I2C_SPEED);
|
||||
|
||||
for (y = minBoundY; y <= maxBoundY; y++) {
|
||||
sendCommand(0xB0 + y);
|
||||
sendCommand(minBoundXp2H);
|
||||
sendCommand(minBoundXp2L);
|
||||
for (x = minBoundX; x <= maxBoundX; x++) {
|
||||
k++;
|
||||
sendBuffer[k] = buffer[x + y * displayWidth];
|
||||
if (k == 16) {
|
||||
brzo_i2c_write(sendBuffer, 17, true);
|
||||
k = 0;
|
||||
}
|
||||
}
|
||||
if (k != 0) {
|
||||
brzo_i2c_write(sendBuffer, k + 1, true);
|
||||
k = 0;
|
||||
}
|
||||
yield();
|
||||
}
|
||||
if (k != 0) {
|
||||
brzo_i2c_write(sendBuffer, k + 1, true);
|
||||
}
|
||||
brzo_i2c_end_transaction();
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
int getBufferOffset(void) {
|
||||
return 0;
|
||||
}
|
||||
inline void sendCommand(uint8_t com) __attribute__((always_inline)){
|
||||
uint8_t command[2] = {0x80 /* command mode */, com};
|
||||
brzo_i2c_start_transaction(_address, BRZO_I2C_SPEED);
|
||||
brzo_i2c_write(command, 2, true);
|
||||
brzo_i2c_end_transaction();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
135
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/src/SH1106Spi.h
Normal file
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
|
||||
* Copyright (c) 2018 by Fabrice Weinberg
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* ThingPulse invests considerable time and money to develop these open source libraries.
|
||||
* Please support us by buying our products (and not the clones) from
|
||||
* https://thingpulse.com
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SH1106Spi_h
|
||||
#define SH1106Spi_h
|
||||
|
||||
#include "OLEDDisplay.h"
|
||||
#include <SPI.h>
|
||||
|
||||
class SH1106Spi : public OLEDDisplay {
|
||||
private:
|
||||
uint8_t _rst;
|
||||
uint8_t _dc;
|
||||
|
||||
public:
|
||||
SH1106Spi(uint8_t _rst, uint8_t _dc, uint8_t _cs, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64) {
|
||||
setGeometry(g);
|
||||
|
||||
this->_rst = _rst;
|
||||
this->_dc = _dc;
|
||||
}
|
||||
|
||||
bool connect(){
|
||||
pinMode(_dc, OUTPUT);
|
||||
pinMode(_rst, OUTPUT);
|
||||
|
||||
SPI.begin ();
|
||||
SPI.setClockDivider (SPI_CLOCK_DIV2);
|
||||
|
||||
// Pulse Reset low for 10ms
|
||||
digitalWrite(_rst, HIGH);
|
||||
delay(1);
|
||||
digitalWrite(_rst, LOW);
|
||||
delay(10);
|
||||
digitalWrite(_rst, HIGH);
|
||||
return true;
|
||||
}
|
||||
|
||||
void display(void) {
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t minBoundY = UINT8_MAX;
|
||||
uint8_t maxBoundY = 0;
|
||||
|
||||
uint8_t minBoundX = UINT8_MAX;
|
||||
uint8_t maxBoundX = 0;
|
||||
|
||||
uint8_t x, y;
|
||||
|
||||
// Calculate the Y bounding box of changes
|
||||
// and copy buffer[pos] to buffer_back[pos];
|
||||
for (y = 0; y < (displayHeight / 8); y++) {
|
||||
for (x = 0; x < displayWidth; x++) {
|
||||
uint16_t pos = x + y * displayWidth;
|
||||
if (buffer[pos] != buffer_back[pos]) {
|
||||
minBoundY = _min(minBoundY, y);
|
||||
maxBoundY = _max(maxBoundY, y);
|
||||
minBoundX = _min(minBoundX, x);
|
||||
maxBoundX = _max(maxBoundX, x);
|
||||
}
|
||||
buffer_back[pos] = buffer[pos];
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
// If the minBoundY wasn't updated
|
||||
// we can savely assume that buffer_back[pos] == buffer[pos]
|
||||
// holdes true for all values of pos
|
||||
if (minBoundY == UINT8_MAX) return;
|
||||
|
||||
// Calculate the colum offset
|
||||
uint8_t minBoundXp2H = (minBoundX + 2) & 0x0F;
|
||||
uint8_t minBoundXp2L = 0x10 | ((minBoundX + 2) >> 4 );
|
||||
|
||||
for (y = minBoundY; y <= maxBoundY; y++) {
|
||||
sendCommand(0xB0 + y);
|
||||
sendCommand(minBoundXp2H);
|
||||
sendCommand(minBoundXp2L);
|
||||
digitalWrite(_dc, HIGH); // data mode
|
||||
for (x = minBoundX; x <= maxBoundX; x++) {
|
||||
SPI.transfer(buffer[x + y * displayWidth]);
|
||||
}
|
||||
yield();
|
||||
}
|
||||
#else
|
||||
for (uint8_t y=0; y<displayHeight/8; y++) {
|
||||
sendCommand(0xB0 + y);
|
||||
sendCommand(0x02);
|
||||
sendCommand(0x10);
|
||||
digitalWrite(_dc, HIGH); // data mode
|
||||
for( uint8_t x=0; x < displayWidth; x++) {
|
||||
SPI.transfer(buffer[x + y * displayWidth]);
|
||||
}
|
||||
yield();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
int getBufferOffset(void) {
|
||||
return 0;
|
||||
}
|
||||
inline void sendCommand(uint8_t com) __attribute__((always_inline)){
|
||||
digitalWrite(_dc, LOW);
|
||||
SPI.transfer(com);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
205
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/src/SH1106Wire.h
Normal file
@@ -0,0 +1,205 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
|
||||
* Copyright (c) 2018 by Fabrice Weinberg
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* ThingPulse invests considerable time and money to develop these open source libraries.
|
||||
* Please support us by buying our products (and not the clones) from
|
||||
* https://thingpulse.com
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SH1106Wire_h
|
||||
#define SH1106Wire_h
|
||||
|
||||
#include "OLEDDisplay.h"
|
||||
#include <Wire.h>
|
||||
|
||||
#define SH1106_SET_PUMP_VOLTAGE 0X30
|
||||
#define SH1106_SET_PUMP_MODE 0XAD
|
||||
#define SH1106_PUMP_ON 0X8B
|
||||
#define SH1106_PUMP_OFF 0X8A
|
||||
//--------------------------------------
|
||||
|
||||
class SH1106Wire : public OLEDDisplay {
|
||||
private:
|
||||
uint8_t _address;
|
||||
uint8_t _sda;
|
||||
uint8_t _scl;
|
||||
bool _doI2cAutoInit = false;
|
||||
TwoWire* _wire = NULL;
|
||||
int _frequency;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create and initialize the Display using Wire library
|
||||
*
|
||||
* Beware for retro-compatibility default values are provided for all parameters see below.
|
||||
* Please note that if you don't wan't SD1306Wire to initialize and change frequency speed ot need to
|
||||
* ensure -1 value are specified for all 3 parameters. This can be usefull to control TwoWire with multiple
|
||||
* device on the same bus.
|
||||
*
|
||||
* @param _address I2C Display address
|
||||
* @param _sda I2C SDA pin number, default to -1 to skip Wire begin call
|
||||
* @param _scl I2C SCL pin number, default to -1 (only SDA = -1 is considered to skip Wire begin call)
|
||||
* @param g display geometry dafault to generic GEOMETRY_128_64, see OLEDDISPLAY_GEOMETRY definition for other options
|
||||
* @param _i2cBus on ESP32 with 2 I2C HW buses, I2C_ONE for 1st Bus, I2C_TWO fot 2nd bus, default I2C_ONE
|
||||
* @param _frequency for Frequency by default Let's use ~700khz if ESP8266 is in 160Mhz mode, this will be limited to ~400khz if the ESP8266 in 80Mhz mode
|
||||
*/
|
||||
SH1106Wire(uint8_t _address, uint8_t _sda, uint8_t _scl, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64, HW_I2C _i2cBus = I2C_ONE, int _frequency = 700000) {
|
||||
setGeometry(g);
|
||||
|
||||
this->_address = _address;
|
||||
this->_sda = _sda;
|
||||
this->_scl = _scl;
|
||||
#if !defined(ARDUINO_ARCH_ESP32)
|
||||
this->_wire = &Wire;
|
||||
#else
|
||||
this->_wire = (_i2cBus==I2C_ONE) ? &Wire : &Wire1;
|
||||
#endif
|
||||
this->_frequency = _frequency;
|
||||
}
|
||||
|
||||
bool connect() {
|
||||
#if !defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_ARCH8266)
|
||||
_wire->begin();
|
||||
#else
|
||||
// On ESP32 arduino, -1 means 'don't change pins', someone else has called begin for us.
|
||||
if(this->_sda != -1)
|
||||
_wire->begin(this->_sda, this->_scl);
|
||||
#endif
|
||||
// Let's use ~700khz if ESP8266 is in 160Mhz mode
|
||||
// this will be limited to ~400khz if the ESP8266 in 80Mhz mode.
|
||||
if(this->_frequency != -1)
|
||||
_wire->setClock(this->_frequency);
|
||||
return true;
|
||||
}
|
||||
|
||||
void display(void) {
|
||||
initI2cIfNeccesary();
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t minBoundY = UINT8_MAX;
|
||||
uint8_t maxBoundY = 0;
|
||||
|
||||
uint8_t minBoundX = UINT8_MAX;
|
||||
uint8_t maxBoundX = 0;
|
||||
|
||||
uint8_t x, y;
|
||||
|
||||
// Calculate the Y bounding box of changes
|
||||
// and copy buffer[pos] to buffer_back[pos];
|
||||
for (y = 0; y < (displayHeight / 8); y++) {
|
||||
for (x = 0; x < displayWidth; x++) {
|
||||
uint16_t pos = x + y * displayWidth;
|
||||
if (buffer[pos] != buffer_back[pos]) {
|
||||
minBoundY = _min(minBoundY, y);
|
||||
maxBoundY = _max(maxBoundY, y);
|
||||
minBoundX = _min(minBoundX, x);
|
||||
maxBoundX = _max(maxBoundX, x);
|
||||
}
|
||||
buffer_back[pos] = buffer[pos];
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
// If the minBoundY wasn't updated
|
||||
// we can savely assume that buffer_back[pos] == buffer[pos]
|
||||
// holdes true for all values of pos
|
||||
if (minBoundY == UINT8_MAX) return;
|
||||
|
||||
// Calculate the colum offset
|
||||
uint8_t minBoundXp2H = (minBoundX + 2) & 0x0F;
|
||||
uint8_t minBoundXp2L = 0x10 | ((minBoundX + 2) >> 4 );
|
||||
|
||||
byte k = 0;
|
||||
for (y = minBoundY; y <= maxBoundY; y++) {
|
||||
sendCommand(0xB0 + y);
|
||||
sendCommand(minBoundXp2H);
|
||||
sendCommand(minBoundXp2L);
|
||||
for (x = minBoundX; x <= maxBoundX; x++) {
|
||||
if (k == 0) {
|
||||
_wire->beginTransmission(_address);
|
||||
_wire->write(0x40);
|
||||
}
|
||||
_wire->write(buffer[x + y * displayWidth]);
|
||||
k++;
|
||||
if (k == 16) {
|
||||
_wire->endTransmission();
|
||||
k = 0;
|
||||
}
|
||||
}
|
||||
if (k != 0) {
|
||||
_wire->endTransmission();
|
||||
k = 0;
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
if (k != 0) {
|
||||
_wire->endTransmission();
|
||||
}
|
||||
#else
|
||||
uint8_t * p = &buffer[0];
|
||||
for (uint8_t y=0; y<8; y++) {
|
||||
sendCommand(0xB0+y);
|
||||
sendCommand(0x02);
|
||||
sendCommand(0x10);
|
||||
for( uint8_t x=0; x<8; x++) {
|
||||
_wire->beginTransmission(_address);
|
||||
_wire->write(0x40);
|
||||
for (uint8_t k = 0; k < 16; k++) {
|
||||
_wire->write(*p++);
|
||||
}
|
||||
_wire->endTransmission();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void setI2cAutoInit(bool doI2cAutoInit) {
|
||||
_doI2cAutoInit = doI2cAutoInit;
|
||||
}
|
||||
|
||||
private:
|
||||
int getBufferOffset(void) {
|
||||
return 0;
|
||||
}
|
||||
inline void sendCommand(uint8_t command) __attribute__((always_inline)){
|
||||
_wire->beginTransmission(_address);
|
||||
_wire->write(0x80);
|
||||
_wire->write(command);
|
||||
_wire->endTransmission();
|
||||
}
|
||||
|
||||
void initI2cIfNeccesary() {
|
||||
if (_doI2cAutoInit) {
|
||||
#ifdef ARDUINO_ARCH_AVR
|
||||
_wire->begin();
|
||||
#else
|
||||
_wire->begin(this->_sda, this->_scl);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
39
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/src/SSD1306.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
|
||||
* Copyright (c) 2018 by Fabrice Weinberg
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* ThingPulse invests considerable time and money to develop these open source libraries.
|
||||
* Please support us by buying our products (and not the clones) from
|
||||
* https://thingpulse.com
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SSD1306_h
|
||||
#define SSD1306_h
|
||||
#include "SSD1306Wire.h"
|
||||
|
||||
// For legacy support make SSD1306 an alias for SSD1306
|
||||
typedef SSD1306Wire SSD1306;
|
||||
|
||||
|
||||
#endif
|
||||
167
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/src/SSD1306Brzo.h
Normal file
@@ -0,0 +1,167 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
|
||||
* Copyright (c) 2018 by Fabrice Weinberg
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* ThingPulse invests considerable time and money to develop these open source libraries.
|
||||
* Please support us by buying our products (and not the clones) from
|
||||
* https://thingpulse.com
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SSD1306Brzo_h
|
||||
#define SSD1306Brzo_h
|
||||
|
||||
#include "OLEDDisplay.h"
|
||||
#include <brzo_i2c.h>
|
||||
|
||||
#if F_CPU == 160000000L
|
||||
#define BRZO_I2C_SPEED 1000
|
||||
#else
|
||||
#define BRZO_I2C_SPEED 800
|
||||
#endif
|
||||
|
||||
class SSD1306Brzo : public OLEDDisplay {
|
||||
private:
|
||||
uint8_t _address;
|
||||
uint8_t _sda;
|
||||
uint8_t _scl;
|
||||
|
||||
public:
|
||||
SSD1306Brzo(uint8_t _address, uint8_t _sda, uint8_t _scl, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64) {
|
||||
setGeometry(g);
|
||||
|
||||
this->_address = _address;
|
||||
this->_sda = _sda;
|
||||
this->_scl = _scl;
|
||||
}
|
||||
|
||||
bool connect(){
|
||||
brzo_i2c_setup(_sda, _scl, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void display(void) {
|
||||
const int x_offset = (128 - this->width()) / 2;
|
||||
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t minBoundY = UINT8_MAX;
|
||||
uint8_t maxBoundY = 0;
|
||||
|
||||
uint8_t minBoundX = UINT8_MAX;
|
||||
uint8_t maxBoundX = 0;
|
||||
|
||||
uint8_t x, y;
|
||||
|
||||
// Calculate the Y bounding box of changes
|
||||
// and copy buffer[pos] to buffer_back[pos];
|
||||
for (y = 0; y < (this->height() / 8); y++) {
|
||||
for (x = 0; x < this->width(); x++) {
|
||||
uint16_t pos = x + y * this->width();
|
||||
if (buffer[pos] != buffer_back[pos]) {
|
||||
minBoundY = _min(minBoundY, y);
|
||||
maxBoundY = _max(maxBoundY, y);
|
||||
minBoundX = _min(minBoundX, x);
|
||||
maxBoundX = _max(maxBoundX, x);
|
||||
}
|
||||
buffer_back[pos] = buffer[pos];
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
// If the minBoundY wasn't updated
|
||||
// we can savely assume that buffer_back[pos] == buffer[pos]
|
||||
// holdes true for all values of pos
|
||||
if (minBoundY == UINT8_MAX) return;
|
||||
|
||||
sendCommand(COLUMNADDR);
|
||||
sendCommand(x_offset + minBoundX);
|
||||
sendCommand(x_offset + maxBoundX);
|
||||
|
||||
sendCommand(PAGEADDR);
|
||||
sendCommand(minBoundY);
|
||||
sendCommand(maxBoundY);
|
||||
|
||||
byte k = 0;
|
||||
|
||||
int buflen = ( this->width() / 8 ) + 1;
|
||||
|
||||
uint8_t sendBuffer[buflen];
|
||||
sendBuffer[0] = 0x40;
|
||||
brzo_i2c_start_transaction(this->_address, BRZO_I2C_SPEED);
|
||||
for (y = minBoundY; y <= maxBoundY; y++) {
|
||||
for (x = minBoundX; x <= maxBoundX; x++) {
|
||||
k++;
|
||||
sendBuffer[k] = buffer[x + y * this->width()];
|
||||
if (k == (buflen-1)) {
|
||||
brzo_i2c_write(sendBuffer, buflen, true);
|
||||
k = 0;
|
||||
}
|
||||
}
|
||||
yield();
|
||||
}
|
||||
brzo_i2c_write(sendBuffer, k + 1, true);
|
||||
brzo_i2c_end_transaction();
|
||||
#else
|
||||
// No double buffering
|
||||
sendCommand(COLUMNADDR);
|
||||
|
||||
sendCommand(x_offset);
|
||||
sendCommand(x_offset + (this->width() - 1));
|
||||
|
||||
sendCommand(PAGEADDR);
|
||||
sendCommand(0x0);
|
||||
sendCommand((this->height() / 8) - 1);
|
||||
|
||||
int buflen = ( this->width() / 8 ) + 1;
|
||||
|
||||
uint8_t sendBuffer[buflen];
|
||||
sendBuffer[0] = 0x40;
|
||||
|
||||
brzo_i2c_start_transaction(this->_address, BRZO_I2C_SPEED);
|
||||
|
||||
for (uint16_t i=0; i<displayBufferSize; i++) {
|
||||
for (uint8_t x=1; x<buflen; x++) {
|
||||
sendBuffer[x] = buffer[i];
|
||||
i++;
|
||||
}
|
||||
i--;
|
||||
brzo_i2c_write(sendBuffer, buflen, true);
|
||||
yield();
|
||||
}
|
||||
brzo_i2c_end_transaction();
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
int getBufferOffset(void) {
|
||||
return 0;
|
||||
}
|
||||
inline void sendCommand(uint8_t com) __attribute__((always_inline)){
|
||||
uint8_t command[2] = {0x80 /* command mode */, com};
|
||||
brzo_i2c_start_transaction(_address, BRZO_I2C_SPEED);
|
||||
brzo_i2c_write(command, 2, true);
|
||||
brzo_i2c_end_transaction();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
152
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/src/SSD1306I2C.h
Normal file
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 by Helmut Tschemernjak - www.radioshuttle.de
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* ThingPulse invests considerable time and money to develop these open source libraries.
|
||||
* Please support us by buying our products (and not the clones) from
|
||||
* https://thingpulse.com
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SSD1306I2C_h
|
||||
#define SSD1306I2C_h
|
||||
|
||||
|
||||
#ifdef __MBED__
|
||||
|
||||
#include "OLEDDisplay.h"
|
||||
#include <mbed.h>
|
||||
|
||||
#ifndef UINT8_MAX
|
||||
#define UINT8_MAX 0xff
|
||||
#endif
|
||||
|
||||
class SSD1306I2C : public OLEDDisplay {
|
||||
public:
|
||||
SSD1306I2C(uint8_t _address, PinName _sda, PinName _scl, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64) {
|
||||
setGeometry(g);
|
||||
|
||||
this->_address = _address << 1; // convert from 7 to 8 bit for mbed.
|
||||
this->_sda = _sda;
|
||||
this->_scl = _scl;
|
||||
_i2c = new I2C(_sda, _scl);
|
||||
}
|
||||
|
||||
bool connect() {
|
||||
// mbed supports 100k and 400k some device maybe 1000k
|
||||
#ifdef TARGET_STM32L4
|
||||
_i2c->frequency(1000000);
|
||||
#else
|
||||
_i2c->frequency(400000);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void display(void) {
|
||||
const int x_offset = (128 - this->width()) / 2;
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t minBoundY = UINT8_MAX;
|
||||
uint8_t maxBoundY = 0;
|
||||
|
||||
uint8_t minBoundX = UINT8_MAX;
|
||||
uint8_t maxBoundX = 0;
|
||||
uint8_t x, y;
|
||||
|
||||
// Calculate the Y bounding box of changes
|
||||
// and copy buffer[pos] to buffer_back[pos];
|
||||
for (y = 0; y < (this->height() / 8); y++) {
|
||||
for (x = 0; x < this->width(); x++) {
|
||||
uint16_t pos = x + y * this->width();
|
||||
if (buffer[pos] != buffer_back[pos]) {
|
||||
minBoundY = std::min(minBoundY, y);
|
||||
maxBoundY = std::max(maxBoundY, y);
|
||||
minBoundX = std::min(minBoundX, x);
|
||||
maxBoundX = std::max(maxBoundX, x);
|
||||
}
|
||||
buffer_back[pos] = buffer[pos];
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
// If the minBoundY wasn't updated
|
||||
// we can savely assume that buffer_back[pos] == buffer[pos]
|
||||
// holdes true for all values of pos
|
||||
|
||||
if (minBoundY == UINT8_MAX) return;
|
||||
|
||||
sendCommand(COLUMNADDR);
|
||||
sendCommand(x_offset + minBoundX); // column start address (0 = reset)
|
||||
sendCommand(x_offset + maxBoundX); // column end address (127 = reset)
|
||||
|
||||
sendCommand(PAGEADDR);
|
||||
sendCommand(minBoundY); // page start address
|
||||
sendCommand(maxBoundY); // page end address
|
||||
|
||||
for (y = minBoundY; y <= maxBoundY; y++) {
|
||||
uint8_t *start = &buffer[(minBoundX + y * this->width())-1];
|
||||
uint8_t save = *start;
|
||||
|
||||
*start = 0x40; // control
|
||||
_i2c->write(_address, (char *)start, (maxBoundX-minBoundX) + 1 + 1);
|
||||
*start = save;
|
||||
}
|
||||
#else
|
||||
|
||||
sendCommand(COLUMNADDR);
|
||||
sendCommand(x_offset); // column start address (0 = reset)
|
||||
sendCommand(x_offset + (this->width() - 1));// column end address (127 = reset)
|
||||
|
||||
sendCommand(PAGEADDR);
|
||||
sendCommand(0x0); // page start address (0 = reset)
|
||||
|
||||
if (geometry == GEOMETRY_128_64) {
|
||||
sendCommand(0x7);
|
||||
} else if (geometry == GEOMETRY_128_32) {
|
||||
sendCommand(0x3);
|
||||
}
|
||||
|
||||
buffer[-1] = 0x40; // control
|
||||
_i2c->write(_address, (char *)&buffer[-1], displayBufferSize + 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
int getBufferOffset(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void sendCommand(uint8_t command) __attribute__((always_inline)) {
|
||||
char _data[2];
|
||||
_data[0] = 0x80; // control
|
||||
_data[1] = command;
|
||||
_i2c->write(_address, _data, sizeof(_data));
|
||||
}
|
||||
|
||||
uint8_t _address;
|
||||
PinName _sda;
|
||||
PinName _scl;
|
||||
I2C *_i2c;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
163
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/src/SSD1306Spi.h
Normal file
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
|
||||
* Copyright (c) 2018 by Fabrice Weinberg
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* ThingPulse invests considerable time and money to develop these open source libraries.
|
||||
* Please support us by buying our products (and not the clones) from
|
||||
* https://thingpulse.com
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SSD1306Spi_h
|
||||
#define SSD1306Spi_h
|
||||
|
||||
#include "OLEDDisplay.h"
|
||||
#include <SPI.h>
|
||||
|
||||
#if F_CPU == 160000000L
|
||||
#define BRZO_I2C_SPEED 1000
|
||||
#else
|
||||
#define BRZO_I2C_SPEED 800
|
||||
#endif
|
||||
|
||||
class SSD1306Spi : public OLEDDisplay {
|
||||
private:
|
||||
uint8_t _rst;
|
||||
uint8_t _dc;
|
||||
uint8_t _cs;
|
||||
|
||||
public:
|
||||
SSD1306Spi(uint8_t _rst, uint8_t _dc, uint8_t _cs, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64) {
|
||||
setGeometry(g);
|
||||
|
||||
this->_rst = _rst;
|
||||
this->_dc = _dc;
|
||||
this->_cs = _cs;
|
||||
}
|
||||
|
||||
bool connect(){
|
||||
pinMode(_dc, OUTPUT);
|
||||
pinMode(_cs, OUTPUT);
|
||||
pinMode(_rst, OUTPUT);
|
||||
|
||||
SPI.begin ();
|
||||
SPI.setClockDivider (SPI_CLOCK_DIV2);
|
||||
|
||||
// Pulse Reset low for 10ms
|
||||
digitalWrite(_rst, HIGH);
|
||||
delay(1);
|
||||
digitalWrite(_rst, LOW);
|
||||
delay(10);
|
||||
digitalWrite(_rst, HIGH);
|
||||
return true;
|
||||
}
|
||||
|
||||
void display(void) {
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t minBoundY = UINT8_MAX;
|
||||
uint8_t maxBoundY = 0;
|
||||
|
||||
uint8_t minBoundX = UINT8_MAX;
|
||||
uint8_t maxBoundX = 0;
|
||||
|
||||
uint8_t x, y;
|
||||
|
||||
// Calculate the Y bounding box of changes
|
||||
// and copy buffer[pos] to buffer_back[pos];
|
||||
for (y = 0; y < (displayHeight / 8); y++) {
|
||||
for (x = 0; x < displayWidth; x++) {
|
||||
uint16_t pos = x + y * displayWidth;
|
||||
if (buffer[pos] != buffer_back[pos]) {
|
||||
minBoundY = _min(minBoundY, y);
|
||||
maxBoundY = _max(maxBoundY, y);
|
||||
minBoundX = _min(minBoundX, x);
|
||||
maxBoundX = _max(maxBoundX, x);
|
||||
}
|
||||
buffer_back[pos] = buffer[pos];
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
// If the minBoundY wasn't updated
|
||||
// we can savely assume that buffer_back[pos] == buffer[pos]
|
||||
// holdes true for all values of pos
|
||||
if (minBoundY == UINT8_MAX) return;
|
||||
|
||||
sendCommand(COLUMNADDR);
|
||||
sendCommand(minBoundX);
|
||||
sendCommand(maxBoundX);
|
||||
|
||||
sendCommand(PAGEADDR);
|
||||
sendCommand(minBoundY);
|
||||
sendCommand(maxBoundY);
|
||||
|
||||
digitalWrite(_cs, HIGH);
|
||||
digitalWrite(_dc, HIGH); // data mode
|
||||
digitalWrite(_cs, LOW);
|
||||
for (y = minBoundY; y <= maxBoundY; y++) {
|
||||
for (x = minBoundX; x <= maxBoundX; x++) {
|
||||
SPI.transfer(buffer[x + y * displayWidth]);
|
||||
}
|
||||
yield();
|
||||
}
|
||||
digitalWrite(_cs, HIGH);
|
||||
#else
|
||||
// No double buffering
|
||||
sendCommand(COLUMNADDR);
|
||||
sendCommand(0x0);
|
||||
sendCommand(0x7F);
|
||||
|
||||
sendCommand(PAGEADDR);
|
||||
sendCommand(0x0);
|
||||
|
||||
if (geometry == GEOMETRY_128_64 || geometry == GEOMETRY_64_48 || geometry == GEOMETRY_64_32 ) {
|
||||
sendCommand(0x7);
|
||||
} else if (geometry == GEOMETRY_128_32) {
|
||||
sendCommand(0x3);
|
||||
}
|
||||
|
||||
digitalWrite(_cs, HIGH);
|
||||
digitalWrite(_dc, HIGH); // data mode
|
||||
digitalWrite(_cs, LOW);
|
||||
for (uint16_t i=0; i<displayBufferSize; i++) {
|
||||
SPI.transfer(buffer[i]);
|
||||
yield();
|
||||
}
|
||||
digitalWrite(_cs, HIGH);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
int getBufferOffset(void) {
|
||||
return 0;
|
||||
}
|
||||
inline void sendCommand(uint8_t com) __attribute__((always_inline)){
|
||||
digitalWrite(_cs, HIGH);
|
||||
digitalWrite(_dc, LOW);
|
||||
digitalWrite(_cs, LOW);
|
||||
SPI.transfer(com);
|
||||
digitalWrite(_cs, HIGH);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
211
P1_gateway_FW/lib/esp8266-oled-ssd1306-4.2.0/src/SSD1306Wire.h
Normal file
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
|
||||
* Copyright (c) 2018 by Fabrice Weinberg
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* ThingPulse invests considerable time and money to develop these open source libraries.
|
||||
* Please support us by buying our products (and not the clones) from
|
||||
* https://thingpulse.com
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SSD1306Wire_h
|
||||
#define SSD1306Wire_h
|
||||
|
||||
#include "OLEDDisplay.h"
|
||||
#include <Wire.h>
|
||||
#include <algorithm>
|
||||
|
||||
#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_STM32)
|
||||
#define _min min
|
||||
#define _max max
|
||||
#endif
|
||||
//--------------------------------------
|
||||
|
||||
class SSD1306Wire : public OLEDDisplay {
|
||||
private:
|
||||
uint8_t _address;
|
||||
int _sda;
|
||||
int _scl;
|
||||
bool _doI2cAutoInit = false;
|
||||
TwoWire* _wire = NULL;
|
||||
int _frequency;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Create and initialize the Display using Wire library
|
||||
*
|
||||
* Beware for retro-compatibility default values are provided for all parameters see below.
|
||||
* Please note that if you don't wan't SD1306Wire to initialize and change frequency speed ot need to
|
||||
* ensure -1 value are specified for all 3 parameters. This can be usefull to control TwoWire with multiple
|
||||
* device on the same bus.
|
||||
*
|
||||
* @param _address I2C Display address
|
||||
* @param _sda I2C SDA pin number, default to -1 to skip Wire begin call
|
||||
* @param _scl I2C SCL pin number, default to -1 (only SDA = -1 is considered to skip Wire begin call)
|
||||
* @param g display geometry dafault to generic GEOMETRY_128_64, see OLEDDISPLAY_GEOMETRY definition for other options
|
||||
* @param _i2cBus on ESP32 with 2 I2C HW buses, I2C_ONE for 1st Bus, I2C_TWO fot 2nd bus, default I2C_ONE
|
||||
* @param _frequency for Frequency by default Let's use ~700khz if ESP8266 is in 160Mhz mode, this will be limited to ~400khz if the ESP8266 in 80Mhz mode
|
||||
*/
|
||||
SSD1306Wire(uint8_t _address, int _sda = -1, int _scl = -1, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_32, HW_I2C _i2cBus = I2C_ONE, int _frequency = 700000) {
|
||||
setGeometry(g);
|
||||
|
||||
this->_address = _address;
|
||||
this->_sda = _sda;
|
||||
this->_scl = _scl;
|
||||
#if !defined(ARDUINO_ARCH_ESP32)
|
||||
this->_wire = &Wire;
|
||||
#else
|
||||
this->_wire = (_i2cBus==I2C_ONE) ? &Wire : &Wire1;
|
||||
#endif
|
||||
this->_frequency = _frequency;
|
||||
}
|
||||
|
||||
bool connect() {
|
||||
#if !defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_ARCH_ESP8266)
|
||||
_wire->begin();
|
||||
#else
|
||||
// On ESP32 arduino, -1 means 'don't change pins', someone else has called begin for us.
|
||||
if(this->_sda != -1)
|
||||
_wire->begin(this->_sda, this->_scl);
|
||||
#endif
|
||||
// Let's use ~700khz if ESP8266 is in 160Mhz mode
|
||||
// this will be limited to ~400khz if the ESP8266 in 80Mhz mode.
|
||||
if(this->_frequency != -1)
|
||||
_wire->setClock(this->_frequency);
|
||||
return true;
|
||||
}
|
||||
|
||||
void display(void) {
|
||||
initI2cIfNeccesary();
|
||||
const int x_offset = (128 - this->width()) / 2;
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t minBoundY = UINT8_MAX;
|
||||
uint8_t maxBoundY = 0;
|
||||
|
||||
uint8_t minBoundX = UINT8_MAX;
|
||||
uint8_t maxBoundX = 0;
|
||||
uint8_t x, y;
|
||||
|
||||
// Calculate the Y bounding box of changes
|
||||
// and copy buffer[pos] to buffer_back[pos];
|
||||
for (y = 0; y < (this->height() / 8); y++) {
|
||||
for (x = 0; x < this->width(); x++) {
|
||||
uint16_t pos = x + y * this->width();
|
||||
if (buffer[pos] != buffer_back[pos]) {
|
||||
minBoundY = std::min(minBoundY, y);
|
||||
maxBoundY = std::max(maxBoundY, y);
|
||||
minBoundX = std::min(minBoundX, x);
|
||||
maxBoundX = std::max(maxBoundX, x);
|
||||
}
|
||||
buffer_back[pos] = buffer[pos];
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
// If the minBoundY wasn't updated
|
||||
// we can savely assume that buffer_back[pos] == buffer[pos]
|
||||
// holdes true for all values of pos
|
||||
|
||||
if (minBoundY == UINT8_MAX) return;
|
||||
|
||||
sendCommand(COLUMNADDR);
|
||||
sendCommand(x_offset + minBoundX);
|
||||
sendCommand(x_offset + maxBoundX);
|
||||
|
||||
sendCommand(PAGEADDR);
|
||||
sendCommand(minBoundY);
|
||||
sendCommand(maxBoundY);
|
||||
|
||||
byte k = 0;
|
||||
for (y = minBoundY; y <= maxBoundY; y++) {
|
||||
for (x = minBoundX; x <= maxBoundX; x++) {
|
||||
if (k == 0) {
|
||||
_wire->beginTransmission(_address);
|
||||
_wire->write(0x40);
|
||||
}
|
||||
|
||||
_wire->write(buffer[x + y * this->width()]);
|
||||
k++;
|
||||
if (k == 16) {
|
||||
_wire->endTransmission();
|
||||
k = 0;
|
||||
}
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
if (k != 0) {
|
||||
_wire->endTransmission();
|
||||
}
|
||||
#else
|
||||
|
||||
sendCommand(COLUMNADDR);
|
||||
sendCommand(x_offset);
|
||||
sendCommand(x_offset + (this->width() - 1));
|
||||
|
||||
sendCommand(PAGEADDR);
|
||||
sendCommand(0x0);
|
||||
|
||||
for (uint16_t i=0; i < displayBufferSize; i++) {
|
||||
_wire->beginTransmission(this->_address);
|
||||
_wire->write(0x40);
|
||||
for (uint8_t x = 0; x < 16; x++) {
|
||||
_wire->write(buffer[i]);
|
||||
i++;
|
||||
}
|
||||
i--;
|
||||
_wire->endTransmission();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void setI2cAutoInit(bool doI2cAutoInit) {
|
||||
_doI2cAutoInit = doI2cAutoInit;
|
||||
}
|
||||
|
||||
private:
|
||||
int getBufferOffset(void) {
|
||||
return 0;
|
||||
}
|
||||
inline void sendCommand(uint8_t command) __attribute__((always_inline)){
|
||||
initI2cIfNeccesary();
|
||||
_wire->beginTransmission(_address);
|
||||
_wire->write(0x80);
|
||||
_wire->write(command);
|
||||
_wire->endTransmission();
|
||||
}
|
||||
|
||||
void initI2cIfNeccesary() {
|
||||
if (_doI2cAutoInit) {
|
||||
#if !defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_ARCH_ESP8266)
|
||||
_wire->begin();
|
||||
#else
|
||||
_wire->begin(this->_sda, this->_scl);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||