Hi all,
I am currently attempting to initialize a Newhaven OLED display (3.12 OLED).
I am using an Arduino Pro Mini 3.3V and created a sketch following the initialization routine specified in the datasheet. From the timing diagram shown in the datasheet it appears that the clock is inactive HIGH (CPOL = 1) and data is shifted on the rising edge (CPHA = 1) resulting in a mode 3 SPI interface.
This is the timing diagram in the datasheet:
However when I set the SPI mode in the sketch to what is shown in the datasheet (Mode 3; pull up on clock line to 3.3V), I get strange values being sent over the SPI bus when I examine the data with a logic analyzer. If I set the SPI mode to mode 1 (pull down on clock line to GND) then the data is shown correctly in the logic analyzer but the communication is not what it should be so the display will not initialize. I am changing the settings in the logic analyzer program to match the SPI mode in each case so that is not the issue.
So, how to get the data to be sent correctly in the correct mode? Here is a screencap of the data when in Mode 3:
As you can see this is incorrect data when compared to the routine in the sketch.
And here is the (correct) data when sent in Mode 1:
Here is the Arduino sketch. It is identical in both cases with the exception of the SPI.setDataMode part.
/*
OLED Display Initialization
This is an initialization routine for the NewHaven 3.12 Blue OLED display.
The routine is taken from the datasheet for the display. The display is
connected in 4-wire serial (SPI) mode as shown in the datasheet.
*/
#include <SPI.h>
const int displaySelect = 7;
const int displayReset = 6;
const int displayDC = 5;
void setup(){
pinMode(displaySelect, OUTPUT);
pinMode(displayReset, OUTPUT);
pinMode(displayDC, OUTPUT);
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV64);
SPI.setDataMode(SPI_MODE3);
SPI.begin();
/* OLED INITIALIZATION ROUTINE */
digitalWrite(displayDC,LOW); // Set data control to COMMAND mode
digitalWrite(displaySelect,LOW); // Select display
SPI.transfer(0xFD); // Unlock Basic Commands (0x12/0x16)
SPI.transfer(0x12|0x12);
SPI.transfer(0XAE|0x00); // Display Off (0x00/0x01)
SPI.transfer(0x15); // Set column address
SPI.transfer(0x1C); // Default 0x00
SPI.transfer(0x5B); // Default 0x77
SPI.transfer(0x75); // Set row address
SPI.transfer(0x00); // Default 0x00
SPI.transfer(0x3F); // Default 0x7F
SPI.transfer(0xB3); // Set display clock @ 80 FPS
SPI.transfer(0x91); // Default 0xD0
SPI.transfer(0xCA); // Set multiplex ratio to 1/64 duty
SPI.transfer(0x3F); // Default 0x7F (1/128 Duty)
SPI.transfer(0xA2); // Set display offset
SPI.transfer(0x00);
SPI.transfer(0xA1); // Set start line
SPI.transfer(0x00);
SPI.transfer(0xA0); // Set remap format
SPI.transfer(0x14);
SPI.transfer(0x11); // Default 0x01 (Disable dual COM mode)
SPI.transfer(0xB5); // Disable GPIO pins input
SPI.transfer(0x00); // Default 0x0A (GPIO pins output LOW)
SPI.transfer(0xAB); // Enable internal VDD regulator
SPI.transfer(0x01);
SPI.transfer(0xB4); // Set display enhancement A
SPI.transfer(0xA0|0xA0); // Enable external VSL - Default 0xA2
SPI.transfer(0x05|0xFD); // Default 0xB5
SPI.transfer(0xC1); // Set segment output current (contrast)
SPI.transfer(0x9F); // Default 0x7F
SPI.transfer(0xC7); // Set scale factor of segment output current control
SPI.transfer(0x0F); // Default 0x0F (Maximum)
SPI.transfer(0xB9); // Set default linear gray scale table
SPI.transfer(0xB1); // Set phase length - phase 1 as 5 clocks and phase 2 as 14 clocks
SPI.transfer(0xE2); // Default 0x74 (7 display clocks [Phase 2] / 9 Display clocks [Phase 1]
SPI.transfer(0xD1); // Set display enhancement B - enhance driving scheme capability
SPI.transfer(0x82|0x20);
SPI.transfer(0x20);
SPI.transfer(0xBB); // Set pre-charge voltage level as 0.6*VCC
SPI.transfer(0x1F); // Default 0x17 (0.50*VCC)
SPI.transfer(0xB6); // Set precharge period - set second pre-charge period as 8 clocks
SPI.transfer(0x08);
SPI.transfer(0xBE); // Set VCOMH - set common pins deselect voltage level as 0.86*VCC
SPI.transfer(0x07); // Default 0x04 (0.80*VCC)
SPI.transfer(0xA4|0x02); // Normal display mode
SPI.transfer(0xA8|0x01); // Disable partial display
SPI.transfer(0xAE|0x01); // Set display on/off (0x00 -> OFF; 0x01 -> ON)
SPI.transfer(0xA5); // Set entire display on
digitalWrite(displaySelect,HIGH); // De-select display
}
void loop(){
// digitalWrite(displaySelect,LOW);
// digitalWrite(displayDC,LOW);
// SPI.transfer(0xAE|0x00);
// delay(500);
// SPI.transfer(0xAE|0x01);
// digitalWrite(displaySelect,HIGH);
}
It looks like there is some weird glitch with the clock when in Mode 3 with the clock pulled high while inactive. It would seem to be shifting all data bits slightly since the datastream is now starting in the wrong place. What to do about this? I am not sure where the strange clock behavior is coming from. Could it have to do with the pull-up? I also have a microSD card on this bus and I am not sure if the pull-up will interfere with it as it may use a different clock polarity - but the CardInfo sketch still works with the pull-up in place so hopefully I am OK.
Any help would be greatly appreciated!