//---------------------------------------------------------
/*
Program for writing to Newhaven Display NHD-1.91-176176UBC3 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) 2024 - 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-176176UBC3 Arduino Due
1 GND
2 3.3V
3 NC
4 D25
5 D26
6 D27
7 D28
8 D29
9 D30
10 D31
11 D32
12 D33
13 D34
14 D35
15 D36
16 D37
17 D38
18 D39
19 D40
20 D41
----------------------------------------------*/
//--------------Interface Selection---------------------------------------------------------------------
const unsigned char interface = 0; //0 = Parallel 6800 1 = Parallel 8080 2 = 4-Wire SPI 3 = I2C
//------------------------------------------------------------------------------------------------------
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Pin Definition
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#define P4 25 //DC
#define P5 26 //RW / WR
#define P6 27 //E / RD
#define P7 28 //DB0
#define P8 29 //DB1
#define P9 30 //DB2
#define P10 31 //DB3
#define P11 32 //DB4
#define P12 33 //DB5
#define P13 34 //DB6
#define P14 35 //DB7
#define P15 36 //GND
#define P16 37 //RES
#define P17 38 //CS
#define P18 39 //GND
#define P19 40 //BS1
#define P20 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(P4, LOW); // D/C set to LOW for comm_out_2
delayMicroseconds(1);
write_8bit(c);
digitalWrite(P5, LOW); // R/W set to LOW for writing
digitalWrite(P6, HIGH); //E set HIGH for latch
delayMicroseconds(1);
digitalWrite(P6, LOW); // E set LOW for latch
break;
case 1: digitalWrite(P4, LOW); //D/C LOW
digitalWrite(P6, HIGH); //RD# HIGH
delayMicroseconds(1);
write_8bit(c);
digitalWrite(P5, LOW); //WR LOW
digitalWrite(P5, HIGH); //WR HIGH
break;
case 2: digitalWrite(P4, LOW); //command
for(i=0;i<8;i++)
{
digitalWrite(P7, LOW);
if((c & mask) >> 7 == 1)
{
digitalWrite(P8, HIGH);
}
else
{
digitalWrite(P8, LOW);
}
digitalWrite(P7, 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(P4, HIGH); // D/C set to HIGH for data_out_2
delayMicroseconds(1);
digitalWrite(P5, LOW); // R/W set to LOW for writing
digitalWrite(P6, HIGH); //E set HIGH for latch
delayMicroseconds(1);
digitalWrite(P6, LOW); // E set LOW for latch
break;
case 1: digitalWrite(P4, HIGH); //DC HIGH
digitalWrite(P6, HIGH); //RD# HIGH
write_8bit(d);
digitalWrite(P5, LOW); //WR LOW
digitalWrite(P5, HIGH); //WR HIGH
break;
case 2: digitalWrite(P4, HIGH);
for(i=0;i<8;i++)
{
digitalWrite(P7, LOW);
if((d & mask) >> 7 == 1)
{
digitalWrite(P8, HIGH);
}
else
{
digitalWrite(P8, LOW);
}
digitalWrite(P7, 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(P7, HIGH);
while(0);
digitalWrite(P8, HIGH);
while(0);
digitalWrite(P8, LOW);
while(0);
}
void I2C_Transmission_Out(unsigned char b)
{
unsigned int n;
for(n=0;n<8;n++){
if((b&0x80)==0x80)
digitalWrite(P8, HIGH);
else
digitalWrite(P8, LOW);
while(0);
b=(b<<1);
digitalWrite(P7, LOW);
while(0);
digitalWrite(P7, HIGH);
while(0);
digitalWrite(P7, LOW);
while(0);
}
}
void I2C_Ack_Ignore()
{
digitalWrite(P7, LOW);
while(0);
digitalWrite(P7, HIGH);
while(0);
digitalWrite(P7, LOW);
while(0);
}
void I2C_Stop_Transmission()
{
digitalWrite(P7, HIGH);
while(0);
digitalWrite(P8, LOW);
while(0);
digitalWrite(P8, 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(P16,LOW);//RES
delay(10);
digitalWrite(P16,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(P4, OUTPUT); //RS
pinMode(P5, OUTPUT); //RW
pinMode(P6, OUTPUT); //E
pinMode(P7, OUTPUT); //DB0
pinMode(P8, OUTPUT); //DB1
pinMode(P9, OUTPUT); //DB2
pinMode(P10,OUTPUT); //DB3
pinMode(P11,OUTPUT); //DB4
pinMode(P12,OUTPUT); //DB5
pinMode(P13,OUTPUT); //DB6
pinMode(P14,OUTPUT); //DB7
pinMode(P15,OUTPUT); //GND
pinMode(P16,OUTPUT); //RES
pinMode(P17,OUTPUT); //CS
pinMode(P18,OUTPUT); //GND
pinMode(P19,OUTPUT); //BS1
pinMode(P20,OUTPUT); //BS2
digitalWrite(P15,LOW); //GND
digitalWrite(P16,HIGH); //RES
digitalWrite(P17,LOW); //CS
digitalWrite(P18,LOW); //GND
switch(interface)
{
case 0: digitalWrite(P19,LOW);//6800 PARALLEL INTERFACE
digitalWrite(P20,HIGH);//6800 PARALLEL INTERFACE
break;
case 1: digitalWrite(P19,HIGH);//8080 PARALLEL INTERFACE
digitalWrite(P20,HIGH);//8080 PARALLEL INTERFACE
break;
case 2: digitalWrite(P19,LOW);//4-Wire SPI INTERFACE
digitalWrite(P20,LOW);//4-Wire SPI INTERFACE
digitalWrite(P9, LOW);
digitalWrite(P10, LOW);
digitalWrite(P11, LOW);
digitalWrite(P12, LOW);
digitalWrite(P13, LOW);
digitalWrite(P14, LOW);
digitalWrite(P15, LOW);
digitalWrite(P5, LOW);
digitalWrite(P6, LOW);
break;
case 3: digitalWrite(P19,HIGH);//I2C INTERFACE
digitalWrite(P20,LOW);//I2C INTERFACE
digitalWrite(P10, LOW);
digitalWrite(P11, LOW);
digitalWrite(P12, LOW);
digitalWrite(P13, LOW);
digitalWrite(P14, LOW);
digitalWrite(P15, LOW);
digitalWrite(P5, LOW);
digitalWrite(P6, LOW);
digitalWrite(P17, 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);
}