-
Notifications
You must be signed in to change notification settings - Fork 1
/
FTOLED.h
415 lines (325 loc) · 12.8 KB
/
FTOLED.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
/*
OLED.h - Support library for Freetronics 128x128 OLED display
Copyright (C) 2013 Freetronics, Inc. (info <at> freetronics <dot> com)
Written by Angus Gratton
Note that this library uses the SPI port for the fastest, low
overhead writing to the display. Keep an eye on conflicts if there
are any other devices running from the same SPI port, and that the
chip select on those devices is correctly set to be inactive when the
OLED is being written to.
---
This program is free software: you can redistribute it and/or modify it under the terms
of the version 3 GNU General Public License as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program.
If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OLED_H_
#define OLED_H_
//Arduino header name is version dependent
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "pins_arduino.h"
#include <SPI.h>
#include "Print.h"
#include "progmem_compat.h"
#define ROWS 128
#define COLUMNS 128
#define ROW_MASK (ROWS-1)
#define COLUMN_MASK (COLUMNS-1)
class File; /* Provided by SD library except sometimes on Yun, see comment at top of FTOLED_BMP.cpp */
struct OLED_Colour
{
byte red : 5;
byte green : 6;
byte blue : 5;
};
/* Allow use of both AU/UK spelling OLED_Colour and US spelling OLED_Color */
typedef OLED_Colour OLED_Color;
#if !defined(FTOLED_NO_COLOUR_PRESETS) && !defined(FTOLED_NO_COLOR_PRESETS)
#include "FTOLED_Colours.h"
#endif
/* Add an internal-use-only preset colours for BLACK, in case the preset
colours aren't loaded */
const OLED_Colour OLED_BLACK = { 0, 0, 0 };
const byte MAX_RED = 31;
const byte MAX_GREEN = 63;
const byte MAX_BLUE = 31;
// Display mode argument for setDisplayMode()
enum OLED_Display_Mode {
DISPLAY_OFF = 0, // No pixels on
DISPLAY_ALL_PIXELS_FULL = 1, // All pixels on GS level 63 (ie max brightness)
DISPLAY_NORMAL = 2, // Normal display on
DISPLAY_INVERSE = 3,
};
// OLED GPIO mode for setGPIO()
enum OLED_GPIO_Mode {
OLED_HIZ = 0,
OLED_LOW = 2,
OLED_HIGH = 3,
};
// Status code returned by displayBMP()
enum BMP_Status {
BMP_OK = 0, // Image Displayed OK
BMP_INVALID_FORMAT = 1, // Not a BMP file
BMP_UNSUPPORTED_HEADER = 2, // Has a rare BMP header format (not v2 or v3)
BMP_TOO_MANY_COLOURS = 3, // Is a 32bpp image (not supported)
BMP_COMPRESSION_NOT_SUPPORTED = 4, // Uses RLE or another unsupported compression format
BMP_UNSUPPORTED_COLOURS = 5, // Uses non-standard colour format
BMP_ORIGIN_OUTSIDE_IMAGE = 6 // You've asked to crop a section that doesn't exist in the image
};
enum OLED_Orientation {
ROTATE_0 = 0,
ROTATE_90 = 1,
ROTATE_180 = 2,
ROTATE_270 = 3
};
class OLED
{
public:
OLED(byte pin_ncsL,byte pin_ncsR, byte pin_dc, byte pin_reset) :
pin_ncsL(pin_ncsL),
pin_ncsR(pin_ncsR),
pin_dc(pin_dc),
pin_reset(pin_reset),
gpio_status(OLED_HIZ | OLED_HIZ<<2),
orientation(ROTATE_0)
{}
void begin();
// Set the colour of a single pixel
void setPixel(const byte x, const byte y, const OLED_Colour colour);
// Fill the screen with a single solid colour
void fillScreen(const OLED_Colour);
void clearScreen() { fillScreen(OLED_BLACK); }
// Turn the display on or off
void setDisplayOn(bool on);
// Turn the display on or off
void setInhibitL(bool InhibitL);
// Turn the display on or off
void setInhibitR(bool InhibitR);
// Turn the display on or off
void setFlipL(bool MirrorL);
// Turn the display on or off
void setFlipR(bool MirrorR);
// Transaction
void setTransaction(bool on);
//Draw a line from x1,y1 to x2,y2
void drawLine( int x1, int y1, int x2, int y2, OLED_Colour colour );
//Draw a box(rectangle) from (x1,y1) to (x2,y2), with sides edgeWidth pixels wide
void drawBox( int x1, int y1, int x2, int y2, int edgeWidth, OLED_Colour colour);
//Draw a filled box(rectangle) from (x1,y1) to (y1,y2), optionally with sides edgeWidth pixels wide
void drawFilledBox( int x1, int y1, int x2, int y2, OLED_Colour fillColour, int edgeWidth, OLED_Colour edgeColour);
void drawFilledBox( int x1, int y1, int x2, int y2, OLED_Colour fillColour) { drawFilledBox(x1,y1,x2,y2,fillColour,0,OLED_BLACK); }
// Draw an outline of a circle of radius r centred at x,y
void drawCircle( int xCenter, int yCenter, int radius, OLED_Colour colour);
// Draw an filled circle of radius r at x,y centre
void drawFilledCircle( int xCenter, int yCenter, int radius, OLED_Colour colour);
void fillLine(byte COL,uint16_t pixelsL[] ,uint16_t pixelsR[] );
//Select a text font
void selectFont(const uint8_t* font);
const inline uint8_t *getFont(void) { return font; }
//Draw a single character
int drawChar(const int x, const int y, const char letter, const OLED_Colour colour, const OLED_Colour background);
// Draw a full string, either from PROGMEM (AVR only) or from normal C-style pointer, or Arduino string object
#ifdef __AVR__
void drawString_P(int x, int y, const char *flashStr, OLED_Colour foreground, OLED_Colour background);
inline void drawString(int x, int y, const __FlashStringHelper *flashStr, OLED_Colour foreground, OLED_Colour background) {
return drawString_P(x,y,(const char*)flashStr,foreground,background);
}
#endif
void drawString(int x, int y, const char *bChars, OLED_Colour foreground, OLED_Colour background);
void drawString(int x, int y, const String &str, OLED_Colour foreground, OLED_Colour background);
//Find the width of a character
int charWidth(const char letter);
//Find the width of a string (width of all characters plus 1 pixel "kerning" between each character)
#ifdef __AVR__
unsigned int stringWidth_P(const char *flashStr);
inline unsigned int stringWidth(const __FlashStringHelper *flashStr) {
return stringWidth_P((const char*)flashStr);
}
#endif
unsigned int stringWidth(const char *bChars);
unsigned int stringWidth(const String &str);
// Bitmap stuff
// Given 'File' containing a BMP image, show it onscreen with bottom left corner at (x,y)
BMP_Status displayBMP(File &source, const int x, const int y);
BMP_Status displayBMP(File &source, const int from_x, const int from_y, const int to_x, const int to_y);
// Given 'pgm_addr', a pointer to a PROGMEM buffer (or const buffer on ARM) containing a BMP,
// show it onscreen with bottom left corner at (x,y)
BMP_Status displayBMP(const uint8_t *pgm_addr, const int x, const int y);
BMP_Status displayBMP(const uint8_t *pgm_addr, const int from_x, const int from_y, const int to_x, const int to_y);
/* Set the grayscale table for pixel brightness to one of these precanned defaults */
void setDefaultGrayscaleTable();
void setBrightGrayscaleTable();
void setDimGrayscaleTable();
/* Set a custom sized grayscale table. "table" must be address of a
PROGMEM table holding 64 grayscale level values (GS0..GS63), which must be
strictly incrementing (see section 8.8 in the datasheet.) Values
in the table can have values 0-180.
*/
inline void setGrayscaleTable_P(const byte *table);
void setGPIO1(OLED_GPIO_Mode gpio1);
/* Set display mode. See enum OLED_Display_Mode, above. */
inline void setDisplayMode(OLED_Display_Mode mode) {
assertCS();
writeCommand(0xA4+(byte)mode);
releaseCS();
}
inline void setOrientation(OLED_Orientation orientation) {
this->orientation = orientation;
}
protected:
byte pin_dc;
byte pin_reset;
byte gpio_status;
byte pin_ncsL;
byte pin_ncsR;
bool inhibitL = false;
bool inhibitR = false;
bool mirrorL = false;
bool mirrorR = false;
OLED_Orientation orientation;
uint8_t *font;
inline void assertCS() {
if (!inhibitL){digitalWrite(pin_ncsL, LOW);}
if (!inhibitR){digitalWrite(pin_ncsR, LOW);}
}
inline void releaseCS() {
if (!inhibitL){digitalWrite(pin_ncsL, HIGH);}
if (!inhibitR){digitalWrite(pin_ncsR, HIGH);}
}
// Note: GPIO0 is panel power on OLED128, hence better to use setDisplayOn()
void setGPIO0(OLED_GPIO_Mode gpio0);
/* These protected methods are for implementing basic OLED commands.
They all assume that the CS is asserted before they've been called
*/
inline void writeCommand(byte command)
{
digitalWrite(pin_dc, LOW);
SPI.transfer(command);
digitalWrite(pin_dc, HIGH);
}
inline void writeData(byte data)
{
SPI.transfer(data);
}
inline void writeData(OLED_Colour colour)
{
writeData((colour.green>>3)|(colour.red<<3));
writeData((colour.green<<5)|(colour.blue));
}
inline void writeCommand(byte command, byte data) {
writeCommand(command);
writeData(data);
}
inline void writeData(byte *data, unsigned int length)
{
for(unsigned int i = 0; i < length; i++) {
writeData(data[i]);
}
}
inline void writePixel(uint16_t pixel)
{
writeData(pixel >> 8);
writeData(pixel & 0xFF);
}
inline void _setPixel(const byte x, const byte y, const OLED_Colour colour)
{
startWrite(x,y,x,y,false);
writeData(colour);
}
enum OLED_Command_Lock {
DISPLAY_COMMAND_UNLOCK = 0x12, // Allow commands (default state)
DISPLAY_COMMAND_LOCK = 0x16, // Disallow all commands until/except next UNLOCK
DISPLAY_COMMAND_LOCK_SPECIAL = 0xB0, // Lock out "special" commands always (default state)
DISPLAY_COMMAND_ALLOW_SPECIAL = 0xB1, // Allow "special" commands when unlocked
};
// Direct commands to the module
inline void setCommandLock(OLED_Command_Lock lock_command)
{
writeCommand(0xFD, (byte)lock_command);
}
// Display clock divisor options, used by setDisplayClock
#define DISPLAY_CLOCK_DIV_1 0
#define DISPLAY_CLOCK_DIV_2 1
#define DISPLAY_CLOCK_DIV_4 2
#define DISPLAY_CLOCK_DIV_8 3
#define DISPLAY_CLOCK_DIV_16 4
#define DISPLAY_CLOCK_DIV_32 5
#define DISPLAY_CLOCK_DIV_64 6
#define DISPLAY_CLOCK_DIV_128 7
#define DISPLAY_CLOCK_DIV_256 8
#define DISPLAY_CLOCK_DIV_512 9
#define DISPLAY_CLOCK_DIV_1024 10
/* set display refresh clock
* Args:
* divisor - a constant (DISPLAY_CLOCK_DIV_xxx), see above.
* frequency - a value 0-15 proportional to oscillator frequency.
*/
inline void setDisplayClock(byte divisor, byte frequency)
{
writeCommand(0xB3, divisor | ((frequency&0x0F)<<4));
}
/* set multiplex ratio (Default of ROW_MASK/127 for 128 should be fine in nearly all cases)
*/
inline void setMultiPlexRatio(byte mux_ratio)
{
writeCommand(0xCA, mux_ratio & ROW_MASK);
}
/* set display offset row (0-127) */
inline void setDisplayOffset(byte row)
{
writeCommand(0xA2, row & ROW_MASK);
}
/* set starting row for display (0-127) */
inline void setStartRow(byte row)
{
writeCommand(0xA1, row & ROW_MASK);
}
/* Start a pixel data write. This function also accounts for remapping coordinates based
on current orientation. */
void startWrite(byte start_x, byte start_y, byte to_x, byte to_y, bool fill_vertical);
/* set color channel contrasts. A,B,C are R,G,B values unless REMAP_ORDER_BGR is set */
inline void setColorContrasts(byte a, byte b, byte c)
{
writeCommand(0xC1);
writeData(a);
writeData(b);
writeData(c);
}
/* Set Master contrast, value 0-15 */
inline void setMasterContrast(byte contrast)
{
writeCommand(0xC7, contrast & 0x0F);
}
/* Set the reset (phase 1) and precharge (phase 2) lengths.
Reset range is 5-31 DCLK periods (odd values only), precharge is 3-15 DCLK periods
*/
inline void setResetPrechargePeriods(byte resetLength, byte precharge) {
resetLength = (resetLength&~1)/2 - 1; // Value we write is 3-15 same as the others
writeCommand(0xB1, (resetLength>>8)|(precharge&0x0F));
}
/* Set precharge voltage, level is a proportion of Vcc where 0x00=0.2 0x1F=0.60,
Default of 0x17 is 0.50 */
inline void setPrechargeVoltage(byte level) {
writeCommand(0xBB, level & 0x1F);
}
/* Set second precharge period (phase 3) as number of DCLK periods 1-15. Default is 8. */
inline void setSecondPrechargePeriod(byte clocks) {
clocks = clocks & 0x0F;
writeCommand(0xB6, clocks ? clocks : 8);
}
/* Set lock bits. Reset means 0x12, 0x16? means nothing works except reset and another unlock? */
inline void setLockBits(byte lock_bits) {
writeCommand(0xFD, lock_bits);
}
// Internal templated displayBMP method, allows us to treat SD card files and PROGMEM buffers
// via the same code paths
template<typename SourceType> BMP_Status _displayBMP(SourceType &source, const int from_x, const int from_y, const int to_x, const int to_y);
};
#endif