update to esp8266-oled-ssd1306-4.0.0
@ -43,22 +43,26 @@
|
||||
#define TELNET_FEATURE
|
||||
|
||||
//WS_DATA_FEATURE: allow to connect serial from Websocket
|
||||
//#define WS_DATA_FEATURE
|
||||
#define WS_DATA_FEATURE
|
||||
|
||||
//DISPLAY_DEVICE: allow screen output
|
||||
//OLED_I2C_SSD1306 1
|
||||
//OLED_I2C_SSDSH1106 2
|
||||
//TFT_SPI_ILI9341_320X240 3
|
||||
//#define DISPLAY_DEVICE TFT_SPI_ILI9341_320X240
|
||||
#define DISPLAY_DEVICE OLED_I2C_SSD1306
|
||||
|
||||
#if defined (DISPLAY_DEVICE)
|
||||
//for ILI9143 edit User_Setup.h of TFT_eSPI library
|
||||
#if (DISPLAY_DEVICE == OLED_I2C_SSD1306) || (DISPLAY_DEVICE == OLED_I2C_SSDSH1106)
|
||||
#define DISPLAY_I2C_PIN_SDA 4
|
||||
#define DISPLAY_I2C_PIN_SCL 15
|
||||
#define DISPLAY_I2C_PIN_RST 16 //comment if not applicable
|
||||
#define DISPLAY_I2C_ADDR 0x3c
|
||||
#endif //(DISPLAY_DEVICE == OLED_I2C_SSD1306) || (DISPLAY_DEVICE == OLED_I2C_SSDSH1106)
|
||||
#define DISPLAY_FLIP_VERTICALY 1 //comment to disable
|
||||
#if DISPLAY_DEVICE == TFT_SPI_ILI9341_320X240
|
||||
#define DISPLAY_TOUCH_DRIVER XPT2046_SPI
|
||||
#endif //DISPLAY_DEVICE == TFT_SPI_ILI9341_320X240
|
||||
#endif //DISPLAY_DEVICE
|
||||
|
||||
//INPUT_DEVICE: allow input
|
||||
|
@ -28,13 +28,13 @@
|
||||
#include "Wire.h"
|
||||
#include "esp3d_logo.h"
|
||||
#if DISPLAY_DEVICE == OLED_I2C_SSD1306
|
||||
#include <SSD1306.h>
|
||||
SSD1306 esp3d_screen(DISPLAY_I2C_ADDR, DISPLAY_I2C_PIN_SDA, DISPLAY_I2C_PIN_SCL);
|
||||
#include <SSD1306Wire.h>
|
||||
SSD1306Wire esp3d_screen(DISPLAY_I2C_ADDR, DISPLAY_I2C_PIN_SDA, DISPLAY_I2C_PIN_SCL);
|
||||
#include "OLED_SSD1306.h"
|
||||
#endif //DISPLAY_DEVICE == OLED_I2C_SSD1306
|
||||
#if DISPLAY_DEVICE == OLED_I2C_SSDSH1106
|
||||
#include <SH1106.h>
|
||||
SH1106 esp3d_screen(DISPLAY_I2C_ADDR, (DISPLAY_I2C_PIN_SDA==-1)?SDA:DISPLAY_I2C_PIN_SDA, (DISPLAY_I2C_PIN_SCL==-1)?SCL:DISPLAY_I2C_PIN_SCL);
|
||||
#include <SH1106Wire.h>
|
||||
SH1106Wire esp3d_screen(DISPLAY_I2C_ADDR, (DISPLAY_I2C_PIN_SDA==-1)?SDA:DISPLAY_I2C_PIN_SDA, (DISPLAY_I2C_PIN_SCL==-1)?SCL:DISPLAY_I2C_PIN_SCL);
|
||||
#include "OLED_SSDSH1106.h"
|
||||
#endif //DISPLAY_DEVICE == OLED_I2C_SSDSH1106
|
||||
#endif //DISPLAY_DEVICE == OLED_I2C_SSD1306 || DISPLAY_DEVICE == OLED_I2C_SSDSH1106
|
||||
@ -127,9 +127,11 @@ bool Display::showStatus(bool force)
|
||||
refresh_status = true;
|
||||
status+=" ";
|
||||
//log_esp3d("current %s", status.c_str());
|
||||
if (status_shift > status.length()) {
|
||||
if (status_shift != -1){
|
||||
if( (uint16_t)(status_shift)> status.length()) {
|
||||
status_shift = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
//log_esp3d("shift %d", status_shift);
|
||||
if (status_shift > 0) {
|
||||
status.remove(0,status_shift);
|
||||
@ -202,8 +204,10 @@ bool Display::display_signal(bool force)
|
||||
static int label_shift = -1;
|
||||
label+=" ";
|
||||
//log_esp3d("current %s", label.c_str());
|
||||
if (label_shift > label.length()) {
|
||||
label_shift = -1;
|
||||
if (label_shift != -1) {
|
||||
if((uint16_t)(label_shift)> label.length()) {
|
||||
label_shift = -1;
|
||||
}
|
||||
}
|
||||
//log_esp3d("shift %d", label_shift);
|
||||
if (label_shift > 0) {
|
||||
@ -665,21 +669,21 @@ void Display::drawString(const char *string, int32_t poX, int32_t poY, int16_t c
|
||||
}
|
||||
|
||||
// Draw a XBM
|
||||
void Display::drawXbm(int16_t x, int16_t y, int16_t width, int16_t height, int16_t color, const unsigned char *xbm)
|
||||
void Display::drawXbm(int16_t x, int16_t y, int16_t width, int16_t height, int16_t color, const uint8_t *xbm)
|
||||
{
|
||||
if ( !ESP3DOutput::isOutput(ESP_SCREEN_CLIENT)) {
|
||||
return;
|
||||
}
|
||||
#if DISPLAY_DEVICE == OLED_I2C_SSD1306 || DISPLAY_DEVICE == OLED_I2C_SSDSH1106
|
||||
(void)color;
|
||||
esp3d_screen.drawXbm(x, y, width, height, (const char *)xbm);
|
||||
esp3d_screen.drawXbm(x, y, width, height, xbm);
|
||||
#endif //#if DISPLAY_DEVICE == OLED_I2C_SSD1306 || DISPLAY_DEVICE == OLED_I2C_SSDSH1106
|
||||
#if DISPLAY_DEVICE == TFT_SPI_ILI9341_320X240
|
||||
esp3d_screen.drawXBitmap(x, y, xbm, width, height,color);
|
||||
#endif //TFT_SPI_ILI9341_240X320
|
||||
}
|
||||
|
||||
void Display::drawXbm(int16_t x, int16_t y, int16_t width, int16_t height, uint16_t fgcolor, uint16_t bgcolor, const unsigned char *xbm)
|
||||
void Display::drawXbm(int16_t x, int16_t y, int16_t width, int16_t height, uint16_t fgcolor, uint16_t bgcolor, const uint8_t *xbm)
|
||||
{
|
||||
if ( !ESP3DOutput::isOutput(ESP_SCREEN_CLIENT)) {
|
||||
return;
|
||||
@ -687,7 +691,7 @@ void Display::drawXbm(int16_t x, int16_t y, int16_t width, int16_t height, uint1
|
||||
#if DISPLAY_DEVICE == OLED_I2C_SSD1306 || DISPLAY_DEVICE == OLED_I2C_SSDSH1106
|
||||
(void)fgcolor;
|
||||
(void)bgcolor;
|
||||
esp3d_screen.drawXbm(x, y, width, height, (const char *)xbm);
|
||||
esp3d_screen.drawXbm(x, y, width, height, xbm);
|
||||
#endif //#if DISPLAY_DEVICE == OLED_I2C_SSD1306 || DISPLAY_DEVICE == OLED_I2C_SSDSH1106
|
||||
#if DISPLAY_DEVICE == TFT_SPI_ILI9341_320X240
|
||||
esp3d_screen.drawXBitmap(x, y, xbm, width, height, fgcolor, bgcolor);
|
||||
|
@ -57,8 +57,8 @@ private:
|
||||
void fillRect(int16_t x, int16_t y, int16_t width, int16_t height, int16_t color);
|
||||
void setTextFont(uint8_t font);
|
||||
void drawString(const char *string, int32_t poX, int32_t poY, int16_t color);
|
||||
void drawXbm(int16_t x, int16_t y, int16_t width, int16_t height, int16_t color, const unsigned char *xbm);
|
||||
void drawXbm(int16_t x, int16_t y, int16_t width, int16_t height, uint16_t fgcolor, uint16_t bgcolor, const unsigned char *xbm);
|
||||
void drawXbm(int16_t x, int16_t y, int16_t width, int16_t height, int16_t color, const uint8_t *xbm);
|
||||
void drawXbm(int16_t x, int16_t y, int16_t width, int16_t height, uint16_t fgcolor, uint16_t bgcolor, const uint8_t *xbm);
|
||||
uint16_t getStringWidth(const char* text);
|
||||
String _status;
|
||||
};
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
#define ESP3D_Logo_width 62
|
||||
#define ESP3D_Logo_height 45
|
||||
const unsigned char ESP3D_Logo[] PROGMEM = {
|
||||
const uint8_t ESP3D_Logo[] PROGMEM = {
|
||||
0x00, 0x00, 0x00, 0xFE, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF,
|
||||
0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF,
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
#define ESP3D_Logo_width 200
|
||||
#define ESP3D_Logo_height 150
|
||||
const unsigned char ESP3D_Logo[] PROGMEM = {
|
||||
const uint8_t ESP3D_Logo[] PROGMEM = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
@ -14,6 +14,7 @@ env:
|
||||
- PLATFORMIO_CI_SRC=examples/SSD1306DrawingDemo
|
||||
- PLATFORMIO_CI_SRC=examples/SSD1306OTADemo
|
||||
- PLATFORMIO_CI_SRC=examples/SSD1306ClockDemo
|
||||
- PLATFORMIO_CI_SRC=examples/SSD1306TwoScreenDemo
|
||||
|
||||
|
||||
install:
|
@ -1,7 +1,8 @@
|
||||
esp8266-oled-ssd1306 [](https://travis-ci.org/squix78/esp8266-oled-ssd1306)
|
||||
============
|
||||
[](https://travis-ci.org/ThingPulse/esp8266-oled-ssd1306)
|
||||
|
||||
> We just released version 3.0.0. Please have a look at our [upgrade guide](UPGRADE-3.0.md)
|
||||
# ESP8266 OLED SSD1306
|
||||
|
||||
> We just released version 4.0.0. Please have a look at our [upgrade guide](UPGRADE-4.0.md)
|
||||
|
||||
This is a driver for the SSD1306 based 128x64 pixel OLED display running on the Arduino/ESP8266 platform.
|
||||
Can be used with either the I2C or SPI version of the display
|
||||
@ -14,17 +15,20 @@ platformio lib install 562
|
||||
```
|
||||
|
||||
## Credits
|
||||
|
||||
This library has initially been written by Daniel Eichhorn (@squix78). Many thanks go to Fabrice Weinberg (@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.
|
||||
The init sequence for the SSD1306 was inspired by Adafruit's library for the same display.
|
||||
|
||||
## Usage
|
||||
|
||||
Check out the examples folder for a few comprehensive demonstrations how to use the library. Also check out the ESP8266 Weather Station library (https://github.com/squix78/esp8266-weather-station) which uses the OLED library to display beautiful weather information.
|
||||
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
|
||||
@ -57,16 +61,16 @@ The library supports different protocols to access the OLED display. Currently t
|
||||
|
||||
```C++
|
||||
#include <Wire.h>
|
||||
#include "SSD1306.h"
|
||||
#include "SSD1306Wire.h"
|
||||
|
||||
SSD1306 display(ADDRESS, SDA, SDC);
|
||||
SSD1306Wire display(ADDRESS, SDA, SDC);
|
||||
```
|
||||
or for a SH1106:
|
||||
```C++
|
||||
#include <Wire.h>
|
||||
#include "SH1106.h"
|
||||
#include "SH1106Wire.h"
|
||||
|
||||
SH1106 display(ADDRESS, SDA, SDC);
|
||||
SH1106Wire display(ADDRESS, SDA, SDC);
|
||||
```
|
||||
|
||||
### I2C with brzo_i2c
|
||||
@ -137,10 +141,18 @@ void invertDisplay(void);
|
||||
void normalDisplay(void);
|
||||
|
||||
// Set display contrast
|
||||
void setContrast(char 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
|
||||
@ -180,7 +192,7 @@ void drawVerticalLine(int16_t x, int16_t y, int16_t length);
|
||||
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 char *image);
|
||||
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);
|
||||
@ -211,7 +223,7 @@ 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 char* fontData);
|
||||
void setFont(const uint8_t* fontData);
|
||||
```
|
||||
|
||||
## Ui Library (OLEDDisplayUi)
|
27
libraries/esp8266-oled-ssd1306-4.0.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);
|
||||
```
|
@ -1,8 +1,7 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
* 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
|
||||
@ -22,6 +21,10 @@
|
||||
* 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>
|
||||
@ -29,8 +32,8 @@
|
||||
// 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 "SSD1306.h" // alias for `#include "SSD1306Wire.h"`
|
||||
// or #include "SH1106.h" alis for `#include "SH1106Wire.h"`
|
||||
#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"
|
||||
@ -66,7 +69,7 @@
|
||||
// SH1106Brzo display(0x3c, D3, D5);
|
||||
|
||||
// Initialize the OLED display using Wire library
|
||||
SSD1306 display(0x3c, D3, D5);
|
||||
SSD1306Wire display(0x3c, D3, D5);
|
||||
// SH1106 display(0x3c, D3, D5);
|
||||
|
||||
OLEDDisplayUi ui ( &display );
|
@ -1,4 +1,4 @@
|
||||
const char activeSymbol[] PROGMEM = {
|
||||
const unsigned char activeSymbol[] PROGMEM = {
|
||||
B00000000,
|
||||
B00000000,
|
||||
B00011000,
|
||||
@ -9,7 +9,7 @@ const char activeSymbol[] PROGMEM = {
|
||||
B00011000
|
||||
};
|
||||
|
||||
const char inactiveSymbol[] PROGMEM = {
|
||||
const unsigned char inactiveSymbol[] PROGMEM = {
|
||||
B00000000,
|
||||
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() { }
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
* 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
|
||||
@ -22,6 +22,10 @@
|
||||
* 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
|
||||
@ -38,8 +42,8 @@
|
||||
// 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 "SSD1306.h" // alias for `#include "SSD1306Wire.h"`
|
||||
// or #include "SH1106.h" alis for `#include "SH1106Wire.h"`
|
||||
#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"
|
||||
@ -69,7 +73,7 @@
|
||||
// SH1106Brzo display(0x3c, D3, D5);
|
||||
|
||||
// Initialize the OLED display using Wire library
|
||||
SSD1306 display(0x3c, D3, D5);
|
||||
SSD1306Wire display(0x3c, D3, D5);
|
||||
// SH1106 display(0x3c, D3, D5);
|
||||
|
||||
|
||||
@ -90,7 +94,7 @@ void setup() {
|
||||
display.clear();
|
||||
display.setFont(ArialMT_Plain_10);
|
||||
display.setTextAlignment(TEXT_ALIGN_CENTER_BOTH);
|
||||
display.drawString(DISPLAY_WIDTH/2, DISPLAY_HEIGHT/2 - 10, "OTA Update");
|
||||
display.drawString(display.getWidth()/2, display.getHeight()/2 - 10, "OTA Update");
|
||||
display.display();
|
||||
});
|
||||
|
||||
@ -103,14 +107,14 @@ void setup() {
|
||||
display.clear();
|
||||
display.setFont(ArialMT_Plain_10);
|
||||
display.setTextAlignment(TEXT_ALIGN_CENTER_BOTH);
|
||||
display.drawString(DISPLAY_WIDTH/2, DISPLAY_HEIGHT/2, "Restart");
|
||||
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_WIDTH/2, DISPLAY_HEIGHT/2, "Ready for OTA:\n" + WiFi.localIP().toString());
|
||||
display.drawString(display.getWidth()/2, display.getHeight()/2, "Ready for OTA:\n" + WiFi.localIP().toString());
|
||||
display.display();
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* 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
|
||||
@ -21,13 +22,17 @@
|
||||
* 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 "SSD1306.h" // alias for `#include "SSD1306Wire.h"`
|
||||
// or #include "SH1106.h" alis for `#include "SH1106Wire.h"`
|
||||
#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"
|
||||
@ -58,7 +63,7 @@
|
||||
// SH1106Brzo display(0x3c, D3, D5);
|
||||
|
||||
// Initialize the OLED display using Wire library
|
||||
SSD1306 display(0x3c, 4, 15);
|
||||
SSD1306Wire display(0x3c, D3, D5);
|
||||
// SH1106 display(0x3c, D3, D5);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#define WiFi_Logo_width 60
|
||||
#define WiFi_Logo_height 36
|
||||
const char WiFi_Logo_bits[] PROGMEM = {
|
||||
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,
|
@ -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,
|
||||
};
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
* 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
|
||||
@ -22,13 +22,17 @@
|
||||
* 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 "SSD1306.h" // alias for `#include "SSD1306Wire.h"`
|
||||
// or #include "SH1106.h" alis for `#include "SH1106Wire.h"`
|
||||
#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"
|
||||
@ -42,6 +46,7 @@
|
||||
#include "OLEDDisplayUi.h"
|
||||
|
||||
// Include custom images
|
||||
|
||||
#include "images.h"
|
||||
|
||||
// Use the corresponding display class:
|
||||
@ -64,8 +69,8 @@
|
||||
// SH1106Brzo display(0x3c, D3, D5);
|
||||
|
||||
// Initialize the OLED display using Wire library
|
||||
SSD1306 display(0x3c, 4, 15);
|
||||
// SH1106 display(0x3c, D3, D5);
|
||||
SSD1306Wire display(0x3c, D3, D5);
|
||||
// SH1106Wire display(0x3c, D3, D5);
|
||||
|
||||
OLEDDisplayUi ui ( &display );
|
||||
|
||||
@ -139,11 +144,6 @@ OverlayCallback overlays[] = { msOverlay };
|
||||
int overlaysCount = 1;
|
||||
|
||||
void setup() {
|
||||
//For Embeded OLED on Wifi kit 32
|
||||
pinMode(16,OUTPUT);
|
||||
digitalWrite(16, LOW); // turn the LED on (HIGH is the voltage level)
|
||||
delay(100); // wait for a second
|
||||
digitalWrite(16, HIGH); // turn the LED off by making the voltage LOW
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.println();
|
@ -1,6 +1,6 @@
|
||||
#define WiFi_Logo_width 60
|
||||
#define WiFi_Logo_height 36
|
||||
const char WiFi_Logo_bits[] PROGMEM = {
|
||||
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,
|
||||
@ -27,7 +27,7 @@ const char WiFi_Logo_bits[] PROGMEM = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const char activeSymbol[] PROGMEM = {
|
||||
const uint8_t activeSymbol[] PROGMEM = {
|
||||
B00000000,
|
||||
B00000000,
|
||||
B00011000,
|
||||
@ -38,7 +38,7 @@ const char activeSymbol[] PROGMEM = {
|
||||
B00011000
|
||||
};
|
||||
|
||||
const char inactiveSymbol[] PROGMEM = {
|
||||
const uint8_t inactiveSymbol[] PROGMEM = {
|
||||
B00000000,
|
||||
B00000000,
|
||||
B00000000,
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ESP8266_SSD1306",
|
||||
"version": "3.2.7",
|
||||
"version": "4.0.0",
|
||||
"keywords": "ssd1306, oled, display, i2c",
|
||||
"description": "A I2C display driver for SSD1306 oled displays connected to an ESP8266 or ESP32",
|
||||
"repository":
|
||||
@ -11,9 +11,9 @@
|
||||
"authors":
|
||||
[
|
||||
{
|
||||
"name": "Daniel Eichhorn",
|
||||
"name": "Daniel Eichhorn, ThingPulse",
|
||||
"email": "squix78@gmail.com",
|
||||
"url": "http://blog.squix.ch"
|
||||
"url": "https://thingpulse.com"
|
||||
},
|
||||
{
|
||||
"name": "Fabrice Weinberg",
|
@ -1,9 +1,9 @@
|
||||
name=ESP8266 and ESP32 Oled Driver for SSD1306 display
|
||||
version=3.2.7
|
||||
version=4.0.0
|
||||
author=Daniel Eichhorn, Fabrice Weinberg
|
||||
maintainer=Daniel Eichhorn <squix78@gmail.com>
|
||||
sentence=A I2C display driver for SSD1306 oled displays connected to an ESP8266 or ESP32
|
||||
paragraph=A I2C display driver for SSD1306 oled displays connected to an ESP8266 or ESP32
|
||||
category=Display
|
||||
url=https://github.com/squix78/esp8266-oled-ssd1306
|
||||
url=https://github.com/ThingPulse/esp8266-oled-ssd1306
|
||||
architectures=esp8266,esp32
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
633
libraries/esp8266-oled-ssd1306-4.0.0/resources/glyphEditor.html
Normal file
@ -0,0 +1,633 @@
|
||||
<!--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 char 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="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() {
|
||||
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 notZero = 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) {
|
||||
notZero = true;
|
||||
}
|
||||
charBytes.push(Font.toHexString(byte));
|
||||
}
|
||||
}
|
||||
// Remove bytes with value 0 at the end of the array.
|
||||
while(parseInt(charBytes[charBytes.length-1]) === 0 && charBytes.length !== 1) {
|
||||
charBytes.pop();
|
||||
}
|
||||
|
||||
if (notZero) {
|
||||
Font.output('data', ` ${charBytes.join(', ')}, // ${charCode}`);
|
||||
// TODO: last param width is not the best value. Need to compute the actual occupied width
|
||||
Font.output('jump', ` ${Font.getMsB(charAddr)}, ${Font.getLsB(charAddr)}, ${Font.toHexString(charBytes.length)}, ${Font.toHexString(this.width)}, // ${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 char ${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('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':
|
||||
pixels = currentContainer.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 = '';
|
||||
}
|
||||
}
|
||||
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.
|
||||
}
|
||||
|
||||
});
|
||||
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>
|
BIN
libraries/esp8266-oled-ssd1306-4.0.0/resources/glyphEditor.png
Normal file
After Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
* 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
|
||||
@ -22,29 +22,43 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
* 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 "OLEDDisplay.h"
|
||||
|
||||
OLEDDisplay::~OLEDDisplay() {
|
||||
end();
|
||||
}
|
||||
|
||||
bool OLEDDisplay::init() {
|
||||
if (!this->connect()) {
|
||||
DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Can't establish connection to display\n");
|
||||
return false;
|
||||
}
|
||||
this->buffer = (uint8_t*) malloc(sizeof(uint8_t) * DISPLAY_BUFFER_SIZE);
|
||||
|
||||
if(this->buffer==NULL) {
|
||||
this->buffer = (uint8_t*) malloc(sizeof(uint8_t) * displayBufferSize);
|
||||
|
||||
if(!this->buffer) {
|
||||
DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Not enough memory to create display\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
this->buffer_back = (uint8_t*) malloc(sizeof(uint8_t) * DISPLAY_BUFFER_SIZE);
|
||||
if(this->buffer_back==NULL) {
|
||||
this->buffer_back = (uint8_t*) malloc(sizeof(uint8_t) * displayBufferSize);
|
||||
|
||||
if(!this->buffer_back) {
|
||||
DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Not enough memory to create back buffer\n");
|
||||
free(this->buffer);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
sendInitCommands();
|
||||
@ -54,16 +68,17 @@ bool OLEDDisplay::init() {
|
||||
}
|
||||
|
||||
void OLEDDisplay::end() {
|
||||
if (this->buffer) free(this->buffer);
|
||||
if (this->buffer) { free(this->buffer); this->buffer = NULL; }
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
if (this->buffer_back) free(this->buffer_back);
|
||||
if (this->buffer_back) { free(this->buffer_back); this->buffer_back = NULL; }
|
||||
#endif
|
||||
if (this->logBuffer != NULL) { free(this->logBuffer); this->logBuffer = NULL; }
|
||||
}
|
||||
|
||||
void OLEDDisplay::resetDisplay(void) {
|
||||
clear();
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
memset(buffer_back, 1, DISPLAY_BUFFER_SIZE);
|
||||
memset(buffer_back, 1, displayBufferSize);
|
||||
#endif
|
||||
display();
|
||||
}
|
||||
@ -72,12 +87,16 @@ void OLEDDisplay::setColor(OLEDDISPLAY_COLOR color) {
|
||||
this->color = color;
|
||||
}
|
||||
|
||||
OLEDDISPLAY_COLOR OLEDDisplay::getColor() {
|
||||
return this->color;
|
||||
}
|
||||
|
||||
void OLEDDisplay::setPixel(int16_t x, int16_t y) {
|
||||
if (x >= 0 && x < 128 && y >= 0 && y < 64) {
|
||||
if (x >= 0 && x < this->width() && y >= 0 && y < this->height()) {
|
||||
switch (color) {
|
||||
case WHITE: buffer[x + (y / 8) * DISPLAY_WIDTH] |= (1 << (y & 7)); break;
|
||||
case BLACK: buffer[x + (y / 8) * DISPLAY_WIDTH] &= ~(1 << (y & 7)); break;
|
||||
case INVERSE: buffer[x + (y / 8) * DISPLAY_WIDTH] ^= (1 << (y & 7)); break;
|
||||
case WHITE: buffer[x + (y / 8) * this->width()] |= (1 << (y & 7)); break;
|
||||
case BLACK: buffer[x + (y / 8) * this->width()] &= ~(1 << (y & 7)); break;
|
||||
case INVERSE: buffer[x + (y / 8) * this->width()] ^= (1 << (y & 7)); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -222,21 +241,21 @@ void OLEDDisplay::fillCircle(int16_t x0, int16_t y0, int16_t radius) {
|
||||
}
|
||||
|
||||
void OLEDDisplay::drawHorizontalLine(int16_t x, int16_t y, int16_t length) {
|
||||
if (y < 0 || y >= DISPLAY_HEIGHT) { return; }
|
||||
if (y < 0 || y >= this->height()) { return; }
|
||||
|
||||
if (x < 0) {
|
||||
length += x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if ( (x + length) > DISPLAY_WIDTH) {
|
||||
length = (DISPLAY_WIDTH - x);
|
||||
if ( (x + length) > this->width()) {
|
||||
length = (this->width() - x);
|
||||
}
|
||||
|
||||
if (length <= 0) { return; }
|
||||
|
||||
uint8_t * bufferPtr = buffer;
|
||||
bufferPtr += (y >> 3) * DISPLAY_WIDTH;
|
||||
bufferPtr += (y >> 3) * this->width();
|
||||
bufferPtr += x;
|
||||
|
||||
uint8_t drawBit = 1 << (y & 7);
|
||||
@ -255,15 +274,15 @@ void OLEDDisplay::drawHorizontalLine(int16_t x, int16_t y, int16_t length) {
|
||||
}
|
||||
|
||||
void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) {
|
||||
if (x < 0 || x >= DISPLAY_WIDTH) return;
|
||||
if (x < 0 || x >= this->width()) return;
|
||||
|
||||
if (y < 0) {
|
||||
length += y;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if ( (y + length) > DISPLAY_HEIGHT) {
|
||||
length = (DISPLAY_HEIGHT - y);
|
||||
if ( (y + length) > this->height()) {
|
||||
length = (this->height() - y);
|
||||
}
|
||||
|
||||
if (length <= 0) return;
|
||||
@ -273,7 +292,7 @@ void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) {
|
||||
uint8_t drawBit;
|
||||
uint8_t *bufferPtr = buffer;
|
||||
|
||||
bufferPtr += (y >> 3) * DISPLAY_WIDTH;
|
||||
bufferPtr += (y >> 3) * this->width();
|
||||
bufferPtr += x;
|
||||
|
||||
if (yOffset) {
|
||||
@ -293,7 +312,7 @@ void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) {
|
||||
if (length < yOffset) return;
|
||||
|
||||
length -= yOffset;
|
||||
bufferPtr += DISPLAY_WIDTH;
|
||||
bufferPtr += this->width();
|
||||
}
|
||||
|
||||
if (length >= 8) {
|
||||
@ -303,14 +322,14 @@ void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) {
|
||||
drawBit = (color == WHITE) ? 0xFF : 0x00;
|
||||
do {
|
||||
*bufferPtr = drawBit;
|
||||
bufferPtr += DISPLAY_WIDTH;
|
||||
bufferPtr += this->width();
|
||||
length -= 8;
|
||||
} while (length >= 8);
|
||||
break;
|
||||
case INVERSE:
|
||||
do {
|
||||
*bufferPtr = ~(*bufferPtr);
|
||||
bufferPtr += DISPLAY_WIDTH;
|
||||
bufferPtr += this->width();
|
||||
length -= 8;
|
||||
} while (length >= 8);
|
||||
break;
|
||||
@ -340,20 +359,20 @@ void OLEDDisplay::drawProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16
|
||||
drawHorizontalLine(xRadius, y + height, width - doubleRadius + 1);
|
||||
drawCircleQuads(x + width - radius, yRadius, radius, 0b00001001);
|
||||
|
||||
uint16_t maxProgressWidth = (width - doubleRadius - 1) * progress / 100;
|
||||
uint16_t maxProgressWidth = (width - doubleRadius + 1) * progress / 100;
|
||||
|
||||
fillCircle(xRadius, yRadius, innerRadius);
|
||||
fillRect(xRadius + 1, y + 2, maxProgressWidth, height - 3);
|
||||
fillCircle(xRadius + maxProgressWidth, yRadius, innerRadius);
|
||||
}
|
||||
|
||||
void OLEDDisplay::drawFastImage(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const char *image) {
|
||||
void OLEDDisplay::drawFastImage(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *image) {
|
||||
drawInternal(xMove, yMove, width, height, image, 0, 0);
|
||||
}
|
||||
|
||||
void OLEDDisplay::drawXbm(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const char *xbm) {
|
||||
void OLEDDisplay::drawXbm(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *xbm) {
|
||||
int16_t widthInXbm = (width + 7) / 8;
|
||||
uint8_t data;
|
||||
uint8_t data = 0;
|
||||
|
||||
for(int16_t y = 0; y < height; y++) {
|
||||
for(int16_t x = 0; x < width; x++ ) {
|
||||
@ -388,11 +407,13 @@ void OLEDDisplay::drawStringInternal(int16_t xMove, int16_t yMove, char* text, u
|
||||
case TEXT_ALIGN_RIGHT:
|
||||
xMove -= textWidth;
|
||||
break;
|
||||
case TEXT_ALIGN_LEFT:
|
||||
break;
|
||||
}
|
||||
|
||||
// Don't draw anything if it is not on the screen.
|
||||
if (xMove + textWidth < 0 || xMove > DISPLAY_WIDTH ) {return;}
|
||||
if (yMove + textHeight < 0 || yMove > DISPLAY_HEIGHT) {return;}
|
||||
if (xMove + textWidth < 0 || xMove > this->width() ) {return;}
|
||||
if (yMove + textHeight < 0 || yMove > this->width() ) {return;}
|
||||
|
||||
for (uint16_t j = 0; j < textLength; j++) {
|
||||
int16_t xPos = xMove + cursorX;
|
||||
@ -525,7 +546,7 @@ void OLEDDisplay::setTextAlignment(OLEDDISPLAY_TEXT_ALIGNMENT textAlignment) {
|
||||
this->textAlignment = textAlignment;
|
||||
}
|
||||
|
||||
void OLEDDisplay::setFont(const char *fontData) {
|
||||
void OLEDDisplay::setFont(const uint8_t *fontData) {
|
||||
this->fontData = fontData;
|
||||
}
|
||||
|
||||
@ -545,9 +566,39 @@ void OLEDDisplay::normalDisplay(void) {
|
||||
sendCommand(NORMALDISPLAY);
|
||||
}
|
||||
|
||||
void OLEDDisplay::setContrast(char contrast) {
|
||||
void OLEDDisplay::setContrast(uint8_t contrast, uint8_t precharge, uint8_t comdetect) {
|
||||
sendCommand(SETPRECHARGE); //0xD9
|
||||
sendCommand(precharge); //0xF1 default, to lower the contrast, put 1-1F
|
||||
sendCommand(SETCONTRAST);
|
||||
sendCommand(contrast);
|
||||
sendCommand(contrast); // 0-255
|
||||
sendCommand(SETVCOMDETECT); //0xDB, (additionally needed to lower the contrast)
|
||||
sendCommand(comdetect); //0x40 default, to lower the contrast, put 0
|
||||
sendCommand(DISPLAYALLON_RESUME);
|
||||
sendCommand(NORMALDISPLAY);
|
||||
sendCommand(DISPLAYON);
|
||||
}
|
||||
|
||||
void OLEDDisplay::setBrightness(uint8_t brightness) {
|
||||
uint8_t contrast = brightness;
|
||||
if (brightness < 128) {
|
||||
// Magic values to get a smooth/ step-free transition
|
||||
contrast = brightness * 1.171;
|
||||
} else {
|
||||
contrast = brightness * 1.171 - 43;
|
||||
}
|
||||
|
||||
uint8_t precharge = 241;
|
||||
if (brightness == 0) {
|
||||
precharge = 0;
|
||||
}
|
||||
uint8_t comdetect = brightness / 8;
|
||||
|
||||
setContrast(contrast, precharge, comdetect);
|
||||
}
|
||||
|
||||
void OLEDDisplay::resetOrientation() {
|
||||
sendCommand(SEGREMAP);
|
||||
sendCommand(COMSCANINC); //Reset screen rotation or mirroring
|
||||
}
|
||||
|
||||
void OLEDDisplay::flipScreenVertically() {
|
||||
@ -555,8 +606,13 @@ void OLEDDisplay::flipScreenVertically() {
|
||||
sendCommand(COMSCANDEC); //Rotate screen 180 Deg
|
||||
}
|
||||
|
||||
void OLEDDisplay::mirrorScreen() {
|
||||
sendCommand(SEGREMAP);
|
||||
sendCommand(COMSCANDEC); //Mirror screen
|
||||
}
|
||||
|
||||
void OLEDDisplay::clear(void) {
|
||||
memset(buffer, 0, DISPLAY_BUFFER_SIZE);
|
||||
memset(buffer, 0, displayBufferSize);
|
||||
}
|
||||
|
||||
void OLEDDisplay::drawLogBuffer(uint16_t xMove, uint16_t yMove) {
|
||||
@ -591,11 +647,20 @@ void OLEDDisplay::drawLogBuffer(uint16_t xMove, uint16_t yMove) {
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t OLEDDisplay::getWidth(void) {
|
||||
return displayWidth;
|
||||
}
|
||||
|
||||
uint16_t OLEDDisplay::getHeight(void) {
|
||||
return displayHeight;
|
||||
}
|
||||
|
||||
bool OLEDDisplay::setLogBuffer(uint16_t lines, uint16_t chars){
|
||||
if (logBuffer != NULL) free(logBuffer);
|
||||
uint16_t size = lines * chars;
|
||||
if (size > 0) {
|
||||
this->logBufferLine = 0; // Lines printed
|
||||
this->logBufferFilled = 0; // Nothing stored yet
|
||||
this->logBufferMaxLines = lines; // Lines max printable
|
||||
this->logBufferSize = size; // Total number of characters the buffer can hold
|
||||
this->logBuffer = (char *) malloc(size * sizeof(uint8_t));
|
||||
@ -612,12 +677,17 @@ size_t OLEDDisplay::write(uint8_t c) {
|
||||
// Don't waste space on \r\n line endings, dropping \r
|
||||
if (c == 13) return 1;
|
||||
|
||||
// convert UTF-8 character to font table index
|
||||
c = (this->fontTableLookupFunction)(c);
|
||||
// drop unknown character
|
||||
if (c == 0) return 1;
|
||||
|
||||
bool maxLineNotReached = this->logBufferLine < this->logBufferMaxLines;
|
||||
bool bufferNotFull = this->logBufferFilled < this->logBufferSize;
|
||||
|
||||
// Can we write to the buffer?
|
||||
if (bufferNotFull && maxLineNotReached) {
|
||||
this->logBuffer[logBufferFilled] = utf8ascii(c);
|
||||
this->logBuffer[logBufferFilled] = c;
|
||||
this->logBufferFilled++;
|
||||
// Keep track of lines written
|
||||
if (c == 10) this->logBufferLine++;
|
||||
@ -665,12 +735,24 @@ size_t OLEDDisplay::write(const char* str) {
|
||||
}
|
||||
|
||||
// Private functions
|
||||
void OLEDDisplay::setGeometry(OLEDDISPLAY_GEOMETRY g) {
|
||||
this->geometry = g;
|
||||
if (g == GEOMETRY_128_64) {
|
||||
this->displayWidth = 128;
|
||||
this->displayHeight = 64;
|
||||
} else if (g == GEOMETRY_128_32) {
|
||||
this->displayWidth = 128;
|
||||
this->displayHeight = 32;
|
||||
}
|
||||
this->displayBufferSize = displayWidth*displayHeight/8;
|
||||
}
|
||||
|
||||
void OLEDDisplay::sendInitCommands(void) {
|
||||
sendCommand(DISPLAYOFF);
|
||||
sendCommand(SETDISPLAYCLOCKDIV);
|
||||
sendCommand(0xF0); // Increase speed of the display max ~96Hz
|
||||
sendCommand(SETMULTIPLEX);
|
||||
sendCommand(0x3F);
|
||||
sendCommand(this->height() - 1);
|
||||
sendCommand(SETDISPLAYOFFSET);
|
||||
sendCommand(0x00);
|
||||
sendCommand(SETSTARTLINE);
|
||||
@ -681,21 +763,35 @@ void OLEDDisplay::sendInitCommands(void) {
|
||||
sendCommand(SEGREMAP);
|
||||
sendCommand(COMSCANINC);
|
||||
sendCommand(SETCOMPINS);
|
||||
sendCommand(0x12);
|
||||
|
||||
if (geometry == GEOMETRY_128_64) {
|
||||
sendCommand(0x12);
|
||||
} else if (geometry == GEOMETRY_128_32) {
|
||||
sendCommand(0x02);
|
||||
}
|
||||
|
||||
sendCommand(SETCONTRAST);
|
||||
sendCommand(0xCF);
|
||||
|
||||
if (geometry == GEOMETRY_128_64) {
|
||||
sendCommand(0xCF);
|
||||
} else if (geometry == GEOMETRY_128_32) {
|
||||
sendCommand(0x8F);
|
||||
}
|
||||
|
||||
sendCommand(SETPRECHARGE);
|
||||
sendCommand(0xF1);
|
||||
sendCommand(SETVCOMDETECT); //0xDB, (additionally needed to lower the contrast)
|
||||
sendCommand(0x40); //0x40 default, to lower the contrast, put 0
|
||||
sendCommand(DISPLAYALLON_RESUME);
|
||||
sendCommand(NORMALDISPLAY);
|
||||
sendCommand(0x2e); // stop scroll
|
||||
sendCommand(DISPLAYON);
|
||||
}
|
||||
|
||||
void inline OLEDDisplay::drawInternal(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const char *data, uint16_t offset, uint16_t bytesInData) {
|
||||
void inline OLEDDisplay::drawInternal(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *data, uint16_t offset, uint16_t bytesInData) {
|
||||
if (width < 0 || height < 0) return;
|
||||
if (yMove + height < 0 || yMove > DISPLAY_HEIGHT) return;
|
||||
if (xMove + width < 0 || xMove > DISPLAY_WIDTH) return;
|
||||
if (yMove + height < 0 || yMove > this->height()) return;
|
||||
if (xMove + width < 0 || xMove > this->width()) return;
|
||||
|
||||
uint8_t rasterHeight = 1 + ((height - 1) >> 3); // fast ceil(height / 8.0)
|
||||
int8_t yOffset = yMove & 7;
|
||||
@ -717,13 +813,13 @@ void inline OLEDDisplay::drawInternal(int16_t xMove, int16_t yMove, int16_t widt
|
||||
byte currentByte = pgm_read_byte(data + offset + i);
|
||||
|
||||
int16_t xPos = xMove + (i / rasterHeight);
|
||||
int16_t yPos = ((yMove >> 3) + (i % rasterHeight)) * DISPLAY_WIDTH;
|
||||
int16_t yPos = ((yMove >> 3) + (i % rasterHeight)) * this->width();
|
||||
|
||||
int16_t yScreenPos = yMove + yOffset;
|
||||
// int16_t yScreenPos = yMove + yOffset;
|
||||
int16_t dataPos = xPos + yPos;
|
||||
|
||||
if (dataPos >= 0 && dataPos < DISPLAY_BUFFER_SIZE &&
|
||||
xPos >= 0 && xPos < DISPLAY_WIDTH ) {
|
||||
if (dataPos >= 0 && dataPos < displayBufferSize &&
|
||||
xPos >= 0 && xPos < this->width() ) {
|
||||
|
||||
if (yOffset >= 0) {
|
||||
switch (this->color) {
|
||||
@ -731,11 +827,12 @@ void inline OLEDDisplay::drawInternal(int16_t xMove, int16_t yMove, int16_t widt
|
||||
case BLACK: buffer[dataPos] &= ~(currentByte << yOffset); break;
|
||||
case INVERSE: buffer[dataPos] ^= currentByte << yOffset; break;
|
||||
}
|
||||
if (dataPos < (DISPLAY_BUFFER_SIZE - DISPLAY_WIDTH)) {
|
||||
|
||||
if (dataPos < (displayBufferSize - this->width())) {
|
||||
switch (this->color) {
|
||||
case WHITE: buffer[dataPos + DISPLAY_WIDTH] |= currentByte >> (8 - yOffset); break;
|
||||
case BLACK: buffer[dataPos + DISPLAY_WIDTH] &= ~(currentByte >> (8 - yOffset)); break;
|
||||
case INVERSE: buffer[dataPos + DISPLAY_WIDTH] ^= currentByte >> (8 - yOffset); break;
|
||||
case WHITE: buffer[dataPos + this->width()] |= currentByte >> (8 - yOffset); break;
|
||||
case BLACK: buffer[dataPos + this->width()] &= ~(currentByte >> (8 - yOffset)); break;
|
||||
case INVERSE: buffer[dataPos + this->width()] ^= currentByte >> (8 - yOffset); break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -754,32 +851,12 @@ void inline OLEDDisplay::drawInternal(int16_t xMove, int16_t yMove, int16_t widt
|
||||
// and setting the new yOffset
|
||||
yOffset = 8 - yOffset;
|
||||
}
|
||||
optimistic_yield(10000);
|
||||
|
||||
yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Code form http://playground.arduino.cc/Main/Utf8ascii
|
||||
uint8_t OLEDDisplay::utf8ascii(byte ascii) {
|
||||
static uint8_t LASTCHAR;
|
||||
|
||||
if ( ascii < 128 ) { // Standard ASCII-set 0..0x7F handling
|
||||
LASTCHAR = 0;
|
||||
return ascii;
|
||||
}
|
||||
|
||||
uint8_t last = LASTCHAR; // get last char
|
||||
LASTCHAR = ascii;
|
||||
|
||||
switch (last) { // conversion depnding on first UTF8-character
|
||||
case 0xC2: return (ascii); break;
|
||||
case 0xC3: return (ascii | 0xC0); break;
|
||||
case 0x82: if (ascii == 0xAC) return (0x80); // special case Euro-symbol
|
||||
}
|
||||
|
||||
return 0; // otherwise: return zero, if character has to be ignored
|
||||
}
|
||||
|
||||
// You need to free the char!
|
||||
char* OLEDDisplay::utf8ascii(String str) {
|
||||
uint16_t k = 0;
|
||||
@ -796,7 +873,7 @@ char* OLEDDisplay::utf8ascii(String str) {
|
||||
length--;
|
||||
|
||||
for (uint16_t i=0; i < length; i++) {
|
||||
char c = utf8ascii(s[i]);
|
||||
char c = (this->fontTableLookupFunction)(s[i]);
|
||||
if (c!=0) {
|
||||
s[k++]=c;
|
||||
}
|
||||
@ -807,3 +884,7 @@ char* OLEDDisplay::utf8ascii(String str) {
|
||||
// This will leak 's' be sure to free it in the calling function.
|
||||
return s;
|
||||
}
|
||||
|
||||
void OLEDDisplay::setFontTableLookupFunction(FontTableLookupFunction function) {
|
||||
this->fontTableLookupFunction = function;
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
* 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
|
||||
@ -22,7 +22,10 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
* 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
|
||||
@ -42,12 +45,6 @@
|
||||
#define OLEDDISPLAY_DOUBLE_BUFFER
|
||||
#endif
|
||||
|
||||
|
||||
// Display settings
|
||||
#define DISPLAY_WIDTH 128
|
||||
#define DISPLAY_HEIGHT 64
|
||||
#define DISPLAY_BUFFER_SIZE 1024
|
||||
|
||||
// Header Values
|
||||
#define JUMPTABLE_BYTES 4
|
||||
|
||||
@ -108,8 +105,22 @@ enum OLEDDISPLAY_TEXT_ALIGNMENT {
|
||||
};
|
||||
|
||||
|
||||
enum OLEDDISPLAY_GEOMETRY {
|
||||
GEOMETRY_128_64 = 0,
|
||||
GEOMETRY_128_32 = 1
|
||||
};
|
||||
|
||||
typedef byte (*FontTableLookupFunction)(const byte ch);
|
||||
|
||||
|
||||
class OLEDDisplay : public Print {
|
||||
|
||||
public:
|
||||
virtual ~OLEDDisplay();
|
||||
|
||||
const uint16_t width(void) const { return displayWidth; };
|
||||
const uint16_t height(void) const { return displayHeight; };
|
||||
|
||||
// Initialize the display
|
||||
bool init();
|
||||
|
||||
@ -123,6 +134,9 @@ class OLEDDisplay : public Print {
|
||||
// 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);
|
||||
|
||||
@ -147,18 +161,18 @@ class OLEDDisplay : public Print {
|
||||
// Draw a line horizontally
|
||||
void drawHorizontalLine(int16_t x, int16_t y, int16_t length);
|
||||
|
||||
// Draw a lin vertically
|
||||
// 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
|
||||
// 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 char *image);
|
||||
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);
|
||||
void drawXbm(int16_t x, int16_t y, int16_t width, int16_t height, const uint8_t *xbm);
|
||||
|
||||
/* Text functions */
|
||||
|
||||
@ -184,7 +198,10 @@ class OLEDDisplay : public Print {
|
||||
|
||||
// Sets the current font. Available default fonts
|
||||
// ArialMT_Plain_10, ArialMT_Plain_16, ArialMT_Plain_24
|
||||
void setFont(const char *fontData);
|
||||
void setFont(const uint8_t *fontData);
|
||||
|
||||
// Set the function that will convert utf-8 to font table index
|
||||
void setFontTableLookupFunction(FontTableLookupFunction function);
|
||||
|
||||
/* Display functions */
|
||||
|
||||
@ -201,11 +218,22 @@ class OLEDDisplay : public Print {
|
||||
void normalDisplay(void);
|
||||
|
||||
// Set display contrast
|
||||
void setContrast(char 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;
|
||||
|
||||
@ -222,22 +250,35 @@ class OLEDDisplay : public Print {
|
||||
// Draw the log buffer at position (x, y)
|
||||
void drawLogBuffer(uint16_t x, uint16_t y);
|
||||
|
||||
// Implementent needed function to be compatible with Print class
|
||||
// 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);
|
||||
|
||||
uint8_t *buffer;
|
||||
uint8_t *buffer = NULL;
|
||||
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t *buffer_back;
|
||||
uint8_t *buffer_back = NULL;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
OLEDDISPLAY_GEOMETRY geometry = GEOMETRY_128_64;
|
||||
|
||||
uint16_t displayWidth = 128;
|
||||
uint16_t displayHeight = 64;
|
||||
uint16_t displayBufferSize = 1024;
|
||||
|
||||
// Set the correct height, width and buffer for the geometry
|
||||
void setGeometry(OLEDDISPLAY_GEOMETRY g);
|
||||
|
||||
OLEDDISPLAY_TEXT_ALIGNMENT textAlignment = TEXT_ALIGN_LEFT;
|
||||
OLEDDISPLAY_COLOR color = WHITE;
|
||||
|
||||
const char *fontData = ArialMT_Plain_10;
|
||||
const uint8_t *fontData = ArialMT_Plain_10;
|
||||
|
||||
// State values for logBuffer
|
||||
uint16_t logBufferSize = 0;
|
||||
@ -247,22 +288,42 @@ class OLEDDisplay : public Print {
|
||||
char *logBuffer = NULL;
|
||||
|
||||
// Send a command to the display (low level function)
|
||||
virtual void sendCommand(uint8_t com) {};
|
||||
virtual void sendCommand(uint8_t com) {(void)com;};
|
||||
|
||||
// Connect to the display
|
||||
virtual bool connect() {};
|
||||
virtual bool connect() { return false; };
|
||||
|
||||
// Send all the init commands
|
||||
void sendInitCommands();
|
||||
|
||||
// converts utf8 characters to extended ascii
|
||||
static char* utf8ascii(String s);
|
||||
static byte utf8ascii(byte ascii);
|
||||
char* utf8ascii(String s);
|
||||
|
||||
void inline drawInternal(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const char *data, uint16_t offset, uint16_t bytesInData) __attribute__((always_inline));
|
||||
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);
|
||||
|
||||
// UTF-8 to font table index converter
|
||||
// Code form http://playground.arduino.cc/Main/Utf8ascii
|
||||
FontTableLookupFunction fontTableLookupFunction = [](const byte ch) {
|
||||
static uint8_t LASTCHAR;
|
||||
|
||||
if (ch < 128) { // Standard ASCII-set 0..0x7F handling
|
||||
LASTCHAR = 0;
|
||||
return ch;
|
||||
}
|
||||
|
||||
uint8_t last = LASTCHAR; // get last char
|
||||
LASTCHAR = ch;
|
||||
|
||||
switch (last) { // conversion depnding on first UTF8-character
|
||||
case 0xC2: return (uint8_t) ch;
|
||||
case 0xC3: return (uint8_t) (ch | 0xC0);
|
||||
case 0x82: if (ch == 0xAC) return (uint8_t) 0x80; // special case Euro-symbol
|
||||
}
|
||||
|
||||
return (uint8_t) 0; // otherwise: return zero, if character has to be ignored
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
@ -1,7 +1,7 @@
|
||||
#ifndef OLEDDISPLAYFONTS_h
|
||||
#define OLEDDISPLAYFONTS_h
|
||||
|
||||
const char ArialMT_Plain_10[] PROGMEM = {
|
||||
const uint8_t ArialMT_Plain_10[] PROGMEM = {
|
||||
0x0A, // Width: 10
|
||||
0x0D, // Height: 13
|
||||
0x20, // First Char: 32
|
||||
@ -425,7 +425,7 @@ const char ArialMT_Plain_10[] PROGMEM = {
|
||||
0x20,0x00,0xC8,0x09,0x00,0x06,0xC8,0x01,0x20 // 255
|
||||
};
|
||||
|
||||
const char ArialMT_Plain_16[] PROGMEM = {
|
||||
const uint8_t ArialMT_Plain_16[] PROGMEM = {
|
||||
0x10, // Width: 16
|
||||
0x13, // Height: 19
|
||||
0x20, // First Char: 32
|
||||
@ -848,7 +848,7 @@ const char ArialMT_Plain_16[] PROGMEM = {
|
||||
0x00,0x00,0x00,0xF8,0xFF,0x03,0x80,0x20,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x80,0x20,0x00,0x00,0x1F, // 254
|
||||
0xC0,0x01,0x00,0x00,0x06,0x02,0x10,0x38,0x02,0x00,0xE0,0x01,0x10,0x38,0x00,0x00,0x07,0x00,0xC0 // 255
|
||||
};
|
||||
const char ArialMT_Plain_24[] PROGMEM = {
|
||||
const uint8_t ArialMT_Plain_24[] PROGMEM = {
|
||||
0x18, // Width: 24
|
||||
0x1C, // Height: 28
|
||||
0x20, // First Char: 32
|
||||
@ -1271,4 +1271,4 @@ const char ArialMT_Plain_24[] PROGMEM = {
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0xFF,0x07,0xE0,0xFF,0xFF,0x07,0x00,0x1C,0x18,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x0E,0x38,0x00,0x00,0x1C,0x1C,0x00,0x00,0xF8,0x0F,0x00,0x00,0xF0,0x03, // 254
|
||||
0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x7E,0x00,0x06,0xC0,0xF0,0x01,0x06,0xC0,0x80,0x0F,0x07,0x00,0x00,0xFE,0x03,0x00,0x00,0xFC,0x00,0xC0,0xC0,0x1F,0x00,0xC0,0xF8,0x03,0x00,0x00,0x3E,0x00,0x00,0x00,0x06 // 255
|
||||
};
|
||||
#endif
|
||||
#endif
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
* 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
|
||||
@ -22,6 +22,10 @@
|
||||
* 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"
|
||||
@ -61,10 +65,10 @@ void OLEDDisplayUi::setAutoTransitionBackwards(){
|
||||
this->lastTransitionDirection = -1;
|
||||
}
|
||||
void OLEDDisplayUi::setTimePerFrame(uint16_t time){
|
||||
this->ticksPerFrame = (int) ( (float) time / (float) updateInterval);
|
||||
this->ticksPerFrame = (uint16_t) ( (float) time / (float) updateInterval);
|
||||
}
|
||||
void OLEDDisplayUi::setTimePerTransition(uint16_t time){
|
||||
this->ticksPerTransition = (int) ( (float) time / (float) updateInterval);
|
||||
this->ticksPerTransition = (uint16_t) ( (float) time / (float) updateInterval);
|
||||
}
|
||||
|
||||
// -/------ Customize indicator position and style -------\-
|
||||
@ -90,10 +94,10 @@ void OLEDDisplayUi::setIndicatorPosition(IndicatorPosition pos) {
|
||||
void OLEDDisplayUi::setIndicatorDirection(IndicatorDirection dir) {
|
||||
this->indicatorDirection = dir;
|
||||
}
|
||||
void OLEDDisplayUi::setActiveSymbol(const char* symbol) {
|
||||
void OLEDDisplayUi::setActiveSymbol(const uint8_t* symbol) {
|
||||
this->activeSymbol = symbol;
|
||||
}
|
||||
void OLEDDisplayUi::setInactiveSymbol(const char* symbol) {
|
||||
void OLEDDisplayUi::setInactiveSymbol(const uint8_t* symbol) {
|
||||
this->inactiveSymbol = symbol;
|
||||
}
|
||||
|
||||
@ -132,7 +136,7 @@ void OLEDDisplayUi::runLoadingProcess(LoadingStage* stages, uint8_t stagesCount)
|
||||
stages[i].callback();
|
||||
|
||||
progress += increment;
|
||||
optimistic_yield(10000);
|
||||
yield();
|
||||
}
|
||||
|
||||
display->clear();
|
||||
@ -190,7 +194,7 @@ OLEDDisplayUiState* OLEDDisplayUi::getUiState(){
|
||||
|
||||
|
||||
int8_t OLEDDisplayUi::update(){
|
||||
long frameStart = millis();
|
||||
unsigned long frameStart = millis();
|
||||
int8_t timeBudget = this->updateInterval - (frameStart - this->state.lastUpdate);
|
||||
if ( timeBudget <= 0) {
|
||||
// Implement frame skipping to ensure time budget is keept
|
||||
@ -251,31 +255,32 @@ void OLEDDisplayUi::drawFrame(){
|
||||
switch (this->state.frameState){
|
||||
case IN_TRANSITION: {
|
||||
float progress = (float) this->state.ticksSinceLastStateSwitch / (float) this->ticksPerTransition;
|
||||
int16_t x, y, x1, y1;
|
||||
int16_t x = 0, y = 0, x1 = 0, y1 = 0;
|
||||
switch(this->frameAnimationDirection){
|
||||
case SLIDE_LEFT:
|
||||
x = -128 * progress;
|
||||
x = -this->display->width() * progress;
|
||||
y = 0;
|
||||
x1 = x + 128;
|
||||
x1 = x + this->display->width();
|
||||
y1 = 0;
|
||||
break;
|
||||
case SLIDE_RIGHT:
|
||||
x = 128 * progress;
|
||||
x = this->display->width() * progress;
|
||||
y = 0;
|
||||
x1 = x - 128;
|
||||
x1 = x - this->display->width();
|
||||
y1 = 0;
|
||||
break;
|
||||
case SLIDE_UP:
|
||||
x = 0;
|
||||
y = -64 * progress;
|
||||
y = -this->display->height() * progress;
|
||||
x1 = 0;
|
||||
y1 = y + 64;
|
||||
y1 = y + this->display->height();
|
||||
break;
|
||||
case SLIDE_DOWN:
|
||||
default:
|
||||
x = 0;
|
||||
y = 64 * progress;
|
||||
y = this->display->height() * progress;
|
||||
x1 = 0;
|
||||
y1 = y - 64;
|
||||
y1 = y - this->display->height();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -331,7 +336,7 @@ void OLEDDisplayUi::drawIndicator() {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t posOfHighlightFrame;
|
||||
uint8_t posOfHighlightFrame = 0;
|
||||
float indicatorFadeProgress = 0;
|
||||
|
||||
// if the indicator needs to be slided in we want to
|
||||
@ -345,6 +350,7 @@ void OLEDDisplayUi::drawIndicator() {
|
||||
posOfHighlightFrame = frameToHighlight;
|
||||
break;
|
||||
case RIGHT_LEFT:
|
||||
default:
|
||||
posOfHighlightFrame = this->frameCount - frameToHighlight;
|
||||
break;
|
||||
}
|
||||
@ -360,27 +366,37 @@ void OLEDDisplayUi::drawIndicator() {
|
||||
break;
|
||||
}
|
||||
|
||||
uint16_t frameStartPos = (12 * frameCount / 2);
|
||||
const char *image;
|
||||
uint16_t x,y;
|
||||
//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 (byte i = 0; i < this->frameCount; i++) {
|
||||
|
||||
switch (this->indicatorPosition){
|
||||
case TOP:
|
||||
y = 0 - (8 * indicatorFadeProgress);
|
||||
x = 64 - frameStartPos + 12 * i;
|
||||
x = (this->display->width() / 2) - frameStartPos + 12 * i;
|
||||
break;
|
||||
case BOTTOM:
|
||||
y = 56 + (8 * indicatorFadeProgress);
|
||||
x = 64 - frameStartPos + 12 * i;
|
||||
y = (this->display->height() - 8) + (8 * indicatorFadeProgress);
|
||||
x = (this->display->width() / 2) - frameStartPos + 12 * i;
|
||||
break;
|
||||
case RIGHT:
|
||||
x = 120 + (8 * indicatorFadeProgress);
|
||||
y = 32 - frameStartPos + 2 + 12 * i;
|
||||
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 = 32 - frameStartPos + 2 + 12 * i;
|
||||
y = (this->display->height() / 2) - frameStartPos + 2 + indicatorSpacing * i;
|
||||
break;
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
* 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
|
||||
@ -22,6 +22,10 @@
|
||||
* 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
|
||||
@ -61,11 +65,11 @@ enum FrameState {
|
||||
};
|
||||
|
||||
|
||||
const char ANIMATION_activeSymbol[] PROGMEM = {
|
||||
const uint8_t ANIMATION_activeSymbol[] PROGMEM = {
|
||||
0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00
|
||||
};
|
||||
|
||||
const char ANIMATION_inactiveSymbol[] PROGMEM = {
|
||||
const uint8_t ANIMATION_inactiveSymbol[] PROGMEM = {
|
||||
0x00, 0x0, 0x0, 0x18, 0x18, 0x0, 0x0, 0x00
|
||||
};
|
||||
|
||||
@ -106,8 +110,8 @@ class OLEDDisplayUi {
|
||||
IndicatorPosition indicatorPosition = BOTTOM;
|
||||
IndicatorDirection indicatorDirection = LEFT_RIGHT;
|
||||
|
||||
const char* activeSymbol = ANIMATION_activeSymbol;
|
||||
const char* inactiveSymbol = ANIMATION_inactiveSymbol;
|
||||
const uint8_t* activeSymbol = ANIMATION_activeSymbol;
|
||||
const uint8_t* inactiveSymbol = ANIMATION_inactiveSymbol;
|
||||
|
||||
bool shouldDrawIndicators = true;
|
||||
|
||||
@ -240,12 +244,12 @@ class OLEDDisplayUi {
|
||||
/**
|
||||
* Set the symbol to indicate an active frame in the indicator bar.
|
||||
*/
|
||||
void setActiveSymbol(const char* symbol);
|
||||
void setActiveSymbol(const uint8_t* symbol);
|
||||
|
||||
/**
|
||||
* Set the symbol to indicate an inactive frame in the indicator bar.
|
||||
*/
|
||||
void setInactiveSymbol(const char* symbol);
|
||||
void setInactiveSymbol(const uint8_t* symbol);
|
||||
|
||||
|
||||
// Frame settings
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
* 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
|
||||
@ -22,7 +22,10 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
* 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
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
* 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
|
||||
@ -22,7 +22,10 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
* 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
|
||||
@ -44,7 +47,9 @@ class SH1106Brzo : public OLEDDisplay {
|
||||
uint8_t _scl;
|
||||
|
||||
public:
|
||||
SH1106Brzo(uint8_t _address, uint8_t _sda, uint8_t _scl) {
|
||||
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;
|
||||
@ -57,18 +62,18 @@ class SH1106Brzo : public OLEDDisplay {
|
||||
|
||||
void display(void) {
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t minBoundY = ~0;
|
||||
uint8_t minBoundY = UINT8_MAX;
|
||||
uint8_t maxBoundY = 0;
|
||||
|
||||
uint8_t minBoundX = ~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 < (DISPLAY_HEIGHT / 8); y++) {
|
||||
for (x = 0; x < DISPLAY_WIDTH; x++) {
|
||||
uint16_t pos = x + y * DISPLAY_WIDTH;
|
||||
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);
|
||||
@ -77,19 +82,19 @@ class SH1106Brzo : public OLEDDisplay {
|
||||
}
|
||||
buffer_back[pos] = buffer[pos];
|
||||
}
|
||||
optimistic_yield(10000);
|
||||
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 == ~0) return;
|
||||
if (minBoundY == UINT8_MAX) return;
|
||||
|
||||
byte k = 0;
|
||||
uint8_t sendBuffer[17];
|
||||
sendBuffer[0] = 0x40;
|
||||
|
||||
// Calculate the colum offset
|
||||
// Calculate the colum offset
|
||||
uint8_t minBoundXp2H = (minBoundX + 2) & 0x0F;
|
||||
uint8_t minBoundXp2L = 0x10 | ((minBoundX + 2) >> 4 );
|
||||
|
||||
@ -101,7 +106,7 @@ class SH1106Brzo : public OLEDDisplay {
|
||||
sendCommand(minBoundXp2L);
|
||||
for (x = minBoundX; x <= maxBoundX; x++) {
|
||||
k++;
|
||||
sendBuffer[k] = buffer[x + y * DISPLAY_WIDTH];
|
||||
sendBuffer[k] = buffer[x + y * displayWidth];
|
||||
if (k == 16) {
|
||||
brzo_i2c_write(sendBuffer, 17, true);
|
||||
k = 0;
|
||||
@ -111,7 +116,7 @@ class SH1106Brzo : public OLEDDisplay {
|
||||
brzo_i2c_write(sendBuffer, k + 1, true);
|
||||
k = 0;
|
||||
}
|
||||
optimistic_yield(10000);
|
||||
yield();
|
||||
}
|
||||
if (k != 0) {
|
||||
brzo_i2c_write(sendBuffer, k + 1, true);
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
* 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
|
||||
@ -22,7 +22,10 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
* 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
|
||||
@ -37,8 +40,9 @@ class SH1106Spi : public OLEDDisplay {
|
||||
uint8_t _dc;
|
||||
|
||||
public:
|
||||
SH1106Spi(uint8_t _rst, uint8_t _dc, uint8_t _cs, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64) {
|
||||
setGeometry(g);
|
||||
|
||||
SH1106Spi(uint8_t _rst, uint8_t _dc) {
|
||||
this->_rst = _rst;
|
||||
this->_dc = _dc;
|
||||
}
|
||||
@ -61,19 +65,19 @@ class SH1106Spi : public OLEDDisplay {
|
||||
|
||||
void display(void) {
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t minBoundY = ~0;
|
||||
uint8_t minBoundY = UINT8_MAX;
|
||||
uint8_t maxBoundY = 0;
|
||||
|
||||
uint8_t minBoundX = ~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 < (DISPLAY_HEIGHT / 8); y++) {
|
||||
for (x = 0; x < DISPLAY_WIDTH; x++) {
|
||||
uint16_t pos = x + y * DISPLAY_WIDTH;
|
||||
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);
|
||||
@ -82,13 +86,13 @@ class SH1106Spi : public OLEDDisplay {
|
||||
}
|
||||
buffer_back[pos] = buffer[pos];
|
||||
}
|
||||
optimistic_yield(10000);
|
||||
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 == ~0) return;
|
||||
if (minBoundY == UINT8_MAX) return;
|
||||
|
||||
// Calculate the colum offset
|
||||
uint8_t minBoundXp2H = (minBoundX + 2) & 0x0F;
|
||||
@ -100,20 +104,20 @@ class SH1106Spi : public OLEDDisplay {
|
||||
sendCommand(minBoundXp2L);
|
||||
digitalWrite(_dc, HIGH); // data mode
|
||||
for (x = minBoundX; x <= maxBoundX; x++) {
|
||||
SPI.transfer(buffer[x + y * DISPLAY_WIDTH]);
|
||||
SPI.transfer(buffer[x + y * displayWidth]);
|
||||
}
|
||||
optimistic_yield(10000);
|
||||
yield();
|
||||
}
|
||||
#else
|
||||
for (uint8_t y=0; y<DISPLAY_HEIGHT/8; y++) {
|
||||
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 < DISPLAY_WIDTH; x++) {
|
||||
SPI.transfer(buffer[x + y * DISPLAY_WIDTH]);
|
||||
for( uint8_t x=0; x < displayWidth; x++) {
|
||||
SPI.transfer(buffer[x + y * displayWidth]);
|
||||
}
|
||||
optimistic_yield(10000);
|
||||
yield();
|
||||
}
|
||||
#endif
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
* 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
|
||||
@ -22,7 +22,10 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
* 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
|
||||
@ -44,7 +47,9 @@ class SH1106Wire : public OLEDDisplay {
|
||||
uint8_t _scl;
|
||||
|
||||
public:
|
||||
SH1106Wire(uint8_t _address, uint8_t _sda, uint8_t _scl) {
|
||||
SH1106Wire(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;
|
||||
@ -60,19 +65,19 @@ class SH1106Wire : public OLEDDisplay {
|
||||
|
||||
void display(void) {
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t minBoundY = ~0;
|
||||
uint8_t minBoundY = UINT8_MAX;
|
||||
uint8_t maxBoundY = 0;
|
||||
|
||||
uint8_t minBoundX = ~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 < (DISPLAY_HEIGHT / 8); y++) {
|
||||
for (x = 0; x < DISPLAY_WIDTH; x++) {
|
||||
uint16_t pos = x + y * DISPLAY_WIDTH;
|
||||
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);
|
||||
@ -81,13 +86,13 @@ class SH1106Wire : public OLEDDisplay {
|
||||
}
|
||||
buffer_back[pos] = buffer[pos];
|
||||
}
|
||||
optimistic_yield(10000);
|
||||
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 == ~0) return;
|
||||
if (minBoundY == UINT8_MAX) return;
|
||||
|
||||
// Calculate the colum offset
|
||||
uint8_t minBoundXp2H = (minBoundX + 2) & 0x0F;
|
||||
@ -103,7 +108,7 @@ class SH1106Wire : public OLEDDisplay {
|
||||
Wire.beginTransmission(_address);
|
||||
Wire.write(0x40);
|
||||
}
|
||||
Wire.write(buffer[x + y * DISPLAY_WIDTH]);
|
||||
Wire.write(buffer[x + y * displayWidth]);
|
||||
k++;
|
||||
if (k == 16) {
|
||||
Wire.endTransmission();
|
||||
@ -114,7 +119,7 @@ class SH1106Wire : public OLEDDisplay {
|
||||
Wire.endTransmission();
|
||||
k = 0;
|
||||
}
|
||||
optimistic_yield(10000);
|
||||
yield();
|
||||
}
|
||||
|
||||
if (k != 0) {
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
* 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
|
||||
@ -22,7 +22,10 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
* 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
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
* 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
|
||||
@ -22,7 +22,10 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
* 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
|
||||
@ -44,7 +47,9 @@ class SSD1306Brzo : public OLEDDisplay {
|
||||
uint8_t _scl;
|
||||
|
||||
public:
|
||||
SSD1306Brzo(uint8_t _address, uint8_t _sda, uint8_t _scl) {
|
||||
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;
|
||||
@ -57,19 +62,19 @@ class SSD1306Brzo : public OLEDDisplay {
|
||||
|
||||
void display(void) {
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t minBoundY = ~0;
|
||||
uint8_t minBoundY = UINT8_MAX;
|
||||
uint8_t maxBoundY = 0;
|
||||
|
||||
uint8_t minBoundX = ~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 < (DISPLAY_HEIGHT / 8); y++) {
|
||||
for (x = 0; x < DISPLAY_WIDTH; x++) {
|
||||
uint16_t pos = x + y * DISPLAY_WIDTH;
|
||||
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);
|
||||
@ -78,13 +83,13 @@ class SSD1306Brzo : public OLEDDisplay {
|
||||
}
|
||||
buffer_back[pos] = buffer[pos];
|
||||
}
|
||||
optimistic_yield(10000);
|
||||
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 == ~0) return;
|
||||
if (minBoundY == UINT8_MAX) return;
|
||||
|
||||
sendCommand(COLUMNADDR);
|
||||
sendCommand(minBoundX);
|
||||
@ -101,13 +106,13 @@ class SSD1306Brzo : public OLEDDisplay {
|
||||
for (y = minBoundY; y <= maxBoundY; y++) {
|
||||
for (x = minBoundX; x <= maxBoundX; x++) {
|
||||
k++;
|
||||
sendBuffer[k] = buffer[x + y * DISPLAY_WIDTH];
|
||||
sendBuffer[k] = buffer[x + y * displayWidth];
|
||||
if (k == 16) {
|
||||
brzo_i2c_write(sendBuffer, 17, true);
|
||||
k = 0;
|
||||
}
|
||||
}
|
||||
optimistic_yield(10000);
|
||||
yield();
|
||||
}
|
||||
brzo_i2c_write(sendBuffer, k + 1, true);
|
||||
brzo_i2c_end_transaction();
|
||||
@ -119,19 +124,24 @@ class SSD1306Brzo : public OLEDDisplay {
|
||||
|
||||
sendCommand(PAGEADDR);
|
||||
sendCommand(0x0);
|
||||
sendCommand(0x7);
|
||||
|
||||
if (geometry == GEOMETRY_128_64) {
|
||||
sendCommand(0x7);
|
||||
} else if (geometry == GEOMETRY_128_32) {
|
||||
sendCommand(0x3);
|
||||
}
|
||||
|
||||
uint8_t sendBuffer[17];
|
||||
sendBuffer[0] = 0x40;
|
||||
brzo_i2c_start_transaction(this->_address, BRZO_I2C_SPEED);
|
||||
for (uint16_t i=0; i<DISPLAY_BUFFER_SIZE; i++) {
|
||||
for (uint16_t i=0; i<displayBufferSize; i++) {
|
||||
for (uint8_t x=1; x<17; x++) {
|
||||
sendBuffer[x] = buffer[i];
|
||||
i++;
|
||||
}
|
||||
i--;
|
||||
brzo_i2c_write(sendBuffer, 17, true);
|
||||
optimistic_yield(10000);
|
||||
yield();
|
||||
}
|
||||
brzo_i2c_end_transaction();
|
||||
#endif
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
* 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
|
||||
@ -22,7 +22,10 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
* 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
|
||||
@ -44,7 +47,9 @@ class SSD1306Spi : public OLEDDisplay {
|
||||
uint8_t _cs;
|
||||
|
||||
public:
|
||||
SSD1306Spi(uint8_t _rst, uint8_t _dc, uint8_t _cs) {
|
||||
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;
|
||||
@ -69,19 +74,19 @@ class SSD1306Spi : public OLEDDisplay {
|
||||
|
||||
void display(void) {
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t minBoundY = ~0;
|
||||
uint8_t minBoundY = UINT8_MAX;
|
||||
uint8_t maxBoundY = 0;
|
||||
|
||||
uint8_t minBoundX = ~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 < (DISPLAY_HEIGHT / 8); y++) {
|
||||
for (x = 0; x < DISPLAY_WIDTH; x++) {
|
||||
uint16_t pos = x + y * DISPLAY_WIDTH;
|
||||
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);
|
||||
@ -90,13 +95,13 @@ class SSD1306Spi : public OLEDDisplay {
|
||||
}
|
||||
buffer_back[pos] = buffer[pos];
|
||||
}
|
||||
optimistic_yield(10000);
|
||||
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 == ~0) return;
|
||||
if (minBoundY == UINT8_MAX) return;
|
||||
|
||||
sendCommand(COLUMNADDR);
|
||||
sendCommand(minBoundX);
|
||||
@ -111,9 +116,9 @@ class SSD1306Spi : public OLEDDisplay {
|
||||
digitalWrite(_cs, LOW);
|
||||
for (y = minBoundY; y <= maxBoundY; y++) {
|
||||
for (x = minBoundX; x <= maxBoundX; x++) {
|
||||
SPI.transfer(buffer[x + y * DISPLAY_WIDTH]);
|
||||
SPI.transfer(buffer[x + y * displayWidth]);
|
||||
}
|
||||
optimistic_yield(10000);
|
||||
yield();
|
||||
}
|
||||
digitalWrite(_cs, HIGH);
|
||||
#else
|
||||
@ -124,14 +129,19 @@ class SSD1306Spi : public OLEDDisplay {
|
||||
|
||||
sendCommand(PAGEADDR);
|
||||
sendCommand(0x0);
|
||||
sendCommand(0x7);
|
||||
|
||||
if (geometry == GEOMETRY_128_64) {
|
||||
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<DISPLAY_BUFFER_SIZE; i++) {
|
||||
for (uint16_t i=0; i<displayBufferSize; i++) {
|
||||
SPI.transfer(buffer[i]);
|
||||
optimistic_yield(10000);
|
||||
yield();
|
||||
}
|
||||
digitalWrite(_cs, HIGH);
|
||||
#endif
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 by Daniel Eichhorn
|
||||
* Copyright (c) 2016 by Fabrice Weinberg
|
||||
* 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
|
||||
@ -22,7 +22,10 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
|
||||
* 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
|
||||
@ -36,9 +39,12 @@ class SSD1306Wire : public OLEDDisplay {
|
||||
uint8_t _address;
|
||||
uint8_t _sda;
|
||||
uint8_t _scl;
|
||||
bool _doI2cAutoInit = false;
|
||||
|
||||
public:
|
||||
SSD1306Wire(uint8_t _address, uint8_t _sda, uint8_t _scl) {
|
||||
SSD1306Wire(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;
|
||||
@ -53,19 +59,21 @@ class SSD1306Wire : public OLEDDisplay {
|
||||
}
|
||||
|
||||
void display(void) {
|
||||
initI2cIfNeccesary();
|
||||
const int x_offset = (128 - this->width()) / 2;
|
||||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
|
||||
uint8_t minBoundY = ~0;
|
||||
uint8_t minBoundY = UINT8_MAX;
|
||||
uint8_t maxBoundY = 0;
|
||||
|
||||
uint8_t minBoundX = ~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 < (DISPLAY_HEIGHT / 8); y++) {
|
||||
for (x = 0; x < DISPLAY_WIDTH; x++) {
|
||||
uint16_t pos = x + y * DISPLAY_WIDTH;
|
||||
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);
|
||||
@ -74,17 +82,18 @@ class SSD1306Wire : public OLEDDisplay {
|
||||
}
|
||||
buffer_back[pos] = buffer[pos];
|
||||
}
|
||||
optimistic_yield(10000);
|
||||
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 == ~0) return;
|
||||
|
||||
if (minBoundY == UINT8_MAX) return;
|
||||
|
||||
sendCommand(COLUMNADDR);
|
||||
sendCommand(minBoundX);
|
||||
sendCommand(maxBoundX);
|
||||
sendCommand(x_offset + minBoundX);
|
||||
sendCommand(x_offset + maxBoundX);
|
||||
|
||||
sendCommand(PAGEADDR);
|
||||
sendCommand(minBoundY);
|
||||
@ -97,14 +106,15 @@ class SSD1306Wire : public OLEDDisplay {
|
||||
Wire.beginTransmission(_address);
|
||||
Wire.write(0x40);
|
||||
}
|
||||
Wire.write(buffer[x + y * DISPLAY_WIDTH]);
|
||||
|
||||
Wire.write(buffer[x + y * this->width()]);
|
||||
k++;
|
||||
if (k == 16) {
|
||||
Wire.endTransmission();
|
||||
k = 0;
|
||||
}
|
||||
}
|
||||
optimistic_yield(10000);
|
||||
yield();
|
||||
}
|
||||
|
||||
if (k != 0) {
|
||||
@ -113,14 +123,20 @@ class SSD1306Wire : public OLEDDisplay {
|
||||
#else
|
||||
|
||||
sendCommand(COLUMNADDR);
|
||||
sendCommand(0x0);
|
||||
sendCommand(0x7F);
|
||||
sendCommand(x_offset);
|
||||
sendCommand(x_offset + (this->width() - 1));
|
||||
|
||||
sendCommand(PAGEADDR);
|
||||
sendCommand(0x0);
|
||||
sendCommand(0x7);
|
||||
sendCommand((this->height() / 8) - 1);
|
||||
|
||||
for (uint16_t i=0; i < DISPLAY_BUFFER_SIZE; i++) {
|
||||
if (geometry == GEOMETRY_128_64) {
|
||||
sendCommand(0x7);
|
||||
} else if (geometry == GEOMETRY_128_32) {
|
||||
sendCommand(0x3);
|
||||
}
|
||||
|
||||
for (uint16_t i=0; i < displayBufferSize; i++) {
|
||||
Wire.beginTransmission(this->_address);
|
||||
Wire.write(0x40);
|
||||
for (uint8_t x = 0; x < 16; x++) {
|
||||
@ -133,14 +149,24 @@ class SSD1306Wire : public OLEDDisplay {
|
||||
#endif
|
||||
}
|
||||
|
||||
void setI2cAutoInit(bool doI2cAutoInit) {
|
||||
_doI2cAutoInit = doI2cAutoInit;
|
||||
}
|
||||
|
||||
private:
|
||||
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) {
|
||||
Wire.begin(this->_sda, this->_scl);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -1,229 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
// 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 "SSD1306.h" // alias for `#include "SSD1306Wire.h"`
|
||||
// or #include "SH1106.h" alis for `#include "SH1106Wire.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
|
||||
SSD1306 display(0x3c, D3, D5);
|
||||
// SH1106 display(0x3c, D3, D5);
|
||||
|
||||
// Adapted from Adafruit_SSD1306
|
||||
void drawLines() {
|
||||
for (int16_t i=0; i<DISPLAY_WIDTH; i+=4) {
|
||||
display.drawLine(0, 0, i, DISPLAY_HEIGHT-1);
|
||||
display.display();
|
||||
delay(10);
|
||||
}
|
||||
for (int16_t i=0; i<DISPLAY_HEIGHT; i+=4) {
|
||||
display.drawLine(0, 0, DISPLAY_WIDTH-1, i);
|
||||
display.display();
|
||||
delay(10);
|
||||
}
|
||||
delay(250);
|
||||
|
||||
display.clear();
|
||||
for (int16_t i=0; i<DISPLAY_WIDTH; i+=4) {
|
||||
display.drawLine(0, DISPLAY_HEIGHT-1, i, 0);
|
||||
display.display();
|
||||
delay(10);
|
||||
}
|
||||
for (int16_t i=DISPLAY_HEIGHT-1; i>=0; i-=4) {
|
||||
display.drawLine(0, DISPLAY_HEIGHT-1, DISPLAY_WIDTH-1, i);
|
||||
display.display();
|
||||
delay(10);
|
||||
}
|
||||
delay(250);
|
||||
|
||||
display.clear();
|
||||
for (int16_t i=DISPLAY_WIDTH-1; i>=0; i-=4) {
|
||||
display.drawLine(DISPLAY_WIDTH-1, DISPLAY_HEIGHT-1, i, 0);
|
||||
display.display();
|
||||
delay(10);
|
||||
}
|
||||
for (int16_t i=DISPLAY_HEIGHT-1; i>=0; i-=4) {
|
||||
display.drawLine(DISPLAY_WIDTH-1, DISPLAY_HEIGHT-1, 0, i);
|
||||
display.display();
|
||||
delay(10);
|
||||
}
|
||||
delay(250);
|
||||
display.clear();
|
||||
for (int16_t i=0; i<DISPLAY_HEIGHT; i+=4) {
|
||||
display.drawLine(DISPLAY_WIDTH-1, 0, 0, i);
|
||||
display.display();
|
||||
delay(10);
|
||||
}
|
||||
for (int16_t i=0; i<DISPLAY_WIDTH; i+=4) {
|
||||
display.drawLine(DISPLAY_WIDTH-1, 0, i, DISPLAY_HEIGHT-1);
|
||||
display.display();
|
||||
delay(10);
|
||||
}
|
||||
delay(250);
|
||||
}
|
||||
|
||||
// Adapted from Adafruit_SSD1306
|
||||
void drawRect(void) {
|
||||
for (int16_t i=0; i<DISPLAY_HEIGHT/2; i+=2) {
|
||||
display.drawRect(i, i, DISPLAY_WIDTH-2*i, DISPLAY_HEIGHT-2*i);
|
||||
display.display();
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
// Adapted from Adafruit_SSD1306
|
||||
void fillRect(void) {
|
||||
uint8_t color = 1;
|
||||
for (int16_t i=0; i<DISPLAY_HEIGHT/2; i+=3) {
|
||||
display.setColor((color % 2 == 0) ? BLACK : WHITE); // alternate colors
|
||||
display.fillRect(i, i, DISPLAY_WIDTH - i*2, DISPLAY_HEIGHT - 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_HEIGHT; i+=2) {
|
||||
display.drawCircle(DISPLAY_WIDTH/2, DISPLAY_HEIGHT/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_WIDTH/2, DISPLAY_HEIGHT/2, DISPLAY_HEIGHT/4, 0b00000001);
|
||||
display.display();
|
||||
delay(200);
|
||||
display.drawCircleQuads(DISPLAY_WIDTH/2, DISPLAY_HEIGHT/2, DISPLAY_HEIGHT/4, 0b00000011);
|
||||
display.display();
|
||||
delay(200);
|
||||
display.drawCircleQuads(DISPLAY_WIDTH/2, DISPLAY_HEIGHT/2, DISPLAY_HEIGHT/4, 0b00000111);
|
||||
display.display();
|
||||
delay(200);
|
||||
display.drawCircleQuads(DISPLAY_WIDTH/2, DISPLAY_HEIGHT/2, DISPLAY_HEIGHT/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() { }
|