From 5b12ba54dc7b8e76ff3dbc99f282aa271f78aedf Mon Sep 17 00:00:00 2001 From: urx Date: Fri, 28 Oct 2016 16:08:37 +0400 Subject: [PATCH] Driver and example for SSD1306 128x64 I2C display (#254) --- examples/ssd1306_i2c/Makefile | 3 + examples/ssd1306_i2c/README.md | 3 + examples/ssd1306_i2c/image.xbm | 89 +++++++ examples/ssd1306_i2c/ssd1306_i2c.c | 65 +++++ extras/ssd1306/LICENSE | 22 ++ extras/ssd1306/README.md | 27 +++ extras/ssd1306/component.mk | 9 + extras/ssd1306/ssd1306.c | 376 +++++++++++++++++++++++++++++ extras/ssd1306/ssd1306.h | 50 ++++ 9 files changed, 644 insertions(+) create mode 100644 examples/ssd1306_i2c/Makefile create mode 100644 examples/ssd1306_i2c/README.md create mode 100644 examples/ssd1306_i2c/image.xbm create mode 100644 examples/ssd1306_i2c/ssd1306_i2c.c create mode 100644 extras/ssd1306/LICENSE create mode 100644 extras/ssd1306/README.md create mode 100644 extras/ssd1306/component.mk create mode 100644 extras/ssd1306/ssd1306.c create mode 100644 extras/ssd1306/ssd1306.h diff --git a/examples/ssd1306_i2c/Makefile b/examples/ssd1306_i2c/Makefile new file mode 100644 index 0000000..805a3bd --- /dev/null +++ b/examples/ssd1306_i2c/Makefile @@ -0,0 +1,3 @@ +PROGRAM=SSD1306_Example +EXTRA_COMPONENTS = extras/ssd1306 extras/i2c +include ../../common.mk diff --git a/examples/ssd1306_i2c/README.md b/examples/ssd1306_i2c/README.md new file mode 100644 index 0000000..9c75bb3 --- /dev/null +++ b/examples/ssd1306_i2c/README.md @@ -0,0 +1,3 @@ +# I2C / SSD1306 OLED LCD Example + +To run this example connect the SSD1306 OLED LCD and configure SDA/SCL pins in ssd1306_i2c.c file. diff --git a/examples/ssd1306_i2c/image.xbm b/examples/ssd1306_i2c/image.xbm new file mode 100644 index 0000000..1bd888c --- /dev/null +++ b/examples/ssd1306_i2c/image.xbm @@ -0,0 +1,89 @@ +#define image_width 128 +#define image_height 64 +static unsigned char image_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf8, 0xc3, 0xc7, 0x0f, 0x00, 0x1e, 0xfc, 0xf0, 0xe7, 0x30, 0xc0, 0x9f, + 0x7f, 0xf0, 0x80, 0x0f, 0x18, 0x30, 0xc4, 0x18, 0x80, 0x61, 0x8c, 0x31, + 0xe0, 0x30, 0xc0, 0x38, 0x0c, 0x0c, 0x63, 0x08, 0x18, 0x30, 0xc0, 0x30, + 0x80, 0x61, 0x0c, 0x33, 0xe0, 0x31, 0xc0, 0x30, 0x0c, 0x0c, 0x63, 0x00, + 0x18, 0xf0, 0xc0, 0x30, 0xc0, 0xc0, 0x0c, 0x33, 0x60, 0x31, 0xc0, 0x30, + 0x0c, 0x06, 0xe6, 0x01, 0xf8, 0xe3, 0xc7, 0x30, 0xc0, 0xc0, 0x0c, 0xf3, + 0x67, 0x33, 0xc0, 0x38, 0x0c, 0x06, 0xc6, 0x0f, 0x18, 0x80, 0xcf, 0x18, + 0xcf, 0xc0, 0x8c, 0x31, 0x60, 0x36, 0xcf, 0x1f, 0x0c, 0x06, 0x06, 0x1f, + 0x18, 0x00, 0xce, 0x0f, 0xcf, 0xc0, 0xfc, 0x30, 0x60, 0x36, 0xcf, 0x18, + 0x0c, 0x06, 0x06, 0x1c, 0x18, 0x00, 0xcc, 0x00, 0x80, 0x61, 0x0c, 0x30, + 0x60, 0x3c, 0xc0, 0x30, 0x0c, 0x0c, 0x03, 0x18, 0x18, 0x10, 0xcc, 0x00, + 0x80, 0x61, 0x0c, 0x30, 0x60, 0x38, 0xc0, 0x30, 0x0c, 0x0c, 0x23, 0x18, + 0xf8, 0xf3, 0xc3, 0x00, 0x00, 0x1e, 0x0c, 0xf0, 0x67, 0x38, 0xc0, 0x60, + 0x0c, 0xf0, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x1f, 0xfc, 0x01, 0x1c, 0xf8, 0x81, + 0x0f, 0x78, 0x00, 0x0c, 0x80, 0x1f, 0xfe, 0x00, 0xf0, 0x87, 0x3f, 0xfc, + 0x07, 0x1f, 0xfc, 0xc3, 0x1f, 0xfc, 0x00, 0x0c, 0xe0, 0x3f, 0xfe, 0x03, + 0x38, 0xc4, 0x21, 0x0c, 0x0e, 0x1b, 0x04, 0xc7, 0x18, 0x8e, 0x00, 0x0c, + 0x70, 0x20, 0x06, 0x07, 0x18, 0xc0, 0x00, 0x0c, 0x0c, 0x18, 0x00, 0x66, + 0x30, 0x07, 0x00, 0x0c, 0x30, 0x00, 0x06, 0x06, 0x18, 0xc0, 0x00, 0x0c, + 0x18, 0x18, 0x00, 0x67, 0x30, 0x03, 0x00, 0x0c, 0x18, 0x00, 0x06, 0x0c, + 0xf0, 0x81, 0x0f, 0x0c, 0x18, 0x18, 0xf0, 0x61, 0x30, 0x7b, 0x00, 0x0c, + 0x18, 0x00, 0x06, 0x0c, 0xe0, 0x07, 0x3f, 0x0c, 0x18, 0x18, 0xf0, 0x63, + 0x30, 0xff, 0x00, 0x0c, 0x18, 0x00, 0x06, 0x0c, 0x00, 0x0e, 0x70, 0x0c, + 0x18, 0x18, 0x00, 0x67, 0x30, 0xc7, 0x01, 0x0c, 0x18, 0x00, 0x06, 0x0c, + 0x00, 0x0c, 0x60, 0x0c, 0x18, 0x18, 0x00, 0x66, 0x30, 0x83, 0x01, 0x0c, + 0x18, 0x00, 0x06, 0x0c, 0x00, 0x0c, 0x60, 0x0c, 0x0c, 0x18, 0x00, 0x66, + 0x30, 0x83, 0x01, 0x0c, 0x30, 0x00, 0x06, 0x06, 0x08, 0x4e, 0x70, 0x0c, + 0x0e, 0x18, 0x04, 0xc7, 0x18, 0xc6, 0x01, 0x0c, 0x70, 0x20, 0x06, 0x07, + 0xf8, 0xc7, 0x3f, 0xfc, 0x07, 0xff, 0xfc, 0xc3, 0x1f, 0xfe, 0x00, 0xfc, + 0xe3, 0x3f, 0xfe, 0x03, 0xf0, 0x83, 0x1f, 0xfc, 0x01, 0xff, 0xf8, 0x81, + 0x0f, 0x78, 0x00, 0xfc, 0x83, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x18, + 0x18, 0x7e, 0xc0, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x18, 0x18, 0xfe, 0x80, 0x61, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x18, 0x18, 0xc6, 0x81, 0x33, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3d, 0x06, 0x06, 0x18, + 0x18, 0x86, 0x01, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x7f, 0x06, 0x06, 0x18, 0x18, 0x86, 0x01, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0xe3, 0x0c, 0x03, 0x18, 0x18, 0xc6, 0x01, 0x0e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc1, 0x0c, 0x03, 0x18, + 0x18, 0xfe, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0xc1, 0x98, 0x01, 0x18, 0x18, 0x7e, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0xc1, 0x98, 0x01, 0x18, 0x18, 0xc6, 0x00, 0x1b, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc1, 0xf0, 0x00, 0x18, + 0x18, 0x86, 0x81, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0xe3, 0xf0, 0x00, 0x30, 0x0c, 0x86, 0x81, 0x71, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x7f, 0x60, 0x00, 0xf0, 0x0f, 0x06, 0xc3, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3d, 0x60, 0x00, 0xc0, + 0x03, 0x06, 0xe7, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; diff --git a/examples/ssd1306_i2c/ssd1306_i2c.c b/examples/ssd1306_i2c/ssd1306_i2c.c new file mode 100644 index 0000000..8ee64ba --- /dev/null +++ b/examples/ssd1306_i2c/ssd1306_i2c.c @@ -0,0 +1,65 @@ +#include "espressif/esp_common.h" +#include "esp/uart.h" + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +#include + +#include "i2c/i2c.h" +#include "ssd1306/ssd1306.h" + +#include "image.xbm" + +/* Change this according to you schematics */ +#define SCL_PIN GPIO_ID_PIN((14)) +#define SDA_PIN GPIO_ID_PIN((12)) + +/* Local frame buffer */ +static uint8_t buffer[SSD1306_ROWS * SSD1306_COLS / 8]; + +static void ssd1306_task(void *pvParameters) +{ + printf("%s: Started user interface task\n", __FUNCTION__); + vTaskDelay(1000/portTICK_RATE_MS); + + + if (ssd1306_load_xbm(image_bits, buffer)) + goto error_loop; + + ssd1306_set_whole_display_lighting(false); + while (1) { + vTaskDelay(2000 / portTICK_RATE_MS); + printf("%s: steel alive\n", __FUNCTION__); + } + +error_loop: + printf("%s: error while loading framebuffer into SSD1306\n", __func__); + for(;;){ + vTaskDelay(2000 / portTICK_RATE_MS); + printf("%s: error loop\n", __FUNCTION__); + } +} + +void user_init(void) +{ + // Setup HW + uart_set_baud(0, 115200); + + printf("SDK version:%s\n", sdk_system_get_sdk_version()); + + i2c_init(SCL_PIN, SDA_PIN); + + if (ssd1306_init()){ + for (;;) { + printf("%s: failed to init SSD1306 lcd\n", __func__); + vTaskDelay(1000/portTICK_RATE_MS); + } + } + + ssd1306_set_whole_display_lighting(true); + vTaskDelay(1000/portTICK_RATE_MS); + // Create user interface task + xTaskCreate(ssd1306_task, "ssd1306_task", 256, NULL, 2, NULL); +} diff --git a/extras/ssd1306/LICENSE b/extras/ssd1306/LICENSE new file mode 100644 index 0000000..1f44f09 --- /dev/null +++ b/extras/ssd1306/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Frank Bargstedt + +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/extras/ssd1306/README.md b/extras/ssd1306/README.md new file mode 100644 index 0000000..cb283b9 --- /dev/null +++ b/extras/ssd1306/README.md @@ -0,0 +1,27 @@ +# Driver for I2C SSD1306 128x64 OLED LCD + +This driver is written for usage with the ESP8266 and FreeRTOS ([esp-open-rtos](https://github.com/SuperHouse/esp-open-rtos)). + +### Usage + +Before using the SSD1306 LCD module, the function `i2c_init(SCL_PIN, SDA_PIN)` needs to be called to setup the I2C interface and then you must call ssd1306_init(). + +#### Example + +``` +#define SCL_PIN GPIO_ID_PIN(0) +#define SDA_PIN GPIO_ID_PIN(2) +... + +i2c_init(SCL_PIN, SDA_PIN); + +if (ssd1306_init()) { +// An error occured, while performing SSD1306 init init (E.g device not found etc.) +} + +// rest of the code +``` + + + + diff --git a/extras/ssd1306/component.mk b/extras/ssd1306/component.mk new file mode 100644 index 0000000..7f93338 --- /dev/null +++ b/extras/ssd1306/component.mk @@ -0,0 +1,9 @@ +# Component makefile for extras/ssd1306 + +# expected anyone using ssd1306 driver includes it as 'ssd1306/ssd1306.h' +INC_DIRS += $(ssd1306_ROOT).. + +# args for passing into compile rule generation +ssd1306_SRC_DIR = $(ssd1306_ROOT) + +$(eval $(call component_compile_rules,ssd1306)) diff --git a/extras/ssd1306/ssd1306.c b/extras/ssd1306/ssd1306.c new file mode 100644 index 0000000..85f641f --- /dev/null +++ b/extras/ssd1306/ssd1306.c @@ -0,0 +1,376 @@ +#include +#include +#include +#include +#include "ssd1306.h" + +/* SSD1306 commands */ +#define SSD1306_SET_MEM_ADDR_MODE (0x20) +#define SSD1306_ADDR_MODE_HORIZ (0x0) +#define SSD1306_ADDR_MODE_VERT (0x1) +#define SSD1306_ADDR_MODE_PAGE (0x2) + +#define SSD1306_SET_COL_ADDR (0x21) +#define SSD1306_SET_PAGE_ADDR (0x22) +#define SSD1306_SET_DISP_START_LINE (0x40) +#define SSD1306_SET_CONTRAST (0x81) +#define SSD1306_SET_SEGMENT_REMAP0 (0xA0) +#define SSD1306_SET_SEGMENT_REMAP1 (0xA1) +#define SSD1306_SET_ENTIRE_DISP_ON (0xA5) +#define SSD1306_SET_ENTIRE_DISP_OFF (0xA4) +#define SSD1306_SET_INVERSION_OFF (0xA6) +#define SSD1306_SET_INVERSION_ON (0xA7) + +#define SSD1306_SET_MUX_RATIO (0xA8) +#define SSD1306_MUX_RATIO_MASK (0x3F) +#define SSD1306_SET_DISPLAY_OFF (0xAE) +#define SSD1306_SET_DISPLAY_ON (0xAF) +#define SSD1306_SET_SCAN_DIR_FWD (0xC0) +#define SSD1306_SET_SCAN_DIR_BWD (0xC8) +#define SSD1306_SET_DISPLAY_OFFSET (0xD3) +#define SSD1306_SET_OSC_FREQ (0xD5) +#define SSD1306_SET_PRE_CHRG_PER (0xD9) + +#define SSD1306_SET_COM_PINS_HW_CFG (0xDA) +#define SSD1306_COM_PINS_HW_CFG_MASK (0x32) +#define SSD1306_SEQ_COM_PINS_CFG (0x02) +#define SSD1306_ALT_COM_PINS_CFG (0x12) +#define SSD1306_COM_LR_REMAP_OFF (0x02) +#define SSD1306_COM_LR_REMAP_ON (0x22) + +#define SSD1306_SET_DESEL_LVL (0xDB) +#define SSD1306_SET_NOP (0xE3) + +#define SSD1306_SET_CHARGE_PUMP (0x8D) +#define SSD1306_CHARGE_PUMP_EN (0x14) +#define SSD1306_CHARGE_PUMP_DIS (0x10) + +#ifdef SSD1306_DEBUG +#define debug(fmt, ...) printf("%s" fmt "\n", "SSD1306", ## __VA_ARGS__); +#else +#define debug(fmt, ...) +#endif + +/* Issue a command to SSD1306 device + * format such follows: + * |S|Slave Address|W|ACK|0x00|Command|Ack|P| + * + * in case of two-bytes command here will be Data byte + * right after command byte. + */ +int ssd1306_command(uint8_t cmd) +{ + i2c_start(); + if (!i2c_write(SSD1306_I2C_ADDR << 1)) { + debug("Error while xmitting I2C slave address\n"); + i2c_stop(); + return -EIO; + } + if (!i2c_write(0x00)) { + debug("Error while xmitting transmission type\n"); + i2c_stop(); + return -EIO; + } + + if (!i2c_write(cmd)) { + debug("Error while xmitting command: 0x%02X\n", cmd); + i2c_stop(); + return -EIO; + } + + i2c_stop(); + + return 0; +} + +/* Perform default init routine according +* to SSD1306 datasheet from adafruit.com */ +int ssd1306_init() +{ + if (!ssd1306_display_on(false) && + !ssd1306_set_osc_freq(0x80) && + !ssd1306_set_mux_ratio(SSD1306_ROWS-1) && + !ssd1306_set_display_offset(0x0) && + !ssd1306_set_display_start_line(0x0) && + !ssd1306_set_charge_pump_enabled(true) && + !ssd1306_set_mem_addr_mode(SSD1306_ADDR_MODE_HORIZ) && + !ssd1306_set_segment_remapping_enabled(false) && + !ssd1306_set_scan_direction_fwd(true) && + !ssd1306_set_com_pin_hw_config(SSD1306_ALT_COM_PINS_CFG) && + !ssd1306_set_contrast(0x9f) && + !ssd1306_set_precharge_period(0xf1) && + !ssd1306_set_deseltct_lvl(0x40) && + !ssd1306_set_whole_display_lighting(true) && + !ssd1306_set_inversion(false) && + !ssd1306_display_on(true)) { + return 0; + } + + return -EIO; +} + +/* + * frame buffer of SSD1306 consists of 8 pages of 128 bits each + * +*/ +int ssd1306_load_frame_buffer(uint8_t buf[], uint16_t len) +{ + uint16_t i; + uint8_t j; + + ssd1306_set_column_addr(0, 127); + ssd1306_set_page_addr(0, 7); + + for (i=0; i= 0x3) + return -EINVAL; + + int err = 0; + if ((err = ssd1306_command(SSD1306_SET_MEM_ADDR_MODE))) + return err; + + return ssd1306_command(mode); +} + +int ssd1306_set_segment_remapping_enabled(bool on) +{ + if (on) + return ssd1306_command(SSD1306_SET_SEGMENT_REMAP1); + + return ssd1306_command(SSD1306_SET_SEGMENT_REMAP0); +} + +int ssd1306_set_scan_direction_fwd(bool fwd) +{ + if (fwd) + return ssd1306_command(SSD1306_SET_SCAN_DIR_FWD); + + return ssd1306_command(SSD1306_SET_SCAN_DIR_BWD); +} + +int ssd1306_set_com_pin_hw_config(uint8_t config) +{ + int err = 0; + if ((err = ssd1306_command(SSD1306_SET_COM_PINS_HW_CFG))) + return err; + + return ssd1306_command(config & SSD1306_COM_PINS_HW_CFG_MASK); +} + +int ssd1306_set_contrast(uint8_t contrast) +{ + int err = 0; + if ((err = ssd1306_command(SSD1306_SET_CONTRAST))) + return err; + + return ssd1306_command(contrast); +} + +int ssd1306_set_inversion(bool on) +{ + if (on) + return ssd1306_command(SSD1306_SET_INVERSION_ON); + + return ssd1306_command(SSD1306_SET_INVERSION_OFF); +} + +int ssd1306_set_osc_freq(uint8_t osc_freq) +{ + int err = 0; + if ((err = ssd1306_command(SSD1306_SET_OSC_FREQ))) + return err; + + return ssd1306_command(osc_freq); +} + +int ssd1306_set_mux_ratio(uint8_t ratio) +{ + if (ratio < 15) + return -EINVAL; + + int err = 0; + if ((err = ssd1306_command(SSD1306_SET_MUX_RATIO))) + return err; + + return ssd1306_command(ratio); +} + +int ssd1306_set_column_addr(uint8_t start, uint8_t stop) +{ + int err = 0; + if ((err = ssd1306_command(SSD1306_SET_COL_ADDR))) + return err; + + if ((err = ssd1306_command(start))) + return err; + + return ssd1306_command(stop); +} + +int ssd1306_set_page_addr(uint8_t start, uint8_t stop) +{ + int err = 0; + if ((err = ssd1306_command(SSD1306_SET_PAGE_ADDR))) + return err; + + if ((err = ssd1306_command(start))) + return err; + + return ssd1306_command(stop); +} + +int ssd1306_set_precharge_period(uint8_t prchrg) +{ + int err = 0; + if ((err = ssd1306_command(SSD1306_SET_PRE_CHRG_PER))) + return err; + + return ssd1306_command(prchrg); +} + +int ssd1306_set_deseltct_lvl(uint8_t lvl) +{ + int err = 0; + if ((err = ssd1306_command(SSD1306_SET_DESEL_LVL))) + return err; + + return ssd1306_command(lvl); +} + +int ssd1306_set_whole_display_lighting(bool light) +{ + if (light) + return ssd1306_command(SSD1306_SET_ENTIRE_DISP_ON); + + return ssd1306_command(SSD1306_SET_ENTIRE_DISP_OFF); +} + + +/* one byte of xbm - 8 dots in line of picture source + * one byte of fb - 8 rows for 1 column of screen + */ +int ssd1306_load_xbm(uint8_t *xbm, uint8_t *fb) +{ + uint8_t bit = 0; + + int row = 0; + int column = 0; + for (row = 0; row < SSD1306_ROWS; row ++) { + for (column = 0; column < SSD1306_COLS/8; column++) { + uint16_t xbm_offset = row * 16 + column; + for (bit = 0; bit < 8; bit++) { + if (*(xbm + xbm_offset) & 1 << bit) { + *(fb + SSD1306_COLS*(row/8)+column*8+bit) |= 1 << row%8; + } + } + } + } + + return ssd1306_load_frame_buffer(fb, SSD1306_ROWS*SSD1306_COLS/8); +} + + diff --git a/extras/ssd1306/ssd1306.h b/extras/ssd1306/ssd1306.h new file mode 100644 index 0000000..933ceae --- /dev/null +++ b/extras/ssd1306/ssd1306.h @@ -0,0 +1,50 @@ +#ifndef _SSD1306__H_ +#define _SSD1306__H_ + +#include +#include +#include + +// shifted +#define SSD1306_I2C_ADDR (0x3C) + +#define SSD1306_ROWS (64) +#define SSD1306_COLS (128) + +/* Issue single command on SSD1306 */ +int ssd1306_command(uint8_t cmd); + +/* Default init for SSD1306 */ +int ssd1306_init(); + +/* Load picture in xbm format into SSD1306 RAM + * xbm - pointer to xbm picture array + * fb - pointer fo local buffer for storing converted xbm image + */ +int ssd1306_load_xbm(uint8_t *xbm, uint8_t *fb); + +/* Load local framebuffer into SSD1306 RAM */ +int ssd1306_load_frame_buffer(uint8_t buf[], uint16_t len); + +/* Clears SSD1306 ram */ +int ssd1306_clear_screen(); + +int ssd1306_display_on(bool on); +int ssd1306_set_display_start_line(uint8_t start); +int ssd1306_set_display_offset(uint8_t offset); +int ssd1306_set_charge_pump_enabled(bool enabled); +int ssd1306_set_mem_addr_mode(uint8_t mode); +int ssd1306_set_segment_remapping_enabled(bool on); +int ssd1306_set_scan_direction_fwd(bool fwd); +int ssd1306_set_com_pin_hw_config(uint8_t config); +int ssd1306_set_contrast(uint8_t contrast); +int ssd1306_set_inversion(bool on); +int ssd1306_set_osc_freq(uint8_t osc_freq); +int ssd1306_set_mux_ratio(uint8_t ratio); +int ssd1306_set_column_addr(uint8_t start, uint8_t stop); +int ssd1306_set_page_addr(uint8_t start, uint8_t stop); +int ssd1306_set_precharge_period(uint8_t prchrg); +int ssd1306_set_deseltct_lvl(uint8_t lvl); +int ssd1306_set_whole_display_lighting(bool light); + +#endif // _SSD1306__H_