Changed to components

This commit is contained in:
nopnop2002 2022-04-26 15:20:31 +09:00
parent 24ddab1dc7
commit dbb01f15f7
15 changed files with 567 additions and 293 deletions

21
LICENSE
View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -0,0 +1,4 @@
set(COMPONENT_SRCS "main.c")
set(COMPONENT_ADD_INCLUDEDIRS "")
register_component()

View File

@ -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

View 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 ".")

View File

@ -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

View 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]);
}

View File

@ -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);

View File

@ -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;

View File

@ -1,4 +0,0 @@
set(COMPONENT_SRCS main.c ssd1306.c ssd1306_i2c.c ssd1306_spi.c)
set(COMPONENT_ADD_INCLUDEDIRS ".")
register_component()

View File

@ -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);
}