mirror of
https://github.com/nopnop2002/esp-idf-ssd1306.git
synced 2024-10-03 18:18:47 -04:00
Changed to components
This commit is contained in:
parent
24ddab1dc7
commit
dbb01f15f7
21
LICENSE
21
LICENSE
@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2020 nopnop2002
|
|
||||||
|
|
||||||
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.
|
|
9
Makefile
9
Makefile
@ -1,9 +0,0 @@
|
|||||||
#
|
|
||||||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
|
||||||
# project subdirectory.
|
|
||||||
#
|
|
||||||
|
|
||||||
PROJECT_NAME := ssd1306
|
|
||||||
|
|
||||||
include $(IDF_PATH)/make/project.mk
|
|
||||||
|
|
@ -2,5 +2,7 @@
|
|||||||
# in this exact order for cmake to work correctly
|
# in this exact order for cmake to work correctly
|
||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
set(EXTRA_COMPONENT_DIRS ../components/ssd1306)
|
||||||
|
|
||||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
project(ssd1306)
|
project(ssd1306)
|
4
TextDemo/main/CMakeLists.txt
Normal file
4
TextDemo/main/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
set(COMPONENT_SRCS "main.c")
|
||||||
|
set(COMPONENT_ADD_INCLUDEDIRS "")
|
||||||
|
|
||||||
|
register_component()
|
@ -66,6 +66,8 @@ void app_main(void)
|
|||||||
|
|
||||||
ssd1306_clear_screen(&dev, false);
|
ssd1306_clear_screen(&dev, false);
|
||||||
ssd1306_contrast(&dev, 0xff);
|
ssd1306_contrast(&dev, 0xff);
|
||||||
|
ssd1306_display_text_x3(&dev, 0, "Hello", 5, false);
|
||||||
|
vTaskDelay(3000 / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
#if CONFIG_SSD1306_128x64
|
#if CONFIG_SSD1306_128x64
|
||||||
top = 2;
|
top = 2;
|
||||||
@ -75,10 +77,10 @@ void app_main(void)
|
|||||||
ssd1306_display_text(&dev, 1, "ABCDEFGHIJKLMNOP", 16, false);
|
ssd1306_display_text(&dev, 1, "ABCDEFGHIJKLMNOP", 16, false);
|
||||||
ssd1306_display_text(&dev, 2, "abcdefghijklmnop",16, false);
|
ssd1306_display_text(&dev, 2, "abcdefghijklmnop",16, false);
|
||||||
ssd1306_display_text(&dev, 3, "Hello World!!", 13, false);
|
ssd1306_display_text(&dev, 3, "Hello World!!", 13, false);
|
||||||
ssd1306_clear_line(&dev, 4, true);
|
//ssd1306_clear_line(&dev, 4, true);
|
||||||
ssd1306_clear_line(&dev, 5, true);
|
//ssd1306_clear_line(&dev, 5, true);
|
||||||
ssd1306_clear_line(&dev, 6, true);
|
//ssd1306_clear_line(&dev, 6, true);
|
||||||
ssd1306_clear_line(&dev, 7, true);
|
//ssd1306_clear_line(&dev, 7, true);
|
||||||
ssd1306_display_text(&dev, 4, "SSD1306 128x64", 14, true);
|
ssd1306_display_text(&dev, 4, "SSD1306 128x64", 14, true);
|
||||||
ssd1306_display_text(&dev, 5, "ABCDEFGHIJKLMNOP", 16, true);
|
ssd1306_display_text(&dev, 5, "ABCDEFGHIJKLMNOP", 16, true);
|
||||||
ssd1306_display_text(&dev, 6, "abcdefghijklmnop",16, true);
|
ssd1306_display_text(&dev, 6, "abcdefghijklmnop",16, true);
|
||||||
@ -91,8 +93,8 @@ void app_main(void)
|
|||||||
bottom = 4;
|
bottom = 4;
|
||||||
ssd1306_display_text(&dev, 0, "SSD1306 128x32", 14, false);
|
ssd1306_display_text(&dev, 0, "SSD1306 128x32", 14, false);
|
||||||
ssd1306_display_text(&dev, 1, "Hello World!!", 13, false);
|
ssd1306_display_text(&dev, 1, "Hello World!!", 13, false);
|
||||||
ssd1306_clear_line(&dev, 2, true);
|
//ssd1306_clear_line(&dev, 2, true);
|
||||||
ssd1306_clear_line(&dev, 3, true);
|
//ssd1306_clear_line(&dev, 3, true);
|
||||||
ssd1306_display_text(&dev, 2, "SSD1306 128x32", 14, true);
|
ssd1306_display_text(&dev, 2, "SSD1306 128x32", 14, true);
|
||||||
ssd1306_display_text(&dev, 3, "Hello World!!", 13, true);
|
ssd1306_display_text(&dev, 3, "Hello World!!", 13, true);
|
||||||
#endif // CONFIG_SSD1306_128x32
|
#endif // CONFIG_SSD1306_128x32
|
5
components/ssd1306/CMakeLists.txt
Normal file
5
components/ssd1306/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
set(component_srcs "ssd1306.c" "ssd1306_i2c.c" "ssd1306_spi.c")
|
||||||
|
|
||||||
|
idf_component_register(SRCS "${component_srcs}"
|
||||||
|
PRIV_REQUIRES driver
|
||||||
|
INCLUDE_DIRS ".")
|
@ -1,5 +1,12 @@
|
|||||||
menu "SSD1306 Configuration"
|
menu "SSD1306 Configuration"
|
||||||
|
|
||||||
|
config GPIO_RANGE_MAX
|
||||||
|
int
|
||||||
|
default 33 if IDF_TARGET_ESP32
|
||||||
|
default 46 if IDF_TARGET_ESP32S2
|
||||||
|
default 19 if IDF_TARGET_ESP32C3
|
||||||
|
default 48 if IDF_TARGET_ESP32S3
|
||||||
|
|
||||||
choice INTERFACE
|
choice INTERFACE
|
||||||
prompt "Interface"
|
prompt "Interface"
|
||||||
default I2C_INTERFACE
|
default I2C_INTERFACE
|
||||||
@ -46,10 +53,11 @@ menu "SSD1306 Configuration"
|
|||||||
config SCL_GPIO
|
config SCL_GPIO
|
||||||
depends on I2C_INTERFACE
|
depends on I2C_INTERFACE
|
||||||
int "SCL GPIO number"
|
int "SCL GPIO number"
|
||||||
range 0 46
|
range 0 GPIO_RANGE_MAX
|
||||||
default 22 if IDF_TARGET_ESP32
|
default 22 if IIDF_TARGET_ESP32
|
||||||
default 12 if IDF_TARGET_ESP32S2
|
default 12 if IDF_TARGET_ESP32S2
|
||||||
default 9 if IDF_TARGET_ESP32C3
|
default 12 if IDF_TARGET_ESP32S3
|
||||||
|
default 9 if IDF_TARGET_ESP32C3
|
||||||
help
|
help
|
||||||
GPIO number (IOxx) to I2C SCL.
|
GPIO number (IOxx) to I2C SCL.
|
||||||
Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to I2C.
|
Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to I2C.
|
||||||
@ -58,9 +66,10 @@ menu "SSD1306 Configuration"
|
|||||||
config SDA_GPIO
|
config SDA_GPIO
|
||||||
depends on I2C_INTERFACE
|
depends on I2C_INTERFACE
|
||||||
int "SDA GPIO number"
|
int "SDA GPIO number"
|
||||||
range 0 46
|
range 0 GPIO_RANGE_MAX
|
||||||
default 21 if IDF_TARGET_ESP32
|
default 21 if IDF_TARGET_ESP32
|
||||||
default 11 if IDF_TARGET_ESP32S2
|
default 11 if IDF_TARGET_ESP32S2
|
||||||
|
default 11 if IDF_TARGET_ESP32S3
|
||||||
default 10 if IDF_TARGET_ESP32C3
|
default 10 if IDF_TARGET_ESP32C3
|
||||||
help
|
help
|
||||||
GPIO number (IOxx) to I2C SDA.
|
GPIO number (IOxx) to I2C SDA.
|
||||||
@ -69,8 +78,11 @@ menu "SSD1306 Configuration"
|
|||||||
|
|
||||||
config RESET_GPIO
|
config RESET_GPIO
|
||||||
int "RESET GPIO number"
|
int "RESET GPIO number"
|
||||||
range -1 46
|
range -1 GPIO_RANGE_MAX
|
||||||
default -1
|
default 33 if IDF_TARGET_ESP32
|
||||||
|
default 38 if IDF_TARGET_ESP32S2
|
||||||
|
default 38 if IDF_TARGET_ESP32S3
|
||||||
|
default 3 if IDF_TARGET_ESP32C3
|
||||||
help
|
help
|
||||||
GPIO number (IOxx) to RESET.
|
GPIO number (IOxx) to RESET.
|
||||||
When it is -1, RESET isn't performed.
|
When it is -1, RESET isn't performed.
|
||||||
@ -80,10 +92,11 @@ menu "SSD1306 Configuration"
|
|||||||
config MOSI_GPIO
|
config MOSI_GPIO
|
||||||
depends on SPI_INTERFACE
|
depends on SPI_INTERFACE
|
||||||
int "MOSI GPIO number"
|
int "MOSI GPIO number"
|
||||||
range 0 46
|
range 0 GPIO_RANGE_MAX
|
||||||
default 23 if IDF_TARGET_ESP32
|
default 23 if IDF_TARGET_ESP32
|
||||||
default 35 if IDF_TARGET_ESP32S2
|
default 35 if IDF_TARGET_ESP32S2
|
||||||
default 0 if IDF_TARGET_ESP32C3
|
default 35 if IDF_TARGET_ESP32S3
|
||||||
|
default 0 if IDF_TARGET_ESP32C3
|
||||||
help
|
help
|
||||||
GPIO number (IOxx) to SPI MOSI.
|
GPIO number (IOxx) to SPI MOSI.
|
||||||
Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to DC.
|
Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to DC.
|
||||||
@ -93,10 +106,11 @@ menu "SSD1306 Configuration"
|
|||||||
config SCLK_GPIO
|
config SCLK_GPIO
|
||||||
depends on SPI_INTERFACE
|
depends on SPI_INTERFACE
|
||||||
int "SCLK GPIO number"
|
int "SCLK GPIO number"
|
||||||
range 0 46
|
range 0 GPIO_RANGE_MAX
|
||||||
default 18 if IDF_TARGET_ESP32
|
default 18 if IDF_TARGET_ESP32
|
||||||
default 36 if IDF_TARGET_ESP32S2
|
default 36 if IDF_TARGET_ESP32S2
|
||||||
default 1 if IDF_TARGET_ESP32C3
|
default 36 if IDF_TARGET_ESP32S3
|
||||||
|
default 1 if IDF_TARGET_ESP32C3
|
||||||
help
|
help
|
||||||
GPIO number (IOxx) to SPI SCLK.
|
GPIO number (IOxx) to SPI SCLK.
|
||||||
Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to DC.
|
Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to DC.
|
||||||
@ -106,9 +120,10 @@ menu "SSD1306 Configuration"
|
|||||||
config CS_GPIO
|
config CS_GPIO
|
||||||
depends on SPI_INTERFACE
|
depends on SPI_INTERFACE
|
||||||
int "CS GPIO number"
|
int "CS GPIO number"
|
||||||
range 0 34
|
range 0 GPIO_RANGE_MAX
|
||||||
default 5 if IDF_TARGET_ESP32
|
default 5 if IDF_TARGET_ESP32
|
||||||
default 34 if IDF_TARGET_ESP32S2
|
default 34 if IDF_TARGET_ESP32S2
|
||||||
|
default 34 if IDF_TARGET_ESP32S3
|
||||||
default 10 if IDF_TARGET_ESP32C3
|
default 10 if IDF_TARGET_ESP32C3
|
||||||
help
|
help
|
||||||
GPIO number (IOxx) to SPI CS.
|
GPIO number (IOxx) to SPI CS.
|
||||||
@ -118,13 +133,15 @@ menu "SSD1306 Configuration"
|
|||||||
config DC_GPIO
|
config DC_GPIO
|
||||||
depends on SPI_INTERFACE
|
depends on SPI_INTERFACE
|
||||||
int "DC GPIO number"
|
int "DC GPIO number"
|
||||||
range 0 34
|
range 0 GPIO_RANGE_MAX
|
||||||
default 2
|
default 27 if IDF_TARGET_ESP32
|
||||||
|
default 37 if IDF_TARGET_ESP32S2
|
||||||
|
default 37 if IDF_TARGET_ESP32S3
|
||||||
|
default 2 if IDF_TARGET_ESP32C3
|
||||||
help
|
help
|
||||||
GPIO number (IOxx) to SPI DC.
|
GPIO number (IOxx) to SPI DC.
|
||||||
Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to DC.
|
Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to DC.
|
||||||
GPIOs 35-39 are input-only so cannot be used as outputs.
|
GPIOs 35-39 are input-only so cannot be used as outputs.
|
||||||
|
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
496
components/ssd1306/ssd1306.c
Normal file
496
components/ssd1306/ssd1306.c
Normal file
@ -0,0 +1,496 @@
|
|||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
|
||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
|
#include "ssd1306.h"
|
||||||
|
#include "font8x8_basic.h"
|
||||||
|
|
||||||
|
#define TAG "SSD1306"
|
||||||
|
|
||||||
|
#define PACK8 __attribute__((aligned( __alignof__( uint8_t ) ), packed ))
|
||||||
|
|
||||||
|
typedef union out_column_t {
|
||||||
|
uint32_t u32;
|
||||||
|
uint8_t u8[4];
|
||||||
|
} PACK8 out_column_t;
|
||||||
|
|
||||||
|
void ssd1306_init(SSD1306_t * dev, int width, int height)
|
||||||
|
{
|
||||||
|
if (dev->_address == SPIAddress) {
|
||||||
|
spi_init(dev, width, height);
|
||||||
|
} else {
|
||||||
|
i2c_init(dev, width, height);
|
||||||
|
}
|
||||||
|
// Initialize internal buffer
|
||||||
|
for (int i=0;i<dev->_pages;i++) {
|
||||||
|
memset(dev->_page[i]._segs, 0, 128);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ssd1306_get_width(SSD1306_t * dev)
|
||||||
|
{
|
||||||
|
return dev->_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ssd1306_get_height(SSD1306_t * dev)
|
||||||
|
{
|
||||||
|
return dev->_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ssd1306_get_pages(SSD1306_t * dev)
|
||||||
|
{
|
||||||
|
return dev->_pages;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssd1306_show_buffer(SSD1306_t * dev)
|
||||||
|
{
|
||||||
|
if (dev->_address == SPIAddress) {
|
||||||
|
for (int page=0; page<dev->_pages;page++) {
|
||||||
|
spi_display_image(dev, page, 0, dev->_page[page]._segs, dev->_width);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int page=0; page<dev->_pages;page++) {
|
||||||
|
i2c_display_image(dev, page, 0, dev->_page[page]._segs, dev->_width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssd1306_display_image(SSD1306_t * dev, int page, int seg, uint8_t * images, int width)
|
||||||
|
{
|
||||||
|
if (dev->_address == SPIAddress) {
|
||||||
|
spi_display_image(dev, page, seg, images, width);
|
||||||
|
} else {
|
||||||
|
i2c_display_image(dev, page, seg, images, width);
|
||||||
|
}
|
||||||
|
// Set to internal buffer
|
||||||
|
memcpy(&dev->_page[page]._segs[seg], images, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssd1306_display_text(SSD1306_t * dev, int page, char * text, int text_len, bool invert)
|
||||||
|
{
|
||||||
|
if (page >= dev->_pages) return;
|
||||||
|
int _text_len = text_len;
|
||||||
|
if (_text_len > 16) _text_len = 16;
|
||||||
|
|
||||||
|
uint8_t seg = 0;
|
||||||
|
uint8_t image[8];
|
||||||
|
for (uint8_t i = 0; i < _text_len; i++) {
|
||||||
|
memcpy(image, font8x8_basic_tr[(uint8_t)text[i]], 8);
|
||||||
|
if (invert) ssd1306_invert(image, 8);
|
||||||
|
if (dev->_flip) ssd1306_flip(image, 8);
|
||||||
|
ssd1306_display_image(dev, page, seg, image, 8);
|
||||||
|
#if 0
|
||||||
|
if (dev->_address == SPIAddress) {
|
||||||
|
spi_display_image(dev, page, seg, image, 8);
|
||||||
|
} else {
|
||||||
|
i2c_display_image(dev, page, seg, image, 8);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
seg = seg + 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// by Coert Vonk
|
||||||
|
void
|
||||||
|
ssd1306_display_text_x3(SSD1306_t * dev, int page, char * text, int text_len, bool invert)
|
||||||
|
{
|
||||||
|
if (page >= dev->_pages) return;
|
||||||
|
int _text_len = text_len;
|
||||||
|
if (_text_len > 5) _text_len = 5;
|
||||||
|
|
||||||
|
uint8_t seg = 0;
|
||||||
|
|
||||||
|
for (uint8_t nn = 0; nn < _text_len; nn++) {
|
||||||
|
|
||||||
|
uint8_t const * const in_columns = font8x8_basic_tr[(uint8_t)text[nn]];
|
||||||
|
|
||||||
|
// make the character 3x as high
|
||||||
|
out_column_t out_columns[8];
|
||||||
|
memset(out_columns, 0, sizeof(out_columns));
|
||||||
|
|
||||||
|
for (uint8_t xx = 0; xx < 8; xx++) { // for each column (x-direction)
|
||||||
|
|
||||||
|
uint32_t in_bitmask = 0b1;
|
||||||
|
uint32_t out_bitmask = 0b111;
|
||||||
|
|
||||||
|
for (uint8_t yy = 0; yy < 8; yy++) { // for pixel (y-direction)
|
||||||
|
if (in_columns[xx] & in_bitmask) {
|
||||||
|
out_columns[xx].u32 |= out_bitmask;
|
||||||
|
}
|
||||||
|
in_bitmask <<= 1;
|
||||||
|
out_bitmask <<= 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// render character in 8 column high pieces, making them 3x as wide
|
||||||
|
for (uint8_t yy = 0; yy < 3; yy++) { // for each group of 8 pixels high (y-direction)
|
||||||
|
|
||||||
|
uint8_t image[24];
|
||||||
|
for (uint8_t xx = 0; xx < 8; xx++) { // for each column (x-direction)
|
||||||
|
image[xx*3+0] =
|
||||||
|
image[xx*3+1] =
|
||||||
|
image[xx*3+2] = out_columns[xx].u8[yy];
|
||||||
|
}
|
||||||
|
if (invert) ssd1306_invert(image, 24);
|
||||||
|
if (dev->_flip) ssd1306_flip(image, 24);
|
||||||
|
if (dev->_address == SPIAddress) {
|
||||||
|
spi_display_image(dev, page+yy, seg, image, 24);
|
||||||
|
} else {
|
||||||
|
i2c_display_image(dev, page+yy, seg, image, 24);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
seg = seg + 24;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssd1306_clear_screen(SSD1306_t * dev, bool invert)
|
||||||
|
{
|
||||||
|
char space[16];
|
||||||
|
memset(space, 0x20, sizeof(space));
|
||||||
|
for (int page = 0; page < dev->_pages; page++) {
|
||||||
|
ssd1306_display_text(dev, page, space, sizeof(space), invert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssd1306_clear_line(SSD1306_t * dev, int page, bool invert)
|
||||||
|
{
|
||||||
|
char space[16];
|
||||||
|
memset(space, 0x20, sizeof(space));
|
||||||
|
ssd1306_display_text(dev, page, space, sizeof(space), invert);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssd1306_contrast(SSD1306_t * dev, int contrast)
|
||||||
|
{
|
||||||
|
if (dev->_address == SPIAddress) {
|
||||||
|
spi_contrast(dev, contrast);
|
||||||
|
} else {
|
||||||
|
i2c_contrast(dev, contrast);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssd1306_software_scroll(SSD1306_t * dev, int start, int end)
|
||||||
|
{
|
||||||
|
ESP_LOGD(TAG, "software_scroll start=%d end=%d _pages=%d", start, end, dev->_pages);
|
||||||
|
if (start < 0 || end < 0) {
|
||||||
|
dev->_scEnable = false;
|
||||||
|
} else if (start >= dev->_pages || end >= dev->_pages) {
|
||||||
|
dev->_scEnable = false;
|
||||||
|
} else {
|
||||||
|
dev->_scEnable = true;
|
||||||
|
dev->_scStart = start;
|
||||||
|
dev->_scEnd = end;
|
||||||
|
dev->_scDirection = 1;
|
||||||
|
if (start > end ) dev->_scDirection = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ssd1306_scroll_text(SSD1306_t * dev, char * text, int text_len, bool invert)
|
||||||
|
{
|
||||||
|
ESP_LOGD(TAG, "dev->_scEnable=%d", dev->_scEnable);
|
||||||
|
if (dev->_scEnable == false) return;
|
||||||
|
|
||||||
|
void (*func)(SSD1306_t * dev, int page, int seg, uint8_t * images, int width);
|
||||||
|
if (dev->_address == SPIAddress) {
|
||||||
|
func = spi_display_image;
|
||||||
|
} else {
|
||||||
|
func = i2c_display_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
int srcIndex = dev->_scEnd - dev->_scDirection;
|
||||||
|
while(1) {
|
||||||
|
int dstIndex = srcIndex + dev->_scDirection;
|
||||||
|
ESP_LOGD(TAG, "srcIndex=%d dstIndex=%d", srcIndex,dstIndex);
|
||||||
|
for(int seg = 0; seg < dev->_width; seg++) {
|
||||||
|
dev->_page[dstIndex]._segs[seg] = dev->_page[srcIndex]._segs[seg];
|
||||||
|
}
|
||||||
|
(*func)(dev, dstIndex, 0, dev->_page[dstIndex]._segs, sizeof(dev->_page[dstIndex]._segs));
|
||||||
|
if (srcIndex == dev->_scStart) break;
|
||||||
|
srcIndex = srcIndex - dev->_scDirection;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _text_len = text_len;
|
||||||
|
if (_text_len > 16) _text_len = 16;
|
||||||
|
|
||||||
|
ssd1306_display_text(dev, srcIndex, text, text_len, invert);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssd1306_scroll_clear(SSD1306_t * dev)
|
||||||
|
{
|
||||||
|
ESP_LOGD(TAG, "dev->_scEnable=%d", dev->_scEnable);
|
||||||
|
if (dev->_scEnable == false) return;
|
||||||
|
|
||||||
|
int srcIndex = dev->_scEnd - dev->_scDirection;
|
||||||
|
while(1) {
|
||||||
|
int dstIndex = srcIndex + dev->_scDirection;
|
||||||
|
ESP_LOGD(TAG, "srcIndex=%d dstIndex=%d", srcIndex,dstIndex);
|
||||||
|
ssd1306_clear_line(dev, dstIndex, false);
|
||||||
|
if (dstIndex == dev->_scStart) break;
|
||||||
|
srcIndex = srcIndex - dev->_scDirection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ssd1306_hardware_scroll(SSD1306_t * dev, ssd1306_scroll_type_t scroll)
|
||||||
|
{
|
||||||
|
if (dev->_address == SPIAddress) {
|
||||||
|
spi_hardware_scroll(dev, scroll);
|
||||||
|
} else {
|
||||||
|
i2c_hardware_scroll(dev, scroll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssd1306_rotate(SSD1306_t * dev, ssd1306_scroll_type_t scroll, int start, int end, uint8_t delay)
|
||||||
|
{
|
||||||
|
if (scroll == SCROLL_RIGHT) {
|
||||||
|
int _start = start; // 0 to 7
|
||||||
|
int _end = end; // 0 to 7
|
||||||
|
if (_end >= dev->_pages) _end = dev->_pages - 1;
|
||||||
|
uint8_t wk;
|
||||||
|
//for (int page=0;page<dev->_pages;page++) {
|
||||||
|
for (int page=_start;page<=_end;page++) {
|
||||||
|
wk = dev->_page[page]._segs[127];
|
||||||
|
for (int seg=127;seg>0;seg--) {
|
||||||
|
dev->_page[page]._segs[seg] = dev->_page[page]._segs[seg-1];
|
||||||
|
}
|
||||||
|
dev->_page[page]._segs[0] = wk;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (scroll == SCROLL_LEFT) {
|
||||||
|
int _start = start; // 0 to 7
|
||||||
|
int _end = end; // 0 to 7
|
||||||
|
if (_end >= dev->_pages) _end = dev->_pages - 1;
|
||||||
|
uint8_t wk;
|
||||||
|
//for (int page=0;page<dev->_pages;page++) {
|
||||||
|
for (int page=_start;page<=_end;page++) {
|
||||||
|
wk = dev->_page[page]._segs[0];
|
||||||
|
for (int seg=0;seg<127;seg++) {
|
||||||
|
dev->_page[page]._segs[seg] = dev->_page[page]._segs[seg+1];
|
||||||
|
}
|
||||||
|
dev->_page[page]._segs[127] = wk;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (scroll == SCROLL_UP) {
|
||||||
|
int _start = start; // 0 to {width-1}
|
||||||
|
int _end = end; // 0 to {width-1}
|
||||||
|
if (_end >= dev->_width) _end = dev->_width - 1;
|
||||||
|
uint8_t wk0;
|
||||||
|
uint8_t wk1;
|
||||||
|
uint8_t wk2;
|
||||||
|
uint8_t save[128];
|
||||||
|
// Save pages 0
|
||||||
|
for (int seg=0;seg<128;seg++) {
|
||||||
|
save[seg] = dev->_page[0]._segs[seg];
|
||||||
|
}
|
||||||
|
// Page0 to Page6
|
||||||
|
for (int page=0;page<dev->_pages-1;page++) {
|
||||||
|
//for (int seg=0;seg<128;seg++) {
|
||||||
|
for (int seg=_start;seg<=_end;seg++) {
|
||||||
|
wk0 = dev->_page[page]._segs[seg];
|
||||||
|
wk1 = dev->_page[page+1]._segs[seg];
|
||||||
|
if (seg == 0) {
|
||||||
|
ESP_LOGD(TAG, "b page=%d wk0=%02x wk1=%02x", page, wk0, wk1);
|
||||||
|
}
|
||||||
|
wk0 = wk0 >> 1;
|
||||||
|
wk1 = wk1 & 0x01;
|
||||||
|
wk1 = wk1 << 7;
|
||||||
|
wk2 = wk0 | wk1;
|
||||||
|
if (seg == 0) {
|
||||||
|
ESP_LOGD(TAG, "a page=%d wk0=%02x wk1=%02x wk2=%02x", page, wk0, wk1, wk2);
|
||||||
|
}
|
||||||
|
dev->_page[page]._segs[seg] = wk2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Page7
|
||||||
|
int pages = dev->_pages-1;
|
||||||
|
//for (int seg=0;seg<128;seg++) {
|
||||||
|
for (int seg=_start;seg<=_end;seg++) {
|
||||||
|
wk0 = dev->_page[pages]._segs[seg];
|
||||||
|
wk1 = save[seg];
|
||||||
|
wk0 = wk0 >> 1;
|
||||||
|
wk1 = wk1 & 0x01;
|
||||||
|
wk1 = wk1 << 7;
|
||||||
|
wk2 = wk0 | wk1;
|
||||||
|
dev->_page[pages]._segs[seg] = wk2;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (scroll == SCROLL_DOWN) {
|
||||||
|
int _start = start; // 0 to {width-1}
|
||||||
|
int _end = end; // 0 to {width-1}
|
||||||
|
if (_end >= dev->_width) _end = dev->_width - 1;
|
||||||
|
uint8_t wk0;
|
||||||
|
uint8_t wk1;
|
||||||
|
uint8_t wk2;
|
||||||
|
uint8_t save[128];
|
||||||
|
// Save pages 7
|
||||||
|
int pages = dev->_pages-1;
|
||||||
|
for (int seg=0;seg<128;seg++) {
|
||||||
|
save[seg] = dev->_page[pages]._segs[seg];
|
||||||
|
}
|
||||||
|
// Page7 to Page1
|
||||||
|
for (int page=pages;page>0;page--) {
|
||||||
|
//for (int seg=0;seg<128;seg++) {
|
||||||
|
for (int seg=_start;seg<=_end;seg++) {
|
||||||
|
wk0 = dev->_page[page]._segs[seg];
|
||||||
|
wk1 = dev->_page[page-1]._segs[seg];
|
||||||
|
if (seg == 0) {
|
||||||
|
ESP_LOGD(TAG, "b page=%d wk0=%02x wk1=%02x", page, wk0, wk1);
|
||||||
|
}
|
||||||
|
wk0 = wk0 << 1;
|
||||||
|
wk1 = wk1 & 0x80;
|
||||||
|
wk1 = wk1 >> 7;
|
||||||
|
wk2 = wk0 | wk1;
|
||||||
|
if (seg == 0) {
|
||||||
|
ESP_LOGD(TAG, "a page=%d wk0=%02x wk1=%02x wk2=%02x", page, wk0, wk1, wk2);
|
||||||
|
}
|
||||||
|
dev->_page[page]._segs[seg] = wk2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Page0
|
||||||
|
//for (int seg=0;seg<128;seg++) {
|
||||||
|
for (int seg=_start;seg<=_end;seg++) {
|
||||||
|
wk0 = dev->_page[0]._segs[seg];
|
||||||
|
wk1 = save[seg];
|
||||||
|
wk0 = wk0 << 1;
|
||||||
|
wk1 = wk1 & 0x80;
|
||||||
|
wk1 = wk1 >> 7;
|
||||||
|
wk2 = wk0 | wk1;
|
||||||
|
dev->_page[0]._segs[seg] = wk2;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int page=0;page<dev->_pages;page++) {
|
||||||
|
if (dev->_address == SPIAddress) {
|
||||||
|
spi_display_image(dev, page, 0, dev->_page[page]._segs, 128);
|
||||||
|
} else {
|
||||||
|
i2c_display_image(dev, page, 0, dev->_page[page]._segs, 128);
|
||||||
|
}
|
||||||
|
if (delay) vTaskDelay(delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssd1306_bitmaps(SSD1306_t * dev, int xpos, int ypos, uint8_t * bitmap, int width, int height)
|
||||||
|
{
|
||||||
|
uint8_t wk0;
|
||||||
|
uint8_t wk1;
|
||||||
|
uint8_t page = (ypos / 8);
|
||||||
|
uint8_t _seg = xpos;
|
||||||
|
uint8_t dstBits = (ypos % 8);
|
||||||
|
ESP_LOGI(TAG, "ypos=%d page=%d dstBits=%d", ypos, page, dstBits);
|
||||||
|
int offset = 0;
|
||||||
|
for(int _height=0;_height<height;_height++) {
|
||||||
|
for (int index=0;index<width;index++) {
|
||||||
|
for (int srcBits=7; srcBits>=0; srcBits--) {
|
||||||
|
wk0 = dev->_page[page]._segs[_seg];
|
||||||
|
wk1 = ssd1306_copy_bit(bitmap[index+offset], srcBits, wk0, dstBits);
|
||||||
|
ESP_LOGD(TAG, "index=%d offset=%d page=%d _seg=%d, wk1=%02x", index, offset, page, _seg, wk1);
|
||||||
|
dev->_page[page]._segs[_seg] = wk1;
|
||||||
|
_seg++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vTaskDelay(1);
|
||||||
|
offset = offset + width;
|
||||||
|
dstBits++;
|
||||||
|
_seg = xpos;
|
||||||
|
if (dstBits == 8) {
|
||||||
|
page++;
|
||||||
|
dstBits=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
for (int _seg=ypos;_seg<ypos+width*8;_seg++) {
|
||||||
|
ssd1306_dump_page(dev, page-1, _seg);
|
||||||
|
}
|
||||||
|
for (int _seg=ypos;_seg<ypos+width*8;_seg++) {
|
||||||
|
ssd1306_dump_page(dev, page, _seg);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ssd1306_show_buffer(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssd1306_invert(uint8_t *buf, size_t blen)
|
||||||
|
{
|
||||||
|
uint8_t wk;
|
||||||
|
for(int i=0; i<blen; i++){
|
||||||
|
wk = buf[i];
|
||||||
|
buf[i] = ~wk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flip upside down
|
||||||
|
void ssd1306_flip(uint8_t *buf, size_t blen)
|
||||||
|
{
|
||||||
|
for(int i=0; i<blen; i++){
|
||||||
|
buf[i] = ssd1306_rotate_byte(buf[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ssd1306_copy_bit(uint8_t src, int srcBits, uint8_t dst, int dstBits)
|
||||||
|
{
|
||||||
|
ESP_LOGD(TAG, "src=%02x srcBits=%d dst=%02x dstBits=%d", src, srcBits, dst, dstBits);
|
||||||
|
uint8_t smask = 0x01 << srcBits;
|
||||||
|
uint8_t _src = src & smask;
|
||||||
|
if (_src != 0) _src = 1;
|
||||||
|
uint8_t _wk = _src << dstBits;
|
||||||
|
uint8_t _dst = dst | _wk;
|
||||||
|
return _dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Rotate 8-bit data
|
||||||
|
// 0x12-->0x48
|
||||||
|
uint8_t ssd1306_rotate_byte(uint8_t ch1) {
|
||||||
|
uint8_t ch2 = 0;
|
||||||
|
for (int j=0;j<8;j++) {
|
||||||
|
ch2 = (ch2 << 1) + (ch1 & 0x01);
|
||||||
|
ch1 = ch1 >> 1;
|
||||||
|
}
|
||||||
|
return ch2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ssd1306_fadeout(SSD1306_t * dev)
|
||||||
|
{
|
||||||
|
void (*func)(SSD1306_t * dev, int page, int seg, uint8_t * images, int width);
|
||||||
|
if (dev->_address == SPIAddress) {
|
||||||
|
func = spi_display_image;
|
||||||
|
} else {
|
||||||
|
func = i2c_display_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t image[1];
|
||||||
|
for(int page=0; page<dev->_pages; page++) {
|
||||||
|
image[0] = 0xFF;
|
||||||
|
for(int line=0; line<8; line++) {
|
||||||
|
if (dev->_flip) {
|
||||||
|
image[0] = image[0] >> 1;
|
||||||
|
} else {
|
||||||
|
image[0] = image[0] << 1;
|
||||||
|
}
|
||||||
|
for(int seg=0; seg<128; seg++) {
|
||||||
|
(*func)(dev, page, seg, image, 1);
|
||||||
|
dev->_page[page]._segs[seg] = image[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssd1306_dump(SSD1306_t dev)
|
||||||
|
{
|
||||||
|
printf("_address=%x\n",dev._address);
|
||||||
|
printf("_width=%x\n",dev._width);
|
||||||
|
printf("_height=%x\n",dev._height);
|
||||||
|
printf("_pages=%x\n",dev._pages);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssd1306_dump_page(SSD1306_t * dev, int page, int seg)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "dev->_page[%d]._segs[%d]=%02x", page, seg, dev->_page[page]._segs[seg]);
|
||||||
|
}
|
||||||
|
|
@ -80,8 +80,8 @@ typedef enum {
|
|||||||
} ssd1306_scroll_type_t;
|
} ssd1306_scroll_type_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool _valid;
|
bool _valid; // Not using it anymore
|
||||||
int _segLen; // 0-128
|
int _segLen; // Not using it anymore
|
||||||
uint8_t _segs[128];
|
uint8_t _segs[128];
|
||||||
} PAGE_t;
|
} PAGE_t;
|
||||||
|
|
||||||
@ -101,8 +101,13 @@ typedef struct {
|
|||||||
} SSD1306_t;
|
} SSD1306_t;
|
||||||
|
|
||||||
void ssd1306_init(SSD1306_t * dev, int width, int height);
|
void ssd1306_init(SSD1306_t * dev, int width, int height);
|
||||||
void ssd1306_display_text(SSD1306_t * dev, int page, char * text, int text_len, bool invert);
|
int ssd1306_get_width(SSD1306_t * dev);
|
||||||
|
int ssd1306_get_height(SSD1306_t * dev);
|
||||||
|
int ssd1306_get_pages(SSD1306_t * dev);
|
||||||
|
void ssd1306_show_buffer(SSD1306_t * dev);
|
||||||
void ssd1306_display_image(SSD1306_t * dev, int page, int seg, uint8_t * images, int width);
|
void ssd1306_display_image(SSD1306_t * dev, int page, int seg, uint8_t * images, int width);
|
||||||
|
void ssd1306_display_text(SSD1306_t * dev, int page, char * text, int text_len, bool invert);
|
||||||
|
void ssd1306_display_text_x3(SSD1306_t * dev, int page, char * text, int text_len, bool invert);
|
||||||
void ssd1306_clear_screen(SSD1306_t * dev, bool invert);
|
void ssd1306_clear_screen(SSD1306_t * dev, bool invert);
|
||||||
void ssd1306_clear_line(SSD1306_t * dev, int page, bool invert);
|
void ssd1306_clear_line(SSD1306_t * dev, int page, bool invert);
|
||||||
void ssd1306_contrast(SSD1306_t * dev, int contrast);
|
void ssd1306_contrast(SSD1306_t * dev, int contrast);
|
||||||
@ -110,11 +115,15 @@ void ssd1306_software_scroll(SSD1306_t * dev, int start, int end);
|
|||||||
void ssd1306_scroll_text(SSD1306_t * dev, char * text, int text_len, bool invert);
|
void ssd1306_scroll_text(SSD1306_t * dev, char * text, int text_len, bool invert);
|
||||||
void ssd1306_scroll_clear(SSD1306_t * dev);
|
void ssd1306_scroll_clear(SSD1306_t * dev);
|
||||||
void ssd1306_hardware_scroll(SSD1306_t * dev, ssd1306_scroll_type_t scroll);
|
void ssd1306_hardware_scroll(SSD1306_t * dev, ssd1306_scroll_type_t scroll);
|
||||||
|
void ssd1306_rotate(SSD1306_t * dev, ssd1306_scroll_type_t scroll, int start, int end, uint8_t delay);
|
||||||
|
void ssd1306_bitmaps(SSD1306_t * dev, int xpos, int ypos, uint8_t * bitmap, int width, int height);
|
||||||
void ssd1306_invert(uint8_t *buf, size_t blen);
|
void ssd1306_invert(uint8_t *buf, size_t blen);
|
||||||
void ssd1306_flip(uint8_t *buf, size_t blen);
|
void ssd1306_flip(uint8_t *buf, size_t blen);
|
||||||
uint8_t ssd1306_rotate(uint8_t ch1);
|
uint8_t ssd1306_copy_bit(uint8_t src, int srcBits, uint8_t dst, int dstBits);
|
||||||
|
uint8_t ssd1306_rotate_byte(uint8_t ch1);
|
||||||
void ssd1306_fadeout(SSD1306_t * dev);
|
void ssd1306_fadeout(SSD1306_t * dev);
|
||||||
void ssd1306_dump(SSD1306_t dev);
|
void ssd1306_dump(SSD1306_t dev);
|
||||||
|
void ssd1306_dump_page(SSD1306_t * dev, int page, int seg);
|
||||||
|
|
||||||
void i2c_master_init(SSD1306_t * dev, int16_t sda, int16_t scl, int16_t reset);
|
void i2c_master_init(SSD1306_t * dev, int16_t sda, int16_t scl, int16_t reset);
|
||||||
void i2c_init(SSD1306_t * dev, int width, int height);
|
void i2c_init(SSD1306_t * dev, int width, int height);
|
@ -12,11 +12,13 @@
|
|||||||
#define tag "SSD1306"
|
#define tag "SSD1306"
|
||||||
|
|
||||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||||
#define LCD_HOST HSPI_HOST
|
#define LCD_HOST HSPI_HOST
|
||||||
#elif defined CONFIG_IDF_TARGET_ESP32S2
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
#define LCD_HOST SPI2_HOST
|
#define LCD_HOST SPI2_HOST
|
||||||
#elif defined CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
#define LCD_HOST SPI2_HOST
|
#define LCD_HOST SPI2_HOST
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#define LCD_HOST SPI2_HOST
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const int SPI_Command_Mode = 0;
|
static const int SPI_Command_Mode = 0;
|
@ -1,4 +0,0 @@
|
|||||||
set(COMPONENT_SRCS main.c ssd1306.c ssd1306_i2c.c ssd1306_spi.c)
|
|
||||||
set(COMPONENT_ADD_INCLUDEDIRS ".")
|
|
||||||
|
|
||||||
register_component()
|
|
229
main/ssd1306.c
229
main/ssd1306.c
@ -1,229 +0,0 @@
|
|||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
|
|
||||||
#include "esp_log.h"
|
|
||||||
|
|
||||||
#include "ssd1306.h"
|
|
||||||
#include "font8x8_basic.h"
|
|
||||||
|
|
||||||
#define tag "SSD1306"
|
|
||||||
|
|
||||||
void ssd1306_init(SSD1306_t * dev, int width, int height)
|
|
||||||
{
|
|
||||||
if (dev->_address == SPIAddress) {
|
|
||||||
spi_init(dev, width, height);
|
|
||||||
} else {
|
|
||||||
i2c_init(dev, width, height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ssd1306_display_text(SSD1306_t * dev, int page, char * text, int text_len, bool invert)
|
|
||||||
{
|
|
||||||
if (page >= dev->_pages) return;
|
|
||||||
int _text_len = text_len;
|
|
||||||
if (_text_len > 16) _text_len = 16;
|
|
||||||
|
|
||||||
uint8_t seg = 0;
|
|
||||||
uint8_t image[8];
|
|
||||||
for (uint8_t i = 0; i < _text_len; i++) {
|
|
||||||
memcpy(image, font8x8_basic_tr[(uint8_t)text[i]], 8);
|
|
||||||
if (invert) ssd1306_invert(image, 8);
|
|
||||||
if (dev->_flip) ssd1306_flip(image, 8);
|
|
||||||
if (dev->_address == SPIAddress) {
|
|
||||||
spi_display_image(dev, page, seg, image, 8);
|
|
||||||
} else {
|
|
||||||
i2c_display_image(dev, page, seg, image, 8);
|
|
||||||
}
|
|
||||||
seg = seg + 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ssd1306_display_image(SSD1306_t * dev, int page, int seg, uint8_t * images, int width)
|
|
||||||
{
|
|
||||||
if (dev->_address == SPIAddress) {
|
|
||||||
spi_display_image(dev, page, seg, images, width);
|
|
||||||
} else {
|
|
||||||
i2c_display_image(dev, page, seg, images, width);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ssd1306_clear_screen(SSD1306_t * dev, bool invert)
|
|
||||||
{
|
|
||||||
char space[16];
|
|
||||||
memset(space, 0x20, sizeof(space));
|
|
||||||
for (int page = 0; page < dev->_pages; page++) {
|
|
||||||
ssd1306_display_text(dev, page, space, sizeof(space), invert);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ssd1306_clear_line(SSD1306_t * dev, int page, bool invert)
|
|
||||||
{
|
|
||||||
char space[16];
|
|
||||||
memset(space, 0x20, sizeof(space));
|
|
||||||
ssd1306_display_text(dev, page, space, sizeof(space), invert);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ssd1306_contrast(SSD1306_t * dev, int contrast)
|
|
||||||
{
|
|
||||||
if (dev->_address == SPIAddress) {
|
|
||||||
spi_contrast(dev, contrast);
|
|
||||||
} else {
|
|
||||||
i2c_contrast(dev, contrast);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ssd1306_software_scroll(SSD1306_t * dev, int start, int end)
|
|
||||||
{
|
|
||||||
ESP_LOGD(tag, "software_scroll start=%d end=%d _pages=%d", start, end, dev->_pages);
|
|
||||||
if (start < 0 || end < 0) {
|
|
||||||
dev->_scEnable = false;
|
|
||||||
} else if (start >= dev->_pages || end >= dev->_pages) {
|
|
||||||
dev->_scEnable = false;
|
|
||||||
} else {
|
|
||||||
dev->_scEnable = true;
|
|
||||||
dev->_scStart = start;
|
|
||||||
dev->_scEnd = end;
|
|
||||||
dev->_scDirection = 1;
|
|
||||||
if (start > end ) dev->_scDirection = -1;
|
|
||||||
for (int i=0;i<dev->_pages;i++) {
|
|
||||||
dev->_page[i]._valid = false;
|
|
||||||
dev->_page[i]._segLen = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ssd1306_scroll_text(SSD1306_t * dev, char * text, int text_len, bool invert)
|
|
||||||
{
|
|
||||||
ESP_LOGD(tag, "dev->_scEnable=%d", dev->_scEnable);
|
|
||||||
if (dev->_scEnable == false) return;
|
|
||||||
|
|
||||||
void (*func)(SSD1306_t * dev, int page, int seg, uint8_t * images, int width);
|
|
||||||
if (dev->_address == SPIAddress) {
|
|
||||||
func = spi_display_image;
|
|
||||||
} else {
|
|
||||||
func = i2c_display_image;
|
|
||||||
}
|
|
||||||
|
|
||||||
int srcIndex = dev->_scEnd - dev->_scDirection;
|
|
||||||
while(1) {
|
|
||||||
int dstIndex = srcIndex + dev->_scDirection;
|
|
||||||
ESP_LOGD(tag, "srcIndex=%d dstIndex=%d", srcIndex,dstIndex);
|
|
||||||
dev->_page[dstIndex]._valid = dev->_page[srcIndex]._valid;
|
|
||||||
dev->_page[dstIndex]._segLen = dev->_page[srcIndex]._segLen;
|
|
||||||
for(int seg = 0; seg < dev->_width; seg++) {
|
|
||||||
dev->_page[dstIndex]._segs[seg] = dev->_page[srcIndex]._segs[seg];
|
|
||||||
}
|
|
||||||
ESP_LOGD(tag, "_valid=%d", dev->_page[dstIndex]._valid);
|
|
||||||
if (dev->_page[dstIndex]._valid) (*func)(dev, dstIndex, 0, dev->_page[dstIndex]._segs, dev->_page[srcIndex]._segLen);
|
|
||||||
if (srcIndex == dev->_scStart) break;
|
|
||||||
srcIndex = srcIndex - dev->_scDirection;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _text_len = text_len;
|
|
||||||
if (_text_len > 16) _text_len = 16;
|
|
||||||
|
|
||||||
uint8_t seg = 0;
|
|
||||||
uint8_t image[8];
|
|
||||||
for (uint8_t i = 0; i < _text_len; i++) {
|
|
||||||
memcpy(image, font8x8_basic_tr[(uint8_t)text[i]], 8);
|
|
||||||
if (invert) ssd1306_invert(image, 8);
|
|
||||||
if (dev->_flip) ssd1306_flip(image, 8);
|
|
||||||
(*func)(dev, srcIndex, seg, image, 8);
|
|
||||||
for(int j=0;j<8;j++) dev->_page[srcIndex]._segs[seg+j] = image[j];
|
|
||||||
seg = seg + 8;
|
|
||||||
}
|
|
||||||
dev->_page[srcIndex]._valid = true;
|
|
||||||
dev->_page[srcIndex]._segLen = seg;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ssd1306_scroll_clear(SSD1306_t * dev)
|
|
||||||
{
|
|
||||||
ESP_LOGD(tag, "dev->_scEnable=%d", dev->_scEnable);
|
|
||||||
if (dev->_scEnable == false) return;
|
|
||||||
|
|
||||||
int srcIndex = dev->_scEnd - dev->_scDirection;
|
|
||||||
while(1) {
|
|
||||||
int dstIndex = srcIndex + dev->_scDirection;
|
|
||||||
ESP_LOGD(tag, "srcIndex=%d dstIndex=%d", srcIndex,dstIndex);
|
|
||||||
ssd1306_clear_line(dev, dstIndex, false);
|
|
||||||
dev->_page[dstIndex]._valid = false;
|
|
||||||
if (dstIndex == dev->_scStart) break;
|
|
||||||
srcIndex = srcIndex - dev->_scDirection;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ssd1306_hardware_scroll(SSD1306_t * dev, ssd1306_scroll_type_t scroll)
|
|
||||||
{
|
|
||||||
if (dev->_address == SPIAddress) {
|
|
||||||
spi_hardware_scroll(dev, scroll);
|
|
||||||
} else {
|
|
||||||
i2c_hardware_scroll(dev, scroll);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ssd1306_invert(uint8_t *buf, size_t blen)
|
|
||||||
{
|
|
||||||
uint8_t wk;
|
|
||||||
for(int i=0; i<blen; i++){
|
|
||||||
wk = buf[i];
|
|
||||||
buf[i] = ~wk;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flip upside down
|
|
||||||
void ssd1306_flip(uint8_t *buf, size_t blen)
|
|
||||||
{
|
|
||||||
for(int i=0; i<blen; i++){
|
|
||||||
buf[i] = ssd1306_rotate(buf[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rotate 8-bit data
|
|
||||||
// 0x12-->0x48
|
|
||||||
uint8_t ssd1306_rotate(uint8_t ch1) {
|
|
||||||
uint8_t ch2 = 0;
|
|
||||||
for (int j=0;j<8;j++) {
|
|
||||||
ch2 = (ch2 << 1) + (ch1 & 0x01);
|
|
||||||
ch1 = ch1 >> 1;
|
|
||||||
}
|
|
||||||
return ch2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ssd1306_fadeout(SSD1306_t * dev)
|
|
||||||
{
|
|
||||||
void (*func)(SSD1306_t * dev, int page, int seg, uint8_t * images, int width);
|
|
||||||
if (dev->_address == SPIAddress) {
|
|
||||||
func = spi_display_image;
|
|
||||||
} else {
|
|
||||||
func = i2c_display_image;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t image[1];
|
|
||||||
for(int page=0; page<dev->_pages; page++) {
|
|
||||||
image[0] = 0xFF;
|
|
||||||
for(int line=0; line<8; line++) {
|
|
||||||
if (dev->_flip) {
|
|
||||||
image[0] = image[0] >> 1;
|
|
||||||
} else {
|
|
||||||
image[0] = image[0] << 1;
|
|
||||||
}
|
|
||||||
for(int seg=0; seg<128; seg++) {
|
|
||||||
(*func)(dev, page, seg, image, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ssd1306_dump(SSD1306_t dev)
|
|
||||||
{
|
|
||||||
printf("_address=%x\n",dev._address);
|
|
||||||
printf("_width=%x\n",dev._width);
|
|
||||||
printf("_height=%x\n",dev._height);
|
|
||||||
printf("_pages=%x\n",dev._pages);
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user