PSoC and SSD1331 oled display

SSD1331 RGB oled display 0.95 inch SPI Full Colour OLED Display SSD1331 96X64

Now you will see plenty of these displays on the web sold as Arduino experimental displays and they all use the very great resources found in the Arduino world.

Many of you know I like PSoC devices and especially the very useful CY8CKIT-059 PSoC® 5LP Prototyping Kit With Onboard Programmer and Debugger

Images from this site

So it will come as no surprise that I have decided to get this development board talking to the SSD1331 display. This is especially pertinent for me as I am writing a series of display drivers with a common graphics core. There are plenty of graphics cores available free on the web, but they all seem to take a large amount of effort to implement in C99 code, which is the favoured programming language of CREATOR the free programming resource and IDE that comes with these development kits.

The secret with the SSD display drivers is having the right initialisation code for the display so in the first part of this blog I am going to build the initialisation code in CREATOR.

At this point I am going to thank PAUL STARON for allowing me to use and blog about his code for the SSD1331 display he has on ARM mbed. I will be mangling and changing his code to suit my code style and the PSoC Creator C99 code environment. So complain to me about any code faults in this blog, Paul is innocent.

First thing that is needed before anything can happen is to configure the SPI hardware that will be used to drive the display. This is manly a drag and drop activity in Creator and is shown below.

Creator IDE placing a SPI Master component and named output pins

It is also a good thing to setup all the outputs to the display and get the order of the output pins of the CY8CKIT-059 development kit to match the order of input pints to the display so that a flat ribbon cable can make the link between the two units.

Creator IDE assigning output pin names to CY8CKIT-0.59 dev board hardware port

Be aware that the display as sold is expected to be run on 3.3volts it will take 5volts but I do not know for how long they will work at this voltage. As the CY8CKIT-059 development kit is programmed at USB 5volt I have taken the precaution of running the display with a 3,3volt module using the E-Bay plug in power supply and just keeping output pins at 5volt while programming. and modifying code.

All the hardware done now just the code to get going.

Header(.H)

/* ========================================
 *
 * Copyright Crusty Consultants, 2021
 * All Rights Reserved
 * PUBLISHED, SOFTWARE.
 * Main Contributor "Paul Staron" from public published work on "Mbed"
 * Ported to PSoC by Crusty Consultants.
 * Please acknowledge the above if using for publication or production.
 * No warranty is provided for the functioning of this software.
 * Used at own risk.
 * ========================================
*/

#ifndef __SSD1331_H__
    #define __SSD1331_H__
     
    #include "project.h"
     
    // Screen Settings
    #define width   96-1        // Max X axial direction in screen
    #define height  64-1        // Max Y axial direction in screen
    #define Set_Column_Address  0x15
    #define Set_Row_Address     0x75
    #define contrastA           0x81
    #define contrastB           0x82
    #define contrastC           0x83
    #define display_on          0xAF
    #define display_off         0xAE
     
    // Internal Font size settings
    #define NORMAL  0
    #define WIDE    1
    #define HIGH    2
    #define WH      3
    #define WHx36   4
    #define X_width 6 
    #define Y_height 8 
     
     
    // GAC hardware acceleration commands
    #define GAC_DRAW_LINE           0x21    // Draw Line
    #define GAC_DRAW_RECTANGLE      0x22    // Rectangle
    #define GAC_COPY_AREA           0x23    // Copy Area
    #define GAC_DIM_WINDOW          0x24    // Dim Window
    #define GAC_CLEAR_WINDOW        0x25    // Clear Window
    #define GAC_FILL_ENABLE_DISABLE 0x26    // Enable Fill
    #define SCROLL_SETUP            0x27    // Setup scroll
    #define SCROLL_STOP             0x2E    // Scroll Stop
    #define SCROLL_START            0x2F    // Scroll Start
     
    // Basic RGB color definitions         RED GREEN BLUE values                         
     
    #define Black           0x0000      //   0,   0,   0 
    #define LightGrey       0xC618      // 192, 192, 192 
    #define DarkGrey        0x7BEF      // 128, 128, 128 
    #define Red             0xF800      // 255,   0,   0 
    #define Green           0x07E0      //   0, 255,   0 
    #define Cyan            0x07FF      //   0, 255, 255 
    #define Blue            0x001F      //   0,   0, 255 
    #define Magenta         0xF81F      // 255,   0, 255 
    #define Yellow          0xFFE0      // 255, 255,   0 
    #define White           0xFFFF      // 255, 255, 255 
 
// Public functions
    void ssd133_Init(void);
    void ssd1331_cls();
    uint16_t ssd1331_toRGB(uint16_t R,uint16_t G,uint16_t B);
    void ssd1331_Fill_Screen(uint16_t color);
    void ssd1331_fillrect(uint8_t x1,uint8_t y1,uint8_t x2,uint8_t y2,uint16_t colorline,uint16_t colorfill);
#endif

/* [] END OF FILE */

Source(.C)

/* ========================================
 *
 * Copyright Crusty Consultants, 2021
 * All Rights Reserved
 * PUBLISHED, SOFTWARE.
 * Main Contributor "Paul Staron" from public published work on "Mbed"
 * Ported to PSoC by Crusty Consultants.
 * Please acknowledge the above if using for publication or production.
 * No warranty is provided for the functioning of this software.
 * Used at own risk.
 * ========================================
*/

#include <ssd1331.h>

// private variables
    uint16_t Char_Color;    // text color
    uint16_t BGround_Color; // background color
    uint8_t chr_size;       // size character to be set at.
    
//private functions specific to ssd1331.c

// Communication functions to commuinicate with Display SPI interface.
// Note CS pin raised and lowered by component along with data and clock timing for each 8 bit byte sent.

    void  ssd1331_RegWrite(unsigned char Command)
    {
        
        DC_Write(0);     // set the display pin D/C pin to low as this is a command
        SPIM_1_WriteByte(Command);//send the command value
    };

    void  ssd1331_RegWriteM(unsigned char *Command, uint8_t count)
    {
        int i;
        DC_Write(0);     // set the display pin D/C pin to low as this is a command
        for( i=0; i<count; i++) {
            SPIM_1_WriteByte(*Command++);//send a series of commands
        }
    }

    void  ssd1331_DataWrite(unsigned char c)
    {
        DC_Write(1);    // set the display pin D/C pin to high as this is DATA
        SPIM_1_WriteByte(c);
    }

    void  ssd1331_DataWrite_to(uint16_t Dat)
    {
        DC_Write(1);    // set the display pin D/C pin to high as this is DATA    
        SPIM_1_WriteByte((unsigned char)((Dat >> 8)));
        SPIM_1_WriteByte((unsigned char)(Dat));
    }
    
//public functions
    void ssd1331_Maxwindow()
    {    
        unsigned char cmd[7]= {Set_Column_Address,0x00,0x5F,Set_Row_Address,0x00,0x3F};
        ssd1331_RegWriteM(cmd, 6);
    }
    
    void ssd1331_foreground(uint16_t color)
    {
        Char_Color = color;
    }
    
    void ssd1331_background(uint16_t color)
    {
        BGround_Color = color;
    }
    
    void ssd1331_cls()
    {
        unsigned char cmd[6]= {GAC_CLEAR_WINDOW,0,0,width,height};
        ssd1331_RegWriteM(cmd,5);
        CyDelay(500);
        ssd1331_Maxwindow();
        ssd1331_background(Black);//
    }
    
    uint16_t ssd1331_toRGB(uint16_t R,uint16_t G,uint16_t B)
    {  
        uint16_t c;
        c = R >> 3;
        c <<= 6;
        c |= G >> 2;
        c <<= 5;
        c |= B >> 3;
        return c;
    }
    
    void ssd1331_fillrect(uint8_t x1,uint8_t y1,uint8_t x2,uint8_t y2,uint16_t colorline,uint16_t colorfill)
    {
        if  ( x1 > width ) x1 = width;
        if  ( y1 > height ) y1 = height;
        if  ( x2 > width ) x2 = width;
        if  ( y2 > height ) y2 = height;
     
        unsigned char cmd[11]= { 0 };
        cmd[0] = GAC_FILL_ENABLE_DISABLE;
        cmd[1] = 1;      // fill 1, empty 0
        ssd1331_RegWriteM(cmd, 2);
        cmd[0] = GAC_DRAW_RECTANGLE;
        cmd[1] = (unsigned char)x1;
        cmd[2] = (unsigned char)y1;
        cmd[3] = (unsigned char)x2;
        cmd[4] = (unsigned char)y2;
        cmd[5] = (unsigned char)((colorline>> 11) << 1);    // Outline Blue
        cmd[6] = (unsigned char)((colorline>> 5 ) & 0x3F);  // Outline Green
        cmd[7] = (unsigned char)((colorline<< 1 ) & 0x3F);  // Outline Red
        cmd[8] = (unsigned char)((colorfill>> 11) << 1);    // fill Blue
        cmd[9] = (unsigned char)((colorfill>> 5 ) & 0x3F);  // fill Green
        cmd[10]= (unsigned char)((colorfill<< 1 ) & 0x3F);  // fill Red
        ssd1331_RegWriteM(cmd, 11);
        CyDelayUs(500);
    }
    
    void ssd1331_Fill_Screen(uint16_t color)
    {
        BGround_Color = color;
        ssd1331_fillrect(0,0,width,height,color,color);
    }
    
    void ssd133_Init(void)
    {

        SPIM_1_Start(); //activate the spi master component
        // reset
        CyDelay(200);
        RES_Write(0);       //Reset active
        CyDelay(200);
        RES_Write(1);       // reset released
        CyDelay(200);       // wait 200mS for display processor to settle
     
        // initialize sequence
        ssd1331_RegWrite(0xAE);    //OLED display OFF
        ssd1331_RegWrite(0x75);    /* Set Row Address */
        ssd1331_RegWrite(0x00);    /* Start = 0 */
        ssd1331_RegWrite(0x3F);    /* End = 63 */
        ssd1331_RegWrite(0x15);    /* Set Column Address */
        ssd1331_RegWrite(0x00);    /* Start = 0 */
        ssd1331_RegWrite(0x5F);    /* End = 95 */
        ssd1331_RegWrite(0xA0);    //Set remap & data format 0111 0000
        ssd1331_RegWrite(0x72);    // RGB colour
        ssd1331_RegWrite(0xA1);    //set display start row RAM
        ssd1331_RegWrite(0x00);
        ssd1331_RegWrite(0xA2);    //set dispaly offset
        ssd1331_RegWrite(0x00);
        ssd1331_RegWrite(0xA4);    //Set Display Mode
        ssd1331_RegWrite(0xA8);    //Set Multiplex Ratio
        ssd1331_RegWrite(0x3F);
        ssd1331_RegWrite(0xAD);    //Set Master Configuration
        ssd1331_RegWrite(0x8F);    //(External VCC Supply Selected)
        ssd1331_RegWrite(0xB0);    //Set Power Saving Mode
        ssd1331_RegWrite(0x1A);
        ssd1331_RegWrite(0xB1);    //Set Phase 1 & 2 Period Adjustment
        ssd1331_RegWrite(0x74);
        ssd1331_RegWrite(0xB3);    //Set Display Clock Divide Ratio / Oscillator Frequency
        ssd1331_RegWrite(0xD0);
        ssd1331_RegWrite(0x8A);    //Set Second Pre-charge Speed of Color A
        ssd1331_RegWrite(0x81);
        ssd1331_RegWrite(0x8B);    //Set Second Pre-charge Speed of Color B
        ssd1331_RegWrite(0x82);
        ssd1331_RegWrite(0x8C);    //Set Second Pre-charge Speed of Color C
        ssd1331_RegWrite(0x83);
        ssd1331_RegWrite(0xBB);    //Set Pre-charge Level
        ssd1331_RegWrite(0x3E);
        ssd1331_RegWrite(0xBE);    //Set VCOMH
        ssd1331_RegWrite(0x3E);
        ssd1331_RegWrite(0x87);    //Set Master Current Control
        ssd1331_RegWrite(0x0F);
        ssd1331_RegWrite(0x81);    //Set Contrast Control for Color gAh
        ssd1331_RegWrite(0x80);
        ssd1331_RegWrite(0x82);    //Set Contrast Control for Color gBh
        ssd1331_RegWrite(0x80);
        ssd1331_RegWrite(0x83);    //Set Contrast Control for Color gCh
        ssd1331_RegWrite(0x80);
        ssd1331_RegWrite(0xAF);    //display ON
     
        chr_size = NORMAL;
        ssd1331_cls();
    }
/* [] END OF FILE */

Main

/* ========================================
 *
 * Copyright Crusty Consultants, 2021
 * All Rights Reserved
 * PUBLISHED, SOFTWARE.
 * Main Contributor "Paul Staron" from public published work on "Mbed"
 * Ported to PSoC by Crusty Consultants.
 * Please acknowledge the above if using for publication or production.
 * No warranty is provided for the functioning of this software.
 * Used at own risk.
 * ========================================
*/

#include "project.h"
#include "ssd1331.h"

int main(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */

    /* Place your initialization/startup code here (e.g. MyInst_Start()) */
    ssd133_Init();

    for(;;)
    {
        /* Place your application code here. */
        ssd1331_Fill_Screen(ssd1331_toRGB(255,0,0)); //red
        CyDelay(500);
        ssd1331_Fill_Screen(ssd1331_toRGB(0,255,0)); //green
        CyDelay(500);
        ssd1331_Fill_Screen(ssd1331_toRGB(0,0,255)); //blue
        CyDelay(500);
        ssd1331_Fill_Screen(ssd1331_toRGB(255,255,255)); //white
        CyDelay(500);
    }
}

/* [] END OF FILE */
Programming the CY8CKIT-0.59 dev board and running the display

I try not to take chances when programming (like blowing up the computer from short circuits) so I programme the dev board by a remote USB network device. This also gets rid of a common ground between the PC and the dev board.

Because I am mean this is not showing the MOV file I took of the ever changing screen block colours. however click on this link to see the actual sequence

Have moved the site to PSoC Crusty Hacks Including (Crusty Bits) as I seem to be able to get on better with the editor software there.http://crusty-hacks-psoc.blogspot.com