[175] | 1 | /*********************************************************************
|
---|
| 2 | This is a library for our Monochrome OLEDs based on SSD1306 drivers
|
---|
| 3 |
|
---|
| 4 | Pick one up today in the adafruit shop!
|
---|
| 5 | ------> http://www.adafruit.com/category/63_98
|
---|
| 6 |
|
---|
| 7 | These displays use SPI to communicate, 4 or 5 pins are required to
|
---|
| 8 | interface
|
---|
| 9 |
|
---|
| 10 | Adafruit invests time and resources providing this open source code,
|
---|
| 11 | please support Adafruit and open-source hardware by purchasing
|
---|
| 12 | products from Adafruit!
|
---|
| 13 |
|
---|
| 14 | Written by Limor Fried/Ladyada for Adafruit Industries.
|
---|
| 15 | BSD license, check license.txt for more information
|
---|
| 16 | All text above, and the splash screen below must be included in any redistribution
|
---|
| 17 |
|
---|
| 18 | - 21 Mar. 2016
|
---|
| 19 | Library modified to work with Arduino Lucky Shield
|
---|
| 20 | by andrea[at]arduino[dot]org
|
---|
| 21 | *********************************************************************/
|
---|
| 22 |
|
---|
| 23 | #include <avr/pgmspace.h>
|
---|
| 24 | #if !defined __SAM3X8E__ && !defined ARDUINO_ARCH_SAMD
|
---|
| 25 | #include <util/delay.h>
|
---|
| 26 | #endif
|
---|
| 27 | #include <stdlib.h>
|
---|
| 28 |
|
---|
| 29 | #include <Wire.h>
|
---|
| 30 |
|
---|
| 31 | #include "Adafruit_GFX.h"
|
---|
| 32 | #include "Adafruit_SSD1306.h"
|
---|
| 33 |
|
---|
| 34 | // the memory buffer for the LCD
|
---|
| 35 |
|
---|
| 36 | static uint8_t buffer[SSD1306_LCDHEIGHT * SSD1306_LCDWIDTH / 8] = {
|
---|
| 37 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 38 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 39 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 40 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
|
---|
| 41 | 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 42 | 0x00, 0x80, 0x80, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 43 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 44 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 45 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 46 | 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xF8, 0xE0, 0x00, 0x00, 0x00, 0x00,
|
---|
| 47 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
|
---|
| 48 | 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xFF,
|
---|
| 49 | #if (SSD1306_LCDHEIGHT * SSD1306_LCDWIDTH > 96*16)
|
---|
| 50 | 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
|
---|
| 51 | 0x80, 0xFF, 0xFF, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80,
|
---|
| 52 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x8C, 0x8E, 0x84, 0x00, 0x00, 0x80, 0xF8,
|
---|
| 53 | 0xF8, 0xF8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 54 | 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x80,
|
---|
| 55 | 0x00, 0xE0, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
|
---|
| 56 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xC7, 0x01, 0x01,
|
---|
| 57 | 0x01, 0x01, 0x83, 0xFF, 0xFF, 0x00, 0x00, 0x7C, 0xFE, 0xC7, 0x01, 0x01, 0x01, 0x01, 0x83, 0xFF,
|
---|
| 58 | 0xFF, 0xFF, 0x00, 0x38, 0xFE, 0xC7, 0x83, 0x01, 0x01, 0x01, 0x83, 0xC7, 0xFF, 0xFF, 0x00, 0x00,
|
---|
| 59 | 0x01, 0xFF, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0xFF, 0x07, 0x01, 0x01, 0x01, 0x00, 0x00, 0x7F, 0xFF,
|
---|
| 60 | 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0xFF,
|
---|
| 61 | 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 62 | 0x03, 0x0F, 0x3F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC7, 0xC7, 0x8F,
|
---|
| 63 | 0x8F, 0x9F, 0xBF, 0xFF, 0xFF, 0xC3, 0xC0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFC,
|
---|
| 64 | 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF8, 0xF0, 0xF0, 0xE0, 0xC0, 0x00, 0x01, 0x03, 0x03, 0x03,
|
---|
| 65 | 0x03, 0x03, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01,
|
---|
| 66 | 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00,
|
---|
| 67 | 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
---|
| 68 | 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x03,
|
---|
| 69 | 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 70 | #if (SSD1306_LCDHEIGHT == 64)
|
---|
| 71 | 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x1F, 0x0F,
|
---|
| 72 | 0x87, 0xC7, 0xF7, 0xFF, 0xFF, 0x1F, 0x1F, 0x3D, 0xFC, 0xF8, 0xF8, 0xF8, 0xF8, 0x7C, 0x7D, 0xFF,
|
---|
| 73 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x0F, 0x07, 0x00, 0x30, 0x30, 0x00, 0x00,
|
---|
| 74 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 75 | 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 76 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xC0, 0x00,
|
---|
| 77 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
|
---|
| 78 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 79 | 0x00, 0xC0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x3F, 0x1F,
|
---|
| 80 | 0x0F, 0x07, 0x1F, 0x7F, 0xFF, 0xFF, 0xF8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xE0,
|
---|
| 81 | 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00,
|
---|
| 82 | 0x00, 0xFC, 0xFE, 0xFC, 0x0C, 0x06, 0x06, 0x0E, 0xFC, 0xF8, 0x00, 0x00, 0xF0, 0xF8, 0x1C, 0x0E,
|
---|
| 83 | 0x06, 0x06, 0x06, 0x0C, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFC,
|
---|
| 84 | 0xFE, 0xFC, 0x00, 0x18, 0x3C, 0x7E, 0x66, 0xE6, 0xCE, 0x84, 0x00, 0x00, 0x06, 0xFF, 0xFF, 0x06,
|
---|
| 85 | 0x06, 0xFC, 0xFE, 0xFC, 0x0C, 0x06, 0x06, 0x06, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xC0, 0xF8,
|
---|
| 86 | 0xFC, 0x4E, 0x46, 0x46, 0x46, 0x4E, 0x7C, 0x78, 0x40, 0x18, 0x3C, 0x76, 0xE6, 0xCE, 0xCC, 0x80,
|
---|
| 87 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 88 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0F, 0x1F, 0x1F, 0x3F, 0x3F, 0x3F, 0x3F, 0x1F, 0x0F, 0x03,
|
---|
| 89 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00,
|
---|
| 90 | 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x03, 0x07, 0x0E, 0x0C,
|
---|
| 91 | 0x18, 0x18, 0x0C, 0x06, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x01, 0x0F, 0x0E, 0x0C, 0x18, 0x0C, 0x0F,
|
---|
| 92 | 0x07, 0x01, 0x00, 0x04, 0x0E, 0x0C, 0x18, 0x0C, 0x0F, 0x07, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00,
|
---|
| 93 | 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x07,
|
---|
| 94 | 0x07, 0x0C, 0x0C, 0x18, 0x1C, 0x0C, 0x06, 0x06, 0x00, 0x04, 0x0E, 0x0C, 0x18, 0x0C, 0x0F, 0x07,
|
---|
| 95 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 96 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 97 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 98 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 99 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 100 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 101 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
---|
| 102 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
---|
| 103 | #endif
|
---|
| 104 | #endif
|
---|
| 105 | };
|
---|
| 106 |
|
---|
| 107 | #define ssd1306_swap(a, b) { int16_t t = a; a = b; b = t; }
|
---|
| 108 |
|
---|
| 109 | // the most basic function, set a single pixel
|
---|
| 110 | void Adafruit_SSD1306::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
---|
| 111 | if ((x < 0) || (x >= width()) || (y < 0) || (y >= height()))
|
---|
| 112 | return;
|
---|
| 113 |
|
---|
| 114 | // check rotation, move pixel around if necessary
|
---|
| 115 | switch (getRotation()) {
|
---|
| 116 | case 1:
|
---|
| 117 | ssd1306_swap(x, y);
|
---|
| 118 | x = WIDTH - x - 1;
|
---|
| 119 | break;
|
---|
| 120 | case 2:
|
---|
| 121 | x = WIDTH - x - 1;
|
---|
| 122 | y = HEIGHT - y - 1;
|
---|
| 123 | break;
|
---|
| 124 | case 3:
|
---|
| 125 | ssd1306_swap(x, y);
|
---|
| 126 | y = HEIGHT - y - 1;
|
---|
| 127 | break;
|
---|
| 128 | }
|
---|
| 129 |
|
---|
| 130 | // x is which column
|
---|
| 131 | switch (color)
|
---|
| 132 | {
|
---|
| 133 | case WHITE: buffer[x+ (y/8)*SSD1306_LCDWIDTH] |= (1 << (y&7)); break;
|
---|
| 134 | case BLACK: buffer[x+ (y/8)*SSD1306_LCDWIDTH] &= ~(1 << (y&7)); break;
|
---|
| 135 | case INVERSE: buffer[x+ (y/8)*SSD1306_LCDWIDTH] ^= (1 << (y&7)); break;
|
---|
| 136 | }
|
---|
| 137 |
|
---|
| 138 | }
|
---|
| 139 |
|
---|
| 140 | // Adafruit_SSD1306::Adafruit_SSD1306(int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS) : Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT) {
|
---|
| 141 | // cs = CS;
|
---|
| 142 | // rst = RST;
|
---|
| 143 | // dc = DC;
|
---|
| 144 | // sclk = SCLK;
|
---|
| 145 | // sid = SID;
|
---|
| 146 | // hwSPI = false;
|
---|
| 147 | // }
|
---|
| 148 |
|
---|
| 149 | // constructor for hardware SPI - we indicate DataCommand, ChipSelect, Reset
|
---|
| 150 | // Adafruit_SSD1306::Adafruit_SSD1306(int8_t DC, int8_t RST, int8_t CS) : Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT) {
|
---|
| 151 | // dc = DC;
|
---|
| 152 | // rst = RST;
|
---|
| 153 | // cs = CS;
|
---|
| 154 | // hwSPI = true;
|
---|
| 155 | // }
|
---|
| 156 |
|
---|
| 157 | // initializer for I2C - we only indicate the reset pin!
|
---|
| 158 | Adafruit_SSD1306::Adafruit_SSD1306() :
|
---|
| 159 | Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT) {
|
---|
| 160 | //sclk = dc = cs = sid = -1;
|
---|
| 161 | //rst = 4;
|
---|
| 162 | }
|
---|
| 163 |
|
---|
| 164 |
|
---|
| 165 | void Adafruit_SSD1306::begin() {
|
---|
| 166 | _vccstate = SSD1306_SWITCHCAPVCC;
|
---|
| 167 | _i2caddr = 0X3C;
|
---|
| 168 |
|
---|
| 169 | #ifdef __SAM3X8E__
|
---|
| 170 | // Force 400 KHz I2C, rawr! (Uses pins 20, 21 for SDA, SCL)
|
---|
| 171 | TWI1->TWI_CWGR = 0;
|
---|
| 172 | TWI1->TWI_CWGR = ((VARIANT_MCK / (2 * 400000)) - 4) * 0x101;
|
---|
| 173 | #endif
|
---|
| 174 | //}
|
---|
| 175 |
|
---|
| 176 | //if (reset) {
|
---|
| 177 | // Setup reset pin direction (used by both SPI and I2C)
|
---|
| 178 | // pinMode(rst, OUTPUT);
|
---|
| 179 | // digitalWrite(rst, HIGH);
|
---|
| 180 | // // VDD (3.3V) goes high at start, lets just chill for a ms
|
---|
| 181 | // delay(1);
|
---|
| 182 | // // bring reset low
|
---|
| 183 | // digitalWrite(rst, LOW);
|
---|
| 184 | // // wait 10ms
|
---|
| 185 | // delay(10);
|
---|
| 186 | // // bring out of reset
|
---|
| 187 | // digitalWrite(rst, HIGH);
|
---|
| 188 | // turn on VCC (9V?)
|
---|
| 189 | Wire.beginTransmission(0x20); // setup out direction registers
|
---|
| 190 | Wire.write(0x03); // pointer
|
---|
| 191 | Wire.write(128); // DDR Port0 bits 0-3 input 4-7 output
|
---|
| 192 | Wire.endTransmission();
|
---|
| 193 | // }
|
---|
| 194 |
|
---|
| 195 | #if defined SSD1306_128_32
|
---|
| 196 | // Init sequence for 128x32 OLED module
|
---|
| 197 | ssd1306_command(SSD1306_DISPLAYOFF); // 0xAE
|
---|
| 198 | ssd1306_command(SSD1306_SETDISPLAYCLOCKDIV); // 0xD5
|
---|
| 199 | ssd1306_command(0x80); // the suggested ratio 0x80
|
---|
| 200 | ssd1306_command(SSD1306_SETMULTIPLEX); // 0xA8
|
---|
| 201 | ssd1306_command(0x1F);
|
---|
| 202 | ssd1306_command(SSD1306_SETDISPLAYOFFSET); // 0xD3
|
---|
| 203 | ssd1306_command(0x0); // no offset
|
---|
| 204 | ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0
|
---|
| 205 | ssd1306_command(SSD1306_CHARGEPUMP); // 0x8D
|
---|
| 206 | if (_vccstate == SSD1306_EXTERNALVCC)
|
---|
| 207 | { ssd1306_command(0x10); }
|
---|
| 208 | else
|
---|
| 209 | { ssd1306_command(0x14); }
|
---|
| 210 | ssd1306_command(SSD1306_MEMORYMODE); // 0x20
|
---|
| 211 | ssd1306_command(0x00); // 0x0 act like ks0108
|
---|
| 212 | ssd1306_command(SSD1306_SEGREMAP | 0x1);
|
---|
| 213 | ssd1306_command(SSD1306_COMSCANDEC);
|
---|
| 214 | ssd1306_command(SSD1306_SETCOMPINS); // 0xDA
|
---|
| 215 | ssd1306_command(0x02);
|
---|
| 216 | ssd1306_command(SSD1306_SETCONTRAST); // 0x81
|
---|
| 217 | ssd1306_command(0x8F);
|
---|
| 218 | ssd1306_command(SSD1306_SETPRECHARGE); // 0xd9
|
---|
| 219 | if (_vccstate == SSD1306_EXTERNALVCC)
|
---|
| 220 | { ssd1306_command(0x22); }
|
---|
| 221 | else
|
---|
| 222 | { ssd1306_command(0xF1); }
|
---|
| 223 | ssd1306_command(SSD1306_SETVCOMDETECT); // 0xDB
|
---|
| 224 | ssd1306_command(0x40);
|
---|
| 225 | ssd1306_command(SSD1306_DISPLAYALLON_RESUME); // 0xA4
|
---|
| 226 | ssd1306_command(SSD1306_NORMALDISPLAY); // 0xA6
|
---|
| 227 | #endif
|
---|
| 228 |
|
---|
| 229 | #if defined SSD1306_128_64
|
---|
| 230 | // Init sequence for 128x64 OLED module
|
---|
| 231 | ssd1306_command(SSD1306_DISPLAYOFF); // 0xAE
|
---|
| 232 | ssd1306_command(SSD1306_SETDISPLAYCLOCKDIV); // 0xD5
|
---|
| 233 | ssd1306_command(0x80); // the suggested ratio 0x80
|
---|
| 234 | ssd1306_command(SSD1306_SETMULTIPLEX); // 0xA8
|
---|
| 235 | ssd1306_command(0x3F);
|
---|
| 236 | ssd1306_command(SSD1306_SETDISPLAYOFFSET); // 0xD3
|
---|
| 237 | ssd1306_command(0x0); // no offset
|
---|
| 238 | ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0
|
---|
| 239 | ssd1306_command(SSD1306_CHARGEPUMP); // 0x8D
|
---|
| 240 | if (_vccstate == SSD1306_EXTERNALVCC)
|
---|
| 241 | { ssd1306_command(0x10); }
|
---|
| 242 | else
|
---|
| 243 | { ssd1306_command(0x14); }
|
---|
| 244 | ssd1306_command(SSD1306_MEMORYMODE); // 0x20
|
---|
| 245 | ssd1306_command(0x00); // 0x0 act like ks0108
|
---|
| 246 | ssd1306_command(SSD1306_SEGREMAP | 0x1);
|
---|
| 247 | ssd1306_command(SSD1306_COMSCANDEC);
|
---|
| 248 | ssd1306_command(SSD1306_SETCOMPINS); // 0xDA
|
---|
| 249 | ssd1306_command(0x12);
|
---|
| 250 | ssd1306_command(SSD1306_SETCONTRAST); // 0x81
|
---|
| 251 | if (_vccstate == SSD1306_EXTERNALVCC)
|
---|
| 252 | { ssd1306_command(0x9F); }
|
---|
| 253 | else
|
---|
| 254 | { ssd1306_command(0xCF); }
|
---|
| 255 | ssd1306_command(SSD1306_SETPRECHARGE); // 0xd9
|
---|
| 256 | if (_vccstate == SSD1306_EXTERNALVCC)
|
---|
| 257 | { ssd1306_command(0x22); }
|
---|
| 258 | else
|
---|
| 259 | { ssd1306_command(0xF1); }
|
---|
| 260 | ssd1306_command(SSD1306_SETVCOMDETECT); // 0xDB
|
---|
| 261 | ssd1306_command(0x40);
|
---|
| 262 | ssd1306_command(SSD1306_DISPLAYALLON_RESUME); // 0xA4
|
---|
| 263 | ssd1306_command(SSD1306_NORMALDISPLAY); // 0xA6
|
---|
| 264 | #endif
|
---|
| 265 |
|
---|
| 266 | #if defined SSD1306_96_16
|
---|
| 267 | // Init sequence for 96x16 OLED module
|
---|
| 268 | ssd1306_command(SSD1306_DISPLAYOFF); // 0xAE
|
---|
| 269 | ssd1306_command(SSD1306_SETDISPLAYCLOCKDIV); // 0xD5
|
---|
| 270 | ssd1306_command(0x80); // the suggested ratio 0x80
|
---|
| 271 | ssd1306_command(SSD1306_SETMULTIPLEX); // 0xA8
|
---|
| 272 | ssd1306_command(0x0F);
|
---|
| 273 | ssd1306_command(SSD1306_SETDISPLAYOFFSET); // 0xD3
|
---|
| 274 | ssd1306_command(0x00); // no offset
|
---|
| 275 | ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0
|
---|
| 276 | ssd1306_command(SSD1306_CHARGEPUMP); // 0x8D
|
---|
| 277 | if (_vccstate == SSD1306_EXTERNALVCC)
|
---|
| 278 | { ssd1306_command(0x10); }
|
---|
| 279 | else
|
---|
| 280 | { ssd1306_command(0x14); }
|
---|
| 281 | ssd1306_command(SSD1306_MEMORYMODE); // 0x20
|
---|
| 282 | ssd1306_command(0x00); // 0x0 act like ks0108
|
---|
| 283 | ssd1306_command(SSD1306_SEGREMAP | 0x1);
|
---|
| 284 | ssd1306_command(SSD1306_COMSCANDEC);
|
---|
| 285 | ssd1306_command(SSD1306_SETCOMPINS); // 0xDA
|
---|
| 286 | ssd1306_command(0x2); //ada x12
|
---|
| 287 | ssd1306_command(SSD1306_SETCONTRAST); // 0x81
|
---|
| 288 | if (_vccstate == SSD1306_EXTERNALVCC)
|
---|
| 289 | { ssd1306_command(0x10); }
|
---|
| 290 | else
|
---|
| 291 | { ssd1306_command(0xAF); }
|
---|
| 292 | ssd1306_command(SSD1306_SETPRECHARGE); // 0xd9
|
---|
| 293 | if (_vccstate == SSD1306_EXTERNALVCC)
|
---|
| 294 | { ssd1306_command(0x22); }
|
---|
| 295 | else
|
---|
| 296 | { ssd1306_command(0xF1); }
|
---|
| 297 | ssd1306_command(SSD1306_SETVCOMDETECT); // 0xDB
|
---|
| 298 | ssd1306_command(0x40);
|
---|
| 299 | ssd1306_command(SSD1306_DISPLAYALLON_RESUME); // 0xA4
|
---|
| 300 | ssd1306_command(SSD1306_NORMALDISPLAY); // 0xA6
|
---|
| 301 | #endif
|
---|
| 302 |
|
---|
| 303 | ssd1306_command(SSD1306_DISPLAYON);//--turn on oled panel
|
---|
| 304 | }
|
---|
| 305 |
|
---|
| 306 |
|
---|
| 307 | void Adafruit_SSD1306::invertDisplay(uint8_t i) {
|
---|
| 308 | if (i) {
|
---|
| 309 | ssd1306_command(SSD1306_INVERTDISPLAY);
|
---|
| 310 | } else {
|
---|
| 311 | ssd1306_command(SSD1306_NORMALDISPLAY);
|
---|
| 312 | }
|
---|
| 313 | }
|
---|
| 314 |
|
---|
| 315 | void Adafruit_SSD1306::ssd1306_command(uint8_t c) {
|
---|
| 316 |
|
---|
| 317 | uint8_t control = 0x00; // Co = 0, D/C = 0
|
---|
| 318 | Wire.beginTransmission(_i2caddr);
|
---|
| 319 | WIRE_WRITE(control);
|
---|
| 320 | WIRE_WRITE(c);
|
---|
| 321 | Wire.endTransmission();
|
---|
| 322 |
|
---|
| 323 | }
|
---|
| 324 |
|
---|
| 325 | // startscrollright
|
---|
| 326 | // Activate a right handed scroll for rows start through stop
|
---|
| 327 | // Hint, the display is 16 rows tall. To scroll the whole display, run:
|
---|
| 328 | // display.scrollright(0x00, 0x0F)
|
---|
| 329 | void Adafruit_SSD1306::startscrollright(uint8_t start, uint8_t stop){
|
---|
| 330 | ssd1306_command(SSD1306_RIGHT_HORIZONTAL_SCROLL);
|
---|
| 331 | ssd1306_command(0X00);
|
---|
| 332 | ssd1306_command(start);
|
---|
| 333 | ssd1306_command(0X00);
|
---|
| 334 | ssd1306_command(stop);
|
---|
| 335 | ssd1306_command(0X00);
|
---|
| 336 | ssd1306_command(0XFF);
|
---|
| 337 | ssd1306_command(SSD1306_ACTIVATE_SCROLL);
|
---|
| 338 | }
|
---|
| 339 |
|
---|
| 340 | // startscrollleft
|
---|
| 341 | // Activate a right handed scroll for rows start through stop
|
---|
| 342 | // Hint, the display is 16 rows tall. To scroll the whole display, run:
|
---|
| 343 | // display.scrollright(0x00, 0x0F)
|
---|
| 344 | void Adafruit_SSD1306::startscrollleft(uint8_t start, uint8_t stop){
|
---|
| 345 | ssd1306_command(SSD1306_LEFT_HORIZONTAL_SCROLL);
|
---|
| 346 | ssd1306_command(0X00);
|
---|
| 347 | ssd1306_command(start);
|
---|
| 348 | ssd1306_command(0X00);
|
---|
| 349 | ssd1306_command(stop);
|
---|
| 350 | ssd1306_command(0X00);
|
---|
| 351 | ssd1306_command(0XFF);
|
---|
| 352 | ssd1306_command(SSD1306_ACTIVATE_SCROLL);
|
---|
| 353 | }
|
---|
| 354 |
|
---|
| 355 | // startscrolldiagright
|
---|
| 356 | // Activate a diagonal scroll for rows start through stop
|
---|
| 357 | // Hint, the display is 16 rows tall. To scroll the whole display, run:
|
---|
| 358 | // display.scrollright(0x00, 0x0F)
|
---|
| 359 | void Adafruit_SSD1306::startscrolldiagright(uint8_t start, uint8_t stop){
|
---|
| 360 | ssd1306_command(SSD1306_SET_VERTICAL_SCROLL_AREA);
|
---|
| 361 | ssd1306_command(0X00);
|
---|
| 362 | ssd1306_command(SSD1306_LCDHEIGHT);
|
---|
| 363 | ssd1306_command(SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL);
|
---|
| 364 | ssd1306_command(0X00);
|
---|
| 365 | ssd1306_command(start);
|
---|
| 366 | ssd1306_command(0X00);
|
---|
| 367 | ssd1306_command(stop);
|
---|
| 368 | ssd1306_command(0X01);
|
---|
| 369 | ssd1306_command(SSD1306_ACTIVATE_SCROLL);
|
---|
| 370 | }
|
---|
| 371 |
|
---|
| 372 | // startscrolldiagleft
|
---|
| 373 | // Activate a diagonal scroll for rows start through stop
|
---|
| 374 | // Hint, the display is 16 rows tall. To scroll the whole display, run:
|
---|
| 375 | // display.scrollright(0x00, 0x0F)
|
---|
| 376 | void Adafruit_SSD1306::startscrolldiagleft(uint8_t start, uint8_t stop){
|
---|
| 377 | ssd1306_command(SSD1306_SET_VERTICAL_SCROLL_AREA);
|
---|
| 378 | ssd1306_command(0X00);
|
---|
| 379 | ssd1306_command(SSD1306_LCDHEIGHT);
|
---|
| 380 | ssd1306_command(SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL);
|
---|
| 381 | ssd1306_command(0X00);
|
---|
| 382 | ssd1306_command(start);
|
---|
| 383 | ssd1306_command(0X00);
|
---|
| 384 | ssd1306_command(stop);
|
---|
| 385 | ssd1306_command(0X01);
|
---|
| 386 | ssd1306_command(SSD1306_ACTIVATE_SCROLL);
|
---|
| 387 | }
|
---|
| 388 |
|
---|
| 389 | void Adafruit_SSD1306::stopscroll(void){
|
---|
| 390 | ssd1306_command(SSD1306_DEACTIVATE_SCROLL);
|
---|
| 391 | }
|
---|
| 392 |
|
---|
| 393 | // Dim the display
|
---|
| 394 | // dim = true: display is dimmed
|
---|
| 395 | // dim = false: display is normal
|
---|
| 396 | void Adafruit_SSD1306::dim(boolean dim) {
|
---|
| 397 | uint8_t contrast;
|
---|
| 398 |
|
---|
| 399 | if (dim) {
|
---|
| 400 | contrast = 0; // Dimmed display
|
---|
| 401 | } else {
|
---|
| 402 | if (_vccstate == SSD1306_EXTERNALVCC) {
|
---|
| 403 | contrast = 0x9F;
|
---|
| 404 | } else {
|
---|
| 405 | contrast = 0xCF;
|
---|
| 406 | }
|
---|
| 407 | }
|
---|
| 408 | // the range of contrast to too small to be really useful
|
---|
| 409 | // it is useful to dim the display
|
---|
| 410 | ssd1306_command(SSD1306_SETCONTRAST);
|
---|
| 411 | ssd1306_command(contrast);
|
---|
| 412 | }
|
---|
| 413 |
|
---|
| 414 | void Adafruit_SSD1306::ssd1306_data(uint8_t c) {
|
---|
| 415 | uint8_t control = 0x40; // Co = 0, D/C = 1
|
---|
| 416 | Wire.beginTransmission(_i2caddr);
|
---|
| 417 | WIRE_WRITE(control);
|
---|
| 418 | WIRE_WRITE(c);
|
---|
| 419 | Wire.endTransmission();
|
---|
| 420 | //}
|
---|
| 421 | }
|
---|
| 422 |
|
---|
| 423 | void Adafruit_SSD1306::display(void) {
|
---|
| 424 | ssd1306_command(SSD1306_COLUMNADDR);
|
---|
| 425 | ssd1306_command(0); // Column start address (0 = reset)
|
---|
| 426 | ssd1306_command(SSD1306_LCDWIDTH-1); // Column end address (127 = reset)
|
---|
| 427 |
|
---|
| 428 | ssd1306_command(SSD1306_PAGEADDR);
|
---|
| 429 | ssd1306_command(0); // Page start address (0 = reset)
|
---|
| 430 | #if SSD1306_LCDHEIGHT == 64
|
---|
| 431 | ssd1306_command(7); // Page end address
|
---|
| 432 | #endif
|
---|
| 433 | #if SSD1306_LCDHEIGHT == 32
|
---|
| 434 | ssd1306_command(3); // Page end address
|
---|
| 435 | #endif
|
---|
| 436 | #if SSD1306_LCDHEIGHT == 16
|
---|
| 437 | ssd1306_command(1); // Page end address
|
---|
| 438 | #endif
|
---|
| 439 |
|
---|
| 440 | #if !defined __SAM3X8E__ && !defined ARDUINO_ARCH_SAMD
|
---|
| 441 | uint8_t twbrbackup = TWBR;
|
---|
| 442 | TWBR = 12; // upgrade to 400KHz!
|
---|
| 443 | #endif
|
---|
| 444 |
|
---|
| 445 | //Serial.println(TWBR, DEC);
|
---|
| 446 | //Serial.println(TWSR & 0x3, DEC);
|
---|
| 447 |
|
---|
| 448 | // I2C
|
---|
| 449 | for (uint16_t i=0; i<(SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8); i++) {
|
---|
| 450 | // send a bunch of data in one xmission
|
---|
| 451 | Wire.beginTransmission(_i2caddr);
|
---|
| 452 | WIRE_WRITE(0x40);
|
---|
| 453 | for (uint8_t x=0; x<16; x++) {
|
---|
| 454 | WIRE_WRITE(buffer[i]);
|
---|
| 455 | i++;
|
---|
| 456 | }
|
---|
| 457 | i--;
|
---|
| 458 | Wire.endTransmission();
|
---|
| 459 | }
|
---|
| 460 | #if !defined __SAM3X8E__ && !defined ARDUINO_ARCH_SAMD
|
---|
| 461 | TWBR = twbrbackup;
|
---|
| 462 | #endif
|
---|
| 463 | //}
|
---|
| 464 | }
|
---|
| 465 |
|
---|
| 466 | // clear everything
|
---|
| 467 | void Adafruit_SSD1306::clearDisplay(void) {
|
---|
| 468 | memset(buffer, 0, (SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8));
|
---|
| 469 | }
|
---|
| 470 |
|
---|
| 471 | void Adafruit_SSD1306::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
|
---|
| 472 | boolean bSwap = false;
|
---|
| 473 | switch(rotation) {
|
---|
| 474 | case 0:
|
---|
| 475 | // 0 degree rotation, do nothing
|
---|
| 476 | break;
|
---|
| 477 | case 1:
|
---|
| 478 | // 90 degree rotation, swap x & y for rotation, then invert x
|
---|
| 479 | bSwap = true;
|
---|
| 480 | ssd1306_swap(x, y);
|
---|
| 481 | x = WIDTH - x - 1;
|
---|
| 482 | break;
|
---|
| 483 | case 2:
|
---|
| 484 | // 180 degree rotation, invert x and y - then shift y around for height.
|
---|
| 485 | x = WIDTH - x - 1;
|
---|
| 486 | y = HEIGHT - y - 1;
|
---|
| 487 | x -= (w-1);
|
---|
| 488 | break;
|
---|
| 489 | case 3:
|
---|
| 490 | // 270 degree rotation, swap x & y for rotation, then invert y and adjust y for w (not to become h)
|
---|
| 491 | bSwap = true;
|
---|
| 492 | ssd1306_swap(x, y);
|
---|
| 493 | y = HEIGHT - y - 1;
|
---|
| 494 | y -= (w-1);
|
---|
| 495 | break;
|
---|
| 496 | }
|
---|
| 497 |
|
---|
| 498 | if(bSwap) {
|
---|
| 499 | drawFastVLineInternal(x, y, w, color);
|
---|
| 500 | } else {
|
---|
| 501 | drawFastHLineInternal(x, y, w, color);
|
---|
| 502 | }
|
---|
| 503 | }
|
---|
| 504 |
|
---|
| 505 | void Adafruit_SSD1306::drawFastHLineInternal(int16_t x, int16_t y, int16_t w, uint16_t color) {
|
---|
| 506 | // Do bounds/limit checks
|
---|
| 507 | if(y < 0 || y >= HEIGHT) { return; }
|
---|
| 508 |
|
---|
| 509 | // make sure we don't try to draw below 0
|
---|
| 510 | if(x < 0) {
|
---|
| 511 | w += x;
|
---|
| 512 | x = 0;
|
---|
| 513 | }
|
---|
| 514 |
|
---|
| 515 | // make sure we don't go off the edge of the display
|
---|
| 516 | if( (x + w) > WIDTH) {
|
---|
| 517 | w = (WIDTH - x);
|
---|
| 518 | }
|
---|
| 519 |
|
---|
| 520 | // if our width is now negative, punt
|
---|
| 521 | if(w <= 0) { return; }
|
---|
| 522 |
|
---|
| 523 | // set up the pointer for movement through the buffer
|
---|
| 524 | register uint8_t *pBuf = buffer;
|
---|
| 525 | // adjust the buffer pointer for the current row
|
---|
| 526 | pBuf += ((y/8) * SSD1306_LCDWIDTH);
|
---|
| 527 | // and offset x columns in
|
---|
| 528 | pBuf += x;
|
---|
| 529 |
|
---|
| 530 | register uint8_t mask = 1 << (y&7);
|
---|
| 531 |
|
---|
| 532 | switch (color)
|
---|
| 533 | {
|
---|
| 534 | case WHITE: while(w--) { *pBuf++ |= mask; }; break;
|
---|
| 535 | case BLACK: mask = ~mask; while(w--) { *pBuf++ &= mask; }; break;
|
---|
| 536 | case INVERSE: while(w--) { *pBuf++ ^= mask; }; break;
|
---|
| 537 | }
|
---|
| 538 | }
|
---|
| 539 |
|
---|
| 540 | void Adafruit_SSD1306::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
|
---|
| 541 | bool bSwap = false;
|
---|
| 542 | switch(rotation) {
|
---|
| 543 | case 0:
|
---|
| 544 | break;
|
---|
| 545 | case 1:
|
---|
| 546 | // 90 degree rotation, swap x & y for rotation, then invert x and adjust x for h (now to become w)
|
---|
| 547 | bSwap = true;
|
---|
| 548 | ssd1306_swap(x, y);
|
---|
| 549 | x = WIDTH - x - 1;
|
---|
| 550 | x -= (h-1);
|
---|
| 551 | break;
|
---|
| 552 | case 2:
|
---|
| 553 | // 180 degree rotation, invert x and y - then shift y around for height.
|
---|
| 554 | x = WIDTH - x - 1;
|
---|
| 555 | y = HEIGHT - y - 1;
|
---|
| 556 | y -= (h-1);
|
---|
| 557 | break;
|
---|
| 558 | case 3:
|
---|
| 559 | // 270 degree rotation, swap x & y for rotation, then invert y
|
---|
| 560 | bSwap = true;
|
---|
| 561 | ssd1306_swap(x, y);
|
---|
| 562 | y = HEIGHT - y - 1;
|
---|
| 563 | break;
|
---|
| 564 | }
|
---|
| 565 |
|
---|
| 566 | if(bSwap) {
|
---|
| 567 | drawFastHLineInternal(x, y, h, color);
|
---|
| 568 | } else {
|
---|
| 569 | drawFastVLineInternal(x, y, h, color);
|
---|
| 570 | }
|
---|
| 571 | }
|
---|
| 572 |
|
---|
| 573 |
|
---|
| 574 | void Adafruit_SSD1306::drawFastVLineInternal(int16_t x, int16_t __y, int16_t __h, uint16_t color) {
|
---|
| 575 |
|
---|
| 576 | // do nothing if we're off the left or right side of the screen
|
---|
| 577 | if(x < 0 || x >= WIDTH) { return; }
|
---|
| 578 |
|
---|
| 579 | // make sure we don't try to draw below 0
|
---|
| 580 | if(__y < 0) {
|
---|
| 581 | // __y is negative, this will subtract enough from __h to account for __y being 0
|
---|
| 582 | __h += __y;
|
---|
| 583 | __y = 0;
|
---|
| 584 |
|
---|
| 585 | }
|
---|
| 586 |
|
---|
| 587 | // make sure we don't go past the height of the display
|
---|
| 588 | if( (__y + __h) > HEIGHT) {
|
---|
| 589 | __h = (HEIGHT - __y);
|
---|
| 590 | }
|
---|
| 591 |
|
---|
| 592 | // if our height is now negative, punt
|
---|
| 593 | if(__h <= 0) {
|
---|
| 594 | return;
|
---|
| 595 | }
|
---|
| 596 |
|
---|
| 597 | // this display doesn't need ints for coordinates, use local byte registers for faster juggling
|
---|
| 598 | register uint8_t y = __y;
|
---|
| 599 | register uint8_t h = __h;
|
---|
| 600 |
|
---|
| 601 |
|
---|
| 602 | // set up the pointer for fast movement through the buffer
|
---|
| 603 | register uint8_t *pBuf = buffer;
|
---|
| 604 | // adjust the buffer pointer for the current row
|
---|
| 605 | pBuf += ((y/8) * SSD1306_LCDWIDTH);
|
---|
| 606 | // and offset x columns in
|
---|
| 607 | pBuf += x;
|
---|
| 608 |
|
---|
| 609 | // do the first partial byte, if necessary - this requires some masking
|
---|
| 610 | register uint8_t mod = (y&7);
|
---|
| 611 | if(mod) {
|
---|
| 612 | // mask off the high n bits we want to set
|
---|
| 613 | mod = 8-mod;
|
---|
| 614 |
|
---|
| 615 | // note - lookup table results in a nearly 10% performance improvement in fill* functions
|
---|
| 616 | // register uint8_t mask = ~(0xFF >> (mod));
|
---|
| 617 | static uint8_t premask[8] = {0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
|
---|
| 618 | register uint8_t mask = premask[mod];
|
---|
| 619 |
|
---|
| 620 | // adjust the mask if we're not going to reach the end of this byte
|
---|
| 621 | if( h < mod) {
|
---|
| 622 | mask &= (0XFF >> (mod-h));
|
---|
| 623 | }
|
---|
| 624 |
|
---|
| 625 | switch (color)
|
---|
| 626 | {
|
---|
| 627 | case WHITE: *pBuf |= mask; break;
|
---|
| 628 | case BLACK: *pBuf &= ~mask; break;
|
---|
| 629 | case INVERSE: *pBuf ^= mask; break;
|
---|
| 630 | }
|
---|
| 631 |
|
---|
| 632 | // fast exit if we're done here!
|
---|
| 633 | if(h<mod) { return; }
|
---|
| 634 |
|
---|
| 635 | h -= mod;
|
---|
| 636 |
|
---|
| 637 | pBuf += SSD1306_LCDWIDTH;
|
---|
| 638 | }
|
---|
| 639 |
|
---|
| 640 |
|
---|
| 641 | // write solid bytes while we can - effectively doing 8 rows at a time
|
---|
| 642 | if(h >= 8) {
|
---|
| 643 | if (color == INVERSE) { // separate copy of the code so we don't impact performance of the black/white write version with an extra comparison per loop
|
---|
| 644 | do {
|
---|
| 645 | *pBuf=~(*pBuf);
|
---|
| 646 |
|
---|
| 647 | // adjust the buffer forward 8 rows worth of data
|
---|
| 648 | pBuf += SSD1306_LCDWIDTH;
|
---|
| 649 |
|
---|
| 650 | // adjust h & y (there's got to be a faster way for me to do this, but this should still help a fair bit for now)
|
---|
| 651 | h -= 8;
|
---|
| 652 | } while(h >= 8);
|
---|
| 653 | }
|
---|
| 654 | else {
|
---|
| 655 | // store a local value to work with
|
---|
| 656 | register uint8_t val = (color == WHITE) ? 255 : 0;
|
---|
| 657 |
|
---|
| 658 | do {
|
---|
| 659 | // write our value in
|
---|
| 660 | *pBuf = val;
|
---|
| 661 |
|
---|
| 662 | // adjust the buffer forward 8 rows worth of data
|
---|
| 663 | pBuf += SSD1306_LCDWIDTH;
|
---|
| 664 |
|
---|
| 665 | // adjust h & y (there's got to be a faster way for me to do this, but this should still help a fair bit for now)
|
---|
| 666 | h -= 8;
|
---|
| 667 | } while(h >= 8);
|
---|
| 668 | }
|
---|
| 669 | }
|
---|
| 670 |
|
---|
| 671 | // now do the final partial byte, if necessary
|
---|
| 672 | if(h) {
|
---|
| 673 | mod = h & 7;
|
---|
| 674 | // this time we want to mask the low bits of the byte, vs the high bits we did above
|
---|
| 675 | // register uint8_t mask = (1 << mod) - 1;
|
---|
| 676 | // note - lookup table results in a nearly 10% performance improvement in fill* functions
|
---|
| 677 | static uint8_t postmask[8] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F };
|
---|
| 678 | register uint8_t mask = postmask[mod];
|
---|
| 679 | switch (color)
|
---|
| 680 | {
|
---|
| 681 | case WHITE: *pBuf |= mask; break;
|
---|
| 682 | case BLACK: *pBuf &= ~mask; break;
|
---|
| 683 | case INVERSE: *pBuf ^= mask; break;
|
---|
| 684 | }
|
---|
| 685 | }
|
---|
| 686 | }
|
---|
| 687 |
|
---|
| 688 | Adafruit_SSD1306 ssd1306;
|
---|