├── resources ├── FontTool.png ├── DemoFrame1.jpg ├── DemoFrame2.jpg ├── DemoFrame3.jpg ├── DemoFrame4.jpg └── SPI_version.jpg ├── library.properties ├── library.json ├── license ├── examples └── SSD1306Demo │ ├── images.h │ └── SSD1306Demo.ino ├── SSD1306.h ├── SSD1306Ui.h ├── SSD1306Ui.cpp ├── README.md ├── SSD1306.cpp └── SSD1306Fonts.h /resources/FontTool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/g3gg0/esp8266-oled-ssd1306/master/resources/FontTool.png -------------------------------------------------------------------------------- /resources/DemoFrame1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/g3gg0/esp8266-oled-ssd1306/master/resources/DemoFrame1.jpg -------------------------------------------------------------------------------- /resources/DemoFrame2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/g3gg0/esp8266-oled-ssd1306/master/resources/DemoFrame2.jpg -------------------------------------------------------------------------------- /resources/DemoFrame3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/g3gg0/esp8266-oled-ssd1306/master/resources/DemoFrame3.jpg -------------------------------------------------------------------------------- /resources/DemoFrame4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/g3gg0/esp8266-oled-ssd1306/master/resources/DemoFrame4.jpg -------------------------------------------------------------------------------- /resources/SPI_version.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/g3gg0/esp8266-oled-ssd1306/master/resources/SPI_version.jpg -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=ESP8266 Oled Driver for SSD1306 display 2 | version=2.0.2 3 | author=Daniel Eichhorn, Fabrice Weinberg 4 | maintainer=Daniel Eichhorn 5 | sentence=A display driver for SSD1306 oled displays connected to an ESP8266 6 | paragraph=A display driver for SSD1306 oled displays connected to an ESP8266 7 | category=Display 8 | url=https://github.com/squix78/esp8266-oled-ssd1306 9 | architectures=esp8266 10 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "SSD1306", 3 | "keywords": "display, oled", 4 | "description": "SSD1306 Oled driver which offers scrolling frames, custom fonts, etc", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/squix78/esp8266-oled-ssd1306.git" 8 | }, 9 | "authors": [{ 10 | "name": "Daniel Eichhorn", 11 | "url": "http://blog.squix.ch", 12 | "email": "squix78@gmail.com", 13 | "maintainer": true 14 | }, 15 | { 16 | "name": "Fabrice Weinberg" 17 | } 18 | ], 19 | "frameworks": "arduino", 20 | "platforms": "espressif", 21 | "version": "2.0.2" 22 | } 23 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | -------------------------------------------------------------------------------- /examples/SSD1306Demo/images.h: -------------------------------------------------------------------------------- 1 | #define WiFi_Logo_width 60 2 | #define WiFi_Logo_height 36 3 | const char WiFi_Logo_bits[] PROGMEM = { 4 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 5 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, 6 | 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 7 | 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, 8 | 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 9 | 0xFF, 0x03, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 10 | 0x00, 0xFF, 0xFF, 0xFF, 0x07, 0xC0, 0x83, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 11 | 0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0C, 0x00, 12 | 0xC0, 0xFF, 0xFF, 0x7C, 0x00, 0x60, 0x0C, 0x00, 0xC0, 0x31, 0x46, 0x7C, 13 | 0xFC, 0x77, 0x08, 0x00, 0xE0, 0x23, 0xC6, 0x3C, 0xFC, 0x67, 0x18, 0x00, 14 | 0xE0, 0x23, 0xE4, 0x3F, 0x1C, 0x00, 0x18, 0x00, 0xE0, 0x23, 0x60, 0x3C, 15 | 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x03, 0x60, 0x3C, 0x1C, 0x70, 0x18, 0x00, 16 | 0xE0, 0x07, 0x60, 0x3C, 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, 17 | 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, 18 | 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x8F, 0x71, 0x3C, 19 | 0x1C, 0x70, 0x18, 0x00, 0xC0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x08, 0x00, 20 | 0xC0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x0C, 0x00, 0x80, 0xFF, 0xFF, 0x1F, 21 | 0x00, 0x00, 0x06, 0x00, 0x80, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x07, 0x00, 22 | 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 23 | 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 24 | 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 25 | 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 26 | 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 27 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 28 | }; 29 | 30 | const char activeSymbole[] PROGMEM = { 31 | B00000000, 32 | B00000000, 33 | B00011000, 34 | B00100100, 35 | B01000010, 36 | B01000010, 37 | B00100100, 38 | B00011000 39 | }; 40 | 41 | const char inactiveSymbole[] PROGMEM = { 42 | B00000000, 43 | B00000000, 44 | B00000000, 45 | B00000000, 46 | B00011000, 47 | B00011000, 48 | B00000000, 49 | B00000000 50 | }; -------------------------------------------------------------------------------- /SSD1306.h: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | 25 | Credits for parts of this code go to Mike Rankin. Thank you so much for sharing! 26 | */ 27 | #pragma once 28 | 29 | #include 30 | #include 31 | #include 32 | #include "SSD1306Fonts.h" 33 | 34 | #define BLACK 0 35 | #define WHITE 1 36 | #define INVERSE 2 37 | 38 | #define WIDTH_POS 0 39 | #define HEIGHT_POS 1 40 | #define FIRST_CHAR_POS 2 41 | #define CHAR_NUM_POS 3 42 | #define CHAR_WIDTH_START_POS 4 43 | 44 | #define TEXT_ALIGN_LEFT 0 45 | #define TEXT_ALIGN_CENTER 1 46 | #define TEXT_ALIGN_RIGHT 2 47 | 48 | #define CHARGEPUMP 0x8D 49 | #define COLUMNADDR 0x21 50 | #define COMSCANDEC 0xC8 51 | #define COMSCANINC 0xC0 52 | #define DISPLAYALLON 0xA5 53 | #define DISPLAYALLON_RESUME 0xA4 54 | #define DISPLAYOFF 0xAE 55 | #define DISPLAYON 0xAF 56 | #define EXTERNALVCC 0x1 57 | #define INVERTDISPLAY 0xA7 58 | #define MEMORYMODE 0x20 59 | #define NORMALDISPLAY 0xA6 60 | #define PAGEADDR 0x22 61 | #define SEGREMAP 0xA0 62 | #define SETCOMPINS 0xDA 63 | #define SETCONTRAST 0x81 64 | #define SETDISPLAYCLOCKDIV 0xD5 65 | #define SETDISPLAYOFFSET 0xD3 66 | #define SETHIGHCOLUMN 0x10 67 | #define SETLOWCOLUMN 0x00 68 | #define SETMULTIPLEX 0xA8 69 | #define SETPRECHARGE 0xD9 70 | #define SETSEGMENTREMAP 0xA1 71 | #define SETSTARTLINE 0x40 72 | #define SETVCOMDETECT 0xDB 73 | #define SWITCHCAPVCC 0x2 74 | 75 | class SSD1306 { 76 | 77 | private: 78 | // I2C 79 | int myI2cAddress; 80 | int mySda; 81 | int mySdc; 82 | bool I2C_io; 83 | 84 | // SPI 85 | int myDC, myRST, myCS; 86 | 87 | uint8_t buffer[128 * 64 / 8]; 88 | int myTextAlignment = TEXT_ALIGN_LEFT; 89 | int myColor = WHITE; 90 | byte lastChar; 91 | const char *myFontData = ArialMT_Plain_10; 92 | 93 | public: 94 | // Create the display object connected to I2C pins pin sda and sdc 95 | SSD1306(int i2cAddress, int sda, int sdc); 96 | 97 | // Create the display object connected to SPI pins and rst, dc and cs (HW_SPI reserved for future use) 98 | SSD1306(bool HW_SPI, int rst, int dc, int cs ); 99 | 100 | // Initialize the display 101 | void init(); 102 | 103 | // Cycle through the initialization 104 | void resetDisplay(void); 105 | 106 | // Connect again to the display through I2C 107 | void reconnect(void); 108 | 109 | // Turn the display on 110 | void displayOn(void); 111 | 112 | // Turn the display offs 113 | void displayOff(void); 114 | 115 | // Clear the local pixel buffer 116 | void clear(void); 117 | 118 | // Write the buffer to the display memory 119 | void display(void); 120 | 121 | // Set display contrast 122 | void setContrast(char contrast); 123 | 124 | // Turn the display upside down 125 | void flipScreenVertically(); 126 | 127 | // Send a command to the display (low level function) 128 | void sendCommand(unsigned char com); 129 | 130 | // Send all the init commands 131 | void sendInitCommands(void); 132 | 133 | // Draw a pixel at given position 134 | void setPixel(int x, int y); 135 | 136 | // Draw 8 bits at the given position 137 | void setChar(int x, int y, unsigned char data); 138 | 139 | // Draw the border of a rectangle at the given location 140 | void drawRect(int x, int y, int width, int height); 141 | 142 | // Fill the rectangle 143 | void fillRect(int x, int y, int width, int height); 144 | 145 | // Draw a bitmap with the given dimensions 146 | void drawBitmap(int x, int y, int width, int height, const char *bitmap); 147 | 148 | // Draw an XBM image with the given dimensions 149 | void drawXbm(int x, int y, int width, int height, const char *xbm); 150 | 151 | // Sets the color of all pixel operations 152 | void setColor(int color); 153 | 154 | // converts utf8 characters to extended ascii 155 | // taken from http://playground.arduino.cc/Main/Utf8ascii 156 | byte utf8ascii(byte ascii); 157 | 158 | // converts utf8 string to extended ascii 159 | // taken from http://playground.arduino.cc/Main/Utf8ascii 160 | String utf8ascii(String s); 161 | 162 | // Draws a string at the given location 163 | void drawString(int x, int y, String text); 164 | 165 | // Draws a String with a maximum width at the given location. 166 | // If the given String is wider than the specified width 167 | // The text will be wrapped to the next line at a space or dash 168 | void drawStringMaxWidth(int x, int y, int maxLineWidth, String text); 169 | 170 | // Returns the width of the String with the current 171 | // font settings 172 | int getStringWidth(String text); 173 | 174 | // Specifies relative to which anchor point 175 | // the text is rendered. Available constants: 176 | // TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT 177 | void setTextAlignment(int textAlignment); 178 | 179 | // Sets the current font. Available default fonts 180 | // defined in SSD1306Fonts.h: 181 | // ArialMT_Plain_10, ArialMT_Plain_16, ArialMT_Plain_24 182 | void setFont(const char *fontData); 183 | 184 | }; -------------------------------------------------------------------------------- /examples/SSD1306Demo/SSD1306Demo.ino: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | */ 25 | #include 26 | #include 27 | #include "SSD1306.h" 28 | #include "SSD1306Ui.h" 29 | #include "images.h" 30 | 31 | // Pin definitions for I2C 32 | #define OLED_SDA D2 // pin 14 33 | #define OLED_SDC D4 // pin 12 34 | #define OLED_ADDR 0x3C 35 | 36 | /* Hardware Wemos D1 mini SPI pins 37 | D5 GPIO14 CLK - D0 pin OLED display 38 | D6 GPIO12 MISO (DIN) - not connected 39 | D7 GPIO13 MOSI (DOUT) - D1 pin OLED display 40 | D8 GPIO15 CS / SS - CS pin OLED display 41 | D0 GPIO16 RST - RST pin OLED display 42 | D2 GPIO4 DC - DC pin OLED 43 | */ 44 | 45 | // Pin definitions for SPI 46 | #define OLED_RESET D0 // RESET 47 | #define OLED_DC D2 // Data/Command 48 | #define OLED_CS D8 // Chip select 49 | 50 | // Uncomment one of the following based on OLED type 51 | // SSD1306 display(true, OLED_RESET, OLED_DC, OLED_CS); // FOR SPI 52 | SSD1306 display(OLED_ADDR, OLED_SDA, OLED_SDC); // For I2C 53 | SSD1306Ui ui ( &display ); 54 | 55 | // this array keeps function pointers to all frames 56 | // frames are the single views that slide from right to left 57 | bool (*frames[])(SSD1306 *display, SSD1306UiState* state, int x, int y) = { drawFrame1, drawFrame2, drawFrame3, drawFrame4 }; 58 | 59 | // how many frames are there? 60 | int frameCount = 4; 61 | 62 | bool (*overlays[])(SSD1306 *display, SSD1306UiState* state) = { msOverlay }; 63 | int overlaysCount = 1; 64 | 65 | void setup() { 66 | Serial.begin(115200); 67 | Serial.println(); 68 | Serial.println(); 69 | 70 | 71 | ui.setTargetFPS(30); 72 | 73 | ui.setActiveSymbole(activeSymbole); 74 | ui.setInactiveSymbole(inactiveSymbole); 75 | 76 | // You can change this to 77 | // TOP, LEFT, BOTTOM, RIGHT 78 | ui.setIndicatorPosition(BOTTOM); 79 | 80 | // Defines where the first frame is located in the bar. 81 | ui.setIndicatorDirection(LEFT_RIGHT); 82 | 83 | // You can change the transition that is used 84 | // SLIDE_LEFT, SLIDE_RIGHT, SLIDE_TOP, SLIDE_DOWN 85 | ui.setFrameAnimation(SLIDE_LEFT); 86 | 87 | // Add frames 88 | ui.setFrames(frames, frameCount); 89 | 90 | // Add overlays 91 | ui.setOverlays(overlays, overlaysCount); 92 | 93 | // Inital UI takes care of initalising the display too. 94 | ui.init(); 95 | 96 | display.flipScreenVertically(); 97 | 98 | } 99 | 100 | void loop() { 101 | int remainingTimeBudget = ui.update(); 102 | 103 | if (remainingTimeBudget > 0) { 104 | // You can do some work here 105 | // Don't do stuff if you are below your 106 | // time budget. 107 | delay(remainingTimeBudget); 108 | } 109 | } 110 | 111 | bool msOverlay(SSD1306 *display, SSD1306UiState* state) { 112 | display->setTextAlignment(TEXT_ALIGN_RIGHT); 113 | display->setFont(ArialMT_Plain_10); 114 | display->drawString(128, 0, String(millis())); 115 | return true; 116 | } 117 | 118 | bool drawFrame1(SSD1306 *display, SSD1306UiState* state, int x, int y) { 119 | // draw an xbm image. 120 | // Please note that everything that should be transitioned 121 | // needs to be drawn relative to x and y 122 | 123 | // if this frame need to be refreshed at the targetFPS you need to 124 | // return true 125 | display->drawXbm(x + 34, y + 14, WiFi_Logo_width, WiFi_Logo_height, WiFi_Logo_bits); 126 | return false; 127 | } 128 | 129 | bool drawFrame2(SSD1306 *display, SSD1306UiState* state, int x, int y) { 130 | // Demonstrates the 3 included default sizes. The fonts come from SSD1306Fonts.h file 131 | // Besides the default fonts there will be a program to convert TrueType fonts into this format 132 | display->setTextAlignment(TEXT_ALIGN_LEFT); 133 | display->setFont(ArialMT_Plain_10); 134 | display->drawString(0 + x, 10 + y, "Arial 10"); 135 | 136 | display->setFont(ArialMT_Plain_16); 137 | display->drawString(0 + x, 20 + y, "Arial 16"); 138 | 139 | display->setFont(ArialMT_Plain_24); 140 | display->drawString(0 + x, 34 + y, "Arial 24"); 141 | 142 | return false; 143 | } 144 | 145 | bool drawFrame3(SSD1306 *display, SSD1306UiState* state, int x, int y) { 146 | // Text alignment demo 147 | display->setFont(ArialMT_Plain_10); 148 | 149 | // The coordinates define the left starting point of the text 150 | display->setTextAlignment(TEXT_ALIGN_LEFT); 151 | display->drawString(0 + x, 11 + y, "Left aligned (0,10)"); 152 | 153 | // The coordinates define the center of the text 154 | display->setTextAlignment(TEXT_ALIGN_CENTER); 155 | display->drawString(64 + x, 22, "Center aligned (64,22)"); 156 | 157 | // The coordinates define the right end of the text 158 | display->setTextAlignment(TEXT_ALIGN_RIGHT); 159 | display->drawString(128 + x, 33, "Right aligned (128,33)"); 160 | return false; 161 | } 162 | 163 | bool drawFrame4(SSD1306 *display, SSD1306UiState* state, int x, int y) { 164 | // Demo for drawStringMaxWidth: 165 | // with the third parameter you can define the width after which words will be wrapped. 166 | // Currently only spaces and "-" are allowed for wrapping 167 | display->setTextAlignment(TEXT_ALIGN_LEFT); 168 | display->setFont(ArialMT_Plain_10); 169 | display->drawStringMaxWidth(0 + x, 10 + y, 128, "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore."); 170 | return false; 171 | } 172 | -------------------------------------------------------------------------------- /SSD1306Ui.h: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Fabrice Weinberg 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | Credits for parts of this code go to Daniel Eichhorn 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include "SSD1306.h" 30 | 31 | enum AnimationDirection { 32 | SLIDE_UP, 33 | SLIDE_DOWN, 34 | SLIDE_LEFT, 35 | SLIDE_RIGHT 36 | }; 37 | 38 | enum IndicatorPosition { 39 | TOP, 40 | RIGHT, 41 | BOTTOM, 42 | LEFT 43 | }; 44 | 45 | enum IndicatorDirection { 46 | LEFT_RIGHT, 47 | RIGHT_LEFT 48 | }; 49 | 50 | enum FrameState { 51 | IN_TRANSITION, 52 | FIXED 53 | }; 54 | 55 | const char ANIMATION_activeSymbole[] PROGMEM = { 56 | 0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00 57 | }; 58 | 59 | const char ANIMATION_inactiveSymbole[] PROGMEM = { 60 | 0x00, 0x0, 0x0, 0x18, 0x18, 0x0, 0x0, 0x00 61 | }; 62 | 63 | 64 | // Structure of the UiState 65 | struct SSD1306UiState { 66 | int lastUpdate = 0; 67 | int ticksSinceLastStateSwitch = 0; 68 | 69 | FrameState frameState = FIXED; 70 | int currentFrame = 0; 71 | }; 72 | 73 | typedef bool (*FrameCallback)(SSD1306 *display, SSD1306UiState* state, int x, int y); 74 | typedef bool (*OverlayCallback)(SSD1306 *display, SSD1306UiState* state); 75 | 76 | class SSD1306Ui { 77 | private: 78 | SSD1306 *display; 79 | 80 | // Global dirty flag to indicate that the display needs to be redraw. 81 | bool dirty = true; 82 | 83 | // Symboles for the Indicator 84 | IndicatorPosition indicatorPosition = BOTTOM; 85 | IndicatorDirection indicatorDirection = LEFT_RIGHT; 86 | 87 | const char* activeSymbole = ANIMATION_activeSymbole; 88 | const char* inactiveSymbole = ANIMATION_inactiveSymbole; 89 | 90 | // Values for the Frames 91 | AnimationDirection frameAnimationDirection = SLIDE_RIGHT; 92 | 93 | int frameTransitionDirection = 1; 94 | 95 | int ticksPerFrame = 151; // ~ 5000ms at 30 FPS 96 | int ticksPerTransition = 15; // ~ 500ms at 30 FPS 97 | 98 | bool autoTransition = true; 99 | 100 | FrameCallback* frameFunctions; 101 | int frameCount = 0; 102 | 103 | // Values for Overlays 104 | OverlayCallback* overlayFunctions; 105 | int overlayCount = 0; 106 | 107 | // UI State 108 | SSD1306UiState state; 109 | 110 | // Bookeeping for update 111 | int updateInterval = 33; 112 | 113 | int getNextFrameNumber(); 114 | void drawIndicator(); 115 | void drawFrame(); 116 | void drawOverlays(); 117 | void tick(); 118 | 119 | public: 120 | 121 | SSD1306Ui(SSD1306 *display); 122 | 123 | /** 124 | * Initialise the display 125 | */ 126 | void init(); 127 | 128 | /** 129 | * Configure the internal used target FPS 130 | */ 131 | void setTargetFPS(byte fps); 132 | 133 | // Automatic Controll 134 | /** 135 | * Enable automatic transition to next frame after the some time can be configured with `setTimePerFrame` and `setTimePerTransition`. 136 | */ 137 | void enableAutoTransition(); 138 | 139 | /** 140 | * Disable automatic transition to next frame. 141 | */ 142 | void disableAutoTransition(); 143 | 144 | /** 145 | * Set the direction if the automatic transitioning 146 | */ 147 | void setAutoTransitionForwards(); 148 | void setAutoTransitionBackwards(); 149 | 150 | /** 151 | * Set the approx. time a frame is displayed 152 | */ 153 | void setTimePerFrame(int time); 154 | 155 | /** 156 | * Set the approx. time a transition will take 157 | */ 158 | void setTimePerTransition(int time); 159 | 160 | // Customize indicator position and style 161 | /** 162 | * Set the position of the indicator bar. 163 | */ 164 | void setIndicatorPosition(IndicatorPosition pos); 165 | 166 | /** 167 | * Set the direction of the indicator bar. Defining the order of frames ASCENDING / DESCENDING 168 | */ 169 | void setIndicatorDirection(IndicatorDirection dir); 170 | 171 | /** 172 | * Set the symbole to indicate an active frame in the indicator bar. 173 | */ 174 | void setActiveSymbole(const char* symbole); 175 | 176 | /** 177 | * Set the symbole to indicate an inactive frame in the indicator bar. 178 | */ 179 | void setInactiveSymbole(const char* symbole); 180 | 181 | // Frame settings 182 | 183 | /** 184 | * Configure what animation is used to transition from one frame to another 185 | */ 186 | void setFrameAnimation(AnimationDirection dir); 187 | 188 | /** 189 | * Add frame drawing functions 190 | */ 191 | void setFrames(FrameCallback* frameFunctions, int frameCount); 192 | 193 | // Overlay 194 | 195 | /** 196 | * Add overlays drawing functions that are draw independent of the Frames 197 | */ 198 | void setOverlays(OverlayCallback* overlayFunctions, int overlayCount); 199 | 200 | // Manuell Controll 201 | void nextFrame(); 202 | void previousFrame(); 203 | 204 | // State Info 205 | SSD1306UiState getUiState(); 206 | 207 | int update(); 208 | }; 209 | 210 | -------------------------------------------------------------------------------- /SSD1306Ui.cpp: -------------------------------------------------------------------------------- 1 | #include "SSD1306Ui.h" 2 | 3 | 4 | SSD1306Ui::SSD1306Ui(SSD1306 *display) { 5 | this->display = display; 6 | } 7 | 8 | void SSD1306Ui::init() { 9 | this->display->init(); 10 | } 11 | 12 | void SSD1306Ui::setTargetFPS(byte fps){ 13 | int oldInterval = this->updateInterval; 14 | this->updateInterval = ((float) 1.0 / (float) fps) * 1000; 15 | 16 | // Calculate new ticksPerFrame 17 | float changeRatio = oldInterval / this->updateInterval; 18 | this->ticksPerFrame *= changeRatio; 19 | this->ticksPerTransition *= changeRatio; 20 | } 21 | 22 | // -/------ Automatic controll ------\- 23 | 24 | void SSD1306Ui::enableAutoTransition(){ 25 | this->autoTransition = true; 26 | } 27 | void SSD1306Ui::disableAutoTransition(){ 28 | this->autoTransition = false; 29 | } 30 | void SSD1306Ui::setAutoTransitionForwards(){ 31 | this->frameTransitionDirection = 1; 32 | } 33 | void SSD1306Ui::setAutoTransitionBackwards(){ 34 | this->frameTransitionDirection = 1; 35 | } 36 | void SSD1306Ui::setTimePerFrame(int time){ 37 | this->ticksPerFrame = (int) ( (float) time / (float) updateInterval); 38 | } 39 | void SSD1306Ui::setTimePerTransition(int time){ 40 | this->ticksPerTransition = (int) ( (float) time / (float) updateInterval); 41 | } 42 | 43 | 44 | // -/------ Customize indicator position and style -------\- 45 | void SSD1306Ui::setIndicatorPosition(IndicatorPosition pos) { 46 | this->indicatorPosition = pos; 47 | this->dirty = true; 48 | } 49 | void SSD1306Ui::setIndicatorDirection(IndicatorDirection dir) { 50 | this->indicatorDirection = dir; 51 | } 52 | void SSD1306Ui::setActiveSymbole(const char* symbole) { 53 | this->activeSymbole = symbole; 54 | this->dirty = true; 55 | } 56 | void SSD1306Ui::setInactiveSymbole(const char* symbole) { 57 | this->inactiveSymbole = symbole; 58 | this->dirty = true; 59 | } 60 | 61 | 62 | // -/----- Frame settings -----\- 63 | void SSD1306Ui::setFrameAnimation(AnimationDirection dir) { 64 | this->frameAnimationDirection = dir; 65 | } 66 | void SSD1306Ui::setFrames(FrameCallback* frameFunctions, int frameCount) { 67 | this->frameCount = frameCount; 68 | this->frameFunctions = frameFunctions; 69 | } 70 | 71 | // -/----- Overlays ------\- 72 | void SSD1306Ui::setOverlays(OverlayCallback* overlayFunctions, int overlayCount){ 73 | this->overlayCount = overlayCount; 74 | this->overlayFunctions = overlayFunctions; 75 | } 76 | 77 | 78 | // -/----- Manuel control -----\- 79 | void SSD1306Ui::nextFrame() { 80 | this->state.frameState = IN_TRANSITION; 81 | this->state.ticksSinceLastStateSwitch = 0; 82 | this->frameTransitionDirection = 1; 83 | } 84 | void SSD1306Ui::previousFrame() { 85 | this->state.frameState = IN_TRANSITION; 86 | this->state.ticksSinceLastStateSwitch = 0; 87 | this->frameTransitionDirection = -1; 88 | } 89 | 90 | 91 | // -/----- State information -----\- 92 | SSD1306UiState SSD1306Ui::getUiState(){ 93 | return this->state; 94 | } 95 | 96 | 97 | int SSD1306Ui::update(){ 98 | int timeBudget = this->updateInterval - (millis() - this->state.lastUpdate); 99 | if ( timeBudget <= 0) { 100 | // Implement frame skipping to ensure time budget is keept 101 | if (this->autoTransition && this->state.lastUpdate != 0) this->state.ticksSinceLastStateSwitch += ceil(-timeBudget / this->updateInterval); 102 | 103 | this->state.lastUpdate = millis(); 104 | this->tick(); 105 | } 106 | return timeBudget; 107 | } 108 | 109 | 110 | void SSD1306Ui::tick() { 111 | this->state.ticksSinceLastStateSwitch++; 112 | 113 | switch (this->state.frameState) { 114 | case IN_TRANSITION: 115 | this->dirty = true; 116 | if (this->state.ticksSinceLastStateSwitch >= this->ticksPerTransition){ 117 | this->state.frameState = FIXED; 118 | this->state.currentFrame = getNextFrameNumber(); 119 | this->state.ticksSinceLastStateSwitch = 0; 120 | } 121 | break; 122 | case FIXED: 123 | if (this->state.ticksSinceLastStateSwitch >= this->ticksPerFrame){ 124 | if (this->autoTransition){ 125 | this->state.frameState = IN_TRANSITION; 126 | this->dirty = true; 127 | } 128 | this->state.ticksSinceLastStateSwitch = 0; 129 | } 130 | break; 131 | } 132 | 133 | if (this->dirty) { 134 | this->dirty = false; 135 | this->display->clear(); 136 | this->drawIndicator(); 137 | this->drawFrame(); 138 | this->drawOverlays(); 139 | this->display->display(); 140 | } 141 | } 142 | 143 | void SSD1306Ui::drawFrame(){ 144 | switch (this->state.frameState){ 145 | case IN_TRANSITION: { 146 | float progress = (float) this->state.ticksSinceLastStateSwitch / (float) this->ticksPerTransition; 147 | int x, y, x1, y1; 148 | switch(this->frameAnimationDirection){ 149 | case SLIDE_LEFT: 150 | x = -128 * progress; 151 | y = 0; 152 | x1 = x + 128; 153 | y1 = 0; 154 | break; 155 | case SLIDE_RIGHT: 156 | x = 128 * progress; 157 | y = 0; 158 | x1 = x - 128; 159 | y1 = 0; 160 | break; 161 | case SLIDE_UP: 162 | x = 0; 163 | y = -64 * progress; 164 | x1 = 0; 165 | y1 = y + 64; 166 | break; 167 | case SLIDE_DOWN: 168 | x = 0; 169 | y = 64 * progress; 170 | x1 = 0; 171 | y1 = y - 64; 172 | break; 173 | } 174 | 175 | // Invert animation if direction is reversed. 176 | int dir = frameTransitionDirection >= 0 ? 1 : -1; 177 | x *= dir; y *= dir; x1 *= dir; y1 *= dir; 178 | 179 | this->dirty |= (this->frameFunctions[this->state.currentFrame])(this->display, &this->state, x, y); 180 | this->dirty |= (this->frameFunctions[this->getNextFrameNumber()])(this->display, &this->state, x1, y1); 181 | break; 182 | } 183 | case FIXED: 184 | this->dirty |= (this->frameFunctions[this->state.currentFrame])(this->display, &this->state, 0, 0); 185 | break; 186 | } 187 | } 188 | 189 | void SSD1306Ui::drawIndicator() { 190 | byte posOfCurrentFrame; 191 | 192 | switch (this->indicatorDirection){ 193 | case LEFT_RIGHT: 194 | posOfCurrentFrame = this->state.currentFrame; 195 | break; 196 | case RIGHT_LEFT: 197 | posOfCurrentFrame = (this->frameCount - 1) - this->state.currentFrame; 198 | break; 199 | } 200 | 201 | for (byte i = 0; i < this->frameCount; i++) { 202 | 203 | const char *image; 204 | 205 | if (posOfCurrentFrame == i) { 206 | image = this->activeSymbole; 207 | } else { 208 | image = this->inactiveSymbole; 209 | } 210 | 211 | int x,y; 212 | switch (this->indicatorPosition){ 213 | case TOP: 214 | y = 0; 215 | x = 64 - (12 * frameCount / 2) + 12 * i; 216 | break; 217 | case BOTTOM: 218 | y = 56; 219 | x = 64 - (12 * frameCount / 2) + 12 * i; 220 | break; 221 | case RIGHT: 222 | x = 120; 223 | y = 32 - (12 * frameCount / 2) + 12 * i; 224 | break; 225 | case LEFT: 226 | x = 0; 227 | y = 32 - (12 * frameCount / 2) + 12 * i; 228 | break; 229 | } 230 | 231 | this->display->drawXbm(x, y, 8, 8, image); 232 | } 233 | } 234 | 235 | void SSD1306Ui::drawOverlays() { 236 | for (int i=0;ioverlayCount;i++){ 237 | this->dirty |= (this->overlayFunctions[i])(this->display, &this->state); 238 | } 239 | } 240 | 241 | int SSD1306Ui::getNextFrameNumber(){ 242 | int nextFrame = (this->state.currentFrame + this->frameTransitionDirection) % this->frameCount; 243 | if (nextFrame < 0){ 244 | nextFrame = this->frameCount + nextFrame; 245 | } 246 | return nextFrame; 247 | } 248 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # esp8266-oled-ssd1306 2 | 3 | This is a driver for the SSD1306 based 128x64 pixel OLED display running on the Arduino/ESP8266 platform. 4 | Can be used with either the I2C or SPI version of the display 5 | 6 | You can either download this library as a zip file and unpack it to your Arduino/libraries folder or (once it has been added) choose it from the Arduino library manager. 7 | 8 | ## Credits 9 | Many thanks go to Fabrice Weinberg (@FWeinb) for optimizing and refactoring the UI library. 10 | The init sequence for the SSD1306 was inspired by Adafruits library for the same display. 11 | The SPI code was inspired by somhi/ESP_SSD1306 and the Adafruit library 12 | 13 | ## Usage 14 | 15 | The SSD1306Demo is a very comprehensive example demonstrating the most important features of the library. 16 | 17 | ## Features 18 | 19 | * Draw pixels at given coordinates 20 | * Draw or fill a rectangle with given dimensions 21 | * Draw Text at given coordinates: 22 | * Define Alignment: Left, Right and Center 23 | * Set the Fontface you want to use (see section Fonts below) 24 | * Limit the width of the text by an amount of pixels. Before this widths will be reached, the renderer will wrap the text to a new line if possible 25 | * Display content in automatically side scrolling carousel 26 | * Define transition cycles 27 | * Define how long one frame will be displayed 28 | * Draw the different frames in callback methods 29 | * One indicator per frame will be automatically displayed. The active frame will be displayed from inactive once 30 | 31 | ## Fonts 32 | 33 | Fonts are defined in a proprietary but open format. You can create new font files by choosing from a given list 34 | of open sourced Fonts from this web app: http://oleddisplay.squix.ch 35 | Choose the font family, style and size, check the preview image and if you like what you see click the "Create" button. This will create the font array in a text area form where you can copy and paste it into a new or existing header file. 36 | 37 | ![FontTool](https://github.com/squix78/esp8266-oled-ssd1306/raw/master/resources/FontTool.png) 38 | 39 | 40 | ## API 41 | 42 | ### Display Control 43 | 44 | ```C++ 45 | // Create the display object connected to pin sda and sdc 46 | SSD1306(int i2cAddress, int sda, int sdc); 47 | 48 | // Initialize the display 49 | void init(); 50 | 51 | // Cycle through the initialization 52 | void resetDisplay(void); 53 | 54 | // Connect again to the display through I2C 55 | void reconnect(void); 56 | 57 | // Turn the display on 58 | void displayOn(void); 59 | 60 | // Turn the display offs 61 | void displayOff(void); 62 | 63 | // Clear the local pixel buffer 64 | void clear(void); 65 | 66 | // Write the buffer to the display memory 67 | void display(void); 68 | 69 | // Set display contrast 70 | void setContrast(char contrast); 71 | 72 | // Turn the display upside down 73 | void flipScreenVertically(); 74 | 75 | // Send a command to the display (low level function) 76 | void sendCommand(unsigned char com); 77 | 78 | // Send all the init commands 79 | void sendInitCommands(void); 80 | ``` 81 | 82 | ## Pixel drawing 83 | 84 | ```C++ 85 | // Draw a pixel at given position 86 | void setPixel(int x, int y); 87 | 88 | // Draw 8 bits at the given position 89 | void setChar(int x, int y, unsigned char data); 90 | 91 | // Draw the border of a rectangle at the given location 92 | void drawRect(int x, int y, int width, int height); 93 | 94 | // Fill the rectangle 95 | void fillRect(int x, int y, int width, int height); 96 | 97 | // Draw a bitmap with the given dimensions 98 | void drawBitmap(int x, int y, int width, int height, const char *bitmap); 99 | 100 | // Draw an XBM image with the given dimensions 101 | void drawXbm(int x, int y, int width, int height, const char *xbm); 102 | 103 | // Sets the color of all pixel operations 104 | void setColor(int color); 105 | ``` 106 | 107 | ## Text operations 108 | 109 | ``` C++ 110 | // Draws a string at the given location 111 | void drawString(int x, int y, String text); 112 | 113 | // Draws a String with a maximum width at the given location. 114 | // If the given String is wider than the specified width 115 | // The text will be wrapped to the next line at a space or dash 116 | void drawStringMaxWidth(int x, int y, int maxLineWidth, String text); 117 | 118 | // Returns the width of the String with the current 119 | // font settings 120 | int getStringWidth(String text); 121 | 122 | // Specifies relative to which anchor point 123 | // the text is rendered. Available constants: 124 | // TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT 125 | void setTextAlignment(int textAlignment); 126 | 127 | // Sets the current font. Available default fonts 128 | // defined in SSD1306Fonts.h: 129 | // ArialMT_Plain_10, ArialMT_Plain_16, ArialMT_Plain_24 130 | // Or create one with the font tool at http://oleddisplay.squix.ch 131 | void setFont(const char *fontData); 132 | ``` 133 | 134 | ## Frame Transition Functions 135 | 136 | The Frame Transition functions are a set of functions on top of the basic library. They allow you to easily write frames which will be shifted in regular intervals. The frame animation (including the frame indicators) will only be activated if you define callback functions with setFrameCallacks(..). If no callback methods are defined no indicators will be displayed. 137 | 138 | ```C++ 139 | // Sets the callback methods of the format void method(x,y). As soon as you define the callbacks 140 | // the library is in "frame mode" and indicators will be drawn. 141 | void setFrameCallbacks(int frameCount, void (*frameCallbacks[])(SSD1306 *display, SSD1306UiState* state,int x, int y)); 142 | 143 | // Tells the framework to move to the next tick. The 144 | // current visible frame callback will be called once 145 | // per tick 146 | void nextFrameTick(void); 147 | 148 | // Draws the frame indicators. In a normal setup 149 | // the framework does this for you 150 | void drawIndicators(int frameCount, int activeFrame); 151 | 152 | // defines how many ticks a frame should remain visible 153 | // This does not include the transition 154 | void setFrameWaitTicks(int frameWaitTicks); 155 | 156 | // Defines how many ticks should be used for a transition 157 | void setFrameTransitionTicks(int frameTransitionTicks); 158 | 159 | // Returns the current state of the internal state machine 160 | // Possible values: FRAME_STATE_FIX, FRAME_STATE_TRANSITION 161 | // You can use this to detect when there is no transition 162 | // on the way to execute operations that would 163 | int getFrameState(); 164 | ``` 165 | 166 | ## Example: SSD1306Demo 167 | 168 | ### Frame 1 169 | ![DemoFrame1](https://github.com/squix78/esp8266-oled-ssd1306/raw/master/resources/DemoFrame1.jpg) 170 | 171 | This frame shows three things: 172 | * How to draw an xbm image 173 | * How to draw a static text which is not moved by the frame transition 174 | * The active/inactive frame indicators 175 | 176 | ### Frame 2 177 | ![DemoFrame2](https://github.com/squix78/esp8266-oled-ssd1306/raw/master/resources/DemoFrame2.jpg) 178 | 179 | Currently there are one fontface with three sizes included in the library: Arial 10, 16 and 24. Once the converter is published you will be able to convert any ttf font into the used format. 180 | 181 | ### Frame 3 182 | 183 | ![DemoFrame3](https://github.com/squix78/esp8266-oled-ssd1306/raw/master/resources/DemoFrame3.jpg) 184 | 185 | This frame demonstrates the text alignment. The coordinates in the frame show relative to which position the texts have been rendered. 186 | 187 | ### Frame 4 188 | 189 | ![DemoFrame4](https://github.com/squix78/esp8266-oled-ssd1306/raw/master/resources/DemoFrame4.jpg) 190 | 191 | This shows how to use define a maximum width after which the driver automatically wraps a word to the next line. This comes in very handy if you have longer texts to display. 192 | 193 | ### SPI version 194 | 195 | ![SPIVersion](https://github.com/neptune2/esp8266-oled-ssd1306/raw/master/resources/SPI_version.jpg) 196 | 197 | This shows the code working on the SPI version of the display. See demo code for ESP8266 pins used. 198 | -------------------------------------------------------------------------------- /SSD1306.cpp: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | 25 | Credits for parts of this code go to Mike Rankin. Thank you so much for sharing! 26 | 27 | SPI additions by Neptune2 28 | */ 29 | 30 | #include "SSD1306.h" 31 | 32 | // constructor for I2C - we indicate i2cAddress, sda and sdc 33 | SSD1306::SSD1306(int i2cAddress, int sda, int sdc) { 34 | myI2cAddress = i2cAddress; 35 | mySda = sda; 36 | mySdc = sdc; 37 | I2C_io = true; 38 | } 39 | 40 | // constructor for hardware SPI - we indicate Reset, DataCommand and ChipSelect 41 | // (HW_SPI used to differentiate constructor - reserved for future use) 42 | SSD1306::SSD1306(bool HW_SPI, int rst, int dc, int cs ) { 43 | myRST = rst; 44 | myDC = dc; 45 | myCS = cs; 46 | I2C_io = false; 47 | } 48 | 49 | void SSD1306::init() { 50 | if (I2C_io){ 51 | Wire.begin(mySda, mySdc); 52 | Wire.setClock(400000); 53 | } else { 54 | pinMode(myDC, OUTPUT); 55 | pinMode(myCS, OUTPUT); 56 | 57 | SPI.begin (); 58 | SPI.setClockDivider (SPI_CLOCK_DIV2); 59 | 60 | pinMode(myRST, OUTPUT); 61 | // Pulse Reset low for 10ms 62 | digitalWrite(myRST, HIGH); 63 | delay(1); 64 | digitalWrite(myRST, LOW); 65 | delay(10); 66 | digitalWrite(myRST, HIGH); 67 | } 68 | sendInitCommands(); 69 | resetDisplay(); 70 | } 71 | 72 | void SSD1306::resetDisplay(void) { 73 | displayOff(); 74 | clear(); 75 | display(); 76 | displayOn(); 77 | } 78 | 79 | void SSD1306::reconnect() { 80 | if (I2C_io){ 81 | Wire.begin(mySda, mySdc); 82 | } else { 83 | SPI.begin (); 84 | } 85 | } 86 | 87 | void SSD1306::displayOn(void) { 88 | sendCommand(0xaf); //display on 89 | } 90 | 91 | void SSD1306::displayOff(void) { 92 | sendCommand(0xae); //display off 93 | } 94 | 95 | void SSD1306::setContrast(char contrast) { 96 | sendCommand(0x81); 97 | sendCommand(contrast); 98 | } 99 | 100 | void SSD1306::flipScreenVertically() { 101 | sendCommand(0xA0 | 0x1); //SEGREMAP //Rotate screen 180 deg 102 | sendCommand(0xC8); //COMSCANDEC Rotate screen 180 Deg 103 | } 104 | 105 | void SSD1306::clear(void) { 106 | memset(buffer, 0, (128 * 64 / 8)); 107 | } 108 | 109 | void SSD1306::display(void) { 110 | sendCommand(COLUMNADDR); 111 | sendCommand(0x0); 112 | sendCommand(0x7F); 113 | 114 | sendCommand(PAGEADDR); 115 | sendCommand(0x0); 116 | sendCommand(0x7); 117 | 118 | 119 | if (I2C_io) { 120 | for (uint16_t i=0; i<(128*64/8); i++) { 121 | // send a bunch of data in one xmission 122 | Wire.beginTransmission(myI2cAddress); 123 | Wire.write(0x40); 124 | for (uint8_t x=0; x<16; x++) { 125 | Wire.write(buffer[i]); 126 | i++; 127 | } 128 | i--; 129 | yield(); 130 | Wire.endTransmission(); 131 | } 132 | } else { 133 | digitalWrite(myCS, HIGH); 134 | digitalWrite(myDC, HIGH); // data mode 135 | digitalWrite(myCS, LOW); 136 | for (uint16_t i=0; i<(128*64/8); i++) { 137 | SPI.transfer(buffer[i]); 138 | } 139 | digitalWrite(myCS, HIGH); 140 | } 141 | } 142 | 143 | void SSD1306::setPixel(int x, int y) { 144 | if (x >= 0 && x < 128 && y >= 0 && y < 64) { 145 | 146 | switch (myColor) { 147 | case WHITE: buffer[x + (y/8)*128] |= (1 << (y&7)); break; 148 | case BLACK: buffer[x + (y/8)*128] &= ~(1 << (y&7)); break; 149 | case INVERSE: buffer[x + (y/8)*128] ^= (1 << (y&7)); break; 150 | } 151 | } 152 | } 153 | 154 | void SSD1306::setChar(int x, int y, unsigned char data) { 155 | for (int i = 0; i < 8; i++) { 156 | if (bitRead(data, i)) { 157 | setPixel(x,y + i); 158 | } 159 | } 160 | } 161 | 162 | // Code form http://playground.arduino.cc/Main/Utf8ascii 163 | byte SSD1306::utf8ascii(byte ascii) { 164 | if ( ascii<128 ) { // Standard ASCII-set 0..0x7F handling 165 | lastChar=0; 166 | return( ascii ); 167 | } 168 | 169 | // get previous input 170 | byte last = lastChar; // get last char 171 | lastChar=ascii; // remember actual character 172 | 173 | switch (last) // conversion depnding on first UTF8-character 174 | { case 0xC2: return (ascii); break; 175 | case 0xC3: return (ascii | 0xC0); break; 176 | case 0x82: if(ascii==0xAC) return(0x80); // special case Euro-symbol 177 | } 178 | 179 | return (0); // otherwise: return zero, if character has to be ignored 180 | } 181 | 182 | // Code form http://playground.arduino.cc/Main/Utf8ascii 183 | String SSD1306::utf8ascii(String s) { 184 | String r= ""; 185 | char c; 186 | for (int i=0; i