source: rtos_arduino/trunk/arduino_lib/libraries/LuckyShield/src/lib/Adafruit_SSD1306.cpp@ 224

Last change on this file since 224 was 224, checked in by ertl-honda, 8 years ago

1.7.10のファイルに更新

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