Dear all,
I have two versions of what I believe to be SSD1306 displays
-
HelTec, CS is already connected to GND, this is the OLD version of the HelTec
http://www.ebay.com/itm/201009010892?_trksid=p2059210.m2749.l2649&ssPageName=STRK%3AMEBIDX%3AIT -
Another brand, CS is brought out as a pin, reason I bought it
http://www.ebay.com/itm/291168368309?_trksid=p2059210.m2749.l2649&ssPageName=STRK%3AMEBIDX%3AIT
Now both displays work with U8Glib, I used the OLED_Scale example with this constructor:
U8GLIB_SSD1306_128X64 u8g(13, 11, 10, 9, 2); // SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
Display (1) seems to work fine with the AdaFruit libraries for the SSD1306, however display (2) only works partially with this code. I want to understand why (in order to write a few very simple functions for my display).
My code taken from the AdaFruit example:
#include <SPI.h>
#include "ssd1306_1.h"
#include "Arduino.h"
#include "glcdfont.h"
typedef volatile uint8_t PortReg;
typedef uint8_t PortMask;
PortReg *mosiport, *clkport, *csport, *dcport;
PortMask mosipinmask, clkpinmask, cspinmask, dcpinmask;
int8_t vccstate, sid, sclk, dc, rst, cs;
void setup()
{
Serial.begin(9600);
dc = 9;
rst = 2;
cs = 10;
vccstate = SSD1306_SWITCHCAPVCC;
pinMode(dc, OUTPUT);
pinMode(cs, OUTPUT);
pinMode(rst, OUTPUT);
csport = portOutputRegister(digitalPinToPort(cs));
cspinmask = digitalPinToBitMask(cs);
dcport = portOutputRegister(digitalPinToPort(dc));
dcpinmask = digitalPinToBitMask(dc);
SPI.begin ();
SPI.setClockDivider (SPI_CLOCK_DIV2); // 8 MHz
// Setup reset pin direction (used by both SPI and I2C)
digitalWrite(rst, HIGH);
// VDD (3.3V) goes high at start, lets just chill for a ms
delay(1);
// bring reset low
digitalWrite(rst, LOW);
// wait 10ms
delay(10);
// bring out of reset
digitalWrite(rst, HIGH);
// turn on VCC (9V?)
// Init sequence for 128x64 OLED module
ssd1306_command(SSD1306_DISPLAYOFF); // 0xAE
ssd1306_command(SSD1306_SETDISPLAYCLOCKDIV); // 0xD5
ssd1306_command(0x80); // the suggested ratio 0x80
ssd1306_command(SSD1306_SETMULTIPLEX); // 0xA8
ssd1306_command(0x3F);
ssd1306_command(SSD1306_SETDISPLAYOFFSET); // 0xD3
ssd1306_command(0x0); // no offset
ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0
ssd1306_command(SSD1306_CHARGEPUMP); // 0x8D
if (vccstate == SSD1306_EXTERNALVCC)
{ ssd1306_command(0x10); }
else
{ ssd1306_command(0x14); }
ssd1306_command(SSD1306_MEMORYMODE); // 0x20
ssd1306_command(0x00); // 0x0 act like ks0108
ssd1306_command(SSD1306_SEGREMAP | 0x1);
ssd1306_command(SSD1306_COMSCANDEC);
ssd1306_command(SSD1306_SETCOMPINS); // 0xDA
ssd1306_command(0x12);
ssd1306_command(SSD1306_SETCONTRAST); // 0x81
if (vccstate == SSD1306_EXTERNALVCC)
{ ssd1306_command(0x9F); }
else
{ ssd1306_command(0xCF); }
ssd1306_command(SSD1306_SETPRECHARGE); // 0xd9
if (vccstate == SSD1306_EXTERNALVCC)
{ ssd1306_command(0x22); }
else
{ ssd1306_command(0xF1); }
ssd1306_command(SSD1306_SETVCOMDETECT); // 0xDB
ssd1306_command(0x40);
ssd1306_command(SSD1306_DISPLAYALLON_RESUME); // 0xA4
ssd1306_command(SSD1306_NORMALDISPLAY); // 0xA6
ssd1306_command(SSD1306_DISPLAYON);//--turn on oled panel
/* fill screen with alternating black and white pixels */
ssd1306_command(SSD1306_COLUMNADDR);
ssd1306_command(0); // Column start address (0 = reset)
ssd1306_command(127); // Column end address (127 = reset)
ssd1306_command(SSD1306_PAGEADDR);
ssd1306_command(0); // Page start address (0 = reset)
ssd1306_command((SSD1306_LCDHEIGHT == 64) ? 7 : 3); // Page end address
// SPI
*csport |= cspinmask;
*dcport |= dcpinmask;
*csport &= ~cspinmask;
for (uint16_t i=0; i<(SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8); i++)
{
(void)SPI.transfer(B10101010);
}
*csport |= cspinmask;
}
void loop()
{
}
void ssd1306_command(uint8_t c)
{
// SPI
//digitalWrite(cs, HIGH);
*csport |= cspinmask;
//digitalWrite(dc, LOW);
*dcport &= ~dcpinmask;
//digitalWrite(cs, LOW);
*csport &= ~cspinmask;
(void)SPI.transfer(c);
//digitalWrite(cs, HIGH);
*csport |= cspinmask;
}
void ssd1306_data(uint8_t c)
{
// SPI
//digitalWrite(cs, HIGH);
*csport |= cspinmask;
//digitalWrite(dc, HIGH);
*dcport |= dcpinmask;
//digitalWrite(cs, LOW);
*csport &= ~cspinmask;
(void)SPI.transfer(c);
//digitalWrite(cs, HIGH);
*csport |= cspinmask;
}
The code is supposed to print alternating black and white lines on the screen. I get the following results:
If I run my own (adafruit-based) code first, I get images (1A) en (2A): a lot of trash on screen (2). Running the U8Glib code yields good results: (1B) and (2B). If I then flash my Arduino to my own code and run it, I get (1C) (good again) and (2C): it seems I can only write to part of the screen. (I ran the tests in the order 1A, 1B, 1C, 2A, 2B, 2C)
Now the U8Glib code is done very nicely, but I find it hard to track what is happening. As far as I can tell it uses the same initialization sequence as AdaFruit (the code says so). Display (2) does work, just not with my code. There must be something I'm missing, but I have no clue. I have worked through the datasheet of the SSD1306, but found no extra clues.
I hope someone (mayhaps even Oliver) can shed some light on this and give me a pointer where to look.
Cheers,
Jack