From 55742774b7c34111bdac2ffd2287e69c7d004fb3 Mon Sep 17 00:00:00 2001 From: Oleksandr Masliuchenko Date: Tue, 6 Jun 2017 22:53:33 +0300 Subject: [PATCH] Splitting SPI and I2C implementation with ifdefs --- Adafruit_SSD1306.cpp | 140 +++++++++++++++++++++++++++---------------- Adafruit_SSD1306.h | 60 ++++++++++++++----- 2 files changed, 133 insertions(+), 67 deletions(-) diff --git a/Adafruit_SSD1306.cpp b/Adafruit_SSD1306.cpp index 570a3358..c3e5484a 100644 --- a/Adafruit_SSD1306.cpp +++ b/Adafruit_SSD1306.cpp @@ -30,11 +30,30 @@ All text above, and the splash screen below must be included in any redistributi #include -#include -#include #include "Adafruit_GFX.h" #include "Adafruit_SSD1306.h" + +#ifdef ADAFRUIT_SSD1306_I2C +#include + + +#if ARDUINO >= 100 + #include "Arduino.h" + #define WIRE_WRITE Wire.write +#else + #include "WProgram.h" + #define WIRE_WRITE Wire.send +#endif + +#endif //ADAFRUIT_SSD1306_I2C + + +#if defined ADAFRUIT_SSD1306_SPI || defined ADAFRUIT_SSD1306_HW_SPI +#include +#endif //ADAFRUIT_SSD1306_SPI + + // the memory buffer for the LCD static uint8_t buffer[SSD1306_LCDHEIGHT * SSD1306_LCDWIDTH / 8] = { @@ -141,75 +160,89 @@ void Adafruit_SSD1306::drawPixel(int16_t x, int16_t y, uint16_t color) { } +#ifdef ADAFRUIT_SSD1306_SPI 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) { cs = CS; rst = RST; dc = DC; sclk = SCLK; sid = SID; - hwSPI = false; } +#endif //ADAFRUIT_SSD1306_SPI +#ifdef ADAFRUIT_SSD1306_HW_SPI // constructor for hardware SPI - we indicate DataCommand, ChipSelect, Reset Adafruit_SSD1306::Adafruit_SSD1306(int8_t DC, int8_t RST, int8_t CS) : Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT) { dc = DC; rst = RST; cs = CS; - hwSPI = true; } +#endif //ADAFRUIT_SSD1306_HW_SPI +#ifdef ADAFRUIT_SSD1306_I2C // initializer for I2C - we only indicate the reset pin! Adafruit_SSD1306::Adafruit_SSD1306(int8_t reset) : Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT) { - sclk = dc = cs = sid = -1; rst = reset; } +#endif //ADAFRUIT_SSD1306_I2C void Adafruit_SSD1306::begin(uint8_t vccstate, uint8_t i2caddr, bool reset) { _vccstate = vccstate; - _i2caddr = i2caddr; + +// SPI specific initialization +#if defined ADAFRUIT_SSD1306_SPI || defined ADAFRUIT_SSD1306_HW_SPI + (void)i2caddr; // suppress unused var warning // set pin directions - if (sid != -1){ - pinMode(dc, OUTPUT); - pinMode(cs, OUTPUT); + pinMode(dc, OUTPUT); + pinMode(cs, OUTPUT); #ifdef HAVE_PORTREG - csport = portOutputRegister(digitalPinToPort(cs)); - cspinmask = digitalPinToBitMask(cs); - dcport = portOutputRegister(digitalPinToPort(dc)); - dcpinmask = digitalPinToBitMask(dc); + csport = portOutputRegister(digitalPinToPort(cs)); + cspinmask = digitalPinToBitMask(cs); + dcport = portOutputRegister(digitalPinToPort(dc)); + dcpinmask = digitalPinToBitMask(dc); #endif - if (!hwSPI){ - // set pins for software-SPI - pinMode(sid, OUTPUT); - pinMode(sclk, OUTPUT); + +#if defined ADAFRUIT_SSD1306_SPI + // set pins for software-SPI + pinMode(sid, OUTPUT); + pinMode(sclk, OUTPUT); #ifdef HAVE_PORTREG - clkport = portOutputRegister(digitalPinToPort(sclk)); - clkpinmask = digitalPinToBitMask(sclk); - mosiport = portOutputRegister(digitalPinToPort(sid)); - mosipinmask = digitalPinToBitMask(sid); + clkport = portOutputRegister(digitalPinToPort(sclk)); + clkpinmask = digitalPinToBitMask(sclk); + mosiport = portOutputRegister(digitalPinToPort(sid)); + mosipinmask = digitalPinToBitMask(sid); #endif - } - if (hwSPI){ - SPI.begin(); +#endif //ADAFRUIT_SSD1306_SPI + +#if defined ADAFRUIT_SSD1306_HW_SPI + SPI.begin(); #ifdef SPI_HAS_TRANSACTION - SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); + SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); #else - SPI.setClockDivider (4); + SPI.setClockDivider (4); #endif - } - } - else - { - // I2C Init +#endif //ADAFRUIT_SSD1306_HW_SPI + +#endif //defined ADAFRUIT_SSD1306_SPI || defined ADAFRUIT_SSD1306_HW_SPI + + +// I2C specific initialization +#ifdef ADAFRUIT_SSD1306_I2C +_i2caddr = i2caddr; + + // I2C Init Wire.begin(); #ifdef __SAM3X8E__ // Force 400 KHz I2C, rawr! (Uses pins 20, 21 for SDA, SCL) TWI1->TWI_CWGR = 0; TWI1->TWI_CWGR = ((VARIANT_MCK / (2 * 400000)) - 4) * 0x101; #endif - } + +#endif //ADAFRUIT_SSD1306_I2C + if ((reset) && (rst >= 0)) { // Setup reset pin direction (used by both SPI and I2C) pinMode(rst, OUTPUT); @@ -297,9 +330,7 @@ void Adafruit_SSD1306::invertDisplay(uint8_t i) { } void Adafruit_SSD1306::ssd1306_command(uint8_t c) { - if (sid != -1) - { - // SPI +#if defined ADAFRUIT_SSD1306_SPI || defined ADAFRUIT_SSD1306_HW_SPI #ifdef HAVE_PORTREG *csport |= cspinmask; *dcport &= ~dcpinmask; @@ -309,22 +340,22 @@ void Adafruit_SSD1306::ssd1306_command(uint8_t c) { digitalWrite(dc, LOW); digitalWrite(cs, LOW); #endif - fastSPIwrite(c); + fastSPIwrite(c); #ifdef HAVE_PORTREG *csport |= cspinmask; #else digitalWrite(cs, HIGH); #endif - } - else - { +#endif //defined ADAFRUIT_SSD1306_SPI || defined ADAFRUIT_SSD1306_HW_SPI + +#ifdef ADAFRUIT_SSD1306_I2C // I2C uint8_t control = 0x00; // Co = 0, D/C = 0 Wire.beginTransmission(_i2caddr); Wire.write(control); Wire.write(c); Wire.endTransmission(); - } +#endif //ADAFRUIT_SSD1306_I2C } // startscrollright @@ -433,9 +464,8 @@ void Adafruit_SSD1306::display(void) { ssd1306_command(1); // Page end address #endif - if (sid != -1) - { - // SPI +#if defined ADAFRUIT_SSD1306_SPI || defined ADAFRUIT_SSD1306_HW_SPI + // SPI #ifdef HAVE_PORTREG *csport |= cspinmask; *dcport |= dcpinmask; @@ -454,9 +484,10 @@ void Adafruit_SSD1306::display(void) { #else digitalWrite(cs, HIGH); #endif - } - else - { +#endif //defined ADAFRUIT_SSD1306_SPI || defined ADAFRUIT_SSD1306_HW_SPI + + +#ifdef ADAFRUIT_SSD1306_I2C // save I2C bitrate #ifdef TWBR uint8_t twbrbackup = TWBR; @@ -481,7 +512,7 @@ void Adafruit_SSD1306::display(void) { #ifdef TWBR TWBR = twbrbackup; #endif - } +#endif// ADAFRUIT_SSD1306_I2C } // clear everything @@ -489,12 +520,8 @@ void Adafruit_SSD1306::clearDisplay(void) { memset(buffer, 0, (SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8)); } - +#ifdef ADAFRUIT_SSD1306_SPI inline void Adafruit_SSD1306::fastSPIwrite(uint8_t d) { - - if(hwSPI) { - (void)SPI.transfer(d); - } else { for(uint8_t bit = 0x80; bit; bit >>= 1) { #ifdef HAVE_PORTREG *clkport &= ~clkpinmask; @@ -508,8 +535,15 @@ inline void Adafruit_SSD1306::fastSPIwrite(uint8_t d) { digitalWrite(sclk, HIGH); #endif } - } } +#endif //ADAFRUIT_SSD1306_SPI + +#ifdef ADAFRUIT_SSD1306_HW_SPI +inline void Adafruit_SSD1306::fastSPIwrite(uint8_t d) { + (void)SPI.transfer(d); +} +#endif// ADAFRUIT_SSD1306_HW_SPI + void Adafruit_SSD1306::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) { boolean bSwap = false; diff --git a/Adafruit_SSD1306.h b/Adafruit_SSD1306.h index 1162f875..701fa652 100644 --- a/Adafruit_SSD1306.h +++ b/Adafruit_SSD1306.h @@ -18,14 +18,28 @@ All text above, and the splash screen must be included in any redistribution #ifndef _Adafruit_SSD1306_H_ #define _Adafruit_SSD1306_H_ -#if ARDUINO >= 100 - #include "Arduino.h" - #define WIRE_WRITE Wire.write -#else - #include "WProgram.h" - #define WIRE_WRITE Wire.send +#include + +/*========================================================================= + SSD1306 Displays + ----------------------------------------------------------------------- + The driver supports display connected via SPI as well as I2C. Use one + of options below + + -----------------------------------------------------------------------*/ +//#define ADAFRUIT_SSD1306_HW_SPI +//#define ADAFRUIT_SSD1306_SPI +#define ADAFRUIT_SSD1306_I2C +/*=========================================================================*/ + +#if defined ADAFRUIT_SSD1306_SPI && defined ADAFRUIT_SSD1306_I2C + #error "Only one communication interface is allowed for connecting SSD1306" +#endif +#if !defined ADAFRUIT_SSD1306_SPI && !defined ADAFRUIT_SSD1306_HW_SPI && !defined ADAFRUIT_SSD1306_I2C + #error "Please specify SSD1306 communication interface in SSD1306.h" #endif + #if defined(__SAM3X8E__) typedef volatile RwReg PortReg; typedef uint32_t PortMask; @@ -45,17 +59,20 @@ All text above, and the splash screen must be included in any redistribution typedef uint32_t PortMask; #endif -#include -#include -#define BLACK 0 -#define WHITE 1 -#define INVERSE 2 +/*========================================================================= + I2C specific options + =========================================================================*/ #define SSD1306_I2C_ADDRESS 0x3C // 011110+SA0+RW - 0x3C or 0x3D // Address for 128x32 is 0x3C // Address for 128x64 is 0x3D (default) or 0x3C (if SA0 is grounded) +#define BLACK 0 +#define WHITE 1 +#define INVERSE 2 + + /*========================================================================= SSD1306 Displays ----------------------------------------------------------------------- @@ -143,9 +160,13 @@ All text above, and the splash screen must be included in any redistribution class Adafruit_SSD1306 : public Adafruit_GFX { public: +#if defined ADAFRUIT_SSD1306_SPI Adafruit_SSD1306(int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS); +#elif defined ADAFRUIT_SSD1306_HW_SPI Adafruit_SSD1306(int8_t DC, int8_t RST, int8_t CS); +#elif defined ADAFRUIT_SSD1306_I2C Adafruit_SSD1306(int8_t RST = -1); +#endif void begin(uint8_t switchvcc = SSD1306_SWITCHCAPVCC, uint8_t i2caddr = SSD1306_I2C_ADDRESS, bool reset=true); void ssd1306_command(uint8_t c); @@ -169,15 +190,26 @@ class Adafruit_SSD1306 : public Adafruit_GFX { virtual void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color); private: - int8_t _i2caddr, _vccstate, sid, sclk, dc, rst, cs; - void fastSPIwrite(uint8_t c); - boolean hwSPI; + int8_t _vccstate; + int8_t rst; + +#ifdef ADAFRUIT_SSD1306_I2C + int8_t _i2caddr; // address of the display on I2C bus +#endif //ADAFRUIT_SSD1306_I2C + +#if defined ADAFRUIT_SSD1306_SPI || defined ADAFRUIT_SSD1306_HW_SPI + int8_t sid, sclk, dc, cs; + #ifdef HAVE_PORTREG PortReg *mosiport, *clkport, *csport, *dcport; PortMask mosipinmask, clkpinmask, cspinmask, dcpinmask; #endif + void fastSPIwrite(uint8_t c); + +#endif //defined ADAFRUIT_SSD1306_SPI || defined ADAFRUIT_SSD1306_HW_SPI + inline void drawFastVLineInternal(int16_t x, int16_t y, int16_t h, uint16_t color) __attribute__((always_inline)); inline void drawFastHLineInternal(int16_t x, int16_t y, int16_t w, uint16_t color) __attribute__((always_inline));