The Newhaven NHD-0420CW series of OLED displays is an expensive (~$40 US) but flexible and brilliant OLED character display available in a variety of colors. I recently used this display in a WWVB time code receiver clock project based on the Canaduino ES100 receiver module. This Newhaven display is based on the US2066 controller and it offers a full selection of data interface options (4-bit and 8-bit parallel, SPI and I2C) as well as operation at 3.3 and 5.0 volts. This 3.3 volt compatibility facilitated its use with the ES100 module by allowing the entire circuit to operate at 3.3 volts. The US2066 has an extended command set that is somewhat abstract and elusive to navigate, and therefore difficult (but possible!) to initialize.

In the 4-bit and 8-bit parallel interface modes, PBP's LCDOUT command works effectively, but in the I2C and SPI modes, the data sent to NHD-0420CW has to be "ASCII-ized" using PBP's ARRAYWRITE command in order for numerical data to display correctly. A text string, inasmuch as already interpreted as ASCII, can be sent directly using PBP's I2CWRITE command, but a numerical quantity, such as decimal 1234 must first be placed in an array as individual ASCII characters 1 (0x31), 2 (0x32), 3 (0x33) and 4 (0x34) before writing to the display via I2CWRITE. Similarly, a hexadecimal quantity such as 1FA7 must be place in an array as individual ASCII characters 1 (0x31), F (0x46), A (0x41) and 7 (0x37) before writing to the display via I2CWRITE.

The sample code below provides a demonstration of (a) initializing the US2066 controller, (b) writing an ASCII text string (on line 1), (c) writing decimal and hexadecimal numerical values using ARRAYWRITE and I2CWRITE commands (on lines 2 and 3), and (d) combining text and numerical values into a single array for writing to the display (on line 4).

This code was developed using Microchip's Curiosity Board equipped with a PIC16F18346 microcontroller and set to operate at 3.3 volts, but can be adapted to any platform with alteration of the target microcontroller parameters.

Comments and supplemental or derivative code samples are encouraged.

Code:
'****************************************************************
'*  Name    : NHD0420CW_US2066_I2C_Demo.BAS                      *
'*  Author  : Roberts                                           *
'*  Notice  : Copyright (c) 2021                                *
'*          : Hack Away                                         *
'*  Date    : 10/06/2021                                         *
'*  Version : 1.0                                               *
'*  Notes   :                                                   *
'*          :                                                   *
'****************************************************************
'
'This program demonstrates the initialization and command/data writing procedures for the Newhaven Display OLED
'NHD-0420CW 4-line x 20 character display used in the 3.3 VDC mode with the I2C interface.  Please refer to the
'OLED display data sheet for wiring information and option configuration (pages 4 & 5).  When used in the I2C mode,
'PBP's ARRAYWRITE command must be used to convert decimal and hexadecimal values into multiple digit ASCII characters
'so that they appear correctly.  This sample code demonstrates writing character strings, decimal, hexadecimal and
'array variables comprising character strings and values to the display's 4 lines and 20 characters.  Additional
'comments are provided adjacent to the code below.  This code was written and runs on a Microchip Curiosity Board
'(DM164137) with a PIC16F18346 uC.  The OLED display is connected to the uC's I/O's RA4 (data) and RA5 (clock).
'
'
'****************************************** PIC16F18346 Initialization *************************************************                                                 
'************************************** Configuration File for the PIC 16F18346 ****************************************
#CONFIG
    __config _CONFIG1, _FEXTOSC_OFF & _RSTOSC_HFINT32 & _CLKOUTEN_OFF & _CSWEN_ON & _FCMEN_ON
    __config _CONFIG2, _MCLRE_ON & _PWRTE_OFF & _WDTE_ON & _LPBOREN_OFF & _BOREN_ON & _BORV_LOW & _PPS1WAY_OFF & _STVREN_ON & _DEBUG_OFF
    __config _CONFIG3, _WRT_OFF & _LVP_OFF
    __config _CONFIG4, _CP_OFF & _CPD_OFF

#ENDCONFIG
@ ERRORLEVEL -306   ; turn off crossing page boundary message

OSCFRQ = 000100    ' Set internal osc to 16MHz
DEFINE OSC 16        ' Tell PBP that the device will clock at 16MHz (necessary for uSec pauses used in bit-banging)

ANSELA = 000000    ' PortA all digital / available pins are A0 through A5 (6 I/O's)
TRISA = 111000   ' PortA mixed I/O

'----------------------------------------- Variables Definition --------------------------------------------------------
D CON 1234                                 'D is a 4-digit constant
H CON $1FA7                                'H is a 4-hexit constant
D_Array VAR BYTE[4]                        'D_Array is a 4-byte array used for ARRAYWRITE D
H_array VAR BYTE[4]                        'H_Array is a 4-byte array used for ARRAYWRITE H
S_Array VAR BYTE[20]                       'S_ARRAY is a 20-byte array used for ARRAYWRITE text, string and H

'OLED Commands:
'----------- Fundamental Set -----------------**********-------------- Extended Set ------------------------------------       
'  0x01  -  Clear Display / Cursor home                 0x2A  -  Invoke extended function set / RE=1 IS=0 SD=0
'  0x02  -  Cursor home                                    0x05 - Set Segment Bidirection (prevents mirrored display)
'  0x08  -  Display OFF                                    0x00 - Disable internal 5V Regulator for 3.3V operation
'  0x0C  -  Display ON                                     0x09 - Set display mode for 4 lines
'  0x80  -  Command prefix (followed by 1 byte command)    0x71 - Function A command
'  0x40  -  Data prefix (followed by 1+ data bytes)     0x28  -  Revert to fundamental function set
'
'The data addresses for the first character on lines 1,2,3 and 4 are 0x01, 0xA0, 0xC0 and 0xE0 respectively
'
'********************************* OLED Display Pin Assignments and Variables*******************************************
SDA_LCD Var PORTA.4                 'I2C data pin
SCK_LCD Var PORTA.5                 'I2C clock pin
i VAR BYTE                          'loop counter and array index used in multiple places

LCDA CON $78                        'OLED LCD I2C Bus address is 0x78
CHDR CON $80                        'CHDR is the command header byte 0x80
DHDR CON $40                        'DHDR is the data header byte 0x40

'******************************************* OLED Initializations ******************************************************                                  
                             
   I2CWRITE SDA_LCD, SCK_LCD, LCDA, [CHDR, $2A, CHDR, $71, CHDR, $00, CHDR, $28]  'Disable internal 5V regulator for 3.3 VDC 
   I2CWRITE SDA_LCD, SCK_LCD, LCDA, [CHDR, $08, CHDR, $01, CHDR, $0C]             'Initialize the OLED LCD (Off / Home & clear / On)
   PAUSE 100                                                                      'Pause 100 mSec
   I2CWRITE SDA_LCD, SCK_LCD, LCDA, [CHDR, $2A, CHDR, $05, CHDR, $28]             'Set Segment Bi-direction function ($05 for normal)
                                                                                  '(prevents backward characters)                                                                
   I2CWRITE SDA_LCD, SCK_LCD, LCDA, [CHDR, $2A, CHDR, $09, CHDR, $28]             'Specify number of display lines
   PAUSE 2                                                                        '($09 for 4 lines / $08 for 2 lines)
   I2CWRITE SDA_LCD, SCK_LCD, LCDA, [CHDR, $01]                                   'Home and clear DDRAM
   PAUSE 2

'================================================= Main Program ========================================================
main:   
 'Write a 20-character string to Line 1 - No ARRAYWRITE Command Required
'-----------------------------------------------------------------------------------------------------------------------
I2CWRITE SDA_LCD, SCK_LCD, LCDA, [CHDR, $01, DHDR, "  ARRAYWRITE DEMO   "]      'Announce the program on Line 1
PAUSE 2000

 'Write a character string and 4-digit decimal variable to Line 2
 'The ARRAYWRITE command places the ASCII character codes for the digits 1,2,3 and 4 into the array D_Array
'-----------------------------------------------------------------------------------------------------------------------   
ARRAYWRITE D_array, [DEC4 D]                                                    'Put 4-digit decimal value D in D_Array
     I2CWRITE SDA_LCD, SCK_LCD, LCDA, [CHDR, $A0, DHDR, "DECIMAL = ", STR D_array\4,"      "]  'Write to display Line 2   
PAUSE 2000

 'Write a character string and 4-digit hexadecimal variable to Line 3
 'The ARRAYWRITE command places the ASCII character codes for the hexits 1,F,A and 7 into the array H_Array
'-----------------------------------------------------------------------------------------------------------------------
ARRAYWRITE H_array, [HEX4 H]                                                    'Put 4-character hex value H in H_Array
I2CWRITE SDA_LCD, SCK_LCD, LCDA, [CHDR, $C0, DHDR, "HEXADECIMAL = ", STR H_array\4, "  "]      'Write to display Line 3
     
PAUSE 2000

'Write an array variable comprising a character string and decimal variable to Line 4
'The ARRAYWRITE command places ASCII text characters, D_Array ASCII digits and the hex constant 1FA7 into the array S_Array
'-----------------------------------------------------------------------------------------------------------------------
ARRAYWRITE S_array, ["HEX: ", STR D_array\4, " ", HEX4 H]         'Put text, ASCII characters and hex value in S_Array
I2CWRITE SDA_LCD, SCK_LCD, LCDA, [CHDR, $E0, DHDR,"DEC & ", STR S_array\14]        'Write to display Line 4
 
PAUSE 2000   
 
I2CWRITE SDA_LCD, SCK_LCD, LCDA, [CHDR, $01]                                   'Home and clear screen

PAUSE 2000
   
Goto main                                                                      'Loop program forever

'******************************************** End of Program ***********************************************************
'***********************************************************************************************************************