Skip to content

Commit a199afa

Browse files
Clean up transactions, thanks prenticedavid!
1 parent fd9ac1d commit a199afa

File tree

3 files changed

+68
-28
lines changed

3 files changed

+68
-28
lines changed

Adafruit_SSD1306.cpp

Lines changed: 65 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -64,33 +64,57 @@
6464
#define SSD1306_MODE_DATA digitalWrite(dcPin, HIGH);
6565
#endif
6666

67-
#if defined(SPI_HAS_TRANSACTION) && !defined(ARDUINO_STM32_FEATHER)
68-
#define SPI_TRANSACTION_START \
69-
spi->beginTransaction(spiSettings); \
70-
SSD1306_SELECT
71-
#define SPI_TRANSACTION_END \
72-
SSD1306_DESELECT \
73-
spi->endTransaction();
74-
#else
75-
#define SPI_TRANSACTION_START SSD1306_SELECT
76-
#define SPI_TRANSACTION_END SSD1306_DESELECT
67+
#if (ARDUINO >= 157)
68+
#define SETWIRECLOCK wire->setClock(WIRECLK)
69+
#define RESWIRECLOCK wire->setClock(restoreClk)
70+
#else // setClock() is not present in older Arduino Wire lib
71+
#define SETWIRECLOCK
72+
#define RESWIRECLOCK
73+
#endif
74+
75+
#if defined(SPI_HAS_TRANSACTION)
76+
#define SPI_TRANSACTION_START spi->beginTransaction(spiSettings)
77+
#define SPI_TRANSACTION_END spi->endTransaction()
78+
#else // SPI transactions likewise not present in older Arduino SPI lib
79+
#define SPI_TRANSACTION_START
80+
#define SPI_TRANSACTION_END
7781
#endif
7882

83+
// The definition of 'transaction' is broadened a bit in the context of
84+
// this library -- referring not just to SPI transactions (if supported
85+
// in the version of the SPI library being used), but also chip select
86+
// (if SPI is being used, whether hardware or soft), and also to the
87+
// beginning and end of I2C transfers (the Wire clock may be sped up before
88+
// issuing data to the display, then restored to the default rate afterward
89+
// so other I2C device types still work). All of these are encapsulated
90+
// in the TRANSACTION_* macros.
91+
7992
#if defined(ARDUINO_STM32_FEATHER)
80-
#define TRANSACTION_START if(!wire) { SPI_TRANSACTION_START }
81-
#define TRANSACTION_END if(!wire) { SPI_TRANSACTION_END }
93+
// The WICED board currently has no SPIClass -- hardware SPI is not
94+
// supported by this library there -- nor is there a Wire setClock()
95+
// function, so the transaction start/end code is a little simpler...
96+
#define TRANSACTION_START if(!wire) { SSD1306_SELECT; }
97+
#define TRANSACTION_END if(!wire) { SSD1306_DESELECT; }
8298
#else
83-
#if (ARDUINO >= 157)
84-
#define TRANSACTION_START \
85-
if(wire) wire->setClock(WIRECLK); \
86-
else { SPI_TRANSACTION_START }
87-
#define TRANSACTION_END \
88-
if(wire) wire->setClock(restoreClk); \
89-
else { SPI_TRANSACTION_END }
90-
#else
91-
#define TRANSACTION_START if(spi) { SPI_TRANSACTION_START }
92-
#define TRANSACTION_END if(spi) { SPI_TRANSACTION_END }
93-
#endif
99+
// Everywhere else, check first if Wire, then hardware SPI, then soft SPI:
100+
#define TRANSACTION_START \
101+
if(wire) { \
102+
SETWIRECLOCK; \
103+
} else { \
104+
if(spi) { \
105+
SPI_TRANSACTION_START; \
106+
} \
107+
SSD1306_SELECT; \
108+
}
109+
#define TRANSACTION_END \
110+
if(wire) { \
111+
RESWIRECLOCK; \
112+
} else { \
113+
SSD1306_DESELECT; \
114+
if(spi) { \
115+
SPI_TRANSACTION_END; \
116+
} \
117+
}
94118
#endif
95119

96120
// CONSTRUCTORS, DESTRUCTOR ------------------------------------------------
@@ -246,7 +270,8 @@ void Adafruit_SSD1306::ssd1306_command(uint8_t c) {
246270

247271
// ALLOCATE & INIT DISPLAY -------------------------------------------------
248272

249-
boolean Adafruit_SSD1306::begin(uint8_t vcs, uint8_t addr, boolean reset) {
273+
boolean Adafruit_SSD1306::begin(uint8_t vcs, uint8_t addr, boolean reset,
274+
boolean periphBegin) {
250275

251276
if((!buffer) && !(buffer = (uint8_t *)malloc(WIDTH * ((HEIGHT + 7) / 8))))
252277
return false;
@@ -267,7 +292,11 @@ boolean Adafruit_SSD1306::begin(uint8_t vcs, uint8_t addr, boolean reset) {
267292
// If I2C address is unspecified, use default
268293
// (0x3C for 32-pixel-tall displays, 0x3D for all others).
269294
i2caddr = addr ? addr : ((HEIGHT == 32) ? 0x3C : 0x3D);
270-
wire->begin();
295+
// TwoWire begin() function might be already performed by the calling
296+
// function if it has unusual circumstances (e.g. TWI variants that
297+
// can accept different SDA/SCL pins, or if two SSD1306 instances
298+
// with different addresses -- only a single begin() is needed).
299+
if(periphBegin) wire->begin();
271300
} else { // Using one of the SPI modes, either soft or hardware
272301
pinMode(dcPin, OUTPUT); // Set data/command pin as output
273302
pinMode(csPin, OUTPUT); // Same for chip select
@@ -280,7 +309,8 @@ boolean Adafruit_SSD1306::begin(uint8_t vcs, uint8_t addr, boolean reset) {
280309
SSD1306_DESELECT
281310
#if !defined(ARDUINO_STM32_FEATHER)
282311
if(spi) { // Hardware SPI
283-
spi->begin();
312+
// SPI peripheral begin same as wire check above.
313+
if(periphBegin) spi->begin();
284314
} else { // Soft SPI
285315
#endif
286316
pinMode(mosiPin, OUTPUT); // MOSI and SCLK outputs
@@ -618,6 +648,12 @@ void Adafruit_SSD1306::display(void) {
618648
ssd1306_command1(WIDTH - 1); // Column end address
619649

620650
#if defined(ESP8266)
651+
// ESP8266 needs a periodic yield() call to avoid watchdog reset.
652+
// With the limited size of SSD1306 displays, and the fast bitrate
653+
// being used (1 MHz or more), I think one yield() immediately before
654+
// a screen write and one immediately after should cover it. But if
655+
// not, if this becomes a problem, yields() might be added in the
656+
// 32-byte transfer condition below.
621657
yield();
622658
#endif
623659
uint16_t count = WIDTH * ((HEIGHT + 7) / 8);
@@ -642,6 +678,9 @@ void Adafruit_SSD1306::display(void) {
642678
while(count--) SPIwrite(*ptr++);
643679
}
644680
TRANSACTION_END
681+
#if defined(ESP8266)
682+
yield();
683+
#endif
645684
}
646685

647686
// SCROLLING FUNCTIONS -----------------------------------------------------

Adafruit_SSD1306.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ class Adafruit_SSD1306 : public Adafruit_GFX {
122122
~Adafruit_SSD1306(void);
123123

124124
boolean begin(uint8_t switchvcc=SSD1306_SWITCHCAPVCC,
125-
uint8_t i2caddr=0, boolean reset=true);
125+
uint8_t i2caddr=0, boolean reset=true,
126+
boolean periphBegin=true);
126127
void display(void);
127128
void clearDisplay(void);
128129
void invertDisplay(boolean i);

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=Adafruit SSD1306
2-
version=1.2.5
2+
version=1.2.6
33
author=Adafruit
44
maintainer=Adafruit <info@adafruit.com>
55
sentence=SSD1306 oled driver library for monochrome 128x64 and 128x32 displays

0 commit comments

Comments
 (0)