//---------------------------------------------------------
/*
Program for writing to Newhaven Display NHD-1.91-176176B with SSD1333 controller.
This code is written for the Arduino Due.
This code will initialize the display and fill the screen with different colors
Copyright (c) 2025 - Newhaven Display International, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
//---------------------------------------------
/*---------------Pinout Table--------------
NHD-1.91-176176B Arduino Due
1
2 GND
3
4
5
6 D35
7 D34
8 D33
9 D32
10 D31
11 D30
12 D29
13 D28
14 D27
15 D26
16 D40
17 D41
18 D38
19 D25
20 D37
21
22 3.3V
23 GND
24
25
26
27
28
29 GND
30
----------------------------------------------*/
//--------------Interface Selection---------------------------------------------------------------------
const unsigned char interface = 0; //0 = Parallel 6800 1 = Parallel 8080 2 = 4-Wire SPI 3 = I2C
//------------------------------------------------------------------------------------------------------
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Pin Definition
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#define DC 25 //DC
#define RW 26 //RW / WR
#define E 27 //E / RD
#define SCL 28 //DB0
#define SDI 29 //DB1
#define D2 30 //DB2
#define D3 31 //DB3
#define D4 32 //DB4
#define D5 33 //DB5
#define D6 34 //DB6
#define D7 35 //DB7
#define RES 37 //RES
#define CS 38 //CS
#define BS1 40 //BS1
#define BS2 41 //BS2
#define WHITE 0xFF, 0xFF
#define RED 0xF8, 0x00
#define ORANGE 0xFB, 0xE0
#define YELLOW 0xFF, 0xE0
#define GREEN 0x07, 0xE0
#define BLUE 0x00, 0x1F
#define VIOLET 0x78, 0x1F
#define BLACK 0x00, 0x00
unsigned char tx_packet[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
const char slave2w = 0x78;
void write_8bit(unsigned char c){
for(int i =35;i>=28;i--){
if( (c&0x80) ==0x80){
digitalWrite(i,HIGH);
}
else {
digitalWrite(i,LOW);
}
c= c<<1;
}
}
void command(unsigned char c) // send command to OLED
{
unsigned char i;
unsigned char mask = 0x80;
switch(interface)
{
case 0: digitalWrite(DC, LOW); // D/C set to LOW for comm_out_2
delayMicroseconds(1);
write_8bit(c);
digitalWrite(RW, LOW); // R/W set to LOW for writing
digitalWrite(E, HIGH); //E set HIGH for latch
delayMicroseconds(1);
digitalWrite(E, LOW); // E set LOW for latch
break;
case 1: digitalWrite(DC, LOW); //D/C LOW
digitalWrite(E, HIGH); //RD# HIGH
delayMicroseconds(1);
write_8bit(c);
digitalWrite(RW, LOW); //WR LOW
digitalWrite(RW, HIGH); //WR HIGH
break;
case 2: digitalWrite(DC, LOW); //command
for(i=0;i<8;i++)
{
digitalWrite(SCL, LOW);
if((c & mask) >> 7 == 1)
{
digitalWrite(SDI, HIGH);
}
else
{
digitalWrite(SDI, LOW);
}
digitalWrite(SCL, HIGH);
c = c << 1;
}
break;
case 3: I2C_Start_Transmission();
I2C_Transmission_Out(0x78);
I2C_Ack_Ignore(); //SDAout disconnected
I2C_Transmission_Out(0x00);
I2C_Ack_Ignore(); //SDAout disconnected
I2C_Transmission_Out(c);
I2C_Ack_Ignore(); //SDAout disconnected
I2C_Stop_Transmission();
break;
}
}
void data(unsigned char d) // send data to OLED
{
unsigned char i;
unsigned char mask = 0x80;
switch (interface)
{
case 0: write_8bit(d);
digitalWrite(DC, HIGH); // D/C set to HIGH for data_out_2
delayMicroseconds(1);
digitalWrite(RW, LOW); // R/W set to LOW for writing
digitalWrite(E, HIGH); //E set HIGH for latch
delayMicroseconds(1);
digitalWrite(E, LOW); // E set LOW for latch
break;
case 1: digitalWrite(DC, HIGH); //DC HIGH
digitalWrite(E, HIGH); //RD# HIGH
write_8bit(d);
digitalWrite(RW, LOW); //WR LOW
digitalWrite(RW, HIGH); //WR HIGH
break;
case 2: digitalWrite(DC, HIGH);
for(i=0;i<8;i++)
{
digitalWrite(SCL, LOW);
if((d & mask) >> 7 == 1)
{
digitalWrite(SDI, HIGH);
}
else
{
digitalWrite(SDI, LOW);
}
digitalWrite(SCL, HIGH);
d = d << 1;
}
break;
case 3: I2C_Start_Transmission();
I2C_Transmission_Out(0x78);
I2C_Ack_Ignore();
I2C_Transmission_Out(0x40);
I2C_Ack_Ignore();
I2C_Transmission_Out(d);
I2C_Ack_Ignore();
I2C_Stop_Transmission();
break;
}
}
void I2C_Start_Transmission()
{
digitalWrite(SCL, HIGH);
while(0);
digitalWrite(SDI, HIGH);
while(0);
digitalWrite(SDI, LOW);
while(0);
}
void I2C_Transmission_Out(unsigned char b)
{
unsigned int n;
for(n=0;n<8;n++){
if((b&0x80)==0x80)
digitalWrite(SDI, HIGH);
else
digitalWrite(SDI, LOW);
while(0);
b=(b<<1);
digitalWrite(SCL, LOW);
while(0);
digitalWrite(SCL, HIGH);
while(0);
digitalWrite(SCL, LOW);
while(0);
}
}
void I2C_Ack_Ignore()
{
digitalWrite(SCL, LOW);
while(0);
digitalWrite(SCL, HIGH);
while(0);
digitalWrite(SCL, LOW);
while(0);
}
void I2C_Stop_Transmission()
{
digitalWrite(SCL, HIGH);
while(0);
digitalWrite(SDI, LOW);
while(0);
digitalWrite(SDI, HIGH);
while(0);
}
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Instruction Setting
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void Set_Column_Address(unsigned char a, unsigned char b)
{
command(0x15); // Set Column Address
data(a); // Default => 0x00 (Start Address)
data(b); // Default => 0x7F (End Address)
}
void Set_Row_Address(unsigned char a, unsigned char b)
{
command(0x75); // Set Row Address
data(a); // Default => 0x00 (Start Address)
data(b); // Default => 0x7F (End Address)
}
void Set_Write_RAM()
{
command(0x5C); // Enable MCU to Write into RAM
}
void Set_Read_RAM()
{
command(0x5D); // Enable MCU to Read from RAM
}
void Set_Remap_Format(unsigned char d)
{
command(0xA0); // Set Re-Map / Color Depth
data(d); // Default => 0x50
// Horizontal Address Increment
// Column Address 0 Mapped to SEG0
// Color Sequence: A => B => C
// Scan from COM0 to COM[N-1]
// Enable COM Split Odd Even
// 65,536 Colors
}
void Set_Start_Line(unsigned char d)
{
command(0xA1); // Set Vertical Scroll by RAM
data(d); // Default => 0x00
}
void Set_Display_Offset(unsigned char d)
{
command(0xA2); // Set Vertical Scroll by Row
data(d); // Default => 0x00
}
void Set_Display_Mode(unsigned char d)
{
command(d); // Set Display Mode
// Default => 0xA6
// 0xA4 => Entire Display Off, All Pixels Turn Off
// 0xA5 => Entire Display On, All Pixels Turn On at GS Level 63
// 0xA6 => Normal Display
// 0xA7 => Inverse Display
}
void Set_IREF(unsigned char d)
{
command(0xAD); // Set IREF
data(d); // Default => 0x80
// 0x80 => Select External IREF
// 0x90 => Enable Internal IREF during Display On
}
void Set_Display_On_Off(unsigned char d)
{
command(d); // Set Display On/Off
// Default => 0xAE
// 0xAE => Display Off (Sleep Mode On)
// 0xAF => Display On (Sleep Mode Off)
}
void Set_Phase_Length(unsigned char d)
{
command(0xB1); // Phase 1 (Reset) & Phase 2 (Pre-Charge) Period Adjustment
data(d); // Default => 0x84 (16 Display Clocks [Phase 2] / 8 Display Clocks [Phase 1])
// D[3:0] => Phase 1 Period in 2~30 Display Clocks
// D[7:4] => Phase 2 Period in 2~30 Display Clocks
}
void Set_Display_Clock(unsigned char d)
{
command(0xB3); // Set Display Clock Divider / Oscillator Frequency
data(d); // Default => 0x90
// A[3:0] => Display Clock Divider
// A[7:4] => Oscillator Frequency
}
void Set_Precharge_Period(unsigned char d)
{
command(0xB6); // Set Second Pre-Charge Period
data(d); // Default => 0x08 (8 Display Clocks)
}
void Set_Precharge_Voltage(unsigned char d)
{
command(0xBB); // Set Pre-Charge Voltage Level
data(d); // Default => 0x17 (0.40*VCC)
}
void Set_VCOMH(unsigned char d)
{
command(0xBE); // Set COM Deselect Voltage Level
data(d); // Default => 0x05 (0.82*VCC)
}
void Set_Contrast_Color(unsigned char a, unsigned char b, unsigned char c)
{
command(0xC1); // Set Contrast Current for Color A, B, C
data(a); // Default => 0x7F (Color A)
data(b); // Default => 0x7F (Color B)
data(c); // Default => 0x7F (Color C)
}
void Set_Master_Current(unsigned char d)
{
command(0xC7); // Master Contrast Current Control
data(d); // Default => 0x0F (Maximum)
}
void Set_Multiplex_Ratio(unsigned char d)
{
command(0xCA); // Set Multiplex Ratio
data(d); // Default => 0xAF (1/176 Duty)
}
void Set_Command_Lock(unsigned char d)
{
command(0xFD); // Set Command Lock
data(d); // Default => 0x12
// 0x12 => Driver IC interface is unlocked from entering command.
// 0x16 => All Commands are locked except 0xFD.
}
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Show Regular Pattern (Full Screen)
//
// a: RRRRRGGG
// b: GGGBBBBB
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void Fill_RAM(unsigned char a, unsigned char b)
{
unsigned char i,j;
Set_Column_Address(0x00,0xAF);
Set_Row_Address(0x00,0xAF);
Set_Write_RAM();
for(i=0;i<176;i++)
{
for(j=0;j<176;j++)
{
data(a);
data(b);
}
}
}
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Sleep Mode
//
// "0x00" Enter Sleep Mode
// "0x01" Exit Sleep Mode
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void OLED_Sleep(unsigned char a)
{
switch(a)
{
case 0:
Set_Display_On_Off(0xAE);
Set_Display_Mode(0xA5);
break;
case 1:
Set_Display_Mode(0xA6);
Set_Display_On_Off(0xAF);
break;
}
}
void Init_OLED(void)
{
unsigned char i;
digitalWrite(RES,LOW);//RES
delay(10);
digitalWrite(RES,HIGH);//RES
Set_Command_Lock(0x12); // Unlock Driver IC (0x12/0x16)
Set_Display_On_Off(0xAE); // Display Off
Set_Remap_Format(0x64); // Set Horizontal Address Increment
Set_Start_Line(0x00); // Set Mapping RAM Display Start Line
Set_Display_Offset(0x00); // Shift Mapping RAM Counter
Set_Display_Mode(0xA6); // Normal Display Mode
Set_Phase_Length(0x24); // Set Phase 1 & Phase 2
Set_Display_Clock(0x80); // Set Clock
Set_Precharge_Period(0x0F); // Set Second Pre-Charge Period
Set_Precharge_Voltage(0x1F); // Set Pre-Charge Voltage Level
Set_VCOMH(0x05); // Set Common Pins Deselect Voltage Level
Set_Contrast_Color(0x3C,0x39,0x43); // Set Contrast of Color A (Red), Color B (Green), and Color C (Blue)
Set_Master_Current(0x0F); // Set Scale Factor of Segment Output Current Control
Set_Multiplex_Ratio(0xAF); // 1/128 Duty (Max_Row)
command(0xB8); //Gamma Look-Up Table
data(0x00);//1
data(0x02);//2
data(0x04);//3
data(0x06);//4
data(0x07);//5
data(0x08);//6
data(0x09);//7
data(0x0a);//8
data(0x0b);//9
data(0x0c);//10
data(0x0d);//11
data(0x0e);//12
data(0x10);//13
data(0x11);//14
data(0x12);//15
data(0x14);//16
data(0x15);//17
data(0x16);//18
data(0x18);//19
data(0x1a);//20
data(0x1b);//21
data(0x1d);//22
data(0x1f);//23
data(0x20);//24
data(0x22);//25
data(0x24);//26
data(0x26);//27
data(0x27);//28
data(0x29);//29
data(0x2b);//30
data(0x2d);//31
data(0x2f);//32
data(0x31);//33
data(0x33);//34
data(0x35);//35
data(0x37);//36
data(0x39);//37
data(0x3b);//38
data(0x3d);//39
data(0x3f);//40
data(0x42);//41
data(0x44);//42
data(0x46);//43
data(0x48);//44
data(0x4b);//45
data(0x4d);//46
data(0x50);//47
data(0x52);//48
data(0x55);//49
data(0x57);//50
data(0x5a);//51
data(0x5b);//52
data(0x5f);//53
data(0x62);//54
data(0x65);//55
data(0x67);//56
data(0x6a);//57
data(0x6d);//58
data(0x70);//59
data(0x73);//60
data(0x76);//61
data(0x79);//62
data(0x7c);//63
Set_Display_On_Off(0xAF); // Display On
}
void Init() // for Arduino, runs first at power on
{
pinMode(DC, OUTPUT); //RS
pinMode(RW, OUTPUT); //RW
pinMode(E, OUTPUT); //E
pinMode(SCL, OUTPUT); //DB0
pinMode(SDI, OUTPUT); //DB1
pinMode(D2, OUTPUT); //DB2
pinMode(D3,OUTPUT); //DB3
pinMode(D4,OUTPUT); //DB4
pinMode(D5,OUTPUT); //DB5
pinMode(D6,OUTPUT); //DB6
pinMode(D7,OUTPUT); //DB7
pinMode(RES,OUTPUT); //RES
pinMode(CS,OUTPUT); //CS
pinMode(BS1,OUTPUT); //BS1
pinMode(BS2,OUTPUT); //BS2
digitalWrite(RES,HIGH); //RES
digitalWrite(CS,LOW); //CS
switch(interface)
{
case 0: digitalWrite(BS1,LOW);//6800 PARALLEL INTERFACE
digitalWrite(BS2,HIGH);//6800 PARALLEL INTERFACE
break;
case 1: digitalWrite(BS1,HIGH);//8080 PARALLEL INTERFACE
digitalWrite(BS2,HIGH);//8080 PARALLEL INTERFACE
break;
case 2: digitalWrite(BS1,LOW);//4-Wire SPI INTERFACE
digitalWrite(BS2,LOW);//4-Wire SPI INTERFACE
digitalWrite(D2, LOW);
digitalWrite(D3, LOW);
digitalWrite(D4, LOW);
digitalWrite(D5, LOW);
digitalWrite(D6, LOW);
digitalWrite(D7, LOW);
digitalWrite(RW, LOW);
digitalWrite(E, LOW);
break;
case 3: digitalWrite(BS1,HIGH);//I2C INTERFACE
digitalWrite(BS2,LOW);//I2C INTERFACE
digitalWrite(D3, LOW);
digitalWrite(D4, LOW);
digitalWrite(D5, LOW);
digitalWrite(D6, LOW);
digitalWrite(D7, LOW);
digitalWrite(RW, LOW);
digitalWrite(E, LOW);
digitalWrite(CS, LOW);
break;
}
Init_OLED(); // initialize display
}
void setup() {
Init();
}
void loop()
{
Fill_RAM(WHITE);
Fill_RAM(RED);
Fill_RAM(ORANGE);
Fill_RAM(YELLOW);
Fill_RAM(GREEN);
Fill_RAM(BLUE);
Fill_RAM(VIOLET);
Fill_RAM(BLACK);
}