From 0e54ad39702cb73b9a4c5809423e8250eba6a170 Mon Sep 17 00:00:00 2001 From: Jordan Schaenzle Date: Tue, 9 Oct 2018 10:33:39 -0400 Subject: [PATCH 1/2] SPI Updates - Allow user to specify use of SPI1 peripheral. - Pass CS to SPI.begin so that default chip select pin is not enabled as an output unnecessarily. --- firmware/Adafruit_SSD1306_mfGFX.cpp | 16 ++++++++++------ firmware/Adafruit_SSD1306_mfGFX.h | 3 ++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/firmware/Adafruit_SSD1306_mfGFX.cpp b/firmware/Adafruit_SSD1306_mfGFX.cpp index 634a317..75d2d31 100644 --- a/firmware/Adafruit_SSD1306_mfGFX.cpp +++ b/firmware/Adafruit_SSD1306_mfGFX.cpp @@ -129,14 +129,16 @@ Adafruit_SSD1306::Adafruit_SSD1306(int8_t SID, int8_t SCLK, int8_t DC, int8_t RS sclk = SCLK; sid = SID; hwSPI = false; + spiClass = NULL; } // 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) { +Adafruit_SSD1306::Adafruit_SSD1306(int8_t DC, int8_t RST, int8_t CS, bool USE_SPI1) : Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT) { dc = DC; rst = RST; cs = CS; hwSPI = true; + spiClass = USE_SPI1 ? &SPI1 : &SPI; } // initializer for I2C - we only indicate the reset pin! @@ -144,6 +146,7 @@ Adafruit_SSD1306::Adafruit_SSD1306(int8_t reset) : Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT) { sclk = dc = cs = sid = -1; rst = reset; + spiClass = NULL; } @@ -162,10 +165,11 @@ void Adafruit_SSD1306::begin(uint8_t vccstate, uint8_t i2caddr) { } if (hwSPI){ digitalWrite(cs, HIGH); - SPI.setBitOrder(MSBFIRST); - SPI.setClockDivider(SPI_CLOCK_DIV8); // 72MHz / 8 = 9Mhz - SPI.setDataMode(0); - SPI.begin(); + spiClass->.setBitOrder(MSBFIRST); + spiClass->.setClockDivider(SPI_CLOCK_DIV8); // 72MHz / 8 = 9Mhz + spiClass->.setDataMode(0); + spiClass->.begin(cs); // Passing the chip-select here just sets the pin mode. + // The peripheral won't automatically assert/deassert the pin during operation. } } else @@ -451,7 +455,7 @@ void Adafruit_SSD1306::clearDisplay(void) { inline void Adafruit_SSD1306::fastSPIwrite(uint8_t d) { if(hwSPI) { - (void)SPI.transfer(d); + (void)spiClass->transfer(d); } else { shiftOut(sid, sclk, MSBFIRST, d); // SSD1306 specs show MSB out first } diff --git a/firmware/Adafruit_SSD1306_mfGFX.h b/firmware/Adafruit_SSD1306_mfGFX.h index 5147bc8..27058d7 100644 --- a/firmware/Adafruit_SSD1306_mfGFX.h +++ b/firmware/Adafruit_SSD1306_mfGFX.h @@ -108,7 +108,7 @@ All text above, and the splash screen must be included in any redistribution class Adafruit_SSD1306 : public Adafruit_GFX { public: Adafruit_SSD1306(int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS); - Adafruit_SSD1306(int8_t DC, int8_t RST, int8_t CS); + Adafruit_SSD1306(int8_t DC, int8_t RST, int8_t CS, bool USE_SPI1=false); Adafruit_SSD1306(int8_t RST); void begin(uint8_t switchvcc = SSD1306_SWITCHCAPVCC, uint8_t i2caddr = SSD1306_I2C_ADDRESS); @@ -135,6 +135,7 @@ class Adafruit_SSD1306 : public Adafruit_GFX { private: int8_t _i2caddr, _vccstate, sid, sclk, dc, rst, cs; + SPIClass * spiClass; void fastSPIwrite(uint8_t c); boolean hwSPI; From e6bb53add2fce9ec64c7918055c3f6f707befd7f Mon Sep 17 00:00:00 2001 From: Jordan Schaenzle Date: Tue, 9 Oct 2018 10:55:40 -0400 Subject: [PATCH 2/2] Added another example file that uses SPI1 --- firmware/examples/ssd1306_128x64_spi1.ino | 365 ++++++++++++++++++++++ 1 file changed, 365 insertions(+) create mode 100644 firmware/examples/ssd1306_128x64_spi1.ino diff --git a/firmware/examples/ssd1306_128x64_spi1.ino b/firmware/examples/ssd1306_128x64_spi1.ino new file mode 100644 index 0000000..8cb15c2 --- /dev/null +++ b/firmware/examples/ssd1306_128x64_spi1.ino @@ -0,0 +1,365 @@ + +/********************************************************************* +This is an example for our Monochrome OLEDs based on SSD1306 drivers + + Pick one up today in the adafruit shop! + ------> http://www.adafruit.com/category/63_98 + +This example is for a 128x64 size display using the SPI1 hardware +peripheral to communicate. 4 or 5 pins are required to interface + +Adafruit invests time and resources providing this open source code, +please support Adafruit and open-source hardware by purchasing +products from Adafruit! + +Written by Limor Fried/Ladyada for Adafruit Industries. +BSD license, check license.txt for more information +All text above, and the splash screen must be included in any redistribution +*********************************************************************/ + +#include "ssd1306_user.h" +#include "Adafruit_mfGFX/Adafruit_mfGFX.h" +#include "Adafruit_SSD1306_mfGFX/Adafruit_SSD1306_mfGFX.h" + +// These can be set to any pins with the exception of the pins +// that are used by the SPI1 peripheral (see below) +#define OLED_DC D2 +#define OLED_CS D1 +#define OLED_RESET D0 + +// SPI1 uses the following pins: +// MISO: D3 +// MOSI: D2 +// SCK: D4 +// SS: D5 (default but overridden by OLED_CD defined above) + +// Use hardware SPI1 +bool useSPI1 = true; +Adafruit_SSD1306 display(OLED_DC, OLED_RESET, OLED_CS, useSPI1); + +#define NUMFLAKES 10 +#define XPOS 0 +#define YPOS 1 +#define DELTAY 2 + +int random(int maxRand) { + return rand() % maxRand; +} + +#define LOGO16_GLCD_HEIGHT 16 +#define LOGO16_GLCD_WIDTH 16 + +static const unsigned char logo16_glcd_bmp[] = +{ 0B00000000, 0B11000000, + 0B00000001, 0B11000000, + 0B00000001, 0B11000000, + 0B00000011, 0B11100000, + 0B11110011, 0B11100000, + 0B11111110, 0B11111000, + 0B01111110, 0B11111111, + 0B00110011, 0B10011111, + 0B00011111, 0B11111100, + 0B00001101, 0B01110000, + 0B00011011, 0B10100000, + 0B00111111, 0B11100000, + 0B00111111, 0B11110000, + 0B01111100, 0B11110000, + 0B01110000, 0B01110000, + 0B00000000, 0B00110000 }; + +#if (SSD1306_LCDHEIGHT != 64) +#error("Height incorrect, please fix Adafruit_SSD1306.h!"); +#endif + +void setup() { + Serial.begin(9600); + + // by default, we'll generate the high voltage from the 3.3v line internally! (neat!) + display.begin(SSD1306_SWITCHCAPVCC); + // init done + + display.display(); // show splashscreen + delay(2000); + display.clearDisplay(); // clears the screen and buffer + + // draw a single pixel + display.drawPixel(10, 10, WHITE); + display.display(); + delay(2000); + display.clearDisplay(); + + // draw many lines + testdrawline(); + display.display(); + delay(2000); + display.clearDisplay(); + + // draw rectangles + testdrawrect(); + display.display(); + delay(2000); + display.clearDisplay(); + + // draw multiple rectangles + testfillrect(); + display.display(); + delay(2000); + display.clearDisplay(); + + // draw mulitple circles + testdrawcircle(); + display.display(); + delay(2000); + display.clearDisplay(); + + // draw a white circle, 10 pixel radius + display.fillCircle(display.width()/2, display.height()/2, 10, WHITE); + display.display(); + delay(2000); + display.clearDisplay(); + + testdrawroundrect(); + delay(2000); + display.clearDisplay(); + + testfillroundrect(); + delay(2000); + display.clearDisplay(); + + testdrawtriangle(); + delay(2000); + display.clearDisplay(); + + testfilltriangle(); + delay(2000); + display.clearDisplay(); + + // draw the first ~12 characters in the font + testdrawchar(); + display.display(); + delay(2000); + display.clearDisplay(); + + // draw scrolling text + testscrolltext(); + delay(2000); + display.clearDisplay(); + + // text display tests + display.setTextSize(1); + display.setTextColor(WHITE); + display.setCursor(0,0); + display.println("Hello, world!"); + display.setTextColor(BLACK, WHITE); // 'inverted' text + display.println(3.141592); + display.setTextSize(2); + display.setTextColor(WHITE); + display.print("0x"); display.println(0xDEADBEEF, HEX); + display.display(); + delay(2000); + + // miniature bitmap display + display.clearDisplay(); + display.drawBitmap(30, 16, logo16_glcd_bmp, 16, 16, 1); + display.display(); + + // invert the display + display.invertDisplay(true); + delay(1000); + display.invertDisplay(false); + delay(1000); + + // draw a bitmap icon and 'animate' movement + testdrawbitmap(logo16_glcd_bmp, LOGO16_GLCD_HEIGHT, LOGO16_GLCD_WIDTH); +} + + +void loop() { + +} + + +void testdrawbitmap(const uint8_t *bitmap, uint8_t w, uint8_t h) { + uint8_t icons[NUMFLAKES][3]; + + // initialize + for (uint8_t f=0; f< NUMFLAKES; f++) { + icons[f][XPOS] = random(display.width()); + icons[f][YPOS] = 0; + icons[f][DELTAY] = random(5) + 1; + + Serial.print("x: "); + Serial.print(icons[f][XPOS], DEC); + Serial.print(" y: "); + Serial.print(icons[f][YPOS], DEC); + Serial.print(" dy: "); + Serial.println(icons[f][DELTAY], DEC); + } + + while (1) { + // draw each icon + for (uint8_t f=0; f< NUMFLAKES; f++) { + display.drawBitmap(icons[f][XPOS], icons[f][YPOS], logo16_glcd_bmp, w, h, WHITE); + } + display.display(); + delay(200); + + // then erase it + move it + for (uint8_t f=0; f< NUMFLAKES; f++) { + display.drawBitmap(icons[f][XPOS], icons[f][YPOS], logo16_glcd_bmp, w, h, BLACK); + // move it + icons[f][YPOS] += icons[f][DELTAY]; + // if its gone, reinit + if (icons[f][YPOS] > display.height()) { + icons[f][XPOS] = random(display.width()); + icons[f][YPOS] = 0; + icons[f][DELTAY] = random(5) + 1; + } + } + } +} + + +void testdrawchar(void) { + display.setTextSize(1); + display.setTextColor(WHITE); + display.setCursor(0,0); + + for (uint8_t i=0; i < 168; i++) { + if (i == '\n') continue; + display.write(i); + if ((i > 0) && (i % 21 == 0)) + display.println(); + } + display.display(); +} + +void testdrawcircle(void) { + for (int16_t i=0; i0; i-=5) { + display.fillTriangle(display.width()/2, display.height()/2-i, + display.width()/2-i, display.height()/2+i, + display.width()/2+i, display.height()/2+i, WHITE); + if (color == WHITE) color = BLACK; + else color = WHITE; + display.display(); + } +} + +void testdrawroundrect(void) { + for (int16_t i=0; i=0; i-=4) { + display.drawLine(0, display.height()-1, display.width()-1, i, WHITE); + display.display(); + } + delay(250); + + display.clearDisplay(); + for (int16_t i=display.width()-1; i>=0; i-=4) { + display.drawLine(display.width()-1, display.height()-1, i, 0, WHITE); + display.display(); + } + for (int16_t i=display.height()-1; i>=0; i-=4) { + display.drawLine(display.width()-1, display.height()-1, 0, i, WHITE); + display.display(); + } + delay(250); + + display.clearDisplay(); + for (int16_t i=0; i