MatrixMiniR4 1.1.4
Matrix Mini R4 Arduino Library API Documentation
Loading...
Searching...
No Matches
MiniR4OLED.cpp
Go to the documentation of this file.
1
7/*
8The MIT License (MIT)
9
10Copyright (c) 2017 Adafruit Industries
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files (the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions:
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29*/
30
31#ifdef __AVR__
32# include <avr/pgmspace.h>
33#elif defined(ESP8266) || defined(ESP32) || defined(ARDUINO_ARCH_RP2040)
34# include <pgmspace.h>
35#else
36# define pgm_read_byte(addr) \
37 (*(const unsigned char*)(addr))
38#endif
39
40#if !defined(__ARM_ARCH) && !defined(ENERGIA) && !defined(ESP8266) && !defined(ESP32) && \
41 !defined(__arc__)
42# include <util/delay.h>
43#endif
44
45#include "MiniR4OLED.h"
46#include "MiniR4_GFX.h"
47
48// SOME DEFINES AND STATIC VARIABLES USED INTERNALLY -----------------------
49
50#if defined(I2C_BUFFER_LENGTH)
51# define WIRE_MAX min(256, I2C_BUFFER_LENGTH)
52#elif defined(BUFFER_LENGTH)
53# define WIRE_MAX min(256, BUFFER_LENGTH)
54#elif defined(SERIAL_BUFFER_SIZE)
55# define WIRE_MAX min(255, SERIAL_BUFFER_SIZE - 1)
56#else
57# define WIRE_MAX 32
58#endif
59
60#define ssd1306_swap(a, b) \
61 (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b)))
62
63#if ARDUINO >= 100
64# define WIRE_WRITE wire->write
65#else
66# define WIRE_WRITE wire->send
67#endif
68
69#ifdef HAVE_PORTREG
70# define SSD1306_SELECT *csPort &= ~csPinMask;
71# define SSD1306_DESELECT *csPort |= csPinMask;
72# define SSD1306_MODE_COMMAND *dcPort &= ~dcPinMask;
73# define SSD1306_MODE_DATA *dcPort |= dcPinMask;
74#else
75# define SSD1306_SELECT digitalWrite(csPin, LOW);
76# define SSD1306_DESELECT digitalWrite(csPin, HIGH);
77# define SSD1306_MODE_COMMAND digitalWrite(dcPin, LOW);
78# define SSD1306_MODE_DATA digitalWrite(dcPin, HIGH);
79#endif
80
81#if (ARDUINO >= 157) && !defined(ARDUINO_STM32_FEATHER)
82# define SETWIRECLOCK wire->setClock(wireClk)
83# define RESWIRECLOCK wire->setClock(restoreClk)
84#else // setClock() is not present in older Arduino Wire lib (or WICED)
85# define SETWIRECLOCK
86# define RESWIRECLOCK
87#endif
88
89#if defined(SPI_HAS_TRANSACTION)
90# define SPI_TRANSACTION_START spi->beginTransaction(spiSettings)
91# define SPI_TRANSACTION_END spi->endTransaction()
92#else // SPI transactions likewise not present in older Arduino SPI lib
93# define SPI_TRANSACTION_START
94# define SPI_TRANSACTION_END
95#endif
96
97// The definition of 'transaction' is broadened a bit in the context of
98// this library -- referring not just to SPI transactions (if supported
99// in the version of the SPI library being used), but also chip select
100// (if SPI is being used, whether hardware or soft), and also to the
101// beginning and end of I2C transfers (the Wire clock may be sped up before
102// issuing data to the display, then restored to the default rate afterward
103// so other I2C device types still work). All of these are encapsulated
104// in the TRANSACTION_* macros.
105
106// Check first if Wire, then hardware SPI, then soft SPI:
107#define TRANSACTION_START \
108 if (wire) { \
109 SETWIRECLOCK; \
110 } else { \
111 if (spi) { \
112 SPI_TRANSACTION_START; \
113 } \
114 SSD1306_SELECT; \
115 }
116#define TRANSACTION_END \
117 if (wire) { \
118 RESWIRECLOCK; \
119 } else { \
120 SSD1306_DESELECT; \
121 if (spi) { \
122 SPI_TRANSACTION_END; \
123 } \
124 }
125
126// CONSTRUCTORS, DESTRUCTOR ------------------------------------------------
127
162 uint8_t w, uint8_t h, TwoWire* twi, int8_t rst_pin, uint32_t clkDuring, uint32_t clkAfter)
163 : Adafruit_GFX(w, h)
164 , spi(NULL)
165 , wire(twi ? twi : &Wire)
166 , buffer(NULL)
167 , mosiPin(-1)
168 , clkPin(-1)
169 , dcPin(-1)
170 , csPin(-1)
171 , rstPin(rst_pin)
172#if ARDUINO >= 157
173 , wireClk(clkDuring)
174 , restoreClk(clkAfter)
175#endif
176{}
177
206 uint8_t w, uint8_t h, int8_t mosi_pin, int8_t sclk_pin, int8_t dc_pin, int8_t rst_pin,
207 int8_t cs_pin)
208 : Adafruit_GFX(w, h)
209 , spi(NULL)
210 , wire(NULL)
211 , buffer(NULL)
212 , mosiPin(mosi_pin)
213 , clkPin(sclk_pin)
214 , dcPin(dc_pin)
215 , csPin(cs_pin)
216 , rstPin(rst_pin)
217{}
218
246 uint8_t w, uint8_t h, SPIClass* spi_ptr, int8_t dc_pin, int8_t rst_pin, int8_t cs_pin,
247 uint32_t bitrate)
248 : Adafruit_GFX(w, h)
249 , spi(spi_ptr ? spi_ptr : &SPI)
250 , wire(NULL)
251 , buffer(NULL)
252 , mosiPin(-1)
253 , clkPin(-1)
254 , dcPin(dc_pin)
255 , csPin(cs_pin)
256 , rstPin(rst_pin)
257{
258#ifdef SPI_HAS_TRANSACTION
259 spiSettings = SPISettings(bitrate, MSBFIRST, SPI_MODE0);
260#endif
261}
262
290 int8_t mosi_pin, int8_t sclk_pin, int8_t dc_pin, int8_t rst_pin, int8_t cs_pin)
292 , spi(NULL)
293 , wire(NULL)
294 , buffer(NULL)
295 , mosiPin(mosi_pin)
296 , clkPin(sclk_pin)
297 , dcPin(dc_pin)
298 , csPin(cs_pin)
299 , rstPin(rst_pin)
300{}
301
323Adafruit_SSD1306::Adafruit_SSD1306(int8_t dc_pin, int8_t rst_pin, int8_t cs_pin)
325 , spi(&SPI)
326 , wire(NULL)
327 , buffer(NULL)
328 , mosiPin(-1)
329 , clkPin(-1)
330 , dcPin(dc_pin)
331 , csPin(cs_pin)
332 , rstPin(rst_pin)
333{
334#ifdef SPI_HAS_TRANSACTION
335 spiSettings = SPISettings(8000000, MSBFIRST, SPI_MODE0);
336#endif
337}
338
355 , spi(NULL)
356 , wire(&Wire)
357 , buffer(NULL)
358 , mosiPin(-1)
359 , clkPin(-1)
360 , dcPin(-1)
361 , csPin(-1)
362 , rstPin(rst_pin)
363{}
364
369{
370 if (buffer) {
371 free(buffer);
372 buffer = NULL;
373 }
374}
375
376// LOW-LEVEL UTILS ---------------------------------------------------------
377
378// Issue single byte out SPI, either soft or hardware as appropriate.
379// SPI transaction/selection must be performed in calling function.
390inline void Adafruit_SSD1306::SPIwrite(uint8_t d)
391{
392 if (spi) {
393 (void)spi->transfer(d);
394 } else {
395 for (uint8_t bit = 0x80; bit; bit >>= 1) {
396#ifdef HAVE_PORTREG
397 if (d & bit)
398 *mosiPort |= mosiPinMask;
399 else
400 *mosiPort &= ~mosiPinMask;
401 *clkPort |= clkPinMask; // Clock high
402 *clkPort &= ~clkPinMask; // Clock low
403#else
404 digitalWrite(mosiPin, d & bit);
405 digitalWrite(clkPin, HIGH);
406 digitalWrite(clkPin, LOW);
407#endif
408 }
409 }
410}
411
425{
426 if (wire) { // I2C
427 wire->beginTransmission(i2caddr);
428 WIRE_WRITE((uint8_t)0x00); // Co = 0, D/C = 0
429 WIRE_WRITE(c);
430 wire->endTransmission();
431 } else { // SPI (hw or soft) -- transaction started in calling function
433 SPIwrite(c);
434 }
435}
436
449void Adafruit_SSD1306::ssd1306_commandList(const uint8_t* c, uint8_t n)
450{
451 if (wire) { // I2C
452 wire->beginTransmission(i2caddr);
453 WIRE_WRITE((uint8_t)0x00); // Co = 0, D/C = 0
454 uint16_t bytesOut = 1;
455 while (n--) {
456 if (bytesOut >= WIRE_MAX) {
457 wire->endTransmission();
458 wire->beginTransmission(i2caddr);
459 WIRE_WRITE((uint8_t)0x00); // Co = 0, D/C = 0
460 bytesOut = 1;
461 }
463 bytesOut++;
464 }
465 wire->endTransmission();
466 } else { // SPI -- transaction started in calling function
468 while (n--) SPIwrite(pgm_read_byte(c++));
469 }
470}
471
472// A public version of ssd1306_command1(), for existing user code that
473// might rely on that function. This encapsulates the command transfer
474// in a transaction start/end, similar to old library's handling of it.
488
489// ALLOCATE & INIT DISPLAY -------------------------------------------------
490
526bool Adafruit_SSD1306::begin(uint8_t vcs, uint8_t addr, bool reset, bool periphBegin)
527{
528
529 if ((!buffer) && !(buffer = (uint8_t*)malloc(WIDTH * ((HEIGHT + 7) / 8)))) return false;
530
531 clearDisplay();
532
533 vccstate = vcs;
534
535 // Setup pin directions
536 if (wire) { // Using I2C
537 // If I2C address is unspecified, use default
538 // (0x3C for 32-pixel-tall displays, 0x3D for all others).
539 i2caddr = addr ? addr : ((HEIGHT == 32) ? 0x3C : 0x3D);
540 // TwoWire begin() function might be already performed by the calling
541 // function if it has unusual circumstances (e.g. TWI variants that
542 // can accept different SDA/SCL pins, or if two SSD1306 instances
543 // with different addresses -- only a single begin() is needed).
544 if (periphBegin) wire->begin();
545 } else { // Using one of the SPI modes, either soft or hardware
546 pinMode(dcPin, OUTPUT); // Set data/command pin as output
547 pinMode(csPin, OUTPUT); // Same for chip select
548#ifdef HAVE_PORTREG
549 dcPort = (PortReg*)portOutputRegister(digitalPinToPort(dcPin));
550 dcPinMask = digitalPinToBitMask(dcPin);
551 csPort = (PortReg*)portOutputRegister(digitalPinToPort(csPin));
552 csPinMask = digitalPinToBitMask(csPin);
553#endif
555 if (spi) { // Hardware SPI
556 // SPI peripheral begin same as wire check above.
557 if (periphBegin) spi->begin();
558 } else { // Soft SPI
559 pinMode(mosiPin, OUTPUT); // MOSI and SCLK outputs
560 pinMode(clkPin, OUTPUT);
561#ifdef HAVE_PORTREG
562 mosiPort = (PortReg*)portOutputRegister(digitalPinToPort(mosiPin));
563 mosiPinMask = digitalPinToBitMask(mosiPin);
564 clkPort = (PortReg*)portOutputRegister(digitalPinToPort(clkPin));
565 clkPinMask = digitalPinToBitMask(clkPin);
566 *clkPort &= ~clkPinMask; // Clock low
567#else
568 digitalWrite(clkPin, LOW); // Clock low
569#endif
570 }
571 }
572
573 // Reset SSD1306 if requested and reset pin specified in constructor
574 if (reset && (rstPin >= 0)) {
575 pinMode(rstPin, OUTPUT);
576 digitalWrite(rstPin, HIGH);
577 delay(1); // VDD goes high at start, pause for 1 ms
578 digitalWrite(rstPin, LOW); // Bring reset low
579 delay(10); // Wait 10 ms
580 digitalWrite(rstPin, HIGH); // Bring out of reset
581 }
582
584
585 // Init sequence
586 static const uint8_t PROGMEM init1[] = {
587 SSD1306_DISPLAYOFF, // 0xAE
589 0x80, // the suggested ratio 0x80
590 SSD1306_SETMULTIPLEX}; // 0xA8
591 ssd1306_commandList(init1, sizeof(init1));
593
594 static const uint8_t PROGMEM init2[] = {
596 0x0, // no offset
597 SSD1306_SETSTARTLINE | 0x0, // line #0
598 SSD1306_CHARGEPUMP}; // 0x8D
599 ssd1306_commandList(init2, sizeof(init2));
600
602
603 static const uint8_t PROGMEM init3[] = {
604 SSD1306_MEMORYMODE, // 0x20
605 0x00, // 0x0 act like ks0108
606 SSD1306_SEGREMAP | 0x1,
608 ssd1306_commandList(init3, sizeof(init3));
609
610 uint8_t comPins = 0x02;
611 contrast = 0x8F;
612
613 if ((WIDTH == 128) && (HEIGHT == 32)) {
614 comPins = 0x02;
615 contrast = 0x8F;
616 } else if ((WIDTH == 128) && (HEIGHT == 64)) {
617 comPins = 0x12;
618 contrast = (vccstate == SSD1306_EXTERNALVCC) ? 0x9F : 0xCF;
619 } else if ((WIDTH == 96) && (HEIGHT == 16)) {
620 comPins = 0x2; // ada x12
621 contrast = (vccstate == SSD1306_EXTERNALVCC) ? 0x10 : 0xAF;
622 } else {
623 // Other screen varieties -- TBD
624 }
625
627 ssd1306_command1(comPins);
630
633 static const uint8_t PROGMEM init5[] = {
634 SSD1306_SETVCOMDETECT, // 0xDB
635 0x40,
637 SSD1306_NORMALDISPLAY, // 0xA6
639 SSD1306_DISPLAYON}; // Main screen turn on
640 ssd1306_commandList(init5, sizeof(init5));
641
643
644 return true; // Success
645}
646
647// DRAWING FUNCTIONS -------------------------------------------------------
648
665void Adafruit_SSD1306::drawPixel(int16_t x, int16_t y, uint16_t color)
666{
667 if ((x >= 0) && (x < width()) && (y >= 0) && (y < height())) {
668 // Pixel is in-bounds. Rotate coordinates if needed.
669 switch (getRotation()) {
670 case 1:
671 ssd1306_swap(x, y);
672 x = WIDTH - x - 1;
673 break;
674 case 2:
675 x = WIDTH - x - 1;
676 y = HEIGHT - y - 1;
677 break;
678 case 3:
679 ssd1306_swap(x, y);
680 y = HEIGHT - y - 1;
681 break;
682 }
683 switch (color) {
684 case SSD1306_WHITE: buffer[x + (y / 8) * WIDTH] |= (1 << (y & 7)); break;
685 case SSD1306_BLACK: buffer[x + (y / 8) * WIDTH] &= ~(1 << (y & 7)); break;
686 case SSD1306_INVERSE: buffer[x + (y / 8) * WIDTH] ^= (1 << (y & 7)); break;
687 }
688 }
689}
690
699{
700 memset(buffer, 0, WIDTH * ((HEIGHT + 7) / 8));
701}
702
719void Adafruit_SSD1306::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
720{
721 bool bSwap = false;
722 switch (rotation) {
723 case 1:
724 // 90 degree rotation, swap x & y for rotation, then invert x
725 bSwap = true;
726 ssd1306_swap(x, y);
727 x = WIDTH - x - 1;
728 break;
729 case 2:
730 // 180 degree rotation, invert x and y, then shift y around for height.
731 x = WIDTH - x - 1;
732 y = HEIGHT - y - 1;
733 x -= (w - 1);
734 break;
735 case 3:
736 // 270 degree rotation, swap x & y for rotation,
737 // then invert y and adjust y for w (not to become h)
738 bSwap = true;
739 ssd1306_swap(x, y);
740 y = HEIGHT - y - 1;
741 y -= (w - 1);
742 break;
743 }
744
745 if (bSwap)
746 drawFastVLineInternal(x, y, w, color);
747 else
748 drawFastHLineInternal(x, y, w, color);
749}
750
768void Adafruit_SSD1306::drawFastHLineInternal(int16_t x, int16_t y, int16_t w, uint16_t color)
769{
770
771 if ((y >= 0) && (y < HEIGHT)) { // Y coord in bounds?
772 if (x < 0) { // Clip left
773 w += x;
774 x = 0;
775 }
776 if ((x + w) > WIDTH) { // Clip right
777 w = (WIDTH - x);
778 }
779 if (w > 0) { // Proceed only if width is positive
780 uint8_t *pBuf = &buffer[(y / 8) * WIDTH + x], mask = 1 << (y & 7);
781 switch (color) {
782 case SSD1306_WHITE:
783 while (w--) {
784 *pBuf++ |= mask;
785 };
786 break;
787 case SSD1306_BLACK:
788 mask = ~mask;
789 while (w--) {
790 *pBuf++ &= mask;
791 };
792 break;
793 case SSD1306_INVERSE:
794 while (w--) {
795 *pBuf++ ^= mask;
796 };
797 break;
798 }
799 }
800 }
801}
802
819void Adafruit_SSD1306::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
820{
821 bool bSwap = false;
822 switch (rotation) {
823 case 1:
824 // 90 degree rotation, swap x & y for rotation,
825 // then invert x and adjust x for h (now to become w)
826 bSwap = true;
827 ssd1306_swap(x, y);
828 x = WIDTH - x - 1;
829 x -= (h - 1);
830 break;
831 case 2:
832 // 180 degree rotation, invert x and y, then shift y around for height.
833 x = WIDTH - x - 1;
834 y = HEIGHT - y - 1;
835 y -= (h - 1);
836 break;
837 case 3:
838 // 270 degree rotation, swap x & y for rotation, then invert y
839 bSwap = true;
840 ssd1306_swap(x, y);
841 y = HEIGHT - y - 1;
842 break;
843 }
844
845 if (bSwap)
846 drawFastHLineInternal(x, y, h, color);
847 else
848 drawFastVLineInternal(x, y, h, color);
849}
850
867void Adafruit_SSD1306::drawFastVLineInternal(int16_t x, int16_t __y, int16_t __h, uint16_t color)
868{
869
870 if ((x >= 0) && (x < WIDTH)) { // X coord in bounds?
871 if (__y < 0) { // Clip top
872 __h += __y;
873 __y = 0;
874 }
875 if ((__y + __h) > HEIGHT) { // Clip bottom
876 __h = (HEIGHT - __y);
877 }
878 if (__h > 0) { // Proceed only if height is now positive
879 // this display doesn't need ints for coordinates,
880 // use local byte registers for faster juggling
881 uint8_t y = __y, h = __h;
882 uint8_t* pBuf = &buffer[(y / 8) * WIDTH + x];
883
884 // do the first partial byte, if necessary - this requires some masking
885 uint8_t mod = (y & 7);
886 if (mod) {
887 // mask off the high n bits we want to set
888 mod = 8 - mod;
889 // note - lookup table results in a nearly 10% performance
890 // improvement in fill* functions
891 // uint8_t mask = ~(0xFF >> mod);
892 static const uint8_t PROGMEM premask[8] = {
893 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE};
894 uint8_t mask = pgm_read_byte(&premask[mod]);
895 // adjust the mask if we're not going to reach the end of this byte
896 if (h < mod) mask &= (0XFF >> (mod - h));
897
898 switch (color) {
899 case SSD1306_WHITE: *pBuf |= mask; break;
900 case SSD1306_BLACK: *pBuf &= ~mask; break;
901 case SSD1306_INVERSE: *pBuf ^= mask; break;
902 }
903 pBuf += WIDTH;
904 }
905
906 if (h >= mod) { // More to go?
907 h -= mod;
908 // Write solid bytes while we can - effectively 8 rows at a time
909 if (h >= 8) {
910 if (color == SSD1306_INVERSE) {
911 // separate copy of the code so we don't impact performance of
912 // black/white write version with an extra comparison per loop
913 do {
914 *pBuf ^= 0xFF; // Invert byte
915 pBuf += WIDTH; // Advance pointer 8 rows
916 h -= 8; // Subtract 8 rows from height
917 } while (h >= 8);
918 } else {
919 // store a local value to work with
920 uint8_t val = (color != SSD1306_BLACK) ? 255 : 0;
921 do {
922 *pBuf = val; // Set byte
923 pBuf += WIDTH; // Advance pointer 8 rows
924 h -= 8; // Subtract 8 rows from height
925 } while (h >= 8);
926 }
927 }
928
929 if (h) { // Do the final partial byte, if necessary
930 mod = h & 7;
931 // this time we want to mask the low bits of the byte,
932 // vs the high bits we did above
933 // uint8_t mask = (1 << mod) - 1;
934 // note - lookup table results in a nearly 10% performance
935 // improvement in fill* functions
936 static const uint8_t PROGMEM postmask[8] = {
937 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F};
938 uint8_t mask = pgm_read_byte(&postmask[mod]);
939 switch (color) {
940 case SSD1306_WHITE: *pBuf |= mask; break;
941 case SSD1306_BLACK: *pBuf &= ~mask; break;
942 case SSD1306_INVERSE: *pBuf ^= mask; break;
943 }
944 }
945 }
946 } // endif positive height
947 } // endif x in bounds
948}
949
961bool Adafruit_SSD1306::getPixel(int16_t x, int16_t y)
962{
963 if ((x >= 0) && (x < width()) && (y >= 0) && (y < height())) {
964 // Pixel is in-bounds. Rotate coordinates if needed.
965 switch (getRotation()) {
966 case 1:
967 ssd1306_swap(x, y);
968 x = WIDTH - x - 1;
969 break;
970 case 2:
971 x = WIDTH - x - 1;
972 y = HEIGHT - y - 1;
973 break;
974 case 3:
975 ssd1306_swap(x, y);
976 y = HEIGHT - y - 1;
977 break;
978 }
979 return (buffer[x + (y / 8) * WIDTH] & (1 << (y & 7)));
980 }
981 return false; // Pixel out of bounds
982}
983
990{
991 return buffer;
992}
993
994// REFRESH DISPLAY ---------------------------------------------------------
995
1004{
1006 static const uint8_t PROGMEM dlist1[] = {
1008 0, // Page start address
1009 0xFF, // Page end (not really, but works here)
1011 0}; // Column start address
1012 ssd1306_commandList(dlist1, sizeof(dlist1));
1013 ssd1306_command1(WIDTH - 1); // Column end address
1014
1015#if defined(ESP8266)
1016 // ESP8266 needs a periodic yield() call to avoid watchdog reset.
1017 // With the limited size of SSD1306 displays, and the fast bitrate
1018 // being used (1 MHz or more), I think one yield() immediately before
1019 // a screen write and one immediately after should cover it. But if
1020 // not, if this becomes a problem, yields() might be added in the
1021 // 32-byte transfer condition below.
1022 yield();
1023#endif
1024 uint16_t count = WIDTH * ((HEIGHT + 7) / 8);
1025 uint8_t* ptr = buffer;
1026 if (wire) { // I2C
1027 wire->beginTransmission(i2caddr);
1028 WIRE_WRITE((uint8_t)0x40);
1029 uint16_t bytesOut = 1;
1030 while (count--) {
1031 if (bytesOut >= WIRE_MAX) {
1032 wire->endTransmission();
1033 wire->beginTransmission(i2caddr);
1034 WIRE_WRITE((uint8_t)0x40);
1035 bytesOut = 1;
1036 }
1037 WIRE_WRITE(*ptr++);
1038 bytesOut++;
1039 }
1040 wire->endTransmission();
1041 } else { // SPI
1043 while (count--) SPIwrite(*ptr++);
1044 }
1046#if defined(ESP8266)
1047 yield();
1048#endif
1049}
1050
1051// SCROLLING FUNCTIONS -----------------------------------------------------
1052
1061// To scroll the whole display, run: display.startscrollright(0x00, 0x0F)
1062void Adafruit_SSD1306::startscrollright(uint8_t start, uint8_t stop)
1063{
1065 static const uint8_t PROGMEM scrollList1a[] = {SSD1306_RIGHT_HORIZONTAL_SCROLL, 0X00};
1066 ssd1306_commandList(scrollList1a, sizeof(scrollList1a));
1067 ssd1306_command1(start);
1068 ssd1306_command1(0X00);
1069 ssd1306_command1(stop);
1070 static const uint8_t PROGMEM scrollList1b[] = {0X00, 0XFF, SSD1306_ACTIVATE_SCROLL};
1071 ssd1306_commandList(scrollList1b, sizeof(scrollList1b));
1073}
1074
1083// To scroll the whole display, run: display.startscrollleft(0x00, 0x0F)
1084void Adafruit_SSD1306::startscrollleft(uint8_t start, uint8_t stop)
1085{
1087 static const uint8_t PROGMEM scrollList2a[] = {SSD1306_LEFT_HORIZONTAL_SCROLL, 0X00};
1088 ssd1306_commandList(scrollList2a, sizeof(scrollList2a));
1089 ssd1306_command1(start);
1090 ssd1306_command1(0X00);
1091 ssd1306_command1(stop);
1092 static const uint8_t PROGMEM scrollList2b[] = {0X00, 0XFF, SSD1306_ACTIVATE_SCROLL};
1093 ssd1306_commandList(scrollList2b, sizeof(scrollList2b));
1095}
1096
1105// display.startscrolldiagright(0x00, 0x0F)
1106void Adafruit_SSD1306::startscrolldiagright(uint8_t start, uint8_t stop)
1107{
1109 static const uint8_t PROGMEM scrollList3a[] = {SSD1306_SET_VERTICAL_SCROLL_AREA, 0X00};
1110 ssd1306_commandList(scrollList3a, sizeof(scrollList3a));
1112 static const uint8_t PROGMEM scrollList3b[] = {
1114 ssd1306_commandList(scrollList3b, sizeof(scrollList3b));
1115 ssd1306_command1(start);
1116 ssd1306_command1(0X00);
1117 ssd1306_command1(stop);
1118 static const uint8_t PROGMEM scrollList3c[] = {0X01, SSD1306_ACTIVATE_SCROLL};
1119 ssd1306_commandList(scrollList3c, sizeof(scrollList3c));
1121}
1122
1131// To scroll the whole display, run: display.startscrolldiagleft(0x00, 0x0F)
1132void Adafruit_SSD1306::startscrolldiagleft(uint8_t start, uint8_t stop)
1133{
1135 static const uint8_t PROGMEM scrollList4a[] = {SSD1306_SET_VERTICAL_SCROLL_AREA, 0X00};
1136 ssd1306_commandList(scrollList4a, sizeof(scrollList4a));
1138 static const uint8_t PROGMEM scrollList4b[] = {
1140 ssd1306_commandList(scrollList4b, sizeof(scrollList4b));
1141 ssd1306_command1(start);
1142 ssd1306_command1(0X00);
1143 ssd1306_command1(stop);
1144 static const uint8_t PROGMEM scrollList4c[] = {0X01, SSD1306_ACTIVATE_SCROLL};
1145 ssd1306_commandList(scrollList4c, sizeof(scrollList4c));
1147}
1148
1159
1160// OTHER HARDWARE SETTINGS -------------------------------------------------
1161
1181
1191{
1192 // the range of contrast to too small to be really useful
1193 // it is useful to dim the display
1198}
#define pgm_read_byte(addr)
Adafruit SSD1306 dependency code.
#define PROGMEM
@ x
@ y
#define TRANSACTION_START
Wire, SPI or bitbang transfer setup.
#define SSD1306_MODE_COMMAND
Command mode.
#define SSD1306_MODE_DATA
Data mode.
#define WIRE_MAX
Use common Arduino core default.
#define WIRE_WRITE
Wire write function in older Arduino lib.
#define ssd1306_swap(a, b)
No-temp-var swap operation.
#define SSD1306_DESELECT
Device deselect.
#define TRANSACTION_END
Wire, SPI or bitbang transfer end.
Handling MiniR4.OLED functions. (Full Wrapping from Adafruit_SSD1306)
#define SSD1306_SETVCOMDETECT
See datasheet.
Definition MiniR4OLED.h:124
#define SSD1306_SETDISPLAYCLOCKDIV
See datasheet.
Definition MiniR4OLED.h:121
#define SSD1306_MEMORYMODE
See datasheet.
Definition MiniR4OLED.h:105
#define SSD1306_DISPLAYALLON_RESUME
See datasheet.
Definition MiniR4OLED.h:111
#define SSD1306_DEACTIVATE_SCROLL
Stop scroll.
Definition MiniR4OLED.h:137
#define SSD1306_SET_VERTICAL_SCROLL_AREA
Set scroll range.
Definition MiniR4OLED.h:139
#define SSD1306_LEFT_HORIZONTAL_SCROLL
Init left scroll.
Definition MiniR4OLED.h:134
#define SSD1306_INVERTDISPLAY
See datasheet.
Definition MiniR4OLED.h:114
#define SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL
Init diag scroll.
Definition MiniR4OLED.h:135
#define SSD1306_SETDISPLAYOFFSET
See datasheet.
Definition MiniR4OLED.h:120
#define SSD1306_RIGHT_HORIZONTAL_SCROLL
Init rt scroll.
Definition MiniR4OLED.h:133
#define SSD1306_SEGREMAP
See datasheet.
Definition MiniR4OLED.h:110
#define SSD1306_ACTIVATE_SCROLL
Start scroll.
Definition MiniR4OLED.h:138
#define SSD1306_PAGEADDR
See datasheet.
Definition MiniR4OLED.h:107
#define SSD1306_SETPRECHARGE
See datasheet.
Definition MiniR4OLED.h:122
#define SSD1306_INVERSE
Invert pixels.
Definition MiniR4OLED.h:103
#define SSD1306_SETCOMPINS
See datasheet.
Definition MiniR4OLED.h:123
#define SSD1306_DISPLAYON
See datasheet.
Definition MiniR4OLED.h:117
#define SSD1306_BLACK
fit into the SSD1306_ naming scheme
Definition MiniR4OLED.h:101
#define SSD1306_WHITE
Draw 'on' pixels.
Definition MiniR4OLED.h:102
#define SSD1306_SETSTARTLINE
See datasheet.
Definition MiniR4OLED.h:128
#define SSD1306_SETCONTRAST
See datasheet.
Definition MiniR4OLED.h:108
#define SSD1306_LCDHEIGHT
DEPRECATED: height w/SSD1306_128_32 defined.
Definition MiniR4OLED.h:148
#define SSD1306_EXTERNALVCC
External display voltage source.
Definition MiniR4OLED.h:130
#define SSD1306_CHARGEPUMP
See datasheet.
Definition MiniR4OLED.h:109
#define SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL
Init diag scroll.
Definition MiniR4OLED.h:136
#define SSD1306_COMSCANDEC
See datasheet.
Definition MiniR4OLED.h:119
#define SSD1306_SETMULTIPLEX
See datasheet.
Definition MiniR4OLED.h:115
#define SSD1306_LCDWIDTH
DEPRECATED: width w/SSD1306_128_32 defined.
Definition MiniR4OLED.h:147
#define SSD1306_NORMALDISPLAY
See datasheet.
Definition MiniR4OLED.h:113
#define SSD1306_DISPLAYOFF
See datasheet.
Definition MiniR4OLED.h:116
#define SSD1306_COLUMNADDR
See datasheet.
Definition MiniR4OLED.h:106
A generic graphics superclass that can handle all sorts of drawing. At a.
Definition MiniR4_GFX.h:51
int16_t HEIGHT
This is the 'raw' display height - never changes.
Definition MiniR4_GFX.h:264
int16_t width(void) const
Get width of the display, accounting for current rotation.
Definition MiniR4_GFX.h:223
uint8_t rotation
Display rotation (0 thru 3)
Definition MiniR4_GFX.h:273
int16_t height(void) const
Get height of the display, accounting for current rotation.
Definition MiniR4_GFX.h:231
uint8_t getRotation(void) const
Get rotation setting for display.
Definition MiniR4_GFX.h:239
int16_t WIDTH
This is the 'raw' display width - never changes.
Definition MiniR4_GFX.h:263
int8_t i2caddr
I2C address initialized when begin method is called.
Definition MiniR4OLED.h:213
void ssd1306_command1(uint8_t c)
Issue single command to SSD1306, using I2C or hard/soft SPI as needed. Because command calls are ofte...
uint8_t * buffer
Definition MiniR4OLED.h:211
void display(void)
Push data currently in RAM to SSD1306 display.
virtual void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
Draw a vertical line. This is also invoked by the Adafruit_GFX library in generating many higher-leve...
uint8_t * getBuffer(void)
Get base address of display buffer for direct reading or writing.
void dim(bool dim)
Dim the display.
SPIClass * spi
Definition MiniR4OLED.h:207
int8_t dcPin
(Data Pin) set when using SPI set during construction.
Definition MiniR4OLED.h:219
void invertDisplay(bool i)
Enable or disable display invert mode (white-on-black vs black-on-white).
void startscrollleft(uint8_t start, uint8_t stop)
Activate a left-handed scroll for all or part of the display.
~Adafruit_SSD1306(void)
Destructor for Adafruit_SSD1306 object.
Adafruit_SSD1306(uint8_t w, uint8_t h, TwoWire *twi=&Wire, int8_t rst_pin=-1, uint32_t clkDuring=400000UL, uint32_t clkAfter=100000UL)
Constructor for I2C-interfaced SSD1306 displays.
void startscrollright(uint8_t start, uint8_t stop)
Activate a right-handed scroll for all or part of the display.
int8_t rstPin
Display reset pin assignment. Set during construction.
Definition MiniR4OLED.h:221
int8_t csPin
(Chip Select Pin) set when using SPI set during construction.
Definition MiniR4OLED.h:220
void ssd1306_commandList(const uint8_t *c, uint8_t n)
Issue list of commands to SSD1306, same rules as above re: transactions. This is a protected function...
virtual void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
Draw a horizontal line. This is also invoked by the Adafruit_GFX library in generating many higher-le...
bool getPixel(int16_t x, int16_t y)
Return color of a single pixel in display buffer.
void startscrolldiagleft(uint8_t start, uint8_t stop)
Activate alternate diagonal scroll for all or part of the display.
void drawFastVLineInternal(int16_t x, int16_t y, int16_t h, uint16_t color)
Draw a vertical line with a width and color. Used by public method drawFastHLine,drawFastVLine.
void ssd1306_command(uint8_t c)
Issue a single low-level command directly to the SSD1306 display, bypassing the library.
bool begin(uint8_t switchvcc=SSD1306_SWITCHCAPVCC, uint8_t i2caddr=0, bool reset=true, bool periphBegin=true)
Allocate RAM for image buffer, initialize peripherals and pins.
void stopscroll(void)
Cease a previously-begun scrolling action.
void drawFastHLineInternal(int16_t x, int16_t y, int16_t w, uint16_t color)
Draw a horizontal line with a width and color. Used by public methods drawFastHLine,...
int8_t clkPin
(Clock Pin) set when using SPI set during construction.
Definition MiniR4OLED.h:218
void startscrolldiagright(uint8_t start, uint8_t stop)
Activate a diagonal scroll for all or part of the display.
int8_t vccstate
VCC selection, set by begin method.
Definition MiniR4OLED.h:214
void drawPixel(int16_t x, int16_t y, uint16_t color)
Set/clear/invert a single pixel. This is also invoked by the Adafruit_GFX library in generating many ...
uint8_t contrast
normal contrast setting for this device
Definition MiniR4OLED.h:231
void SPIwrite(uint8_t d) __attribute__((always_inline))
Write a single byte to the SPI port.
void clearDisplay(void)
Clear contents of display buffer (set all pixels to off).