diff --git a/LICENSE b/LICENSE deleted file mode 100644 index e66ff19..0000000 --- a/LICENSE +++ /dev/null @@ -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. diff --git a/Makefile b/Makefile deleted file mode 100644 index fca741b..0000000 --- a/Makefile +++ /dev/null @@ -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 - diff --git a/CMakeLists.txt b/TextDemo/CMakeLists.txt similarity index 82% rename from CMakeLists.txt rename to TextDemo/CMakeLists.txt index 8dd06e2..2aa16fe 100644 --- a/CMakeLists.txt +++ b/TextDemo/CMakeLists.txt @@ -2,5 +2,7 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +set(EXTRA_COMPONENT_DIRS ../components/ssd1306) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(ssd1306) diff --git a/TextDemo/main/CMakeLists.txt b/TextDemo/main/CMakeLists.txt new file mode 100644 index 0000000..647a294 --- /dev/null +++ b/TextDemo/main/CMakeLists.txt @@ -0,0 +1,4 @@ +set(COMPONENT_SRCS "main.c") +set(COMPONENT_ADD_INCLUDEDIRS "") + +register_component() diff --git a/main/component.mk b/TextDemo/main/component.mk similarity index 100% rename from main/component.mk rename to TextDemo/main/component.mk diff --git a/main/main.c b/TextDemo/main/main.c similarity index 94% rename from main/main.c rename to TextDemo/main/main.c index 4ed55f5..e761b6c 100644 --- a/main/main.c +++ b/TextDemo/main/main.c @@ -66,6 +66,8 @@ void app_main(void) ssd1306_clear_screen(&dev, false); ssd1306_contrast(&dev, 0xff); + ssd1306_display_text_x3(&dev, 0, "Hello", 5, false); + vTaskDelay(3000 / portTICK_PERIOD_MS); #if CONFIG_SSD1306_128x64 top = 2; @@ -75,10 +77,10 @@ void app_main(void) ssd1306_display_text(&dev, 1, "ABCDEFGHIJKLMNOP", 16, false); ssd1306_display_text(&dev, 2, "abcdefghijklmnop",16, false); ssd1306_display_text(&dev, 3, "Hello World!!", 13, false); - ssd1306_clear_line(&dev, 4, true); - ssd1306_clear_line(&dev, 5, true); - ssd1306_clear_line(&dev, 6, true); - ssd1306_clear_line(&dev, 7, true); + //ssd1306_clear_line(&dev, 4, true); + //ssd1306_clear_line(&dev, 5, true); + //ssd1306_clear_line(&dev, 6, true); + //ssd1306_clear_line(&dev, 7, true); ssd1306_display_text(&dev, 4, "SSD1306 128x64", 14, true); ssd1306_display_text(&dev, 5, "ABCDEFGHIJKLMNOP", 16, true); ssd1306_display_text(&dev, 6, "abcdefghijklmnop",16, true); @@ -91,8 +93,8 @@ void app_main(void) bottom = 4; ssd1306_display_text(&dev, 0, "SSD1306 128x32", 14, false); ssd1306_display_text(&dev, 1, "Hello World!!", 13, false); - ssd1306_clear_line(&dev, 2, true); - ssd1306_clear_line(&dev, 3, true); + //ssd1306_clear_line(&dev, 2, true); + //ssd1306_clear_line(&dev, 3, true); ssd1306_display_text(&dev, 2, "SSD1306 128x32", 14, true); ssd1306_display_text(&dev, 3, "Hello World!!", 13, true); #endif // CONFIG_SSD1306_128x32 diff --git a/components/ssd1306/CMakeLists.txt b/components/ssd1306/CMakeLists.txt new file mode 100644 index 0000000..ac32f0a --- /dev/null +++ b/components/ssd1306/CMakeLists.txt @@ -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 ".") diff --git a/main/Kconfig.projbuild b/components/ssd1306/Kconfig.projbuild similarity index 76% rename from main/Kconfig.projbuild rename to components/ssd1306/Kconfig.projbuild index 22b5239..873cd36 100644 --- a/main/Kconfig.projbuild +++ b/components/ssd1306/Kconfig.projbuild @@ -1,5 +1,12 @@ 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 prompt "Interface" default I2C_INTERFACE @@ -46,10 +53,11 @@ menu "SSD1306 Configuration" config SCL_GPIO depends on I2C_INTERFACE int "SCL GPIO number" - range 0 46 - default 22 if IDF_TARGET_ESP32 + range 0 GPIO_RANGE_MAX + default 22 if IIDF_TARGET_ESP32 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 GPIO number (IOxx) to I2C SCL. 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 depends on I2C_INTERFACE int "SDA GPIO number" - range 0 46 + range 0 GPIO_RANGE_MAX default 21 if IDF_TARGET_ESP32 default 11 if IDF_TARGET_ESP32S2 + default 11 if IDF_TARGET_ESP32S3 default 10 if IDF_TARGET_ESP32C3 help GPIO number (IOxx) to I2C SDA. @@ -69,8 +78,11 @@ menu "SSD1306 Configuration" config RESET_GPIO int "RESET GPIO number" - range -1 46 - default -1 + range -1 GPIO_RANGE_MAX + 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 GPIO number (IOxx) to RESET. When it is -1, RESET isn't performed. @@ -80,10 +92,11 @@ menu "SSD1306 Configuration" config MOSI_GPIO depends on SPI_INTERFACE int "MOSI GPIO number" - range 0 46 + range 0 GPIO_RANGE_MAX default 23 if IDF_TARGET_ESP32 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 GPIO number (IOxx) to SPI MOSI. 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 depends on SPI_INTERFACE int "SCLK GPIO number" - range 0 46 + range 0 GPIO_RANGE_MAX default 18 if IDF_TARGET_ESP32 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 GPIO number (IOxx) to SPI SCLK. 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 depends on SPI_INTERFACE int "CS GPIO number" - range 0 34 - default 5 if IDF_TARGET_ESP32 + range 0 GPIO_RANGE_MAX + default 5 if IDF_TARGET_ESP32 default 34 if IDF_TARGET_ESP32S2 + default 34 if IDF_TARGET_ESP32S3 default 10 if IDF_TARGET_ESP32C3 help GPIO number (IOxx) to SPI CS. @@ -118,13 +133,15 @@ menu "SSD1306 Configuration" config DC_GPIO depends on SPI_INTERFACE int "DC GPIO number" - range 0 34 - default 2 + range 0 GPIO_RANGE_MAX + 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 GPIO number (IOxx) to SPI 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. - endmenu diff --git a/main/font8x8_basic.h b/components/ssd1306/font8x8_basic.h similarity index 100% rename from main/font8x8_basic.h rename to components/ssd1306/font8x8_basic.h diff --git a/components/ssd1306/ssd1306.c b/components/ssd1306/ssd1306.c new file mode 100644 index 0000000..06d36d2 --- /dev/null +++ b/components/ssd1306/ssd1306.c @@ -0,0 +1,496 @@ +#include + +#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_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_pages;page++) { + spi_display_image(dev, page, 0, dev->_page[page]._segs, dev->_width); + } + } else { + for (int page=0; page_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_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_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_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_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=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;_seg0x48 +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_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]); +} + diff --git a/main/ssd1306.h b/components/ssd1306/ssd1306.h similarity index 87% rename from main/ssd1306.h rename to components/ssd1306/ssd1306.h index 73a294a..fd3d43b 100644 --- a/main/ssd1306.h +++ b/components/ssd1306/ssd1306.h @@ -80,8 +80,8 @@ typedef enum { } ssd1306_scroll_type_t; typedef struct { - bool _valid; - int _segLen; // 0-128 + bool _valid; // Not using it anymore + int _segLen; // Not using it anymore uint8_t _segs[128]; } PAGE_t; @@ -101,8 +101,13 @@ typedef struct { } SSD1306_t; 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_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_line(SSD1306_t * dev, int page, bool invert); 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_clear(SSD1306_t * dev); 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_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_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_init(SSD1306_t * dev, int width, int height); diff --git a/main/ssd1306_i2c.c b/components/ssd1306/ssd1306_i2c.c similarity index 100% rename from main/ssd1306_i2c.c rename to components/ssd1306/ssd1306_i2c.c diff --git a/main/ssd1306_spi.c b/components/ssd1306/ssd1306_spi.c similarity index 97% rename from main/ssd1306_spi.c rename to components/ssd1306/ssd1306_spi.c index ac5b7e9..88db509 100644 --- a/main/ssd1306_spi.c +++ b/components/ssd1306/ssd1306_spi.c @@ -12,11 +12,13 @@ #define tag "SSD1306" #ifdef CONFIG_IDF_TARGET_ESP32 -#define LCD_HOST HSPI_HOST -#elif defined CONFIG_IDF_TARGET_ESP32S2 -#define LCD_HOST SPI2_HOST -#elif defined CONFIG_IDF_TARGET_ESP32C3 -#define LCD_HOST SPI2_HOST +#define LCD_HOST HSPI_HOST +#elif CONFIG_IDF_TARGET_ESP32S2 +#define LCD_HOST SPI2_HOST +#elif CONFIG_IDF_TARGET_ESP32S3 +#define LCD_HOST SPI2_HOST +#elif CONFIG_IDF_TARGET_ESP32C3 +#define LCD_HOST SPI2_HOST #endif static const int SPI_Command_Mode = 0; diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt deleted file mode 100644 index c931a02..0000000 --- a/main/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -set(COMPONENT_SRCS main.c ssd1306.c ssd1306_i2c.c ssd1306_spi.c) -set(COMPONENT_ADD_INCLUDEDIRS ".") - -register_component() diff --git a/main/ssd1306.c b/main/ssd1306.c deleted file mode 100644 index 65f5f7c..0000000 --- a/main/ssd1306.c +++ /dev/null @@ -1,229 +0,0 @@ -#include - -#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_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; i0x48 -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_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); -} -